mirror of
https://github.com/hakril/PythonForWindows
synced 2026-06-08 14:31:45 +00:00
Add doc on PEB + samples in sphinx
This commit is contained in:
@@ -16,6 +16,8 @@ Contents:
|
||||
winproxy.rst
|
||||
utils.rst
|
||||
native_exec.rst
|
||||
various.rst
|
||||
sample.rst
|
||||
|
||||
|
||||
Indices and tables
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
Processes and Threads
|
||||
"""""""""""""""""""""
|
||||
|
||||
.. module:: windows.winobject
|
||||
|
||||
CurrentProcess
|
||||
''''''''''''''
|
||||
|
||||
.. note::
|
||||
|
||||
See sample :ref:`sample_current_process`
|
||||
|
||||
.. autoclass:: CurrentProcess
|
||||
:members:
|
||||
:inherited-members:
|
||||
|
||||
CurrentThread
|
||||
'''''''''''''
|
||||
|
||||
.. autoclass:: CurrentThread
|
||||
:members:
|
||||
:inherited-members:
|
||||
|
||||
WinProcess
|
||||
''''''''''
|
||||
|
||||
.. note::
|
||||
|
||||
See sample :ref:`sample_remote_process`
|
||||
|
||||
.. autoclass:: WinProcess
|
||||
:members:
|
||||
:inherited-members:
|
||||
|
||||
|
||||
WinThread
|
||||
'''''''''
|
||||
|
||||
.. autoclass:: WinThread
|
||||
:members:
|
||||
:inherited-members:
|
||||
|
||||
|
||||
.. autoclass:: DeadThread
|
||||
:members:
|
||||
:inherited-members:
|
||||
|
||||
|
||||
PEB Exploration
|
||||
"""""""""""""""
|
||||
|
||||
The :mod:`windows` module is able to parse the PEB of the current process or remote process.
|
||||
The :class:`PEB` is accessible via ``process.peb`` and is of type :class:`PEB`.
|
||||
|
||||
.. note::
|
||||
|
||||
See sample :ref:`sample_peb_exploration`
|
||||
|
||||
.. autoclass:: PEB
|
||||
:members:
|
||||
:inherited-members:
|
||||
|
||||
.. autoclass:: WinUnicodeString
|
||||
|
||||
.. autoclass:: LoadedModule
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
Registry
|
||||
""""""""
|
||||
|
||||
.. module:: windows.registry
|
||||
|
||||
REGISTRY
|
||||
|
||||
.. class:: Registry
|
||||
@@ -0,0 +1,99 @@
|
||||
Samples of code
|
||||
===============
|
||||
|
||||
.. _sample_current_process:
|
||||
|
||||
``windows.current_process``
|
||||
"""""""""""""""""""""""""""
|
||||
|
||||
.. literalinclude:: ..\..\samples\current_process.py
|
||||
|
||||
Output::
|
||||
|
||||
(cmd λ) python32.exe current_process.py
|
||||
current process is <windows.winobject.CurrentProcess object at 0x026CD190>
|
||||
current process is a <32> bits process
|
||||
current process is a SysWow64 process ? <True>
|
||||
current process pid <7432> and ppid <5412>
|
||||
Here are the current process threads: <[<WinThread 5264 owner "python.exe" at 0x28563f0>]>
|
||||
Let's execute some native code ! (0x41 + 1)
|
||||
Waiting for execution to finish !
|
||||
Native code returned <0x42L>
|
||||
Allocating memory in current process
|
||||
Allocated memory is at <0x3f0000>
|
||||
Writing 'SOME STUFF' in allocation memory
|
||||
Reading memory : <'SOME STUFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'>
|
||||
|
||||
.. _sample_remote_process:
|
||||
|
||||
Remote process : :class:`WinProcess`
|
||||
""""""""""""""""""""""""""""""""""""
|
||||
|
||||
.. literalinclude:: ..\..\samples\remote_calc.py
|
||||
|
||||
Output::
|
||||
|
||||
(cmd λ) python.exe remote_calc.py
|
||||
Creating a calc
|
||||
Looking for calcs in the processes
|
||||
They are currently <1> calcs running on the system
|
||||
Let's play with our calc: <<WinProcess "calc.exe" pid 8052 at 0x27bd5d0>>
|
||||
Our calc pid is 8052
|
||||
Our calc is a <32> bits process
|
||||
Our calc is a SysWow64 process ? <True>
|
||||
Our calc have threads ! <[<WinThread 8552 owner "calc.exe" at 0x27f7f30>, <WinThread 3464 owner "calc.exe" at 0x27f7f80>, <WinThread 3840 owner "calc.exe" at 0x27fa030>]>
|
||||
Exploring our calc PEB ! <windows.winobject.RemotePEB object at 0x026DDD00>
|
||||
Command line is <RemoteWinUnicodeString ""C:\windows\system32\calc.exe"" at 0x26ddee0>
|
||||
Here are 3 loaded modules: [<RemoteLoadedModule "calc.exe" at 0x26dde40>, <RemoteLoadedModule "ntdll.dll" at 0x26ddf30>, <RemoteLoadedModule "kernel32.dll" at 0x26ddc60>]
|
||||
Allocating memory in our calc
|
||||
Allocated memory is at <0x5c90000>
|
||||
Writing 'SOME STUFF' in allocated memory
|
||||
Reading allocated memory : <'SOME STUFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'>
|
||||
Execution some native code in our calc (write 0x424242 at allocated address + return 0x1337
|
||||
Executing native code !
|
||||
Return code = 0x1337L
|
||||
Reading allocated memory : <'BBBB STUFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'>
|
||||
Executing python code !
|
||||
Reading allocated memory : <'HELLO FROM CALC\x00\x00\x00\x00\x00'>
|
||||
Trying to import in remote module 'FAKE_MODULE'
|
||||
Remote ERROR !
|
||||
Traceback (most recent call last):
|
||||
File "<string>", line 3, in <module>
|
||||
File "<string>", line 2, in func
|
||||
ImportError: No module named FAKE_MODULE
|
||||
|
||||
That's all ! killing the calc
|
||||
|
||||
|
||||
.. _sample_peb_exploration:
|
||||
|
||||
:class:`PEB` exploration
|
||||
""""""""""""""""""""""""
|
||||
|
||||
.. literalinclude:: ..\..\samples\peb.py
|
||||
|
||||
Output::
|
||||
|
||||
(cmd λ) python.exe peb.py
|
||||
Exploring the current process PEB
|
||||
PEB is <<windows.winobject.PEB object at 0x02649B70>>
|
||||
Commandline object is <WinUnicodeString "python.exe peb.py " at 0x2649c60>
|
||||
Commandline string is u'python.exe peb.py '
|
||||
Imagepath <WinUnicodeString "C:\Python27\python.exe" at 0x2649d50>
|
||||
Printing some modules: <LoadedModule "python.exe" at 0x272a030>
|
||||
<LoadedModule "ntdll.dll" at 0x272a080>
|
||||
<LoadedModule "kernel32.dll" at 0x272acb0>
|
||||
<LoadedModule "kernelbase.dll" at 0x272ad00>
|
||||
<LoadedModule "python27.dll" at 0x272ad50>
|
||||
<LoadedModule "msvcr90.dll" at 0x272ada0>
|
||||
=== K32 ===
|
||||
Looking for kernel32.dll
|
||||
Kernel32 module: <LoadedModule "kernel32.dll" at 0x272acb0>
|
||||
Module name = <kernel32.dll> | Fullname = <C:\Windows\SYSTEM32\KERNEL32.DLL>
|
||||
Kernel32 is loaded at address 0x774c0000
|
||||
=== K32 PE ===
|
||||
PE Representation of k32: <windows.pe_parse.PEFile object at 0x0272D350>
|
||||
Here are some exports {0: 2001566688L, u'CreateFileA': 2001635616L, 42: 2001647872L, u'VirtualAlloc': 2001570704L}
|
||||
Import DLL dependancies are (without api-*): [u'ntdll.dll', u'kernelbase.dll']
|
||||
IAT Entry for ntdll!NtCreateFile = <IATEntry "NtCreateFile" ordinal 253> | addr = 0x77541128L
|
||||
Sections: [<PESection ".text">, <PESection ".rdata">, <PESection ".data">, <PESection ".rsrc">, <PESection ".reloc">]
|
||||
@@ -0,0 +1,13 @@
|
||||
The :mod:`windows` objects
|
||||
==========================
|
||||
|
||||
Through the :ref:`system <object_system>` object many classes representing various `Windows`
|
||||
part are accessible.
|
||||
|
||||
This sections describes them by group of relation.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
process.rst
|
||||
registry.rst
|
||||
@@ -14,7 +14,8 @@ The submodules that you might use by themself are:
|
||||
* :mod:`windows.winproxy`
|
||||
* :mod:`windows.utils`
|
||||
|
||||
|
||||
.. _object_system:
|
||||
|
||||
The ``system`` object
|
||||
"""""""""""""""""""""
|
||||
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
import sys
|
||||
import os.path
|
||||
sys.path.append(os.path.abspath(__file__ + "\..\.."))
|
||||
|
||||
import windows
|
||||
|
||||
print("Exploring the current process PEB")
|
||||
peb = windows.current_process.peb
|
||||
print("PEB is <{0}>".format(peb))
|
||||
commandline = peb.commandline
|
||||
print("Commandline object is {0}".format(commandline))
|
||||
print("Commandline string is {0}".format(repr(commandline.Buffer)))
|
||||
|
||||
imagepath = peb.imagepath
|
||||
print("Imagepath {0}".format(imagepath))
|
||||
|
||||
modules = peb.modules
|
||||
print("Printing some modules: {0}".format("\n".join(str(m) for m in modules[:6])))
|
||||
|
||||
print("=== K32 ===")
|
||||
print("Looking for kernel32.dll")
|
||||
k32 = [m for m in modules if m.name == "kernel32.dll"][0]
|
||||
print("Kernel32 module: {0}".format(k32))
|
||||
|
||||
print("Module name = <{0}> | Fullname = <{1}>".format(k32.name, k32.fullname))
|
||||
print("Kernel32 is loaded at address {0}".format(hex(k32.baseaddr)))
|
||||
|
||||
print("=== K32 PE ===")
|
||||
k32pe = k32.pe
|
||||
print("PE Representation of k32: {0}".format(k32pe))
|
||||
exports = k32pe.exports
|
||||
some_exports = dict((k,v) for k,v in exports.items() if k in [0, 42, "VirtualAlloc", "CreateFileA"])
|
||||
print("Here are some exports {0}".format(some_exports))
|
||||
|
||||
imports = k32pe.imports
|
||||
print("Import DLL dependancies are (without api-*): {0}".format([x for x in imports.keys() if not x.startswith("api-")]))
|
||||
|
||||
NtCreateFile_iat = [x for x in imports["ntdll.dll"] if x.name == "NtCreateFile"][0]
|
||||
print("IAT Entry for ntdll!NtCreateFile = {0} | addr = {1}".format(NtCreateFile_iat, hex(NtCreateFile_iat.addr)))
|
||||
print("Sections: {0}".format(k32pe.sections))
|
||||
+85
-27
@@ -32,15 +32,12 @@ class AutoHandle(object):
|
||||
|
||||
@property
|
||||
def handle(self):
|
||||
"""A handle on the object
|
||||
"""An handle on the object
|
||||
|
||||
:type: HANDLE
|
||||
|
||||
|
||||
.. note::
|
||||
The handle is automaticaly closed when the object is destroyed
|
||||
|
||||
|
||||
"""
|
||||
if hasattr(self, "_handle"):
|
||||
return self._handle
|
||||
@@ -48,6 +45,7 @@ class AutoHandle(object):
|
||||
return self._handle
|
||||
|
||||
def wait(self, timeout=INFINITE):
|
||||
"""Wait for the object"""
|
||||
return winproxy.WaitForSingleObject(self.handle, timeout)
|
||||
|
||||
def __del__(self):
|
||||
@@ -167,6 +165,10 @@ class WinThread(THREADENTRY32, AutoHandle):
|
||||
|
||||
@property
|
||||
def start_address(self):
|
||||
"""The start address of the thread
|
||||
|
||||
:type: :class:`int`
|
||||
"""
|
||||
if windows.current_process.bitness == 32 and self.owner.bitness == 64:
|
||||
res = ULONGLONG()
|
||||
windows.syswow64.NtQueryInformationThread_32_to_64(self.handle, ThreadQuerySetWin32StartAddress, byref(res), ctypes.sizeof(res))
|
||||
@@ -180,12 +182,15 @@ class WinThread(THREADENTRY32, AutoHandle):
|
||||
return res.value
|
||||
|
||||
def exit(self, code=0):
|
||||
"""Exit the thread"""
|
||||
return winproxy.TerminateThread(self.handle, code)
|
||||
|
||||
def resume(self):
|
||||
"""Resume the thread"""
|
||||
return winproxy.ResumeThread(self.handle)
|
||||
|
||||
def suspend(self):
|
||||
"""Suspend the thread"""
|
||||
return winproxy.SuspendThread(self.handle)
|
||||
|
||||
def _get_handle(self):
|
||||
@@ -193,10 +198,18 @@ class WinThread(THREADENTRY32, AutoHandle):
|
||||
|
||||
@property
|
||||
def is_exit(self):
|
||||
"""Is ``True`` if the thread is terminated
|
||||
|
||||
:type: :class:`bool`
|
||||
"""
|
||||
return self.exit_code != STILL_ACTIVE
|
||||
|
||||
@property
|
||||
def exit_code(self):
|
||||
"""The exit code of the thread : ``STILL_ACTIVE`` means the process is not dead
|
||||
|
||||
:type: :class:`int`
|
||||
"""
|
||||
res = DWORD()
|
||||
winproxy.GetExitCodeThread(self.handle, byref(res))
|
||||
return res.value
|
||||
@@ -222,7 +235,7 @@ class WinThread(THREADENTRY32, AutoHandle):
|
||||
return DeadThread(handle, tid)
|
||||
|
||||
class DeadThread(AutoHandle):
|
||||
"""A simple object arround an already dead thread"""
|
||||
"""An already dead thread"""
|
||||
def __init__(self, handle, tid=None):
|
||||
if tid is None:
|
||||
tid = winproxy.GetThreadId(handle)
|
||||
@@ -232,10 +245,18 @@ class DeadThread(AutoHandle):
|
||||
|
||||
@property
|
||||
def is_exit(self):
|
||||
"""Is ``True`` if the thread is terminated
|
||||
|
||||
:type: :class:`bool`
|
||||
"""
|
||||
return self.exit_code != STILL_ACTIVE
|
||||
|
||||
@property
|
||||
def exit_code(self):
|
||||
"""The exit code of the thread : ``STILL_ACTIVE`` means the process is not dead
|
||||
|
||||
:type: :class:`int`
|
||||
"""
|
||||
res = DWORD()
|
||||
winproxy.GetExitCodeThread(self.handle, byref(res))
|
||||
return res.value
|
||||
@@ -244,11 +265,9 @@ class DeadThread(AutoHandle):
|
||||
class Process(AutoHandle):
|
||||
@utils.fixedpropety
|
||||
def is_wow_64(self):
|
||||
"""Is True if the process is a SysWow64 process
|
||||
"""Is ``True`` if the process is a SysWow64 process (32bit process on 64bits system).
|
||||
|
||||
This means a 32bits process on a 64bits system
|
||||
|
||||
:type: bool
|
||||
:type: :class:`bool`
|
||||
"""
|
||||
return utils.is_wow_64(self.handle)
|
||||
|
||||
@@ -256,7 +275,7 @@ class Process(AutoHandle):
|
||||
def bitness(self):
|
||||
"""The bitness of the process
|
||||
|
||||
:returns: int -- 32 or 64"""
|
||||
:returns: :class:`int` -- 32 or 64"""
|
||||
if windows.system.bitness == 32:
|
||||
return 32
|
||||
if self.is_wow_64:
|
||||
@@ -268,7 +287,6 @@ class Process(AutoHandle):
|
||||
"""The threads of the process
|
||||
|
||||
:type: [:class:`WinThread`] -- A list of Thread
|
||||
|
||||
"""
|
||||
return [thread for thread in windows.system.threads if thread.th32OwnerProcessID == self.pid]
|
||||
|
||||
@@ -277,12 +295,20 @@ class Process(AutoHandle):
|
||||
|
||||
@property
|
||||
def exit_code(self):
|
||||
"""The exit code of the process : ``STILL_ACTIVE`` means the process is not dead
|
||||
|
||||
:type: :class:`int`
|
||||
"""
|
||||
res = DWORD()
|
||||
winproxy.GetExitCodeProcess(self.handle, byref(res))
|
||||
return res.value
|
||||
|
||||
@property
|
||||
def is_exit(self):
|
||||
"""Is ``True`` if the process is terminated
|
||||
|
||||
:type: :class:`bool`
|
||||
"""
|
||||
return self.exit_code == STILL_ACTIVE
|
||||
|
||||
def execute(self, code):
|
||||
@@ -292,6 +318,10 @@ class Process(AutoHandle):
|
||||
return self.create_thread(x, 0)
|
||||
|
||||
def query_memory(self, addr):
|
||||
"""Query the memory informations about page at ```addr``
|
||||
|
||||
:rtype: :class:`MEMORY_BASIC_INFORMATION`
|
||||
"""
|
||||
if windows.current_process.bitness == 32 and self.bitness == 64:
|
||||
res = MEMORY_BASIC_INFORMATION64()
|
||||
try:
|
||||
@@ -309,6 +339,10 @@ class Process(AutoHandle):
|
||||
return res
|
||||
|
||||
def memory_state(self):
|
||||
"""Yield the memory information for the whole address space of the process
|
||||
|
||||
:yield: :class:`MEMORY_BASIC_INFORMATION`
|
||||
"""
|
||||
addr = 0
|
||||
res = []
|
||||
while True:
|
||||
@@ -386,7 +420,7 @@ class CurrentProcess(Process):
|
||||
def pid(self):
|
||||
"""Process ID
|
||||
|
||||
:type: int
|
||||
:type: :class:`int`
|
||||
"""
|
||||
return os.getpid()
|
||||
|
||||
@@ -395,7 +429,7 @@ class CurrentProcess(Process):
|
||||
def ppid(self):
|
||||
"""Parent Process ID
|
||||
|
||||
:type: int
|
||||
:type: :class:`int`
|
||||
"""
|
||||
return [p for p in windows.system.processes if p.pid == self.pid][0].ppid
|
||||
|
||||
@@ -411,7 +445,7 @@ class CurrentProcess(Process):
|
||||
def bitness(self):
|
||||
"""The bitness of the process
|
||||
|
||||
:returns: int -- 32 or 64"""
|
||||
:type: :class:`int` -- 32 or 64"""
|
||||
import platform
|
||||
bits = platform.architecture()[0]
|
||||
return int(bits[:2])
|
||||
@@ -419,7 +453,7 @@ class CurrentProcess(Process):
|
||||
def virtual_alloc(self, size):
|
||||
"""Allocate memory in the current process
|
||||
|
||||
:returns: int
|
||||
:returns: :class:`int`
|
||||
"""
|
||||
return winproxy.VirtualAlloc(dwSize=size)
|
||||
|
||||
@@ -440,6 +474,8 @@ class CurrentProcess(Process):
|
||||
|
||||
.. note::
|
||||
CreateThread https://msdn.microsoft.com/en-us/library/windows/desktop/ms682453%28v=vs.85%29.aspx
|
||||
|
||||
:rtype: :class:`WinThread` or :class:`DeadThread`
|
||||
"""
|
||||
handle = winproxy.CreateThread(lpStartAddress=lpStartAddress, lpParameter=lpParameter, dwCreationFlags=dwCreationFlags)
|
||||
return WinThread._from_handle(handle)
|
||||
@@ -462,7 +498,7 @@ class WinProcess(PROCESSENTRY32, Process):
|
||||
def name(self):
|
||||
"""Name of the process
|
||||
|
||||
:type: str
|
||||
:type: :class:`str`
|
||||
"""
|
||||
return self.szExeFile[:].decode()
|
||||
|
||||
@@ -470,7 +506,7 @@ class WinProcess(PROCESSENTRY32, Process):
|
||||
def pid(self):
|
||||
"""Process ID
|
||||
|
||||
:type: int
|
||||
:type: :class:`int`
|
||||
"""
|
||||
return self.th32ProcessID
|
||||
|
||||
@@ -478,7 +514,7 @@ class WinProcess(PROCESSENTRY32, Process):
|
||||
def ppid(self):
|
||||
"""Parent Process ID
|
||||
|
||||
:type: int
|
||||
:type: :class:`int`
|
||||
"""
|
||||
return self.th32ParentProcessID
|
||||
|
||||
@@ -491,7 +527,7 @@ class WinProcess(PROCESSENTRY32, Process):
|
||||
def virtual_alloc(self, size):
|
||||
"""Allocate memory in the process
|
||||
|
||||
:returns: int
|
||||
:rtype: :class:`int`
|
||||
"""
|
||||
return winproxy.VirtualAllocEx(self.handle, dwSize=size)
|
||||
|
||||
@@ -532,12 +568,17 @@ class WinProcess(PROCESSENTRY32, Process):
|
||||
# return page_data[addr & 0xfff: (addr & 0xfff) + size]
|
||||
|
||||
def read_memory_into(self, addr, struct):
|
||||
"""Read a :mod:`ctypes` struct from `addr`"""
|
||||
"""Read a :mod:`ctypes` struct from `addr`
|
||||
|
||||
:returns: struct"""
|
||||
self.low_read_memory(addr, ctypes.byref(struct), ctypes.sizeof(struct))
|
||||
return struct
|
||||
|
||||
def create_thread(self, addr, param):
|
||||
"""Create a remote thread"""
|
||||
"""Create a remote thread
|
||||
|
||||
:rtype: :class:`WinThread` or :class:`DeadThread`
|
||||
"""
|
||||
if windows.current_process.bitness == 32 and self.bitness == 64:
|
||||
thread_handle = HANDLE()
|
||||
windows.syswow64.NtCreateThreadEx_32_to_64(ThreadHandle=byref(thread_handle) ,ProcessHandle=self.handle, lpStartAddress=addr, lpParameter=param)
|
||||
@@ -552,15 +593,25 @@ class WinProcess(PROCESSENTRY32, Process):
|
||||
return self.create_thread(LoadLibrary, x)
|
||||
|
||||
def execute_python(self, pycode):
|
||||
"""Execute Python code into the remote process"""
|
||||
"""Execute Python code into the remote process.
|
||||
|
||||
This function waits for the remote process to end and
|
||||
raises an exception if the remote thread raised one"""
|
||||
return injection.safe_execute_python(self, pycode)
|
||||
|
||||
def execute_python_unsafe(self, pycode):
|
||||
"""Execute Python code into the remote process"""
|
||||
"""Execute Python code into the remote process.
|
||||
|
||||
Unsafe means that no information are returned about the execution of the thread
|
||||
"""
|
||||
return injection.execute_python_code(self, pycode)
|
||||
|
||||
@utils.fixedpropety
|
||||
def peb_addr(self):
|
||||
"""The address of the PEB
|
||||
|
||||
:type: :class:`int`
|
||||
"""
|
||||
if windows.current_process.bitness == 32 and self.bitness == 64:
|
||||
x = windows.remotectypes.transform_type_to_remote64bits(PROCESS_BASIC_INFORMATION)
|
||||
# Fuck-it <3
|
||||
@@ -584,6 +635,10 @@ class WinProcess(PROCESSENTRY32, Process):
|
||||
|
||||
@utils.fixedpropety
|
||||
def peb(self):
|
||||
"""The PEB of the remote process (see :mod:`remotectypes`)
|
||||
|
||||
:type: :class:`PEB`
|
||||
"""
|
||||
if windows.current_process.bitness == 32 and self.bitness == 64:
|
||||
return RemotePEB64(self.peb_addr, self)
|
||||
if windows.current_process.bitness == 64 and self.bitness == 32:
|
||||
@@ -599,9 +654,9 @@ class LoadedModule(LDR_DATA_TABLE_ENTRY):
|
||||
"""An entry in the PEB Ldr list"""
|
||||
@property
|
||||
def baseaddr(self):
|
||||
"""base address of the module
|
||||
"""Base address of the module
|
||||
|
||||
:type: int
|
||||
:type: :class:`int`
|
||||
"""
|
||||
return self.DllBase
|
||||
|
||||
@@ -609,7 +664,7 @@ class LoadedModule(LDR_DATA_TABLE_ENTRY):
|
||||
def name(self):
|
||||
"""Name of the module
|
||||
|
||||
:type: str
|
||||
:type: :class:`str`
|
||||
"""
|
||||
return str(self.BaseDllName.Buffer).lower()
|
||||
|
||||
@@ -617,7 +672,7 @@ class LoadedModule(LDR_DATA_TABLE_ENTRY):
|
||||
def fullname(self):
|
||||
"""Full name of the module (path)
|
||||
|
||||
:type: str
|
||||
:type: :class:`str`
|
||||
"""
|
||||
return self.FullDllName.Buffer.decode()
|
||||
|
||||
@@ -635,6 +690,9 @@ class LoadedModule(LDR_DATA_TABLE_ENTRY):
|
||||
|
||||
class WinUnicodeString(LSA_UNICODE_STRING):
|
||||
"""LSA_UNICODE_STRING with a nice `__repr__`"""
|
||||
fields = [f[0] for f in LSA_UNICODE_STRING._fields_]
|
||||
"""The fields of the structure"""
|
||||
|
||||
def __repr__(self):
|
||||
return """<{0} "{1}" at {2}>""".format(type(self).__name__, self.Buffer, hex(id(self)))
|
||||
|
||||
|
||||
Reference in New Issue
Block a user