gcc是否在编译时重新排序局部变量? [英] Is gcc reordering local variables at compilation time?

查看:293
本文介绍了gcc是否在编译时重新排序局部变量?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我现在正在阅读(第二次)黑客攻击的艺术,并且偶然发现了一些东西。本书提出了两种不同的方式利用这两个类似的程序: auth_overflow auth_overflow2



在第一个,有一个像这样的密码检查功能

  int check_authentication(char * password){
int auth_flag = 0;
char password_buffer [16];

strcpy(password_buffer,password);
...
}

输入16个以上的ASCII字符会改变auth_flag的值大于0,从而绕过检查,如此gdb输出所示:

  gdb $ x / 12x $ esp 
0xbffff400:0xffffffff 0x0000002f 0xb7e0fd24 0x41414141
0xbffff410:0x41414141 0x41414141 0x41414141 0x00000001
0xbffff420:0x00000002 0xbffff4f4 0xbffff448 0x08048556

password_buffer @ 0xbffff40c
auth_flag @ 0xbffff41c

第二个程序颠倒了两个变量:

  int check_authentication(char * password){$ b $ char password_buffer [16]; 
int auth_flag = 0;

strcpy(password_buffer,password);
...
}

然后笔者建议,溢出到auth_flag,我真的相信。然后我开始溢出缓冲区,令我惊讶的是,它仍然有效。 auth_flag变量仍然在缓冲区之后,就像你在这个gdb输出中看到的那样:

  gdb $ x / 12x $ esp 
0xbffff400:0xffffffff 0x0000002f 0xb7e0fd24 0x41414141
0xbffff410:0x41414141 0x41414141 0x41414141 0x00000001
0xbffff420:0x00000002 0xbffff4f4 0xbffff448 0x08048556

password_buffer @ 0xbffff40c
auth_flag @ 0xbffff41c

我想知道gcc是不是将局部变量重新排序以用于对齐/优化。



我试着用-O0标志进行编译,但结果是一样的。

您是否知道为什么会发生这种情况?



在此先感谢。

解决方案

编译器作者完全免费实现具有自动存储的局部变量的任何分配方案。可以在 password_buffer 之前或之后设置 auth_flag ,它可以在寄存器中,它可以完全消失如果适当的代码分析允许它。甚至可能没有堆栈......标准给你的唯一保证是这样的:
$ b

strcpy(password_buffer,password);

如果包含其空终止符的源字符串比目标数组长 password_buffer ,则code>调用未定义的行为。这种未定义的行为是否符合你的需求完全在语言规范之外。

事实上,一些实现者故意使得在发布的代码等情况下,这些黑客会随机化。


I'm currently reading (for the second time) "Hacking : The Art of Exploitation" and have stumbled on something.

The book suggests two different ways to exploit these two similar programs : auth_overflow and auth_overflow2

In the first one, there is a password checking function layed out like this

int check_authentication(char *password) {
    int auth_flag = 0;
    char password_buffer[16];

    strcpy(password_buffer, password);
    ...
}

Inputing more than 16 ASCII characters will change the value of auth_flag to something greater than 0, thus bypassing the check, as shown on this gdb output:

gdb$ x/12x $esp
0xbffff400: 0xffffffff  0x0000002f  0xb7e0fd24  0x41414141
0xbffff410: 0x41414141  0x41414141  0x41414141  0x00000001
0xbffff420: 0x00000002  0xbffff4f4  0xbffff448  0x08048556

password_buffer @ 0xbffff40c
auth_flag @ 0xbffff41c

The second program inverts the two variables :

int check_authentication(char *password) {
    char password_buffer[16];
    int auth_flag = 0;

    strcpy(password_buffer, password);
    ...
}

The author then suggests than it's not possible to overflow into auth_flag, which I really believed. I then proceeded to overflow the buffer, and to my surprise, it still worked. The auth_flag variable was still sitting after the buffer, as you can see on this gdb output:

gdb$ x/12x $esp
0xbffff400: 0xffffffff  0x0000002f  0xb7e0fd24  0x41414141
0xbffff410: 0x41414141  0x41414141  0x41414141  0x00000001
0xbffff420: 0x00000002  0xbffff4f4  0xbffff448  0x08048556

password_buffer @ 0xbffff40c
auth_flag @ 0xbffff41c

I'm wondering if gcc is not reordering local variables for alignement/optimization purposes.

I tried to compile using -O0 flag, but the result is the same.

Does one of you knows why is this happening ?

Thanks in advance.

解决方案

The compiler authors are completely free to implement any allocation scheme for local variables with automatic storage. auth_flag could be set before or after password_buffer on the stack, it could be in a register, it could be elided completely if proper analysis of the code allows it. There might not even be a stack... The only guarantee the Standard gives you is this:

strcpy(password_buffer, password); invokes undefined behavior if the source string including its null terminator is longer than the destination array password_buffer. Whether this undefined behavior fits your needs is completely outside of the language specification.

As a matter of fact, some implementors purposely complicate the task of would be hackers by randomizing the behavior in cases such as the posted code.

这篇关于gcc是否在编译时重新排序局部变量?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆