GP-5263: Update Debugger GhidraClass

This commit is contained in:
Dan 2025-01-15 11:47:36 -05:00
parent 2d10fa1be2
commit dc4b0692a9
17 changed files with 102 additions and 41 deletions

View file

@ -34,6 +34,7 @@ import docking.action.DockingActionIf;
import docking.widgets.fieldpanel.FieldPanel;
import generic.Unique;
import generic.jar.ResourceFile;
import ghidra.GhidraTestApplicationLayout;
import ghidra.app.cmd.disassemble.DisassembleCommand;
import ghidra.app.context.ProgramLocationActionContext;
import ghidra.app.decompiler.component.DecompilerPanel;
@ -109,6 +110,7 @@ import ghidra.util.Msg;
import ghidra.util.exception.CancelledException;
import ghidra.util.task.ConsoleTaskMonitor;
import help.screenshot.GhidraScreenShotGenerator;
import utility.application.ApplicationLayout;
public class TutorialDebuggerScreenShots extends GhidraScreenShotGenerator
implements AsyncTestUtils {
@ -145,6 +147,18 @@ public class TutorialDebuggerScreenShots extends GhidraScreenShotGenerator
}
};
@Override
protected ApplicationLayout createApplicationLayout() throws IOException {
return new GhidraTestApplicationLayout(new File(getTestDirectoryPath())) {
@Override
protected Set<String> getDependentModulePatterns() {
Set<String> patterns = super.getDependentModulePatterns();
patterns.add("Debugger-agent");
return patterns;
}
};
}
@Override
protected TestEnv newTestEnv() throws Exception {
return env = new MyTestEnv("DebuggerCourse");
@ -734,7 +748,7 @@ public class TutorialDebuggerScreenShots extends GhidraScreenShotGenerator
mappings.addModuleMappings(proposal.computeMap().values(), monitor, true);
}
waitForCondition(() -> flatDbg.translateDynamicToStatic(dynAddr) != null);
//waitForCondition(() -> flatDbg.translateDynamicToStatic(dynAddr) != null);
runSwing(() -> tool.setSize(1920, 1080));
captureProvider(DebuggerStaticMappingProvider.class);

View file

@ -152,12 +152,16 @@ id="toc-customized-launching">Customized Launching</a></li>
<li><a href="#exercise-launch-with-command-line-help"
id="toc-exercise-launch-with-command-line-help">Exercise: Launch with
Command-line Help</a></li>
<li><a href="#attaching" id="toc-attaching">Attaching</a></li>
<li><a href="#exercise-attach" id="toc-exercise-attach">Exercise:
Attach</a></li>
<li><a href="#attaching" id="toc-attaching">Attaching</a>
<ul>
<li><a href="#troubleshooting-1"
id="toc-troubleshooting-1">Troubleshooting</a></li>
</ul></li>
<li><a href="#exercise-attach" id="toc-exercise-attach">Exercise:
Attach</a></li>
<li><a href="#troubleshooting-2"
id="toc-troubleshooting-2">Troubleshooting</a></li>
</ul></li>
</ul>
</nav>
<section id="getting-started" class="level1">
@ -453,13 +457,14 @@ target waits for input.</p>
<li>Run <code>termmines</code> in a terminal outside of Ghidra with the
desired command-line parameters.</li>
<li>In the Ghidra Debugger, use the <strong>Launch</strong> button
drop-down and select <strong>Configured and Launch termmines using… →
raw gdb</strong>. The “raw” connector will give us a GDB session without
a target.</li>
drop-down and select <strong>Configure and Launch termmines using… →
gdb</strong>.</li>
<li>Clear the <strong>Image</strong> field to configure a GDB session
without a target.</li>
<li>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 systems copy of GDB. Probably, you can just click
<strong>Launch</strong>.</li>
the systems copy of GDB.</li>
<li>Click <strong>Launch</strong>.</li>
<li>In the <strong>Model</strong> window (to the left), expand the
<em>Available</em> node.</li>
<li>In the filter box, type <code>termmines</code>.</li>
@ -467,6 +472,17 @@ the systems copy of GDB. Probably, you can just click
you prefer, note the PID, e.g. 1234, then in the
<strong>Terminal</strong> type, e.g., <code>attach 1234</code>.</li>
</ol>
<p><strong>TIP</strong>: In later exercises, you may use the
<strong>Reset</strong> button to re-populate the default value for the
<strong>Image</strong> field. Be sure to change <strong>Run
Command</strong> back to “start”, though.</p>
<section id="troubleshooting-1" class="level3">
<h3>Troubleshooting</h3>
<p>If the <strong>Model</strong> window is blank, check for a “noname”
tab in the Dynamic Listing, and click it.</p>
<p>If the <strong>Model</strong> window seems incomplete after
attaching, check that its Filter box is cleared.</p>
</section>
</section>
<section id="exercise-attach" class="level2">
<h2>Exercise: Attach</h2>
@ -476,7 +492,7 @@ in <code>read</code> you have completed this exercise. Quit GDB from the
<strong>Terminal</strong> before proceeding to the next module: <a
href="A2-UITour.html">A Tour of the UI</a></p>
</section>
<section id="troubleshooting-1" class="level2">
<section id="troubleshooting-2" class="level2">
<h2>Troubleshooting</h2>
<p>If you get <code>Operation not permitted</code> or similar when
trying to attach, it is likely your Linux system is configured with

View file

@ -219,15 +219,24 @@ when using Trace RMI.
Note this technique is only possible because the target waits for input.
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... &rarr; raw gdb**.
The "raw" connector will give us a GDB session without a target.
1. In the Ghidra Debugger, use the **Launch** button drop-down and select **Configure and Launch termmines using... &rarr; gdb**.
1. Clear the **Image** field to configure 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. 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 node and select **Attach**, or, if you prefer, note the PID, e.g. 1234, then in the **Terminal** type, e.g., `attach 1234`.
**TIP**: In later exercises, you may use the **Reset** button to re-populate the default value for the **Image** field.
Be sure to change **Run Command** back to "start", though.
### Troubleshooting
If the **Model** window is blank, check for a "noname" tab in the Dynamic Listing, and click it.
If the **Model** window seems incomplete after attaching, check that its Filter box is cleared.
## Exercise: Attach
Try attaching on your own, if you have not already.

View file

@ -312,7 +312,10 @@ forward a single instruction each time you press it. Also notice that
the Static Listing moves with the Dynamic Listing. You may navigate in
either listing, and so long as there is a corresponding location in the
other, the two will stay synchronized. You may also open the Decompiler
just as you would in the CodeBrowser, and it will stay in sync too.</p>
just as you would in the CodeBrowser, and it will stay in sync too.
<strong>TIP</strong>: If you get lost in memory, you can seek back to
the program counter by double-clicking “pc = …” in the top right of the
listing.</p>
<p>When you have clicked <img src="images/stepinto.png"
alt="step into" /> <strong>Step Into</strong> a sufficient number of
times, you should end up in a subroutine. You can click <img

View file

@ -142,6 +142,7 @@ Notice that the Dynamic Listing moves forward a single instruction each time you
Also notice that the Static Listing moves with the Dynamic Listing.
You may navigate in either listing, and so long as there is a corresponding location in the other, the two will stay synchronized.
You may also open the Decompiler just as you would in the CodeBrowser, and it will stay in sync too.
**TIP**: If you get lost in memory, you can seek back to the program counter by double-clicking "pc = ..." in the top right of the listing.
When you have clicked ![step into](images/stepinto.png) **Step Into** a sufficient number of times, you should end up in a subroutine.
You can click ![step out](images/stepout.png) **Step Out** to leave the subroutine.

View file

@ -273,7 +273,9 @@ toggle action, press <strong><code>K</code></strong> on the keyboard, or
double-click its icon in the margin.</li>
<li>From the Model window, expand the <em>Breakpoints</em> node and
double-click a breakpoint, or select one with the keyboard and press
<strong><code>ENTER</code></strong>.</li>
<strong><code>ENTER</code></strong>. For GDB, this must be done from the
top-level <em>Breakpoints</em> node, not the one subordinate to the
<em>inferior</em>.</li>
<li>From the Breakpoints window, single-click the breakpoints status
icon, right-click an entry and select a toggle action, or create a
selection and use a toggling action from the local toolbar. Either panel
@ -340,7 +342,8 @@ synchronized after importing libc</figcaption>
<section id="troubleshooting" class="level4">
<h4>Troubleshooting</h4>
<p>If it seems nothing has changed, except now you have a second program
database open, then the new module may not be successfully mapped.</p>
database open, then the new module may not be successfully mapped. Try
one or more of the following:</p>
<ol type="1">
<li>Re-check the Debug Console window and verify the note has been
removed.</li>
@ -349,6 +352,9 @@ system, so the name of the module and the name of the program database
do not match.</li>
<li>Ensure that <code>libc</code> is the current program (tab) in the
Static Listing.</li>
<li>Wait for auto-analysis of <code>libc</code> to complete. Yeah, it
may take a moment, but auto-mapping is queued as a background task, and
so it cannot map things until auto-analysis is done.</li>
<li>In the Modules window, right-click on <code>libc</code>, and select
<strong>Map Module to libc</strong>. (Names and titles will likely
differ.)</li>
@ -446,7 +452,7 @@ boards for any <code>termmines</code> session.</p>
<p>Write a program that takes a seed from the user and prints a diagram
of the first game board with the mines indicated. Optionally, have it
print each subsequent game board when the user presses
<strong>ENTER</strong>. Check your work by re-launching
<strong><code>ENTER</code></strong>. Check your work by re-launching
<code>termmines</code>, capturing its seed, inputting it into your
program, and then winning the game. Optionally, win 2 more games in the
same session.</p>

View file

@ -96,6 +96,7 @@ There are several ways to toggle a breakpoint:
1. In any listing, as in setting a breakpoint, right-click and select a toggle action, press **`K`** on the keyboard, or double-click its icon in the margin.
1. From the Model window, expand the *Breakpoints* node and double-click a breakpoint, or select one with the keyboard and press **`ENTER`**.
For GDB, this must be done from the top-level *Breakpoints* node, not the one subordinate to the *inferior*.
1. From the Breakpoints window, single-click the breakpoint's status icon, right-click an entry and select a toggle action, or create a selection and use a toggling action from the local toolbar.
Either panel works, but the top panel is preferred to keep the breakpoints consistent.
The local toolbar also has actions for toggling all breakpoints in the session.
@ -138,10 +139,13 @@ Once imported, the Breakpoints window should update to reflect the static addres
#### Troubleshooting
If it seems nothing has changed, except now you have a second program database open, then the new module may not be successfully mapped.
Try one or more of the following:
1. Re-check the Debug Console window and verify the note has been removed.
1. If not, it might be because the module is symlinked in the file system, so the name of the module and the name of the program database do not match.
1. Ensure that `libc` is the current program (tab) in the Static Listing.
1. Wait for auto-analysis of `libc` to complete.
Yeah, it may take a moment, but auto-mapping is queued as a background task, and so it cannot map things until auto-analysis is done.
1. In the Modules window, right-click on `libc`, and select **Map Module to libc**. (Names and titles will likely differ.)
### Capturing the Random Seed
@ -214,6 +218,6 @@ Because, as we have now confirmed, `termmines` is importing its random number ge
Further, because we can capture the seed, and we know the placement algorithm, we can perfectly replicate the sequence of game boards for any `termmines` session.
Write a program that takes a seed from the user and prints a diagram of the first game board with the mines indicated.
Optionally, have it print each subsequent game board when the user presses **ENTER**.
Optionally, have it print each subsequent game board when the user presses **`ENTER`**.
Check your work by re-launching `termmines`, capturing its seed, inputting it into your program, and then winning the game.
Optionally, win 2 more games in the same session.

View file

@ -195,8 +195,8 @@ pointer there, just like you would in the Static Listing. You can now
navigate to that address by double-clicking it. To return to the stack
pointer, you can use the back arrow in the global toolbar, you can click
the <img src="images/register-marker.png" alt="track location" /> Track
Location button, or you can double-click the <code>sp = [Address]</code>
label in the top right of the Dynamic Listing.</p>
Location button, or you can double-click the “sp = …” label in the top
right of the Dynamic Listing.</p>
<p>To examine a more complicated stack segment, we will break at
<code>rand</code>. Ensure your breakpoint at <code>rand</code> is
enabled and press <img src="images/resume.png" alt="resume" /> Resume.
@ -295,6 +295,13 @@ section of <code>termmines</code> in the Static Listing, the Dynamic
Listing will follow along showing you the live values in memory. You can
also experiment by placing code units in the Dynamic Listing before
committing to them in the Static Listing.</p>
<p><strong>NOTE</strong>: Theres a known issue with auto-seek obtruding
user navigation in the listings. In most cases, just navigating again
will make it stick. If it becomes a real annoyance, set the
<strong>Auto-Track</strong> drop-down in the top right of the Dynamic
Listing to <strong>Do Not Track</strong> while youre doing static RE.
Be sure to put it back to <strong>Track Program Counter</strong> when
you are done.</p>
<section id="questions" class="level4">
<h4>Questions:</h4>
<ol type="1">
@ -450,7 +457,7 @@ address is into <code>main</code>, you could use
href="../../../Ghidra/Features/Decompiler/src/main/doc/sleigh.xml">Sleigh
documentation</a>.</p>
<p>Sleigh is a bit unconventional in that its operators are typed rather
than its variables. All variables are fix-length bit vectors. Their
than its variables. All variables are fixed-length bit vectors. Their
sizes are specified in bytes, but they have no other type
information.</p>
<section id="variables-and-constants" class="level3">

View file

@ -68,7 +68,7 @@ Since the target has just entered `main`, we should expect a return address at t
With your cursor at the stack pointer, press **`P`** to place a pointer there, just like
you would in the Static Listing.
You can now navigate to that address by double-clicking it.
To return to the stack pointer, you can use the back arrow in the global toolbar, you can click the ![track location](images/register-marker.png) Track Location button, or you can double-click the `sp = [Address]` label in the top right of the Dynamic Listing.
To return to the stack pointer, you can use the back arrow in the global toolbar, you can click the ![track location](images/register-marker.png) Track Location button, or you can double-click the "sp = ..." label in the top right of the Dynamic Listing.
To examine a more complicated stack segment, we will break at `rand`.
Ensure your breakpoint at `rand` is enabled and press ![resume](images/resume.png) Resume.
@ -137,6 +137,11 @@ Because you are in a dynamic session, you have an example board to work with.
As you navigate the `.data` section of `termmines` in the Static Listing, the Dynamic Listing will follow along showing you the live values in memory.
You can also experiment by placing code units in the Dynamic Listing before committing to them in the Static Listing.
**NOTE**: There's a known issue with auto-seek obtruding user navigation in the listings.
In most cases, just navigating again will make it stick.
If it becomes a real annoyance, set the **Auto-Track** drop-down in the top right of the Dynamic Listing to **Do Not Track** while you're doing static RE.
Be sure to put it back to **Track Program Counter** when you are done.
#### Questions:
1. How are the cells allocated?
@ -244,7 +249,7 @@ For example, to see how far a return address is into `main`, you could use `*:8
For the complete specification, see the Semantic Section in the [Sleigh documentation](../../../Ghidra/Features/Decompiler/src/main/doc/sleigh.xml).
Sleigh is a bit unconventional in that its operators are typed rather than its variables.
All variables are fix-length bit vectors.
All variables are fixed-length bit vectors.
Their sizes are specified in bytes, but they have no other type information.
### Variables and Constants

View file

@ -676,8 +676,7 @@ Invalidate Emulator Cache</strong>.</li>
<strong>Resume</strong>.</li>
</ol>
<p>Stubbing any remaining external calls is left as an exercise. You are
successful when the emulator crashes with
<code>pc = 00000000</code>.</p>
successful when the emulator crashes with “pc = 00000000”.</p>
<p>Clear or disable your breakpoint and invalidate the emulator cache
again before proceeding to the next technique.</p>
</section>
@ -718,7 +717,7 @@ write the Sleigh code to mimic a <code>RET</code>. As with the
<code>CALL</code> override technique, you must now invalidate the
emulator cache and resume. Stubbing any remaining external functions is
left as an exercise. You are successful when the emulator crashes with
<code>pc = 00000000</code>.</p>
“pc = 00000000”.</p>
</section>
</section>
<section id="wrapping-up" class="level3">

View file

@ -377,7 +377,7 @@ After you have written your Sleigh code:
1. Click ![resume button](images/resume.png) **Resume**.
Stubbing any remaining external calls is left as an exercise.
You are successful when the emulator crashes with `pc = 00000000`.
You are successful when the emulator crashes with "pc = 00000000".
Clear or disable your breakpoint and invalidate the emulator cache again before proceeding to the next technique.
@ -412,7 +412,7 @@ return [RIP];
Notice that we cannot just write `RET`, but instead must write the Sleigh code to mimic a `RET`.
As with the `CALL` override technique, you must now invalidate the emulator cache and resume.
Stubbing any remaining external functions is left as an exercise.
You are successful when the emulator crashes with `pc = 00000000`.
You are successful when the emulator crashes with "pc = 00000000".
### Wrapping Up

View file

@ -168,17 +168,14 @@ class="sourceCode numberSource java numberLines"><code class="sourceCode java"><
<span id="cb1-6"><a href="#cb1-6"></a> <span class="kw">protected</span> <span class="dt">void</span> <span class="fu">run</span><span class="op">()</span> <span class="kw">throws</span> <span class="bu">Exception</span> <span class="op">{</span></span>
<span id="cb1-7"><a href="#cb1-7"></a> <span class="op">}</span></span>
<span id="cb1-8"><a href="#cb1-8"></a><span class="op">}</span></span></code></pre></div>
<p><strong>NOTE</strong>: The scripting API has been refactored a little
since the transition from Recorder-based to TraceRmi-based targets.
Parts of the API that are back-end agnostic are accessible from the
<p><strong>NOTE</strong>: The scripting API has been refactored since
the transition from Recorder-based to TraceRmi-based targets. Parts of
the API that are back-end agnostic are accessible from the
<code>FlatDebuggerAPI</code> interface. Parts of the API that require a
specific back end are in <code>FlatDebuggerRmiAPI</code> and
<code>FlatDebuggerRecorderAPI</code>, the latter of which is deprecated.
If a script written for version 11.0.2 or prior is not compiling, it can
most likely be patched up by changing
<code>implements FlatDebuggerAPI</code> to
<code>implements FlatDebuggerRecorderAPI</code>, but we recommend
porting it to use <code>implements FlatDebuggerRmiAPI</code>.</p>
specific back end are in <code>FlatDebuggerRmiAPI</code>. The old
<code>FlatDebuggerRecorderAPI</code> was removed in Ghidra 11.3, and
scripts needing it should be ported to
<code>FlatDebuggerRmiAPI</code>.</p>
<p>Technically, the Debuggers “deep” API is accessible to scripts;
however, the flat API is preferred for scripting. Also, the flat API is
usually more stable than the deep API. However, because the dynamic

View file

@ -24,10 +24,10 @@ public class DemoDebuggerScript extends GhidraScript implements FlatDebuggerAPI
}
```
**NOTE**: The scripting API has been refactored a little since the transition from Recorder-based to TraceRmi-based targets.
**NOTE**: The scripting API has been refactored since the transition from Recorder-based to TraceRmi-based targets.
Parts of the API that are back-end agnostic are accessible from the `FlatDebuggerAPI` interface.
Parts of the API that require a specific back end are in `FlatDebuggerRmiAPI` and `FlatDebuggerRecorderAPI`, the latter of which is deprecated.
If a script written for version 11.0.2 or prior is not compiling, it can most likely be patched up by changing `implements FlatDebuggerAPI` to `implements FlatDebuggerRecorderAPI`, but we recommend porting it to use `implements FlatDebuggerRmiAPI`.
Parts of the API that require a specific back end are in `FlatDebuggerRmiAPI`.
The old `FlatDebuggerRecorderAPI` was removed in Ghidra 11.3, and scripts needing it should be ported to `FlatDebuggerRmiAPI`.
Technically, the Debugger's "deep" API is accessible to scripts; however, the flat API is preferred for scripting.
Also, the flat API is usually more stable than the deep API.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 17 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 22 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 26 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 23 KiB

Before After
Before After