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解包了。
解包生成的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
用010editor添加原kernel的首部和尾部二进制数据到文件zImage.gz(新的zImage.gz文件必须比原zImage.gz文件小,并且回写回去时不能改变原kernel文件的大小及修改原kernel文件后面的内容,否则会很麻烦),这时得到了kernel文件。
添加首部3DEB长的数据
先占位,然后复制首部的数据到头部
添加尾部数据
替换原先的kernel文件,重新生成新的boot.img
bootimg.exe --repack-bootimg
0x04刷入新的内核
手机重启到bootloader模式
刷入新的boot
fastboot flash boot boot-new.img
重启
如果手机开不了机,那么重新刷回老的内核
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是否打开
返回值:Enforcing:强制模式 Permissive:宽容模式 Disabled:关闭
临时关闭SELinux
0为关闭,1为打开,执行后立即生效,无需重启
0x06小结
工欲善其事,必先利其器,有一个基本的调试环境对逆向学习是非常有帮助的。因为很多的手机产商没有将手机系统源代码放出,所以只能采取逆向内核的方式进行修改,如果手机厂商有把系统的源代码放出,那么从源码编译将会更具有修改性,可以定制更多的内核特性。如果手机有开源的安卓系统支持,比如lineage os或者CM的支持,也可以选择这些优秀的开源代码来编译。
参考:
逆向修改手机内核,绕过反调试
Android逆向之旅—应用的”反调试”方案解析(附加修改IDA调试端口和修改内核信息)
[原创]支持windows下打包boot/recovery.img的bootimg.exe,且支持自动解包/打包dt.img,加入MTK机型支持
Android反调试笔记
记录下android SELinux造成ida无法调试
修改Android手机内核,绕过反调试