No-exec / NX

Tip

Učite i vežbajte AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Učite i vežbajte GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Učite i vežbajte Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Podržite HackTricks

Osnovne informacije

The No-Execute (NX) bit, also known as Execute Disable (XD) in Intel terminology, is a hardware-based security feature designed to mitigate the effects of buffer overflow attacks. When implemented and enabled, it distinguishes between memory regions that are intended for executable code and those meant for data, such as the stack and heap. The core idea is to prevent an attacker from executing malicious code through buffer overflow vulnerabilities by putting the malicious code in the stack for example and directing the execution flow to it.

Modern operating systems enforce NX through the page table attributes that back the ELF program headers. For example, the PT_GNU_STACK header combined with the GNU_PROPERTY_X86_FEATURE_1_SHSTK or GNU_PROPERTY_X86_FEATURE_1_IBT properties let the loader know whether the stack should be RW or RWX. When NX is enabled and the binary was linked with a non-executable stack (-z noexecstack), any attempt to pivot execution into attacker-controlled data pages (stack, heap, mmap’ed buffers, etc.) will raise a fault unless those pages were explicitly marked as executable.

Brzo otkrivanje NX

  • checksec --file ./vuln will display NX enabled or NX disabled based on the GNU_STACK program header.
  • readelf -W -l ./vuln | grep GNU_STACK exposes the stack permissions; the presence of an E flag indicates that the stack is executable. Example:
$ readelf -W -l ./vuln | grep GNU_STACK
GNU_STACK      0x000000 0x000000 0x000000 0x000000 0x000000 RW  0x10
  • execstack -q ./vuln (from prelink) je koristan pri auditu velikih kolekcija binarnih fajlova jer ispisuje X za binarije koje i dalje imaju izvršni stack.
  • U runtime-u, /proc/<pid>/maps će pokazati da li je alokacija rwx, rw-, r-x, itd., što je korisno pri proveri JIT engines-a ili custom allocators-a.

Zaobilaženja

Primitivi za ponovno korišćenje koda

Moguće je koristiti tehnike kao što je ROP da biste zaobišli ovu zaštitu izvršavanjem delova izvršnog koda koji su već prisutni u binarnom fajlu. Tipični lanci uključuju:

  • Ret2libc
  • Ret2syscall
  • Ret2dlresolve kada binar ne importuje system/execve
  • Ret2csu ili Ret2vdso za sintezu syscall-ova
  • Ret2… — bilo koji dispatcher koji vam omogućava da spojite kontrolisano stanje registara sa postojećim izvršnim kodom da biste pozvali syscall-ove ili library gadgets.

Tok rada obično je: (1) leak pointera u kodu ili libc kroz info leak, (2) rešavanje baza funkcija, i (3) izrada lanca koji nikada ne zahteva izvršne bajtove pod kontrolom napadača.

Sigreturn Oriented Programming (SROP)

SROP gradi lažni sigframe na writable strani i pivota izvršenje na sys_rt_sigreturn (ili odgovarajući ABI ekvivalent). Kernel zatim „vraća“ kreirani kontekst, odmah dajući punu kontrolu nad svim opštim registrima, rip, i eflags. Nedavni CTF izazovi (npr. zadatak Hostel na n00bzCTF 2023) pokazuju kako SROP lanci prvo pozivaju mprotect da prebace stack na RWX, zatim ponovo koriste isti stack za shellcode, efektivno zaobilazeći NX čak i kada je dostupan samo jedan syscall; ret gadget. Check the dedicated SROP page for more architecture-specific tricks.

Ret2mprotect / ret2syscall za promenu permisija

Ako možete pozvati mprotect, pkey_mprotect, ili čak dlopen, možete legitimno zatražiti izvršno mapiranje pre pokretanja shellcode-a. Mali pwntools skelet izgleda ovako:

from pwn import *
elf = ELF("./vuln")
rop = ROP(elf)
rop.mprotect(elf.bss(), 0x1000, 7)
payload = flat({offset: rop.chain(), offset+len(rop.chain()): asm(shellcraft.sh())})

Ista ideja važi i za ret2syscall lance koji постave rax=__NR_mprotect, усмере rdi на mmap/.bss страницу, сместе жељену дужину у rsi и поставе rdx=7 (PROT_RWX). Када постоји RWX регион, извршавање може безбедно скочити у бајтове које контролише нападач.

RWX primitives from JIT engines and kernels

JIT engines, interpreters, GPU drivers и kernel subsistemi који динамички емитују код често су начин да се поврати извршна меморија чак и под строгим NX политикама. Ranljivost Linux kernela из 2024. CVE-2024-42067 показала је да пропусти у set_memory_rox() остављају eBPF JIT странице записивим и извршним, допуштајући нападачима да распрше gadgets или читаве shellcode blob-ове унутар кернела упркос NX/W^X очекивањима. Eksploiti који добију контролу над JIT компајлером (BPF, JavaScript, Lua итд.) могу зато поставити свој payload да борави у тим RWX зонама и потребна им је само једна function pointer overwrite да скоче у њих.

Non-return code reuse (JOP/COP)

Ако су ret инструкције ојачане (нпр. CET/IBT) или бинарни фајл нема изразите ret gadgets, пређите на Jump-Oriented Programming (JOP) или Call-Oriented Programming (COP). Ове технике праве dispatchere који користе jmp [reg] или call [reg] секвенце пронађене у бинарцу или учитаним библиотекама. Оне и даље поштују NX јер поново користе постојећи извршни код, али заобилазе mitigacije које посебно прате велике ланце ret инструкција.

ROP & JOP

References

Tip

Učite i vežbajte AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Učite i vežbajte GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Učite i vežbajte Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Podržite HackTricks