0%

逆向修改安卓内核 x64 过TracerPID反调试

建议在git bash下操作

由于解压kernel.gz时使用的不是命令行,导致没有看到输出信息gzip trailing garbage ignored,进而没有对这些数据进行处理,浪费了很多时间。

概述

直接修改内核,降维打击绕过反调试。
如果有内核源码以及环境,当然可以通过直接修改源码的方式生成boot.img
在无内核源码(或者还没配置安卓源码编译环境)的情况下则只能通过逆向来修改内核。

环境

Redmi Note 3, arm64, cm12.1

过程

1. 找到并导出boot.img

进入adb shell并执行su命令获取root权限(platform下文件夹可能会有所不同,即可能不是mtk-msdc.0)

1
ls -al /dev/block/platform/mtk-msdc.0/by-name

根据输出信息boot -> /dev/block/mmcblk0p7得知boot对应该mmcblk0p7
dd大法导出该文件

1
2
dd if=/dev/block/mmcblk0p7 of=/data/local/boot.img
adb pull /data/local/boot.img boot.img

2. 解包boot.img以及内核

此处使用的是bootimg工具(下载地址),创建一个临时文件夹,执行./bootimg.exe --unpack-bootimg .\boot.img,再解压kernel.gz得到内核文件
强烈建议在git bash下使用gzip -d解压,这样才能查看具体的输出信息
输出gzip trailing garbage ignored(尾部垃圾被忽略处理)
gzip认为这是尾部垃圾,实际上却是必要的数据,不考虑的话可能会导致无限重启。

收集尾部数据

解压kernel.gz后重新压缩内核文件,得到没有尾部数据的真实kernel.gz
再通过010Editor在原kernel.gz中,查找真实kernel.gz文件尾(一般四个字节就只有一个结果了),定位到尾部这段数据,保存下来

3. 使用IDA64反编译

processor type选择ARM Little-endian
弹出来一个提示框,点击确定,然后输入ROM start addressLoading address为内核基址:0xffffffc000080000

4.修改内核文件

方法1 修改TracerPid的格式字符串

(该思路来自逆向修改内核,绕过TracerPID反调试
使用010Editor打开内核文件,搜索TracerPid,修改TracerPid后的第一个 "%d"
改成 "0\t" (30 09) 或 "0\n" (30 10) 或 "00" (十六进制30 30)

方法2 修改proc_pid_status函数指令

查看函数地址
1
2
3
echo 0 > /proc/sys/kernel/kptr_restrict
cat /proc/kallsyms |grep proc_pid_status
cat /proc/kallsyms |grep __task_pid_nr_ns

输出为

1
2
ffffffc0001f7aa8 T proc_pid_status
ffffffc0000bb1f0 T __task_pid_nr_ns
定位函数及patch

在ida中按g跳转到ffffffc0000bb1f0(task_pid_nr_ns),按p解析函数
再按g跳转到ffffffc0001f7aa8(proc_pid_status),按p解析函数
然后回到ffffffc0000bb1f0(task_pid_nr_ns),按x查看交叉引用,发现已经有ffffffc0001f7aa8(proc_pid_status)调用的信息了
双击进入,在IDA View视图中定位到关键指令

1
2
3
4
MOV W1, W25
MOV X2, X19
BL sub_FFFFFFC0000BB1F0
MOV W25, W0

修改往前第两条和后一条的mov指令(可使用KeyPatch插件),结果为

1
2
3
4
MOV W1, #0
MOV X2, X19
BL sub_FFFFFFC0000BB1F0
MOV W25, #0

对应机器码为01 00 80 5219 00 80 52

5. gzip压缩内核

git bash下使用gzip压缩修改后的内核文件

1
gzip -n -f -9 kernel

6. 重打包boot.img

方法1 使用bootimg打包(推荐)

使用010Editor编辑刚刚生成的kernel.gz,添加上之前获取的尾部数据
然后执行./bootimg.exe --repack-bootimg得到的boot-new.img文件,刷入即可

方法2 手动写入boot.img

使用010Editor分别打开kernel.gzboot.img,搜索1F 8B 08 00,定位到内核gzip位置(一般是0x800,不确定的话可以打开原本kernel.gz对比)

压缩后大小<=真实kernel.gz时

按下insert键,将010改为overwrite(右下角有提示)
然后把kernel.gz的内容复制到boot.img的相应位置,保存即可
(根据引用文章所说,小于的话可以直接不考虑后面的字节)

压缩后大小>真实kernel.gz时

按下insert键,将010改为insert(右下角有提示)
选定真实kernel.gz部分(即不包括之前获取的尾部数据)
然后把kernel.gz的内容复制到boot.img的相应位置,保存即可

6. 使用fastboot刷入

使用adb reboot bootloader重启到fastboot
然后执行

1
2
fastboot flash boot boot.img
fastboot reboot

如果成功的话就直接正常开机了,失败的话看看是不是修改错了内核文件的内容,从原内核开始修改,再次尝试

参考

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