我必须使用buffer oveflow覆盖函数的返回地址。
函数本身看起来像这样(我传递了name参数):
void vuln(char *name)
{
int n = 20;
char buf[1024];
int f[n];
int i;
for (i=0; i<n; i++) {
f[i] = fib(i);
}
strcpy(buf, name);
...
}
我正在使用gdb拆解它,它给了我以下
0x080485ae <+0>: push %ebp
0x080485af <+1>: mov %esp,%ebp
0x080485b1 <+3>: push %ebx
0x080485b2 <+4>: sub $0x414,%esp
0x080485b8 <+10>: mov %esp,%eax
0x080485ba <+12>: mov %eax,%ebx
0x080485bc <+14>: movl $0x14,-0x10(%ebp)
0x080485c3 <+21>: mov -0x10(%ebp),%eax
0x080485c6 <+24>: lea -0x1(%eax),%edx
0x080485c9 <+27>: mov %edx,-0x14(%ebp)
0x080485cc <+30>: shl $0x2,%eax
0x080485cf <+33>: lea 0x3(%eax),%edx
0x080485d2 <+36>: mov $0x10,%eax
0x080485d7 <+41>: sub $0x1,%eax
0x080485da <+44>: add %edx,%eax
0x080485dc <+46>: mov $0x10,%ecx
0x080485e1 <+51>: mov $0x0,%edx
0x080485e6 <+56>: div %ecx
0x080485e8 <+58>: imul $0x10,%eax,%eax
0x080485eb <+61>: sub %eax,%esp
0x080485ed <+63>: mov %esp,%eax
0x080485ef <+65>: add $0x3,%eax
0x080485f2 <+68>: shr $0x2,%eax
0x080485f5 <+71>: shl $0x2,%eax
0x080485f8 <+74>: mov %eax,-0x18(%ebp)
0x080485fb <+77>: movl $0x0,-0xc(%ebp)
0x08048602 <+84>: jmp 0x8048621 <vuln+115>
0x08048604 <+86>: sub $0xc,%esp
0x08048607 <+89>: pushl -0xc(%ebp)
0x0804860a <+92>: call 0x8048560 <fib>
0x0804860f <+97>: add $0x10,%esp
0x08048612 <+100>: mov %eax,%ecx
0x08048614 <+102>: mov -0x18(%ebp),%eax
0x08048617 <+105>: mov -0xc(%ebp),%edx
0x0804861a <+108>: mov %ecx,(%eax,%edx,4)
0x0804861d <+111>: addl $0x1,-0xc(%ebp)
0x08048621 <+115>: mov -0xc(%ebp),%eax
0x08048624 <+118>: cmp -0x10(%ebp),%eax
0x08048627 <+121>: jl 0x8048604 <vuln+86>
0x08048629 <+123>: sub $0x8,%esp
0x0804862c <+126>: pushl 0x8(%ebp)
0x0804862f <+129>: lea -0x418(%ebp),%eax
0x08048635 <+135>: push %eax
0x08048636 <+136>: call 0x80483c0 <strcpy@plt>
0x0804863b <+141>: add $0x10,%esp
0x0804863e <+144>: sub $0x8,%esp
0x08048641 <+147>: lea -0x418(%ebp),%eax
0x08048647 <+153>: push %eax
0x08048648 <+154>: push $0x80487b7
0x0804864d <+159>: call 0x80483a0 <printf@plt>
0x08048652 <+164>: add $0x10,%esp
0x08048655 <+167>: movl $0x0,-0xc(%ebp)
0x0804865c <+174>: jmp 0x804867f <vuln+209>
0x0804865e <+176>: mov -0x18(%ebp),%eax
0x08048661 <+179>: mov -0xc(%ebp),%edx
=> 0x08048664 <+182>: mov (%eax,%edx,4),%eax
0x08048667 <+185>: sub $0x4,%esp
0x0804866a <+188>: push %eax
0x0804866b <+189>: pushl -0xc(%ebp)
0x0804866e <+192>: push $0x80487c4
0x08048673 <+197>: call 0x80483a0 <printf@plt>
0x08048678 <+202>: add $0x10,%esp
0x0804867b <+205>: addl $0x1,-0xc(%ebp)
0x0804867f <+209>: cmpl $0x13,-0xc(%ebp)
0x08048683 <+213>: jle 0x804865e <vuln+176>
0x08048685 <+215>: mov %ebx,%esp
0x08048687 <+217>: nop
0x08048688 <+218>: mov -0x4(%ebp),%ebx
0x0804868b <+221>: leave
0x0804868c <+222>: ret
应该通过返回vuln()调用的函数的地址是0x804850b。 在到达要覆盖的返回地址之前,我怎么知道填充量? 我想name参数应该采用&#34; a&#34; * n +&#34; \ x0b \ x85 \ x04 \ x08&#34;的形式,其中n是我想猜的一些数字。我想这应该是基本的东西,但我还是初学者,所以请不要评判我......
答案 0 :(得分:0)
我怎么知道...
您的代码是:
0x080485ae <+0>: push %ebp
0x080485af <+1>: mov %esp,%ebp
...
0x0804862f <+129>: lea -0x418(%ebp),%eax
0x08048635 <+135>: push %eax
0x08048636 <+136>: call 0x80483c0 <strcpy@plt>
在输入函数之前,返回地址位于偏移0(%esp)
。
在第一个push
之后,它位于4(%esp)
。自%esp
下次复制到%ebp
后,它也会4(%ebp)
。
接下来,您会看到您开始复制的位置位于-0x418(%ebp)
。
结论:&buf[0]
和&return_address
之间的差值为0x418 + 4 == 0x41C
。
替代解决方案:使用无效地址填写name
输入:0x01010101
,0x01010102
,... 0x010102FF
。执行代码并观察它崩溃的地址。
如果我的计算是正确的,当vuln
尝试返回&#34; slot&#34; 0x41C / 4 == 0x107
,应包含0x01010208
。