缓冲区溢出,调用函数

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 输入:0x010101010x01010102、... 0x010102FF。执行代码并观察它崩溃的地址。

如果我的计算是正确的,当 vuln 尝试 return 到 "slot" 0x41C / 4 == 0x107 时它会崩溃,其中应该包含 0x01010208.