解决Android加固多进程ptrace反调试的思路整理
本文博客链接:http://blog.csdn.net/qq1084283172/article/details/53613481
一、Android多进程反调试的原理代码
当ptrace附加目标进程时出现失败,正常情况下有理由认为目标进程已经被别的进程ptrace附加了。像梆梆加固就是采用的这种反调试的手法,效果还是不错的。
/******************************************************
// 附加目标进程失败,说明目标进程已经被调试
if (ptrace(PTRACE_TRACEME, 0, 1, 0) < 0) {
printf("DEBUGGING... Bye\n");
return 1;
}
******************************************************/
// 多进程ptrace反调试
void anti_ptrace(void)
{
pid_t child;
// 创建子进程
child = fork();
if (child)
{
// 返回在父进程中
wait(NULL);
}
else
{
// 获取父进程的pid
pid_t parent = getppid();
// ptrace附加父进程
if (ptrace(PTRACE_ATTACH, parent, 0, 0) < 0)
{
while(1);
sleep(1);
}
// 释放附加的进程
ptrace(PTRACE_DETACH, parent, 0, 0);
// 结束当前进程
exit(0);
}
}
二、Android多进程反调试的解决方法整理
A.方法一
对于梆梆,之前有文章讨论可以attach到其binder线程上,通过gcore、dd来dump内存中的dex。
但对于其最新版本,当使用gdb attach到主进程的任一线程上时,要么permission denied,要么会退出。
对其实现机理进行一下分析:
1. 主进程fork子进程c1,c1 fork子进程c2;
2. c1会ptrace attach到主进程的主线程与GC线程(其也会操作memory,所以需要用ptrace方法保护),
这样当试图ptrace attach时,会有permission denied;
3. 主进程为了能让c1这个子进程跟踪,需要调用prctl,option为SET_DUMPABLE。但这个API比较危险,
其效果与AndroidManifest文件中debuggable选项设为true等价。如果不调用这个api,子进程是不能ptrace父进程的;
4. c1也会ptrace到c2进程,来对其进行保护;
5. 这个三个进程间彼此用pipe进行通信;
6. c1会向主进程内存空间注入大约52字节的数据,应为密钥;
7. 之后c1进入pipe读阻塞sleep;
8. c2使用inotify监控主进程的每个clone process的mem与pagemap,于是当gdb、dd试图dump内存时,mem的access事件被触发,
三个进程集体退出,导致内存dump不完整;这边漏了一个,同时c2会不断打开主进程的各个status文件,看其tracerpid是否为0,非0则被attach--退出;
9. c2并monitor主进程的task目录,来判断是否有新的clone process或现有的已消亡,来更新monitor的select loop的fd集合。
另外,梆梆还hook了write方法,来阻止在进程内部将header为dex的magic code的内容写入磁盘。
破解办法:
hook write那个好破解 ,字节流中转出来到其他进程就好了
或者写的时候,把dex,改成xxx就好啦。
上文中可以看出主进程的孙子进程是起到防gdb/gcore的关键,那么如何绕过它,依然使用gdb去dump出完整dex呢?
开始时,我是重新编译了一个rom,屏蔽与重定向了相关API,可以dump出来,显然这个方法相对烦躁一点。
下面介绍一种在目前梆梆的版本上,更为简单粗暴的方法:
1. 首先通过ps找出孙子进程的pid,记为pid3;
2. 查看/proc/<pid3>/task找出孙子进程所有的thread,通常是3个,并记录下他们的tid;
3. 使用kill -19 <tid> 将这些孙子线程挂起;
4. gdb 主进程,顺利gcore 。
kill命令的用法连接:
http://www.cnblogs.com/peida/archive/2012/12/20/2825837.html
http://fredrick8.blog.163.com/blog/static/11734560120126213347827/
提供Android多进程反调试的方法的大神eewolf的链接:
http://bbs.pediy.com/showthread.php?t=198778
http://bbs.pediy.com/showthread.php?t=198995
prctl函数的简单说明:
http://blog.chinaunix.net/uid-23145525-id-4026304.html
http://www.cppblog.com/beautykingdom/archive/2009/11/08/100419.aspx
B.方法二
原理:多进程都是通过fork出来的,因此我们修改/bionic/libc/bionic/fork.c里面的fork函数来使得目标进程fork失败,代码如下:
作者王正飞给出的思路是正确的,但是他给出的过滤代码是有问题的,本来是想编译Android源码试试的,时间比较急没来得及去测试代码了,正确的过滤代码我已经在下面给出了,其中"com.xxxx.yyy"为需要过滤的脱壳的apk的包名,后面我会测试一下,检查一下有没有问题再修改和补充:
// 修改Android系统的/bionic/libc/bionic/fork.c里面的fork函数,过反调试
#define BUF_LENTH 1024
// 进行脱壳apk进程的过滤
int is_target_apk_pid()
{
char szBuffer[BUF_LENTH] = {0};
char szCmd[BUF_LENTH] = {0};
// 格式化字符串得到/proc/pid/cmdline
sprintf(szCmd, "/proc/%d/cmdline", getpid());
// 获取当前pid进程的文件名称字符串(比较粗糙)
int fd = open(szCmd, O_RDONLY);
if (read(fd, szBuffer, BUF_LENTH))
{
//......
}
else
{
//......
}
close(fd);
// 判断当前pid进程是否是需要的过滤的脱壳apk进程
//memset(szCmd, 0, sizeof(szCmd));
//sprintf(szCmd,"/data/data/%s", szBuffer);
if (strstr(szBuffer, "com.xxxx.yyy"))
{
return 1;
}
return 0;
}
// 调用脱壳apk进程的过滤函数进行相应的处理
int fork(void)
{
int ret;
// 添加的代码
if (is_target_apk_pid())
{
return -1;
}
}
// 重新编译Android的fork函数所在的模块,定制ROM
结果:修改fork函数后,目标APK只剩下一个进程了,使用gdb attach正常,效果如下:
思路扩展:
这个get_target2函数就是作为过滤条件用的,可以考虑结合注入+HOOK 。
作者王正飞的方法讨论链接:
http://bbs.pediy.com/showthread.php?t=211548
好了,可以睡觉了,晚安~
解决Android加固多进程ptrace反调试的思路整理的更多相关文章
- 手动绕过百度加固Debug.isDebuggerConnected反调试的方法
本文博客地址:http://blog.csdn.net/qq1084283172/article/details/78237571 1.调用Debug.isDebuggerConnected函数这种反 ...
- 一种绕过PTRACE反调试的办法
Linux 系统gdb等调试器,都是通过ptrace系统调用实现.Android加固中,ptrace自身防止调试器附加是一种常用的反调试手段. 调试时一般需要手工在ptrace处下断点,通过修改ptr ...
- Android反调试笔记
1)代码执行时间检测 通过取系统时间,检测关键代码执行耗时,检测单步调试,类似函数有:time,gettimeofday,clock_gettime. 也可以直接使用汇编指令RDTSC读取,但测试AR ...
- APP加固反调试(Anti-debugging)技术点汇总
0x00 时间相关反调试 通过计算某部分代码的执行时间差来判断是否被调试,在Linux内核下可以通过time.gettimeofday,或者直接通过sys call来获取当前时间.另外,还可以通过自定 ...
- 修改Android手机内核,绕过反调试
本文博客链接:http://blog.csdn.net/qq1084283172/article/details/57086486 0x1.手机设备环境 Model number: Nexus 5 O ...
- 编译Android内核 For nexus 5 以及绕过Android的反调试
本文博客链接:http://blog.csdn.net/qq1084283172/article/details/54880488 前面的博客中已经记录了Nexus 5手机的Android 4.4.4 ...
- Android trap攻防思路整理
Android trap攻防 图/文 h_one 0x01 反 ...
- 浅谈android反调试之 转发端口
反调试方案: 我们最通常使用的动态工具是IDA, IDA的动态调试端口默认为23946,我们可以通过/pro/net/tcp 查看android 系统所有TCP Socket 启动android_se ...
- 浅谈Android反调试 之 PTRACE_TRACEME
反调试原理: 关于Ptrace: http://www.cnblogs.com/tangr206/articles/3094358.html ptrace函数 原型为: #include & ...
随机推荐
- 9.Vue之webpack打包基础---模块化思维
主要内容: 1. 什么是模块化思维? 2. ES6包的封装思想 一.什么是模块化思维呢? 现实工作中, 一个项目可能会有多个人同时开发. 然后, 将所有人开发的内容, 合并到一个文件中. 比如: 1 ...
- Nginx解析漏洞复现以及哥斯拉连接Webshell实践
Nginx解析漏洞复现以及哥斯拉连接Webshell实践 目录 1. 环境 2. 过程 2.1 vulhub镜像拉取 2.2 漏洞利用 2.3 webshell上传 2.4 哥斯拉Webshell连接 ...
- C语言中指针和多维数组
指针和多维数组 数组名是特殊的指针 数组是一个特殊的指针,多维数组也是更为复杂的数组,它们的关系是什么样的呢? 我们通过一个简单的例子来比较形象的了解指针和多维数组: int a[2][3]; 这是一 ...
- GNS3通过“云”连接到虚拟机实验
GNS3通过"云"连接到虚拟机实验并使用wireshark工具对数据分析 观看本文之前注意!!!!! 做这次实验,我所遇到的问题,会全部写在文章结尾,如果读者们遇到问题,可查看. ...
- 04----python入门----文件处理
一.大致介绍 我们在计算机上进行的操作,归根结底是对文件的操作,其实质是由操作系统发送请求,将用户或者应用程序对文件读写操作转换成具体的硬盘指令. 众所周知,内存中的数据是无法永久保存的.在计算机硬件 ...
- 理解函数式编程中的函数组合--Monoids(二)
使用函数式语言来建立领域模型--类型组合 理解函数式编程语言中的组合--前言(一) 理解函数式编程中的函数组合--Monoids(二) 继上篇文章引出<范畴论>之后,我准备通过几篇文章,来 ...
- ubuntu18.04+gunicorn+nginx+supervisor+mysql+redis安装django项目
Ubuntu18.04 install Django project 项目准备: ECS 实例 (云服务器) 此安装部署方案适合本地ubuntu18.04系统安装和虚拟机中ubuntu18.04系统安 ...
- 攻防世界 reverse 进阶 notsequence
notsequence RCTF-2015 关键就是两个check函数 1 signed int __cdecl check1_80486CD(int a1[]) 2 { 3 signed int ...
- vue+django实现websocket连接
一.概述 在项目中,需要使用websocket,来展示一些实时信息. 这里使用django 3.1.5 二.django项目 安装模块 pip3 install django-cors-headers ...
- Python | random 模块:Python 中如何生成随机数和随机抽样?
random 是平时开发过程中常用的一个模块,该模块实现了各种分布的伪随机数生成器,以及和随机数相关的各种实用函数.基本函数 random() 在区间 [0.0, 1.0) 内均匀生成随机浮点数,是模 ...