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 *)¶m); //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); } |