2 pontos por GN⁺ 2024-03-18 | 1 comentários | Compartilhar no WhatsApp
  • LLM4Decompile é um projeto open source de modelo de linguagem de grande porte que reverte binários Linux x86_64, nos níveis de otimização GCC O0~O3, para código-fonte C legível por humanos
  • A abordagem converte primeiro o binário em assembly com Objdump, e depois o LLM o descompila para código C; também há a linha LLM4Decompile-Ref, que refina o pseudocódigo gerado pelo Ghidra
  • Os modelos são disponibilizados em tamanhos de 1.3B a 22B, e o llm4decompile-9b-v2 registrou taxa de reexecução de 64.9% no benchmark Decompile
  • A métrica de avaliação é a taxa de reexecução, que verifica se o código descompilado executa corretamente ao passar em testes predefinidos; os benchmarks usados são 164 funções C do HumanEval-Decompile e 2.621 funções do ExeBench
  • Em 2025, o projeto lançou decompile-bench e SK²Decompile, e segue em expansão com suporte a mais arquiteturas, configurações e integração com ferramentas de descompilação

Objetivo e escopo de suporte do LLM4Decompile

  • LLM4Decompile é um projeto open source de modelo de linguagem de grande porte especializado em descompilação
  • A versão atual descompila binários Linux x86_64 para código-fonte C legível por humanos na faixa de otimização GCC O0~O3
  • O projeto está sendo expandido para oferecer suporte a arquiteturas e configurações mais amplas
  • Há duas formas principais de uso
    • LLM4Decompile-End: família de modelos que descompila o binário diretamente
    • LLM4Decompile-Ref: família de modelos que refina com LLM o pseudocódigo descompilado pelo Ghidra

Fluxo de treinamento e avaliação da descompilação

  • O processo de compilação começa no código-fonte C e passa por pré-processamento, compilação, montagem e linkedição até gerar o executável
  • A descompilação segue esse processo ao contrário, convertendo novamente o código binário em arquivo-fonte
  • Como o LLM não consegue processar diretamente os dados binários, o binário precisa primeiro ser desmontado para linguagem assembly com Objdump
  • O README explica que o binário e o ASM desmontado são mutuamente conversíveis, por isso são tratados como equivalentes
  • No treinamento, calcula-se a perda entre o código descompilado e o código-fonte original, e na avaliação a funcionalidade é verificada pelo sucesso nas asserções de teste

Métrica de avaliação e benchmarks

  • A métrica central é Re-executability
    • Verifica se o código descompilado executa corretamente
    • Avalia se ele passa em todos os casos de teste predefinidos
  • HumanEval-Decompile é um conjunto de 164 funções C que dependem apenas da biblioteca padrão de C
  • ExeBench é um conjunto de 2.621 funções extraídas de projetos reais
    • Inclui funções definidas pelo usuário, structs e macros

Modelos públicos e desempenho

  • O LLM4Decompile inclui modelos com 1.3B~33B parâmetros, e eles são disponibilizados no Hugging Face
  • As taxas de reexecução dos principais modelos são as seguintes
  • A linha V1.5 foi treinada com um dataset maior de 15B tokens e comprimento máximo de 4.096 tokens, e afirma ter obtido melhora de desempenho superior a 100% em relação aos modelos anteriores
  • A linha V2 é baseada em Ghidra e foi treinada com 2B tokens para refinar o pseudocódigo decompilado gerado pelo Ghidra
  • O 22B-V2 apresentou desempenho adicional 40.1% superior ao 6.7B-V1.5, segundo o projeto

Itens divulgados recentemente

  • Em 4 de outubro de 2025, foi lançado o SK²Decompile
    • A etapa 1, Structure Recovery, ou etapa Skeleton, converte o binário ou o pseudocódigo em uma representação intermediária ofuscada
    • A etapa 2, Identifier Naming, ou etapa Skin, gera código-fonte legível por humanos com identificadores significativos
    • Links dos modelos: sk2decompile-struct-6.7b, sk2decompile-ident-6.7
  • Em 20 de maio de 2025, foi lançado o decompile-bench
    • Inclui 2 milhões de pares função binária-código-fonte para treinamento
    • Inclui 70 mil pares de funções para avaliação
    • Os detalhes estão na pasta decompile-bench
  • Em 17 de outubro de 2024, foi lançado o decompile-ghidra-100k
    • Inclui 100.000 amostras de treinamento no total, com 25.000 para cada nível de otimização
    • Fornece um script de treinamento que roda em cerca de 3,5 horas em uma única GPU A100 40G
    • O custo de reprodução rápida é inferior a 20 dólares no total, e alcança taxa de reexecução de 0.26
  • Em 23 de setembro de 2024, foi lançado o LLM4Decompile-9B-v2
    • Foi ajustado com fine-tuning a partir do Yi-Coder-9B
    • Alcançou 0.6494 de taxa de reexecução no benchmark Decompile

Fluxo de uso

  • O início rápido consiste em clonar o repositório, criar um ambiente Conda e instalar o requirements.txt
  • Na etapa de pré-processamento, o código C é compilado em binário com GCC e, em seguida, objdump -d é usado para extrair as instruções em assembly
  • O nome da função deve ser alterado de func0 no exemplo para o nome da função que se deseja descompilar
  • O assembly de entrada deve seguir o formato abaixo
    • <FUNCTION_NAME>:
    • várias linhas de instruções em assembly na sequência
  • Na etapa de descompilação, o modelo do Hugging Face é carregado com AutoTokenizer e AutoModelForCausalLM do transformers, gerando código C a partir do prompt em assembly
  • Também é possível usar Docker
    • Após construir a imagem, o contêiner é executado com opção de GPU
    • Há um fluxo que executa demo.py no diretório ghidra

Formato dos dados HumanEval-Decompile

  • Os dados do HumanEval-Decompile são armazenados em formato de lista JSON em llm4decompile/decompile-eval/decompile-eval-executable-gcc-obj.json
  • O número de amostras é 164*4, resultado de 164 funções multiplicadas pelos níveis de otimização O0, O1, O2 e O3
  • Cada amostra possui 5 chaves
    • task_id: ID do problema
    • type: etapa de otimização, uma entre O0, O1, O2 e O3
    • c_func: resposta C do problema HumanEval
    • c_test: asserção de teste em C
    • input_asm_prompt: instruções em assembly e prompt
  • O script de avaliação está na pasta evaluation

Itens em andamento e licença

  • Os itens em andamento incluem datasets de treinamento maiores e processos de curadoria, suporte a linguagens, plataformas e configurações populares, suporte a executáveis e integração com ferramentas de descompilação como Ghidra e Rizin
  • Datasets de treinamento maiores e suporte a executáveis são marcados como itens concluídos em 13 de maio de 2024
  • O repositório de código é licenciado sob MIT License e DeepSeek License
  • O artigo está em arXiv:2403.05286, e o projeto também fornece materiais no Colab e no YouTube

1 comentários

 
GN⁺ 2024-03-18
Opiniões no Hacker News
  • É uma ideia interessante, mas fico curioso para saber se os resultados seriam confiáveis.
    Ao recompilar, pode sair um código de máquina diferente, então fica difícil identificar alucinações; preocupa especialmente a possibilidade de falhar silenciosamente em novas estruturas que podem ser o ponto central do código.
    Fico curioso se há uma forma de, ao executar em modo generativo, o LLM também informar o grau de confiança em determinados trechos; no fim, parece que ainda seria necessária uma verificação humana.

    • Por isso a conversão de ida e volta é importante.
      Depois de decompilar o binário para código-fonte e recompilá-lo de volta para binário, o binário original deveria ser produzido; basta repetir até que a perda caia para um nível aceitável.
      Aprendizado por reforço se encaixa muito bem nesse tipo de problema e, na prática, é conhecido por ser anormalmente eficaz em casos desse tipo.
    • LLMs são probabilísticos por natureza, então funcionam razoavelmente bem em áreas não precisas, como processamento de linguagem natural, mas usá-los para decompilação ou desmontagem, pessoalmente, me parece algo próximo de “escolher a ferramenta errada”.
      Pode até ser um experimento para explorar o meme comum hoje em dia de “é só usar LLM”, mas a objeção maior é que decompiladores existentes já fazem isso melhor com muito menos computação.
    • Dá para usar uma ferramenta de verificação formal que recebe a entrada, a saída e uma prova formal de que a entrada corresponde semanticamente à saída, e fazer o LLM gerar essa prova junto com a saída.
      Depois, a ferramenta de verificação pode confirmar se o resultado está correto de acordo com a prova fornecida pelo LLM.
      Claro que construir e treinar um LLM capaz de produzir esse tipo de prova seria um problema ainda maior, mas poderia ser uma forma segura de detectar alucinações.
    • Também dá para usar fuzzing diferencial.
    • Mesmo que não seja totalmente confiável, ao modificar um binário, normalmente basta alterar algumas funções.
      Portanto, só é preciso recompilar essas poucas funções.
  • Se você souber quem desenvolveu a aplicação, seria interessante ver se dá para treinar um módulo de decompilação usando o código antigo dessas pessoas como dados de treinamento.
    Por exemplo, Super Mario 64 e Zelda 64 já foram totalmente decompilados, e outros jogos de N64 estão em andamento; então fico curioso se seria possível mapear os desenvolvedores que participaram dos dois jogos, até estimar quem criou quais módulos, e usar isso na decompilação de outros jogos.
    Se isso ficar realmente bom, dá até para sonhar com uma vida em que todos os blobs binários dentro do PC sejam decifrados, drivers sejam abertos e até o sistema operacional seja escancarado.
    Também dá para imaginar não se contentar com Linux, ressuscitar o Windows XP, fazer backport de segurança moderna e compatibilidade com apps, e deixar o Windows 11 da Microsoft como está.

    • Decompiladores já existem e têm bom desempenho.
      Se um LLM conseguir fazer a mesma coisa que um decompilador existente, os advogados provavelmente verão isso como um procedimento equivalente.
      O problema central não é técnico, mas jurídico e político.
    • Na minha monografia, tratei de um tema parecido; havia pesquisas mostrando que, sob certas condições, é possível treinar um classificador de identificação de autor capaz de adivinhar quem escreveu um programa olhando apenas para o binário compilado.
      Não sei bem de casos em que isso tenha sido usado de forma útil, mas é interessante que o estilo de programação individual permaneça mesmo depois do processo de compilação, permitindo distinguir programas compilados de pessoas diferentes.
    • Não acho que seja possível identificar o código realmente escrito em si.
      O resultado seria muito parecido com o original, mas muitos elementos de estilo de código desapareceriam, e o estilo que parecesse restar provavelmente seria, em grande parte, algo próximo de alucinação.
  • Como é fácil criar, a partir de código C público, um grande conjunto de dados de pares entrada/saída, este é um caso de uso muito bom para fine-tuning de LLM.

    • Usar um LLM de programação, por exemplo um modelo como o DeepSeek, para gerar muito código C, verificar se compila e usar isso como dados sintéticos de treinamento também parece bastante vantajoso nesse contexto.
      Normalmente, a qualidade de dados sintéticos de treinamento é uma grande preocupação, mas aqui o ponto central é o fato de o código compilar.
  • Se li corretamente os números de reexecutabilidade na figura de resultados, a ideia é excelente, mas na prática parece não funcionar bem.
    https://raw.githubusercontent.com/albertan017/LLM4Decompile/...
    Complementando: reexecutabilidade é a métrica central para medir a correção semântica.
    Ela recompila o resultado da decompilação e executa casos de teste para avaliar se a lógica e o comportamento do programa foram preservados; recompilabilidade e reexecutabilidade indicam, respectivamente, recuperação sintática e preservação semântica.

  • Este problema é interessante em pelo menos dois aspectos.
    Primeiro, um decompilador ideal poderia enfraquecer o significado de código-fonte proprietário.
    Segundo, há muito código C público, então é fácil criar conjuntos de dados pareados de assembly e código-fonte, com vários níveis de otimização, compiladores e plataformas.
    Ainda assim, fico curioso sobre por que os autores fizeram fine-tuning do DeepSeek-Coder.
    Também me pergunto se seria possível treinar um LLM do zero com um conjunto de dados semelhante, qual tamanho seria necessário e se ele poderia rodar localmente.

    • A maior parte do código proprietário roda atrás de firewalls, então não seria muito afetada por esse tipo de abordagem.
      Mesmo que a tarefa desejada não seja muito próxima do modelo inicial, quase sempre é melhor começar de um modelo pré-treinado do que de uma inicialização aleatória.
    • Um decompilador ideal não existe.
      Como compiladores perdem informação, em certo sentido ele jamais poderia existir; e mesmo olhando pela perspectiva mais generosa de “entendimento de alto nível do código resultante”, isso é um problema de nível AGI na área de segurança computacional.
      Ninguém chegou nem perto disso ainda.
    • Treinar um modelo de linguagem do zero exige muitos dados.
      O Llama2 foi desenvolvido com 2 trilhões de tokens, mas este conjunto de dados fica em torno de 4 bilhões de tokens.
      Também não é simples decidir o tamanho adequado do modelo; nos experimentos, o modelo de 7 bilhões de parâmetros mostrou 21% de executabilidade, enquanto o de 1 bilhão de parâmetros ficou em apenas 10%.
      Porém, a recompilabilidade dos dois é bastante parecida.
      O modelo de 1 bilhão de parâmetros precisa de pelo menos 2 GB de memória de GPU, viável na maioria das GPUs; o de 7 bilhões precisa de 14 GB, adequado para a linha 3090/4090.
      Para o modelo de 33 bilhões, uma A100 de 80 GB é a opção em placa única; tecnicamente talvez fosse possível em um MacBook, mas você provavelmente não ia querer usá-lo assim.
    • Imagino que seja por causa da diferença entre custo de treinamento e custo de fine-tuning.
      Também pode ser um ponto de partida para validar a ideia.
  • Está sendo criado um descompilador baseado em LLM para bytecode Python: https://github.com/kukas/deepcompyle
    Parece que não há muita gente trabalhando nessa direção de pesquisa, mas acho que ela pode ser bem interessante, especialmente agora que contextos de atenção longos estão se tornando possíveis
    Se alguém conhecer uma equipe que lide com essa área, há interesse em colaborar

    • Fico curioso se há alguma vantagem em usar LLM para bytecode Python
      Pela minha experiência, o bytecode Python é de nível alto o bastante para ser convertido diretamente em código-fonte
    • Fico curioso por que Python
      Python tem um grande ecossistema de bibliotecas open source, mas não vejo como algo muito usado em software distribuído em forma binária
    • Existe o PyLingual, mas infelizmente não é open source
      Também não está claro se é baseado em LLM
    • O trabalho de descompilação parece ser mais voltado para C
      Não parece haver muitos projetos Python compilados para binário
  • Eu estava planejando tentar fazer algo assim
    Em algum momento alguém vai destravar um pipeline de entrada binária → saída de bom código-fonte, mas acho que ainda vai levar alguns anos
    Digo isso porque não parece haver uma grande quantia de dinheiro esperando no fim desse problema, embora eu possa estar errado
    Uma boa abordagem provisória seria criar um pipeline de descompilação que rode o Ghidra em modo headless e combine a precisão sintática rígida do descompilador com a capacidade intuitiva dos LLMs
    Como no AlphaGeometry, o descompilador e o LLM precisam compensar as fraquezas um do outro: https://deepmind.google/discover/blog/alphageometry-an-olymp...
    Também seria necessário usar algo como AICI como cola para orquestrar a geração de código-fonte C: https://github.com/microsoft/aici
    Em vez de usar os pesos do LLM para gerar código-fonte C gramaticalmente correto, seria melhor fazê-lo pensar em nomes de variáveis, padrões de snippets e escolhas arquiteturais, deixando ferramentas como Ghidra ou LLVM cuidarem do restante
    É um comentário de poltrona de um ex-aluno de pós-graduação, meio no estilo hand-waving, mas é ótimo que esses pesquisadores tenham entrado nisso, e o fato de os autores mencionarem integração com Ghidra em trabalhos futuros sugere que a direção parece correta

  • É interessante que o modelo de 6 bilhões se saia melhor que o modelo de 33 bilhões
    Fico curioso se isso significa que o modelo de 33 bilhões precisa de mais dados de treinamento
    Comparando algo pré-treinado com cerca de 1 milhão de programas em C com o DeepSeek-Coder, treinado em trilhões de tokens, há uma diferença de várias ordens de magnitude na quantidade de dados
    Também fico curioso sobre como ele se compara a soluções que não usam LLM

    • Esse padrão já vem aparecendo em LLMs há algum tempo
      A maioria dos LLMs é bastante subtreinada, e os modelos de 7 bilhões são, entre os modelos populares, alguns dos menos subtreinados, por isso se espalharam bastante na comunidade de fine-tuning de LLMs
    • Treinar um modelo de 33 bilhões não é fácil
      No fine-tuning ingênuo, em que se faz apenas fine-tuning simples seguindo o método padrão, treinar modelos grandes é complicado, e não só a quantidade de dados, mas também fatores como limpeza dos dados, taxa de aprendizado e decaimento afetam o desempenho final
    • Tenho dúvidas se dá para comparar diretamente cerca de 1 milhão de programas em C com 2 trilhões de tokens dessa forma
      Para isso, seria preciso assumir que o tamanho médio desses programas em C é várias ordens de magnitude menor que 2 milhões de tokens; na prática isso pode até ser verdade, mas soa como uma suposição bastante otimista
  • Fico curioso se, caso tenha sucesso, isso equivaleria a replicar 1:1 o código de máquina do compilador
    Nesse caso, significaria que o código completo pode existir como uma distribuição de probabilidade dentro do espaço latente
    Ou, mais provavelmente, pode ser uma forma de apenas replicar a lógica e depois traduzi-la para a linguagem-alvo
    Binários que exigem entradas não determinísticas na compilação, como chaves ou hashes, provavelmente quebrariam
    É realmente interessante

  • É surpreendente que o GPT-4 ainda se saia bastante bem na comparação
    Ele gera código compilável muito melhor do que esse modelo, mas tem menor precisão ao reproduzir código com comportamento correto
    Ainda assim, é bem impressionante

    • O GPT-4 é muito impressionante, mesmo não sendo um modelo treinado diretamente para descompilação
      Estamos melhorando o modelo, então continue acompanhando as atualizações
    • Seria impressionante se essa abordagem fosse tão boa em C++ quanto em C, mas aqui não é o caso