Ghidra Printf String Inliner
August 21, 2025 · View on GitHub
Inline printf-style messages directly into Ghidra's decompiled view, with smart detection for Go and C, variable cleanup, and readable formatting.
Features
- Go-aware printf inlining: detects
fmt.Printf/friends, even when format strings are concatenated in a single large constant - Splits a large banner of messages into individual lines and assigns them to calls in code order
- Rejects Go-internal garbage (e.g.,
reflect.Value,runtime.) and binary noise - Rewrites decompiled code preview with:
- Clean
printf("…", args);lines - Blank line before and after each inserted printf, preserving indentation
- Removal of temporary Go variables like
format_XX.*anda_XX.* - Removal of
varX = fmt_Printf(...);assignment forms
- Clean
- Adds informative comments for each call (e.g., “safe operation”, “vulnerability warning”)
- Batch mode across all functions
Requirements
- Ghidra 11.4.1
- Java 21
Build
We use a standalone builder script that auto-discovers Ghidra JARs.
cd ghidra-printf-inliner
./compile.sh
Artifacts created:
dist/StringInliner.zip– generic extension zipdist/StringInlinerVXX_*.zip– versioned zips for convenience
Install
- Open Ghidra
- File → Install Extensions → select a zip from
dist/ - Restart Ghidra
- File → Configure → Plugins → search “StringInliner” and enable
Usage
-
Single function: open a function and run the action “Inline Printf Strings” (toolbar or Analysis menu). A results window shows:
- Original decompiled code
- Found calls with resolved messages
- Modified code preview with clean printf lines and variable cleanup
-
Batch: Analysis → “Batch Inline Printf Strings” to process all functions.
Example transformation
Before:
format.len = in_stack_ffffffffffffff60;
format.ptr = puVar10;
a_00.len = in_stack_ffffffffffffff70;
a_00.ptr = (runtime._interface *)uVar12;
a_00.cap = uVar14;
sVar9 = fmt.Printf(format,a_00);
After (clean preview in results):
printf("Testing index: %d, value: %dn", index, value); // CALL 1: shows test parameters
Limitations
- The decompiler output is read-only. The plugin presents a cleaned “Modified code” preview, adds comments, and may rename symbols/locals, but cannot rewrite the true decompiler output.
- Extremely obfuscated or optimized binaries may hide format strings in ways this tool won’t catch.
Troubleshooting
- No strings found: ensure string blocks are present and not stripped
- Extension not visible: check the zip layout is
ExtensionName/lib/*.jarand restart Ghidra - Java/API errors: verify you’re on Ghidra 11.4.1 and Java 21
License
Apache 2.0