堆栈粉碎代码无法在Linux内核2.6.38.7上运行...请帮忙

pfl*_*flz 2 linux stack-overflow stack gcc

我一直在阅读"Shellcoders手册",并指的是这个链接,用于实现堆栈溢出.但似乎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);
}
Run Code Online (Sandbox Code Playgroud)

给出输出

$ cc smash.c
smash.c: In function ‘function’:
smash.c:7:8: warning: assignment from incompatible pointer type
$ ./a.out
1
Run Code Online (Sandbox Code Playgroud)

用的线*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
...
...
Run Code Online (Sandbox Code Playgroud)

如果我更换 ret = buffer1 + 6ret = buffer1 + 7,结果同上.如果我ret = buffer1 +ret=buffer1+8(或任何更大的值)替换 6 ,那么上面描述的情况(即,我是将值*ret 增加8还是将其更改为8)都会有碎片堆栈 .

请告诉我这是怎么回事.有用的链接也将不胜感激.最重要的是,如何禁用Linux内核的这种安全功能,以便我可以使用本书?

平台:i386内核:2.6.38

Wil*_*hin 11

要禁用堆栈粉碎检测,请在编译时使用-fno-stack-protector.在处理"Shellcoders Handbook"时,您可能还希望使用-ggdb和-mpreferred-stack-boundary = 4来启用GDB符号并标准化堆栈.

编辑:当我编译你提供的代码(gcc -fno-stack-protector -ggdb -mpreferred-stack-boundary=4 -o sc in.c)时,编译器重新排列了局部变量的顺序function.我通过使用GDB找到了这个:

willi@ubuntu:~/testing$ gdb sc
(gdb) set disassembly-flavor intel
(gdb) disassemble function
Dump of assembler code for function function:
   0x080483c4 <+0>: push   ebp
   0x080483c5 <+1>: mov    ebp,esp
   0x080483c7 <+3>: sub    esp,0x20
   0x080483ca <+6>: lea    eax,[ebp-0xc]
   0x080483cd <+9>: add    eax,0x6
   0x080483d0 <+12>:    mov    DWORD PTR [ebp-0x4],eax
   0x080483d3 <+15>:    mov    eax,DWORD PTR [ebp-0x4]
   0x080483d6 <+18>:    mov    eax,DWORD PTR [eax]
   0x080483d8 <+20>:    lea    edx,[eax+0x8]
   0x080483db <+23>:    mov    eax,DWORD PTR [ebp-0x4]
   0x080483de <+26>:    mov    DWORD PTR [eax],edx
   0x080483e0 <+28>:    leave  
   0x080483e1 <+29>:    ret    
End of assembler dump.
Run Code Online (Sandbox Code Playgroud)

0x080483ca告诉我那ebp - 0xC是buffer1,而0x080483d0告诉我ebp - 0x4是ret.因此,堆栈中不存在变量,因为它们存在于我们的C代码中.鉴于这ret是我们最顶级的局部变量,我们可以直接使用它.但是,让我们使用您的代码.

要修改返回指针,我们需要更改存储在保存的ebp下面的地址,这样ebp + 0x4.因此,要从我们的变量buffer1获取返回指针,我们必须添加0xC(以获取ebp),然后添加0x4(返回指针为0x4 ebp).现在我们可以进行修改.

我从您的C代码中取出您想要跳过的分配x = 1并直接返回到printf.我反汇编main以找到对返回指针的适当修改:

(gdb) disassemble main
Dump of assembler code for function main:
   0x080483e2 <+0>: push   ebp
   0x080483e3 <+1>: mov    ebp,esp
   0x080483e5 <+3>: and    esp,0xfffffff0
   0x080483e8 <+6>: sub    esp,0x20
   0x080483eb <+9>: mov    DWORD PTR [esp+0x1c],0x0
   0x080483f3 <+17>:    mov    DWORD PTR [esp+0x8],0x3
   0x080483fb <+25>:    mov    DWORD PTR [esp+0x4],0x2
   0x08048403 <+33>:    mov    DWORD PTR [esp],0x1
   0x0804840a <+40>:    call   0x80483c4 <function>
   0x0804840f <+45>:    mov    DWORD PTR [esp+0x1c],0x1
   0x08048417 <+53>:    mov    eax,DWORD PTR [esp+0x1c]
   0x0804841b <+57>:    mov    DWORD PTR [esp+0x4],eax
   0x0804841f <+61>:    mov    DWORD PTR [esp],0x80484f0
   0x08048426 <+68>:    call   0x80482f4 <printf@plt>
   0x0804842b <+73>:    leave  
   0x0804842c <+74>:    ret    
End of assembler dump.
Run Code Online (Sandbox Code Playgroud)

在不修改返回指针的情况下,对function0x0804840a 的调用返回0x0804840f.但是我们想跳过这个并返回到下一条指令.下一条指令从0x08048417开始,进一步为0x8字节.因此,我们对返回指针的修改必须将其值增加0x8.

考虑到这些因素,我使用以下代码打印"0"而不是"1":

void function(int a, int b, int c) {
   char buffer1[8];
   char buffer2[10];
   int* ret;

   ret = buffer1 + 0x10;
   *ret+=8;
}

void main() {
  int x;

  x = 0;
  function(1,2,3);
  x = 1;
  printf("%d\n",x);
}
Run Code Online (Sandbox Code Playgroud)