mirror of
https://github.com/hakril/PythonForWindows
synced 2026-06-08 14:31:45 +00:00
1046 lines
178 KiB
HTML
1046 lines
178 KiB
HTML
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
|
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
|
|
|
|
|
<html xmlns="http://www.w3.org/1999/xhtml">
|
|
<head>
|
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
|
|
|
<title>windows.debug.debugger — PythonForWindows 0.2 documentation</title>
|
|
|
|
<link rel="stylesheet" href="../../../_static/classic.css" type="text/css" />
|
|
<link rel="stylesheet" href="../../../_static/pygments.css" type="text/css" />
|
|
|
|
<script type="text/javascript">
|
|
var DOCUMENTATION_OPTIONS = {
|
|
URL_ROOT: '../../../',
|
|
VERSION: '0.2',
|
|
COLLAPSE_INDEX: false,
|
|
FILE_SUFFIX: '.html',
|
|
HAS_SOURCE: true,
|
|
SOURCELINK_SUFFIX: '.txt'
|
|
};
|
|
</script>
|
|
<script type="text/javascript" src="../../../_static/jquery.js"></script>
|
|
<script type="text/javascript" src="../../../_static/underscore.js"></script>
|
|
<script type="text/javascript" src="../../../_static/doctools.js"></script>
|
|
<link rel="index" title="Index" href="../../../genindex.html" />
|
|
<link rel="search" title="Search" href="../../../search.html" />
|
|
</head>
|
|
<body role="document">
|
|
<div class="related" role="navigation" aria-label="related navigation">
|
|
<h3>Navigation</h3>
|
|
<ul>
|
|
<li class="right" style="margin-right: 10px">
|
|
<a href="../../../genindex.html" title="General Index"
|
|
accesskey="I">index</a></li>
|
|
<li class="right" >
|
|
<a href="../../../py-modindex.html" title="Python Module Index"
|
|
>modules</a> |</li>
|
|
<li class="nav-item nav-item-0"><a href="../../../index.html">PythonForWindows 0.2 documentation</a> »</li>
|
|
<li class="nav-item nav-item-1"><a href="../../index.html" accesskey="U">Module code</a> »</li>
|
|
</ul>
|
|
</div>
|
|
|
|
<div class="document">
|
|
<div class="documentwrapper">
|
|
<div class="bodywrapper">
|
|
<div class="body" role="main">
|
|
|
|
<h1>Source code for windows.debug.debugger</h1><div class="highlight"><pre>
|
|
<span></span><span class="kn">import</span> <span class="nn">os.path</span>
|
|
<span class="kn">from</span> <span class="nn">collections</span> <span class="k">import</span> <span class="n">defaultdict</span><span class="p">,</span> <span class="n">namedtuple</span>
|
|
<span class="kn">from</span> <span class="nn">contextlib</span> <span class="k">import</span> <span class="n">contextmanager</span>
|
|
|
|
<span class="kn">import</span> <span class="nn">windows</span>
|
|
<span class="kn">import</span> <span class="nn">windows.winobject.exception</span> <span class="k">as</span> <span class="nn">winexception</span>
|
|
<span class="kn">import</span> <span class="nn">windows.native_exec.simple_x86</span> <span class="k">as</span> <span class="nn">x86</span>
|
|
<span class="kn">import</span> <span class="nn">windows.native_exec.simple_x64</span> <span class="k">as</span> <span class="nn">x64</span>
|
|
|
|
<span class="kn">from</span> <span class="nn">windows.winobject.process</span> <span class="k">import</span> <span class="n">WinProcess</span><span class="p">,</span> <span class="n">WinThread</span>
|
|
<span class="kn">from</span> <span class="nn">windows.dbgprint</span> <span class="k">import</span> <span class="n">dbgprint</span>
|
|
<span class="kn">from</span> <span class="nn">windows</span> <span class="k">import</span> <span class="n">winproxy</span>
|
|
<span class="kn">from</span> <span class="nn">windows.generated_def.winstructs</span> <span class="k">import</span> <span class="o">*</span>
|
|
<span class="kn">from</span> <span class="nn">windows.generated_def</span> <span class="k">import</span> <span class="n">windef</span>
|
|
<span class="kn">from</span> <span class="nn">.breakpoints</span> <span class="k">import</span> <span class="o">*</span>
|
|
|
|
<span class="c1">#from windows.syswow64 import CS_32bits</span>
|
|
<span class="kn">from</span> <span class="nn">windows.winobject.exception</span> <span class="k">import</span> <span class="n">VectoredException</span>
|
|
|
|
|
|
<span class="n">PAGE_SIZE</span> <span class="o">=</span> <span class="mh">0x1000</span>
|
|
|
|
|
|
<span class="k">class</span> <span class="nc">DEBUG_EVENT</span><span class="p">(</span><span class="n">DEBUG_EVENT</span><span class="p">):</span>
|
|
<span class="n">KNOWN_EVENT_CODE</span> <span class="o">=</span> <span class="nb">dict</span><span class="p">((</span><span class="n">x</span><span class="p">,</span><span class="n">x</span><span class="p">)</span> <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="p">[</span><span class="n">EXCEPTION_DEBUG_EVENT</span><span class="p">,</span>
|
|
<span class="n">CREATE_THREAD_DEBUG_EVENT</span><span class="p">,</span> <span class="n">CREATE_PROCESS_DEBUG_EVENT</span><span class="p">,</span>
|
|
<span class="n">EXIT_THREAD_DEBUG_EVENT</span><span class="p">,</span> <span class="n">EXIT_PROCESS_DEBUG_EVENT</span><span class="p">,</span> <span class="n">LOAD_DLL_DEBUG_EVENT</span><span class="p">,</span>
|
|
<span class="n">UNLOAD_DLL_DEBUG_EVENT</span><span class="p">,</span> <span class="n">OUTPUT_DEBUG_STRING_EVENT</span><span class="p">,</span> <span class="n">RIP_EVENT</span><span class="p">])</span>
|
|
|
|
<span class="nd">@property</span>
|
|
<span class="k">def</span> <span class="nf">code</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
|
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">KNOWN_EVENT_CODE</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">dwDebugEventCode</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">dwDebugEventCode</span><span class="p">)</span>
|
|
|
|
<span class="n">WatchedPage</span> <span class="o">=</span> <span class="n">namedtuple</span><span class="p">(</span><span class="s1">'WatchedPage'</span><span class="p">,</span> <span class="p">[</span><span class="s2">"original_prot"</span><span class="p">,</span> <span class="s2">"bps"</span><span class="p">])</span>
|
|
|
|
|
|
<div class="viewcode-block" id="Debugger"><a class="viewcode-back" href="../../../debug.html#windows.debug.Debugger">[docs]</a><span class="k">class</span> <span class="nc">Debugger</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
|
|
<span class="sd">"""A debugger based on standard Win32 API. Handle :</span>
|
|
|
|
<span class="sd"> * Standard BP (int3)</span>
|
|
<span class="sd"> * Hardware-Exec BP (DrX)</span>
|
|
<span class="sd"> * Memory BP (virtual_protect)"""</span>
|
|
|
|
<div class="viewcode-block" id="Debugger.__init__"><a class="viewcode-back" href="../../../debug.html#windows.debug.Debugger.__init__">[docs]</a> <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">target</span><span class="p">):</span>
|
|
<span class="sd">"""``target`` must be a debuggable :class:`WinProcess`."""</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_init_dispatch_handlers</span><span class="p">()</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">target</span> <span class="o">=</span> <span class="n">target</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">is_target_launched</span> <span class="o">=</span> <span class="kc">False</span>
|
|
<span class="c1">#if not already_debuggable:</span>
|
|
<span class="c1"># winproxy.DebugActiveProcess(target.pid)</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">processes</span> <span class="o">=</span> <span class="p">{}</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">threads</span> <span class="o">=</span> <span class="p">{}</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">current_process</span> <span class="o">=</span> <span class="kc">None</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">current_thread</span> <span class="o">=</span> <span class="kc">None</span>
|
|
<span class="c1"># List of breakpoints</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">breakpoints</span> <span class="o">=</span> <span class="p">{}</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_pending_breakpoints</span> <span class="o">=</span> <span class="p">{}</span> <span class="c1">#Breakpoints to put in new process / threads</span>
|
|
<span class="c1"># Values rewritten by "\xcc"</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_memory_save</span> <span class="o">=</span> <span class="nb">dict</span><span class="p">()</span>
|
|
<span class="c1"># Dict of {tid : {drx taken : BP}}</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_hardware_breakpoint</span> <span class="o">=</span> <span class="p">{}</span>
|
|
<span class="c1"># Breakpoints to reput..</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_breakpoint_to_reput</span> <span class="o">=</span> <span class="p">{}</span>
|
|
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_module_by_process</span> <span class="o">=</span> <span class="p">{}</span>
|
|
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_pending_breakpoints_new</span> <span class="o">=</span> <span class="n">defaultdict</span><span class="p">(</span><span class="nb">list</span><span class="p">)</span>
|
|
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_explicit_single_step</span> <span class="o">=</span> <span class="p">{}</span>
|
|
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_watched_pages</span> <span class="o">=</span> <span class="p">{}</span><span class="c1"># Dict [page_modif] -> [mem bp on the page]</span>
|
|
|
|
<span class="c1"># [start] -> (size, current_proctection, original_prot)</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_virtual_protected_memory</span> <span class="o">=</span> <span class="p">[]</span> <span class="c1"># List of memory-range modified by a MemBP</span></div>
|
|
|
|
|
|
<span class="nd">@classmethod</span>
|
|
<div class="viewcode-block" id="Debugger.attach"><a class="viewcode-back" href="../../../debug.html#windows.debug.Debugger.attach">[docs]</a> <span class="k">def</span> <span class="nf">attach</span><span class="p">(</span><span class="bp">cls</span><span class="p">,</span> <span class="n">target</span><span class="p">):</span>
|
|
<span class="sd">"""attach to ``target`` (must be a :class:`WinProcess`)</span>
|
|
|
|
<span class="sd"> :rtype: :class:`Debugger`"""</span>
|
|
<span class="n">winproxy</span><span class="o">.</span><span class="n">DebugActiveProcess</span><span class="p">(</span><span class="n">target</span><span class="o">.</span><span class="n">pid</span><span class="p">)</span>
|
|
<span class="k">return</span> <span class="bp">cls</span><span class="p">(</span><span class="n">target</span><span class="p">)</span></div>
|
|
|
|
<div class="viewcode-block" id="Debugger.detach"><a class="viewcode-back" href="../../../debug.html#windows.debug.Debugger.detach">[docs]</a> <span class="k">def</span> <span class="nf">detach</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">target</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
|
|
<span class="sd">"""Detach from all debugged processes or process ``target``"""</span>
|
|
<span class="k">if</span> <span class="n">target</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="n">targets</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">processes</span><span class="o">.</span><span class="n">values</span><span class="p">()</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="n">targets</span><span class="p">:</span>
|
|
<span class="c1"># We are not following any process</span>
|
|
<span class="c1"># maybe a attach/detach with Debugger.loop</span>
|
|
<span class="c1"># Just detach from the initial target</span>
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">target</span><span class="p">:</span>
|
|
<span class="n">tpid</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">target</span><span class="o">.</span><span class="n">pid</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">target</span> <span class="o">=</span> <span class="kc">None</span> <span class="c1"># Remove ref to process -> GC -> CloseHandle -> process is destroyed</span>
|
|
<span class="n">windows</span><span class="o">.</span><span class="n">winproxy</span><span class="o">.</span><span class="n">DebugActiveProcessStop</span><span class="p">(</span><span class="n">tpid</span><span class="p">)</span>
|
|
<span class="k">return</span>
|
|
<span class="k">for</span> <span class="n">proc</span> <span class="ow">in</span> <span class="n">targets</span><span class="p">:</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">detach</span><span class="p">(</span><span class="n">proc</span><span class="p">)</span>
|
|
<span class="k">del</span> <span class="n">targets</span>
|
|
<span class="k">return</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">target</span><span class="p">,</span> <span class="n">WinProcess</span><span class="p">):</span>
|
|
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s2">"Detach accept only WinProcess"</span><span class="p">)</span>
|
|
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">disable_all_memory_breakpoints</span><span class="p">(</span><span class="n">target</span><span class="p">)</span>
|
|
<span class="k">for</span> <span class="n">bp</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">breakpoints</span><span class="p">[</span><span class="n">target</span><span class="o">.</span><span class="n">pid</span><span class="p">]</span><span class="o">.</span><span class="n">values</span><span class="p">():</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="n">bp</span><span class="o">.</span><span class="n">apply_to_target</span><span class="p">(</span><span class="n">target</span><span class="p">):</span>
|
|
<span class="n">target_threads</span> <span class="o">=</span> <span class="p">[</span><span class="n">t</span> <span class="k">for</span> <span class="n">t</span> <span class="ow">in</span> <span class="n">target</span><span class="o">.</span><span class="n">threads</span> <span class="k">if</span> <span class="n">t</span><span class="o">.</span><span class="n">tid</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">threads</span><span class="p">]</span>
|
|
<span class="n">bp_threads</span> <span class="o">=</span> <span class="p">[]</span>
|
|
<span class="c1"># TODO: clean API tu request HXBP on a thread</span>
|
|
<span class="k">for</span> <span class="n">t</span> <span class="ow">in</span> <span class="n">target_threads</span><span class="p">:</span>
|
|
<span class="n">t_bps</span> <span class="o">=</span> <span class="p">[</span><span class="n">pos</span> <span class="k">for</span> <span class="n">pos</span><span class="p">,</span> <span class="n">hbp</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">_hardware_breakpoint</span><span class="p">[</span><span class="n">t</span><span class="o">.</span><span class="n">tid</span><span class="p">]</span><span class="o">.</span><span class="n">items</span><span class="p">()</span> <span class="k">if</span> <span class="n">hbp</span> <span class="o">==</span> <span class="n">bp</span><span class="p">]</span>
|
|
<span class="k">if</span> <span class="n">t_bps</span><span class="p">:</span>
|
|
<span class="n">bp_threads</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">t</span><span class="p">)</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">del_bp</span><span class="p">(</span><span class="n">bp</span><span class="p">,</span> <span class="n">bp_threads</span><span class="p">)</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">del_bp</span><span class="p">(</span><span class="n">bp</span><span class="p">,</span> <span class="p">[</span><span class="n">target</span><span class="p">])</span>
|
|
|
|
<span class="k">for</span> <span class="n">thread</span> <span class="ow">in</span> <span class="p">[</span><span class="n">t</span> <span class="k">for</span> <span class="n">t</span> <span class="ow">in</span> <span class="n">target</span><span class="o">.</span><span class="n">threads</span> <span class="k">if</span> <span class="n">t</span><span class="o">.</span><span class="n">tid</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">threads</span><span class="p">]:</span>
|
|
<span class="k">del</span> <span class="bp">self</span><span class="o">.</span><span class="n">_explicit_single_step</span><span class="p">[</span><span class="n">thread</span><span class="o">.</span><span class="n">tid</span><span class="p">]</span>
|
|
<span class="k">del</span> <span class="bp">self</span><span class="o">.</span><span class="n">_breakpoint_to_reput</span><span class="p">[</span><span class="n">thread</span><span class="o">.</span><span class="n">tid</span><span class="p">]</span>
|
|
<span class="k">del</span> <span class="bp">self</span><span class="o">.</span><span class="n">threads</span><span class="p">[</span><span class="n">thread</span><span class="o">.</span><span class="n">tid</span><span class="p">]</span>
|
|
<span class="n">ctx</span> <span class="o">=</span> <span class="n">thread</span><span class="o">.</span><span class="n">context</span>
|
|
<span class="k">if</span> <span class="n">ctx</span><span class="o">.</span><span class="n">EEFlags</span><span class="o">.</span><span class="n">TF</span><span class="p">:</span> <span class="c1"># Remove TRAPFlag before detaching (or it will lead to a crash)</span>
|
|
<span class="n">ctx</span><span class="o">.</span><span class="n">EEFlags</span><span class="o">.</span><span class="n">TF</span> <span class="o">=</span> <span class="mi">0</span>
|
|
<span class="n">thread</span><span class="o">.</span><span class="n">set_context</span><span class="p">(</span><span class="n">ctx</span><span class="p">)</span>
|
|
<span class="k">del</span> <span class="bp">self</span><span class="o">.</span><span class="n">processes</span><span class="p">[</span><span class="n">target</span><span class="o">.</span><span class="n">pid</span><span class="p">]</span>
|
|
<span class="k">del</span> <span class="bp">self</span><span class="o">.</span><span class="n">_watched_pages</span><span class="p">[</span><span class="n">target</span><span class="o">.</span><span class="n">pid</span><span class="p">]</span>
|
|
<span class="k">del</span> <span class="bp">self</span><span class="o">.</span><span class="n">_module_by_process</span><span class="p">[</span><span class="n">target</span><span class="o">.</span><span class="n">pid</span><span class="p">]</span>
|
|
|
|
<span class="k">if</span> <span class="n">target</span> <span class="ow">is</span> <span class="bp">self</span><span class="o">.</span><span class="n">current_process</span><span class="p">:</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_finish_debug_event</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">REMOVE_ME_debug_event</span><span class="p">,</span> <span class="n">DBG_CONTINUE</span><span class="p">)</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">current_process</span> <span class="o">=</span> <span class="kc">None</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">current_thread</span> <span class="o">=</span> <span class="kc">None</span>
|
|
|
|
<span class="k">if</span> <span class="n">target</span><span class="o">.</span><span class="n">pid</span> <span class="o">==</span> <span class="bp">self</span><span class="o">.</span><span class="n">target</span><span class="o">.</span><span class="n">pid</span><span class="p">:</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">target</span> <span class="o">=</span> <span class="kc">None</span>
|
|
<span class="n">windows</span><span class="o">.</span><span class="n">winproxy</span><span class="o">.</span><span class="n">DebugActiveProcessStop</span><span class="p">(</span><span class="n">target</span><span class="o">.</span><span class="n">pid</span><span class="p">)</span></div>
|
|
|
|
<span class="k">def</span> <span class="nf">_killed_in_action</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
|
<span class="sd">"""Return ``True`` if current process have been detached by user callback"""</span>
|
|
<span class="c1"># Fix ? _handle_exit_process remove from processes but need a FinishDebugEvent</span>
|
|
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">current_process</span> <span class="ow">is</span> <span class="kc">None</span> <span class="ow">or</span> <span class="bp">self</span><span class="o">.</span><span class="n">current_process</span><span class="o">.</span><span class="n">pid</span> <span class="ow">not</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">processes</span>
|
|
|
|
<span class="nd">@classmethod</span>
|
|
<div class="viewcode-block" id="Debugger.debug"><a class="viewcode-back" href="../../../debug.html#windows.debug.Debugger.debug">[docs]</a> <span class="k">def</span> <span class="nf">debug</span><span class="p">(</span><span class="bp">cls</span><span class="p">,</span> <span class="n">path</span><span class="p">,</span> <span class="n">args</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">dwCreationFlags</span><span class="o">=</span><span class="mi">0</span><span class="p">,</span> <span class="n">show_windows</span><span class="o">=</span><span class="kc">False</span><span class="p">):</span>
|
|
<span class="sd">"""Create a process and debug it.</span>
|
|
|
|
<span class="sd"> :rtype: :class:`Debugger`"""</span>
|
|
<span class="n">dwCreationFlags</span> <span class="o">|=</span> <span class="n">DEBUG_PROCESS</span>
|
|
<span class="n">c</span> <span class="o">=</span> <span class="n">windows</span><span class="o">.</span><span class="n">utils</span><span class="o">.</span><span class="n">create_process</span><span class="p">(</span><span class="n">path</span><span class="p">,</span> <span class="n">args</span><span class="o">=</span><span class="n">args</span><span class="p">,</span> <span class="n">dwCreationFlags</span><span class="o">=</span><span class="n">dwCreationFlags</span><span class="p">,</span> <span class="n">show_windows</span><span class="o">=</span><span class="n">show_windows</span><span class="p">)</span>
|
|
<span class="k">return</span> <span class="bp">cls</span><span class="p">(</span><span class="n">c</span><span class="p">)</span></div>
|
|
|
|
<span class="k">def</span> <span class="nf">_init_dispatch_handlers</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
|
<span class="n">dbg_evt_dispatch</span> <span class="o">=</span> <span class="p">{}</span>
|
|
<span class="n">dbg_evt_dispatch</span><span class="p">[</span><span class="n">EXCEPTION_DEBUG_EVENT</span><span class="p">]</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_handle_exception</span>
|
|
<span class="n">dbg_evt_dispatch</span><span class="p">[</span><span class="n">CREATE_THREAD_DEBUG_EVENT</span><span class="p">]</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_handle_create_thread</span>
|
|
<span class="n">dbg_evt_dispatch</span><span class="p">[</span><span class="n">CREATE_PROCESS_DEBUG_EVENT</span><span class="p">]</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_handle_create_process</span>
|
|
<span class="n">dbg_evt_dispatch</span><span class="p">[</span><span class="n">EXIT_PROCESS_DEBUG_EVENT</span><span class="p">]</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_handle_exit_process</span>
|
|
<span class="n">dbg_evt_dispatch</span><span class="p">[</span><span class="n">EXIT_THREAD_DEBUG_EVENT</span><span class="p">]</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_handle_exit_thread</span>
|
|
<span class="n">dbg_evt_dispatch</span><span class="p">[</span><span class="n">LOAD_DLL_DEBUG_EVENT</span><span class="p">]</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_handle_load_dll</span>
|
|
<span class="n">dbg_evt_dispatch</span><span class="p">[</span><span class="n">UNLOAD_DLL_DEBUG_EVENT</span><span class="p">]</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_handle_unload_dll</span>
|
|
<span class="n">dbg_evt_dispatch</span><span class="p">[</span><span class="n">RIP_EVENT</span><span class="p">]</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_handle_rip</span>
|
|
<span class="n">dbg_evt_dispatch</span><span class="p">[</span><span class="n">OUTPUT_DEBUG_STRING_EVENT</span><span class="p">]</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_handle_output_debug_string</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_DebugEventCode_dispatch</span> <span class="o">=</span> <span class="n">dbg_evt_dispatch</span>
|
|
|
|
<span class="k">def</span> <span class="nf">_debug_event_generator</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
|
<span class="k">while</span> <span class="kc">True</span><span class="p">:</span>
|
|
<span class="n">debug_event</span> <span class="o">=</span> <span class="n">DEBUG_EVENT</span><span class="p">()</span>
|
|
<span class="n">winproxy</span><span class="o">.</span><span class="n">WaitForDebugEvent</span><span class="p">(</span><span class="n">debug_event</span><span class="p">)</span>
|
|
<span class="k">yield</span> <span class="n">debug_event</span>
|
|
|
|
<span class="k">def</span> <span class="nf">_finish_debug_event</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">event</span><span class="p">,</span> <span class="n">action</span><span class="p">):</span>
|
|
<span class="k">if</span> <span class="n">action</span> <span class="ow">not</span> <span class="ow">in</span> <span class="p">[</span><span class="n">windef</span><span class="o">.</span><span class="n">DBG_CONTINUE</span><span class="p">,</span> <span class="n">windef</span><span class="o">.</span><span class="n">DBG_EXCEPTION_NOT_HANDLED</span><span class="p">]:</span>
|
|
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s1">'Unknow action : <0>'</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">action</span><span class="p">))</span>
|
|
<span class="n">winproxy</span><span class="o">.</span><span class="n">ContinueDebugEvent</span><span class="p">(</span><span class="n">event</span><span class="o">.</span><span class="n">dwProcessId</span><span class="p">,</span> <span class="n">event</span><span class="o">.</span><span class="n">dwThreadId</span><span class="p">,</span> <span class="n">action</span><span class="p">)</span>
|
|
|
|
<span class="k">def</span> <span class="nf">_update_debugger_state</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">debug_event</span><span class="p">):</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">current_process</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">processes</span><span class="p">[</span><span class="n">debug_event</span><span class="o">.</span><span class="n">dwProcessId</span><span class="p">]</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">current_thread</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">threads</span><span class="p">[</span><span class="n">debug_event</span><span class="o">.</span><span class="n">dwThreadId</span><span class="p">]</span>
|
|
|
|
<span class="k">def</span> <span class="nf">_dispatch_debug_event</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">debug_event</span><span class="p">):</span>
|
|
<span class="c1">#print("DISPATCH {0}".format(DEBUG_EVENT.KNOWN_EVENT_CODE.get(debug_event.dwDebugEventCode)))</span>
|
|
<span class="n">handler</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_DebugEventCode_dispatch</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">debug_event</span><span class="o">.</span><span class="n">dwDebugEventCode</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">_handle_unknown_debug_event</span><span class="p">)</span>
|
|
<span class="k">return</span> <span class="n">handler</span><span class="p">(</span><span class="n">debug_event</span><span class="p">)</span>
|
|
|
|
<span class="k">def</span> <span class="nf">_dispatch_breakpoint</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">exception</span><span class="p">,</span> <span class="n">addr</span><span class="p">):</span>
|
|
<span class="n">bp</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">breakpoints</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">current_process</span><span class="o">.</span><span class="n">pid</span><span class="p">][</span><span class="n">addr</span><span class="p">]</span>
|
|
<span class="k">with</span> <span class="bp">self</span><span class="o">.</span><span class="n">DisabledMemoryBreakpoint</span><span class="p">():</span>
|
|
<span class="n">x</span> <span class="o">=</span> <span class="n">bp</span><span class="o">.</span><span class="n">trigger</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">exception</span><span class="p">)</span>
|
|
<span class="k">return</span> <span class="n">x</span>
|
|
|
|
<span class="k">def</span> <span class="nf">_resolve</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">addr</span><span class="p">,</span> <span class="n">target</span><span class="p">):</span>
|
|
<span class="n">dbgprint</span><span class="p">(</span><span class="s2">"Resolving <</span><span class="si">{0}</span><span class="s2">> in <</span><span class="si">{1}</span><span class="s2">>"</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">addr</span><span class="p">,</span> <span class="n">target</span><span class="p">),</span> <span class="s2">"DBG"</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">addr</span><span class="p">,</span> <span class="n">basestring</span><span class="p">):</span>
|
|
<span class="k">return</span> <span class="n">addr</span>
|
|
<span class="n">dll</span><span class="p">,</span> <span class="n">api</span> <span class="o">=</span> <span class="n">addr</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s2">"!"</span><span class="p">)</span>
|
|
<span class="n">dll</span> <span class="o">=</span> <span class="n">dll</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span>
|
|
<span class="n">modules</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_module_by_process</span><span class="p">[</span><span class="n">target</span><span class="o">.</span><span class="n">pid</span><span class="p">]</span>
|
|
<span class="n">mod</span> <span class="o">=</span> <span class="kc">None</span>
|
|
<span class="k">if</span> <span class="n">dll</span> <span class="ow">in</span> <span class="n">modules</span><span class="p">:</span>
|
|
<span class="n">mod</span> <span class="o">=</span> <span class="p">[</span><span class="n">modules</span><span class="p">[</span><span class="n">dll</span><span class="p">]]</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="n">mod</span><span class="p">:</span>
|
|
<span class="k">return</span> <span class="kc">None</span>
|
|
<span class="c1"># TODO: optim exports are the same for whole system (32 vs 64 bits)</span>
|
|
<span class="c1"># I don't have to reparse the exports each time..</span>
|
|
<span class="c1"># Try to interpret api as an int</span>
|
|
<span class="k">try</span><span class="p">:</span>
|
|
<span class="n">api_int</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">api</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span>
|
|
<span class="k">return</span> <span class="n">mod</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">baseaddr</span> <span class="o">+</span> <span class="n">api_int</span>
|
|
<span class="k">except</span> <span class="ne">ValueError</span><span class="p">:</span>
|
|
<span class="k">pass</span>
|
|
<span class="n">exports</span> <span class="o">=</span> <span class="n">mod</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">exports</span>
|
|
<span class="k">if</span> <span class="n">api</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">exports</span><span class="p">:</span>
|
|
<span class="n">dbgprint</span><span class="p">(</span><span class="s2">"Error resolving <</span><span class="si">{0}</span><span class="s2">> in <</span><span class="si">{1}</span><span class="s2">>"</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">addr</span><span class="p">,</span> <span class="n">target</span><span class="p">),</span> <span class="s2">"DBG"</span><span class="p">)</span>
|
|
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s2">"Unknown API <</span><span class="si">{0}</span><span class="s2">> in DLL </span><span class="si">{1}</span><span class="s2">"</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">api</span><span class="p">,</span> <span class="n">dll</span><span class="p">))</span>
|
|
<span class="k">return</span> <span class="n">exports</span><span class="p">[</span><span class="n">api</span><span class="p">]</span>
|
|
|
|
<span class="k">def</span> <span class="nf">add_pending_breakpoint</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">bp</span><span class="p">,</span> <span class="n">target</span><span class="p">):</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_pending_breakpoints_new</span><span class="p">[</span><span class="n">target</span><span class="p">]</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">bp</span><span class="p">)</span>
|
|
|
|
<span class="k">def</span> <span class="nf">remove_pending_breakpoint</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">bp</span><span class="p">,</span> <span class="n">target</span><span class="p">):</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_pending_breakpoints_new</span><span class="p">[</span><span class="n">target</span><span class="p">]</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">bp</span><span class="p">)</span>
|
|
|
|
<span class="k">def</span> <span class="nf">_setup_breakpoint</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">bp</span><span class="p">,</span> <span class="n">target</span><span class="p">):</span>
|
|
<span class="n">_setup_method</span> <span class="o">=</span> <span class="nb">getattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="s2">"_setup_breakpoint_"</span> <span class="o">+</span> <span class="n">bp</span><span class="o">.</span><span class="n">type</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="n">target</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="n">bp</span><span class="o">.</span><span class="n">type</span> <span class="ow">in</span> <span class="p">[</span><span class="n">STANDARD_BP</span><span class="p">,</span> <span class="n">MEMORY_BREAKPOINT</span><span class="p">]:</span> <span class="c1">#TODO: better..</span>
|
|
<span class="n">targets</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">processes</span><span class="o">.</span><span class="n">values</span><span class="p">()</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="n">targets</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">threads</span><span class="o">.</span><span class="n">values</span><span class="p">()</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="n">targets</span> <span class="o">=</span> <span class="p">[</span><span class="n">target</span><span class="p">]</span>
|
|
<span class="k">for</span> <span class="n">target</span> <span class="ow">in</span> <span class="n">targets</span><span class="p">:</span>
|
|
<span class="k">return</span> <span class="n">_setup_method</span><span class="p">(</span><span class="n">bp</span><span class="p">,</span> <span class="n">target</span><span class="p">)</span>
|
|
|
|
<span class="k">def</span> <span class="nf">_restore_breakpoints</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
|
<span class="k">for</span> <span class="n">bp</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">_breakpoint_to_reput</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">current_thread</span><span class="o">.</span><span class="n">tid</span><span class="p">]:</span>
|
|
<span class="k">if</span> <span class="n">bp</span><span class="o">.</span><span class="n">type</span> <span class="o">==</span> <span class="n">HARDWARE_EXEC_BP</span><span class="p">:</span>
|
|
<span class="k">raise</span> <span class="ne">NotImplementedError</span><span class="p">(</span><span class="s2">"Why is this here ? we use RF flags to pass HXBP"</span><span class="p">)</span>
|
|
<span class="n">restore</span> <span class="o">=</span> <span class="nb">getattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="s2">"_restore_breakpoint_"</span> <span class="o">+</span> <span class="n">bp</span><span class="o">.</span><span class="n">type</span><span class="p">)</span>
|
|
<span class="n">restore</span><span class="p">(</span><span class="n">bp</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">current_process</span><span class="p">)</span>
|
|
<span class="k">del</span> <span class="bp">self</span><span class="o">.</span><span class="n">_breakpoint_to_reput</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">current_thread</span><span class="o">.</span><span class="n">tid</span><span class="p">][:]</span>
|
|
<span class="k">return</span>
|
|
|
|
<span class="k">def</span> <span class="nf">_setup_breakpoint_BP</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">bp</span><span class="p">,</span> <span class="n">target</span><span class="p">):</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">target</span><span class="p">,</span> <span class="n">WinProcess</span><span class="p">):</span>
|
|
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s2">"SETUP STANDARD_BP on </span><span class="si">{0}</span><span class="s2">"</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">target</span><span class="p">))</span>
|
|
|
|
<span class="n">addr</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_resolve</span><span class="p">(</span><span class="n">bp</span><span class="o">.</span><span class="n">addr</span><span class="p">,</span> <span class="n">target</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="n">addr</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="k">return</span> <span class="kc">False</span>
|
|
<span class="n">bp</span><span class="o">.</span><span class="n">_addr</span> <span class="o">=</span> <span class="n">addr</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_memory_save</span><span class="p">[</span><span class="n">target</span><span class="o">.</span><span class="n">pid</span><span class="p">][</span><span class="n">addr</span><span class="p">]</span> <span class="o">=</span> <span class="n">target</span><span class="o">.</span><span class="n">read_memory</span><span class="p">(</span><span class="n">addr</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">breakpoints</span><span class="p">[</span><span class="n">target</span><span class="o">.</span><span class="n">pid</span><span class="p">][</span><span class="n">addr</span><span class="p">]</span> <span class="o">=</span> <span class="n">bp</span>
|
|
<span class="n">target</span><span class="o">.</span><span class="n">write_memory</span><span class="p">(</span><span class="n">addr</span><span class="p">,</span> <span class="s2">"</span><span class="se">\xcc</span><span class="s2">"</span><span class="p">)</span>
|
|
<span class="k">return</span> <span class="kc">True</span>
|
|
|
|
<span class="k">def</span> <span class="nf">_restore_breakpoint_BP</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">bp</span><span class="p">,</span> <span class="n">target</span><span class="p">):</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_memory_save</span><span class="p">[</span><span class="n">target</span><span class="o">.</span><span class="n">pid</span><span class="p">][</span><span class="n">bp</span><span class="o">.</span><span class="n">_addr</span><span class="p">]</span> <span class="o">=</span> <span class="n">target</span><span class="o">.</span><span class="n">read_memory</span><span class="p">(</span><span class="n">bp</span><span class="o">.</span><span class="n">_addr</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
|
|
<span class="k">return</span> <span class="n">target</span><span class="o">.</span><span class="n">write_memory</span><span class="p">(</span><span class="n">bp</span><span class="o">.</span><span class="n">_addr</span><span class="p">,</span> <span class="s2">"</span><span class="se">\xcc</span><span class="s2">"</span><span class="p">)</span>
|
|
|
|
<span class="k">def</span> <span class="nf">_remove_breakpoint_BP</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">bp</span><span class="p">,</span> <span class="n">target</span><span class="p">):</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">target</span><span class="p">,</span> <span class="n">WinProcess</span><span class="p">):</span>
|
|
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s2">"SETUP STANDARD_BP on </span><span class="si">{0}</span><span class="s2">"</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">target</span><span class="p">))</span>
|
|
<span class="n">addr</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_resolve</span><span class="p">(</span><span class="n">bp</span><span class="o">.</span><span class="n">addr</span><span class="p">,</span> <span class="n">target</span><span class="p">)</span>
|
|
<span class="n">target</span><span class="o">.</span><span class="n">write_memory</span><span class="p">(</span><span class="n">addr</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">_memory_save</span><span class="p">[</span><span class="n">target</span><span class="o">.</span><span class="n">pid</span><span class="p">][</span><span class="n">addr</span><span class="p">])</span>
|
|
<span class="k">del</span> <span class="bp">self</span><span class="o">.</span><span class="n">_memory_save</span><span class="p">[</span><span class="n">target</span><span class="o">.</span><span class="n">pid</span><span class="p">][</span><span class="n">addr</span><span class="p">]</span>
|
|
<span class="k">del</span> <span class="bp">self</span><span class="o">.</span><span class="n">breakpoints</span><span class="p">[</span><span class="n">target</span><span class="o">.</span><span class="n">pid</span><span class="p">][</span><span class="n">addr</span><span class="p">]</span>
|
|
<span class="k">return</span> <span class="kc">True</span>
|
|
|
|
<span class="k">def</span> <span class="nf">_setup_breakpoint_HXBP</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">bp</span><span class="p">,</span> <span class="n">target</span><span class="p">):</span>
|
|
<span class="c1">#print("Setup {0} into {1}".format(bp, target))</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">target</span><span class="p">,</span> <span class="n">WinThread</span><span class="p">):</span>
|
|
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s2">"SETUP HXBP_BP on </span><span class="si">{0}</span><span class="s2">"</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">target</span><span class="p">))</span>
|
|
<span class="c1"># Todo: opti, not reparse exports for all thread of the same process..</span>
|
|
<span class="n">addr</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_resolve</span><span class="p">(</span><span class="n">bp</span><span class="o">.</span><span class="n">addr</span><span class="p">,</span> <span class="n">target</span><span class="o">.</span><span class="n">owner</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="n">addr</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="k">return</span> <span class="kc">False</span>
|
|
<span class="n">x</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_hardware_breakpoint</span><span class="p">[</span><span class="n">target</span><span class="o">.</span><span class="n">tid</span><span class="p">]</span>
|
|
<span class="k">if</span> <span class="nb">all</span><span class="p">(</span><span class="n">pos</span> <span class="ow">in</span> <span class="n">x</span> <span class="k">for</span> <span class="n">pos</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">4</span><span class="p">)):</span>
|
|
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s2">"Cannot put </span><span class="si">{0}</span><span class="s2"> in </span><span class="si">{1}</span><span class="s2"> (DRx full)"</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">bp</span><span class="p">,</span> <span class="n">target</span><span class="p">))</span>
|
|
<span class="n">empty_drx</span> <span class="o">=</span> <span class="nb">str</span><span class="p">([</span><span class="n">pos</span> <span class="k">for</span> <span class="n">pos</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">4</span><span class="p">)</span> <span class="k">if</span> <span class="n">pos</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">x</span><span class="p">][</span><span class="mi">0</span><span class="p">])</span>
|
|
<span class="n">ctx</span> <span class="o">=</span> <span class="n">target</span><span class="o">.</span><span class="n">context</span>
|
|
<span class="n">ctx</span><span class="o">.</span><span class="n">EDr7</span><span class="o">.</span><span class="n">GE</span> <span class="o">=</span> <span class="mi">1</span>
|
|
<span class="n">ctx</span><span class="o">.</span><span class="n">EDr7</span><span class="o">.</span><span class="n">LE</span> <span class="o">=</span> <span class="mi">1</span>
|
|
<span class="nb">setattr</span><span class="p">(</span><span class="n">ctx</span><span class="o">.</span><span class="n">EDr7</span><span class="p">,</span> <span class="s2">"L"</span> <span class="o">+</span> <span class="n">empty_drx</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
|
|
<span class="nb">setattr</span><span class="p">(</span><span class="n">ctx</span><span class="p">,</span> <span class="s2">"Dr"</span> <span class="o">+</span> <span class="n">empty_drx</span><span class="p">,</span> <span class="n">addr</span><span class="p">)</span>
|
|
<span class="n">x</span><span class="p">[</span><span class="nb">int</span><span class="p">(</span><span class="n">empty_drx</span><span class="p">)]</span> <span class="o">=</span> <span class="n">bp</span>
|
|
<span class="n">target</span><span class="o">.</span><span class="n">set_context</span><span class="p">(</span><span class="n">ctx</span><span class="p">)</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">breakpoints</span><span class="p">[</span><span class="n">target</span><span class="o">.</span><span class="n">owner</span><span class="o">.</span><span class="n">pid</span><span class="p">][</span><span class="n">addr</span><span class="p">]</span> <span class="o">=</span> <span class="n">bp</span>
|
|
<span class="k">return</span> <span class="kc">True</span>
|
|
|
|
<span class="k">def</span> <span class="nf">_remove_breakpoint_HXBP</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">bp</span><span class="p">,</span> <span class="n">target</span><span class="p">):</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">target</span><span class="p">,</span> <span class="n">WinThread</span><span class="p">):</span>
|
|
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s2">"SETUP HXBP_BP on </span><span class="si">{0}</span><span class="s2">"</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">target</span><span class="p">))</span>
|
|
<span class="n">addr</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_resolve</span><span class="p">(</span><span class="n">bp</span><span class="o">.</span><span class="n">addr</span><span class="p">,</span> <span class="n">target</span><span class="o">.</span><span class="n">owner</span><span class="p">)</span>
|
|
<span class="n">bp_pos</span> <span class="o">=</span> <span class="p">[</span><span class="n">pos</span> <span class="k">for</span> <span class="n">pos</span><span class="p">,</span> <span class="n">hbp</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">_hardware_breakpoint</span><span class="p">[</span><span class="n">target</span><span class="o">.</span><span class="n">tid</span><span class="p">]</span><span class="o">.</span><span class="n">items</span><span class="p">()</span> <span class="k">if</span> <span class="n">hbp</span> <span class="o">==</span> <span class="n">bp</span><span class="p">]</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="n">bp_pos</span><span class="p">:</span>
|
|
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s2">"Asked to remove </span><span class="si">{0}</span><span class="s2"> from </span><span class="si">{1}</span><span class="s2"> but not present in hbp_list"</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">bp</span><span class="p">,</span> <span class="n">target</span><span class="p">))</span>
|
|
<span class="n">bp_pos_str</span> <span class="o">=</span> <span class="nb">str</span><span class="p">(</span><span class="n">bp_pos</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span>
|
|
<span class="n">ctx</span> <span class="o">=</span> <span class="n">target</span><span class="o">.</span><span class="n">context</span>
|
|
<span class="nb">setattr</span><span class="p">(</span><span class="n">ctx</span><span class="o">.</span><span class="n">EDr7</span><span class="p">,</span> <span class="s2">"L"</span> <span class="o">+</span> <span class="n">bp_pos_str</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span>
|
|
<span class="nb">setattr</span><span class="p">(</span><span class="n">ctx</span><span class="p">,</span> <span class="s2">"Dr"</span> <span class="o">+</span> <span class="n">bp_pos_str</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span>
|
|
<span class="n">target</span><span class="o">.</span><span class="n">set_context</span><span class="p">(</span><span class="n">ctx</span><span class="p">)</span>
|
|
<span class="k">try</span><span class="p">:</span> <span class="c1"># TODO: vraiment faire les HXBP par thread ? ...</span>
|
|
<span class="k">del</span> <span class="bp">self</span><span class="o">.</span><span class="n">breakpoints</span><span class="p">[</span><span class="n">target</span><span class="o">.</span><span class="n">owner</span><span class="o">.</span><span class="n">pid</span><span class="p">][</span><span class="n">addr</span><span class="p">]</span>
|
|
<span class="k">except</span><span class="p">:</span>
|
|
<span class="k">pass</span>
|
|
<span class="k">return</span> <span class="kc">True</span>
|
|
|
|
<span class="c1">## MemBP internal helpers</span>
|
|
<span class="k">def</span> <span class="nf">_compute_page_access_for_event</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">target</span><span class="p">,</span> <span class="n">events</span><span class="p">):</span>
|
|
<span class="k">if</span> <span class="s2">"R"</span> <span class="ow">in</span> <span class="n">events</span><span class="p">:</span>
|
|
<span class="k">return</span> <span class="n">PAGE_NOACCESS</span>
|
|
<span class="k">if</span> <span class="nb">set</span><span class="p">(</span><span class="s2">"WX"</span><span class="p">)</span><span class="o">.</span><span class="n">issubset</span><span class="p">(</span><span class="n">events</span><span class="p">):</span>
|
|
<span class="k">return</span> <span class="n">PAGE_READONLY</span>
|
|
<span class="k">if</span> <span class="n">events</span> <span class="o">==</span> <span class="nb">set</span><span class="p">(</span><span class="s2">"W"</span><span class="p">):</span>
|
|
<span class="k">return</span> <span class="n">PAGE_EXECUTE_READ</span>
|
|
<span class="k">if</span> <span class="n">events</span> <span class="o">==</span> <span class="nb">set</span><span class="p">(</span><span class="s2">"X"</span><span class="p">):</span>
|
|
<span class="c1"># Might have problem if DEP is not enabled</span>
|
|
<span class="k">if</span> <span class="n">windows</span><span class="o">.</span><span class="n">winproxy</span><span class="o">.</span><span class="n">is_implemented</span><span class="p">(</span><span class="n">windows</span><span class="o">.</span><span class="n">winproxy</span><span class="o">.</span><span class="n">GetProcessDEPPolicy</span><span class="p">):</span>
|
|
<span class="n">has_DEP</span> <span class="o">=</span> <span class="n">DWORD</span><span class="p">()</span>
|
|
<span class="n">permaned</span> <span class="o">=</span> <span class="n">LONG</span><span class="p">()</span>
|
|
<span class="n">windows</span><span class="o">.</span><span class="n">winproxy</span><span class="o">.</span><span class="n">GetProcessDEPPolicy</span><span class="p">(</span><span class="n">target</span><span class="o">.</span><span class="n">handle</span><span class="p">,</span> <span class="n">has_DEP</span><span class="p">,</span> <span class="n">permaned</span><span class="p">)</span>
|
|
<span class="n">has_DEP</span> <span class="o">=</span> <span class="n">has_DEP</span><span class="o">.</span><span class="n">value</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="n">has_DEP</span> <span class="o">=</span> <span class="mi">0</span>
|
|
<span class="k">return</span> <span class="n">PAGE_READWRITE</span> <span class="k">if</span> <span class="n">has_DEP</span> <span class="k">else</span> <span class="n">PAGE_NOACCESS</span>
|
|
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s2">"Unexpected set of event for Membp: </span><span class="si">{0}</span><span class="s2">"</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">events</span><span class="p">))</span>
|
|
|
|
|
|
<span class="k">def</span> <span class="nf">_setup_breakpoint_MEMBP</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">bp</span><span class="p">,</span> <span class="n">target</span><span class="p">):</span>
|
|
<span class="n">addr</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_resolve</span><span class="p">(</span><span class="n">bp</span><span class="o">.</span><span class="n">addr</span><span class="p">,</span> <span class="n">target</span><span class="p">)</span>
|
|
<span class="n">bp</span><span class="o">.</span><span class="n">_addr</span> <span class="o">=</span> <span class="n">addr</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_events</span> <span class="o">=</span> <span class="nb">set</span><span class="p">(</span><span class="n">bp</span><span class="o">.</span><span class="n">events</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="n">addr</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="k">return</span> <span class="kc">False</span>
|
|
<span class="c1"># Split in affected pages:</span>
|
|
<span class="n">protection_for_bp</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_compute_page_access_for_event</span><span class="p">(</span><span class="n">target</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">_events</span><span class="p">)</span>
|
|
<span class="n">affected_pages</span> <span class="o">=</span> <span class="nb">range</span><span class="p">((</span><span class="n">addr</span> <span class="o">>></span> <span class="mi">12</span><span class="p">)</span> <span class="o"><<</span> <span class="mi">12</span><span class="p">,</span> <span class="n">addr</span> <span class="o">+</span> <span class="n">bp</span><span class="o">.</span><span class="n">size</span><span class="p">,</span> <span class="n">PAGE_SIZE</span><span class="p">)</span>
|
|
<span class="n">old_prot</span> <span class="o">=</span> <span class="n">DWORD</span><span class="p">()</span>
|
|
<span class="n">cp_watch_page</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_watched_pages</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">current_process</span><span class="o">.</span><span class="n">pid</span><span class="p">]</span>
|
|
<span class="k">for</span> <span class="n">page_addr</span> <span class="ow">in</span> <span class="n">affected_pages</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="n">page_addr</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">cp_watch_page</span><span class="p">:</span>
|
|
<span class="n">target</span><span class="o">.</span><span class="n">virtual_protect</span><span class="p">(</span><span class="n">page_addr</span><span class="p">,</span> <span class="n">PAGE_SIZE</span><span class="p">,</span> <span class="n">protection_for_bp</span><span class="p">,</span> <span class="n">old_prot</span><span class="p">)</span>
|
|
<span class="c1"># Page with no other MemBP</span>
|
|
<span class="n">cp_watch_page</span><span class="p">[</span><span class="n">page_addr</span><span class="p">]</span> <span class="o">=</span> <span class="n">WatchedPage</span><span class="p">(</span><span class="n">old_prot</span><span class="o">.</span><span class="n">value</span><span class="p">,</span> <span class="p">[</span><span class="n">bp</span><span class="p">])</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="c1"># Reduce the right of the page to the common need</span>
|
|
<span class="n">cp_watch_page</span><span class="p">[</span><span class="n">page_addr</span><span class="p">]</span><span class="o">.</span><span class="n">bps</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">bp</span><span class="p">)</span>
|
|
<span class="n">full_page_events</span> <span class="o">=</span> <span class="nb">set</span><span class="o">.</span><span class="n">union</span><span class="p">(</span><span class="o">*</span><span class="p">[</span><span class="n">bp</span><span class="o">.</span><span class="n">events</span> <span class="k">for</span> <span class="n">bp</span> <span class="ow">in</span> <span class="n">cp_watch_page</span><span class="p">[</span><span class="n">page_addr</span><span class="p">]</span><span class="o">.</span><span class="n">bps</span><span class="p">])</span>
|
|
<span class="n">protection_for_page</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_compute_page_access_for_event</span><span class="p">(</span><span class="n">target</span><span class="p">,</span> <span class="n">full_page_events</span><span class="p">)</span>
|
|
<span class="n">target</span><span class="o">.</span><span class="n">virtual_protect</span><span class="p">(</span><span class="n">page_addr</span><span class="p">,</span> <span class="n">PAGE_SIZE</span><span class="p">,</span> <span class="n">protection_for_page</span><span class="p">,</span> <span class="kc">None</span><span class="p">)</span>
|
|
<span class="c1"># TODO: watch for overlap with other MEM breakpoints</span>
|
|
<span class="k">return</span> <span class="kc">True</span>
|
|
|
|
<span class="k">def</span> <span class="nf">_restore_breakpoint_MEMBP</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">bp</span><span class="p">,</span> <span class="n">target</span><span class="p">):</span>
|
|
<span class="p">(</span><span class="n">page_addr</span><span class="p">,</span> <span class="n">page_prot</span><span class="p">)</span> <span class="o">=</span> <span class="n">bp</span><span class="o">.</span><span class="n">_reput_page</span>
|
|
<span class="k">return</span> <span class="n">target</span><span class="o">.</span><span class="n">virtual_protect</span><span class="p">(</span><span class="n">page_addr</span><span class="p">,</span> <span class="n">PAGE_SIZE</span><span class="p">,</span> <span class="n">page_prot</span><span class="p">,</span> <span class="kc">None</span><span class="p">)</span>
|
|
|
|
|
|
<span class="k">def</span> <span class="nf">_remove_breakpoint_MEMBP</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">bp</span><span class="p">,</span> <span class="n">target</span><span class="p">):</span>
|
|
<span class="n">affected_pages</span> <span class="o">=</span> <span class="nb">range</span><span class="p">((</span><span class="n">bp</span><span class="o">.</span><span class="n">_addr</span> <span class="o">>></span> <span class="mi">12</span><span class="p">)</span> <span class="o"><<</span> <span class="mi">12</span><span class="p">,</span> <span class="n">bp</span><span class="o">.</span><span class="n">_addr</span> <span class="o">+</span> <span class="n">bp</span><span class="o">.</span><span class="n">size</span><span class="p">,</span> <span class="n">PAGE_SIZE</span><span class="p">)</span>
|
|
<span class="n">vprot_begin</span> <span class="o">=</span> <span class="n">affected_pages</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
|
|
<span class="n">vprot_size</span> <span class="o">=</span> <span class="n">PAGE_SIZE</span> <span class="o">*</span> <span class="nb">len</span><span class="p">(</span><span class="n">affected_pages</span><span class="p">)</span>
|
|
<span class="n">cp_watch_page</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_watched_pages</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">current_process</span><span class="o">.</span><span class="n">pid</span><span class="p">]</span>
|
|
<span class="k">for</span> <span class="n">page_addr</span> <span class="ow">in</span> <span class="n">affected_pages</span><span class="p">:</span>
|
|
<span class="n">cp_watch_page</span><span class="p">[</span><span class="n">page_addr</span><span class="p">]</span><span class="o">.</span><span class="n">bps</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">bp</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="n">cp_watch_page</span><span class="p">[</span><span class="n">page_addr</span><span class="p">]</span><span class="o">.</span><span class="n">bps</span><span class="p">:</span>
|
|
<span class="n">target</span><span class="o">.</span><span class="n">virtual_protect</span><span class="p">(</span><span class="n">page_addr</span><span class="p">,</span> <span class="n">PAGE_SIZE</span><span class="p">,</span> <span class="n">cp_watch_page</span><span class="p">[</span><span class="n">page_addr</span><span class="p">]</span><span class="o">.</span><span class="n">original_prot</span><span class="p">,</span> <span class="kc">None</span><span class="p">)</span>
|
|
<span class="k">del</span> <span class="n">cp_watch_page</span><span class="p">[</span><span class="n">page_addr</span><span class="p">]</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="n">full_page_events</span> <span class="o">=</span> <span class="nb">set</span><span class="o">.</span><span class="n">union</span><span class="p">(</span><span class="o">*</span><span class="p">[</span><span class="n">bp</span><span class="o">.</span><span class="n">events</span> <span class="k">for</span> <span class="n">bp</span> <span class="ow">in</span> <span class="n">cp_watch_page</span><span class="p">[</span><span class="n">page_addr</span><span class="p">]</span><span class="o">.</span><span class="n">bps</span><span class="p">])</span>
|
|
<span class="n">protection_for_page</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_compute_page_access_for_event</span><span class="p">(</span><span class="n">target</span><span class="p">,</span> <span class="n">full_page_events</span><span class="p">)</span>
|
|
<span class="n">target</span><span class="o">.</span><span class="n">virtual_protect</span><span class="p">(</span><span class="n">page_addr</span><span class="p">,</span> <span class="n">PAGE_SIZE</span><span class="p">,</span> <span class="n">protection_for_page</span><span class="p">,</span> <span class="kc">None</span><span class="p">)</span>
|
|
<span class="k">return</span> <span class="kc">True</span>
|
|
|
|
|
|
<span class="k">def</span> <span class="nf">_setup_pending_breakpoints_new_process</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">new_process</span><span class="p">):</span>
|
|
<span class="k">for</span> <span class="n">bp</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">_pending_breakpoints_new</span><span class="p">[</span><span class="kc">None</span><span class="p">]:</span>
|
|
<span class="k">if</span> <span class="n">bp</span><span class="o">.</span><span class="n">apply_to_target</span><span class="p">(</span><span class="n">new_process</span><span class="p">):</span> <span class="c1">#BP for thread or process ?</span>
|
|
<span class="n">_setup_method</span> <span class="o">=</span> <span class="nb">getattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="s2">"_setup_breakpoint_"</span> <span class="o">+</span> <span class="n">bp</span><span class="o">.</span><span class="n">type</span><span class="p">)</span>
|
|
<span class="n">_setup_method</span><span class="p">(</span><span class="n">bp</span><span class="p">,</span> <span class="n">new_process</span><span class="p">)</span>
|
|
|
|
<span class="k">for</span> <span class="n">bp</span> <span class="ow">in</span> <span class="nb">list</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_pending_breakpoints_new</span><span class="p">[</span><span class="n">new_process</span><span class="o">.</span><span class="n">pid</span><span class="p">]):</span>
|
|
<span class="k">if</span> <span class="n">bp</span><span class="o">.</span><span class="n">apply_to_target</span><span class="p">(</span><span class="n">new_process</span><span class="p">):</span>
|
|
<span class="n">_setup_method</span> <span class="o">=</span> <span class="nb">getattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="s2">"_setup_breakpoint_"</span> <span class="o">+</span> <span class="n">bp</span><span class="o">.</span><span class="n">type</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="n">_setup_method</span><span class="p">(</span><span class="n">bp</span><span class="p">,</span> <span class="n">new_process</span><span class="p">):</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_pending_breakpoints_new</span><span class="p">[</span><span class="n">new_process</span><span class="o">.</span><span class="n">pid</span><span class="p">]</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">bp</span><span class="p">)</span>
|
|
|
|
<span class="k">def</span> <span class="nf">_setup_pending_breakpoints_new_thread</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">new_thread</span><span class="p">):</span>
|
|
<span class="k">for</span> <span class="n">bp</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">_pending_breakpoints_new</span><span class="p">[</span><span class="kc">None</span><span class="p">]:</span>
|
|
<span class="k">if</span> <span class="n">bp</span><span class="o">.</span><span class="n">apply_to_target</span><span class="p">(</span><span class="n">new_thread</span><span class="p">):</span> <span class="c1">#BP for thread or process ?</span>
|
|
<span class="n">_setup_method</span> <span class="o">=</span> <span class="nb">getattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="s2">"_setup_breakpoint_"</span> <span class="o">+</span> <span class="n">bp</span><span class="o">.</span><span class="n">type</span><span class="p">)</span>
|
|
<span class="n">_setup_method</span><span class="p">(</span><span class="n">bp</span><span class="p">,</span> <span class="n">new_thread</span><span class="p">)</span>
|
|
|
|
<span class="k">for</span> <span class="n">bp</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">_pending_breakpoints_new</span><span class="p">[</span><span class="n">new_thread</span><span class="o">.</span><span class="n">owner</span><span class="o">.</span><span class="n">pid</span><span class="p">]:</span>
|
|
<span class="k">if</span> <span class="n">bp</span><span class="o">.</span><span class="n">apply_to_target</span><span class="p">(</span><span class="n">new_thread</span><span class="p">):</span>
|
|
<span class="n">_setup_method</span> <span class="o">=</span> <span class="nb">getattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="s2">"_setup_breakpoint_"</span> <span class="o">+</span> <span class="n">bp</span><span class="o">.</span><span class="n">type</span><span class="p">)</span>
|
|
<span class="n">_setup_method</span><span class="p">(</span><span class="n">bp</span><span class="p">,</span> <span class="n">new_thread</span><span class="p">)</span>
|
|
|
|
<span class="k">for</span> <span class="n">bp</span> <span class="ow">in</span> <span class="nb">list</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_pending_breakpoints_new</span><span class="p">[</span><span class="n">new_thread</span><span class="o">.</span><span class="n">tid</span><span class="p">]):</span>
|
|
<span class="n">_setup_method</span> <span class="o">=</span> <span class="nb">getattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="s2">"_setup_breakpoint_"</span> <span class="o">+</span> <span class="n">bp</span><span class="o">.</span><span class="n">type</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="n">_setup_method</span><span class="p">(</span><span class="n">bp</span><span class="p">,</span> <span class="n">new_thread</span><span class="p">):</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_pending_breakpoints_new</span><span class="p">[</span><span class="n">new_thread</span><span class="o">.</span><span class="n">tid</span><span class="p">]</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">bp</span><span class="p">)</span>
|
|
|
|
|
|
<span class="k">def</span> <span class="nf">_setup_pending_breakpoints_load_dll</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">dll_name</span><span class="p">):</span>
|
|
<span class="k">for</span> <span class="n">bp</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">_pending_breakpoints_new</span><span class="p">[</span><span class="kc">None</span><span class="p">]:</span>
|
|
<span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">bp</span><span class="o">.</span><span class="n">addr</span><span class="p">,</span> <span class="n">basestring</span><span class="p">):</span>
|
|
<span class="n">target_dll</span> <span class="o">=</span> <span class="n">bp</span><span class="o">.</span><span class="n">addr</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s2">"!"</span><span class="p">)[</span><span class="mi">0</span><span class="p">]</span>
|
|
<span class="c1"># Cannot work AS-IS yet. Implement it ?</span>
|
|
<span class="c1"># if target_dll == "*" or target_dll == dll_name:</span>
|
|
<span class="k">if</span> <span class="n">target_dll</span> <span class="o">==</span> <span class="n">dll_name</span><span class="p">:</span>
|
|
<span class="n">_setup_method</span> <span class="o">=</span> <span class="nb">getattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="s2">"_setup_breakpoint_"</span> <span class="o">+</span> <span class="n">bp</span><span class="o">.</span><span class="n">type</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="n">bp</span><span class="o">.</span><span class="n">apply_to_target</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">current_process</span><span class="p">):</span>
|
|
<span class="n">_setup_method</span><span class="p">(</span><span class="n">bp</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">current_process</span><span class="p">)</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="k">for</span> <span class="n">t</span> <span class="ow">in</span> <span class="p">[</span><span class="n">t</span> <span class="k">for</span> <span class="n">t</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">current_process</span><span class="o">.</span><span class="n">threads</span> <span class="k">if</span> <span class="n">t</span><span class="o">.</span><span class="n">tid</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">threads</span><span class="p">]:</span>
|
|
<span class="n">_setup_method</span><span class="p">(</span><span class="n">bp</span><span class="p">,</span> <span class="n">t</span><span class="p">)</span>
|
|
|
|
<span class="k">for</span> <span class="n">bp</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">_pending_breakpoints_new</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">current_process</span><span class="o">.</span><span class="n">pid</span><span class="p">]:</span>
|
|
<span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">bp</span><span class="o">.</span><span class="n">addr</span><span class="p">,</span> <span class="n">basestring</span><span class="p">):</span>
|
|
<span class="n">target_dll</span> <span class="o">=</span> <span class="n">bp</span><span class="o">.</span><span class="n">addr</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s2">"!"</span><span class="p">)[</span><span class="mi">0</span><span class="p">]</span>
|
|
<span class="k">if</span> <span class="n">target_dll</span> <span class="o">==</span> <span class="n">dll_name</span><span class="p">:</span>
|
|
<span class="n">_setup_method</span> <span class="o">=</span> <span class="nb">getattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="s2">"_setup_breakpoint_"</span> <span class="o">+</span> <span class="n">bp</span><span class="o">.</span><span class="n">type</span><span class="p">)</span>
|
|
<span class="n">_setup_method</span><span class="p">(</span><span class="n">bp</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">current_process</span><span class="p">)</span>
|
|
|
|
<span class="k">for</span> <span class="n">thread</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">current_process</span><span class="o">.</span><span class="n">threads</span><span class="p">:</span>
|
|
<span class="k">for</span> <span class="n">bp</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">_pending_breakpoints_new</span><span class="p">[</span><span class="n">thread</span><span class="o">.</span><span class="n">tid</span><span class="p">]:</span>
|
|
<span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">bp</span><span class="o">.</span><span class="n">addr</span><span class="p">,</span> <span class="n">basestring</span><span class="p">):</span>
|
|
<span class="n">target_dll</span> <span class="o">=</span> <span class="n">bp</span><span class="o">.</span><span class="n">addr</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s2">"!"</span><span class="p">)[</span><span class="mi">0</span><span class="p">]</span>
|
|
<span class="k">if</span> <span class="n">target_dll</span> <span class="o">==</span> <span class="n">dll_name</span><span class="p">:</span>
|
|
<span class="n">_setup_method</span> <span class="o">=</span> <span class="nb">getattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="s2">"_setup_breakpoint_"</span> <span class="o">+</span> <span class="n">bp</span><span class="o">.</span><span class="n">type</span><span class="p">)</span>
|
|
<span class="n">_setup_method</span><span class="p">(</span><span class="n">bp</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">thread</span><span class="p">)</span>
|
|
|
|
<span class="k">def</span> <span class="nf">_pass_breakpoint</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">addr</span><span class="p">):</span>
|
|
<span class="n">process</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">current_process</span>
|
|
<span class="n">thread</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">current_thread</span>
|
|
<span class="n">process</span><span class="o">.</span><span class="n">write_memory</span><span class="p">(</span><span class="n">addr</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">_memory_save</span><span class="p">[</span><span class="n">process</span><span class="o">.</span><span class="n">pid</span><span class="p">][</span><span class="n">addr</span><span class="p">])</span>
|
|
<span class="n">regs</span> <span class="o">=</span> <span class="n">thread</span><span class="o">.</span><span class="n">context</span>
|
|
<span class="n">regs</span><span class="o">.</span><span class="n">EFlags</span> <span class="o">|=</span> <span class="p">(</span><span class="mi">1</span> <span class="o"><<</span> <span class="mi">8</span><span class="p">)</span>
|
|
<span class="c1">#regs.pc -= 1 # Done in _handle_exception_breakpoint before dispatch</span>
|
|
<span class="n">thread</span><span class="o">.</span><span class="n">set_context</span><span class="p">(</span><span class="n">regs</span><span class="p">)</span>
|
|
<span class="n">bp</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">breakpoints</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">current_process</span><span class="o">.</span><span class="n">pid</span><span class="p">][</span><span class="n">addr</span><span class="p">]</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_breakpoint_to_reput</span><span class="p">[</span><span class="n">thread</span><span class="o">.</span><span class="n">tid</span><span class="p">]</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">bp</span><span class="p">)</span> <span class="c1">#Register pending breakpoint for next single step</span>
|
|
|
|
<span class="k">def</span> <span class="nf">_pass_memory_breakpoint</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">bp</span><span class="p">,</span> <span class="n">page_protect</span><span class="p">,</span> <span class="n">fault_page</span><span class="p">):</span>
|
|
<span class="n">cp</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">current_process</span>
|
|
<span class="n">page_prot</span> <span class="o">=</span> <span class="n">DWORD</span><span class="p">()</span>
|
|
<span class="n">cp</span><span class="o">.</span><span class="n">virtual_protect</span><span class="p">(</span><span class="n">fault_page</span><span class="p">,</span> <span class="n">PAGE_SIZE</span><span class="p">,</span> <span class="n">page_protect</span><span class="p">,</span> <span class="n">page_prot</span><span class="p">)</span>
|
|
<span class="n">thread</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">current_thread</span>
|
|
<span class="n">ctx</span> <span class="o">=</span> <span class="n">thread</span><span class="o">.</span><span class="n">context</span>
|
|
<span class="n">ctx</span><span class="o">.</span><span class="n">EEFlags</span><span class="o">.</span><span class="n">TF</span> <span class="o">=</span> <span class="mi">1</span>
|
|
<span class="n">thread</span><span class="o">.</span><span class="n">set_context</span><span class="p">(</span><span class="n">ctx</span><span class="p">)</span>
|
|
<span class="n">bp</span><span class="o">.</span><span class="n">_reput_page</span> <span class="o">=</span> <span class="p">(</span><span class="n">fault_page</span><span class="p">,</span> <span class="n">page_prot</span><span class="o">.</span><span class="n">value</span><span class="p">)</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_breakpoint_to_reput</span><span class="p">[</span><span class="n">thread</span><span class="o">.</span><span class="n">tid</span><span class="p">]</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">bp</span><span class="p">)</span>
|
|
|
|
<span class="c1"># debug event handlers</span>
|
|
<span class="k">def</span> <span class="nf">_handle_unknown_debug_event</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">debug_event</span><span class="p">):</span>
|
|
<span class="k">raise</span> <span class="ne">NotImplementedError</span><span class="p">(</span><span class="s2">"dwDebugEventCode = </span><span class="si">{0}</span><span class="s2">"</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">debug_event</span><span class="o">.</span><span class="n">dwDebugEventCode</span><span class="p">))</span>
|
|
|
|
|
|
<span class="k">def</span> <span class="nf">_handle_exception_breakpoint</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">exception</span><span class="p">,</span> <span class="n">excp_addr</span><span class="p">):</span>
|
|
<span class="n">excp_bitness</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_exception_bitness</span><span class="p">(</span><span class="n">exception</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="n">excp_addr</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">breakpoints</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">current_process</span><span class="o">.</span><span class="n">pid</span><span class="p">]:</span>
|
|
<span class="n">thread</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">current_thread</span>
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">current_process</span><span class="o">.</span><span class="n">bitness</span> <span class="o">==</span> <span class="mi">32</span> <span class="ow">and</span> <span class="n">excp_bitness</span> <span class="o">==</span> <span class="mi">64</span><span class="p">:</span>
|
|
<span class="n">ctx</span> <span class="o">=</span> <span class="n">thread</span><span class="o">.</span><span class="n">context_syswow</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="n">ctx</span> <span class="o">=</span> <span class="n">thread</span><span class="o">.</span><span class="n">context</span>
|
|
<span class="n">ctx</span><span class="o">.</span><span class="n">pc</span> <span class="o">-=</span> <span class="mi">1</span>
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">current_process</span><span class="o">.</span><span class="n">bitness</span> <span class="o">==</span> <span class="mi">32</span> <span class="ow">and</span> <span class="n">excp_bitness</span> <span class="o">==</span> <span class="mi">64</span><span class="p">:</span>
|
|
<span class="n">thread</span><span class="o">.</span><span class="n">set_syswow_context</span><span class="p">(</span><span class="n">ctx</span><span class="p">)</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="n">thread</span><span class="o">.</span><span class="n">set_context</span><span class="p">(</span><span class="n">ctx</span><span class="p">)</span>
|
|
<span class="k">del</span> <span class="n">thread</span>
|
|
<span class="n">continue_flag</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_dispatch_breakpoint</span><span class="p">(</span><span class="n">exception</span><span class="p">,</span> <span class="n">excp_addr</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">_killed_in_action</span><span class="p">():</span>
|
|
<span class="k">return</span> <span class="n">continue_flag</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_explicit_single_step</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">current_thread</span><span class="o">.</span><span class="n">tid</span><span class="p">]</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">current_thread</span><span class="o">.</span><span class="n">context</span><span class="o">.</span><span class="n">EEFlags</span><span class="o">.</span><span class="n">TF</span>
|
|
<span class="k">if</span> <span class="n">excp_addr</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">breakpoints</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">current_process</span><span class="o">.</span><span class="n">pid</span><span class="p">]:</span>
|
|
<span class="c1"># Setup BP if not suppressed</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_pass_breakpoint</span><span class="p">(</span><span class="n">excp_addr</span><span class="p">)</span>
|
|
<span class="k">return</span> <span class="n">continue_flag</span>
|
|
<span class="k">with</span> <span class="bp">self</span><span class="o">.</span><span class="n">DisabledMemoryBreakpoint</span><span class="p">():</span>
|
|
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">on_exception</span><span class="p">(</span><span class="n">exception</span><span class="p">)</span>
|
|
|
|
<span class="k">def</span> <span class="nf">_handle_exception_singlestep</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">exception</span><span class="p">,</span> <span class="n">excp_addr</span><span class="p">):</span>
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">current_thread</span><span class="o">.</span><span class="n">tid</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">_breakpoint_to_reput</span> <span class="ow">and</span> <span class="bp">self</span><span class="o">.</span><span class="n">_breakpoint_to_reput</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">current_thread</span><span class="o">.</span><span class="n">tid</span><span class="p">]:</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_restore_breakpoints</span><span class="p">()</span>
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">_explicit_single_step</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">current_thread</span><span class="o">.</span><span class="n">tid</span><span class="p">]:</span>
|
|
<span class="k">with</span> <span class="bp">self</span><span class="o">.</span><span class="n">DisabledMemoryBreakpoint</span><span class="p">():</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">on_single_step</span><span class="p">(</span><span class="n">exception</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">_killed_in_action</span><span class="p">():</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_explicit_single_step</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">current_thread</span><span class="o">.</span><span class="n">tid</span><span class="p">]</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">current_thread</span><span class="o">.</span><span class="n">context</span><span class="o">.</span><span class="n">EEFlags</span><span class="o">.</span><span class="n">TF</span>
|
|
<span class="k">return</span> <span class="n">DBG_CONTINUE</span>
|
|
<span class="k">elif</span> <span class="n">excp_addr</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">breakpoints</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">current_process</span><span class="o">.</span><span class="n">pid</span><span class="p">]:</span>
|
|
<span class="c1"># Verif that's not a standard BP ?</span>
|
|
<span class="n">bp</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">breakpoints</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">current_process</span><span class="o">.</span><span class="n">pid</span><span class="p">][</span><span class="n">excp_addr</span><span class="p">]</span>
|
|
<span class="k">with</span> <span class="bp">self</span><span class="o">.</span><span class="n">DisabledMemoryBreakpoint</span><span class="p">():</span>
|
|
<span class="n">bp</span><span class="o">.</span><span class="n">trigger</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">exception</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">_killed_in_action</span><span class="p">():</span>
|
|
<span class="k">return</span> <span class="n">DBG_CONTINUE</span>
|
|
<span class="n">ctx</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">current_thread</span><span class="o">.</span><span class="n">context</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_explicit_single_step</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">current_thread</span><span class="o">.</span><span class="n">tid</span><span class="p">]</span> <span class="o">=</span> <span class="n">ctx</span><span class="o">.</span><span class="n">EEFlags</span><span class="o">.</span><span class="n">TF</span>
|
|
<span class="k">if</span> <span class="n">excp_addr</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">breakpoints</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">current_process</span><span class="o">.</span><span class="n">pid</span><span class="p">]:</span>
|
|
<span class="n">ctx</span><span class="o">.</span><span class="n">EEFlags</span><span class="o">.</span><span class="n">RF</span> <span class="o">=</span> <span class="mi">1</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">current_thread</span><span class="o">.</span><span class="n">set_context</span><span class="p">(</span><span class="n">ctx</span><span class="p">)</span>
|
|
<span class="k">return</span> <span class="n">DBG_CONTINUE</span>
|
|
<span class="k">elif</span> <span class="bp">self</span><span class="o">.</span><span class="n">_explicit_single_step</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">current_thread</span><span class="o">.</span><span class="n">tid</span><span class="p">]:</span>
|
|
<span class="k">with</span> <span class="bp">self</span><span class="o">.</span><span class="n">DisabledMemoryBreakpoint</span><span class="p">():</span>
|
|
<span class="n">continue_flag</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">on_single_step</span><span class="p">(</span><span class="n">exception</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">_killed_in_action</span><span class="p">():</span>
|
|
<span class="k">return</span> <span class="n">continue_flag</span>
|
|
<span class="c1"># Does not handle case where EEFlags.TF was by the debugge before trigering the exception</span>
|
|
<span class="c1"># Should set the flag explicitly in single_step ? and not just use EEFlags.TF ?</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_explicit_single_step</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">current_thread</span><span class="o">.</span><span class="n">tid</span><span class="p">]</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">current_thread</span><span class="o">.</span><span class="n">context</span><span class="o">.</span><span class="n">EEFlags</span><span class="o">.</span><span class="n">TF</span>
|
|
<span class="k">return</span> <span class="n">continue_flag</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="k">with</span> <span class="bp">self</span><span class="o">.</span><span class="n">DisabledMemoryBreakpoint</span><span class="p">():</span>
|
|
<span class="n">continue_flag</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">on_exception</span><span class="p">(</span><span class="n">exception</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">_killed_in_action</span><span class="p">():</span>
|
|
<span class="k">return</span> <span class="n">continue_flag</span>
|
|
<span class="c1"># Does not handle case where EEFlags.TF was by the debugge before trigering the exception</span>
|
|
<span class="c1"># Should set the flag explicitly in single_step ? and not just use EEFlags.TF ?</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_explicit_single_step</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">current_thread</span><span class="o">.</span><span class="n">tid</span><span class="p">]</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">current_thread</span><span class="o">.</span><span class="n">context</span><span class="o">.</span><span class="n">EEFlags</span><span class="o">.</span><span class="n">TF</span>
|
|
<span class="k">return</span> <span class="n">continue_flag</span>
|
|
|
|
<span class="c1"># === Testing PAGE_NOACCESS(0x1L) ===</span>
|
|
<span class="c1"># exception: access violation reading 0x00470000</span>
|
|
<span class="c1"># exception: access violation writing 0x00470000</span>
|
|
<span class="c1"># === Testing PAGE_READONLY(0x2L) ===</span>
|
|
<span class="c1"># exception: access violation writing 0x00470000</span>
|
|
<span class="c1"># === Testing PAGE_READWRITE(0x4L) ===</span>
|
|
<span class="c1"># === Testing PAGE_EXECUTE(0x10L) ===</span>
|
|
<span class="c1"># exception: access violation writing 0x00470000</span>
|
|
<span class="c1"># === Testing PAGE_EXECUTE_READ(0x20L) ===</span>
|
|
<span class="c1"># exception: access violation writing 0x00470000</span>
|
|
<span class="c1"># === Testing PAGE_EXECUTE_READWRITE(0x40L) ===</span>
|
|
|
|
<span class="k">def</span> <span class="nf">_handle_exception_access_violation</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">exception</span><span class="p">,</span> <span class="n">excp_addr</span><span class="p">):</span>
|
|
<span class="n">READ</span> <span class="o">=</span> <span class="mi">0</span>
|
|
<span class="n">WRITE</span> <span class="o">=</span> <span class="mi">1</span>
|
|
<span class="n">EXEC</span> <span class="o">=</span> <span class="mi">2</span>
|
|
<span class="n">EVENT_STR</span> <span class="o">=</span> <span class="s2">"RWX"</span>
|
|
|
|
<span class="n">fault_type</span> <span class="o">=</span> <span class="n">exception</span><span class="o">.</span><span class="n">ExceptionRecord</span><span class="o">.</span><span class="n">ExceptionInformation</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
|
|
<span class="n">fault_addr</span> <span class="o">=</span> <span class="n">exception</span><span class="o">.</span><span class="n">ExceptionRecord</span><span class="o">.</span><span class="n">ExceptionInformation</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
|
|
<span class="n">pc_addr</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">current_thread</span><span class="o">.</span><span class="n">context</span><span class="o">.</span><span class="n">pc</span>
|
|
<span class="k">if</span> <span class="n">fault_addr</span> <span class="o">==</span> <span class="n">pc_addr</span><span class="p">:</span>
|
|
<span class="n">fault_type</span> <span class="o">=</span> <span class="n">EXEC</span>
|
|
<span class="n">event</span> <span class="o">=</span> <span class="n">EVENT_STR</span><span class="p">[</span><span class="n">fault_type</span><span class="p">]</span>
|
|
|
|
<span class="n">fault_page</span> <span class="o">=</span> <span class="p">(</span><span class="n">fault_addr</span> <span class="o">>></span> <span class="mi">12</span><span class="p">)</span> <span class="o"><<</span> <span class="mi">12</span>
|
|
<span class="n">cp_watch_page</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_watched_pages</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">current_process</span><span class="o">.</span><span class="n">pid</span><span class="p">]</span>
|
|
|
|
<span class="n">mem_bp</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_memory_breakpoint_at</span><span class="p">(</span><span class="n">fault_addr</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">current_process</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="n">mem_bp</span> <span class="ow">is</span> <span class="kc">False</span><span class="p">:</span> <span class="c1"># No BP on this page</span>
|
|
<span class="k">with</span> <span class="bp">self</span><span class="o">.</span><span class="n">DisabledMemoryBreakpoint</span><span class="p">():</span>
|
|
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">on_exception</span><span class="p">(</span><span class="n">exception</span><span class="p">)</span>
|
|
<span class="n">original_prot</span> <span class="o">=</span> <span class="n">cp_watch_page</span><span class="p">[</span><span class="n">fault_page</span><span class="p">]</span><span class="o">.</span><span class="n">original_prot</span>
|
|
<span class="k">if</span> <span class="n">mem_bp</span> <span class="ow">is</span> <span class="kc">None</span> <span class="ow">or</span> <span class="n">event</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">mem_bp</span><span class="o">.</span><span class="n">events</span><span class="p">:</span> <span class="c1"># Page has MEMBP but None handle this address | event not asked by membp</span>
|
|
<span class="c1"># This hack is bad, find a BP on the page to restore original access..</span>
|
|
<span class="n">bp</span> <span class="o">=</span> <span class="n">cp_watch_page</span><span class="p">[</span><span class="n">fault_page</span><span class="p">]</span><span class="o">.</span><span class="n">bps</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_pass_memory_breakpoint</span><span class="p">(</span><span class="n">bp</span><span class="p">,</span> <span class="n">original_prot</span><span class="p">,</span> <span class="n">fault_page</span><span class="p">)</span>
|
|
<span class="k">return</span> <span class="n">DBG_CONTINUE</span>
|
|
|
|
<span class="k">with</span> <span class="bp">self</span><span class="o">.</span><span class="n">DisabledMemoryBreakpoint</span><span class="p">():</span>
|
|
<span class="n">continue_flag</span> <span class="o">=</span> <span class="n">mem_bp</span><span class="o">.</span><span class="n">trigger</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">exception</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">_killed_in_action</span><span class="p">():</span>
|
|
<span class="k">return</span> <span class="n">continue_flag</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_explicit_single_step</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">current_thread</span><span class="o">.</span><span class="n">tid</span><span class="p">]</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">current_thread</span><span class="o">.</span><span class="n">context</span><span class="o">.</span><span class="n">EEFlags</span><span class="o">.</span><span class="n">TF</span>
|
|
<span class="c1"># If BP has not been removed in trigger, pas it</span>
|
|
<span class="k">if</span> <span class="n">fault_page</span> <span class="ow">in</span> <span class="n">cp_watch_page</span> <span class="ow">and</span> <span class="n">mem_bp</span> <span class="ow">in</span> <span class="n">cp_watch_page</span><span class="p">[</span><span class="n">fault_page</span><span class="p">]</span><span class="o">.</span><span class="n">bps</span><span class="p">:</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_pass_memory_breakpoint</span><span class="p">(</span><span class="n">mem_bp</span><span class="p">,</span> <span class="n">original_prot</span><span class="p">,</span> <span class="n">fault_page</span><span class="p">)</span>
|
|
<span class="k">return</span> <span class="n">continue_flag</span>
|
|
|
|
|
|
<span class="c1"># TODO: self._explicit_single_step setup by single_step() ? check at the end ? finally ?</span>
|
|
<span class="k">def</span> <span class="nf">_handle_exception</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">debug_event</span><span class="p">):</span>
|
|
<span class="sd">"""Handle EXCEPTION_DEBUG_EVENT"""</span>
|
|
<span class="n">exception</span> <span class="o">=</span> <span class="n">debug_event</span><span class="o">.</span><span class="n">u</span><span class="o">.</span><span class="n">Exception</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_update_debugger_state</span><span class="p">(</span><span class="n">debug_event</span><span class="p">)</span>
|
|
|
|
<span class="k">if</span> <span class="n">windows</span><span class="o">.</span><span class="n">current_process</span><span class="o">.</span><span class="n">bitness</span> <span class="o">==</span> <span class="mi">32</span><span class="p">:</span>
|
|
<span class="n">exception</span><span class="o">.</span><span class="vm">__class__</span> <span class="o">=</span> <span class="n">winexception</span><span class="o">.</span><span class="n">EEXCEPTION_DEBUG_INFO32</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="n">exception</span><span class="o">.</span><span class="vm">__class__</span> <span class="o">=</span> <span class="n">winexception</span><span class="o">.</span><span class="n">EEXCEPTION_DEBUG_INFO64</span>
|
|
|
|
<span class="n">excp_code</span> <span class="o">=</span> <span class="n">exception</span><span class="o">.</span><span class="n">ExceptionRecord</span><span class="o">.</span><span class="n">ExceptionCode</span>
|
|
<span class="n">excp_addr</span> <span class="o">=</span> <span class="n">exception</span><span class="o">.</span><span class="n">ExceptionRecord</span><span class="o">.</span><span class="n">ExceptionAddress</span>
|
|
<span class="k">if</span> <span class="n">excp_code</span> <span class="ow">in</span> <span class="p">[</span><span class="n">EXCEPTION_BREAKPOINT</span><span class="p">,</span> <span class="n">STATUS_WX86_BREAKPOINT</span><span class="p">]</span> <span class="ow">and</span> <span class="n">excp_addr</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">breakpoints</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">current_process</span><span class="o">.</span><span class="n">pid</span><span class="p">]:</span>
|
|
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_handle_exception_breakpoint</span><span class="p">(</span><span class="n">exception</span><span class="p">,</span> <span class="n">excp_addr</span><span class="p">)</span>
|
|
<span class="k">elif</span> <span class="n">excp_code</span> <span class="ow">in</span> <span class="p">[</span><span class="n">EXCEPTION_SINGLE_STEP</span><span class="p">,</span> <span class="n">STATUS_WX86_SINGLE_STEP</span><span class="p">]:</span>
|
|
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_handle_exception_singlestep</span><span class="p">(</span><span class="n">exception</span><span class="p">,</span> <span class="n">excp_addr</span><span class="p">)</span>
|
|
<span class="k">elif</span> <span class="n">excp_code</span> <span class="o">==</span> <span class="n">EXCEPTION_ACCESS_VIOLATION</span><span class="p">:</span>
|
|
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_handle_exception_access_violation</span><span class="p">(</span><span class="n">exception</span><span class="p">,</span> <span class="n">excp_addr</span><span class="p">)</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="k">with</span> <span class="bp">self</span><span class="o">.</span><span class="n">DisabledMemoryBreakpoint</span><span class="p">():</span>
|
|
<span class="n">continue_flag</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">on_exception</span><span class="p">(</span><span class="n">exception</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">_killed_in_action</span><span class="p">():</span>
|
|
<span class="k">return</span> <span class="n">continue_flag</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_explicit_single_step</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">current_thread</span><span class="o">.</span><span class="n">tid</span><span class="p">]</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">current_thread</span><span class="o">.</span><span class="n">context</span><span class="o">.</span><span class="n">EEFlags</span><span class="o">.</span><span class="n">TF</span>
|
|
<span class="k">return</span> <span class="n">continue_flag</span>
|
|
|
|
|
|
<span class="k">def</span> <span class="nf">_get_loaded_dll</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">load_dll</span><span class="p">):</span>
|
|
<span class="n">name_sufix</span> <span class="o">=</span> <span class="s2">""</span>
|
|
<span class="n">pe</span> <span class="o">=</span> <span class="n">windows</span><span class="o">.</span><span class="n">pe_parse</span><span class="o">.</span><span class="n">GetPEFile</span><span class="p">(</span><span class="n">load_dll</span><span class="o">.</span><span class="n">lpBaseOfDll</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">current_process</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">current_process</span><span class="o">.</span><span class="n">bitness</span> <span class="o">==</span> <span class="mi">32</span> <span class="ow">and</span> <span class="n">pe</span><span class="o">.</span><span class="n">bitness</span> <span class="o">==</span> <span class="mi">64</span><span class="p">:</span>
|
|
<span class="n">name_sufix</span> <span class="o">=</span> <span class="s2">"64"</span>
|
|
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="n">load_dll</span><span class="o">.</span><span class="n">lpImageName</span><span class="p">:</span>
|
|
<span class="k">return</span> <span class="n">pe</span><span class="o">.</span><span class="n">export_name</span> <span class="o">+</span> <span class="n">name_sufix</span>
|
|
<span class="k">try</span><span class="p">:</span>
|
|
<span class="n">addr</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">current_process</span><span class="o">.</span><span class="n">read_ptr</span><span class="p">(</span><span class="n">load_dll</span><span class="o">.</span><span class="n">lpImageName</span><span class="p">)</span>
|
|
<span class="k">except</span><span class="p">:</span>
|
|
<span class="n">addr</span> <span class="o">=</span> <span class="kc">None</span>
|
|
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="n">addr</span><span class="p">:</span>
|
|
<span class="n">pe</span> <span class="o">=</span> <span class="n">windows</span><span class="o">.</span><span class="n">pe_parse</span><span class="o">.</span><span class="n">GetPEFile</span><span class="p">(</span><span class="n">load_dll</span><span class="o">.</span><span class="n">lpBaseOfDll</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">current_process</span><span class="p">)</span>
|
|
<span class="n">dll_name</span> <span class="o">=</span> <span class="n">pe</span><span class="o">.</span><span class="n">export_name</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="n">dll_name</span><span class="p">:</span>
|
|
<span class="n">dll_name</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">basename</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">current_process</span><span class="o">.</span><span class="n">get_mapped_filename</span><span class="p">(</span><span class="n">load_dll</span><span class="o">.</span><span class="n">lpBaseOfDll</span><span class="p">))</span>
|
|
<span class="k">return</span> <span class="n">dll_name</span> <span class="o">+</span> <span class="n">name_sufix</span>
|
|
|
|
<span class="k">if</span> <span class="n">load_dll</span><span class="o">.</span><span class="n">fUnicode</span><span class="p">:</span>
|
|
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">current_process</span><span class="o">.</span><span class="n">read_wstring</span><span class="p">(</span><span class="n">addr</span><span class="p">)</span> <span class="o">+</span> <span class="n">name_sufix</span>
|
|
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">current_process</span><span class="o">.</span><span class="n">read_string</span><span class="p">(</span><span class="n">addr</span><span class="p">)</span> <span class="o">+</span> <span class="n">name_sufix</span>
|
|
|
|
<span class="k">def</span> <span class="nf">_handle_create_process</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">debug_event</span><span class="p">):</span>
|
|
<span class="sd">"""Handle CREATE_PROCESS_DEBUG_EVENT"""</span>
|
|
<span class="n">create_process</span> <span class="o">=</span> <span class="n">debug_event</span><span class="o">.</span><span class="n">u</span><span class="o">.</span><span class="n">CreateProcessInfo</span>
|
|
<span class="c1"># Duplicate handle, so garbage collection of the process/thread does not</span>
|
|
<span class="c1"># break the debug API invariant (those x_event handle are close by the debug API itself)</span>
|
|
<span class="n">proc_handle</span> <span class="o">=</span> <span class="n">HANDLE</span><span class="p">()</span>
|
|
<span class="n">thread_handle</span> <span class="o">=</span> <span class="n">HANDLE</span><span class="p">()</span>
|
|
<span class="n">cp_handle</span> <span class="o">=</span> <span class="n">windows</span><span class="o">.</span><span class="n">current_process</span><span class="o">.</span><span class="n">handle</span>
|
|
|
|
<span class="n">winproxy</span><span class="o">.</span><span class="n">DuplicateHandle</span><span class="p">(</span><span class="n">cp_handle</span><span class="p">,</span> <span class="n">create_process</span><span class="o">.</span><span class="n">hProcess</span><span class="p">,</span> <span class="n">cp_handle</span><span class="p">,</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">byref</span><span class="p">(</span><span class="n">proc_handle</span><span class="p">),</span> <span class="n">dwOptions</span><span class="o">=</span><span class="n">DUPLICATE_SAME_ACCESS</span><span class="p">)</span>
|
|
<span class="n">winproxy</span><span class="o">.</span><span class="n">DuplicateHandle</span><span class="p">(</span><span class="n">cp_handle</span><span class="p">,</span> <span class="n">create_process</span><span class="o">.</span><span class="n">hThread</span><span class="p">,</span> <span class="n">cp_handle</span><span class="p">,</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">byref</span><span class="p">(</span><span class="n">thread_handle</span><span class="p">),</span> <span class="n">dwOptions</span><span class="o">=</span><span class="n">DUPLICATE_SAME_ACCESS</span><span class="p">)</span>
|
|
|
|
<span class="n">dbgprint</span><span class="p">(</span><span class="s2">" Got PROC handle </span><span class="si">{0:#x}</span><span class="s2">"</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">create_process</span><span class="o">.</span><span class="n">hProcess</span><span class="p">,</span> <span class="bp">self</span><span class="p">),</span> <span class="s2">"HANDLE"</span><span class="p">)</span>
|
|
<span class="n">dbgprint</span><span class="p">(</span><span class="s2">" PROC handle duplicated: </span><span class="si">{0:#x}</span><span class="s2">"</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">proc_handle</span><span class="o">.</span><span class="n">value</span><span class="p">),</span> <span class="s2">"HANDLE"</span><span class="p">)</span>
|
|
|
|
<span class="n">dbgprint</span><span class="p">(</span><span class="s2">" Got THREAD handle </span><span class="si">{0:#x}</span><span class="s2">"</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">create_process</span><span class="o">.</span><span class="n">hThread</span><span class="p">,</span> <span class="bp">self</span><span class="p">),</span> <span class="s2">"HANDLE"</span><span class="p">)</span>
|
|
<span class="n">dbgprint</span><span class="p">(</span><span class="s2">" THREAD handle duplicated: </span><span class="si">{0:#x}</span><span class="s2">"</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">thread_handle</span><span class="o">.</span><span class="n">value</span><span class="p">),</span> <span class="s2">"HANDLE"</span><span class="p">)</span>
|
|
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">current_process</span> <span class="o">=</span> <span class="n">WinProcess</span><span class="o">.</span><span class="n">_from_handle</span><span class="p">(</span><span class="n">proc_handle</span><span class="o">.</span><span class="n">value</span><span class="p">)</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">current_thread</span> <span class="o">=</span> <span class="n">WinThread</span><span class="o">.</span><span class="n">_from_handle</span><span class="p">(</span><span class="n">thread_handle</span><span class="o">.</span><span class="n">value</span><span class="p">)</span>
|
|
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">threads</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">current_thread</span><span class="o">.</span><span class="n">tid</span><span class="p">]</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">current_thread</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_explicit_single_step</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">current_thread</span><span class="o">.</span><span class="n">tid</span><span class="p">]</span> <span class="o">=</span> <span class="kc">False</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_hardware_breakpoint</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">current_thread</span><span class="o">.</span><span class="n">tid</span><span class="p">]</span> <span class="o">=</span> <span class="p">{}</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_breakpoint_to_reput</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">current_thread</span><span class="o">.</span><span class="n">tid</span><span class="p">]</span> <span class="o">=</span> <span class="p">[]</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">processes</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">current_process</span><span class="o">.</span><span class="n">pid</span><span class="p">]</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">current_process</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_watched_pages</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">current_process</span><span class="o">.</span><span class="n">pid</span><span class="p">]</span> <span class="o">=</span> <span class="p">{}</span> <span class="c1">#defaultdict(list)</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">breakpoints</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">current_process</span><span class="o">.</span><span class="n">pid</span><span class="p">]</span> <span class="o">=</span> <span class="p">{}</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_memory_save</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">current_process</span><span class="o">.</span><span class="n">pid</span><span class="p">]</span> <span class="o">=</span> <span class="p">{}</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_module_by_process</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">current_process</span><span class="o">.</span><span class="n">pid</span><span class="p">]</span> <span class="o">=</span> <span class="p">{}</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_update_debugger_state</span><span class="p">(</span><span class="n">debug_event</span><span class="p">)</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_setup_pending_breakpoints_new_process</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">current_process</span><span class="p">)</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_setup_pending_breakpoints_new_thread</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">current_thread</span><span class="p">)</span>
|
|
<span class="k">with</span> <span class="bp">self</span><span class="o">.</span><span class="n">DisabledMemoryBreakpoint</span><span class="p">():</span>
|
|
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">on_create_process</span><span class="p">(</span><span class="n">create_process</span><span class="p">)</span>
|
|
<span class="c1"># TODO: close hFile</span>
|
|
|
|
<span class="k">def</span> <span class="nf">_handle_exit_process</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">debug_event</span><span class="p">):</span>
|
|
<span class="sd">"""Handle EXIT_PROCESS_DEBUG_EVENT"""</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_update_debugger_state</span><span class="p">(</span><span class="n">debug_event</span><span class="p">)</span>
|
|
<span class="n">exit_process</span> <span class="o">=</span> <span class="n">debug_event</span><span class="o">.</span><span class="n">u</span><span class="o">.</span><span class="n">ExitProcess</span>
|
|
<span class="n">retvalue</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">on_exit_process</span><span class="p">(</span><span class="n">exit_process</span><span class="p">)</span>
|
|
<span class="k">del</span> <span class="bp">self</span><span class="o">.</span><span class="n">threads</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">current_thread</span><span class="o">.</span><span class="n">tid</span><span class="p">]</span>
|
|
<span class="k">del</span> <span class="bp">self</span><span class="o">.</span><span class="n">_explicit_single_step</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">current_thread</span><span class="o">.</span><span class="n">tid</span><span class="p">]</span>
|
|
<span class="k">del</span> <span class="bp">self</span><span class="o">.</span><span class="n">_hardware_breakpoint</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">current_thread</span><span class="o">.</span><span class="n">tid</span><span class="p">]</span>
|
|
<span class="k">del</span> <span class="bp">self</span><span class="o">.</span><span class="n">_breakpoint_to_reput</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">current_thread</span><span class="o">.</span><span class="n">tid</span><span class="p">]</span>
|
|
<span class="k">del</span> <span class="bp">self</span><span class="o">.</span><span class="n">processes</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">current_process</span><span class="o">.</span><span class="n">pid</span><span class="p">]</span>
|
|
<span class="k">del</span> <span class="bp">self</span><span class="o">.</span><span class="n">_watched_pages</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">current_process</span><span class="o">.</span><span class="n">pid</span><span class="p">]</span>
|
|
<span class="k">del</span> <span class="bp">self</span><span class="o">.</span><span class="n">_memory_save</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">current_process</span><span class="o">.</span><span class="n">pid</span><span class="p">]</span>
|
|
<span class="k">del</span> <span class="bp">self</span><span class="o">.</span><span class="n">_module_by_process</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">current_process</span><span class="o">.</span><span class="n">pid</span><span class="p">]</span>
|
|
|
|
<span class="n">cpid</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">current_process</span><span class="o">.</span><span class="n">pid</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">current_thread</span> <span class="o">=</span> <span class="kc">None</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">current_process</span> <span class="o">=</span> <span class="kc">None</span>
|
|
|
|
<span class="k">if</span> <span class="n">cpid</span> <span class="o">==</span> <span class="bp">self</span><span class="o">.</span><span class="n">target</span><span class="o">.</span><span class="n">pid</span><span class="p">:</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">target</span> <span class="o">=</span> <span class="kc">None</span>
|
|
|
|
<span class="k">return</span> <span class="n">retvalue</span>
|
|
|
|
<span class="k">def</span> <span class="nf">_handle_create_thread</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">debug_event</span><span class="p">):</span>
|
|
<span class="sd">"""Handle CREATE_THREAD_DEBUG_EVENT"""</span>
|
|
<span class="n">create_thread</span> <span class="o">=</span> <span class="n">debug_event</span><span class="o">.</span><span class="n">u</span><span class="o">.</span><span class="n">CreateThread</span>
|
|
<span class="c1"># Duplicate handle, so garbage collection of the thread does not</span>
|
|
<span class="c1"># break the debug API invariant (those x_event handle are close by the debug API itself)</span>
|
|
<span class="n">thread_handle</span> <span class="o">=</span> <span class="n">HANDLE</span><span class="p">()</span>
|
|
<span class="n">cp_handle</span> <span class="o">=</span> <span class="n">windows</span><span class="o">.</span><span class="n">current_process</span><span class="o">.</span><span class="n">handle</span>
|
|
<span class="n">winproxy</span><span class="o">.</span><span class="n">DuplicateHandle</span><span class="p">(</span><span class="n">cp_handle</span><span class="p">,</span> <span class="n">create_thread</span><span class="o">.</span><span class="n">hThread</span><span class="p">,</span> <span class="n">cp_handle</span><span class="p">,</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">byref</span><span class="p">(</span><span class="n">thread_handle</span><span class="p">),</span> <span class="n">dwOptions</span><span class="o">=</span><span class="n">DUPLICATE_SAME_ACCESS</span><span class="p">)</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">current_thread</span> <span class="o">=</span> <span class="n">WinThread</span><span class="o">.</span><span class="n">_from_handle</span><span class="p">(</span><span class="n">thread_handle</span><span class="o">.</span><span class="n">value</span><span class="p">)</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">threads</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">current_thread</span><span class="o">.</span><span class="n">tid</span><span class="p">]</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">current_thread</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_explicit_single_step</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">current_thread</span><span class="o">.</span><span class="n">tid</span><span class="p">]</span> <span class="o">=</span> <span class="kc">False</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_breakpoint_to_reput</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">current_thread</span><span class="o">.</span><span class="n">tid</span><span class="p">]</span> <span class="o">=</span> <span class="p">[]</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_hardware_breakpoint</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">current_thread</span><span class="o">.</span><span class="n">tid</span><span class="p">]</span> <span class="o">=</span> <span class="p">{}</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_setup_pending_breakpoints_new_thread</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">current_thread</span><span class="p">)</span>
|
|
<span class="k">with</span> <span class="bp">self</span><span class="o">.</span><span class="n">DisabledMemoryBreakpoint</span><span class="p">():</span>
|
|
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">on_create_thread</span><span class="p">(</span><span class="n">create_thread</span><span class="p">)</span>
|
|
|
|
|
|
<span class="k">def</span> <span class="nf">_handle_exit_thread</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">debug_event</span><span class="p">):</span>
|
|
<span class="sd">"""Handle EXIT_THREAD_DEBUG_EVENT"""</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_update_debugger_state</span><span class="p">(</span><span class="n">debug_event</span><span class="p">)</span>
|
|
<span class="n">exit_thread</span> <span class="o">=</span> <span class="n">debug_event</span><span class="o">.</span><span class="n">u</span><span class="o">.</span><span class="n">ExitThread</span>
|
|
<span class="k">with</span> <span class="bp">self</span><span class="o">.</span><span class="n">DisabledMemoryBreakpoint</span><span class="p">():</span>
|
|
<span class="n">retvalue</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">on_exit_thread</span><span class="p">(</span><span class="n">exit_thread</span><span class="p">)</span>
|
|
<span class="k">del</span> <span class="bp">self</span><span class="o">.</span><span class="n">threads</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">current_thread</span><span class="o">.</span><span class="n">tid</span><span class="p">]</span>
|
|
<span class="k">del</span> <span class="bp">self</span><span class="o">.</span><span class="n">_hardware_breakpoint</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">current_thread</span><span class="o">.</span><span class="n">tid</span><span class="p">]</span>
|
|
<span class="k">del</span> <span class="bp">self</span><span class="o">.</span><span class="n">_explicit_single_step</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">current_thread</span><span class="o">.</span><span class="n">tid</span><span class="p">]</span>
|
|
<span class="k">del</span> <span class="bp">self</span><span class="o">.</span><span class="n">_breakpoint_to_reput</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">current_thread</span><span class="o">.</span><span class="n">tid</span><span class="p">]</span>
|
|
<span class="k">return</span> <span class="n">retvalue</span>
|
|
|
|
<span class="k">def</span> <span class="nf">_handle_load_dll</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">debug_event</span><span class="p">):</span>
|
|
<span class="sd">"""Handle LOAD_DLL_DEBUG_EVENT"""</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_update_debugger_state</span><span class="p">(</span><span class="n">debug_event</span><span class="p">)</span>
|
|
<span class="n">load_dll</span> <span class="o">=</span> <span class="n">debug_event</span><span class="o">.</span><span class="n">u</span><span class="o">.</span><span class="n">LoadDll</span>
|
|
<span class="n">dll</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_get_loaded_dll</span><span class="p">(</span><span class="n">load_dll</span><span class="p">)</span>
|
|
<span class="n">dll_name</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">basename</span><span class="p">(</span><span class="n">dll</span><span class="p">)</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span>
|
|
<span class="k">if</span> <span class="n">dll_name</span><span class="o">.</span><span class="n">endswith</span><span class="p">(</span><span class="s2">".dll"</span><span class="p">):</span>
|
|
<span class="n">dll_name</span> <span class="o">=</span> <span class="n">dll_name</span><span class="p">[:</span><span class="o">-</span><span class="mi">4</span><span class="p">]</span>
|
|
<span class="k">if</span> <span class="n">dll_name</span><span class="o">.</span><span class="n">endswith</span><span class="p">(</span><span class="s2">".dll64"</span><span class="p">):</span>
|
|
<span class="n">dll_name</span> <span class="o">=</span> <span class="n">dll_name</span><span class="p">[:</span><span class="o">-</span><span class="mi">6</span><span class="p">]</span> <span class="o">+</span> <span class="s2">"64"</span> <span class="c1"># Crade..</span>
|
|
<span class="c1">#print("Load {0} -> {1}".format(dll, dll_name))</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_module_by_process</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">current_process</span><span class="o">.</span><span class="n">pid</span><span class="p">][</span><span class="n">dll_name</span><span class="p">]</span> <span class="o">=</span> <span class="n">windows</span><span class="o">.</span><span class="n">pe_parse</span><span class="o">.</span><span class="n">GetPEFile</span><span class="p">(</span><span class="n">load_dll</span><span class="o">.</span><span class="n">lpBaseOfDll</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">current_process</span><span class="p">)</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_setup_pending_breakpoints_load_dll</span><span class="p">(</span><span class="n">dll_name</span><span class="p">)</span>
|
|
<span class="k">with</span> <span class="bp">self</span><span class="o">.</span><span class="n">DisabledMemoryBreakpoint</span><span class="p">():</span>
|
|
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">on_load_dll</span><span class="p">(</span><span class="n">load_dll</span><span class="p">)</span>
|
|
|
|
<span class="k">def</span> <span class="nf">_handle_unload_dll</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">debug_event</span><span class="p">):</span>
|
|
<span class="sd">"""Handle UNLOAD_DLL_DEBUG_EVENT"""</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_update_debugger_state</span><span class="p">(</span><span class="n">debug_event</span><span class="p">)</span>
|
|
<span class="n">unload_dll</span> <span class="o">=</span> <span class="n">debug_event</span><span class="o">.</span><span class="n">u</span><span class="o">.</span><span class="n">UnloadDll</span>
|
|
<span class="k">with</span> <span class="bp">self</span><span class="o">.</span><span class="n">DisabledMemoryBreakpoint</span><span class="p">():</span>
|
|
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">on_unload_dll</span><span class="p">(</span><span class="n">unload_dll</span><span class="p">)</span>
|
|
|
|
<span class="k">def</span> <span class="nf">_handle_output_debug_string</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">debug_event</span><span class="p">):</span>
|
|
<span class="sd">"""Handle OUTPUT_DEBUG_STRING_EVENT"""</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_update_debugger_state</span><span class="p">(</span><span class="n">debug_event</span><span class="p">)</span>
|
|
<span class="n">debug_string</span> <span class="o">=</span> <span class="n">debug_event</span><span class="o">.</span><span class="n">u</span><span class="o">.</span><span class="n">DebugString</span>
|
|
<span class="k">with</span> <span class="bp">self</span><span class="o">.</span><span class="n">DisabledMemoryBreakpoint</span><span class="p">():</span>
|
|
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">on_output_debug_string</span><span class="p">(</span><span class="n">debug_string</span><span class="p">)</span>
|
|
|
|
<span class="k">def</span> <span class="nf">_handle_rip</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">debug_event</span><span class="p">):</span>
|
|
<span class="sd">"""Handle RIP_EVENT"""</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_update_debugger_state</span><span class="p">(</span><span class="n">debug_event</span><span class="p">)</span>
|
|
<span class="n">rip_info</span> <span class="o">=</span> <span class="n">debug_event</span><span class="o">.</span><span class="n">u</span><span class="o">.</span><span class="n">RipInfo</span>
|
|
<span class="k">with</span> <span class="bp">self</span><span class="o">.</span><span class="n">DisabledMemoryBreakpoint</span><span class="p">():</span>
|
|
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">on_rip</span><span class="p">(</span><span class="n">rip_info</span><span class="p">)</span>
|
|
|
|
<span class="c1">## Public API</span>
|
|
<div class="viewcode-block" id="Debugger.loop"><a class="viewcode-back" href="../../../debug.html#windows.debug.Debugger.loop">[docs]</a> <span class="k">def</span> <span class="nf">loop</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
|
<span class="sd">"""Debugging loop: handle event / dispatch to breakpoint. Returns when all targets are dead/detached"""</span>
|
|
<span class="k">for</span> <span class="n">debug_event</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">_debug_event_generator</span><span class="p">():</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">REMOVE_ME_debug_event</span> <span class="o">=</span> <span class="n">debug_event</span>
|
|
<span class="n">dbg_continue_flag</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_dispatch_debug_event</span><span class="p">(</span><span class="n">debug_event</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="n">dbg_continue_flag</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="n">dbg_continue_flag</span> <span class="o">=</span> <span class="n">DBG_CONTINUE</span>
|
|
<span class="k">if</span> <span class="n">debug_event</span><span class="o">.</span><span class="n">dwDebugEventCode</span> <span class="o">==</span> <span class="n">EXIT_PROCESS_DEBUG_EVENT</span> <span class="ow">or</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">_killed_in_action</span><span class="p">():</span>
|
|
<span class="c1">#if not self._killed_in_action():</span>
|
|
<span class="c1"># should we always _finish_debug_event even if process was killed ?</span>
|
|
<span class="c1"># rhaaa _killed_in_action is a REALLY bad name, it's not killed, it's detached</span>
|
|
<span class="c1"># TODO: FIXME</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_finish_debug_event</span><span class="p">(</span><span class="n">debug_event</span><span class="p">,</span> <span class="n">dbg_continue_flag</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">processes</span><span class="p">:</span>
|
|
<span class="k">break</span></div>
|
|
|
|
<div class="viewcode-block" id="Debugger.add_bp"><a class="viewcode-back" href="../../../debug.html#windows.debug.Debugger.add_bp">[docs]</a> <span class="k">def</span> <span class="nf">add_bp</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">bp</span><span class="p">,</span> <span class="n">addr</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="nb">type</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">target</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
|
|
<span class="sd">"""Add a breakpoint, bp can be:</span>
|
|
|
|
<span class="sd"> * a :class:`Breakpoint` (addr and type must be ``None``)</span>
|
|
<span class="sd"> * any callable (addr and type must NOT be ``None``) (NON-TESTED)</span>
|
|
|
|
<span class="sd"> If the ``bp`` type is ``STANDARD_BP`` or ``MEMORY_BREAKPOINT``, target can be ``None`` (all targets) or a process.</span>
|
|
|
|
<span class="sd"> If the ``bp`` type is ``HARDWARE_EXEC_BP``, target can be ``None`` (all targets), a process or a thread.</span>
|
|
<span class="sd"> """</span>
|
|
<span class="k">if</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">bp</span><span class="p">,</span> <span class="s2">"addr"</span><span class="p">,</span> <span class="kc">None</span><span class="p">)</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="n">addr</span> <span class="ow">is</span> <span class="kc">None</span> <span class="ow">or</span> <span class="nb">type</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s2">"SUCK YOUR NONE"</span><span class="p">)</span>
|
|
<span class="n">bp</span> <span class="o">=</span> <span class="n">ProxyBreakpoint</span><span class="p">(</span><span class="n">bp</span><span class="p">,</span> <span class="n">addr</span><span class="p">,</span> <span class="nb">type</span><span class="p">)</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="n">addr</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span> <span class="ow">or</span> <span class="nb">type</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s2">"Given <addr|type> by parameters but BP object have them"</span><span class="p">)</span>
|
|
<span class="k">del</span> <span class="n">addr</span>
|
|
<span class="k">del</span> <span class="nb">type</span>
|
|
|
|
<span class="k">if</span> <span class="n">target</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="c1"># Need to add it to all other breakpoint</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">add_pending_breakpoint</span><span class="p">(</span><span class="n">bp</span><span class="p">,</span> <span class="kc">None</span><span class="p">)</span>
|
|
<span class="k">elif</span> <span class="n">target</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="c1"># Check that targets are accepted</span>
|
|
<span class="k">if</span> <span class="n">target</span> <span class="ow">not</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">processes</span><span class="o">.</span><span class="n">values</span><span class="p">()</span> <span class="o">+</span> <span class="bp">self</span><span class="o">.</span><span class="n">threads</span><span class="o">.</span><span class="n">values</span><span class="p">():</span>
|
|
<span class="k">if</span> <span class="n">target</span> <span class="o">==</span> <span class="bp">self</span><span class="o">.</span><span class="n">target</span><span class="p">:</span> <span class="c1"># Original target (that have not been lauched yet)</span>
|
|
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">add_pending_breakpoint</span><span class="p">(</span><span class="n">bp</span><span class="p">,</span> <span class="n">target</span><span class="p">)</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s2">"Unknown target </span><span class="si">{0}</span><span class="s2">"</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">target</span><span class="p">))</span>
|
|
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_setup_breakpoint</span><span class="p">(</span><span class="n">bp</span><span class="p">,</span> <span class="n">target</span><span class="p">)</span></div>
|
|
|
|
<div class="viewcode-block" id="Debugger.del_bp"><a class="viewcode-back" href="../../../debug.html#windows.debug.Debugger.del_bp">[docs]</a> <span class="k">def</span> <span class="nf">del_bp</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">bp</span><span class="p">,</span> <span class="n">targets</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
|
|
<span class="sd">"""Delete a breakpoint, if targets is ``None``: delete it from all targets"""</span>
|
|
<span class="n">original_target</span> <span class="o">=</span> <span class="n">targets</span>
|
|
<span class="n">_remove_method</span> <span class="o">=</span> <span class="nb">getattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="s2">"_remove_breakpoint_"</span> <span class="o">+</span> <span class="n">bp</span><span class="o">.</span><span class="n">type</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="n">targets</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="n">bp</span><span class="o">.</span><span class="n">type</span> <span class="ow">in</span> <span class="p">[</span><span class="n">STANDARD_BP</span><span class="p">,</span> <span class="n">MEMORY_BREAKPOINT</span><span class="p">]:</span> <span class="c1">#TODO: better..</span>
|
|
<span class="n">targets</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">processes</span><span class="o">.</span><span class="n">values</span><span class="p">()</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="n">targets</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">threads</span><span class="o">.</span><span class="n">values</span><span class="p">()</span>
|
|
<span class="k">for</span> <span class="n">target</span> <span class="ow">in</span> <span class="n">targets</span><span class="p">:</span>
|
|
<span class="n">_remove_method</span><span class="p">(</span><span class="n">bp</span><span class="p">,</span> <span class="n">target</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="n">original_target</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">remove_pending_breakpoint</span><span class="p">(</span><span class="n">bp</span><span class="p">,</span> <span class="n">original_target</span><span class="p">)</span></div>
|
|
|
|
<div class="viewcode-block" id="Debugger.single_step"><a class="viewcode-back" href="../../../debug.html#windows.debug.Debugger.single_step">[docs]</a> <span class="k">def</span> <span class="nf">single_step</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
|
<span class="sd">"""Make the ``current_thread`` ``single_step``. ``Debugger.on_single_step`` will be called after that"""</span>
|
|
<span class="n">t</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">current_thread</span>
|
|
<span class="n">ctx</span> <span class="o">=</span> <span class="n">t</span><span class="o">.</span><span class="n">context</span>
|
|
<span class="n">ctx</span><span class="o">.</span><span class="n">EEFlags</span><span class="o">.</span><span class="n">TF</span> <span class="o">=</span> <span class="mi">1</span>
|
|
<span class="n">t</span><span class="o">.</span><span class="n">set_context</span><span class="p">(</span><span class="n">ctx</span><span class="p">)</span></div>
|
|
|
|
<span class="c1">## Memory Breakpoint helper</span>
|
|
<div class="viewcode-block" id="Debugger.get_memory_breakpoint_at"><a class="viewcode-back" href="../../../debug.html#windows.debug.Debugger.get_memory_breakpoint_at">[docs]</a> <span class="k">def</span> <span class="nf">get_memory_breakpoint_at</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">addr</span><span class="p">,</span> <span class="n">process</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
|
|
<span class="sd">"""Get the memory breakpoint that handle ``addr``</span>
|
|
|
|
<span class="sd"> Return values are:</span>
|
|
|
|
<span class="sd"> * ``False`` if the page has no memory breakpoint (real fault)</span>
|
|
<span class="sd"> * ``None`` if the page as memBP but None handle ``addr``</span>
|
|
<span class="sd"> * ``bp`` the MemBP that handle ``addr``</span>
|
|
<span class="sd"> """</span>
|
|
<span class="k">if</span> <span class="n">process</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="n">process</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">current_process</span>
|
|
|
|
<span class="n">fault_page</span> <span class="o">=</span> <span class="p">(</span><span class="n">addr</span> <span class="o">>></span> <span class="mi">12</span><span class="p">)</span> <span class="o"><<</span> <span class="mi">12</span>
|
|
<span class="k">if</span> <span class="n">fault_page</span> <span class="ow">not</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">_watched_pages</span><span class="p">[</span><span class="n">process</span><span class="o">.</span><span class="n">pid</span><span class="p">]:</span>
|
|
<span class="k">return</span> <span class="kc">False</span>
|
|
|
|
<span class="k">for</span> <span class="n">bp</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">_watched_pages</span><span class="p">[</span><span class="n">process</span><span class="o">.</span><span class="n">pid</span><span class="p">][</span><span class="n">fault_page</span><span class="p">]</span><span class="o">.</span><span class="n">bps</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="n">bp</span><span class="o">.</span><span class="n">_addr</span> <span class="o"><=</span> <span class="n">addr</span> <span class="o"><</span> <span class="n">bp</span><span class="o">.</span><span class="n">_addr</span> <span class="o">+</span> <span class="n">bp</span><span class="o">.</span><span class="n">size</span><span class="p">:</span>
|
|
<span class="k">return</span> <span class="n">bp</span>
|
|
<span class="k">return</span> <span class="kc">None</span></div>
|
|
|
|
<div class="viewcode-block" id="Debugger.disable_all_memory_breakpoints"><a class="viewcode-back" href="../../../debug.html#windows.debug.Debugger.disable_all_memory_breakpoints">[docs]</a> <span class="k">def</span> <span class="nf">disable_all_memory_breakpoints</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">target</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
|
|
<span class="sd">"""Restore all pages to their original access rights.</span>
|
|
<span class="sd"> If target is ``None``, use ``current_process``</span>
|
|
|
|
<span class="sd"> :return: a mapping of all disabled breakpoints that must be passed to :func:`restore_all_memory_breakpoints`"""</span>
|
|
<span class="k">if</span> <span class="n">target</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="n">target</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">current_process</span>
|
|
<span class="n">res</span> <span class="o">=</span> <span class="p">{}</span>
|
|
<span class="n">cp_watch_page</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_watched_pages</span><span class="p">[</span><span class="n">target</span><span class="o">.</span><span class="n">pid</span><span class="p">]</span>
|
|
<span class="n">page_protection</span> <span class="o">=</span> <span class="n">DWORD</span><span class="p">()</span>
|
|
<span class="k">for</span> <span class="n">page_addr</span><span class="p">,</span> <span class="n">watched_page</span> <span class="ow">in</span> <span class="n">cp_watch_page</span><span class="o">.</span><span class="n">items</span><span class="p">():</span>
|
|
<span class="n">target</span><span class="o">.</span><span class="n">virtual_protect</span><span class="p">(</span><span class="n">page_addr</span><span class="p">,</span> <span class="n">PAGE_SIZE</span><span class="p">,</span> <span class="n">watched_page</span><span class="o">.</span><span class="n">original_prot</span><span class="p">,</span> <span class="n">page_protection</span><span class="p">)</span>
|
|
<span class="n">res</span><span class="p">[</span><span class="n">page_addr</span><span class="p">]</span> <span class="o">=</span> <span class="n">page_protection</span><span class="o">.</span><span class="n">value</span>
|
|
<span class="k">return</span> <span class="n">res</span></div>
|
|
|
|
|
|
<div class="viewcode-block" id="Debugger.restore_all_memory_breakpoints"><a class="viewcode-back" href="../../../debug.html#windows.debug.Debugger.restore_all_memory_breakpoints">[docs]</a> <span class="k">def</span> <span class="nf">restore_all_memory_breakpoints</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">data</span><span class="p">,</span> <span class="n">target</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
|
|
<span class="sd">"""Re-setup all memory breakpoints, affecting pages access rights.</span>
|
|
<span class="sd"> If target is ``None``, use ``current_process``</span>
|
|
|
|
<span class="sd"> ``data`` is the result of the corresponding call to :func:`disable_all_memory_breakpoints`"""</span>
|
|
<span class="k">if</span> <span class="n">target</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="n">target</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">current_process</span>
|
|
<span class="k">for</span> <span class="n">page_addr</span><span class="p">,</span> <span class="n">protection</span> <span class="ow">in</span> <span class="n">data</span><span class="o">.</span><span class="n">items</span><span class="p">():</span>
|
|
<span class="c1"># Prevent restoring deleted breakpoints</span>
|
|
<span class="k">if</span> <span class="n">page_addr</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">_watched_pages</span><span class="p">[</span><span class="n">target</span><span class="o">.</span><span class="n">pid</span><span class="p">]:</span>
|
|
<span class="n">target</span><span class="o">.</span><span class="n">virtual_protect</span><span class="p">(</span><span class="n">page_addr</span><span class="p">,</span> <span class="n">PAGE_SIZE</span><span class="p">,</span> <span class="n">protection</span><span class="p">,</span> <span class="kc">None</span><span class="p">)</span>
|
|
<span class="k">return</span></div>
|
|
|
|
<span class="nd">@contextmanager</span>
|
|
<div class="viewcode-block" id="Debugger.DisabledMemoryBreakpoint"><a class="viewcode-back" href="../../../debug.html#windows.debug.Debugger.DisabledMemoryBreakpoint">[docs]</a> <span class="k">def</span> <span class="nf">DisabledMemoryBreakpoint</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">target</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
|
|
<span class="sd">"""A context-manager that disable all memory breakpoints and restore them on exit"""</span>
|
|
<span class="n">data</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">disable_all_memory_breakpoints</span><span class="p">(</span><span class="n">target</span><span class="p">)</span>
|
|
<span class="k">try</span><span class="p">:</span>
|
|
<span class="k">yield</span>
|
|
<span class="k">finally</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">_killed_in_action</span><span class="p">():</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">restore_all_memory_breakpoints</span><span class="p">(</span><span class="n">data</span><span class="p">,</span> <span class="n">target</span><span class="p">)</span></div>
|
|
|
|
<div class="viewcode-block" id="Debugger.get_exception_bitness"><a class="viewcode-back" href="../../../debug.html#windows.debug.Debugger.get_exception_bitness">[docs]</a> <span class="k">def</span> <span class="nf">get_exception_bitness</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">exc</span><span class="p">):</span>
|
|
<span class="sd">"""Return the bitness in which the exception occured.</span>
|
|
<span class="sd"> Useful when debugingg a 32b process from a 64bits one</span>
|
|
|
|
<span class="sd"> :return: :class:`int` -- 32 or 64"""</span>
|
|
<span class="k">if</span> <span class="n">windows</span><span class="o">.</span><span class="n">current_process</span><span class="o">.</span><span class="n">bitness</span> <span class="o">==</span> <span class="mi">32</span><span class="p">:</span>
|
|
<span class="k">return</span> <span class="mi">32</span>
|
|
<span class="k">if</span> <span class="n">exc</span><span class="o">.</span><span class="n">ExceptionRecord</span><span class="o">.</span><span class="n">ExceptionCode</span> <span class="ow">in</span> <span class="p">[</span><span class="n">STATUS_WX86_BREAKPOINT</span><span class="p">,</span> <span class="n">STATUS_WX86_SINGLE_STEP</span><span class="p">]:</span>
|
|
<span class="k">return</span> <span class="mi">32</span>
|
|
<span class="k">return</span> <span class="mi">64</span></div>
|
|
|
|
<span class="c1"># Public callback</span>
|
|
<div class="viewcode-block" id="Debugger.on_exception"><a class="viewcode-back" href="../../../debug.html#windows.debug.Debugger.on_exception">[docs]</a> <span class="k">def</span> <span class="nf">on_exception</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">exception</span><span class="p">):</span>
|
|
<span class="sd">"""Called on exception event other that known breakpoint or requested single step. ``exception`` is one of the following type:</span>
|
|
|
|
<span class="sd"> * :class:`windows.winobject.exception.EEXCEPTION_DEBUG_INFO32`</span>
|
|
<span class="sd"> * :class:`windows.winobject.exception.EEXCEPTION_DEBUG_INFO64`</span>
|
|
|
|
<span class="sd"> The default behaviour is to return ``DBG_CONTINUE`` for the known exception code</span>
|
|
<span class="sd"> and ``DBG_EXCEPTION_NOT_HANDLED`` else</span>
|
|
<span class="sd"> """</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="n">exception</span><span class="o">.</span><span class="n">ExceptionRecord</span><span class="o">.</span><span class="n">ExceptionCode</span> <span class="ow">in</span> <span class="n">winexception</span><span class="o">.</span><span class="n">exception_name_by_value</span><span class="p">:</span>
|
|
<span class="k">return</span> <span class="n">DBG_EXCEPTION_NOT_HANDLED</span>
|
|
<span class="k">return</span> <span class="n">DBG_CONTINUE</span></div>
|
|
|
|
<div class="viewcode-block" id="Debugger.on_single_step"><a class="viewcode-back" href="../../../debug.html#windows.debug.Debugger.on_single_step">[docs]</a> <span class="k">def</span> <span class="nf">on_single_step</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">exception</span><span class="p">):</span>
|
|
<span class="sd">"""Called on requested single step ``exception`` is one of the following type:</span>
|
|
|
|
<span class="sd"> * :class:`windows.winobject.exception.EEXCEPTION_DEBUG_INFO32`</span>
|
|
<span class="sd"> * :class:`windows.winobject.exception.EEXCEPTION_DEBUG_INFO64`</span>
|
|
|
|
<span class="sd"> There is no default implementation, if you use ``Debugger.single_step()`` you should implement ``on_single_step``</span>
|
|
<span class="sd"> """</span>
|
|
<span class="k">raise</span> <span class="ne">NotImplementedError</span><span class="p">(</span><span class="s2">"Debugger that explicitly single step should implement <on_single_step>"</span><span class="p">)</span></div>
|
|
|
|
<div class="viewcode-block" id="Debugger.on_create_process"><a class="viewcode-back" href="../../../debug.html#windows.debug.Debugger.on_create_process">[docs]</a> <span class="k">def</span> <span class="nf">on_create_process</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">create_process</span><span class="p">):</span>
|
|
<span class="sd">"""Called on create_process event (for param type see https://msdn.microsoft.com/en-us/library/windows/desktop/ms679286(v=vs.85).aspx)"""</span>
|
|
<span class="k">pass</span></div>
|
|
|
|
<div class="viewcode-block" id="Debugger.on_exit_process"><a class="viewcode-back" href="../../../debug.html#windows.debug.Debugger.on_exit_process">[docs]</a> <span class="k">def</span> <span class="nf">on_exit_process</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">exit_process</span><span class="p">):</span>
|
|
<span class="sd">"""Called on exit_process event (for param type see https://msdn.microsoft.com/en-us/library/windows/desktop/ms679334(v=vs.85).aspx)"""</span>
|
|
<span class="k">pass</span></div>
|
|
|
|
<div class="viewcode-block" id="Debugger.on_create_thread"><a class="viewcode-back" href="../../../debug.html#windows.debug.Debugger.on_create_thread">[docs]</a> <span class="k">def</span> <span class="nf">on_create_thread</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">create_thread</span><span class="p">):</span>
|
|
<span class="sd">"""Called on create_thread event (for param type see https://msdn.microsoft.com/en-us/library/windows/desktop/ms679287(v=vs.85).aspx)"""</span>
|
|
<span class="k">pass</span></div>
|
|
|
|
<div class="viewcode-block" id="Debugger.on_exit_thread"><a class="viewcode-back" href="../../../debug.html#windows.debug.Debugger.on_exit_thread">[docs]</a> <span class="k">def</span> <span class="nf">on_exit_thread</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">exit_thread</span><span class="p">):</span>
|
|
<span class="sd">"""Called on exit_thread event (for param type see https://msdn.microsoft.com/en-us/library/windows/desktop/ms679335(v=vs.85).aspx)"""</span>
|
|
<span class="k">pass</span></div>
|
|
|
|
<div class="viewcode-block" id="Debugger.on_load_dll"><a class="viewcode-back" href="../../../debug.html#windows.debug.Debugger.on_load_dll">[docs]</a> <span class="k">def</span> <span class="nf">on_load_dll</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">load_dll</span><span class="p">):</span>
|
|
<span class="sd">"""Called on load_dll event (for param type see https://msdn.microsoft.com/en-us/library/windows/desktop/ms680351(v=vs.85).aspx)"""</span>
|
|
<span class="k">pass</span></div>
|
|
|
|
<div class="viewcode-block" id="Debugger.on_unload_dll"><a class="viewcode-back" href="../../../debug.html#windows.debug.Debugger.on_unload_dll">[docs]</a> <span class="k">def</span> <span class="nf">on_unload_dll</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">unload_dll</span><span class="p">):</span>
|
|
<span class="sd">"""Called on unload_dll event (for param type see https://msdn.microsoft.com/en-us/library/windows/desktop/ms681403(v=vs.85).aspx)"""</span>
|
|
<span class="k">pass</span></div>
|
|
|
|
<div class="viewcode-block" id="Debugger.on_output_debug_string"><a class="viewcode-back" href="../../../debug.html#windows.debug.Debugger.on_output_debug_string">[docs]</a> <span class="k">def</span> <span class="nf">on_output_debug_string</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">debug_string</span><span class="p">):</span>
|
|
<span class="sd">"""Called on debug_string event (for param type see https://msdn.microsoft.com/en-us/library/windows/desktop/ms680545(v=vs.85).aspx)"""</span>
|
|
<span class="k">pass</span></div>
|
|
|
|
<div class="viewcode-block" id="Debugger.on_rip"><a class="viewcode-back" href="../../../debug.html#windows.debug.Debugger.on_rip">[docs]</a> <span class="k">def</span> <span class="nf">on_rip</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">rip_info</span><span class="p">):</span>
|
|
<span class="sd">"""Called on rip_info event (for param type see https://msdn.microsoft.com/en-us/library/windows/desktop/ms680587(v=vs.85).aspx)"""</span>
|
|
<span class="k">pass</span></div></div>
|
|
</pre></div>
|
|
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sphinxsidebar" role="navigation" aria-label="main navigation">
|
|
<div class="sphinxsidebarwrapper">
|
|
<div id="searchbox" style="display: none" role="search">
|
|
<h3>Quick search</h3>
|
|
<form class="search" action="../../../search.html" method="get">
|
|
<div><input type="text" name="q" /></div>
|
|
<div><input type="submit" value="Go" /></div>
|
|
<input type="hidden" name="check_keywords" value="yes" />
|
|
<input type="hidden" name="area" value="default" />
|
|
</form>
|
|
</div>
|
|
<script type="text/javascript">$('#searchbox').show(0);</script>
|
|
</div>
|
|
</div>
|
|
<div class="clearer"></div>
|
|
</div>
|
|
<div class="related" role="navigation" aria-label="related navigation">
|
|
<h3>Navigation</h3>
|
|
<ul>
|
|
<li class="right" style="margin-right: 10px">
|
|
<a href="../../../genindex.html" title="General Index"
|
|
>index</a></li>
|
|
<li class="right" >
|
|
<a href="../../../py-modindex.html" title="Python Module Index"
|
|
>modules</a> |</li>
|
|
<li class="nav-item nav-item-0"><a href="../../../index.html">PythonForWindows 0.2 documentation</a> »</li>
|
|
<li class="nav-item nav-item-1"><a href="../../index.html" >Module code</a> »</li>
|
|
</ul>
|
|
</div>
|
|
<div class="footer" role="contentinfo">
|
|
© Copyright 2015, Clement Rouault.
|
|
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.5.5.
|
|
</div>
|
|
</body>
|
|
</html> |