Windbg Preview
WinDbg Preview is a modern, user-friendly debugger tool provided by Microsoft. It is an evolution of the traditional WinDbg debugger.
Last updated
WinDbg Preview is a modern, user-friendly debugger tool provided by Microsoft. It is an evolution of the traditional WinDbg debugger.
Last updated
Windbg Preview is an updated version of Windbg. It has additional features such as the extensible debugger data model whilst still having the same commands and workflows that Windbg had.
Windbg Preview can be downloaded and installed from the Microsoft Store, simply search for it and press the Get button:
Now that the basic tools are installed we can remind ourselves of basic Windbg commands we will need to debug our shellcode. Feel free to skip over these if you are well versed in WinDbg.
This short section will serve as a reminder on how to do basic debugging in Windbg Preview.
Open a new Notepad instance then open Windbg Preview. If we press the File tabe we will be presented with many debugging options. To debug the Notepad process we should press Attach to a Process and then find notepad.exe:
Press the Attach button and your debugging session will begin. When the debugging session starts the Notepad process (more specifically it's threads) are 'broken into'. That is a breakpoint has been inserted and hit:
It is likely that your workspace does not reflect mine. It is worth having a play around with the View tab to build the workspace you are more comfortable with.
Windbg supports different types of breakpoints: Software, Hardware, Access, Condition, and Function breakpoints.
We have already seen a software breakpoint. These are implemented using the int3
instruction. This allows us to examine the program's state and perform debugging operations. The int3
instruction is typically inserted into shellcode temporarily for debugging purposes and is removed in the final exploit code. If we look at the familiar MessageBox call we explored in an earlier section, we can insert an int3
breakpoint (line 16
):
We might choose to break into the code and ensure the registers and stack are set up correctly before the function call (line 16
).
At this point we can debug the shellcode, such as examine registers, unassemble instructions, and examine the stack, to name a few. We will examine other types of breakpoints when we encounter them in other sections.
We can set a breakpoint in WinDbg by symbol (using bp
), and then list the existing breakpoints (using bl
):
Breakpoints can also be cleared using the bc
command:
In the preceding example we used the *
operator to clear all existing breakpoints, we could have cleared a single breakpoint using the index displayed in the list using bl
.
Breakpoints can be disabled using the bc
command:
We can display the contents of the general purpose registers all at once or individually. To display the registers we use the r
command:
If we are only interested in a single register, we can specify the register with the r
command:
Sometimes it is beneficial to display the memory that is at the location pointed to by a register. That will be discussed in the next sub-section.
The addresses in memory essentially point to 64-bit values stored as binary. This binary numbner can represent many different things depending upon the context. For example it can be an ASCII string, a Unicode string, a pointer to another object in memory, or a QWORD etc.
Memory can be displayed using the d
command. We can also specify how many memory entries we would like to list using the L
operand. Using MessageBoxA as an example we can examine the outputs of the display command:
If there are strings stored in the memory we would like to display we can use the da
(ASCII) and du
(UNICODE) commands.
It does not make sense to display the memory at User32!MessageBoxA as a string. if we do, it is displayed as 'garbage':
Finally, we can display the contents of memory by dereferencing a pointer (using poi
):
In the example above, we are dereferencing the value stored in rsp
. This could easily be a memory address being dereferenced: 0:002> dq poi(0000005d`7507f898)
.
We can unassemble machine code in memory using the u
command. This can be done by symbol or by memory address location. In the example below we show the beginning of the MessageBoxA function in user32.dll:
If we know the address of the function, we can unassemble this too:
TODO.
TODO
This section was a short reminder of some of the most common Windbg commands, more will be discussed as the course progresses.