记录IDA动态调试进行APK脱壳流程

时间:2024-10-25 11:39:55

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类型的二级指针,具体表示什么,我也不知道
脱壳只用到 addr 和 len 这两个参数,所以需要获取 R0 和 R1 寄存器的值(ARM的传递参数机制规定 R0 保存着函数从左至右的第一个参数,R1 保存着函数从左至右的第二个参数)