前言
在逆向和保护的过程中,总会涉及到反调试和反反调试的问题,这篇文章主要是总结一下几种常见的反调试手段以及反反调试的方法。
反调试
ptrace
为了方便应用软件的开发和调试,从Unix的早期版本开始就提供了一种对运行中的进程进行跟踪和控制的手段,那就是系统调用ptrace()
。
通过ptrace
可以对另一个进程实现调试跟踪,同时ptrace
还提供了一个非常有用的参数那就是PT_DENY_ATTACH
,这个参数用来告诉系统,阻止调试器依附。
所以最常用的反调试方案就是通过调用ptrace
来实现反调试。
1 | #ifndef PT_DENY_ATTACH |
sysctl
当一个进程被调试的时候,该进程会有一个标记来标记自己正在被调试,所以可以通过sysctl
去查看当前进程的信息,看有没有这个标记位即可检查当前调试状态。
1 | BOOL isDebuggerPresent(){ |
检测到调试器就退出,或者制造崩溃,或者隐藏工程啥的,当然也可以定时去查看有没有这个标记。
syscall
为从实现从用户态切换到内核态,系统提供了一个系统调用函数syscall
,上面讲到的ptrace
也是通过系统调用去实现的。
在Kernel Syscalls这里可以找到ptrace
对应的编号。
1 | 26. ptrace 801e812c T |
所以如下的调用等同于调用ptrace
:
1 | syscall(26,31,0,0,0); |
arm
syscall
是通过软中断来实现从用户态到内核态,也可以通过汇编svc
调用来实现。
1 | #ifdef __arm__ |
下面几种可能在实际中用到的比较少,不过也可以尝试一下。
SIGSTOP
通过捕获系统SIGSTOP
信号来判断。
1 | dispatch_source_t source = dispatch_source_create(DISPATCH_SOURCE_TYPE_SIGNAL, SIGSTOP, 0, dispatch_get_main_queue()); |
task_get_exception_ports
获取异常端口:
1 | struct macosx_exception_info{ |
isatty
1 | if (isatty(1)) { |
ioctl
1 | if (!ioctl(1, TIOCGWINSZ)) { |
反反调试(Tweak)
了解了几种不同的反调试的方法,那么就可以根据几种常用的反调试方法来反反调试。
这里主要针对ptrace
、sysctl
、syscall
来反反调试,做法就很简单了,hook函数,判断参数,返回结果。
1 | #import <substrate.h> |
反反调试(lldb)
通过lldb
下断点,然后修改参数,或者直接返回也可以达到反反调试的效果。不过这里讲的是通过python
脚本把过程自动化的一种方法。
为了方便直接使用facebook
的chisel
来增加脚本。
新建一个文件夹,然后使用
1 | commandsDirectory = os.path.join(lldbHelperDir, '文件名') |
加载即可。
下面是python
代码:
1 | #!/usr/bin/python |
总结
反调试的方式有多种,可以通过:
1 | ebugserver *:1234 -x auto /path/to/executable |
启动附加,然后断点测试。
本文代码地址:
有问题或者有更好的方法欢迎一起探讨。