Created
October 6, 2020 03:01
-
-
Save JohnLaTwC/0b7d3e0132f8d0247801d0c02dd8c1ec to your computer and use it in GitHub Desktop.
Revisions
-
JohnLaTwC created this gist
Oct 6, 2020 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,295 @@ // Raccine // A Simple Ransomware Vaccine // https://github.com/Neo23x0/Raccine // // Florian Roth, Ollie Whitehouse #include <WCHAR.h> #include <windows.h> #include <tlhelp32.h> #include <stdio.h> #include <string.h> #include <stdio.h> #include <chrono> #include <thread> #include <locale.h> #include <psapi.h> #include <string> #include <vector> #pragma comment(lib,"advapi32.lib") DWORD getppid(DWORD pid) { PROCESSENTRY32 pe32; HANDLE hSnapshot; DWORD ppid = 0; hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); __try { if (hSnapshot == INVALID_HANDLE_VALUE) __leave; ZeroMemory(&pe32, sizeof(pe32)); pe32.dwSize = sizeof(pe32); if (!Process32First(hSnapshot, &pe32)) __leave; do { if (pe32.th32ProcessID == pid){ ppid = pe32.th32ParentProcessID; break; } } while (Process32Next(hSnapshot, &pe32)); } __finally { if (hSnapshot != INVALID_HANDLE_VALUE) CloseHandle(hSnapshot); } return ppid; } DWORD IntegrityLevel(HANDLE hProcess) { HANDLE hToken = INVALID_HANDLE_VALUE; DWORD dwIntegrityLevel = 0; PTOKEN_MANDATORY_LABEL pTIL; DWORD dwLengthNeeded = sizeof(pTIL); OpenProcessToken(hProcess, TOKEN_QUERY, &hToken); GetTokenInformation(hToken, TokenIntegrityLevel, NULL, 0, &dwLengthNeeded); pTIL = (PTOKEN_MANDATORY_LABEL) LocalAlloc(0, dwLengthNeeded); if (!pTIL) { return 0; } if (GetTokenInformation(hToken, TokenIntegrityLevel, pTIL, dwLengthNeeded, &dwLengthNeeded)) { dwIntegrityLevel = *GetSidSubAuthority(pTIL->Label.Sid, (DWORD)(UCHAR)(*GetSidSubAuthorityCount(pTIL->Label.Sid) - 1)); LocalFree(pTIL); if (dwIntegrityLevel == SECURITY_MANDATORY_LOW_RID) { // Low Integrity return 1; } else if (dwIntegrityLevel >= SECURITY_MANDATORY_MEDIUM_RID && dwIntegrityLevel < SECURITY_MANDATORY_HIGH_RID) { // Medium Integrity return 2; } else if (dwIntegrityLevel >= SECURITY_MANDATORY_HIGH_RID && dwIntegrityLevel < SECURITY_MANDATORY_SYSTEM_RID) { // High Integrity return 3; } else if (dwIntegrityLevel >= SECURITY_MANDATORY_SYSTEM_RID) { // System Integrity return 4; } else { return 0; } } else { LocalFree(pTIL); return 0; } return 0; } BOOL isallowlisted(DWORD pid) { WCHAR allowlist[3][MAX_PATH] = { L"wininit.exe", L"winlogon.exe", L"explorer.exe" }; PROCESSENTRY32 pe32 = { 0 }; HANDLE hSnapshot; hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); __try { if(hSnapshot == INVALID_HANDLE_VALUE) __leave; ZeroMemory(&pe32, sizeof(pe32)); pe32.dwSize = sizeof(pe32); if (!Process32First(hSnapshot, &pe32)) __leave; do { if (pe32.th32ProcessID == pid){ for (uint8_t i = 0; i < ARRAYSIZE(allowlist); i++) { if (_wcsicmp((wchar_t*)pe32.szExeFile, allowlist[i]) == 0 ) { HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pe32.th32ProcessID); if (hProcess != NULL) { wchar_t filePath[MAX_PATH] = { 0 }; if (GetModuleFileNameEx(hProcess, NULL, filePath, MAX_PATH)) { DWORD dwInLevel = IntegrityLevel(hProcess); // Are they in the Windows directory? if (_wcsnicmp(filePath, L"C:\\Windows\\System32\\", wcslen(L"C:\\Windows\\System32\\")) == 0) { // Is the process running as SYSTEM if (IntegrityLevel(hProcess) == 4) { CloseHandle(hProcess); return TRUE; } } // Are you explorer running in the Windows dir if (_wcsnicmp(filePath, L"C:\\Windows\\Explorer.exe", wcslen(L"C:\\Windows\\Explorer.exe")) == 0) { // Is the process running as MEDIUM (which Explorer does) if (IntegrityLevel(hProcess) == 2) { CloseHandle(hProcess); return TRUE; } } } else { CloseHandle(hProcess); } } } // _wcsicmp } break; } } while (Process32Next(hSnapshot, &pe32)); } __finally { if (hSnapshot != INVALID_HANDLE_VALUE) CloseHandle(hSnapshot); } return FALSE; } BOOL killprocess(DWORD dwProcessId, UINT uExitCode) { DWORD dwDesiredAccess = PROCESS_TERMINATE; BOOL bInheritHandle = FALSE; HANDLE hProcess = OpenProcess(dwDesiredAccess, bInheritHandle, dwProcessId); if (hProcess == NULL) return FALSE; BOOL result = TerminateProcess(hProcess, uExitCode); CloseHandle(hProcess); return result; } int wmain(int argc, WCHAR* argv[]) { DWORD pids[1024] = { 0 }; uint8_t c = 0; DWORD pid = GetCurrentProcessId(); setlocale(LC_ALL, ""); bool bVssadmin = false; bool bWmic = false; bool bWbadmin = false; bool bDelete = false; bool bShadow = false; bool bResize = false; bool bShadowStorage = false; bool bShadowCopy = false; bool bCatalog = false; bool bQuiet = false; if (argc > 1) { // check for invoked program if ((_wcsicmp(L"vssadmin.exe", argv[1]) == 0) || (_wcsicmp(L"vssadmin", argv[1]) == 0)) { bVssadmin = true; } else if ((_wcsicmp(L"wmic.exe", argv[1]) == 0) || (_wcsicmp(L"wmic", argv[1]) == 0)) { bWmic = true; } else if ((_wcsicmp(L"wbadmin.exe", argv[1]) == 0) || (_wcsicmp(L"wbadmin", argv[1]) == 0)) { bWbadmin = true; } } // check for keywords in command line parameters for (int iCount = 0; iCount < argc; iCount++) { if (_wcsicmp(L"delete", argv[iCount]) == 0) { bDelete = true; } else if (_wcsicmp(L"shadows", argv[iCount]) == 0) { bShadow = true; } else if (_wcsicmp(L"shadowstorage", argv[iCount]) == 0) { bShadowStorage = true; } else if (_wcsicmp(L"resize", argv[iCount]) == 0) { bResize = true; } else if (_wcsicmp(L"shadowcopy", argv[iCount]) == 0) { bShadowCopy = true; } else if (_wcsicmp(L"catalog", argv[iCount]) == 0) { bCatalog = true; } else if (_wcsicmp(L"-quiet", argv[iCount]) == 0) { bQuiet = true; } } // OK this is not want we want // we want to kill the process responsible if ((bVssadmin && bDelete && bShadow) || (bVssadmin && bResize && bShadowStorage) || // vssadmin.exe (bWmic && bDelete && bShadowCopy) || // wmic.exe (bWbadmin && bDelete && bCatalog && bQuiet)) { // wbadmin.exe wprintf(L"Raccine detected malicious activity\n"); // Collect PIDs to kill while (true) { try { pid = getppid(pid); if (pid == 0) { break; } if (!isallowlisted(pid)) { wprintf(L"Collecting PID %d for a kill\n", pid); pids[c] = pid; c++; } else { wprintf(L"Process with PID %d is on allowlist\n", pid); } } catch (...) { wprintf(L"Couldn't kill PID %d\n", pid); break; } } // Loop over collected PIDs and try to kill the processes for (uint8_t i = c; i > 0; --i) { wprintf(L"Kill PID %d\n", pids[i - 1]); killprocess(pids[i - 1], 1); } wprintf(L"Raccine v0.5.0 finished\n"); std::this_thread::sleep_for(std::chrono::milliseconds(5000)); } // // Otherwise launch it // else { DEBUG_EVENT debugEvent = { 0 }; std::wstring commandLineStr = L""; for (int i = 1; i < argc; i++) commandLineStr.append(std::wstring(argv[i]).append(L" ")); STARTUPINFO info = { sizeof(info) }; PROCESS_INFORMATION processInfo; if (CreateProcess(NULL, (LPWSTR)commandLineStr.c_str(), NULL, NULL, TRUE, DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS, NULL, NULL, &info, &processInfo)) { DebugActiveProcessStop(processInfo.dwProcessId); WaitForSingleObject(processInfo.hProcess, INFINITE); CloseHandle(processInfo.hProcess); CloseHandle(processInfo.hThread); } } return 0; }