首页
社区
课程
招聘
[原创]iOS LLDB中反反调试分析与实现
发表于: 2019-8-13 20:03 19341

[原创]iOS LLDB中反反调试分析与实现

2019-8-13 20:03
19341

关于反调试和反反调试,已经有很多人分析过了,也有很多解决方案。但是在LLDB中做反反调试还没人做过,这也是我一直想解决的一个方案,毕竟本身就是为了调试,那么在LLDB直接输入一行命令就能反反调试应该相对酸爽。本文将介绍一种基于内存单指令patch的方式进行反反调试的方案,大概意思就是通过直接修改代码段的指令来绕过反调试机制。

这里庆哥写了一遍文章分析了 关于反调试&反反调试那些事

这里简单归纳一下,有如下几种:

这里实际上就大概三种,其他都是基于ptrace的变种。ptrace这个函数是linux就提供的一个接口,常常用作linux系的反调试,本质就是通过26号系统调用来完成的,目前大多反调试都利用该方案。

后面看到庆哥同样提供了一个反反调试的LLDB脚本,不过看了下和我的思路还是不一样的。(

正如文章里面写到通过lldb下断点,然后修改参数,或者直接返回也可以达到反反调试的效果。由于要不断去检查执行状态等,或者程序有定时器定时检测,这个脚本影响性能及变得很卡影响调试体验。不过还是膜庆哥的方案,学习了。

说一下大概思路:

直接将首调指令修改为ret指令

刚开始以为就这样简单就完了,结果实际写代码的时候才发现过程远比想象中复杂。

由于iOS不允许直接将代码段map为写权限,这里调用mach_vm_protectmprotect都会异常。但是类似frida、substitute以及hookzz都能进行指令hook。这样说来,肯定是可以修改代码段的。看了下substitute以及frida中关于这块的实现,才发现可以用一种remap的方式修改代码段。

大致的流程如下:

不过当我写代码测试的时候发现,remap以后整个页数据都变成了0。实在不清楚原因,向Zz求助,Zz直接扔了我他实现这块的代码。我看了以后收益匪浅,只怪之前没分析hookzz的具体实现。后面才知道由于我的设备是iOS12,Zz意思是codesign的问题,hookZz也没支持。于是换了一台iOS9的设备,果然就可以了,向Zz低头。

期间还由于我手残忘记调用mprotect把new改为rx。导致直接执行异常,用memory region查看地址才知道页保护属性为rw

相关代码如下:

1、map new page for patch

2、start patch

3、set new page back to r-x

4、remap the target page

5、clear cache

完整的代码在xia0LLDB里面已经集成:https://github.com/4ch12dy/xia0LLDB

这里以爱奇艺为例子分析,爱奇艺在main函数里面动态调用了ptrace函数进行反调试。

后台启动方式启动爱奇艺

LLDB挂上以后在main函数下断点以后直接执行debugme命令

下面查看对比下patch前后指令ptrace首指令的变化

Patch之前

Patch之后

可以发现首地址已经变成了ret指令。

执行continue命令,发现爱奇艺已经能够正常调试。

这里只是简单的绕过了ptrace方式的反调试,针对直接用汇编写的反调试我的做法是静态内存搜索匹配svc位置,发现是调用26号系统调用则利用内存patch为nop。或者写一个简单的hook代码,hook所有的svc地址,判断寄存器的值然后进行hook即可,这样就能绕过这些反调试机制,再次向Zz和庆哥低头。

https://gist.github.com/piaoger/4ba83f6a954bca113505

https://github.com/comex/substitute/blob/master/lib/darwin/execmem.c

https://www.codercto.com/a/63507.html

https://github.com/jmpews/HookZz/blob/dev/srcxx/UserMode/ExecMemory/code-patch-tool-darwin.cc#L26

https://github.com/gdbinit/readmem/blob/master/readmem/main.c

https://github.com/frida/frida-gum/blob/master/gum/backend-darwin/machexc.h

http://newosxbook.com/src.jl?tree=xnu&file=/libsyscall/mach/mach_vm.c

https://github.com/DaKnOb/memscan/blob/master/main.mm

http://iosre.com/t/topic/8179

 
 
 
 
 

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

最后于 2019-8-13 20:04 被xia0编辑 ,原因:
收藏
免费 3
支持
分享
最新回复 (24)
雪    币: 916
活跃值: (3434)
能力值: ( LV8,RANK:120 )
在线值:
发帖
回帖
粉丝
2
“于是换了一台iOS9的设备”
向土豪低头
2019-8-13 20:11
0
雪    币: 1597
活跃值: (719)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
3

非要我放截图吗

最后于 2019-8-14 13:23 被xia0编辑 ,原因:
2019-8-13 20:16
0
雪    币: 977
活跃值: (435)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
4
xia0 非要我放截图吗
修改没有用 我已经看到了 大佬之间的互相伤害
最后于 2019-8-14 14:01 被上海刘一刀编辑 ,原因:
2019-8-14 14:01
0
雪    币: 614
活跃值: (883)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
5
2019-8-14 14:07
0
雪    币: 48
活跃值: (3434)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
看大佬撕逼
2019-8-14 14:38
0
雪    币: 1597
活跃值: (719)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
7
上海刘一刀 xia0 非要我放截图吗 修改没有用 我已经看到了 大佬之间的互相伤害
完了,暴露了葫芦娃上海第一豪的身份
2019-8-14 15:21
0
雪    币: 2512
活跃值: (672)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
8
task_get_exception_ports,这个方法不能用的,会误报。
2019-8-14 15:41
0
雪    币: 1597
活跃值: (719)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
9
暗夜盗魔 task_get_exception_ports,这个方法不能用的,会误报。
嗯,一般也没怎么用。iOS大多还是用ptrace
2019-8-14 16:44
0
雪    币: 138
活跃值: (470)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
10
Zz 有一套反反调试的代码, 基于hookzz, xia0LLDB 直接集成是不是更省事些?
当然 这从研究的角度来说 还是自己撸一遍原理来的透彻些,  给xiao0 点个赞
2019-8-15 09:18
0
雪    币: 1597
活跃值: (719)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
11
Nermor Zz 有一套反反调试的代码, 基于hookzz, xia0LLDB 直接集成是不是更省事些? 当然 这从研究的角度来说 还是自己撸一遍原理来的透彻些, 给xiao0 点个赞[em_63]
这里并没有重复造轮子,原因在于LLDB中的代码限制很大,不可能集成一个hookzz这样的框架。虽然hookzz已经算轻量级hook框架了,但在这里也显得太重了,而且也没必要。这里并不需要一个通用的hook框架。后面我对于SVC指令hook的思路也仅仅是判断寄存器简单操作,不然还会涉及污染寄存器等考虑因素。所以基于以上原因,我就自己实现了一遍,应该算最轻的一种hook方案。
最后于 2019-8-15 10:34 被xia0编辑 ,原因:
2019-8-15 10:34
0
雪    币: 138
活跃值: (470)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
12
xia0 Nermor Zz 有一套反反调试的代码, 基于hookzz, xia0LLDB 直接集成是不是更省事些? 当然 这从研究的角度来说 还是自己撸一遍原理来的 ...
原来如此, 感谢大佬指点。
2019-8-15 11:28
0
雪    币: 145
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
Kill antiDebug by xia0:error: Execution was interrupted, reason: EXC_BAD_INSTRUCTION (code=1, subcode=0x0).
The process has been returned to the state before expression evaluation.
请问大佬这样的情况该如何排除呢?
2019-8-16 01:40
0
雪    币: 1597
活跃值: (719)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
14
TinHsieh Kill antiDebug by xia0:error: Execution was interrupted, reason: EXC_BAD_INSTRUCTION (code=1, subcod ...
设备和系统版本是多少
2019-8-16 12:13
0
雪    币: 145
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
15
MacOS: 10.14.6
iphone iOS: 12.4 
Xcode: 10.3
2019-9-14 00:01
0
雪    币: 1597
活跃值: (719)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
16
TinHsieh MacOS: 10.14.6 iphone iOS: 12.4 Xcode: 10.3
iOS12之前有问题(文章也提到了)最新的已经修复了,请用最新的debugme试下
2019-9-14 18:37
0
雪    币: 145
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
17
xia0 iOS12之前有问题(文章也提到了)最新的已经修复了,请用最新的debugme试下
(lldb) debugme
[*] start patch ptrace funtion to bypass antiDebug
[+] success ptrace funtion to bypass antiDebug
[*] start patch svc ins to bypass antiDebug
[-] failed to get text segment:["error: warning: got name from symbols: header\nerror: Can't run the expression locally: Interpreter doesn't handle one of the expression's opcodes\n"]
[x] happy debugging~ kill antiDebug by xia0@2019
2019-9-18 00:20
0
雪    币: 145
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
18
TinHsieh (lldb) debugme [*] start patch ptrace funtion to bypass antiDebug [+] success ptrace funtion to by ...
[*] start patch ptrace funtion to bypass antiDebug
[+] success ptrace funtion to bypass antiDebug
[*] start patch svc ins to bypass antiDebug
[-] failed to get text segment:["error: use of undeclared identifier '_dyld_get_image_header'\nerror: use of undeclared identifier '_dyld_get_image_vmaddr_slide'\n"]
[x] happy debugging~ kill antiDebug by xia0@2019
2019-9-18 00:23
0
雪    币: 145
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
19
TinHsieh (lldb) debugme [*] start patch ptrace funtion to bypass antiDebug [+] success ptrace funtion to by ...
[*] start patch ptrace funtion to bypass antiDebug
[+] success ptrace funtion to bypass antiDebug
[*] start patch svc ins to bypass antiDebug
Error [IRForTarget]: Rewriting an Objective-C constant string requires CFStringCreateWithBytes
[-] failed to get text segment:['error: The expression could not be prepared to run in the target\n']
[x] happy debugging~ kill antiDebug by xia0@2019

2019-9-18 00:24
0
雪    币: 145
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
20
TinHsieh (lldb) debugme [*] start patch ptrace funtion to bypass antiDebug [+] success ptrace funtion to by ...
会出现各种不一样的问题,都是同一个app
2019-9-18 00:24
0
雪    币: 145
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
21
TinHsieh (lldb) debugme [*] start patch ptrace funtion to bypass antiDebug [+] success ptrace funtion to by ...
Traceback (most recent call last):
  File "<input>", line 1, in <module>
  File "/usr/local/Cellar/python@2/2.7.15_1/Frameworks/Python.framework/Versions/2.7/lib/python2.7/copy.py", line 52, in <module>
    import weakref
  File "/usr/local/Cellar/python@2/2.7.15_1/Frameworks/Python.framework/Versions/2.7/lib/python2.7/weakref.py", line 14, in <module>
    from _weakref import (
ImportError: cannot import name _remove_dead_weakref
Traceback (most recent call last):
  File "<input>", line 1, in <module>
NameError: name 'sys' is not defined
Traceback (most recent call last):
  File "<input>", line 1, in <module>
NameError: name 'sys' is not defined
Traceback (most recent call last):
  File "<input>", line 1, in <module>
NameError: name 'sys' is not defined
Traceback (most recent call last):
  File "<input>", line 1, in <module>
NameError: name 'sys' is not defined
Traceback (most recent call last):
  File "<input>", line 1, in <module>
NameError: name 'sys' is not defined
Traceback (most recent call last):
  File "<input>", line 1, in <module>
NameError: name 'sys' is not defined
Traceback (most recent call last):
  File "<input>", line 1, in <module>
NameError: name 'sys' is not defined
Traceback (most recent call last):
  File "<input>", line 1, in <module>
NameError: name 'sys' is not defined
Traceback (most recent call last):
  File "<input>", line 1, in <module>
NameError: name 'sys' is not defined
Traceback (most recent call last):
  File "<input>", line 1, in <module>
NameError: name 'sys' is not defined
Traceback (most recent call last):
  File "<input>", line 1, in <module>
NameError: name 'sys' is not defined
Traceback (most recent call last):
  File "<input>", line 1, in <module>
NameError: name 'sys' is not defined
Traceback (most recent call last):
  File "<input>", line 1, in <module>
NameError: name 'sys' is not defined
Traceback (most recent call last):
  File "<input>", line 1, in <module>
NameError: name 'sys' is not defined
Traceback (most recent call last):
  File "<input>", line 1, in <module>
NameError: name 'sys' is not defined
Traceback (most recent call last):
  File "<input>", line 1, in <module>
NameError: name 'sys' is not defined
Traceback (most recent call last):
  File "<input>", line 1, in <module>
NameError: name 'sys' is not defined
Traceback (most recent call last):
  File "<input>", line 1, in <module>
NameError: name 'sys' is not defined
Traceback (most recent call last):
  File "<input>", line 1, in <module>
NameError: name 'sys' is not defined
Traceback (most recent call last):
  File "<input>", line 1, in <module>
NameError: name 'sys' is not defined
Traceback (most recent call last):
  File "<input>", line 1, in <module>
NameError: name 'sys' is not defined
Traceback (most recent call last):
  File "<input>", line 1, in <module>
NameError: name 'sys' is not defined
Traceback (most recent call last):
  File "<input>", line 1, in <module>
NameError: name 'sys' is not defined
Traceback (most recent call last):
  File "<input>", line 1, in <module>
NameError: name 'sys' is not defined
Traceback (most recent call last):
  File "<input>", line 1, in <module>
NameError: name 'sys' is not defined
Traceback (most recent call last):
  File "<input>", line 1, in <module>
NameError: name 'sys' is not defined
Traceback (most recent call last):
  File "<input>", line 1, in <module>
NameError: name 'sys' is not defined
Traceback (most recent call last):
  File "<input>", line 1, in <module>
NameError: name 'sys' is not defined
Traceback (most recent call last):
  File "<input>", line 1, in <module>
NameError: name 'sys' is not defined
Traceback (most recent call last):
  File "<input>", line 1, in <module>
NameError: name 'sys' is not defined
Traceback (most recent call last):
  File "<input>", line 1, in <module>
NameError: name 'sys' is not defined
Traceback (most recent call last):
  File "<input>", line 1, in <module>
NameError: name 'sys' is not defined
Traceback (most recent call last):
  File "<input>", line 1, in <module>
NameError: name 'sys' is not defined
Traceback (most recent call last):
  File "<input>", line 1, in <module>
NameError: name 'sys' is not defined
Traceback (most recent call last):
  File "<input>", line 1, in <module>
NameError: name 'sys' is not defined
Traceback (most recent call last):
  File "<input>", line 1, in <module>
NameError: name 'sys' is not defined
Traceback (most recent call last):
  File "<input>", line 1, in <module>
NameError: name 'sys' is not defined
Traceback (most recent call last):
  File "<input>", line 1, in <module>
NameError: name 'sys' is not defined
Traceback (most recent call last):
  File "<input>", line 1, in <module>
NameError: name 'sys' is not defined
Traceback (most recent call last):
  File "<input>", line 1, in <module>
NameError: name 'sys' is not defined
Traceback (most recent call last):
  File "<input>", line 1, in <module>
NameError: name 'sys' is not defined
Traceback (most recent call last):
  File "<input>", line 1, in <module>
NameError: name 'sys' is not defined
Traceback (most recent call last):
  File "<input>", line 1, in <module>
NameError: name 'sys' is not defined
Traceback (most recent call last):
  File "<input>", line 1, in <module>
NameError: name 'sys' is not defined
Traceback (most recent call last):
  File "<input>", line 1, in <module>
NameError: name 'sys' is not defined
Traceback (most recent call last):
  File "<input>", line 1, in <module>
NameError: name 'sys' is not defined
Traceback (most recent call last):
  File "<input>", line 1, in <module>
NameError: name 'sys' is not defined
Traceback (most recent call last):
  File "<input>", line 1, in <module>
NameError: name 'sys' is not defined
Traceback (most recent call last):
  File "<input>", line 1, in <module>
NameError: name 'sys' is not defined
Traceback (most recent call last):
  File "<input>", line 1, in <module>
NameError: name 'sys' is not defined
Traceback (most recent call last):
  File "<input>", line 1, in <module>
NameError: name 'sys' is not defined
Traceback (most recent call last):
  File "<input>", line 1, in <module>
NameError: name 'sys' is not defined
Traceback (most recent call last):
  File "<input>", line 1, in <module>
NameError: name 'sys' is not defined
Traceback (most recent call last):
  File "<input>", line 1, in <module>
NameError: name 'sys' is not defined
Traceback (most recent call last):
  File "<input>", line 1, in <module>
NameError: name 'sys' is not defined
Traceback (most recent call last):
  File "<input>", line 1, in <module>
NameError: name 'sys' is not defined
Traceback (most recent call last):
  File "<input>", line 1, in <module>
NameError: name 'sys' is not defined
Traceback (most recent call last):
  File "<input>", line 1, in <module>
NameError: name 'sys' is not defined
Traceback (most recent call last):
  File "<input>", line 1, in <module>
NameError: name 'sys' is not defined
Traceback (most recent call last):
  File "<input>", line 1, in <module>
NameError: name 'sys' is not defined
Traceback (most recent call last):
  File "<input>", line 1, in <module>
NameError: name 'sys' is not defined
Traceback (most recent call last):
  File "<input>", line 1, in <module>
NameError: name 'sys' is not defined
Traceback (most recent call last):
  File "<input>", line 1, in <module>
NameError: name 'sys' is not defined
Traceback (most recent call last):
  File "<input>", line 1, in <module>
NameError: name 'sys' is not defined
Traceback (most recent call last):
  File "<input>", line 1, in <module>
NameError: name 'sys' is not defined
Traceback (most recent call last):
  File "<input>", line 1, in <module>
NameError: name 'sys' is not defined
2019-9-18 00:30
0
雪    币: 145
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
22
TinHsieh (lldb) debugme [*] start patch ptrace funtion to bypass antiDebug [+] success ptrace funtion to by ...
是不是因为这些错误,导致出了一些问题?
2019-9-18 00:30
0
雪    币: 1597
活跃值: (719)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
23
TinHsieh 是不是因为这些错误,导致出了一些问题?
什么app我这边测试一下,我看日志的话ptrace这种反调试已经成功patch了,svc指令patch好像出问题了
2019-9-18 12:39
0
雪    币: 36
活跃值: (1061)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
24
mark,感谢大佬分享
2019-9-18 14:37
0
雪    币: 707
活跃值: (1301)
能力值: ( LV9,RANK:190 )
在线值:
发帖
回帖
粉丝
25
mark,感谢大佬分享
2021-4-29 14:31
0
游客
登录 | 注册 方可回帖
返回
//