MSDN.WhiteKnight - Stack Overflow answers
Ответ на "Получить список модулей 64-битного процесса из 32-битной программы"
Answer 844207
Можно сделать это путем чтения Process Environment Block (PEB) с помощью функций Native API NtWow64QueryInformationProcess64 и NtWow64ReadVirtualMemory64:
#include <stdlib.h> #include <tchar.h> #include <cstdint> #include <iostream> #include <stdexcept> #include <string> #include <vector> #include <windows.h> #define NT_SUCCESS(x) ((x) >= 0) // Namespace is present Not to collide with "winbase.h" // definition of PROCESS_INFORMATION_CLASS and others. namespace sys { typedef enum _PROCESS_INFORMATION_CLASS { ProcessBasicInformation, ProcessQuotaLimits, ProcessIoCounters, ProcessVmCounters, ProcessTimes, ProcessBasePriority, ProcessRaisePriority, ProcessDebugPort, ProcessExceptionPort, ProcessAccessToken, ProcessLdtInformation, ProcessLdtSize, ProcessDefaultHardErrorMode, ProcessIoPortHandlers, ProcessPooledUsageAndLimits, ProcessWorkingSetWatch, ProcessUserModeIOPL, ProcessEnableAlignmentFaultFixup, ProcessPriorityClass, ProcessWx86Information, ProcessHandleCount, ProcessAffinityMask, ProcessPriorityBoost, MaxProcessInfoClass } PROCESS_INFORMATION_CLASS, *PPROCESS_INFORMATION_CLASS; // ------------------------------------------------------------------------ // Structs. // ------------------------------------------------------------------------ typedef struct _PROCESS_BASIC_INFORMATION64 { ULONGLONG Reserved1; ULONGLONG PebBaseAddress; ULONGLONG Reserved2[2]; ULONGLONG UniqueProcessId; ULONGLONG Reserved3; } PROCESS_BASIC_INFORMATION64; typedef struct _PEB_LDR_DATA64 { ULONG Length; BOOLEAN Initialized; ULONGLONG SsHandle; LIST_ENTRY64 InLoadOrderModuleList; LIST_ENTRY64 InMemoryOrderModuleList; LIST_ENTRY64 InInitializationOrderModuleList; } PEB_LDR_DATA64, *PPEB_LDR_DATA64; // Structure is cut down to ProcessHeap. typedef struct _PEB64 { BOOLEAN InheritedAddressSpace; BOOLEAN ReadImageFileExecOptions; BOOLEAN BeingDebugged; BOOLEAN Spare; ULONGLONG Mutant; ULONGLONG ImageBaseAddress; ULONGLONG LoaderData; ULONGLONG ProcessParameters; ULONGLONG SubSystemData; ULONGLONG ProcessHeap; } PEB64; typedef struct _UNICODE_STRING64 { USHORT Length; USHORT MaximumLength; ULONGLONG Buffer; } UNICODE_STRING64; typedef struct _LDR_DATA_TABLE_ENTRY64 { LIST_ENTRY64 InLoadOrderModuleList; LIST_ENTRY64 InMemoryOrderModuleList; LIST_ENTRY64 InInitializationOrderModuleList; ULONGLONG BaseAddress; ULONGLONG EntryPoint; DWORD64 SizeOfImage; UNICODE_STRING64 FullDllName; UNICODE_STRING64 BaseDllName; ULONG Flags; SHORT LoadCount; SHORT TlsIndex; LIST_ENTRY64 HashTableEntry; ULONGLONG TimeDateStamp; } LDR_DATA_TABLE_ENTRY64, *PLDR_DATA_TABLE_ENTRY64; } // namespace sys // ------------------------------------------------------------------------ // Function prototypes. // ------------------------------------------------------------------------ typedef NTSTATUS(NTAPI *_NtWow64QueryInformationProcess64)( IN HANDLE ProcessHandle, ULONG ProcessInformationClass, OUT PVOID ProcessInformation, IN ULONG ProcessInformationLength, OUT PULONG ReturnLength OPTIONAL); typedef NTSTATUS(NTAPI *_NtWow64ReadVirtualMemory64)( IN HANDLE ProcessHandle, IN DWORD64 BaseAddress, OUT PVOID Buffer, IN ULONG64 Size, OUT PDWORD64 NumberOfBytesRead); //Functions to print error messages void ErrorMes(LPTSTR lpszFunction,WCHAR* buf) { // Retrieve the system error message for the last-error code LPVOID lpMsgBuf; LPVOID lpDisplayBuf; DWORD dw = GetLastError(); FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpMsgBuf, 0, NULL ); // Print the error message lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT, (lstrlen((LPCTSTR)lpMsgBuf) + lstrlen((LPCTSTR)lpszFunction) + 40) * sizeof(TCHAR)); swprintf(buf,L"%s returned error 0x%x: %s", lpszFunction, dw, lpMsgBuf); LocalFree(lpMsgBuf); LocalFree(lpDisplayBuf); } void RaiseError(LPTSTR lpszFunction){ WCHAR buf[1024]={0}; ErrorMes(lpszFunction,buf); std::wcout << buf << std::endl; throw std::exception("WINAPI call failed"); } #ifndef WIN32 # error "This application must be built as an x86 executable" #endif #define GET_FUNC_ADDR(name) _##name name = (_##name)::GetProcAddress(::GetModuleHandleA("ntdll.dll"), #name) #define CHECK_ERROR(clause, func) if (!(clause)) { RaiseError(func); } namespace { struct close_on_exit { close_on_exit(HANDLE ptr) : ptr_(ptr) { }; ~close_on_exit() { if (ptr_) { ::CloseHandle(ptr_); ptr_ = nullptr; } } private: HANDLE ptr_; }; // Create C++ string based on unicode data std::wstring CreateString(std::vector<uint8_t> &raw_bytes) { std::vector<uint16_t> unicode(raw_bytes.size() >> 1, 0); memcpy(unicode.data(), raw_bytes.data(), raw_bytes.size()); const std::wstring wide_string(unicode.begin(), unicode.end()); return wide_string; } //Open process handle by its ID void *get_handle(uint32_t id) { HANDLE handle = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, id); CHECK_ERROR(NULL != handle, L"OpenProcess"); return handle; } void check_if_process_is_x64(HANDLE handle) { BOOL is_wow64_process = TRUE; CHECK_ERROR(::IsWow64Process(handle, &is_wow64_process), L"IsWow64Process"); if(FALSE != is_wow64_process) throw std::exception( "Target process is not x64 one"); } std::vector<uint8_t> read_mem(HANDLE handle, uint64_t address, uint32_t length) { if(handle == NULL)throw std::exception("Process handle is null"); std::vector<uint8_t> data(length, 0); GET_FUNC_ADDR(NtWow64ReadVirtualMemory64); NTSTATUS status = NtWow64ReadVirtualMemory64(handle, address, data.data(), data.size(), FALSE); if(!NT_SUCCESS(status)){ std::wcout << L"NtWow64ReadVirtualMemory64 status: " << status <<std::endl; throw std::exception("NT API call failed"); } return data; } void read_pbi(HANDLE handle, sys::PROCESS_BASIC_INFORMATION64 &pbi) { if(handle == NULL)throw std::exception("Process handle is null"); GET_FUNC_ADDR(NtWow64QueryInformationProcess64); NTSTATUS status = NtWow64QueryInformationProcess64(handle, sys::ProcessBasicInformation, &pbi, sizeof(pbi), NULL); if(!NT_SUCCESS(status)){ std::wcout << L"NtQueryInformationProcess status: " << status << std::endl; throw std::exception("NT API call failed"); } } std::vector<uint8_t> read_peb_data(HANDLE handle) { sys::PROCESS_BASIC_INFORMATION64 pbi = { 0 }; read_pbi(handle, pbi); return read_mem(handle, pbi.PebBaseAddress, sizeof(sys::PEB64)); } //Prints 64-bit process modules bool get_modules_load_order_via_peb(HANDLE handle) { std::vector<uint8_t> read_peb = read_peb_data(handle); sys::PEB64 *peb = (sys::PEB64 *)read_peb.data(); // ------------------------------------------------------------------------ // Read memory from pointer to loader data structures. // ------------------------------------------------------------------------ std::vector<uint8_t> read_peb_ldr_data = read_mem(handle, (uintptr_t)peb->LoaderData, sizeof(sys::PEB_LDR_DATA64)); sys::PEB_LDR_DATA64 *peb_ldr_data = (sys::PEB_LDR_DATA64 *)read_peb_ldr_data.data(); sys::PEB_LDR_DATA64 *loader_data = (sys::PEB_LDR_DATA64 *)peb->LoaderData; const uintptr_t addr_of_ptr_to_first_ldr_module = (uintptr_t)loader_data + ((uintptr_t)&loader_data->InLoadOrderModuleList - (uintptr_t)&loader_data->Length); ULONGLONG address = peb_ldr_data->InLoadOrderModuleList.Flink; uint32_t counter = 1; // ------------------------------------------------------------------------ // Traversing loader data structures. // ------------------------------------------------------------------------ do { std::vector<uint8_t> read_ldr_table_entry = read_mem(handle, address, sizeof(sys::LDR_DATA_TABLE_ENTRY64)); sys::LDR_DATA_TABLE_ENTRY64 *ldr_table_entry = (sys::LDR_DATA_TABLE_ENTRY64 *)read_ldr_table_entry.data(); std::vector<uint8_t> unicode_name = read_mem(handle, ldr_table_entry->BaseDllName.Buffer, ldr_table_entry->BaseDllName.MaximumLength); std::wstring name = CreateString(unicode_name); std::wcout << name << std::endl; ldr_table_entry = (sys::LDR_DATA_TABLE_ENTRY64 *)read_ldr_table_entry.data(); address = (uintptr_t)ldr_table_entry->InLoadOrderModuleList.Flink; } while (addr_of_ptr_to_first_ldr_module != address); return true; } } // namespace /********************************************************************************/ int _tmain(int argc, _TCHAR* argv[]) { try { HANDLE handle = get_handle(2564); close_on_exit auto_close_handle(handle); check_if_process_is_x64(handle); std::wcout << L"------------- Modules: ------------------------\n"; get_modules_load_order_via_peb(handle); std::wcout << L"-----------------------------------------------\n"; } catch (const std::exception &e) { std::wcout << L"\n----------------------------------------------------\n"; std::wcout << "Exception occurred: " << e.what(); std::wcout << L"\n----------------------------------------------------\n"; } return 0; }
Источник: ответ greenpiece на stackoverflow.com
Content is retrieved from StackExchange API.
Auto-generated by ruso-archive tools.