我一直在http://insecure.org/stf/smashstack.html学习本教程,但是在example3.c我的函数返回地址与他所暗示的逻辑并不对应。我可以理解如何在函数中更改返回地址,但在我的计算机上执行此操作只是不起作用。我已经使用-fno-stack-protector和gdb与info寄存器和反汇编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指令。
我的问题是,为什么不能指向一个与主要相应地址有点接近的地址?
对不起我的英语。
祝你好运, Vcoder
答案 0 :(得分: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,如你的例子,呃 - 哦。
P.S。在您的编译器和操作系统以及优化选项上,它可能不是0x18,而是其他值。尝试。实验。黑客是关于试验的,而不是关于运行某些人的脚本。
祝你好运。