堆栈粉碎代码无法在 Linux 内核 2.6.38.7 上运行...请帮忙
我一直在阅读“The Shellcoders Handbook”,并参考此链接来练习堆栈溢出。但看起来 Linux 内核开发者已经让内核变得非常安全了。这是我的问题。
1) 此代码
void function(int a, int b, int c) {
char buffer1[8];
char buffer2[10];
int* ret;
ret = buffer1 + 6;
*ret+=8;
}
void main() {
int x;
x = 0;
function(1,2,3);
x = 1;
printf("%d\n",x);
}
给出输出
$ cc smash.c
smash.c: In function ‘function’:
smash.c:7:8: warning: assignment from incompatible pointer type
$ ./a.out
1
,但将行 *ret+=8
替换为 *ret=8
会给出以下输出
*** stack smashing detected ***: ./a.out terminated
======= Backtrace: =========
/lib/i386-linux-gnu/libc.so.6(__fortify_fail+0x50)[0xa86df0]
/lib/i386-linux-gnu/libc.so.6(+0xe5d9a)[0xa86d9a]
./a.out[0x8048448]
./a.out[0x8048477]
/lib/i386-linux-gnu/libc.so.6(__libc_start_main+0xe7)[0x9b7e37]
./a.out[0x8048381]
======= Memory map: ========
003df000-003e0000 r-xp 00000000 00:00 0 [vdso]
009a1000-00afb000 r-xp 00000000 08:01 3277633 /lib/i386-linux-gnu/libc-2.13.so
00afb000-00afc000 ---p 0015a000 08:01 3277633 /lib/i386-linux-gnu/libc-2.13.so
00afc000-00afe000 r--p 0015a000 08:01 3277633 /lib/i386-linux-gnu/libc-2.13.so
...
...
如果我替换 ret = buffer1 + 6< /code> 和
ret = buffer1 + 7
,结果同上。 如果我将 ret = buffer1 + 6 替换为 ret=buffer1+8 (或任何更大的值),则上述两种情况都会出现堆栈损坏(即我是否递增将值 *ret
增加 8 或将其更改为 8)。
请告诉我这是怎么发生的。有用的链接也将受到赞赏。 最重要的是,我怎样才能禁用 Linux 内核的这个安全功能,以便我可以使用这本书?
平台:i386 内核:2.6.38
I have been reading "The Shellcoders Handbook" and been referring to this link for practice of stack overflow. But it seems the Linux kernel developers have made the kernel very secure. Here are my problems.
1) This code
void function(int a, int b, int c) {
char buffer1[8];
char buffer2[10];
int* ret;
ret = buffer1 + 6;
*ret+=8;
}
void main() {
int x;
x = 0;
function(1,2,3);
x = 1;
printf("%d\n",x);
}
gives the output
$ cc smash.c
smash.c: In function ‘function’:
smash.c:7:8: warning: assignment from incompatible pointer type
$ ./a.out
1
but replacing the line *ret+=8
with *ret=8
gives the following output
*** stack smashing detected ***: ./a.out terminated
======= Backtrace: =========
/lib/i386-linux-gnu/libc.so.6(__fortify_fail+0x50)[0xa86df0]
/lib/i386-linux-gnu/libc.so.6(+0xe5d9a)[0xa86d9a]
./a.out[0x8048448]
./a.out[0x8048477]
/lib/i386-linux-gnu/libc.so.6(__libc_start_main+0xe7)[0x9b7e37]
./a.out[0x8048381]
======= Memory map: ========
003df000-003e0000 r-xp 00000000 00:00 0 [vdso]
009a1000-00afb000 r-xp 00000000 08:01 3277633 /lib/i386-linux-gnu/libc-2.13.so
00afb000-00afc000 ---p 0015a000 08:01 3277633 /lib/i386-linux-gnu/libc-2.13.so
00afc000-00afe000 r--p 0015a000 08:01 3277633 /lib/i386-linux-gnu/libc-2.13.so
...
...
If I replace ret = buffer1 + 6
with ret = buffer1 + 7
, the result is same as above.
If I replace ret = buffer1 +
6 with ret=buffer1+8
(or any larger value), there is smashed stack for BOTH the cases described above (i.e. whether I increment the value *ret
by 8 or change it to 8).
Please tell me how this happens. Helpful links will also be appreciated.
And above all, how can I disable this security feature of the Linux kernel so that I can work with this book?
Platform: i386
Kernel: 2.6.38
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
要禁用堆栈粉碎检测,请在编译时使用 -fno-stack-protector 。在阅读“The Shellcoders Handbook”时,您可能还想使用 -ggdb 和 -mpreferred-stack-boundary=4 来启用 GDB 符号并标准化堆栈。
编辑:
当我编译您提供的代码时(
gcc -fno-stack-protector -ggdb -mpreferred-stack-boundary=4 -o sc in.c
),编译器重新排列了局部变量的顺序函数
。我通过使用 GDB 发现了这一点:0x080483ca 告诉我
ebp - 0xC
是 buffer1,0x080483d0 告诉我ebp - 0x4
是 ret。因此,变量并不像 C 代码中那样存在于堆栈中。鉴于 ret 是我们最顶层的局部变量,我们可以直接使用它。不过,让我们使用您的代码。要修改返回指针,我们需要更改保存的 ebp 下面存储的地址,即
ebp + 0x4
。因此,要从变量 buffer1 获取返回指针,我们必须添加 0xC(以获取ebp
),然后添加 0x4(返回指针是ebp
下的 0x4) )。现在我们可以进行修改了。我从您的 C 代码中得知您希望跳过
x = 1
的赋值并直接返回到printf
。我反汇编了main
以找到对返回指针的适当修改:如果不修改返回指针,对 0x0804840a 处的
function
的调用将返回到 0x0804840f。但我们想跳过这个并返回到下一条指令。下一条指令从 0x08048417 开始,再往前 0x8 字节。所以我们对返回指针的修改必须将其值增加0x8。考虑到这些因素,我使用以下代码来打印“0”而不是“1”:
To disable the stack smashing detection, use -fno-stack-protector when compiling. You may also want to use -ggdb and -mpreferred-stack-boundary=4 when working through "The Shellcoders Handbook" to enable GDB symbols and standardize the stack.
edit:
When I compiled the code you provided (
gcc -fno-stack-protector -ggdb -mpreferred-stack-boundary=4 -o sc in.c
), the compiler rearranged the order of the local variables infunction
. I found this by using GDB:0x080483ca tells me that
ebp - 0xC
is buffer1, and 0x080483d0 tells meebp - 0x4
is ret. So, the variables do not exist on the stack as they exist in our C code. Given thatret
is our top-most local variable, we could work with it directly. Let's work with your code, though.To modify the return pointer, we need to change the address stored just below the saved ebp, so
ebp + 0x4
. So, to get to the return pointer from from our variable buffer1, we have to add 0xC (to get toebp
), and then 0x4 (return pointer is 0x4 underebp
). Now we can make our modifications.I take from your C code that you'd like to skip the assignment of
x = 1
and return directly to theprintf
. I disassembledmain
to find the appropriate modification to the return pointer:Without modification to the return pointer, the call to
function
at 0x0804840a returns to 0x0804840f. But we want to skip this and return to the next instruction. The next instruction begins at 0x08048417, which is 0x8 bytes further along. So our modification to the return pointer must increase its value by 0x8.Taking these things into consideration, I used the following code to print "0" rather than "1":
可以像这样禁用堆栈粉碎保护:
此链接提供了更多信息有关 Linux 安全功能的信息
Stack smashing protection can be disabled like so:
This link provides more information on Linux's security features