Add files via upload

This commit is contained in:
PYDT authored and GitHub committed 2025-08-22 23:13:46 +08:00
1 parent 424914b842
commit 8295e6bb5b
12 files changed
+708 -287

No files matched your search

+27 -20
View File
@@ -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(&regAlt, regAltBuf);
status = CmRegisterCallbackEx(RegistryProtectCallback, &regAlt, 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;
}
}
+5
View File
@@ -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 -1
View File
@@ -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)
{
+7 -37
View File
@@ -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 -1
View File
@@ -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;
+372
View File
@@ -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;
}
+22
View File
@@ -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 -1
View File
@@ -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)
{
+96
View File
@@ -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
View File
@@ -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
};
+20 -10
View File
@@ -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[];
+80
View File
@@ -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;
}
}