# 9. `windows.debug` – Debugging

Note

See sample Debugging

Note

If you are interrested by symbols (PDB) handling, go to subsection windows.debug.symbols – Using symbols.

You can also look at the symbols-related samples: Symbols

## 9.1. `Debugger`

The `Debugger` is the base class to perform the debugging of a remote process. The `Debugger` have some functions called on given event that can be implemented by subclasses.

All Memory-breakpoint are disabled when callind a public callback or a breakpoint `trigger()` function.

This means that those methods see the original `current_process` memory access rights.

class `windows.debug.``Debugger`(target)

  A debugger based on standard Win32 API. Handle :

  - Standard BP (int3)
  - Hardware-Exec BP (DrX)
  - Memory BP (virtual_protect)
  `__init__`(target)

    `target` must be a debuggable `WinProcess`.

  classmethod `attach`(target)

    attach to `target` (must be a `WinProcess`)

    Return type: | `Debugger`

    Note

    see Debugger.attach sample

  `detach`(target=None)

    Detach from all debugged processes or process `target`

  classmethod `debug`(path, args=None, dwCreationFlags=0, show_windows=False)

    Create a process and debug it.

    Return type: | `Debugger`

  `loop`()

    Debugging loop: handle event / dispatch to breakpoint. Returns when all targets are dead/detached

  `add_bp`(bp, addr=None, type=None, target=None)

    Add a breakpoint, bp can be:

    - a `Breakpoint` (addr and type must be `None`)
    - any callable (addr and type must NOT be `None`) (NON-TESTED)

    If the `bp` type is `STANDARD_BP` or `MEMORY_BREAKPOINT`, 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.

  `del_bp`(bp, targets=None)

    Delete a breakpoint, if targets is `None`: delete it from all targets

  `single_step`()

    Make the `current_thread` `single_step`. `Debugger.on_single_step` will be called after that

  `get_memory_breakpoint_at`(addr, process=None)

    Get the memory breakpoint that handle `addr`

    Return values are:

    > - `False` if the page has no memory breakpoint (real fault)
    > - `None` if the page as memBP but None handle `addr`
    > - `bp` the MemBP that handle `addr`

  `disable_all_memory_breakpoints`(target=None)

    Restore all pages to their original access rights. If target is `None`, use `current_process`

    Returns: | a mapping of all disabled breakpoints that must be passed to `restore_all_memory_breakpoints()`

  `restore_all_memory_breakpoints`(data, target=None)

    Re-setup all memory breakpoints, affecting pages access rights. If target is `None`, use `current_process`

    `data` is the result of the corresponding call to `disable_all_memory_breakpoints()`

  `DisabledMemoryBreakpoint`(**kwds)

    A context-manager that disable all memory breakpoints and restore them on exit

  `get_exception_bitness`(exc)

    Return the bitness in which the exception occured. Useful when debugingg a 32b process from a 64bits one

    Returns: | `int` – 32 or 64

  static `kill_on_exit`(choice)

    If set to True(default in Windows) will kill all attached process on thread exit. Otherwise, the thread detaches from all processes being debugged on exit.

    See: https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-debugsetprocesskillonexit

  `on_setup`()

    Called on the first breakpoint event occuring in the debugger. This callback allow to setup hook / interact with the debugee when ready:

    - If `on_setup()` is overriden by a subclass it will be called and `on_exception()` will NOT be called for this event (first BP).
    - If `on_setup()` is not defined the first BP will trigger an `on_exception()`.

    Note

    see sample on_setup

  `on_exception`(exception)

    Called on exception event other that known breakpoint or requested single step. `exception` is one of the following type:

    > - `windows.winobject.exception.EEXCEPTION_DEBUG_INFO32`
    > - `windows.winobject.exception.EEXCEPTION_DEBUG_INFO64`

    The default behaviour is to return `DBG_CONTINUE` for the known exception code and `DBG_EXCEPTION_NOT_HANDLED` else

  `on_single_step`(exception)

    Called on requested single step `exception` is one of the following type:

    > - `windows.winobject.exception.EEXCEPTION_DEBUG_INFO32`
    > - `windows.winobject.exception.EEXCEPTION_DEBUG_INFO64`

    There is no default implementation, if you use `Debugger.single_step()` you should implement `on_single_step`

  `on_create_process`(create_process)

    Called on create_process event

    Parameters: | create_process (CREATE_PROCESS_DEBUG_INFO) –

  `on_exit_process`(exit_process)

    Called on exit_process event

    Parameters: | exit_process (EXIT_PROCESS_DEBUG_INFO) –

  `on_create_thread`(create_thread)

    Called on create_thread event

    Parameters: | create_thread (CREATE_THREAD_DEBUG_INFO) –

  `on_exit_thread`(exit_thread)

    Called on exit_thread event

    Parameters: | exit_thread (EXIT_THREAD_DEBUG_INFO) –

  `on_load_dll`(load_dll)

    Called on load_dll event

    Parameters: | load_dll (LOAD_DLL_DEBUG_INFO) –

  `on_unload_dll`(unload_dll)

    Called on unload_dll event

    Parameters: | unload_dll (UNLOAD_DLL_DEBUG_INFO) –

  `on_output_debug_string`(debug_string)

    Called on debug_string event

    Parameters: | debug_string (OUTPUT_DEBUG_STRING_INFO) –

  `on_rip`(rip_info)

    Called on rip_info event

    Parameters: | rip_info (RIP_INFO) –

## 9.2. `SymbolDebugger`

Note

See sample SymbolDebugger

class `windows.debug.``SymbolDebugger`(*args, **kwargs)

  Bases: `windows.debug.debugger.Debugger`

  A debugger using the symbol API (hence PDB) for name resolution. To use PDB, a correct version of dbghelp should be configured as well as `_NT_SYMBOL_PATH`. (See windows.debug.symbols – Using symbols)

  This debugger add a `current_resolver` variable (A `ProcessSymbolHandler`) for the `current_process`.

## 9.3. `LocalDebugger`

Note

See sample LocalDebugger

The `Debugger` is the base class to perform the debugging the current process. It is based on `VectoredException()` (see VectoredException())

There is not much documentation for now as the code might change soon.

class `windows.debug.``LocalDebugger`

  A debugger interface around `AddVectoredExceptionHandler()`.

  Handle:

  > - Standard BP (int3)
  > - Hardware-Exec BP (DrX)

  `add_bp`(bp, target=None)

    Add a breakpoint, bp is a “class:Breakpoint

    If the `bp` type is `STANDARD_BP`, target must be None.

    If the `bp` type is `HARDWARE_EXEC_BP`, target can be None (all threads), or some threads of the process

  `del_bp`(bp, targets=None)

    Delete a breakpoint

  `get_exception_code`()

    Return ExceptionCode of current exception

  `get_exception_context`()

    Return context of current exception

  `on_exception`(exc)

    Called on exception

  `single_step`()

    Make the current thread to single step

## 9.4. `Breakpoint`

Standard breakpoints types expect an address as argument.

An address can be:

> - An `int`

> - A `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.

class `windows.debug.``Breakpoint`(addr)

  An standard (Int3) breakpoint (type == `STANDARD_BP`)

  `trigger`(dbg, exception)

    Called when breakpoint is hit

class `windows.debug.``HXBreakpoint`(addr)

  An hardware-execution breakpoint (type == `HARDWARE_EXEC_BP`)

  `trigger`(dbg, exception)

    Called when breakpoint is hit

class `windows.debug.``MemoryBreakpoint`(addr, size=None, events=None)

  A memory breakpoint (type == `MEMORY_BREAKPOINT`)

  `__init__`(addr, size=None, events=None)

    `size`: the size of the memory breakpoint.

    `events`: a string representing the events that interest the BP (any of “RWX”)

  `trigger`(dbg, exception)

    Called when breakpoint is hit

Note

MemoryBreakpoint are triggered based on the fault address only (as I don’t know a way to get the size of the read/write causing the fault without embedding a disassembler).

This means that a MEMBP at address `X` won’t be triggered by a write of size 4 at address `X - 1`. it’s sad I know.

class `windows.debug.``FunctionCallBP`(addr)

  A Breakpoint that allow to trigger at the return of a function

  `__init__`(addr)

    x.__init__(…) initializes x; see help(type(x)) for signature

  `break_on_ret`(dbg, exception)

    Setup a breakpoint at the return address of the function, this breakpoint will call `ret_trigger()`

  `get_ret_addr`(dbg, exception)

    Get the return address of the current target, only valid in the trigger() function.

  `ret_trigger`(dbg, exception)

    Called at the return of the function if `break_on_ret()` was called

  `trigger`(dbg, exception)

    Called when breakpoint is hit

Note

See sample windows.debug.FunctionCallBP

class `windows.debug.``FunctionBP`(addr=None, target=None)

  A breakpoint that accepts a function from `windows.winproxy` and able to:

  - Extract the arguments of the functions
  - Break at the return of the function
  `__init__`(addr=None, target=None)

    x.__init__(…) initializes x; see help(type(x)) for signature

  `arguments`(dbg)

    TEST PARAM DICT

  `break_on_ret`(dbg, exception)

    Setup a breakpoint at the return address of the function, this breakpoint will call `ret_trigger()`

  `extract_arguments`(cproc, cthread)

    Extracts the functions parameters in an `OrderedDict`

  `get_ret_addr`(dbg, exception)

    Get the return address of the current target, only valid in the trigger() function.

  `ret_trigger`(dbg, exception)

    Called at the return of the function if `break_on_ret()` was called

  `trigger`(dbg, exception)

    Called when breakpoint is hit

Note

See sample windows.debug.FunctionBP

## 9.5. `windows.debug.symbols` – Using symbols

The `windows.debug.symbols` module provide classes to load PDB and resolve name/address. In its current state, this module does not handle types.

Note

See samples Symbols

### 9.5.1. Configuration

In order to be able to automatically download PDB and parse remote `_NT_SYMBOL_PATH`, a debug version of the DLL dbghelp.dll must be used. (See MSDN: DbgHelp Versions)

As it is NOT recommended to replace `system32/dbghelp.dll`, its path must be provided to PythonForWindows. This path must be provided before any call to the `dbghelp.dll` APIs. Also, the `symsrv.dll` DLL should be present in the same directory as `dbghelp.dll` (See SymSrv Installation)

There is 2 ways to pass this information to `PythonForWindows`:

> - Using the function `set_dbghelp_path()`
> - Using the environment variable `PFW_DBGHELP_PATH`
>     - If this variable exists it will simply trigger a call to `set_dbghelp_path(PFW_DBGHELP_PATH)`

If the given path is a directory, the final path will be computer as `path\<current_process_bitness>\dbghelp.dll`. This allow to use the same script (or environment variable) transparently in bot 32b & 64b python interpreters.

Note

For example, on my computer my setup is done through the environment variable: `PFW_DBGHELP_PATH=D:\pysym\bin`

This directory have the following layout:

> $ tree /A /F %PFW_DBGHELP_PATH%
> D:\PYSYM\BIN
> | symsrv.yes
> |
> +---32
> | dbghelp.dll
> | symsrv.dll
> |
> \---64
> dbghelp.dll
> symsrv.dll

### 9.5.2. Helpers

`windows.debug.symbols.``set_dbghelp_path`(path)

  Set the path of the `dbghelp.dll` file to use. It allow to configure a different version of the DLL handling PDB downloading.

  If `path` is a directory, the final `dbghelp.dll` will be computed as `path\<current_process_bitness>\dbghelp.dll`.

  This allow to use the same script transparently in both 32b & 64b python interpreters.

class `windows.debug.symbols.``SymbolEngine`

  Represent the global symbol engine. Just a proxy to get/set global engine options

  Its instance can be accessed using `windows.debug.symbols.engine`

  Exemple:

      >>> windows.debug.symbols.engine.options
      6L
      >>> windows.debug.symbols.engine.options = gdef.SYMOPT_UNDNAME
      >>> windows.debug.symbols.engine.options
      2L

  `options`

    The options of the Symbol engine (see options)

    Note

    Default options are: `gdef.SYMOPT_DEFERRED_LOADS + gdef.SYMOPT_UNDNAME`

### 9.5.3. `VirtualSymbolHandler`

class `windows.debug.symbols.``VirtualSymbolHandler`(search_path=None)

  Bases: `windows.debug.symbols.SymbolHandler`

  A SymbolHandler where its handle is not a valid process handle Allow to create/resolve symbol in a ‘virtual’ process But all API needing a real process handle will fail

  `__getitem__`(name_or_addr)

    Resolve `name_or_addr`.

    If its an int -> Return the `SymbolInfo` at the address. If its a string -> Return the `SymbolInfo` corresponding to the symbol name

    Returns: | `SymbolInfo`

    Note

    `__getitem__` is an alias for `resolve()`

    Exemple:

        >>> sh = windows.debug.symbols.VirtualSymbolHandler()
        >>> mod = sh.load_file(r"c:\windows\system32\kernelbase.dll")
        >>> mod
        <SymbolModule name="kernelbase" type=SymPdb pdb="wkernelbase.pdb" addr=0x10000000>
        >>> sh.resolve("kernelbase!CreateFileInternal")
        <SymbolInfoA name="CreateFileInternal" addr=0x100f2120 tag=SymTagFunction>
        >>> sh[0x100f2042]
        <SymbolInfoA name="ReadFile" addr=0x100f1ee0 displacement=0x162 tag=SymTagFunction>
        >>> str(sh[0x100f2042])
        'kernelbase!ReadFile+0x162'

  `load`(path, name=None, addr=0, size=0, data=None, flags=0)

    An alias for `VirtualSymbolHandler.load_file()`

  `load_file`(path, name=None, addr=0, size=0, data=None, flags=0)

    Load the module `path` at `addr`

    Returns: | `SymbolModule` – The loaded module

  `load_module`(file_handle=None, path=None, name=None, addr=0, size=0, data=None, flags=0)

    Load a module at a given `addr`. The module to load can be pass via a `file_handle` or the direct `path` of the file to load.

    Returns: | `SymbolModule` – The loaded module

    Note

    The logic of `SymLoadModuleEx` seems somewhat strange about the naming of the loaded module. A custom module `name` is only taken into account if the file is passed via a File handle. To make it more intuitive, if this function is call with a `path` and `name` and no `file_handle`, it will open the path and directly call `SymLoadModuleEx` with a file handle and a name.

  `modules`

    The list of loaded modules

    Returns: | [`SymbolModule`] – A list of modules

  `refresh`()

    Do nothing for a `VirtualSymbolHandler`

  `resolve`(name_or_addr)

    Resolve `name_or_addr`.

    If its an int -> Return the `SymbolInfo` at the address. If its a string -> Return the `SymbolInfo` corresponding to the symbol name

    Returns: | `SymbolInfo`

    Note

    `__getitem__` is an alias for `resolve()`

    Exemple:

        >>> sh = windows.debug.symbols.VirtualSymbolHandler()
        >>> mod = sh.load_file(r"c:\windows\system32\kernelbase.dll")
        >>> mod
        <SymbolModule name="kernelbase" type=SymPdb pdb="wkernelbase.pdb" addr=0x10000000>
        >>> sh.resolve("kernelbase!CreateFileInternal")
        <SymbolInfoA name="CreateFileInternal" addr=0x100f2120 tag=SymTagFunction>
        >>> sh[0x100f2042]
        <SymbolInfoA name="ReadFile" addr=0x100f1ee0 displacement=0x162 tag=SymTagFunction>
        >>> str(sh[0x100f2042])
        'kernelbase!ReadFile+0x162'

  `search`(mask, mod=0, tag=0, options=SYMSEARCH_ALLITEMS(0x8), callback=None)

    Search the symbols matching `mask` (`Windbg` like).

    Returns: | [`SymbolInfo`] – A list of `SymbolInfo`

        >>> sh = windows.debug.symbols.VirtualSymbolHandler()
        >>> mod = sh.load_file(r"c:\windows\system32\kernelbase.dll")
        >>> sh.search("kernelbase!CreateFile*")
        [<SymbolInfoA name="CreateFileInternal" addr=0x100f2120 tag=SymTagFunction>,
            <SymbolInfoA name="CreateFileMoniker" addr=0x10117d80 tag=SymTagFunction>,
            <SymbolInfoA name="CreateFile2" addr=0x1011e690 tag=SymTagFunction>,
            ...]

  `unload`(addr)

    Unload the module at `addr`

### 9.5.4. `ProcessSymbolHandler`

class `windows.debug.symbols.``ProcessSymbolHandler`(process, search_path=None, invade_process=False)

  Bases: `windows.debug.symbols.SymbolHandler`

  `__getitem__`(name_or_addr)

    Resolve `name_or_addr`.

    If its an int -> Return the `SymbolInfo` at the address. If its a string -> Return the `SymbolInfo` corresponding to the symbol name

    Returns: | `SymbolInfo`

    Note

    `__getitem__` is an alias for `resolve()`

    Exemple:

        >>> sh = windows.debug.symbols.VirtualSymbolHandler()
        >>> mod = sh.load_file(r"c:\windows\system32\kernelbase.dll")
        >>> mod
        <SymbolModule name="kernelbase" type=SymPdb pdb="wkernelbase.pdb" addr=0x10000000>
        >>> sh.resolve("kernelbase!CreateFileInternal")
        <SymbolInfoA name="CreateFileInternal" addr=0x100f2120 tag=SymTagFunction>
        >>> sh[0x100f2042]
        <SymbolInfoA name="ReadFile" addr=0x100f1ee0 displacement=0x162 tag=SymTagFunction>
        >>> str(sh[0x100f2042])
        'kernelbase!ReadFile+0x162'

  `load`(name)

    Load the `SymbolModule` associated with the loaded module `name` (as found in the PEB)

    Returns: | `SymbolModule`

    Exemple:

        >>> sh = windows.debug.symbols.ProcessSymbolHandler(windows.test.pop_proc_64())
        <windows.debug.symbols.ProcessSymbolHandler object at 0x033A2C30>
        >>> sh
        <windows.debug.symbols.ProcessSymbolHandler object at 0x033A2C30>
        >>> sh.load("kernelbase.dll")
        <SymbolModule name="kernelbase" type=SymDeferred pdb="" addr=0x7ffb5b090000>
        >>> sh["kernelbase!CreateProcessA"]
        <SymbolInfoA name="CreateProcessA" start=0x7ffb5b2371f0 tag=SymTagPublicSymbol>

  `load_file`(path, name=None, addr=0, size=0, data=None, flags=0)

    Load the module `path` at `addr`

    Returns: | `SymbolModule` – The loaded module

  `load_module`(file_handle=None, path=None, name=None, addr=0, size=0, data=None, flags=0)

    Load a module at a given `addr`. The module to load can be pass via a `file_handle` or the direct `path` of the file to load.

    Returns: | `SymbolModule` – The loaded module

    Note

    The logic of `SymLoadModuleEx` seems somewhat strange about the naming of the loaded module. A custom module `name` is only taken into account if the file is passed via a File handle. To make it more intuitive, if this function is call with a `path` and `name` and no `file_handle`, it will open the path and directly call `SymLoadModuleEx` with a file handle and a name.

  `modules`

    The list of loaded modules

    Returns: | [`SymbolModule`] – A list of modules

  `refresh`()

    Update the list of loaded modules to match the modules present in the target process

    Note

    This function only call SymRefreshModuleList for now. It seems that this function do not handle refreshing a 64b target from a 32b python

    Also, on a 32b target from a 64b python it seems to only load symbols for the 64b modules (ntdll + syswow dll)

    Exemple:

        >>> sh = windows.debug.symbols.ProcessSymbolHandler(windows.test.pop_proc_64())
        >>> sh.modules
        []
        >>> sh.refresh()
        44
        >>> sh.modules
        [<SymbolModule name="notepad" type=SymDeferred pdb="" addr=0x7ff772b80000>,
            <SymbolModule name="ntdll" type=SymDeferred pdb="" addr=0x7ffb5d860000>,
            <SymbolModule name="KERNEL32" type=SymDeferred pdb="" addr=0x7ffb5bb90000>,
            <SymbolModule name="KERNELBASE" type=SymDeferred pdb="" addr=0x7ffb5b090000>,
            ...]

  `resolve`(name_or_addr)

    Resolve `name_or_addr`.

    If its an int -> Return the `SymbolInfo` at the address. If its a string -> Return the `SymbolInfo` corresponding to the symbol name

    Returns: | `SymbolInfo`

    Note

    `__getitem__` is an alias for `resolve()`

    Exemple:

        >>> sh = windows.debug.symbols.VirtualSymbolHandler()
        >>> mod = sh.load_file(r"c:\windows\system32\kernelbase.dll")
        >>> mod
        <SymbolModule name="kernelbase" type=SymPdb pdb="wkernelbase.pdb" addr=0x10000000>
        >>> sh.resolve("kernelbase!CreateFileInternal")
        <SymbolInfoA name="CreateFileInternal" addr=0x100f2120 tag=SymTagFunction>
        >>> sh[0x100f2042]
        <SymbolInfoA name="ReadFile" addr=0x100f1ee0 displacement=0x162 tag=SymTagFunction>
        >>> str(sh[0x100f2042])
        'kernelbase!ReadFile+0x162'

  `search`(mask, mod=0, tag=0, options=SYMSEARCH_ALLITEMS(0x8), callback=None)

    Search the symbols matching `mask` (`Windbg` like).

    Returns: | [`SymbolInfo`] – A list of `SymbolInfo`

        >>> sh = windows.debug.symbols.VirtualSymbolHandler()
        >>> mod = sh.load_file(r"c:\windows\system32\kernelbase.dll")
        >>> sh.search("kernelbase!CreateFile*")
        [<SymbolInfoA name="CreateFileInternal" addr=0x100f2120 tag=SymTagFunction>,
            <SymbolInfoA name="CreateFileMoniker" addr=0x10117d80 tag=SymTagFunction>,
            <SymbolInfoA name="CreateFile2" addr=0x1011e690 tag=SymTagFunction>,
            ...]

  `unload`(addr)

    Unload the module at `addr`

### 9.5.5. `SymbolModule`

class `windows.debug.symbols.``SymbolModule`(resolver)

  Bases: `windows.generated_def.winstructs._IMAGEHLP_MODULE64`

  Represent a loaded symbol module (see MSDN IMAGEHLP_MODULE64)

  Note

  This represent a module in the `symbol space` for symbol resolution. This can be completly virtual (particularly in the case of `VirtualSymbolHandler`

  `addr`

    The load address of the module

  `name`

    The name of the module

  `path`

    The full path and file name of the file from which symbols were loaded.

  `pdb`

    The local path of the loaded PDB if present

    Exemple:

          >>> sh = windows.debug.symbols.VirtualSymbolHandler()
          >>> mod = sh.load_file(r"c:\windows\system32\kernelbase.dll")
          >>> mod.pdb
          'd:\symbols\wkernelbase.pdb\017FA9C5278235B7E6BFBA74A9A5AAD91\wkernelbase.pdb'

  `type`

    The type of module (`SYM_TYPE`), which can be one of:

    > SymCoff | COFF symbols.
    > SymCv | CodeView symbols.
    > SymDeferred | Symbol loading deferred.
    > SymDia | DIA symbols.
    > SymExport | Symbols generated from a DLL export table.
    > SymNone | No symbols are loaded.
    > SymPdb | PDB symbols.
    > SymSym | .sym file.
    > SymVirtual | The virtual module created by SymLoadModuleEx with SLMFLAG_VIRTUAL.

### 9.5.6. `SymbolInfo`

`windows.debug.symbols.``SymbolInfo`

  alias of `windows.debug.symbols.SymbolInfoA`

class `windows.debug.symbols.``SymbolInfoA`

  Bases: `windows.generated_def.winstructs._SYMBOL_INFO`, `windows.debug.symbols.SymbolInfoBase`

  Represent a Symbol. This class in based on the class SYMBOL_INFO with the handling on displacement embeded into it.s

  Exemple:

      >>> sh = windows.debug.symbols.VirtualSymbolHandler()
      >>> mod = sh.load_file(r"c:\windows\system32\kernelbase.dll")
      >>> sym1 = sh["kernelbase!CreateFileW"]
      >>> sym2 = sh[int(sym1) + 3]
      >>> sym2
      <SymbolInfoA name="CreateFileW" start=0x100f20b0 displacement=0x3 tag=SymTagPublicSymbol>
      >>> hex(sym2.start)
      '0x100f20b0L'
      >>> hex(sym2.addr)
      '0x100f20b3L'
      >>> hex(sym2.displacement)
      '0x3L'
      >>> str(sym2)
      'kernelbase!CreateFileW+0x3'

  `displacement`

    The displacement between the addresse and the start of the symbol (name)

  `CHAR_TYPE`

    alias of `ctypes.c_char`

  `__int__`()

    An alias for `addr`

  `__str__`()

    The fullname of the symbol in the windbg format `mod!sym+displacement`

  `addr`

    The address of the symbol

  `fullname`

    The fullname of the symbol in the windbg format `mod!sym+displacement`

  `module`

    The module containing the symbol

    Type: | `SymbolModule`

  `name`

    The name of the symbol

  `start`

    The address of the start of the symbol If the symbol include a displacement, it is not taken into account

  `tag`

    The Tag of the module

    Type: | `SymTagEnum`