本文共 1593 字,大约阅读时间需要 5 分钟。
在为C语言的数组等赋值时,可能赋值大小超出了数组的长度限制,这时超出的部分就会覆盖掉栈中其他部分的内容,从而发生缓冲区溢出。
下面用一个危险的例子进行说明:在这个程序中,我们利用strcpy()函数进行赋值操作。
C代码:
#include#include #include void StringCopy(char *str){ char p[10]; strcpy(p,str);}void hacked(){ while(1){ printf("you are hacked!!!"); }}int main(){ char str[] = "0123456789012345678901234567891111"; unsigned long long *p = (unsigned long long*)&str[18]; (*p) = (unsigned long long)hacked; //用hack函数的地址覆盖字符串str中的部分内容 //这里的18是在ubuntu64位下测试得到,其他系统可能会出现问题,不能正常运行 StringCopy(str); return 0;}
运行结果:
程序疯狂显示you are hacked;但这不是hack()函数的功能吗?我们并没有调用hack函数啊。
然后会分配内存空间,如%esp-0x20(即分配32个空间,这个值具体看程序和OS),在这部分空间中进行函数内部操作;
函数执行完毕后,会清理掉这部分内存空间,弹出%ebp,并开始执行返回地址所指向的命令!
那么我们只需要覆盖这个返回地址,让它变成我们hack()程序的地址,那么程序就会执行hack程序了!
所以我们只需要计算返回地址的位置即可,StringCopy函数对应的汇编代码如下:
;4 : void StringCopy(char *str){ 0x555555555169 endbr640x55555555516d push %rbp0x55555555516e mov %rsp,%rbp0x555555555171 sub $0x20,%rsp0x555555555175 mov %rdi,-0x18(%rbp);5 : char p[10];;6 : strcpy(p,str);0x555555555179 mov -0x18(%rbp),%rdx0x55555555517d lea -0xa(%rbp),%rax#%ebp-0xa即为p的地址,p占十个字节;再加上%ebp占8个字节0x555555555181 mov %rdx,%rsi0x555555555184 mov %rax,%rdi0x555555555187 callq 0x555555555060;7 : }0x55555555518c nop0x55555555518d leaveq0x55555555518e retq
从上述程序我们可以看出,从变量p到栈底%ebp,一共占18个字节,而18个字节之后,便是返回地址所在的位置。
执行strcpy之前:
转载地址:http://ygth.baihongyu.com/