Debugger Feature: Break Point Command Strings
The Microsoft debuggers support the automatic execution of several commands upon encountering a breakpoint. This allows you to automate what you can do at a break point. You can use this to add modifications to the program execution at runtime and avoid recompiling.
The debugger command syntax is bp <Address> "<Command String>". There are other parameters that can also be specified, but this is the simplest form. The command string can contain several commands separated by a semicolon. The limitation of this command is that they will not be executed if you are single-stepping program execution to the break point location.
The command string may also contain what is known as a conditional break point. This is essentially an if-then-else statement in the command string whose syntax resembles the C ternary operator. The syntax of the command string for this is j <expression> ? <then> : <else>. These allow you to conditionally break into or display different messages depending on the value of some variable or register.
Using Command Strings as "OutputDebugString"
Let's say that you want to track every file creation in an application, every registry key or perhaps window creation. Or you may want to track a function call that's internal to your own source. Perhaps this isn't even your application but another application you have installed on your system that you do not have the source code to modify. How do you go about doing this?
There are many ways to do this and it all depends on what you want to accomplish. There are many tools you can use such as FileMon (http://www.sysinternals.com/), RegMon (http://www.sysinternals.com/), Microsoft Spy++ and application verifiers as well as advanced debugger features. There is however a simple solution that may sometimes be all that you need — just a break point.
The problem with a traditional breakpoint on a call such as CreateFile is that you would need to manually verify the parameters and then manually type g. CreateFile is also called all the time by a lot of components outside of your own code. The solution is simply to display the parameters you want to the debugger and go. This can be accomplished by using bp kernel32!CreateFileW "du poi(esp + 4);g".
The break point has two parameters in which the last parameter is g to continue. This allows the previous parameters, only one in this case, to display output and then automatically continue executing the application. The du command will dump memory contents and treat it as a Unicode string pointer. The poi is essentially a pointer dereference, so to get the value contained at the stack location pointed to by ESP, we need to dereference the stack address.
Figure 1 shows a partial stack example of CreateFileW. When a break point set on a function is performed ESP will always point to the return address. The stack grows downward in memory so you simply need to add to ESP in multiples of 4 to dereference any parameter.