动态调试防护 (30) (上)

简介: ptrace (process trace 进程跟踪)

ptrace (process trace 进程跟踪)


提供一个进程监察和控制另一个进程, 并且可以读取和改变被控制进程的内存和寄存器里面的数据.它就可以用来实现断点调试(修改pc寄存器里的值)和系统调用跟踪.


  1. ptrace -> iOS系统没有, 但是macOS里有


  1. 想看具体的参数, 可以创建一个macOS工程
  2. #import <sys/ptrace.h> -> 就可以查看ptrace参数


  1. ptrace函数说明 -> ptarce(PT_DENY_ATTACH,0,0,0); -> 拒绝附加进程操作(枚举31)


  1. arg1: 需要ptrace做的事情
  2. arg2: 需要操作的进程ID
  3. arg3(地址)/4(数据): 取决于第一个参数


  1. 调用了就不能进行debug调试了, 但是用户可以点击正常运行


查看ptrace符号


  1. 拿到MachO文件
  2. 查看懒加载和非懒加载符号表
  3. 发现ptrace在懒加载符号表里很显眼


怎么破解ptrace


  1. 导入自己定义的ptrace头文件
  2. InjectCode注入, 用fishhook干掉ptrace
  3. 运行如果报错 -> 注意插件的运行版本要小于手机的版本, 测试的时候可以都调为iOS11


相应的hook代码


//ptrace声明文件
#import "MyPtraceHeader.h"
#import "fishhook.h"
//定义一个函数指针!!
int (*ptrace_p)(int _request, pid_t _pid, caddr_t _addr, int _data);
//自定义的函数
int my_ptrace(int _request, pid_t _pid, caddr_t _addr, int _data){
    if (_request != PT_DENY_ATTACH) {//如果不是拒绝附加保留原始调用!
        return ptrace_p(_request,_pid,_addr,_data);
    }
    return 0;
}
+(void)load
{
    //交换!
    struct rebinding ptraceBd;
    ptraceBd.name = "ptrace";
    ptraceBd.replacement = my_ptrace;
    ptraceBd.replaced = (void *)&ptrace_p;
    struct rebinding bds[] = {ptraceBd};
    rebind_symbols(bds, 1);
}


sysctl


  1. 导入头文件 #import <sys/sysctl.h>


  1. sysctl参数说明 -> sysctl(<#int *#>, <#u_int#>, <#void *#>, <#size_t *#>, <#void *#>, <#size_t#>)


  1. 查询信息数组
  2. 数组中数据类型的大小
  3. 接收信息结构体的指针
  4. 接收信息结构体的大小


判断调试模式的代码


BOOL isDebugger(){
    int name[4];//里面放字节码。查询的信息
    name[0] = CTL_KERN;//内核查询
    name[1] = KERN_PROC;//查询进程
    name[2] = KERN_PROC_PID;//传递的参数是进程的ID(PID)
    name[3] = getpid();//PID的值告诉它!
    struct kinfo_proc info;//接收进程信息的结构体
    size_t info_size = sizeof(info);
    /**
     1、查询信息数组
     2、数组中数据类型的大小
     3、接受信息结构体的指针
     4、接受信息结构体的大小的指针
     */
    int error = sysctl(name, sizeof(name)/sizeof(*name), &info, &info_size, 0, 0);
    assert(error == 0);//0 就是没有错误,其他就是错误码!
    return  ((info.kp_proc.p_flag & P_TRACED) != 0);
}


& 解析


最后的判断条件

-> info.kp_proc.p_flag & P_TRACED) != 0
  1. 因为p_flag是状态标识


  1. 取值如图

微信图片_20220510043549.png
image.png


      b.那我们拿的时候的计算方式为 ->

微信图片_20220510043554.png
image.png


  1. 可以写一个定时器来定时调用来检测是否被调试
  2. 如果检测到了


  1. exit(0);
  2. 或者上报服务器
  3. 或者请求控制


  1. 用sysctl这种检测手段, 那么可延展性很好.


用fishhook破解sysctl


#import <sys/sysctl.h>
#import "fishhook.h"
@implementation InjectCode
+(void)load
{
    rebind_symbols((struct rebinding[1]){{"sysctl",my_sysctl,(void *)&sysctl_p}}, 1);
}
//原始函数地址
int (*sysctl_p)(int *, u_int, void *, size_t *, void *, size_t);
//定义新的函数
int my_sysctl(int *name, u_int namelen, void *info, size_t *infosize, void *newinfo, size_t newinfosize){
    if (namelen == 4
        && name[0] == CTL_KERN
        && name[1] == KERN_PROC
        && name[2] == KERN_PROC_PID
        && info) {
        int err = sysctl_p(name,namelen,info,infosize,newinfo,newinfosize);
        struct kinfo_proc * myinfo = (struct kinfo_proc *)info;
        if (myinfo->kp_proc.p_flag & P_TRACED) {
            //使用异或可以取反!
            myinfo->kp_proc.p_flag ^= P_TRACED;
        }
        return err;
    }
    return  sysctl_p(name,namelen,info,infosize,newinfo,newinfosize);
}
@end


防fishhook


  1. 只要比你的rebind_symbols提前执行就OK了
  2. 将防护代码封装到一个framework里面, 这样这个framework里面的代码永远会比你注入的代码提前执行.
  3. 我们经常使用的MonKeyDev是带有自动破解ptrace和sysctl的, 但是这种防护手段也是有效的
  4. 所以只要做了提前执行 -> 你所有的注入手段,都失效了


破解提前注入


修改二进制


  1. 正常情况, 我想运行别人的包, 但是一运行就闪退, 首先打符号断点, 看看是否有ptrace


  1. 如果能断到, 就是有


微信图片_20220510043558.png
image.png


      b.这时候可以bt 来打印堆栈, 能查看到包含ptrace代码的动态库名称


微信图片_20220510043602.png
image.png


  1. 这时候需要找到两个关键值


  1. 所在的动态库
  2. 地址上图的72bb44


  1. image list -> 搜动态库找到动态库的地址 -> 两个地址相减, 就找到偏移了


  1. 在所在的动态库找到偏移地址


  1. 找到要破解的可执行文件里面找到对应的framework里的macho -> 用hopper打开


  1. 搜索上面得到的地址 -> 注意pc寄存器保存的是下一个指令的地址, 所以这里要找上一条指令


微信图片_20220510043606.png
image.png


       b.[shift + alt + a]修改上面对应调用ptrace的地方, 改为nop


微信图片_20220510043610.png
image.png


       c.nop相当于一个空指令


  1. 修改完后File -> Produce New Executable
  2. 生成的动态库的macho去替换对应的文件
  3. 再用MonkeyDev运行, 发现完美破解防护


  1. 其实MonkeyDev是带有反防护sysctl的代码的, 需要手动打开


微信图片_20220510043614.png

image.png


       c.所以这种二进制的修改破解防护, 只要你找到就搞定了 -> 暴力破解


破解sysctl


  1. 下符号断点


微信图片_20220510043617.png
image.png


  1. 发现block_invoke -> 系统调用的 -> 因为之前我们写防护是在dispath中
  2. 找不到任何的调用代码的痕迹 -> 这里说明用GCD防护很棒
  3. 这时候用hopper打开工程的macho全局搜索sysctl, 发现找不到


  1. 这时候就怀疑的动态库, 所以要用hopper打开我们怀疑的动态库的macho来遍历搜索sysctl
  2. 记住这里我们只是测试, 但是真实的环境中, 这个查找应该很慢


5.运行后崩溃, 是因为这里nop修改sysctl后, assert报错(这给我们什么启示)


微信图片_20220510043621.png
image.png


防护总结


  1. 提前执行, 写在自己的私有动态库里
  2. 写在GCD里面
  3. 攻防博弈 -> 找到就赢




目录
相关文章
|
存储 安全 网络协议
绕过WAF和多个防护软件提权案例
绕过WAF和多个防护软件提权案例
188 0
|
安全 网络安全
技巧!通过360卫士白名单绕过查杀
技巧!通过360卫士白名单绕过查杀
546 0
|
安全 网络协议 Linux
安全检查与加固
安全检查与加固
|
安全 PHP 数据安全/隐私保护
记一次webshell文件及流量免杀
记一次webshell文件及流量免杀
328 0
|
安全 算法 编译器
逆向分析 工具、加壳、安全防护篇
作者主页:https://www.couragesteak.com/
逆向分析 工具、加壳、安全防护篇
|
iOS开发
越狱防护(25)
Tweak原理DYLD_INSERT_LIBRARIES
398 0
越狱防护(25)
|
SQL 算法 安全
php网站漏洞检测对sql注入漏洞防护
近日,我们SINE安全对metinfo进行网站安全检测发现,metinfo米拓建站系统存在高危的sql注入漏洞,攻击者可以利用该漏洞对网站的代码进行sql注入攻击,伪造恶意的sql非法语句,对网站的数据库,以及后端服务器进行攻击,该metinfo漏洞影响版本较为广泛,metinfo6.1.0版本,metinfo 6.1.3版本,metinfo 6.2.0都会受到该网站漏洞的攻击。
2116 0
|
安全 NoSQL Redis
Rediswwwxtg168com13099636600服务器被攻击后该如何安全加固
在特定条件下,如果 Redis 以 root 身份运行,黑客可以给 root 账号写入 SSH 公钥文件,直接通过 SSH 登录受害服务器,从而获取服务器权限和数据。一旦入侵成功,攻击者可直接添加账号用于 SSH 远程登录控制服务器,给用户的 Redis 运行环境以及 Linux 主机带来安全风险,如删除、泄露或加密重要数据,引发勒索事件等。
1479 0