c - 堆栈缓冲区溢出导致的怪异执行路径

标签 c buffer-overflow

我读了一些关于堆栈缓冲区溢出的文章,比如 this一,并了解了攻击者如何通过覆盖函数指针来利用堆栈缓冲区溢出错误。然后我写了一个小程序来演示攻击:

#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

Address of fun2: 0x8048452

In fun1, buffer= abcdefghijklmnopqrstuvR�

HELLO fun2!

HELLO fun2!

我们可以看到fun2()调用成功了,但是不知道为什么跑了两次。然后我 GDBed 它(见下文)。 (我只知道一些关于GDB的基本说明╮( ̄▽ ̄)╭)

我在谷歌上搜索了一些关键字,如“__libc_csu_fini()”,但没有找到一个明确的方法来帮助我理解程序的执行路径。我对编译器和进程的内部结构知之甚少,所以我认为我可能必须找到一些详细描述这些东西的书籍或文章。有什么建议吗?谢谢!


GDB 记录:

(gdb) list

7 printf( "In fun1, buffer= %s\n", buffer );

8 }

9

10 void fun2 ( void ) {

11 printf ( "HELLO fun2!\n" );

12 }

13

14 int main ( int argc, char * argv[] )

15 {

16 printf ( "Address of fun2: %p\n", fun2 );

(gdb)

17 fun1( "abcdefghijklmnopqrstuv\x52\x84\x04\x08" );

18 return 0;

19 }

(gdb) break 16

Breakpoint 1 at 0x804846f: file hello.c, line 16.

(gdb) run

Starting program: /home/yuliang/test/hello

Breakpoint 1, main (argc=1, argv=0xbffff394) at hello.c:16

16 printf ( "Address of fun2: %p\n", fun2 );

Missing separate debuginfos, use: debuginfo-install glibc-2.13-2.i686

(gdb) step

Address of fun2: 0x8048452

17 fun1( "abcdefghijklmnopqrstuv\x52\x84\x04\x08" );

(gdb)

fun1 (input=0x804859a "abcdefghijklmnopqrstuvR\204\004\b") at hello.c:6

6 strcpy( buffer, input );

(gdb)

7 printf( "In fun1, buffer= %s\n", buffer );

(gdb)

In fun1, buffer= 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)

Single stepping until exit from function __libc_csu_fini,

which has no line number information.

fun2 () at hello.c:10

10 void fun2 ( void ) {

(gdb)

11 printf ( "HELLO fun2!\n" );

(gdb)

HELLO fun2!

12 }

(gdb)

Cannot access memory at address 0x76757477

(gdb)

Single stepping until exit from function __libc_csu_init,

which has no line number information.

0x009aae36 in __libc_start_main () from /lib/libc.so.6

(gdb)

Single stepping until exit from function __libc_start_main,

which has no line number information.

Program exited with code 0241.

(gdb)

最佳答案

当在 gdb 中运行您的程序时,在 strcpy() 之前不久中断并查看栈帧(即保存 eip 的存储位置)。然后运行直到 printf() 之后不久,再次查看存储的 eip(命令是 info frame)。

由于您将函数 fun2() 的地址传递给 fun1() 它将覆盖保存的 eip,并且一旦调用返回(在您的情况下是隐含的)将执行下一条指令(由 eip 给出,在您的情况下它是 fun2() 的地址)

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

关于c - 堆栈缓冲区溢出导致的怪异执行路径,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9530957/

相关文章:

c - 如何从终端编译这个简单的 shellcode c 程序?

ARM64 缓冲区溢出 - 无法覆盖 $pc

python - 汇编的十六进制内存地址

有人可以帮我解决算法中的错误吗

objective-c - Xcode项目中的.c文件如何使用/实现?

c - 不一致的 recv() 行为

Android MediaRecorder 采样率和噪声

c - 编译器中的 -p 和 -g 标志是什么

c - 功能级别是否影响主变量的内存分配区域

python - 使用 python 将列表中的每个对象与同一列表中的所有其他对象进行一次测试