From ddeb2faa2184de08acf6bf539c5e15fcdffc43d9 Mon Sep 17 00:00:00 2001 From: ALittlePatate Date: Wed, 6 Nov 2024 17:05:11 +0100 Subject: [PATCH] feat: initial commit of the files --- .gitignore | 4 + EdomResu/EdomResu.vcxproj | 153 +++++++++++ EdomResu/EdomResu.vcxproj.filters | 39 +++ EdomResu/EdomResu.vcxproj.user | 4 + EdomResu/Operations.cpp | 68 +++++ EdomResu/Operations.hpp | 76 ++++++ EdomResu/Registry.cpp | 88 +++++++ EdomResu/Registry.hpp | 9 + EdomResu/main.cpp | 16 ++ Revird.sln | 57 ++++ Revird/Dispatcher.cpp | 65 +++++ Revird/Dispatcher.hpp | 3 + Revird/Entry.cpp | 63 +++++ Revird/Memory.cpp | 121 +++++++++ Revird/Memory.hpp | 12 + Revird/Operation.hpp | 8 + Revird/Output.hpp | 7 + Revird/Process.cpp | 172 ++++++++++++ Revird/Process.hpp | 158 +++++++++++ Revird/Registry.cpp | 425 ++++++++++++++++++++++++++++++ Revird/Registry.hpp | 16 ++ Revird/Revird.vcxproj | 118 +++++++++ Revird/Revird.vcxproj.filters | 64 +++++ Revird/Revird.vcxproj.user | 9 + Revird/Utils.cpp | 10 + Revird/Utils.hpp | 4 + 26 files changed, 1769 insertions(+) create mode 100644 .gitignore create mode 100644 EdomResu/EdomResu.vcxproj create mode 100644 EdomResu/EdomResu.vcxproj.filters create mode 100644 EdomResu/EdomResu.vcxproj.user create mode 100644 EdomResu/Operations.cpp create mode 100644 EdomResu/Operations.hpp create mode 100644 EdomResu/Registry.cpp create mode 100644 EdomResu/Registry.hpp create mode 100644 EdomResu/main.cpp create mode 100644 Revird.sln create mode 100644 Revird/Dispatcher.cpp create mode 100644 Revird/Dispatcher.hpp create mode 100644 Revird/Entry.cpp create mode 100644 Revird/Memory.cpp create mode 100644 Revird/Memory.hpp create mode 100644 Revird/Operation.hpp create mode 100644 Revird/Output.hpp create mode 100644 Revird/Process.cpp create mode 100644 Revird/Process.hpp create mode 100644 Revird/Registry.cpp create mode 100644 Revird/Registry.hpp create mode 100644 Revird/Revird.vcxproj create mode 100644 Revird/Revird.vcxproj.filters create mode 100644 Revird/Revird.vcxproj.user create mode 100644 Revird/Utils.cpp create mode 100644 Revird/Utils.hpp diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e419c59 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +.vs +.git +kdmapper +x64 \ No newline at end of file diff --git a/EdomResu/EdomResu.vcxproj b/EdomResu/EdomResu.vcxproj new file mode 100644 index 0000000..3afb584 --- /dev/null +++ b/EdomResu/EdomResu.vcxproj @@ -0,0 +1,153 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 16.0 + Win32Proj + {2a246068-e114-49a5-bdbd-1e4be88d97a8} + EdomResu + 10.0 + + + + Application + true + v143 + Unicode + + + Application + false + v143 + true + Unicode + + + Application + true + v143 + Unicode + + + Application + false + v143 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + + + false + + + true + + + false + + + + Level3 + true + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + Level3 + true + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + + + + + Level3 + true + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + Level3 + true + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdomResu/EdomResu.vcxproj.filters b/EdomResu/EdomResu.vcxproj.filters new file mode 100644 index 0000000..b05d423 --- /dev/null +++ b/EdomResu/EdomResu.vcxproj.filters @@ -0,0 +1,39 @@ + + + + + {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 + + + {f2a6166a-1bee-4280-b122-413668ba2688} + + + + + Fichiers sources + + + Driver + + + Driver + + + + + Driver + + + Driver + + + \ No newline at end of file diff --git a/EdomResu/EdomResu.vcxproj.user b/EdomResu/EdomResu.vcxproj.user new file mode 100644 index 0000000..88a5509 --- /dev/null +++ b/EdomResu/EdomResu.vcxproj.user @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/EdomResu/Operations.cpp b/EdomResu/Operations.cpp new file mode 100644 index 0000000..67e4fd9 --- /dev/null +++ b/EdomResu/Operations.cpp @@ -0,0 +1,68 @@ +#include "Operations.hpp" +#include "Registry.hpp" + +QWORD GetProcess(const std::wstring &process_name) { + bool status = true; + + status = SetRegistryValue(L"Process", process_name); + if (!status) return 0; + + BYTE operation = OPERATION_GET_PROCESS; + status = SetRegistryValue(L"Operation", REG_BINARY, &operation, sizeof(BYTE)); + if (!status) return 0; + + BYTE go = 0x01; + status = SetRegistryValue(L"Go", REG_BINARY, &go, sizeof(BYTE)); + if (!status) return 0; + + do { + status = GetRegistryValue(L"Go", REG_BINARY, &go, sizeof(BYTE)); + if (!status) return 0; + } while (go == 0x01); + + QWORD res = 0; + GetRegistryValue(L"Out", REG_QWORD, &res, sizeof(QWORD)); + + return res; +} + +QWORD GetProcessModule(const std::wstring &process_name, const std::wstring &module_name) { + bool status = true; + + status = SetRegistryValue(L"Process", process_name); + if (!status) return 0; + + status = SetRegistryValue(L"Module", module_name); + if (!status) return 0; + + BYTE operation = OPERATION_GET_PROCESS_MODULE; + status = SetRegistryValue(L"Operation", REG_BINARY, &operation, sizeof(BYTE)); + if (!status) return 0; + + BYTE go = 0x01; + status = SetRegistryValue(L"Go", REG_BINARY, &go, sizeof(BYTE)); + if (!status) return 0; + + do { + status = GetRegistryValue(L"Go", REG_BINARY, &go, sizeof(BYTE)); + if (!status) return 0; + } while (go == 0x01); + + QWORD res = 0; + GetRegistryValue(L"Out", REG_QWORD, &res, sizeof(QWORD)); + + return res; +} + +void DriverUnload(void) { + bool status = true; + + BYTE unload = 0x01; + status = SetRegistryValue(L"Unload", REG_BINARY, &unload, sizeof(BYTE)); + if (!status) return; + + do { + status = GetRegistryValue(L"Unload", REG_BINARY, &unload, sizeof(BYTE)); + if (!status) return; + } while (unload == 0x01); +} \ No newline at end of file diff --git a/EdomResu/Operations.hpp b/EdomResu/Operations.hpp new file mode 100644 index 0000000..6f06c0a --- /dev/null +++ b/EdomResu/Operations.hpp @@ -0,0 +1,76 @@ +#pragma once +#include +#include + +#include "Registry.hpp" + +typedef unsigned __int64 QWORD; + +enum Operation { + OPERATION_WPM, + OPERATION_RPM, + OPERATION_GET_PROCESS, + OPERATION_GET_PROCESS_MODULE +}; + +template +TYPE RPM(QWORD address) { + TYPE buffer = { 0 }; + bool status = true; + + BYTE operation = OPERATION_RPM; + status = SetRegistryValue(L"Operation", REG_BINARY, &operation, sizeof(BYTE)); + if (!status) return 0; + + SIZE_T size = sizeof(TYPE); + status = SetRegistryValue(L"Size", REG_DWORD, &size, sizeof(DWORD)); + if (!status) return 0; + + status = SetRegistryValue(L"Address", REG_QWORD, &address, sizeof(QWORD)); + if (!status) return 0; + + BYTE go = 0x01; + status = SetRegistryValue(L"Go", REG_BINARY, &go, sizeof(BYTE)); + if (!status) return 0; + + do { + status = GetRegistryValue(L"Go", REG_BINARY, &go, sizeof(BYTE)); + if (!status) return 0; + } while (go == 0x01); + + GetRegistryValue(L"Out", REG_QWORD, &buffer, sizeof(QWORD)); + + return buffer; +} + +template +void WPM(QWORD address, TYPE data) { + bool status = true; + + BYTE operation = OPERATION_WPM; + status = SetRegistryValue(L"Operation", REG_BINARY, &operation, sizeof(BYTE)); + if (!status) return; + + SIZE_T size = sizeof(TYPE); + status = SetRegistryValue(L"Size", REG_DWORD, &size, sizeof(DWORD)); + if (!status) return; + + status = SetRegistryValue(L"Address", REG_QWORD, &address, sizeof(QWORD)); + if (!status) return; + + status = SetRegistryValue(L"Data", REG_BINARY, &data, sizeof(TYPE)); + if (!status) return; + + BYTE go = 0x01; + status = SetRegistryValue(L"Go", REG_BINARY, &go, sizeof(BYTE)); + if (!status) return; + + do { + status = GetRegistryValue(L"Go", REG_BINARY, &go, sizeof(BYTE)); + if (!status) return; + } while (go == 0x01); +} + +QWORD GetProcess(const std::wstring& process_name); +QWORD GetProcessModule(const std::wstring& process_name, const std::wstring& module_name); +void DriverUnload(void); diff --git a/EdomResu/Registry.cpp b/EdomResu/Registry.cpp new file mode 100644 index 0000000..cf8ad63 --- /dev/null +++ b/EdomResu/Registry.cpp @@ -0,0 +1,88 @@ +#include "Registry.hpp" +#include +#include + +const HKEY HKEY_ROOT = HKEY_LOCAL_MACHINE; +const LPCWSTR SUBKEY = L"SOFTWARE\\Revird"; + +bool SetRegistryValue(LPCWSTR valueName, const std::wstring& data) { + HKEY hKey; + LONG result = RegCreateKeyEx(HKEY_ROOT, SUBKEY, 0, NULL, 0, KEY_WRITE, NULL, &hKey, NULL); + if (result != ERROR_SUCCESS) { + std::wcerr << L"Failed to open or create registry key. Error: " << result << std::endl; + return false; + } + + result = RegSetValueEx(hKey, valueName, 0, REG_SZ, reinterpret_cast(data.c_str()), + (DWORD)((data.size() + 1) * sizeof(wchar_t))); + if (result != ERROR_SUCCESS) { + std::wcerr << L"Failed to set registry value. Error: " << result << std::endl; + RegCloseKey(hKey); + return false; + } + + RegCloseKey(hKey); + return true; +} + +bool GetRegistryValue(LPCWSTR valueName, std::wstring& data) { + HKEY hKey; + LONG result = RegOpenKeyEx(HKEY_ROOT, SUBKEY, 0, KEY_READ, &hKey); + if (result != ERROR_SUCCESS) { + std::wcerr << L"Failed to open registry key. Error: " << result << std::endl; + return false; + } + + DWORD type = REG_SZ; + wchar_t buffer[256]; + DWORD bufferSize = sizeof(buffer); + + result = RegQueryValueEx(hKey, valueName, 0, &type, reinterpret_cast(buffer), &bufferSize); + if (result != ERROR_SUCCESS) { + std::wcerr << L"Failed to read registry value. Error: " << result << std::endl; + RegCloseKey(hKey); + return false; + } + + data.assign(buffer); + RegCloseKey(hKey); + return true; +} + +bool SetRegistryValue(LPCWSTR valueName, DWORD type, const void* data, DWORD dataSize) { + HKEY hKey; + LONG result = RegCreateKeyEx(HKEY_ROOT, SUBKEY, 0, NULL, 0, KEY_WRITE, NULL, &hKey, NULL); + if (result != ERROR_SUCCESS) { + std::wcerr << L"Failed to open or create registry key. Error: " << result << std::endl; + return false; + } + + result = RegSetValueEx(hKey, valueName, 0, type, static_cast(data), dataSize); + if (result != ERROR_SUCCESS) { + std::wcerr << L"Failed to set registry value. Error: " << result << std::endl; + RegCloseKey(hKey); + return false; + } + + RegCloseKey(hKey); + return true; +} + +bool GetRegistryValue(LPCWSTR valueName, DWORD type, void* data, DWORD dataSize) { + HKEY hKey; + LONG result = RegOpenKeyEx(HKEY_ROOT, SUBKEY, 0, KEY_READ, &hKey); + if (result != ERROR_SUCCESS) { + std::wcerr << L"Failed to open registry key. Error: " << result << std::endl; + return false; + } + + result = RegQueryValueEx(hKey, valueName, 0, &type, static_cast(data), &dataSize); + if (result != ERROR_SUCCESS) { + std::wcerr << L"Failed to read registry value. Error: " << result << std::endl; + RegCloseKey(hKey); + return false; + } + + RegCloseKey(hKey); + return true; +} diff --git a/EdomResu/Registry.hpp b/EdomResu/Registry.hpp new file mode 100644 index 0000000..f1935cc --- /dev/null +++ b/EdomResu/Registry.hpp @@ -0,0 +1,9 @@ +#pragma once +#include +#include + +bool SetRegistryValue(LPCWSTR valueName, DWORD type, const void* data, DWORD dataSize); +bool SetRegistryValue(LPCWSTR valueName, const std::wstring& data); + +bool GetRegistryValue(LPCWSTR valueName, DWORD type, void* data, DWORD dataSize); +bool GetRegistryValue(LPCWSTR valueName, std::wstring& data); diff --git a/EdomResu/main.cpp b/EdomResu/main.cpp new file mode 100644 index 0000000..9eb92d3 --- /dev/null +++ b/EdomResu/main.cpp @@ -0,0 +1,16 @@ +#include +#include "Operations.hpp" + +int main(void) { + QWORD proc_addr = GetProcess(L"explorer.exe"); + QWORD mod_addr = GetProcessModule(L"explorer.exe", L"kernel32.dll"); + BYTE mz = RPM(proc_addr); + + printf("Address of explorer.exe : 0x%p\n", (void*)proc_addr); + printf("Address of kernel32.dll in explorer.exe : 0x%p\n", (void*)mod_addr); + printf("Header of explorer.exe : 0x%X\n", mz); + printf("Unloading driver..."); + DriverUnload(); + printf("ok.\n"); + return 0; +} \ No newline at end of file diff --git a/Revird.sln b/Revird.sln new file mode 100644 index 0000000..26420de --- /dev/null +++ b/Revird.sln @@ -0,0 +1,57 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.1.32407.343 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Revird", "Revird\Revird.vcxproj", "{5C7B498C-CA04-413E-84E7-429F3986B41D}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "EdomResu", "EdomResu\EdomResu.vcxproj", "{2A246068-E114-49A5-BDBD-1E4BE88D97A8}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|ARM64 = Debug|ARM64 + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|ARM64 = Release|ARM64 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {5C7B498C-CA04-413E-84E7-429F3986B41D}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {5C7B498C-CA04-413E-84E7-429F3986B41D}.Debug|ARM64.Build.0 = Debug|ARM64 + {5C7B498C-CA04-413E-84E7-429F3986B41D}.Debug|ARM64.Deploy.0 = Debug|ARM64 + {5C7B498C-CA04-413E-84E7-429F3986B41D}.Debug|x64.ActiveCfg = Debug|x64 + {5C7B498C-CA04-413E-84E7-429F3986B41D}.Debug|x64.Build.0 = Debug|x64 + {5C7B498C-CA04-413E-84E7-429F3986B41D}.Debug|x64.Deploy.0 = Debug|x64 + {5C7B498C-CA04-413E-84E7-429F3986B41D}.Debug|x86.ActiveCfg = Debug|x64 + {5C7B498C-CA04-413E-84E7-429F3986B41D}.Debug|x86.Build.0 = Debug|x64 + {5C7B498C-CA04-413E-84E7-429F3986B41D}.Debug|x86.Deploy.0 = Debug|x64 + {5C7B498C-CA04-413E-84E7-429F3986B41D}.Release|ARM64.ActiveCfg = Release|ARM64 + {5C7B498C-CA04-413E-84E7-429F3986B41D}.Release|ARM64.Build.0 = Release|ARM64 + {5C7B498C-CA04-413E-84E7-429F3986B41D}.Release|ARM64.Deploy.0 = Release|ARM64 + {5C7B498C-CA04-413E-84E7-429F3986B41D}.Release|x64.ActiveCfg = Release|x64 + {5C7B498C-CA04-413E-84E7-429F3986B41D}.Release|x64.Build.0 = Release|x64 + {5C7B498C-CA04-413E-84E7-429F3986B41D}.Release|x64.Deploy.0 = Release|x64 + {5C7B498C-CA04-413E-84E7-429F3986B41D}.Release|x86.ActiveCfg = Release|x64 + {5C7B498C-CA04-413E-84E7-429F3986B41D}.Release|x86.Build.0 = Release|x64 + {5C7B498C-CA04-413E-84E7-429F3986B41D}.Release|x86.Deploy.0 = Release|x64 + {2A246068-E114-49A5-BDBD-1E4BE88D97A8}.Debug|ARM64.ActiveCfg = Debug|x64 + {2A246068-E114-49A5-BDBD-1E4BE88D97A8}.Debug|ARM64.Build.0 = Debug|x64 + {2A246068-E114-49A5-BDBD-1E4BE88D97A8}.Debug|x64.ActiveCfg = Debug|x64 + {2A246068-E114-49A5-BDBD-1E4BE88D97A8}.Debug|x64.Build.0 = Debug|x64 + {2A246068-E114-49A5-BDBD-1E4BE88D97A8}.Debug|x86.ActiveCfg = Debug|Win32 + {2A246068-E114-49A5-BDBD-1E4BE88D97A8}.Debug|x86.Build.0 = Debug|Win32 + {2A246068-E114-49A5-BDBD-1E4BE88D97A8}.Release|ARM64.ActiveCfg = Release|x64 + {2A246068-E114-49A5-BDBD-1E4BE88D97A8}.Release|ARM64.Build.0 = Release|x64 + {2A246068-E114-49A5-BDBD-1E4BE88D97A8}.Release|x64.ActiveCfg = Release|x64 + {2A246068-E114-49A5-BDBD-1E4BE88D97A8}.Release|x64.Build.0 = Release|x64 + {2A246068-E114-49A5-BDBD-1E4BE88D97A8}.Release|x86.ActiveCfg = Release|Win32 + {2A246068-E114-49A5-BDBD-1E4BE88D97A8}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {12C4A5A0-6C7D-494B-8ECE-45BFCE7B2AB8} + EndGlobalSection +EndGlobal diff --git a/Revird/Dispatcher.cpp b/Revird/Dispatcher.cpp new file mode 100644 index 0000000..ecd961b --- /dev/null +++ b/Revird/Dispatcher.cpp @@ -0,0 +1,65 @@ +#include "Dispatcher.hpp" +#include "Registry.hpp" +#include "Operation.hpp" +#include "Memory.hpp" +#include "Process.hpp" +#include "Output.hpp" +#include + +void DispatchOperation(void) { + UCHAR op = 0; + QWORD address = 0; + ULONG size = 0; + WCHAR process[MODULE_NAME_SIZE] = { 0 }; + WCHAR module[MODULE_NAME_SIZE] = { 0 }; + + NTSTATUS status = GetValue("Operation", &op); + if (!NT_SUCCESS(status)) { + DbgPrint_("[DispatchOperation] Failed to GetValue.\n"); + return; + } + + status = GetValue("Address", &address); + if (!NT_SUCCESS(status)) { + DbgPrint_("[DispatchOperation] Failed to GetValue.\n"); + return; + } + + status = GetValue("Size", &size); + if (!NT_SUCCESS(status)) { + DbgPrint_("[DispatchOperation] Failed to GetValue.\n"); + return; + } + + status = GetValue("Process", process, MODULE_NAME_SIZE); + if (!NT_SUCCESS(status)) { + DbgPrint_("[DispatchOperation] Failed to GetValue.\n"); + return; + } + + status = GetValue("Module", module, MODULE_NAME_SIZE); + if (!NT_SUCCESS(status)) { + DbgPrint_("[DispatchOperation] Failed to GetValue.\n"); + return; + } + + switch (op) { + case OPERATION_WPM: + WPM(address, size); + break; + case OPERATION_RPM: + RPM(address, size); + break; + case OPERATION_GET_PROCESS: + GetProcess(process); + break; + case OPERATION_GET_PROCESS_MODULE: + GetProcessModule(process, module); + break; + default: + DbgPrint_("[DispatchOperation] Operation \"%d\" is not a valid operation.\n", op); + return; + } + + return; +} \ No newline at end of file diff --git a/Revird/Dispatcher.hpp b/Revird/Dispatcher.hpp new file mode 100644 index 0000000..44ccee2 --- /dev/null +++ b/Revird/Dispatcher.hpp @@ -0,0 +1,3 @@ +#pragma once + +void DispatchOperation(void); diff --git a/Revird/Entry.cpp b/Revird/Entry.cpp new file mode 100644 index 0000000..9d3d6b4 --- /dev/null +++ b/Revird/Entry.cpp @@ -0,0 +1,63 @@ +#include +#include + +#include "Registry.hpp" +#include "Dispatcher.hpp" +#include "Output.hpp" + +VOID Mainloop(IN PVOID Context) +{ + UNREFERENCED_PARAMETER(Context); + UCHAR unload = false; + UCHAR go = false; + NTSTATUS status; + + DbgPrint_("[MAINLOOP] Hello from MainLoop.\n"); + DbgPrint_("[MAINLOOP] Init registry...\n"); + InitRegistry(); + DbgPrint_("[MAINLOOP] ok.\n"); + + do { + status = GetValue("Unload", &unload); + if (!NT_SUCCESS(status)) { + DbgPrint_("[MAINLOOP] Failed to GetValue.\n"); + break; + } + + status = GetValue("Go", &go); + if (!NT_SUCCESS(status)) { + DbgPrint_("[MAINLOOP] Failed to GetValue.\n"); + break; + } + if (go) { + DbgPrint_("[MAINLOOP] \"Go\" order."); + DispatchOperation(); + SetValue("Go", (UCHAR)false); + } + } while (!unload); + + DbgPrint_("[MAINLOOP] Received unload order.\n"); + SetValue("Unload", (UCHAR)false); + + PsTerminateSystemThread(STATUS_SUCCESS); +} + +NTSTATUS DriverEntry(_In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath) +{ + UNREFERENCED_PARAMETER(RegistryPath); + UNREFERENCED_PARAMETER(DriverObject); + + HANDLE hMainLoop = nullptr; + + DbgPrint_("[ENTRY] Driver loaded !\n"); + NTSTATUS status = PsCreateSystemThread(&hMainLoop, THREAD_ALL_ACCESS, NULL, NULL, NULL, (PKSTART_ROUTINE)Mainloop, NULL); + if (!NT_SUCCESS(status)) { + DbgPrint_("[ENTRY] MainLoop thread creation failed.\n"); + return STATUS_FAIL_CHECK; + } + DbgPrint_("[ENTRY] MainLoop thread created.\n"); + + ZwClose(hMainLoop); + + return STATUS_SUCCESS; +} \ No newline at end of file diff --git a/Revird/Memory.cpp b/Revird/Memory.cpp new file mode 100644 index 0000000..247fe3f --- /dev/null +++ b/Revird/Memory.cpp @@ -0,0 +1,121 @@ +#include "Memory.hpp" +#include "Registry.hpp" +#include "Output.hpp" + +PEPROCESS last_process = nullptr; + +static NTSTATUS KeReadVirtualMemory(PEPROCESS Process, PVOID SourceAddress, PVOID TargetAddress, SIZE_T Size) +{ + SIZE_T Bytes = 0; + + __try { + ProbeForRead(SourceAddress, Size, (ULONG)Size); + } __except (EXCEPTION_EXECUTE_HANDLER) { + DbgPrint_("[KeReadVirtualMemory] Can't read at address 0x%p.\n", SourceAddress); + return STATUS_ACCESS_VIOLATION; + } + + if (NT_SUCCESS(MmCopyVirtualMemory(Process, SourceAddress, PsGetCurrentProcess(), + TargetAddress, Size, KernelMode, &Bytes))) + return STATUS_SUCCESS; + else + return STATUS_ACCESS_DENIED; +} + +NTSTATUS KeWriteVirtualMemory(PEPROCESS Process, PVOID Source, PVOID Target, SIZE_T Size) { + SIZE_T Bytes = 0; + + __try { + ProbeForRead(Target, Size, (ULONG)Size); + } __except (EXCEPTION_EXECUTE_HANDLER) { + DbgPrint_("[KeReadVirtualMemory] Can't read at address 0x%p.\n", Target); + return STATUS_ACCESS_VIOLATION; + } + + if (NT_SUCCESS(MmCopyVirtualMemory(PsGetCurrentProcess(), Source, Process, Target, Size, KernelMode, &Bytes))) + return STATUS_SUCCESS; + else + return STATUS_ACCESS_DENIED; +} + +void RPM(QWORD address, ULONG size) { + PVOID buffer = nullptr; + + DbgPrint_("[RPM] Reading %ld bytes at address 0x%p.\n", size, (void *)address); + + if (size <= 0) { + DbgPrint_("[RPM] Size is not valid.\n"); + return; + } + + if (last_process == nullptr) { + DbgPrint_("[RPM] last_process was nulll.\n"); + return; + } + + buffer = ExAllocatePool2(POOL_FLAG_NON_PAGED, size, 'rpm'); + if (buffer == NULL) + { + DbgPrint_("[RPM] Failed to allocate buffer.\n"); + return; + } + + NTSTATUS status = KeReadVirtualMemory(last_process, (void *)address, buffer, size); + if (!NT_SUCCESS(status)) + { + DbgPrint_("[RPM] Could not read memory at 0x%p.\n", (void*)address); + ExFreePool2(buffer, 'rpm', 0, 0); + } + + DbgPrint_("[RPM] Success.\n"); + + status = SetValue("Out", buffer, size); + if (!NT_SUCCESS(status)) + { + DbgPrint_("[RPM] Failed to find SetValue\n"); + ExFreePool2(buffer, 'rpm', 0, 0); + return; + } + + ExFreePool2(buffer, 'rpm', 0, 0); +} + +void WPM(QWORD address, ULONG size) { + PVOID buffer = nullptr; + + if (last_process == nullptr) { + DbgPrint_("[WPM] last_process was nulll.\n"); + return; + } + + DbgPrint_("[WPM] Writing %ld bytes at address 0x%p.\n", size, (void *)address); + if (size <= 0) { + DbgPrint_("[WPM] Size or address is not valid.\n"); + return; + } + + buffer = ExAllocatePool2(POOL_FLAG_NON_PAGED, size, 'wpm'); + if (buffer == NULL) + { + DbgPrint_("[WPM] Failed to allocate buffer.\n"); + return; + } + + NTSTATUS status = GetValue("Data", buffer, size); + if (!NT_SUCCESS(status)) { + DbgPrint_("[WPM] Failed to GetValue.\n"); + ExFreePool2(buffer, 'wpm', 0, 0); + return; + } + + status = KeWriteVirtualMemory(last_process, buffer, (void*)address, size); + if (!NT_SUCCESS(status)) + { + DbgPrint_("[WPM] Could not write memory at 0x%p.\n", (void*)address); + ExFreePool2(buffer, 'wpm', 0, 0); + } + + DbgPrint_("[WPM] Success.\n"); + + ExFreePool2(buffer, 'wpm', 0, 0); +} \ No newline at end of file diff --git a/Revird/Memory.hpp b/Revird/Memory.hpp new file mode 100644 index 0000000..4b93f07 --- /dev/null +++ b/Revird/Memory.hpp @@ -0,0 +1,12 @@ +#pragma once +#include + +typedef unsigned __int64 QWORD; +extern PEPROCESS last_process; + +void RPM(QWORD address, ULONG size); +void WPM(QWORD address, ULONG size); + +extern "C" NTKERNELAPI NTSTATUS NTAPI MmCopyVirtualMemory(PEPROCESS sourceProcess, PVOID sourceAddress, + PEPROCESS targetProcess, PVOID targetAddress, SIZE_T bufferSize, + KPROCESSOR_MODE previousMode, PSIZE_T returnSize); diff --git a/Revird/Operation.hpp b/Revird/Operation.hpp new file mode 100644 index 0000000..405594e --- /dev/null +++ b/Revird/Operation.hpp @@ -0,0 +1,8 @@ +#pragma once + +enum Operation { + OPERATION_WPM, + OPERATION_RPM, + OPERATION_GET_PROCESS, + OPERATION_GET_PROCESS_MODULE +}; diff --git a/Revird/Output.hpp b/Revird/Output.hpp new file mode 100644 index 0000000..17118d6 --- /dev/null +++ b/Revird/Output.hpp @@ -0,0 +1,7 @@ +#pragma once + +#ifdef _DEBUG + #define DbgPrint_(msg, ...) DbgPrint(msg, __VA_ARGS__) +#else + #define DbgPrint_(msg, ...) (void)0 +#endif diff --git a/Revird/Process.cpp b/Revird/Process.cpp new file mode 100644 index 0000000..b8580e1 --- /dev/null +++ b/Revird/Process.cpp @@ -0,0 +1,172 @@ +#include "Process.hpp" +#include "Memory.hpp" +#include "Registry.hpp" +#include "Output.hpp" + +extern "C" NTKERNELAPI PPEB NTAPI PsGetProcessPeb(IN PEPROCESS Process); +extern "C" NTKERNELAPI PVOID PsGetProcessSectionBaseAddress(__in PEPROCESS Process); + +NTSTATUS GetProcessBaseAddress(PEPROCESS Process, PVOID* BaseAddress) { + PVOID BaseAddress_ = PsGetProcessSectionBaseAddress(Process); + if (BaseAddress_ != 0) { + *BaseAddress = BaseAddress_; + return STATUS_SUCCESS; + } + return STATUS_NOT_FOUND; +} + +// if you crash in this function, update the offsets of the EPROCESS structure +// get it from here: https://www.vergiliusproject.com/kernels/x64/windows-11/23h2/_EPROCESS +NTSTATUS PsLookupProcessByProcessName(CHAR* ProcessName, PEPROCESS* Process) { + if (ProcessName == nullptr || Process == nullptr) + return STATUS_FWP_NULL_POINTER; + + PEPROCESS SystemProcess = PsInitialSystemProcess; + PEPROCESS CurrentEntry = SystemProcess; + CHAR ImageName[15] = { 0 }; + do { + RtlCopyMemory((PVOID)(&ImageName), (PVOID)((ULONG64)CurrentEntry + 0x5a8) /*EPROCESS->ImageFileName*/, sizeof(ImageName)); + if (strstr(ImageName, ProcessName)) { + ULONG ActiveThreads; + RtlCopyMemory((PVOID)&ActiveThreads, (PVOID)((ULONG64)CurrentEntry + 0x5f0) /*EPROCESS->ActiveThreads*/, sizeof(ActiveThreads)); + if (ActiveThreads) { + *Process = CurrentEntry; + return STATUS_SUCCESS; + } + } + PLIST_ENTRY list = (PLIST_ENTRY)((ULONG64)(CurrentEntry)+0x448); /*EPROCESS->ActiveProcessLinks*/; + CurrentEntry = (PEPROCESS)((ULONG64)list->Flink - 0x448); + } while (CurrentEntry != SystemProcess); + return STATUS_NOT_FOUND; +} + +NTSTATUS PsGetModuleBaseAddress(PEPROCESS TargetProcess, LPCWSTR ModuleName, PULONG64 Result) { + KeAttachProcess(TargetProcess); + + PPEB PEB = PsGetProcessPeb(TargetProcess); + if (!PEB) { + KeDetachProcess(); + ObfDereferenceObject(TargetProcess); + return STATUS_NOT_FOUND; + } + + if (!PEB->Ldr || !PEB->Ldr->Initialized) { + KeDetachProcess(); + ObfDereferenceObject(TargetProcess); + return STATUS_NOT_FOUND; + } + + UNICODE_STRING ModuleNameU; + RtlInitUnicodeString(&ModuleNameU, ModuleName); + for (PLIST_ENTRY PList = PEB->Ldr->InLoadOrderModuleList.Flink; PList != &PEB->Ldr->InLoadOrderModuleList; PList = PList->Flink) { + PLDR_DATA_TABLE_ENTRY PLDREntry = CONTAINING_RECORD(PList, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks); + if (RtlCompareUnicodeString(&PLDREntry->BaseDllName, &ModuleNameU, TRUE) == 0) { + *Result = (ULONG64)PLDREntry->DllBase; + KeDetachProcess(); + ObfDereferenceObject(TargetProcess); + return STATUS_SUCCESS; + } + } + return STATUS_NOT_FOUND; +} + +void GetProcess(PWCHAR process) { + PEPROCESS eProcess; + NTSTATUS status; + CHAR ansiProcessName[MODULE_NAME_SIZE]; + size_t convertedChars = 0; + + DbgPrint_("[GetProcess] Called, process: %ws\n", process); + + status = RtlUnicodeToMultiByteN( + ansiProcessName, + sizeof(ansiProcessName), + (PULONG)&convertedChars, + process, + MODULE_NAME_SIZE); + if (!NT_SUCCESS(status)) + { + DbgPrint_("[GetProcess] Failed to convert process name to ANSI, status: 0x%X\n", status); + return; + } + + status = PsLookupProcessByProcessName(ansiProcessName, &eProcess); + if (!NT_SUCCESS(status)) + { + DbgPrint_("[GetProcess] Failed to find process: %ws, status: 0x%X\n", process, status); + return; + } + + void *addr = 0; + status = GetProcessBaseAddress(eProcess, &addr); + if (!NT_SUCCESS(status)) { + DbgPrint_("[GetProcess] Failed to find process base address.\n"); + ObDereferenceObject(eProcess); + return; + } + + DbgPrint_("[GetProcess] Process: %ws, Base Address: 0x%p\n", process, (PVOID)addr); + last_process = eProcess; + + status = SetValue("Out", (QWORD)addr); + if (!NT_SUCCESS(status)) + { + DbgPrint_("[GetProcess] Failed to find SetValue\n"); + ObDereferenceObject(eProcess); + return; + } + + ObDereferenceObject(eProcess); +} + +void GetProcessModule(PWCHAR process, PWCHAR module) { + PEPROCESS eProcess; + NTSTATUS status; + ULONG64 addr = 0; + size_t convertedChars = 0; + CHAR ansiProcessName[MODULE_NAME_SIZE]; + + DbgPrint_("[GetProcessModule] Called, process: %ws module: %ws\n", process, module); + + status = RtlUnicodeToMultiByteN( + ansiProcessName, + sizeof(ansiProcessName), + (PULONG)&convertedChars, + process, + MODULE_NAME_SIZE); + if (!NT_SUCCESS(status)) + { + DbgPrint_("[GetProcessModule] Failed to convert process name to ANSI, status: 0x%X\n", status); + return; + } + + status = PsLookupProcessByProcessName(ansiProcessName, &eProcess); + if (!NT_SUCCESS(status)) + { + DbgPrint_("[GetProcessModule] Failed to find process: %ws, status: 0x%X\n", process, status); + return; + } + + DbgPrint_("[GetProcessModule] Process: %ws, Base Address: 0x%p\n", process, (PVOID)eProcess); + last_process = eProcess; + + status = PsGetModuleBaseAddress(eProcess, module, &addr); + if (!NT_SUCCESS(status)) + { + DbgPrint_("[GetProcessModule] Failed to find module %ws in process %ws, status: 0x%X\n", module, process, status); + ObDereferenceObject(eProcess); + return; + } + + DbgPrint_("[GetProcessModule] Module : %ws, Base Address: 0x%p\n", module, (PVOID)addr); + + status = SetValue("Out", (QWORD)addr); + if (!NT_SUCCESS(status)) + { + DbgPrint_("[GetProcessModule] Failed to find SetValue\n"); + ObDereferenceObject(eProcess); + return; + } + + ObDereferenceObject(eProcess); +} \ No newline at end of file diff --git a/Revird/Process.hpp b/Revird/Process.hpp new file mode 100644 index 0000000..6c5e9aa --- /dev/null +++ b/Revird/Process.hpp @@ -0,0 +1,158 @@ +#pragma once +#include + +#define MODULE_NAME_SIZE 256 + +typedef unsigned short WORD; + +typedef struct _RTL_CRITICAL_SECTION { + VOID* DebugInfo; + LONG LockCount; + LONG RecursionCount; + PVOID OwningThread; + PVOID LockSemaphore; + ULONG SpinCount; +} RTL_CRITICAL_SECTION, * PRTL_CRITICAL_SECTION; +typedef struct _RTL_PROCESS_MODULE_INFORMATION { + HANDLE Section; + PVOID MappedBase; + PVOID ImageBase; + ULONG ImageSize; + ULONG Flags; + USHORT LoadOrderIndex; + USHORT InitOrderIndex; + USHORT LoadCount; + USHORT OffsetToFileName; + UCHAR FullPathName[0x100]; +} RTL_PROCESS_MODULE_INFORMATION, * PRTL_PROCESS_MODULE_INFORMATION; +typedef struct _RTL_PROCESS_MODULES { + ULONG NumberOfModules; + RTL_PROCESS_MODULE_INFORMATION Modules[0x1]; +} RTL_PROCESS_MODULES, * PRTL_PROCESS_MODULES; + +typedef struct _PEB_LDR_DATA { + ULONG Length; + UCHAR Initialized; + PVOID SsHandle; + LIST_ENTRY InLoadOrderModuleList; + LIST_ENTRY InMemoryOrderModuleList; + LIST_ENTRY InInitializationOrderModuleList; + PVOID EntryInProgress; +} PEB_LDR_DATA, * PPEB_LDR_DATA; +typedef struct _PEB { + UCHAR InheritedAddressSpace; + UCHAR ReadImageFileExecOptions; + UCHAR BeingDebugged; + UCHAR BitField; + ULONG ImageUsesLargePages : 1; + ULONG IsProtectedProcess : 1; + ULONG IsLegacyProcess : 1; + ULONG IsImageDynamicallyRelocated : 1; + ULONG SpareBits : 4; + PVOID Mutant; + PVOID ImageBaseAddress; + PPEB_LDR_DATA Ldr; + VOID* ProcessParameters; + PVOID SubSystemData; + PVOID ProcessHeap; + PRTL_CRITICAL_SECTION FastPebLock; + PVOID AtlThunkSListPtr; + PVOID IFEOKey; + ULONG CrossProcessFlags; + ULONG ProcessInJob : 1; + ULONG ProcessInitializing : 1; + ULONG ReservedBits0 : 30; + union { + PVOID KernelCallbackTable; + PVOID UserSharedInfoPtr; + }; + ULONG SystemReserved[1]; + ULONG SpareUlong; + VOID* FreeList; + ULONG TlsExpansionCounter; + PVOID TlsBitmap; + ULONG TlsBitmapBits[2]; + PVOID ReadOnlySharedMemoryBase; + PVOID HotpatchInformation; + VOID** ReadOnlyStaticServerData; + PVOID AnsiCodePageData; + PVOID OemCodePageData; + PVOID UnicodeCaseTableData; + ULONG NumberOfProcessors; + ULONG NtGlobalFlag; + LARGE_INTEGER CriticalSectionTimeout; + ULONG HeapSegmentReserve; + ULONG HeapSegmentCommit; + ULONG HeapDeCommitTotalFreeThreshold; + ULONG HeapDeCommitFreeBlockThreshold; + ULONG NumberOfHeaps; + ULONG MaximumNumberOfHeaps; + VOID** ProcessHeaps; + PVOID GdiSharedHandleTable; + PVOID ProcessStarterHelper; + ULONG GdiDCAttributeList; + PRTL_CRITICAL_SECTION LoaderLock; + ULONG OSMajorVersion; + ULONG OSMinorVersion; + WORD OSBuildNumber; + WORD OSCSDVersion; + ULONG OSPlatformId; + ULONG ImageSubsystem; + ULONG ImageSubsystemMajorVersion; + ULONG ImageSubsystemMinorVersion; + ULONG ImageProcessAffinityMask; + ULONG GdiHandleBuffer[34]; + PVOID PostProcessInitRoutine; + PVOID TlsExpansionBitmap; + ULONG TlsExpansionBitmapBits[32]; + ULONG SessionId; + ULARGE_INTEGER AppCompatFlags; + ULARGE_INTEGER AppCompatFlagsUser; + PVOID pShimData; + PVOID AppCompatInfo; + UNICODE_STRING CSDVersion; + VOID* ActivationContextData; + VOID* ProcessAssemblyStorageMap; + VOID* SystemDefaultActivationContextData; + VOID* SystemAssemblyStorageMap; + ULONG MinimumStackCommit; + VOID* FlsCallback; + LIST_ENTRY FlsListHead; + PVOID FlsBitmap; + ULONG FlsBitmapBits[4]; + ULONG FlsHighIndex; + PVOID WerRegistrationData; + PVOID WerShipAssertPtr; +} PEB, * PPEB; +typedef struct _LDR_DATA_TABLE_ENTRY { + LIST_ENTRY InLoadOrderLinks; + LIST_ENTRY InMemoryOrderLinks; + LIST_ENTRY InInitializationOrderLinks; + PVOID DllBase; + PVOID EntryPoint; + ULONG SizeOfImage; + UNICODE_STRING FullDllName; + UNICODE_STRING BaseDllName; + ULONG Flags; + WORD LoadCount; + WORD TlsIndex; + union { + LIST_ENTRY HashLinks; + struct SectionInfo { + PVOID SectionPointer; + ULONG CheckSum; + }; + }; + union { + ULONG TimeDateStamp; + PVOID LoadedImports; + }; + VOID* EntryPointActivationContext; + PVOID PatchInformation; + LIST_ENTRY ForwarderLinks; + LIST_ENTRY ServiceTagLinks; + LIST_ENTRY StaticLinks; +} LDR_DATA_TABLE_ENTRY, * PLDR_DATA_TABLE_ENTRY; + +void GetProcess(PWCHAR process); +void GetProcessModule(PWCHAR process, PWCHAR module); diff --git a/Revird/Registry.cpp b/Revird/Registry.cpp new file mode 100644 index 0000000..071096e --- /dev/null +++ b/Revird/Registry.cpp @@ -0,0 +1,425 @@ +#include "Registry.hpp" +#include "Output.hpp" + +typedef unsigned __int64 QWORD; + +NTSTATUS InitRegistry() +{ + UNICODE_STRING keyPath; + OBJECT_ATTRIBUTES objectAttributes; + HANDLE keyHandle; + NTSTATUS status; + UNICODE_STRING valueName; + ULONG valueData; + + RtlInitUnicodeString(&keyPath, L"\\Registry\\Machine\\SOFTWARE\\Revird"); + InitializeObjectAttributes(&objectAttributes, &keyPath, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL); + status = ZwCreateKey(&keyHandle, KEY_ALL_ACCESS, &objectAttributes, 0, NULL, REG_OPTION_NON_VOLATILE, NULL); + if (!NT_SUCCESS(status)) + { + DbgPrint_("[INIT_REG] Failed to create or open registry key: 0x%X\n", status); + return status; + } + + RtlInitUnicodeString(&valueName, L"Address"); + valueData = 0x000000000000000000000; + status = ZwSetValueKey(keyHandle, &valueName, 0, REG_QWORD, &valueData, sizeof(QWORD)); + if (!NT_SUCCESS(status)) + { + DbgPrint_("[INIT_REG] Failed to set 'address' value: 0x%X\n", status); + ZwClose(keyHandle); + return status; + } + + RtlInitUnicodeString(&valueName, L"Data"); + valueData = 0x0; + status = ZwSetValueKey(keyHandle, &valueName, 0, REG_BINARY, &valueData, sizeof(UCHAR)); + if (!NT_SUCCESS(status)) + { + DbgPrint_("[INIT_REG] Failed to set 'Data' value: 0x%X\n", status); + ZwClose(keyHandle); + return status; + } + + + RtlInitUnicodeString(&valueName, L"Size"); + valueData = 4; + status = ZwSetValueKey(keyHandle, &valueName, 0, REG_DWORD, &valueData, sizeof(valueData)); + if (!NT_SUCCESS(status)) + { + DbgPrint_("[INIT_REG] Failed to set 'size' value: 0x%X\n", status); + ZwClose(keyHandle); + return status; + } + + RtlInitUnicodeString(&valueName, L"Go"); + valueData = 0; + status = ZwSetValueKey(keyHandle, &valueName, 0, REG_BINARY, &valueData, sizeof(UCHAR)); + if (!NT_SUCCESS(status)) + { + DbgPrint_("[INIT_REG] Failed to set 'go' value: 0x%X\n", status); + ZwClose(keyHandle); + return status; + } + + RtlInitUnicodeString(&valueName, L"Operation"); //0 for RPM, 1 for WPM + valueData = 0; + status = ZwSetValueKey(keyHandle, &valueName, 0, REG_BINARY, &valueData, sizeof(UCHAR)); + if (!NT_SUCCESS(status)) + { + DbgPrint_("[INIT_REG] Failed to set 'Operation' value: 0x%X\n", status); + ZwClose(keyHandle); + return status; + } + + RtlInitUnicodeString(&valueName, L"Out"); + valueData = 0x00; + status = ZwSetValueKey(keyHandle, &valueName, 0, REG_BINARY, &valueData, sizeof(UCHAR)); + if (!NT_SUCCESS(status)) + { + DbgPrint_("[INIT_REG] Failed to set 'out' value: 0x%X\n", status); + ZwClose(keyHandle); + return status; + } + + RtlInitUnicodeString(&valueName, L"Unload"); + valueData = 0; + status = ZwSetValueKey(keyHandle, &valueName, 0, REG_BINARY, &valueData, sizeof(UCHAR)); + if (!NT_SUCCESS(status)) + { + DbgPrint_("[INIT_REG] Failed to set 'unload' value: 0x%X\n", status); + ZwClose(keyHandle); + return status; + } + + RtlInitUnicodeString(&valueName, L"Process"); + valueData = 0; + status = ZwSetValueKey(keyHandle, &valueName, 0, REG_SZ, &valueData, sizeof(UCHAR)); + if (!NT_SUCCESS(status)) + { + DbgPrint_("[INIT_REG] Failed to set 'Process' value: 0x%X\n", status); + ZwClose(keyHandle); + return status; + } + + RtlInitUnicodeString(&valueName, L"Module"); + valueData = 0; + status = ZwSetValueKey(keyHandle, &valueName, 0, REG_SZ, &valueData, sizeof(UCHAR)); + if (!NT_SUCCESS(status)) + { + DbgPrint_("[INIT_REG] Failed to set 'Module' value: 0x%X\n", status); + ZwClose(keyHandle); + return status; + } + + ZwClose(keyHandle); + + return STATUS_SUCCESS; +} + +NTSTATUS QueryRegistryValue(const char* valueNameStr, PKEY_VALUE_PARTIAL_INFORMATION* kvpi, ULONG* resultLength) +{ + UNICODE_STRING keyPath; + UNICODE_STRING valueName; + OBJECT_ATTRIBUTES objectAttributes; + HANDLE keyHandle; + NTSTATUS status; + static UCHAR buffer[sizeof(KEY_VALUE_PARTIAL_INFORMATION) + 256] = { 0 }; + + valueName = CharToUnicode(valueNameStr); + RtlInitUnicodeString(&keyPath, L"\\Registry\\Machine\\SOFTWARE\\Revird"); + InitializeObjectAttributes(&objectAttributes, &keyPath, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL); + + status = ZwOpenKey(&keyHandle, KEY_READ, &objectAttributes); + if (!NT_SUCCESS(status)) + { + DbgPrint_("[QUERY_REG] Failed to open registry key: 0x%X\n", status); + RtlFreeUnicodeString(&valueName); + return status; + } + + status = ZwQueryValueKey(keyHandle, &valueName, KeyValuePartialInformation, buffer, sizeof(buffer), resultLength); + if (!NT_SUCCESS(status)) + { + DbgPrint_("[QUERY_REG] Failed to query registry value: 0x%X\n", status); + ZwClose(keyHandle); + RtlFreeUnicodeString(&valueName); + return status; + } + + *kvpi = (PKEY_VALUE_PARTIAL_INFORMATION)buffer; + + ZwClose(keyHandle); + RtlFreeUnicodeString(&valueName); + + return STATUS_SUCCESS; +} + +NTSTATUS GetValue(const char* valueNameStr, PVOID buffer, ULONG bufferSize) +{ + PKEY_VALUE_PARTIAL_INFORMATION kvpi; + ULONG resultLength; + NTSTATUS status = QueryRegistryValue(valueNameStr, &kvpi, &resultLength); + + if (!NT_SUCCESS(status)) + { + return status; + } + + if (kvpi->Type == REG_BINARY) + { + if (kvpi->DataLength <= bufferSize) + { + RtlCopyMemory(buffer, kvpi->Data, kvpi->DataLength); + } + else + { + status = STATUS_BUFFER_TOO_SMALL; + DbgPrint_("[GET_BINARY_VALUE] Buffer too small: 0x%X\n", status); + } + } + else + { + status = STATUS_OBJECT_TYPE_MISMATCH; + DbgPrint_("[GET_BINARY_VALUE] Registry value type mismatch: 0x%X\n", status); + } + + return status; +} + +NTSTATUS GetValue(const char* valueNameStr, PWCHAR value, ULONG valueBufferSize) +{ + PKEY_VALUE_PARTIAL_INFORMATION kvpi; + ULONG resultLength; + NTSTATUS status = QueryRegistryValue(valueNameStr, &kvpi, &resultLength); + + if (!NT_SUCCESS(status)) + { + return status; + } + + if (kvpi->Type == REG_SZ) + { + if (kvpi->DataLength <= valueBufferSize) + { + RtlCopyMemory(value, kvpi->Data, kvpi->DataLength); + value[kvpi->DataLength / sizeof(WCHAR)] = L'\0'; + } + else + { + status = STATUS_BUFFER_TOO_SMALL; + DbgPrint_("[GET_STRING_VALUE][SZ] Buffer too small: 0x%X\n", status); + } + } + else + { + status = STATUS_OBJECT_TYPE_MISMATCH; + DbgPrint_("[GET_STRING_VALUE][SZ] Registry value type mismatch: 0x%X\n", status); + } + + return status; +} + +NTSTATUS GetValue(const char* valueNameStr, ULONG* value) +{ + PKEY_VALUE_PARTIAL_INFORMATION kvpi; + ULONG resultLength; + NTSTATUS status = QueryRegistryValue(valueNameStr, &kvpi, &resultLength); + + if (!NT_SUCCESS(status)) + { + return status; + } + + if (kvpi->Type == REG_DWORD) + { + *value = *(ULONG*)(kvpi->Data); + } + else + { + status = STATUS_OBJECT_TYPE_MISMATCH; + DbgPrint_("[GET_VALUE][DWORD] Registry value type mismatch: 0x%X\n", status); + } + + return status; +} + +NTSTATUS GetValue(const char* valueNameStr, ULONGLONG* value) +{ + PKEY_VALUE_PARTIAL_INFORMATION kvpi; + ULONG resultLength; + NTSTATUS status = QueryRegistryValue(valueNameStr, &kvpi, &resultLength); + + if (!NT_SUCCESS(status)) + { + return status; + } + + if (kvpi->Type == REG_QWORD) + { + *value = *(ULONGLONG*)(kvpi->Data); + } + else + { + status = STATUS_OBJECT_TYPE_MISMATCH; + DbgPrint_("[GET_VALUE][QWORD] Registry value type mismatch: 0x%X\n", status); + } + + return status; +} + +NTSTATUS GetValue(const char* valueNameStr, PUCHAR value) +{ + PKEY_VALUE_PARTIAL_INFORMATION kvpi; + ULONG resultLength; + NTSTATUS status = QueryRegistryValue(valueNameStr, &kvpi, &resultLength); + + if (!NT_SUCCESS(status)) + { + return status; + } + + if (kvpi->Type == REG_BINARY) + { + RtlCopyMemory(value, kvpi->Data, kvpi->DataLength); + } + else + { + status = STATUS_OBJECT_TYPE_MISMATCH; + DbgPrint_("[GET_VALUE][BINARY] Registry value type mismatch or buffer too small: 0x%X\n", status); + } + + return status; +} + +NTSTATUS SetValue(const char* valueNameStr, PVOID buffer, ULONG bufferSize) +{ + UNICODE_STRING keyPath; + UNICODE_STRING valueName; + OBJECT_ATTRIBUTES objectAttributes; + HANDLE keyHandle; + NTSTATUS status; + + // Convert the ANSI string to a UNICODE string + valueName = CharToUnicode(valueNameStr); + RtlInitUnicodeString(&keyPath, L"\\Registry\\Machine\\SOFTWARE\\Revird"); + InitializeObjectAttributes(&objectAttributes, &keyPath, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL); + + // Open the registry key for writing + status = ZwOpenKey(&keyHandle, KEY_WRITE, &objectAttributes); + if (!NT_SUCCESS(status)) + { + DbgPrint_("[SetValue][BINARY] Failed to open registry key for writing: 0x%X\n", status); + RtlFreeUnicodeString(&valueName); + return status; + } + + // Write the buffer as a REG_BINARY value + status = ZwSetValueKey(keyHandle, &valueName, 0, REG_BINARY, buffer, bufferSize); + if (!NT_SUCCESS(status)) + { + DbgPrint_("[SetValue][BINARY] Failed to set binary value: 0x%X\n", status); + } + + // Clean up resources + ZwClose(keyHandle); + RtlFreeUnicodeString(&valueName); + + return status; +} + +NTSTATUS SetValue(const char* valueNameStr, ULONG value) +{ + UNICODE_STRING keyPath; + UNICODE_STRING valueName; + OBJECT_ATTRIBUTES objectAttributes; + HANDLE keyHandle; + NTSTATUS status; + + valueName = CharToUnicode(valueNameStr); + RtlInitUnicodeString(&keyPath, L"\\Registry\\Machine\\SOFTWARE\\Revird"); + InitializeObjectAttributes(&objectAttributes, &keyPath, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL); + + status = ZwOpenKey(&keyHandle, KEY_WRITE, &objectAttributes); + if (!NT_SUCCESS(status)) + { + DbgPrint_("[SET_VALUE][DWORD] Failed to open registry key for writing: 0x%X\n", status); + RtlFreeUnicodeString(&valueName); + return status; + } + + status = ZwSetValueKey(keyHandle, &valueName, 0, REG_DWORD, &value, sizeof(value)); + if (!NT_SUCCESS(status)) + { + DbgPrint_("[SET_VALUE][DWORD] Failed to set DWORD value: 0x%X\n", status); + } + + ZwClose(keyHandle); + RtlFreeUnicodeString(&valueName); + + return status; +} + +NTSTATUS SetValue(const char* valueNameStr, ULONGLONG value) +{ + UNICODE_STRING keyPath; + UNICODE_STRING valueName; + OBJECT_ATTRIBUTES objectAttributes; + HANDLE keyHandle; + NTSTATUS status; + + valueName = CharToUnicode(valueNameStr); + RtlInitUnicodeString(&keyPath, L"\\Registry\\Machine\\SOFTWARE\\Revird"); + InitializeObjectAttributes(&objectAttributes, &keyPath, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL); + + status = ZwOpenKey(&keyHandle, KEY_WRITE, &objectAttributes); + if (!NT_SUCCESS(status)) + { + DbgPrint_("[SET_VALUE][QWORD] Failed to open registry key for writing: 0x%X\n", status); + RtlFreeUnicodeString(&valueName); + return status; + } + + status = ZwSetValueKey(keyHandle, &valueName, 0, REG_QWORD, &value, sizeof(value)); + if (!NT_SUCCESS(status)) + { + DbgPrint_("[SET_VALUE][QWORD] Failed to set QWORD value: 0x%X\n", status); + } + + ZwClose(keyHandle); + RtlFreeUnicodeString(&valueName); + + return status; +} + +NTSTATUS SetValue(const char* valueNameStr, UCHAR value) +{ + UNICODE_STRING keyPath; + UNICODE_STRING valueName; + OBJECT_ATTRIBUTES objectAttributes; + HANDLE keyHandle; + NTSTATUS status; + + valueName = CharToUnicode(valueNameStr); + RtlInitUnicodeString(&keyPath, L"\\Registry\\Machine\\SOFTWARE\\Revird"); + InitializeObjectAttributes(&objectAttributes, &keyPath, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL); + + status = ZwOpenKey(&keyHandle, KEY_WRITE, &objectAttributes); + if (!NT_SUCCESS(status)) + { + DbgPrint_("[SET_VALUE][BINARY] Failed to open registry key for writing: 0x%X\n", status); + RtlFreeUnicodeString(&valueName); + return status; + } + + status = ZwSetValueKey(keyHandle, &valueName, 0, REG_BINARY, &value, sizeof(UCHAR)); + if (!NT_SUCCESS(status)) + { + DbgPrint_("[SET_VALUE][BINARY] Failed to set binary value: 0x%X\n", status); + } + + ZwClose(keyHandle); + RtlFreeUnicodeString(&valueName); + + return status; +} diff --git a/Revird/Registry.hpp b/Revird/Registry.hpp new file mode 100644 index 0000000..62974ea --- /dev/null +++ b/Revird/Registry.hpp @@ -0,0 +1,16 @@ +#pragma once +#include "Utils.hpp" + +NTSTATUS InitRegistry(); +NTSTATUS QueryRegistryValue(const char* valueNameStr, PKEY_VALUE_PARTIAL_INFORMATION* kvpi, ULONG* resultLength); + +NTSTATUS GetValue(const char* valueNameStr, PVOID buffer, ULONG bufferSize); +NTSTATUS GetValue(const char* valueNameStr, PWCHAR value, ULONG valueBufferSize); +NTSTATUS GetValue(const char* valueNameStr, ULONG* value); +NTSTATUS GetValue(const char* valueNameStr, ULONGLONG* value); +NTSTATUS GetValue(const char* valueNameStr, PUCHAR value); + +NTSTATUS SetValue(const char* valueNameStr, PVOID buffer, ULONG bufferSize); +NTSTATUS SetValue(const char* valueNameStr, ULONG value); +NTSTATUS SetValue(const char* valueNameStr, ULONGLONG value); +NTSTATUS SetValue(const char* valueNameStr, UCHAR value); diff --git a/Revird/Revird.vcxproj b/Revird/Revird.vcxproj new file mode 100644 index 0000000..765efe7 --- /dev/null +++ b/Revird/Revird.vcxproj @@ -0,0 +1,118 @@ + + + + + Debug + x64 + + + Release + x64 + + + Debug + ARM64 + + + Release + ARM64 + + + + {5C7B498C-CA04-413E-84E7-429F3986B41D} + {dd38f7fc-d7bd-488b-9242-7d8754cde80d} + v4.5 + 12.0 + Debug + x64 + Revird + + + + Windows10 + true + WindowsKernelModeDriver10.0 + Driver + WDM + + + Windows10 + false + WindowsKernelModeDriver10.0 + Driver + WDM + + + Windows10 + true + WindowsKernelModeDriver10.0 + Driver + WDM + + + Windows10 + false + WindowsKernelModeDriver10.0 + Driver + WDM + + + + + + + + + + + DbgengKernelDebugger + + + DbgengKernelDebugger + + + DbgengKernelDebugger + + + DbgengKernelDebugger + + + + sha256 + + + DriverEntry + + + + + sha256 + + + DriverEntry + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Revird/Revird.vcxproj.filters b/Revird/Revird.vcxproj.filters new file mode 100644 index 0000000..a160108 --- /dev/null +++ b/Revird/Revird.vcxproj.filters @@ -0,0 +1,64 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;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 + + + {8E41214B-6785-4CFE-B992-037D68949A14} + inf;inv;inx;mof;mc; + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + \ No newline at end of file diff --git a/Revird/Revird.vcxproj.user b/Revird/Revird.vcxproj.user new file mode 100644 index 0000000..c9c9b9b --- /dev/null +++ b/Revird/Revird.vcxproj.user @@ -0,0 +1,9 @@ + + + + Off + + + Off + + \ No newline at end of file diff --git a/Revird/Utils.cpp b/Revird/Utils.cpp new file mode 100644 index 0000000..5fc0584 --- /dev/null +++ b/Revird/Utils.cpp @@ -0,0 +1,10 @@ +#include "Utils.hpp" + +UNICODE_STRING CharToUnicode(const char* str) +{ + ANSI_STRING ansiString; + UNICODE_STRING unicodeString; + RtlInitAnsiString(&ansiString, str); + RtlAnsiStringToUnicodeString(&unicodeString, &ansiString, TRUE); + return unicodeString; +} \ No newline at end of file diff --git a/Revird/Utils.hpp b/Revird/Utils.hpp new file mode 100644 index 0000000..1515c43 --- /dev/null +++ b/Revird/Utils.hpp @@ -0,0 +1,4 @@ +#pragma once +#include + +UNICODE_STRING CharToUnicode(const char* str);