这篇文章上次修改于 225 天前,可能其部分内容已经发生变化,如有疑问可询问作者。

安卓中base.odex文件本质上是一个ELF文件,由系统对原本的apk优化所生成

在使用stackplz打印堆栈的时候,有一些栈是base.odex的,同时也能看到有boot.oat的,也就是说如果用stackplz对odex或者oat下断,也是能用来打印一些内容的

比如搞清楚有些方法到底有没有被调用,堆栈情况;当然直接打印参数是不太现实的,但有个曲折的方法,定位到native操作数据的地方...

不过有个问题,怎么知道java方法在odex/oat中的偏移呢?

stackplz能解析到信息,是因为libunwindstack从odex/oat中解析了信息,这些信息位于odex/oat的.gun_debugdata部分,然而直接使用IDA打开odex/oat却不能解析出来java方法有关的信息

如何处理?

  1. 用7z打开odex/oat文件,直接把.gun_debugdata的内容解压出来
  2. 根据实测,解压出来后是xz压缩的内容,所以再用7z解压一次
  3. 上一步会得到一个elf文件,这个时候再用IDA去解析,就可以看到java方法在odex/oat中的偏移情况了

tips: 后面的数字是函数大小

2024-04-01T07:28:10.png

到这一步基本上够用了,拿到这些偏移,就可以对对应的文件下断了

如果还想把这些符号信息合并到odex/oat怎么办呢,也就是方便在IDA中直接查看?

一个方法是,把gun_debugdata最后提取的elf信息导出,也就是

  • File -> Produce file -> Dump database to IDC file

这样会生成一个idc文件,保留idc文件中有关set_name的调用即可

然后IDA打开odex/oat后,再选择File -> Script File执行修改后的idc脚本即可

#!/bin/bash
# 1. use 7z unzip .odex file .gun_debugdata section
# 2. use 7z unzip .gun_debugdata section file (xz format)
# 3. use IDA load unzipped file, then File -> Produce file -> Dump database to IDC file
# 4. ./gen_set_name_idc.sh input.idc odex_use.idc
# 5. use IDA open odex/oat file, then File -> Script File to load odex_use.idc

gun_debugdata_xz_unzipped="$1"

idcname="$2"

cat > $idcname << EOF
#include <idc.idc>
static main() {
EOF
grep 'set_name' $gun_debugdata_xz_unzipped >> $idcname
echo "}" >> $idcname

效果如下:

2024-04-01T07:37:02.png

要更完整还需要进一步创建函数等等...