Dx64.exe (v1) Debugger for PE64 Windows desktop applications Dx64 is a 64-bit windows application to debug PE64 formatted desktop applications on windows 8 or higher. Dx64 implements a mode to show addresses relative to their module base. Relative addresses and module numbers remain valid over different debug sessions. Contents Download Dx64 Launching Dx64 About the Dx64 window Address presentation mode Debug commands Dump commands set register commands set memory commands: find commands: command operand syntax: Breakpoints Other commands: The representation of the flag register bits Menu functions: About the log About the disassembly pane About code probing Storage of the probe data. About winapi function calls About module number preservation Exception handling. User break-in Termination of the debuggee Trace-run List differences Adding comment Right-click to pick a hex value or a function name Search on the internet Documentation menu Debugging plug-in dll files. Debugging code in an executable buffer Limits of Dx64 version 1 anti anti-debug Shell cmd-line parameters cmd-line-file Debugging Child processes alfabetic list of the commands: Warranty Download Dx64 Download the Dx64.zip from here. You may have to deal with a warning about a suspicious download. Move the unzipped Dx64.exe application to any location on your local computer. You may make a shortcut on your desktop. Launching Dx64 Dx64 can be launched in 4 ways: 1 Launch Dx64.exe by clicking it's icon (or a link to it). Dx64 will show a dialog to choose the debuggee. 2 Drag the icon of the debuggee (or a link to it) over the Dx64 icon (or a link to it). Note: This way you can not pass switches nor parameters. 3 Via a shell command (bat/pws) with switches and ascii parameters. See the "shell cmd-line parameters" section below for details. 4 Via a cmd-line-file (.clf) with switches and utf-8 parameters. See the "cmd-line-file" section below for details. Dx64 launches the debuggee and will break at the entrypoint or the first encountered breakpoint. About the Dx64 window Dx64 uses a single resizeable window to display the debug results. The window has the following panes: 1 dump of the general purpose registers 2 disassembly pane 3 log pane with unicode aware rtf text 4 text box with the code and its operands at the current rip 5 input box to enter debug commands Dx64 miminizes its window while the debuggee is running. Click on the minimized window to break-in the debuggee at Ntdll DbgBreakPoint. Address presentation mode Dx64 can display addresses in absolute hex or relative hex in their module. The button named "Rel." or "Abs." toggles the mode while being pressed. The adjacent checkbox toggles the mode permanently. Dx64 presents relative addresses as "m_ra". m is the module number in hex, ra is the relative address in hex. The modules are numbered sequencially while being loaded. The application itself has module number 0. Unless stated othewise, Dx64 commands accept absolute or relative addresses. Debug commands: F7 step into F8 step over F9 continue (go) step over (same as F8) ctrl key + → step into (same as F7) g ⏎ continue (same as F9) g + address ⏎ set breakpoint at address and continue (go until) t + address ⏎ trace-run until reaching the address t ⏎ trace-run until reaching the next OS call tret ⏎ trace-run until reaching any return instruction tsra ⏎ trace-run until reaching the return address on the stack tcal ⏎ trace-run until any return instruction and log all calls x + address ⏎ add a break at address r + address ⏎ remove break Dump commands: Dump commands have one operand (an address). Press the enter key to repeat the command without operand. a ascii b byte B byte + ascii w word (2-byte little endian) W word (2-byte little endian) + utf16 l long (4-byte big endian) L long (4-byte big endian) + ascii p pointer (4-byte little endian) q quad pointer (8-byte little endian) d disassemble code u unicode utf16 (wchar) U unicode utf-8 set register commands: The "set register" commands take 1 operand: a 64-bit value or address. The commands implicitely specify the register: srax, srbx, srcx, srdx, srsi, srdi, srbp, sr8, sr9, sr10, sr11, sr12, sr13, sr14, sr15, srip, sflg srip requires an executable address. srsp requires an address with read/write access. set memory commands: The set memory commands have 2 operands: a writeable address and a value. A set memory command stores the given value into the given address in little endian format. sb address 1-byte sw address 2-byte sl address 4-byte sq address 8-byte example: sq [rbp+8] A050 will store 0xA050 in the memory location pointed by the contents of rbp+8. sa address aaaaaa store up to 32 ascii chars sh address hhhhhh store up to 16 hex pairs su address aaaaaa store up to 16 ascii chars as utf-16 little endian find commands: The find commands have 2 operands: an address and a string to match. The search starts at the given address up to a none accessible address. The string can be specified in ascii or utf16 (case insensitive) or as hex pairs (big endian). Press return to search for the next match. fa address aaaaaa find the ascii string of up to 32 chars starting at address fu address aaaaaa find the utf-16 (LE) string of up to 16 chars that match the ascii data fh address hhhhhh find up to 16 hex-pairs starting at address command operand syntax: The operands of a command may specify a register or a value or an address (max. 64 bits). An absolute address is entered by specifying its hex representation without leading zeroes. A relative address is entered by specifiying its module number in hex (0 to FF), a single underscore character, and the relative address in hex without leading zero. e.g. command "b 1_45B". hex data example: 1A7 or -a25 decimal data example: 0175 or -045 4-byte float data example: 1.45 or -0.3 litteral ascii data example: "abc" (up to 8 chars, left aligned) winapi function example: "lineTo" (case insensitive) register example: rbp absolute address example: 7FFE145AC508 (without leading zero) relative address example: 0_125A or Mydll.dll_125A The following integer math operations are implemented: integer arithmetic + - * / logical not ! grouping ( . . . ) Indirection [ . . . ] Example: [[(rip+20)]+50*7-rbx] Commands do not accept math operations on float values in operands. Breakpoints You can set multiple breakpoints using the command "x address". You can list the breakpoints using the menu function " List > Breakpoints". You can reset a breakpoint using the command "r address". You can reset all breakpoints using the command "r 0". By default, breakpoints are removed from the breakpoint list when the breakpoint is reached. Sticky breaks are not removed from the breakpoint list when they occur. Use the X command (capital x) to set a sticky break. The x and X commands accept a relative address in a named module. Examples: x ole32.dlll_1000 x ole32.dll_CoSetState x MyDll.dll_MyFunc If the module is not yet loaded, then the breakpoint is pending until the module is loaded. The operand specifies the module name and a relative address in hex or a function name. The module name is case insensitive but must be ascii without spaces, and end with ".dll". The function name is case insensitive but must be ascii containing only letters, numbers, and underscore. Note: decorated function names are not recognized. Note: math operations can not be applied to a pending breakpoint address. The menufunction "List > Breakpoints" lists the pending breakpoints. Other commands: tab toggle the window visibility (collapse /expand the window) esc quit Dx64 (same as menufunction File>Quit) . value show the evaluated value in decimal, in float, in hex, and as relative address in a module v value display a message box with various representations of the evaluated value e mod.nb. list the exported functions of the specified module i mod.nb. list the imported functions of the specified module * text add comment to the log ? "text" launch the browser to search the internet for "winapi" + the text (handy for winapi functions) The representation of the flag register bits (flg) o overflow (0x800) d direction (0x400) i interrupt (0x200) a arithmetic (0x010) c carry (0x001 The letters are capitalized when the corresponding bit is set. The last drawn symbol is the combination of the sign and zero flag: < less then [ less then or equal > greater then ] greater then or equal Menu functions: File quit (Ctrl+Q) exit Dx64 and the debugged process (same as esc key) restart (Ctrl+R) launch Dx64 again and exit the current one. open probe-files folder (see below) Edit copy cmd (Ctrl+C) copy the text in the command box into the clipboard paste cmd (Ctrl+V) paste the clipboard text to the command box Find in log (Ctrl+F) finds text downwards in the log (circle around) copy log copy the entire log to the clipboard (rtf/asc/unicode) clear log (F2) clears the log and logs the shell cmd line clear input box (Delete) clears the input box recall the last command (F3) List xxxx various lists - see below Documentation various viewable documents - see below The last menu shows the name of the module in view in the disassembly pane. It has no menu-items. About the log Dx64 displays the unicode shell cmd-line at the beginning of the log. Dx64 displays dump and list results in the log. Dx64 displays the debugstrings output by the debuggee in the log, without halting the debuggee. The log can be scrolled freely with the scroll bar and mouse wheel. Only the last 900K bytes of data are kept in the log. Menu functions: Edit > Clear log Edit > Copy log (the copied text can be pasted and edited in an rtf or txt aware editor). Edit > find text in log (run around find logic). shortkeys: Page Up, Page Down, Home, End. See "Right-click" below for picking a value or address into the input box. About the disassembly pane The disassembly pane displays the decoding result. While stepping/tracing, the current operation comes into view on a blue background. Calls to a function in another module are drawn on an orange background. See "Right-click" below on how to pick a value or address in the input box. A "Ctrl-Left-click" in the disassembly pane continues to that address (same as g command). About code probing Dx64 tries to determine the start address of each instruction. It does this by tracking the module entrypoint and the addresses of exported functions. In the disassembly, Dx64 shows the start address, end address, and size of blocks of unprobed bytes. for example: "0_14324 ~ 1447F 348 unprobed bytes." The probe process may automatically discover more code while debugging. Switch to absolute mode to temporarely force the decoding of unprobed code. To avoid needless probing, Dx64 only probes modules when actually needed. Use the "pr" command to force probing starting at a specified code address. Storage of the probe data. The probing process may take time. When Dx64 terminates or restarts, it stores the probe data in the appdata folder of the user. On startup, Dx64 enters the saved probe data to avoid needless probing again. Note: To undo probing, delete the corresponding probe data file in the appdata folder and restart Dx64. Alternatively, restore a previous copy of the probe data file. Note: there is a menu function File>Open probe files folder. About winapi function calls Dx64 displays the name of imported winapi functions in the disassembly. The name of runtime loaded functions is displayed only after a trace or break event occured on a function call. Dx64 displays the number of parameters behind the function e.g. CreateWindowExA (12). Remember the fastcall convention : rcx, rdx, r8, r9 , parameters on the stack. A function who's name occurs again in another module is shown with an additional "°" symbol. A nameless function is shown as modulename (without .dll) and its ordinal number. example "ole32#2". About module number preservation Dx64 assigns module numbers in the sequence that they are first loaded. Dx64 stores this assignment in the Appdata folder as a xxxx.mon file. On next sessions, Dx64 retains the module numbering of the initial load sequence. Therefore, unloaded and reloaded modules retain their number. Exception handling. Dx64 handles an expected trap and the int3 (0xCC) exception (return from step or breakpoint reached). Dx64 passes CLR exceptions and multi-NOP exceptions unhandled to the debuggee without logging them. Dx64 logs unknown exceptions (such as undocumented microsoft debug codes) but passes them unhandled. Dx64 handles known exceptions: int3, access error, priviledged instruction, array bounds, floating point, etc. The current operation is shown on a red background if continuation is not possible. User break-in Dx64 minimizes its window when the debuggee is running. Click in the minimized window to interrupt the running debuggee. The debuggee breaks at the Ntdll DbgBreakpoint function. Type tab to toggle the view between Dx64 and the debuggee. Type enter (=comand g) to resume the debuggee. Termination of the debuggee When the debuggee terminates, it's process is unloaded, and further execution (step, trace, go) is inhibited. Dx64 displays the last obtained debuggee context. Dump and decode commands remain possible. The set memory command is inhibited. Trace-run Trace-run (command t or T) continuously steps through the debugee until reaching one of the following : step until command - any functioncall by the application t ⏎ - any functioncall by any module t Ctrl+⏎ - a call of a specific function t "LoadLibraryExW" ⏎ - an absolute address t address ⏎ - a relative address in a loaded module t m_ra ⏎ - the return address on the stack tsra ⏎ - any "ret" instruction tret ⏎ - any "ret" instruction + log calls tcal ⏎ A trace-run may take time. You can interrupt tracing by clicking the mouse. Use command "T" to display each execution step while tracing (much slower). Note: a trace-run may intercept program errors before an exception occurs. The tcal command logs the address and the target address or the function name of every traced call instruction. List differences This menufunction lists the memory locations who's contents has changed during your debug actions. Changes in executable code are displayed byte per byte, left to right (big endian). Data changes are displayed in hex per 8-byte little endian value. The "List>Reset differences" menufunction resets the differences. Adding comment The "*" command allows you to add comment to the log. If the previous command was repeatable, it remains repeatable. This allows you to enter comment in dumps without having to type the dump command again. Right-click to pick a hex value or a function name A right-click on a hex value transfers the value to the command line. Unless a command is already present, the "." command is generated in front. A right-click on a relative address also copies the preceding module number. A value in brackets (a pointer) is copied with brackets if clicked in the closing bracket. A right-click on a function name transfers the name to the command line. This only works for functions that belong to a loaded module. Unless a command is already present, the "?" command is generated in front. This is very handy to search the function description on the internet using your browser. Search on the internet The ? command will launch your browser to search the specified word(s) on the internet. Double and single quotes are omitted and spaces are replaced with the "+" character. This command can be used to search for OS function calls on the internet. example: ? LoadLibraryExW Documentation menu The Help menu (F1) lists the command summary in the log. The other menu items are the url's or filenames found in the Documentation.txt file. Dx64 created this file in the Appdata folder. You may remove or add other url's or file pathnames. Debugging plug-in dll files. To debug a plug-in dll file, you must launch a PE64 application that imports that dll. Use the g, t, or x command to specify a pending breakpoint. example: x "MyDll.dll MyFunction". The pending address will be resolved as breakpoint when the specified dll is loaded. Debugging code in an executable buffer Dx64 may discover code in an excecutable buffer that is allocated by the application. Relative addressing is not possible because this code does not belong to any module. The code in an executable buffer is probed, but the probe data is not stored in the AppData folder. Limits of Dx64 version 1 Dx64 runs on 64-bit windows to debug 64-bit desktop applications in user space. No mmx/xmm support other then a hex dump. No support for hardware debug registers. No support to debug an already running process. No post-mortum crash report of a crashed process. No support for compiler symbols nb. modules 1000 nb. functions 50.000 nb, breakpoints 200 anti anti-debug The debuggee may implement logic to prevent being debugged. It can do this in many ways, and It may take serious efforts to circumvent the anti-debug logic. By default, Dx64 replaces calls to "IsDebuggerPresent" with "xor rax,rax" as a anti anti-debug method. Use the cmd line -a switch to prevent Dx64 from doing this. Shell cmd-line parameters Dx64 may be launched via a shell command (bat/pws) containing: . optional switches: -b : do not break at the entry-point -s : silent : don't play tic sounds (for sound applications) -a : do not kill the IsDebuggerPresent calls -c : do not debug child processes -d : do not log DebugStrings -x : set breakpoint (see below) . ascii path\name to the debuggee (or to a link to it) . ascii cmd-line parameters to pass unmodified to the debuggee (if any) Note: the elements must be space or tab separated, and surrounded with quotes if they contain space(s). Example: Dx64.exe -b -x0_1234 MyApp.exe param1 "param 2" A relative breakpoint address can be specified in 3 ways in the shell cmd-lline: -xhhhh set breakpoint at the relative address in the application module (same as -x0_hhhh) -xfunction set or add pending breakpoint at the address of the specified function -xmodnam_hhhh set or add pending breakpoint at the relative address in the specified module Examples: -xMyDll.dll_A125, -xMyfunc°2 cmd-line-file Create a cmd-line-file to launch Dx64 with unicode parameters. Dx64 accepts the pathname of a cmd-line-file as single parameter. The name of the cmd-line-file must be ascii and have the .clf extension. The file contains the switches and breaks, debuggee pathname and parameters. The data in the cmd-line-file can be coded in ascii or utf-8. A shortcut to the debuggee is accepted. Return chararcters are discarded as if they were spaces. Text that follows a tab character is skipped until the end of the text line. Note: dont forget to add quotes to the filepathname if it contains spaces. Example of a cmd-line-file to debug appy.exe with a utf8 parameter: -s keep silent -xDraw set a break at the Draw function comment follows a tab character appy.exe the debuggee param1 a first parameter "param 2" parameter with a space "ᾡΩ♥ 3" parameter with unicode text The resulting cmd-line is -s -xDraw appy.exe param1 "param 2" "ᾡΩ♥ 3" Note: you can make a shortcut to Dx64.exe with a cmd-line-file as parameter. Debugging Child processes Dx64 debugs child processes in a separate instance of Dx64. The window title reveals the process ID. Dx64 will discard the child if it is the debuggee. Dx64 will discard the child if it is located in the system32 folder (conhost, etc). alfabetic list of the commands: a dump ascii b dump bytes d disassemble e list exported functions fa find ascii fh find hex g go (continue) p dump pointer pr force probing q dump quad pointer r remove breakpoint(s) sa store ascii sh store hex sb set address 1-byte sw set address 2-byte sl set address 4-byte sq set address 8-byte srax, srbx, srcx, srdx, srsi, srdi, srbp, sr8, sr9, sr10, sr11, sr12, sr13, sr14, sr15, srip, sflg t trace-run v display msg. box with details of the specified value x set breakpoint . display calculation result * log comment ? launch browser with "winapi"+text Warranty This software is provided as-is, without warranty of ANY KIND, either expressed or implied, including but not limited to the implied warranties of merchantability and/or fitness for a particular purpose. The author shall NOT be held liable for ANY damage to you, your computer, or to anyone or anything else, that may result from its use, or misuse. Use it at YOUR OWN RISK