2

我在使用gdb调试我的代码时,遇到了这个问题。gdb显示如下:

(gdb) ni
0x08048ca5 in getbufn ()
(gdb) disas 0x08048c98
Dump of assembler code for function getbufn:
0x08048c89 <+0>:     push   %ebp
0x08048c8a <+1>:     mov    %esp,%ebp
0x08048c8c <+3>:     sub    $0x208,%esp
0x08048c92 <+9>:     lea    -0x200(%ebp),%eax
0x08048c98 <+15>:    mov    %eax,(%esp)
0x08048c9b <+18>:    call   0x8048bf4 <Gets>
0x08048ca0 <+23>:    mov    $0x1,%eax
=> 0x08048ca5 <+28>:    leave  
0x08048ca6 <+29>:    ret    
End of assembler dump.
(gdb) p /x $ebp
$1 = 0x55683950
(gdb) p /x $esp
$2 = 0x55683748
(gdb) ni
0x08048ca6 in getbufn ()
(gdb) p /x $ebp
$3 = 0x4030201
(gdb) p /x $esp
$4 = 0x55683954
(gdb) x /1xw $esp
0x55683954:     0x55683750
(gdb) si
Cannot access memory at address 0x4030205
(gdb) 

0x08048ca6中的代码是“ret”,意思是jmp(%esp), addl 0x4,%esp 所以我想知道为什么gdb的最后一句是“Cannot access memory at address 0x4030205” 是不是应该执行地址0x55683750的指令代码?

谢谢!

4

2 回答 2

1

你好 -

                     ; Enter subroutine: build stack frame
0x08048c89 <+0>:     push   %ebp            ; Save the old buffer pointer
0x08048c8a <+1>:     mov    %esp,%ebp       ; Save the current stack pointer
0x08048c8c <+3>:     sub    $0x208,%esp     ; Allocate space for local variables

0x08048c92 <+9>:     lea    -0x200(%ebp),%eax ; call "gets()" subroutine
0x08048c98 <+15>:    mov    %eax,(%esp)
0x08048c9b <+18>:    call   0x8048bf4 <Gets>

0x08048ca0 <+23>:    mov    $0x1,%eax       ; eax <= 1

=> 0x08048ca5 <+28>:    leave  ; we *think* we're leaving the subroutine...but
0x08048ca6 <+29>:    ret       ; in fact we crash at this point

结论:

“gets()”中的某些东西破坏了你的堆栈,所以你不能从你的子程序中返回。

建议:

不要使用“gets()”。这不安全。大多数编译器实际上会警告您它不安全。改用“fgets()”(或任何数量的其他替代方法来输入字符串):

http://cboard.cprogramming.com/c-programming/137352-gets-unsafe-method-alternatives.html

恕我直言...

于 2012-06-17T05:03:17.653 回答
0

“=>”指向即将执行的指令,在这种情况下是“离开”。并且“leave”被定义为首先设置espebp,然后是 pop ebp。一旦esp设置为ebp(即0x4030201,一个错误的地址,并且看起来可疑地像是从字节 1、2、3、4 生成的),弹出失败。

您可能想查看ebp调用 . 之前和之后的值Gets()。我的猜测是调用会Gets()导致该寄存器被修改,这不应该像ebp通常被调用者保存那样发生。

请注意,虽然Gets()使用 512 字节的堆栈缓冲区调用可能是不可取的,但在这种情况下,缓冲区溢出不会导致崩溃。缓冲区溢出可能会ret跳转到其他地方,但不会导致ebp被修改。

于 2013-02-13T23:20:46.670 回答