This cheat sheet outlines tips for reversing malicious Windows executables via static and dynamic code analysis with the help of a debugger and a disassembler. To print it, use the one-page PDF version; you can also edit the Word version to customize it for you own needs.
Overview of the Code Analysis Process
Examine static properties of the Windows executable for initial assessment and triage.
Identify strings and API calls that highlight the program’s suspicious or malicious capabilities.
Perform automated and manual behavioral analysis to gather additional details.
Emulate code execution to identify characteristics and areas for further analysis.
Use a disassembler and decompiler to statically examine code related to risky strings and APIs calls.
Use a debugger for dynamic analysis to examine how risky strings and API calls are used.
If appropriate, unpack the code and its artifacts.
As your understanding of the code increases, add comments, labels; rename functions, variables.
Progress to examine the code that references or depends upon the code you’ve already analyzed.
Repeat steps 5-9 above as necessary (the order may vary) until analysis objectives are met.
Common 32-Bit Registers and Uses
Addition, multiplication, function results
Counter; used by LOOP and others
Baseline/frame pointer for referencing function arguments (EBP+offset) and local variables (EBP-offset)
Points to the current “top” of the stack; changes via PUSH, POP, and others
Instruction pointer; points to the next instruction; shellcode gets it via call/pop
Contains flags that store outcomes of computations (e.g., Zero and Carry flags)
F segment register; FS: points to SEH chain, FS:[0x30] points to the PEB.
Common x86 Assembly Instructions
Put the value 0xB8 in EAX.
Put EAX contents on the stack.
Remove contents from top of the stack and put them in EAX .
Put the address of variable EBP-4 in EAX.
Call the function whose address resides in the EAX register.
Increase ESP by 8 to shrink the stack by two 4-byte arguments.
Shift ESP by 0x54 to make room on the stack for local variable(s).
Set EAX contents to zero.
Check whether EAX contains zero, set the appropriate EFLAGS bits.
Compare EAX to 0xB8, set the appropriate EFLAGS bits.
Understanding 64-Bit Registers
EAX→RAX, ECX→RCX, EBX→RBX, ESP→RSP, EIP→RIP
Additional 64-bit registers are R8-R15.
RSP is often used to access stack arguments and local variables, instead of EBP.
Sign up for my newsletter if you'd like to receive a note from me whenever I publish an article or embark on a project. This doesn't happen often, so I won't overwhelm you with updates.
About the Author
Lenny Zeltser develops products and programs that use security to achieve business results. He is the CISO at Axonius and Faculty Fellow at SANS Institute. Lenny has been leading efforts to establish resilient security practices and solve hard security problems for over two decades. A respected author and practitioner, he has been advancing tradecraft and contributing to the community. His insights build upon real-world experience, a Computer Science degree from the University of Pennsylvania, and an MBA degree from MIT Sloan.