【问题标题】:Stack address not corresponding (Trying to understand Buffer overflow)堆栈地址不对应(试图理解缓冲区溢出)
【发布时间】:2014-12-09 15:43:15
【问题描述】:

我一直在 http://insecure.org/stf/smashstack.html 关注本教程,但在 example3.c 我的函数返回地址与他暗示的逻辑不符。我可以理解如何在函数中更改返回地址,但在我的计算机上执行此操作并不能解决问题。我已经将 -fno-stack-protector 和 gdb 与信息寄存器一起使用,并反汇编 main 并反汇编函数,但无济于事。我对大会有点陌生。 我的电脑运行的是 xubuntu 14 32bits。 我的 gcc 指令是: gcc -Wall -ansi -g -fno-stack-protector example3.c

example3.c:
------------------------------------------------------------------------------
void function(int a, int b, int c) {
   char buffer1[5];
   char buffer2[10];
   int *ret;

   ret = buffer1 + 12;
   (*ret) += 8;
}

void main() {
  int x;

  x = 0;
  function(1,2,3);
  x = 1;
  printf("%d\n",x);
}
------------------------------------------------------------------------------

gdb 在 main 上反汇编,并在函数调用上设置断点

(gdb) disassemble main
Dump of assembler code for function main:
   0x0804843b <+0>: push   %ebp
   0x0804843c <+1>: mov    %esp,%ebp
   0x0804843e <+3>: and    $0xfffffff0,%esp
   0x08048441 <+6>: sub    $0x20,%esp
   0x08048444 <+9>: movl   $0x0,0x1c(%esp)
=> 0x0804844c <+17>:    movl   $0x3,0x8(%esp)
   0x08048454 <+25>:    movl   $0x2,0x4(%esp)
   0x0804845c <+33>:    movl   $0x1,(%esp)
   0x08048463 <+40>:    call   0x804841d <function>
   0x08048468 <+45>:    movl   $0x1,0x1c(%esp)
   0x08048470 <+53>:    mov    0x1c(%esp),%eax
   0x08048474 <+57>:    mov    %eax,0x4(%esp)
   0x08048478 <+61>:    movl   $0x8048520,(%esp)
   0x0804847f <+68>:    call   0x80482f0 <printf@plt>
   0x08048484 <+73>:    leave  
   0x08048485 <+74>:    ret    
End of assembler dump.


(gdb) disassemble function 
Dump of assembler code for function function:
   0x0804841d <+0>: push   %ebp
   0x0804841e <+1>: mov    %esp,%ebp
   0x08048420 <+3>: sub    $0x20,%esp
=> 0x08048423 <+6>: lea    -0x9(%ebp),%eax
   0x08048426 <+9>: add    $0xc,%eax
   0x08048429 <+12>:    mov    %eax,-0x4(%ebp)
   0x0804842c <+15>:    mov    -0x4(%ebp),%eax
   0x0804842f <+18>:    mov    (%eax),%eax
   0x08048431 <+20>:    lea    0x8(%eax),%edx
   0x08048434 <+23>:    mov    -0x4(%ebp),%eax
   0x08048437 <+26>:    mov    %edx,(%eax)
   0x08048439 <+28>:    leave  
   0x0804843a <+29>:    ret    
End of assembler dump.

在函数的第9行,*ret指向一个完全不同的地址

9     (*ret) += 8;
(gdb) p/x *ret
$1 = 0x48468c7 (already with the + 8)

所以澄清一下,这个程序应该打印 0,因为返回被更改为跳过 x = 1 指令。

我的问题是,为什么 *ret 不指向一个与 main 对应地址有点接近的地址?

对不起我的英语。

最好的问候, 视频编码器

【问题讨论】:

    标签: c gcc assembly stack-overflow


    【解决方案1】:

    你的教程是关于一些非常古老的编译器的。

    让我们处理具有相同结果的实验​​(例如 gcc 4.8.1,64 位 Win32):

    第 1 步。确定函数真正开始的位置:

    (gdb) disassemble function
    Dump of assembler code for function function:
    => 0x00000000004014f0 <+0>:     push   %rbp
    

    第 2 步。将其地址存储在某处并在此处中断

    (gdb) b *0x00000000004014f0
    Breakpoint 1 at 0x4014f0: file test3.c, line 1.
    (gdb) r
    Breakpoint 1, function (a=1, b=4200201, c=4) at test3.c:1
    1       void function(int a, int b, int c) {
    

    第 3 步。好的,我们到了。让我们探索一下我们的返回地址存储在哪里:

    (gdb) p $rsp
    $1 = (void *) 0x22fe18
    (gdb) x 0x22fe18
    0x22fe18:       0x0040154c
    

    哇。让我们检查一下 main:

    0x0000000000401547 <+36>:    callq  0x4014f0 <function>
    0x000000000040154c <+41>:    movl   $0x1,-0x4(%rbp)
    

    第 4 步。看起来我们找到了。在某处存储 $rsp=0x22fe18 的值,现在让我们看看什么是缓冲区开始:

    7          (*ret) += 8;
    (gdb) p &buffer1[0] 
    $2 = 0x22fe00 "`\035L"
    

    所以缓冲区[0]地址是我们目标的 0x22fe18 - 0x22fe00 = 0x18。不是 0xc,就像在你的例子中那样,呃-哦。

    附:在您的编译器和操作系统以及您的优化选项上,它可能不是 0x18,而是其他值。尝试。实验。成为黑客是关于试验,而不是运行某人的脚本。

    祝你好运。

    【讨论】:

    • “实验。作为黑客是关于实验,而不是运行某人的脚本。”我明白这一点,但我需要先了解我在做什么,对不起,但我被认为是先思考再做,而不是相反,从这个脚本开始我试图理解汇编。不过谢谢你的回答。
    • 我概述了思考过程。您必须先计算正确的偏移量,然后再覆盖它。什么不清楚?
    • 没有什么不清楚的对不起,你的回答很完美。我被你的评论冒犯了,因为我明白什么是脚本小子。但这是我的问题。没关系。
    • 我很抱歉。我的目的是启发,而不是冒犯。
    猜你喜欢
    • 1970-01-01
    • 2017-02-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-11
    • 2019-01-05
    • 1970-01-01
    • 2015-07-03
    相关资源
    最近更新 更多