Voltar às atualizações
New releaseAug 12, 2026

TinyLoad v7.3

Empacotador e criptografador de PE Windows x64 de código aberto. Comprime e criptografa executáveis com uma máquina virtual personalizada em um stub auto-extraível.

Compartilhar

github-social-preview

TinyLoad v7.4 - PE packer e crypter para windows

build Mentioned in Awesome

TinyLoad é um crypter/packer de PE para executáveis x64 que empacota um exe de entrada com várias camadas de proteção para impedir que ele seja submetido a engenharia reversa. É um único arquivo .cpp e não possui dependências externas.

como funciona

O TinyLoad anexa seu payload a uma cópia de si mesmo. Quando o exe empacotado é executado, ele extrai o payload, o descriptografa e o executa diretamente na memória, sem nunca gravar o original no disco. Toda vez que você empacota algo, os opcodes da VM são alterados aleatoriamente e colocados em 4 subtabelas com chaves independentes, de modo que não existem 2 builds iguais.

pipeline pack()
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"]

download

pegue um binário pré-compilado em releases ou compile você mesmo.

compilando a partir do código-fonte

você precisa do MinGW (g++). basta executar:

g++ -o TinyLoad.exe TinyLoad.cpp -static -O2 -s

ou use o build.bat.

uso

TinyLoad.exe --i <input> [--o <output>] [--vm] [--c] [--veh]
flago que faz
--i <arquivo>exe de entrada para empacotar
--o <arquivo>caminho de saída (padrão: input_packed.exe)
--vmcriptografia por VM
--ccompressão LZ77
--vehdescriptografia por page fault via VEH
--noconsolesubsistema GUI

você precisa de pelo menos 1 entre --vm, --c ou --veh.

exemplos

2026-08-1118-55-14-ezgif com-video-to-gif-converter

imagens do DIE

die-gui-packed die-gui-entropy

compressão

compressão LZ77 personalizada com correspondência por hash chain e uma janela deslizante de 64KB. a compressão roda primeiro e depois a criptografia por VM é aplicada por cima, de modo que quaisquer padrões nos dados comprimidos também ficam ocultos.

criptografia por VM

máquina virtual personalizada de 28 opcodes que roda dentro do stub. os opcodes são colocados aleatoriamente em 4 subtabelas de 8 cada, e cada subtabela é criptografada com XOR usando uma chave diferente derivada dos dados do payload. quebrar 1 subtabela revela no máximo 8 opcodes de 28. a cifra em si é uma cifra de fluxo de 128 bits usando mistura de chaves com rotl e rotr, executada inteiramente dentro do interpretador da VM. O payload é criptografado usando XXTEA.

descriptografia por page fault via VEH

com --veh habilitado, todas as páginas das seções do PE são mapeadas como PAGE_NOACCESS. quando o programa tenta acessar uma página, isso dispara uma exceção; um manipulador de exceção vetorial descriptografa apenas aquela 1 página e define a proteção correta. uma thread de vigilância roda em segundo plano e re-criptografa qualquer página que não tenha sido acessada em 200ms. a qualquer momento, a maior parte do seu programa ainda está criptografada na memória, então dumps de memória capturam apenas o que foi acessado recentemente.

anti dump

as 4 APIs mais críticas (GetModuleHandleA, GetProcAddress, ExitProcess, VirtualAlloc) são redirecionadas por meio de funções wrapper dentro do stub. depois que o payload é carregado, todo o diretório de imports é zerado, de modo que dumps de memória não conseguem reconstruir a tabela de imports.

licença

MIT

notas adicionais

  • Há muitos recursos que não coloquei no readme; você pode ler o código você mesmo ou consultar changelog.md
  • isso funciona na maioria dos arquivos que testei; se quebrar no seu, abra uma issue e eu vou investigar
  • sugestões e ideias de recursos também vão nas issues
  • se você usar, uma estrela ajuda muito <3
  • sim, AVs sinalizam packers, isso é esperado. (Atualmente tem 9 detecções no virustotal; qualquer arquivo que você empacotar com ele terá 9 detecções, o conteúdo não importa)
  • por favor, não empacote malware com isso; é destinado a fins legítimos

Categorias