文章

android模拟器内核修改

android模拟器内核修改

B站教程 修改模拟器内核, 视频是安卓8, 我自己用的是安卓14, 全程在wsl下操作, 因为方便 建议整体看完再自己操作, 不要跟着我踩坑

root权限输入0接触内核函数地址保护

1
echo 0 > /proc/sys/kernel/kptr_restrict

查看函数地址的shell

1
cat /proc/kallsyms|grep proc_pid_status

记录关键函数地址

联想知识: 内核代码一般位于虚拟地址空间的高位, 这也忒高了, 任何一个进程的虚拟地址空间高达2G, 该函数就位于

1
2
ffffffffbd7148e0 T __cfi_proc_pid_status
ffffffffbd7148f0 T proc_pid_status

视频教程 06:23

视频教程 07:17 利用2进制编辑器删除 1F8B0800

没搞懂1F8B0800从哪儿来的, android-api-34内核确实有,且仅有一个 但明显不同于安卓8的 问了以下AI

手动修改android内核文件时, 为什么要手动查找1F8B0800这个hex字符? Qwen3-Max 在手动修改 Android 内核文件(如从 boot.img 中提取出的 kernel 或 zImage)时,查找十六进制字节序列 1F 8B 08 00 的目的是为了==定位内嵌的 gzip 压缩数据的起始位置==。这是因为在大多数 Android 设备中,Linux 内核是以 gzip 压缩格式打包进 zImage 的。

那就搞起, 就是为了gzip解压呗, 直接用wsl弄就得了. 不怼! 文件体积变化太大了, 作者的安卓8kernel才5485kb->5469kb 我的少了一大半了, 不应该啊 管他呢先解压再说 确实有问题, 拷贝内核文件改个名再来 ==AI提示==用如下命令看文件类型

1
file kernel

输出如下

根据你提供的 file 命令输出结果,你的 kernel 文件是一个 bzImage 格式的 Linux 内核镜像,版本为 6.1.23,适用于 x86_64 架构的 Android 系统。bzImage 是一种压缩格式的内核映像,通常用于 x86 架构,它包含了自解压代码和压缩后的内核数据。

确认这个文件确实存在自解压行为, 接着找自解压起点

==AI提示==用这个命令来看gzip起点

1
binwalk kernel

看来是用了新的压缩方式LZ4 那压缩起点就是42E0

再夸一下AI, 文件头也给对了, 后边也看到了熟悉的ELF魔数

这是我本地的android14搜索结果

那就安装LZ4来解压

1
sudo apt install lz4

我已经另存为kernel_1.lz4文件了

1
lz4 -d kernel_1.lz4 vmlinux

解压后,啧,看着就舒服, 一步一步向UP靠近 开始用IDA分析它

1
ffffffffbd7148f0

尴尬了这个位置, vmlinux文件没有这么长…, ida啥函数也没分析出来

==AI提示==先找内核代码段基址

1
adb shell cat /proc/kallsyms | grep -E ' T _stext$'

==AI提示==计算偏移

1
offset = 0xffffffffbd7148f0 - 0xffffffffbd400000 = 0x3148F0

接下来在IDA中找代码段基址, 看来代码段基址就在这儿咯

1
FFFFFFFF81000000

计算偏移 FFFF FFFF 8131 48F0 感觉不对劲 怎么是一个跳转?弄成函数看看 确实不对劲 跳到该函数看看 啥也没有, 尝试直接搜索关键字TracerPid: 珍妮马找到了 那就改呗 不敢改, 前后变量不一样, 先看看安卓8源码中的位置

再看看安卓14源码中的位置 源码没咋变, 但是为什么ida看到的不对呢???这几个常量都分开了, 尝试按x又叉不出来, 头痛 双击进去看看 再双击去看看, 似乎是找到了!!! F5看看函数(害羞) 三个参数还挺像 v113值的来源就行了 找关键函数sub_FFFFFFFF811DB0C0 看不懂了, 不是应该有什么return关键字么?那只能在原函数改值了? 原函数关键部分如下

1
2
3
4
5
6
7
  if ( v9 || (v103 = *(_QWORD *)(a4 + 1416)) == 0 )
    v10 = 0LL;//没有调试就是0
  else
    v10 = (int)sub_FFFFFFFF811DB0C0(v103, 0LL, a2);//应该是获取到调试者pid的函数
  v113 = v10;//交给v113
  ......
  sub_FFFFFFFF8149F420(a1, aTracerpid, v113);//从接口输出

改的姿势还挺多,2种, 我可以

  • 改if判断条件
  • 改v113=v10赋值语句

==我==提示: ALT + 方向键可以在历史光标中穿梭 上方工具栏-Options-General可以调节显示机器码 把这里nop掉, 就能直接走xor eax, eax, 然后tracerpid就是0了. 你看它的位置 别忘咯v113就是tracerpid的值, 也就是v10的值. 开始nop覆盖, 先找到它的位置FFFFFFFF8151498B 然后HexView中跳到这个位置, 按G可以触发跳转位置弹窗 查看字节码, 刚好是0F 85 D2 0A 00 00 直接用90覆盖(共6个字节) HexView是这样 观察前后汇编代码没变, 那就改对了. 改完后的关键伪代码就变成这样

1
2
3
4
5
unsigned __int64 v115; // [rsp+38h] [rbp-50h]
  ......
  v115 = 0LL;
  ......
  sub_FFFFFFFF8149F420(a1, aTracerpid, v115);

保存吧 照样用lz4压缩回去

1
lz4 vmlinux kernel_1_p.lz4

我就改了6个字节, 这变化有亿点点大 拐火, 文件头不一样

==AI提示==看来得指定压缩算法

1
lz4 -B4 -l --no-frame-crc vmlinux kernel_1_p.lz4

这才对嘛 塞回去 打开原内核文件 Ctrl+F查找 文件头

1
02 21 4C 18

把前面赋值粘贴到改过的内核中 我是瞎子, 难怪v半天都是覆盖 单击Insert就行, 如果是手提电脑, 请按住Fn, 不然是delete, 直到右下角表示是插入模式 欧~这才对嘛 体积还变大了…有种不详的预感 很好, 白忙活了

AI又给出了一个压缩命令

1
lz4 -B4 --content-size --no-frame-crc vmlinux vmlinux.lz4

经过验证, 同一个内核文件用lz4 -d kernel vmlinux解压后, 不做任何修改再用上面的命令压回来, 还是大便了. 正确思路应该是查找源码中的压缩脚本 先查手机版本代码

1
adb shell getprop ro.build.fingerprint

结果是这个

1
google/sdk_gphone64_x86_64/emu64xa:14/UE1A.230829.050/12077443:userdebug/dev-keys

终于对应上版本 真有啊 https://android.googlesource.com/platform/external/lz4/+/refs/heads/android14-dev

直接下载下来自己编译 wsl启动!! 执行安装 此时系统里面就有2个lz4了 看看版本 差别不大? 压缩目标文件试试 经测试, 还是不行 直接翻源码看kernel是如何炼成的 … 看不出来 https://android.googlesource.com/platform/build/+/refs/heads/android14-dev/core/Makefile 看来AI靠不住了, 参拜看雪 https://bbs.kanxue.com/thread-266625-1.htm 没啥用, 吃完饭回来继续看到这一篇台湾老哥的 https://htcfz.wordpress.com/2017/11/19/htc-android-8-0-lz4-kernel-touch-patch/ 用到的压缩指令是

1
lz4 -9 vmlinux vmlinux.lz4

压缩改过的, 体积变化不大了vmlinux->kernel_1_t.lz4 再压缩没改过的试试 vmlinux_s->kernel_1_s.lz4 还是大了一点… 才发现, -9与压缩比正相关, 换成-20试试 又变小了一点, 换成-18试试 -12 压缩率就在37.28%-37.40%徘徊? -11 更接近了,再来 绷不住了, -9是高压缩率的意思, 但我用-11确实能压出来 来接头 变化终于变小了 续尾kernel_p 这样就一样大了, 解释一下为什么续尾不影响内核加载, 因为内核启动的过程是一个自解压的过程,并且lz4解压速度极快500MB/S, 很快就把无意义的尾巴覆盖了. 替换测试 启动成功!!!

额, 原来是回光返照啊, 还是启动失败

-9试试吧

错错错, 是我的错 还是没能以正确的姿势压缩回去, mkbootimg才像是像样的网站, 果然不能全靠ai ai又说

1
lz4 -l -12 --favor-decSpeed vmlinux Image.lz4

但确实有这个lz4直接出现了啊, 安卓14的打包代码 利用未修改文件解压再压缩, 确定就是该命令 上区域1kernel_split的就是未修改过的内核, 下区域就是将上面解压后重新压缩回来的,少了一些东西, 红框部分完全一样, 那么1kernel_split还要拆成2份, 也就是把1kernel_split尾巴上多出来的这一小节加到4kernel_split_patch的尾巴上 就这里少了2个字节,估计是指令都为909090…, 被算法发现然后合并了, 其他地方基本一样, 为了对齐, 我手动加了00 00, 加尾巴,加头 终于启动成功了!!! 这回是真的成了

能调试咯 4kernel_split_patch_0000_tail_head

本文由作者按照 CC BY 4.0 进行授权