首页 文章

堆栈缓冲区溢出导致奇怪的执行路径

提问于
浏览
2

我读了一些关于Stack Buffer Overflow的文章,比如this,并了解了攻击者如何通过覆盖函数指针来利用Stack Buffer-Overflow错误 . 然后我写了一个小程序来演示攻击:

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

void fun1 ( char * input ) {
    char buffer[10];
    strcpy( buffer, input );
    printf( "In fun1, buffer= %s\n", buffer );
}

void fun2 ( void ) {
    printf ( "HELLO fun2!\n" );
}

int main ( int argc, char * argv[] )
{
    printf ( "Address of fun2: %p\n", fun2 );
    fun1( "abcdefghijklmnopqrstuv\x52\x84\x04\x08" );
    return 0;
}

该程序是在Fedora 14 x86下使用GCC 4.5.1编译的 . 以下是输出:

$ ./exp01 fun2的地址:0x8048452在fun1中,buffer =abcdefghijklmnopqrstuvR HELLOfun2!你好fun2!

我们可以看到fun2()被成功调用,但我不知道它为什么会运行两次 . 然后我GDB了它(见下文) . (我只知道关于GDB的一些基本指令╮(¯▽¯)╭)

我用Google搜索了一些关键词,例如“__libc_csu_fini()”,但没有找到一种清晰的方法可以帮助我理解程序的执行路径 . 我对编译器和进程的内部结构知之甚少,所以我认为我可能必须找到一些详细描述这些内容的书籍或文章 . 有什么建议吗?谢谢!


GDB Record:

(gdb)list 7 printf(“在fun1中,缓冲区=%s \ n”,缓冲区); 8} 9 10 void fun2(void){11 printf(“HELLO fun2!\ n”); 12} 13 14 int main(int argc,char * argv [])15 {16 printf(“fun2的地址:%p \ n”,fun2); (gdb)17 fun1(“abcdefghijklmnopqrstuv \ x52 \ x84 \ x04 \ x08”); 18返回0; 19}(gdb)break 16 Breakpoint 1 at 0x804846f:file hello.c,第16行 . (gdb)run启动程序:/ home / yuliang / test / hello断点1,main(argc = 1,argv = 0xbffff394)你好.c:16 16 printf(“fun2的地址:%p \ n”,fun2);缺少单独的debuginfos,请使用:debuginfo-install glibc-2.13-2.i686(gdb)step fun2的地址:0x8048452 17 fun1(“abcdefghijklmnopqrstuv \ x52 \ x84 \ x04 \ x08”); (gdb)fun1(输入= 0x804859a“abcdefghijklmnopqrstuvR \ 204 \ 004 \ b”)在hello.c:6 6 strcpy(缓冲区,输入); (gdb)7 printf(“在fun1中,缓冲区=%s \ n”,缓冲区); (gdb)在fun1中,缓冲区=abcdefghijklmnopqrstuvR 8}(gdb)fun2()at hello.c:10 10 void fun2(void){(gdb)11 printf(“HELLO fun2!\ n”); (gdb)HELLO fun2! 12}(gdb)0x08048500 in __libc_csu_fini()(gdb)单步执行直到退出函数__libc_csu_fini,该函数没有行号信息 . fun2()at hello.c:10 10 void fun2(void){(gdb)11 printf(“HELLO fun2!\ n”); (gdb)HELLO fun2! 12}(gdb)无法访问地址0x76757477处的内存(gdb)单步执行直到退出函数__libc_csu_init,该函数没有行号信息 . 来自/lib/libc.so.6的__libc_start_main()中的0x009aae36(gdb)单步执行直到退出函数__libc_start_main,该函数没有行号信息 . 程序退出,代码为0241.(gdb)

1 回答

  • 0

    strcpy() 之前不久在gdb中运行程序并查看堆栈帧(即存储save eip的位置) . 然后运行到 printf() 后不久,再看一下存储的eip(命令是 info frame ) .

    因为你将函数 fun2() 的地址传递给 fun1() 它会覆盖保存的eip,一旦调用return(在你的情况下隐含),将执行下一条指令(由eip给出,在你的情况下,它是地址 fun2()

    别忘了阅读aleph1的Smashing the stack for fun and profit

相关问题