Someone asked me about my debugging progress. In particular, I had to debug a program recently for which I did not have any source available and they were curious how I approached that. I have spent years taking apart games, looking at disassembly, and trying to figure out why I am seeing certain behavior and how I can change it, which is just debugging in a nutshell. I’d like to believe that I picked up some skills and tools during that time that are applicable beyond reverse engineering; they help when you need to understand what a program is doing without reading its source (lack of source or lack of time).
This post is a small collection of things I found useful. There are probably newer tools that I don’t know about – many of the things here have been around for 15 years or longer. Let me know what you are using and what tools I am missing.
- The first tool is not a piece of software, but just a working understanding of computers. An understanding that there is no magic and that you can fundamentally understand computers. It also helps to have some fluency in assembly language and knowledge ABIs, calling conventions, and OSs in general. I regularly joke about how much mileage you can get out of just knowing what registers generally hold return values.
- Get a text-editor that doesn’t complain about huge files. I like Notepad++. Reading logs is often the first step in debugging. It’s generally helpful to be able to filter logs and quickly discard irrelevant information. Notepad++ has a search-and-mark feature for that. Not great, but works. I am actually frequently wondering whether I’m missing a tool that simply allows me to filter text more quickly. VSCode is nice for its multi-line editing capabilities, which I prefer over Notepad++’s version. Debugging usually involves lots of note taking and I usually do this digitally.
- Learn to work with Google Sheets or Excel or something else that allows you to quickly look and understand numeric data. Adding temporary code paths that dump out information is an essential tool to quickly extract information and knowing how to process CSV data is helpful. Google sheets is good enough, though I am surprised every time how annoying it is to just draw a histogram in sheets.
- Get a screen-snipping tool like Microsoft’s snipping tool. Take many screenshots and store them. Make that process simple. I also love ScreenToGif as a tool to quickly record what I’m seeing into a GIF if I need to show it to someone else during debugging.
- Get a debugger. Ironically, I don’t have as many opinions here. I use Visual Studio’s debugger a bunch and occasionally WinDbg. I have tried older debuggers and there’s also Remedy, but I have never used it.
- Get a good profiler. I like Superluminal. A profiler can tell you what a process is roughly doing over a period of time instead of all the details at any particular instant (like a debugger). It helps to understand what is happening in broad strokes and understand the big picture. It’s often a good first step to just profile a program. If you have symbols available (e.g. code you compiled yourself or anything you can find on a symbol server), then a profiler will essentially allow you to put your program through an X-ray machine and only see the relevant parts. Knowing what part executes, roughly, tells you what code is most likely worth understanding.
- Get a good hex editor. I like HxD, it’s very basic but works nicely with huge files, can open memory directly, and can show a variety of interpretations for bytes. Hex-editors are useful to study files more closely and search for binary data. You probably also want to search for strings some times, and HxD supports searching for the two most common encodings. Fancier hex-editors exist, and as teenager I dreamt of affording the expensive Hex Editor Neo Ultimate Edition, but I don’t think you need more than the basics – unless you are reverse engineering file formats, then you want structural coloring and such! In that case, also see HexWorkshop and visit Luigi Auriemma’s website for all of the tools there (e.g. QuickBMS). Adjacent to hex editors, there’s also Strings to just dump out strings from binary files, but compared to its linux equivalent it seems painfully slow.
- Get a static analysis tool with a good disassembler. I like IDA Free, though note that this is only for non-commerical use. There’s also Ghidra, Binary Ninja, Radare, and probably a whole host of other tools. Looking at tools from the reverse engineering space is generally a good idea. Static analysis tools allow you to explore binaries without necessarily running them. You can annotate the disassembly, add your own types to interpret data, see cross-references, sometimes maybe even get decompilation etc. – It takes a while to get used to it, and IDA in particular has its rough edges, but it’s way easier than the alternative of going through a heap of assembly without anything else. IDA is quite good at detecting helpful meta-data in binaries, for example C++ programs often have RTTI baked in and IDA finds and dectects virtual function tables for you.
- Look for tracing and monitoring tools. Any tool that allows you to observe a program’s behavior without having to change the program itself is helpful. I have grown very fond of Process Monitor, it fits that bill exactly. It can record all file I/O interactions, network activity, major events such as thread spawning etc.. There are tons of options for filtering the events and most events have a callstack associated with them. It’s based on Event Tracing for Windows (ETW) and quite robust. I use it constantly, daily. Process Explorer is a great task-manager replacement, it gives you quick access to say all modules of a process. The Windows SysInternals page also has other useful tools such as RAMMap and VMMap. Browse around, pick what you like.
- API Monitor is a useful tool for instrumenting and intercepting a whole bunch of different APIs on Windows. Seriously, anything that goes through COM and probably much more can be logged out. Using it at scale has quite a heavy performance impact but when you need to intercept all DirectDraw (R) calls that a game from the late 90s submits, it’s here for you.
- If you ever need to look at DLL imports and exports, try CFF Explorer. It’s a neat little utility to edit and view PE files. There’s also DLL Export Viewer which I have used many times in the past but it’s old by now. Dependency Walker takes a few more steps and draws entire dependency trees. DLLs are a good thing to understand because anything that calls into a DLL usually does so by name, which makes DLL exports a good place to build an understanding of what happens when you don’t have source code or symbols.
- CheatEngine has tons of goodies and can do way more than help someone cheat. I have not used it in a long time but it’s proven useful in the past and now finding it in my tools directory makes me want to come back to it. You can scan memory, inject code, and just generally tinker with your target process.
- WinSpy is a tool that can give you helpful information about windows on Windows. It’s not that I need to do this exact thing particularly often, but the general category of tools that allow you to point at a clearly visible thing and then give you the “behind the scenes tour” is so useful. Debugging is essentially all about taking a clearly visible side-effect (usually a defect) and uncovering its background story. These tools are shortcuts. When you find one, keep it.
- If you need to make changes to a program in binary form and your changes are very simple, get an assembler. It’s way easier nowadays with online tools if you know that you are only ever operating on a handful of instructions and are only really messing around, e.g this. There are tons more. I usually just use it to take opcodes, turn them into assembly, make tiny changes, and get the opcodes back. Anything that’s larger than the original code needs more surgery but patching single instructions this way is often just fine.