- A equipe Crusaders of Rust encontrou um bug de use-after-free no escalonador de pacotes do Linux e desenvolveu um exploit
- Na competição Google kernelCTF, por causa da necessidade de uma solução rápida de PoW (Proof of Work), tentou otimizações de alto desempenho
- Com assembly próprio e otimização SIMD usando instruções AVX512IFMA, alcançou desempenho quase 7 vezes mais rápido que as implementações existentes em Python/GMP e Rust
- Ajustando minuciosamente princípio de funcionamento, operações modulares, gerenciamento de memória e uso de registradores, reduziu o tempo de processamento do PoW para 0,21 s
- Por fim, fez uma submissão bem-sucedida ao kernelCTF no menor tempo da história (3,6 s), após o que a política de PoW foi oficialmente abolida
Visão geral e objetivo
- Em maio de 2025, William Liu e Savy Dicanosa, da equipe Crusaders of Rust, encontraram uma vulnerabilidade de use-after-free no Linux e participaram da competição kernelCTF do Google
- Este texto trata do processo de otimização para resolver rapidamente a verificação de PoW (Proof of Work) e, assim, enviar a submissão antes de outras equipes globais em uma disputa com bounty limitado
Processo de submissão no kernelCTF e contexto competitivo
- O kernelCTF é uma competição em que equipes profissionais de segurança do mundo todo participam com tudo, automatizando submissões e otimizando o PoW por causa das grandes recompensas
- A cada janela de submissão (aberta a cada 2 semanas), apenas a equipe mais rápida recebe o prêmio
- Procedimento de submissão:
- conectar ao servidor no horário exato
- resolver o PoW, o que leva alguns segundos
- esperar o boot da VM
- executar o código de exploit e obter a flag
- enviar o formulário do Google
- Recentemente houve até um registro de envio da flag em 4,5 s, mas como só o PoW e o boot da VM já levavam 6,5 s, melhorar a velocidade de resolução do PoW era uma tarefa essencial
Análise do algoritmo de PoW (VDF-Sloth) e a primeira otimização
- O PoW do kernelCTF usa a sloth VDF, uma verifiable delay function baseada em operações sequenciais
- para um inteiro x de 1280 bits, repete operações de quadrado modular e inversão de bits
- Mesmo nas implementações existentes (Python + gmpy e Rust), paralelização em múltiplos núcleos não ajudava, e o GMP já estava suficientemente otimizado
- Ainda assim, aproveitando que a operação de módulo era baseada no número de Mersenne (2^1279-1), conseguiram melhorar o desempenho para 1,9~1,4 s com uma implementação manual de módulo em C++ mais rápida
A grande virada para AVX512 e a implementação ultrarrápida baseada em SIMD
- Depois disso, a atenção foi para a ISA AVX512 e, dentro dela, especialmente para AVX512IFMA (instruções de multiplicação e acumulação de 52 bits)
- O número de 1280 bits foi dividido em limbs de 52 bits para maximizar a aceleração por SIMD (25 limbs → uso de 4 registradores zmm)
- Repetiram ajustes de baixo nível como simetria da operação de quadrado modular, máscaras de acumulação, broadcast de memória, otimização de alocação de registradores e comparações sem branch
- Usando ASM (inline assembly), impediram spill/reload ineficiente de registradores por parte do compilador e, com otimizações de broadcast e masking, elevaram a velocidade final para 0,21 s
Automação da submissão do PoW e cenário real da competição
- Na submissão final, usaram um servidor Zen 5 no Google Cloud (região de Amsterdã) para minimizar também a latência de rede até o formulário do Google
- Com um programa de submissão automática (patch no POST do formulário do Google e otimizações com colaboração interna da equipe), conseguiram enviar a flag com sucesso em 3,6 s, o menor tempo já registrado
- A equipe do kernelCTF anunciou oficialmente o fim da política de PoW, encerrando a corrida por otimizações de PoW e permitindo a divulgação da técnica
Detalhes avançados de implementação
Otimização de operações modulares
- A operação módulo 2^1279-1 (primo) foi substituída por alguns shifts de bits e operações aritméticas básicas, alcançando uma operação modular muito mais rápida que a do GMP padrão
Squaring de bigint com base em AVX512IFMA
- Usando as instruções AVX512 de multiplicação e acumulação de 52 bits (
vpmadd52luq, vpmadd52huq), fizeram multiplicação e acumulação paralela de blocos de 8 limbs
- Como a estrutura tem 25 limbs, ela foi distribuída por 4 zmm, com uma lógica desenhada para minimizar masking e acumulações desnecessárias
Layout de dados e uso de registradores
- Resolveram gargalos de SIMD com unidades por offset, layout de dados em escada e reorganização entre registradores (
valignq, broadcast)
- Dobrar o número de acumuladores garantiu throughput máximo sem espera ociosa da unidade de multiplicação
- Até a propagação de carry (
carry propagation) foi executada apenas no mínimo necessário
Automação final da submissão e colaboração
- Distribuição de membros da equipe na madrugada para atingir a campanha, além de otimizações de localização de rede e execução do exploit
- Na submissão real, houve automação consistente do início ao fim: resolução do PoW, execução do exploit, inserção da flag e requisição POST ao Google Form
Conclusão e significado
- A otimização do PoW do kernelCTF exigiu um entendimento quase anatômico do hardware, do nível de bits até memória, registradores e CNN
- Com o fim da política de PoW, o foco da competição passou a ser apenas a velocidade pura de rede/exploit
- Este caso mostra o encontro entre hacking prático e computação de alto desempenho e sugere que, no futuro, o know-how de otimização de algoritmos e o código open source continuarão contribuindo para a comunidade de pesquisa
Referências e apêndice
- Todo o código do algoritmo de PoW e das funções de conversão (GMP <-> arranjo de 52 bits), além das operações modulares baseadas em SIMD e do código de tuning em ASM, foi publicado
- Embora seja um código “bruto”, desenvolvido intensivamente ao longo de cerca de 12 horas para uso real, ele foi aberto sob a licença GNU AGPL 3.0
- Dúvidas ou colaboração relacionada a VDF podem ser tratadas via Discord (@forevermilk)
1 comentários
Comentários no Hacker News
A equipe vencedora registrou 3,6 segundos, e o 2º lugar marcou 3,73 ou 3,74 segundos; fica a impressão de que o 2º colocado também fez otimização de PoW ou talvez tenha usado FPGA. Em comparação com envios antigos de FPGA que passavam de 4 segundos, teria sido bom se o autor tivesse mencionado que o resultado do 2º lugar nesta semana também pode ter sido um recorde histórico.
Fica a impressão de que este método é muito parecido com o usado em implementações de RSA otimizadas para AVX-512, porque o RSA também exige operações de exponenciação muito grandes. O artigo (https://dpitt.me/files/sime.pdf) trata da técnica de windowing e do fato de que o tamanho da janela pode ser ajustado arbitrariamente. Nas implementações de RSA com AVX-512, há ainda o detalhe de armazenar os resultados da multiplicação em uma tabela no intervalo [0..2^{window-size}) para usar o resultado em cada janela. Um exemplo real pode ser visto em rsaz-2k-avx512.pl no código do aws-lc.
Sobre a afirmação de que o AVX512 foi suportado em CPUs de consumo ao longo de várias gerações, a lembrança é de que, antes do Rocket Lake (11ª geração), o AVX512 só estava disponível em processadores entusiastas, Xeon e alguns modelos móveis. Depois da 12ª geração e da introdução de núcleos P/E, ele foi desativado e desapareceu em poucos meses. Fica a previsão de que, se a AMD tiver sucesso com AVX512, a Intel vai adotá-lo de novo; a pessoa comenta que usa um i9-11900.
Há dúvidas sobre a própria natureza da competição CTF: em vez de uma corrida pela velocidade do envio, seria melhor um modelo em que todas as equipes que enviassem a flag dentro de uma janela definida compartilhassem o prêmio.
Se entendi direito, trata-se de um proof of work de 4 segundos com pagamentos mensais; fica a curiosidade se realmente surgem tantos exploits por mês a ponto de haver essa competição acirrada.
É um desafio impressionante, mas a complexidade dos obstáculos para vencer e o clima meio absurdo chamam atenção; surge a comparação divertida com uma máquina de Rube Goldberg.
Para quem quiser saber mais sobre a parte de base-52 mencionada no texto, recomendam este post que esteve em alta hoje (https://news.ycombinator.com/item?id=44132673).
Comentário de que matemática é legal.
Apresentação do sloth, uma VDF (Verifiable Delay Function) usada no proof of work, que exige uma sequência longa de cálculos para provar a passagem do tempo, enquanto o resultado pode ser verificado rapidamente. Como o cálculo é serial, não dá para reduzir o tempo de execução usando vários núcleos. Surge a curiosidade sobre se essa área poderia se tornar um novo mercado para fabricantes de CPU. Também se propõe adicionar instruções dedicadas para as iterações do sloth e seus resultados, além de um recurso de hardware contra overclock, e se sugere a ideia de monitorar o uptime da CPU e assinar isso junto com o desafio. Isso se parece com um conceito de proof of stake em que a CPU continua sendo usada em produção, mas ao mesmo tempo prova a posse da CPU por n segundos.
Fica a dúvida de como a função em Python mostrada no blog é equivalente à implementação de PoW do Google; parece difícil de acompanhar.
exponent = (p + 1) // 4é igual a 2^1277. Para elevar um número a um expoente tão gigantesco, seria preciso fazer 1277 quadraturas, e a função em Python realmente implementa isso. Se o valor inicial é x, a cada quadratura a multiplicação dobra, e no final chega-se a 2^1277 delas; é esse o princípio explicado.