This document is about "how to make Cutter a proper debugger" # UI and UX of other debuggers This section describes the basic specifications of a usable debugger, it covers only the most essentials features. One has to recap all the features from all the existing debugger and then we have to decide which are the features that are the most interesting to port over Cutter. Final document - https://hackmd.io/0AWnIUeDR2q0hwouc33MxA ---- ## Assignments Feel free to take overlapping tasks ---- ## Breakpoints ### R2 * add, remove, disable * remove all * run command when breakpoint is hit - doesn't seem to be fully implemented * breakpoint condition - help has weird description * every non return function * breakpoint trace * breakpoint plugin handlers * breakpoint expr - address calculated from expression? * hardware breakpoint * count - not sure if current implementation is usable for anything * other configurable break reasons TODO * dbg.bep break on entry * dbg.aftersyscall - conflicting descriptions * dbg.bpsysign ignore system breakpoints * dbg.clone Stop execution if new thread is created * dbg.consbreak ? SIGINT handle for attached processes * dbg.execs: Stop execution if new thread is created * dbg.forks: Stop execution if fork() is done (see dbg.threads) * dbg.unlibs: If set stop when unloading matching libname * instruction trace start/end, not the same as tracepoint TODO ### DDD ![](https://i.imgur.com/nOTFjt6.png) ![](https://i.imgur.com/SHztusZ.png) The icons for the state of the breakpoints: ![](https://i.imgur.com/1Y4PU1L.png) ### GDB * Command execution on breakpoint hit - see 'command', lets you create a macro with gdb commands that will be executed automatically when the breakpoint is hit, an optional part of the command's content is specifying that the breakpoint should continue after executing the macro * Hardware breakpoints * Self-deleting breakpoint after being hit once * Breakpoint that only stops on successful evaluation of a condition expression * It's possible to configure gdbserver to let gdb(/r2) evaluate the condition - `set breakpoint condition-evaluation host` * Includes if/else and catch(in case the condition doesn't exist, for example a pointer you are derefing) * Types: * A reference to the value of a single variable. * An address cast to an appropriate data type. For example, ‘*(int *)0x12345678’ will watch a 4-byte region at the specified address * An arbitrarily complex expression, such as ‘a*b + c/d’. The expression can use any operators valid in the program’s native language * regex breakpoint that searches source code of the given files, could do the same in Cutter with assembly search (For example, mov.*, class member offset) - also has filter options for specific files * Breakpoint on throw/rethrow/catch (of exception), special case for unhandled exceptions as well * Ptrace breakpoints(or stop conditions) (fork, clone, vfork, vfork end, syscall etc) * (Breakpoint?) - static probe points - when the current PC is at the probe’s location you can setup SystemTap and DTrace probes. Supposed to be very light for tracing various data * Source code based breakpoints ### LLDB * Command execution on breakpoint hit - breakpoint has the -G flag to indicate that the breakpoint will auto-continue after running it's command * Hardware breakpoints * Skip function prolog if the breakpoint is at the start of the function * Set language interpretation on breakpoint * C++ method name breakpoints * Thread specific breakpoints * Breakpoint based on file offset (set up breakpoint in a shared dll before it's loaded and it will be rebased to the load addr) * Breakpoint that only stops on successful evaluation of a condition expression * Source code based breakpoints * C++ Exception breakpoint * Breakpoint ignore count - set the number of times the breakpoint should be skipped * In gdb this would require a manual implementation of a `command` macro on break with a counter * Self-deleting breakpoint after being hit once * regex breakpoint that searches source code of the given files, could do the same in Cutter with assembly search (For example, mov.*, class member offset) * Set the breakpoint only in a shared library - not sure when this is useful, maybe duplicates? ### GDBgui Too Limited ![](https://i.imgur.com/9GJHbOv.png) ### IDA By default, using <kbd>f2</kbd> on an instruction will set a memory breakpoint. ![](https://i.imgur.com/E5cHN9p.png) IDA has a special widget for breakpoints, called breakpoints list window. Unlike Cutter, IDA is not only showing the offset of the BP, but also the function name + offset. As we have in other widgets. IDA supports grouping of different breakpoints and thus allowing to disable or enable multiple breakpoints by group. ![](https://i.imgur.com/7g3ryyB.png) From this window, the user can insert a new breakpoint using a reach dialog with the following options. ![](https://i.imgur.com/nQhmxdh.png) IDA can execute IDA Python or IDC code upon reaching a breakpoint. It can also apply multiple actions when reaching a breakpoint. By default it Breaks but not necessarily. Thank to its decompiler, IDA can support special breakponts for the decompiler. Since multiple assembly instructions can be added into a single line of C in decompiler, this is helpful. ### Ollydbg vanilla No specific features not already found in x64dbg ### WinDBG Very limited on the UI only the dialog listing them, otherwise it is done via the console. Shortcut for the dialog is alt+F9 ![](https://i.imgur.com/FNJwJkv.png) ### x64dbg In disassembly one can click or use F2 to set-up a breakpoint, clicking on the pin can change status of the breakpoint (disabled/) ![](https://i.imgur.com/pTgsF44.png) One can also add specific breakpoints like hardware or conditional ![](https://i.imgur.com/m74wVRS.png) From the dump ability to add breakpoint for various cases ![](https://i.imgur.com/9IKo8nA.png) Breakpoint panel (alt+b) shows type, address, Module/Label/Eception, State, Disassembly on which the breakpoint is set, number of Hits - It also have a column if the breakpoint is "special" like "entry breakpoint etc." Leaving cursor on Address shows rest of disassembly Right click - Remove, Disable, Edit, there is also a R, D and E (all) The edit is also used for conditional breakpoint dialog ![](https://i.imgur.com/0galhlb.png) Add dll Exception ![](https://i.imgur.com/keeg7jX.png) Add exception breakpoint ![](https://i.imgur.com/dTpOZCt.png) Ability to copy breakpoint information ![](https://i.imgur.com/ehDlk2p.png) Preference shows list of "common" breakpoints to select - Entrypoint, DLL, Thread, TLS callback etc. ![](https://i.imgur.com/D7FilbZ.png) Preference provides ability to change default Breakpoint type ![](https://i.imgur.com/ib2iQnD.png) And ignore inconsistent breakpoint ![](https://i.imgur.com/ajD82FB.png) ### Summary * [+] Done * [C-] Missing in Cutter * [C*] Broken/partial in Cutter * [R-] Missing in R2 * [R*] Broken/partial in R2 * [R?] Requires testing * [?] unclear #### Functionality * Position * [+] Fixed address with rebase (can be initially specified as expression calculated once) * [R?] named or expression - more reusable, function in a module that isn't loaded yet, other uses * [R-] Module relative offset (when does r2 calculate it?) * Similar to the point above but for modules (dll, share libs) * [R-] source code, debug information based * PDB info is not really working on r2? (need to check and open an issue) * Is this integrated with flags or requires a special command * [R-/C-] asm regex? Maybe it could be done by genearating breakpoints from search results or selection in any addressable item widget. - Can use existing r2 search just need to integrate it with breakpoints on r2's or cutter's side * Suggestion + TODO: Support multiple selection in Search widget and apply several actions to the selected addresses (e.g add breakpoints) * Type * [+] software * [R*] hardware * [+] RWX * [C-] size * [R*] some kind of UI indicator when count limit is exceeded. How to get info? - have to manually parse drx output * Conditional * [R?] evaluated in R2 * [R-] Evaluated in debugger? Can we ask gdbserver to evaluate complex c++ expression? * Breakpoint conditions can be evaluated on gdb target’s side if the target supports it. Instead of evaluating the conditions locally, GDB encodes the expression into an agent expression (see [Agent Expressions](https://sourceware.org/gdb/onlinedocs/gdb/Agent-Expressions.html#Agent-Expressions)) suitable for execution on the target, independently of GDB. Global variables become raw memory locations, locals become stack accesses, and so forth. * Which parts are affected by condition (break, trace, custom cmd, hitcount)? * [R-] thread specific - could be done as exmaple condition instead inside r2 * Temporary disable * [+] Fixed. ~~It seems that r2 currently does it only partially. What happens with extra features.~~ * [R?] hit count - r2 state unclear * [R-] ignore first x hits * [R-] ignore after x hits * [R-] one time - deletes completley * [R-] debugger side? * Low priority - could be useful to save bandwidth when working with remote debuggers and not too hard to implement * Action on hit * [+] break * [R*] tracepoint (currently disables break) * [R+] r2 command - partially exists in code but doesn't seem to be executed * [R-] Continue after hit? Explicit or implicit in combination with other features? * [?] tracing mode - need to clarify r2 functionality. Special buttons not necesarry (but nice to have) if tracing mode can be enabled using r2 command action. * Need to clarify what it is and how it should be used * [R-] External plugin callback * gdb-style static probe points - when the current PC is at the probe’s location you can setup SystemTap and DTrace probes. Supposed to be very light for tracing various data * This is something that should be discussed with r2devs * [R?] Special break conditions - based on r2 capabilities (some of these break without being breakpoints) * [R*?] Initial break on restart * [R-] exceptions (throw/rethrow/catch/uncaught) - is anything feasable without a lot of language specific code? Minimum of CPP would still be useful * [R*?] thread and process events - based on debugger and r2 capabilities * dynamic library events * [R*?] syscalls * Known error handling, panic functions * [R*?] non return functions - not sure if r2 implements it as condition or generates once #### UI * Disassembly widget * [+] indicate breakpoints * [+] keyboard shortcut for setting basic breakpoint * [C*] context menu for basic breakpoint operations, doesn't need to contain everything - only available outside of debug mode atm * [+] Add, remove * [C-] Edit or Add advanced depending on current line containing breakpoint * [C-] Open breakpoint dialog * Breakpoint widget * [+] List all breakpoints * [C-] Two groups bp groups: * regular breakpoints * other break conditions (bep, new thread, loading library, ...) * Display * [C-] Red circle icon for indicating enable state (- Lamp?) * [+] Address * [C-/R-] Position - function with offset possibly module, position expression * [C-] Tooltip/preview * [+] Enable/Disable state * [C-] Type sw, hw, could be merged with hw watchpoint permissions * [C-] Presence of condition or command * [+] Easy way for toggling breakpoint enable state * [+] Allow add, delete, toggle * [+] Support delete and toggle for multiple row selection * [+] Addressable item functionality * [C-] Use new/edit breakpoint dialog * [C-] New/Edit breakpoint dialog * Dialog for editing all breakpoint options * Position (multiple kind) * Type sw or hw, hw breakpoint config * Action when breakpoint is triggered (see functionality section) * command * Condition (include help or example) * [C-] Create breakpoints from AddressableItemContextMenu, choose default config based on access permissions * Decompiler widget * [+] indicate lines with breakpoints * set basic sw breakpoint ## Registers ### DDD ![](https://i.imgur.com/xu7fcHM.jpg) ### Qt Creator ![](https://i.imgur.com/ewJWSci.png) ### Hopper Pretty basic but they have a cool UX for flags with toggleable buttons ![](https://i.imgur.com/uaPrYY6.png) ### GDB <details> <summary>Full register view</summary> ``` info all-registers rax 0x0 0x0 rbx 0x0 0x0 rcx 0x7ffff7261187 0x7ffff7261187 rdx 0x14 0x14 rsi 0x14 0x14 rdi 0x0 0x0 rbp 0x7fffffffcc60 0x7fffffffcc60 rsp 0x7fffffffcc48 0x7fffffffcc48 r8 0x7ffff760f8c0 0x7ffff760f8c0 r9 0x7ffff7fbf180 0x7ffff7fbf180 r10 0x23 0x23 r11 0x206 0x206 r12 0x555555554910 0x555555554910 r13 0x7fffffffe350 0x7fffffffe350 r14 0x0 0x0 r15 0x0 0x0 rip 0x7ffff7261187 0x7ffff7261187 <kill+7> eflags 0x206 [ PF IF ] cs 0x33 0x33 ss 0x2b 0x2b ds 0x0 0x0 es 0x0 0x0 fs 0x0 0x0 gs 0x0 0x0 st0 0 (raw 0x00000000000000000000) st1 0 (raw 0x00000000000000000000) st2 0 (raw 0x00000000000000000000) st3 0 (raw 0x00000000000000000000) st4 0 (raw 0x00000000000000000000) st5 0 (raw 0x00000000000000000000) st6 0 (raw 0x00000000000000000000) st7 0 (raw 0x00000000000000000000) fctrl 0x2249 0x2249 fstat 0x2b95 0x2b95 ftag 0xbbea 0xbbea fiseg 0x0 0x0 fioff 0x0 0x0 foseg 0x0 0x0 fooff 0x0 0x0 fop 0x0 0x0 mxcsr 0x1fa0 [ PE IM DM ZM OM UM PM ] bndcfgu { raw = 0x0, base = 0x0, reserved = 0x0, preserved = 0x0, enabled = 0x0 } } { raw = 0x0, config = { base = 0x0, reserved = 0x0, preserved = 0x0, enabled = 0x0 } } bndstatus { raw = 0x0, status = { bde = 0x0, error = 0x0 } } { raw = 0x0, status = { bde = 0x0, error = 0x0 } } ymm0-15(all are printed in this manner) { v8_float = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, v4_double = {0x0, 0x0, 0x0, 0x0}, v32_int8 = {0xd, 0x5, 0x52, 0xd, 0x52, 0x47, 0xd, 0x1b, 0x1c, 0xd, 0x11, 0xd, 0x42, 0x47, 0xd, 0x1b, 0x0 <repeats 16 times>}, v16_int16 = {0x50d, 0xd52, 0x4752, 0x1b0d, 0xd1c, 0xd11, 0x4742, 0x1b0d, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, v8_int32 = {0xd52050d, 0x1b0d4752, 0xd110d1c, 0x1b0d4742, 0x0, 0x0, 0x0, 0x0}, v4_int64 = {0x1b0d47520d52050d, 0x1b0d47420d110d1c, 0x0, 0x0}, v2_int128 = {0x1b0d47420d110d1c1b0d47520d52050d, 0x0} } bnd0 {lbound = 0x0, ubound = 0xffffffffffffffff} : size -1 {lbound = 0x0, ubound = 0xffffffffffffffff} : size -1 bnd1 {lbound = 0x0, ubound = 0xffffffffffffffff} : size -1 {lbound = 0x0, ubound = 0xffffffffffffffff} : size -1 bnd2 {lbound = 0x0, ubound = 0xffffffffffffffff} : size -1 {lbound = 0x0, ubound = 0xffffffffffffffff} : size -1 bnd3 {lbound = 0x0, ubound = 0xffffffffffffffff} : size -1 {lbound = 0x0, ubound = 0xffffffffffffffff} : size -1 ``` </details> `info registers <reggroup>` can be used in a similar manner to `drt regroup`(which doesn't work for most groups atm btw) `print $xmm1` lets you print a specific register in a similar manner to `dr reg`. This returns a struct with all display options: ``` $1 = { v4_float = {0, 0, 0, 0}, v2_double = {0, 0}, v16_int8 = {0x0 <repeats 16 times>}, v8_int16 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, v4_int32 = {0x0, 0x0, 0x0, 0x0}, v2_int64 = {0x0, 0x0}, uint128 = 0x0 } ``` #### GEF (gdb scripts bundle) Has a telescope view similar to r2 ![](https://i.imgur.com/22ZhDPQ.png) ### LLDB <details> <summary>Full register view</summary> ``` (lldb) register read --all General Purpose Registers: rax = 0x00005555555546f0 main`main at test.c:47 rbx = 0x0000000000000000 rcx = 0x0000000000000100 rdx = 0x00007fffffffe3b8 rdi = 0x0000000000000001 rsi = 0x00007fffffffe3a8 rbp = 0x0000000000000001 rsp = 0x00007fffffffe2b0 r8 = 0x00007ffff79f0d80 libc.so.6`initial r9 = 0x0000000000000000 r10 = 0x0000000000000006 r11 = 0x00007ffff7b3abc0 libstdc++.so.6`std::num_get<wchar_t, std::istreambuf_iterator<wchar_t, std::char_traits<wchar_t> > > const& std::use_facet<std::num_get<wchar_t, std::istr eambuf_iterator<wchar_t, std::char_traits<wchar_t> > > >(std::locale const&) r12 = 0x0000555555554790 main`_start r13 = 0x00007fffffffe3a0 r14 = 0x0000000000000000 r15 = 0x0000000000000000 rip = 0x00005555555546f6 main`main + 6 at test.c:48 rflags = 0x0000000000000246 cs = 0x0000000000000033 fs = 0x0000000000000000 gs = 0x0000000000000000 ss = 0x000000000000002b ds = 0x0000000000000000 es = 0x0000000000000000 eax = 0x555546f0 ebx = 0x00000000 ecx = 0x00000100 edx = 0xffffe3b8 edi = 0x00000001 esi = 0xffffe3a8 ebp = 0x00000001 esp = 0xffffe2b0 r8d = 0xf79f0d80 r9d = 0x00000000 r10d = 0x00000006 r11d = 0xf7b3abc0 r12d = 0x55554790 r13d = 0xffffe3a0 r14d = 0x00000000 r15d = 0x00000000 ax = 0x46f0 bx = 0x0000 cx = 0x0100 dx = 0xe3b8 di = 0x0001 si = 0xe3a8 bp = 0x0001 sp = 0xe2b0 r8w = 0x0d80 r9w = 0x0000 r10w = 0x0006 r11w = 0xabc0 r12w = 0x4790 r13w = 0xe3a0 r14w = 0x0000 r15w = 0x0000 ah = 0x46 bh = 0x00 ch = 0x01 dh = 0xe3 al = 0xf0 bl = 0x00 cl = 0x00 dl = 0xb8 dil = 0x01 sil = 0xa8 bpl = 0x01 spl = 0xb0 r8l = 0x80 r9l = 0x00 r10l = 0x06 r11l = 0xc0 r12l = 0x90 r13l = 0xa0 r14l = 0x00 r15l = 0x00 Floating Point Registers: fctrl = 0x0000 fstat = 0x0000 ftag = 0x0000 fop = 0x0000 fiseg = 0x00000000 fioff = 0x00000000 foseg = 0x00000000 fooff = 0x00000000 mxcsr = 0x00001f80 mxcsrmask = 0x0000ffff st0 = {0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00} st1 = {0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00} st2 = {0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00} st3 = {0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00} st4 = {0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00} st5 = {0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00} st6 = {0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00} st7 = {0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00} mm0 = 0x0000000000000000 mm1 = 0x0000000000000000 mm2 = 0x0000000000000000 mm3 = 0x0000000000000000 mm4 = 0x0000000000000000 mm5 = 0x0000000000000000 mm6 = 0x0000000000000000 mm7 = 0x0000000000000000 xmm0 = {0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00} xmm1 = {0x00 0x00 0xff 0x00 0x00 0x00 0x00 0x00 0xff 0xff 0x00 0x00 0x00 0x00 0x00 0x00} xmm2 = {0x7d 0x00 0x00 0x00 0x7e 0x00 0x00 0x00 0x7f 0x00 0x00 0x00 0x80 0x00 0x00 0x00} xmm3 = {0x30 0xfc 0x9e 0xf7 0xff 0x7f 0x00 0x00 0x30 0xfc 0x9e 0xf7 0xff 0x7f 0x00 0x00} xmm4 = {0x0e 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x0e 0x00 0x00 0x00 0x00 0x00 0x00 0x00} xmm5 = {0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00} xmm6 = {0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff} xmm7 = {0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00} xmm8 = {0x20 0x04 0x9f 0xf7 0xff 0x7f 0x00 0x00 0x20 0x04 0x9f 0xf7 0xff 0x7f 0x00 0x00} xmm9 = {0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00} xmm10 = {0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00} xmm11 = {0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00} xmm12 = {0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00} xmm13 = {0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00} xmm14 = {0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00} xmm15 = {0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00} Advanced Vector Extensions: ymm0 = {0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00} ymm1 = {0x00 0x00 0xff 0x00 0x00 0x00 0x00 0x00 0xff 0xff 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00} ymm2 = {0x7d 0x00 0x00 0x00 0x7e 0x00 0x00 0x00 0x7f 0x00 0x00 0x00 0x80 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00} ymm3 = {0x30 0xfc 0x9e 0xf7 0xff 0x7f 0x00 0x00 0x30 0xfc 0x9e 0xf7 0xff 0x7f 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00} ymm4 = {0x0e 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x0e 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00} ymm5 = {0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00} ymm6 = {0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00} ymm7 = {0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00} ymm8 = {0x20 0x04 0x9f 0xf7 0xff 0x7f 0x00 0x00 0x20 0x04 0x9f 0xf7 0xff 0x7f 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00} ymm9 = {0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00} ymm10 = {0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00} ymm11 = {0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00} ymm12 = {0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00} ymm13 = {0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00} ymm14 = {0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00} ymm15 = {0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00} Memory Protection Extensions: bnd0 = {0x0000000000000000 0x0000000000000000} bnd1 = {0x0000000000000000 0x0000000000000000} bnd2 = {0x0000000000000000 0x0000000000000000} bnd3 = {0x0000000000000000 0x0000000000000000} bndcfgu = {0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00} bndstatus = {0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00} ``` </details> * You can set register format printing for all registers (similar to manual `p` per register with a C style cast in gdb) to: <details> <summary>Register formats</summary> ``` 'B' or "boolean" 'b' or "binary" 'y' or "bytes" 'Y' or "bytes with ASCII" 'c' or "character" 'C' or "printable character" 'F' or "complex float" 's' or "c-string" 'd' or "decimal" 'E' or "enumeration" 'x' or "hex" 'X' or "uppercase hex" 'f' or "float" 'o' or "octal" 'O' or "OSType" 'U' or "unicode16" "unicode32" 'u' or "unsigned decimal" 'p' or "pointer" "char[]" "int8_t[]" "uint8_t[]" "int16_t[]" "uint16_t[]" "int32_t[]" "uint32_t[]" "int64_t[]" "uint64_t[]" "float16[]" "float32[]" "float64[]" "uint128_t[]" 'I' or "complex integer" 'a' or "character array" 'A' or "address" "hex float" 'i' or "instruction" 'v' or "void" ``` </details> Resulting in: <details> <summary>Formatted register output</summary> ``` register read --format float64[] General Purpose Registers: rax = {4.63557053837459e-310} main`main at test.c:47 rbx = {0} rcx = {1.26480805335359e-321} rdx = {6.9533558074773e-310} rdi = {4.94065645841247e-324} rsi = {6.95335580747651e-310} rbp = {4.94065645841247e-324} rsp = {6.95335580746426e-310} r8 = {6.95334886269177e-310} libc.so.6`initial r9 = {0} r10 = {2.96439387504748e-323} r11 = {6.9533489294515e-310} libstdc++.so.6`std::num_get<wchar_t, std::istreambuf_iterator<wchar_t, std::char_traits<wchar_t> > > const& std::use_facet<std::num_get<wchar_t, std::istreambuf_iterator<wchar_t, std::char_traits<wchar_t> > > >(std::locale const&) r12 = {4.63557053838249e-310} main`_start r13 = {6.95335580747612e-310} r14 = {0} r15 = {0} rip = {4.63557053837489e-310} main`main + 6 at test.c:48 rflags = {2.87546205879605e-321} cs = {2.51973479379036e-322} fs = {0} gs = {0} ss = {2.12448227711736e-322} ds = {0} es = {0} ``` </details> ### GDBtui Godawful program but here you go ![](https://i.imgur.com/E5c1sfL.png) ### GDBgui ### IDA By default, IDA shows the General Registers view that looks like the image below. It will show all the General Registers as well az flags and more bollean registers to the right. IDA shows an easy-to-read relative-names (unlike our ugly verbosy-can't-never-read telescoping). A little button is used to jump to the address on a simple click. ![](https://i.imgur.com/DvA8qSQ.png) On right click, IDA will show a contesxt menu with several checkboxes. The special registers (mmx, xmm, fpu, ...) are there, but others (ymm, zmm,...) are only available on recent versions. Right clicking on a register will show this context menu that will help modifying it easily. Double click on a register will open a dialog in which the user can edit the value. ![](https://i.imgur.com/6FiGWvr.png) When a register is modified by the user, its color becoms purple. When stepping, registers whose their value changed will be highlighted with blue to indicate. The right panel can be used to easily toggle the different flags. This can be done by pressing them and then <kbd>space</kbd> to toggle, or right clicking to see this menu ![](https://i.imgur.com/8un7YrB.png) XMM Registers: ![](https://i.imgur.com/U88a6r8.png) MMX Registers: ![](https://i.imgur.com/XwD9nJj.png) FPU Registers: ![](https://i.imgur.com/Hrpn6Zg.png) **Plugins** [dereferencing](https://github.com/danigargu/deREferencing) - A very nice plugin for IDA will show dereferences ![](https://i.imgur.com/peCrUk5.png) ### Ollydbg vanilla ### WinDBG * basic UI ![](https://i.imgur.com/ZH6CO6x.png) ### Visual Studio * Show/hide groups of registers for reducing clutter ### x64dbg * Ability to copy all * Copy per register value * Copy symbol value * Highlight * Zero/Increment * Push/Pop * Tooltips ![](https://i.imgur.com/JnOHGgS.png) * Follow in dump/Disassembler/Memory Map/Stack * Right click to change display mode of a register (change simd to float for example) * Toggle for flags * 2 views, one compact - one full with all the registers * (FPU) XMM, YMM, DRR, MM, Mx, x87, ST, *S, LastError, LastStatus * FLAGS separated + RFLAGS and double click to swap value 1/0 * Telsecoping * Color to highlight changed one's * Edit registry ![](https://i.imgur.com/zPMKxbp.png) ### Summary * [+] Done * [C-] Missing in Cutter * [C*] Broken/partial in Cutter * [R-] Missing in R2 * [R*] Broken/partial in R2 * [R?] Requires testing * [?] unclear * Read/Write * [+] regular registers * [C-/R-] read vector registers - for now drml/drmf, drmyq(ymm), nothing is available for zmm registers yet * Doesn't work in remote debug * [R-] write vector registers * [+] Navigate in memory views * [C-] Display options (hex,dec,float, double) * [C-] Flags * [R-?] Array format for vector registers * [R-] Better remote register sync with flags and structs * [ ] Telescoping * [ ] Solve the performance issue by using Async fetching of the values * [ ] Colormap [see Dereferencing plugin for IDA] * [+] Highlight registers that changed in the previous step * [ ] Edit the registry * [ ] Get registers comment (drC) via tooltip * [ ] We need to improve the describing text from r2 * [ ] Export the entire register view * [ ] Double click to seek * [ ] Right click -> Highlight to highlight tokens across all disassembly (and graph) views. ## Stack ### gdb manual examine - x/20xw $sp ``` 0x7fffffffcc58: 0xf790a608 0x00007fff 0x00000000 0x00000000 0x7fffffffcc68: 0x00000014 0x00000000 0xffffcc80 0x00007fff 0x7fffffffcc78: 0xf790a686 0x00007fff 0xffffcca0 0x00007fff 0x7fffffffcc88: 0xf6863f5e 0x00007fff 0x00000000 0x00000000 0x7fffffffcc98: 0x5575d970 0x0000001a 0xffffcde0 0x00007fff ``` info frame - show stack start/end/args/locals pointers ``` Stack level 2, frame at 0x7fffffffe2a0: rip = 0x555555554cfd in main (test.c:48); saved rip = 0x7ffff71eeb97 caller of frame at 0x7fffffffe240 source language c++. Arglist at 0x7fffffffe238, args: argc=<optimized out>, argv=<optimized out> Locals at 0x7fffffffe238, Previous frame's sp is 0x7fffffffe2a0 Saved registers: rbx at 0x7fffffffe270, rbp at 0x7fffffffe278, r12 at 0x7fffffffe280, r13 at 0x7fffffffe288, r14 at 0x7fffffffe290, rip at 0x7fffffffe298 ``` Can use `frame [num]` to go up and down the stack and show different frame info ### gef Basic view with telescoping similar to r2 ``` 0x00007fffffffcc78│+0x20: 0x00007ffff790a686 → <r_sys_stop+37> test eax, eax 0x00007fffffffcc80│+0x28: 0x00007fffffffcca0 → 0x00007fffffffcde0 → 0x00007fffffffce20 → 0x00007fffffffceb0 → 0x00007fffffffcec0 → 0x00007fffffffcef0 → 0x00007fffffffcf40 0x00007fffffffcc88│+0x30: 0x00007ffff6863f5e → <r_cons_controlz+42> mov eax, 0x0 0x00007fffffffcc90│+0x38: 0x0000000000000000 0x00007fffffffcc98│+0x40: 0x0000001a5575d970 0x00007fffffffcca0│+0x48: 0x00007fffffffcde0 → 0x00007fffffffce20 → 0x00007fffffffceb0 → 0x00007fffffffcec0 → 0x00007fffffffcef0 → 0x00007fffffffcf40 → 0x00007fffffffdf80 ``` ### lldb frame variable - Show variables for the current stack frame. Defaults to all arguments and local variables in scope. Names of argument, local, file static and file global variables can be specified. Children of aggregate variables can be specified such as 'var->child.x'. ``` (pthread_t) threadid = 140737335453440 (void **) thread_return = 0x0000000000000000 (const timespec *) abstime = 0x0000000000000000 (bool) block = true (pthread *) pd = 0x00007ffff6e2e700 (pthread *) self = <variable not available> (int) result = 0 (_pthread_cleanup_buffer) _buffer = { __routine = 0x00007ffff7bbeb90 (libpthread.so.0`cleanup at pthread_join_common.c:30) __arg = 0x00007ffff6e2ed28 __canceltype = -7552 __prev = 0x0000000000000000 } (int) oldtype = 0 (pid_t) __tid = 34503 ``` Can use `up`\`down` or `frame select` to go up and down the stack and show variables ### x64dbg Has a dedicated window that shows the current stack. Telescoping only seems to work for strings. ![](https://i.imgur.com/dwxRQ64.png) Right clicking on an address allows freezing the stack(Only freezes the GUI but it's a cool idea that we can copy :)), pushing/poping values, modifying values, adding a watchpoint ![](https://i.imgur.com/RXIYRfi.png) Double-click shows Stack delta ![](https://i.imgur.com/AFUUbi1.png) ### IDA INFO: I just revealed that IDA's Stack view is basically their Hexdump view with different defaults (number of columns, size of data, so names, highlight SPm add two actions to jump to ESP and EBP). The most basic Stack view on IDA looks like this: ![](https://i.imgur.com/vpwWE5Y.png) It shows a simple table of [addr | value | name ] where it shows the name and relavtive offset of the current value. Stack Pointer is highlighted in blue and stays like this no matter where is the focus of the cursor. It also lets you to choose the number of columns and the daat format displayed. ![](https://i.imgur.com/kjpE6js.png) Clicking on any valid address or name will jump to this address in the disassembly window. **Plugins** [dereferencing](https://github.com/danigargu/deREferencing) - A very nice plugin for IDA will show dereferences ![](https://i.imgur.com/lxfs9vZ.png) ### Summary * [+] Done * [C-] Missing in Cutter * [C*] Broken/partial in Cutter * [R-] Missing in R2 * [R*] Broken/partial in R2 * [R?] Requires testing * [?] unclear --- * [C-] Synchronize memory widget with register (RSP, RBP, ...) * [C*] Telescoping * [C*] Currently slows down out debugging sessions on Cutter * [C*] Better formatting of the telescoping * [ ] View frames, local variables, type information * [ ] Push and Pop [Q\D]Words from\to the stack (Worth consider adding multiple values to the stack and not only one) * [ ] Edit the values * [ ] Freezing the stack (GUI? The stack in general?) * [ ] Highlight the SP * [ ] Jump to SP or BP ## Callstack Backtrace ### gdb backtrace ``` #0 0x00007ffff7bbed2d in __GI___pthread_timedjoin_ex (threadid=0x7ffff6e2e700, thread_return=0x0, abstime=0x0, block=<optimized out>) at pthread_join_common.c:89 #1 0x00007ffff78a6aa3 in std::thread::join() () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6 #2 0x0000555555554cfd in main (argc=<optimized out>, argv=<optimized out>) at test.c:48 ``` ### lldb Backtrace of all threads(or a requested one) with stop reasons thread backtrace all ``` * thread #1, name = 'main', stop reason = signal SIGSTOP frame #0: 0x00007ffff7bbed2d libpthread.so.0`__GI___pthread_timedjoin_ex(threadid=140737335453440, thread_return=0x0000000000000000, abstime=0x0000000000000000, block=true) at pthread_join_common.c:89 frame #1: 0x00007ffff78a6aa3 libstdc++.so.6`std::thread::join() + 19 frame #2: 0x0000555555554cfd main`main(argc=<unavailable>, argv=<unavailable>) at test.c:48 * frame #3: 0x00007ffff71eeb97 libc.so.6`__libc_start_main(main=(main`main at test.c:36), argc=1, argv=0x00007fffffffe3b8, init=<unavailable>, fini=<unavailable>, rtld_fini=<unavailable>, stack_end=0x00007fffffffe3a8) at libc-start.c:310 frame #4: 0x0000555555554e0a main`_start + 42 thread #2, name = 'main' frame #0: 0x00007ffff72b19d0 libc.so.6`__GI___nanosleep(requested_time=0x00007ffff6e2de90, remaining=0x00007ffff6e2de90) at nanosleep.c:28 frame #1: 0x00007ffff72b18aa libc.so.6`__sleep(seconds=0) at sleep.c:55 frame #2: 0x0000555555554f1a main`thread_func2() at test.c:24 frame #3: 0x00007ffff78a6870 libstdc++.so.6`___lldb_unnamed_symbol609$$libstdc++.so.6 + 16 frame #4: 0x00007ffff7bbd6db libpthread.so.0`start_thread(arg=0x00007ffff6e2e700) at pthread_create.c:463 frame #5: 0x00007ffff72ee88f libc.so.6`__GI___clone at clone.S:95 ``` You can also edit the info shown in the backtrace to show any info lldb has https://lldb.llvm.org/use/formatting.html ### x64dbg Very basic info with a preview of the address ![](https://i.imgur.com/d8XfOMN.png) Right clicking on an entry allows you to show the "suspected call stack" with more detailed information ![](https://i.imgur.com/X5oEfG2.png) ### IDA ![](https://i.imgur.com/xpNaYei.png) Very basic view, clicking on the line jumps to the address ### Summary * Address * Function name+offset * Module name * should show name for functions from loaded dynamic libraries * Easy way of viewing each position in disassembly view * [ ] BUG: Double clicking a cell will edit it (shouldn't eb editable) * [ ] what is "suspected call stack" in x64dbg, and do we need it? * [ ] Stop reason (lldb, gdb) * [ ] Show variable that were passed to each function * [ ] Make other threads' backtrace more accessible (show bt of all threads, show bt of thread X, etc...) * [ ] Add something for `dbta` that shows the layout. * [ ] Export to txt, SVG * [ ] Add Frames widget that will be accessible from Stack and Backtrace widgets via right-click ## Tracepoints/checkpoints A form of reverse debugging that allows returning the process to a previous state. ### R2 Same as the tracepoints used in reverse debugging * Create with `dts+` * `dts` to list * `dtsC` to add a comment * load/save from file with `dtsf`/`dtsl` How do you jump back to the tracepoint without ### GDB * Checkpoints https://sourceware.org/gdb/onlinedocs/gdb/Checkpoint_002fRestart.html * Fork of process at a requested point - almost ideal restoration of previous state, a forked process can save the state of user memory and registers, as well as some subset of external (kernel) state. * `checkpoint` to save, `info checkpoints` for a list, `restart checkpoint-id` to return, `delete checkpoint-id` to remove. ### LLDB Unavailable ## Tracing Wasn't this discussed in breakpoints? ### R2 `dt` seems to fit the description but it's unclear how to get it to work ### GDB Easily achieved with breakpoint functionality but there's a lighter tracepoint concept for expressions(all instances) and it only works with remote targets for some reason. * Only works on single thread targets * Documentation says it only works on remote target * Set tracepoints with `trace [expression]`, doesn't work on addresses * List with `tracepoints`/`info b` * See number of hits with `tfind` ``` Found trace frame 0, tracepoint 2 #0 0x00007ffff72b19d0 in __GI___nanosleep (requested_time=<unavailable>, remaining=<unavailable>) at ../sysdeps/unix/sysv/linux/nanosleep.c:28 28 in ../sysdeps/unix/sysv/linux/nanosleep.c ``` * Save with `tdump` * `teval` evaluate expression on tracepoint hit * `tstop`\`tstart` to stop/start collection ### LLDB Unavailable ### x64dbg https://help.x64dbg.com/en/latest/commands/tracing/ ### IDA -*tested on IDA 7.0 and not IDA 7.4*- IDA's tracing is quite useful. The most simple option is to trace a single instruction by right clicking and choosing the apropriate option from the context menu. If the instruction will hit, IDA will color it with a soft yellow and add an entry to the Trace window, a deidacted widget. More complex tracing are [tracing of functions](https://www.hex-rays.com/products/ida/support/idadoc/1447.shtml), [basic blocks](https://www.hex-rays.com/products/ida/support/idadoc/1628.shtml), and [instruction tracing](https://www.hex-rays.com/products/ida/support/idadoc/1446.shtml). Read the links to learn more. IDA has a rich Tracing Options dialog with the following features: ![](https://i.imgur.com/ddS4KcF.png) The following image will show the Graph and graph overview as a result of Functions tracing. As you can see, the `call`s are highlighted. In the mini-graph, the blocks that were traced are highlighted. ![](https://i.imgur.com/gE0wliJ.png) Tracing basic blocks: ![](https://i.imgur.com/5dpB1kg.png) The trace window looks like this: ![](https://i.imgur.com/TpU6j4J.png) It also allows to save or import a trace-file ## Threads ### Visual Studio * View - Thread ID, Category, Name, Location, Priority, Afinity Mask, Suspend Count, Process name, process id * Threads from all processes grouped by process id * Freeze threads - frozen't threads aren't resumed when doing continue * search thread by callstack * show threads in source - source(dissasembly) shows PC indicator for all threads not just current one * view callstacks inline with thread list ![](https://i.imgur.com/vetiUCB.png) ### QtCreator ![](https://i.imgur.com/4VFaHgD.png) ### Summary * Status * PID * name * Module+function - Pause/resume certain threads while others ar running to prevent them from interfering with part being debugged ## Processes * in ideal case switching as easy as between threads - might be difficult to achieve due to analysis ![](https://i.imgur.com/wW8KVyX.jpg) ## Disassembly View ## Graph View ## Dump ## Memory Map ### R2 `dm` ``` 0x000055a3fc525000 - 0x000055a3fc527000 - usr 8K s r-x /home/yossi/workspace/tests/main /home/yossi/workspace/tests/main ; class.vtable_for_std::thread::_State_impl_std::thread::_Invoker_std 0x000055a3fc726000 - 0x000055a3fc728000 - usr 8K s rw- /home/yossi/workspace/tests/main /home/yossi/workspace/tests/main ; map.home_yossi_workspace_tests_main.rw 0x00007fa8076c0000 - 0x00007fa8076e7000 * usr 156K s r-x /lib/x86_64-linux-gnu/ld-2.27.so /lib/x86_64-linux-gnu/ld-2.27.so ; map.lib_x86_64_linux_gnu_ld_2.27.so.r_x 0x00007fa8078e7000 - 0x00007fa8078e9000 - usr 8K s rw- /lib/x86_64-linux-gnu/ld-2.27.so /lib/x86_64-linux-gnu/ld-2.27.so ; map.lib_x86_64_linux_gnu_ld_2.27.so.rw 0x00007fa8078e9000 - 0x00007fa8078ea000 - usr 4K s rw- unk0 unk0 ; map.unk0.rw 0x00007ffcf935d000 - 0x00007ffcf937e000 - usr 132K s rw- [stack] [stack] ; map.stack_.rw 0x00007ffcf9391000 - 0x00007ffcf9394000 - usr 12K s r-- [vvar] [vvar] ; map.vvar_.r 0x00007ffcf9394000 - 0x00007ffcf9396000 - usr 8K s r-x [vdso] [vdso] ; map.vdso_.r_x 0xffffffffff600000 - 0xffffffffff601000 - usr 4K s r-x [vsyscall] [vsyscall] ; map.vsyscall_.r_x ``` ### gdb `info proc map` (truncated) ``` 0x7ffff7bab000 0x7ffff7bb6000 0xb000 0x0 0x7ffff7bb6000 0x7ffff7bd0000 0x1a000 0x0 /lib/x86_64-linux-gnu/libpthread-2.27.so 0x7ffff7bd0000 0x7ffff7dcf000 0x1ff000 0x1a000 /lib/x86_64-linux-gnu/libpthread-2.27.so 0x7ffff7dcf000 0x7ffff7dd0000 0x1000 0x19000 /lib/x86_64-linux-gnu/libpthread-2.27.so 0x7ffff7dd0000 0x7ffff7dd1000 0x1000 0x1a000 /lib/x86_64-linux-gnu/libpthread-2.27.so 0x7ffff7dd1000 0x7ffff7dd5000 0x4000 0x0 0x7ffff7dd5000 0x7ffff7dfc000 0x27000 0x0 /lib/x86_64-linux-gnu/ld-2.27.so 0x7ffff7f8d000 0x7ffff7fa5000 0x18000 0x0 /home/yossi/workspace/tests/main 0x7ffff7fa5000 0x7ffff7fbe000 0x19000 0x0 /usr/local/share/radare2/4.2.0-git/opcodes/x86.sdb 0x7ffff7fbe000 0x7ffff7fcc000 0xe000 0x0 0x7ffff7fe0000 0x7ffff7fe7000 0x7000 0x0 /usr/local/share/radare2/4.2.0-git/syscall/linux-x86-64.sdb 0x7ffff7fe8000 0x7ffff7fef000 0x7000 0x0 /usr/local/share/radare2/4.2.0-git/syscall/linux-x86-64.sdb 0x7ffff7ff7000 0x7ffff7ffa000 0x3000 0x0 [vvar] 0x7ffff7ffa000 0x7ffff7ffc000 0x2000 0x0 [vdso] 0x7ffff7ffc000 0x7ffff7ffd000 0x1000 0x27000 /lib/x86_64-linux-gnu/ld-2.27.so 0x7ffff7ffd000 0x7ffff7ffe000 0x1000 0x28000 /lib/x86_64-linux-gnu/ld-2.27.so 0x7ffff7ffe000 0x7ffff7fff000 0x1000 0x0 0x7ffffffde000 0x7ffffffff000 0x21000 0x0 [stack] 0xffffffffff600000 0xffffffffff601000 0x1000 0x0 [vsyscall] ``` `info files` to show loaded file sections which is more of an expanded memory view ``` 0x00007ffff7633a04 - 0x00007ffff7633a0d is .fini in /usr/local/lib/libr_main.so 0x00007ffff7633a10 - 0x00007ffff763b948 is .rodata in /usr/local/lib/libr_main.so 0x00007ffff763b948 - 0x00007ffff763bcc4 is .eh_frame_hdr in /usr/local/lib/libr_main.so 0x00007ffff763bcc8 - 0x00007ffff763cacc is .eh_frame in /usr/local/lib/libr_main.so 0x00007ffff783cc40 - 0x00007ffff783cc48 is .init_array in /usr/local/lib/libr_main.so 0x00007ffff783cc48 - 0x00007ffff783cc50 is .fini_array in /usr/local/lib/libr_main.so 0x00007ffff783cc50 - 0x00007ffff783cf70 is .dynamic in /usr/local/lib/libr_main.so 0x00007ffff783cf70 - 0x00007ffff783d000 is .got in /usr/local/lib/libr_main.so 0x00007ffff783d000 - 0x00007ffff783dc90 is .got.plt in /usr/local/lib/libr_main.so 0x00007ffff783dca0 - 0x00007ffff783df11 is .data in /usr/local/lib/libr_main.so 0x00007ffff783df20 - 0x00007ffff789f190 is .bss in /usr/local/lib/libr_main.so 0x00007ffff7222270 - 0x00007ffff7222294 is .note.gnu.build-id in /lib/x86_64-linux-gnu/libc.so.6 0x00007ffff7222294 - 0x00007ffff72222b4 is .note.ABI-tag in /lib/x86_64-linux-gnu/libc.so.6 0x00007ffff72222b8 - 0x00007ffff7225ee8 is .gnu.hash in /lib/x86_64-linux-gnu/libc.so.6 0x00007ffff7225ee8 - 0x00007ffff72339d0 is .dynsym in /lib/x86_64-linux-gnu/libc.so.6 0x00007ffff72339d0 - 0x00007ffff72398ae is .dynstr in /lib/x86_64-linux-gnu/libc.so.6 0x00007ffff72398ae - 0x00007ffff723aaec is .gnu.version in /lib/x86_64-linux-gnu/libc.so.6 0x00007ffff723aaf0 - 0x00007ffff723aef4 is .gnu.version_d in /lib/x86_64-linux-gnu/libc.so.6 0x00007ffff723aef8 - 0x00007ffff723af28 is .gnu.version_r in /lib/x86_64-linux-gnu/libc.so.6 0x00007ffff723af28 - 0x00007ffff7242b78 is .rela.dyn in /lib/x86_64-linux-gnu/libc.so.6 0x00007ffff7242b78 - 0x00007ffff7242fc8 is .rela.plt in /lib/x86_64-linux-gnu/libc.so.6 ``` ### lldb Couldn't find anything useful in apropos and google, `image list` seems to be the closest with loaded lib info ``` [ 0] 3E8B43FF-0DAF-9DA9-F550-3910B5ABD645-1AAA1202 /home/yossi/workspace/tests/main [ 1] 64DF1B96-1228-382F-E186-84249ED800AB-1DCEAAD4 /lib/x86_64-linux-gnu/ld-2.27.so /usr/lib/debug/lib/x86_64-linux-gnu/ld-2.27.so [ 2] CB3D0602-91CD-129C-4F6F-B35E537B9822-932FB871 0x00007ffff7ffa000 [vdso] (0x00007ffff7ffa000) [ 3] 28C6AADE-70B2-D40D-1F0F-3D0A1A0CAD1A-B816448F /lib/x86_64-linux-gnu/libpthread.so.0 /usr/lib/debug/.build-id/28/c6aade70b2d40d1f0f3d0a1a0cad1ab816448f.debug [ 4] 3511DF4E-2083-54E8-1617-377CC524CA31-6DDB192E /usr/lib/x86_64-linux-gnu/libstdc++.so.6 [ 5] DFEEFA01-D550-CA5E-8922-23A232A3C8AF-C85C3E66 /lib/x86_64-linux-gnu/libgcc_s.so.1 [ 6] B417C0BA-7CC5-CF06-D1D1-BED6652CEDB9-253C60D0 /lib/x86_64-linux-gnu/libc.so.6 /usr/lib/debug/lib/x86_64-linux-gnu/libc-2.27.so [ 7] A33761AB-8FB4-8531-1B3C-85BF4253099D-7CABE653 /lib/x86_64-linux-gnu/libm.so.6 /usr/lib/debug/lib/x86_64-linux-gnu/libm-2.27.so ``` `image dump sections` for similar output to gdb's info files that shows each module's sections Since everything is symbolic they probably use strings instead of addresses so it doesn't matter where the libs are loaded. ### x64dbg Basic view with detailed section info on each lib like in gdb/lldb ![](https://i.imgur.com/NXOyBsJ.png) Interesting right click options including dumping memory, allocating memory(why?), changing permissions, creating a virtual module(why?) ![](https://i.imgur.com/eXcr2l4.png) ### IDA IDA has a view called Program Segmentation. The screenshot below shows this view which looks just a bit more detailed than x64dbg's. ![](https://i.imgur.com/1UvzMq8.png) A context menu looks like this: ![](https://i.imgur.com/DcVDdkW.png) Interesting feature: - add a new segment ![](https://i.imgur.com/XyKt8Js.png) - Editing a segment ![](https://i.imgur.com/n22bHHF.png) - Break on access Will set a read-HW breakpoint of size `length_of(segment)`. I use it a lot to break when shellcode is being manipulated on a segment - Move segment (or multiple) to a new address ![](https://i.imgur.com/zWDDVOp.png) ### Process hacker 2 Upon right clicking on a Process, PH will show us this view in the Memory tab: ![](https://i.imgur.com/Kc6fBft.png) Umlike most other GUIs, in PH, there is a tree that contain multiple items inside an allocated map (e.g see the expanded value). Right click on a specific map will show this context menu ![](https://i.imgur.com/Uz02NYz.png) Most interesting items are: - Save... - will allow to save a dump of the memory map - Change protection - the user can change the protection of the map to either one of the following options: ![](https://i.imgur.com/dV1c2ZU.png) - Free ### Summary * [R*] Output - Current memory map widget info seems to be competitive, we can add section info for each loaded lib. * [C-/R-?] x64dbg right click options? * Allocate/free memory * Set memory page permissions * Dump memory * Add virtual module * [C-/R-?] Right click to analyze loaded maps * [C-] Right click to download pdb(/dwarf? doesn't anal apply it automatically?) for loaded libs * [C-] Segway to heap view(different widget we haven't discussed yet) through memory map view * [C-/R-?] Right click -> Break on [acess\read\write] * [C-] Add memory `x` breakpoint on the first byte of the section * [C-/R+] Right click -> Show strings in this memory map * [C-/R?] Change memory protection * [C-] Search in > memory map. need to add a list of available maps. * Also, cross l;ink from the Memory maps widget. Right Click -> Search in map; ## Symbols ## Commands ## Signal handling * stop/nostop * pass/ignore * print? - gdb has this * send manually ![](https://i.imgur.com/V8NcKGR.jpg) ## Reverse debugging ### R2 * dts+ - start a recording * dsb - step back * dcb - continue back * Breakpoints are hit backwards * Seems to only restore reg arena without much thought beyond that Issues after more than two-three steps back. Doesn't work well at all with emulation. ### GDB * "target record" ("record") - Start process record/replay (ie. start recording the subsequent execution of the child process). You must start debugging the program (with the "run" command) before using this command to start recording. You can start recording at any point after the child process has been started (eg. at a breakpoint). * "record stop" - Stop process record/replay (ie. cease recording the program execution), and discard any existing execution log. The child process is not terminated, and you may continue to debug it normally. * "record goto" - can switch to a point in the execution directly. * "record delete" - Discard the existing execution log, and begin recording a new log. * "set record insn-number-max" - Set the maximum number of instruction executions that will be recorded (ie. the size of the process record log buffer). Zero means unlimited. Default is 200,000. * "set record stop-at-limit" - Controls the behavior when the buffer becomes full. If "on", gdb will stop and ask the user what to do. If "off", the buffer acts as a circular buffer, deleting the oldest records to make room for new ones. Default is "on". * "info record insn-number" - This command will show how many instructions are currently saved in the execution log. * "info record" - Show various statistics about the state of process record and its in-memory execution log buffer. * reverse-continue ('rc') - Continue program being debugged but run it in reverse * reverse-finish - Execute backward until just before the selected stack frame is called * reverse-next ('rn') - Step program backward, proceeding through subroutine calls. * reverse-nexti ('rni') - Step backward one instruction, but proceed through called subroutines. * reverse-step ('rs') - Step program backward until it reaches the beginning of a previous source line * reverse-stepi - Step backward exactly one instruction * set exec-direction (forward/reverse) - Set direction of execution. All subsequent execution commands (continue, step, until etc.) will run the program being debugged in the selected direction. * Breakpoints and watchpoints will work in reverse -- allowing you for instance to proceed directly to the previous point at which a variable was modified. * Per syscall record handling - warnings if the syscall might break something like with munmap https://github.com/bminor/binutils-gdb/blob/master/gdb/linux-record.c#L671 * GDB is supposed to have the ability to restore io but I couldn't find any documentation, I assume it's a part of the syscall handling, need to check * Save and Restore execution logs - dump an execution log (together with a core file image) into a modified core file that can be loaded and debugged again later. ~~* Reverse debug is supported over remote connections.~~ The remote commands for rs and rc exist but it's not implemented in gdbserver ### LLDB Unavailable ### QIRA https://qira.me very hard to build from source due to qemu issues and it seems to be unmaintained. Awful interface, you use arrows to move up and down, double click to continue to an address. The main advantage is that it runs in an emulated environment so the entire memory snapshot can be restored. Has an IDA plugin for remote debug which is probably a better way to integrate this type of VM based debugging. ### RR https://rr-project.org/ * User-space memory and register values are preserved exactly * File descriptors are not opened, signal handlers are not installed, and filesystem operations are not performed. Instead the recorded user-space visible effects of those operations, and future related operations, are replayed. ### Tetrane https://www.tetrane.com/#technology ### Visual Studio ## Summary R2 reverse debugging barely works and requires a ton of syscall emulation to be on GDB/RR level, it's probably best to focus on integrating gdb/rr remote only reverse debugging. Basic reverse debugging could be provided for native debug but it will have tons of issues. * skip functions - the idea is that there are some functions that don't need to be traced because we will never want to debug them. Omitting these functions from the trace can make the trace smaller, therefore making replay faster and increasing the size of the programs that we can record. ## Other topics * debugger native functionality vs r2 implementation on top of debugger basic functions * access to debugger specific functions # Archive ## Input/Output ### DDD * File -> Attach * Arguments provided from command line at opening * Input/Output - By default, mixed with the console, otherwise Program ⇒ Run in Execution Window ### GDB * Attach -> Command line * Arguments -> command line * Stdin/Stdout -> command line ### GDBgui * Arguments provided from command line at opening * Input/Output - By default, mixed with the console * A small input box for load binary and attach to process ### IDA * Debugger -> Attach -> remote/local Choose process to attach (list of all process (PID and Name) to click on) * Debugger Parameters for EXE/DLL have to be given completly * Input/Output - in the terminal ### Ollydbg vanilla * File -> Attach * Call DLL exports * Debug -> Arguments * stdin/stdout is handled by the terminal running the program ### WinDBG * Debugger -> Attach -> remote/local Choose process to attach (list of all process (Process, PID, Platform, User, Session, Command line) to click on) * Call DLL exports -> manual * argument -> Via command line * stdin/stdout -> arguments ### x64dbg * Debugger -> Attach -> Choose process to attach (list of all process (PID, Name, Title Path) to click on) * Call DLL exports -> debug -> change command line * argument -> debug -> change command line * stdin/stdout is handled by the terminal running the program