cd /news/large-language-models/identifying-the-processor-of-a-bare-… · home topics large-language-models article
[ARTICLE · art-86641] src=dev.to ↗ pub= topic=large-language-models verified=true sentiment=· neutral

Identifying the Processor of a Bare-Metal Binary (Strategy 2): Testing LLMs

A developer evaluated the use of large language models to identify the processor of a bare-metal binary by disassembling it with Ghidra against 177 architectures and prompting local LLMs to analyze the outputs. The benchmark, using models like qwen3-coder:30b, revealed an exceptionally high false-positive rate, with models validating between 35 and 172 candidates out of 177, failing as a selective heuristic. The developer attributes this to superficial syntax validation and contextual blind spots from limiting analysis to the first 50 instructions.

read5 min views1 publishedAug 4, 2026

Industrializing the disassembly of an undocumented processor from a raw binary is a complex challenge that can be broken down into 4 main phases:

For the first step of this project, the goal is to evaluate different strategies and identify the most effective approach.

The first strategy aimed to generate a transcodification table (mapping byte sequences to assembly instructions) in order to disassemble the binary both statically and dynamically for a given processor. This process continues until one or more bytes fail to match any known instruction for that processor, or until disassembly completes successfully (note: successful disassembly does not necessarily mean the binary was compiled for that specific processor).

To implement this strategy and build the transcodification table, several approaches were tested:

Ghidra transcodification table generation: Failed.

Native disassembler transcodification table generation: Failed.

Using Gemini to generate the table from raw byte sequences: Successful.

(For a full summary of the tests conducted under Strategy 1, see "Identifying the Processor of a Bare-Metal Binary — Strategy 1".)

The second strategy takes a completely different approach. It consists of using Ghidra to disassemble the binary against a large number of target architectures (177 processors) and then leveraging a Large Language Model (LLM) to analyze the resulting disassembly outputs to determine which processor truly matches the binary.

The local LLMs selected for this benchmark are:

Using a single C source code file and an automated toolchain, test binaries were generated for approximately 30 different processors in both raw bare-metal and standard ELF formats.

Three specific binaries were selected for the evaluation:

Disassembly output files were batch-generated using PyGhidra and a custom Java headless script. Each model was then prompted to analyze every generated disassembly file using the exact same system prompt:

Python

SYSTEM_PROMPT = """You are an expert in reverse engineering and processor architectures.
Your task is to verify the consistency of a raw firmware disassembly.
Examine the provided instructions, verify whether the architecture's syntax is valid,
and determine if the instructions appear coherent (absence of repeated invalid instructions, aberrant opcodes, etc.).
Respond strictly in valid JSON format."""

The models were instructed to respond using a strict JSON schema:

JSON
{
    "processor_id": "{processor_id}",
    "is_valid": true,
    "confidence_score": 0.85,
    "summary": "Short explanation of the analysis",
    "detected_anomalies": ["list of errors or anomalies"]
}

This firmware was generated for a processor supported by Ghidra.

This firmware was generated for a target architecture not supported by Ghidra.

Given the poor baseline performance of local models, this test was conducted exclusively on qwen3-coder:30b.

qwen3-coder:30b: Generated reports for all 177 files. Identified 42 potential candidate processors (including the correct one).

The empirical results show an exceptionally high rate of false positives: models validated between 35 and 172 candidates out of 177, failing to act as a selective heuristic filter. Several key technical factors explain this shortfall:

Superficial Syntax Validation vs. Semantic Verification:

Most code-focused LLMs evaluate assembly primarily at a syntactic level. When Ghidra forces a disassembly, it outputs valid instruction strings (e.g., MOV R0, R1) according to the target architecture's grammar. The LLMs mistake syntactically valid instructions for semantically logical code, ignoring structural red flags like non-sensical control flow, impossible stack frame allocations, or meaningless register usage.

Window-Size Contraint & Contextual Blind Spots (First 50 Instructions):

Limiting context to the first 50 instructions creates a severe bias. In raw bare-metal binaries (and especially ELF files parsed as raw bytes), the offset often starts with interrupt vectors, padding, or raw header metadata (\x7fELF). Disassembling metadata produces random, garbage instructions. The LLM either accepts this garbage as valid initialization code or misses real function prologues (PUSH {LR}, frame setup) located further down in the binary.

Hallucination of High Confidence Scores:

Smaller, quantized local models lack calibrated uncertainty. They frequently assign confidence scores between 0.80 and 1.0 to highly improbable disassemblies simply because no explicit .byte unknown directives appeared in the 50-sample window.

JSON Schema Inflation and Special Token Leaks:

Models like gemma4:26b failed due to prompt-adherence degradation when handling low-level assembly syntax, leaking internal reasoning/channel tokens (e.g., thought...) into the JSON stream, which corrupted output parsing.

To transform this approach into a viable industrial pipeline, several adjustments are required:

Heuristic Pre-Filtering & Metrics Computation (Hybrid Static Analysis + LLM):

Before calling the LLM, compute mathematical heuristics on the disassembly output:

Invalid Instruction Ratio: Reject architectures where .byte or ?? directives exceed 5% of the total output.

Control Flow Density: Measure the ratio of control-flow instructions (JMP, CALL, BRANCH) to data movement (MOV, LDR). Random/incorrect disassemblies display abnormally low or erratic jump densities.

Entropy & String Artifacts: Calculate entropy across the binary sections to skip static headers before sampling.

Few-Shot Prompting with Counter-Examples:

Update the system prompt with explicit Few-Shot examples contrasting a valid disassembly (coherent stack operations, standard function prologues, structured loops) with an invalid/garbage disassembly (repetitive opcodes, dead jumps, aberrant immediate values).

Dynamic Sample Windowing (Skipping Metadata):

Instead of feeding the first 50 raw instructions, extract 50 instructions starting from detected function entry points (e.g., identified by CALL targets or push/pop entry sequences). For ELF binaries treated as bare metal, automatically skip the initial offset matching known header lengths.

Chain-of-Thought (CoT) Reasoning Before JSON Output:

Forcing the LLM to output raw JSON immediately suppresses its internal analytical capabilities. Changing the prompt structure to require a step-by-step reasoning phase before emitting the final JSON object significantly improves accuracy:

Plaintext
1. Analyze control flow coherence...
2. Check register consistency...
3. Identify function entry signatures...
4. Output JSON verdict.

This benchmark highlights the clear limitations of current local LLMs when used out-of-the-box for low-level reverse engineering heuristics. Without statistical pre-filtering, dynamic windowing, and structured chain-of-thought prompting, local models act as overly permissive classifiers.

Can refined prompt engineering, dynamic context sampling, or cloud-grade LLMs bridge this gap to reliably pinpoint unknown architectures? That will be the subject of our next evaluation.

── more in #large-language-models 4 stories · sorted by recency
── more on @ghidra 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
Live at https://your-agent.zahid.host
Get free account → Pricing
from €0/mo · no card required
LIVE [news/identifying-the-proc…] indexed:0 read:5min 2026-08-04 ·