首页
社区
课程
招聘
[原创]逆向分析(一)--首次针对苹果M1芯片的恶意软件GoSearch22
2023-12-16 10:20 6614

[原创]逆向分析(一)--首次针对苹果M1芯片的恶意软件GoSearch22

2023-12-16 10:20
6614

arm64恶意软件分析

​ 能够理解汇编语言并在底层上进行逆向是恶意软件分析人员的核心技能要求。

​ 有很多可以在沙箱环境中执行自动分析并记录软件运行时的任何变化的工具。对于更高级更深入的分析,恶意软件分析师使用静态和动态分析工具(反汇编器、反编译器、系统监控工具、调试器)的组合来绕过反分析和混淆技术,进行收集、检测和修复。

​ 动态分析主要是执行二进制文件,如恶意软件,以观察其行为。我们要确保这个过程始终在分隔的虚拟机中执行,或者在专用的恶意软件分析机上进行。千万不要在主系统上执行动态分析!关于如何创建一个专用的macOS恶意软件分析虚拟机,请参考https://www.sentinelone.com/blog/how-to-reverse-macos-malware-part-one/。

GoSearch22

​ 如果你想玩,你可以从下面的地址下载GoSearch这个恶意软件:http://objective-see.com/downloads/blog/blog_0x62/GoSearch.zip

​ 记住,这是恶意软件,一定要在隔离环境中运行!!!

1
2
3
4
5
6
7
8
9
10
11
首先,我们要通过lipo的-archs来枚举Gosearch22这个二进制文件的架构,我们需要注意的是arm64的
 
% lipo -archs GoSearch22
x86_64 arm64
 
然后通过-thin,提取arm64二进制文件,使用file确认解压成功
 
% lipo GoSearch22 -thin arm64 -output GoSearch22_arm64
 
% file GoSearch22_arm64
GoSearch22_arm64: Mach-O 64-bit executable arm64

Anti-Analysis Techniques

​ 恶意软件的作者一般非常了解常见的恶意软件分析技术,因此,他们可能会实施所谓的“反分析”,来使逆向工作复杂化。在分析恶意软件时,会遇到各种类型的防御机制,例如anti-debugging,检测是否正在被调试,anti-VM,是否在虚拟机里运行。在GoSearch22这个恶意软件里用了这两种防御机制,所以将在此进行详细讨论。

​ 你还可能遇到其他的防御机制,如anti-emulation、anti-dumping。

​ 如何确定恶意软件中是否包含这些防御机制呢?一种方法是当你试图动态分析它时,它是否会过早退出。

​ 如果你怀疑恶意软件中包含这样的逻辑,那么首先应该是找出恶意软件中造成这种情况的特定代码的行为。一旦确定,就想办法绕过它。

anti-debugging logic(via ptrace)

1
2
3
4
5
6
% lldb GoSearch22.app
(lldb) target create "GoSearch22.app"
Current executable set to '/Users/user/Downloads/GoSearch22.app' (arm64).
(lldb) c
Process 654 resuming
Process 654 exited with status = 45 (0x0000002d)

注:lldb(http://lldb.llvm.org/use/tutorial.html) 实际上是Apple系统(包括macOS)的调试器。可通过命令行直接执行,也可集成到多种逆向工具中。(在本文中,我们使用了专注于macOS的反汇编器和反编译器Hopper。)

1
2
3
4
5
6
% 11db Gosearch22.app
(11db) target create "GoSearch22.app"
Current executable set to '/Users/user/Downloads/GoSearch22.app' (arm64).
(lldb) c
Process 654 resuming
Process 654 exited with status = 45 (0x0000002d)

​ 退出代码45(0x2d)相当独特,实际上相当说明问题。经验丰富的macOS恶意软件分析人员将识别出这个状态代码,因为debuggee(在这里,恶意软件)调用ptrace系统调用(或API)的结果,带有PT_DENY_ATTACH标志。
​ 顾名思义,PT_DENY_ATTACH标志指示操作系统阻止debuggee被调试。一旦发出ptrace系统调用,随后连接调试器的尝试将失败,或者如果进程已经被调试,它将提前终止,退出代码为45(0x2d)。
这个标志是一个非标准的ptrace请求类型,由苹果添加,因此只在其操作系统上得到支持。检查苹果的XNU源代码(bsd/sys/ptrace.h)显示PT_DENY_ATTACH标志的值为0x1F。
​ 当然,恶意软件肯定不愿被调试,因此GoSearch22实现这种反分析逻辑并不奇怪。不过幸运的是,通过跳过ptrace调用,绕过调试器中的这种反分析技术是相当简单的,因此它从一开始就不会执行。要做到这一点,我们需要定位恶意软件调用ptrace的位置。查看GoSearch22的反编译代码,会发现大量旨在使静态分析复杂化的花指令(如定位反分析逻辑)。例如,在恶意软件的入口点中发现的以下代码中,请注意无意义的嵌套条件检查以及对dlsym函数的虚假调用:

1
2
3
4
5
6
7
8
9
10
11
12
r9 = 0x3f35713b;
...
r8 = r9;
 if (r8 <= 0xb33cc16b) {
 if (r8 > 0x9fbc741a) {
 if (r8 > 0xa693fc1a) {
 if (r8 != 0xa693fc1b) {
 if (r8 != 0xb0d2dccd) {
...
dlsym(dlopen(0x0, 0xa), 0x100076458);
dlsym(dlopen(0x0, 0xa), 0x100076440);
dlsym(dlopen(0x0, 0xa), 0x100076428);

注:有关此方案和其他类似混淆方案的更多详细信息,请参阅“Using LLVM to obfuscate your code during compilation”(www.apriorit.com/dev-blog/687-reverse-engineering-llvm-obfuscation) 。此外,如下图,该恶意软件不包含对 ptrace 用户模式 API 的调用。

​ 很奇怪吗?其实并不特别,因为恶意软件很可能只是试图掩盖调试功能的调用。实现这一点的一个简单方法是通过直接调用ptrace系统调用(SYS_ptrace)实现的。参考系统调用名称到它们的系统调用号的映射,我们看到ptrace系统调用被分配为26 (0x1a)。

1
2
3
4
% less /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.
platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/syscall.h
...
#define SYS_ptrace 26

回顾调用系统调用的arm64汇编指令是svc(supervisor call),我们可以使用反汇编器的搜索功能(⌘+F)来查找对该指令的调用,如图12.8所示。

​ 如果找到svc指令,Hopper将跳转到主拆卸窗口中的位置。Hopper在0x00000001000541fc找到该指令的第一个实例:

1
2
3
4
5
6
7
0x00000001000541e8 movz x0, #0x1a
0x00000001000541ec movz x1, #0x1f
0x00000001000541f0 movz x2, #0x0
0x00000001000541f4 movz x3, #0x0
...
0x00000001000541fc svc #0x80
0x0000000100054200 mov w11, #0x6b8f

​ 首先,用0x1a初始化X0寄存器,这是ptrace (SYS_ptrace)的系统调用号。x1寄存器设置为0x1f,即PT_DENY_ATTACH的值。另外两个参数X2和X3被设置为零。然后在0x00000001000541fc处,通过SVC指令进行调用。
​ 如前所述,使用PT_DENY_ATTACH调用SYS_ptrace试图阻止调试,或者,如果正在调试恶意软件,将导致恶意软件以退出码45 (0x2d)终止。
​ 现在我们已经在调试会话中检测到反调试逻辑的位置,我们可以跳过调用。一种简单的方法是在SVC指令上设置一个断点。由于SVC指令在0x00000001000541fc处执行,我们通过以下命令在LLDB调试会话中设置一个断点:

1
2
3
% lldb GoSearch22.app
...
(lldb) b 0x00000001000541fc

​ 设置了这个断点后,一旦CPU被设置为执行该指令,调试器将停止执行。此时,我们可以将程序计数器(PC)的地址更改为SVC指令之后的指令。在反汇编程序中,我们可以看到下一条指令位于0x0000000100054200。
​ 可以通过reg write调试器命令更改任何寄存器的值,包括程序计数器。在调试会话中,一旦遇到断点,我们就可以执行该命令,将程序计数器设置为0x0000000100054200,并跳过有问题的SVC指令。

1
2
3
4
5
6
7
% lldb GoSearch22.app
(lldb) b 0x00000001000541fc
Breakpoint 1: address = 0x00000001000541fc(lldb) Process 1486 stopped
* thread #1, queue = 'com.apple.main-thread'
 stop reason = breakpoint 1.1:
-> 0x00000001000541fc svc #0x80
(lldb) reg write $pc 0x0000000100054200

​ 当SVC指令被跳过时,它将不会被执行。这巧妙地避免了SYS_ptrace反调试逻辑…不过,不幸的是类似的还有更多。


[CTF入门培训]顶尖高校博士及硕士团队亲授《30小时教你玩转CTF》,视频+靶场+题目!助力进入CTF世界

最后于 2023-12-16 10:31 被boilsnow编辑 ,原因:
收藏
点赞7
打赏
分享
最新回复 (1)
雪    币: 19349
活跃值: (28971)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
秋狝 2023-12-16 23:20
2
0
感谢分享
游客
登录 | 注册 方可回帖
返回