我一直在CSAPPS的bufbomb实验室工作,但我被其中一个阶段卡住了。
我不会深入这个项目的血淋淋的细节,因为我只需要在正确的方向上推动一下。在给定的程序集中,我很难找到名为"buf“的数组的起始地址。
我们得到了一个名为getbuf的函数:
#define NORMAL_BUFFER_SIZE 32
int getbuf()
{
char buf[NORMAL_BUFFER_SIZE];
Gets(buf);
return 1;
}和程序集转储:
Dump of assembler code for function getbuf:
0x08048d92 <+0>: sub $0x3c,%esp
0x08048d95 <+3>: lea 0x10(%esp),%eax
0x08048d99 <+7>: mov %eax,(%esp)
0x08048d9c <+10>: call 0x8048c66 <Gets>
0x08048da1 <+15>: mov $0x1,%eax
0x08048da6 <+20>: add $0x3c,%esp
0x08048da9 <+23>: ret
End of assembler dump.
Dump of assembler code for function Gets:
0x08048c66 <+0>: push %ebp
0x08048c67 <+1>: push %edi
0x08048c68 <+2>: push %esi
0x08048c69 <+3>: push %ebx
0x08048c6a <+4>: sub $0x1c,%esp
0x08048c6d <+7>: mov 0x30(%esp),%esi
0x08048c71 <+11>: movl $0x0,0x804e100
0x08048c7b <+21>: mov %esi,%ebx
0x08048c7d <+23>: jmp 0x8048ccf <Gets+105>
0x08048c7f <+25>: mov %eax,%ebp
0x08048c81 <+27>: mov %al,(%ebx)
0x08048c83 <+29>: add $0x1,%ebx
0x08048c86 <+32>: mov 0x804e100,%eax
0x08048c8b <+37>: cmp $0x3ff,%eax
0x08048c90 <+42>: jg 0x8048ccf <Gets+105>
0x08048c92 <+44>: lea (%eax,%eax,2),%edx
0x08048c95 <+47>: mov %ebp,%ecx
0x08048c97 <+49>: sar $0x4,%cl
0x08048c9a <+52>: mov %ecx,%edi
0x08048c9c <+54>: and $0xf,%edi
0x08048c9f <+57>: movzbl 0x804a478(%edi),%edi
0x08048ca6 <+64>: mov %edi,%ecx
---Type <return> to continue, or q <return> to quit---
0x08048ca8 <+66>: mov %cl,0x804e140(%edx)
0x08048cae <+72>: mov %ebp,%ecx
0x08048cb0 <+74>: and $0xf,%ecx
0x08048cb3 <+77>: movzbl 0x804a478(%ecx),%ecx
0x08048cba <+84>: mov %cl,0x804e141(%edx)
0x08048cc0 <+90>: movb $0x20,0x804e142(%edx)
0x08048cc7 <+97>: add $0x1,%eax
0x08048cca <+100>: mov %eax,0x804e100
0x08048ccf <+105>: mov 0x804e110,%eax
0x08048cd4 <+110>: mov %eax,(%esp)
0x08048cd7 <+113>: call 0x8048820 <_IO_getc@plt>
0x08048cdc <+118>: cmp $0xffffffff,%eax
0x08048cdf <+121>: je 0x8048ce6 <Gets+128>
0x08048ce1 <+123>: cmp $0xa,%eax
0x08048ce4 <+126>: jne 0x8048c7f <Gets+25>
0x08048ce6 <+128>: movb $0x0,(%ebx)
0x08048ce9 <+131>: mov 0x804e100,%eax
0x08048cee <+136>: movb $0x0,0x804e140(%eax,%eax,2)
0x08048cf6 <+144>: mov %esi,%eax
0x08048cf8 <+146>: add $0x1c,%esp
0x08048cfb <+149>: pop %ebx
0x08048cfc <+150>: pop %esi
0x08048cfd <+151>: pop %edi
---Type <return> to continue, or q <return> to quit---
0x08048cfe <+152>: pop %ebp
0x08048cff <+153>: ret
End of assembler dump.我很难找到buf的起始地址在哪里(或者buf在这个乱七八糟的地方!)。如果有人能指出这一点,我将不胜感激。
尝试解决方案
Reading symbols from /home/user/CS247/buflab/buflab-handout/bufbomb...(no debugging symbols found)...done.
(gdb) break getbuf
Breakpoint 1 at 0x8048d92
(gdb) run -u user < firecracker-exploit.bin
Starting program: /home/user/CS247/buflab/buflab-handout/bufbomb -u user < firecracker-exploit.bin
Userid: ...
Cookie: ...
Breakpoint 1, 0x08048d92 in getbuf ()
(gdb) print buf
No symbol table is loaded. Use the "file" command.
(gdb) 发布于 2013-05-19 02:29:04
正如其他一些人所指出的那样,buf是在运行时在堆栈上分配的。请参阅getbuf()函数中的以下行:
0x08048d92 <+0>: sub $0x3c,%esp
0x08048d95 <+3>: lea 0x10(%esp),%eax
0x08048d99 <+7>: mov %eax,(%esp)第一行从堆栈指针中减去0x3c (60)字节,有效地分配了这么多空间。超出32的额外字节可能是Gets的参数(很难说Gets的调用约定是什么,所以很难说)第二行获取16个字节的地址。这会在它上面留下44个未分配的字节。第三行将该地址放到堆栈中,可能是为了进行gets函数调用。(请记住,堆栈会向下增长,因此堆栈指针将指向堆栈上的最后一项)。我不确定为什么编译器会产生如此奇怪的偏移量(60个字节,然后是44个字节),但可能有一个很好的原因。如果我弄清楚了,我会在这里更新。
在gets函数中,我们有以下几行:
0x08048c66 <+0>: push %ebp
0x08048c67 <+1>: push %edi
0x08048c68 <+2>: push %esi
0x08048c69 <+3>: push %ebx
0x08048c6a <+4>: sub $0x1c,%esp
0x08048c6d <+7>: mov 0x30(%esp),%esi在这里我们可以看到,我们保存了一些寄存器的状态,这些寄存器加起来有16个字节,然后在堆栈上保留28 (0x1c)个字节。最后一行是关键:它获取堆栈上0x30字节的值,并将其加载到%esi中。这个值是getbuf放在堆栈上的buf的地址。为什么?返回地址为4加上保留的registers+28地址为16 = 48。0x30 = 48,所以它在调用get之前获取getbuf()放在堆栈上的最后一项。
要获得buf的地址,您必须在调试器中实际运行程序,因为每次运行程序时,地址可能会不同,甚至调用函数也是如此。您可以在上述任意行设置断点,并在%eax寄存器包含要放入堆栈的getbuf第二行的地址时转储%eax寄存器,或在将%esi寄存器从堆栈中取出时转储%esi寄存器。这将是指向缓冲区的指针。
发布于 2013-05-18 12:39:42
buf在堆栈上分配。因此,您将无法从程序集列表中找到它的地址。换句话说,只有在运行时进入函数getbuf()时,才会分配buf (因此知道它的地址)。
如果您必须知道地址,一种选择是使用gbd (但请确保使用-g标志进行编译以启用调试支持),然后:
gdb a.out # I'm assuming your binary is a.out
break getbuf # Set a breakpoint where you want gdb to stop
run # Run the program. Supply args if you need to
# WAIT FOR your program to reach getbuf and stop
print buf如果你想走这条路,一个好的gdb教程(example)是必不可少的。您还可以在getbuf中放置一个printf并以这种方式进行调试-这取决于您正在尝试做什么。
另一点从您的代码中突显出来。从getbuf返回时,Gets的结果将被丢弃。这是因为Gets可能会将其结果写入堆栈分配的buf中。当你从getbuf返回时,你的堆栈已经崩溃,你不能可靠地访问buf。
发布于 2013-05-18 13:33:53
为了能够在使用gdb时查看调试信息,您必须在compile.see手册时将-g3开关与gcc配合使用,以了解有关-g开关的更多详细信息。只有这样,gcc才会在可执行文件中添加调试信息(符号表)。
https://stackoverflow.com/questions/16620696
复制相似问题