GP-3887: Update Debugger course for Trace RMI.

This commit is contained in:
Dan 2024-04-22 10:11:25 -04:00
parent 190f1eaa1e
commit a93a695e6a
79 changed files with 2235 additions and 1663 deletions

View file

@ -30,7 +30,10 @@ Run it:
```
You should see a 9x9 grid and a cursor you can move with the arrow keys.
Hit **Ctrl-C** to exit.
![Termmines running in a Terminal](images/GettingStarted_Termmines.png)
Hit **`CTRL`-`C`** to exit.
Probe it for help.
Most Linux programs accept a `-h` argument for help:
@ -55,23 +58,29 @@ There are many ways to do this, but for the sake of simplicity, import and launc
![Debugger tool with termmines open](images/GettingStarted_ToolWSpecimen.png)
1. In the Debugger tool, click the dropdown ▾ for the debug ![debug button](images/debugger.png) icon in the global tool bar, and select "Debug termmines in GDB locally IN-VM."
1. In the Debugger tool, click the dropdown ▾ for the debug ![debug button](images/debugger.png) icon in the global tool bar, and select **Configure and Launch termmines using... → gdb**.
![Launch GDB Dialog](images/GettingStarted_LaunchGDBDialog.png)
1. Change the **Run Command** to "start" (not "starti").
**NOTE**: In practice, this is rarely recommended, because most targets do not export their `main` function.
1. Click the **Launch** button in the dialog.
1. Wait a bit then verify the Dynamic Listing window (top) is displaying disassembly code.
![Debugger tool after launching termmines](images/GettingStarted_DisassemblyAfterLaunch.png)
## Launching on Windows
On Windows, we will use dbgeng to debug the specimen.
On Windows, we will use the Windows Debugger dbgeng.dll to debug the specimen.
This is the engine that backs WinDbg.
You may choose an alternative Minesweeper, since terminal applications are less representative of Windows executables.
Follow the same process as for Linux, except import `termmines.exe` and select "Debug termmines.exe in dbgeng locally IN-VM."
Follow the same process as for Linux, except import `termmines.exe` and select **Configure and Launch termmines.exe using... → dbgeng**.
## Launching on macOS
Unfortunately, things are not so simple on macOS.
See the instructions for [Building LLDB-Java Bindings](../../../Ghidra/Debug/Debugger-swig-lldb/InstructionsForBuildingLLDBInterface.txt).
Once built, follow the same process as for Linux, except select "Debug termmines in LLDB locally IN-VM."
On macOS, we will use LLDB to debug the specimen.
This is the debugger included with Xcode.
Follow the same process as for Linux, except choose **lldb** in the last menu.
## Troubleshooting
@ -97,59 +106,53 @@ Double-check that you are in the Debugger tool, not the CodeBrowser tool.
If it is still not there, then you may need to re-import the default Debugger tool as under the previous heading.
If it is still not there, your installation may be corrupt.
### There is no "Debug termmines in GDB locally IN-VM" option in the launch drop-down
### There is no **gdb** option in the launch drop-down
You may need to install GDB and/or configure Ghidra with its location.
If you have a copy or custom build of GDB in a non-system path, note its full path.
If you intend to use the system's copy of GDB, then in a terminal:
You may have an older Debugger tool still configured for Recorder-based targets.
We are transitioning to TraceRmi-based targets.
Delete your Debugger tool and re-import the default one using the instructions above.
If it is still not there, it's possible your installation is corrupt.
Search for a file called `local-gdb.sh` in your installation.
Unlike the previous system, Trace RMI will not probe your system for dependencies nor hide incompatible launchers.
All installed launchers should be present in the menus, even though some may not work on your configuration.
```bash
which gdb
```
### The launch hangs for several seconds and then I get prompted with a wall of text
Note the path given.
(If you get an error, then you need to install GDB.)
In a terminal, type the full path of GDB to ensure it executes properly.
Type `q` to quit GDB.
Read the wall of text.
The first line should tell you the exception that it encountered.
Often this is a timeout.
Press the **Keep** button and then find the Terminal, usually in the bottom right.
If you do not see it there, check the **Window → Terminals** menu.
Once you have found the Terminal, check its output *starting at the top* for diagnostic messages.
If you have something like `bash: gdb: command not found`, it is because you are missing `gdb`, or you need to tell Ghidra where to find it.
1. From the Debugger Targets window, click the Connect ![connect button](images/connect.png) button.
1. In the Connect dialog, select "gdb" from the dropdown at the top.
1. Enter the full path, e.g., `/usr/bin/gdb`, in the "GDB launch command" field.
1. Click "Connect"
1. If you get an Interpreter window, then things have gone well.
1. Type `echo test` into it to verify it's responsive, then type `q` to disconnect.
1. Close the Debugger tool, then retry.
### The launch hangs for several seconds and then prompt for a "recorder"
You probably have a stale GDB connection, so when you launched you now have multiple connections.
For the prompt, select the option with the highest score.
Examine the Targets window to confirm you have multiple GDB connections.
If you know which is the stale connection, you can right-click it and choose **Disconnect**.
Otherwise, use **Disconnect All** from the drop-down menu and re-launch.
If it is just missing, then install it and try again.
If you need to tell Ghidra where it is, then in the launcher drop-down, select **Configure and Launch termmines using... → gdb**.
DO NOT select **Re-launch termmines using gdb**, since this will not allow you to correct the configuration.
### The Dynamic Listing is empty
Check for an actual connection.
You should see an entry in the Debugger Targets window, a populated Object window, and there should be an Interpreter window.
You should see an entry in the **Connection Manager** window, a populated **Model** window, and there should be a **Terminal** window.
If not, then your GDB connector may not be configured properly.
Try the steps under the previous heading.
If you have an Interpreter window, there are several possibilities:
If you have a **Terminal** window, there are several possibilities:
#### Ghidra or GDB failed to launch the target:
If this is the case, you should see an error message in the Terminal, e.g.: `termmines: no such file or directory`.
Check that the original `termmines` exists and is executable.
It must be at the path from where it was originally imported.
If you imported from a share, consider copying it locally, setting its permissions, then re-importing.
You may also need to adjust the **Image** option when configuring the launch.
#### The target was launched, but immediately terminated:
If this is the case, you should see a message in the Terminal, e.g.: `[Inferior 1 (process 1234) exited normally]`.
Check that the specimen has a `main` symbol.
NOTE: It is not sufficient to place a `main` label in Ghidra.
**NOTE**: It is not sufficient to place a `main` label in Ghidra.
The original file must have a `main` symbol.
Alternatively, in the menus try **Debugger → Debug termmines → in GDB locally IN-VM**, and select "Use starti."
Alternatively, in the menus try **Debugger → Configure and Launch termmines using → gdb**, and select "starti" for **Run Command**.
This will break at the system entry point.
If you have labeled `main` in Ghidra, then you can place a breakpoint there and continue — these features are covered later in the course.
@ -158,75 +161,74 @@ Alternatively, try debugging the target in GDB from a separate terminal complete
#### The target was launched, but has not stopped, yet
Try pressing the Interrupt ![interrupt button](images/interrupt.png) button.
If that doesn't work or is unsatisfactory, try the remedies under the previous heading — for an immediately terminating target.
If that doesn't work or is unsatisfactory, try the remedies under the previous heading.
#### You hit an uncommon bug where the memory map is not applied properly
This is the case if the Dynamic Listing is completely blank but the Regions window is replete.
The Dynamic Listing just needs to be kicked a little.
The easiest way is to step once, using the ![step into](images/stepinto.png) Step Into button in the main toolbar.
This is the case if the **Dynamic Listing** is completely blank but the **Regions** window is replete.
The **Dynamic Listing** just needs to be kicked a little.
The easiest way is to step once, using the ![step into](images/stepinto.png) **Step Into** button in the main toolbar.
If this is not desirable, then you can toggle **Force Full View** back and forth.
In the Regions window, use the drop-down menu to toggle it on, then toggle it off.
The Dynamic Listing should now be populated.
In the **Regions** window, use the drop-down menu to toggle it on, then toggle it off.
The **Dynamic Listing** should now be populated.
To go to the program counter, double-click the "pc = ..." label in the top right.
#### Something else has gone wrong
Try typing `info inferiors` and similar GDB diagnostic commands into the Interpreter.
Try typing `info inferiors` and similar GDB diagnostic commands into the **Terminal**.
### The listings are in sync, but the Dynamic Listing is grey 00s
Check the Auto-Read drop-down near the top right of the Dynamic Listing.
Check the **Auto-Read** drop-down near the top right of the **Dynamic Listing**.
It should be set to **Read Visible Memory, RO Once**.
## Exercise: Launch `termmines`
If you were following along with an instructor, delete your import of `termmines` and/or start a new Ghidra Project.
Starting from the beginning, import `termmines` and launch it in the Ghidra Debugger with GDB.
When your tool looks like the screenshot with a populated Dynamic Listing, you have completed the exercise.
When your tool looks like the screenshot with a populated **Dynamic Listing**, you have completed the exercise.
Disconnect before proceeding to the next exercise.
## Customized Launching
For this specimen, you may occasionally need to provide custom command-line parameters.
By default, Ghidra attempts to launch the target without any parameters.
In the menus, use **Debugger → Debug termmmines → in GDB locally IN-VM** to launch with customizations.
Ghidra will remember these customizations the next time you launch using the drop-down button from the toolbar.
The first dialog allows you to customize the connection to the back-end debugger.
Unless you have a special copy of GDB, you should probably just click Connect.
The second dialog allows you to customize how the back-end debugger launches the target.
This is where you tweak the command line.
You can also change the actual image, in case it has moved or you want to experiment with a patched version.
In the **Debugger** menu, or the **Launch** button's drop-down menu, use **Configure and Launch termmmines → gdb** to adjust your configuration.
This is where you can specify the image path and command-line parameters of your target.
Ghidra will remember this configuration the next time you launch using the drop-down button from the toolbar.
Launchers with memorized configurations are presented as **Re-launch termmines using...** options.
Using one of those entries will re-launch with the saved configuration rather than prompting.
## Exercise: Launch with Command-line Help
Launch the specimen so that it prints its usage.
When successful, you will see the usage info in the Debugger's Interpreter window.
When successful, you will see the usage info in the Debugger's **Terminal** window.
**NOTE**: The process will terminate after printing its usage, and as a result, the rest of the UI will be mostly empty.
## Attaching
Attaching is slightly more advanced, but because the target will need to read from stdin, and Ghidra does not properly attach the Interpreter to stdin, we will need to launch the target in a terminal and attach to it instead.
Attaching is slightly more advanced, but can be useful if the target is part of a larger system, and it needs to be running *in situ*.
For this section, we will just run `termmines` in a separate terminal and then attach to it from Ghidra.
This used to be required, because the older Recorder-based system did not provide target I/O, but this limitation is overcome by the new **Terminal** window
when using Trace RMI.
Note this technique is only possible because the target waits for input.
Depending on the task for future exercises, you may still need to launch from the Debugger instead of attaching.
1. Run `termmines` in a proper terminal with the desired command-line parameters.
1. In the Ghidra Debugger, find the Targets window, and click the ![connect](images/connect.png) Connect button.
1. Select "gdb" from the drop-down box.
1. This dialog should look familiar from the Customized Launching section.
Just click the Connect button.
1. In the Objects window (below the Targets window), expand the node labeled "Available."
1. Run `termmines` in a terminal outside of Ghidra with the desired command-line parameters.
1. In the Ghidra Debugger, use the **Launch** button drop-down and select **Configured and Launch termmines using... → raw gdb**.
The "raw" connector will give us a GDB session without a target.
1. Ghidra needs to know the location of gdb and the architecture of the intended target.
The defaults are correct for 64-bit x86 targets using the system's copy of GDB.
Probably, you can just click **Launch**.
1. In the **Model** window (to the left), expand the *Available* node.
1. In the filter box, type `termmines`.
1. Right-click on the termmines process and select Attach.
If this fails, select Available again, and click the <img alt="refresh" src="images/view-refresh.png" width="16px"> Refresh button.
1. Note the PID, e.g. 1234, then in the **Terminal** type, e.g., `attach 1234`.
## Exercise: Attach
Try attaching on your own, if you have not already.
Check your work by typing `bt` into the Interpreter.
Check your work by typing `bt` into the **Terminal**.
If you are in `read` you have completed this exercise.
Disconnect before proceeding to the next module: [A Tour of the UI](A2-UITour.md)
Quit GDB from the **Terminal** before proceeding to the next module: [A Tour of the UI](A2-UITour.md)
## Troubleshooting
@ -241,5 +243,5 @@ For example:
```
Alternatively, if you have root access, you can rectify the issue using the relevant documentation available online.
**Beware!** You should not modify this setting on your daily driver, as this substantially reduces the security of your system.
**Beware!** You should not set `ptrace_scope=0` globally, except on a system set aside for debugging, as this substantially reduces the security of that system.
Any compromised process would be allowed to attach to and steal data, e.g., credentials, from any other process owned by the same user.