macOS软件安全与逆向分析初探

MacOS安全机制

Rootless

MacOS 10.11引入了一个新的安全特性:Rootless,又称为SIP (System Integrity Protection,系统完整性保护)。通过Rootless系统可以决定即使第三方程序获取了系统Root权限,也不能:

  • 文件系统保护,系统中重要的目录与文件不能被第三方程序任意修改;
  • 运行时保护,向一个系统进程注入代码是受限的;
  • 内核扩展限制,禁止通过设置kext-dev-mode=1来加载第三方驱动。

可以通过以下命令查看是否开启了Rootless:

1
2
3
4
5
$ csrutil status
# System Integrity Protection status: disabled.
# 禁用Rootless
$ csrutil disable

Gatekeeper

Gatekeeper安全机制用于检测从互联网上下载或者其他地方安装的软件,当他们在系统中首次运行时,确保他们的行为对系统没有危害。
可以通过以下命令查看是否开启了Gatekeeper:

1
2
3
4
5
$ spctl --status
# assessments disabled
# 关闭Gatekeeper
$ sudo spctl --master-disable

第一个逆向工程

HelloCrack

这里用一个简单的小程序来入门:

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <stdio.h>
int main() {
int secret = 0;
printf("Please enter the secret num:");
scanf("%d", &secret);
if (secret != 123) {
printf("Incorrect secret num.\n");
return 0;
}
printf("Hello world!\n");
return 0;
}

1
$ clang hellocrack.c -o HelloCrack

HT Editor

我们编译安装HT Editor来反汇编二进制程序。

1
2
3
4
5
$ git clone https://github.com/sebastianbiallas/ht.git
$ cd ht
$ ./autogen.sh
$ ./configure
$ make; make htdoc.h # due to bad dependency

如果是从release版的tarball安装,可能会遇到如下错误:

1
2
3
htapp.cc:3026:9: error: call to 'abs' is ambiguous
while (abs(a - b) > 1) {
^~~

将这里的abs改成fabs再编译即可。

定位修改逻辑

使用HT Editor或Hopper对二进制程序分析,得到反汇编代码。根据错误提示,搜索字符串”Incorrect secret num”,定位到逻辑点:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
0000000100000ef0 je loc_100000f13
0000000100000ef6 lea rdi, qword [0x100000f84] ; "Incorrect secret num.\\n", argument "format" for method imp___stubs__printf
0000000100000efd mov al, 0x0
0000000100000eff call imp___stubs__printf
0000000100000f04 mov dword [rbp+var_4], 0x0
0000000100000f0b mov dword [rbp+var_14], eax
0000000100000f0e jmp loc_100000f2b
loc_100000f13:
0000000100000f13 lea rdi, qword [0x100000f9b] ; "Hello world!\\n", argument "format" for method imp___stubs__printf, CODE XREF=_main+64
0000000100000f1a mov al, 0x0
0000000100000f1c call imp___stubs__printf
0000000100000f21 mov dword [rbp+var_4], 0x0
0000000100000f28 mov dword [rbp+var_18], eax
loc_100000f2b:
0000000100000f2b mov eax, dword [rbp+var_4] ; CODE XREF=_main+94
0000000100000f2e add rsp, 0x20
0000000100000f32 pop rbp
0000000100000f33 ret
; endp

可以看到当验证成功程序跳转到了地址100000f13,调用printf输出了Hello World

1
0000000100000ef0 je loc_100000f13

je命令改为jnz,可以让程序逻辑反转,即错误的密码可以输出Hello World。但是这样的破解并不完美,想要在任何情况下都输出Hello World,将je改为jmp即可。