|
| 1 | +#pragma warning(disable: 4996) //exallocatepoolwithtag |
| 2 | +#include <ntifs.h> |
| 3 | + |
| 4 | +#include "interface.h" |
| 5 | + |
| 6 | +#include "utils.h" |
| 7 | + |
| 8 | +const unsigned long PLUGIN_POOL_TAG = 'LEDS'; |
| 9 | + |
| 10 | +#pragma warning(disable: 6011) |
| 11 | +PluginApis g_Apis; |
| 12 | + |
| 13 | +#if defined(ENABLE_LOG) |
| 14 | +#if defined(__GNUC__) || defined(__clang__) |
| 15 | + |
| 16 | +// On GCC and Clang __VA_ARGS__ must be used differently. |
| 17 | +#define DBGPRINT(format, ...) DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[STRACE] " format "\n", ##__VA_ARGS__) |
| 18 | +#define LOG_DEBUG(fmt,...) g_Apis.pLogPrint(LogLevelDebug, __FUNCTION__, fmt, ##__VA_ARGS__) |
| 19 | +#define LOG_INFO(fmt,...) g_Apis.pLogPrint(LogLevelInfo, __FUNCTION__, fmt, ##__VA_ARGS__) |
| 20 | +#define LOG_WARN(fmt,...) g_Apis.pLogPrint(LogLevelWarn, __FUNCTION__, fmt, ##__VA_ARGS__) |
| 21 | +#define LOG_ERROR(fmt,...) g_Apis.pLogPrint(LogLevelError, __FUNCTION__, fmt, ##__VA_ARGS__) |
| 22 | +#else |
| 23 | + |
| 24 | +#define DBGPRINT(format, ...) DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[STRACE] " format "\n", __VA_ARGS__) |
| 25 | +#define LOG_DEBUG(fmt,...) g_Apis.pLogPrint(LogLevelDebug, __FUNCTION__, fmt, __VA_ARGS__) |
| 26 | +#define LOG_INFO(fmt,...) g_Apis.pLogPrint(LogLevelInfo, __FUNCTION__, fmt, __VA_ARGS__) |
| 27 | +#define LOG_WARN(fmt,...) g_Apis.pLogPrint(LogLevelWarn, __FUNCTION__, fmt, __VA_ARGS__) |
| 28 | +#define LOG_ERROR(fmt,...) g_Apis.pLogPrint(LogLevelError, __FUNCTION__, fmt, __VA_ARGS__) |
| 29 | +#endif // __GNUC__ || __clang__ |
| 30 | + |
| 31 | +#else |
| 32 | + |
| 33 | +#define DBGPRINT(format, ...) ((void)format) |
| 34 | + |
| 35 | +#endif // _DEBUG |
| 36 | + |
| 37 | +enum PROBE_IDS : ULONG64 { |
| 38 | + IdSetInformationFile = 0, |
| 39 | +}; |
| 40 | + |
| 41 | +extern "C" __declspec(dllexport) void StpInitialize(PluginApis & pApis) { |
| 42 | + g_Apis = pApis; |
| 43 | + LOG_INFO("Plugin Initializing...\r\n"); |
| 44 | + |
| 45 | + g_Apis.pSetCallback("SetInformationFile", PROBE_IDS::IdSetInformationFile); |
| 46 | + LOG_INFO("Plugin Initialized\r\n"); |
| 47 | +} |
| 48 | +ASSERT_INTERFACE_IMPLEMENTED(StpInitialize, tStpInitialize, "StpInitialize does not match the interface type"); |
| 49 | + |
| 50 | +extern "C" __declspec(dllexport) void StpDeInitialize() { |
| 51 | + LOG_INFO("Plugin DeInitializing...\r\n"); |
| 52 | + |
| 53 | + g_Apis.pUnsetCallback("SetInformationFile"); |
| 54 | + |
| 55 | + LOG_INFO("Plugin DeInitialized\r\n"); |
| 56 | +} |
| 57 | +ASSERT_INTERFACE_IMPLEMENTED(StpDeInitialize, tStpDeInitialize, "StpDeInitialize does not match the interface type"); |
| 58 | + |
| 59 | +extern "C" __declspec(dllexport) bool StpIsTarget(CallerInfo & callerinfo) { |
| 60 | + UNREFERENCED_PARAMETER(callerinfo); |
| 61 | + return true; |
| 62 | +} |
| 63 | +ASSERT_INTERFACE_IMPLEMENTED(StpIsTarget, tStpIsTarget, "StpIsTarget does not match the interface type"); |
| 64 | + |
| 65 | +void PrintStackTrace(CallerInfo& callerinfo) { |
| 66 | + for (int i = 0; i < callerinfo.frameDepth; i++) { |
| 67 | + if ((callerinfo.frames)[i].frameaddress) { |
| 68 | + const auto modulePathLen = (callerinfo.frames)[i].modulePath ? strlen((callerinfo.frames)[i].modulePath) : 0; |
| 69 | + |
| 70 | + // add brackets around module dynamically |
| 71 | + if (modulePathLen) { |
| 72 | + char moduleName[sizeof(CallerInfo::StackFrame::modulePath) + 2] = { 0 }; |
| 73 | + moduleName[0] = '['; |
| 74 | + strcpy(&moduleName[1], (callerinfo.frames)[i].modulePath); |
| 75 | + moduleName[modulePathLen + 1] = ']'; |
| 76 | + |
| 77 | + LOG_INFO(" %-18s +0x%08llx\r\n", moduleName, (callerinfo.frames)[i].frameaddress - (callerinfo.frames)[i].modulebase); |
| 78 | + } |
| 79 | + else { |
| 80 | + LOG_INFO(" %-18s 0x%016llx\r\n", "[UNKNOWN MODULE]", (callerinfo.frames)[i].frameaddress); |
| 81 | + } |
| 82 | + } |
| 83 | + else { |
| 84 | + LOG_INFO(" Frame Missing\r\n"); |
| 85 | + } |
| 86 | + } |
| 87 | +} |
| 88 | + |
| 89 | + |
| 90 | + |
| 91 | +OBJECT_NAME_INFORMATION* getFilePathFromHandle(HANDLE hFile) { |
| 92 | + ULONG dwSize = 0; |
| 93 | + OBJECT_NAME_INFORMATION* pObjectName = nullptr; |
| 94 | + NTSTATUS status = ZwQueryObject(hFile, (OBJECT_INFORMATION_CLASS)1 /*ObjectNameInformation*/, pObjectName, 0, &dwSize); |
| 95 | + if (dwSize) |
| 96 | + { |
| 97 | + pObjectName = (OBJECT_NAME_INFORMATION*)ExAllocatePoolWithTag(NonPagedPoolNx, dwSize, PLUGIN_POOL_TAG); |
| 98 | + if (pObjectName) { |
| 99 | + status = ZwQueryObject(hFile, (OBJECT_INFORMATION_CLASS)1 /*ObjectNameInformation*/, pObjectName, dwSize, &dwSize); |
| 100 | + } |
| 101 | + } |
| 102 | + |
| 103 | + if (status == STATUS_SUCCESS && pObjectName) { |
| 104 | + return pObjectName; |
| 105 | + } |
| 106 | + |
| 107 | + if (pObjectName) { |
| 108 | + ExFreePoolWithTag(pObjectName, PLUGIN_POOL_TAG); |
| 109 | + pObjectName = nullptr; |
| 110 | + } |
| 111 | + return nullptr; |
| 112 | +} |
| 113 | + |
| 114 | +extern "C" __declspec(dllexport) void StpCallbackEntry(ULONG64 pService, ULONG32 probeId, MachineState & ctx, CallerInfo & callerinfo) |
| 115 | +{ |
| 116 | + //LOG_INFO("[ENTRY] %s[0x%x](%d) Id: %d Parameters: [%d]\r\n", callerinfo.processName, callerinfo.processId, callerinfo.isWow64 ? 32 : 64, pService, probeId, ctx.paramCount); |
| 117 | + UNREFERENCED_PARAMETER(pService); |
| 118 | + UNREFERENCED_PARAMETER(probeId); |
| 119 | + UNREFERENCED_PARAMETER(ctx); |
| 120 | + UNREFERENCED_PARAMETER(callerinfo); |
| 121 | + switch (probeId) { |
| 122 | + case PROBE_IDS::IdSetInformationFile: { |
| 123 | + auto hFile = (HANDLE)ctx.read_argument(0); |
| 124 | + auto InformationClass = ctx.read_argument(4); |
| 125 | + if (InformationClass == 13) { // FileDispositionInformation |
| 126 | + auto pInformation = (char*)ctx.read_argument(2); // 1 == DeleteFile |
| 127 | + if (*pInformation == 1) { |
| 128 | + auto pFilePath = getFilePathFromHandle(hFile); |
| 129 | + |
| 130 | + if (pFilePath) { |
| 131 | + LOG_INFO("File %wZ deleted\r\n", pFilePath->Name); |
| 132 | + //backupFile((wchar_t*)backup_directory, pFilePath->Name, hFile); |
| 133 | + //ExFreePoolWithTag(pFilePath, PLUGIN_POOL_TAG); |
| 134 | + //pFilePath = nullptr; |
| 135 | + LOG_INFO("File Backup Complete\r\n"); |
| 136 | + } |
| 137 | + else { |
| 138 | + LOG_INFO("File [unknown] deleted\r\n"); |
| 139 | + } |
| 140 | + |
| 141 | + PrintStackTrace(callerinfo); |
| 142 | + } |
| 143 | + } |
| 144 | + break; |
| 145 | + } |
| 146 | + } |
| 147 | +} |
| 148 | +ASSERT_INTERFACE_IMPLEMENTED(StpCallbackEntry, tStpCallbackEntryPlugin, "StpCallbackEntry does not match the interface type"); |
| 149 | + |
| 150 | +extern "C" __declspec(dllexport) void StpCallbackReturn(ULONG64 pService, ULONG32 probeId, MachineState & ctx, CallerInfo & callerinfo) { |
| 151 | + UNREFERENCED_PARAMETER(pService); |
| 152 | + UNREFERENCED_PARAMETER(probeId); |
| 153 | + UNREFERENCED_PARAMETER(ctx); |
| 154 | + UNREFERENCED_PARAMETER(callerinfo); |
| 155 | + //LOG_INFO("[RETURN] %s[%x](%d) %016llx Id: %d\r\n", callerinfo.processName, callerinfo.processId, callerinfo.isWow64 ? 32 : 64, pService, probeId); |
| 156 | +} |
| 157 | +ASSERT_INTERFACE_IMPLEMENTED(StpCallbackReturn, tStpCallbackReturnPlugin, "StpCallbackEntry does not match the interface type"); |
| 158 | + |
| 159 | + |
| 160 | +NTSTATUS DeviceCreateClose(_In_ PDEVICE_OBJECT DeviceObject, _Inout_ PIRP Irp) |
| 161 | +{ |
| 162 | + UNREFERENCED_PARAMETER(DeviceObject); |
| 163 | + |
| 164 | + Irp->IoStatus.Status = STATUS_SUCCESS; |
| 165 | + Irp->IoStatus.Information = 0; |
| 166 | + IoCompleteRequest(Irp, IO_NO_INCREMENT); |
| 167 | + |
| 168 | + return STATUS_SUCCESS; |
| 169 | +} |
| 170 | + |
| 171 | +VOID DeviceUnload(_In_ PDRIVER_OBJECT DriverObject) |
| 172 | +{ |
| 173 | + UNREFERENCED_PARAMETER(DriverObject); |
| 174 | + DBGPRINT("FileDeleteRecord::DeviceUnload"); |
| 175 | +} |
| 176 | + |
| 177 | + |
| 178 | +/* |
| 179 | +* /GS- must be set to disable stack cookies and have DriverEntry |
| 180 | +* be the entrypoint. GsDriverEntry sets up stack cookie and calls |
| 181 | +* Driver Entry normally. |
| 182 | +*/ |
| 183 | +NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath) |
| 184 | +{ |
| 185 | + UNREFERENCED_PARAMETER(RegistryPath); |
| 186 | + |
| 187 | + DBGPRINT("FileDeleteRecord::DriverEntry()"); |
| 188 | + |
| 189 | + |
| 190 | + DriverObject->MajorFunction[IRP_MJ_CREATE] = DeviceCreateClose; |
| 191 | + DriverObject->MajorFunction[IRP_MJ_CLOSE] = DeviceCreateClose; |
| 192 | + DriverObject->DriverUnload = DeviceUnload; |
| 193 | + |
| 194 | + return STATUS_SUCCESS; |
| 195 | +} |
0 commit comments