1.启动IDA文件夹dbgsrv中的android_server 命令
2.端口转发
新开一个cmd进行端口转发:adb forward tcp:23946 tcp:23946
如果不进行端口转发,IDA将无法正常连接到端口23946
3.以调试模式启动应用
调试模式启动应用:adb shell am start -D -n 包名/MainActivity路径名
4.打开IDA附件进程
设置Debugger Option选项
根据包名找到想要调试的进程
在modules窗口中找到
双击打开,查找...dvmDexFileOpenPartial...方法,方法名很长。app加载Dex 文件的过程需要用到此方法
接下来就是运行jdb调试。假设859就是要调试的APP进程,先将进程转发到任意指定端口,然后启动jdb
接下来回到IDA界面,在...dvmDexFileOpenPartial...方法开始处下断点,然后启动程序进行调试
程序运行到断点处,通过查看寄存器的地址,最终可在内存中dump出真实的dex文件(后续补充详细内容)。
以下内容摘自****:
dvmDexOpenPartial 函数的定义:
[C++]
纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
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
|
[/size]
[size=16px]
/*[/size]
[size=16px]* Create a DexFile structure for a "partial" DEX. This is one that is in[/size]
[size=16px]* the process of being optimized. The optimization header isn't finished[/size]
[size=16px]* and we won't have any of the auxillary data tables, so we have to do[/size]
[size=16px]* the initialization slightly differently.[/size]
[size=16px]*[/size]
[size=16px]* Returns nonzero on error.[/size]
[size=16px]*/
[/size]
[size=16px]
int
dvmDexFileOpenPartial(
const
void
* addr,
int
len, DvmDex** ppDvmDex)[/size]
[size=16px]{[/size]
[size=16px] DvmDex* pDvmDex;[/size]
[size=16px] DexFile* pDexFile;[/size]
[size=16px]
int
parseFlags = kDexParseDefault;[/size]
[size=16px]
int
result = -1;[/size]
[size=16px]
/* -- file is incomplete, new checksum has not yet been calculated[/size]
[size=16px] if ()[/size]
[size=16px] parseFlags |= kDexParseVerifyChecksum;[/size]
[size=16px] */
[/size]
[size=16px] pDexFile = dexFileParse((u1*)addr, len, parseFlags);[/size]
[size=16px]
if
(pDexFile == NULL) {[/size]
[size=16px] ALOGE(
"DEX parse failed"
);[/size]
[size=16px]
goto
bail;[/size]
[size=16px] }[/size]
[size=16px] pDvmDex = allocateAuxStructures(pDexFile);[/size]
[size=16px]
if
(pDvmDex == NULL) {[/size]
[size=16px] dexFileFree(pDexFile);[/size]
[size=16px]
goto
bail;[/size]
[size=16px] }[/size]
[size=16px] pDvmDex->isMappedReadOnly =
false
;[/size]
[size=16px] *ppDvmDex = pDvmDex;[/size]
[size=16px] result = 0;[/size]
[size=16px]bail:[/size]
[size=16px]
return
result;[/size]
[size=16px]}[/size]
[size=16px
|
dvmDexFileOpenPartial 函数的原型如下所示:
int dvmDexFileOpenPartial(const void* addr, int len, DvmDex** ppDvmDex)
其中 addr表示Dex文件在内存中的起始地址,
len 表示Dex文件的大小,
ppDvmDex是一个指向DvmDex类型的二级指针,具体表示什么,我也不知道
int dvmDexFileOpenPartial(const void* addr, int len, DvmDex** ppDvmDex)
其中 addr表示Dex文件在内存中的起始地址,
len 表示Dex文件的大小,
ppDvmDex是一个指向DvmDex类型的二级指针,具体表示什么,我也不知道
脱壳只用到 addr 和 len 这两个参数,所以需要获取 R0 和 R1 寄存器的值(ARM的传递参数机制规定 R0 保存着函数从左至右的第一个参数,R1 保存着函数从左至右的第二个参数)