
Packer e crypter PE open source per Windows x64. Comprime e crittografa gli eseguibili tramite una macchina virtuale personalizzata, racchiudendoli in uno stub autoestraente.
<p align="center"> <img src="https://assets.kitploit.com/production/public/readmes/785/7ff1b51788aec918215f14448f75634857f9c725958c5fb66694ab16f5e8542d.png" alt="github-social-preview" width="600" /> </p>
## *TinyLoad v7.4 - PE packer e crypter per Windows*
<p align="left">
<a href="https://github.com/iamsopotatoe-coder/TinyLoad/actions/workflows/build.yml"><img src="https://img.shields.io/github/actions/workflow/status/iamsopotatoe-coder/TinyLoad/build.yml?style=flat&logo=github&logoColor=white&label=build&labelColor=0d0d0d" alt="build"></a>
<a href="https://github.com/gmh5225/awesome-game-security"><img src="https://awesome.re/mentioned-badge.svg" alt="Mentioned in Awesome" height="20"></a>
</p>
TinyLoad è un crypter/packer PE per eseguibili x64: comprime un exe in input con diversi livelli di protezione per impedirne il reverse engineering. È un singolo file .cpp e non ha dipendenze esterne.
## *come funziona*
TinyLoad aggiunge il tuo payload a una copia di se stesso. Quando l'exe compresso viene eseguito, estrae il payload, lo decripta e lo esegue direttamente in memoria senza mai scrivere l'originale su disco. Ogni volta che comprimi qualcosa, gli opcode della VM vengono modificati casualmente e inseriti in 4 sottotabelle con chiavi indipendenti, così non esistono due build identiche.
<details>
<summary><b>Pipeline di pack()</b></summary>
```mermaid
flowchart TD
start["pack(in, out, vm, comp, veh, noconsole)"] --> load["loadFile(in) → orig"]
load --> pe{"MZ + PE00 + Machine 0x8664 + NumberOfSections in 1..96?"}
pe -->|fail| err["printf error / return false"]
pe -->|ok| init["pay = orig flags = 0"]
init --> cdec{"--c ?"}
cdec -->|yes| lz["flags |= 1<br/>lzPack: WINDOW=0xFFFF MAXCHAIN=4096<br/>MAXMATCH=258 MINMATCH=3 HSIZE=65536<br/>hash4 = FNV-ish fold * 0x1000193<br/>lazy lookahead la = 1,2<br/>out = uint32le origSz + 8-token flag bytes<br/>match → varint dist, varint len-3"]
cdec -->|no| vmq
lz --> vmq{"--vm ?"}
vmq -->|yes| scatter["flags |= 2<br/>Fisher-Yates 32 slots, scatter NUM_OPS=28<br/>into subtables 4x8, unused stay 0xFF<br/>opmap_enc op = tbl shl 6 OR idx"]
scatter --> canary["canary corridor n=8, skip first 0x400 of pay<br/>canExp c = pay at off XOR prev"]
canary --> mkvm["makeVmProgram opmap_enc, key1, key2, canary<br/>key1,key2 ← mt19937_64 TickCount64 XOR QPC<br/>opaque predicates + stream loop + canary mask"]
mkvm --> venc["vmEncryptPayload 192-bit state<br/>k3 = 0x9E3779B97F4A7C15<br/>ks = uint8((k1 XOR k2) + k3)<br/>b = NOT(b XOR ks)<br/>k1 = rotl64(k1,11) XOR k2<br/>k2 = rotr64(k2,19) + k1 + k3<br/>k3 = k3 * phi XOR k1"]
vmq -->|no| vehq
venc --> vehq{"--veh ?"}
vehq -->|yes| vflag["flags |= FLAG_VEH 4"]
vehq -->|no| stub
vflag --> stub["stub = loadFile GetModuleFileNameA self<br/>saveFile out, stub as host image"]
stub --> skey["stubKey = 0x9E3779B97F4A7C15<br/>for i in 0x1000 .. min n, 0x2000:<br/>stubKey = (stubKey XOR stub i) * phi"]
skey --> disp["prime vmRun dispKey=0 → fill g_off<br/>dispKey ← rng<br/>encOff j = uint64(g_off j) XOR dispKey"]
disp --> tail["Tail: sig TINYLD60, origSz, packSz, flags,<br/>dispOff x28, subtables 4x8, vmCodeSz,<br/>dispKey, canary*, chunk*,<br/>payHash = SHA-256 orig first 8B"]
tail --> hide["sig i XOR= stubKey shr 8i<br/>xorOpmap FNV-1a 0x811C9DC5 / 0x01000193<br/>feeds origSz, packSz, vmCodeSz + first 32B<br/>of vmCode and pay, per-table<br/>flags |= FLAG_CHUNK 8"]
hide --> tenc["XOR-encode Tail fields with stubKey slices<br/>vmCode vi XOR= stubKey shr ((vi*3) and 63)"]
tenc --> ovl["payload = vmCode || pay<br/>interleave: insert 0x00 after every 3 bytes"]
ovl --> chunks["split into 4 chunks, shuffle physical order<br/>Tail placeholder TAIL_SERIALIZED_SZ = 419<br/>before each chunk: 128..640 RNG junk"]
chunks --> tea["xxteaEncrypt bytes after Tail<br/>DELTA=0x9E3779B9 rounds=6+52/n<br/>remainder XOR pxKey0 xor pxKey1 xor pxKey2 xor pxKey3<br/>patch k i XOR FEEDF00D / CAFEBABE /<br/>DEADBEEF / 8BADF00D into _pxBlock<br/>between C0DE1337 and B007DEAD"]
tea --> ser["XOR chunkOff / chunkSz / chunkOrder / chunkCnt<br/>serializeTail: 16 TLV records id + u16le sz + bytes<br/>Fisher-Yates order, LCG 1103515245+12345<br/>seed = stubKey XOR filesize<br/>append DWORD LE: tailOff XOR stubKey low 32"]
ser --> fin{"--noconsole ?"}
fin -->|yes| gui["OptionalHeader.Subsystem = IMAGE_SUBSYSTEM_WINDOWS_GUI"]
fin -->|no| scr
gui --> scr["scrambleSections: cycle names<br/>.text .data .rdata .bss .idata"]
scr --> done["saveFile out, result"]
```
</details>
## *download*
Prendi un binario precompilato dalle [release](https://github.com/iamsopotatoe-coder/tinyload/releases) oppure compilalo tu stesso.
## *compilazione dal sorgente*
Ti serve MinGW (g++). Basta eseguire:
```cmd
g++ -o TinyLoad.exe TinyLoad.cpp -static -O2 -s
```
oppure usa `build.bat`.
## *utilizzo*
```cmd
TinyLoad.exe --i <input> [--o <output>] [--vm] [--c] [--veh]
```
| flag | cosa fa |
|------|-------------|
| `--i <file>` | exe di input da comprimere |
| `--o <file>` | percorso di output (default: `input_packed.exe`) |
| `--vm` | crittografia VM |
| `--c` | compressione LZ77 |
| `--veh` | decrittografia VEH tramite page fault |
| `--noconsole` | sottosistema GUI |
Devi usare almeno uno tra `--vm`, `--c` o `--veh`.
### esempi
<img width="800" height="103" alt="2026-08-1118-55-14-ezgif com-video-to-gif-converter" src="https://assets.kitploit.com/production/public/readmes/785/7ce7b0012acf9d4aa5710a0d65dbd20d0e5162a794e0590aad42c450a39dabdb.gif" />
## *immagini DIE*
<p align="center">
<img src="https://assets.kitploit.com/production/public/readmes/785/9272d64113a13607fb2bac80ae094f39240d1294be380965a878d3a949814b96.png" alt="die-gui-packed" height="250" " />
<img src="https://assets.kitploit.com/production/public/readmes/785/347ba4f6f37f73ace650716b77f93895119ff6509cb476e27b69fab81bba6de4.png" alt="die-gui-entropy" height="250" " />
</p>
## *compressione*
Compressione LZ77 personalizzata con matching tramite hash chain e una finestra scorrevole da 64KB. La compressione viene eseguita per prima, poi la crittografia VM viene applicata sopra, così anche eventuali pattern nei dati compressi vengono nascosti.
## *crittografia VM*
Macchina virtuale personalizzata con 28 opcode che viene eseguita all'interno dello stub. Gli opcode vengono posizionati casualmente in 4 sottotabelle da 8 ciascuna e ogni sottotabella viene crittografata con XOR usando una chiave diversa derivata dai dati del payload. Decifrare 1 sottotabella rivela al massimo 8 opcode su 28. La cifratura stessa è un cifrario a flusso a 128 bit che usa rotl e rotr per il mixing delle chiavi, eseguito interamente dentro l'interprete della VM. Il payload viene crittografato con XXTEA.
## *decrittografia VEH tramite page fault*
Con `--veh` abilitato, tutte le pagine delle sezioni PE vengono mappate come PAGE_NOACCESS. Quando il programma tenta di accedere a una pagina, viene generata un'eccezione; un gestore di eccezioni vettoriale decripta solo quella singola pagina e imposta la protezione corretta. Un thread watchdog gira in background e ri-crittografa qualsiasi pagina che non è stata toccata per 200ms. In ogni momento la maggior parte del tuo programma è ancora crittografata in memoria, quindi i memory dump catturano solo ciò che è stato acceduto di recente.
## *anti dump*
Le 4 API più critiche (GetModuleHandleA, GetProcAddress, ExitProcess, VirtualAlloc) vengono reindirizzate tramite funzioni wrapper all'interno dello stub. Dopo che il payload è stato caricato, l'intera directory delle importazioni viene azzerata, così i memory dump non possono ricostruire la tabella delle importazioni.
## *licenza*
MIT
## *note a margine*
- Ci sono molte funzionalità che non ho inserito nel readme: puoi leggere il codice da solo oppure guardare [changelog.md](https://github.com/iamsopotatoe-coder/tinyload/blob/main/docs/CHANGELOG.md)
- Funziona sulla maggior parte dei file che ho testato; se si rompe sul tuo, apri una issue e ci do un'occhiata
- Suggerimenti e idee per nuove funzionalità vanno anch'essi nelle issue
- Se lo usi, una stella aiuta molto <3
- Sì, gli AV segnalano i packer, è normale. (Attualmente ha 9 rilevamenti su VirusTotal; qualsiasi file che comprimi con esso ottiene 9 rilevamenti, il contenuto non conta)
- Per favore non comprimere malware con questo: è pensato per scopi legittimi