安卓 dex 通用脱壳技术研究(四)

http://my.oschina.net/cve2015/blog/508919


摘要  本文剖析安卓 Dalvik 解释器 Portable 的原理与实现,并通过修改 Dalvik 虚拟机实现 dex 文件的通用脱壳方案;本方法同样适应于 ART 虚拟机;

?
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
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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
/*
     当第一个类执行到此函数时,我们在dvmDefineClass执行之前,也就是第一个类加载之前
     注入我们的dump代码;即DumpClass()函数
*/
 
static  void  Dalvik_dalvik_system_DexFile_defineClassNative( const  u4* args,
     JValue* pResult)
{
     StringObject* nameObj = (StringObject*) args[0];
     Object* loader = (Object*) args[1];
     int  cookie = args[2];
     ClassObject* clazz = NULL;
     DexOrJar* pDexOrJar = (DexOrJar*) cookie;
     DvmDex* pDvmDex;
     char * name;
     char * descriptor;
 
     name = dvmCreateCstrFromString(nameObj);
     descriptor = dvmDotToDescriptor(name);
     ALOGV( "--- Explicit class load '%s' l=%p c=0x%08x" ,
         descriptor, loader, cookie);
     free (name);
 
     if  (!validateCookie(cookie))
         RETURN_VOID();
 
     if  (pDexOrJar->isDex)
         pDvmDex = dvmGetRawDexFileDex(pDexOrJar->pRawDexFile);
     else
         pDvmDex = dvmGetJarFileDex(pDexOrJar->pJarFile);
 
     /* once we load something, we can't unmap the storage */
     pDexOrJar->okayToFree =  false ;
 
//------------------------added begin----------------------//
     int  uid=getuid();
 
     if  (uid) {
         if  (readable) {
             pthread_mutex_lock(&read_mutex);
             if  (readable) {
                 readable= false ;
                 pthread_mutex_unlock(&read_mutex);
 
                 pthread_t read_thread;
                 pthread_create(&read_thread, NULL, ReadThread, NULL);
 
             } else {
                 pthread_mutex_unlock(&read_mutex);
             }
         }
     }
 
     //每个APP都对应一个Thread
     if (uid &&  strcmp (dexname, "" )) {  //dexname非空
         char  * res= strstr (pDexOrJar->fileName, dexname);
         if  (res && flag) {
             pthread_mutex_lock(&mutex);
             if  (flag) {
                 flag =  false ;
                 pthread_mutex_unlock(&mutex);
  
                 DexFile* pDexFile=pDvmDex->pDexFile;     //取dex file
                 MemMapping * mem=&pDvmDex->memMap;   //取memmory map 
//part1区,classdef前内容
                 char  * temp= new  char [100];
                 strcpy (temp,dumppath);
                 strcat (temp, "part1" );
                 FILE  *fp =  fopen (temp,  "wb+" );
                 const  u1 *addr = ( const  u1*)mem->addr;
                 int  length= int (pDexFile->baseAddr+pDexFile->pHeader->classDefsOff-addr);
                 fwrite (addr,1,length,fp);
                 fflush (fp);
                 fclose (fp);
//data区,classdef后内容
                 strcpy (temp,dumppath);
                 strcat (temp, "data" );
                 fp =  fopen (temp,  "wb+" );
                 addr = pDexFile->baseAddr+pDexFile->pHeader->classDefsOff+ sizeof (DexClassDef)*pDexFile->pHeader->classDefsSize;
                 length= int (( const  u1*)mem->addr+mem->length-addr);
                 fwrite (addr,1,length,fp);
                 fflush (fp);
                 fclose (fp);
                 delete  temp;
 
                 param.loader=loader;
                 param.pDvmDex=pDvmDex;
 
                 pthread_t dumpthread;
                 dvmCreateInternalThread(&dumpthread, "ClassDumper" ,DumpClass,( void *)&param);      
//DumpClass用来生成classdef 和 extra内容                
 
             } else {
                 pthread_mutex_unlock(&mutex);
             }
         }
     }
//------------------------added end----------------------//
 
     clazz = dvmDefineClass(pDvmDex, descriptor, loader);     //加载类。当APP第一个类加载之前,调用我们的脱壳代码
     Thread* self = dvmThreadSelf();
     if  (dvmCheckException(self)) {
         /*
          * If we threw a "class not found" exception, stifle it, since the
          * contract in the higher method says we simply return null if
          * the class is not found.
          */
         Object* excep = dvmGetException(self);
         if  ( strcmp (excep->clazz->descriptor,
                    "Ljava/lang/ClassNotFoundException;" ) == 0 ||
             strcmp (excep->clazz->descriptor,
                    "Ljava/lang/NoClassDefFoundError;" ) == 0)
         {
             dvmClearException(self);
         }
         clazz = NULL;
     }
 
     free (descriptor);
     RETURN_PTR(clazz);
}

猜你喜欢

转载自blog.csdn.net/problc/article/details/48756613