The Debugger has an updated and simplified launcher system. A nice collection of basic launchers for our supported platforms are provided out of the box. For Linux, we provide a suite of GDB-based launchers. For macOS, we provide a suite of LLDB-based launchers (though, these work on Linux, too). For Windows, we provide a launcher based on the Windows Debugger (dbgeng.dll and dbgmodel.dll).
Each launcher automates the creation of a Trace RMI acceptor, executes the back-end shell script in a Terminal, then waits for the resulting target trace. In contrast to the previous system, the Terminal is the first and most basic interface presented. Even if just about everything else goes wrong, the terminal should still be faithfully operational:
The Terminal is fully integrated into Ghidra's UI and so can be docked or undocked just like the rest of Ghidra's windows. It provides fairly robust VT-100 emulation. Thus, the user experience from the Terminal is nearly identical to using the same debugger outside of Ghidra. This terminal-first approach also ensures that you interact with the target application's standard I/O. This was not possible in the previous system, as we re-implemented the CLI using the back end's execute method. The debugger's (and so also the target's) actual I/O streams were hidden away within a GDB/MI wrapper.
Each launcher script sets up a — usually Python — environment, launches the actual debugger, and provides a sequence of commands for it to load the Trace RMI plugin, connect back to Ghidra, launch the actual target process, and start the target trace. At this point, the plugin generally takes over, reacting to user and target events, accepting front-end requests, and generally keeping Ghidra and the back end synchronized.
The list of launchers can be accessed in either of two places:
1) In the Debugger → Configure and Launch ... menu or more conveniently from the
Launch button in the main toolbar. This is the blue bug
button near the top center. The Configure and Launch ... menu lists all available
launchers. Selecting one will prompt for its options then launch. To re-launch quickly, use the
Launch button. Clicking it will re-launch using the most recent launcher and
configuration for the current program. If this is the first launch of the given program, the
button will instead activate its drop-down menu. The drop-down is also accessible by clicking
the down arrow next to the Launch button. The drop-down lists all launchers that have
been previously configured for the current program. Clicking one will immediately launch the
program without prompting. The Configure and Launch ... sub-menu of the drop-down
functions exactly like in the Debugger menu.
The Terminal provides some fairly standard actions. Other keyboard control sequences, notably CTRL-C, are interpreted by the terminal, rather than Ghidra's action system, to achieve their expected behavior, e.g., interrupt.
This is accessed using the toolbar button or the key sequence CTRL-SHIFT-C. As expected, it copies the current selection to the system clipboard.
This is accessed using the toolbar button or the key sequence CTRL-SHIFT-V. As expected, it pastes the text contents of the system clipboard into the terminal, as if typed.
This is accessed using the local drop-down menu or the key sequence CTRL-SHIFT-F. It displays a dialog for searching the terminal's scrollback buffer.
These actions are accessed using the local drop-down menu or the key sequence CTRL-SHIFT-H or CTRL-SHIFT-G, respectively. They repeat the last search in the forward or backward direction.
This is accessed using the local drop-down menu or the key sequence CTRL-SHIFT-A. It selects all text in the terminal, including its scrollback buffer. If all the text is already selected, then this selects nothing, so that pressing the keystroke twice is effectively "Select None."
This is accessed using the local drop-down menu or the key sequence CTRL-SHIFT-PLUS. It increases the font size for this terminal.
This is accessed using the local drop-down menu or the key sequence CTRL-MINUS. It decreases the font size for this terminal.
This is accessed using the local drop-down menu or the key sequence CTRL-0. It resets the font size for this terminal according to the theme's configuration'.
This action is accessed using the local drop-down menu. It will terminate the Terminal's current session. Exactly what that means is determined by the Terminal's creator. In general, it means to destroy the full debugging session associated with the Terminal. That may cause related terminals, e.g., a secondary terminal for target I/O and associated target traces, to be terminated as well. NOTE: This action is not implied by closing the Terminal window. Closing the window with an active session merely hides it. It can be recalled using the Window → Terminals menu. If the session has already been terminated (indicated by an orange border) then closing the window will, in fact, destroy the Terminal.
The following launchers based on GDB (GNU Debugger) are included out of the box:
This launcher is a Python plugin for GDB, and so is best suited for debugging Linux user-space targets as well as many embedded systems. Please note you may need to obtain a properly-configured build of GDB for your target. If you are working with an embedded system, it is probably safest to install the "multiarch" build of GDB from your package manager.
The plain "gdb" launch script defaults to launching the current program as a user-mode process on the local system. If there is no current program, or if you clear the Image option, this launcher will only start gdb and get it connected to a Ghidra trace. You may then manually start or connect to your target. Note that this may also require manual mapping of your program database(s) to the target memory.
You must have GDB installed on the local system, and it must embed the Python 3 interpreter. If you have access to PyPI, setting up your Python 3 environment is done using Pip. Please note the version specifier for Protobuf.
python3 -m pip install psutil protobuf==3.20.3
If you are offline, or would like to use our provided packages, we still use Pip, but with a more complicated invocation:
cd /path/to/ghidra_ version/Ghidra/Debug python3 -m pip install --no-index -f Debugger-rmi-trace/pypkg/dist -f Debugger-agent-gdb/pypkg/dist psutil protobuf
Beware that GDB may embed a different Python interpreter than your system's default. If you are still getting import errors, check the version that GDB embeds:
(bash)$ gdb (gdb) python-interactive >>> import sys >>> sys.version
Note the version and ensure that you are invoking Pip with that version. Supposing sys.version indicates 3.10, you should invoke Pip using python3.10 -m pip.
Warning: Modern Linux distributions are beginning to adopt PEP 668, which prevents installation of Python packages outside of a virtual environment (venv) even for non-root user accounts. Unfortunately, gdb does not seem to honor the currently activated venv, and so such configurations are not officially supported. You may be able to work around this by modifying the PYTHONPATH lines of the launcher script, but your mileage may vary. For now, we recommend using the --break-system-packages argument with Pip.
Once running, you are presented with GDB's command-line interface in Ghidra's Terminal. This is the bona fide GDB command-line interface, so it has all the functionality you would expect. If you command GDB from this shell, the plugin will keep Ghidra in sync. The terminal can also be used to interact with the target application when it is running. The plugin provides an additional set of commands for managing the connection to Ghidra, as well as controlling trace synchronization. These are all in the "ghidra" command prefix. You can use tab completion to enumerate the available commands and GDB's "help" command to examine their documentation.
This works the same as the GDB launcher, but runs gdb on a remote system via ssh. In contrast to the previous system, which used an SSH library for Java, this launcher uses the ssh command on the local system. Thus, it should have broader compatibility with remote systems, and it should use the same configuration files as you are accustomed to. That said, we developed it using OpenSSH, so your experience will be best if your copy understands the same command-line arguments.
You must install GDB and an SSH server onto the target host. Your local SSH client must support remote port forwarding (-R option) and terminal allocation (-t option), and the remote server must be configured to permit them.
You will need to manually install the required Python packages on the target host, comprising our plugin for GDB and its dependencies. Copy all of the Python packages from Ghidra/Debug/Debugger-rmi-trace/pypkg/dist/ and Ghidra/Debug/Debugger-agent-gdb/pypkg/dist/ to the remote system. It is easiest to put them all in one directory, e.g., ~/ghidra-pypgk/. Then install them:
python3 -m pip install --no-index -f ~/ghidra-pypkg/ ghidragdb
Please see GDB Setup for notes about embedded Python interpreter versions.
This works similarly to the GDB via SSH launcher, but instead of tunneling the Trace RMI connection, tunnels the RSP (gdbserver) connection. There is actually a fairly elegant method of doing this straight from within gdb, which is exactly what this launcher does:
target remote | ssh user@host gdbserver - /path/to/image
This has some advantages compared to running gdb on the remote target:
But, it also has some drawbacks:
You must have GDB installed on the local system and a compatible version of gdbserver installed on the target system. You must have an SSH server installed on the target system. It may be worth testing your setup manually (outside of Ghidra) to ensure everything is configured correctly. On the local system, follow the steps given in GDB Setup. There are no additional Python requirements on the target system.
These launchers orchestrate a QEMU user- or system-mode target and connect to it using our Python plugin for GDB. Ghidra will inspect the current program and attempt to map its language to the appropriate QEMU command, but due to subtle errors and/or outright failure, the default value for the QEMU command option often requires careful inspection.
There are two separate scripts for QEMU, one for user mode and one for system mode. Note that QEMU does not support user-mode emulation on Windows, so that script is not available on Windows hosts.
You must acquire versions of QEMU and GDB that support the target architecture. Aside from the copy of QEMU required, setup is the same whether for user or system mode. As for GDB, on many distributions of Linux, you can install gdb-multiarch. Follow the steps given in GDB Setup.
This launchers runs wine in a gdb session on Linux and directs it to a target Windows executable. There are other ways to rig a Windows target in GDB on Linux, but this is the method we have chosen. This may prevent GDB from processing the object file, because it is a PE file, and most copies of GDB for UNIX will support only ELF. Nevertheless, Ghidra should recognize the target and map it, giving you symbols and debug info in the front end, even if not in the GDB CLI.
In addition to the steps given in GDB Setup, you must install Wine on your system. Prepare for configuration by locating the actual wine executable. These are often in some library directory and named "wine32" or "wine64." To find them, either examine the file list of the installed package, or dissect the wrapper wine script, usually on your path:
less $(which wine)
The locations are usually given in variables at the top of the script, e.g., "/usr/lib/wine/wine64". One is for 64-bit Windows targets and another is for 32-bit Windows targets. Unlike native Windows, Wine does not (yet) implement WoW64 (Windows on Windows 64). Instead, the 32-bit target is loaded using a 32-bit copy of Wine, and so is serviced by Linux's 32-bit system calls. NOTE: Careful attention must be given to select the correct wine executable for the target program's architecture! Even though the wine executable is smart enough to correct this mistake, it results in calls to exec, which confuse this launcher. If GDB complains that it cannot place breakpoints because of memory access, it is probably because of this mistake.
The launcher loads some additional support packages in our plugin for GDB, e.g., to scan the memory map for PE files and amend the module list. Thus, Ghidra can display both Windows and Linux modules, and map them to its program databases accordingly, despite GDB's inability to process PE files. There are perhaps other configurations of GDB for Linux that can process ELFs as well as PEs loaded by Wine, but they do not seem to be readily available in any popular package repositories.
This launcher can target any TCP-based GDB stub that is compatible with a local copy of gdb. Essentially, it just starts gdb and then enters
target remote [host]:[port]
into it. It is best to test this command outside of Ghidra to be sure everything is compatible before using this launcher. This launcher does not require an image, nor does it create your target. Thus, it can be used without a current program.
On your local system, follow the steps given in GDB Setup. Your version of GDB must be compatible with the stub (e.g., gdbserver) on the target system. There are no additional requirements on the target system.
NOTE: The target program image must match that imported in Ghidra, or else things may not map or synchronize correctly.
The following launchers based on the LLDB Debugger are included out of the box:
This launcher is a Python plugin for LLDB, and so is well suited for debugging user-space targets on a variety of platforms. It is the de facto debugger for macOS. It can be obtained by installing Xcode from the App Store. Though it may require a bit more careful configuration, it can also be obtained from other repositories like brew.
You must have LLDB installed on the local system, and it must embed the Python 3 interpreter. If you have access to PyPI, setting up your Python 3 environment is done using Pip. Please note the version specifier for Protobuf.
python3 -m pip install psutil protobuf==3.20.3
If you are offline, or would like to use our provided packages, we still use Pip, but with a more complicated invocation:
cd /path/to/ghidra_ version/Ghidra/Debug python3 -m pip install --no-index -f Debugger-rmi-trace/pypkg/dist -f Debugger-agent-lldb/pypkg/dist psutil protobuf
Beware that LLDB may embed a different Python interpreter than your system's default. If you are still getting import errors, check the version that LLDB embeds:
(bash)$ lldb (lldb) script >>> import sys >>> sys.version
Note the version and ensure that you are invoking Pip with that version. Supposing sys.version indicates 3.10, you should invoke Pip using python3.10 -m pip.
Once running, you are presented with LLDB's command-line interface in Ghidra's Terminal. This is the bona fide LLDB command-line interface, so it has all the functionality you would expect. If you command LLDB from this shell, the plugin will keep Ghidra in sync. The terminal can be used to interact with the target application when it is running. The plugin provides an additional set of commands for managing the connection to Ghidra, as well as controlling trace synchronization. These are all in the "ghidra" category. You can use tab completion to enumerate the available commands and LLDB's "help" command to examine their documentation.
This launcher can target any TCP-based GDB stub that is compatible with a local copy of lldb. Essentially, it just starts lldb and then enters
gdb-remote [host]:[port]
into it. It is best to test this command outside of Ghidra to be sure everything is compatible before using this launcher. This launcher does not require an image, nor does it create your target. Thus, it can be used without a current program.
On your local system, follow the steps given in LLDB Setup. Your version of LLDB must be compatible with the stub (e.g., gdbserver) on the target system. There are no additional requirements on the target system.
NOTE: The target program image must match that imported in Ghidra, or else things may not map or synchronize correctly.
This launcher connects to macos kernels booted in debug-mode using lldb. Essentially, it just starts lldb and then enters
kdp-remote [host]
It is best to test this command outside of Ghidra to be sure everything is compatible before using this launcher. This launcher does not require an image, nor does it create your target. Thus, it can be used without a current program.
On your local system, follow the steps given in LLDB Setup. Before connecting to the target kernel, you must force an NMI on the target to ready the connection. On actual hardware, this is typically achieved by some button sequence, e.g. L/R-Options + Power or Command+Option+Control+Shift+Esc. In a VM, you may have to pause the VM and modify its state. For example, by cd'ing to the VM's container and issuing the command:
perl -i -pe 's/(?<=pendingNMI\x00{4})\x00/\x01/' macOS_15-1234567.vmss
The following launchers based on Microsoft's dbgeng.dll are included out of the box:
This launcher is actually a Python implementation of a console debugger based on dbgeng.dll. This DLL represents the Microsoft Windows Debugger engine, and so is best suited for debugging Windows user-space targets. Windows kernel targets are not yet supported. This DLL also backs WinDbg and several other debuggers on Windows. By default, the launcher will search for this DLL in an installation of the Windows Debugging Kits version 10. If it does not find it there, it will probably crash with a message in the Terminal.
Please note on some system configurations, one of the debugger's dependencies dbghelp.dll may get loaded from the system directory instead of from the WinDbg installation, usually because a security product has pre-loaded it into the Python process. You might work around this by copying the affected DLLs from your WinDbg installation into your Python installation.
Installing WinDbg is highly recommended. If you wish to forego installing WinDbg, you can use the DLL provided with Windows, which is substantially less capable, by manually pointing this connector to C:\Windows\system32. If you do this, some commands, e.g. .server, will not be available.
If you have access to PyPI, setting up your Python 3 environment is done using Pip. Please note the version specifier for Protobuf.
python3 -m pip install pybag protobuf==3.20.3
If you are offline, or would like to use our provided packages, we still use Pip, but with a more complicated invocation:
cd C:\path\to\ghidra_ version\Ghidra\Debug python3 -m pip install --no-index -f Debugger-rmi-trace\pypkg\dist -f Debugger-agent-dbgeng\pypkg\dist pybag protobuf
If you get an import error regarding distutils, it is due to a transitive dependency on a buggy version of capstone. Work around it by installing setuptools.
Once running, you are presented with a command-line interface in Ghidra's Terminal. This CLI accepts your usual WinDbg (kd) commands. You can escape from this CLI and enter a Python 3 REPL by entering ".exit". This is not an actual kd command, but our implementation understands this to mean exit the kd REPL. From the Python 3 REPL, you can access the underlying Python-based API pybag. This is an uncommon need, but may be useful for diagnostics and/or workarounds. To re-enter the kd REPL, enter "repl()". Alternatively, if you are trying to quit, but typed ".exit", just type "quit()" to terminate the session.
This launcher extends the base dbgeng launcher adding extra options (a la IDebugClient's CreateProcess2).
This launcher allows the user to attach to a local running process. Options are the same as those for the base dbgeng, except for ProcessId and AttachFlags
This launcher extends the base dbgeng launcher adding an option for connecting through a remote process server.
dbgsrv -t tcp:port=12345
This version of the dbgeng should be used for kernel-debugging of a remote machine. Options are the same as the base dbgeng, except for the connection-string arguments. For remote debugging, the target machine should be booted with the appropriate options, set using BCDEDIT or the equivalent, such as:
bcdedit /debug ON bdcedit /dbgsettings NET HOSTIP:IP PORT:54321 KEY:1.1.1.1
where IP= the address of the machine runing Ghidra.
Setup for EXDI connections is fairly complicated and difficult to get correct. The argument string typically should be something like:
exdi:CLSID={29f9906e-9dbe-4d4b-b0fb-6acf7fb6d014},Kd=Guess,DataBreaks=Exdi
The CLSID here should match the CLSID in the exdiConfigData.xml file in the debugger architectural directory. If windbg has been run using EXDI at some point, there will also be an entry in the System Registry for this CLSID. The InprocServer32 subentry for this CLSID in the Registry should point to a copy of ExdiGdbSrv.dll, typically the one in the same directory. This DLL must reside somewhere that the debugger has permission to load from, i.e. not in the WindowsApps directory tree. The exdiConfigData file should be configured for the target you're using. We heavily recommend using displayCommPackets==yes, as many of the tasks take considerable time, and this is the only indicator of progress.
The Kd=Guess parameter causes the underlying engine to scan memory for the kernel's base address, which will probably not be provided by the gdbstub. (Kd=NtBaseAddr is also a valid option, as is eliminating the parameter, but, currently, we have no idea how to point the configuration at a correct value. Using this option will cause the load to spin pointlessly.) If you can, we highly recommend breaking the target near the base address, as the search proceeds down through memory starting at the current program counter. If the difference between the PC and the base address is large, the loading process will punt before useful values are detected. If anyone understand how to extend this search (or knows how to set the base address to sidestep the scan), we would really love some guidance.
This is a nascent extension to our launcher for the Windows Debugger. The launcher itself functions well, but lacks full integration. It is not yet properly packaged for the Ghidra distribution, but is available in development environments. It also needs some additional protocol support, namely to integrate its notion of time travel with Ghidra's notion. For the time being, we map our time specifications as follows. MS TTD uses a tuple for its time specs, both displayed in hexadecimal, e.g., "B5:1A". The first is the "major," which we believe counts the events that warrant a snapshot. The second is the "minor," which we believe counts instructions executed since the major event. Thus, we would like to map the major to a Ghidra trace snapshot and the minor to steps of p-code emulation. For example, the "B5:1A" notation would map to "181:26". It should be no surprise the notations are similar, since both MS TTD and Ghidra (as well as several other "timeless" debuggers) use a snapshot-replay strategy to recover past machine states. However, we have not yet worked out how to have Ghidra cooperate with a back end in the replay part of this strategy. Currently, Ghidra will always apply p-code emulation, despite having a perfectly good and performant back end available. So, for the time being, we multiply the major number by 1000, thus reserving that many Ghidra snapshots between major events for MS TTD minor steps. Thus, the notation "B5:1A" will actually map to "181026", that is snapshot 181026 with no steps of p-code emulation. This hack will fall short if you visit a time where the minor number exceeds 999.
Furthermore, if you use the Ghidra Debugger UI to visit a past snapshot, the back end is not yet informed of your intent. You will probably only see stale records of the machine state. Instead, please use the kd commands from the Terminal to navigate through time. The back end (MS TTD) will perform the replay, record the snapshot, and command Ghidra to navigate there.
This launcher has the same options as the WinDbg launcher, except that the DLL path must contain dbgmodel.dll and the scripts that implement TTD. These are most easily obtained by installing WinDbg Preview or later.
The following launchers based on the Java Debugger are included out of the box:
This launcher uses the native Java Debug Interface (JDI) to launch the current .class file.
You must have Java installed on the local system. No additional setup is required.
This launcher uses the native Java Debug Interface (JDI) to attach to a running java program launched with an open Java Debug Wire Port (JDWP), e.g.:
java -agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=localhost:54321 Target.class
Identical to that for the java launcher.
This launcher uses the native Java Debug Interface (JDI) to attach to a running java program launched with a Java Debug Wire Port (JDWP) identified by process id.
Identical to that for the java launcher.
We currently provide one launcher for Trace RMI API exploration and development:
This launcher runs Python in a Terminal window, connects a Trace RMI client back to Ghidra, then starts a blank trace. Once running, it presents the Python interpreter, with the ghidratrace and ghidratrace.client packages imported into the local namespace. Thus, a developer can explore the API, invoke methods, and observer how Ghidra reacts.
If you have access to PyPI, setting up your Python 3 environment is done using Pip. Please note the version specifier for Protobuf.
python3 -m pip install protobuf==3.20.3
If you are offline, or would like to use our provided packages, we still use Pip, but with a more complicated invocation:
cd /path/to/ghidra_ version/Ghidra/Debug python3 -m pip install --no-index -f Debugger-rmi-trace/pypkg/dist protobuf