Skip to content
KitploitKITPLOIT
StrumentiBlog
Invia
StrumentiBlog
Invia

Strumenti di Hacking, PenTest e Cybersecurity per il tuo Arsenale di Sicurezza!

Kitploit è una directory di strumenti di hacking, cybersecurity e pentesting. Scopri gli ultimi aggiornamenti dei progetti per trovare vulnerabilità, analizzare sistemi, automatizzare i test e rafforzare la tua sicurezza.

··Feed·Contatto·Privacy·© 2026 Kitploit

Directory degli strumenti

Categorie

Vedi tutte le categorie
Loading categories
static_asm — Assembler C++2x solo header per la codifica di istruzioni x86/x86-64 a tempo di compilazione | Kitploit
Strumenti/GitHubGitHub/mahmoudimus/static_asm
Generazione di PayloadAnalisi del CodiceExploitReverse EngineeringShellcodeAnalisi di BinariApprendimento e FormazioneGenerazione di ShellcodePercorsi e Corsi
GitHubmahmoudimus/static_asm

static_asm

Assembler C++2x solo header per la codifica di istruzioni x86/x86-64 a tempo di compilazione

3116 mesi faRevisionato da Kitploit

Più Popolari

Vedi tutti →

Scopri gli strumenti più utilizzati dalla nostra community.

Esplora tutti gli strumenti

Sfoglia la nostra collezione di strumenti

Vedi tutti gli strumenti →
Condividi
Vedi RepositorySito web

static_asm

CI License

Una libreria C++20 solo header per la codifica di istruzioni x86/x86-64 in fase di compilazione.

Questo progetto è concesso in doppia licenza sotto la Boost Software License 1.0 e la MIT License. Puoi scegliere una delle due licenze.

Scopo

  • Imparare la codifica assembly x86 in modo pratico e divertente
  • Generare istruzioni assembly in fase di compilazione con piena sicurezza dei tipi
  • Creare shellcode e template di codice JIT senza overhead a runtime

Avvio rapido

root@kitploit:~
#include "static_asm.hpp"

using namespace static_asm::x86::registers;
using namespace static_asm::x86::instructions;

// Codice macchina compilato a tempo di compilazione
constexpr auto code = core::assemble(
    mov(rax, 0x12345678),    // mov rax, imm32
    add(rax, rcx),           // add rax, rcx
    xor_(r8, r8),            // xor r8, r8
    call(rax),               // call rax
    ret()                    // ret
);
// code è std::array<uint8_t, N> - completamente constexpr!

Esempi per categoria

Operazioni ALU

root@kitploit:~
// Registro a registro
add(rax, rbx);           // 48 01 D8
sub(ecx, edx);           // 29 D1
and_(r8, r9);            // 4D 21 C8
or_(rsi, rdi);           // 48 09 FE
xor_(eax, eax);          // 31 C0 (idioma comune per azzerare un registro)
cmp(rax, rcx);           // 48 39 C8

// Registro con immediato
add(rax, 0x10);          // 48 83 C0 10 (imm8 esteso con segno)
add(rax, 0x10000);       // 48 05 00 00 01 00 (imm32)
sub(ecx, 100);           // 83 E9 64
and_(rdx, 0xFF);         // 48 83 E2 FF

// Con operandi di memoria
add(eax, dword_ptr(rbx));              // 03 03
add(rax, qword_ptr(rcx + 0x10));       // 48 03 41 10
sub(dword_ptr(rsp + 0x20), eax);       // 29 44 24 20

Movimento dati

root@kitploit:~
// Registro a registro
mov(rax, rbx);           // 48 89 D8
mov(eax, ecx);           // 89 C8
mov(r8, r9);             // 4D 89 C8

// Immediato a registro
mov(rax, 0x12345678);    // 48 C7 C0 78 56 34 12
mov(eax, 0xDEADBEEF);    // B8 EF BE AD DE

// Operazioni di memoria
mov(rax, qword_ptr(rbx));              // 48 8B 03
mov(eax, dword_ptr(rcx + 0x10));       // 8B 41 10
mov(qword_ptr(rsp + 0x8), rax);        // 48 89 44 24 08
mov(dword_ptr(rbp - 0x20), 0x100);     // C7 45 E0 00 01 00 00

// Estensione zero / segno
movzx(eax, bl);          // 0F B6 C3 (estensione zero da byte a dword)
movzx(rax, bx);          // 48 0F B7 C3 (estensione zero da word a qword)
movsx(eax, cl);          // 0F BE C1 (estensione segno da byte a dword)
movsx(rax, dx);          // 48 0F BF C2 (estensione segno da word a qword)
movsxd(rax, ecx);        // 48 63 C1 (estensione segno da dword a qword)

// Carica indirizzo effettivo
lea(rax, qword_ptr(rbx + rcx * s4));           // 48 8D 04 8B
lea(rax, qword_ptr(rbx + rcx * s8 + 0x10));    // 48 8D 44 CB 10

// Scambio
xchg(rax, rbx);          // 48 87 D8

Indirizzamento SIB (Scale-Index-Base)

root@kitploit:~
// [base + index*scale]
mov(eax, dword_ptr(rbx + rcx * s1));   // 8B 04 0B
mov(eax, dword_ptr(rbx + rcx * s2));   // 8B 04 4B
mov(eax, dword_ptr(rbx + rcx * s4));   // 8B 04 8B
mov(eax, dword_ptr(rbx + rcx * s8));   // 8B 04 CB

// [base + index*scale + displacement]
mov(rax, qword_ptr(rbx + rcx * s4 + 0x10));     // 48 8B 44 8B 10
mov(rax, qword_ptr(r12 + r13 * s8 + 0x1000));   // 4B 8B 84 EC 00 10 00 00

// Memorizza su indirizzo SIB
mov(dword_ptr(rax + rdx * s4), ecx);            // 89 0C 90
mov(qword_ptr(rbx + rsi * s8 + 0x20), rax);     // 48 89 44 F3 20

// LEA con SIB (utile per calcoli di indirizzi)
lea(rax, qword_ptr(rbx + rcx * s4));            // 48 8D 04 8B
lea(rax, qword_ptr(rdi + rsi * s8 + 0x100));    // 48 8D 84 F7 00 01 00 00

Shift e Rotazione

root@kitploit:~
// Shift di 1
shl(eax, 1);             // D1 E0
shr(rax, 1);             // 48 D1 E8
sar(ecx, 1);             // D1 F9

// Shift con immediato
shl(eax, 4);             // C1 E0 04
shr(rax, 8);             // 48 C1 E8 08
sar(rdx, 16);            // 48 C1 FA 10

// Shift con registro CL
shl(eax, cl);            // D3 E0
shr(rax, cl);            // 48 D3 E8

// Rotazione
rol(eax, 1);             // D1 C0
ror(rax, 8);             // 48 C1 C8 08
rcl(ecx, cl);            // D3 D1
rcr(rdx, 1);             // 48 D1 DA

Moltiplicazione e Divisione

root@kitploit:~
// Operando singolo (risultato in rdx:rax)
mul(rbx);                // 48 F7 E3 (unsigned: rdx:rax = rax * rbx)
imul(rcx);               // 48 F7 E9 (signed: rdx:rax = rax * rcx)
div(rbx);                // 48 F7 F3 (unsigned: rax = rdx:rax / rbx, rdx = resto)
idiv(rcx);               // 48 F7 F9 (divisione signed)

// IMUL a due operandi (dest = dest * src)
imul(rax, rbx);          // 48 0F AF C3
imul(ecx, edx);          // 0F AF CA

// IMUL a tre operandi (dest = src * imm)
imul(rax, rbx, 10);      // 48 6B C3 0A
imul(ecx, edx, 1000);    // 69 CA E8 03 00 00

Flusso di controllo

root@kitploit:~
// Salti incondizionati
jmp(0x10);               // EB 10 (short, offset a 8 bit)
jmp(0x1000);             // E9 00 10 00 00 (near, offset a 32 bit)
jmp(rax);                // FF E0 (indiretto)
jmp(here);               // EB FE (jmp $, ciclo infinito)

// Salti condizionati (offset a 8 bit)
jz(0x10);                // 74 10
jnz(0x20);               // 75 20
jb(0x08);                // 72 08 (below/carry)
jae(0x08);               // 73 08 (above or equal/no carry)
jl(0x10);                // 7C 10 (less than, signed)
jge(0x10);               // 7D 10 (greater or equal, signed)

// Salti condizionati (offset a 32 bit per rami più lunghi)
jz_near(0x10000);        // 0F 84 00 00 01 00
jnz_near(0x20000);       // 0F 85 00 00 02 00

// Call e return
call(rax);               // FF D0 (chiamata indiretta)
call(0x100);             // E8 00 01 00 00 (chiamata relativa)
ret();                   // C3
ret(0x10);               // C2 10 00 (return e pop di 16 byte)

Mosse condizionate

root@kitploit:~
// Muovi se la condizione è vera (nessuna penalità di branch!)
cmovz(rax, rbx);         // 48 0F 44 C3 (muovi se zero)
cmovnz(eax, ecx);        // 0F 45 C1 (muovi se non zero)
cmovl(rax, rdx);         // 48 0F 4C C2 (muovi se minore, signed)
cmovge(ecx, esi);        // 0F 4D CE (muovi se maggiore o uguale, signed)
cmovb(rax, rbx);         // 48 0F 42 C3 (muovi se below, unsigned)
cmovae(edx, edi);        // 0F 43 D7 (muovi se above o uguale, unsigned)

// Con sorgente di memoria
cmovz(rax, qword_ptr(rbx));           // 48 0F 44 03
cmovnz(eax, dword_ptr(rcx + 0x10));   // 0F 45 41 10

Operazioni bit

root@kitploit:~
// Test bit
bt(eax, 5);              // 0F BA E0 05
bt(rax, rbx);            // 48 0F A3 D8

// Test bit e set/reset/complemento
bts(eax, 10);            // 0F BA E8 0A (test e set)
btr(rax, rcx);           // 48 0F B3 C8 (test e reset)
btc(edx, 3);             // 0F BA FA 03 (test e complemento)

// Scansione bit
bsf(eax, ecx);           // 0F BC C1 (scansiona in avanti per il primo 1)
bsr(rax, rbx);           // 48 0F BD C3 (scansiona all'indietro per il primo 1)

// Conteggio popolazione e zeri iniziali/finali
popcnt(eax, ecx);        // F3 0F B8 C1
lzcnt(rax, rbx);         // F3 48 0F BD C3
tzcnt(eax, edx);         // F3 0F BC C2

// Byte swap
bswap(eax);              // 0F C8 (inverte ordine dei byte)
bswap(rax);              // 48 0F C8

Operazioni sulle stringhe

root@kitploit:~
// Operazioni base su stringhe (operano su [rsi] e/o [rdi])
movsb();                 // A4 (muovi byte [rsi] -> [rdi])
movsw();                 // 66 A5
movsd();                 // A5
movsq();                 // 48 A5

cmpsb();                 // A6 (confronta [rsi] con [rdi])
stosb();                 // AA (memorizza al -> [rdi])
lodsb();                 // AC (carica [rsi] -> al)
scasb();                 // AE (confronta al con [rdi])

// Con prefisso REP (ripeti rcx volte)
rep_movsb();             // F3 A4 (memcpy)
rep_movsq();             // F3 48 A5 (memcpy veloce, 8 byte alla volta)
rep_stosb();             // F3 AA (memset)
rep_stosq();             // F3 48 AB

// Con REPE/REPNE (ripeti mentre uguale/diverso)
repe_cmpsb();            // F3 A6 (confronta stringhe fino a mismatch)
repne_scasb();           // F2 AE (cerca byte nella stringa)

Operazioni stack

root@kitploit:~
push(rax);               // 50
push(rbx);               // 53
push(r8);                // 41 50
push(0x10);              // 6A 10 (push imm8)
push(0x1000);            // 68 00 10 00 00 (push imm32)

pop(rax);                // 58
pop(rbx);                // 5B
pop(r15);                // 41 5F

Istruzioni di sistema

root@kitploit:~
// Chiamate di sistema
syscall_();              // 0F 05 (syscall a 64 bit)
sysenter();              // 0F 34
sysexit();               // 0F 35

// Interrupt
int3();                  // CC (breakpoint)
int_(0x80);              // CD 80 (syscall Linux a 32 bit)
int_(0x21);              // CD 21 (interrupt DOS)

// Informazioni CPU
cpuid();                 // 0F A2
rdtsc();                 // 0F 31
rdtscp();                // 0F 01 F9

// Privilegio
cli();                   // FA (clear interrupts)
sti();                   // FB (set interrupts)
hlt();                   // F4 (halt)

// Ritorno da interrupt
iret();                  // CF (16 bit)
iretd();                 // CF (32 bit)
iretq();                 // 48 CF (64 bit)

Assemblaggio di più istruzioni

Usa core::assemble() per concatenare array di byte di istruzioni:

root@kitploit:~
constexpr auto prologue = core::assemble(
    push(rbp),
    mov(rbp, rsp),
    sub(rsp, 0x20)
);

constexpr auto epilogue = core::assemble(
    add(rsp, 0x20),
    pop(rbp),
    ret()
);

// Combinali
constexpr auto full_function = core::assemble(prologue, epilogue);

Installazione

Opzione 1: CMake FetchContent (consigliata)

Aggiungi al tuo CMakeLists.txt:

root@kitploit:~
include(FetchContent)
FetchContent_Declare(
    static_asm
    GIT_REPOSITORY https://github.com/mahmoudimus/static_asm.git
    GIT_TAG v1.0.0  # o commit specifico
)
FetchContent_MakeAvailable(static_asm)

target_link_libraries(tuo_target PRIVATE static_asm::static_asm)

Opzione 2: CMake add_subdirectory

Clona o aggiungi come sottomodulo git:

root@kitploit:~
git submodule add https://github.com/mahmoudimus/static_asm.git external/static_asm

Poi nel tuo CMakeLists.txt:

root@kitploit:~
add_subdirectory(external/static_asm)
target_link_libraries(tuo_target PRIVATE static_asm::static_asm)

Quando incluso tramite add_subdirectory o FetchContent, viene aggiunto al progetto solo il target della libreria di interfaccia static_asm::static_asm. I test e gli esempi non vengono compilati a meno che non siano esplicitamente abilitati con -DSTATIC_ASM_BUILD_TESTS=ON.

Opzione 3: Singolo header

Scarica static_asm.hpp dalla pagina delle release e includilo direttamente:

root@kitploit:~
#include "static_asm.hpp"

Opzione 4: Installazione di sistema

root@kitploit:~
cmake -B build -DCMAKE_BUILD_TYPE=Release
cmake --install build --prefix /usr/local

Poi usa find_package:

root@kitploit:~
find_package(static_asm REQUIRED)
target_link_libraries(tuo_target PRIVATE static_asm::static_asm)

Compilazione

root@kitploit:~
# Configura
cmake -B build -DCMAKE_BUILD_TYPE=Release

# Compila
cmake --build build

# Esegui i test
ctest --test-dir build --output-on-failure

# Compila con esempi (solo Clang, utilizza assembly inline)
cmake -B build -DCMAKE_BUILD_TYPE=Release -DSTATIC_ASM_BUILD_EXAMPLES=ON

Supporto piattaforma:

  • Linux (GCC 11+, Clang 14+)
  • macOS (Apple Clang, Clang)
  • Windows (MSVC 2022+)

Nota: La funzionalità core::emit() con assembly inline richiede Clang con ottimizzazione -O2.

Istruzioni supportate

Supporto operandi:

  • Tutti i registri generali a 8/16/32/64 bit (AL-R15)
  • Registri estesi (R8-R15, R8D-R15D, R8W-R15W, R8B-R15B)
  • Valori immediati (8/16/32/64 bit)
  • Operandi di memoria con registro base e displacement
  • Indirizzamento SIB: [base + index*scale + disp] con fattori di scala 1, 2, 4, 8

Nota: Nessuna estensione SIMD/AVX ancora.

Sviluppo

Configurazione dell'ambiente

Questo progetto utilizza uv per gli strumenti Python (generazione di codice, amalgama singolo header).

root@kitploit:~
# Installa uv (se non già installato)
curl -LsSf https://astral.sh/uv/install.sh | sh

# Verifica installazione
uv --version

# Tutti gli script Python possono essere eseguiti direttamente con uv (le dipendenze sono gestite automaticamente)
uv run scripts/gen_from_x86ref.py --help
uv run scripts/amalgamate.sh

Strumenti richiesti:

Strumenti opzionali per lo sviluppo:

StrumentoScopoInstallazione
clang-formatFormattazione del codiceTramite LLVM o pacchetto di sistema
clang-tidyAnalisi staticaTramite LLVM o pacchetto di sistema

Aggiungere nuove istruzioni

Opzione 1: Usa il generatore di codice

Il progetto include un generatore che analizza il database XML x86reference:

root@kitploit:~
# Mostra riepilogo del database istruzioni
uv run scripts/gen_from_x86ref.py

# Mostra dettagli per un'istruzione specifica
uv run scripts/gen_from_x86ref.py -i lea
uv run scripts/gen_from_x86ref.py -i imul

# Genera file del database istruzioni
uv run scripts/gen_from_x86ref.py --generate-db

# Genera file di test esaustivo
uv run scripts/gen_from_x86ref.py --generate-tests

Opzione 2: Aggiunta manuale

  1. Aggiungi al file db delle istruzioni (array instdb, prefix_db, prefix_0fdb)
  2. Codifica l'encoder in encoder.hpp o estendi un encoder esistente
  3. Aggiungi test

Tecniche per creare una libreria singolo header

Nessuno strumento automatico può convertire in modo affidabile una libreria C++ multi-file arbitraria in una versione pulita solo header senza una preparazione manuale. Le seguenti tecniche aiutano a garantire che la tua libreria possa essere amalgamata con successo in un unico file header rimanendo corretta, manutenibile e conforme agli standard.

Nota: Questo progetto utilizza quom per l'amalgama e clang-tidy con il controllo google-build-using-namespace per automatizzare l'applicazione di queste regole. quom gestisce anche parzialmente la tecnica #4 (marcatori inline) attraverso le sue capacità di elaborazione.

1. Evita using namespace nei file sorgente

using namespace a livello di file nei file .cpp è pericoloso quando quei file vengono successivamente inclusi in un header — inquina lo spazio dei nomi globale per ogni unità di traduzione che include il tuo header.

Pattern consigliati invece:

root@kitploit:~
// Preferito: avvolgi l'implementazione nello spazio dei nomi
namespace MyLib {
    Foo::Foo() {
        // ...
    }
}

oppure

root@kitploit:~
// Qualificazione esplicita (più verbosa ma molto chiara)
MyLib::Foo::Foo() {
    // ...
}

2. Posiziona le API interne/private in uno spazio dei nomi annidato

Le API pubbliche dovrebbero risiedere nello spazio dei nomi principale. Tutto ciò che non è destinato agli utenti finali dovrebbe essere nascosto in uno spazio dei nomi annidato come detail o impl.

Convenzioni comuni:

root@kitploit:~
namespace MyLib {
    namespace detail {           // molto usato
        // classi interne, funzioni, ecc.
    }
}

oppure

root@kitploit:~
namespace MyLib::impl {          // più corto, anch'esso comune
    // dettagli interni di implementazione
}

C++17 e successivi supportano definizioni di spazi dei nomi annidati inline, che sono più pulite:

root@kitploit:~
namespace MyLib::detail {
    class InternalHelper { /* ... */ };
}

3. Converti dati statici a livello di file in membri di classe static inline

Le variabili static a livello di file definite nei file .cpp diventano problematiche in un mondo solo header (definizioni multiple, violazioni ODR).

Soluzione moderna (C++17+):

root@kitploit:~
// Prima (in .cpp)
namespace MyLib {
    static int s_counter = 0;

    int next_id() {
        return ++s_counter;
    }
}
root@kitploit:~
// Dopo (sicuro per header)
namespace MyLib::detail {
    struct Globals {
        static inline int counter = 0;
    };
}

inline int MyLib::next_id() {
    return ++detail::Globals::counter;
}

La variabile static inline garantisce di avere una singola definizione anche se inclusa più volte.

4. Marca le funzioni definite al di fuori dei corpi di classe come inline

Qualsiasi funzione, funzione membro, costruttore o distruttore il cui corpo appare nell'header (ma non all'interno della definizione di classe) deve essere marcata inline per evitare violazioni della regola di definizione unica (ODR).

Poiché molti script di amalgama sono puramente testuali e non analizzano la semantica C++, una convenzione comune è usare una macro segnaposto (ad es. inline_t) durante lo sviluppo:

root@kitploit:~
// MyLib.h (o header comune)
#define inline_t   /* vuoto durante le build normali */

// MyLib.cpp (durante lo sviluppo)
namespace MyLib::detail {
    inline_t void Helper::do_work() {
        // implementazione
    }
}

Durante l'amalgama, lo strumento sostituisce inline_t con inline:

root@kitploit:~
// Dopo amalgama / trasformazione
inline void MyLib::detail::Helper::do_work() {
    // ...
}

Puoi scegliere qualsiasi nome di macro preferisci (ad es. MYLIB_INLINE, INLINE_IMP, ecc.) e configurare di conseguenza il tuo script di amalgama.

Nota: Strumenti come quom possono automatizzare parzialmente questo processo comprendendo le semantiche di inclusione C++ e gestendo correttamente le definizioni di funzione durante l'amalgama, riducendo la necessità di marcatori inline manuali in molti casi.

Riepilogo — Le quattro regole chiave

  1. Mai scrivere using namespace … a livello di namespace/file nei file di implementazione.
  2. Mettere tutti i simboli interni/non pubblici in uno spazio dei nomi annidato (detail / impl).
  3. Sostituire i dati static a livello di file con membri static inline di una struct/classe.
  4. Marcare i corpi di funzione fuori linea con una macro marcatore inline (sostituita durante l'amalgama).

Seguire queste quattro pratiche rende la transizione a una distribuzione singolo header molto più fluida e molto meno soggetta a errori — anche quando si utilizzano strumenti di amalgama puramente testuali.

Crediti

  • Godbolt per il prototipo
  • Manuale Intel x86-64 manuale
  • Defuse.ca per verificare gli output
  • Geek ABC reference
  • mazegen/x86reference per il database XML delle istruzioni

Riconoscimenti

Questo progetto è basato su cx_assembler di Midi12. La libreria originale ha fornito le basi per la codifica di assembly x86 in fase di compilazione in C++.

Scarica lo strumento
CategoriaIstruzioni
ALUADD, ADC, SUB, SBB, AND, OR, XOR, CMP, TEST
UnarieINC, DEC, NEG, NOT
Moltiplicazione/DivisioneMUL, IMUL (forme 1/2/3 operandi), DIV, IDIV
Movimento datiMOV, MOVABS, MOVZX, MOVSX, MOVSXD, LEA, XCHG, PUSH, POP
Shift/RotazioneSHL, SHR, SAL, SAR, ROL, ROR, RCL, RCR
Flusso di controlloJMP, CALL, RET, RETF
Salti condizionatiJZ/JE, JNZ/JNE, JB/JC, JNB/JNC, JBE/JNA, JNBE/JA, JL, JNL, JLE, JNLE, JO, JNO, JS, JNS, JP, JNP (offset a 8 e 32 bit)
Mosse condizionateCMOVA, CMOVAE, CMOVB, CMOVBE, CMOVE, CMOVG, CMOVGE, CMOVL, CMOVLE, CMOVNE, CMOVNO, CMOVNP, CMOVNS, CMOVO, CMOVP, CMOVS
Operazioni bitBT, BTC, BTR, BTS
Scansione/conteggio bitBSF, BSR, POPCNT, LZCNT, TZCNT, BSWAP
Operazioni stringheMOVSB/W/D/Q, CMPSB/W/D/Q, LODSB/W/D/Q, STOSB/W/D/Q, SCASB/W/D/Q (con prefissi REP/REPE/REPNE)
SistemaSYSCALL, SYSENTER, SYSEXIT, INT, INT3, IRET/D/Q, CLI, STI, HLT, CPUID, RDTSC, RDTSCP
VarieNOP, UD2
StrumentoScopoInstallazione
uvGestore pacchetti/progetti Pythoncurl -LsSf https://astral.sh/uv/install.sh | sh
quomAmalgama singolo headeruv tool install quom
CMake 3.19+Sistema di buildcmake.org
Compilatore C++20GCC 11+, Clang 14+, MSVC 2022+-