diff --git a/C/FileDeleteRecordPluginDriver/FileDeleteRecordPluginDriver.cpp b/C/FileDeleteRecordPluginDriver/FileDeleteRecordPluginDriver.cpp
index 0a9849d..cc861db 100644
--- a/C/FileDeleteRecordPluginDriver/FileDeleteRecordPluginDriver.cpp
+++ b/C/FileDeleteRecordPluginDriver/FileDeleteRecordPluginDriver.cpp
@@ -3,9 +3,10 @@
#include "interface.h"
-#include "utils.h"
+#include "..\Utils\Utils.h"
const unsigned long PLUGIN_POOL_TAG = 'LEDS';
+const wchar_t* backup_directory = L"\\??\\C:\\deleted";
#pragma warning(disable: 6011)
PluginApis g_Apis;
@@ -68,29 +69,6 @@ void PrintStackTrace(CallerInfo& callerinfo) {
}
}
-OBJECT_NAME_INFORMATION* getFilePathFromHandle(HANDLE hFile) {
- ULONG dwSize = 0;
- OBJECT_NAME_INFORMATION* pObjectName = nullptr;
- NTSTATUS status = ZwQueryObject(hFile, (OBJECT_INFORMATION_CLASS)1 /*ObjectNameInformation*/, pObjectName, 0, &dwSize);
- if (dwSize)
- {
- pObjectName = (OBJECT_NAME_INFORMATION*)ExAllocatePoolWithTag(NonPagedPoolNx, dwSize, PLUGIN_POOL_TAG);
- if (pObjectName) {
- status = ZwQueryObject(hFile, (OBJECT_INFORMATION_CLASS)1 /*ObjectNameInformation*/, pObjectName, dwSize, &dwSize);
- }
- }
-
- if (status == STATUS_SUCCESS && pObjectName) {
- return pObjectName;
- }
-
- if (pObjectName) {
- ExFreePoolWithTag(pObjectName, PLUGIN_POOL_TAG);
- pObjectName = nullptr;
- }
- return nullptr;
-}
-
extern "C" __declspec(dllexport) void StpCallbackEntry(ULONG64 pService, ULONG32 probeId, MachineState & ctx, CallerInfo & callerinfo)
{
//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);
@@ -109,9 +87,9 @@ extern "C" __declspec(dllexport) void StpCallbackEntry(ULONG64 pService, ULONG32
if (pFilePath) {
LOG_INFO("File %wZ deleted\r\n", pFilePath->Name);
- //backupFile((wchar_t*)backup_directory, pFilePath->Name, hFile);
- //ExFreePoolWithTag(pFilePath, PLUGIN_POOL_TAG);
- //pFilePath = nullptr;
+ backupFile((wchar_t*)backup_directory, pFilePath->Name, hFile);
+ ExFreePoolWithTag(pFilePath, PLUGIN_POOL_TAG);
+ pFilePath = nullptr;
LOG_INFO("File Backup Complete\r\n");
}
else {
diff --git a/C/FileDeleteRecordPluginDriver/FileDeleteRecordPluginDriver.vcxproj b/C/FileDeleteRecordPluginDriver/FileDeleteRecordPluginDriver.vcxproj
index 4879809..23ea11b 100644
--- a/C/FileDeleteRecordPluginDriver/FileDeleteRecordPluginDriver.vcxproj
+++ b/C/FileDeleteRecordPluginDriver/FileDeleteRecordPluginDriver.vcxproj
@@ -92,10 +92,13 @@
false
false
stdcpp20
- _WIN64;_AMD64_;AMD64;ENABLE_LOG;%(PreprocessorDefinitions)
+ KERNEL_MODE;_WIN64;_AMD64_;AMD64;ENABLE_LOG;%(PreprocessorDefinitions)
+ false
DriverEntry
+ %(AdditionalDependencies);$(KernelBufferOverflowLib);$(DDK_LIB_PATH)ntoskrnl.lib;$(DDK_LIB_PATH)hal.lib;$(DDK_LIB_PATH)wmilib.lib;Utils.lib
+ $(outdir)
@@ -107,9 +110,13 @@
false
Default
stdcpp20
+ KERNEL_MODE;_WIN64;_AMD64_;AMD64;%(PreprocessorDefinitions)
+ false
DriverEntry
+ %(AdditionalDependencies);$(KernelBufferOverflowLib);$(DDK_LIB_PATH)ntoskrnl.lib;$(DDK_LIB_PATH)hal.lib;$(DDK_LIB_PATH)wmilib.lib;Utils.lib
+ $(outdir)
diff --git a/C/STrace.sln b/C/STrace.sln
index 4372585..e58276f 100644
--- a/C/STrace.sln
+++ b/C/STrace.sln
@@ -7,6 +7,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "STrace", "STrace\STrace.vcx
ProjectSection(ProjectDependencies) = postProject
{4349310C-30F9-48A9-9AE7-13D181F958B5} = {4349310C-30F9-48A9-9AE7-13D181F958B5}
{C09F1082-CDCA-4320-AB91-CC3EAB12560C} = {C09F1082-CDCA-4320-AB91-CC3EAB12560C}
+ {D237889B-F553-478C-857A-A6BF4B883AE9} = {D237889B-F553-478C-857A-A6BF4B883AE9}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "STraceCLI", "STraceCLI\STraceCLI.vcxproj", "{4349310C-30F9-48A9-9AE7-13D181F958B5}"
@@ -21,6 +22,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AddNewEtwEventPlugin", "Add
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FileDeleteRecordPluginDriver", "FileDeleteRecordPluginDriver\FileDeleteRecordPluginDriver.vcxproj", "{CD47158C-73E3-4197-AE90-92DC38D8BC0E}"
EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Utils", "Utils\Utils.vcxproj", "{D237889B-F553-478C-857A-A6BF4B883AE9}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|ARM64 = Debug|ARM64
@@ -127,6 +130,18 @@ Global
{CD47158C-73E3-4197-AE90-92DC38D8BC0E}.Release|x86.ActiveCfg = Release|x64
{CD47158C-73E3-4197-AE90-92DC38D8BC0E}.Release|x86.Build.0 = Release|x64
{CD47158C-73E3-4197-AE90-92DC38D8BC0E}.Release|x86.Deploy.0 = Release|x64
+ {D237889B-F553-478C-857A-A6BF4B883AE9}.Debug|ARM64.ActiveCfg = Debug|x64
+ {D237889B-F553-478C-857A-A6BF4B883AE9}.Debug|ARM64.Build.0 = Debug|x64
+ {D237889B-F553-478C-857A-A6BF4B883AE9}.Debug|x64.ActiveCfg = Debug|x64
+ {D237889B-F553-478C-857A-A6BF4B883AE9}.Debug|x64.Build.0 = Debug|x64
+ {D237889B-F553-478C-857A-A6BF4B883AE9}.Debug|x86.ActiveCfg = Debug|Win32
+ {D237889B-F553-478C-857A-A6BF4B883AE9}.Debug|x86.Build.0 = Debug|Win32
+ {D237889B-F553-478C-857A-A6BF4B883AE9}.Release|ARM64.ActiveCfg = Release|x64
+ {D237889B-F553-478C-857A-A6BF4B883AE9}.Release|ARM64.Build.0 = Release|x64
+ {D237889B-F553-478C-857A-A6BF4B883AE9}.Release|x64.ActiveCfg = Release|x64
+ {D237889B-F553-478C-857A-A6BF4B883AE9}.Release|x64.Build.0 = Release|x64
+ {D237889B-F553-478C-857A-A6BF4B883AE9}.Release|x86.ActiveCfg = Release|Win32
+ {D237889B-F553-478C-857A-A6BF4B883AE9}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/C/STraceCLI/STraceCLI.cpp b/C/STraceCLI/STraceCLI.cpp
index e330253..5764fa5 100644
--- a/C/STraceCLI/STraceCLI.cpp
+++ b/C/STraceCLI/STraceCLI.cpp
@@ -10,6 +10,7 @@
#include
HANDLE g_Driver;
+SC_HANDLE g_Scm;
std::filesystem::path AskForFile() {
wchar_t szFileName[MAX_PATH] = { 0 };
@@ -99,11 +100,21 @@ int main()
printf("[+] Opening driver\n");
g_Driver = CreateFileW(L"\\\\.\\STrace", GENERIC_ALL, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM, 0);
if (g_Driver == INVALID_HANDLE_VALUE) {
- printf("[!] Handle open to driver failed\n");
+ printf("[!] Handle open to driver failed: %d\n", GetLastError());
return 1;
}
printf("[+] Driver Opened Successfully\n");
+ printf("[+] Opening Service Manager\n");
+ g_Scm = OpenSCManagerA(NULL, NULL, SC_MANAGER_ALL_ACCESS);
+ if (NULL == g_Scm)
+ {
+ printf("[!] OpenServiceManager failed with: %d\n", GetLastError());
+ return 1;
+ }
+ printf("[+] Service Manager Opened Successfully\n");
+
+
while (true) {
std::cout << "Input command: load, unload, exit" << std::endl;
std::string input;
diff --git a/C/Utils/Utils.cpp b/C/Utils/Utils.cpp
new file mode 100644
index 0000000..6d8e997
--- /dev/null
+++ b/C/Utils/Utils.cpp
@@ -0,0 +1,280 @@
+#include "..\FileDeleteRecordPlugin\Interface.h"
+#include "..\FileDeleteRecordPlugin\KernelApis.h"
+#include "..\FileDeleteRecordPlugin\config.h"
+#include "..\FileDeleteRecordPlugin\string.h"
+
+#include
+#include
+#include
+#include
+
+#include "Utils.h"
+
+template
+int string_printf(String& str, T printer, Args&&... args) {
+ char tmp[512] = { 0 };
+
+ int size = printer(tmp, sizeof(tmp), std::forward(args)...);
+ if (size < 0) {
+ return -1;
+ }
+
+ str += (char*)tmp;
+ return size;
+}
+
+using hash_t = std::uint64_t;
+
+consteval uint64_t fnv1a_imp(uint64_t h, const char* s)
+{
+ return (*s == 0) ? h :
+ fnv1a_imp((h ^ static_cast(*s)) * 1099511628211ull, s + 1);
+}
+
+consteval uint64_t fnv1a(const char* s)
+{
+ return fnv1a_imp(14695981039346656037ull, s);
+}
+
+// Abuse template instantion rules to generate a unique name for a given type. Each template is a unique function in C++.
+// Then, convert that string to a numeric hash. Stable for the lifetime of the application, may change between compilations.
+template
+consteval uint64_t get_type_id() {
+ return fnv1a(__FUNCSIG__);
+}
+
+// given a typedef, match the arg list and convert each arg to a typeid. Store results in an array.
+template
+struct arg_types {};
+
+template
+struct arg_types {
+ static constexpr std::array value = { get_type_id()... };
+};
+
+// msvc doesn't implement a constructor for std::span from iterators. This does that...
+template
+constexpr auto make_span(It begin, It end) {
+ return std::span>>(&(*begin), std::distance(begin, end));
+}
+
+template
+class FinalAction {
+public:
+ FinalAction(Func f) :FinalActionFunc(std::move(f)) {}
+ ~FinalAction()
+ {
+ FinalActionFunc();
+ }
+private:
+ Func FinalActionFunc;
+
+ /*Uses RAII to call a final function on destruction
+ C++ 11 version of java's finally (kindof)*/
+};
+
+template
+FinalAction finally(F f) {
+ return FinalAction(f);
+}
+
+template
+T FnCast(uint64_t fnToCast, T pFnCastTo) {
+ PH_UNUSED(pFnCastTo);
+ return (T)fnToCast;
+}
+
+template
+T FnCast(void* fnToCast, T pFnCastTo) {
+ PH_UNUSED(pFnCastTo);
+ return (T)fnToCast;
+}
+
+// analog of dtrace_copyin. Given a pointer to a usermode structure, safely read that structure in.
+// Dtrace returns a pointer to that result. We can be slightly nicer and give a copy of the value exactly.
+template
+std::remove_pointer_t readUserArg(T2 pUserAddress, PluginApis pApis) {
+ std::remove_pointer_t tmp = { 0 };
+ pApis.pTraceAccessMemory(&tmp, (uint64_t)pUserAddress, sizeof(tmp), 1, TRUE);
+ return tmp;
+}
+
+bool createFile(PUNICODE_STRING filePath, PHANDLE hFileOut) {
+ *hFileOut = INVALID_HANDLE_VALUE;
+
+ OBJECT_ATTRIBUTES attrs = { 0 };
+ InitializeObjectAttributes(&attrs, filePath, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL);
+
+ IO_STATUS_BLOCK IoStatus;
+ NTSTATUS Status = ZwCreateFile(hFileOut,
+ FILE_WRITE_DATA | SYNCHRONIZE,
+ &attrs,
+ &IoStatus,
+ NULL,
+ FILE_ATTRIBUTE_SYSTEM,
+ FILE_SHARE_READ,
+ FILE_OPEN_IF,
+ FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE,
+ NULL,
+ 0);
+ return Status == STATUS_SUCCESS;
+}
+
+bool openFile(PUNICODE_STRING filePath, PHANDLE hFileOut) {
+ *hFileOut = INVALID_HANDLE_VALUE;
+
+ OBJECT_ATTRIBUTES attrs = { 0 };
+ InitializeObjectAttributes(&attrs, filePath, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL);
+
+ IO_STATUS_BLOCK IoStatus;
+ NTSTATUS Status = ZwOpenFile(hFileOut,
+ FILE_READ_DATA | SYNCHRONIZE,
+ &attrs,
+ &IoStatus,
+ FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+ FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE
+ );
+ return Status == STATUS_SUCCESS;
+}
+
+// backupFileName must begin with a slash, or be a filepath with slashes
+bool __stdcall backupFile(PWSTR backupDir, UNICODE_STRING backupFileName, HANDLE hFileSource) {
+ if (!backupFileName.Buffer || backupFileName.Length <= sizeof(wchar_t))
+ return false;
+
+ // scan backwards until first slash
+ PWCHAR fileName = backupFileName.Buffer + (backupFileName.Length - sizeof(wchar_t));
+ size_t fileNameLen = 0;
+ while (*fileName != L'\\') {
+ fileName--;
+ fileNameLen++;
+ }
+
+ UNICODE_STRING backupPath = { 0 };
+ backupPath.Length = (USHORT)(wcslen(backupDir) * sizeof(wchar_t));
+ backupPath.MaximumLength = (USHORT)(backupPath.Length + (fileNameLen * sizeof(wchar_t)));
+ backupPath.Buffer = (PWSTR)ExAllocatePoolWithTag(NonPagedPoolNx, backupPath.MaximumLength, POOL_TAG);
+ memcpy(backupPath.Buffer, backupDir, backupPath.Length);
+
+ NTSTATUS status = RtlAppendUnicodeToString(&backupPath, fileName);
+ if (status != STATUS_SUCCESS)
+ return false;
+
+ HANDLE hFileCopy = INVALID_HANDLE_VALUE;
+ auto close_handles = finally([&] {
+ if (hFileCopy != INVALID_HANDLE_VALUE) {
+ ZwClose(hFileCopy);
+ }
+ });
+
+ if (!createFile(&backupPath, &hFileCopy))
+ return false;
+
+ LARGE_INTEGER pos = { 0 };
+ IO_STATUS_BLOCK iosb = { 0 };
+
+ LARGE_INTEGER pos_write = { 0 };
+ IO_STATUS_BLOCK iosb_write = { 0 };
+
+ while (true) {
+ char pBuf[512] = { 0 };
+ status = ZwReadFile(
+ hFileSource,
+ NULL, NULL, NULL,
+ &iosb,
+ pBuf, (ULONG)sizeof(pBuf),
+ &pos,
+ NULL
+ );
+
+ if (status == STATUS_END_OF_FILE) {
+ if (iosb.Information == 0) {
+ break;
+ }
+ }
+
+ if (status != STATUS_SUCCESS) {
+ break;
+ }
+
+ status = ZwWriteFile(hFileCopy,
+ NULL, NULL, NULL,
+ &iosb_write,
+ pBuf, (ULONG)sizeof(pBuf),
+ &pos_write,
+ NULL
+ );
+
+ if (iosb_write.Status != STATUS_SUCCESS) {
+ break;
+ }
+
+ if (status != STATUS_SUCCESS) {
+ break;
+ }
+
+ pos.QuadPart += iosb.Information;
+ pos_write.QuadPart += iosb_write.Information;
+ }
+ return true;
+}
+
+VOID NTAPI FreeUnicodeString(PUNICODE_STRING UnicodeString, ULONG Tag)
+{
+ if (UnicodeString->Buffer)
+ {
+ ExFreePoolWithTag(UnicodeString->Buffer, Tag);
+ }
+}
+
+NTSTATUS DuplicateUnicodeString(PCUNICODE_STRING SourceString, PUNICODE_STRING DestinationString, ULONG Tag)
+{
+ if (SourceString == NULL || DestinationString == NULL ||
+ SourceString->Length > SourceString->MaximumLength ||
+ (SourceString->Length == 0 && SourceString->MaximumLength > 0 && SourceString->Buffer == NULL))
+ {
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ if (SourceString->Length == 0)
+ {
+ DestinationString->Length = 0;
+ DestinationString->MaximumLength = 0;
+ DestinationString->Buffer = NULL;
+ }
+ else {
+ UINT DestMaxLength = SourceString->Length;
+
+ DestinationString->Buffer = (PWSTR)ExAllocatePoolWithTag(NonPagedPoolNx, DestMaxLength, Tag);
+ if (DestinationString->Buffer == NULL)
+ return STATUS_NO_MEMORY;
+
+ memcpy(DestinationString->Buffer, SourceString->Buffer, SourceString->Length);
+ DestinationString->Length = SourceString->Length;
+ DestinationString->MaximumLength = DestMaxLength;
+ }
+ return STATUS_SUCCESS;
+}
+
+OBJECT_NAME_INFORMATION* __stdcall getFilePathFromHandle(HANDLE hFile) {
+ ULONG dwSize = 0;
+ OBJECT_NAME_INFORMATION* pObjectName = nullptr;
+ NTSTATUS status = ZwQueryObject(hFile, ObjectNameInformation, pObjectName, 0, &dwSize);
+ if (dwSize)
+ {
+ pObjectName = (OBJECT_NAME_INFORMATION*)ExAllocatePoolWithTag(NonPagedPoolNx, dwSize, POOL_TAG);
+ if (pObjectName) {
+ status = ZwQueryObject(hFile, ObjectNameInformation, pObjectName, dwSize, &dwSize);
+ }
+ }
+
+ if (status == STATUS_SUCCESS && pObjectName) {
+ return pObjectName;
+ }
+
+ if (pObjectName) {
+ ExFreePoolWithTag(pObjectName, POOL_TAG);
+ pObjectName = nullptr;
+ }
+ return nullptr;
+}
\ No newline at end of file
diff --git a/C/Utils/Utils.h b/C/Utils/Utils.h
new file mode 100644
index 0000000..8758ff3
--- /dev/null
+++ b/C/Utils/Utils.h
@@ -0,0 +1,5 @@
+#pragma once
+
+
+extern "C" bool __stdcall backupFile(PWSTR backupDir, UNICODE_STRING backupFileName, HANDLE hFileSource);
+extern "C" OBJECT_NAME_INFORMATION * __stdcall getFilePathFromHandle(HANDLE hFile);
\ No newline at end of file
diff --git a/C/Utils/Utils.vcxproj b/C/Utils/Utils.vcxproj
new file mode 100644
index 0000000..2f2256d
--- /dev/null
+++ b/C/Utils/Utils.vcxproj
@@ -0,0 +1,168 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ x64
+
+
+
+ 16.0
+ Win32Proj
+ {d237889b-f553-478c-857a-a6bf4b883ae9}
+ Utils
+ 10.0
+
+
+
+ StaticLibrary
+ true
+ v143
+ Unicode
+
+
+ StaticLibrary
+ false
+ v143
+ true
+ Unicode
+
+
+ StaticLibrary
+ true
+ v143
+ Unicode
+
+
+ StaticLibrary
+ false
+ v143
+ true
+ Unicode
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Level3
+ true
+ WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)
+ true
+ Use
+ pch.h
+
+
+
+
+ true
+
+
+
+
+ Level3
+ true
+ true
+ true
+ WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)
+ true
+ Use
+ pch.h
+
+
+
+
+ true
+ true
+ true
+
+
+
+
+ Level3
+ false
+ _DEBUG;_LIB;%(PreprocessorDefinitions)
+ true
+ NotUsing
+ pch.h
+ MultiThreadedDebug
+ false
+ stdcpp20
+ ProgramDatabase
+ /kernel %(AdditionalOptions)
+ Default
+ false
+
+
+
+
+ true
+
+
+ true
+
+
+
+
+ Level3
+ true
+ true
+ false
+ NDEBUG;_LIB;%(PreprocessorDefinitions)
+ true
+ NotUsing
+ pch.h
+ MultiThreaded
+ false
+ stdcpp20
+ /kernel %(AdditionalOptions)
+ false
+
+
+
+
+ true
+ true
+ true
+
+
+ true
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/C/Utils/Utils.vcxproj.filters b/C/Utils/Utils.vcxproj.filters
new file mode 100644
index 0000000..e53c4ac
--- /dev/null
+++ b/C/Utils/Utils.vcxproj.filters
@@ -0,0 +1,27 @@
+
+
+
+
+ {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
+ cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx
+
+
+ {93995380-89BD-4b04-88EB-625FBE52EBFB}
+ h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd
+
+
+ {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
+ rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
+
+
+
+
+ Source Files
+
+
+
+
+ Header Files
+
+
+
\ No newline at end of file