DexExtractor

转载博客链接:http://blog.youkuaiyun.com/qq1084283172/article/details/53557894

周末有空就写下博客了,今天来扯一扯Android平台的脱壳工具DexExtractor。DexExtractor工具的使用比较简单,脱壳的原理也比较简单,工具的作者bunnyrene讲这个android脱壳工具只要是针对bangbang (Bangcle)和ijiami加固的脱壳工具,应该是这两类加固的免费版吧。之前在分析android病毒的时候使用过,但是有时候脱壳还是不成功,需要人工手工脱壳来完成或者说这个工具需要进一步完善一下,不管怎么说谢谢作者大牛。


i.DexExtractor脱壳工具的使用说明和讨论链接

看雪论坛:http://bbs.pediy.com/showthread.php?t=201799

github地址:https://github.com/bunnyblue/DexExtractor


ii.作者编译好的镜像文件system.img的下载地址

网盘地址:http://pan.baidu.com/s/1jG3WQMU


iii.DexExtractor脱壳工具的使用说明截图





iiii.通过阅读DexExtractor作者提供的使用说明,写下需要注意的地方:

1.DexExtractor脱壳工具的原理是修改了android源码的DexFile.cpp的dexFileParse函数也就是原来的脱壳点函数处进行dexdump的处理,作者提供了Android 4.4---api 19版本系统脱壳的system.img文件(推荐android模拟器用)和libdvm.so文件(android模拟器和android真机都可以使用)。



2.由于DexExtractor工具需要不断的向sdcard写文件,因此特别是android模拟器使用该脱壳工具一定设置Android模拟的sdcard的空间大小。

3.由于DexExtractor工具需要不断的向sdcard写文件,因此被脱壳的apk需要有向sdcard写文件的权限<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

4.DexExtractor工具的system.img文件(Android 4.4.2版本)使用比较简单--直接替换Android 4.4.2版本系统的system.img文件文件即可,Android模拟器的system.img文件的替换比较简单,Android真机的替换可能需要是Android真机进入recovery模式进行替换;DexExtractor工具的libdvm.so文件使用--需要使用abd的push命令将libdvm.so推送到android系统中然后在su权限将libdvm.so文件拷贝或者备份到Android系统的/system/lib/libdvm.so或者Android真机在root的情况下,使用rootexplore.apk(RE管理器工具)libdvm.so文件拷贝到手机系统的/system/lib/libdvm.so下,替换掉原来Android系统的的/system/lib/libdvm.so文件,并赋予刚才拷贝替换的/system/lib/libdvm.so文件以0775权限然后重启Android真机即可。

  1. adb push xxx/libdvm.so /data/local/tmp/libdvm.so  
  2. adb shell  
  3. su  
  4. mount -r -w -o remount/system  
  5. mount -o remount,rw /system  
  6. dd if=/system/lib/libdvm.so of=/data/local/tmp/libdvm.bak  
  7. rm /system/lib/libdvm.so   
  8. cat /data/local/tmp/libdvm.so >/system/lib/libdvm.so  
  9. chmod 0775 /system/lib/libdvm.so  
  10. mount -o remount,ro /system  
  11. exit  
  12. exit  
  13. adb reboot  
adb push xxx/libdvm.so /data/local/tmp/libdvm.so
adb shell
su
mount -r -w -o remount/system
mount -o remount,rw /system
dd if=/system/lib/libdvm.so of=/data/local/tmp/libdvm.bak
rm /system/lib/libdvm.so 
cat /data/local/tmp/libdvm.so >/system/lib/libdvm.so
chmod 0775 /system/lib/libdvm.so
mount -o remount,ro /system
exit
exit
adb reboot


iiiii.使用DexExtractor工具的system.img文件配置Android 4.4.2的android模拟器进行脱壳实验

使用前提条件

1.如果是android模拟器使用脱壳镜像文件system.img,一定要配置sdcard参数

2.需要脱壳的apk如果没有写权限,需要添加上写sdcard的权限
如:
apk没有写权限的反编译了加上write权限

说明:
< !--往sdcard写入数据权限 -->
< uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
< !--sdcard创建/删除文件权限 -->
< uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>

需要使用的权限:
< uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
#如果脱壳apk没有文件的写权限,反编译以后加上sdcard文件的写权限,然后重新打包apk程序。


DexExtractor脱壳实例(使用Android模拟器):

1.找到Android 4.4.2对应的API 19的系统文件的目录,如下:

E:\BaiduYunDownload\adt-bundle-windows-x86_64-20140702\sdk\system-images\android-19\default\armeabi-v7a
备份原来的system.img文件,然后将修改的system.img文件解压后拷贝到这个目录里。

2.在android模拟器上创建API为19的android模拟器,千万不能忘了为模拟器添加sdcard的内存空间参数。

3.用反编译工具查看被脱壳的apk是否有-----写文件的权限<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>没有就添加上写文件的权限并重新打包apk程序

4.adb install xxx.apk 安装需要脱壳的apk程序到上面创建的android模拟器上。

5.打开logcat的logcat 监视log  "被加固的包名" 和 "dvmtag" ,当看到 "create file end",说明脱壳成功;从eclipse中导出log日志文件并保存。(这里请参考作者提供的脱壳成功的说明)



6.adb pull  /sdcard/classes_xxx.dex 从android模拟器的sdcard中导出脱壳后但是经过base64加密的dex文件
示例:
adb  pull  /sdcard/tx.qq898507339.bzy9_classes_5528.dex

7.脱壳后的dex文件被Base64编码了,需要解码。 
解码dex文件:
Java -jar Decoder.jar  dex目录  
java -jar Decoder.jar   xxxx\tx.qq898507339.bzy9_classes_5528.dex

======================================================================================================
java环境的正确配置

安装JDK,比如目录在C:\Java

为了方便java程序的开发,需要配置一下环境变量,右击我的电脑->属性->高级->环境变量->用户变量中单击[新建(N)]添加以下环境变量

(假定你的JDK安装路径为C:\Java\jdk1.6.0_30)

JAVA_HOME
C:\Java\jdk1.6.0_30

PATH
C:\Java\jdk1.6.0_30\bin

CLASSPATH
.;%JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\lib\tools.jar;(注前面的点号和分号一定不能丢,还有中间的,后面的分号也不要丢了)

说明:CLASSPATH可以再增加一些第三方的jar文件,方便手工编译和运行程序。
======================================================================================================


iiiiii.DexExtractor脱壳工具的代码分析:

DexExtractor脱壳工具的脱壳原理是修改了android系统的dvm虚拟机模块的代码/dalvik/libdex/DexFile.cpp文件的dexFileParse函数,在系统调用dexFileParse函数之前将加固释放出的原始dex文件从内存dump出来。


但是呢,由于一些加固如梆梆加固,会对dex的内存dump脱壳进行检测,具体的就是hook修改当前进程的read、write读写相关的函数,一旦检测到read、write读写相关的函数的操作中有对dex文件的dump行为会有对抗的处理,防止dex的内存dump,因此呢,DexExtractor脱壳工具的作者为了过掉这种内存dump的对抗,需要先将原始的dex文件数据进行base64加密然后进行写文件到sdcard中进行输出,当pull导出拿到base64加密的dex文件时还需要进行base64的解密才能获取到原始的dex文件,具体的脱壳功能见DexHacker.cpp文件。

  1. //  
  2. //  DexHacker.cpp  
  3. //    
  4. //  
  5. //  Created by BunnyBlue on 6/23/15.  
  6. //  
  7. //  
  8.   
  9. #include "DexHacker.h"  
  10. void DexHacker::writeDex2Encoded(unsigned char *data, size_t length){  
  11.       
  12. #ifdef CODE_DVM  
  13.     ALOGE("--pacthed--  inject  .dex length %d  flag=%d",length,flags);  
  14.      
  15.     char dexbuffer[64]={0};  
  16.       
  17.     char dexbufferNamed[128]={0};  
  18.     char bufferProcess[256]={0};  
  19.   
  20.     // 获取当前进程的名称字符串  
  21.     bufferProcess= getProcessName(bufferProcess);  
  22.     sprintf(dexbuffer, "classes_%d", length);  
  23.     strcat(dexbufferNamed,"/sdcard/");  
  24.       
  25.     if (bufferProcess!=NULL) {  
  26.      strcat(dexbufferNamed, bufferProcess);  
  27.         strcat(dexbufferNamed, dexbuffer);  
  28.     }else{  
  29.           ALOGE("--pacthed-- , FAULT pid not  found\n");  
  30.         return;  
  31.     }  
  32.       
  33.     // strcat(dexbufferNamed,dexbuffer);  
  34.     strcat(dexbufferNamed,".dex");  
  35.       
  36.     ALOGE("--pacthed-- , %s\n", dexbufferNamed);  
  37.     ALOGE("--pacthed--  debug dalvikParse   find dex try write file  ");  
  38.       
  39.     // 删除原来存在的文件  
  40.     int status = remove(dexbufferNamed);  
  41.     if( status == 0 )  
  42.         ALOGE("%s file deleted successfully.\n",dexbufferNamed);  
  43.     else  
  44.     {  
  45.         ALOGE("Unable to delete the file\n");  
  46.           
  47.     }  
  48.       
  49.     // 申请内存缓冲区备份信息  
  50.     u1* buffer_data_dest=(u1*)malloc((length+1)*sizeof(u1));  
  51.     // 拷贝内存中的dex文件的数据到内存缓冲区buffer_data_dest中备份  
  52.     memcpy(buffer_data_dest, data, length);  
  53.       
  54.     // 创建文件  
  55.     FILE *fp = fopen(dexbufferNamed,"wb");  
  56.     if(NULL==fp) {  
  57.           
  58.         ALOGE("--pacthed-- , can't create file ! maybe  you need mount sdcard again!");  
  59.         ALOGE( "%s data %s\n", strerror(errno),data);  
  60.           
  61.     } else {  
  62.           
  63.         ALOGE("--pacthed--   create file  %s ",dexbufferNamed);  
  64.         int dex_lem_local = length>2048? 1024:length;  
  65.           
  66.         //  申请内存空间保存base64加密后的dex文件的数据  
  67.         unsigned char *dst=(unsigned char*)malloc(length*2.5);  
  68.         unsigned long dlen=length*2.5;  
  69.           
  70.         // 将原始的dex文件的数据进行base64加密  
  71.         base64_encode(dst, &dlen, data, length);  
  72.         // 将base64加密后的dex文件的数据进行写文件输出到sdcard中  
  73.         fwrite(dst, dlen, 1, fp);  
  74.           
  75.           
  76.           
  77.         //fwrite(data, sizeof(u1), length, fp);  
  78.         ALOGE("--pacthed--  create file  end ");  
  79.           
  80.         //fflush(fp);  
  81.         fclose(fp);  
  82.         fp = NULL;  
  83.     }  
  84.     free(buffer_data_dest);  
  85. #else   
  86.       
  87.     char dexbuffer[64]={0};  
  88.     char dexbufferNamed[128]={0};  
  89.     sprintf(dexbuffer, "classes_%d", length);  
  90.     //strcat(dexbufferNamed,");  
  91.     strcat(dexbufferNamed,dexbuffer);  
  92.     strcat(dexbufferNamed,".dex");  
  93.      
  94.     int status = remove(dexbufferNamed);  
  95.    
  96.     FILE *fp = fopen(dexbufferNamed,"wb");  
  97.     if(NULL==fp){  
  98.           
  99.     } else {  
  100.          
  101.         unsigned char *dst=(unsigned char*)malloc(length*2.5);  
  102.         unsigned long dlen=length*2.5;  
  103.         base64_encode(dst, &dlen, data, length);  
  104.           
  105.         fwrite(dst, dlen, 1, fp);  
  106.         //fflush(fp);  
  107.         fclose(fp);  
  108.         fp = NULL;  
  109.     }  
  110.       
  111. #endif  
  112. }  
  113.   
  114.   
  115. void DexHacker::writeEncodedDex2Dex(const char *encodedDex){  
  116.       
  117.     FILE *srcDexFile=fopen(encodedDex,"rb");  
  118.     std::string outDexFile(encodedDex);  
  119.     outDexFile.append(".read.dex");  
  120.       
  121.       
  122.     FILE *outFile=fopen(outDexFile.c_str(), "wb");  
  123.       
  124.     if (srcDexFile!=NULL) {  
  125.         fseek(srcDexFile,0,SEEK_END);  
  126.         long fsize =ftell(srcDexFile);  
  127.         rewind(srcDexFile);  
  128.           
  129.         std::cout<<sizeof(char)<<"\nxxxxxxxx"<<fsize;  
  130.         unsigned  char *list=(unsigned char*)malloc(sizeof(char)*fsize);  
  131.         unsigned long  numread =fread(list,sizeof(char),fsize,srcDexFile);  
  132.         // blue_dump_data(list, (unsigned long )fsize);  
  133.         unsigned char *dst=(unsigned char*)malloc(numread);  
  134.         unsigned long dlen=numread;  
  135.         base64_decode(dst, &dlen, list, numread);  
  136.           
  137.         fclose(srcDexFile);  
  138.           
  139.         int ret=fwrite(dst, 1, dlen, outFile);  
  140.         fclose(outFile);  
  141.         //   std::cout<<"\n"<<repeate<<"numread"<<numread;   
  142.     }  
  143.       
  144. }  
  145.   
  146. char* itoa(int i, char b[]){  
  147.       
  148.     char const digit[] = "0123456789";  
  149.     char* p = b;  
  150.     if(i<0){  
  151.         *p++ = '-';  
  152.         i *= -1;  
  153.     }  
  154.     int shifter = i;  
  155.     do//Move to where representation ends  
  156.         ++p;  
  157.         shifter = shifter/10;  
  158.     }while(shifter);  
  159.     *p = '\0';  
  160.     do//Move back, inserting digits as u go  
  161.         *--p = digit[i%10];  
  162.         i = i/10;  
  163.     }while(i);  
  164.     return b;  
  165. }  
  166.   
  167.   
  168. // 获取当前进程的名称  
  169. char * DexHacker::getProcessName(char * buffer){  
  170.       
  171.     char path_t[256]={0};  
  172.     // char buffer[512]={0} ;  
  173.    
  174.     // 获取当前进程的pid  
  175.     pid_t pid=getpid();  
  176.     char str[15];  
  177.     sprintf(str, "%d", pid);  
  178.     memset(path_t, 0 , sizeof(path_t));  
  179.     strcat(path_t, "/proc/");  
  180.     strcat(path_t, str);  
  181.     strcat(path_t, "/cmdline");  
  182.       
  183.     //LOG_ERROR("zhw", "path:%s", path_t);  
  184.     int fd_t = open(path_t, O_RDONLY);  
  185.     if(fd_t>0){  
  186.           
  187.         int read_count = read(fd_t, buffer, BUFLEN);  
  188.         if(read_count>0){  
  189.           
  190.             return buffer;  
  191.         }  
  192.     }  
  193.       
  194.     return NULL;  
  195. }  
//
//  DexHacker.cpp
//  
//
//  Created by BunnyBlue on 6/23/15.
//
//

#include "DexHacker.h"
void DexHacker::writeDex2Encoded(unsigned char *data, size_t length){
    
#ifdef CODE_DVM
    ALOGE("--pacthed--  inject  .dex length %d  flag=%d",length,flags);
   
    char dexbuffer[64]={0};
    
    char dexbufferNamed[128]={0};
    char bufferProcess[256]={0};

	// 获取当前进程的名称字符串
    bufferProcess= getProcessName(bufferProcess);
    sprintf(dexbuffer, "classes_%d", length);
    strcat(dexbufferNamed,"/sdcard/");
    
    if (bufferProcess!=NULL) {
     strcat(dexbufferNamed, bufferProcess);
        strcat(dexbufferNamed, dexbuffer);
    }else{
          ALOGE("--pacthed-- , FAULT pid not  found\n");
        return;
    }
    
    // strcat(dexbufferNamed,dexbuffer);
    strcat(dexbufferNamed,".dex");
    
    ALOGE("--pacthed-- , %s\n", dexbufferNamed);
    ALOGE("--pacthed--  debug dalvikParse   find dex try write file  ");
    
    // 删除原来存在的文件
    int status = remove(dexbufferNamed);
    if( status == 0 )
        ALOGE("%s file deleted successfully.\n",dexbufferNamed);
    else
    {
        ALOGE("Unable to delete the file\n");
        
    }
    
    // 申请内存缓冲区备份信息
    u1* buffer_data_dest=(u1*)malloc((length+1)*sizeof(u1));
    // 拷贝内存中的dex文件的数据到内存缓冲区buffer_data_dest中备份
    memcpy(buffer_data_dest, data, length);
    
    // 创建文件
    FILE *fp = fopen(dexbufferNamed,"wb");
    if(NULL==fp) {
		
        ALOGE("--pacthed-- , can't create file ! maybe  you need mount sdcard again!");
        ALOGE( "%s data %s\n", strerror(errno),data);
        
    } else {
		
        ALOGE("--pacthed--   create file  %s ",dexbufferNamed);
        int dex_lem_local = length>2048? 1024:length;
        
        //  申请内存空间保存base64加密后的dex文件的数据
        unsigned char *dst=(unsigned char*)malloc(length*2.5);
        unsigned long dlen=length*2.5;
        
        // 将原始的dex文件的数据进行base64加密
        base64_encode(dst, &dlen, data, length);
        // 将base64加密后的dex文件的数据进行写文件输出到sdcard中
        fwrite(dst, dlen, 1, fp);
        
        
        
        //fwrite(data, sizeof(u1), length, fp);
        ALOGE("--pacthed--  create file  end ");
        
        //fflush(fp);
        fclose(fp);
        fp = NULL;
    }
    free(buffer_data_dest);
#else 
    
    char dexbuffer[64]={0};
    char dexbufferNamed[128]={0};
    sprintf(dexbuffer, "classes_%d", length);
    //strcat(dexbufferNamed,");
    strcat(dexbufferNamed,dexbuffer);
    strcat(dexbufferNamed,".dex");
   
    int status = remove(dexbufferNamed);
 
    FILE *fp = fopen(dexbufferNamed,"wb");
    if(NULL==fp){
        
    } else {
       
        unsigned char *dst=(unsigned char*)malloc(length*2.5);
        unsigned long dlen=length*2.5;
        base64_encode(dst, &dlen, data, length);
        
        fwrite(dst, dlen, 1, fp);
        //fflush(fp);
        fclose(fp);
        fp = NULL;
    }
    
#endif
}


void DexHacker::writeEncodedDex2Dex(const char *encodedDex){
	
    FILE *srcDexFile=fopen(encodedDex,"rb");
    std::string outDexFile(encodedDex);
    outDexFile.append(".read.dex");
    
    
    FILE *outFile=fopen(outDexFile.c_str(), "wb");
    
    if (srcDexFile!=NULL) {
        fseek(srcDexFile,0,SEEK_END);
        long fsize =ftell(srcDexFile);
        rewind(srcDexFile);
        
        std::cout<<sizeof(char)<<"\nxxxxxxxx"<<fsize;
        unsigned  char *list=(unsigned char*)malloc(sizeof(char)*fsize);
        unsigned long  numread =fread(list,sizeof(char),fsize,srcDexFile);
        // blue_dump_data(list, (unsigned long )fsize);
        unsigned char *dst=(unsigned char*)malloc(numread);
        unsigned long dlen=numread;
        base64_decode(dst, &dlen, list, numread);
        
        fclose(srcDexFile);
        
        int ret=fwrite(dst, 1, dlen, outFile);
        fclose(outFile);
        //   std::cout<<"\n"<<repeate<<"numread"<<numread; 
    }
    
}

char* itoa(int i, char b[]){
	
    char const digit[] = "0123456789";
    char* p = b;
    if(i<0){
        *p++ = '-';
        i *= -1;
    }
    int shifter = i;
    do{ //Move to where representation ends
        ++p;
        shifter = shifter/10;
    }while(shifter);
    *p = '\0';
    do{ //Move back, inserting digits as u go
        *--p = digit[i%10];
        i = i/10;
    }while(i);
    return b;
}


// 获取当前进程的名称
char * DexHacker::getProcessName(char * buffer){
	
    char path_t[256]={0};
	// char buffer[512]={0} ;
 
	// 获取当前进程的pid
    pid_t pid=getpid();
    char str[15];
    sprintf(str, "%d", pid);
    memset(path_t, 0 , sizeof(path_t));
    strcat(path_t, "/proc/");
    strcat(path_t, str);
    strcat(path_t, "/cmdline");
    
    //LOG_ERROR("zhw", "path:%s", path_t);
    int fd_t = open(path_t, O_RDONLY);
    if(fd_t>0){
		
        int read_count = read(fd_t, buffer, BUFLEN);
        if(read_count>0){
        
            return buffer;
        }
    }
    
    return NULL;
}


iiiiii.DexExtractor脱壳工具作者提供的文件的说明





关于DexExtractor脱壳工具的自行修改和扩展:根据自己的脱壳思路,编写额外的脱壳代码文件,添加自选Android系统版本的DexFile.cpp文件并将额外的脱壳代码文件添加到编译配置文件Android.mk中,然后在DexFile.cpp文件路径下进行android源码的局部模块的编译,具体编译参考见http://blog.youkuaiyun.com/qq1084283172/article/details/53365659


iiiiii.DexExtractor脱壳工具的其他代码文件

  1. /* 
  2.  * Copyright (C) 2008 The Android Open Source Project 
  3.  * 
  4.  * Licensed under the Apache License, Version 2.0 (the "License"); 
  5.  * you may not use this file except in compliance with the License. 
  6.  * You may obtain a copy of the License at 
  7.  * 
  8.  *      http://www.apache.org/licenses/LICENSE-2.0 
  9.  * 
  10.  * Unless required by applicable law or agreed to in writing, software 
  11.  * distributed under the License is distributed on an "AS IS" BASIS, 
  12.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
  13.  * See the License for the specific language governing permissions and 
  14.  * limitations under the License. 
  15.  */  
  16.   
  17. /* 
  18.  * Access the contents of a .dex file. 
  19.  */  
  20.   
  21. #include "DexFile.h"  
  22. #include "DexOptData.h"  
  23. #include "DexProto.h"  
  24. #include "DexCatch.h"  
  25. #include "Leb128.h"  
  26. #include "sha1.h"  
  27. #include "ZipArchive.h"  
  28.   
  29. #include <zlib.h>  
  30.   
  31. #include <stdlib.h>  
  32. #include <stddef.h>  
  33. #include <string.h>  
  34. #include <fcntl.h>  
  35. #include <errno.h>  
  36. #include "DexHacker.cpp"  
  37.   
  38. /* 
  39.  * Verifying checksums is good, but it slows things down and causes us to 
  40.  * touch every page.  In the "optimized" world, it doesn't work at all, 
  41.  * because we rewrite the contents. 
  42.  */  
  43. static const bool kVerifyChecksum = false;  
  44. static const bool kVerifySignature = false;  
  45.   
  46. /* (documented in header) */  
  47. char dexGetPrimitiveTypeDescriptorChar(PrimitiveType type) {  
  48.     const char* string = dexGetPrimitiveTypeDescriptor(type);  
  49.   
  50.     return (string == NULL) ? '\0' : string[0];  
  51. }  
  52.   
  53. /* (documented in header) */  
  54. const char* dexGetPrimitiveTypeDescriptor(PrimitiveType type) {  
  55.     switch (type) {  
  56.         case PRIM_VOID:    return "V";  
  57.         case PRIM_BOOLEAN: return "Z";  
  58.         case PRIM_BYTE:    return "B";  
  59.         case PRIM_SHORT:   return "S";  
  60.         case PRIM_CHAR:    return "C";  
  61.         case PRIM_INT:     return "I";  
  62.         case PRIM_LONG:    return "J";  
  63.         case PRIM_FLOAT:   return "F";  
  64.         case PRIM_DOUBLE:  return "D";  
  65.         default:           return NULL;  
  66.     }  
  67.   
  68.     return NULL;  
  69. }  
  70.   
  71. /* (documented in header) */  
  72. const char* dexGetBoxedTypeDescriptor(PrimitiveType type) {  
  73.     switch (type) {  
  74.         case PRIM_VOID:    return NULL;  
  75.         case PRIM_BOOLEAN: return "Ljava/lang/Boolean;";  
  76.         case PRIM_BYTE:    return "Ljava/lang/Byte;";  
  77.         case PRIM_SHORT:   return "Ljava/lang/Short;";  
  78.         case PRIM_CHAR:    return "Ljava/lang/Character;";  
  79.         case PRIM_INT:     return "Ljava/lang/Integer;";  
  80.         case PRIM_LONG:    return "Ljava/lang/Long;";  
  81.         case PRIM_FLOAT:   return "Ljava/lang/Float;";  
  82.         case PRIM_DOUBLE:  return "Ljava/lang/Double;";  
  83.         default:           return NULL;  
  84.     }  
  85. }  
  86.   
  87. /* (documented in header) */  
  88. PrimitiveType dexGetPrimitiveTypeFromDescriptorChar(char descriptorChar) {  
  89.     switch (descriptorChar) {  
  90.         case 'V'return PRIM_VOID;  
  91.         case 'Z'return PRIM_BOOLEAN;  
  92.         case 'B'return PRIM_BYTE;  
  93.         case 'S'return PRIM_SHORT;  
  94.         case 'C'return PRIM_CHAR;  
  95.         case 'I'return PRIM_INT;  
  96.         case 'J'return PRIM_LONG;  
  97.         case 'F'return PRIM_FLOAT;  
  98.         case 'D'return PRIM_DOUBLE;  
  99.         default:  return PRIM_NOT;  
  100.     }  
  101. }  
  102.   
  103. /* Return the UTF-8 encoded string with the specified string_id index, 
  104.  * also filling in the UTF-16 size (number of 16-bit code points).*/  
  105. const char* dexStringAndSizeById(const DexFile* pDexFile, u4 idx,  
  106.         u4* utf16Size) {  
  107.     const DexStringId* pStringId = dexGetStringId(pDexFile, idx);  
  108.     const u1* ptr = pDexFile->baseAddr + pStringId->stringDataOff;  
  109.   
  110.     *utf16Size = readUnsignedLeb128(&ptr);  
  111.     return (const char*) ptr;  
  112. }  
  113.   
  114. /* 
  115.  * Format an SHA-1 digest for printing.  tmpBuf must be able to hold at 
  116.  * least kSHA1DigestOutputLen bytes. 
  117.  */  
  118. const char* dvmSHA1DigestToStr(const unsigned char digest[], char* tmpBuf);  
  119.   
  120. /* 
  121.  * Compute a SHA-1 digest on a range of bytes. 
  122.  */  
  123. static void dexComputeSHA1Digest(const unsigned char* data, size_t length,  
  124.     unsigned char digest[])  
  125. {  
  126.     SHA1_CTX context;  
  127.     SHA1Init(&context);  
  128.     SHA1Update(&context, data, length);  
  129.     SHA1Final(digest, &context);  
  130. }  
  131.   
  132. /* 
  133.  * Format the SHA-1 digest into the buffer, which must be able to hold at 
  134.  * least kSHA1DigestOutputLen bytes.  Returns a pointer to the buffer, 
  135.  */  
  136. static const char* dexSHA1DigestToStr(const unsigned char digest[],char* tmpBuf)  
  137. {  
  138.     static const char hexDigit[] = "0123456789abcdef";  
  139.     char* cp;  
  140.     int i;  
  141.   
  142.     cp = tmpBuf;  
  143.     for (i = 0; i < kSHA1DigestLen; i++) {  
  144.         *cp++ = hexDigit[digest[i] >> 4];  
  145.         *cp++ = hexDigit[digest[i] & 0x0f];  
  146.     }  
  147.     *cp++ = '\0';  
  148.   
  149.     assert(cp == tmpBuf + kSHA1DigestOutputLen);  
  150.   
  151.     return tmpBuf;  
  152. }  
  153.   
  154. /* 
  155.  * Compute a hash code on a UTF-8 string, for use with internal hash tables. 
  156.  * 
  157.  * This may or may not be compatible with UTF-8 hash functions used inside 
  158.  * the Dalvik VM. 
  159.  * 
  160.  * The basic "multiply by 31 and add" approach does better on class names 
  161.  * than most other things tried (e.g. adler32). 
  162.  */  
  163. static u4 classDescriptorHash(const char* str)  
  164. {  
  165.     u4 hash = 1;  
  166.   
  167.     while (*str != '\0')  
  168.         hash = hash * 31 + *str++;  
  169.   
  170.     return hash;  
  171. }  
  172.   
  173. /* 
  174.  * Add an entry to the class lookup table.  We hash the string and probe 
  175.  * until we find an open slot. 
  176.  */  
  177. static void classLookupAdd(DexFile* pDexFile, DexClassLookup* pLookup,  
  178.     int stringOff, int classDefOff, int* pNumProbes)  
  179. {  
  180.     const char* classDescriptor =  
  181.         (const char*) (pDexFile->baseAddr + stringOff);  
  182.     const DexClassDef* pClassDef =  
  183.         (const DexClassDef*) (pDexFile->baseAddr + classDefOff);  
  184.     u4 hash = classDescriptorHash(classDescriptor);  
  185.     int mask = pLookup->numEntries-1;  
  186.     int idx = hash & mask;  
  187.   
  188.     /* 
  189.      * Find the first empty slot.  We oversized the table, so this is 
  190.      * guaranteed to finish. 
  191.      */  
  192.     int probes = 0;  
  193.     while (pLookup->table[idx].classDescriptorOffset != 0) {  
  194.         idx = (idx + 1) & mask;  
  195.         probes++;  
  196.     }  
  197.     //if (probes > 1)  
  198.     //    ALOGW("classLookupAdd: probes=%d", probes);  
  199.   
  200.     pLookup->table[idx].classDescriptorHash = hash;  
  201.     pLookup->table[idx].classDescriptorOffset = stringOff;  
  202.     pLookup->table[idx].classDefOffset = classDefOff;  
  203.     *pNumProbes = probes;  
  204. }  
  205.   
  206. /* 
  207.  * Create the class lookup hash table. 
  208.  * 
  209.  * Returns newly-allocated storage. 
  210.  */  
  211. DexClassLookup* dexCreateClassLookup(DexFile* pDexFile)  
  212. {  
  213.     DexClassLookup* pLookup;  
  214.     int allocSize;  
  215.     int i, numEntries;  
  216.     int numProbes, totalProbes, maxProbes;  
  217.   
  218.     numProbes = totalProbes = maxProbes = 0;  
  219.   
  220.     assert(pDexFile != NULL);  
  221.   
  222.     /* 
  223.      * Using a factor of 3 results in far less probing than a factor of 2, 
  224.      * but almost doubles the flash storage requirements for the bootstrap 
  225.      * DEX files.  The overall impact on class loading performance seems 
  226.      * to be minor.  We could probably get some performance improvement by 
  227.      * using a secondary hash. 
  228.      */  
  229.     numEntries = dexRoundUpPower2(pDexFile->pHeader->classDefsSize * 2);  
  230.     allocSize = offsetof(DexClassLookup, table)  
  231.                     + numEntries * sizeof(pLookup->table[0]);  
  232.   
  233.     pLookup = (DexClassLookup*) calloc(1, allocSize);  
  234.     if (pLookup == NULL)  
  235.         return NULL;  
  236.     pLookup->size = allocSize;  
  237.     pLookup->numEntries = numEntries;  
  238.   
  239.     for (i = 0; i < (int)pDexFile->pHeader->classDefsSize; i++) {  
  240.         const DexClassDef* pClassDef;  
  241.         const char* pString;  
  242.   
  243.         pClassDef = dexGetClassDef(pDexFile, i);  
  244.         pString = dexStringByTypeIdx(pDexFile, pClassDef->classIdx);  
  245.   
  246.         classLookupAdd(pDexFile, pLookup,  
  247.             (u1*)pString - pDexFile->baseAddr,  
  248.             (u1*)pClassDef - pDexFile->baseAddr, &numProbes);  
  249.   
  250.         if (numProbes > maxProbes)  
  251.             maxProbes = numProbes;  
  252.         totalProbes += numProbes;  
  253.     }  
  254.   
  255.     ALOGV("Class lookup: classes=%d slots=%d (%d%% occ) alloc=%d"  
  256.          " total=%d max=%d",  
  257.         pDexFile->pHeader->classDefsSize, numEntries,  
  258.         (100 * pDexFile->pHeader->classDefsSize) / numEntries,  
  259.         allocSize, totalProbes, maxProbes);  
  260.   
  261.     return pLookup;  
  262. }  
  263.   
  264.   
  265. /* 
  266.  * Set up the basic raw data pointers of a DexFile. This function isn't 
  267.  * meant for general use. 
  268.  */  
  269. void dexFileSetupBasicPointers(DexFile* pDexFile, const u1* data) {  
  270.     DexHeader *pHeader = (DexHeader*) data;  
  271.   
  272.     pDexFile->baseAddr = data;  
  273.     pDexFile->pHeader = pHeader;  
  274.     pDexFile->pStringIds = (const DexStringId*) (data + pHeader->stringIdsOff);  
  275.     pDexFile->pTypeIds = (const DexTypeId*) (data + pHeader->typeIdsOff);  
  276.     pDexFile->pFieldIds = (const DexFieldId*) (data + pHeader->fieldIdsOff);  
  277.     pDexFile->pMethodIds = (const DexMethodId*) (data + pHeader->methodIdsOff);  
  278.     pDexFile->pProtoIds = (const DexProtoId*) (data + pHeader->protoIdsOff);  
  279.     pDexFile->pClassDefs = (const DexClassDef*) (data + pHeader->classDefsOff);  
  280.     pDexFile->pLinkData = (const DexLink*) (data + pHeader->linkOff);  
  281. }  
  282.   
  283. /* 
  284.  * Parse an optimized or unoptimized .dex file sitting in memory.  This is 
  285.  * called after the byte-ordering and structure alignment has been fixed up. 
  286.  * 
  287.  * On success, return a newly-allocated DexFile. 
  288.  */  
  289. DexFile* dexFileParse(const u1* data, size_t length, int flags)  
  290. {  
  291.   
  292. //******************************添加的脱壳代码**************************  
  293.     // 构建脱壳工具实例  
  294.     DexHacker mDexHacker;  
  295.     // 从内存dump dex文件  
  296.     mDexHacker.writeDex2Encoded(data,(unsigned int)length);  
  297.   
  298. //******************************常规手动脱壳点**************************  
  299.   
  300.     DexFile* pDexFile = NULL;  
  301.     const DexHeader* pHeader;  
  302.     const u1* magic;  
  303.     int result = -1;  
  304.   
  305.     if (length < sizeof(DexHeader)) {  
  306.         ALOGE("too short to be a valid .dex");  
  307.         goto bail;      /* bad file format */  
  308.     }  
  309.   
  310.     pDexFile = (DexFile*) malloc(sizeof(DexFile));  
  311.     if (pDexFile == NULL)  
  312.         goto bail;      /* alloc failure */  
  313.     memset(pDexFile, 0, sizeof(DexFile));  
  314.   
  315.     /* 
  316.      * Peel off the optimized header. 
  317.      */  
  318.     if (memcmp(data, DEX_OPT_MAGIC, 4) == 0) {  
  319.         magic = data;  
  320.         if (memcmp(magic+4, DEX_OPT_MAGIC_VERS, 4) != 0) {  
  321.             ALOGE("bad opt version (0x%02x %02x %02x %02x)",  
  322.                  magic[4], magic[5], magic[6], magic[7]);  
  323.             goto bail;  
  324.         }  
  325.   
  326.         pDexFile->pOptHeader = (const DexOptHeader*) data;  
  327.         ALOGV("Good opt header, DEX offset is %d, flags=0x%02x",  
  328.             pDexFile->pOptHeader->dexOffset, pDexFile->pOptHeader->flags);  
  329.   
  330.         /* parse the optimized dex file tables */  
  331.         if (!dexParseOptData(data, length, pDexFile))  
  332.             goto bail;  
  333.   
  334.         /* ignore the opt header and appended data from here on out */  
  335.         data += pDexFile->pOptHeader->dexOffset;  
  336.         length -= pDexFile->pOptHeader->dexOffset;  
  337.         if (pDexFile->pOptHeader->dexLength > length) {  
  338.             ALOGE("File truncated? stored len=%d, rem len=%d",  
  339.                 pDexFile->pOptHeader->dexLength, (int) length);  
  340.             goto bail;  
  341.         }  
  342.         length = pDexFile->pOptHeader->dexLength;  
  343.     }  
  344.   
  345.     dexFileSetupBasicPointers(pDexFile, data);  
  346.     pHeader = pDexFile->pHeader;  
  347.   
  348.     if (!dexHasValidMagic(pHeader)) {  
  349.         goto bail;  
  350.     }  
  351.   
  352.     /* 
  353.      * Verify the checksum(s).  This is reasonably quick, but does require 
  354.      * touching every byte in the DEX file.  The base checksum changes after 
  355.      * byte-swapping and DEX optimization. 
  356.      */  
  357.     if (flags & kDexParseVerifyChecksum) {  
  358.         u4 adler = dexComputeChecksum(pHeader);  
  359.         if (adler != pHeader->checksum) {  
  360.             ALOGE("ERROR: bad checksum (%08x vs %08x)",  
  361.                 adler, pHeader->checksum);  
  362.             if (!(flags & kDexParseContinueOnError))  
  363.                 goto bail;  
  364.         } else {  
  365.             ALOGV("+++ adler32 checksum (%08x) verified", adler);  
  366.         }  
  367.   
  368.         const DexOptHeader* pOptHeader = pDexFile->pOptHeader;  
  369.         if (pOptHeader != NULL) {  
  370.             adler = dexComputeOptChecksum(pOptHeader);  
  371.             if (adler != pOptHeader->checksum) {  
  372.                 ALOGE("ERROR: bad opt checksum (%08x vs %08x)",  
  373.                     adler, pOptHeader->checksum);  
  374.                 if (!(flags & kDexParseContinueOnError))  
  375.                     goto bail;  
  376.             } else {  
  377.                 ALOGV("+++ adler32 opt checksum (%08x) verified", adler);  
  378.             }  
  379.         }  
  380.     }  
  381.   
  382.     /* 
  383.      * Verify the SHA-1 digest.  (Normally we don't want to do this -- 
  384.      * the digest is used to uniquely identify the original DEX file, and 
  385.      * can't be computed for verification after the DEX is byte-swapped 
  386.      * and optimized.) 
  387.      */  
  388.     if (kVerifySignature) {  
  389.         unsigned char sha1Digest[kSHA1DigestLen];  
  390.         const int nonSum = sizeof(pHeader->magic) + sizeof(pHeader->checksum) +  
  391.                             kSHA1DigestLen;  
  392.   
  393.         dexComputeSHA1Digest(data + nonSum, length - nonSum, sha1Digest);  
  394.         if (memcmp(sha1Digest, pHeader->signature, kSHA1DigestLen) != 0) {  
  395.             char tmpBuf1[kSHA1DigestOutputLen];  
  396.             char tmpBuf2[kSHA1DigestOutputLen];  
  397.             ALOGE("ERROR: bad SHA1 digest (%s vs %s)",  
  398.                 dexSHA1DigestToStr(sha1Digest, tmpBuf1),  
  399.                 dexSHA1DigestToStr(pHeader->signature, tmpBuf2));  
  400.             if (!(flags & kDexParseContinueOnError))  
  401.                 goto bail;  
  402.         } else {  
  403.             ALOGV("+++ sha1 digest verified");  
  404.         }  
  405.     }  
  406.   
  407.     if (pHeader->fileSize != length) {  
  408.         ALOGE("ERROR: stored file size (%d) != expected (%d)",  
  409.             (int) pHeader->fileSize, (int) length);  
  410.         if (!(flags & kDexParseContinueOnError))  
  411.             goto bail;  
  412.     }  
  413.   
  414.     if (pHeader->classDefsSize == 0) {  
  415.         ALOGE("ERROR: DEX file has no classes in it, failing");  
  416.         goto bail;  
  417.     }  
  418.   
  419.     /* 
  420.      * Success! 
  421.      */  
  422.     result = 0;  
  423.   
  424. bail:  
  425.     if (result != 0 && pDexFile != NULL) {  
  426.         dexFileFree(pDexFile);  
  427.         pDexFile = NULL;  
  428.     }  
  429.     return pDexFile;  
  430. }  
  431.   
  432. /* 
  433.  * Free up the DexFile and any associated data structures. 
  434.  * 
  435.  * Note we may be called with a partially-initialized DexFile. 
  436.  */  
  437. void dexFileFree(DexFile* pDexFile)  
  438. {  
  439.     if (pDexFile == NULL)  
  440.         return;  
  441.   
  442.     free(pDexFile);  
  443. }  
  444.   
  445. /* 
  446.  * Look up a class definition entry by descriptor. 
  447.  * 
  448.  * "descriptor" should look like "Landroid/debug/Stuff;". 
  449.  */  
  450. const DexClassDef* dexFindClass(const DexFile* pDexFile,  
  451.     const char* descriptor)  
  452. {  
  453.     const DexClassLookup* pLookup = pDexFile->pClassLookup;  
  454.     u4 hash;  
  455.     int idx, mask;  
  456.   
  457.     hash = classDescriptorHash(descriptor);  
  458.     mask = pLookup->numEntries - 1;  
  459.     idx = hash & mask;  
  460.   
  461.     /* 
  462.      * Search until we find a matching entry or an empty slot. 
  463.      */  
  464.     while (true) {  
  465.         int offset;  
  466.   
  467.         offset = pLookup->table[idx].classDescriptorOffset;  
  468.         if (offset == 0)  
  469.             return NULL;  
  470.   
  471.         if (pLookup->table[idx].classDescriptorHash == hash) {  
  472.             const char* str;  
  473.   
  474.             str = (const char*) (pDexFile->baseAddr + offset);  
  475.             if (strcmp(str, descriptor) == 0) {  
  476.                 return (const DexClassDef*)  
  477.                     (pDexFile->baseAddr + pLookup->table[idx].classDefOffset);  
  478.             }  
  479.         }  
  480.   
  481.         idx = (idx + 1) & mask;  
  482.     }  
  483. }  
  484.   
  485.   
  486. /* 
  487.  * Compute the DEX file checksum for a memory-mapped DEX file. 
  488.  */  
  489. u4 dexComputeChecksum(const DexHeader* pHeader)  
  490. {  
  491.     const u1* start = (const u1*) pHeader;  
  492.   
  493.     uLong adler = adler32(0L, Z_NULL, 0);  
  494.     const int nonSum = sizeof(pHeader->magic) + sizeof(pHeader->checksum);  
  495.   
  496.     return (u4) adler32(adler, start + nonSum, pHeader->fileSize - nonSum);  
  497. }  
  498.   
  499. /* 
  500.  * Compute the size, in bytes, of a DexCode. 
  501.  */  
  502. size_t dexGetDexCodeSize(const DexCode* pCode)  
  503. {  
  504.     /* 
  505.      * The catch handler data is the last entry.  It has a variable number 
  506.      * of variable-size pieces, so we need to create an iterator. 
  507.      */  
  508.     u4 handlersSize;  
  509.     u4 offset;  
  510.     u4 ui;  
  511.   
  512.     if (pCode->triesSize != 0) {  
  513.         handlersSize = dexGetHandlersSize(pCode);  
  514.         offset = dexGetFirstHandlerOffset(pCode);  
  515.     } else {  
  516.         handlersSize = 0;  
  517.         offset = 0;  
  518.     }  
  519.   
  520.     for (ui = 0; ui < handlersSize; ui++) {  
  521.         DexCatchIterator iterator;  
  522.         dexCatchIteratorInit(&iterator, pCode, offset);  
  523.         offset = dexCatchIteratorGetEndOffset(&iterator, pCode);  
  524.     }  
  525.   
  526.     const u1* handlerData = dexGetCatchHandlerData(pCode);  
  527.   
  528.     //ALOGD("+++ pCode=%p handlerData=%p last offset=%d",  
  529.     //    pCode, handlerData, offset);  
  530.   
  531.     /* return the size of the catch handler + everything before it */  
  532.     return (handlerData - (u1*) pCode) + offset;  
  533. }  
  534.   
  535. /* 
  536.  * Round up to the next highest power of 2. 
  537.  * 
  538.  * Found on http://graphics.stanford.edu/~seander/bithacks.html. 
  539.  */  
  540. u4 dexRoundUpPower2(u4 val)  
  541. {  
  542.     val--;  
  543.     val |= val >> 1;  
  544.     val |= val >> 2;  
  545.     val |= val >> 4;  
  546.     val |= val >> 8;  
  547.     val |= val >> 16;  
  548.     val++;  
  549.   
  550.     return val;  
  551. }  
/*
 * Copyright (C) 2008 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*
 * Access the contents of a .dex file.
 */

#include "DexFile.h"
#include "DexOptData.h"
#include "DexProto.h"
#include "DexCatch.h"
#include "Leb128.h"
#include "sha1.h"
#include "ZipArchive.h"

#include <zlib.h>

#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include "DexHacker.cpp"

/*
 * Verifying checksums is good, but it slows things down and causes us to
 * touch every page.  In the "optimized" world, it doesn't work at all,
 * because we rewrite the contents.
 */
static const bool kVerifyChecksum = false;
static const bool kVerifySignature = false;

/* (documented in header) */
char dexGetPrimitiveTypeDescriptorChar(PrimitiveType type) {
    const char* string = dexGetPrimitiveTypeDescriptor(type);

    return (string == NULL) ? '\0' : string[0];
}

/* (documented in header) */
const char* dexGetPrimitiveTypeDescriptor(PrimitiveType type) {
    switch (type) {
        case PRIM_VOID:    return "V";
        case PRIM_BOOLEAN: return "Z";
        case PRIM_BYTE:    return "B";
        case PRIM_SHORT:   return "S";
        case PRIM_CHAR:    return "C";
        case PRIM_INT:     return "I";
        case PRIM_LONG:    return "J";
        case PRIM_FLOAT:   return "F";
        case PRIM_DOUBLE:  return "D";
        default:           return NULL;
    }

    return NULL;
}

/* (documented in header) */
const char* dexGetBoxedTypeDescriptor(PrimitiveType type) {
    switch (type) {
        case PRIM_VOID:    return NULL;
        case PRIM_BOOLEAN: return "Ljava/lang/Boolean;";
        case PRIM_BYTE:    return "Ljava/lang/Byte;";
        case PRIM_SHORT:   return "Ljava/lang/Short;";
        case PRIM_CHAR:    return "Ljava/lang/Character;";
        case PRIM_INT:     return "Ljava/lang/Integer;";
        case PRIM_LONG:    return "Ljava/lang/Long;";
        case PRIM_FLOAT:   return "Ljava/lang/Float;";
        case PRIM_DOUBLE:  return "Ljava/lang/Double;";
        default:           return NULL;
    }
}

/* (documented in header) */
PrimitiveType dexGetPrimitiveTypeFromDescriptorChar(char descriptorChar) {
    switch (descriptorChar) {
        case 'V': return PRIM_VOID;
        case 'Z': return PRIM_BOOLEAN;
        case 'B': return PRIM_BYTE;
        case 'S': return PRIM_SHORT;
        case 'C': return PRIM_CHAR;
        case 'I': return PRIM_INT;
        case 'J': return PRIM_LONG;
        case 'F': return PRIM_FLOAT;
        case 'D': return PRIM_DOUBLE;
        default:  return PRIM_NOT;
    }
}

/* Return the UTF-8 encoded string with the specified string_id index,
 * also filling in the UTF-16 size (number of 16-bit code points).*/
const char* dexStringAndSizeById(const DexFile* pDexFile, u4 idx,
        u4* utf16Size) {
    const DexStringId* pStringId = dexGetStringId(pDexFile, idx);
    const u1* ptr = pDexFile->baseAddr + pStringId->stringDataOff;

    *utf16Size = readUnsignedLeb128(&ptr);
    return (const char*) ptr;
}

/*
 * Format an SHA-1 digest for printing.  tmpBuf must be able to hold at
 * least kSHA1DigestOutputLen bytes.
 */
const char* dvmSHA1DigestToStr(const unsigned char digest[], char* tmpBuf);

/*
 * Compute a SHA-1 digest on a range of bytes.
 */
static void dexComputeSHA1Digest(const unsigned char* data, size_t length,
    unsigned char digest[])
{
    SHA1_CTX context;
    SHA1Init(&context);
    SHA1Update(&context, data, length);
    SHA1Final(digest, &context);
}

/*
 * Format the SHA-1 digest into the buffer, which must be able to hold at
 * least kSHA1DigestOutputLen bytes.  Returns a pointer to the buffer,
 */
static const char* dexSHA1DigestToStr(const unsigned char digest[],char* tmpBuf)
{
    static const char hexDigit[] = "0123456789abcdef";
    char* cp;
    int i;

    cp = tmpBuf;
    for (i = 0; i < kSHA1DigestLen; i++) {
        *cp++ = hexDigit[digest[i] >> 4];
        *cp++ = hexDigit[digest[i] & 0x0f];
    }
    *cp++ = '\0';

    assert(cp == tmpBuf + kSHA1DigestOutputLen);

    return tmpBuf;
}

/*
 * Compute a hash code on a UTF-8 string, for use with internal hash tables.
 *
 * This may or may not be compatible with UTF-8 hash functions used inside
 * the Dalvik VM.
 *
 * The basic "multiply by 31 and add" approach does better on class names
 * than most other things tried (e.g. adler32).
 */
static u4 classDescriptorHash(const char* str)
{
    u4 hash = 1;

    while (*str != '\0')
        hash = hash * 31 + *str++;

    return hash;
}

/*
 * Add an entry to the class lookup table.  We hash the string and probe
 * until we find an open slot.
 */
static void classLookupAdd(DexFile* pDexFile, DexClassLookup* pLookup,
    int stringOff, int classDefOff, int* pNumProbes)
{
    const char* classDescriptor =
        (const char*) (pDexFile->baseAddr + stringOff);
    const DexClassDef* pClassDef =
        (const DexClassDef*) (pDexFile->baseAddr + classDefOff);
    u4 hash = classDescriptorHash(classDescriptor);
    int mask = pLookup->numEntries-1;
    int idx = hash & mask;

    /*
     * Find the first empty slot.  We oversized the table, so this is
     * guaranteed to finish.
     */
    int probes = 0;
    while (pLookup->table[idx].classDescriptorOffset != 0) {
        idx = (idx + 1) & mask;
        probes++;
    }
    //if (probes > 1)
    //    ALOGW("classLookupAdd: probes=%d", probes);

    pLookup->table[idx].classDescriptorHash = hash;
    pLookup->table[idx].classDescriptorOffset = stringOff;
    pLookup->table[idx].classDefOffset = classDefOff;
    *pNumProbes = probes;
}

/*
 * Create the class lookup hash table.
 *
 * Returns newly-allocated storage.
 */
DexClassLookup* dexCreateClassLookup(DexFile* pDexFile)
{
    DexClassLookup* pLookup;
    int allocSize;
    int i, numEntries;
    int numProbes, totalProbes, maxProbes;

    numProbes = totalProbes = maxProbes = 0;

    assert(pDexFile != NULL);

    /*
     * Using a factor of 3 results in far less probing than a factor of 2,
     * but almost doubles the flash storage requirements for the bootstrap
     * DEX files.  The overall impact on class loading performance seems
     * to be minor.  We could probably get some performance improvement by
     * using a secondary hash.
     */
    numEntries = dexRoundUpPower2(pDexFile->pHeader->classDefsSize * 2);
    allocSize = offsetof(DexClassLookup, table)
                    + numEntries * sizeof(pLookup->table[0]);

    pLookup = (DexClassLookup*) calloc(1, allocSize);
    if (pLookup == NULL)
        return NULL;
    pLookup->size = allocSize;
    pLookup->numEntries = numEntries;

    for (i = 0; i < (int)pDexFile->pHeader->classDefsSize; i++) {
        const DexClassDef* pClassDef;
        const char* pString;

        pClassDef = dexGetClassDef(pDexFile, i);
        pString = dexStringByTypeIdx(pDexFile, pClassDef->classIdx);

        classLookupAdd(pDexFile, pLookup,
            (u1*)pString - pDexFile->baseAddr,
            (u1*)pClassDef - pDexFile->baseAddr, &numProbes);

        if (numProbes > maxProbes)
            maxProbes = numProbes;
        totalProbes += numProbes;
    }

    ALOGV("Class lookup: classes=%d slots=%d (%d%% occ) alloc=%d"
         " total=%d max=%d",
        pDexFile->pHeader->classDefsSize, numEntries,
        (100 * pDexFile->pHeader->classDefsSize) / numEntries,
        allocSize, totalProbes, maxProbes);

    return pLookup;
}


/*
 * Set up the basic raw data pointers of a DexFile. This function isn't
 * meant for general use.
 */
void dexFileSetupBasicPointers(DexFile* pDexFile, const u1* data) {
    DexHeader *pHeader = (DexHeader*) data;

    pDexFile->baseAddr = data;
    pDexFile->pHeader = pHeader;
    pDexFile->pStringIds = (const DexStringId*) (data + pHeader->stringIdsOff);
    pDexFile->pTypeIds = (const DexTypeId*) (data + pHeader->typeIdsOff);
    pDexFile->pFieldIds = (const DexFieldId*) (data + pHeader->fieldIdsOff);
    pDexFile->pMethodIds = (const DexMethodId*) (data + pHeader->methodIdsOff);
    pDexFile->pProtoIds = (const DexProtoId*) (data + pHeader->protoIdsOff);
    pDexFile->pClassDefs = (const DexClassDef*) (data + pHeader->classDefsOff);
    pDexFile->pLinkData = (const DexLink*) (data + pHeader->linkOff);
}

/*
 * Parse an optimized or unoptimized .dex file sitting in memory.  This is
 * called after the byte-ordering and structure alignment has been fixed up.
 *
 * On success, return a newly-allocated DexFile.
 */
DexFile* dexFileParse(const u1* data, size_t length, int flags)
{

//******************************添加的脱壳代码**************************
	// 构建脱壳工具实例
	DexHacker mDexHacker;
	// 从内存dump dex文件
	mDexHacker.writeDex2Encoded(data,(unsigned int)length);

//******************************常规手动脱壳点**************************

    DexFile* pDexFile = NULL;
    const DexHeader* pHeader;
    const u1* magic;
    int result = -1;

    if (length < sizeof(DexHeader)) {
        ALOGE("too short to be a valid .dex");
        goto bail;      /* bad file format */
    }

    pDexFile = (DexFile*) malloc(sizeof(DexFile));
    if (pDexFile == NULL)
        goto bail;      /* alloc failure */
    memset(pDexFile, 0, sizeof(DexFile));

    /*
     * Peel off the optimized header.
     */
    if (memcmp(data, DEX_OPT_MAGIC, 4) == 0) {
        magic = data;
        if (memcmp(magic+4, DEX_OPT_MAGIC_VERS, 4) != 0) {
            ALOGE("bad opt version (0x%02x %02x %02x %02x)",
                 magic[4], magic[5], magic[6], magic[7]);
            goto bail;
        }

        pDexFile->pOptHeader = (const DexOptHeader*) data;
        ALOGV("Good opt header, DEX offset is %d, flags=0x%02x",
            pDexFile->pOptHeader->dexOffset, pDexFile->pOptHeader->flags);

        /* parse the optimized dex file tables */
        if (!dexParseOptData(data, length, pDexFile))
            goto bail;

        /* ignore the opt header and appended data from here on out */
        data += pDexFile->pOptHeader->dexOffset;
        length -= pDexFile->pOptHeader->dexOffset;
        if (pDexFile->pOptHeader->dexLength > length) {
            ALOGE("File truncated? stored len=%d, rem len=%d",
                pDexFile->pOptHeader->dexLength, (int) length);
            goto bail;
        }
        length = pDexFile->pOptHeader->dexLength;
    }

    dexFileSetupBasicPointers(pDexFile, data);
    pHeader = pDexFile->pHeader;

    if (!dexHasValidMagic(pHeader)) {
        goto bail;
    }

    /*
     * Verify the checksum(s).  This is reasonably quick, but does require
     * touching every byte in the DEX file.  The base checksum changes after
     * byte-swapping and DEX optimization.
     */
    if (flags & kDexParseVerifyChecksum) {
        u4 adler = dexComputeChecksum(pHeader);
        if (adler != pHeader->checksum) {
            ALOGE("ERROR: bad checksum (%08x vs %08x)",
                adler, pHeader->checksum);
            if (!(flags & kDexParseContinueOnError))
                goto bail;
        } else {
            ALOGV("+++ adler32 checksum (%08x) verified", adler);
        }

        const DexOptHeader* pOptHeader = pDexFile->pOptHeader;
        if (pOptHeader != NULL) {
            adler = dexComputeOptChecksum(pOptHeader);
            if (adler != pOptHeader->checksum) {
                ALOGE("ERROR: bad opt checksum (%08x vs %08x)",
                    adler, pOptHeader->checksum);
                if (!(flags & kDexParseContinueOnError))
                    goto bail;
            } else {
                ALOGV("+++ adler32 opt checksum (%08x) verified", adler);
            }
        }
    }

    /*
     * Verify the SHA-1 digest.  (Normally we don't want to do this --
     * the digest is used to uniquely identify the original DEX file, and
     * can't be computed for verification after the DEX is byte-swapped
     * and optimized.)
     */
    if (kVerifySignature) {
        unsigned char sha1Digest[kSHA1DigestLen];
        const int nonSum = sizeof(pHeader->magic) + sizeof(pHeader->checksum) +
                            kSHA1DigestLen;

        dexComputeSHA1Digest(data + nonSum, length - nonSum, sha1Digest);
        if (memcmp(sha1Digest, pHeader->signature, kSHA1DigestLen) != 0) {
            char tmpBuf1[kSHA1DigestOutputLen];
            char tmpBuf2[kSHA1DigestOutputLen];
            ALOGE("ERROR: bad SHA1 digest (%s vs %s)",
                dexSHA1DigestToStr(sha1Digest, tmpBuf1),
                dexSHA1DigestToStr(pHeader->signature, tmpBuf2));
            if (!(flags & kDexParseContinueOnError))
                goto bail;
        } else {
            ALOGV("+++ sha1 digest verified");
        }
    }

    if (pHeader->fileSize != length) {
        ALOGE("ERROR: stored file size (%d) != expected (%d)",
            (int) pHeader->fileSize, (int) length);
        if (!(flags & kDexParseContinueOnError))
            goto bail;
    }

    if (pHeader->classDefsSize == 0) {
        ALOGE("ERROR: DEX file has no classes in it, failing");
        goto bail;
    }

    /*
     * Success!
     */
    result = 0;

bail:
    if (result != 0 && pDexFile != NULL) {
        dexFileFree(pDexFile);
        pDexFile = NULL;
    }
    return pDexFile;
}

/*
 * Free up the DexFile and any associated data structures.
 *
 * Note we may be called with a partially-initialized DexFile.
 */
void dexFileFree(DexFile* pDexFile)
{
    if (pDexFile == NULL)
        return;

    free(pDexFile);
}

/*
 * Look up a class definition entry by descriptor.
 *
 * "descriptor" should look like "Landroid/debug/Stuff;".
 */
const DexClassDef* dexFindClass(const DexFile* pDexFile,
    const char* descriptor)
{
    const DexClassLookup* pLookup = pDexFile->pClassLookup;
    u4 hash;
    int idx, mask;

    hash = classDescriptorHash(descriptor);
    mask = pLookup->numEntries - 1;
    idx = hash & mask;

    /*
     * Search until we find a matching entry or an empty slot.
     */
    while (true) {
        int offset;

        offset = pLookup->table[idx].classDescriptorOffset;
        if (offset == 0)
            return NULL;

        if (pLookup->table[idx].classDescriptorHash == hash) {
            const char* str;

            str = (const char*) (pDexFile->baseAddr + offset);
            if (strcmp(str, descriptor) == 0) {
                return (const DexClassDef*)
                    (pDexFile->baseAddr + pLookup->table[idx].classDefOffset);
            }
        }

        idx = (idx + 1) & mask;
    }
}


/*
 * Compute the DEX file checksum for a memory-mapped DEX file.
 */
u4 dexComputeChecksum(const DexHeader* pHeader)
{
    const u1* start = (const u1*) pHeader;

    uLong adler = adler32(0L, Z_NULL, 0);
    const int nonSum = sizeof(pHeader->magic) + sizeof(pHeader->checksum);

    return (u4) adler32(adler, start + nonSum, pHeader->fileSize - nonSum);
}

/*
 * Compute the size, in bytes, of a DexCode.
 */
size_t dexGetDexCodeSize(const DexCode* pCode)
{
    /*
     * The catch handler data is the last entry.  It has a variable number
     * of variable-size pieces, so we need to create an iterator.
     */
    u4 handlersSize;
    u4 offset;
    u4 ui;

    if (pCode->triesSize != 0) {
        handlersSize = dexGetHandlersSize(pCode);
        offset = dexGetFirstHandlerOffset(pCode);
    } else {
        handlersSize = 0;
        offset = 0;
    }

    for (ui = 0; ui < handlersSize; ui++) {
        DexCatchIterator iterator;
        dexCatchIteratorInit(&iterator, pCode, offset);
        offset = dexCatchIteratorGetEndOffset(&iterator, pCode);
    }

    const u1* handlerData = dexGetCatchHandlerData(pCode);

    //ALOGD("+++ pCode=%p handlerData=%p last offset=%d",
    //    pCode, handlerData, offset);

    /* return the size of the catch handler + everything before it */
    return (handlerData - (u1*) pCode) + offset;
}

/*
 * Round up to the next highest power of 2.
 *
 * Found on http://graphics.stanford.edu/~seander/bithacks.html.
 */
u4 dexRoundUpPower2(u4 val)
{
    val--;
    val |= val >> 1;
    val |= val >> 2;
    val |= val >> 4;
    val |= val >> 8;
    val |= val >> 16;
    val++;

    return val;
}

  1. //  
  2. //  DexHacker.h  
  3. //    
  4. //  
  5. //  Created by BunnyBlue on 6/23/15.  
  6. //  
  7. //  
  8.   
  9. #ifndef ____DexHacker__  
  10. #define ____DexHacker__  
  11. #include <iostream>  
  12. #include<string.h>  
  13. #include<stdio.h>  
  14. #include "base64.h"  
  15. #include <sys/types.h>  
  16. #include <unistd.h>  
  17. #include <stdio.h>  
  18. #include <fcntl.h>  
  19. #define BUFLEN 1024  
  20.   
  21. class DexHacker{  
  22. public:  
  23.     void  writeDex2Encoded(unsigned char * data,size_t length);  
  24.     void  writeEncodedDex2Dex(const char *dexPath);  
  25.     char * getProcessName(char * buffer);  
  26. };  
  27. #endif /* defined(____DexHacker__) */  
//
//  DexHacker.h
//  
//
//  Created by BunnyBlue on 6/23/15.
//
//

#ifndef ____DexHacker__
#define ____DexHacker__
#include <iostream>
#include<string.h>
#include<stdio.h>
#include "base64.h"
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>
#define BUFLEN 1024

class DexHacker{
public:
    void  writeDex2Encoded(unsigned char * data,size_t length);
    void  writeEncodedDex2Dex(const char *dexPath);
    char * getProcessName(char * buffer);
};
#endif /* defined(____DexHacker__) */

  1. /** 
  2.  * \file base64.h 
  3.  * 
  4.  * \brief RFC 1521 base64 encoding/decoding 
  5.  * 
  6.  *  Copyright (C) 2006-2010, Brainspark B.V. 
  7.  * 
  8.  *  This file is part of PolarSSL (http://www.polarssl.org) 
  9.  *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org> 
  10.  * 
  11.  *  All rights reserved. 
  12.  * 
  13.  *  This program is free software; you can redistribute it and/or modify 
  14.  *  it under the terms of the GNU General Public License as published by 
  15.  *  the Free Software Foundation; either version 2 of the License, or 
  16.  *  (at your option) any later version. 
  17.  * 
  18.  *  This program is distributed in the hope that it will be useful, 
  19.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of 
  20.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
  21.  *  GNU General Public License for more details. 
  22.  * 
  23.  *  You should have received a copy of the GNU General Public License along 
  24.  *  with this program; if not, write to the Free Software Foundation, Inc., 
  25.  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 
  26.  */  
  27. #define  POLARSSL_BASE64_C  
  28. #define POLARSSL_SELF_TEST  
  29. #ifndef POLARSSL_BASE64_H  
  30. #define POLARSSL_BASE64_H  
  31.   
  32. #include <string.h>  
  33.   
  34. #define POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL               -0x002A  /**< Output buffer too small. */  
  35. #define POLARSSL_ERR_BASE64_INVALID_CHARACTER              -0x002C  /**< Invalid character in input. */  
  36.   
  37. #ifdef __cplusplus  
  38. extern "C" {  
  39. #endif  
  40.   
  41. /** 
  42.  * \brief          Encode a buffer into base64 format 
  43.  * 
  44.  * \param dst      destination buffer 
  45.  * \param dlen     size of the buffer 
  46.  * \param src      source buffer 
  47.  * \param slen     amount of data to be encoded 
  48.  * 
  49.  * \return         0 if successful, or POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL. 
  50.  *                 *dlen is always updated to reflect the amount 
  51.  *                 of data that has (or would have) been written. 
  52.  * 
  53.  * \note           Call this function with *dlen = 0 to obtain the 
  54.  *                 required buffer size in *dlen 
  55.  */  
  56. int base64_encode( unsigned char *dst, size_t *dlen,  
  57.                    const unsigned char *src, size_t slen );  
  58.   
  59. /** 
  60.  * \brief          Decode a base64-formatted buffer 
  61.  * 
  62.  * \param dst      destination buffer 
  63.  * \param dlen     size of the buffer 
  64.  * \param src      source buffer 
  65.  * \param slen     amount of data to be decoded 
  66.  * 
  67.  * \return         0 if successful, POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL, or 
  68.  *                 POLARSSL_ERR_BASE64_INVALID_CHARACTER if the input data is 
  69.  *                 not correct. *dlen is always updated to reflect the amount 
  70.  *                 of data that has (or would have) been written. 
  71.  * 
  72.  * \note           Call this function with *dlen = 0 to obtain the 
  73.  *                 required buffer size in *dlen 
  74.  */  
  75. int base64_decode( unsigned char *dst, size_t *dlen,  
  76.                    const unsigned char *src, size_t slen );  
  77.     int base64_self_test( int verbose );  
  78.   
  79.   
  80. #ifdef __cplusplus  
  81. }  
  82. #endif  
  83.   
  84. #endif /* base64.h */  
/**
 * \file base64.h
 *
 * \brief RFC 1521 base64 encoding/decoding
 *
 *  Copyright (C) 2006-2010, Brainspark B.V.
 *
 *  This file is part of PolarSSL (http://www.polarssl.org)
 *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
 *
 *  All rights reserved.
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License along
 *  with this program; if not, write to the Free Software Foundation, Inc.,
 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */
#define  POLARSSL_BASE64_C
#define POLARSSL_SELF_TEST
#ifndef POLARSSL_BASE64_H
#define POLARSSL_BASE64_H

#include <string.h>

#define POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL               -0x002A  /**< Output buffer too small. */
#define POLARSSL_ERR_BASE64_INVALID_CHARACTER              -0x002C  /**< Invalid character in input. */

#ifdef __cplusplus
extern "C" {
#endif

/**
 * \brief          Encode a buffer into base64 format
 *
 * \param dst      destination buffer
 * \param dlen     size of the buffer
 * \param src      source buffer
 * \param slen     amount of data to be encoded
 *
 * \return         0 if successful, or POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL.
 *                 *dlen is always updated to reflect the amount
 *                 of data that has (or would have) been written.
 *
 * \note           Call this function with *dlen = 0 to obtain the
 *                 required buffer size in *dlen
 */
int base64_encode( unsigned char *dst, size_t *dlen,
                   const unsigned char *src, size_t slen );

/**
 * \brief          Decode a base64-formatted buffer
 *
 * \param dst      destination buffer
 * \param dlen     size of the buffer
 * \param src      source buffer
 * \param slen     amount of data to be decoded
 *
 * \return         0 if successful, POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL, or
 *                 POLARSSL_ERR_BASE64_INVALID_CHARACTER if the input data is
 *                 not correct. *dlen is always updated to reflect the amount
 *                 of data that has (or would have) been written.
 *
 * \note           Call this function with *dlen = 0 to obtain the
 *                 required buffer size in *dlen
 */
int base64_decode( unsigned char *dst, size_t *dlen,
                   const unsigned char *src, size_t slen );
    int base64_self_test( int verbose );


#ifdef __cplusplus
}
#endif

#endif /* base64.h */

  1. /* 
  2.  *  RFC 1521 base64 encoding/decoding 
  3.  * 
  4.  *  Copyright (C) 2006-2013, Brainspark B.V. 
  5.  * 
  6.  *  This file is part of PolarSSL (http://www.polarssl.org) 
  7.  *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org> 
  8.  * 
  9.  *  All rights reserved. 
  10.  * 
  11.  *  This program is free software; you can redistribute it and/or modify 
  12.  *  it under the terms of the GNU General Public License as published by 
  13.  *  the Free Software Foundation; either version 2 of the License, or 
  14.  *  (at your option) any later version. 
  15.  * 
  16.  *  This program is distributed in the hope that it will be useful, 
  17.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of 
  18.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
  19.  *  GNU General Public License for more details. 
  20.  * 
  21.  *  You should have received a copy of the GNU General Public License along 
  22.  *  with this program; if not, write to the Free Software Foundation, Inc., 
  23.  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 
  24.  */  
  25.   
  26. #define POLARSSL_BASE64_C  
  27. #define POLARSSL_SELF_TEST  
  28.   
  29. #if defined(POLARSSL_BASE64_C)  
  30.   
  31. #include "base64.h"  
  32.   
  33. #if defined(_MSC_VER) && !defined(EFIX64) && !defined(EFI32)  
  34. #include <basetsd.h>  
  35. typedef UINT32 uint32_t;  
  36. #else  
  37. #include <inttypes.h>  
  38. #endif  
  39.   
  40. static const unsigned char base64_enc_map[64] =  
  41. {  
  42.     'A''B''C''D''E''F''G''H''I''J',  
  43.     'K''L''M''N''O''P''Q''R''S''T',  
  44.     'U''V''W''X''Y''Z''a''b''c''d',  
  45.     'e''f''g''h''i''j''k''l''m''n',  
  46.     'o''p''q''r''s''t''u''v''w''x',  
  47.     'y''z''0''1''2''3''4''5''6''7',  
  48.     '8''9''+''/'  
  49. };  
  50.   
  51. static const unsigned char base64_dec_map[128] =  
  52. {  
  53.     127, 127, 127, 127, 127, 127, 127, 127, 127, 127,  
  54.     127, 127, 127, 127, 127, 127, 127, 127, 127, 127,  
  55.     127, 127, 127, 127, 127, 127, 127, 127, 127, 127,  
  56.     127, 127, 127, 127, 127, 127, 127, 127, 127, 127,  
  57.     127, 127, 127,  62, 127, 127, 127,  63,  52,  53,  
  58.      54,  55,  56,  57,  58,  59,  60,  61, 127, 127,  
  59.     127,  64, 127, 127, 127,   0,   1,   2,   3,   4,  
  60.       5,   6,   7,   8,   9,  10,  11,  12,  13,  14,  
  61.      15,  16,  17,  18,  19,  20,  21,  22,  23,  24,  
  62.      25, 127, 127, 127, 127, 127, 127,  26,  27,  28,  
  63.      29,  30,  31,  32,  33,  34,  35,  36,  37,  38,  
  64.      39,  40,  41,  42,  43,  44,  45,  46,  47,  48,  
  65.      49,  50,  51, 127, 127, 127, 127, 127  
  66. };  
  67.   
  68. /* 
  69.  * Encode a buffer into base64 format 
  70.  */  
  71. int base64_encode( unsigned char *dst, size_t *dlen,  
  72.                    const unsigned char *src, size_t slen )  
  73. {  
  74.     size_t i, n;  
  75.     int C1, C2, C3;  
  76.     unsigned char *p;  
  77.   
  78.     if( slen == 0 )  
  79.         return( 0 );  
  80.   
  81.     n = (slen << 3) / 6;  
  82.   
  83.     switch( (slen << 3) - (n * 6) )  
  84.     {  
  85.         case  2: n += 3; break;  
  86.         case  4: n += 2; break;  
  87.         defaultbreak;  
  88.     }  
  89.   
  90.     if( *dlen < n + 1 )  
  91.     {  
  92.         *dlen = n + 1;  
  93.         return( POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL );  
  94.     }  
  95.   
  96.     n = (slen / 3) * 3;  
  97.   
  98.     for( i = 0, p = dst; i < n; i += 3 )  
  99.     {  
  100.         C1 = *src++;  
  101.         C2 = *src++;  
  102.         C3 = *src++;  
  103.   
  104.         *p++ = base64_enc_map[(C1 >> 2) & 0x3F];  
  105.         *p++ = base64_enc_map[(((C1 &  3) << 4) + (C2 >> 4)) & 0x3F];  
  106.         *p++ = base64_enc_map[(((C2 & 15) << 2) + (C3 >> 6)) & 0x3F];  
  107.         *p++ = base64_enc_map[C3 & 0x3F];  
  108.     }  
  109.   
  110.     if( i < slen )  
  111.     {  
  112.         C1 = *src++;  
  113.         C2 = ((i + 1) < slen) ? *src++ : 0;  
  114.   
  115.         *p++ = base64_enc_map[(C1 >> 2) & 0x3F];  
  116.         *p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F];  
  117.   
  118.         if( (i + 1) < slen )  
  119.              *p++ = base64_enc_map[((C2 & 15) << 2) & 0x3F];  
  120.         else *p++ = '=';  
  121.   
  122.         *p++ = '=';  
  123.     }  
  124.   
  125.     *dlen = p - dst;  
  126.     *p = 0;  
  127.   
  128.     return( 0 );  
  129. }  
  130.   
  131. /* 
  132.  * Decode a base64-formatted buffer 
  133.  */  
  134. int base64_decode( unsigned char *dst, size_t *dlen,  
  135.                    const unsigned char *src, size_t slen )  
  136. {  
  137.     size_t i, n;  
  138.     uint32_t j, x;  
  139.     unsigned char *p;  
  140.   
  141.     for( i = n = j = 0; i < slen; i++ )  
  142.     {  
  143.         if( ( slen - i ) >= 2 &&  
  144.             src[i] == '\r' && src[i + 1] == '\n' )  
  145.             continue;  
  146.   
  147.         if( src[i] == '\n' )  
  148.             continue;  
  149.   
  150.         if( src[i] == '=' && ++j > 2 )  
  151.             return( POLARSSL_ERR_BASE64_INVALID_CHARACTER );  
  152.   
  153.         if( src[i] > 127 || base64_dec_map[src[i]] == 127 )  
  154.             return( POLARSSL_ERR_BASE64_INVALID_CHARACTER );  
  155.   
  156.         if( base64_dec_map[src[i]] < 64 && j != 0 )  
  157.             return( POLARSSL_ERR_BASE64_INVALID_CHARACTER );  
  158.   
  159.         n++;  
  160.     }  
  161.   
  162.     if( n == 0 )  
  163.         return( 0 );  
  164.   
  165.     n = ((n * 6) + 7) >> 3;  
  166.   
  167.     if( dst == NULL || *dlen < n )  
  168.     {  
  169.         *dlen = n;  
  170.         return( POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL );  
  171.     }  
  172.   
  173.    for( j = 3, n = x = 0, p = dst; i > 0; i--, src++ )  
  174.    {  
  175.         if( *src == '\r' || *src == '\n' )  
  176.             continue;  
  177.   
  178.         j -= ( base64_dec_map[*src] == 64 );  
  179.         x  = (x << 6) | ( base64_dec_map[*src] & 0x3F );  
  180.   
  181.         if( ++n == 4 )  
  182.         {  
  183.             n = 0;  
  184.             if( j > 0 ) *p++ = (unsigned char)( x >> 16 );  
  185.             if( j > 1 ) *p++ = (unsigned char)( x >>  8 );  
  186.             if( j > 2 ) *p++ = (unsigned char)( x       );  
  187.         }  
  188.     }  
  189.   
  190.     *dlen = p - dst;  
  191.   
  192.     return( 0 );  
  193. }  
  194.   
  195. #if defined(POLARSSL_SELF_TEST)  
  196.   
  197. #include <string.h>  
  198. #include <stdio.h>  
  199.   
  200. static const unsigned char base64_test_dec[64] =  
  201. {  
  202.     0x24, 0x48, 0x6E, 0x56, 0x87, 0x62, 0x5A, 0xBD,  
  203.     0xBF, 0x17, 0xD9, 0xA2, 0xC4, 0x17, 0x1A, 0x01,  
  204.     0x94, 0xED, 0x8F, 0x1E, 0x11, 0xB3, 0xD7, 0x09,  
  205.     0x0C, 0xB6, 0xE9, 0x10, 0x6F, 0x22, 0xEE, 0x13,  
  206.     0xCA, 0xB3, 0x07, 0x05, 0x76, 0xC9, 0xFA, 0x31,  
  207.     0x6C, 0x08, 0x34, 0xFF, 0x8D, 0xC2, 0x6C, 0x38,  
  208.     0x00, 0x43, 0xE9, 0x54, 0x97, 0xAF, 0x50, 0x4B,  
  209.     0xD1, 0x41, 0xBA, 0x95, 0x31, 0x5A, 0x0B, 0x97  
  210. };  
  211.   
  212. static const unsigned char base64_test_enc[] =  
  213.     "JEhuVodiWr2/F9mixBcaAZTtjx4Rs9cJDLbpEG8i7hPK"  
  214.     "swcFdsn6MWwINP+Nwmw4AEPpVJevUEvRQbqVMVoLlw==";  
  215.   
  216. /* 
  217.  * Checkup routine 
  218.  */  
  219. int base64_self_test( int verbose )  
  220. {  
  221.     size_t len;  
  222.     const unsigned char *src;  
  223.     unsigned char buffer[128];  
  224.   
  225.     if( verbose != 0 )  
  226.         printf( "  Base64 encoding test: " );  
  227.   
  228.     len = sizeof( buffer );  
  229.     src = base64_test_dec;  
  230.   
  231.     if( base64_encode( buffer, &len, src, 64 ) != 0 ||  
  232.          memcmp( base64_test_enc, buffer, 88 ) != 0 )  
  233.     {  
  234.         if( verbose != 0 )  
  235.             printf( "failed\n" );  
  236.   
  237.         return( 1 );  
  238.     }  
  239.   
  240.     if( verbose != 0 )  
  241.         printf( "passed\n  Base64 decoding test: " );  
  242.   
  243.     len = sizeof( buffer );  
  244.     src = base64_test_enc;  
  245.   
  246.     if( base64_decode( buffer, &len, src, 88 ) != 0 ||  
  247.          memcmp( base64_test_dec, buffer, 64 ) != 0 )  
  248.     {  
  249.         if( verbose != 0 )  
  250.             printf( "failed\n" );  
  251.   
  252.         return( 1 );  
  253.     }  
  254.   
  255.     if( verbose != 0 )  
  256.         printf( "passed\n\n" );  
  257.   
  258.     return( 0 );  
  259. }  
  260.   
  261. #endif  
  262.   
  263. #endif  
/*
 *  RFC 1521 base64 encoding/decoding
 *
 *  Copyright (C) 2006-2013, Brainspark B.V.
 *
 *  This file is part of PolarSSL (http://www.polarssl.org)
 *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
 *
 *  All rights reserved.
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License along
 *  with this program; if not, write to the Free Software Foundation, Inc.,
 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#define POLARSSL_BASE64_C
#define POLARSSL_SELF_TEST

#if defined(POLARSSL_BASE64_C)

#include "base64.h"

#if defined(_MSC_VER) && !defined(EFIX64) && !defined(EFI32)
#include <basetsd.h>
typedef UINT32 uint32_t;
#else
#include <inttypes.h>
#endif

static const unsigned char base64_enc_map[64] =
{
    'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
    'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
    'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd',
    'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
    'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
    'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7',
    '8', '9', '+', '/'
};

static const unsigned char base64_dec_map[128] =
{
    127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
    127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
    127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
    127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
    127, 127, 127,  62, 127, 127, 127,  63,  52,  53,
     54,  55,  56,  57,  58,  59,  60,  61, 127, 127,
    127,  64, 127, 127, 127,   0,   1,   2,   3,   4,
      5,   6,   7,   8,   9,  10,  11,  12,  13,  14,
     15,  16,  17,  18,  19,  20,  21,  22,  23,  24,
     25, 127, 127, 127, 127, 127, 127,  26,  27,  28,
     29,  30,  31,  32,  33,  34,  35,  36,  37,  38,
     39,  40,  41,  42,  43,  44,  45,  46,  47,  48,
     49,  50,  51, 127, 127, 127, 127, 127
};

/*
 * Encode a buffer into base64 format
 */
int base64_encode( unsigned char *dst, size_t *dlen,
                   const unsigned char *src, size_t slen )
{
    size_t i, n;
    int C1, C2, C3;
    unsigned char *p;

    if( slen == 0 )
        return( 0 );

    n = (slen << 3) / 6;

    switch( (slen << 3) - (n * 6) )
    {
        case  2: n += 3; break;
        case  4: n += 2; break;
        default: break;
    }

    if( *dlen < n + 1 )
    {
        *dlen = n + 1;
        return( POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL );
    }

    n = (slen / 3) * 3;

    for( i = 0, p = dst; i < n; i += 3 )
    {
        C1 = *src++;
        C2 = *src++;
        C3 = *src++;

        *p++ = base64_enc_map[(C1 >> 2) & 0x3F];
        *p++ = base64_enc_map[(((C1 &  3) << 4) + (C2 >> 4)) & 0x3F];
        *p++ = base64_enc_map[(((C2 & 15) << 2) + (C3 >> 6)) & 0x3F];
        *p++ = base64_enc_map[C3 & 0x3F];
    }

    if( i < slen )
    {
        C1 = *src++;
        C2 = ((i + 1) < slen) ? *src++ : 0;

        *p++ = base64_enc_map[(C1 >> 2) & 0x3F];
        *p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F];

        if( (i + 1) < slen )
             *p++ = base64_enc_map[((C2 & 15) << 2) & 0x3F];
        else *p++ = '=';

        *p++ = '=';
    }

    *dlen = p - dst;
    *p = 0;

    return( 0 );
}

/*
 * Decode a base64-formatted buffer
 */
int base64_decode( unsigned char *dst, size_t *dlen,
                   const unsigned char *src, size_t slen )
{
    size_t i, n;
    uint32_t j, x;
    unsigned char *p;

    for( i = n = j = 0; i < slen; i++ )
    {
        if( ( slen - i ) >= 2 &&
            src[i] == '\r' && src[i + 1] == '\n' )
            continue;

        if( src[i] == '\n' )
            continue;

        if( src[i] == '=' && ++j > 2 )
            return( POLARSSL_ERR_BASE64_INVALID_CHARACTER );

        if( src[i] > 127 || base64_dec_map[src[i]] == 127 )
            return( POLARSSL_ERR_BASE64_INVALID_CHARACTER );

        if( base64_dec_map[src[i]] < 64 && j != 0 )
            return( POLARSSL_ERR_BASE64_INVALID_CHARACTER );

        n++;
    }

    if( n == 0 )
        return( 0 );

    n = ((n * 6) + 7) >> 3;

    if( dst == NULL || *dlen < n )
    {
        *dlen = n;
        return( POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL );
    }

   for( j = 3, n = x = 0, p = dst; i > 0; i--, src++ )
   {
        if( *src == '\r' || *src == '\n' )
            continue;

        j -= ( base64_dec_map[*src] == 64 );
        x  = (x << 6) | ( base64_dec_map[*src] & 0x3F );

        if( ++n == 4 )
        {
            n = 0;
            if( j > 0 ) *p++ = (unsigned char)( x >> 16 );
            if( j > 1 ) *p++ = (unsigned char)( x >>  8 );
            if( j > 2 ) *p++ = (unsigned char)( x       );
        }
    }

    *dlen = p - dst;

    return( 0 );
}

#if defined(POLARSSL_SELF_TEST)

#include <string.h>
#include <stdio.h>

static const unsigned char base64_test_dec[64] =
{
    0x24, 0x48, 0x6E, 0x56, 0x87, 0x62, 0x5A, 0xBD,
    0xBF, 0x17, 0xD9, 0xA2, 0xC4, 0x17, 0x1A, 0x01,
    0x94, 0xED, 0x8F, 0x1E, 0x11, 0xB3, 0xD7, 0x09,
    0x0C, 0xB6, 0xE9, 0x10, 0x6F, 0x22, 0xEE, 0x13,
    0xCA, 0xB3, 0x07, 0x05, 0x76, 0xC9, 0xFA, 0x31,
    0x6C, 0x08, 0x34, 0xFF, 0x8D, 0xC2, 0x6C, 0x38,
    0x00, 0x43, 0xE9, 0x54, 0x97, 0xAF, 0x50, 0x4B,
    0xD1, 0x41, 0xBA, 0x95, 0x31, 0x5A, 0x0B, 0x97
};

static const unsigned char base64_test_enc[] =
    "JEhuVodiWr2/F9mixBcaAZTtjx4Rs9cJDLbpEG8i7hPK"
    "swcFdsn6MWwINP+Nwmw4AEPpVJevUEvRQbqVMVoLlw==";

/*
 * Checkup routine
 */
int base64_self_test( int verbose )
{
    size_t len;
    const unsigned char *src;
    unsigned char buffer[128];

    if( verbose != 0 )
        printf( "  Base64 encoding test: " );

    len = sizeof( buffer );
    src = base64_test_dec;

    if( base64_encode( buffer, &len, src, 64 ) != 0 ||
         memcmp( base64_test_enc, buffer, 88 ) != 0 )
    {
        if( verbose != 0 )
            printf( "failed\n" );

        return( 1 );
    }

    if( verbose != 0 )
        printf( "passed\n  Base64 decoding test: " );

    len = sizeof( buffer );
    src = base64_test_enc;

    if( base64_decode( buffer, &len, src, 88 ) != 0 ||
         memcmp( base64_test_dec, buffer, 64 ) != 0 )
    {
        if( verbose != 0 )
            printf( "failed\n" );

        return( 1 );
    }

    if( verbose != 0 )
        printf( "passed\n\n" );

    return( 0 );
}

#endif

#endif

  1. # Copyright (C) 2008 The Android Open Source Project  
  2. #  
  3. # Licensed under the Apache License, Version 2.0 (the "License");  
  4. # you may not use this file except in compliance with the License.  
  5. # You may obtain a copy of the License at  
  6. #  
  7. #      http://www.apache.org/licenses/LICENSE-2.0  
  8. #  
  9. # Unless required by applicable law or agreed to in writing, software  
  10. # distributed under the License is distributed on an "AS IS" BASIS,  
  11. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  
  12. # See the License for the specific language governing permissions and  
  13. # limitations under the License.  
  14.   
  15. LOCAL_PATH:= $(call my-dir)  
  16.   
  17. dex_src_files := \  
  18.     CmdUtils.cpp \  
  19.     DexCatch.cpp \  
  20.     DexClass.cpp \  
  21.     DexDataMap.cpp \  
  22.     DexDebugInfo.cpp \  
  23.     DexFile.cpp \  
  24.     DexInlines.cpp \  
  25.     DexOptData.cpp \  
  26.     DexOpcodes.cpp \  
  27.     DexProto.cpp \  
  28.     DexSwapVerify.cpp \  
  29.     DexUtf.cpp \  
  30.     InstrUtils.cpp \  
  31.     Leb128.cpp \  
  32.     OptInvocation.cpp \  
  33.     sha1.cpp \  
  34.     SysUtil.cpp \  
  35.     ZipArchive.cpp\  
  36.     base64.c  
  37.   
  38. dex_include_files := \  
  39.     dalvik \  
  40.     external/zlib \  
  41.     external/safe-iop/include  
  42.   
  43. ##  
  44. ##  
  45. ## Build the device version of libdex  
  46. ##  
  47. ##  
  48. ifneq ($(SDK_ONLY),true)  # SDK_only doesn't need device version  
  49.   
  50. include $(CLEAR_VARS)  
  51. LOCAL_CFLAGS += -DCODE_DVM -fpermissive  
  52. LOCAL_CXXFLAGS += -DCODE_DVM -fpermissive  
  53. LOCAL_CPPFLAGS += -DCODE_DVM -fpermissive  
  54. #LOCAL_CFLAGS += -UNDEBUG -DDEBUG=1  
  55. LOCAL_SRC_FILES := $(dex_src_files)  
  56. LOCAL_C_INCLUDES += $(dex_include_files)  
  57. LOCAL_STATIC_LIBRARIES := liblog  
  58. LOCAL_MODULE_TAGS := optional  
  59. LOCAL_MODULE := libdex  
  60. include $(BUILD_STATIC_LIBRARY)  
  61.   
  62. endif # !SDK_ONLY  
  63.   
  64.   
  65. ##  
  66. ##  
  67. ## Build the host version of libdex  
  68. ##  
  69. ##  
  70. include $(CLEAR_VARS)  
  71. LOCAL_CFLAGS += -DCODE_DVM  
  72. LOCAL_CXXFLAGS += -DCODE_DVM -fpermissive  
  73. LOCAL_CPPFLAGS += -DCODE_DVM -fpermissive  
  74. LOCAL_SRC_FILES := $(dex_src_files)  
  75. LOCAL_C_INCLUDES += $(dex_include_files)  
  76. LOCAL_STATIC_LIBRARIES := liblog  
  77. LOCAL_MODULE_TAGS := optional  
  78. LOCAL_MODULE := libdex  
  79. include $(BUILD_HOST_STATIC_LIBRARY)  
# Copyright (C) 2008 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

LOCAL_PATH:= $(call my-dir)

dex_src_files := \
	CmdUtils.cpp \
	DexCatch.cpp \
	DexClass.cpp \
	DexDataMap.cpp \
	DexDebugInfo.cpp \
	DexFile.cpp \
	DexInlines.cpp \
	DexOptData.cpp \
	DexOpcodes.cpp \
	DexProto.cpp \
	DexSwapVerify.cpp \
	DexUtf.cpp \
	InstrUtils.cpp \
	Leb128.cpp \
	OptInvocation.cpp \
	sha1.cpp \
	SysUtil.cpp \
	ZipArchive.cpp\
	base64.c

dex_include_files := \
	dalvik \
	external/zlib \
	external/safe-iop/include

##
##
## Build the device version of libdex
##
##
ifneq ($(SDK_ONLY),true)  # SDK_only doesn't need device version

include $(CLEAR_VARS)
LOCAL_CFLAGS += -DCODE_DVM -fpermissive
LOCAL_CXXFLAGS += -DCODE_DVM -fpermissive
LOCAL_CPPFLAGS += -DCODE_DVM -fpermissive
#LOCAL_CFLAGS += -UNDEBUG -DDEBUG=1
LOCAL_SRC_FILES := $(dex_src_files)
LOCAL_C_INCLUDES += $(dex_include_files)
LOCAL_STATIC_LIBRARIES := liblog
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE := libdex
include $(BUILD_STATIC_LIBRARY)

endif # !SDK_ONLY


##
##
## Build the host version of libdex
##
##
include $(CLEAR_VARS)
LOCAL_CFLAGS += -DCODE_DVM
LOCAL_CXXFLAGS += -DCODE_DVM -fpermissive
LOCAL_CPPFLAGS += -DCODE_DVM -fpermissive
LOCAL_SRC_FILES := $(dex_src_files)
LOCAL_C_INCLUDES += $(dex_include_files)
LOCAL_STATIC_LIBRARIES := liblog
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE := libdex
include $(BUILD_HOST_STATIC_LIBRARY)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值