Add files via upload
This commit is contained in:
12 files changed
+708
-287
No files matched your search
@@ -171,19 +171,19 @@ static NTSTATUS AttachFsFilters(PDRIVER_OBJECT DriverObject)
|
||||
NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(RegistryPath);
|
||||
|
||||
|
||||
KeInitializeSpinLock(&g_ProtectLock);
|
||||
ExInitializeFastMutex(&HookMutex);
|
||||
KeInitializeEvent(&g_LogDrainEvent, NotificationEvent, TRUE);
|
||||
g_Unloading = FALSE;
|
||||
g_CmRegActive = FALSE;
|
||||
|
||||
|
||||
InterlockedExchange(&g_LogWorkCount, 0);
|
||||
ExInitializeRundownProtection(&g_Rundown);
|
||||
{
|
||||
UNICODE_STRING guardName = RTL_CONSTANT_STRING(L"\\Device\\PYAS_Driver_Guard");
|
||||
NTSTATUS gs = IoCreateDevice(DriverObject, 0, &guardName, FILE_DEVICE_UNKNOWN, 0, FALSE, &g_GuardDevice);
|
||||
if (!NT_SUCCESS(gs))
|
||||
if (!NT_SUCCESS(gs))
|
||||
return STATUS_DEVICE_BUSY;
|
||||
}
|
||||
{
|
||||
@@ -194,12 +194,13 @@ NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
|
||||
g_DeviceName.Length = (USHORT)(wcslen(g_DeviceName.Buffer) * sizeof(WCHAR));
|
||||
}
|
||||
NTSTATUS status = IoCreateDevice(DriverObject, 0, &g_DeviceName, FILE_DEVICE_UNKNOWN, 0, FALSE, &g_ControlDeviceObject);
|
||||
if (!NT_SUCCESS(status))
|
||||
if (!NT_SUCCESS(status))
|
||||
return status;
|
||||
|
||||
|
||||
DriverObject->DriverUnload = DriverUnload;
|
||||
for (ULONG i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; ++i)
|
||||
for (ULONG i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; ++i)
|
||||
DriverObject->MajorFunction[i] = CombinedDispatch;
|
||||
|
||||
g_ControlDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
|
||||
IoDeleteSymbolicLink(&g_SymLink);
|
||||
{
|
||||
@@ -208,6 +209,7 @@ NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
|
||||
status = IoCreateSymbolicLink(&g_SymLink, &g_DeviceName);
|
||||
if (NT_SUCCESS(status))
|
||||
break;
|
||||
|
||||
LARGE_INTEGER d = { 0 };
|
||||
d.QuadPart = -10LL * 1000LL * 10LL;
|
||||
KeDelayExecutionThread(KernelMode, FALSE, &d);
|
||||
@@ -216,10 +218,7 @@ NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
|
||||
if (!NT_SUCCESS(status)) {
|
||||
IoDeleteDevice(g_ControlDeviceObject);
|
||||
g_ControlDeviceObject = NULL;
|
||||
if (g_GuardDevice) {
|
||||
IoDeleteDevice(g_GuardDevice);
|
||||
g_GuardDevice = NULL;
|
||||
}
|
||||
if (g_GuardDevice) { IoDeleteDevice(g_GuardDevice); g_GuardDevice = NULL; }
|
||||
return status;
|
||||
}
|
||||
}
|
||||
@@ -230,32 +229,40 @@ NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
|
||||
LARGE_INTEGER t = KeQueryPerformanceCounter(NULL);
|
||||
RtlStringCchPrintfW(regAltBuf, RTL_NUMBER_OF(regAltBuf), L"385100.%I64x", t.QuadPart);
|
||||
RtlInitUnicodeString(®Alt, regAltBuf);
|
||||
|
||||
status = CmRegisterCallbackEx(RegistryProtectCallback, ®Alt, DriverObject, NULL, &g_CmRegHandle, NULL);
|
||||
if (NT_SUCCESS(status))
|
||||
if (NT_SUCCESS(status))
|
||||
g_CmRegActive = TRUE;
|
||||
}
|
||||
InitImageProtect();
|
||||
InitInjectProtect();
|
||||
InitRemoteProtect();
|
||||
InitScreenProtect();
|
||||
AttachFsFilters(DriverObject);
|
||||
AttachDiskFilters(DriverObject);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
VOID DriverUnload(PDRIVER_OBJECT DriverObject)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(DriverObject);
|
||||
|
||||
g_Unloading = TRUE;
|
||||
if (g_SymLinkCreated) {
|
||||
IoDeleteSymbolicLink(&g_SymLink);
|
||||
g_SymLinkCreated = FALSE;
|
||||
g_SymLinkCreated = FALSE;
|
||||
}
|
||||
if (g_CmRegActive) {
|
||||
CmUnRegisterCallback(g_CmRegHandle);
|
||||
g_CmRegActive = FALSE;
|
||||
if (g_CmRegActive) {
|
||||
CmUnRegisterCallback(g_CmRegHandle);
|
||||
g_CmRegActive = FALSE;
|
||||
}
|
||||
UninitInjectProtect();
|
||||
UninitImageProtect();
|
||||
UninitRemoteProtect();
|
||||
UninitScreenProtect();
|
||||
ExWaitForRundownProtectionRelease(&g_Rundown);
|
||||
|
||||
if (InterlockedCompareExchange(&g_LogWorkCount, 0, 0) != 0) {
|
||||
KeResetEvent(&g_LogDrainEvent);
|
||||
while (InterlockedCompareExchange(&g_LogWorkCount, 0, 0) != 0)
|
||||
@@ -269,16 +276,16 @@ VOID DriverUnload(PDRIVER_OBJECT DriverObject)
|
||||
}
|
||||
}
|
||||
g_MbrFilterCount = 0;
|
||||
if (DiskDrvObj) {
|
||||
ObDereferenceObject(DiskDrvObj);
|
||||
DiskDrvObj = NULL;
|
||||
if (DiskDrvObj) {
|
||||
ObDereferenceObject(DiskDrvObj);
|
||||
DiskDrvObj = NULL;
|
||||
}
|
||||
if (g_ControlDeviceObject) {
|
||||
if (g_ControlDeviceObject) {
|
||||
IoDeleteDevice(g_ControlDeviceObject);
|
||||
g_ControlDeviceObject = NULL;
|
||||
}
|
||||
if (g_GuardDevice) {
|
||||
IoDeleteDevice(g_GuardDevice);
|
||||
g_GuardDevice = NULL;
|
||||
g_GuardDevice = NULL;
|
||||
}
|
||||
}
|
||||
@@ -97,6 +97,7 @@ static __forceinline PVOID PYAS_ExAllocatePool2(ULONG f, SIZE_T s, ULONG t) {
|
||||
static __forceinline VOID PYAS_ExFreePool2(PVOID a, ULONG t, PVOID h, ULONG f) {
|
||||
UNREFERENCED_PARAMETER(h);
|
||||
UNREFERENCED_PARAMETER(f);
|
||||
|
||||
static _pyas_ExFreePool2 p2 = 0;
|
||||
if (!p2) {
|
||||
UNICODE_STRING n = RTL_CONSTANT_STRING(L"ExFreePool2");
|
||||
@@ -124,6 +125,8 @@ VOID DriverUnload(PDRIVER_OBJECT DriverObject);
|
||||
VOID SendPipeLog(PCSTR msg, SIZE_T len);
|
||||
VOID UninitImageProtect(VOID);
|
||||
VOID UninitInjectProtect(VOID);
|
||||
VOID UninitRemoteProtect(VOID);
|
||||
VOID UninitScreenProtect(VOID);
|
||||
|
||||
NTSYSAPI NTSTATUS NTAPI ZwQueryInformationProcess(
|
||||
_In_ HANDLE ProcessHandle,
|
||||
@@ -148,5 +151,7 @@ NTSTATUS FileProtectDispatch(PDEVICE_OBJECT DeviceObject, PIRP Irp);
|
||||
NTSTATUS RegistryProtectCallback(PVOID ctx, PVOID arg1, PVOID arg2);
|
||||
NTSTATUS InitImageProtect(VOID);
|
||||
NTSTATUS InitInjectProtect(VOID);
|
||||
NTSTATUS InitRemoteProtect(VOID);
|
||||
NTSTATUS InitScreenProtect(VOID);
|
||||
|
||||
BOOLEAN GetProcessImagePathByPid(HANDLE pid, PUNICODE_STRING ProcessImagePath);
|
||||
@@ -1,6 +1,6 @@
|
||||
#include <ntifs.h>
|
||||
#include "DriverEntry.h"
|
||||
#include "ProtectRules.h"
|
||||
#include "ProtectMatch.h"
|
||||
|
||||
static BOOLEAN GetFilePathFromFileObject(PFILE_OBJECT fo, PUNICODE_STRING out)
|
||||
{
|
||||
|
||||
@@ -1,35 +1,15 @@
|
||||
#include <ntifs.h>
|
||||
#include "DriverEntry.h"
|
||||
#include "ProtectRules.h"
|
||||
#include "ProtectMatch.h"
|
||||
|
||||
static BOOLEAN g_ImageNotifyEnabled = FALSE;
|
||||
|
||||
static BOOLEAN StrStrI(const wchar_t* s, const wchar_t* sub)
|
||||
{
|
||||
if (!s || !sub)
|
||||
return FALSE;
|
||||
size_t n = wcslen(s), m = wcslen(sub);
|
||||
if (m == 0 || n < m)
|
||||
return FALSE;
|
||||
for (size_t i = 0; i + m <= n; i++) {
|
||||
size_t j = 0;
|
||||
for (; j < m; j++) {
|
||||
WCHAR a = s[i + j], b = sub[j];
|
||||
if (a >= L'A' && a <= L'Z') a += 32;
|
||||
if (b >= L'A' && b <= L'Z') b += 32;
|
||||
if (a != b) break;
|
||||
}
|
||||
if (j == m)
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static BOOLEAN CheckVadExec(PVOID a)
|
||||
{
|
||||
MEMORY_BASIC_INFORMATION mbi = { 0 };
|
||||
SIZE_T ret = 0;
|
||||
NTSTATUS s = ZwQueryVirtualMemory(NtCurrentProcess(), a, MemoryBasicInformation, &mbi, sizeof(mbi), &ret);
|
||||
|
||||
if (!NT_SUCCESS(s))
|
||||
return FALSE;
|
||||
if (mbi.State != MEM_COMMIT)
|
||||
@@ -48,9 +28,11 @@ static BOOLEAN WalkForShellcode(ULONG h)
|
||||
ULONG c = RtlWalkFrameChain(frames, MAXWALK, 1);
|
||||
if (c == 0)
|
||||
return FALSE;
|
||||
|
||||
ULONG limit = RTL_NUMBER_OF(frames);
|
||||
ULONG count = c < limit ? c : limit;
|
||||
ULONG d = h < count ? h : count;
|
||||
|
||||
for (ULONG i = 0; i < d; i++) {
|
||||
PVOID p = frames[i];
|
||||
if (p && CheckVadExec(p))
|
||||
@@ -67,25 +49,13 @@ static BOOLEAN WalkForShellcode(ULONG h)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static BOOLEAN IsFrameworkClrPath(const wchar_t* s)
|
||||
{
|
||||
if (!s)
|
||||
return FALSE;
|
||||
if (!StrStrI(s, L"\\Windows\\Microsoft.NET\\"))
|
||||
return FALSE;
|
||||
if (!StrStrI(s, L"\\Framework\\") && !StrStrI(s, L"\\Framework64\\"))
|
||||
return FALSE;
|
||||
if (StrStrI(s, L"\\clr.dll") || StrStrI(s, L"\\mscorwks.dll"))
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static VOID LogAnsi3(PCSTR tag, ULONG upid, PUNICODE_STRING s1, PUNICODE_STRING s2)
|
||||
{
|
||||
ANSI_STRING a1 = { 0 }, a2 = { 0 };
|
||||
CHAR buf[1024] = { 0 };
|
||||
RtlUnicodeStringToAnsiString(&a1, s1, TRUE);
|
||||
if (s2) RtlUnicodeStringToAnsiString(&a2, s2, TRUE);
|
||||
if (s2)
|
||||
RtlUnicodeStringToAnsiString(&a2, s2, TRUE);
|
||||
RtlStringCchPrintfA(buf, RTL_NUMBER_OF(buf), "%s | %u | %s | %s", tag, upid, a1.Buffer ? a1.Buffer : "", a2.Buffer ? a2.Buffer : "");
|
||||
SendPipeLog(buf, strlen(buf));
|
||||
RtlFreeAnsiString(&a1);
|
||||
@@ -134,7 +104,7 @@ static VOID ImageLoadNotify(IN PUNICODE_STRING FullImageName, IN HANDLE ProcessI
|
||||
return;
|
||||
}
|
||||
if (FullImageName && FullImageName->Buffer) {
|
||||
if ((StrStrI(FullImageName->Buffer, L"clr.dll") || StrStrI(FullImageName->Buffer, L"mscorwks.dll")) && !IsFrameworkClrPath(FullImageName->Buffer)) {
|
||||
if (MatchClrFromNonFramework(FullImageName)) {
|
||||
LogAnsi3("CLR_BLOCK", (ULONG)(ULONG_PTR)ProcessId, &exe, FullImageName);
|
||||
ExReleaseRundownProtection(&g_Rundown);
|
||||
return;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#include <ntifs.h>
|
||||
#include "DriverEntry.h"
|
||||
#include "ProtectRules.h"
|
||||
#include "ProtectMatch.h"
|
||||
|
||||
static PVOID g_ObRegHandle = NULL;
|
||||
static POB_OPERATION_REGISTRATION g_ObOps = NULL;
|
||||
|
||||
@@ -0,0 +1,372 @@
|
||||
#include <ntifs.h>
|
||||
#include "DriverEntry.h"
|
||||
#include "ProtectRules.h"
|
||||
#include "ProtectMatch.h"
|
||||
|
||||
static BOOLEAN WildMatchN(const wchar_t* str, SIZE_T n, const wchar_t* pat)
|
||||
{
|
||||
if (*pat == 0)
|
||||
return n == 0;
|
||||
|
||||
if (*pat == L'*') {
|
||||
if (pat[1] == L'*') {
|
||||
for (SIZE_T i = 0; i <= n; ++i)
|
||||
if (WildMatchN(str + i, n - i, pat + 2))
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
SIZE_T i = 0;
|
||||
for (; i < n && str[i] != L'\\'; ++i)
|
||||
if (WildMatchN(str + i, n - i, pat + 1))
|
||||
return TRUE;
|
||||
return WildMatchN(str + i, n - i, pat + 1);
|
||||
}
|
||||
if (*pat == L'?')
|
||||
return n > 0 && str[0] != L'\\' && WildMatchN(str + 1, n - 1, pat + 1);
|
||||
if (n == 0)
|
||||
return FALSE;
|
||||
|
||||
WCHAR sc = str[0], pc = *pat;
|
||||
if (sc >= L'A' && sc <= L'Z')
|
||||
sc += 32;
|
||||
if (pc >= L'A' && pc <= L'Z')
|
||||
pc += 32;
|
||||
return sc == pc && WildMatchN(str + 1, n - 1, pat + 1);
|
||||
}
|
||||
|
||||
static BOOLEAN MatchList(PUNICODE_STRING s, wchar_t** list)
|
||||
{
|
||||
if (!s || !s->Buffer || s->Length == 0)
|
||||
return FALSE;
|
||||
|
||||
size_t s_len = s->Length / sizeof(WCHAR);
|
||||
for (SIZE_T i = 0; list[i]; ++i) {
|
||||
wchar_t* pat = list[i];
|
||||
size_t pat_len = wcslen(pat);
|
||||
if (wcschr(pat, L'*') || wcschr(pat, L'?')) {
|
||||
if (WildMatchN(s->Buffer, s_len, pat))
|
||||
return TRUE;
|
||||
}
|
||||
else {
|
||||
if (s_len == pat_len && _wcsnicmp(s->Buffer, pat, pat_len) == 0)
|
||||
return TRUE;
|
||||
if (s_len > pat_len && _wcsnicmp(s->Buffer + s_len - pat_len, pat, pat_len) == 0)
|
||||
return TRUE;
|
||||
if (s_len > pat_len && _wcsnicmp(s->Buffer, pat, pat_len) == 0)
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static wchar_t* MatchListGetRule(PUNICODE_STRING s, wchar_t** list)
|
||||
{
|
||||
if (!s || !s->Buffer || s->Length == 0)
|
||||
return 0;
|
||||
|
||||
size_t s_len = s->Length / sizeof(WCHAR);
|
||||
for (SIZE_T i = 0; list[i]; ++i) {
|
||||
wchar_t* pat = list[i];
|
||||
size_t pat_len = wcslen(pat);
|
||||
if (wcschr(pat, L'*') || wcschr(pat, L'?')) {
|
||||
if (WildMatchN(s->Buffer, s_len, pat))
|
||||
return pat;
|
||||
}
|
||||
else {
|
||||
if (s_len == pat_len && _wcsnicmp(s->Buffer, pat, pat_len) == 0)
|
||||
return pat;
|
||||
if (s_len > pat_len && _wcsnicmp(s->Buffer + s_len - pat_len, pat, pat_len) == 0)
|
||||
return pat;
|
||||
if (s_len > pat_len && _wcsnicmp(s->Buffer, pat, pat_len) == 0)
|
||||
return pat;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static __forceinline BOOLEAN USOK(PUNICODE_STRING s)
|
||||
{
|
||||
return s && s->Buffer && s->Length;
|
||||
}
|
||||
|
||||
static BOOLEAN StrStrIW(const wchar_t* s, const wchar_t* sub)
|
||||
{
|
||||
if (!s || !sub)
|
||||
return FALSE;
|
||||
|
||||
SIZE_T n = wcslen(s), m = wcslen(sub);
|
||||
if (m == 0 || n < m)
|
||||
return FALSE;
|
||||
|
||||
for (SIZE_T i = 0; i + m <= n; i++) {
|
||||
SIZE_T j = 0;
|
||||
for (; j < m; j++) {
|
||||
WCHAR a = s[i + j], b = sub[j];
|
||||
if (a >= L'A' && a <= L'Z') a += 32;
|
||||
if (b >= L'A' && b <= L'Z') b += 32;
|
||||
if (a != b) break;
|
||||
}
|
||||
if (j == m)
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static BOOLEAN EndsWithNameUS(PUNICODE_STRING s, const wchar_t* name)
|
||||
{
|
||||
if (!USOK(s) || !name)
|
||||
return FALSE;
|
||||
SIZE_T n = s->Length / sizeof(WCHAR);
|
||||
SIZE_T m = wcslen(name);
|
||||
if (n < m)
|
||||
return FALSE;
|
||||
return _wcsnicmp(s->Buffer + (n - m), name, m) == 0;
|
||||
}
|
||||
|
||||
BOOLEAN IsRegistryBlock(PUNICODE_STRING key, PUNICODE_STRING valueName, PUNICODE_STRING exe)
|
||||
{
|
||||
if (USOK(key)) {
|
||||
size_t klen0 = key->Length / sizeof(WCHAR);
|
||||
if (WildMatchN(key->Buffer, klen0, L"\\REGISTRY\\MACHINE\\SYSTEM\\ControlSet001\\Services\\**"))
|
||||
return FALSE;
|
||||
}
|
||||
if (USOK(exe)) {
|
||||
if (IsWhitelist(exe))
|
||||
return FALSE;
|
||||
}
|
||||
if (USOK(exe) && USOK(key)) {
|
||||
size_t elen = exe->Length / sizeof(WCHAR);
|
||||
size_t klen = key->Length / sizeof(WCHAR);
|
||||
|
||||
if (((elen >= 12 && _wcsnicmp(exe->Buffer + elen - 12, L"services.exe", 12) == 0) ||
|
||||
(elen >= 11 && _wcsnicmp(exe->Buffer + elen - 11, L"svchost.exe", 11) == 0) ||
|
||||
(elen >= 6 && _wcsnicmp(exe->Buffer + elen - 6, L"sc.exe", 6) == 0))) {
|
||||
if (WildMatchN(key->Buffer, klen, L"\\REGISTRY\\**\\SYSTEM\\CurrentControlSet\\Services\\**"))
|
||||
return FALSE;
|
||||
}
|
||||
if ((elen >= 14 && _wcsnicmp(exe->Buffer + elen - 14, L"powershell.exe", 14) == 0) ||
|
||||
(elen >= 8 && _wcsnicmp(exe->Buffer + elen - 8, L"pwsh.exe", 8) == 0)) {
|
||||
if (WildMatchN(key->Buffer, klen, L"\\REGISTRY\\**\\CurrentVersion\\Internet Settings\\ZoneMap") ||
|
||||
WildMatchN(key->Buffer, klen, L"\\REGISTRY\\**\\CurrentVersion\\Internet Settings\\ZoneMap\\**") ||
|
||||
WildMatchN(key->Buffer, klen, L"\\REGISTRY\\**\\CurrentVersion\\Notifications\\Data") ||
|
||||
WildMatchN(key->Buffer, klen, L"\\REGISTRY\\**\\CurrentVersion\\Notifications\\Data\\**"))
|
||||
return FALSE;
|
||||
}
|
||||
if ((elen >= 11 && _wcsnicmp(exe->Buffer + elen - 11, L"msiexec.exe", 11) == 0) ||
|
||||
(elen >= 20 && _wcsnicmp(exe->Buffer + elen - 20, L"TrustedInstaller.exe", 20) == 0)) {
|
||||
if (WildMatchN(key->Buffer, klen, L"\\REGISTRY\\**\\CurrentVersion\\Installer\\**") ||
|
||||
WildMatchN(key->Buffer, klen, L"\\REGISTRY\\**\\CurrentVersion\\Uninstall\\**") ||
|
||||
WildMatchN(key->Buffer, klen, L"\\REGISTRY\\**\\SYSTEM\\CurrentControlSet\\Services\\**"))
|
||||
return FALSE;
|
||||
}
|
||||
if (elen >= 12 && _wcsnicmp(exe->Buffer + elen - 12, L"schtasks.exe", 12) == 0) {
|
||||
if (WildMatchN(key->Buffer, klen, L"\\REGISTRY\\**\\Windows NT\\CurrentVersion\\Schedule\\TaskCache\\**"))
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
if (USOK(key)) {
|
||||
if (MatchBlockReg(key))
|
||||
return TRUE;
|
||||
}
|
||||
if (USOK(valueName)) {
|
||||
SIZE_T n = valueName->Length / sizeof(WCHAR);
|
||||
for (SIZE_T i = 0; i < (SIZE_T)-1 && g_BlockReg[i]; ++i) {
|
||||
wchar_t* pat = g_BlockReg[i];
|
||||
if (wcschr(pat, L'\\') || wcschr(pat, L'*') || wcschr(pat, L'?'))
|
||||
continue;
|
||||
size_t m = wcslen(pat);
|
||||
if (n == m && _wcsnicmp(valueName->Buffer, pat, m) == 0)
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOLEAN GetProcessImagePathByPid(HANDLE pid, PUNICODE_STRING ProcessImagePath)
|
||||
{
|
||||
PEPROCESS process = NULL;
|
||||
NTSTATUS status = PsLookupProcessByProcessId(pid, &process);
|
||||
if (!NT_SUCCESS(status))
|
||||
return FALSE;
|
||||
|
||||
HANDLE h = NULL;
|
||||
status = ObOpenObjectByPointer(process, OBJ_KERNEL_HANDLE, NULL, PROCESS_QUERY_LIMITED_INFORMATION, *PsProcessType, KernelMode, &h);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
ObDereferenceObject(process);
|
||||
return FALSE;
|
||||
}
|
||||
ULONG len = 0;
|
||||
status = ZwQueryInformationProcess(h, ProcessImageFileName, NULL, 0, &len);
|
||||
if (status != STATUS_INFO_LENGTH_MISMATCH || len == 0) {
|
||||
ZwClose(h);
|
||||
ObDereferenceObject(process);
|
||||
return FALSE;
|
||||
}
|
||||
PVOID buf = ExAllocatePool2(POOL_FLAG_NON_PAGED, len, 'iPgN');
|
||||
if (!buf) {
|
||||
ZwClose(h);
|
||||
ObDereferenceObject(process);
|
||||
return FALSE;
|
||||
}
|
||||
status = ZwQueryInformationProcess(h, ProcessImageFileName, buf, len, &len);
|
||||
if (NT_SUCCESS(status)) {
|
||||
PUNICODE_STRING image = (PUNICODE_STRING)buf;
|
||||
if (image->Buffer && image->Length > 0 && ProcessImagePath->MaximumLength >= image->Length + sizeof(WCHAR)) {
|
||||
RtlCopyMemory(ProcessImagePath->Buffer, image->Buffer, image->Length);
|
||||
ProcessImagePath->Length = image->Length;
|
||||
ProcessImagePath->Buffer[image->Length / sizeof(WCHAR)] = 0;
|
||||
ExFreePool2(buf, 'iPgN', NULL, 0);
|
||||
ZwClose(h);
|
||||
ObDereferenceObject(process);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
ExFreePool2(buf, 'iPgN', NULL, 0);
|
||||
ZwClose(h);
|
||||
ObDereferenceObject(process);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOLEAN IsWhitelist(PUNICODE_STRING s)
|
||||
{
|
||||
if (MatchList(s, g_WhitelistExcept))
|
||||
return FALSE;
|
||||
return MatchList(s, g_Whitelist);
|
||||
}
|
||||
|
||||
BOOLEAN MatchBlockReg(PUNICODE_STRING s)
|
||||
{
|
||||
return MatchList(s, g_BlockReg);
|
||||
}
|
||||
|
||||
wchar_t* GetMatchedBlockRegRule(PUNICODE_STRING s)
|
||||
{
|
||||
return MatchListGetRule(s, g_BlockReg);
|
||||
}
|
||||
|
||||
BOOLEAN MatchBlockFile(PUNICODE_STRING s)
|
||||
{
|
||||
return MatchList(s, g_BlockFile);
|
||||
}
|
||||
|
||||
BOOLEAN MatchBlockRansom(PUNICODE_STRING s)
|
||||
{
|
||||
return MatchList(s, g_BlockRansom);
|
||||
}
|
||||
|
||||
wchar_t* GetMatchedBlockFileRule(PUNICODE_STRING s)
|
||||
{
|
||||
return MatchListGetRule(s, g_BlockFile);
|
||||
}
|
||||
|
||||
BOOLEAN HasBlockedSuffix(PUNICODE_STRING s)
|
||||
{
|
||||
if (!USOK(s))
|
||||
return FALSE;
|
||||
SIZE_T n = s->Length / sizeof(WCHAR);
|
||||
for (SIZE_T i = 0; g_Blocksuffix[i]; ++i) {
|
||||
wchar_t* ext = g_Blocksuffix[i];
|
||||
SIZE_T m = wcslen(ext);
|
||||
if (n >= m && _wcsnicmp(s->Buffer + (n - m), ext, m) == 0)
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOLEAN MatchRemoteSuspectBin(PUNICODE_STRING img)
|
||||
{
|
||||
for (SIZE_T i = 0; g_RemoteSuspectBins[i]; ++i)
|
||||
if (EndsWithNameUS(img, g_RemoteSuspectBins[i]))
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOLEAN MatchRemoteCommand(PUNICODE_STRING cmd, PUNICODE_STRING img)
|
||||
{
|
||||
if (!USOK(cmd))
|
||||
return FALSE;
|
||||
|
||||
const wchar_t* s = cmd->Buffer;
|
||||
for (SIZE_T i = 0; g_RemoteCmdIndicatorsHttp[i]; ++i)
|
||||
if (StrStrIW(s, g_RemoteCmdIndicatorsHttp[i]))
|
||||
return TRUE;
|
||||
|
||||
for (SIZE_T i = 0; g_RemoteCmdIndicatorsGeneric[i]; ++i)
|
||||
if (StrStrIW(s, g_RemoteCmdIndicatorsGeneric[i]))
|
||||
return TRUE;
|
||||
|
||||
if (USOK(img) && EndsWithNameUS(img, L"cmd.exe")) {
|
||||
for (SIZE_T i = 0; g_RemoteCmdFromCmdExe[i]; ++i)
|
||||
if (StrStrIW(s, g_RemoteCmdFromCmdExe[i]))
|
||||
return TRUE;
|
||||
}
|
||||
if (USOK(img) && EndsWithNameUS(img, L"rundll32.exe")) {
|
||||
for (SIZE_T i = 0; g_RemoteCmdFromRundll32Exe[i]; ++i)
|
||||
if (StrStrIW(s, g_RemoteCmdFromRundll32Exe[i]))
|
||||
return TRUE;
|
||||
}
|
||||
if (USOK(img) && EndsWithNameUS(img, L"regsvr32.exe")) {
|
||||
BOOLEAN need = FALSE, http = FALSE;
|
||||
for (SIZE_T i = 0; g_RemoteCmdRegsvr32Need[i]; ++i)
|
||||
if (StrStrIW(s, g_RemoteCmdRegsvr32Need[i])) {
|
||||
need = TRUE;
|
||||
break;
|
||||
}
|
||||
for (SIZE_T i = 0; g_RemoteCmdIndicatorsHttp[i]; ++i)
|
||||
if (StrStrIW(s, g_RemoteCmdIndicatorsHttp[i])) {
|
||||
http = TRUE;
|
||||
break;
|
||||
}
|
||||
if (need && http)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (USOK(img) && EndsWithNameUS(img, L"mshta.exe")) {
|
||||
for (SIZE_T i = 0; g_RemoteCmdFromMshtaExe[i]; ++i)
|
||||
if (StrStrIW(s, g_RemoteCmdFromMshtaExe[i]))
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOLEAN MatchScreenCapModule(PUNICODE_STRING mod)
|
||||
{
|
||||
for (SIZE_T i = 0; g_ScreenCapModules[i]; ++i)
|
||||
if (EndsWithNameUS(mod, g_ScreenCapModules[i]))
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOLEAN MatchSuspiciousProcPath(PUNICODE_STRING img)
|
||||
{
|
||||
if (!USOK(img))
|
||||
return FALSE;
|
||||
|
||||
const wchar_t* s = img->Buffer;
|
||||
if (StrStrIW(s, L"\\Users\\")) {
|
||||
for (SIZE_T i = 0; g_ScreenUserSubdirs[i]; ++i)
|
||||
if (StrStrIW(s, g_ScreenUserSubdirs[i]))
|
||||
return TRUE;
|
||||
}
|
||||
for (SIZE_T i = 0; g_ScreenOtherProcNeedles[i]; ++i)
|
||||
if (StrStrIW(s, g_ScreenOtherProcNeedles[i]))
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOLEAN MatchClrFromNonFramework(PUNICODE_STRING fullImageName)
|
||||
{
|
||||
if (!USOK(fullImageName))
|
||||
return FALSE;
|
||||
|
||||
const wchar_t* s = fullImageName->Buffer;
|
||||
BOOLEAN isClr = StrStrIW(s, L"\\clr.dll") || StrStrIW(s, L"\\mscorwks.dll");
|
||||
|
||||
if (!isClr)
|
||||
return FALSE;
|
||||
if (!StrStrIW(s, L"\\Windows\\Microsoft.NET\\"))
|
||||
return TRUE;
|
||||
if (!StrStrIW(s, L"\\Framework\\") && !StrStrIW(s, L"\\Framework64\\"))
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
#include <ntifs.h>
|
||||
|
||||
wchar_t* GetMatchedBlockRegRule(PUNICODE_STRING s);
|
||||
wchar_t* GetMatchedBlockFileRule(PUNICODE_STRING s);
|
||||
|
||||
BOOLEAN IsWhitelist(PUNICODE_STRING s);
|
||||
BOOLEAN GetProcessImagePathByPid(HANDLE pid, PUNICODE_STRING ProcessImagePath);
|
||||
|
||||
BOOLEAN MatchBlockReg(PUNICODE_STRING s);
|
||||
BOOLEAN IsRegistryBlock(PUNICODE_STRING key, PUNICODE_STRING valueName, PUNICODE_STRING exe);
|
||||
|
||||
BOOLEAN MatchBlockFile(PUNICODE_STRING s);
|
||||
BOOLEAN MatchBlockRansom(PUNICODE_STRING s);
|
||||
BOOLEAN HasBlockedSuffix(PUNICODE_STRING s);
|
||||
|
||||
BOOLEAN MatchRemoteSuspectBin(PUNICODE_STRING img);
|
||||
BOOLEAN MatchRemoteCommand(PUNICODE_STRING cmd, PUNICODE_STRING img);
|
||||
|
||||
BOOLEAN MatchScreenCapModule(PUNICODE_STRING mod);
|
||||
BOOLEAN MatchSuspiciousProcPath(PUNICODE_STRING img);
|
||||
BOOLEAN MatchClrFromNonFramework(PUNICODE_STRING fullImageName);
|
||||
@@ -1,6 +1,6 @@
|
||||
#include <ntifs.h>
|
||||
#include "ProtectRules.h"
|
||||
#include "DriverEntry.h"
|
||||
#include "ProtectMatch.h"
|
||||
|
||||
static BOOLEAN QueryRegPathFromObject(PVOID KeyObject, PUNICODE_STRING OutPath, POBJECT_NAME_INFORMATION* OutInfo)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
#include <ntifs.h>
|
||||
#include "DriverEntry.h"
|
||||
#include "ProtectMatch.h"
|
||||
|
||||
static BOOLEAN g_RemoteNotifyEnabled = FALSE;
|
||||
|
||||
static VOID LogAnsi3(PCSTR tag, ULONG upid, PUNICODE_STRING s1, PUNICODE_STRING s2)
|
||||
{
|
||||
ANSI_STRING a1 = { 0 }, a2 = { 0 };
|
||||
CHAR buf[1024] = { 0 };
|
||||
RtlUnicodeStringToAnsiString(&a1, s1, TRUE);
|
||||
if (s2)
|
||||
RtlUnicodeStringToAnsiString(&a2, s2, TRUE);
|
||||
RtlStringCchPrintfA(buf, RTL_NUMBER_OF(buf), "%s | %u | %s | %s", tag, upid, a1.Buffer ? a1.Buffer : "", a2.Buffer ? a2.Buffer : "");
|
||||
SendPipeLog(buf, strlen(buf));
|
||||
RtlFreeAnsiString(&a1);
|
||||
RtlFreeAnsiString(&a2);
|
||||
}
|
||||
|
||||
static VOID ProcessNotifyEx(PEPROCESS Process, HANDLE ProcessId, PPS_CREATE_NOTIFY_INFO CreateInfo)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(Process);
|
||||
UNREFERENCED_PARAMETER(ProcessId);
|
||||
|
||||
if (!CreateInfo)
|
||||
return;
|
||||
if (g_Unloading)
|
||||
return;
|
||||
if (KeGetCurrentIrql() != PASSIVE_LEVEL)
|
||||
return;
|
||||
if (!ExAcquireRundownProtection(&g_Rundown))
|
||||
return;
|
||||
|
||||
HANDLE ppid = CreateInfo->CreatingThreadId.UniqueProcess;
|
||||
if (ppid == (HANDLE)0 || ppid == (HANDLE)4) {
|
||||
ExReleaseRundownProtection(&g_Rundown);
|
||||
return;
|
||||
}
|
||||
UNICODE_STRING parent = { 0 };
|
||||
WCHAR pbuf[512] = { 0 };
|
||||
parent.Buffer = pbuf;
|
||||
parent.MaximumLength = sizeof(pbuf);
|
||||
|
||||
if (!GetProcessImagePathByPid(ppid, &parent)) {
|
||||
PEPROCESS eproc = PsGetCurrentProcess();
|
||||
PCSTR n = PsGetProcessImageFileName(eproc);
|
||||
size_t l = n ? strlen(n) : 0;
|
||||
for (size_t i = 0; i < l && i < RTL_NUMBER_OF(pbuf) - 1; i++)
|
||||
pbuf[i] = (WCHAR)n[i];
|
||||
pbuf[l] = 0;
|
||||
parent.Length = (USHORT)(l * sizeof(WCHAR));
|
||||
}
|
||||
if (IsWhitelist(&parent)) {
|
||||
ExReleaseRundownProtection(&g_Rundown);
|
||||
return;
|
||||
}
|
||||
UNICODE_STRING img = { 0 };
|
||||
if (CreateInfo->ImageFileName)
|
||||
img = *CreateInfo->ImageFileName;
|
||||
UNICODE_STRING cmd = { 0 };
|
||||
if (CreateInfo->CommandLine)
|
||||
cmd = *CreateInfo->CommandLine;
|
||||
|
||||
BOOLEAN suspect = FALSE;
|
||||
if (MatchRemoteSuspectBin(&img) && MatchRemoteCommand(&cmd, &img))
|
||||
suspect = TRUE;
|
||||
|
||||
if (suspect) {
|
||||
CreateInfo->CreationStatus = STATUS_ACCESS_DENIED;
|
||||
if (cmd.Buffer && cmd.Length)
|
||||
LogAnsi3("REMOTE_BLOCK", (ULONG)(ULONG_PTR)ppid, &parent, &cmd);
|
||||
else if (img.Buffer && img.Length)
|
||||
LogAnsi3("REMOTE_BLOCK", (ULONG)(ULONG_PTR)ppid, &parent, &img);
|
||||
else {
|
||||
UNICODE_STRING none = RTL_CONSTANT_STRING(L"None");
|
||||
LogAnsi3("REMOTE_BLOCK", (ULONG)(ULONG_PTR)ppid, &parent, &none);
|
||||
}
|
||||
}
|
||||
ExReleaseRundownProtection(&g_Rundown);
|
||||
}
|
||||
|
||||
NTSTATUS InitRemoteProtect(VOID)
|
||||
{
|
||||
NTSTATUS s = PsSetCreateProcessNotifyRoutineEx(ProcessNotifyEx, FALSE);
|
||||
if (NT_SUCCESS(s))
|
||||
g_RemoteNotifyEnabled = TRUE;
|
||||
return s;
|
||||
}
|
||||
|
||||
VOID UninitRemoteProtect(VOID)
|
||||
{
|
||||
if (g_RemoteNotifyEnabled) {
|
||||
PsSetCreateProcessNotifyRoutineEx(ProcessNotifyEx, TRUE);
|
||||
g_RemoteNotifyEnabled = FALSE;
|
||||
}
|
||||
}
|
||||
+76
-217
@@ -1,5 +1,4 @@
|
||||
#include <ntifs.h>
|
||||
#include "DriverEntry.h"
|
||||
#include "ProtectRules.h"
|
||||
|
||||
wchar_t* g_Whitelist[] = {
|
||||
@@ -209,228 +208,88 @@ wchar_t* g_BlockReg[] = {
|
||||
NULL
|
||||
};
|
||||
|
||||
static BOOLEAN WildMatchN(const wchar_t* str, SIZE_T n, const wchar_t* pat)
|
||||
{
|
||||
if (*pat == 0)
|
||||
return n == 0;
|
||||
if (*pat == L'*') {
|
||||
if (pat[1] == L'*') {
|
||||
for (SIZE_T i = 0; i <= n; ++i)
|
||||
if (WildMatchN(str + i, n - i, pat + 2))
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
SIZE_T i = 0;
|
||||
for (; i < n && str[i] != L'\\'; ++i)
|
||||
if (WildMatchN(str + i, n - i, pat + 1))
|
||||
return TRUE;
|
||||
return WildMatchN(str + i, n - i, pat + 1);
|
||||
}
|
||||
if (*pat == L'?')
|
||||
return n > 0 && str[0] != L'\\' && WildMatchN(str + 1, n - 1, pat + 1);
|
||||
if (n == 0)
|
||||
return FALSE;
|
||||
WCHAR sc = str[0], pc = *pat;
|
||||
if (sc >= L'A' && sc <= L'Z')
|
||||
sc += 32;
|
||||
if (pc >= L'A' && pc <= L'Z')
|
||||
pc += 32;
|
||||
return sc == pc && WildMatchN(str + 1, n - 1, pat + 1);
|
||||
}
|
||||
wchar_t* g_RemoteSuspectBins[] = {
|
||||
L"powershell.exe",
|
||||
L"pwsh.exe",
|
||||
L"wscript.exe",
|
||||
L"cscript.exe",
|
||||
L"mshta.exe",
|
||||
L"rundll32.exe",
|
||||
L"regsvr32.exe",
|
||||
L"cmd.exe",
|
||||
L"bitsadmin.exe",
|
||||
L"msbuild.exe",
|
||||
L"installutil.exe",
|
||||
L"wmic.exe",
|
||||
NULL
|
||||
};
|
||||
|
||||
static BOOLEAN MatchList(PUNICODE_STRING s, wchar_t** list)
|
||||
{
|
||||
if (!s || !s->Buffer || s->Length == 0)
|
||||
return FALSE;
|
||||
size_t s_len = s->Length / sizeof(WCHAR);
|
||||
for (SIZE_T i = 0; list[i]; ++i) {
|
||||
wchar_t* pat = list[i];
|
||||
size_t pat_len = wcslen(pat);
|
||||
if (wcschr(pat, L'*') || wcschr(pat, L'?')) {
|
||||
if (WildMatchN(s->Buffer, s_len, pat))
|
||||
return TRUE;
|
||||
}
|
||||
else {
|
||||
if (s_len == pat_len && _wcsnicmp(s->Buffer, pat, pat_len) == 0)
|
||||
return TRUE;
|
||||
if (s_len > pat_len && _wcsnicmp(s->Buffer + s_len - pat_len, pat, pat_len) == 0)
|
||||
return TRUE;
|
||||
if (s_len > pat_len && _wcsnicmp(s->Buffer, pat, pat_len) == 0)
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
wchar_t* g_RemoteCmdIndicatorsHttp[] = {
|
||||
L"http://",
|
||||
L"https://",
|
||||
NULL
|
||||
};
|
||||
|
||||
static wchar_t* MatchListGetRule(PUNICODE_STRING s, wchar_t** list)
|
||||
{
|
||||
if (!s || !s->Buffer || s->Length == 0)
|
||||
return 0;
|
||||
size_t s_len = s->Length / sizeof(WCHAR);
|
||||
for (SIZE_T i = 0; list[i]; ++i) {
|
||||
wchar_t* pat = list[i];
|
||||
size_t pat_len = wcslen(pat);
|
||||
if (wcschr(pat, L'*') || wcschr(pat, L'?')) {
|
||||
if (WildMatchN(s->Buffer, s_len, pat))
|
||||
return pat;
|
||||
}
|
||||
else {
|
||||
if (s_len == pat_len && _wcsnicmp(s->Buffer, pat, pat_len) == 0)
|
||||
return pat;
|
||||
if (s_len > pat_len && _wcsnicmp(s->Buffer + s_len - pat_len, pat, pat_len) == 0)
|
||||
return pat;
|
||||
if (s_len > pat_len && _wcsnicmp(s->Buffer, pat, pat_len) == 0)
|
||||
return pat;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
wchar_t* g_RemoteCmdIndicatorsGeneric[] = {
|
||||
L"-enc",
|
||||
L" -e ",
|
||||
L"-encodedcommand",
|
||||
L"frombase64string(",
|
||||
L"iex(",
|
||||
L"downloadstring(",
|
||||
NULL
|
||||
};
|
||||
|
||||
static __forceinline BOOLEAN USOK(PUNICODE_STRING s)
|
||||
{
|
||||
return s && s->Buffer && s->Length;
|
||||
}
|
||||
wchar_t* g_RemoteCmdFromCmdExe[] = {
|
||||
L"powershell",
|
||||
L"pwsh",
|
||||
L"mshta",
|
||||
L"rundll32",
|
||||
L"wscript",
|
||||
L"cscript",
|
||||
NULL
|
||||
};
|
||||
|
||||
BOOLEAN IsRegistryBlock(PUNICODE_STRING key, PUNICODE_STRING valueName, PUNICODE_STRING exe)
|
||||
{
|
||||
if (USOK(exe)) {
|
||||
if (IsWhitelist(exe))
|
||||
return FALSE;
|
||||
}
|
||||
if (USOK(exe) && USOK(key)) {
|
||||
size_t elen = exe->Length / sizeof(WCHAR);
|
||||
size_t klen = key->Length / sizeof(WCHAR);
|
||||
if (((elen >= 12 && _wcsnicmp(exe->Buffer + elen - 12, L"services.exe", 12) == 0) ||
|
||||
(elen >= 11 && _wcsnicmp(exe->Buffer + elen - 11, L"svchost.exe", 11) == 0) ||
|
||||
(elen >= 6 && _wcsnicmp(exe->Buffer + elen - 6, L"sc.exe", 6) == 0))) {
|
||||
if (WildMatchN(key->Buffer, klen, L"\\REGISTRY\\**\\SYSTEM\\CurrentControlSet\\Services\\**"))
|
||||
return FALSE;
|
||||
}
|
||||
if ((elen >= 14 && _wcsnicmp(exe->Buffer + elen - 14, L"powershell.exe", 14) == 0) ||
|
||||
(elen >= 8 && _wcsnicmp(exe->Buffer + elen - 8, L"pwsh.exe", 8) == 0)) {
|
||||
if (WildMatchN(key->Buffer, klen, L"\\REGISTRY\\**\\CurrentVersion\\Internet Settings\\ZoneMap") ||
|
||||
WildMatchN(key->Buffer, klen, L"\\REGISTRY\\**\\CurrentVersion\\Internet Settings\\ZoneMap\\**") ||
|
||||
WildMatchN(key->Buffer, klen, L"\\REGISTRY\\**\\CurrentVersion\\Notifications\\Data") ||
|
||||
WildMatchN(key->Buffer, klen, L"\\REGISTRY\\**\\CurrentVersion\\Notifications\\Data\\**"))
|
||||
return FALSE;
|
||||
}
|
||||
if ((elen >= 11 && _wcsnicmp(exe->Buffer + elen - 11, L"msiexec.exe", 11) == 0) ||
|
||||
(elen >= 20 && _wcsnicmp(exe->Buffer + elen - 20, L"TrustedInstaller.exe", 20) == 0)) {
|
||||
if (WildMatchN(key->Buffer, klen, L"\\REGISTRY\\**\\CurrentVersion\\Installer\\**") ||
|
||||
WildMatchN(key->Buffer, klen, L"\\REGISTRY\\**\\CurrentVersion\\Uninstall\\**") ||
|
||||
WildMatchN(key->Buffer, klen, L"\\REGISTRY\\**\\SYSTEM\\CurrentControlSet\\Services\\**"))
|
||||
return FALSE;
|
||||
}
|
||||
if (elen >= 12 && _wcsnicmp(exe->Buffer + elen - 12, L"schtasks.exe", 12) == 0) {
|
||||
if (WildMatchN(key->Buffer, klen, L"\\REGISTRY\\**\\Windows NT\\CurrentVersion\\Schedule\\TaskCache\\**"))
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
if (USOK(key)) {
|
||||
if (MatchBlockReg(key))
|
||||
return TRUE;
|
||||
}
|
||||
if (USOK(valueName)) {
|
||||
SIZE_T n = valueName->Length / sizeof(WCHAR);
|
||||
for (SIZE_T i = 0; g_BlockReg[i]; ++i) {
|
||||
wchar_t* pat = g_BlockReg[i];
|
||||
if (wcschr(pat, L'\\') || wcschr(pat, L'*') || wcschr(pat, L'?'))
|
||||
continue;
|
||||
size_t m = wcslen(pat);
|
||||
if (n == m && _wcsnicmp(valueName->Buffer, pat, m) == 0)
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
wchar_t* g_RemoteCmdFromRundll32Exe[] = {
|
||||
L".dll,",
|
||||
L"javascript:",
|
||||
L"http",
|
||||
NULL
|
||||
};
|
||||
|
||||
BOOLEAN GetProcessImagePathByPid(HANDLE pid, PUNICODE_STRING ProcessImagePath)
|
||||
{
|
||||
PEPROCESS process = NULL;
|
||||
NTSTATUS status = PsLookupProcessByProcessId(pid, &process);
|
||||
if (!NT_SUCCESS(status))
|
||||
return FALSE;
|
||||
wchar_t* g_RemoteCmdRegsvr32Need[] = {
|
||||
L"/i:",
|
||||
NULL
|
||||
};
|
||||
|
||||
HANDLE h = NULL;
|
||||
status = ObOpenObjectByPointer(process, OBJ_KERNEL_HANDLE, NULL, PROCESS_QUERY_LIMITED_INFORMATION, *PsProcessType, KernelMode, &h);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
ObDereferenceObject(process);
|
||||
return FALSE;
|
||||
}
|
||||
ULONG len = 0;
|
||||
status = ZwQueryInformationProcess(h, ProcessImageFileName, NULL, 0, &len);
|
||||
if (status != STATUS_INFO_LENGTH_MISMATCH || len == 0) {
|
||||
ZwClose(h);
|
||||
ObDereferenceObject(process);
|
||||
return FALSE;
|
||||
}
|
||||
PVOID buf = ExAllocatePool2(POOL_FLAG_NON_PAGED, len, 'iPgN');
|
||||
if (!buf) {
|
||||
ZwClose(h);
|
||||
ObDereferenceObject(process);
|
||||
return FALSE;
|
||||
}
|
||||
status = ZwQueryInformationProcess(h, ProcessImageFileName, buf, len, &len);
|
||||
if (NT_SUCCESS(status)) {
|
||||
PUNICODE_STRING image = (PUNICODE_STRING)buf;
|
||||
if (image->Buffer && image->Length > 0 && ProcessImagePath->MaximumLength >= image->Length + sizeof(WCHAR)) {
|
||||
RtlCopyMemory(ProcessImagePath->Buffer, image->Buffer, image->Length);
|
||||
ProcessImagePath->Length = image->Length;
|
||||
ProcessImagePath->Buffer[image->Length / sizeof(WCHAR)] = 0;
|
||||
ExFreePool2(buf, 'iPgN', NULL, 0);
|
||||
ZwClose(h);
|
||||
ObDereferenceObject(process);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
ExFreePool2(buf, 'iPgN', NULL, 0);
|
||||
ZwClose(h);
|
||||
ObDereferenceObject(process);
|
||||
return FALSE;
|
||||
}
|
||||
wchar_t* g_RemoteCmdFromMshtaExe[] = {
|
||||
L"http://",
|
||||
L"https://",
|
||||
NULL
|
||||
};
|
||||
|
||||
BOOLEAN IsWhitelist(PUNICODE_STRING s)
|
||||
{
|
||||
if (MatchList(s, g_WhitelistExcept))
|
||||
return FALSE;
|
||||
return MatchList(s, g_Whitelist);
|
||||
}
|
||||
wchar_t* g_ScreenCapModules[] = {
|
||||
L"windows.graphics.capture.dll",
|
||||
L"dxgi.dll",
|
||||
L"d3d11.dll",
|
||||
L"dwmapi.dll",
|
||||
L"dcomp.dll",
|
||||
L"mfreadwrite.dll",
|
||||
L"mfplat.dll",
|
||||
L"opengl32.dll",
|
||||
L"gdi32full.dll",
|
||||
L"win32u.dll",
|
||||
NULL
|
||||
};
|
||||
|
||||
BOOLEAN MatchBlockReg(PUNICODE_STRING s)
|
||||
{
|
||||
return MatchList(s, g_BlockReg);
|
||||
}
|
||||
wchar_t* g_ScreenUserSubdirs[] = {
|
||||
L"\\AppData\\",
|
||||
L"\\Temp\\",
|
||||
L"\\Downloads\\",
|
||||
NULL
|
||||
};
|
||||
|
||||
wchar_t* GetMatchedBlockRegRule(PUNICODE_STRING s)
|
||||
{
|
||||
return MatchListGetRule(s, g_BlockReg);
|
||||
}
|
||||
|
||||
BOOLEAN MatchBlockFile(PUNICODE_STRING s)
|
||||
{
|
||||
return MatchList(s, g_BlockFile);
|
||||
}
|
||||
|
||||
BOOLEAN MatchBlockRansom(PUNICODE_STRING s)
|
||||
{
|
||||
return MatchList(s, g_BlockRansom);
|
||||
}
|
||||
|
||||
wchar_t* GetMatchedBlockFileRule(PUNICODE_STRING s)
|
||||
{
|
||||
return MatchListGetRule(s, g_BlockFile);
|
||||
}
|
||||
|
||||
BOOLEAN HasBlockedSuffix(PUNICODE_STRING s)
|
||||
{
|
||||
if (!USOK(s))
|
||||
return FALSE;
|
||||
SIZE_T n = s->Length / sizeof(WCHAR);
|
||||
for (SIZE_T i = 0; g_Blocksuffix[i]; ++i) {
|
||||
wchar_t* ext = g_Blocksuffix[i];
|
||||
SIZE_T m = wcslen(ext);
|
||||
if (n >= m && _wcsnicmp(s->Buffer + (n - m), ext, m) == 0)
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
wchar_t* g_ScreenOtherProcNeedles[] = {
|
||||
L"\\ProgramData\\",
|
||||
NULL
|
||||
};
|
||||
@@ -1,15 +1,25 @@
|
||||
#pragma once
|
||||
#include <ntifs.h>
|
||||
|
||||
wchar_t* GetMatchedBlockRegRule(PUNICODE_STRING s);
|
||||
BOOLEAN MatchBlockReg(PUNICODE_STRING s);
|
||||
BOOLEAN IsWhitelist(PUNICODE_STRING s);
|
||||
BOOLEAN GetProcessImagePathByPid(HANDLE pid, PUNICODE_STRING ProcessImagePath);
|
||||
BOOLEAN IsRegistryBlock(PUNICODE_STRING key, PUNICODE_STRING valueName, PUNICODE_STRING exe);
|
||||
|
||||
BOOLEAN MatchBlockFile(PUNICODE_STRING s);
|
||||
BOOLEAN MatchBlockRansom(PUNICODE_STRING s);
|
||||
BOOLEAN HasBlockedSuffix(PUNICODE_STRING s);
|
||||
wchar_t* GetMatchedBlockFileRule(PUNICODE_STRING s);
|
||||
extern wchar_t* g_Whitelist[];
|
||||
extern wchar_t* g_WhitelistExcept[];
|
||||
|
||||
extern wchar_t* g_AttachDisk[];
|
||||
extern wchar_t* g_BlockFile[];
|
||||
extern wchar_t* g_BlockRansom[];
|
||||
extern wchar_t* g_Blocksuffix[];
|
||||
|
||||
extern wchar_t* g_BlockReg[];
|
||||
|
||||
extern wchar_t* g_RemoteSuspectBins[];
|
||||
|
||||
extern wchar_t* g_RemoteCmdIndicatorsHttp[];
|
||||
extern wchar_t* g_RemoteCmdIndicatorsGeneric[];
|
||||
extern wchar_t* g_RemoteCmdFromCmdExe[];
|
||||
extern wchar_t* g_RemoteCmdFromRundll32Exe[];
|
||||
extern wchar_t* g_RemoteCmdRegsvr32Need[];
|
||||
extern wchar_t* g_RemoteCmdFromMshtaExe[];
|
||||
|
||||
extern wchar_t* g_ScreenCapModules[];
|
||||
extern wchar_t* g_ScreenUserSubdirs[];
|
||||
extern wchar_t* g_ScreenOtherProcNeedles[];
|
||||
@@ -0,0 +1,80 @@
|
||||
#include <ntifs.h>
|
||||
#include "DriverEntry.h"
|
||||
#include "ProtectMatch.h"
|
||||
|
||||
static BOOLEAN g_ScreenImgCb = FALSE;
|
||||
|
||||
static VOID LogAnsi3(PCSTR tag, ULONG upid, PUNICODE_STRING s1, PUNICODE_STRING s2)
|
||||
{
|
||||
ANSI_STRING a1 = { 0 }, a2 = { 0 };
|
||||
CHAR buf[1024] = { 0 };
|
||||
RtlUnicodeStringToAnsiString(&a1, s1, TRUE);
|
||||
if (s2)
|
||||
RtlUnicodeStringToAnsiString(&a2, s2, TRUE);
|
||||
RtlStringCchPrintfA(buf, RTL_NUMBER_OF(buf), "%s | %u | %s | %s", tag, upid, a1.Buffer ? a1.Buffer : "", a2.Buffer ? a2.Buffer : "");
|
||||
SendPipeLog(buf, strlen(buf));
|
||||
RtlFreeAnsiString(&a1);
|
||||
RtlFreeAnsiString(&a2);
|
||||
}
|
||||
|
||||
static VOID ImageLoadNotify(PUNICODE_STRING FullImageName, HANDLE ProcessId, PIMAGE_INFO ImageInfo)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(ImageInfo);
|
||||
if (g_Unloading)
|
||||
return;
|
||||
if (KeGetCurrentIrql() != PASSIVE_LEVEL)
|
||||
return;
|
||||
if (!ExAcquireRundownProtection(&g_Rundown))
|
||||
return;
|
||||
if (!FullImageName || !FullImageName->Buffer || FullImageName->Length == 0) {
|
||||
ExReleaseRundownProtection(&g_Rundown);
|
||||
return;
|
||||
}
|
||||
|
||||
UNICODE_STRING proc = { 0 };
|
||||
WCHAR pbuf[512] = { 0 };
|
||||
proc.Buffer = pbuf;
|
||||
proc.MaximumLength = sizeof(pbuf);
|
||||
|
||||
if (!GetProcessImagePathByPid(ProcessId, &proc)) {
|
||||
PEPROCESS eproc = NULL;
|
||||
if (NT_SUCCESS(PsLookupProcessByProcessId(ProcessId, &eproc))) {
|
||||
PCSTR n = PsGetProcessImageFileName(eproc);
|
||||
SIZE_T l = n ? strlen(n) : 0;
|
||||
for (SIZE_T i = 0; i < l && i < RTL_NUMBER_OF(pbuf) - 1; i++)
|
||||
pbuf[i] = (WCHAR)n[i];
|
||||
pbuf[l] = 0;
|
||||
proc.Length = (USHORT)(l * sizeof(WCHAR));
|
||||
ObDereferenceObject(eproc);
|
||||
}
|
||||
}
|
||||
if (proc.Length == 0) {
|
||||
ExReleaseRundownProtection(&g_Rundown);
|
||||
return;
|
||||
}
|
||||
if (IsWhitelist(&proc)) {
|
||||
ExReleaseRundownProtection(&g_Rundown);
|
||||
return;
|
||||
}
|
||||
|
||||
BOOLEAN suspicious = MatchSuspiciousProcPath(&proc);
|
||||
if (suspicious && MatchScreenCapModule(FullImageName))
|
||||
LogAnsi3("SCREEN_BLOCK", (ULONG)(ULONG_PTR)ProcessId, &proc, FullImageName);
|
||||
|
||||
ExReleaseRundownProtection(&g_Rundown);
|
||||
}
|
||||
|
||||
NTSTATUS InitScreenProtect(VOID)
|
||||
{
|
||||
NTSTATUS s = PsSetLoadImageNotifyRoutine(ImageLoadNotify);
|
||||
if (NT_SUCCESS(s)) g_ScreenImgCb = TRUE;
|
||||
return s;
|
||||
}
|
||||
|
||||
VOID UninitScreenProtect(VOID)
|
||||
{
|
||||
if (g_ScreenImgCb) {
|
||||
PsRemoveLoadImageNotifyRoutine(ImageLoadNotify);
|
||||
g_ScreenImgCb = FALSE;
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user