結果 | ?型號| 快速入門 | HumanEval-反編譯 | ?引文| 紙| 科拉布 |
逆向工程:使用大型語言模型反編譯二進位程式碼
在編譯期間,預處理器處理原始程式碼 (SRC) 以消除註解並擴展巨集或包含。然後,清理後的程式碼被轉送到編譯器,編譯器將其轉換為彙編程式碼 (ASM)。此 ASM 由彙編器轉換為二進位代碼(0 和 1)。連結器透過連結函數呼叫來建立可執行檔來完成該過程。另一方面,反編譯涉及將二進位程式碼轉換回原始檔。受過文字訓練的法學碩士缺乏直接處理二進位資料的能力。因此,二進位檔案必須先被Objdump
反彙編為組合語言(ASM)。應該注意的是,二進制和反彙編的 ASM 是等效的,它們可以相互轉換,因此我們可以互換使用它們。最後,計算反編譯程式碼和原始程式碼之間的損失以指導訓練。為了評估反編譯程式碼 (SRC') 的質量,透過測試斷言(可重新執行性)對其功能進行測試。
我們的 LLM4Decompile 包含參數大小在 13 億到 330 億之間的模型,並且我們已在 Hugging Face 上提供這些模型。
模型 | 檢查站 | 尺寸 | 可重複執行性 | 筆記 |
---|---|---|---|---|
llm4decompile-1.3b-v1.5 | ?高頻鏈路 | 1.3B | 27.3% | 註3 |
llm4decompile-6.7b-v1.5 | ?高頻鏈路 | 6.7B | 45.4% | 註3 |
llm4decompile-1.3b-v2 | ?高頻鏈路 | 1.3B | 46.0% | 註4 |
llm4decompile-6.7b-v2 | ?高頻鏈路 | 6.7B | 52.7% | 註4 |
llm4decompile-9b-v2 | ?高頻鏈路 | 9B | 64.9% | 註4 |
llm4decompile-22b-v2 | ?高頻鏈路 | 22B | 63.6% | 註4 |
註3:V1.5系列使用更大的資料集(15B token)和最大token大小4,096進行訓練,與之前的模型相比,具有顯著的性能(超過100%的改進)。
註 4:V2 系列基於Ghidra構建,並在 20 億個代幣上進行訓練,以細化Ghidra 反編譯的偽代碼。檢查 ghidra 資料夾以獲取詳細資訊。
安裝:請使用下面的腳本安裝必要的環境。
git clone https://github.com/albertan017/LLM4Decompile.git
cd LLM4Decompile
conda create -n 'llm4decompile' python=3.9 -y
conda activate llm4decompile
pip install -r requirements.txt
以下是如何使用我們的模型的範例(針對 V1.5 進行了修訂。對於先前的模型,請在 HF 上查看相應的模型頁面)。注意:將“func0”替換為你要反編譯的函數名。
預處理:將C程式碼編譯為二進位,並將二進位反組譯為組譯指令。
import subprocess
import os
func_name = 'func0'
OPT = [ "O0" , "O1" , "O2" , "O3" ]
fileName = 'samples/sample' #'path/to/file'
for opt_state in OPT :
output_file = fileName + '_' + opt_state
input_file = fileName + '.c'
compile_command = f'gcc -o { output_file } .o { input_file } - { opt_state } -lm' #compile the code with GCC on Linux
subprocess . run ( compile_command , shell = True , check = True )
compile_command = f'objdump -d { output_file } .o > { output_file } .s' #disassemble the binary file into assembly instructions
subprocess . run ( compile_command , shell = True , check = True )
input_asm = ''
with open ( output_file + '.s' ) as f : #asm file
asm = f . read ()
if '<' + func_name + '>:' not in asm : #IMPORTANT replace func0 with the function name
raise ValueError ( "compile fails" )
asm = '<' + func_name + '>:' + asm . split ( '<' + func_name + '>:' )[ - 1 ]. split ( ' n n ' )[ 0 ] #IMPORTANT replace func0 with the function name
asm_clean = ""
asm_sp = asm . split ( " n " )
for tmp in asm_sp :
if len ( tmp . split ( " t " )) < 3 and '00' in tmp :
continue
idx = min (
len ( tmp . split ( " t " )) - 1 , 2
)
tmp_asm = " t " . join ( tmp . split ( " t " )[ idx :]) # remove the binary code
tmp_asm = tmp_asm . split ( "#" )[ 0 ]. strip () # remove the comments
asm_clean += tmp_asm + " n "
input_asm = asm_clean . strip ()
before = f"# This is the assembly code: n " #prompt
after = " n # What is the source code? n " #prompt
input_asm_prompt = before + input_asm . strip () + after
with open ( fileName + '_' + opt_state + '.asm' , 'w' , encoding = 'utf-8' ) as f :
f . write ( input_asm_prompt )
組裝說明應採用以下格式:
<FUNCTION_NAME>:n操作n操作n
典型的組裝指令可能如下所示:
<func0>:
endbr64
lea (%rdi,%rsi,1),%eax
retq
反編譯:使用LLM4Decompile將組譯指令翻譯成C:
from transformers import AutoTokenizer , AutoModelForCausalLM
import torch
model_path = 'LLM4Binary/llm4decompile-6.7b-v1.5' # V1.5 Model
tokenizer = AutoTokenizer . from_pretrained ( model_path )
model = AutoModelForCausalLM . from_pretrained ( model_path , torch_dtype = torch . bfloat16 ). cuda ()
with open ( fileName + '_' + OPT [ 0 ] + '.asm' , 'r' ) as f : #optimization level O0
asm_func = f . read ()
inputs = tokenizer ( asm_func , return_tensors = "pt" ). to ( model . device )
with torch . no_grad ():
outputs = model . generate ( ** inputs , max_new_tokens = 2048 ) ### max length to 4096, max new tokens should be below the range
c_func_decompile = tokenizer . decode ( outputs [ 0 ][ len ( inputs [ 0 ]): - 1 ])
with open ( fileName + '.c' , 'r' ) as f : #original file
func = f . read ()
print ( f'original function: n { func } ' ) # Note we only decompile one function, where the original file may contain multiple functions
print ( f'decompiled function: n { c_func_decompile } ' )
資料儲存在llm4decompile/decompile-eval/decompile-eval-executable-gcc-obj.json
中,使用 JSON 清單格式。有 164*4(O0、O1、O2、O3)個樣本,每個樣本有 5 個按鍵:
task_id
:表示問題的ID。type
:最佳化階段,是[O0, O1, O2, O3]之一。c_func
:HumanEval 問題的 C 解。c_test
:C 測試斷言。input_asm_prompt
:帶有提示的彙編指令,可以像我們的預處理範例一樣匯出。請檢查評估腳本。
此程式碼儲存庫已根據 MIT 和 DeepSeek 許可證獲得許可。
@misc{tan2024llm4decompile,
title={LLM4Decompile: Decompiling Binary Code with Large Language Models},
author={Hanzhuo Tan and Qi Luo and Jing Li and Yuqun Zhang},
year={2024},
eprint={2403.05286},
archivePrefix={arXiv},
primaryClass={cs.PL}
}