Pwn - 基本 ROP

基本ROP

参考资料:

环境配置

TODO

ROP简介

Wikipedia:
返回导向编程(英语:Return-Oriented Programming,缩写:ROP)是计算机安全中的一种漏洞利用技术,该技术允许攻击者在程序启用了安全保护技术(如堆栈不可执行)的情况下控制程序执行流,执行恶意代码。其核心思想是通过栈缓冲区溢出等方式控制堆栈调用以劫持程序控制流并执行针对性的机器语言指令序列(称为Gadgets)。所谓 gadgets 就是以 ret 结尾的指令序列,通过这些指令序列,我们可以修改某些地址的内容,方便控制程序的执行流程。

gadgets tools

  • ROPgadget
    • 命令:ROPgadget --binary ./binary | grep "pop rdi; ret"
  • ropper
    • 命令:ropper -f ./binary --search "pop rdi; ret"

ret2text

  • 也叫做 ret2win
  • 控制程序执行本身已有的代码

ctf-wiki:
ret2text 即控制程序执行程序本身已有的的代码 (.text)。其实,这种攻击方法是一种笼统的描述。我们控制执行程序已有的代码的时候也可以控制程序执行好几段不相邻的程序已有的代码 (也就是 gadgets),这就是我们所要说的 ROP。

实例

一般思路

  • 寻找程序中是否存在能够直接 getshell 的函数
  • 寻找有用的代码片段,用于指定寄存器的值

ret2syscall

  • 控制程序执行系统调用
    • 例如调用此函数: execve('/bin/sh', NULL, NULL)

系统调用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 查看系统调用说明文档
man syscall

# ...
Arch/ABI Instruction System Ret Ret Error Notes
───────────────────────────────────────────────────────────────────
i386 int $0x80 eax eax edx -
x86-64 syscall rax rax rdx - 5

# The second table shows the registers used to pass the system call arguments.

Arch/ABI arg1 arg2 arg3 arg4 arg5 arg6 arg7 Notes
──────────────────────────────────────────────────────────────
i386 ebx ecx edx esi edi ebp -
x86-64 rdi rsi rdx r10 r8 r9 -

看到 i386 架构需要通过 int $0x80 触发系统调用,系统调用号存放在 eax 中,参数依次通过 ebx、ecx、edx 等寄存器传递;x86-64 架构则是通过 syscall 触发系统调用,系统调用号存储在 rax 中,参数依次通过 rdi、rsi、rdx 等寄存器传递

1
2
3
4
5
6
7
8
9
10
# 查看系统调用号
cat /usr/include/x86_64-linux-gnu/asm/unistd_32.h
cat /usr/include/x86_64-linux-gnu/asm/unistd_64.h

❯ cat /usr/include/x86_64-linux-gnu/asm/unistd_32.h | grep execve
#define __NR_execve 11
#define __NR_execveat 358
❯ cat /usr/include/x86_64-linux-gnu/asm/unistd_64.h | grep execve
#define __NR_execve 59
#define __NR_execveat 322

这里以执行 execve('/bin/sh', NULL, NULL) 为例,execve 在 32bit 的系统调用号为 11,即 0xb;在 64bit 的系统调用号为 59,即 0x3b

32bit:

  • eax 赋值为 0xb
  • ebx 赋值为 /bin/sh 字符串地址
  • ecx 赋值为 NULL(0)
  • edx 赋值为 NULL(0)
  • 调用: int 0x80

64bit:

  • rax 赋值为 0x3b
  • rdi 赋值为 /bin/sh 字符串地址
  • rsi 赋值为 0
  • rdx 赋值为 0
  • 调用:syscall

实例

  • bamboofox - ret2syscall (x86)
  • ret2syscall_ex1 (x86-64)
    • 64 位程序,使用 syscall 触发系统调用,执行 execve('/bin/sh', NULL, NULL)
    • 题目下载: TODO
    • writeup: TODO

一般思路

  • 寻找 int 0x80syscall 的 gadget
  • 寻找能够控制 eax/rax 的 gadget

ret2shellcode

  • 控制程序执行shellcode代码,注意shellcode所在段需要具有可执行权限
  • 一般情况下,相关题目存在可执行的内存空间

shellcode题目分类:

  1. getshell
  2. orw (open read write)
  3. 时间盲注/布尔盲注

扩展资料: 📔 shellcode题目整理

实例

ret2libc

  • 控制程序执行libc中的函数
    • 直接调用程序 plt 表中的 libc 函数
    • 泄露 got 表中 libc 函数真实地址,根据偏移计算目标 libc 函数地址

参考资料: 深入了解GOT, PLT和动态链接

实例与 Writeup

TODO

练习与扩展