Reverse Engineering Firmware With Ghidra
Once the firmware is extracted, the binaries inside still have to be understood. Ghidra, the open reverse-engineering suite the NSA released, turns raw machine code into readable pseudocode for free. It is how you find the hardcoded password, the hidden command, or the broken crypto that a vendor assumed no one would ever look at. Here is the workflow I use.
Why Decompilation Changes the Game
Vendors often treat compiled firmware as if it were secret. It is not. A decompiler reconstructs C-like logic from machine code, so a binary you cannot read in a hex editor becomes a function you can follow line by line. Stripping symbols slows this down; it does not stop it. Assume any logic in the firmware is readable by a motivated analyst, because it is.
Step 1: Triage With strings First
Before loading anything, pull the printable strings. Five seconds here often points straight at the code worth decompiling:
strings -n 8 fw.bin | grep -iE 'http|key|pass|admin'
https://api.vendor-cloud.example/v1/telemetry admin Login failed for user %s AES key load failed /etc/config/secret.conf
Hardcoded URLs, an admin user, and a reference to an AES key are all leads. Each one has code behind it that you can now jump to directly.
Step 2: Load It Into Ghidra
For a Linux-based device you can import an executable straight from the extracted filesystem. For bare-metal firmware, use the headless analyzer and tell it the exact processor:

analyzeHeadless ./proj MyProj -import fw.bin \ -processor ARM:LE:32:Cortex
INFO Opening project: /home/lab/proj/MyProj INFO IMPORTING: fw.bin INFO REPORT: Analysis succeeded for file: fw.bin INFO ANALYZING all memory and code: fw.bin (ARM:LE:32:Cortex) INFO Packed database into project file
Getting the processor and the load address right is the whole game for bare-metal images. Set the wrong base address and every string reference and function pointer lands in empty space.
Where to Start Reading
A firmware image can hold thousands of functions. You do not read them in order; you pivot in from one of three anchors:

Step 3: Read the Decompiler
Follow a string like "Login failed" to the function that prints it, and the decompiler shows you the logic in near-C. This is where the findings live:
undefined4 check_login(char *user,char *pass)
{
int iVar1;
iVar1 = strcmp(pass,"SuperSecret123");
if (iVar1 == 0) {
return 1;
}
return 0;
}
A password compared against a string literal baked into the firmware is a backdoor that ships in every unit. This is one of the highest-impact findings a firmware review produces, and the decompiler hands it to you in plain sight.
Defending Your Firmware
You cannot make a binary unreadable, so do not rely on obscurity. Remove debug backdoors and test credentials before release, keep real secrets in a secure element rather than in code, and have someone reverse your own firmware before an attacker does. The goal is that when the binary is read, and it will be, there is nothing embarrassing inside.
Where This Fits
Firmware reverse engineering is where a product security assessment finds the issues automated tools miss: logic bugs, backdoors, and broken cryptography. Reading the binary the way an attacker would is the kind of work we do at Berkner Tech.