我目前正在(第二次)阅读“黑客:剥削的艺术”,偶然发现了一些东西。
该书提出了两种不同的方法来利用这两个类似的程序: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) {
char password_buffer[16];
int auth_flag = 0;
strcpy(password_buffer, password);
...
}
然后作者提出,不可能溢出到auth_flag中,这是我真正相信的。然后,我继续使缓冲区溢出,令我惊讶的是,它仍然有效。可以在此gdb输出上看到,auth_flag变量仍位于缓冲区之后。
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标志进行编译,但结果是相同的。
你们中的一个人知道为什么会这样吗?
提前致谢。
编译器作者可以完全自由地为具有自动存储功能的局部变量实现任何分配方案。auth_flag
可以password_buffer
在堆栈之前或之后设置,可以在寄存器中,如果对代码进行适当的分析允许,则可以完全删除它。甚至可能没有堆栈...标准为您提供的唯一保证是:
strcpy(password_buffer, password);
如果包含空终止符的源字符串比目标数组长,则调用未定义的行为password_buffer
。这种不确定的行为是否符合您的需求,完全超出了语言规范的范围。
实际上,某些实施者通过随机分配诸如张贴代码之类的行为来故意使黑客的任务复杂化。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句