Ghidra: what auto-analysis is claiming
Auto-analysis is a queue of analyzers that propose functions, strings, references, and signatures. Each proposal is a hypothesis you can check against the bytes. The listing is still yours to correct.
A queue of specialized passes
When import offers to analyze, or when you choose Analysis > Auto Analyze, Ghidra runs a list of analyzers. Each one looks for a particular kind of structure. String analyzers define runs of ASCII or UTF-16 as data. Function-start search looks for prologues and other entry shapes. The reference analyzer follows operands that name an address and records a cross-reference. Stack analysis builds the frame the decompiler will later describe. Decompiler Parameter ID uses the decompiler itself to improve calling conventions and parameter storage. None of these passes execute the program. They read the database and add annotations.
The dialog lets you turn analyzers off. The defaults are a reasonable start for a normal compiled program. Aggressive Instruction Finder is the one to be slow with: it will invent instructions in gaps, and some of those gaps are data. If the listing suddenly contains functions whose bytes are obviously text or a table of addresses, that analyzer is the first place you look.
Analyzers worth recognizing by name ASCII Strings / Unicode Strings define text runs Function Start Search propose function entries Reference build cross-references Stack recover stack variables Decompiler Parameter ID improve signatures using the decompiler Non-Returning Functions mark calls that do not come back
Read the result as a set of claims
A finished pass is a set of claims. “These bytes are a function.” “This run of bytes is a string.” “This operand refers to that address.” “This function takes four arguments in these registers.” Each claim can be wrong without the others falling over. The habit is to test the claims that anchor the program: entry exists and is code, the string you know from the source is defined, and a call you expect, such as fopen or printf, shows up as an external symbol.
Placeholder names are part of the claim’s modesty. FUN_00101240 means “a function at this address, with no better name yet.” DAT_ means data. LAB_ means a code address that is not a function entry. s_ often prefixes a string label. Quote them in your notes as addresses you have not understood. The moment you understand the body, you replace the placeholder with a name of your own. That rename is the next layer of analysis, and it is yours.
Correct the database, then run the pass again
Clearing a bad function, defining a string, or marking a table as an array of pointers are edits to the database. The executable on disk does not change. After a correction, references and signatures may still reflect the old idea. Analysis > One Shot runs one analyzer. Auto Analyze runs the enabled set again. User-defined names, the ones you set yourself, are kept. Default placeholders can be recomputed.
If the entire listing looks like the wrong instruction set, stop repairing. That is a bad language at import, and the efficient fix is to remove the program and import it again. Analysis is powerful on a correct decode and confidently wrong on a bad one.
- Let the first auto-analysis finish before you start renaming.
- Check entry, one known string, and one known library call.
- Treat FUN_ names as unnamed, not as facts from the file.
- Clear code that landed on data, then rerun the analyzer that was misled.
Lab: three claims, checked
Open harbor-check after analysis completes. Find three claims that hold: a defined string containing check.conf, an external function whose name is a libc routine you can justify from the source (fopen, fgets, sscanf, printf, or fclose), and at least one function whose body is a normal prologue rather than data. Write them down with addresses from your database.
Find one claim that is still unfinished: a function whose name is still FUN_. You do not have to rename it yet. Record its entry address and one sentence about why you are not ready to name it, such as “callers not read” or “signature still full of undefined types.” That sentence is the analysis behaving correctly. It left you the work it could not do.
Holds: string "/etc/harbor/check.conf" at <addr> block .rodata import fopen referenced from <addr> code entry has a real prologue Still open: FUN_<addr> body not read yet
Diagram
Two ways to treat a finished analysis pass
- Queue
Analysis > Auto Analyze runs the enabled analyzers. The status line shows the one that is working.
- Proposals
They create functions, defined strings, cross-references, and sometimes a recovered signature.
- Check
You check the proposals that matter: the entry function, the string you expect, a library call you expect.
- Again
After you correct a boundary, Analysis > One Shot can rerun a single analyzer on the program you just improved.
What you do with an analyzer’s proposal
Functions. You open one and see a real prologue and a return.
Names. FUN_ addresses stay until you understand the body.
Repair. A jump table marked as code gets cleared and redefined as data.
Functions. Every green function is assumed to be a real routine.
Names. You quote FUN_ labels in a report as if they were symbols from the file.
Repair. A bad boundary is left in place because the analyzer already ran.
ASCII Strings / Unicode Strings define text runs Function Start Search propose function entries Reference build cross-references Stack recover stack variables Decompiler Parameter ID improve signatures using the decompiler Non-Returning Functions mark calls that do not come back
Check yourself
1. Auto-analysis finishes and three functions are named FUN_ plus an address. What do those names mean?
2. A “function” begins in the middle of the characters of a string you can read in the bytes. What happened?
3. You fixed a function’s end address and you want reference analysis to look at the program again. Where do you do that?