我不能在64位linux上修改RIP寄存器

时间:2014-01-03 17:00:46

标签: gcc assembly gdb 64-bit stack-overflow

我正在尝试了解堆栈溢出,但我读到的只是32位。我的处理器是64位,我遇到以下问题:

C代码:

#include <stdio.h>
#include <string.h>
void return_input (void)
{ 
char array[30]; 
gets (array); 
printf("%s\n", array); 
}
int main() 
{ 
return_input(); 
return 0; 

}

GDB disas main:

Dump of assembler code for function main:
   0x000000000040055f <+0>: push   %rbp
   0x0000000000400560 <+1>: mov    %rsp,%rbp
   0x0000000000400563 <+4>: callq  0x40053d <return_input>
   0x0000000000400568 <+9>: mov    $0x0,%eax
   0x000000000040056d <+14>:    pop    %rbp
   0x000000000040056e <+15>:    retq   
End of assembler dump.

GDB disas return_input:

   Dump of assembler code for function return_input:
   0x000000000040053d <+0>: push   %rbp
   0x000000000040053e <+1>: mov    %rsp,%rbp
   0x0000000000400541 <+4>: sub    $0x20,%rsp
   0x0000000000400545 <+8>: lea    -0x20(%rbp),%rax
   0x0000000000400549 <+12>:    mov    %rax,%rdi
   0x000000000040054c <+15>:    callq  0x400440 <gets@plt>
   0x0000000000400551 <+20>:    lea    -0x20(%rbp),%rax
   0x0000000000400555 <+24>:    mov    %rax,%rdi
   0x0000000000400558 <+27>:    callq  0x400410 <puts@plt>
   0x000000000040055d <+32>:    leaveq 
   0x000000000040055e <+33>:    retq 

编译说明:

cc -mpreferred-stack-boundary=4 -ggdb overflow.c -o overflow
or
cc -mpreferred-stack-boundary=4 -ggdb -fno-stack-protector -z execstack overflow.c -o overflow

好吧,我正在尝试将RIP修改为0x0000000000400563,并使代码要求输入两次,但它可以正常工作。

我发现代码崩溃时输入了40个字符。所以我尝试了以下输入:

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\x63\x05\x40\x00

break *0x000000000040055

(gdb) x/12x $rsp
0x7fffffffe280: 0x41414141  0x41414141  0x41414141  0x41414141
0x7fffffffe290: 0x41414141  0x41414141  0x41414141  0x41414141
0x7fffffffe2a0: 0x41414141  0x41414141  0x3336785c  0x3530785c
(gdb) 

没有崩溃的正常输入:

AAAAAAAAAAAAAAAAAAAAAAAAA

break *0x000000000040055

(gdb) x/12x $rsp
0x7fffffffe280: 0x41414141  0x41414141  0x41414141  0x41414141
0x7fffffffe290: 0x41414141  0x41414141  0x00400041  0x00000000
0x7fffffffe2a0: 0xffffe2b0  0x00007fff  0x00400568  0x00000000
(gdb) 

正如您所看到的,此处堆栈指向0x00400568但是对于controll的输入,RIP指向0x3336785c。为什么?我不能以正确的方式注入地址。

感谢您的时间。我会真的回应任何答案。

1 个答案:

答案 0 :(得分:1)

  

所以我尝试了以下输入:

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\x63\x05\x40\x00

您将文字字符'\\', '6', '3', '\\', '0', '5'等(即其ASCII码)放入缓冲区。但你假设将实际数字0x400563放在那里,而不是'4', '0'等的ASCII代码。

通常的方法是通过管道输出来实现,例如

perl -e 'print "A" x 20, "\x63", "\x05", "\x40", "\x00"'

到你的程序输入。

更新

  

但我如何把gdb“perl -e ...”

实现此目的的通常方法是将所需的输出放入文件中:

printf "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\x63\x05\x40\x00" > /tmp/t

然后使用GDB输入重定向:

(gdb) run < /tmp/t