Skip to content

Instantly share code, notes, and snippets.

@JohnLaTwC
Created October 6, 2020 03:01
Show Gist options
  • Save JohnLaTwC/0b7d3e0132f8d0247801d0c02dd8c1ec to your computer and use it in GitHub Desktop.
Save JohnLaTwC/0b7d3e0132f8d0247801d0c02dd8c1ec to your computer and use it in GitHub Desktop.
raccine
// 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