逆向修改MIUI(X64)内核,反制TracerPID反调试踩坑指南

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

mtk-msdc.0不同的机型是不一样的,但是platform下一般就只有一个文件夹,很容易就能找出。

dd if=/dev/block/mmcblk0p7 of=/data/local/boot.img
exit
adb pull /data/local/boot.img e:\boot.img

在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 

如果不清到底应该用哪个也没关系

回到adb shell 中

echo 0 > /proc/sys/kernel/kptr_restrict
cat /proc/kallsyms |grep proc_pid_status
cat /proc/kallsyms |grep __task_pid_nr_ns

记录下这两个重要的地址,从地址也可以看出应该使用哪个基址。用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

重打包成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

万一手抖引起的修改失误引发了无限重启,只需用上述命令重刷原版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 “逆向修改手机内核,绕过反调试”

感谢上述文章作者的无私分享。

猜你喜欢

转载自blog.csdn.net/druke/article/details/80502571