如何在 GCC、windows XP、x86 中编写缓冲区溢出漏洞利用程序? [英] How to write a buffer-overflow exploit in GCC,windows XP,x86?

查看:18
本文介绍了如何在 GCC、windows XP、x86 中编写缓冲区溢出漏洞利用程序?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

   ret = buffer1 + 12;
   (*ret) += 8;//why is it 8??
}

void main() {
  int x;

  x = 0;
  function(1,2,3);
  x = 1;
  printf("%d
",x);
}

上面的demo来自这里:

The above demo is from here:

http://insecure.org/stf/smashstack.html

但它在这里不起作用:

D:	est>gcc -Wall -Wextra hw.cpp && a.exe
hw.cpp: In function `void function(int, int, int)':
hw.cpp:6: warning: unused variable 'buffer2'
hw.cpp: At global scope:
hw.cpp:4: warning: unused parameter 'a'
hw.cpp:4: warning: unused parameter 'b'
hw.cpp:4: warning: unused parameter 'c'
1

虽然作者认为,但我不明白为什么它是 8:

And I don't understand why it's 8 though the author thinks:

一个小数学告诉我们距离是8 个字节.

A little math tells us the distance is 8 bytes.

我的 gdb 转储调用:

My gdb dump as called:

Dump of assembler code for function main:
0x004012ee <main+0>:    push   %ebp
0x004012ef <main+1>:    mov    %esp,%ebp
0x004012f1 <main+3>:    sub    $0x18,%esp
0x004012f4 <main+6>:    and    $0xfffffff0,%esp
0x004012f7 <main+9>:    mov    $0x0,%eax
0x004012fc <main+14>:   add    $0xf,%eax
0x004012ff <main+17>:   add    $0xf,%eax
0x00401302 <main+20>:   shr    $0x4,%eax
0x00401305 <main+23>:   shl    $0x4,%eax
0x00401308 <main+26>:   mov    %eax,0xfffffff8(%ebp)
0x0040130b <main+29>:   mov    0xfffffff8(%ebp),%eax
0x0040130e <main+32>:   call   0x401b00 <_alloca>
0x00401313 <main+37>:   call   0x4017b0 <__main>
0x00401318 <main+42>:   movl   $0x0,0xfffffffc(%ebp)
0x0040131f <main+49>:   movl   $0x3,0x8(%esp)
0x00401327 <main+57>:   movl   $0x2,0x4(%esp)
0x0040132f <main+65>:   movl   $0x1,(%esp)
0x00401336 <main+72>:   call   0x4012d0 <function>
0x0040133b <main+77>:   movl   $0x1,0xfffffffc(%ebp)
0x00401342 <main+84>:   mov    0xfffffffc(%ebp),%eax
0x00401345 <main+87>:   mov    %eax,0x4(%esp)
0x00401349 <main+91>:   movl   $0x403000,(%esp)
0x00401350 <main+98>:   call   0x401b60 <printf>
0x00401355 <main+103>:  leave
0x00401356 <main+104>:  ret
0x00401357 <main+105>:  nop
0x00401358 <main+106>:  add    %al,(%eax)
0x0040135a <main+108>:  add    %al,(%eax)
0x0040135c <main+110>:  add    %al,(%eax)
0x0040135e <main+112>:  add    %al,(%eax)
End of assembler dump.

Dump of assembler code for function function:
0x004012d0 <function+0>:        push   %ebp
0x004012d1 <function+1>:        mov    %esp,%ebp
0x004012d3 <function+3>:        sub    $0x38,%esp
0x004012d6 <function+6>:        lea    0xffffffe8(%ebp),%eax
0x004012d9 <function+9>:        add    $0xc,%eax
0x004012dc <function+12>:       mov    %eax,0xffffffd4(%ebp)
0x004012df <function+15>:       mov    0xffffffd4(%ebp),%edx
0x004012e2 <function+18>:       mov    0xffffffd4(%ebp),%eax
0x004012e5 <function+21>:       movzbl (%eax),%eax
0x004012e8 <function+24>:       add    $0x5,%al
0x004012ea <function+26>:       mov    %al,(%edx)
0x004012ec <function+28>:       leave
0x004012ed <function+29>:       ret

在我的情况下,距离应该是 - = 5,对吧?但它似乎不起作用..

In my case the distance should be - = 5,right?But it seems not working..

为什么 function 需要 56 字节的局部变量?( sub $0x38,%esp )

Why function needs 56 bytes for local variables?( sub $0x38,%esp )

推荐答案

As joveha指出call指令保存在栈上的EIP值(返回地址)需要自增7 字节 (0x00401342 - 0x0040133b = 7) 以跳过 x = 1; 指令(movl $0x1,0xfffffffc(%ebp)).

As joveha pointed out, the value of EIP saved on the stack (return address) by the call instruction needs to be incremented by 7 bytes (0x00401342 - 0x0040133b = 7) in order to skip the x = 1; instruction (movl $0x1,0xfffffffc(%ebp)).

您是正确的,为局部变量(sub $0x38,%esp)保留了 56 个字节,因此缺少的部分是在 buffer1 之后有多少字节stack是保存的EIP.

You are correct that 56 bytes are being reserved for local variables (sub $0x38,%esp), so the missing piece is how many bytes past buffer1 on the stack is the saved EIP.

一些测试代码和内联汇编告诉我,我的测试的神奇值是 28.我无法提供关于为什么它是 28 的明确答案,但我会假设编译器正在添加填充和/或 堆栈金丝雀.

A bit of test code and inline assembly tells me that the magic value is 28 for my test. I cannot provide a definitive answer as to why it is 28, but I would assume the compiler is adding padding and/or stack canaries.

以下代码使用 GCC 3.4.5 (MinGW) 编译并在 Windows XP SP3 (x86) 上测试.

The following code was compiled using GCC 3.4.5 (MinGW) and tested on Windows XP SP3 (x86).


unsigned long get_ebp() {
   __asm__("pop %ebp
	"
           "movl %ebp,%eax
	"
           "push %ebp
	");
}

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

   /* distance in bytes from buffer1 to return address on the stack */
   printf("test %d
", ((get_ebp() + 4) - (unsigned long)&buffer1));

   ret = (int *)(buffer1 + 28);

   (*ret) += 7;
}

void main() {
   int x;

   x = 0;
   function(1,2,3);
   x = 1;
   printf("%d
",x);
}

我可以很容易地使用 gdb 来确定这个值.

I could have just as easily used gdb to determine this value.

(使用 -g 编译以包含调试符号)

(compiled w/ -g to include debug symbols)

(gdb) break function
...
(gdb) run
...
(gdb) p $ebp
$1 = (void *) 0x22ff28
(gdb) p &buffer1
$2 = (char (*)[5]) 0x22ff10
(gdb) quit

(0x22ff28 + 4) - 0x22ff10 = 28

(0x22ff28 + 4) - 0x22ff10 = 28

(ebp 值 + 字大小) - buffer1 的地址 = 字节数

(ebp value + size of word) - address of buffer1 = number of bytes

除了为了乐趣和利润而粉碎堆栈,我建议阅读一些我在 我对上一个问题的回答中提到的文章您的 和/或有关该主题的其他材料.对这种类型的漏洞利用如何工作有一个很好的了解应该可以帮助您编写更安全的代码.

In addition to Smashing The Stack For Fun And Profit, I would suggest reading some of the articles I mentioned in my answer to a previous question of yours and/or other material on the subject. Having a good understanding of exactly how this type of exploit works should help you write more secure code.

这篇关于如何在 GCC、windows XP、x86 中编写缓冲区溢出漏洞利用程序?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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