吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 31387|回复: 63
收起左侧

[Android 分享] 逆向修改内核,绕过TracerPID反调试

[复制链接]
527900417 发表于 2018-5-2 16:10
本帖最后由 527900417 于 2018-11-21 00:39 编辑

前言

上次DDCTF结束后,和BinCrack师傅交流,他提到用了自己编译的安卓内核,直接修改源码更改了TracerPID,之后在国赛也遇到了对status的检测,虽然可以修改内存绕过(ref 4),但是还是想试一试把内核patch掉。查阅了很多资料后,大概有三种方法:
1.修改源码,重新编译内核 (ref 2)
2.逆向修改内核文件,patch二进制文件
3.hook fopen 函数,检测/proc/pid/status调用 (ref 3)
比较了几种方法的工作量和自己的基础知识(并没有),选择了第二种方法,以看雪的一篇文章最为典型,但由于机型和版本的区别,遇到了几个坑,找到了一个较为通用的方法。
以下工作基于samsung note3 9008,armeabi-v7a2,第三方官改rom,5.0,twrp rec
原文同时保存在blog

准备工作

boot.img提取

首先确保有root权限
先找到目录
FrjzAn1q1REOE1uVjeqAAdRNZ_F7
将boot导出为boot.img      

dd if=/dev/block/mmcblk0p14 of=/data/local/boot.img
adb pull /data/local/boot.img boot.img
准备bootimg-tools工具

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目录下生成了相应的二进制执行文件。
Fn45BYYDxqbHlZYJM58anzcVoN0M
解开boot.img
FnUZUhSF5S9Pzn7fK2Qdd5RIexvb

注:使用其他工具一直提取失败,最后回头来看其实并不重要,如果熟悉boot.img格式的话,手动提取也可以。但是三星的这个文件,试了很多工具,也只有上面提到的这个工具能提取出来,但打包有些问题,后面有相应的解决方法。

提取原始zImage

将kernel文件复制为文件名为zImage.gz的文件,并使用010editor查找十六进制1f 8b 08 00,找到后把前面的数据全删掉,使文件变成标准的gzip压缩文件,这样子就可以使用gunzip解压了。
命令:gunzip zImage.gz
生成文件就是祼二进制文件zImage。
FkC2yIHjESZO3I01isl_G-oNR0dL

内核修改

zImage文件可以直接使用IDA(推荐6.8,7.0的话需要自己尝试定位函数)去打开,但需要设置参数。
FoOzIFTNngyh84Kugw9HdBHOq2JG
在上图,设置处理器类型为ARM Little-endian,点ok后,弹下图
FiJkPZPoiGsNUOvBy9f8XebfF5BY
在ROM start address和Loading address填0xc0008000,点ok,没有函数名,不方便定位代码。

先回到root下的adb shell,输入命令:
echo 0 > /proc/sys/kernel/kptr_restrict
关闭符号屏蔽
再输入以下命令查看这两函数的地址

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

FtRMzOapuBcKrx3TeW9iF0CcGDSp
回到IDA,按g跳转到c0964058(__task_pid_nr_ns)地址处,在光标放在在该函数处:
FmrtCdEToGBDhoGtwZOfRcK-HV-J
然后按x,弹出引用搜索框,找到sub_c0888ac0(这里由于解析程度不同,显示和我的会不一样,但是重点在于sub_c0888ac0),双击进入。
FmxiBVfo80w0b-WnOCbdwIoOGqCo
如果IDA没有分析出该函数,就进行以下操作:按shift+f12,搜索TracerPid,找到以下项
Ft9ttPWjfE0jsR2E2jYMqMZEw-Wf
双击
FkP-Bo421kItvfV_cDQsHlkpI3cN
我这里是没有解析出来引用函数的,如果有引用函数,跟进去就可以解析出来sub_c0888ac0了。
在这里,我们强制解析sub_c0888ac0函数,按g输入c0888ac0,如果ida没有识别为函数,按p强制解析。回到c0964058,按x寻找sub_c0888ac0。
跟进去:
FvuNVtEkrbS316dOCQ7wmTEcDvtA
根据其他文章的分析和我的实践,得到的修改方法是把MOVEQ R10, R0替换为MOV R10, #0,机器码为00 A0 A0 E3,指令的文件偏移为(C0889110-C0008000),及把下面第三行的BL sub_C0964058替换为MOV R0, #0,机器码为00 00 A0 E3,指令的文件偏移为(C0889120-C0008000)。根据偏移地址在文件里使用010修改或者使用keypatch插件直接修改。
内核文件修改成功。

另,在更改的过程中联想到直接修改TracerPid的格式字符串值,因为不太熟悉,感觉可能会导致占位符后移而报错,就没考虑这个思路,之后也发现确实可以这样做。原始格式化字符串内容为:\t%s\nTgid:\t%d\nPid:\t%d\nPPid:\t%d\nTracerPid:\t0\t\nUid:\t%d\t%d\t%d\t%d\nGid:\t%d\t%d\t%d\t%d\n
这里应该用到了C语言中的占位符%d,来进行值的填充,那么我们可以把TracerPid那一项的占位符%d,改成'0',但是'%d'是两个字符,所以我们可以改成'00',或者'0\t'(十六进制30 09),或者'0\n';只要保证修改后的字符串内容对齐就好。这样TracerPid这一项的值占位符就失效了,值永远都是0了。

打包boog.img

使用之前的解包时提供的打包方法,打包后刷入失败..
最后探索到的方法是直接修改原boot.img
使用gzip -n -f -9 zImage压缩修改后的内核裸文件,压缩后会比原来的小,必须比原来的文件小才可以。
得到zImage.gz,我们使用010分别打开zImage.gz和boot.img,搜索1F 8B 08 00。
按下insert键,将010改为overwrite,注意这里必须是覆盖,这样就不用考虑插入后大小的问题了,把zImage.gz的内容复制到boot.img的相应位置。
FnAy5kaViLN66ZSB875MZC85tmkc
修改完成,使用twrp rec刷入镜像,选择刷入boot。重启。

调试查看

使用ida调试so文件,查看status文件。
FhnP1YDYiijeHyCo73Mx6Wabyqqj
更改后
FlFP8GeyEiGU_L6ar2KSlmMvY35m
更改成功。

变砖补救

但愿还是能够一次成功的,刷内核失败无限重启或者不能开机也比较正常。在尝试过程中失败了三次,只要之前备份了原始的boot.img,变砖之后重新进入rec,刷入原始的boot.img就好。
如果是使用odin刷入的话,需要将boot.img打包为tar文件才可以。

ref
1.逆向修改手机内核,绕过反调试
2.Android系统内核编译及刷机实战 (修改反调试标志位)
3.基于HOOK的Anti-debug调用点trace和Anti-anti
4.Android动态调试和ptrace反调试之读取进程status文件



作为一只菜鸟,搞了好久才将内核更改成功,斗胆与各位分享自己的经历,希望各位大神多指点。

原文同时保存在blog

免费评分

参与人数 27吾爱币 +31 热心值 +27 收起 理由
m0nst3r + 1 + 1 谢谢@Thanks!
ttimasdf + 2 + 1 哈哈哈哈~博客已mark,棒!
丶咖啡猫丶 + 1 + 1 谢谢@Thanks!
fgdg + 1 + 1 用心讨论,共获提升!
Fury_Vector + 1 + 1 用心讨论,共获提升!
老张有大梦想 + 1 + 1 热心回复!
阿尔卡伊达 + 1 + 1 热心回复!
Jack_007 + 1 + 1 热心回复!
bbn + 1 + 1 我很赞同!
akria00 + 1 + 1 用心讨论,共获提升!
XhyEax + 3 + 1 我很赞同!
hdc8899 + 1 + 1 大佬能不能教下如何在用三星源码编译内核
zzzlucas + 1 + 1 谢谢@Thanks!
liphily + 2 + 1 原来精品不需要太长——
Mfeng + 1 我很赞同!
吾爱_欢迎您 + 1 + 1 我很赞同!
imlk + 1 + 1 谢谢@Thanks!
dibh10 + 1 + 1 用心讨论,共获提升!
一牛神一 + 1 + 1 用心讨论,共获提升!
小白670 + 1 + 1 写的挺好的,有时间自己也尝试一下,谢谢分享
不羁的生命 + 1 + 1 谢谢@Thanks!
60000ak + 1 + 1 热心回复!
e007 + 1 + 1 我很赞同!
夏雨微凉 + 2 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
sumile + 1 + 1 用心讨论,共获提升!
nosilence + 1 + 1 用心讨论,共获提升!
xinkui + 1 + 1 谢谢@Thanks!

查看全部评分

本帖被以下淘专辑推荐:

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

mrnull 发表于 2018-6-27 20:27
先说一下,这里的教程不适用用于大多数机子,我昨天搞了一晚上了,说几个需要注意的
首先是提取boot,有些机子是另一种格式叫什么mtd好像,提取和刷内核的话我还是推荐用第三方的rec的备份和恢复功能,这里需要关闭md5校验
然后是解压boot,mtk和高通好像都不一样,但是好像有通用的工具,所以这个不算一个坑
然后是解压内核,这里不一定是gzip压缩的,需要用binwalk看个究竟,比如我的三星a5就是用lz4压缩的,这是第一个坑,记好
然后调试,cpu有32和64,所以入口又不一样了
修改,修改我并不怎么会,所以说不出什么
压缩,这个真心是个谜,我昨天晚上解压不修改重新压缩回刷都能开不了机子,所以这个看运气吧
整个过程就是在看运气
最后就是最好别先改东西刷入,先试一下不改什么然后压缩再压缩回刷看看有没有问题,再继续下一步,这个真的有必要
连这个都不行的话,就看你自己了= =反正我是不行,似乎头文件的数据是验证来着,不然我不改什么回刷都能开不了机子

免费评分

参与人数 1热心值 +1 收起 理由
527900417 + 1 我很赞同!

查看全部评分

mrnull 发表于 2018-6-27 20:30
然后我贴一下网上找的一段代码吧


[C] 纯文本查看 复制代码
static inline void task_state(struct seq_file *m, struct pid_namespace *ns,
				struct pid *pid, struct task_struct *p)
{
	struct user_namespace *user_ns = seq_user_ns(m);
	struct group_info *group_info;
	int g;
	struct fdtable *fdt = NULL;
	const struct cred *cred;
	pid_t ppid, tpid;
	rcu_read_lock();
	ppid = pid_alive(p) ?
		task_tgid_nr_ns(rcu_dereference(p->real_parent), ns) : 0;
	tpid = 0;
	if (pid_alive(p)) {
		struct task_struct *tracer = ptrace_parent(p);
		if (tracer)
			tpid = task_pid_nr_ns(tracer, ns);
	}
	cred = get_task_cred(p);
	seq_printf(m,
		"State:\t%s\n"
		"Tgid:\t%d\n"
		"Pid:\t%d\n"
		"PPid:\t%d\n"
		"TracerPid:\t%d\n"
		"Uid:\t%d\t%d\t%d\t%d\n"
		"Gid:\t%d\t%d\t%d\t%d\n",
		get_task_state(p),
		task_tgid_nr_ns(p, ns),
		pid_nr_ns(pid, ns),
		ppid, tpid,
		from_kuid_munged(user_ns, cred->uid),
		from_kuid_munged(user_ns, cred->euid),
		from_kuid_munged(user_ns, cred->suid),
		from_kuid_munged(user_ns, cred->fsuid),
		from_kgid_munged(user_ns, cred->gid),
		from_kgid_munged(user_ns, cred->egid),
		from_kgid_munged(user_ns, cred->sgid),
		from_kgid_munged(user_ns, cred->fsgid));
	task_lock(p);
	if (p->files)
		fdt = files_fdtable(p->files);
	seq_printf(m,
		"FDSize:\t%d\n"
		"Groups:\t",
		fdt ? fdt->max_fds : 0);
	rcu_read_unlock();
	group_info = cred->group_info;
	task_unlock(p);
	for (g = 0; g < group_info->ngroups; g++)
		seq_printf(m, "%d ",
			   from_kgid_munged(user_ns, GROUP_AT(group_info, g)));
	put_cred(cred);
	seq_putc(m, '\n');
}
Ericky 发表于 2018-5-2 16:23
 楼主| 527900417 发表于 2018-5-2 16:53
Ericky 发表于 2018-5-2 16:23
https://bbs.pediy.com/thread-207538.htm

对,ref第一条便是您说的看雪的这篇文章。其中几个具体的交叉引用可能无法识别,有一些小改动。感谢。
牛奶君 发表于 2018-5-2 17:07
boot.img中有两个1f 8b 08 00。( ̄(工) ̄)这可怎么办
 楼主| 527900417 发表于 2018-5-2 17:37
牛奶君 发表于 2018-5-2 17:07
boot.img中有两个1f 8b 08 00。( ̄(工) ̄)这可怎么办

可以查一下bootimg.h的结构信息,开头是一个header,之后第一个出现的是kernel,一般情况下第一个1f 8b 08 00就是kernel的位置。
6767 发表于 2018-5-2 22:23
锁死ptraceID的一个风险是,如果有应用ptrace ME去检测就会露馅。。。
不过到目前还没有遇到过这样检测的
神一样的小白 发表于 2018-5-2 23:30 来自手机
看不懂。感觉好牛逼
chenjingyes 发表于 2018-5-3 00:17
感谢楼主分享  哈哈哈
刘留留 发表于 2018-5-3 05:19
学习了,谢谢分享
头像被屏蔽
sstm 发表于 2018-5-3 09:04
看看,了解了解。
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-12-22 15:35

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表