源码中的内核文件dtb格式结尾的内核文件位于aosp/device目录下
https://source.android.com/source/building-kernels
查看当前内核文件
# tree -NCfhl|grep dtb
下载内核源码:
// 清华??// 谷歌
# git clone https://aosp.tuna.tsinghua.edu.cn/android/kernel/msm.git
# git clone https://android.googlesource.com/kernel/msm.git
# cd msm //进入msm工程目录
查看手机内核版本:
# adb ahell
# su
# cat /proc/version
g开头的后面XXXXXX就是对应的版本
检出内核版本:
# git checkout XXXXXX
设置编译环境,源码目录要对应
export PATH=$PATH:/root/aosp/prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9/bin
设置目标架构,Pixel Xl(marlin)是arm64的CPU
export ARCH=arm64
export SUBARCH=arm64
export PATH=$PATH:$ANDROID_AARCH64
export CROSS_COMPILE=aarch64-linux-android-
准备编译参数
make marlin_defconfig
开始编译
make
可能两个报错,安装库
# apt install bc
# apt install liblz4-tool
生成成功的内核位于arch/arm64/boot/Image.lz4-dtb 路径中
重新生成刷机镜像
cd /root/aosp/
. build/envsetup.sh && lunch aosp_marlin-userdebug
(在这个版本中,选择aosp_marlin_userdebug)
按照官网指示,重新定义下TARGET_PREBUILT_KERNEL 变量的路径
export TARGET_PREBUILT_KERNEL=/root/aosp/arch/arm64/boot/Image.lz4-dtb
然后重新编译boot镜像,不需要全部重新编译了。
make bootimage
最后生成的boot镜像还是在out/target/product/marlin/目录下,可以看到boot.img镜像是刚刚生成的,其余原先已经生成过的各种img的最后修改日期是Yesterday。
最后使用新的boot.img来制作刷机包,刷机即可。重新开机后可以看到内核已经是新编译的了,甚至都能看到我的编译系统的hostname,编译时间也是2020年的时间。
修改内核源码
在《安卓4.4的内核源码,也就是msm/fs/proc/base.c、msm/fs/proc/array.c、msm/fs/proc/array.c这三个文件
在《安卓7.1.2 内核编译修改 TracerPid》文章中修改的是msm/fs/proc/base.c和msm/fs/proc/array.c这两个文件。
在《安卓8.1.0_r1版本的内核。原因是proc_pid_wchan这个函数,在三个版本中都进行了重构,8.1.0_r1版本的fs/proc/base.c中的proc_pid_wchan函数
当前修改为8.1.0版本如下
fs/proc/base.c中的proc_pid_wchan函数
修改前
/*
* Provides a wchan file via kallsyms in a proper one-value-per-file format.
* Returns the resolved symbol. If that fails, simply return the address.
*/
static int proc_pid_wchan(struct seq_file *m, struct pid_namespace *ns,
struct pid *pid, struct task_struct *task)
{
unsigned long wchan;
char symname[KSYM_NAME_LEN];
wchan = get_wchan(task);
if (lookup_symbol_name(wchan, symname) < 0)
if (!ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS))
return 0;
else
return seq_printf(m, "%lu", wchan);
else
return seq_printf(m, "%s", symname);
}
修改后
/*
* Provides a wchan file via kallsyms in a proper one-value-per-file format.
* Returns the resolved symbol. If that fails, simply return the address.
*/
static int proc_pid_wchan(struct seq_file *m, struct pid_namespace *ns,
struct pid *pid, struct task_struct *task)
{
unsigned long wchan;
char symname[KSYM_NAME_LEN];
wchan = get_wchan(task);
if (lookup_symbol_name(wchan, symname) < 0)
if (!ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS))
return 0;
else
return seq_printf(m, "%lu", wchan);
else {
if (strstr(symname, "trace")) {
return seq_printf(m, "%s", "sys_epoll_wait");
}
return seq_printf(m, "%s", symname);
}
}
然后就是跟老版本一样的,在fs/proc/array.c 文件中,将
修改前
/*
* The task state array is a strange "bitmap" of
* reasons to sleep. Thus "running" is zero, and
* you can test for combinations of others with
* simple bit tests.
*/
static const char * const task_state_array[] = {
"R (running)", /* 0 */
"S (sleeping)", /* 1 */
"D (disk sleep)", /* 2 */
"T (stopped)", /* 4 */
"t (tracing stop)", /* 8 */
"X (dead)", /* 16 */
"Z (zombie)", /* 32 */
};
修改后
/*
* The task state array is a strange "bitmap" of
* reasons to sleep. Thus "running" is zero, and
* you can test for combinations of others with
* simple bit tests.
*/
static const char * const task_state_array[] = {
"R (running)", /* 0 */
"S (sleeping)", /* 1 */
"D (disk sleep)", /* 2 */
"S (sleeping)", /* 4 */
"S (sleeping)", /* 8 */
"X (dead)", /* 16 */
"Z (zombie)", /* 32 */
};
将
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"
"Ngid:\t%d\n",
get_task_state(p),
leader ? task_pid_nr_ns(leader, ns) : 0,
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_numa_group_id(p));
更改为:
seq_printf(m,
"State:\t%s\n"
"Tgid:\t%d\n"
"Pid:\t%d\n"
"PPid:\t%d\n"
"TracerPid:\t0\n"
"Uid:\t%d\t%d\t%d\t%d\n"
"Gid:\t%d\t%d\t%d\t%d\n"
"Ngid:\t%d\n",
get_task_state(p),
leader ? task_pid_nr_ns(leader, ns) : 0,
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_numa_group_id(p));
确保更改无误后,直接重新编译内核即可,然后按照同样的流程刷入手机。
进一步反反反调试 当然,是不是只要在内核中修改了TracerPid部分的机制的源码,就可以一劳永逸了呢?答案并不是这样,App还可以通过fork出子进程附加父进程的方式,父进程中读自己的TracerPid是否为子进程的PID,如果不是则说明TracerPid机制已经失效,此系统为修改版的系统,同样结束自己的进程。
|