LLM4Decompile Framework

repository·main·Indexed 27 days ago

https://github.com/albertan017/llm4decompile

An open-source large language model framework for reverse engineering, designed to decompile Linux x86_64 binaries into human-readable C source code. It includes V1.5 models for translating assembly instructions and V2 models (LLM4Decompile-Ref) for refining Ghidra pseudo-code. The framework provides tools for preprocessing C code, running evaluations via vLLM, and measuring performance using re-executability and edit similarity metrics.

Tokens
26.6K
Snippets
39
Records
63
Agent score
92%

What's inside LLM4Decompile

  1. Understand the Decompile-Eval evaluation methodology

    main

    Decompile-Eval evaluates the re-executability of decompilation systems rather than relying on N-gram or edit similarity (like BLEU or ES), which can be misleading.

    The evaluation process follows these steps:

    1. Compilation: The original C source code is compiled into a binary using the GCC compiler.
    2. Disassembly: The binary is disassembled into assembly code.
    3. Decompilation: The assembly code is fed into the decompilation system to reconstruct C source code.
    4. Execution Check: The regenerated C code is combined with the original assertions (c_test) to verify if it can successfully execute and pass all assertions.
  2. Install additional dependencies for SK²Decompile

    main

    Depending on which reward function you are using, you may need additional system and Python packages.

    For Structure Recovery (Compiler-based rewards)

    Requires gcc and psychec for compilability verification.

    For Identifier Naming (Embedding-based rewards)

    Requires tree-sitter and openai for semantic similarity calculations.

    # For compiler-based rewards (Structure Recovery)
    apt install gcc
    pip install psychec
    
    # For embedding-based rewards (Identifier Naming)
    pip install tree-sitter==0.24.0 tree-sitter-c==0.23.4 openai
  3. Run Phase 0: Data Preprocessing

    main

    Transform raw pseudo-code into normalized representations for training using the following steps in the Preprocess/ directory.

    1. Install Preprocessing Requirements:

    cd Preprocess
    pip install tree-sitter==0.24.0 tree-sitter-c==0.23.4 tqdm

    2. Execute Preprocessing Pipeline:

    • Normalize pseudo-code (R2I standard): python3 normalize_pseudo.py --input_json <input.json> --output_json <output.json> --key_name pseudo
    • Obfuscate source code to generate IR: python3 normalize_src_basedonpseudo.py --input_json <input.json> --output_json <output.json> --top 0 --pseudo pseudo_norm
    • Format codes with clang-format: python3 format.py --input <input.json> --output <output.json>
    • Infer types for obfuscated IR: python3 inf_type.py --input_json <input.json> --output_name <output_name> --generator ../psychec/psychecgen --solver ../psychec/psychecsolver-exe --split 2 --idx 0
    cd Preprocess
    # Requirements
    pip install tree-sitter==0.24.0 tree-sitter-c==0.23.4 tqdm
    
    # Step 1: Normalize pseudo-code according to R2I standard
    python3 normalize_pseudo.py --input_json exebench_c.json --output_json exebench_pseudonorm.json --key_name pseudo
    
    # Step 2: Obfuscate source code to generate IR
    python3 normalize_src_basedonpseudo.py --input_json exebench_pseudonorm.json --output_json exebench_norm_top0.json --top 0 --pseudo pseudo_norm
    
    # Step 3: Format codes with clang-format
    python3 format.py --input exebench_norm_top0.json --output exebench_format_top0.json
    
    # Step 4: Infer types for obfuscated IR (used for compiler-based rewards)
    python3 inf_type.py --input_json train_format_top0.json --output_name train_format_top0_type \
        --generator ../psychec/psychecgen --solver ../psychec/psychecsolver-exe --split 2 --idx 0
  4. Install Ghidra and Java-SDK-17 for LLM4Decompile-Ref

    main

    To use the V2 series models (LLM4Decompile-Ref), you must first install Ghidra and Java-SDK-17. The V2 models are designed to refine the pseudo-code output generated by Ghidra.

    1. Install Ghidra

    Download and unzip Ghidra into your current folder. On Ubuntu, you can use the following commands:

    cd LLM4Decompile/ghidra
    wget https://github.com/NationalSecurityAgency/ghidra/releases/download/Ghidra_11.0.3_build/ghidra_11.0.3_PUBLIC_20240410.zip
    unzip ghidra_11.0.3_PUBLIC_20240410.zip

    2. Install Java-SDK-17

    Ghidra 11 requires Java-SDK-17. On Ubuntu, install it using:

    apt-get update
    apt-get upgrade
    apt install openjdk-17-jdk openjdk-17-jre
    cd LLM4Decompile/ghidra
    wget https://github.com/NationalSecurityAgency/ghidra/releases/download/Ghidra_11.0.3_build/ghidra_11.0.3_PUBLIC_20240410.zip
    unzip ghidra_11.0.3_PUBLIC_20240410.zip
  5. Decompile binary using Ghidra Headless

    main

    Use Ghidra's headless analyzer to decompile a binary into pseudo-code. This process involves compiling C code into a binary, then running the headless analyzer with a post-script to extract the function's pseudo-code.

    Note: You must replace func0 in the script with the actual name of the function you wish to decompile.

    Required variables to configure in the script:

    • ghidra_path: Path to the headless analyzer (e.g., ./ghidra_11.0.3_PUBLIC/support/analyzeHeadless).
    • postscript: Path to your decompiler helper function (e.g., ./decompile.py).
    • project_path: Temporary folder for analysis.
    • func_path: Path to the C source code for compilation.
    • fileName: Base name for output files.
    import os
    import subprocess
    from tqdm import tqdm,trange
    
    OPT = ["O0", "O1", "O2", "O3"]
    timeout_duration = 10
    
    ghidra_path = "./ghidra_11.0.3_PUBLIC/support/analyzeHeadless"
    postscript = "./decompile.py"
    project_path = "."
    project_name = "tmp_ghidra_proj"
    func_path = "../samples/sample.c"
    fileName = "sample"
    
    # ... (rest of the subprocess and Ghidra execution logic) ...
            command = [
                ghidra_path,
                temp_dir,
                project_name,
                "-import", executable_path,
                "-postScript", postscript, output_path,
                "-deleteProject",
            ]
            result = subprocess.run(command, text=True, capture_output=True, check=True)
  6. Quick Start: Run BringUpBench Evaluation Only

    main

    If you only want to reproduce the evaluation step (Step 5) using pre-built data, follow these steps. You must have the Bringup-Bench source repository cloned locally.

    1. Clone the benchmark repository:
      git clone https://github.com/toddmaustin/bringup-bench.git
    2. Configure the environment paths in config.env by setting BENCH_REPO_ROOT to your local bringup-bench path.
    3. Run the evaluation script (e.g., for optimization level O0):
      python3 scripts/eval_infer_out.py data/infer_results/merged.O0.func_map.infer.jsonl
    4. View the results in the reports/ directory.
    # 1. Clone Bringup-Bench
    git clone https://github.com/toddmaustin/bringup-bench.git
    
    # 2. Configure paths
    cd bringupbench
    # Set BENCH_REPO_ROOT to your bringup-bench path in config.env
    
    # 3. Run evaluation (e.g., O0)
    python3 scripts/eval_infer_out.py data/infer_results/merged.O0.func_map.infer.jsonl
    
    # 4. Check results
    cat reports/O0_results.md
  7. Construct training data from AnghaBench

    main

    To construct training data based on Objdump assembly using the AnghaBench dataset:

    1. Clone the AnghaBench repository:
    git clone https://github.com/brenocfg/AnghaBench
    1. Compile the dataset using compile.py:
    python compile.py --root <Anghabench_path> --output AnghaBench_compile.jsonl
    git clone https://github.com/brenocfg/AnghaBench
    python compile.py --root Anghabench_path --output AnghaBench_compile.jsonl
  8. Install and Setup Decompile-Bench

    main

    To set up the environment for Decompile-Bench, clone the repository, create a Conda environment with Python 3.9, and install the required dependencies.

    Important System Dependencies: You must install libboost-dev and libssl-dev via apt for compilation to work, and editdistance via pip for metric calculations.

    # Clone and environment setup
    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
    
    # Required system libraries for compilation
    apt-get update
    apt-get install -y libboost-dev libssl-dev
    
    # Required python library for metrics
    pip install editdistance
  9. Launch Identifier Naming RL training

    main

    Identifier Naming RL requires a running embedding server (e.g., vLLM) to calculate semantic similarity.

    1. Start the embedding server

    Run a vLLM server with the Qwen3-Embedding-0.6B model on port 8000.

    2. Run the training script

    Edit scripts/run_ident_rl.sh to set the required configuration variables (VERL_DIR, VENV_PATH, MODEL_PATH, TRAIN_DATA, VAL_DATA, WANDB_*), then execute the script.

    # 1. Start the embedding server
    python -m vllm.entrypoints.openai.api_server \
        --model Qwen3-Embedding-0.6B --port 8000 --dtype float16
    
    # 2. Edit scripts/run_ident_rl.sh to set variables, then run:
    bash scripts/run_ident_rl.sh