缓冲区溢出 - 无法覆盖返回地址

时间:2017-03-07 18:40:10

标签: c return-value buffer-overflow

尝试缓冲区溢出以覆盖堆栈上的返回地址以用于以下程序。我想在两个strcmp()

的情况下调用accept
void accept()
{ 
  printf ("\nAccess Granted!\n");
  return;
}    
void deny()
{
  printf ("\nAccess Denied!\n");
  return;
}
int main()
{
  char pwd[16]={0};
  printf ("Enter Password: ");
  gets (pwd);
  if(strcmp(pwd, "pwd1"))
    deny ();
  else
    accept ();
return 0;
}

在拆解main时,可以理解为0x080484fb <+14>: sub $0x14,%esp中的变量分配20个字节     函数main的汇编代码转储:

   0x080484ed <+0>:     lea    0x4(%esp),%ecx
   0x080484f1 <+4>:     and    $0xfffffff0,%esp
   0x080484f4 <+7>:     pushl  -0x4(%ecx)
   0x080484f7 <+10>:    push   %ebp
   0x080484f8 <+11>:    mov    %esp,%ebp
   0x080484fa <+13>:    push   %ecx
   0x080484fb <+14>:    sub    $0x14,%esp
   0x080484fe <+17>:    movl   $0x0,-0x18(%ebp)
   0x08048505 <+24>:    movl   $0x0,-0x14(%ebp)
   0x0804850c <+31>:    movl   $0x0,-0x10(%ebp)
   0x08048513 <+38>:    movl   $0x0,-0xc(%ebp)
   0x0804851a <+45>:    sub    $0xc,%esp
   0x0804851d <+48>:    push   $0x8048611
   0x08048522 <+53>:    call   0x8048370 <printf@plt>
   0x08048527 <+58>:    add    $0x10,%esp
   0x0804852a <+61>:    sub    $0xc,%esp
   0x0804852d <+64>:    lea    -0x18(%ebp),%eax
   0x08048530 <+67>:    push   %eax
   0x08048531 <+68>:    call   0x8048380 <gets@plt>
   0x08048536 <+73>:    add    $0x10,%esp
   0x08048539 <+76>:    sub    $0x8,%esp
   0x0804853c <+79>:    push   $0x8048622
   0x08048541 <+84>:    lea    -0x18(%ebp),%eax
   0x08048544 <+87>:    push   %eax
   0x08048545 <+88>:    call   0x8048360 <strcmp@plt>
   0x0804854a <+93>:    add    $0x10,%esp
   0x0804854d <+96>:    test   %eax,%eax
   0x0804854f <+98>:    je     0x8048558 <main+107>
   0x08048551 <+100>:   call   0x80484d4 <deny>
   0x08048556 <+105>:   jmp    0x804855d <main+112>
   0x08048558 <+107>:   call   0x80484bb <accept>
   0x0804855d <+112>:   mov    $0x0,%eax
   0x08048562 <+117>:   mov    -0x4(%ebp),%ecx
   0x08048565 <+120>:   leave  
   0x08048566 <+121>:   lea    -0x4(%ecx),%esp
   0x08048569 <+124>:   ret

当我尝试用输入字符串AAAAA模糊时...我发现缓冲区上的覆盖是部分

Backtrace stopped: Cannot access memory at address 0x41413d
(gdb) R
The program being debugged has been started already.
Start it from the beginning? (y or n) Y
Starting program: BufferOverflow.x 
\Enter Password: AAAAAAAAAAAAAAAAAAAAAAAA

Access Denied!

Program received signal SIGSEGV, Segmentation fault.
0x08048569 in main ()
(gdb) BT
#0  0x08048569 in main ()
Backtrace stopped: Cannot access memory at address 0x4141413d
(gdb) R
The program being debugged has been started already.
Start it from the beginning? (y or n) Y
Starting program: BufferOverflow.x 
Enter Password: AAAAAAAAAAAAAAAAAAAAAAAAA

Access Denied!

Program received signal SIGSEGV, Segmentation fault.
0x08048569 in main ()
(gdb) BT
#0  0x08048569 in main ()
Backtrace stopped: Cannot access memory at address 0x4141413d
(gdb) r
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: BufferOverflow.x 
Enter Password: AAAAAAAAAAAAAAAAAAAAAAAAAA

Access Denied!

Program received signal SIGSEGV, Segmentation fault.
0x08048569 in main ()
(gdb) bt
#0  0x08048569 in main ()
Backtrace stopped: Cannot access memory at address 0x4141413d

如果仔细观察,返回地址不会完全溢出,但部分为0x4141413d,如果注意地址始终以3d结尾,即使是100 A s - 返回地址相同0x4141413d

我在开始之前禁用了

cat  /proc/sys/kernel/randomize_va_space
0

编译为:

gcc BufferOverflow.c -o BufferOverflow.x -m32 -fno-stack-protector

使用gcc

gcc (Ubuntu 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609

任何帮助确定缓冲区未正确溢出的原因将不胜感激。

由于

2 个答案:

答案 0 :(得分:0)

因为缓冲区溢出导致未定义的行为,所以很难说没有查看gets()函数的内部结构导致这种情况的原因。

很可能是一些指针内部的get()被操纵并导致这种损坏。

另请注意“?”通常用于表示ASCII中不可打印的字符。这可能与您看到的行为有关,但我找不到任何描述此类行为的文档gets()

答案 1 :(得分:0)

只是有同样的问题,并最终找到答案here。简而言之,您需要将易受攻击的调用包装在另一个函数中,然后在main()中调用该函数。