mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-04 10:19:23 +02:00
334 lines
16 KiB
HTML
334 lines
16 KiB
HTML
<!DOCTYPE html>
|
||
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
|
||
<head>
|
||
<meta charset="utf-8" />
|
||
<meta name="generator" content="pandoc" />
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
|
||
<title>Ghidra Debugger</title>
|
||
<style>
|
||
code{white-space: pre-wrap;}
|
||
span.smallcaps{font-variant: small-caps;}
|
||
div.columns{display: flex; gap: min(4vw, 1.5em);}
|
||
div.column{flex: auto; overflow-x: auto;}
|
||
div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
|
||
ul.task-list{list-style: none;}
|
||
ul.task-list li input[type="checkbox"] {
|
||
width: 0.8em;
|
||
margin: 0 0.8em 0.2em -1.6em;
|
||
vertical-align: middle;
|
||
}
|
||
.display.math{display: block; text-align: center; margin: 0.5rem auto;}
|
||
</style>
|
||
<link rel="stylesheet" href="style.css" />
|
||
<!--[if lt IE 9]>
|
||
<script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
|
||
<![endif]-->
|
||
</head>
|
||
<body>
|
||
<header id="nav"><a
|
||
class="beginner" href="A1-GettingStarted.html">Getting Started</a><a
|
||
class="beginner" href="A2-UITour.html">UI Tour</a><a
|
||
class="beginner" href="A3-Breakpoints.html">Breakpoints</a><a
|
||
class="beginner" href="A4-MachineState.html">Machine State</a><a
|
||
class="beginner" href="A5-Navigation.html">Navigation</a><a
|
||
class="beginner" href="A6-MemoryMap.html">Memory Map</a><a
|
||
class="advanced" href="B1-RemoteTargets.html">Remote Targets</a><a
|
||
class="advanced" href="B2-Emulation.html">Emulation</a><a
|
||
class="advanced" href="B3-Scripting.html">Scripting</a><a
|
||
class="advanced" href="B4-Modeling.html">Modeling</a>
|
||
</header>
|
||
<header id="title-block-header">
|
||
<h1 class="title">Ghidra Debugger</h1>
|
||
</header>
|
||
<nav id="TOC" role="doc-toc">
|
||
<ul>
|
||
<li><a href="#memory-map" id="toc-memory-map">Memory Map</a>
|
||
<ul>
|
||
<li><a href="#regions" id="toc-regions">Regions</a></li>
|
||
<li><a href="#modules" id="toc-modules">Modules</a></li>
|
||
<li><a href="#optional-exercise-find-the-time-surgically"
|
||
id="toc-optional-exercise-find-the-time-surgically">Optional Exercise:
|
||
Find the Time Surgically</a></li>
|
||
<li><a href="#static-mappings" id="toc-static-mappings">Static
|
||
Mappings</a></li>
|
||
<li><a href="#moving-knowledge-from-dynamic-to-static"
|
||
id="toc-moving-knowledge-from-dynamic-to-static">Moving Knowledge from
|
||
Dynamic to Static</a></li>
|
||
<li><a href="#exercise-export-and-map-ncurses"
|
||
id="toc-exercise-export-and-map-ncurses">Exercise: Export and Map
|
||
<code>ncurses</code></a></li>
|
||
<li><a href="#exercise-cheat-like-the-devs"
|
||
id="toc-exercise-cheat-like-the-devs">Exercise: Cheat Like the
|
||
Devs</a></li>
|
||
</ul></li>
|
||
</ul>
|
||
</nav>
|
||
<section id="memory-map" class="level1">
|
||
<h1>Memory Map</h1>
|
||
<p>This modules assumes you know how to launch <code>termmines</code> in
|
||
Ghidra using GDB, and know where to find the basic Debugger GUI
|
||
components. If not, please refer to the previous modules.</p>
|
||
<p>This module will address the following features in more depth:</p>
|
||
<ul>
|
||
<li>The Regions window</li>
|
||
<li>The Modules window</li>
|
||
<li>The Static Mappings window</li>
|
||
</ul>
|
||
<p>If you do not have an active session, please launch
|
||
<code>termmines</code> in the Debugger.</p>
|
||
<section id="regions" class="level2">
|
||
<h2>Regions</h2>
|
||
<figure>
|
||
<img src="images/MemoryMap_RegionsAfterLaunch.png"
|
||
alt="Regions window after launch" />
|
||
<figcaption aria-hidden="true">Regions window after launch</figcaption>
|
||
</figure>
|
||
<p>The Regions window displays a list of all the memory regions known to
|
||
the back-end debugger. In practice, not all targets will report this
|
||
information. The nearest analog from the CodeBrowser is the Memory Map
|
||
window. Unlike the Memory Map window, the Regions window includes all
|
||
regions mapped to external modules, as well as regions allocated for
|
||
stacks, heaps, or other system objects. The columns are:</p>
|
||
<ul>
|
||
<li>The <strong>Name</strong> column gives the name of the region. For
|
||
file-backed mappings, this should include the name of the file. It may
|
||
or may not include a section name. Typically, the name will include the
|
||
start address to avoid collisions.</li>
|
||
<li>The <strong>Lifespan</strong> column gives the span of snapshots
|
||
where the region has been observed. Memory maps can change during the
|
||
course of execution, and this is how Ghidra records and presents that
|
||
history.</li>
|
||
<li>The <strong>Start</strong> column gives the minimum address of the
|
||
region.</li>
|
||
<li>The <strong>End</strong> column gives the maximum (inclusive)
|
||
address of the region.</li>
|
||
<li>The <strong>Length</strong> column gives the number of bytes in the
|
||
region.</li>
|
||
<li>The <strong>Read</strong>, <strong>Write</strong>,
|
||
<strong>Execute</strong>, and <strong>Volatile</strong> columns give the
|
||
permissions/flags of the region.</li>
|
||
</ul>
|
||
<p>Try using the filter and column headers to sift and sort for
|
||
interesting regions. Double-click the start or end address to navigate
|
||
to them in the Dynamic Listing. Select one or more regions, right-click,
|
||
and choose <strong>Select Addresses</strong>. That should select all the
|
||
addresses in those regions in the Dynamic Listing. Used with the Refresh
|
||
button, you can surgically capture memory into the current snapshot.</p>
|
||
</section>
|
||
<section id="modules" class="level2">
|
||
<h2>Modules</h2>
|
||
<figure>
|
||
<img src="images/MemoryMap_ModulesAfterLaunch.png"
|
||
alt="Modules window after launch" />
|
||
<figcaption aria-hidden="true">Modules window after launch</figcaption>
|
||
</figure>
|
||
<p>The Modules window has two panes. The top pane displays a list of all
|
||
the <em>modules</em> known to the back-end debugger. The bottom pane
|
||
displays a list of all the <em>sections</em> known to the back-end
|
||
debugger. In practice, not all targets will report module information.
|
||
Fewer targets report section information. The nearest analog to the
|
||
bottom panel from the CodeBrowser is (also) the Memory Map window. The
|
||
top panel has no real analog; however, the tabs above the Static Listing
|
||
pane serve a similar purpose.</p>
|
||
<p>For a target that reports section information, the bottom panel will
|
||
display a lot of the same information as the Regions window. The columns
|
||
differ slightly, and the sections panel will <em>not</em> include
|
||
stacks, heaps, etc.</p>
|
||
<p>The module columns are:</p>
|
||
<ul>
|
||
<li>The <strong>Base</strong> column gives the image base for the
|
||
module. This should be the minimum address of the module.</li>
|
||
<li>The <strong>Max Address</strong> column gives the maximum address of
|
||
the module.</li>
|
||
<li>The <strong>Name</strong> column gives the (short) name of the
|
||
module.</li>
|
||
<li>The <strong>Module Name</strong> column gives the full file path of
|
||
the module <em>on target</em>. In some cases, this gives some other
|
||
description of the module.</li>
|
||
<li>The <strong>Lifespan</strong> column gives the span of snapshots
|
||
where the module has been observed.</li>
|
||
<li>The <strong>Length</strong> column gives the distance between the
|
||
base and max address (inclusive). Note that not every address between
|
||
base and max is necessarily mapped to the module. ELF headers specify
|
||
the load address of each section, so the memory footprint usually has
|
||
many gaps.</li>
|
||
</ul>
|
||
<p>The section columns are:</p>
|
||
<ul>
|
||
<li>The <strong>Start Address</strong> gives the minimum address of the
|
||
section.</li>
|
||
<li>The <strong>End Address</strong> gives the maximum (inclusive)
|
||
address of the section.</li>
|
||
<li>The <strong>Section Name</strong> gives the name of the
|
||
section.</li>
|
||
<li>The <strong>Module Name</strong> gives the name of the module
|
||
containing the section.</li>
|
||
<li>The <strong>Length</strong> gives the number of bytes contained in
|
||
the section.</li>
|
||
</ul>
|
||
<p><strong>NOTE</strong>: There is no lifespan column for a section. The
|
||
lifespan of a section is the lifespan of its containing module.</p>
|
||
<p>Try using the filter and column headers in each pane to sift and
|
||
sort. This is especially helpful for the sections: Type the name of a
|
||
module or section. You can also toggle the filter button in the local
|
||
toolbar to filter the sections pane to those contained in a selected
|
||
module from the top pane. Double-click any address to navigate to it.
|
||
Make a selection of modules or sections, right-click, and choose
|
||
<strong>Select Addresses</strong>. Again, combined with the Dynamic
|
||
Listing’s Refresh button, you can capture memory surgically.</p>
|
||
</section>
|
||
<section id="optional-exercise-find-the-time-surgically" class="level2">
|
||
<h2>Optional Exercise: Find the Time Surgically</h2>
|
||
<p>Repeat the “Find the Time” exercise from the previous module, but use
|
||
the Modules and Regions windows to form a more surgical selection for
|
||
capturing into the snapshots.</p>
|
||
</section>
|
||
<section id="static-mappings" class="level2">
|
||
<h2>Static Mappings</h2>
|
||
<p>The Static Mappings window provides user access to the trace’s static
|
||
mapping table. There are two ways to open the window:</p>
|
||
<ol type="1">
|
||
<li>In the menu: <strong>Window → Debugger → Static
|
||
Mappings</strong>.</li>
|
||
<li>From the Modules window, click Map Manually in the local
|
||
toolbar.</li>
|
||
</ol>
|
||
<figure>
|
||
<img src="images/MemoryMap_StaticMappingAfterLaunch.png"
|
||
alt="Static mappings window after launch" />
|
||
<figcaption aria-hidden="true">Static mappings window after
|
||
launch</figcaption>
|
||
</figure>
|
||
<p>Each row in the table is a range of mapped addresses. The columns
|
||
are:</p>
|
||
<ul>
|
||
<li>The <strong>Dynamic Address</strong> column gives the minimum
|
||
dynamic address in the mapped range.</li>
|
||
<li>The <strong>Static Program</strong> column gives the Ghidra URL of
|
||
the static image.</li>
|
||
<li>The <strong>Static Address</strong> column gives the minimum static
|
||
address in the mapped range.</li>
|
||
<li>The <strong>Length</strong> column gives the number of bytes in the
|
||
range.</li>
|
||
<li>The <strong>Shift</strong> column gives the difference in address
|
||
offsets from static to dynamic.</li>
|
||
<li>The <strong>Lifespan</strong> column gives the span of snapshots for
|
||
which this mapped range applies.</li>
|
||
</ul>
|
||
<p>The Ghidra Debugger relies heavily on Module information to
|
||
synchronize the listings and to correlate its static and dynamic
|
||
knowledge. Instead of using the module list directly for this
|
||
correlation, it populates a <em>static mapping</em> table. This permits
|
||
other sources, including user overrides, to inform the correlation. By
|
||
default, whenever a new program is opened and/or imported, the Debugger
|
||
will attempt to match it to a module in the trace and map it.
|
||
Furthermore, when you navigate to an address in a module that it is not
|
||
yet mapped to a program, it will search your project for a match and
|
||
open it automatically. You may notice the two address columns, as well
|
||
as the shift column. This illustrates that the Debugger can recognize
|
||
and cope with module relocation, especially from ASLR.</p>
|
||
<p>There are many ways to manually override the mappings:</p>
|
||
<ul>
|
||
<li>From the Modules window, select one or more modules, and choose from
|
||
the <strong>Map Module</strong> actions. Selecting a single module at a
|
||
time, it is possible to surgically map each to a chosen program.</li>
|
||
<li>From the Sections window, select one or more sections, and choose
|
||
from the <strong>Map Section</strong> actions. This is certainly more
|
||
tedious and atypical, but it allows the surgical mapping of each section
|
||
to a chosen memory block from among your open programs.</li>
|
||
<li>From the Regions window, select one or more regions, and choose from
|
||
the <strong>Map Region</strong> actions.</li>
|
||
<li>Click the Map Identically button in the Modules window toolbar.</li>
|
||
<li>Use the Add and Remove buttons in the Static Mappings window
|
||
toolbar.</li>
|
||
</ul>
|
||
<p>These methods are not described in detail here. For more information,
|
||
hover over the relevant actions and press <strong>F1</strong> for
|
||
help.</p>
|
||
</section>
|
||
<section id="moving-knowledge-from-dynamic-to-static" class="level2">
|
||
<h2>Moving Knowledge from Dynamic to Static</h2>
|
||
<p>There are occasions when it is necessary or convenient to transfer
|
||
data or markup from the dynamic session into a static program database.
|
||
For example, suppose during experimentation, you have placed a bunch of
|
||
code units in the Dynamic Listing. You might have done this because the
|
||
memory is uninitialized in the Static Listing, and you preferred some
|
||
trial and error in the Dynamic Listing, where the memory is populated.
|
||
In this case, you would want to copy those code units (though not
|
||
necessarily the byte values) from the Dynamic Listing into the Static
|
||
Listing. After selecting the units to copy, from the menus, you would
|
||
use <strong>Debugger → Copy Into Current Program</strong>.</p>
|
||
<p>In another example, you might not have an on-disk image for a module,
|
||
but you would still like to perform static analysis on that module. In
|
||
this case, you would want to copy everything within that module from the
|
||
dynamic session into a program database. After selecting the addresses
|
||
in that module, from the menus, you would use <strong>Debugger → Copy
|
||
Into New Program</strong>.</p>
|
||
<p>For demonstration, we will walk through this second case, pretending
|
||
we cannot load <code>libncurses</code> from disk:</p>
|
||
<ol type="1">
|
||
<li><p>In the top pane of the Modules window, right-click
|
||
<code>libncurses</code> and choose <strong>Select Addresses</strong>.
|
||
(Do not click <strong>Import From File System</strong>, since we are
|
||
pretending you cannot.)</p></li>
|
||
<li><p>Change focus to the Dynamic Listing.</p></li>
|
||
<li><p>In the global menu, choose <strong>Debugger → Copy Into New
|
||
Program</strong>.</p>
|
||
<figure>
|
||
<img src="images/MemoryMap_CopyNcursesInto.png"
|
||
alt="Copy dialog for ncurses" />
|
||
<figcaption aria-hidden="true">Copy dialog for ncurses</figcaption>
|
||
</figure></li>
|
||
<li><p>Keep Destination set to “New Program.”</p></li>
|
||
<li><p>Ensure “Read live target’s memory” is checked. This will spare
|
||
you from having to create a full snapshot manually.</p></li>
|
||
<li><p>Do <em>not</em> check “Use overlays where blocks already
|
||
present.” It should not have any effect for a new program,
|
||
anyway.</p></li>
|
||
<li><p>It is probably best to include everything, though “Bytes” is the
|
||
bare minimum.</p></li>
|
||
<li><p>The table displays the <em>copy plan</em>. For a new program,
|
||
this will copy with an identical mapping of addresses, which is probably
|
||
the best plan, since the target system has already applied fixups. Do
|
||
not change any addresses, lest your corrupt references in the
|
||
copy.</p></li>
|
||
<li><p>Click Copy.</p></li>
|
||
<li><p>When prompted, name the program <code>libncurses</code>.</p></li>
|
||
<li><p>You may need to click the <code>termmines</code> tab in the
|
||
Static Listing to get the UI to completely update.</p></li>
|
||
<li><p>Click back over to <code>libncurses</code> and save the program.
|
||
If you are prompted to analyze, go ahead.</p></li>
|
||
</ol>
|
||
<p>Undoubtedly, we would like to map that new program into our dynamic
|
||
session.</p>
|
||
<ol type="1">
|
||
<li>Again, in the top pane of the Modules window, right-click
|
||
<code>libncurses</code> and choose <strong>Select
|
||
Addresses</strong>.</li>
|
||
<li>Ensure the cursor in the Static Listing is at the minimum address of
|
||
<code>libncurses</code>.</li>
|
||
<li>In the Static Mappings window, click Add in the toolbar.</li>
|
||
<li>Click OK.</li>
|
||
</ol>
|
||
<p><strong>NOTE</strong>: This should be done by choosing <strong>Map to
|
||
libncurses</strong> in the right-click menu, but a bug seems to stifle
|
||
that, currently.</p>
|
||
</section>
|
||
<section id="exercise-export-and-map-ncurses" class="level2">
|
||
<h2>Exercise: Export and Map <code>ncurses</code></h2>
|
||
<p>Repeat this technique for the “system-supplied DSO” module. In
|
||
practice, there is no real reason to do this, but this particular module
|
||
prevents you from using <strong>Import From File System</strong>.</p>
|
||
</section>
|
||
<section id="exercise-cheat-like-the-devs" class="level2">
|
||
<h2>Exercise: Cheat Like the Devs</h2>
|
||
<p>This concludes the portion on the basic features of the Ghidra
|
||
Debugger. Now, let’s put your new knowledge to good use!</p>
|
||
<p>The developers left a cheat code in <code>termmines</code>. Your goal
|
||
is to figure out the cheat code, determine what it does, and describe
|
||
how it is implemented. If you have already stumbled upon this cheat, you
|
||
must still explain how it is implemented.</p>
|
||
</section>
|
||
</section>
|
||
</body>
|
||
</html>
|