Created
October 6, 2020 03:01
-
-
Save JohnLaTwC/0b7d3e0132f8d0247801d0c02dd8c1ec to your computer and use it in GitHub Desktop.
raccine
This file contains 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 characters
// 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; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment