diff --git a/generated_def/windef.py b/generated_def/windef.py index 8a2a528..11553e1 100644 --- a/generated_def/windef.py +++ b/generated_def/windef.py @@ -15,6 +15,9 @@ MAX_PATH = Flag("MAX_PATH", 260) ANYSIZE_ARRAY = Flag("ANYSIZE_ARRAY", 1) IMAGE_SIZEOF_SHORT_NAME = Flag("IMAGE_SIZEOF_SHORT_NAME", 8) IMAGE_NUMBEROF_DIRECTORY_ENTRIES = Flag("IMAGE_NUMBEROF_DIRECTORY_ENTRIES", 16) +STD_INPUT_HANDLE = Flag("STD_INPUT_HANDLE", -10) +STD_OUTPUT_HANDLE = Flag("STD_OUTPUT_HANDLE", -11) +STD_ERROR_HANDLE = Flag("STD_ERROR_HANDLE", -12) WARMING_NOT_SAME_FLAG_FOR_WINXP = Flag("WARMING_NOT_SAME_FLAG_FOR_WINXP", 0) PROCESS_ALL_ACCESS = Flag("PROCESS_ALL_ACCESS", 0x001F0FFF) THREAD_ALL_ACCESS = Flag("THREAD_ALL_ACCESS", 0x001F03FF) diff --git a/generated_def/winfuncs.py b/generated_def/winfuncs.py index 23b0f60..6ee9e27 100644 --- a/generated_def/winfuncs.py +++ b/generated_def/winfuncs.py @@ -3,7 +3,7 @@ from ctypes import * from ctypes.wintypes import * from winstructs import * -functions = ['ExitProcess', 'GetLastError', 'GetCurrentProcess', 'CreateFileA', 'CreateFileW', 'NtQuerySystemInformation', 'VirtualAlloc', 'VirtualAllocEx', 'VirtualProtect', 'VirtualQuery', 'GetModuleFileNameA', 'GetModuleFileNameW', 'CreateRemoteThread', 'VirtualProtect', 'CreateProcessA', 'CreateProcessW', 'GetThreadContext', 'SetThreadContext', 'OpenThread', 'OpenProcess', 'CloseHandle', 'ReadProcessMemory', 'WriteProcessMemory', 'CreateToolhelp32Snapshot', 'Thread32First', 'Thread32Next', 'Process32First', 'Process32Next', 'Process32FirstW', 'Process32NextW', 'GetProcAddress', 'LoadLibraryA', 'LoadLibraryW', 'OpenProcessToken', 'LookupPrivilegeValueA', 'LookupPrivilegeValueW', 'AdjustTokenPrivileges', 'FindResourceA', 'FindResourceW', 'SizeofResource', 'LoadResource', 'LockResource', 'GetVersionExA', 'GetVersionExW', 'GetVersion'] +functions = ['ExitProcess', 'GetLastError', 'GetCurrentProcess', 'CreateFileA', 'CreateFileW', 'NtQuerySystemInformation', 'VirtualAlloc', 'VirtualAllocEx', 'VirtualProtect', 'VirtualQuery', 'GetModuleFileNameA', 'GetModuleFileNameW', 'CreateRemoteThread', 'VirtualProtect', 'CreateProcessA', 'CreateProcessW', 'GetThreadContext', 'SetThreadContext', 'OpenThread', 'OpenProcess', 'CloseHandle', 'ReadProcessMemory', 'WriteProcessMemory', 'CreateToolhelp32Snapshot', 'Thread32First', 'Thread32Next', 'Process32First', 'Process32Next', 'Process32FirstW', 'Process32NextW', 'GetProcAddress', 'LoadLibraryA', 'LoadLibraryW', 'OpenProcessToken', 'LookupPrivilegeValueA', 'LookupPrivilegeValueW', 'AdjustTokenPrivileges', 'FindResourceA', 'FindResourceW', 'SizeofResource', 'LoadResource', 'LockResource', 'GetVersionExA', 'GetVersionExW', 'GetVersion', 'GetCurrentThread', 'GetCurrentProcessorNumber', 'AllocConsole', 'GetStdHandle', 'SetStdHandle', 'SetThreadAffinityMask', 'WriteFile'] # ExitProcess(uExitCode): ExitProcessPrototype = WINFUNCTYPE(VOID, UINT) @@ -185,3 +185,31 @@ GetVersionExWParams = ((1, 'lpVersionInformation'),) GetVersionPrototype = WINFUNCTYPE(DWORD) GetVersionParams = () +# GetCurrentThread(): +GetCurrentThreadPrototype = WINFUNCTYPE(HANDLE) +GetCurrentThreadParams = () + +# GetCurrentProcessorNumber(): +GetCurrentProcessorNumberPrototype = WINFUNCTYPE(DWORD) +GetCurrentProcessorNumberParams = () + +# AllocConsole(): +AllocConsolePrototype = WINFUNCTYPE(BOOL) +AllocConsoleParams = () + +# GetStdHandle(nStdHandle): +GetStdHandlePrototype = WINFUNCTYPE(HANDLE, DWORD) +GetStdHandleParams = ((1, 'nStdHandle'),) + +# SetStdHandle(nStdHandle, hHandle): +SetStdHandlePrototype = WINFUNCTYPE(BOOL, DWORD, HANDLE) +SetStdHandleParams = ((1, 'nStdHandle'), (1, 'hHandle')) + +# SetThreadAffinityMask(hThread, dwThreadAffinityMask): +SetThreadAffinityMaskPrototype = WINFUNCTYPE(DWORD, HANDLE, DWORD) +SetThreadAffinityMaskParams = ((1, 'hThread'), (1, 'dwThreadAffinityMask')) + +# WriteFile(hFile, lpBuffer, nNumberOfBytesToWrite, lpNumberOfBytesWritten, lpOverlapped): +WriteFilePrototype = WINFUNCTYPE(BOOL, HANDLE, LPCVOID, DWORD, LPDWORD, LPOVERLAPPED) +WriteFileParams = ((1, 'hFile'), (1, 'lpBuffer'), (1, 'nNumberOfBytesToWrite'), (1, 'lpNumberOfBytesWritten'), (1, 'lpOverlapped')) + diff --git a/generated_def/winstructs.py b/generated_def/winstructs.py index c34bcee..1a093fe 100644 --- a/generated_def/winstructs.py +++ b/generated_def/winstructs.py @@ -17,12 +17,13 @@ ULONG_PTR = PULONG CHAR = c_char FARPROC = PVOID HGLOBAL = PVOID -HRESULT = c_long ULONGLONG = c_ulonglong +ULONG64 = c_ulonglong +PULONG64 = POINTER(ULONG64) PHANDLE = POINTER(HANDLE) VOID = DWORD -structs = ['_LIST_ENTRY', '_PEB_LDR_DATA', '_LSA_UNICODE_STRING', '_RTL_USER_PROCESS_PARAMETERS', '_PEB', '_SECURITY_ATTRIBUTES', '_SYSTEM_VERIFIER_INFORMATION', '_LDR_DATA_TABLE_ENTRY', '_PEB_LDR_DATA', '_IMAGE_FILE_HEADER', '_IMAGE_DATA_DIRECTORY', '_IMAGE_SECTION_HEADER', '_IMAGE_OPTIONAL_HEADER64', '_IMAGE_OPTIONAL_HEADER', '_IMAGE_NT_HEADERS64', '_IMAGE_NT_HEADERS', '_IMAGE_IMPORT_DESCRIPTOR', '_MEMORY_BASIC_INFORMATION', '_STARTUPINFOA', '_STARTUPINFOW', '_PROCESS_INFORMATION', '_FLOATING_SAVE_AREA', '_CONTEXT', 'tagPROCESSENTRY32W', 'tagPROCESSENTRY32', 'tagTHREADENTRY32', '_LUID', '_LUID_AND_ATTRIBUTES', '_TOKEN_PRIVILEGES', '_OSVERSIONINFOA', '_OSVERSIONINFOW', '_OSVERSIONINFOEXA', '_OSVERSIONINFOEXW'] +structs = ['_LIST_ENTRY', '_PEB_LDR_DATA', '_LSA_UNICODE_STRING', '_RTL_USER_PROCESS_PARAMETERS', '_PEB', '_SECURITY_ATTRIBUTES', '_SYSTEM_VERIFIER_INFORMATION', '_LDR_DATA_TABLE_ENTRY', '_PEB_LDR_DATA', '_IMAGE_FILE_HEADER', '_IMAGE_DATA_DIRECTORY', '_IMAGE_SECTION_HEADER', '_IMAGE_OPTIONAL_HEADER64', '_IMAGE_OPTIONAL_HEADER', '_IMAGE_NT_HEADERS64', '_IMAGE_NT_HEADERS', '_IMAGE_IMPORT_DESCRIPTOR', '_IMAGE_IMPORT_BY_NAME', '_MEMORY_BASIC_INFORMATION', '_STARTUPINFOA', '_STARTUPINFOW', '_PROCESS_INFORMATION', '_FLOATING_SAVE_AREA', '_CONTEXT', 'tagPROCESSENTRY32W', 'tagPROCESSENTRY32', 'tagTHREADENTRY32', '_LUID', '_LUID_AND_ATTRIBUTES', '_TOKEN_PRIVILEGES', '_OSVERSIONINFOA', '_OSVERSIONINFOW', '_OSVERSIONINFOEXA', '_OSVERSIONINFOEXW', '_OVERLAPPED'] enums = ['_SYSTEM_INFORMATION_CLASS'] @@ -394,6 +395,15 @@ class _IMAGE_IMPORT_DESCRIPTOR(Structure): IMAGE_IMPORT_DESCRIPTOR = _IMAGE_IMPORT_DESCRIPTOR PIMAGE_IMPORT_DESCRIPTOR = POINTER(_IMAGE_IMPORT_DESCRIPTOR) +# Struct _IMAGE_IMPORT_BY_NAME definitions +class _IMAGE_IMPORT_BY_NAME(Structure): + _fields_ = [ + ("Hint", WORD), + ("Name", BYTE * 1), + ] +PIMAGE_IMPORT_BY_NAME = POINTER(_IMAGE_IMPORT_BY_NAME) +IMAGE_IMPORT_BY_NAME = _IMAGE_IMPORT_BY_NAME + # Struct _MEMORY_BASIC_INFORMATION definitions class _MEMORY_BASIC_INFORMATION(Structure): _fields_ = [ @@ -666,3 +676,14 @@ OSVERSIONINFOEXW = _OSVERSIONINFOEXW POSVERSIONINFOEXW = POINTER(_OSVERSIONINFOEXW) RTL_OSVERSIONINFOEXW = _OSVERSIONINFOEXW +# Struct _OVERLAPPED definitions +class _OVERLAPPED(Structure): + _fields_ = [ + ("Internal", ULONG_PTR), + ("InternalHigh", ULONG_PTR), + ("Pointer", PVOID), + ("hEvent", HANDLE), + ] +LPOVERLAPPED = POINTER(_OVERLAPPED) +OVERLAPPED = _OVERLAPPED + diff --git a/k32testing.py b/k32testing.py index 41875c2..3dd42a8 100644 --- a/k32testing.py +++ b/k32testing.py @@ -120,6 +120,11 @@ LoadLibraryA = TransparentKernel32Proxy("LoadLibraryA") LoadLibraryW = TransparentKernel32Proxy("LoadLibraryW") GetLastError = TransparentKernel32Proxy("GetLastError", no_error_check) GetCurrentProcess = TransparentKernel32Proxy("GetCurrentProcess") +GetCurrentProcessorNumber = TransparentKernel32Proxy("GetCurrentProcessorNumber", no_error_check) +GetCurrentThread = TransparentKernel32Proxy("GetCurrentThread") +AllocConsole = TransparentKernel32Proxy("AllocConsole") +GetStdHandle = TransparentKernel32Proxy("GetStdHandle") +SetStdHandle = TransparentKernel32Proxy("SetStdHandle") # This kind of function could be fully done by using paramflags @Kernel32Proxy("VirtualAlloc") @@ -202,6 +207,14 @@ def WriteProcessMemory(hProcess, lpBaseAddress, lpBuffer, nSize=None, lpNumberOf nSize = len(lpBuffer) return WriteProcessMemory.ctypes_function(hProcess, lpBaseAddress, lpBuffer, nSize, lpNumberOfBytesWritten) +@Kernel32Proxy('SetThreadAffinityMask') +def SetThreadAffinityMask(hThread=None, dwThreadAffinityMask=NeededParameter): + """If hThread is not given, it will be the current thread""" + if hThread is None: + hThread = GetCurrentThread() + return SetThreadAffinityMask.ctypes_function(hThread, dwThreadAffinityMask) + + @Kernel32Proxy("CreateToolhelp32Snapshot") def CreateToolhelp32Snapshot(dwFlags, th32ProcessID=0): return CreateToolhelp32Snapshot.ctypes_function(dwFlags, th32ProcessID) @@ -233,6 +246,16 @@ def Process32Next(hSnapshot, lpte): if type(lpte) == THREADENTRY32: lpte = ctypes.byref(lpte) return Process32Next.ctypes_function(hSnapshot, lpte) + +# File stuff + +@Kernel32Proxy("WriteFile") +def WriteFile(hFile, lpBuffer, nNumberOfBytesToWrite=None, lpNumberOfBytesWritten=None, lpOverlapped=None): + if nNumberOfBytesToWrite is None: + nNumberOfBytesToWrite = len(lpBuffer) + if lpOverlapped is None and lpNumberOfBytesWritten is None: + lpNumberOfBytesWritten = ctypes.byref(DWORD()) + return WriteFile.ctypes_function(hFile, lpBuffer, nNumberOfBytesToWrite, lpNumberOfBytesWritten, lpOverlapped) ###### ADVAPI32 ######## diff --git a/native_exec/native_function.py b/native_exec/native_function.py index cfb05d5..b93eed9 100644 --- a/native_exec/native_function.py +++ b/native_exec/native_function.py @@ -260,7 +260,6 @@ def generate_stub_64(callback): code += Mov_RAX_X(save_r9) code += Mov_R9_DRAX() # Call python code - code += Int3() code += Mov_RAX_X(c_callback) code += Reserve_space_for_call code += Call_RAX() # no need for stack alignement here as we poped the return addr diff --git a/remote_callback.py b/remote_callback.py index a4cbd87..b6950ea 100644 --- a/remote_callback.py +++ b/remote_callback.py @@ -4,13 +4,13 @@ from windows.hooks import * # Example of callback for IAT hooks -@Callback(ctypes.c_ulong, ctypes.c_ulong) +@Callback(ctypes.c_void_p, ctypes.c_ulong) def exit_callback(x, real_function): print("Try to quit with {0} | {1}".format(x, type(x))) if x == 3: print("TRYING TO REAL EXIT") return real_function(1234) - return 0 + return 0x4242424243444546 @CreateFileACallback def createfile_callback(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile, real_function): diff --git a/utils.py b/utils.py index e36ae64..3a5f661 100644 --- a/utils.py +++ b/utils.py @@ -1,8 +1,12 @@ import ctypes +import msvcrt +import os +import copy +import sys + import k32testing as kernel32proxy import generated_def.windef as windef import winobject -import copy import native_exec from generated_def.winstructs import * @@ -50,6 +54,27 @@ def is_wow_64(hProcess): if res: return bool(Wow64Process) raise ctypes.WinError() + +def create_file_from_handle(handle, mode="r"): + fd = msvcrt.open_osfhandle(handle, os.O_TEXT) + return os.fdopen(fd, mode, 0) + +def get_handle_from_file(f): + return msvcrt.get_osfhandle(f.fileno()) + +def create_console(): + kernel32proxy.AllocConsole() + stdout_handle = kernel32proxy.GetStdHandle(windef.STD_OUTPUT_HANDLE) + console_stdout = create_file_from_handle(stdout_handle, "w") + sys.stdout = console_stdout + + stdin_handle = kernel32proxy.GetStdHandle(windef.STD_INPUT_HANDLE) + console_stdin = create_file_from_handle(stdin_handle, "r+") + sys.stdin = console_stdin + + stderr_handle = kernel32proxy.GetStdHandle(windef.STD_ERROR_HANDLE) + console_stderr = create_file_from_handle(stderr_handle, "w") + sys.stderr = console_stderr class VirtualProtected(object): def __init__(self, addr, size, new_protect):