Files
2025-08-14 10:37:06 +02:00

1328 lines
212 KiB
HTML

<!DOCTYPE html>
<html lang="en" data-content_root="../../../">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>windows.debug.debugger &#8212; PythonForWindows 1.0.4 documentation</title>
<link rel="stylesheet" type="text/css" href="../../../_static/pygments.css?v=fa44fd50" />
<link rel="stylesheet" type="text/css" href="../../../_static/classic.css?v=def86cc0" />
<link rel="stylesheet" type="text/css" href="../../../_static/css/mbasic.css?v=957880af" />
<script src="../../../_static/documentation_options.js?v=71272d9f"></script>
<script src="../../../_static/doctools.js?v=9a2dae69"></script>
<script src="../../../_static/sphinx_highlight.js?v=dc90522c"></script>
<link rel="index" title="Index" href="../../../genindex.html" />
<link rel="search" title="Search" href="../../../search.html" />
</head><body>
<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 1.0.4 documentation</a> &#187;</li>
<li class="nav-item nav-item-1"><a href="../../index.html" accesskey="U">Module code</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">windows.debug.debugger</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="kn">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="kn">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.generated_def</span> <span class="k">as</span> <span class="nn">gdef</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="kn">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="kn">import</span> <span class="n">dbgprint</span>
<span class="kn">from</span> <span class="nn">windows</span> <span class="kn">import</span> <span class="n">winproxy</span>
<span class="kn">from</span> <span class="nn">windows.generated_def.winstructs</span> <span class="kn">import</span> <span class="o">*</span>
<span class="kn">from</span> <span class="nn">windows.generated_def</span> <span class="kn">import</span> <span class="n">windef</span>
<span class="kn">from</span> <span class="nn">.breakpoints</span> <span class="kn">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="kn">import</span> <span class="n">VectoredException</span>
<span class="kn">from</span> <span class="nn">windows.pycompat</span> <span class="kn">import</span> <span class="n">basestring</span>
<span class="n">PAGE_SIZE</span> <span class="o">=</span> <span class="mh">0x1000</span>
<span class="k">class</span> <span class="nc">DebuggerError</span><span class="p">(</span><span class="ne">Exception</span><span class="p">):</span>
<span class="k">pass</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">&#39;WatchedPage&#39;</span><span class="p">,</span> <span class="p">[</span><span class="s2">&quot;original_prot&quot;</span><span class="p">,</span> <span class="s2">&quot;bps&quot;</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="w"> </span><span class="sd">&quot;&quot;&quot;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>
<span class="sd"> &quot;&quot;&quot;</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="fm">__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="w"> </span><span class="sd">&quot;&quot;&quot;``target`` must be a debuggable :class:`WinProcess`.&quot;&quot;&quot;</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="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="bp">self</span><span class="o">.</span><span class="n">first_bp_encoutered</span> <span class="o">=</span> <span class="kc">False</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 &quot;\xcc&quot;</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] -&gt; [mem bp on the page]</span>
<span class="c1"># [start] -&gt; (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>
<span class="bp">self</span><span class="o">.</span><span class="n">_current_debug_event</span> <span class="o">=</span> <span class="kc">None</span></div>
<div class="viewcode-block" id="Debugger.attach">
<a class="viewcode-back" href="../../../debug.html#windows.debug.Debugger.attach">[docs]</a>
<span class="nd">@classmethod</span>
<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="w"> </span><span class="sd">&quot;&quot;&quot;attach to ``target`` (must be a :class:`WinProcess`)</span>
<span class="sd"> :rtype: :class:`Debugger`</span>
<span class="sd"> .. note::</span>
<span class="sd"> see :ref:`Debugger.attach sample &lt;sample_debugger_attach&gt;`&quot;&quot;&quot;</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="w"> </span><span class="sd">&quot;&quot;&quot;Detach from all debugged processes or process ``target``&quot;&quot;&quot;</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 -&gt; GC -&gt; CloseHandle -&gt; 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="nb">list</span><span class="p">(</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">&quot;Detach accept only WinProcess&quot;</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="nb">list</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="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">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">target</span><span class="o">.</span><span class="n">pid</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">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="c1"># Bug if CTRL+C and current_process changed ?</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">_current_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="bp">self</span><span class="o">.</span><span class="n">target</span> <span class="ow">and</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="w"> </span><span class="sd">&quot;&quot;&quot;Return ``True`` if current process have been detached by user callback&quot;&quot;&quot;</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>
<div class="viewcode-block" id="Debugger.debug">
<a class="viewcode-back" href="../../../debug.html#windows.debug.Debugger.debug">[docs]</a>
<span class="nd">@classmethod</span>
<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="w"> </span><span class="sd">&quot;&quot;&quot;Create a process and debug it.</span>
<span class="sd"> :rtype: :class:`Debugger`&quot;&quot;&quot;</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">gdef</span><span class="o">.</span><span class="n">DEBUG_EVENT</span><span class="p">()</span>
<span class="k">try</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">except</span> <span class="ne">KeyboardInterrupt</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
<span class="c1"># So we will go out of the loop because of a Ctrl+c</span>
<span class="c1"># BP trigger will not be called.</span>
<span class="c1"># So AT LEAST quit loop with a coherent context</span>
<span class="c1"># Fix thread PC if we just triggered a BP</span>
<span class="k">if</span> <span class="p">(</span><span class="n">debug_event</span><span class="o">.</span><span class="n">dwDebugEventCode</span> <span class="o">==</span> <span class="n">gdef</span><span class="o">.</span><span class="n">EXCEPTION_DEBUG_EVENT</span> <span class="ow">and</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="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">gdef</span><span class="o">.</span><span class="n">EXCEPTION_BREAKPOINT</span><span class="p">,</span> <span class="n">gdef</span><span class="o">.</span><span class="n">STATUS_WX86_BREAKPOINT</span><span class="p">]):</span>
<span class="c1"># This is a breakpoint: One of ours ?</span>
<span class="n">bp_addr</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="o">.</span><span class="n">ExceptionRecord</span><span class="o">.</span><span class="n">ExceptionAddress</span>
<span class="k">if</span> <span class="n">bp_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="n">debug_event</span><span class="o">.</span><span class="n">dwProcessId</span><span class="p">]:</span>
<span class="c1"># Leave the thread in a coherent state for detach</span>
<span class="c1"># Should it be done in detach ?</span>
<span class="c1"># And just stock the &quot;Interrupted debug_event&quot; here ?</span>
<span class="n">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="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="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">raise</span>
<span class="k">finally</span><span class="p">:</span> <span class="c1"># If user Ctrl+c -&gt; we could raise just at the return of WaitForDebugEvent</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_current_debug_event</span> <span class="o">=</span> <span class="n">debug_event</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="bp">self</span><span class="o">.</span><span class="n">current_thread</span><span class="p">:</span>
<span class="n">dbgprint</span><span class="p">(</span><span class="s2">&quot;Finishing event for TID &lt;</span><span class="si">{0}</span><span class="s2">&gt;&quot;</span><span class="o">.</span><span class="n">format</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="s2">&quot;DBG&quot;</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">dbgprint</span><span class="p">(</span><span class="s2">&quot;Finishing event&quot;</span><span class="p">,</span> <span class="s2">&quot;DBG&quot;</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">&#39;Unknow action : &lt;0&gt;&#39;</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="bp">self</span><span class="o">.</span><span class="n">_current_debug_event</span> <span class="o">=</span> <span class="kc">None</span>
<span class="k">def</span> <span class="nf">_add_exe_to_module_list</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">create_process_event</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;Add the intial exe file described by create_process_event to the list of module in the process&quot;&quot;&quot;</span>
<span class="n">exe_path</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">get_mapped_filename</span><span class="p">(</span><span class="n">create_process_event</span><span class="o">.</span><span class="n">lpBaseOfImage</span><span class="p">)</span>
<span class="n">exe_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">exe_path</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">exe_name</span><span class="o">.</span><span class="n">endswith</span><span class="p">(</span><span class="s2">&quot;.exe&quot;</span><span class="p">):</span>
<span class="n">exe_name</span> <span class="o">=</span> <span class="n">exe_name</span><span class="p">[:</span><span class="o">-</span><span class="nb">len</span><span class="p">(</span><span class="s2">&quot;.exe&quot;</span><span class="p">)]</span>
<span class="c1">#print(&quot;Exe name is {0}&quot;.format(exe_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">exe_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">create_process_event</span><span class="o">.</span><span class="n">lpBaseOfImage</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="c1">#self._setup_pending_breakpoints_load_dll(exe_name) # Already setup in _setup_pending_breakpoints_new_process</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="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">&quot;Resolving &lt;</span><span class="si">{0}</span><span class="s2">&gt; in &lt;</span><span class="si">{1}</span><span class="s2">&gt;&quot;</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">&quot;DBG&quot;</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">&quot;!&quot;</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">elif</span> <span class="n">target</span><span class="o">.</span><span class="n">is_wow_64</span> <span class="ow">and</span> <span class="n">dll</span> <span class="o">==</span> <span class="s2">&quot;ntdll&quot;</span> <span class="ow">and</span> <span class="s2">&quot;ntdll32&quot;</span> <span class="ow">in</span> <span class="n">modules</span><span class="p">:</span>
<span class="c1"># https://twitter.com/hakril/status/1555473886321549312</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="s2">&quot;ntdll32&quot;</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&#39;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">&quot;Error resolving &lt;</span><span class="si">{0}</span><span class="s2">&gt; in &lt;</span><span class="si">{1}</span><span class="s2">&gt;&quot;</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">&quot;DBG&quot;</span><span class="p">)</span>
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s2">&quot;Unknown API &lt;</span><span class="si">{0}</span><span class="s2">&gt; in DLL </span><span class="si">{1}</span><span class="s2">&quot;</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="n">target_addr</span> <span class="o">=</span> <span class="n">exports</span><span class="p">[</span><span class="n">api</span><span class="p">]</span>
<span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">target_addr</span><span class="p">,</span> <span class="n">basestring</span><span class="p">):</span>
<span class="n">target_string</span> <span class="o">=</span> <span class="n">target_addr</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s2">&quot;.&quot;</span><span class="p">,</span> <span class="s2">&quot;!&quot;</span><span class="p">)</span>
<span class="n">dbgprint</span><span class="p">(</span><span class="s2">&quot;&lt;</span><span class="si">{0}</span><span class="s2">&gt; is export proxy to &lt;</span><span class="si">{1}</span><span class="s2">&gt;&quot;</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_string</span><span class="p">),</span> <span class="s2">&quot;DBG&quot;</span><span class="p">)</span>
<span class="c1"># Possible infinite loop ?</span>
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_resolve</span><span class="p">(</span><span class="n">target_string</span><span class="p">,</span> <span class="n">target</span><span class="p">)</span>
<span class="k">return</span> <span class="n">target_addr</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">&quot;_setup_breakpoint_&quot;</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_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">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">&quot;Why is this here ? we use RF flags to pass HXBP&quot;</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">&quot;_restore_breakpoint_&quot;</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="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_process</span><span class="o">.</span><span class="n">pid</span><span class="p">]</span><span class="o">.</span><span class="n">clear</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">&quot;Cannot setup STANDARD_BP on </span><span class="si">{0}</span><span class="s2">&quot;</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="c1"># raise DebuggerError(&quot;Could not set breakpoint {0} at &lt;{1}&gt;&quot;.format(bp, bp.addr))</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">dbgprint</span><span class="p">(</span><span class="s2">&quot;Setting soft-BP at &lt;</span><span class="si">{0:#x}</span><span class="s2">&gt; in &lt;</span><span class="si">{1}</span><span class="s2">&gt;&quot;</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">&quot;DBG&quot;</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">_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">&quot;</span><span class="se">\xcc</span><span class="s2">&quot;</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">&quot;</span><span class="se">\xcc</span><span class="s2">&quot;</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">&quot;SETUP STANDARD_BP on </span><span class="si">{0}</span><span class="s2">&quot;</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(&quot;Setup {0} into {1}&quot;.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">&quot;SETUP HXBP_BP on </span><span class="si">{0}</span><span class="s2">&quot;</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">&quot;Cannot put </span><span class="si">{0}</span><span class="s2"> in </span><span class="si">{1}</span><span class="s2"> (DRx full)&quot;</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="c1"># Windows DebugCtl aliasing in DR7</span>
<span class="c1"># See https://www.codeproject.com/Articles/517466/Last-branch-records-and-branch-tracing</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">0</span> <span class="c1"># bit 8 of DR7 represents bit 0 of DebugCtl. This is the LBR bit. (last branch record, will explain)</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">0</span> <span class="c1"># bit 9 of DR7 represents bit 1 of DebugCtl. This is the BTF bit. (single-step on branches)</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">&quot;L&quot;</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">&quot;Dr&quot;</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="n">dbgprint</span><span class="p">(</span><span class="s2">&quot;Setting HXBP at &lt;</span><span class="si">{0:#x}</span><span class="s2">&gt; in &lt;</span><span class="si">{1}</span><span class="s2">&gt; (Dr</span><span class="si">{2}</span><span class="s2">)&quot;</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="n">empty_drx</span><span class="p">),</span> <span class="s2">&quot;DBG&quot;</span><span class="p">)</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">&quot;SETUP HXBP_BP on </span><span class="si">{0}</span><span class="s2">&quot;</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">&quot;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&quot;</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">&quot;L&quot;</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">&quot;Dr&quot;</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">&quot;R&quot;</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">&quot;WX&quot;</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">&quot;W&quot;</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">&quot;X&quot;</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">target</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">has_DEP</span> <span class="o">=</span> <span class="kc">True</span>
<span class="k">elif</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="kc">False</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">&quot;Unexpected set of event for Membp: </span><span class="si">{0}</span><span class="s2">&quot;</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">&gt;&gt;</span> <span class="mi">12</span><span class="p">)</span> <span class="o">&lt;&lt;</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="k">for</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="ow">in</span> <span class="n">bp</span><span class="o">.</span><span class="n">_reput_pages</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">page_prot</span><span class="p">,</span> <span class="kc">None</span><span class="p">)</span>
<span class="k">del</span> <span class="n">bp</span><span class="o">.</span><span class="n">_reput_pages</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">&gt;&gt;</span> <span class="mi">12</span><span class="p">)</span> <span class="o">&lt;&lt;</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="k">try</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">except</span> <span class="ne">WindowsError</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
<span class="c1"># TODO</span>
<span class="c1"># What should we do if the virtual protect fail on a Non-Free page ?</span>
<span class="c1"># It may be because the page was dealloc + map as a view..</span>
<span class="c1"># For now: keep the page as-is</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">target</span><span class="o">.</span><span class="n">query_memory</span><span class="p">(</span><span class="n">page_addr</span><span class="p">)</span><span class="o">.</span><span class="n">State</span> <span class="o">==</span> <span class="n">MEM_FREE</span><span class="p">:</span>
<span class="k">pass</span>
<span class="c1"># If page is MEM_FREE ignore the error</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="k">try</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">except</span> <span class="ne">Exception</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
<span class="c1"># if not target.query_memory(page_addr).State == MEM_FREE:</span>
<span class="c1"># raise</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">bp</span><span class="o">.</span><span class="n">on_error</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">page_addr</span><span class="p">)</span>
<span class="c1"># TODO: handle case were it is mem-free ?</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">&quot;_setup_breakpoint_&quot;</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">&quot;_setup_breakpoint_&quot;</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">&quot;_setup_breakpoint_&quot;</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">&quot;_setup_breakpoint_&quot;</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">&quot;_setup_breakpoint_&quot;</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">&quot;!&quot;</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 == &quot;*&quot; or target_dll == dll_name:</span>
<span class="k">if</span> <span class="p">(</span><span class="n">target_dll</span> <span class="o">==</span> <span class="n">dll_name</span> <span class="ow">or</span>
<span class="c1"># https://twitter.com/hakril/status/1555473886321549312</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">is_wow_64</span> <span class="ow">and</span> <span class="n">target_dll</span> <span class="o">==</span> <span class="s2">&quot;ntdll&quot;</span> <span class="ow">and</span> <span class="n">dll_name</span> <span class="o">==</span> <span class="s2">&quot;ntdll32&quot;</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">&quot;_setup_breakpoint_&quot;</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">&quot;!&quot;</span><span class="p">)[</span><span class="mi">0</span><span class="p">]</span>
<span class="k">if</span> <span class="p">(</span><span class="n">target_dll</span> <span class="o">==</span> <span class="n">dll_name</span> <span class="ow">or</span>
<span class="c1"># https://twitter.com/hakril/status/1555473886321549312</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">is_wow_64</span> <span class="ow">and</span> <span class="n">target_dll</span> <span class="o">==</span> <span class="s2">&quot;ntdll&quot;</span> <span class="ow">and</span> <span class="n">dll_name</span> <span class="o">==</span> <span class="s2">&quot;ntdll32&quot;</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">&quot;_setup_breakpoint_&quot;</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">&quot;!&quot;</span><span class="p">)[</span><span class="mi">0</span><span class="p">]</span>
<span class="k">if</span> <span class="p">(</span><span class="n">target_dll</span> <span class="o">==</span> <span class="n">dll_name</span> <span class="ow">or</span>
<span class="c1"># https://twitter.com/hakril/status/1555473886321549312</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">is_wow_64</span> <span class="ow">and</span> <span class="n">target_dll</span> <span class="o">==</span> <span class="s2">&quot;ntdll&quot;</span> <span class="ow">and</span> <span class="n">dll_name</span> <span class="o">==</span> <span class="s2">&quot;ntdll32&quot;</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">&quot;_setup_breakpoint_&quot;</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">&lt;&lt;</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">process</span><span class="o">.</span><span class="n">pid</span><span class="p">]</span><span class="o">.</span><span class="n">add</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_pages</span><span class="o">.</span><span class="n">append</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">cp</span><span class="o">.</span><span class="n">pid</span><span class="p">]</span><span class="o">.</span><span class="n">add</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">&quot;dwDebugEventCode = </span><span class="si">{0}</span><span class="s2">&quot;</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="n">YOLO</span> <span class="o">=</span> <span class="kc">False</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">context</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="n">dbgprint</span><span class="p">(</span><span class="s2">&quot;Single step as begin of _handle_exception_breakpoint&quot;</span><span class="p">,</span> <span class="s2">&quot;DBG&quot;</span><span class="p">)</span>
<span class="c1"># import pdb;pdb.set_trace()</span>
<span class="n">YOLO</span> <span class="o">=</span> <span class="kc">True</span>
<span class="c1"># Sub-method _do_setup() ?</span>
<span class="n">dbg_has_setup</span> <span class="o">=</span> <span class="kc">None</span>
<span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">first_bp_encoutered</span><span class="p">:</span>
<span class="n">dbg_has_setup</span> <span class="o">=</span> <span class="ow">not</span> <span class="nb">getattr</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">on_setup</span><span class="p">,</span> <span class="s2">&quot;_abstract_on_setup_&quot;</span><span class="p">,</span> <span class="kc">False</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">first_bp_encoutered</span> <span class="o">=</span> <span class="kc">True</span>
<span class="k">if</span> <span class="n">dbg_has_setup</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_setup</span><span class="p">()</span> <span class="c1"># Handle single-step here ?</span>
<span class="c1"># Check killed in action ?</span>
<span class="c1"># What if setup + BP object() ?</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="ow">and</span> <span class="ow">not</span> <span class="n">YOLO</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="n">dbgprint</span><span class="p">(</span><span class="s2">&quot;Someone ask for an explicit Single step&quot;</span><span class="p">,</span> <span class="s2">&quot;DBG&quot;</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="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">if</span> <span class="n">dbg_has_setup</span><span class="p">:</span> <span class="c1"># setup() was called on this BP-event: no on_exception()</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">_breakpoint_to_reput</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">current_process</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">_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">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="n">dbgprint</span><span class="p">(</span><span class="s2">&quot;Someone ask for an explicit Single step - 7&quot;</span><span class="p">,</span> <span class="s2">&quot;DBG&quot;</span><span class="p">)</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&#39;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="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="n">dbgprint</span><span class="p">(</span><span class="s2">&quot;Someone ask for an explicit Single step - 2&quot;</span><span class="p">,</span> <span class="s2">&quot;DBG&quot;</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">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">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="n">dbgprint</span><span class="p">(</span><span class="s2">&quot;Someone ask for an explicit Single step - 3&quot;</span><span class="p">,</span> <span class="s2">&quot;DBG&quot;</span><span class="p">)</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">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="n">dbgprint</span><span class="p">(</span><span class="s2">&quot;Someone ask for an explicit Single step - 4&quot;</span><span class="p">,</span> <span class="s2">&quot;DBG&quot;</span><span class="p">)</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">&quot;RWX&quot;</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="n">dbgprint</span><span class="p">(</span><span class="s2">&quot;Handling access_violation at pc=</span><span class="si">{0:#x}</span><span class="s2"> addr=</span><span class="si">{1:#x}</span><span class="s2">&quot;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">pc_addr</span><span class="p">,</span> <span class="n">fault_addr</span><span class="p">),</span> <span class="s2">&quot;DBG&quot;</span><span class="p">)</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">&gt;&gt;</span> <span class="mi">12</span><span class="p">)</span> <span class="o">&lt;&lt;</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="c1"># We may have setup the &quot;EEFlags.TF&quot; ourself if the membreakpoint triggered twice on the same instruction</span>
<span class="c1"># Ex: write on two pages handled by our breakpoint (unaligned write on 0xfff-0x1000)</span>
<span class="n">originalctx</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="n">original_tf</span> <span class="o">=</span> <span class="n">originalctx</span><span class="o">.</span><span class="n">EEFlags</span><span class="o">.</span><span class="n">TF</span>
<span class="c1"># Temporary disable EEFlags.TF to see if user callback explicit ask for it</span>
<span class="n">originalctx</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="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">originalctx</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="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="c1"># Update explicit trigger based on new value of 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="c1"># Reupdate the real EEFlags.TF based on its current value and the original one</span>
<span class="k">if</span> <span class="n">original_tf</span> <span class="o">!=</span> <span class="mi">0</span> <span class="ow">and</span> <span class="ow">not</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="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">single_step</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="n">dbgprint</span><span class="p">(</span><span class="s2">&quot;Someone ask for an explicit Single step - 5&quot;</span><span class="p">,</span> <span class="s2">&quot;DBG&quot;</span><span class="p">)</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="w"> </span><span class="sd">&quot;&quot;&quot;Handle EXCEPTION_DEBUG_EVENT&quot;&quot;&quot;</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="n">dbgprint</span><span class="p">(</span><span class="s2">&quot;Handle exception as breakpoint in TID </span><span class="si">{0}</span><span class="s2">&quot;</span><span class="o">.</span><span class="n">format</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="s2">&quot;DBG&quot;</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="n">dbgprint</span><span class="p">(</span><span class="s2">&quot;Handle exception as single step in TID </span><span class="si">{0}</span><span class="s2">&quot;</span><span class="o">.</span><span class="n">format</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="s2">&quot;DBG&quot;</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="n">dbgprint</span><span class="p">(</span><span class="s2">&quot;Handle exception as access_violation in TID </span><span class="si">{0}</span><span class="s2">&quot;</span><span class="o">.</span><span class="n">format</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="s2">&quot;DBG&quot;</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">dbgprint</span><span class="p">(</span><span class="s2">&quot;Handle exception as on_exception&quot;</span><span class="o">.</span><span class="n">format</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="s2">&quot;DBG&quot;</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">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="n">dbgprint</span><span class="p">(</span><span class="s2">&quot;Someone ask for an explicit Single step - 6&quot;</span><span class="p">,</span> <span class="s2">&quot;DBG&quot;</span><span class="p">)</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">&quot;&quot;</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">&quot;64&quot;</span>
<span class="n">addr</span> <span class="o">=</span> <span class="kc">None</span>
<span class="k">if</span> <span class="n">load_dll</span><span class="o">.</span><span class="n">lpImageName</span><span class="p">:</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="k">pass</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="w"> </span><span class="sd">&quot;&quot;&quot;Handle CREATE_PROCESS_DEBUG_EVENT&quot;&quot;&quot;</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">&quot; Got PROC handle </span><span class="si">{0:#x}</span><span class="s2">&quot;</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">&quot;HANDLE&quot;</span><span class="p">)</span>
<span class="n">dbgprint</span><span class="p">(</span><span class="s2">&quot; PROC handle duplicated: </span><span class="si">{0:#x}</span><span class="s2">&quot;</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">&quot;HANDLE&quot;</span><span class="p">)</span>
<span class="n">dbgprint</span><span class="p">(</span><span class="s2">&quot; Got THREAD handle </span><span class="si">{0:#x}</span><span class="s2">&quot;</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">&quot;HANDLE&quot;</span><span class="p">)</span>
<span class="n">dbgprint</span><span class="p">(</span><span class="s2">&quot; THREAD handle duplicated: </span><span class="si">{0:#x}</span><span class="s2">&quot;</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">&quot;HANDLE&quot;</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="n">dbgprint</span><span class="p">(</span><span class="s2">&quot;New process: </span><span class="si">{0}</span><span class="s2">&quot;</span><span class="o">.</span><span class="n">format</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="s2">&quot;DBG&quot;</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">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">_breakpoint_to_reput</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="nb">set</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">_internal_on_create_process</span><span class="p">(</span><span class="n">create_process</span><span class="p">)</span> <span class="c1"># Allow hook for symbol-debugger</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">_add_exe_to_module_list</span><span class="p">(</span><span class="n">create_process</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">try</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="k">finally</span><span class="p">:</span>
<span class="k">if</span> <span class="n">create_process</span><span class="o">.</span><span class="n">hFile</span><span class="p">:</span>
<span class="n">winproxy</span><span class="o">.</span><span class="n">CloseHandle</span><span class="p">(</span><span class="n">create_process</span><span class="o">.</span><span class="n">hFile</span><span class="p">)</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="w"> </span><span class="sd">&quot;&quot;&quot;Handle EXIT_PROCESS_DEBUG_EVENT&quot;&quot;&quot;</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_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">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="bp">self</span><span class="o">.</span><span class="n">target</span> <span class="ow">and</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="w"> </span><span class="sd">&quot;&quot;&quot;Handle CREATE_THREAD_DEBUG_EVENT&quot;&quot;&quot;</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="n">new_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="n">new_thread</span><span class="o">.</span><span class="n">tid</span><span class="p">]</span> <span class="o">=</span> <span class="n">new_thread</span>
<span class="c1"># The new thread is on the thread pool: we can now update the debugger state</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">_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">_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="w"> </span><span class="sd">&quot;&quot;&quot;Handle EXIT_THREAD_DEBUG_EVENT&quot;&quot;&quot;</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">return</span> <span class="n">retvalue</span>
<span class="k">def</span> <span class="nf">_internal_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="k">return</span> <span class="kc">None</span>
<span class="k">def</span> <span class="nf">_internal_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="k">return</span> <span class="kc">None</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="w"> </span><span class="sd">&quot;&quot;&quot;Handle LOAD_DLL_DEBUG_EVENT&quot;&quot;&quot;</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">&quot;.dll&quot;</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="c1"># Mais c&#39;est debile..</span>
<span class="c1"># Si j&#39;ai ntdll et ntdll64: les deux vont avoir le meme nom..</span>
<span class="c1"># A changer sur Win11 ou ntdll est remontee en tant que ntdll32.dll</span>
<span class="c1"># https://twitter.com/hakril/status/1555473886321549312</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">&quot;.dll64&quot;</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">&quot;64&quot;</span> <span class="c1"># Crade..</span>
<span class="c1">#print(&quot;Load {0} -&gt; {1}&quot;.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">_internal_on_load_dll</span><span class="p">(</span><span class="n">load_dll</span><span class="p">)</span> <span class="c1"># Allow hook for symbol-debugger</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">try</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">finally</span><span class="p">:</span>
<span class="k">if</span> <span class="n">load_dll</span><span class="o">.</span><span class="n">hFile</span><span class="p">:</span>
<span class="n">winproxy</span><span class="o">.</span><span class="n">CloseHandle</span><span class="p">(</span><span class="n">load_dll</span><span class="o">.</span><span class="n">hFile</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="w"> </span><span class="sd">&quot;&quot;&quot;Handle UNLOAD_DLL_DEBUG_EVENT&quot;&quot;&quot;</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="w"> </span><span class="sd">&quot;&quot;&quot;Handle OUTPUT_DEBUG_STRING_EVENT&quot;&quot;&quot;</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="w"> </span><span class="sd">&quot;&quot;&quot;Handle RIP_EVENT&quot;&quot;&quot;</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="w"> </span><span class="sd">&quot;&quot;&quot;Debugging loop: handle event / dispatch to breakpoint. Returns when all targets are dead/detached&quot;&quot;&quot;</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="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&#39;s not killed, it&#39;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="w"> </span><span class="sd">&quot;&quot;&quot;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"> &quot;&quot;&quot;</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">&quot;addr&quot;</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">&quot;Breakpoing should have addr attribute or function should receive explicite addr parameter&quot;</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">&quot;Given &lt;addr|type&gt; by parameters but BP object have them&quot;</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="nb">list</span><span class="p">(</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="nb">list</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="n">values</span><span class="p">()):</span>
<span class="c1"># if target == self.target: # 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="c1"># else:</span>
<span class="c1"># raise ValueError(&quot;Unknown target {0}&quot;.format(target))</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="w"> </span><span class="sd">&quot;&quot;&quot;Delete a breakpoint, if targets is ``None``: delete it from all targets&quot;&quot;&quot;</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">&quot;_remove_breakpoint_&quot;</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="w"> </span><span class="sd">&quot;&quot;&quot;Make the ``current_thread`` ``single_step``. ``Debugger.on_single_step`` will be called after that&quot;&quot;&quot;</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="w"> </span><span class="sd">&quot;&quot;&quot;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"> &quot;&quot;&quot;</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">&gt;&gt;</span> <span class="mi">12</span><span class="p">)</span> <span class="o">&lt;&lt;</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">&lt;=</span> <span class="n">addr</span> <span class="o">&lt;</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="w"> </span><span class="sd">&quot;&quot;&quot;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`&quot;&quot;&quot;</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="k">try</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="k">except</span> <span class="ne">WindowsError</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
<span class="c1"># Check if page have been unmapped</span>
<span class="c1"># print(&quot;disable_all_memory_breakpoints failed on page {0:#x} in state {1:#x}&quot;.format(page_addr, target.query_memory(page_addr).State))</span>
<span class="c1"># if not target.query_memory(page_addr).State == MEM_FREE:</span>
<span class="c1"># import pdb;pdb.set_trace()</span>
<span class="c1"># raise</span>
<span class="c1"># If page have been unmap, warn the concerned Breakpoints.</span>
<span class="k">for</span> <span class="n">bp</span> <span class="ow">in</span> <span class="n">watched_page</span><span class="o">.</span><span class="n">bps</span><span class="p">:</span>
<span class="c1"># TODO: Document</span>
<span class="n">bp</span><span class="o">.</span><span class="n">on_error</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">page_addr</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="w"> </span><span class="sd">&quot;&quot;&quot;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`&quot;&quot;&quot;</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>
<div class="viewcode-block" id="Debugger.DisabledMemoryBreakpoint">
<a class="viewcode-back" href="../../../debug.html#windows.debug.Debugger.DisabledMemoryBreakpoint">[docs]</a>
<span class="nd">@contextmanager</span>
<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="w"> </span><span class="sd">&quot;&quot;&quot;A context-manager that disable all memory breakpoints and restore them on exit&quot;&quot;&quot;</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="w"> </span><span class="sd">&quot;&quot;&quot;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&quot;&quot;&quot;</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>
<div class="viewcode-block" id="Debugger.kill_on_exit">
<a class="viewcode-back" href="../../../debug.html#windows.debug.Debugger.kill_on_exit">[docs]</a>
<span class="nd">@staticmethod</span>
<span class="k">def</span> <span class="nf">kill_on_exit</span><span class="p">(</span><span class="n">choice</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;If set to True(default in Windows) will kill all attached process on thread exit.</span>
<span class="sd"> Otherwise, the thread detaches from all processes being debugged on exit.</span>
<span class="sd"> See: https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-debugsetprocesskillonexit</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">return</span> <span class="n">windows</span><span class="o">.</span><span class="n">winproxy</span><span class="o">.</span><span class="n">DebugSetProcessKillOnExit</span><span class="p">(</span><span class="n">choice</span><span class="p">)</span></div>
<span class="c1"># Public callback</span>
<div class="viewcode-block" id="Debugger.on_setup">
<a class="viewcode-back" href="../../../debug.html#windows.debug.Debugger.on_setup">[docs]</a>
<span class="k">def</span> <span class="nf">on_setup</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;Called on the first breakpoint event occuring in the debugger.</span>
<span class="sd"> This callback allow to setup hook / interact with the debugee when ready:</span>
<span class="sd"> - If :func:`on_setup` is overriden by a subclass it will be called and :func:`on_exception` will NOT be called for this event (first BP).</span>
<span class="sd"> - If :func:`on_setup` is not defined the first BP will trigger an :func:`on_exception`.</span>
<span class="sd"> .. note::</span>
<span class="sd"> see sample :ref:`sample_debugger_on_setup`</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">return</span> <span class="kc">None</span></div>
<span class="c1"># Help detect if on_setup was override</span>
<span class="n">on_setup</span><span class="o">.</span><span class="n">_abstract_on_setup_</span> <span class="o">=</span> <span class="kc">True</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="w"> </span><span class="sd">&quot;&quot;&quot;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"> &quot;&quot;&quot;</span>
<span class="n">dbgprint</span><span class="p">(</span><span class="s2">&quot;Exception: </span><span class="si">{0}</span><span class="s2"> at &quot;</span><span class="o">.</span><span class="n">format</span><span class="p">(</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="p">,</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="p">),</span> <span class="s2">&quot;DBG&quot;</span><span class="p">)</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="w"> </span><span class="sd">&quot;&quot;&quot;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"> &quot;&quot;&quot;</span>
<span class="k">raise</span> <span class="ne">NotImplementedError</span><span class="p">(</span><span class="s2">&quot;Debugger that explicitly single step should implement &lt;on_single_step&gt;&quot;</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="w"> </span><span class="sd">&quot;&quot;&quot;Called on create_process event</span>
<span class="sd"> :param CREATE_PROCESS_DEBUG_INFO create_process:&quot;&quot;&quot;</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="w"> </span><span class="sd">&quot;&quot;&quot;Called on exit_process event</span>
<span class="sd"> :param EXIT_PROCESS_DEBUG_INFO exit_process:&quot;&quot;&quot;</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="w"> </span><span class="sd">&quot;&quot;&quot;Called on create_thread event</span>
<span class="sd"> :param CREATE_THREAD_DEBUG_INFO create_thread:&quot;&quot;&quot;</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="w"> </span><span class="sd">&quot;&quot;&quot;Called on exit_thread event</span>
<span class="sd"> :param EXIT_THREAD_DEBUG_INFO exit_thread:&quot;&quot;&quot;</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="w"> </span><span class="sd">&quot;&quot;&quot;Called on load_dll event</span>
<span class="sd"> :param LOAD_DLL_DEBUG_INFO load_dll:&quot;&quot;&quot;</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="w"> </span><span class="sd">&quot;&quot;&quot;Called on unload_dll event</span>
<span class="sd"> :param UNLOAD_DLL_DEBUG_INFO unload_dll:&quot;&quot;&quot;</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="w"> </span><span class="sd">&quot;&quot;&quot;Called on debug_string event</span>
<span class="sd"> :param OUTPUT_DEBUG_STRING_INFO debug_string:&quot;&quot;&quot;</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="w"> </span><span class="sd">&quot;&quot;&quot;Called on rip_info event</span>
<span class="sd"> :param RIP_INFO rip_info:&quot;&quot;&quot;</span>
<span class="k">pass</span></div>
</div>
</pre></div>
<div class="clearer"></div>
</div>
</div>
</div>
<div class="sphinxsidebar" role="navigation" aria-label="main navigation">
<div class="sphinxsidebarwrapper">
<search id="searchbox" style="display: none" role="search">
<h3 id="searchlabel">Quick search</h3>
<div class="searchformwrapper">
<form class="search" action="../../../search.html" method="get">
<input type="text" name="q" aria-labelledby="searchlabel" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"/>
<input type="submit" value="Go" />
</form>
</div>
</search>
<script>document.getElementById('searchbox').style.display = "block"</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 1.0.4 documentation</a> &#187;</li>
<li class="nav-item nav-item-1"><a href="../../index.html" >Module code</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">windows.debug.debugger</a></li>
</ul>
</div>
<div class="footer" role="contentinfo">
&#169; Copyright 2015-2020, Clement Rouault.
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 7.3.7.
</div>
</body>
</html>