Binary Only Fuzzing
When we don't have source code
So far, we have mostly seen Fuzzing on programs whose source code we have
But in Reverse Engineering and Fuzzing, there are many times when we only have an executable file
For example
program.exe
or
program
We don't have the source
Or proper documentation
Or we don't even know exactly what's going on inside the program
This is where we need to first examine the program
To understand where it gets its input
To understand how that input moves inside the program
Then prepare the same path for Fuzzing
Step One
Opening the Binary
First, we open the program in tools like Ghidra or IDA
Our goal is not to understand the entire program from the beginning
We are not going to sit down and read millions of instructions one by one
First, we look for places where the program deals with external data
For example, in Linux and various programs, we may encounter things like
read
recv
fread
fgets
scanf
In Windows also has things like
ReadFile
recv
fgets
can be a good clue
But here's an important point
Just seeing the name of a function doesn't mean that the main input to the program is there
Data may be passed through several functions
We may have a Wrapper
There may be a separate Parser
So we need to follow the data path
Step 2
Follow the data path
Suppose we get something like this in the Decompiler
buffer = malloc(256);
read(fd, buffer, size);
process_data(buffer);
Here we have a very good path
External Input
↓
read
↓
buffer
↓
process_data
That is, external data entered the program
It is placed in a Buffer
Then it goes into a function that probably processes that data. Now we not only know that the program has input, but we also have a clue where the input goes after it enters the program
Step 3
Find out what the input looks like
This part is very important
Because the Fuzzer cannot just throw a bunch of random data into the program and expect the program to happily process it all
The program usually expects the input to have a specific structure
For example, the program may read a file
program sample.dat
Or take input from stdin
program < sample.dat
Or even input from the network
Client
↓
Network
↓
recv
↓
Parser
So we need to understand
Where the input comes from
What format it is
Where it is parsed
And what parts of the program work with it. This information is very important for Fuzzing because the more Understand the input structure
Fuzzer
can also generate more useful inputs
Step 4
Creating a Seed
Now suppose we understand that the program reads a file with its own format
For example:
sample.dat
First we find a healthy and small file
We call this
Seed
Then the Fuzzer modifies this Seed
Seed
↓
Mutation
↓
Program
↓
New Path
or
Crash
For example, a part of the file changes
Then the program runs
Fuzzer checks whether the program has entered a new path or not
Or whether it has crashed
Why is this important
This is exactly where Fuzzing comes in handy
Fuzzer
Alone can't always figure out what the input structure is
But we can find clues by examining the Assembly and Decompiler
For example, suppose we see in the Assembly:
cmp byte ptr [rax], 48h
jne invalid
Here we see the program is checking a specific Byte
That is, it is probably A specific part of the input is important to the program
We will see it later in another place
cmp dword ptr [rax+4], 100h
Here the program is checking a value at Offset 4
Now if we put a few of these checks together
We can gradually guess what the input structure is
For example, we might get something like this:
Offset 0
↓
Magic
Offset 4
↓
Size
Offset 8
↓
Flags
Offset 12
↓
Data
That is, without having the Source Code, we can gradually deduce the Input Format structure from the Binary behavior
Of course, one important point
Post #1743
53