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
copy-fail-c — Portabilidade multiplataforma em C do Copy Fail Linux LPE (CVE-2026-31431). Divulgado em 2026-04-29 por Theori / Xint. | Kitploit
Ferramentas/GitHubGitHub/tgies/copy-fail-c
Escalada de PrivilégiosFrameworks de ExploraçãoAnálise de VulnerabilidadesExploraçãoPapers e PesquisaAprendizado e EducaçãoDesenvolvimento de PayloadsExploração de Binários
GitHubtgies/copy-fail-c

copy-fail-c

Portabilidade multiplataforma em C do Copy Fail Linux LPE (CVE-2026-31431). Divulgado em 2026-04-29 por Theori / Xint.

Ver Repositório
440121há 1 mêsRevisado 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

Copy Fail (CVE-2026-31431) - C port

English (en) ∙ 日本語 (ja) ∙ 简体中文 (zh-cn) ∙ 한국어 (ko) ∙ Русский (ru)

Uma reimplementação em C multiplataforma do LPE (Escalada de Privilégio Local) do Linux Copy Fail (CVE-2026-31431), divulgado em 2026-04-29 por Theori / Xint. Veja o writeup canônico em copy.fail para a descrição completa da vulnerabilidade, cronograma e processo de descoberta da Theori.

O proof-of-concept lançado publicamente é um script Python de 732 bytes. Esta porta em C demonstra que o mesmo exploit pode ser expresso como C portátil compilável para qualquer arquitetura que o nolibc suporta, sem blobs hex por arquitetura ou assembly inline na própria fonte do projeto.

Autor desta porta: Tony Gies [email protected]. Descoberta e divulgação original: Theori / Xint.

Repository layout

root@kitploit:~
copy-fail-c/
├── exploit.c           o dropper (variante de mutação binária)
├── exploit-passwd.c    o dropper (variante de inversão de UID do /etc/passwd)
├── vulnerable.c        verificador de vulnerabilidade não destrutivo
├── payload.c           o corpo que é dropado (setgid+setuid+execve sh)
├── utils.c, utils.h    primitiva de mutação de cache de página compartilhada AF_ALG/splice
├── Makefile            orquestração de compilação
├── nolibc/             fornecido de torvalds/linux tools/include/nolibc
└── README.md           este arquivo

Após make:

root@kitploit:~
├── payload             tiny static ELF, embedded into the dropper as bytes
├── payload.o           payload wrapped as a relocatable .o by `ld -r -b binary`
├── exploit             dropper, variante de mutação binária
├── exploit-passwd      dropper, variante de inversão de UID do /etc/passwd
└── vulnerable          verificador de vulnerabilidade não destrutivo

exploit.c abre o binário alvo como somente leitura, então para cada janela de 4 bytes do payload embutido executa uma AEAD-decrypt falsa através do AF_ALG cuja entrada de ciphertext é fornecida via splice() a partir das páginas de cache de página do alvo. A otimização in-place do template authencesn trata as páginas de origem spliceadas tanto como entrada de ciphertext quanto como destino de plaintext, então o decrypt (com falha) já sobrescreveu a página de cache de página no momento em que a verificação de autenticação rejeita a requisição. Após 4 * N iterações a imagem em cache do alvo foi substituída byte a byte pelo payload. Executar execve() no alvo carrega as páginas mutadas; o inode no disco ainda é setuid root, então o kernel concede credenciais de root e executa o payload.

payload.c é C portátil simples: setgid(0); setuid(0); execve("/bin/sh", ...). nolibc fornece o _start, a maquinaria de syscall e o malabarismo de registradores por arquitetura.

Uma segunda variante, exploit-passwd.c, muta quatro bytes do cache de página do /etc/passwd em vez da imagem de um binário setuid. Ela não precisa de payload embutido e funciona em sistemas onde a rota de mutação binária está bloqueada, mas sua superfície de cashout é muito mais estreita.

vulnerable.c não é um exploit. Ele cria um testfile local contendo a string init, então executa a mesma primitiva patch_chunk() contra o cache de página do próprio arquivo para sobrescrever os bytes com vulnerable. Se o conteúdo lido de volta corresponder, o kernel em execução está na janela do CVE-2026-31431. O inode no disco nunca é modificado; testfile é removido na saída; a mutação do cache de página evapora com ele. Executa sem privilégios. Sai com 100 se vulnerável, 0 se a primitiva executou mas a mutação não ocorreu, 2 se a família de socket AF_ALG ou o template authencesn estiver indisponível, então o estado de patch não pode ser determinado, e 1 para outros erros em tempo de execução.

Build

Padrão (nativo da arquitetura do host):

root@kitploit:~
make

Compilação cruzada para aarch64 (ou qualquer outra arquitetura Linux para a qual um cross-toolchain está instalado):

root@kitploit:~
make CC=aarch64-linux-gnu-gcc LD=aarch64-linux-gnu-ld

Arquiteturas suportadas pelo nolibc fornecido (de acordo com upstream): x86_64, i386, arm, aarch64, riscv32/64, mips, ppc, s390x, loongarch, m68k, sh, sparc. O nolibc despacha com base nas macros de arquitetura do compilador, então escolher o CC/LD correto é suficiente.

Necessário para compilar:

  • um compilador C (cc, gcc, ou qualquer variante cruzada)
  • um linker que suporta ld -r -b binary (ld do binutils e lld ambos suportam)
  • cabeçalhos UAPI do kernel fornecendo linux/if_alg.h e <asm/unistd.h> (Debian/Ubuntu: linux-libc-dev; variantes cruzadas: normalmente trazidas pelo pacote cross-toolchain)

Conjuntos de cabeçalhos anteriores ao Linux 5.6 são anteriores a __kernel_old_time_t e struct __kernel_old_timespec, que o nolibc fornecido usa. compat.h (forçadamente incluído na compilação do payload) os fornece quando ausentes, então um linux-libc-dev mais antigo ainda compila. É um no-op em cabeçalhos 5.6+.

Não há dependências de bibliotecas externas. O payload é compilado freestanding contra o nolibc; o dropper faz link contra a libc do host apenas para fprintf e perror.

Architectural choices

A few small toolchain features carry most of the weight in keeping the source portable and the payload small.

nolibc

nolibc/ é a substituição minúscula de libc apenas com cabeçalhos do kernel, fornecida de torvalds/linux tools/include/nolibc/. Ela fornece _start, uma macro syscall() portátil e wrappers inline de syscall, com as convenções de registradores por arquitetura codificadas em nolibc/arch-*.h. Compilar o payload com -nostdlib -static -ffreestanding -Inolibc produz um tiny static ELF que chama o kernel diretamente sem arrastar a inicialização do glibc, TLS init ou encanamento de stack-canary. Resultado após empacotamento e remoção de seções (ambos abaixo): ~720 bytes no x86_64, ~1.2 KB no aarch64, versus ~17 KB para o mesmo payload.c linkado contra musl-static ou ~700 KB contra glibc-static.

ld -r -b binary para embutir

O Makefile transforma o payload ELF construído em payload.o via ld -r -b binary -o payload.o payload. O linker emite os bytes de entrada textualmente como a seção de dados de um arquivo objeto relocável e sintetiza três símbolos a partir do nome do arquivo de entrada:

root@kitploit:~
_binary_payload_start    endereço do primeiro byte do payload
_binary_payload_end      endereço um byte após o último byte do payload
_binary_payload_size     símbolo absoluto cujo valor é o tamanho em bytes

exploit.c declara os dois primeiros como extern const unsigned char[] e calcula o tamanho como _binary_payload_end - _binary_payload_start.

-Wl,-N mais max-page-size apertado

O payload é linkado estaticamente com -Wl,-N -Wl,-z,max-page-size=0x10, que colapsa .text/.rodata/.data em um único segmento LOAD com alinhamento de arquivo de 16 bytes em vez do padrão de 4 KB por segmento alinhado à página do kernel. Isso produz um aviso "RWX permissions" do ld, que é apenas informacional – a proteção de memória em tempo de execução do payload não importa para seu programa de propósito único. Sem essa flag, o mesmo código linka para ~13 KB no x86_64 (principalmente preenchimento zero entre segmentos); com ela, ~1.3 KB antes da remoção do cabeçalho de seção abaixo.

Remoção de cabeçalhos de seção

Após o link, objcopy --strip-section-headers remove a tabela de cabeçalhos de seção do payload e .shstrtab. O carregador ELF do kernel mapeia um programa a partir de seus cabeçalhos de programa sozinhos, então esses bytes nunca são carregados em tempo de execução e, como payload é embutido textualmente, eles também inflam o drop e a contagem de iterações patch_chunk. Removê-los reduz o payload x86_64 de ~1.3 KB para 720 bytes (de 322 iterações de quatro bytes para 180). Duas flags de link diminuem o resto: -Wl,--build-id=none remove a nota de build-id, e -fcf-protection=none remove a nota CET x86 onde o compilador suporta.

O strip precisa de binutils >= 2.40. Compilações cruzadas passam o objcopy alvo via OBJCOPY= (ex.: OBJCOPY=aarch64-linux-gnu-objcopy); quando objcopy não consegue fazer, a compilação imprime uma nota e mantém um payload válido maior.

Variants and cashout viability

Este repositório fornece duas variantes de exploit que compartilham a primitiva de mutação de cache de página AF_ALG/splice, mas cashoutam em execução de root de forma diferente. Seus perfis de confiabilidade não são equivalentes, e a diferença importa ao raciocinar sobre modelos de ameaça do mundo real.

Variante de mutação binária (exploit)

Muta o cache de página de um binário setuid alvo com os bytes do payload embutido, então executa o binário. O kernel concede credenciais de root a partir do bit setuid intacto do binário no disco, carrega a imagem corrompida em memória e executa o payload.

Funciona onde quer que o atacante possa open(target, O_RDONLY) para qualquer binário setuid root no sistema. Mais ou menos derrotada por ambientes que limitam binários setuid a diretórios de leitura restrita e por designs de sistema sem setuid.

Variante de inversão de UID do /etc/passwd (exploit-passwd)

Muta quatro bytes do cache de página do /etc/passwd para definir o campo UID do usuário em execução para "0000". /etc/passwd é legível mundialmente em todo sistema Linux padrão, então a mutação é universal. Traduzi-la em execução de root depende de algum processo do lado root que resolve o usuário via getpwnam/getpwuid e age com base no uid resolvido sem validação cruzada. Muitos consumidores existem; muitos deles verificam defensivamente contra a visão do kernel do uid chamador ou contra a propriedade do arquivo no disco, quebrando o cashout.

Matrix de viabilidade de cashout

Pivoteando após falha do su

exploit-passwd executa su <user> após mutar, como o cashout mais simples possível. Isso funciona contra util-linux su mas falha contra shadow-utils su com "Cannot determine your user name." A mutação do cache de página ainda está em vigor nesse ponto, e pivotear para qualquer outro cashout (ex.: usando um daemon que resolve usuários via getpwnam sem verificação cruzada) é possível nesse ponto. Execute echo 3 > /proc/sys/vm/drop_caches como root para limpar o cache de página corrompido quando terminar os testes.

Affected kernels

root@kitploit:~
floor:    torvalds/linux 72548b093ee3   Agosto de 2017, v4.14
                                        (reestruturação do iov_iter do AF_ALG que
                                         introduziu a primitiva de escrita em página de arquivo
                                         via splice no scatterlist do AEAD)

ceiling:  torvalds/linux a664bf3d603d   Abril de 2026, mainline
                                        (reverte a otimização in-place do algif_aead de 2017;
                                         separa os scatterlists de origem e destino
                                         para que páginas de cache de página não possam mais
                                         ser um destino criptográfico gravável)

No meio: todo kernel de distribuição importante que não aplicou o backport da correção. Ubuntu, RHEL, SUSE, Amazon Linux e Debian foram todos confirmados vulneráveis em suas imagens de kernel de nuvem padrão no momento da divulgação. Backports em nível de distribuição começaram a ser lançados por volta de 2026-04-29 juntamente com a divulgação pública. Para verificar se um kernel alvo está na janela, verifique se a664bf3d603d (ou seu backport específico da distribuição) está presente no git log do kernel ou no changelog da distribuição.

Commercial support

Para revisão de segurança paga, trabalho de portabilidade personalizado ou avisos de segurança privados, entre em contato com o autor através de sua consultoria, Crash United, LLC.

Contato: [email protected] · https://crashunited.com
GitHub: @tgies · X/Twitter: @me_irl

License and credits

Descoberta e divulgação original do CVE-2026-31431: Theori / Xint. Writeup público: https://copy.fail/.

Esta porta em C: Tony Gies [email protected]

nolibc/: fornecido da árvore do kernel Linux, licenciado duplamente LGPL-2.1-ou-superior OU MIT (veja nolibc/nolibc.h e cabeçalhos SPDX individuais).

As fontes do dropper e payload neste repositório são lançadas sob os mesmos termos duplos LGPL-2.1-ou-superior OU MIT que a árvore nolibc da qual dependem, para manter o licenciamento trivialmente compatível para qualquer um que forneça este diretório inteiro em seu próprio trabalho.

O exploit e o payload são publicados para fins de pesquisa de segurança e detecção defensiva. O uso contra sistemas que você não possui ou para os quais não tem autorização explícita para testar é problema seu, não do autor.

Baixar ferramenta
CashoutConfiguração pré-root necessáriaNotas
Spawn de sessão WSL2NãoO setuid(getpwnam(default_user)->pw_uid) por sessão do WSL não faz validação. Funciona perfeitamente.
util-linux suNãoTratamento permissivo de identidade do chamador.
shadow-utils suSimA verificação de identidade do chamador getpwuid(getuid()) falha porque a mutação desmapeia o uid real.
sshd (StrictModes yes padrão)Sim (desabilitar StrictModes)StrictModes exige que o diretório home seja propriedade de root ou pw->pw_uid. A mutação faz pw_uid=0; o proprietário no disco permanece no uid original; incompatibilidade recusa autenticação.
Entrega local MTA (postfix, exim, etc.)VariávelDepende da validação de permissões de home do MDA. Testar por MTA.