In part two of this series, we learned to solve the exercise stack1 using x64dbg, debugging tool that allows us to analyze a program by running it, tracing it, even allowing us to set breakpoints, etc.
In those tools we’re not only running the program, we can also reach the function to analyze and execute it. But even when a tool like this is easy to use, there are many cases where it’s not necessary to run the program. A static analysis would be enough, getting conclusions without running the application or running the minimum possible amount. Static analysis can typically be used in malware analysis, function analysis of programs that don’t run, research of vulnerabilities, code reconstruction and more.
In the case of exploit writers, when they analyze a program patch that fixes a program vulnerability, they usually do something called binary diffing or diff. A diff is when we use a tool to compare the vulnerable version with the patched one to figure out if and how the patch solved the issue. This the exact stage of the vulnerability to start developing an exploit.
The problem with this approach is that there could be hundreds of changed functions and not all of them are patches. Most of them are little fixes, new functionalities, or minor changes only. To examine all the changes individually to uncover which one is responsible for the fix requires so much complex analysis and debugging that it’s simply unfeasible. We don’t even know how to reach some program functions, which could require testing thousands of combinations in order access the function, making the work far too time consuming.
Antonio Rodriguez of Incibe explains binary diffing as follows:
As part of the training, there will be a few exercises of binary diffing to find patches.
There are some disassembler programs that are interactive, so those not only show the functions and instructions but allow us (according to reversing experts) detection functionality of each one and working with what we’ll see it is the static reversing.
In general, static reversing is a powerful technique when mastered and helps us to find a correct path to the wanted function, and it can sometimes complement dynamic reversing.
We have to master and gain expertise of all the techniques for later use and to combine them as best as possible to meet our goals.
Static reversing also depends on if the programs contain symbols. When you installed Windbg you should have configured a folder for symbols where symbols will be downloaded automatically. This should happen for most of the system binary files. If we program something, you should be able to compile and save symbols in a file with the pdb extension.
At the moment, your symbols folder is most likely empty now. As you start working with windbg, IDA symbols will be downloaded and saved in there.
Having symbols makes the static analysis easier, so we will start the stack1 analysis with these symbols. Later you will find some cases where symbols are not available, which will require additional steps and skills in the static reversing. For example, this will not happen with third party programs that are not part of the operating system.
In the exercise folder, there are three files that correspond to stack1: the executable binary file with EXE extension, the source code CPP, and the symbols files PDB (if you can’t see the extension, go to the folder options or file explorer options in the Windows 10 versions and uncheck ”Hide extensions for known file types.”
We can now see the file extensions and can begin opening the executable one with IDA FREE. Drag the file to the IDA icon or open IDA, which will prompt us to open a file. Search for the .exe file and open it.
Select “NEW” to work with a new analysis file:
Search the stack1 executable.
It will detect that the executable is a PE exe file. Since IDA FREE does not come with two versions (one for 32 bits and other for 64 bits), it will say that the binary is a 64 bit, which also work.
If it says that it can’t find the pdb because it’s not in the symbols folder, click “YES” and search for symbols manually:
As IDA loads the symbols, it will detect the main function and displays it directly.
Only the pro version of IDA free has a decompiler. IDA FREE does not have a decompiler, so pressing F5, which is the shortcut in the PRO version for decompile a function will just say:
In the image, the comparison between printf and gets for the cookie with the value 0x41424344. If the values are not the same, it will follow the path of either the green arrow or the red arrow.
GREEN ARROW = Conditional jump result is true.
RED ARROW = Conditional jump result is false.
In this particular case, the parameters are that
JNZ (jump if not zero) or JNE (jump if not equal) = TRUE which means that it will go through the green arrow if values are not the same and through the red arrow if they are the same. In our example, the value is not the same, which means it will be following the green arrow.
It’s worth keeping in mind what we saw in the x64dbg debugger, which we can compare with what we see in IDA.
Remember that after the PROLOGUE function, EBP was set as a frame pointer and the function was EBP BASED, so the EBP value would be constant until the EPILOGUE. All the variables and parameters that remained constant and were referenced using EBP were called the HORIZON.
The HORIZON line can be seen in the stack: