From 5431b575604d7b5939e007550a809e79b3fd13bd Mon Sep 17 00:00:00 2001 From: Clement Rouault Date: Tue, 4 Apr 2017 10:10:21 +0200 Subject: [PATCH] fix ImprovedVariant.asbool + com.create_instance accept a context parameter + fix RemoteWCharP.value logic + winutils.decompress_buffer --- windows/com.py | 4 +-- windows/remotectypes.py | 24 +++++++++++++++--- windows/utils/winutils.py | 8 ++++++ windows/winproxy.py | 53 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 84 insertions(+), 5 deletions(-) diff --git a/windows/com.py b/windows/com.py index 29e66ae..c9d34c1 100644 --- a/windows/com.py +++ b/windows/com.py @@ -126,10 +126,10 @@ class ImprovedVariant(VARIANT): -def create_instance(clsiid, targetinterface, custom_iid=None): +def create_instance(clsiid, targetinterface, custom_iid=None, context=CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER): if custom_iid is None: custom_iid = targetinterface.IID - return winproxy.CoCreateInstance(byref(clsiid), None, CLSCTX_INPROC_SERVER, byref(custom_iid), byref(targetinterface)) + return winproxy.CoCreateInstance(byref(clsiid), None, context, byref(custom_iid), byref(targetinterface)) class ComVtable(object): diff --git a/windows/remotectypes.py b/windows/remotectypes.py index 2f3fd73..84d0098 100644 --- a/windows/remotectypes.py +++ b/windows/remotectypes.py @@ -106,9 +106,27 @@ class RemoteWCharP(RemotePtr, ctypes.c_char_p): @property def value(self): base = self.raw_value - res = [] - for i in itertools.count(): - x = self.target.read_memory(base + (i * 0x100), 0x100) + # Simple case where target in a WinProcess + try: + return self.target.read_wstring(base) + except AttributeError as e: + pass + # Copy of Winprocess.read_wstring if target is a custom object + read_size = 0x100 + readden = 0 + # I am trying to do something smart here.. + while True: + try: + x = self.read_memory(addr + readden, read_size) + except winproxy.Kernel32Error as e: + if read_size == 2: + raise + # handle read_wstring at end of page + # Of read failed: read only the half of size + # read_size must remain a multiple of 2 + read_size = read_size / 2 + continue + readden += read_size utf16_chars = ["".join(c) for c in zip(*[iter(x)] * 2)] if "\x00\x00" in utf16_chars: res.extend(utf16_chars[:utf16_chars.index("\x00\x00")]) diff --git a/windows/utils/winutils.py b/windows/utils/winutils.py index 5ea58a5..b7a2be3 100644 --- a/windows/utils/winutils.py +++ b/windows/utils/winutils.py @@ -223,6 +223,14 @@ def get_shared_mapping(name, size=0x1000): # addr = windows.winproxy.MapViewOfFile(h, dwDesiredAccess=FILE_MAP_READ, dwNumberOfBytesToMap=1) # return addr +def decompress_buffer(comptype, buffer, uncompress_size=None): + if uncompress_size is None: + uncompress_size = len(buffer) * 10 + result_size = DWORD() + uncompressed = ctypes.c_buffer(uncompress_size) + windows.winproxy.RtlDecompressBuffer(comptype, uncompressed, uncompress_size, buffer, len(buffer), result_size) + return uncompressed[:result_size.value] + class VirtualProtected(object): """ A context manager usable like `VirtualProtect` that will restore the old protection at exit :: diff --git a/windows/winproxy.py b/windows/winproxy.py index 8aba36d..b094b6c 100644 --- a/windows/winproxy.py +++ b/windows/winproxy.py @@ -192,6 +192,10 @@ class Crypt32Proxy(ApiProxy): APIDLL = "crypt32" default_error_check = staticmethod(zero_is_fail_error_check) +class Shell32Proxy(ApiProxy): + APIDLL = "shell32" + default_error_check = staticmethod(zero_is_fail_error_check) + #class OptionalExport(object): # """used 'around' a Proxy decorator # Should be used for export that are not available everywhere (ntdll internals | 32/64 bits stuff) @@ -286,6 +290,7 @@ GetVersionExA = TransparentKernel32Proxy("GetVersionExA") GetVersionExW = TransparentKernel32Proxy("GetVersionExW") GetComputerNameA = TransparentKernel32Proxy("GetComputerNameA") GetComputerNameW = TransparentKernel32Proxy("GetComputerNameW") +LocalFree = TransparentKernel32Proxy("LocalFree", should_return_zero_check) @@ -823,6 +828,13 @@ def NtQuerySymbolicLinkObject(LinkHandle, LinkTarget, ReturnedLength): def NtOpenSymbolicLinkObject(LinkHandle, DesiredAccess, ObjectAttributes): return NtOpenSymbolicLinkObject.ctypes_function(LinkHandle, DesiredAccess, ObjectAttributes) + +@NtdllProxy("RtlDecompressBuffer", error_ntstatus) +def RtlDecompressBuffer(CompressionFormat, UncompressedBuffer, UncompressedBufferSize, CompressedBuffer, CompressedBufferSize, FinalUncompressedSize): + return RtlDecompressBuffer.ctypes_function(CompressionFormat, UncompressedBuffer, UncompressedBufferSize, CompressedBuffer, CompressedBufferSize, FinalUncompressedSize) + + + # ##### ADVAPI32 ####### # @Advapi32Proxy('OpenProcessToken') @@ -833,6 +845,10 @@ def OpenProcessToken(ProcessHandle=None, DesiredAccess=NeededParameter, TokenHan return OpenProcessToken.ctypes_function(ProcessHandle, DesiredAccess, TokenHandle) +@Advapi32Proxy('OpenThreadToken') +def OpenThreadToken(ThreadHandle, DesiredAccess, OpenAsSelf, TokenHandle): + return OpenThreadToken.ctypes_function(ThreadHandle, DesiredAccess, OpenAsSelf, TokenHandle) + @Advapi32Proxy('LookupPrivilegeValueA') def LookupPrivilegeValueA(lpSystemName=None, lpName=NeededParameter, lpLuid=NeededParameter): return LookupPrivilegeValueA.ctypes_function(lpSystemName, lpName, lpLuid) @@ -871,6 +887,10 @@ def GetTokenInformation(TokenHandle=NeededParameter, TokenInformationClass=Neede return GetTokenInformation.ctypes_function(TokenHandle, TokenInformationClass, TokenInformation, TokenInformationLength, ReturnLength) +@Advapi32Proxy('SetTokenInformation') +def SetTokenInformation(TokenHandle, TokenInformationClass, TokenInformation, TokenInformationLength): + return SetTokenInformation.ctypes_function(TokenHandle, TokenInformationClass, TokenInformation, TokenInformationLength) + @Advapi32Proxy('RegOpenKeyExA', should_return_zero_check) def RegOpenKeyExA(hKey, lpSubKey, ulOptions, samDesired, phkResult): return RegOpenKeyExA.ctypes_function(hKey, lpSubKey, ulOptions, samDesired, phkResult) @@ -892,6 +912,24 @@ def GetSecurityInfo(handle, ObjectType, SecurityInfo, ppsidOwner=None, ppsidGrou return GetSecurityInfo.ctypes_function(handle, ObjectType, SecurityInfo, ppsidOwner, ppsidGroup, ppDacl, ppSacl, ppSecurityDescriptor) +# Sid stuff +@Advapi32Proxy('ConvertStringSidToSidA') +def ConvertStringSidToSidA(StringSid, Sid): + return ConvertStringSidToSidA.ctypes_function(StringSid, Sid) + +@Advapi32Proxy('ConvertStringSidToSidW') +def ConvertStringSidToSidW(StringSid, Sid): + return ConvertStringSidToSidW.ctypes_function(StringSid, Sid) + +@Advapi32Proxy('ConvertSidToStringSidA') +def ConvertSidToStringSidA(Sid, StringSid): + return ConvertSidToStringSidA.ctypes_function(Sid, StringSid) + +@Advapi32Proxy('ConvertSidToStringSidW') +def ConvertSidToStringSidW(Sid, StringSid): + return ConvertSidToStringSidW.ctypes_function(Sid, StringSid) + + # Registry stuff # TODO: default values? which ones ? @@ -910,6 +948,13 @@ def RegGetValueA(hkey, lpSubKey, lpValue, dwFlags, pdwType, pvData, pcbData): def RegGetValueW(hkey, lpSubKey=None, lpValue=NeededParameter, dwFlags=0, pdwType=None, pvData=None, pcbData=None): return RegGetValueW.ctypes_function(hkey, lpSubKey, lpValue, dwFlags, pdwType, pvData, pcbData) +@Advapi32Proxy('RegQueryValueExA', should_return_zero_check) +def RegQueryValueExA(hKey, lpValueName, lpReserved, lpType, lpData, lpcbData): + return RegQueryValueExA.ctypes_function(hKey, lpValueName, lpReserved, lpType, lpData, lpcbData) + +@Advapi32Proxy('RegQueryValueExW', should_return_zero_check) +def RegQueryValueExW(hKey, lpValueName, lpReserved, lpType, lpData, lpcbData): + return RegQueryValueExA.ctypes_function(hKey, lpValueName, lpReserved, lpType, lpData, lpcbData) @Advapi32Proxy('RegCloseKey', should_return_zero_check) def RegCloseKey(hKey): @@ -1239,4 +1284,12 @@ def CoInitializeSecurity(pSecDesc, cAuthSvc, asAuthSvc, pReserved1, dwAuthnLevel def CoCreateInstance(rclsid, pUnkOuter=None, dwClsContext=CLSCTX_INPROC_SERVER, riid=NeededParameter, ppv=NeededParameter): return CoCreateInstance.ctypes_function(rclsid, pUnkOuter, dwClsContext, riid, ppv) +# ## Shell32 ## # +@Shell32Proxy('ShellExecuteA') +def ShellExecuteA(hwnd, lpOperation, lpFile, lpParameters, lpDirectory, nShowCmd): + return ShellExecuteA.ctypes_function(hwnd, lpOperation, lpFile, lpParameters, lpDirectory, nShowCmd) + +@Shell32Proxy('ShellExecuteW') +def ShellExecuteW(hwnd, lpOperation, lpFile, lpParameters, lpDirectory, nShowCmd): + return ShellExecuteW.ctypes_function(hwnd, lpOperation, lpFile, lpParameters, lpDirectory, nShowCmd)