版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/Druke/article/details/80502571
0x00、前言
刷CTF时经常能遇到TracerPID反调试,手动nop掉当然是一种好方法,但是每次都得重新打包难免会觉得烦躁。正好在逛吾爱时发现一篇patch内核绕过反调试的文章,果断尝试一番,于是有了这篇X64版本的patch内核踩坑指南。
本次踩坑环境Redmi Note2 ,MIUI 9 8.4.19 |开发版 ,Android 5.0.2 。
0x01、boot.img 提取
方案一、adb
adb shell
cd /dev/block/platform/mtk-msdc.0/by-name
1
2
mtk-msdc.0不同的机型是不一样的,但是platform下一般就只有一个文件夹,很容易就能找出。
dd if=/dev/block/mmcblk0p7 of=/data/local/boot.img
exit
adb pull /data/local/boot.img e:\boot.img
1
2
3
在E盘就能找到提取出来的boot.img。
方案二、Flashify
什么?你说你是手残党,觉得手动提取boot.img太麻烦,那我们可以使用Flashify来提取。只需安装Flashify,在BACKUP/RESTORE下就可以一键备份内核。
备份后pull到电脑就可以操作了。
两种方式都必须拥有root权限。
0x02、解包boot.img提取zImage
方案一、bootimg-tools 、mkbootimg
在Linux下可以使用mkbootimg 或bootimg-tools来解包boot.img。以下解包操作引用自文章《逆向修改内核,绕过TracerPID反调试》。
bootimg-tools工具是一款基于mkbootimg开发的boot.img 解包重打包C语言工具
github地址:https://github.com/pbatard/bootimg-tools
git clone https://github.com/pbatard/bootimg-tools.git
下载后进入bootimg-tools目录,执行make 命令编译该项目,在 makebootimg目录下生成了相应的二进制执行文件。
解包
将kernel文件复制为文件名为zImage.gz的文件,并使用010editor查找十六进制1f 8b 08 00,找到后把前面的数据全删掉,使文件变成标准的gzip压缩文件,这样子就可以使用gunzip解压了。
命令:gunzip zImage.gz
生成文件就是祼二进制文件zImage。
方案二、Android Image Kitchen
如果是在Windows下的话可以使用Android Image Kitchen。该工具使用非常简单,下载并解压该工具后只需将boot.img拖入unpacking.bak即可解包。
在生成的split_img下即可找到boot.img-zImage(因为ROM的缘故,解包后该文件已经是标准的gz格式,可以直接解压,如果不是标准的,请参照方案一的 方式提取出gz后解压)。
使用解压软件直接将其解压即可得到zImage
解包的工具有跟多并且选择哪个无关紧要,三个解包工具我都尝试过,最终的结果都一样,纯看个人喜好。
0x03、Patch kernel
在修改内核前我们需要了解内核的基址。
32 bit: 0xC0008000
64 bit: 0xffffffc000080000
1
2
如果不清到底应该用哪个也没关系
回到adb shell 中
echo 0 > /proc/sys/kernel/kptr_restrict
cat /proc/kallsyms |grep proc_pid_status
cat /proc/kallsyms |grep __task_pid_nr_ns
1
2
3
记录下这两个重要的地址,从地址也可以看出应该使用哪个基址。用IDA打开我们刚提取出的zImage文件(此处我解压后的的文件名为boot),processor type 选择ARM Little-endian
之后更改ROM start address 和 Loading address为我们上面提到的内核基址。我的机型是64位的,所以选择0xffffffc000080000。
打开后左边Function窗一片空白。
但是不要方,向下一路摁c便可解析出函数
摁g跳转到0xffffffc0000bb488(__task_pid_nr_ns的地址)
选中sub_FFFFFFC0000BB488后摁x查看引用,search搜索ffffffc0001fb8a4(proc_pid_status的地址)。
然而IDA并没有分析出该函数
摁g跳转到ffffffc0001fb8a4(proc_pid_status的地址),之后摁p强制解析该函数。
之后g跳转回到0xffffffc0000bb488(__task_pid_nr_ns的地址),选中sub_FFFFFFC0000BB488后摁x查看引用,已经可以发现proc_pid_status对其的引用。
跟进去,经过分析找到需要修改的两个地方,应该修改为MOV W1, #0和MOV W25, #0
对应的16进制修改位置
0xFFFFFFC0001FBE90h-0xFFFFFFC000080000h=0x17BE90h
得出要修改的地址,用010Editor打开zImage文件,Ctrl+g跳转到17BE90,摁下insert转为overwrite模式修改上图两处。修改的机器码为 01 00 80 52 和 19 00 80 52。
如果你实在是手抖,看到十六进制就眼花,那么修改完后可以丢入IDA查看是否修改正确。
稳到不行(逃)
0x04、重新打包成boot.img
将修改后的zImage(此处我的文件名为boot)在Linux下用gzip
gzip -n -f -9 zImage
1
重打包成boot.gz。
boot.gz 必须比原来的boot.img-zImage小否则会造成不必要的麻烦。
此处有两种重新打包的方法。
方案一、覆盖boot.img-zImage
用010Editor同时打开原boot.img-zImage和boot.gz。记录下boot.gz的结束地址0x664C8A并复制boot.gz的全部内容,在boot.img-zImage跳转到该地址,摁下insert改为overwrite模式,选中该地址之前的全部数据之后粘贴覆盖。
结果如下,记得保存。
后面的内容千万不要动,后面的内容千万不要动,后面的内容千万不要动,之后就可以使用Android Image Kitchen中的repackimg.bat重新打包便可生成image-new.img,重命名为boot.img即可。
在这里会发现一个不是问题的问题,新生成boot.img比原来的boot.img小了一半,但是实测并不会影响使用。
方案二、覆盖原boot.img(强迫症福音)
此方案是为了解决上一个不是问题的问题而提出的,用010Editor同时打开原boot.img和boot.gz。在boot.img中搜索1F 8B 08 00 (gz的开头),会搜索出两个结果,一般是第一个,不放心的话可以用010Editor对照一下原boot.img-zImage。
回到boot.gz看到boot.gz结束地址是0x664C8A
所以我们修改到的最终地址是0x800h+0x664C8Ah=0x66548Ah
选中0x800h到0x66548Ah间的数据用boot.gz的数据覆盖,结果如下
后面的内容千万不要动,后面的内容千万不要动,后面的内容千万不要动…….保存即可。
此方法获得的boot.img和原版大小无异,极大地满足了强迫症的需求(大雾)
0x05、刷入boot.img
在刷入之前一定要记得备份原boot.img,刷入错误的boot.img虽说不会变砖,但是会无限重启。
刷入的方法有很多,强烈推荐使用fastboot 刷入。
fastboot flash boot boot.img
1
万一手抖引起的修改失误引发了无限重启,只需用上述命令重刷原版boot.img就可以解决。
当然Flashify,TWRP等工具也是可以刷入的,在此就不详细展开了,有兴趣的自己尝试。
最终IDA调试时的效果
于是便可解放双手,开心地刷CTF了(大雾)…….
参考链接:
ref[1]: https://www.52pojie.cn/thread-733981-1-1.html “逆向修改内核,绕过TracerPID反调试”
ref[2]: https://bbs.pediy.com/thread-207538.htm “逆向修改手机内核,绕过反调试”
感谢上述文章作者的无私分享。
————————————————
版权声明:本文为CSDN博主「Pyinal」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/Druke/article/details/80502571