使用 GDB 测试 Shellcode

Testing Shellcode With GDB

如果我只是执行shell代码程序它会产生这样的分段错误

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

但是,当我用 GDB 调试这个程序时,这个程序执行 /bin/sh 成功

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

用GDB调试后,这个程序运行良好... 我找不到它们之间的区别

为什么我在调试前无法通过 sh02 程序 运行 /bin/sh?

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

以上是sh02.c代码。

我读了那个问题和答案。但我认为我的情况有点不同。在使用 GDB 调试期间和调试 sh02 程序后,成功执行 /bin/sh。然而,仅在调试之前,它会导致分段错误

我使用 Ubuntu 16.04 和 x64 架构

当调用未定义的行为时,程序可能会崩溃或不会崩溃(运气好)。程序没有空终止发送给 exec 的字符串,结果是未定义的。

试试这个:

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

请注意,我删除了多余的“/”并在字符串末尾添加了“\0”。

我能够使用 gdb 确定问题。

这是会话,也许这将帮助您学习汇编调试。

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 [=11=]x68732f6e69622f2f,%rdi
   0x00000000004005d5 <+21>:    push   %rdi
   0x00000000004005d6 <+22>:    push   %rsp
   0x00000000004005d7 <+23>:    pop    %rdi
   0x00000000004005d8 <+24>:    pushq  [=11=]x3b
   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
 = 0x7fffffffdef8 "//bin/sh 77777"

如您所见,该字符串有一个额外的“/”并且没有 NULL 终止符。一个简单的两个字符修复,一切都很好。