Dette er den reneste formen for feilen: angriperen leverer *instruksjonene*,
ikke bare adressen til instruksjoner som allerede finnes. Ingen libc-offsets
nødvendig, så det virker i prinsippet mot et statisk linket, fullt
randomisert mål.
`make verify` assemblerer `shellcode.S` og diff'er det mot byte-arrayet
innebygd i `fooc.c`, så de to ikke kan drive fra hverandre.
**Forsvar:** **NX** (også kalt W^X, "no execute"). Å markere stacken som
ikke-kjørbar gjør at maskinvaren nekter å hente instruksjoner fra den, og
`ret`-et lander på en side som ikke kan kjøres. Det er derfor `make food`
sender `-z execstack`: en vanlig Linux-stack er `rw-p`, ikke `rwx`, og
teknikken dør med SIGSEGV ved `RIP = payloadens adresse`. Den absolutt
viktigste leksjonen i laboratoriet er at hver eneste av disse bytene bare
virker fordi kompilatoren fikk beskjed om å la stacken være kjørbar. Det
flagget er på til gagn for ingen.
### Også inkludert
| Modus | Hva den gjør |
|---|---|
| `-t leak` | kobler til, skriver ut leaks, sender ingenting |
| `-t demo` | sender `rip_off + 8` bytes `0x41`, så `RIP` blir `0x4141...` og daemonen dør. Beviser feilen helt uten adressekunnskap |
| `-t sled` | et ret-sled, bevisst beholdt som et **feilende** eksempel. Uten et leak ville du brute-force ASLR ved å fylle bufferen med adressen til et `ret`. Det kan ikke virke her: `food` aksepterer 512 bytes, så sleden har ~53 slots mot ~28 bits entropi. Implementert så du kan se det feile og bekrefte at mekanismen virkelig er "CPU-en følger en kjede av rets" |
---
## Mottiltak-tabellen
Dette er delen å huske. Hver rad er et ekte forsvar, og høyre kolonne viser hva
den faktisk gjør med hendelseskjeden.
| Mottiltak | Slik aktiverer du | Hva den stopper | Hva den *ikke* stopper |
|---|---|---|---|
| **Begrens read** | `n = read(fd, buf, sizeof buf - 1);` | **Alt.** Feilen finnes ikke, så ingenting nedstrøms betyr noe | Ingenting — dette er den eneste fullstendige fixen |
| **Stack-canary** | `-fstack-protector-strong` (gccs standard) | `ret`-et: canaryen sjekkes ved funksjonsavslutningen, så smadringen oppdages og prosessen aborter før `RIP` poppes | En feil i en funksjon *uten* array (ingenting å beskytte); et overløp som holder seg under canaryen; alt som ikke returnerer normalt |
| **NX / W^X** | `-z noexecstack` (standarden) | Shellcode. Payloadens egne instruksjoner kan ikke hentes | ret2win og ret2libc fullstendig. Disse er *grunnen* til at ROP finnes |
| **PIE + ASLR** | `-fPIE` + ASLR=2 (begge standard) | ret2wins hardkodede adresser. Alt flytter seg ved hver kjøring | Alt der angriperen har et leak. ASLR hever prisen på et exploit; det er ikke en fix. Merk at stack, heap og mmap randomiseres, men hoved-binærfilens *innhold* gjør det ikke — det er det ROP-kjeder bruker |
| **Ikke lek** | ingen `printf("%p")` til klienter; initialiser før du skriver ut | Informasjonsleaket som gjør ASLR fra "dyrt" til "gratis" | — |
| **Ikke bruk `printf(user_data)`** | `printf("%s", buf)` i stedet for `printf(buf)` | Format-streng-feil: `%x`-stack-reads, `%n`-vilkårlige skrivninger, som er en *annen* vei til RCE | — |
| **Ikke bruk upålitelige stier** | valider og `openat()` under en fast mappe | Sti-traversal ([CWE-22](https://cwe.mitre.org/data/definitions/22.html)) | — |
| **CET / shadow stack** | `-fcf-protection=full`, kjernens og CPU-ens støtte | `ret`-et selv: shadow stacken husker den *ekte* returadressen og feiler ved mismatch. Fanger ROP-kjeder som bruker maskinvare-`ret` | Angrep som aldri `ret`-er (call-oriented, eller å overskrive en funksjonspekermål med en gadget-kjede som ikke trenger retur) |
| **Sikre språk** | Rust, Go, C# for ny kode | Hele klassen. Bounds-sjekker utføres ved kjøring, ikke håpet på ved review | — |
### Se det selv
```sh
make run # sårbar daemon
make test # alle tre teknikkene virker
make test-hardened # samme kildekode, mottiltak på
```
`test-hardened` bygger `food_hardened` med `-fstack-protector-strong -fPIE -pie
-z noexecstack`, bytter den inn, kjører alle tre igjen og legger så den
sårbare tilbake. Du vil se:
```
### stack segment: 'rw-p' (NOT executable) is what you want to see
--- ret2win was stopped by the mitigations (as expected)
--- ret2libc was stopped by the mitigations (as expected)
--- shellcode was stopped by the mitigations (as expected)
```
Og i den hardnede daemonens logg, canaryen som utløses:
```
*** stack smashing detected ***: terminated
```
Les det nøye, for det er den viktigste linjen i hele laboratoriet: **canaryen
fanget ret2win, ikke PIE.** Alle tre teknikkene dør ved canaryen, fordi alle
tre går gjennom det samme `read()` og ødelegger den samme rammen. NX stopper
bare i tillegg shellcodens *kode*; PIE bryter bare i tillegg den hardkodede
adressen. Slå dem på enkeltvis, og du vil oppdage at de fleste enkeltstående
mottiltak etterlater deg utsatt for noe.
---
## Filer
| Fil | Formål |
|---|---|
| `food.c` | den sårbare daemonen. 6 nummererte feil, hver med sin fix i kommentaren |