
Codificador binário polimórfico para payloads de segurança ofensiva. Codifica shellcode com loop de feedback baseado em LFSR, injeção de instruções de lixo e ofuscação de múltiplas iterações para evadir a detecção estática.
SGN é um codificador binário polimórfico para fins de segurança ofensiva, como gerar payloads binários estaticamente indetectáveis. Ele usa um loop de realimentação aditiva para codificar determinadas instruções binárias, similar ao LFSR. Este projeto é a reimplementação do Shikata ga nai original em golang, com muitas melhorias.
[!WARNING]
O projeto foi recentemente migrado para Rust. Esta migração mantém o design e o comportamento originais, mas substitui o montador de texto keystone pelo montador puro-Rust , portanto — a compilação é feita com um simples . Confira o branch para a versão legada em Go.
cargo buildPara a comunidade de segurança ofensiva, a implementação original do codificador shikata ga nai é considerada o melhor codificador de shellcode (até agora). Mas, ao longo dos anos, pesquisadores de segurança encontraram várias armadilhas na detecção estática do stub de decodificação (trabalho relacionado: artigo da FireEye). A principal motivação deste projeto foi criar um codificador melhor, que codifique o binário fornecido a ponto de ser idêntico a dados totalmente aleatórios e impossível de detectar a presença de um decodificador.
Finally properly encoded x64 shellcodes !LFSR key reduced to 1 byteDecoder stub is also encoded with a psudo random schemaStub decodes itself WITHOUT using any loop conditions !!Random garbage instruction generator added with keystoneNon of the registers are clobbered (optional preable, may reduce polimorphism)Cada passagem de codificação:
--plain seja usado, cifra o próprio stub com uma cifra
de esquema aleatória por execução (XOR/ADD/SUB/ROL/ROR/NOT sobre DWORDs) e prefixa um
decodificador de esquema autolocalizável, para que até o decodificador pareça dados aleatórios;--enc vezes com novas sementes;cargo install sgn
Você também pode obter os binários pré-compilados AQUI.
Uso
-h é bem autoexplicativo; use -v se quiser ver o que está acontecendo nos bastidores ( ͡° ͜ʖ ͡°)_/¯
__ _ __ __ _
___ / / (_) /_____ _/ /____ _ ___ ____ _ ___ ___ _(_)
(_-</ _ \/ / '_/ _ `/ __/ _ `/ / _ `/ _ `/ / _ \/ _ `/ /
/___/_//_/_/_/\_\\_,_/\__/\_,_/ \_, /\_,_/ /_//_/\_,_/_/
========[Author:-Ege-Balcı-]====/___/=======v2.0.2=========
┻━┻ ︵ヽ(`Д´)ノ︵ ┻━┻ (ノ ゜Д゜)ノ ︵ 仕方がない
sgn [OPTIONS]
Options:
-i, --input <INPUT> Input binary path
-o, --out <OUT> Encoded output binary name (default: <input>.sgn)
-a, --arch <ARCH> Binary architecture (32/64) [default: 64]
-c, --enc <ENC> Number of times to encode the binary [default: 1]
-M, --max <MAX> Maximum bytes per garbage block [default: 50]
--plain Do not encode the decoder stub
--ascii Generate a fully ASCII-printable payload (slow)
-S, --safe Preserve all register values (no clobber)
--badchars <BADCHARS> Avoid these bytes, hex format (e.g. \x00\x0a)
-v, --verbose Verbose mode
-h, --help Print help
-V, --version Print version
Exemplo:
sgn -i shellcode.bin -o encoded.bin -a 64 --badchars '\x00\x0a\x0d'
A imagem a seguir é um diagrama básico de fluxo de trabalho do codificador. Mas lembre-se de que os tamanhos, locais e ordens mudarão para instruções de lixo, decodificadores e decodificadores de esquema a cada iteração.
O próprio LFSR é bastante poderoso em termos de espaço de probabilidade. Para ainda mais polimorfismo, instruções de lixo são adicionadas no início do payload bruto não codificado. A imagem abaixo mostra a matriz companheira do polinômio característico do LFSR e, representando a semente como um vetor coluna, o estado do registrador na configuração de Fibonacci após k passos.
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());
Veja examples/encode_binary.rs.
cargo test
A suíte inclui testes unitários de cifragem/decifragem, além de testes de execução reais: shellcode x64 codificado é mapeado como executável e executado no processo, e shellcode x86 é executado por meio de um harness auxiliar cc -m32 (ignorado automaticamente se não houver toolchain de 32 bits). Ambas as arquiteturas são exercitadas nos modos plain, schema, multicamadas e registrador seguro, incluindo um loop de estresse aleatorizado.
iced-x86 em vez do texto de montagem do keystone; os stubs de decodificação foram reconstruídos em torno do endereçamento relativo a RIP (x64) e de um esquema de duas passagens call/pop (x86).random_byte agora cobre toda a faixa 0..=255, e o orçamento de tamanho do lixo (--max) é aplicado consistentemente como um limite por bloco.