mirror of
https://github.com/hakril/PythonForWindows
synced 2026-06-08 14:31:45 +00:00
Writing samples and doc !
This commit is contained in:
@@ -0,0 +1,46 @@
|
||||
:mod:`windows.debug` -- Debugging
|
||||
=================================
|
||||
|
||||
.. module:: windows.debug
|
||||
|
||||
.. note::
|
||||
|
||||
See sample :ref:`sample_debugger`
|
||||
|
||||
:class:`Debugger`
|
||||
"""""""""""""""""
|
||||
|
||||
The :class:`Debugger` is the base class to perform the debugging of a remote process.
|
||||
The :class:`Debugger` have some functions called on given event that can be implemented by subclasses.
|
||||
|
||||
.. autoclass:: Debugger
|
||||
:members:
|
||||
|
||||
.. automethod:: __init__
|
||||
|
||||
|
||||
|
||||
:class:`Breakpoint`
|
||||
"""""""""""""""""""
|
||||
|
||||
Standard breakpoints types expect an address as argument.
|
||||
|
||||
An address can be:
|
||||
|
||||
* An :class:`int`
|
||||
* A :class:`str` of form (breakpoint will be put when ``DLL`` is loaded):
|
||||
|
||||
* ``"DLL!ApiName"``
|
||||
* ``"DLL!Offset"`` where offset is a int ("16", "0x10", ..)
|
||||
|
||||
|
||||
When a breakpoint is hit, its ``trigger`` function is called with the debugger and a
|
||||
``DEBUG_EXECEPTION_EVENT`` structure as argument.
|
||||
|
||||
|
||||
.. autoclass:: Breakpoint
|
||||
:members:
|
||||
|
||||
.. autoclass:: HXBreakpoint
|
||||
:members:
|
||||
:inherited-members:
|
||||
@@ -0,0 +1,96 @@
|
||||
Exception and Context related structures
|
||||
========================================
|
||||
|
||||
.. module:: windows.exception
|
||||
|
||||
|
||||
This module regroups all the Exception/Context related structures and functions.
|
||||
Most of the structures are the Windows structure with a prefix ``E`` (For enhanced)
|
||||
|
||||
Those structure have the same fields that the normal windows ones but its types might vary for a simpler use.
|
||||
|
||||
|
||||
This module also define the decorator :func:`VectoredException` which allows to play with ``Vectored Exception Handler`` in Python
|
||||
See sample :ref:`sample_vectoredexception`
|
||||
|
||||
Exception Records
|
||||
'''''''''''''''''
|
||||
|
||||
.. autoclass:: EEXCEPTION_RECORD
|
||||
:members:
|
||||
:inherited-members:
|
||||
|
||||
.. autoclass:: EEXCEPTION_RECORD32
|
||||
:inherited-members:
|
||||
|
||||
.. autoclass:: EEXCEPTION_RECORD64
|
||||
:members:
|
||||
:inherited-members:
|
||||
|
||||
EXCEPTION DEBUG INFO
|
||||
''''''''''''''''''''
|
||||
|
||||
.. autoclass:: EEXCEPTION_DEBUG_INFO32
|
||||
:members:
|
||||
:inherited-members:
|
||||
|
||||
.. data:: ExceptionRecord
|
||||
|
||||
:type: :class:`EEXCEPTION_RECORD32`
|
||||
|
||||
|
||||
.. autoclass:: EEXCEPTION_DEBUG_INFO64
|
||||
:members:
|
||||
:inherited-members:
|
||||
|
||||
.. data:: ExceptionRecord
|
||||
|
||||
:type: :class:`EEXCEPTION_RECORD64`
|
||||
|
||||
Context
|
||||
'''''''
|
||||
|
||||
.. autoclass:: ECONTEXT32
|
||||
:members:
|
||||
:inherited-members:
|
||||
|
||||
.. autoclass:: ECONTEXTWOW64
|
||||
:members:
|
||||
:inherited-members:
|
||||
|
||||
.. autoclass:: ECONTEXT64
|
||||
:members:
|
||||
:inherited-members:
|
||||
|
||||
.. autoclass:: EEflags
|
||||
:members:
|
||||
|
||||
.. autoclass:: EDr7
|
||||
:members:
|
||||
|
||||
EXCEPTION POINTERS
|
||||
''''''''''''''''''
|
||||
|
||||
.. autoclass:: EEXCEPTION_POINTERS
|
||||
:members:
|
||||
|
||||
.. data:: ExceptionRecord
|
||||
|
||||
:type: POINTER to :class:`EEXCEPTION_RECORD`
|
||||
|
||||
.. data:: ContextRecord
|
||||
|
||||
:type: POINTER to :class:`ECONTEXT32` or :class:`ECONTEXT64`
|
||||
|
||||
|
||||
.. _vectoredexception:
|
||||
|
||||
Vectored Exception
|
||||
''''''''''''''''''
|
||||
|
||||
.. note::
|
||||
|
||||
See sample :ref:`sample_vectoredexception`
|
||||
|
||||
.. autoclass:: VectoredException
|
||||
:members:
|
||||
@@ -4,7 +4,7 @@
|
||||
contain the root `toctree` directive.
|
||||
|
||||
Welcome to PythonForWindows's documentation!
|
||||
=====================================
|
||||
============================================
|
||||
|
||||
Contents:
|
||||
|
||||
@@ -17,6 +17,7 @@ Contents:
|
||||
native_exec.rst
|
||||
winproxy.rst
|
||||
utils.rst
|
||||
debug.rst
|
||||
iat_hook.rst
|
||||
wip.rst
|
||||
internals.rst
|
||||
|
||||
@@ -181,3 +181,56 @@ Demo::
|
||||
|
||||
|
||||
|
||||
:mod:`windows.native_exec.nativeutils` -- Native utility functions
|
||||
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||
|
||||
.. module:: windows.native_exec.nativeutils
|
||||
|
||||
This module contains some native-code functions that can be used for various purposes.
|
||||
Each function export a label that allow another :class:`MultipleInstr` to call the code of the function.
|
||||
|
||||
The current functions are:
|
||||
|
||||
* ``StrlenW64`` A 64bits wide-string STRLEN (``Label(":FUNC_STRLENW64")``)
|
||||
* ``StrlenA64`` A 64bits ASCII STRLEN (``Label(":FUNC_STRLENA64")``)
|
||||
* ``GetProcAddress64`` A 64bits export resolver (``Label(":FUNC_GETPROCADDRESS64")``)
|
||||
|
||||
* Arg1: The DLL (wstring)
|
||||
* Arg2: The API (string)
|
||||
* Return value:
|
||||
|
||||
* 0xfffffffffffffffe if the DLL is not found
|
||||
* 0xffffffffffffffff if the API is not found
|
||||
* The address of the function
|
||||
|
||||
* ``StrlenW32`` A 32bits wide-string STRLEN (``Label(":FUNC_STRLENW32")``)
|
||||
* ``StrlenA32`` A 32bits ASCII STRLEN (``Label(":FUNC_STRLENA32")``)
|
||||
* ``GetProcAddress32`` A 32bits export resolver (``Label(":FUNC_GETPROCADDRESS32")``)
|
||||
|
||||
* Arg1: The DLL (wstring)
|
||||
* Arg2: The API (string)
|
||||
* Return value:
|
||||
|
||||
* 0xfffffffe if the DLL is not found
|
||||
* 0xffffffff if the API is not found
|
||||
* The address of the function
|
||||
|
||||
To use those functions in a :class:`MultipleInstr` just call the label in your code and append the function at
|
||||
the end of your :class:`MultipleInstr`
|
||||
|
||||
|
||||
Example::
|
||||
|
||||
RemoteManualLoadLibray = x86.MultipleInstr()
|
||||
|
||||
RemoteManualLoadLibray += x86.Mov("ECX", x86.mem("[ESP + 4]"))
|
||||
RemoteManualLoadLibray += x86.Push(x86.mem("[ECX + 4]"))
|
||||
RemoteManualLoadLibray += x86.Push(x86.mem("[ECX]"))
|
||||
RemoteManualLoadLibray += x86.Call(":FUNC_GETPROCADDRESS32")
|
||||
RemoteManualLoadLibray += x86.Push(x86.mem("[ECX + 8]"))
|
||||
RemoteManualLoadLibray += x86.Call("EAX") # LoadLibrary
|
||||
RemoteManualLoadLibray += x86.Pop("ECX")
|
||||
RemoteManualLoadLibray += x86.Pop("ECX")
|
||||
RemoteManualLoadLibray += x86.Ret()
|
||||
|
||||
RemoteManualLoadLibray += GetProcAddress32
|
||||
@@ -50,6 +50,13 @@ WinThread
|
||||
:show-inheritance:
|
||||
:inherited-members:
|
||||
|
||||
Token
|
||||
'''''
|
||||
|
||||
.. autoclass:: Token
|
||||
:members:
|
||||
:inherited-members:
|
||||
|
||||
|
||||
PEB Exploration
|
||||
"""""""""""""""
|
||||
|
||||
@@ -188,3 +188,97 @@ Output::
|
||||
...
|
||||
KeyValue(name='PathName', value=u'C:\\Windows', type=1)]
|
||||
registered owner = <KeyValue(name='RegisteredOwner', value=u'hakril', type=1)>
|
||||
|
||||
|
||||
.. _sample_vectoredexception:
|
||||
|
||||
:func:`VectoredException`
|
||||
"""""""""""""""""""""""""
|
||||
|
||||
In local process
|
||||
''''''''''''''''
|
||||
|
||||
.. literalinclude:: ..\..\samples\veh_segv.py
|
||||
|
||||
Output::
|
||||
|
||||
(cmd λ) python.exe veh_segv.py
|
||||
Protected page is at <0x1db0000>
|
||||
Setting page protection to <PAGE_NOACCESS>
|
||||
|
||||
==Entry of VEH handler==
|
||||
Instr at 0x1d1ab574 accessed to addr 0x1db0000
|
||||
Resetting page protection to <PAGE_READWRITE>
|
||||
==Entry of VEH handler==
|
||||
Exception of type EXCEPTION_SINGLE_STEP(0x80000004L)
|
||||
Resetting page protection to <PAGE_NOACCESS>
|
||||
Value 1 read
|
||||
|
||||
==Entry of VEH handler==
|
||||
Instr at 0x1d1ab574 accessed to addr 0x1db0010
|
||||
Resetting page protection to <PAGE_READWRITE>
|
||||
==Entry of VEH handler==
|
||||
Exception of type EXCEPTION_SINGLE_STEP(0x80000004L)
|
||||
Resetting page protection to <PAGE_NOACCESS>
|
||||
Value 2 read
|
||||
|
||||
|
||||
In remote process
|
||||
'''''''''''''''''
|
||||
|
||||
.. literalinclude:: ..\..\samples\remote_veh_segv.py
|
||||
|
||||
Output::
|
||||
|
||||
(cmd λ) python .exe.\samples\remote_veh_segv.py
|
||||
(In another console)
|
||||
|
||||
Tracing execution in module: <gdi32.dll>
|
||||
Protected page is at 0x7ffa3c700000L
|
||||
|
||||
Instr at 0x7ffa3c70f0f0L accessed to addr 0x7ffa3c70f0f0L (gdi32.dll)
|
||||
Exception of type EXCEPTION_SINGLE_STEP(0x80000004L)
|
||||
Resetting page protection to <PAGE_READWRITE>
|
||||
|
||||
Instr at 0x7ffa3c70f0f5L accessed to addr 0x7ffa3c70f0f5L (gdi32.dll)
|
||||
Exception of type EXCEPTION_SINGLE_STEP(0x80000004L)
|
||||
Resetting page protection to <PAGE_READWRITE>
|
||||
|
||||
Instr at 0x7ffa3c70f0faL accessed to addr 0x7ffa3c70f0faL (gdi32.dll)
|
||||
Exception of type EXCEPTION_SINGLE_STEP(0x80000004L)
|
||||
Resetting page protection to <PAGE_READWRITE>
|
||||
|
||||
Instr at 0x7ffa3c70f0ffL accessed to addr 0x7ffa3c70f0ffL (gdi32.dll)
|
||||
Exception of type EXCEPTION_SINGLE_STEP(0x80000004L)
|
||||
Resetting page protection to <PAGE_READWRITE>
|
||||
|
||||
Instr at 0x7ffa3c70f100L accessed to addr 0x7ffa3c70f100L (gdi32.dll)
|
||||
No more tracing !
|
||||
|
||||
|
||||
.. _sample_debugger:
|
||||
|
||||
Debugging
|
||||
"""""""""
|
||||
|
||||
.. literalinclude:: ..\..\samples\debugger.py
|
||||
|
||||
Ouput::
|
||||
|
||||
(cmd λ) python.exe .\samples\debugger.py
|
||||
Loading <KERNEL32.DLL>
|
||||
Got exception EXCEPTION_BREAKPOINT(0x80000003L) at 0x77a73bad
|
||||
Loading <C:\Windows\system32\IMM32.DLL>
|
||||
Loading <C:\Windows\system32\uxtheme.dll>
|
||||
Loading <C:\Windows\system32\uxtheme.dll>
|
||||
Loading <C:\Windows\system32\uxtheme.dll>
|
||||
Loading <C:\Windows\system32\uxtheme.dll>
|
||||
Loading <kernel32.dll>
|
||||
Loading <C:\Windows\WinSxS\x86_microsoft.windows.gdiplus_6595b64144ccf1df_1.1.9600.17415_none_dad8722c5bcc2d8f\gdiplus.dll>
|
||||
Loading <comctl32.dll>
|
||||
Loading <comctl32.dll>
|
||||
Loading <comctl32.dll>
|
||||
Loading <C:\Windows\system32\shell32.dll>
|
||||
Loading <C:\Windows\SYSTEM32\WINMM.dll>
|
||||
Loading <C:\Windows\system32\ole32.dll>
|
||||
Ask to load <ole32.dll>: exiting process
|
||||
@@ -10,6 +10,7 @@ This sections describes them by group of relation.
|
||||
:maxdepth: 3
|
||||
|
||||
process.rst
|
||||
exception.rst
|
||||
registry.rst
|
||||
network.rst
|
||||
com.rst
|
||||
+37
-17
@@ -3,42 +3,62 @@ import windows.test
|
||||
|
||||
from windows.generated_def.winstructs import *
|
||||
|
||||
#c = windows.test.pop_calc_64()
|
||||
|
||||
|
||||
c = windows.test.pop_calc_64(dwCreationFlags=CREATE_SUSPENDED)
|
||||
|
||||
|
||||
python_code = """
|
||||
import windows
|
||||
import ctypes
|
||||
import windows
|
||||
from windows.vectored_exception import VectoredException
|
||||
from windows.exception import VectoredException
|
||||
import windows.generated_def.windef as windef
|
||||
from windows.generated_def.winstructs import *
|
||||
|
||||
windows.utils.create_console()
|
||||
|
||||
module_to_trace = "gdi32.dll"
|
||||
nb_repeat = [5]
|
||||
|
||||
@VectoredException
|
||||
def handler(exc):
|
||||
print("POUET EXCEPTION")
|
||||
if exc[0].ExceptionRecord[0].ExceptionCode == EXCEPTION_ACCESS_VIOLATION:
|
||||
print("")
|
||||
target_addr = ctypes.cast(exc[0].ExceptionRecord[0].ExceptionInformation[1], ctypes.c_void_p).value
|
||||
print("Instr at {0} accessed to addr {1}".format(hex(exc[0].ExceptionRecord[0].ExceptionAddress), hex(target_addr)))
|
||||
windows.winproxy.VirtualProtect(target_page, 0x1000, windef.PAGE_READWRITE)
|
||||
print("Instr at {0} accessed to addr {1} ({2})".format(hex(exc[0].ExceptionRecord[0].ExceptionAddress), hex(target_addr), module_to_trace))
|
||||
windows.winproxy.VirtualProtect(target_page, code_size, windef.PAGE_EXECUTE_READWRITE)
|
||||
nb_repeat[0] -= 1
|
||||
if nb_repeat[0]:
|
||||
exc[0].ContextRecord[0].EEFlags.TF = 1
|
||||
else:
|
||||
print("No more tracing !")
|
||||
return windef.EXCEPTION_CONTINUE_EXECUTION
|
||||
else:
|
||||
print("Exception of type {0}".format(exc[0].ExceptionRecord[0].ExceptionCode))
|
||||
print("Resetting page protection to <PAGE_READWRITE>")
|
||||
windows.winproxy.VirtualProtect(target_page, code_size, windef.PAGE_READWRITE)
|
||||
return windef.EXCEPTION_CONTINUE_EXECUTION
|
||||
return windef.EXCEPTION_CONTINUE_SEARCH
|
||||
|
||||
|
||||
windows.winproxy.AddVectoredExceptionHandler(0, handler)
|
||||
|
||||
target_page = windows.current_process.virtual_alloc(0x1000)
|
||||
print("Protected page is at {0}".format(hex(target_page)))
|
||||
windows.winproxy.VirtualProtect(target_page, 0x1000, windef.PAGE_NOACCESS)
|
||||
print("Tracing execution in module: <{0}>".format(module_to_trace))
|
||||
|
||||
print("YOLO <3")
|
||||
print(ctypes.c_uint.from_address(target_page + 0x42).value)
|
||||
module = [x for x in windows.current_process.peb.modules if x.name == module_to_trace][0]
|
||||
target_page = module.baseaddr
|
||||
code_size = module.pe.get_OptionalHeader().SizeOfCode
|
||||
|
||||
print("Protected page is at {0}".format(hex(target_page)))
|
||||
windows.winproxy.VirtualProtect(target_page, code_size, windef.PAGE_READWRITE)
|
||||
"""
|
||||
|
||||
c = windows.test.pop_calc_64(dwCreationFlags=CREATE_SUSPENDED)
|
||||
x = c.execute_python(python_code)
|
||||
|
||||
c.threads[0].resume()
|
||||
|
||||
import time
|
||||
time.sleep(0.1)
|
||||
|
||||
for t in c.threads:
|
||||
t.suspend()
|
||||
|
||||
time.sleep(1)
|
||||
c.exit()
|
||||
|
||||
x = c.execute_python(python_code)
|
||||
+12
-21
@@ -1,21 +1,23 @@
|
||||
import ctypes
|
||||
import windows
|
||||
from windows.vectored_exception import VectoredException
|
||||
from windows.exception import VectoredException
|
||||
import windows.generated_def.windef as windef
|
||||
from windows.generated_def.winstructs import *
|
||||
|
||||
|
||||
@VectoredException
|
||||
def handler(exc):
|
||||
print("POUET")
|
||||
print("==Entry of VEH handler==")
|
||||
if exc[0].ExceptionRecord[0].ExceptionCode == EXCEPTION_ACCESS_VIOLATION:
|
||||
target_addr = ctypes.cast(exc[0].ExceptionRecord[0].ExceptionInformation[1], ctypes.c_void_p).value
|
||||
print("Instr at {0} accessed to addr {1}".format(hex(exc[0].ExceptionRecord[0].ExceptionAddress), hex(target_addr)))
|
||||
print("Resetting page protection to <PAGE_READWRITE>")
|
||||
windows.winproxy.VirtualProtect(target_page, 0x1000, windef.PAGE_READWRITE)
|
||||
exc[0].ContextRecord[0].EEFlags.TF = 1
|
||||
return windef.EXCEPTION_CONTINUE_EXECUTION
|
||||
else:
|
||||
print("HAHAH {0}".format(exc[0].ExceptionRecord[0].ExceptionCode))
|
||||
print("Exception of type {0}".format(exc[0].ExceptionRecord[0].ExceptionCode))
|
||||
print("Resetting page protection to <PAGE_NOACCESS>")
|
||||
windows.winproxy.VirtualProtect(target_page, 0x1000, windef.PAGE_NOACCESS)
|
||||
return windef.EXCEPTION_CONTINUE_EXECUTION
|
||||
|
||||
@@ -23,25 +25,14 @@ def handler(exc):
|
||||
windows.winproxy.AddVectoredExceptionHandler(0, handler)
|
||||
|
||||
target_page = windows.current_process.virtual_alloc(0x1000)
|
||||
print("Protected page is at {0}".format(hex(target_page)))
|
||||
print("Protected page is at <{0}>".format(hex(target_page)))
|
||||
print("Setting page protection to <PAGE_NOACCESS>")
|
||||
windows.winproxy.VirtualProtect(target_page, 0x1000, windef.PAGE_NOACCESS)
|
||||
|
||||
print("")
|
||||
v = ctypes.c_uint.from_address(target_page).value
|
||||
print("POINT1")
|
||||
print("Value 1 read")
|
||||
|
||||
print("")
|
||||
v = ctypes.c_uint.from_address(target_page + 0x10).value
|
||||
print("POINT2")
|
||||
|
||||
|
||||
|
||||
# (cmd) python.exe samples\veh_segv.py
|
||||
#Protected page is at 0x3f0000
|
||||
#POUET
|
||||
#Instr at 0x1d1ab5f4 accessed to addr 0x3f0000
|
||||
#POUET
|
||||
#HAHAH EXCEPTION_SINGLE_STEP(0x80000004L)
|
||||
#POINT1
|
||||
#POUET
|
||||
#Instr at 0x1d1ab5f4 accessed to addr 0x3f0010
|
||||
#POUET
|
||||
#HAHAH EXCEPTION_SINGLE_STEP(0x80000004L)
|
||||
#POINT2
|
||||
print("Value 2 read")
|
||||
|
||||
+2
-57
@@ -32,7 +32,7 @@ class Debugger(object):
|
||||
def __init__(self, target, already_debuggable=False):
|
||||
"""``target`` must be a WinProcess.
|
||||
|
||||
``already_debuggable`` must be set to ``True`` if process is already expecting a debugger (created with DEBUG_PROCESS)"""
|
||||
``already_debuggable`` must be set to ``True`` if process is already expecting a debugger (created with ``DEBUG_PROCESS``)"""
|
||||
self._init_dispatch_handlers()
|
||||
self.target = target
|
||||
self.is_target_launched = False
|
||||
@@ -45,7 +45,6 @@ class Debugger(object):
|
||||
# List of breakpoints
|
||||
self.breakpoints = {}
|
||||
self._pending_breakpoints = {} #Breakpoints to put in new process / threads
|
||||
self._pending_address = {} # Breakpoints that address have not been resolved yet
|
||||
# Values rewritten by "\xcc"
|
||||
self._memory_save = defaultdict(dict)
|
||||
# Dict of {tid : {drx taken : BP}}
|
||||
@@ -55,12 +54,6 @@ class Debugger(object):
|
||||
|
||||
self._module_by_process = {}
|
||||
|
||||
#TODO: remove this: THIS IS A TEST
|
||||
self._breakpoints_new_targets = {}
|
||||
self._breakpoint_resolvable_address = {}
|
||||
|
||||
self._pending_breakpoints_new = {}
|
||||
|
||||
self._pending_breakpoints_new = defaultdict(list)
|
||||
|
||||
|
||||
@@ -103,7 +96,6 @@ class Debugger(object):
|
||||
return x
|
||||
|
||||
def _resolve(self, addr, target):
|
||||
print("Resolving <{0}> for {1}".format(addr, self.current_process))
|
||||
if not isinstance(addr, basestring):
|
||||
return addr
|
||||
dll, api = addr.split("!")
|
||||
@@ -397,58 +389,11 @@ class Debugger(object):
|
||||
if not self.processes:
|
||||
break
|
||||
|
||||
#def add_bp(self, bp, addr=None, type=None, target=None):
|
||||
# """Add a breakpoint, bp can be:
|
||||
#
|
||||
# * a :class:`Breakpoint` (addr and type must be None)
|
||||
# * any callable (addr and type must NOT be None)
|
||||
#
|
||||
# If the ``bp`` type is ``STANDARD_BP``, target can be None (all targets) or a process.
|
||||
#
|
||||
# If the ``bp`` type is ``HARDWARE_EXEC_BP``, target can be None (all targets), a process or a thread.
|
||||
# """
|
||||
# if getattr(bp, "addr", None) is None:
|
||||
# if addr is None or type is None:
|
||||
# raise ValueError("SUCK YOUR NONE")
|
||||
# bp = ProxyBreakpoint(bp, addr, type)
|
||||
# else:
|
||||
# if addr is not None or type is not None:
|
||||
# raise ValueError("Given <addr|type> by parameters but BP object have them")
|
||||
# del addr
|
||||
# del type
|
||||
# if target is None:
|
||||
# # Raise on multiple pending at same addr ?
|
||||
# # We will add the pending breakpoint to other new processes
|
||||
# if bp.addr in self._pending_breakpoints:
|
||||
# raise ValueError("Pending breakpoint already at {0}".format(hex(bp.addr)))
|
||||
# self._pending_breakpoints[bp.addr] = (bp, target)
|
||||
# targets = self.processes.values()
|
||||
# if targets is None:
|
||||
# return
|
||||
# else:
|
||||
# targets = [target]
|
||||
# if bp.addr in self.breakpoints:
|
||||
# raise ValueError("Breakpoint already at {0}".format(hex(bp.addr)))
|
||||
#
|
||||
# #self.breakpoints[bp.addr] = bp
|
||||
#
|
||||
# if isinstance(bp.addr, basestring):
|
||||
# dll, api = bp.addr.split("!")
|
||||
# dll = dll.lower()
|
||||
# if dll not in self._pending_address: #TODO: default dict
|
||||
# self._pending_address[dll] = []
|
||||
# self._pending_address[dll].append((api, bp))
|
||||
#
|
||||
# _setup_method = getattr(self, "_setup_breakpoint_" + bp.type)
|
||||
# _setup_method(bp, targets)
|
||||
# return True
|
||||
|
||||
|
||||
def add_bp(self, bp, addr=None, type=None, target=None):
|
||||
"""Add a breakpoint, bp can be:
|
||||
|
||||
* a :class:`Breakpoint` (addr and type must be None)
|
||||
* any callable (addr and type must NOT be None)
|
||||
* any callable (addr and type must NOT be None) (NON-TESTED)
|
||||
|
||||
If the ``bp`` type is ``STANDARD_BP``, target can be None (all targets) or a process.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user