0x00前言
一个安卓应用可以被调试的条件是应用AndroidManifest.xml显示指定android:debuggable="true",如果没有设置android:debuggable的值,则默认android:debuggable="false",所以发布的应用大部分都是不可调试的,如果要调试,则需要解包,改属性然后重打包,这样非常麻烦,而且效率低。第二个条件是内核配置文件default.prop的属性ro.debuggable=1,这样就不用管应用里面设置的属性了,看来是一个比较好的解决方案,我们只要修改一次内核就可以一劳永逸了。
安卓应用程序常用的一种反调试手段是查看/proc/[pid]/status下的信息,如果处于调试状态,那么TracerPid的值就是调试进程的Pid,那么程序就会做出相应的行为来反调试。
0x01提取内核
查看boot所在的分区
ls -l /dev/block/platform/msm_sdcc.1/by-name
提取内核
dd if= /dev/block/mmcblk0p17 of=/data/local/boot.img adb pull /data/local/boot.img boot.img
解包内核
bootimg.exe --unpack-bootimg
解包之后的文件结构
0x02修改ro.debuggable
修改initrd/default.prop文件中的ro.debuggable=1
0x03修改kernel文件
复制一份kernel为zImage.gz方便后面的修改
用010editor打开zImage.gz查找十六进制1F 8B 08 00,删除前面的所有数据,使文件变成一个标准的gzip压缩文件,这样就可以使用gunzip解包了。
gunzip zImage.gz
解包生成的zImage就是内核二进制文件了。
用IDA打开文件,设置处理器类型为ARM Little-endian
设置ROM start address和Loading address为0xc0008000
在安卓root终端关闭符号屏蔽
echo 0 > /proc/sys/kernel/kptr_restrict
查看proc_pid_status和__task_pid_nr_ns函数地址
cat /proc/kallsyms | grep proc_pid_status
cat /proc/kallsyms | grep __task_pid_nr_ns
为什么要查找这两个函数呢,我们根据源码/kernel/msm/fs/proc/array.c来看一下
函数proc_pid_status内联了task_state函数,在task_state内联函数里面通过函数__task_pid_nr_ns 获取到tracerpid并且打印出来。
在IDA中按快捷键g跳转到函数c0187f88(__task_pid_nr_ns)函数处,按x出来引用搜索框,在其中找到函数c02764b8(proc_pid_status)
查看局部的调用为
可以看到调用的结果会存储在R11中,所以修改命令MOV R11, R0为MOV R11, #0,机器码为00 B0 A0 E3,文件的偏移为(0xC02765F8-0xC0008000= 26E5F8)
重新压缩zImage
gzip -n -f -9 zImage
用010editor添加原kernel的首部和尾部二进制数据到文件zImage.gz(新的zImage.gz文件必须比原zImage.gz文件小,并且回写回去时不能改变原kernel文件的大小及修改原kernel文件后面的内容,否则会很麻烦),这时得到了kernel文件。
添加首部3DEB长的数据
先占位,然后复制首部的数据到头部
添加尾部数据
替换原先的kernel文件,重新生成新的boot.img
bootimg.exe --repack-bootimg
0x04刷入新的内核
手机重启到bootloader模式
adb reboot bootloader
刷入新的boot
fastboot flash boot boot-new.img
重启
fastboot reboot
如果手机开不了机,那么重新刷回老的内核
fastboot flash boot boot-old.img
0x05SELinux导致IDA无法调试
在安卓端以root权限启动andorid_server之后,并在本机做端口转发,IDA可以正常列出可调试的应用列表,但是当选择某个程序的时候就会出现如下错误
The debugger could not attach to the selected process.
This can perhaps indicate the process was just terminated, or that you dot‘t have the necessary privileges.
关闭SELinux,之后就正常了,不知道是不是MIUI独家的问题。
检测SELinux是否打开
getenforce
返回值:Enforcing:强制模式 Permissive:宽容模式 Disabled:关闭
临时关闭SELinux
setenforce 0
0为关闭,1为打开,执行后立即生效,无需重启
0x06小结
工欲善其事,必先利其器,有一个基本的调试环境对逆向学习是非常有帮助的。因为很多的手机产商没有将手机系统源代码放出,所以只能采取逆向内核的方式进行修改,如果手机厂商有把系统的源代码放出,那么从源码编译将会更具有修改性,可以定制更多的内核特性。如果手机有开源的安卓系统支持,比如lineage os或者CM的支持,也可以选择这些优秀的开源代码来编译。
参考:
Android逆向之旅—应用的”反调试”方案解析(附加修改IDA调试端口和修改内核信息)
[原创]支持windows下打包boot/recovery.img的bootimg.exe,且支持自动解包/打包dt.img,加入MTK机型支持