简体   繁体   English

c ++有缓冲区溢出helloworld吗?

[英]Is there a buffer overflow helloworld for c++?

I tried the code provided by this question ,but it doesn't work. 我尝试了这个问题提供的代码,但它不起作用。

How to contrive an overflow to wrap my head around? 怎么设计溢出来包裹我的头?

Update: 更新:

    .file   "hw.cpp"
    .section .rdata,"dr"
LC0:
    .ascii "Oh shit really bad~!\15\12\0"
    .text
    .align 2
.globl __Z3badv
    .def    __Z3badv;   .scl    2;  .type   32; .endef
__Z3badv:
    pushl   %ebp
    movl    %esp, %ebp
    subl    $8, %esp
    movl    $LC0, (%esp)
    call    _printf
    leave
    ret
    .section .rdata,"dr"
LC1:
    .ascii "WOW\0"
    .text
    .align 2
.globl __Z3foov
    .def    __Z3foov;   .scl    2;  .type   32; .endef
__Z3foov:
    pushl   %ebp
    movl    %esp, %ebp
    subl    $4, %esp
    movl    LC1, %eax
    movl    %eax, -4(%ebp)
    movl    $__Z3badv, 4(%ebp)
    leave
    ret
    .def    ___main;    .scl    2;  .type   32; .endef
    .align 2
.globl _main
    .def    _main;  .scl    2;  .type   32; .endef
_main:
    pushl   %ebp
    movl    %esp, %ebp
    subl    $8, %esp
    andl    $-16, %esp
    movl    $0, %eax
    addl    $15, %eax
    addl    $15, %eax
    shrl    $4, %eax
    sall    $4, %eax
    movl    %eax, -4(%ebp)
    movl    -4(%ebp), %eax
    call    __alloca
    call    ___main
    call    __Z3foov
    movl    $0, %eax
    leave
    ret
    .def    _printf;    .scl    2;  .type   32; .endef

You can use the C example you posted. 您可以使用您发布的C示例。 It works the same in C as C++. 它在C和C ++中的工作方式相同。

The smallest readable answer I can think of: 我能想到的最小可读答案:

int main() {
    return ""[1]; // Undefined behaviour (reading past '\0' in string)
}

It would help to compile the example in the other question to assembly so you can get a feel for how the stack is laid out for your given compiler and processor. 将其他问题中的示例编译为汇编将有助于您了解堆栈如何为给定的编译器和处理器布局。 The +8 in the example may not be the correct number for your environment. 示例中的+8可能不是您环境的正确数字。 What you need to determine is where the return address is stored on the stack relative to the array stored on the stack. 您需要确定的是返回地址相对于存储在堆栈中的数组存储在堆栈中的位置。

By the way, the example worked for me. 顺便说一下,这个例子对我有用。 I compiled on Win XP with Cygwin, gcc version 4.3.4. 我用Wing编译了Cygwin,gcc版本4.3.4。 When I say it "worked", I mean that it ran code in the bad() function, even though that function was never called by the code. 当我说它“有效”时,我的意思是它在bad()函数中运行代码,即使该函数从未被代码调用过。

$ gcc -Wall -Wextra buffer-overflow.c && ./a.exe
Oh shit really bad~!
Segmentation fault (core dumped)

The code really isn't an example of a buffer overflow, it's an example of what bad things can happen when a buffer overflow is exploited. 代码实际上不是缓冲区溢出的示例,它是利用缓冲区溢出时可能发生的坏事的一个示例。

I'm not great with x86 assembly, but here's my interpretation of how this exploit works. 我对x86程序集不是很了解,但这是我对这个漏洞利用程序的解释。

$ gcc -S buffer-overflow.c && cat buffer-overflow.s
_foo:
        pushl   %ebp           ;2
        movl    %esp, %ebp     ;3
        subl    $16, %esp      ;4
        movl    LC1, %eax      ;5
        movl    %eax, -4(%ebp) ;6
        leal    -4(%ebp), %eax ;7
        leal    8(%eax), %edx  ;8
        movl    $_bad, %eax    ;9
        movl    %eax, (%edx)   ;10
        leave
        ret

_main:
    ...
        call    _foo            ;1
    ...

When main calls foo (1), the call instruction pushes onto the stack the address within main to return to once the call to foo completes. main调用foo (1)时, call指令将main中的地址推送到堆栈,以便在对foo的调用完成后返回。 Pushing onto the stack involves decrementing ESP and storing a value there. 推入堆栈涉及减少ESP并在那里存储值。

Once in foo , the old base pointer value is also pushed onto the stack (2). 一旦进入foo ,旧的基指针值也被推入堆栈(2)。 This will be restored when foo returns. foo返回时,这将被恢复。 The stack pointer is saved as the base pointer for this stack frame (3). 堆栈指针被保存为该堆栈帧的基指针(3)。 The stack pointer is decremented by 16 (4), which creates space on this stack frame for local variables. 堆栈指针递减16(4),这会在此堆栈帧上为局部变量创建空间。

The address of literal "WOW\\0" is copied into local variable overme on the stack (5,6) -- this seems strange to me, shouldn't it be copying the 4 characters into space allocated on the stack? 文字“WOW \\ 0”的地址被复制到堆栈上的局部变量overme (5,6) - 这对我来说似乎很奇怪,难道不应该将4个字符复制到堆栈中分配的空间吗? Anyway, the place where WOW (or a pointer to it) is copied is 4 bytes below the current base pointer. 无论如何,复制WOW(或指向它的指针)的位置是当前基指针下方4个字节。 So the stack contains this value, then the old base pointer, then the return address. 所以堆栈包含这个值,然后是旧的基指针,然后是返回地址。

The address of overme is put into EAX (7) and an integer pointer is created 8 bytes beyond that address (8). overme的地址被放入EAX(7)中,并且在该地址(8)之外的8个字节处创建一个整数指针。 The address of the bad function is put into EAX (9) and then that address is stored in memory pointed to by the integer pointer (10). bad函数的地址放入EAX(9)中,然后将该地址存储在由整数指针(10)指向的存储器中。

The stack looks like this: 堆栈看起来像这样:

     // 4 bytes on each row
ESP: (unused)
   : (unused)
   : (unused)
   : &"WOW\0"
   : old EBP from main
   : return PC, overwritten with &bad

When you compile with optimization, all the interesting stuff gets optimized away as "useless code" (which it is). 当你使用优化进行编译时,所有有趣的东西都会被优化为“无用的代码”(就是这样)。

$ gcc -S -O2 buffer-overflow.c && cat buffer-overflow.s
_foo:
        pushl   %ebp
        movl    %esp, %ebp
        popl    %ebp
        ret

Something like this? 像这样的东西?

int main()
{
    char arr[1];
    arr[1000000] = 'a';
}

A simple buffer overflow would be something like this: 一个简单的缓冲区溢出将是这样的:

#include <stdio.h>
#include <string.h>

int main() {
   char a[4] = {0};
   char b[32] = {0};

   printf("before: b == \"%s\"\n", b);

   strcpy(a, "Putting too many characters in array a");

   printf("after:  b == \"%s\"\n", b);
}

A possible output: 可能的输出:

before: b == ""
after:  b == " characters in array a"

The actual behavior of the program is undefined , so the buffer overflow might also cause different output, crashes or no observable effect at all. 程序的实际行为是未定义的 ,因此缓冲区溢出也可能导致不同的输出,崩溃或根本没有可观察到的影响。

#define _WIN32_WINNT 0x0400
#define WIN32_LEAN_AND_MEAN
#include <windows.h>

void process_msg(const char *pSrc)
{
    char cBuff[5];
    strcpy(cBuff, pSrc);
}

void main()
{
    char szInput[] = "hello world!";
    process_msg(szInput);
}

Running this program at Visual Studio 2008 in Debug mode gives this message: 在调试模式下在Visual Studio 2008上运行此程序会显示以下消息:

Run-Time Check Failure #2 - Stack around the variable 'cBuff' was corrupted.

The 'cBuff' char array is allocated on the stack in this example and it's of 5 bytes in size. 在这个例子中,'cBuff'char数组被分配在堆栈上,它的大小为5个字节。 Copying the given pointer's data (pSrc) to that char arrat (cBuff) overwrites the stack frame's data which will result in a possible exploit. 将给定指针的数据(pSrc)复制到该charrat(cBuff)会覆盖堆栈帧的数据,这将导致可能的漏洞利用。

This technique is used by hackers - they send a specially crafted array of chars which will overwrite the pointer to the "return" address, on the stack, and change it to their desired location at the memory. 黑客使用这种技术 - 它们发送一个特制的字符数组,它将覆盖堆栈上指向“返回”地址的指针,并将其更改为它们在内存中的所需位置。

So, for example, they could point that "return" address to any system/program code that will open a port or establish a connection, and then they get to you PC, with the application's privileges (many times this means root/administrator). 因此,例如,他们可以将“返回”地址指向将打开端口或建立连接的任何系统/程序代码,然后他们使用应用程序的权限(多次这意味着root / administrator)到达您的PC 。

Read more at http://en.wikipedia.org/wiki/Buffer_overflow . 更多信息,请访问http://en.wikipedia.org/wiki/Buffer_overflow

In addition to the excellent article pointed out by Eric , you might also check out the following reading materials: 除了Eric指出优秀文章外 ,您还可以查看以下阅读材料:

The following article focuses more on heap overflows: 以下文章更多地关注堆溢出:

This was copied from my answer here . 这是从我的答案抄在这里

The term buffer overflow precisely means accessing past the end of the buffer (sloppily needing to include the idea of buffer underflow , too). 术语缓冲区溢出精确地意味着访问缓冲区的末尾(也需要包括缓冲区下溢的想法)。 But there's a whole class of "memory safety problems" having to do with buffer overflows, pointers, arrays, allocation and deallocation, all of which can produce crashes and/or exploit opportunities in code. 但是有一整类“内存安全问题”与缓冲区溢出,指针,数组,分配和释放有关,所有这些都会在代码中产生崩溃和/或利用机会。 See this C example of another memory safety problem (and our way to detect it). 请参阅此C另一个内存安全问题的示例(以及我们检测它的方法)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM