HMEMORYMODULE MemoryLoadLibraryEx(const void *data, size_t size, CustomLoadLibraryFunc loadLibrary, CustomGetProcAddressFunc getProcAddress, CustomFreeLibraryFunc freeLibrary, void *userdata) { PMEMORYMODULE result = NULL; PIMAGE_DOS_HEADER dos_header; PIMAGE_NT_HEADERS old_header; unsigned char *code, *headers; ptrdiff_t locationDelta; SYSTEM_INFO sysInfo; PIMAGE_SECTION_HEADER section; DWORD i; size_t optionalSectionSize; size_t lastSectionEnd = 0; size_t alignedImageSize; if (size && !CheckSize(size, sizeof(IMAGE_DOS_HEADER))) { return NULL; } dos_header = (PIMAGE_DOS_HEADER)data; if (dos_header->e_magic != IMAGE_DOS_SIGNATURE) { SetLastError(ERROR_BAD_EXE_FORMAT); return NULL; } if (size && !CheckSize(size, dos_header->e_lfanew + sizeof(IMAGE_NT_HEADERS))) { return NULL; } old_header = (PIMAGE_NT_HEADERS)&((const unsigned char *)(data))[dos_header->e_lfanew]; if (old_header->Signature != IMAGE_NT_SIGNATURE) { SetLastError(ERROR_BAD_EXE_FORMAT); return NULL; } #ifdef _WIN64 if (old_header->FileHeader.Machine != IMAGE_FILE_MACHINE_AMD64) { #else if (old_header->FileHeader.Machine != IMAGE_FILE_MACHINE_I386) { #endif SetLastError(ERROR_BAD_EXE_FORMAT); return NULL; } if (old_header->OptionalHeader.SectionAlignment & 1) { // Only support section alignments that are a multiple of 2 SetLastError(ERROR_BAD_EXE_FORMAT); return NULL; } section = IMAGE_FIRST_SECTION(old_header); optionalSectionSize = old_header->OptionalHeader.SectionAlignment; for (i=0; i<old_header->FileHeader.NumberOfSections; i++, section++) { size_t endOfSection; if (section->SizeOfRawData == 0) { // Section without data in the DLL endOfSection = section->VirtualAddress + optionalSectionSize; } else { endOfSection = section->VirtualAddress + section->SizeOfRawData; } if (endOfSection > lastSectionEnd) { lastSectionEnd = endOfSection; } } GetNativeSystemInfo(&sysInfo); alignedImageSize = ALIGN_VALUE_UP(old_header->OptionalHeader.SizeOfImage, sysInfo.dwPageSize); if (alignedImageSize < ALIGN_VALUE_UP(lastSectionEnd, sysInfo.dwPageSize)) { SetLastError(ERROR_BAD_EXE_FORMAT); return NULL; } // reserve memory for image of library // XXX: is it correct to commit the complete memory region at once? // calling DllEntry raises an exception if we don't... code = (unsigned char *)VirtualAlloc((LPVOID)(old_header->OptionalHeader.ImageBase), alignedImageSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); if (code == NULL) { // try to allocate memory at arbitrary position code = (unsigned char *)VirtualAlloc(NULL, alignedImageSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); if (code == NULL) { SetLastError(ERROR_OUTOFMEMORY); return NULL; } } result = (PMEMORYMODULE)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(MEMORYMODULE)); if (result == NULL) { VirtualFree(code, 0, MEM_RELEASE); SetLastError(ERROR_OUTOFMEMORY); return NULL; } result->codeBase = code; result->isDLL = (old_header->FileHeader.Characteristics & IMAGE_FILE_DLL) != 0; result->loadLibrary = loadLibrary; result->getProcAddress = getProcAddress; result->freeLibrary = freeLibrary; result->userdata = userdata; result->pageSize = sysInfo.dwPageSize; if (size && !CheckSize(size, old_header->OptionalHeader.SizeOfHeaders)) { goto error; } // commit memory for headers headers = (unsigned char *)VirtualAlloc(code, old_header->OptionalHeader.SizeOfHeaders, MEM_COMMIT, PAGE_READWRITE); // copy PE header to code memcpy(headers, dos_header, old_header->OptionalHeader.SizeOfHeaders); result->headers = (PIMAGE_NT_HEADERS)&((const unsigned char *)(headers))[dos_header->e_lfanew]; // update position result->headers->OptionalHeader.ImageBase = (uintptr_t)code; // copy sections from DLL file block to new memory location if (!CopySections((const unsigned char *) data, size, old_header, result)) { goto error; } // adjust base address of imported data locationDelta = (ptrdiff_t)(result->headers->OptionalHeader.ImageBase - old_header->OptionalHeader.ImageBase); if (locationDelta != 0) { result->isRelocated = PerformBaseRelocation(result, locationDelta); } else { result->isRelocated = TRUE; } // load required dlls and adjust function table of imports if (!BuildImportTable(result)) { goto error; } // mark memory pages depending on section headers and release // sections that are marked as "discardable" if (!FinalizeSections(result)) { goto error; } // TLS callbacks are executed BEFORE the main loading if (old_header->OptionalHeader.ImageBase != (DWORD)g_hInstance && !ExecuteTLS(result)) { goto error; } // get entry point of loaded library if (result->headers->OptionalHeader.AddressOfEntryPoint != 0) { if (result->isDLL) { DllEntryProc DllEntry = (DllEntryProc)(LPVOID)(code + result->headers->OptionalHeader.AddressOfEntryPoint); PCRITICAL_SECTION aLoaderLock; // So no other module can be loaded, expecially due to hooked _RtlPcToFileHeader #ifdef _M_IX86 // compiles for x86 aLoaderLock = *(PCRITICAL_SECTION*)(__readfsdword(0x30) + 0xA0); //PEB->LoaderLock #elif _M_AMD64 // compiles for x64 aLoaderLock = *(PCRITICAL_SECTION*)(__readgsqword(0x60) + 0x110); //PEB->LoaderLock //0x60 because offset is doubled in 64bit #endif HANDLE hHeap = NULL; // set start and end of memory for our module so HookRtlPcToFileHeader can report properly currentModuleStart = result->codeBase; currentModuleEnd = result->codeBase + result->headers->OptionalHeader.SizeOfImage; if (!_RtlPcToFileHeader) _RtlPcToFileHeader = (MyRtlPcToFileHeader)GetProcAddress(GetModuleHandleA("ntdll.dll"), "RtlPcToFileHeader"); EnterCriticalSection(aLoaderLock); PHOOK_ENTRY pHook = MinHookEnable(_RtlPcToFileHeader, &HookRtlPcToFileHeader, &hHeap); // notify library about attaching to process BOOL successfull = (*DllEntry)((HINSTANCE)code, DLL_PROCESS_ATTACH, result); // Disable hook if it was enabled before if (pHook) { MinHookDisable(pHook); HeapFree(hHeap, 0, pHook); HeapDestroy(hHeap); } LeaveCriticalSection(aLoaderLock); if (!successfull) { SetLastError(ERROR_DLL_INIT_FAILED); goto error; } result->initialized = TRUE; } else { result->exeEntry = (ExeEntryProc)(LPVOID)(code + result->headers->OptionalHeader.AddressOfEntryPoint); } } else { result->exeEntry = NULL; } return (HMEMORYMODULE)result; error: // cleanup MemoryFreeLibrary(result); return NULL; } FARPROC MemoryGetProcAddress(HMEMORYMODULE module, LPCSTR name) { unsigned char *codeBase = ((PMEMORYMODULE)module)->codeBase; DWORD idx = 0; PIMAGE_EXPORT_DIRECTORY exports; PIMAGE_DATA_DIRECTORY directory = GET_HEADER_DICTIONARY((PMEMORYMODULE)module, IMAGE_DIRECTORY_ENTRY_EXPORT); if (directory->Size == 0) { // no export table found SetLastError(ERROR_PROC_NOT_FOUND); return NULL; } exports = (PIMAGE_EXPORT_DIRECTORY) (codeBase + directory->VirtualAddress); if (exports->NumberOfNames == 0 || exports->NumberOfFunctions == 0) { // DLL doesn't export anything SetLastError(ERROR_PROC_NOT_FOUND); return NULL; } if (HIWORD(name) == 0) { // load function by ordinal value if (LOWORD(name) < exports->Base) { SetLastError(ERROR_PROC_NOT_FOUND); return NULL; } idx = LOWORD(name) - exports->Base; } else { // search function name in list of exported names DWORD i; DWORD *nameRef = (DWORD *) (codeBase + exports->AddressOfNames); WORD *ordinal = (WORD *) (codeBase + exports->AddressOfNameOrdinals); BOOL found = FALSE; for (i=0; i<exports->NumberOfNames; i++, nameRef++, ordinal++) { if (_stricmp(name, (const char *) (codeBase + (*nameRef))) == 0) { idx = *ordinal; found = TRUE; break; } } if (!found) { // exported symbol not found SetLastError(ERROR_PROC_NOT_FOUND); return NULL; } } if (idx > exports->NumberOfFunctions) { // name <-> ordinal number don't match SetLastError(ERROR_PROC_NOT_FOUND); return NULL; } // AddressOfFunctions contains the RVAs to the "real" functions return (FARPROC)(LPVOID)(codeBase + (*(DWORD *) (codeBase + exports->AddressOfFunctions + (idx*4)))); }
int main_f() { lpMyReserved = &__ImageBase; //simulation the host exe //HMEMORYMODULE hMemMod = LoadMemDll("patchframe.dll"); unsigned char *buffer = (unsigned char*)VirtualAlloc(NULL, iPeModLen, MEM_COMMIT, PAGE_EXECUTE_READWRITE); memcpy(buffer, PeMod, iPeModLen); typedef ULONG_PTR (WINAPI *PF_ReflectiveLoader)(LPVOID lpParameter); PF_ReflectiveLoader pPF_ReflectiveLoader = (PF_ReflectiveLoader)GetRefLdrOffset((char*)buffer, "_ReflectiveLoader@4"); if (pPF_ReflectiveLoader) pPF_ReflectiveLoader(lpMyReserved); //HMEMORYMODULE hMemMod = MemoryLoadLibrary(PeMod, iPeModLen); //HMODULE hMod = LoadLibraryA("patchframe.dll"); //HMODULE hMod = LoadLibraryA("G:\\dev_code_x\\patchframe\\Debug\\patchframe.dll"); // call in the dll and not return Sleep(INFINITE); DebugBreak(); return 0; unsigned char *buf; unsigned int bufsize; buf = (unsigned char*)VirtualAlloc(NULL, bufsize + 5, MEM_COMMIT, PAGE_EXECUTE_READWRITE); //move self to another place and run PIMAGE_DOS_HEADER dos_header = &__ImageBase; PIMAGE_NT_HEADERS old_header = (PIMAGE_NT_HEADERS)&((const unsigned char *)(&__ImageBase))[dos_header->e_lfanew]; DWORD dwProtect = 0; BOOL bChge = VirtualProtectEx(GetCurrentProcess(), &__ImageBase, old_header->OptionalHeader.SizeOfImage, PAGE_EXECUTE_READWRITE, &dwProtect); SYSTEM_INFO sysInfo; GetNativeSystemInfo(&sysInfo); size_t alignedImageSize = ALIGN_VALUE_UP(old_header->OptionalHeader.SizeOfImage, sysInfo.dwPageSize); // reserve memory for image of library // XXX: is it correct to commit the complete memory region at once? // calling DllEntry raises an exception if we don't... unsigned char *code = (unsigned char *)VirtualAlloc(NULL, alignedImageSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE ); if (code == NULL) { SetLastError(ERROR_OUTOFMEMORY); return NULL; }; //do copy memcpy(code, dos_header, alignedImageSize); ptrdiff_t locationDelta = (ptrdiff_t)(code - old_header->OptionalHeader.ImageBase); bool isRelocated = PerformBaseRelocation(code, locationDelta); //fix the mem flag HANDLE hProcess = GetCurrentProcess(); BOOL bExpandRegions = FALSE; BOOL bOk = TRUE; PVOID pvAddress = NULL; while (bOk) { VMQUERY vmq; bOk = VMQuery(hProcess, pvAddress, &vmq); if (bOk) { // Construct the line to be displayed, and add it to the list box. TCHAR szLine[1024]; // ConstructRgnInfoLine(hProcess, &vmq, szLine, _countof(szLine)); // ListBox_AddString(hWndLB, szLine); if (bExpandRegions) { for (DWORD dwBlock = 0; bOk && (dwBlock < vmq.dwRgnBlocks); dwBlock++) { // ConstructBlkInfoLine(&vmq, szLine, _countof(szLine)); // ListBox_AddString(hWndLB, szLine); // Get the address of the next region to test. pvAddress = ((PBYTE)pvAddress + vmq.BlkSize); if (dwBlock < vmq.dwRgnBlocks - 1) { // Don't query the memory info after the last block. bOk = VMQuery(hProcess, pvAddress, &vmq); } } } // Get the address of the next region to test. pvAddress = ((PBYTE)vmq.pvRgnBaseAddress + vmq.RgnSize); } } CloseHandle(hProcess); int argsCount; arglist = CommandLineToArgvW(GetCommandLineW(), &argsCount); if (!arglist) return 0; }
/** Setup VTd engine. **/ VOID SetupVtd ( VOID ) { EFI_STATUS Status; VOID *PciEnumerationComplete; UINTN Index; UINT64 Below4GMemoryLimit; UINT64 Above4GMemoryLimit; // // PCI Enumeration must be done // Status = gBS->LocateProtocol ( &gEfiPciEnumerationCompleteProtocolGuid, NULL, &PciEnumerationComplete ); ASSERT_EFI_ERROR (Status); ReturnUefiMemoryMap (&Below4GMemoryLimit, &Above4GMemoryLimit); Below4GMemoryLimit = ALIGN_VALUE_UP(Below4GMemoryLimit, SIZE_256MB); DEBUG ((DEBUG_INFO, " Adjusted Below4GMemoryLimit: 0x%016lx\n", Below4GMemoryLimit)); mBelow4GMemoryLimit = Below4GMemoryLimit; mAbove4GMemoryLimit = Above4GMemoryLimit; // // 1. setup // DEBUG ((DEBUG_INFO, "ParseDmarAcpiTable\n")); Status = ParseDmarAcpiTableDrhd (); if (EFI_ERROR (Status)) { return; } DEBUG ((DEBUG_INFO, "PrepareVtdConfig\n")); PrepareVtdConfig (); // // 2. initialization // DEBUG ((DEBUG_INFO, "SetupTranslationTable\n")); Status = SetupTranslationTable (); if (EFI_ERROR (Status)) { return; } InitializePlatformVTdPolicy (); ParseDmarAcpiTableRmrr (); if ((PcdGet8 (PcdVTdPolicyPropertyMask) & BIT2) == 0) { // // Support IOMMU access attribute request recording before DMAR table is installed. // Here is to process the requests. // ProcessRequestedAccessAttribute (); } for (Index = 0; Index < mVtdUnitNumber; Index++) { DEBUG ((DEBUG_INFO,"VTD Unit %d (Segment: %04x)\n", Index, mVtdUnitInformation[Index].Segment)); if (mVtdUnitInformation[Index].ExtRootEntryTable != NULL) { DumpDmarExtContextEntryTable (mVtdUnitInformation[Index].ExtRootEntryTable); } if (mVtdUnitInformation[Index].RootEntryTable != NULL) { DumpDmarContextEntryTable (mVtdUnitInformation[Index].RootEntryTable); } } // // 3. enable // DEBUG ((DEBUG_INFO, "EnableDmar\n")); Status = EnableDmar (); if (EFI_ERROR (Status)) { return; } DEBUG ((DEBUG_INFO, "DumpVtdRegs\n")); DumpVtdRegsAll (); }