user4929293 user4929293 - 1 year ago 66
C Question

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

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[]=

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

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


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

Answer Source

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:


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

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.