#include <stdio.h> #include <stdlib.h> #include <string.h> /* 函数表的全局符号表,类似 ELF 格式的 GOT 表格 */ void (*fptr[])() = { &strcpy, &printf }; void foo() { char s[4]; (fptr[0])(s, "aksdfjalsfjaslfjaslf"); /* strcpy(),很明显会导致溢出,覆盖返回值 */ (fptr[1])("I'm foo()\n"); } int cookie = 0; /* cookie 值 */ /***** 出错出处理例程示例 *********/ void do_fault() { printf("do_fault(): buffer overflow! return addres error\n"); exit(1); } /*** 安插 cookie 例程 ****/ void set_cookie_value(int cookie_addr, char *pos) { pos[0] = 0xff; /* push cookie */ pos[1] = 0x35; *((int *)&pos[2]) = cookie_addr; } /*** 安插cookie检测例程 ***/ void set_check_fun(int cookie_addr, char *pos) { pos[0] = 0x5a; /* pop edx */ pos[1] = 0x39; /* cmp [cookie], edx */ pos[2] = 0x15; *((int *)&pos[3]) = cookie_addr; pos[7] = 0x74; /* je +9 : ret */ pos[8] = 0x07; pos[9] = 0xbe; /* mov esi, do_fault */ *((int *)&pos[10]) = (int)do_fault; pos[14] = 0xff; /* call esi */ pos[15] = 0xd6; pos[16] = 0xc3; } char *get_ret(char *buf, int len) { while (len-- && (*buf != (char)0xc3)) buf++; if (len) return buf; else return 0; } int main() { cookie = (int)time(0); /* 随机的 cookie 值 */ char *buf = malloc(200); /* 分配空间用来作编译试验 */ set_cookie_value((int)&cookie, buf); /* 在函数头安插 cookie 信息 */ memcpy(buf+6, foo, 200); char *p = get_ret(buf+6, 200); set_check_fun((int)&cookie, p); /* 在函数尾安插检测例程 */ ((void (*)())buf)(); /* 测试 */ // foo() /* 直接调用 foo(),将产生 segmenation fault */ } |
foo: <---------- 在此处安插 cookie 值 pushl %ebp movl %esp, %ebp subl $24, %esp movl fptr, %eax movl $.LC0, 4(%esp) leal -4(%ebp), %edx movl %edx, (%esp) call *%eax movl fptr+4, %eax movl $.LC1, (%esp) call *%eax leave ret <---------- 在函数返回前安插检测代码 |
foo: pushl cookie <---------- 在此处安插 cookie 值 pushl %ebp movl %esp, %ebp subl $24, %esp movl fptr, %eax movl $.LC0, 4(%esp) leal -4(%ebp), %edx movl %edx, (%esp) call *%eax movl fptr+4, %eax movl $.LC1, (%esp) call *%eax leave pop %edx <---------- 在函数返回前安插检测代码 cmpl %edx, cookie je 1f movl $do_fault, %esi call *%esi /* 出错处理例程 */ 1f: ret |
I'm foo() do_fault(): buffer overflow! return addres error |
I'm foo() |
I'm foo() segmentation fault |
原帖由 bobozhang 于 2008-8-17 08:43 发表
gcc一样有,stackguard和stackshieft都可以降低栈受缓冲区溢出攻击的威胁,你上面贴的贴子的方法就是stackguard,但好像不够完整,那个cookie值应该有一个字节为'\0',这样可以防止strcpy这种字符串操作的缓冲区溢出
原帖由 bobozhang 于 2008-8-17 08:43 发表
gcc一样有,stackguard和stackshieft都可以降低栈受缓冲区溢出攻击的威胁,你上面贴的贴子的方法就是stackguard,但好像不够完整,那个cookie值应该有一个字节为'\0',这样可以防止strcpy这种字符串操作的缓冲区溢出
原帖由 mik 于 2008-8-17 09:31 发表
stackguard 应该用什么参数来产生?
cookie 应该是一个整型值,不应是个串。cookie 本身就是为了防止缓冲区溢出,有 '\0' 是多余的。
原帖由 jamesr 于 2008-8-17 09:43 发表
gcc果然有溢出保护:
gcc -fstack-protector-all -Wstack-protector yourfile.c
写了一个最简单的测试:
#include
int main()
{
char str[3];
strcpy(str,"hello"
return ...
原帖由 bobozhang 于 2008-8-17 09:45 发表
好像不需要指定什么参数让gcc产生吧,这些gcc是被修改过的。
'\0'好像不一定多于吧?比如我们有个函数调用了strcpy,正好这个strcpy会产生缓冲区溢出,如果攻击者计算出了那个cookie值的话,有'\0'和没 ...
原帖由 mik 于 2008-8-17 10:06 发表
好的cookie值是个随机性的,微软的cookie值这一点做得比较好,每调用一次cookie都会不同,要计算这个cookie 不那么容易。
话说回来,cookie 技术也不是什么保险的措施。绕过cookie值是完全可以做到的。
原帖由 mik 于 2008-8-17 10:06 发表
好的cookie值是个随机性的,微软的cookie值这一点做得比较好,每调用一次cookie都会不同,要计算这个cookie 不那么容易。
话说回来,cookie 技术也不是什么保险的措施。绕过cookie值是完全可以做到的。
int main(int argc, char *argv[]) { char buf[8]; strcpy(buf, argv[1]); return 0; } |
原帖由 bobozhang 于 2008-8-17 19:11 发表
我说绕不过是指攻击者无法成功攻击
比如一个简单的如下程序在一个用cookie保护的系统上,我想没人能够成功利用这个缓冲区溢出而攻击吧
int main(int argc, char *argv[])
{
char bu ...
int main() { } main: leal 4(%esp), %ecx andl $-16, %esp pushl -4(%ecx) pushl %ebp movl %esp, %ebp pushl %ecx popl %ecx popl %ebp leal -4(%ecx), %esp ret |
原帖由 mik 于 2008-8-21 00:16 发表
刚刚发现的 gcc 应对缓冲区溢出改写返回地址的另一个措施
int main()
{
}
main:
leal 4(%esp), %ecx
andl $-16, %esp
pushl -4(%ecx)
pushl %ebp
movl %esp, %ebp
pushl %ecx
popl %ec ...
欢迎光临 Chinaunix (http://bbs.chinaunix.net/) | Powered by Discuz! X3.2 |