
Codificatore binario polimorfico per payload di sicurezza offensiva. Codifica shellcode con loop di feedback basato su LFSR, iniezione di istruzioni spazzatura e offuscamento a iterazioni multiple per eludere il rilevamento statico.
SGN è un codificatore binario polimorfo per scopi di sicurezza offensiva, come la generazione di payload binari staticamente non rilevabili. Utilizza un ciclo di feedback additivo per codificare le istruzioni binarie fornite, simile a LFSR. Questo progetto è la reimplementazione dell'originale Shikata ga nai in golang con molti miglioramenti.
[!WARNING]
Il progetto è stato recentemente portato in Rust. Questo porting mantiene il design e il comportamento originali, ma sostituisce l'assemblatore testuale keystone con l'assemblatore puro Rusticed-x86, quindi non ci sono dipendenze da librerie native — viene compilato con un semplicecargo build. Dai un'occhiata al branch sgn-go per la versione legacy in Go.
Per la comunità della sicurezza offensiva, l'implementazione originale del codificatore shikata ga nai è considerata il miglior codificatore di shellcode (fino ad ora). Ma nel corso degli anni i ricercatori di sicurezza hanno trovato diverse insidie per rilevare staticamente lo stub del decodificatore (lavoro correlato articolo FireEye). La motivazione principale di questo progetto è stata quella di creare un codificatore migliore che codifichi il binario fornito al punto da renderlo identico a dati completamente casuali e che non sia possibile rilevare la presenza di un decodificatore.
Finalmente shellcode x64 codificati correttamente!Chiave LFSR ridotta a 1 byteAnche lo stub decodificatore è codificato con uno schema pseudo-casualeLo stub si decodifica da solo SENZA usare alcuna condizione di ciclo!!Generatore casuale di istruzioni spazzatura aggiunto con keystoneNessun registro viene sovrascritto (preambolo opzionale, può ridurre il polimorfismo)Ogni passaggio di codifica:
--plain, crittografa lo stub stesso con un cifrario a schema casuale per esecuzione (XOR/ADD/SUB/ROL/ROR/NOT su DWORD) e antepone un decodificatore dello schema che si auto-localizza, così anche il decodificatore sembra dati casuali;--enc volte con seed freschi;cargo install sgn
Puoi anche ottenere i binari precompilati QUI.
Utilizzo
-h è abbastanza autoesplicativo, usa -v se vuoi vedere cosa succede dietro le quinte ( ͡° ͜ʖ ͡°)_/¯
__ _ __ __ _
___ / / (_) /_____ _/ /____ _ ___ ____ _ ___ ___ _(_)
(_-</ _ \/ / '_/ _ `/ __/ _ `/ / _ `/ _ `/ / _ \/ _ `/ /
/___/_//_/_/_/\_\\_,_/\__/\_,_/ \_, /\_,_/ /_//_/\_,_/_/
========[Author:-Ege-Balcı-]====/___/=======v2.0.2=========
┻━┻ ︵ヽ(`Д´)ノ︵ ┻━┻ (ノ ゜Д゜)ノ ︵ 仕方がない
sgn [OPZIONI]
Opzioni:
-i, --input <INPUT> Percorso del binario in input
-o, --out <OUT> Nome del binario codificato in output (default: <input>.sgn)
-a, --arch <ARCH> Architettura del binario (32/64) [default: 64]
-c, --enc <ENC> Numero di volte per codificare il binario [default: 1]
-M, --max <MAX> Byte massimi per blocco di istruzioni spazzatura [default: 50]
--plain Non codificare lo stub del decodificatore
--ascii Genera un payload completamente stampabile in ASCII (lento)
-S, --safe Preserva tutti i valori dei registri (nessuna sovrascrittura)
--badchars <BADCHARS> Evita questi byte, formato hex (es. \x00\x0a)
-v, --verbose Modalità verbosa
-h, --help Stampa aiuto
-V, --version Stampa versione
Esempio:
sgn -i shellcode.bin -o encoded.bin -a 64 --badchars '\x00\x0a\x0d'
L'immagine seguente è un diagramma di base del flusso di lavoro per il codificatore. Tieni presente che le dimensioni, le posizioni e l'ordine delle istruzioni spazzatura, dei decodificatori e dei decodificatori di schema cambieranno a ogni iterazione.
L'LFSR stesso è piuttosto potente in termini di spazio di probabilità. Per un polimorfismo ancora maggiore, le istruzioni spazzatura vengono aggiunte all'inizio del payload grezzo non codificato. L'immagine seguente mostra la matrice compagna del polinomio caratteristico dell'LFSR e, denotando il seme come vettore colonna, lo stato del registro nella configurazione di Fibonacci dopo k passi.
use sgn::Encoder;
let shellcode = std::fs::read("payload.bin")?;
let mut encoder = sgn::Encoder::new(64)?;
let encoded = encoder.encode(&shellcode)?;
println!("encoded {} bytes", encoded.len());
Vedi examples/encode_binary.rs.
cargo test
La suite include test unitari di andata e ritorno della cifratura più test di esecuzione reali:
lo shellcode x64 codificato viene mappato come eseguibile e eseguito in-process, mentre lo shellcode x86
viene eseguito tramite un harness helper cc -m32 (saltato automaticamente se non è presente una
toolchain a 32 bit). Entrambe le architetture vengono esercitate attraverso le modalità plain, schema,
multi-layer e safe-register, incluso un ciclo di stress randomizzato.
iced-x86 invece del
testo assembly di keystone; gli stub decodificatore sono stati ricostruiti attorno all'indirizzamento
RIP-relativo (x64) e a uno schema a due passi call/pop (x86).random_byte ora copre l'intero intervallo 0..=255 e il budget di dimensione
per la spazzatura (--max) viene applicato in modo coerente come limite per blocco.