Search code examples
csegmentation-faultgdbshellcode

Testing Shellcode With GDB


If I just execute shell code program It makes segmentation fault like this

desktop:~$ ./sh02
Segmentaion fault (core dumped)

But, when I debug this program with GDB, this program executes /bin/sh successfully

(gdb) disass 0x4005a0
No function contains specified address.
(gdb) shell ps
  PID TTY          TIME CMD
 4075 pts/4    00:00:00 bash
 4099 pts/4    00:00:00 gdb
 4101 pts/4    00:00:00 sh
 4107 pts/4    00:00:00 ps
(gdb) 

After debugging with GDB, this program works well ... I can't find difference between them

Why I can't run /bin/sh via sh02 program before debugging?

const char str[]=
"\x55"
"\x48\x89\xe5"
"\x48\x31\xff"
"\x57"
"\x57"
"\x5e"
"\x5a"
"\x48\xbf\x2f\x2f\x62\x69\x6e"
"\x2f\x73\x68"
"\x57"
"\x54"
"\x5f"
"\x6a\x3b"
"\x58"
"\x0f\x05"
"\x90"
"\x5d"
"\xc3";

int main()
{
    int (*func)();

    func = (int (*)()) str;

    (int)(*func)();
}

Above is sh02.c code.

I read that questions and answers. But I think my case is little bit different. During debugging with GDB and after debugging sh02 program execute /bin/sh successfully. However only before debugging, it makes segmentation fault

I use Ubuntu 16.04 and x64 architecture


Solution

  • When undefined behavior is invoked the program may crash or not crash (by luck). The program does not null terminate the string sent to exec, the results are undefined.

    Try this:

    "\x48\xbf\x2f\x62\x69\x6e"
    "\x2f\x73\x68\x00"
    

    Note that I dropped the extra '/' and added the '\0' at the end of the string.

    I was able to determine the issue by using gdb.

    Here is the session perhaps this will help you to learn assembly debugging.

    parallels@ubuntu:/tmp$ gcc -g  -fno-stack-protector -z execstack -o shellcode shellcode2.c
    parallels@ubuntu:/tmp$ gdb ./shellcode 
    GNU gdb (Ubuntu 7.7.1-0ubuntu5~14.04.2) 7.7.1
    ...
    Reading symbols from ./shellcode...done.
    (gdb) b main
    Breakpoint 1 at 0x4004f5: file shellcode2.c, line 25.
    (gdb) r
    Starting program: /tmp/shellcode 
    
    Breakpoint 1, main () at shellcode2.c:25
    25      func = (int (*)()) str;
    (gdb) n
    27      (int)(*func)();
    (gdb) stepi
    0x0000000000400501  27      (int)(*func)();
    (gdb) stepi
    0x0000000000400506  27      (int)(*func)();
    (gdb) stepi
    0x00000000004005c0 in str ()
    (gdb) disass
    Dump of assembler code for function str:
    => 0x00000000004005c0 <+0>: push   %rbp
       0x00000000004005c1 <+1>: mov    %rsp,%rbp
       0x00000000004005c4 <+4>: xor    %rdi,%rdi
       0x00000000004005c7 <+7>: push   %rdi
       0x00000000004005c8 <+8>: push   %rdi
       0x00000000004005c9 <+9>: pop    %rsi
       0x00000000004005ca <+10>:    pop    %rdx
       0x00000000004005cb <+11>:    movabs $0x68732f6e69622f2f,%rdi
       0x00000000004005d5 <+21>:    push   %rdi
       0x00000000004005d6 <+22>:    push   %rsp
       0x00000000004005d7 <+23>:    pop    %rdi
       0x00000000004005d8 <+24>:    pushq  $0x3b
       0x00000000004005da <+26>:    pop    %rax
       0x00000000004005db <+27>:    syscall 
       0x00000000004005dd <+29>:    nop
       0x00000000004005de <+30>:    pop    %rbp
       0x00000000004005df <+31>:    retq   
       0x00000000004005e0 <+32>:    add    %al,(%rax)
    End of assembler dump.
    (gdb) b *0x4005db
    Breakpoint 2 at 0x4005db
    (gdb) c
    Continuing.
    
    Breakpoint 2, 0x00000000004005db in str ()
    (gdb) info reg
    rax            0x3b 59
    rbx            0x0  0
    rcx            0x0  0
    rdx            0x0  0
    rsi            0x0  0
    rdi            0x7fffffffdef8   140737488346872
    rbp            0x7fffffffdf00   0x7fffffffdf00
    rsp            0x7fffffffdef8   0x7fffffffdef8
    r8             0x7ffff7dd4e80   140737351863936
    r9             0x7ffff7dea560   140737351951712
    r10            0x7fffffffddb0   140737488346544
    r11            0x7ffff7a36dd0   140737348070864
    r12            0x400400 4195328
    r13            0x7fffffffe000   140737488347136
    r14            0x0  0
    r15            0x0  0
    rip            0x4005db 0x4005db <str+27>
    eflags         0x246    [ PF ZF IF ]
    cs             0x33 51
    ss             0x2b 43
    ds             0x0  0
    es             0x0  0
    fs             0x0  0
    gs             0x0  0
    (gdb) p (char*) $rdi
    $1 = 0x7fffffffdef8 "//bin/sh \337\377\377\377\177"
    

    As you can see the string has an extra '/' and no NULL terminator. A simple two character fix and all is well.