feat: initial commit of the files

This commit is contained in:
2024-11-06 17:05:11 +01:00
commit ddeb2faa21
26 changed files with 1769 additions and 0 deletions

65
Revird/Dispatcher.cpp Normal file
View File

@@ -0,0 +1,65 @@
#include "Dispatcher.hpp"
#include "Registry.hpp"
#include "Operation.hpp"
#include "Memory.hpp"
#include "Process.hpp"
#include "Output.hpp"
#include <ntifs.h>
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;
}

3
Revird/Dispatcher.hpp Normal file
View File

@@ -0,0 +1,3 @@
#pragma once
void DispatchOperation(void);

63
Revird/Entry.cpp Normal file
View File

@@ -0,0 +1,63 @@
#include <ntifs.h>
#include <wdm.h>
#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;
}

121
Revird/Memory.cpp Normal file
View File

@@ -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);
}

12
Revird/Memory.hpp Normal file
View File

@@ -0,0 +1,12 @@
#pragma once
#include <ntifs.h>
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);

8
Revird/Operation.hpp Normal file
View File

@@ -0,0 +1,8 @@
#pragma once
enum Operation {
OPERATION_WPM,
OPERATION_RPM,
OPERATION_GET_PROCESS,
OPERATION_GET_PROCESS_MODULE
};

7
Revird/Output.hpp Normal file
View File

@@ -0,0 +1,7 @@
#pragma once
#ifdef _DEBUG
#define DbgPrint_(msg, ...) DbgPrint(msg, __VA_ARGS__)
#else
#define DbgPrint_(msg, ...) (void)0
#endif

172
Revird/Process.cpp Normal file
View File

@@ -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);
}

158
Revird/Process.hpp Normal file
View File

@@ -0,0 +1,158 @@
#pragma once
#include <ntifs.h>
#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);

425
Revird/Registry.cpp Normal file
View File

@@ -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;
}

16
Revird/Registry.hpp Normal file
View File

@@ -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);

118
Revird/Revird.vcxproj Normal file
View File

@@ -0,0 +1,118 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|ARM64">
<Configuration>Debug</Configuration>
<Platform>ARM64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|ARM64">
<Configuration>Release</Configuration>
<Platform>ARM64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{5C7B498C-CA04-413E-84E7-429F3986B41D}</ProjectGuid>
<TemplateGuid>{dd38f7fc-d7bd-488b-9242-7d8754cde80d}</TemplateGuid>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<MinimumVisualStudioVersion>12.0</MinimumVisualStudioVersion>
<Configuration>Debug</Configuration>
<Platform Condition="'$(Platform)' == ''">x64</Platform>
<RootNamespace>Revird</RootNamespace>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<TargetVersion>Windows10</TargetVersion>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
<ConfigurationType>Driver</ConfigurationType>
<DriverType>WDM</DriverType>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<TargetVersion>Windows10</TargetVersion>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
<ConfigurationType>Driver</ConfigurationType>
<DriverType>WDM</DriverType>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="Configuration">
<TargetVersion>Windows10</TargetVersion>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
<ConfigurationType>Driver</ConfigurationType>
<DriverType>WDM</DriverType>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="Configuration">
<TargetVersion>Windows10</TargetVersion>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
<ConfigurationType>Driver</ConfigurationType>
<DriverType>WDM</DriverType>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
<DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
<DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<DriverSign>
<FileDigestAlgorithm>sha256</FileDigestAlgorithm>
</DriverSign>
<Link>
<EntryPointSymbol>DriverEntry</EntryPointSymbol>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<DriverSign>
<FileDigestAlgorithm>sha256</FileDigestAlgorithm>
</DriverSign>
<Link>
<EntryPointSymbol>DriverEntry</EntryPointSymbol>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<FilesToPackage Include="$(TargetPath)" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="Dispatcher.cpp" />
<ClCompile Include="Entry.cpp" />
<ClCompile Include="Memory.cpp" />
<ClCompile Include="Process.cpp" />
<ClCompile Include="Registry.cpp" />
<ClCompile Include="Utils.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="Dispatcher.hpp" />
<ClInclude Include="Memory.hpp" />
<ClInclude Include="Operation.hpp" />
<ClInclude Include="Output.hpp" />
<ClInclude Include="Process.hpp" />
<ClInclude Include="Registry.hpp" />
<ClInclude Include="Utils.hpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@@ -0,0 +1,64 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
<Filter Include="Driver Files">
<UniqueIdentifier>{8E41214B-6785-4CFE-B992-037D68949A14}</UniqueIdentifier>
<Extensions>inf;inv;inx;mof;mc;</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="Entry.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Registry.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Utils.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Memory.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Process.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Dispatcher.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="Registry.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Utils.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Memory.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Operation.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Process.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Dispatcher.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Output.hpp">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project>

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<SignMode>Off</SignMode>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<SignMode>Off</SignMode>
</PropertyGroup>
</Project>

10
Revird/Utils.cpp Normal file
View File

@@ -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;
}

4
Revird/Utils.hpp Normal file
View File

@@ -0,0 +1,4 @@
#pragma once
#include <ntifs.h>
UNICODE_STRING CharToUnicode(const char* str);