Add get_mapped_filename to WinProcess

This commit is contained in:
Clement Rouault
2016-02-10 16:29:46 +01:00
parent b789a12040
commit c40cb0c8b0
5 changed files with 168 additions and 112 deletions
+14
View File
@@ -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
View File
@@ -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']
+9 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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")