mirror of
https://github.com/hakril/PythonForWindows
synced 2026-06-08 14:31:45 +00:00
Add get_mapped_filename to WinProcess
This commit is contained in:
@@ -45,6 +45,7 @@ NTSTATUS WINAPI NtQuerySystemInformation(
|
||||
_Out_opt_ PULONG ReturnLength
|
||||
);
|
||||
|
||||
|
||||
NTSTATUS WINAPI NtQueryInformationProcess(
|
||||
_In_ HANDLE ProcessHandle,
|
||||
_In_ PROCESSINFOCLASS ProcessInformationClass,
|
||||
@@ -748,3 +749,16 @@ BOOL WINAPI Wow64SetThreadContext(
|
||||
__in CONST WOW64_CONTEXT *lpContext
|
||||
);
|
||||
|
||||
DWORD WINAPI GetMappedFileNameW (
|
||||
__in HANDLE hProcess,
|
||||
__in LPVOID lpv,
|
||||
__out PVOID lpFilename,
|
||||
__in DWORD nSize
|
||||
);
|
||||
|
||||
DWORD WINAPI GetMappedFileNameA (
|
||||
__in HANDLE hProcess,
|
||||
__in LPVOID lpv,
|
||||
__out PVOID lpFilename,
|
||||
__in DWORD nSize
|
||||
);
|
||||
+2
-1
@@ -22,9 +22,10 @@ current_thread = CurrentThread()
|
||||
# Late import: other imports should go here
|
||||
# Do not move it: risk of circular import
|
||||
|
||||
import windows.vectored_exception
|
||||
import windows.exception
|
||||
import windows.wmi
|
||||
import windows.utils
|
||||
import windows.debug
|
||||
|
||||
__all__ = ["system", "VirtualProtected", 'current_process', 'current_thread', 'winproxy']
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ from ctypes import *
|
||||
from ctypes.wintypes import *
|
||||
from .winstructs import *
|
||||
|
||||
functions = ['ExitProcess', 'TerminateProcess', 'GetLastError', 'GetCurrentProcess', 'CreateFileA', 'CreateFileW', 'LdrLoadDll', 'NtQuerySystemInformation', 'NtQueryInformationProcess', 'NtQueryVirtualMemory', 'NtCreateThreadEx', 'NtQueryInformationThread', 'GetExitCodeThread', 'GetExitCodeProcess', 'VirtualAlloc', 'VirtualAllocEx', 'VirtualFree', 'VirtualFreeEx', 'VirtualProtect', 'VirtualQuery', 'VirtualQueryEx', 'GetModuleFileNameA', 'GetModuleFileNameW', 'CreateThread', 'CreateRemoteThread', 'VirtualProtect', 'CreateProcessA', 'CreateProcessW', 'GetThreadContext', 'NtGetContextThread', 'SetThreadContext', 'NtSetContextThread', 'OpenThread', 'OpenProcess', 'CloseHandle', 'ReadProcessMemory', 'NtWow64ReadVirtualMemory64', 'WriteProcessMemory', 'CreateToolhelp32Snapshot', 'Thread32First', 'Thread32Next', 'Process32First', 'Process32Next', 'Process32FirstW', 'Process32NextW', 'GetProcAddress', 'LoadLibraryA', 'LoadLibraryW', 'OpenProcessToken', 'LookupPrivilegeValueA', 'LookupPrivilegeValueW', 'AdjustTokenPrivileges', 'FindResourceA', 'FindResourceW', 'SizeofResource', 'LoadResource', 'LockResource', 'GetVersionExA', 'GetVersionExW', 'GetVersion', 'GetCurrentThread', 'GetCurrentThreadId', 'GetCurrentProcessorNumber', 'AllocConsole', 'FreeConsole', 'GetStdHandle', 'SetStdHandle', 'SetThreadAffinityMask', 'WriteFile', 'GetExtendedTcpTable', 'GetExtendedUdpTable', 'SetTcpEntry', 'AddVectoredContinueHandler', 'AddVectoredExceptionHandler', 'TerminateThread', 'ExitThread', 'RemoveVectoredExceptionHandler', 'ResumeThread', 'SuspendThread', 'WaitForSingleObject', 'GetThreadId', 'LoadLibraryExA', 'LoadLibraryExW', 'SymInitialize', 'SymFromName', 'SymLoadModuleEx', 'SymSetOptions', 'SymGetTypeInfo', 'DeviceIoControl', 'GetTokenInformation', 'RegOpenKeyExA', 'RegOpenKeyExW', 'RegGetValueA', 'RegGetValueW', 'RegCloseKey', 'Wow64DisableWow64FsRedirection', 'Wow64RevertWow64FsRedirection', 'Wow64EnableWow64FsRedirection', 'Wow64GetThreadContext', 'SetConsoleCtrlHandler', 'WinVerifyTrust', 'GlobalAlloc', 'GlobalFree', 'GlobalUnlock', 'GlobalLock', 'OpenClipboard', 'EmptyClipboard', 'CloseClipboard', 'SetClipboardData', 'GetClipboardData', 'EnumClipboardFormats', 'GetClipboardFormatNameA', 'GetClipboardFormatNameW', 'WinVerifyTrust', 'OpenProcessToken', 'OpenThreadToken', 'GetTokenInformation', 'SetTokenInformation', 'GetSidIdentifierAuthority', 'GetSidSubAuthority', 'GetSidSubAuthorityCount', 'DebugBreak', 'WaitForDebugEvent', 'ContinueDebugEvent', 'DebugActiveProcess', 'DebugActiveProcessStop', 'DebugSetProcessKillOnExit', 'DebugBreakProcess', 'GetProcessId', 'Wow64SetThreadContext']
|
||||
functions = ['ExitProcess', 'TerminateProcess', 'GetLastError', 'GetCurrentProcess', 'CreateFileA', 'CreateFileW', 'LdrLoadDll', 'NtQuerySystemInformation', 'NtQueryInformationProcess', 'NtQueryVirtualMemory', 'NtCreateThreadEx', 'NtQueryInformationThread', 'GetExitCodeThread', 'GetExitCodeProcess', 'VirtualAlloc', 'VirtualAllocEx', 'VirtualFree', 'VirtualFreeEx', 'VirtualProtect', 'VirtualQuery', 'VirtualQueryEx', 'GetModuleFileNameA', 'GetModuleFileNameW', 'CreateThread', 'CreateRemoteThread', 'VirtualProtect', 'CreateProcessA', 'CreateProcessW', 'GetThreadContext', 'NtGetContextThread', 'SetThreadContext', 'NtSetContextThread', 'OpenThread', 'OpenProcess', 'CloseHandle', 'ReadProcessMemory', 'NtWow64ReadVirtualMemory64', 'WriteProcessMemory', 'CreateToolhelp32Snapshot', 'Thread32First', 'Thread32Next', 'Process32First', 'Process32Next', 'Process32FirstW', 'Process32NextW', 'GetProcAddress', 'LoadLibraryA', 'LoadLibraryW', 'OpenProcessToken', 'LookupPrivilegeValueA', 'LookupPrivilegeValueW', 'AdjustTokenPrivileges', 'FindResourceA', 'FindResourceW', 'SizeofResource', 'LoadResource', 'LockResource', 'GetVersionExA', 'GetVersionExW', 'GetVersion', 'GetCurrentThread', 'GetCurrentThreadId', 'GetCurrentProcessorNumber', 'AllocConsole', 'FreeConsole', 'GetStdHandle', 'SetStdHandle', 'SetThreadAffinityMask', 'WriteFile', 'GetExtendedTcpTable', 'GetExtendedUdpTable', 'SetTcpEntry', 'AddVectoredContinueHandler', 'AddVectoredExceptionHandler', 'TerminateThread', 'ExitThread', 'RemoveVectoredExceptionHandler', 'ResumeThread', 'SuspendThread', 'WaitForSingleObject', 'GetThreadId', 'LoadLibraryExA', 'LoadLibraryExW', 'SymInitialize', 'SymFromName', 'SymLoadModuleEx', 'SymSetOptions', 'SymGetTypeInfo', 'DeviceIoControl', 'GetTokenInformation', 'RegOpenKeyExA', 'RegOpenKeyExW', 'RegGetValueA', 'RegGetValueW', 'RegCloseKey', 'Wow64DisableWow64FsRedirection', 'Wow64RevertWow64FsRedirection', 'Wow64EnableWow64FsRedirection', 'Wow64GetThreadContext', 'SetConsoleCtrlHandler', 'WinVerifyTrust', 'GlobalAlloc', 'GlobalFree', 'GlobalUnlock', 'GlobalLock', 'OpenClipboard', 'EmptyClipboard', 'CloseClipboard', 'SetClipboardData', 'GetClipboardData', 'EnumClipboardFormats', 'GetClipboardFormatNameA', 'GetClipboardFormatNameW', 'WinVerifyTrust', 'OpenProcessToken', 'OpenThreadToken', 'GetTokenInformation', 'SetTokenInformation', 'GetSidIdentifierAuthority', 'GetSidSubAuthority', 'GetSidSubAuthorityCount', 'DebugBreak', 'WaitForDebugEvent', 'ContinueDebugEvent', 'DebugActiveProcess', 'DebugActiveProcessStop', 'DebugSetProcessKillOnExit', 'DebugBreakProcess', 'GetProcessId', 'Wow64SetThreadContext', 'GetMappedFileNameW', 'GetMappedFileNameA']
|
||||
|
||||
# ExitProcess(uExitCode):
|
||||
ExitProcessPrototype = WINFUNCTYPE(VOID, UINT)
|
||||
@@ -525,3 +525,11 @@ GetProcessIdParams = ((1, 'Process'),)
|
||||
Wow64SetThreadContextPrototype = WINFUNCTYPE(BOOL, HANDLE, POINTER(WOW64_CONTEXT))
|
||||
Wow64SetThreadContextParams = ((1, 'hThread'), (1, 'lpContext'))
|
||||
|
||||
# GetMappedFileNameW(hProcess, lpv, lpFilename, nSize):
|
||||
GetMappedFileNameWPrototype = WINFUNCTYPE(DWORD, HANDLE, LPVOID, PVOID, DWORD)
|
||||
GetMappedFileNameWParams = ((1, 'hProcess'), (1, 'lpv'), (1, 'lpFilename'), (1, 'nSize'))
|
||||
|
||||
# GetMappedFileNameA(hProcess, lpv, lpFilename, nSize):
|
||||
GetMappedFileNameAPrototype = WINFUNCTYPE(DWORD, HANDLE, LPVOID, PVOID, DWORD)
|
||||
GetMappedFileNameAParams = ((1, 'hProcess'), (1, 'lpv'), (1, 'lpFilename'), (1, 'nSize'))
|
||||
|
||||
|
||||
+99
-102
@@ -11,7 +11,7 @@ import windows
|
||||
import windows.network
|
||||
import windows.registry
|
||||
import windows.syswow64
|
||||
#import windows.vectored_exception
|
||||
import windows.exception
|
||||
import windows.winproxy as winproxy
|
||||
import windows.injection as injection
|
||||
import windows.native_exec as native_exec
|
||||
@@ -71,27 +71,21 @@ class System(object):
|
||||
def processes(self):
|
||||
"""The list of running processes
|
||||
|
||||
:type: [:class:`WinProcess`] -- A list of Process
|
||||
|
||||
"""
|
||||
:type: [:class:`WinProcess`] -- A list of Process"""
|
||||
return self.enumerate_processes()
|
||||
|
||||
@property
|
||||
def threads(self):
|
||||
"""The list of running threads
|
||||
|
||||
:type: [:class:`WinThread`] -- A list of Thread
|
||||
|
||||
"""
|
||||
:type: [:class:`WinThread`] -- A list of Thread"""
|
||||
return self.enumerate_threads()
|
||||
|
||||
@utils.fixedpropety
|
||||
def bitness(self):
|
||||
"""The bitness of the system
|
||||
|
||||
:type: :class:`int` -- 32 or 64
|
||||
|
||||
"""
|
||||
:type: :class:`int` -- 32 or 64"""
|
||||
if os.environ["PROCESSOR_ARCHITECTURE"].lower() != "x86":
|
||||
return 64
|
||||
if "PROCESSOR_ARCHITEW6432" in os.environ:
|
||||
@@ -136,9 +130,7 @@ class WinThread(THREADENTRY32, AutoHandle):
|
||||
def owner(self):
|
||||
"""The Process owning the thread
|
||||
|
||||
:type: :class:`WinProcess`
|
||||
|
||||
"""
|
||||
:type: :class:`WinProcess`"""
|
||||
if hasattr(self, "_owner"):
|
||||
return self._owner
|
||||
try:
|
||||
@@ -149,28 +141,32 @@ class WinThread(THREADENTRY32, AutoHandle):
|
||||
|
||||
@property
|
||||
def context(self):
|
||||
"""The context of the thread, type depend of the target process.
|
||||
|
||||
:type: :class:`windows.exception.ECONTEXT32` or :class:`windows.exception.ECONTEXT64` or :class:`windows.exception.ECONTEXTWOW64` """
|
||||
if self.owner.bitness == 32 and windows.current_process.bitness == 64:
|
||||
# Wow64
|
||||
x = windows.vectored_exception.EnhancedCONTEXTWOW64()
|
||||
x = windows.exception.ECONTEXTWOW64()
|
||||
x.ContextFlags = CONTEXT_ALL
|
||||
winproxy.Wow64GetThreadContext(self.handle, x)
|
||||
return x
|
||||
|
||||
if self.owner.bitness == 64 and windows.current_process.bitness == 32:
|
||||
x = windows.vectored_exception.EnhancedCONTEXT64.new_aligned()
|
||||
x = windows.exception.ECONTEXT64.new_aligned()
|
||||
x.ContextFlags = CONTEXT_ALL
|
||||
windows.syswow64.NtGetContextThread_32_to_64(self.handle, x)
|
||||
return x
|
||||
|
||||
if self.owner.bitness == 32:
|
||||
x = windows.vectored_exception.EnhancedCONTEXT32()
|
||||
x = windows.exception.ECONTEXT32()
|
||||
else:
|
||||
x = windows.vectored_exception.EnhancedCONTEXT64.new_aligned()
|
||||
x = windows.exception.ECONTEXT64.new_aligned()
|
||||
x.ContextFlags = CONTEXT_ALL
|
||||
winproxy.GetThreadContext(self.handle, x)
|
||||
return x
|
||||
|
||||
def set_context(self, context):
|
||||
"""Set the thread context to ``context``"""
|
||||
if self.owner.bitness == windows.current_process.bitness:
|
||||
return winproxy.SetThreadContext(self.handle, context)
|
||||
if windows.current_process.bitness == 64 and self.owner.bitness == 32:
|
||||
@@ -181,8 +177,7 @@ class WinThread(THREADENTRY32, AutoHandle):
|
||||
def start_address(self):
|
||||
"""The start address of the thread
|
||||
|
||||
:type: :class:`int`
|
||||
"""
|
||||
: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))
|
||||
@@ -214,16 +209,14 @@ class WinThread(THREADENTRY32, AutoHandle):
|
||||
def is_exit(self):
|
||||
"""Is ``True`` if the thread is terminated
|
||||
|
||||
:type: :class:`bool`
|
||||
"""
|
||||
: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`
|
||||
"""
|
||||
:type: :class:`int`"""
|
||||
res = DWORD()
|
||||
winproxy.GetExitCodeThread(self.handle, byref(res))
|
||||
return res.value
|
||||
@@ -263,16 +256,14 @@ class DeadThread(AutoHandle):
|
||||
def is_exit(self):
|
||||
"""Is ``True`` if the thread is terminated
|
||||
|
||||
:type: :class:`bool`
|
||||
"""
|
||||
: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`
|
||||
"""
|
||||
:type: :class:`int`"""
|
||||
res = DWORD()
|
||||
winproxy.GetExitCodeThread(self.handle, byref(res))
|
||||
return res.value
|
||||
@@ -283,8 +274,7 @@ class Process(AutoHandle):
|
||||
def is_wow_64(self):
|
||||
"""``True`` if the process is a SysWow64 process (32bit process on 64bits system).
|
||||
|
||||
:type: :class:`bool`
|
||||
"""
|
||||
:type: :class:`bool`"""
|
||||
return utils.is_wow_64(self.handle)
|
||||
|
||||
@utils.fixedpropety
|
||||
@@ -302,8 +292,7 @@ class Process(AutoHandle):
|
||||
def threads(self):
|
||||
"""The threads of the process
|
||||
|
||||
:type: [:class:`WinThread`] -- A list of Thread
|
||||
"""
|
||||
:type: [:class:`WinThread`] -- A list of Thread"""
|
||||
return [thread for thread in windows.system.threads if thread.th32OwnerProcessID == self.pid]
|
||||
|
||||
def virtual_alloc(self, size):
|
||||
@@ -316,8 +305,7 @@ class Process(AutoHandle):
|
||||
def exit_code(self):
|
||||
"""The exit code of the process : ``STILL_ACTIVE`` means the process is not dead
|
||||
|
||||
:type: :class:`int`
|
||||
"""
|
||||
:type: :class:`int`"""
|
||||
res = DWORD()
|
||||
winproxy.GetExitCodeProcess(self.handle, byref(res))
|
||||
return res.value
|
||||
@@ -326,12 +314,14 @@ class Process(AutoHandle):
|
||||
def is_exit(self):
|
||||
"""``True`` if the process is terminated
|
||||
|
||||
:type: :class:`bool`
|
||||
"""
|
||||
:type: :class:`bool`"""
|
||||
return self.exit_code != STILL_ACTIVE
|
||||
|
||||
@contextmanager
|
||||
def allocated_memory(self, size):
|
||||
"""ContextManager to allocate memory and free it
|
||||
|
||||
:type: :class:`int` -- the address of the allocated memory"""
|
||||
addr = self.virtual_alloc(size)
|
||||
try:
|
||||
yield addr
|
||||
@@ -350,8 +340,7 @@ class Process(AutoHandle):
|
||||
def query_memory(self, addr):
|
||||
"""Query the memory informations about page at ``addr``
|
||||
|
||||
:rtype: :class:`MEMORY_BASIC_INFORMATION`
|
||||
"""
|
||||
:rtype: :class:`MEMORY_BASIC_INFORMATION`"""
|
||||
if windows.current_process.bitness == 32 and self.bitness == 64:
|
||||
res = MEMORY_BASIC_INFORMATION64()
|
||||
try:
|
||||
@@ -371,8 +360,7 @@ class Process(AutoHandle):
|
||||
def memory_state(self):
|
||||
"""Yield the memory information for the whole address space of the process
|
||||
|
||||
:yield: :class:`MEMORY_BASIC_INFORMATION`
|
||||
"""
|
||||
:yield: :class:`MEMORY_BASIC_INFORMATION`"""
|
||||
addr = 0
|
||||
res = []
|
||||
while True:
|
||||
@@ -383,24 +371,40 @@ class Process(AutoHandle):
|
||||
return
|
||||
addr += x.RegionSize
|
||||
|
||||
def read_char(self, addr):
|
||||
def mapped_filename(self, addr):
|
||||
"""The filename mapped at address ``addr`` or None
|
||||
|
||||
:rtype: :class:`str` or None"""
|
||||
buffer = ctypes.c_buffer(0x1024)
|
||||
try:
|
||||
size = windows.winproxy.GetMappedFileNameA(self.handle, addr, buffer)
|
||||
except windows.winproxy.Kernel32Error:
|
||||
return None
|
||||
return buffer[:size]
|
||||
|
||||
def read_byte(self, addr):
|
||||
"""Read a ``CHAR`` at ``addr``"""
|
||||
sizeof_char = sizeof(CHAR)
|
||||
return struct.unpack("<B", self.read_memory(addr, sizeof_char))[0]
|
||||
|
||||
def read_dword(self, addr):
|
||||
"""Read a ``DWORD`` at ``addr``"""
|
||||
sizeof_dword = sizeof(DWORD)
|
||||
return struct.unpack("<I", self.read_memory(addr, sizeof_dword))[0]
|
||||
|
||||
def read_qword(self, addr):
|
||||
"""Read a ``ULONG64`` at ``addr``"""
|
||||
sizeof_qword = sizeof(ULONG64)
|
||||
return struct.unpack("<Q", self.read_memory(addr, sizeof_qword))[0]
|
||||
|
||||
def read_ptr(self, addr):
|
||||
"""Read a ``PTR`` at ``addr``"""
|
||||
if self.bitness == 32:
|
||||
return self.read_dword(addr)
|
||||
return self.read_qword(addr)
|
||||
|
||||
def read_string(self, addr):
|
||||
"""Read an ascii string at ``addr``"""
|
||||
res = []
|
||||
for i in itertools.count():
|
||||
x = self.read_memory(addr + (i * 0x100), 0x100)
|
||||
@@ -411,6 +415,7 @@ class Process(AutoHandle):
|
||||
return "".join(res)
|
||||
|
||||
def read_wstring(self, addr):
|
||||
"""Read a windows UTF16 string at ``addr``"""
|
||||
res = []
|
||||
for i in itertools.count():
|
||||
x = self.read_memory(addr + (i * 0x100), 0x100)
|
||||
@@ -422,24 +427,26 @@ class Process(AutoHandle):
|
||||
return "".join(res).decode('utf16')
|
||||
|
||||
def write_byte(self, addr, byte):
|
||||
"""write a byte to virtual memory"""
|
||||
"""write a byte at ``addr``"""
|
||||
return self.write_memory(addr, struct.pack("<B", byte))
|
||||
|
||||
def write_word(self, addr, word):
|
||||
"""write a word to virtual memory"""
|
||||
"""write a word at ``addr``"""
|
||||
return self.write_memory(addr, struct.pack("<H", word))
|
||||
|
||||
def write_dword(self, addr, dword):
|
||||
"""write a dword to virtual memory"""
|
||||
"""write a dword at ``addr``"""
|
||||
return self.write_memory(addr, struct.pack("<I", dword))
|
||||
|
||||
def write_qword(self, addr, qword):
|
||||
"""write a qword to virtual memory"""
|
||||
"""write a qword at ``addr``"""
|
||||
return self.write_memory(addr, struct.pack("<Q", qword))
|
||||
|
||||
@utils.fixedpropety
|
||||
def token(self):
|
||||
"""TODO: DOC"""
|
||||
"""The token of the process
|
||||
|
||||
:type: :class:`Token`"""
|
||||
token_handle = HANDLE()
|
||||
winproxy.OpenProcessToken(self.handle, TOKEN_ALL_ACCESS, byref(token_handle))
|
||||
return Token(token_handle.value)
|
||||
@@ -458,8 +465,7 @@ class CurrentThread(AutoHandle):
|
||||
def owner(self):
|
||||
"""The current process
|
||||
|
||||
:type: :class:`CurrentProcess`
|
||||
"""
|
||||
:type: :class:`CurrentProcess`"""
|
||||
return windows.current_process
|
||||
|
||||
def _get_handle(self):
|
||||
@@ -513,8 +519,7 @@ class CurrentProcess(Process):
|
||||
def pid(self):
|
||||
"""Process ID
|
||||
|
||||
:type: :class:`int`
|
||||
"""
|
||||
:type: :class:`int`"""
|
||||
return os.getpid()
|
||||
|
||||
# Is there a better way ?
|
||||
@@ -522,16 +527,14 @@ class CurrentProcess(Process):
|
||||
def ppid(self):
|
||||
"""Parent Process ID
|
||||
|
||||
:type: :class:`int`
|
||||
"""
|
||||
:type: :class:`int`"""
|
||||
return [p for p in windows.system.processes if p.pid == self.pid][0].ppid
|
||||
|
||||
@utils.fixedpropety
|
||||
def peb(self):
|
||||
"""The Process Environment Block of the current process
|
||||
|
||||
:type: :class:`PEB`
|
||||
"""
|
||||
:type: :class:`PEB`"""
|
||||
return PEB.from_address(self.get_peb_builtin()())
|
||||
|
||||
@utils.fixedpropety
|
||||
@@ -547,8 +550,7 @@ class CurrentProcess(Process):
|
||||
"""Allocate memory in the process
|
||||
|
||||
:return: The address of the allocated memory
|
||||
:rtype: :class:`int`
|
||||
"""
|
||||
:rtype: :class:`int`"""
|
||||
return winproxy.VirtualAlloc(dwSize=size)
|
||||
|
||||
def virtual_free(self, addr):
|
||||
@@ -565,8 +567,7 @@ class CurrentProcess(Process):
|
||||
"""Read ``size`` from ``addr``
|
||||
|
||||
:return: The data read
|
||||
:rtype: :class:`str`
|
||||
"""
|
||||
:rtype: :class:`str`"""
|
||||
dbgprint('Read CurrentProcess Memory', 'READMEM')
|
||||
buffer = (c_char * size).from_address(addr)
|
||||
return buffer[:]
|
||||
@@ -574,8 +575,7 @@ class CurrentProcess(Process):
|
||||
def create_thread(self, lpStartAddress, lpParameter, dwCreationFlags=0):
|
||||
"""Create a new thread
|
||||
|
||||
:rtype: :class:`WinThread` or :class:`DeadThread`
|
||||
"""
|
||||
:rtype: :class:`WinThread` or :class:`DeadThread`"""
|
||||
handle = winproxy.CreateThread(lpStartAddress=lpStartAddress, lpParameter=lpParameter, dwCreationFlags=dwCreationFlags)
|
||||
return WinThread._from_handle(handle)
|
||||
|
||||
@@ -587,6 +587,14 @@ class CurrentProcess(Process):
|
||||
"""Raise ``ValueError`` to prevent deadlock :D"""
|
||||
raise ValueError("wait() on current thread")
|
||||
|
||||
@utils.fixedpropety
|
||||
def peb_syswow(self):
|
||||
"""The 64bits PEB of a SysWow64 process
|
||||
|
||||
:type: :class:`PEB`"""
|
||||
if not self.is_wow_64:
|
||||
raise ValueError("Not a syswow process")
|
||||
return windows.syswow64.get_current_process_syswow_peb()
|
||||
|
||||
class WinProcess(PROCESSENTRY32, Process):
|
||||
"""A Process on the system"""
|
||||
@@ -606,24 +614,21 @@ class WinProcess(PROCESSENTRY32, Process):
|
||||
def name(self):
|
||||
"""Name of the process
|
||||
|
||||
:type: :class:`str`
|
||||
"""
|
||||
:type: :class:`str`"""
|
||||
return self.szExeFile[:].decode()
|
||||
|
||||
@utils.fixedpropety
|
||||
def pid(self):
|
||||
"""Process ID
|
||||
|
||||
:type: :class:`int`
|
||||
"""
|
||||
:type: :class:`int`"""
|
||||
return self.th32ProcessID
|
||||
|
||||
@utils.fixedpropety
|
||||
def ppid(self):
|
||||
"""Parent Process ID
|
||||
|
||||
:type: :class:`int`
|
||||
"""
|
||||
:type: :class:`int`"""
|
||||
return self.th32ParentProcessID
|
||||
|
||||
def _get_handle(self):
|
||||
@@ -636,8 +641,7 @@ class WinProcess(PROCESSENTRY32, Process):
|
||||
"""Allocate memory in the process
|
||||
|
||||
:return: The address of the allocated memory
|
||||
:rtype: :class:`int`
|
||||
"""
|
||||
:rtype: :class:`int`"""
|
||||
return winproxy.VirtualAllocEx(self.handle, dwSize=size)
|
||||
|
||||
def virtual_free(self, addr):
|
||||
@@ -652,16 +656,18 @@ class WinProcess(PROCESSENTRY32, Process):
|
||||
if windows.current_process.bitness == 32 and self.bitness == 64:
|
||||
# OptionalExport can be None (see winproxy.py)
|
||||
if winproxy.NtWow64ReadVirtualMemory64 is None:
|
||||
raise ValueError("NtWow64ReadVirtualMemory64 non available in ntdll: cannot write into 64bits processus")
|
||||
raise ValueError("NtWow64ReadVirtualMemory64 non available in ntdll: cannot read into 64bits processus")
|
||||
return winproxy.NtWow64ReadVirtualMemory64(self.handle, addr, buffer_addr, size)
|
||||
NtWow64ReadVirtualMemory64
|
||||
#if self.is_wow_64 and addr > 0xffffffff:
|
||||
# return winproxy.NtWow64ReadVirtualMemory64(self.handle, addr, buffer_addr, size)
|
||||
return winproxy.ReadProcessMemory(self.handle, addr, lpBuffer=buffer_addr, nSize=size)
|
||||
|
||||
def read_memory(self, addr, size):
|
||||
"""Read ``size`` from ``addr``
|
||||
|
||||
:return: The data read
|
||||
:rtype: :class:`str`
|
||||
"""
|
||||
:rtype: :class:`str`"""
|
||||
buffer = ctypes.create_string_buffer(size)
|
||||
self.low_read_memory(addr, ctypes.byref(buffer), size)
|
||||
return buffer[:]
|
||||
@@ -694,8 +700,7 @@ class WinProcess(PROCESSENTRY32, Process):
|
||||
def create_thread(self, addr, param):
|
||||
"""Create a remote thread
|
||||
|
||||
:rtype: :class:`WinThread` or :class:`DeadThread`
|
||||
"""
|
||||
: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)
|
||||
@@ -724,8 +729,7 @@ class WinProcess(PROCESSENTRY32, Process):
|
||||
def peb_addr(self):
|
||||
"""The address of the PEB
|
||||
|
||||
:type: :class:`int`
|
||||
"""
|
||||
: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
|
||||
@@ -751,8 +755,7 @@ class WinProcess(PROCESSENTRY32, Process):
|
||||
def peb(self):
|
||||
"""The PEB of the remote process (see :mod:`remotectypes`)
|
||||
|
||||
:type: :class:`PEB`
|
||||
"""
|
||||
: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:
|
||||
@@ -761,6 +764,9 @@ class WinProcess(PROCESSENTRY32, Process):
|
||||
|
||||
@utils.fixedpropety
|
||||
def peb_syswow(self):
|
||||
"""The 64bits PEB of a SysWow64 process
|
||||
|
||||
:type: :class:`PEB`"""
|
||||
if not self.is_wow_64:
|
||||
raise ValueError("Not a syswow process")
|
||||
if windows.current_process.bitness == 64:
|
||||
@@ -785,11 +791,15 @@ class WinProcess(PROCESSENTRY32, Process):
|
||||
|
||||
# Create ProcessToken and Thread Token objects ?
|
||||
class Token(AutoHandle):
|
||||
"""The token of a process"""
|
||||
def __init__(self, handle):
|
||||
self._handle = handle
|
||||
|
||||
@property
|
||||
def integrity(self):
|
||||
"""Return the integrity level of a process
|
||||
|
||||
:type: :class:`int`"""
|
||||
buffer_size = self.get_required_information_size(TokenIntegrityLevel)
|
||||
buffer = ctypes.c_buffer(buffer_size)
|
||||
self.get_informations(TokenIntegrityLevel, buffer)
|
||||
@@ -825,24 +835,21 @@ class LoadedModule(LDR_DATA_TABLE_ENTRY):
|
||||
def baseaddr(self):
|
||||
"""Base address of the module
|
||||
|
||||
:type: :class:`int`
|
||||
"""
|
||||
:type: :class:`int`"""
|
||||
return self.DllBase
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
"""Name of the module
|
||||
|
||||
:type: :class:`str`
|
||||
"""
|
||||
:type: :class:`str`"""
|
||||
return str(self.BaseDllName.Buffer).lower()
|
||||
|
||||
@property
|
||||
def fullname(self):
|
||||
"""Full name of the module (path)
|
||||
|
||||
:type: :class:`str`
|
||||
"""
|
||||
:type: :class:`str`"""
|
||||
return self.FullDllName.Buffer.decode()
|
||||
|
||||
def __repr__(self):
|
||||
@@ -852,8 +859,7 @@ class LoadedModule(LDR_DATA_TABLE_ENTRY):
|
||||
def pe(self):
|
||||
"""A PE representation of the module
|
||||
|
||||
:type: :class:`windows.pe_parse.PEFile`
|
||||
"""
|
||||
:type: :class:`windows.pe_parse.PEFile`"""
|
||||
return pe_parse.GetPEFile(self.baseaddr)
|
||||
|
||||
|
||||
@@ -892,16 +898,14 @@ class PEB(Structure):
|
||||
def imagepath(self):
|
||||
"""The ImagePathName of the PEB
|
||||
|
||||
:type: :class:`WinUnicodeString`
|
||||
"""
|
||||
:type: :class:`WinUnicodeString`"""
|
||||
return self.ProcessParameters.contents.ImagePathName
|
||||
|
||||
@property
|
||||
def commandline(self):
|
||||
"""The CommandLine of the PEB
|
||||
|
||||
:type: :class:`WinUnicodeString`
|
||||
"""
|
||||
:type: :class:`WinUnicodeString`"""
|
||||
# This or changing the __repr__ of LSA_UNICODE_STRING
|
||||
return self.ProcessParameters.contents.CommandLine
|
||||
|
||||
@@ -909,8 +913,7 @@ class PEB(Structure):
|
||||
def modules(self):
|
||||
"""The loaded modules present in the PEB
|
||||
|
||||
:type: [:class:`LoadedModule`] -- List of loaded modules
|
||||
"""
|
||||
:type: [:class:`LoadedModule`] -- List of loaded modules"""
|
||||
res = []
|
||||
list_entry_ptr = ctypes.cast(self.Ldr.contents.InMemoryOrderModuleList.Flink, LIST_ENTRY_PTR)
|
||||
current_dll = list_entry_ptr.TO_LDR_ENTRY()
|
||||
@@ -927,8 +930,7 @@ class RemoteLoadedModule(rctypes.RemoteStructure.from_structure(LoadedModule)):
|
||||
def pe(self):
|
||||
"""A PE representation of the module
|
||||
|
||||
:type: :class:`windows.pe_parse.PEFile`
|
||||
"""
|
||||
:type: :class:`windows.pe_parse.PEFile`"""
|
||||
return pe_parse.GetPEFile(self.baseaddr, target=self._target)
|
||||
|
||||
|
||||
@@ -941,8 +943,7 @@ class RemotePEB(rctypes.RemoteStructure.from_structure(PEB)):
|
||||
def modules(self):
|
||||
"""The loaded modules present in the PEB
|
||||
|
||||
:type: [:class:`LoadedModule`] -- List of loaded modules
|
||||
"""
|
||||
:type: [:class:`LoadedModule`] -- List of loaded modules"""
|
||||
res = []
|
||||
if not self.Ldr.value:
|
||||
raise ValueError("PEB->Ldr is NULL: cannot walk the module list")
|
||||
@@ -961,8 +962,7 @@ if CurrentProcess().bitness == 32:
|
||||
def pe(self):
|
||||
"""A PE representation of the module
|
||||
|
||||
:type: :class:`windows.pe_parse.PEFile`
|
||||
"""
|
||||
:type: :class:`windows.pe_parse.PEFile`"""
|
||||
return pe_parse.GetPEFile(self.baseaddr, target=self._target)
|
||||
|
||||
class RemotePEB64(rctypes.transform_type_to_remote64bits(PEB)):
|
||||
@@ -974,8 +974,7 @@ if CurrentProcess().bitness == 32:
|
||||
def modules(self):
|
||||
"""The loaded modules present in the PEB
|
||||
|
||||
:type: [:class:`LoadedModule`] -- List of loaded modules
|
||||
"""
|
||||
:type: [:class:`LoadedModule`] -- List of loaded modules"""
|
||||
res = []
|
||||
if not self.Ldr.value:
|
||||
raise ValueError("PEB->Ldr is NULL: cannot walk the module list")
|
||||
@@ -994,8 +993,7 @@ if CurrentProcess().bitness == 64:
|
||||
def pe(self):
|
||||
"""A PE representation of the module
|
||||
|
||||
:type: :class:`windows.pe_parse.PEFile`
|
||||
"""
|
||||
:type: :class:`windows.pe_parse.PEFile`"""
|
||||
return pe_parse.GetPEFile(self.baseaddr, target=self._target)
|
||||
|
||||
class RemotePEB32(rctypes.transform_type_to_remote32bits(PEB)):
|
||||
@@ -1007,8 +1005,7 @@ if CurrentProcess().bitness == 64:
|
||||
def modules(self):
|
||||
"""The loaded modules present in the PEB
|
||||
|
||||
:type: [:class:`LoadedModule`] -- List of loaded modules
|
||||
"""
|
||||
:type: [:class:`LoadedModule`] -- List of loaded modules"""
|
||||
res = []
|
||||
if not self.Ldr.value:
|
||||
raise ValueError("PEB->Ldr is NULL: cannot walk the module list")
|
||||
|
||||
+44
-8
@@ -136,6 +136,7 @@ class ApiProxy(object):
|
||||
return self._cprototyped(*args)
|
||||
|
||||
setattr(python_proxy, "ctypes_function", perform_call)
|
||||
setattr(python_proxy, "force_resolution", generate_ctypes_function)
|
||||
return python_proxy
|
||||
|
||||
|
||||
@@ -166,7 +167,9 @@ class Ole32Proxy(ApiProxy):
|
||||
APIDLL = "ole32"
|
||||
default_error_check = staticmethod(no_error_check)
|
||||
|
||||
|
||||
class PsapiProxy(ApiProxy):
|
||||
APIDLL = "psapi"
|
||||
default_error_check = staticmethod(kernel32_error_check)
|
||||
|
||||
class OptionalExport(object):
|
||||
"""used 'around' a Proxy decorator
|
||||
@@ -183,7 +186,9 @@ class OptionalExport(object):
|
||||
|
||||
def __call__(self, f):
|
||||
try:
|
||||
return self.subdecorator(f)
|
||||
x = self.subdecorator(f)
|
||||
x.force_resolution()
|
||||
return x
|
||||
except ExportNotFound as e:
|
||||
dbgprint("Export <{e.func_name}> not found in <{e.api_name}>".format(e=e), "EXPORTNOTFOUND")
|
||||
return None
|
||||
@@ -200,14 +205,17 @@ class TransparentApiProxy(object):
|
||||
|
||||
def __call__(self, *args, **kwargs):
|
||||
if self._ctypes_function is None:
|
||||
try:
|
||||
c_prototyped = self.prototype((self.func_name, getattr(ctypes.windll, self.dll_name)), self.args)
|
||||
except AttributeError:
|
||||
raise ExportNotFound(func_name, APIDLL)
|
||||
c_prototyped.errcheck = functools.wraps(self.error_check)(functools.partial(self.error_check, self.func_name))
|
||||
self._ctypes_function = c_prototyped
|
||||
self.force_resolution()
|
||||
return self._ctypes_function(*args, **kwargs)
|
||||
|
||||
def force_resolution(self):
|
||||
try:
|
||||
c_prototyped = self.prototype((self.func_name, getattr(ctypes.windll, self.dll_name)), self.args)
|
||||
except AttributeError:
|
||||
raise ExportNotFound(func_name, APIDLL)
|
||||
c_prototyped.errcheck = functools.wraps(self.error_check)(functools.partial(self.error_check, self.func_name))
|
||||
self._ctypes_function = c_prototyped
|
||||
|
||||
|
||||
TransparentKernel32Proxy = lambda func_name, error_check=kernel32_error_check: TransparentApiProxy("kernel32", func_name, error_check)
|
||||
TransparentAdvapi32Proxy = lambda func_name, error_check=kernel32_error_check: TransparentApiProxy("advapi32", func_name, error_check)
|
||||
@@ -470,6 +478,34 @@ def DeviceIoControl(hDevice, dwIoControlCode, lpInBuffer, nInBufferSize=None, lp
|
||||
return DeviceIoControl.ctypes_function(hDevice, dwIoControlCode, lpInBuffer, nInBufferSize, lpOutBuffer, nOutBufferSize, lpBytesReturned, lpOverlapped)
|
||||
|
||||
|
||||
# TODO: might be in another DLL depending of version
|
||||
# Should handle this..
|
||||
|
||||
@OptionalExport(Kernel32Proxy("GetMappedFileNameW"))
|
||||
def GetMappedFileNameW(hProcess, lpv, lpFilename, nSize=None):
|
||||
if nSize is None:
|
||||
nSize = ctypes.sizeof(lpFilename)
|
||||
return GetMappedFileNameW.ctypes_function(hProcess, lpv, lpFilename, nSize)
|
||||
|
||||
@OptionalExport(Kernel32Proxy("GetMappedFileNameA"))
|
||||
def GetMappedFileNameA(hProcess, lpv, lpFilename, nSize=None):
|
||||
if nSize is None:
|
||||
nSize = ctypes.sizeof(lpFilename)
|
||||
return GetMappedFileNameA.ctypes_function(hProcess, lpv, lpFilename, nSize)
|
||||
|
||||
if GetMappedFileNameA is None:
|
||||
@PsapiProxy("GetMappedFileNameW")
|
||||
def GetMappedFileNameW(hProcess, lpv, lpFilename, nSize=None):
|
||||
if nSize is None:
|
||||
nSize = ctypes.sizeof(lpFilename)
|
||||
return GetMappedFileNameW.ctypes_function(hProcess, lpv, lpFilename, nSize)
|
||||
|
||||
@PsapiProxy("GetMappedFileNameA")
|
||||
def GetMappedFileNameA(hProcess, lpv, lpFilename, nSize=None):
|
||||
if nSize is None:
|
||||
nSize = ctypes.sizeof(lpFilename)
|
||||
return GetMappedFileNameA.ctypes_function(hProcess, lpv, lpFilename, nSize)
|
||||
|
||||
# Debug API
|
||||
|
||||
DebugBreak = TransparentKernel32Proxy("DebugBreak")
|
||||
|
||||
Reference in New Issue
Block a user