0% found this document useful (0 votes)
12 views5 pages

Fortnite Driver

The document outlines the implementation of a Fortnite IOCTL driver that facilitates device creation, physical memory read/write operations, CR3 decryption, and stack walk capture with validation. It defines various IOCTL codes for device control and includes structures for handling physical memory access and stack walk requests. The driver also ensures BSOD safety and includes functions for reading and writing physical memory, decrypting CR3 values, and capturing stack traces.

Uploaded by

Malek.Elkhatib
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
12 views5 pages

Fortnite Driver

The document outlines the implementation of a Fortnite IOCTL driver that facilitates device creation, physical memory read/write operations, CR3 decryption, and stack walk capture with validation. It defines various IOCTL codes for device control and includes structures for handling physical memory access and stack walk requests. The driver also ensures BSOD safety and includes functions for reading and writing physical memory, decrypting CR3 values, and capturing stack traces.

Uploaded by

Malek.Elkhatib
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
You are on page 1/ 5

// Fortnite IOCTL Driver - optimized for device creation, MMPTE CR3 decryption,

// physical memory read/write, stack walk capture with full validation, and BSOD
safety.

#include <ntddk.h>

#define DEVICE_NAME L"\\Device\\FortniteDevice"


#define SYMLINK_NAME L"\\DosDevices\\FortniteDevice"

// IOCTL codes
#define IOCTL_FORT_READ_PHYS CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, METHOD_BUFFERED,
FILE_ANY_ACCESS)
#define IOCTL_FORT_WRITE_PHYS CTL_CODE(FILE_DEVICE_UNKNOWN, 0x801, METHOD_BUFFERED,
FILE_ANY_ACCESS)
#define IOCTL_FORT_DECRYPT_CR3 CTL_CODE(FILE_DEVICE_UNKNOWN, 0x802,
METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_FORT_STACK_WALK CTL_CODE(FILE_DEVICE_UNKNOWN, 0x803, METHOD_BUFFERED,
FILE_ANY_ACCESS)

// Device extension
typedef struct _DEVICE_EXTENSION {
PDEVICE_OBJECT DeviceObject;
UNICODE_STRING SymLinkName;
} DEVICE_EXTENSION, *PDEVICE_EXTENSION;

// Physical memory access structure


typedef struct _PHYS_MEM_ACCESS {
ULONG64 PhysicalAddress;
ULONG Size;
UCHAR Data[1];
} PHYS_MEM_ACCESS, *PPHYS_MEM_ACCESS;

// Stack walk capture input structure


typedef struct _STACK_WALK_REQUEST {
ULONG64 ThreadId;
ULONG MaxFrames;
} STACK_WALK_REQUEST, *PSTACK_WALK_REQUEST;

// Stack walk capture output structure


typedef struct _STACK_WALK_RESULT {
ULONG FrameCount;
ULONG64 Frames[64];
} STACK_WALK_RESULT, *PSTACK_WALK_RESULT;

// Forward declarations
DRIVER_INITIALIZE DriverEntry;
DRIVER_UNLOAD DriverUnload;
_Dispatch_type_(IRP_MJ_CREATE) DRIVER_DISPATCH DispatchCreate;
_Dispatch_type_(IRP_MJ_CLOSE) DRIVER_DISPATCH DispatchClose;
_Dispatch_type_(IRP_MJ_DEVICE_CONTROL) DRIVER_DISPATCH DispatchDeviceControl;

// Helper functions
NTSTATUS ReadPhysicalMemory(ULONG64 physAddr, PVOID buffer, ULONG size);
NTSTATUS WritePhysicalMemory(ULONG64 physAddr, PVOID buffer, ULONG size);
ULONG64 DecryptCR3(ULONG64 encryptedCr3);
NTSTATUS CaptureStackWalk(ULONG64 threadId, ULONG maxFrames, PSTACK_WALK_RESULT
result);

// DriverEntry - create device and symlink, setup dispatch


NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath) {
UNREFERENCED_PARAMETER(RegistryPath);
NTSTATUS status;
PDEVICE_OBJECT deviceObject = NULL;
UNICODE_STRING deviceName = RTL_CONSTANT_STRING(DEVICE_NAME);
UNICODE_STRING symLinkName = RTL_CONSTANT_STRING(SYMLINK_NAME);

status = IoCreateDevice(DriverObject, sizeof(DEVICE_EXTENSION), &deviceName,


FILE_DEVICE_UNKNOWN, 0, FALSE, &deviceObject);
if (!NT_SUCCESS(status)) {
return status;
}

status = IoCreateSymbolicLink(&symLinkName, &deviceName);


if (!NT_SUCCESS(status)) {
IoDeleteDevice(deviceObject);
return status;
}

PDEVICE_EXTENSION devExt = (PDEVICE_EXTENSION)deviceObject->DeviceExtension;


devExt->DeviceObject = deviceObject;
devExt->SymLinkName = symLinkName;

DriverObject->MajorFunction[IRP_MJ_CREATE] = DispatchCreate;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = DispatchClose;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchDeviceControl;
DriverObject->DriverUnload = DriverUnload;

deviceObject->Flags |= DO_BUFFERED_IO;
deviceObject->Flags &= ~DO_DEVICE_INITIALIZING;

return STATUS_SUCCESS;
}

void DriverUnload(PDRIVER_OBJECT DriverObject) {


PDEVICE_OBJECT deviceObject = DriverObject->DeviceObject;
if (deviceObject) {
PDEVICE_EXTENSION devExt = (PDEVICE_EXTENSION)deviceObject-
>DeviceExtension;
IoDeleteSymbolicLink(&devExt->SymLinkName);
IoDeleteDevice(deviceObject);
}
}

NTSTATUS DispatchCreate(PDEVICE_OBJECT DeviceObject, PIRP Irp) {


UNREFERENCED_PARAMETER(DeviceObject);
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}

NTSTATUS DispatchClose(PDEVICE_OBJECT DeviceObject, PIRP Irp) {


UNREFERENCED_PARAMETER(DeviceObject);
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
ULONG64 DecryptCR3(ULONG64 encryptedCr3) {
// Custom decryption logic - example XOR pattern for Fortnite
return encryptedCr3 ^ 0xA5A5A5A5A5A5A5A5ULL;
}

NTSTATUS ReadPhysicalMemory(ULONG64 physAddr, PVOID buffer, ULONG size) {


PHYSICAL_ADDRESS physAddrStruct;
physAddrStruct.QuadPart = physAddr;

PVOID mappedAddr = MmMapIoSpace(physAddrStruct, size, MmNonCached);


if (!mappedAddr) return STATUS_INSUFFICIENT_RESOURCES;

__try {
RtlCopyMemory(buffer, mappedAddr, size);
}
__except (EXCEPTION_EXECUTE_HANDLER) {
MmUnmapIoSpace(mappedAddr, size);
return STATUS_ACCESS_VIOLATION;
}

MmUnmapIoSpace(mappedAddr, size);
return STATUS_SUCCESS;
}

NTSTATUS WritePhysicalMemory(ULONG64 physAddr, PVOID buffer, ULONG size) {


PHYSICAL_ADDRESS physAddrStruct;
physAddrStruct.QuadPart = physAddr;

PVOID mappedAddr = MmMapIoSpace(physAddrStruct, size, MmNonCached);


if (!mappedAddr) return STATUS_INSUFFICIENT_RESOURCES;

__try {
RtlCopyMemory(mappedAddr, buffer, size);
}
__except (EXCEPTION_EXECUTE_HANDLER) {
MmUnmapIoSpace(mappedAddr, size);
return STATUS_ACCESS_VIOLATION;
}

MmUnmapIoSpace(mappedAddr, size);
return STATUS_SUCCESS;
}

// Stack walk capture implementation with full recheck


NTSTATUS CaptureStackWalk(ULONG64 threadId, ULONG maxFrames, PSTACK_WALK_RESULT
result) {
if (!result || maxFrames > 64) return STATUS_INVALID_PARAMETER;

PETHREAD thread;
NTSTATUS status = PsLookupThreadByThreadId((HANDLE)threadId, &thread);
if (!NT_SUCCESS(status)) return status;

CONTEXT context = { 0 };
context.ContextFlags = CONTEXT_FULL;

status = ZwGetContextThread(thread, &context);


if (!NT_SUCCESS(status)) {
ObDereferenceObject(thread);
return status;
}

ULONG frameCount = 0;
ULONG64* frames = result->Frames;

__try {
ULONG64 framePointer = context.Rbp;
while (frameCount < maxFrames && framePointer) {
ULONG64 returnAddress = *((ULONG64*)(framePointer + 8));
if (!MmIsAddressValid((PVOID)returnAddress)) break;
frames[frameCount++] = returnAddress;

ULONG64 nextFramePointer = *((ULONG64*)framePointer);


if (nextFramePointer <= framePointer) break; // prevent infinite loops
framePointer = nextFramePointer;
}
}
__except (EXCEPTION_EXECUTE_HANDLER) {
ObDereferenceObject(thread);
return STATUS_ACCESS_VIOLATION;
}

ObDereferenceObject(thread);

result->FrameCount = frameCount;
return STATUS_SUCCESS;
}

// Device control dispatch


NTSTATUS DispatchDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp) {
UNREFERENCED_PARAMETER(DeviceObject);

PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation(Irp);


NTSTATUS status = STATUS_INVALID_DEVICE_REQUEST;
ULONG_PTR info = 0;

switch (irpSp->Parameters.DeviceIoControl.IoControlCode) {
case IOCTL_FORT_READ_PHYS: {
if (irpSp->Parameters.DeviceIoControl.InputBufferLength <
sizeof(PHYS_MEM_ACCESS) ||
irpSp->Parameters.DeviceIoControl.OutputBufferLength <
sizeof(PHYS_MEM_ACCESS)) {
status = STATUS_BUFFER_TOO_SMALL;
break;
}
PPHYS_MEM_ACCESS access = (PPHYS_MEM_ACCESS)Irp-
>AssociatedIrp.SystemBuffer;
status = ReadPhysicalMemory(access->PhysicalAddress, access->Data,
access->Size);
if (NT_SUCCESS(status)) {
info = sizeof(PHYS_MEM_ACCESS) + access->Size - 1;
}
break;
}
case IOCTL_FORT_WRITE_PHYS: {
if (irpSp->Parameters.DeviceIoControl.InputBufferLength <
sizeof(PHYS_MEM_ACCESS)) {
status = STATUS_BUFFER_TOO_SMALL;
break;
}
PPHYS_MEM_ACCESS access = (PPHYS_MEM_ACCESS)Irp-
>AssociatedIrp.SystemBuffer;
status = WritePhysicalMemory(access->PhysicalAddress, access->Data,
access->Size);
if (NT_SUCCESS(status)) {
info = 0;
}
break;
}
case IOCTL_FORT_DECRYPT_CR3: {
if (irpSp->Parameters.DeviceIoControl.InputBufferLength <
sizeof(ULONG64) ||
irpSp->Parameters.DeviceIoControl.OutputBufferLength <
sizeof(ULONG64)) {
status = STATUS_BUFFER_TOO_SMALL;
break;
}
ULONG64* encryptedCr3 = (ULONG64*)Irp->AssociatedIrp.SystemBuffer;
ULONG64 decryptedCr3 = DecryptCR3(*encryptedCr3);
*((ULONG64*)Irp->AssociatedIrp.SystemBuffer) = decryptedCr3;
info = sizeof(ULONG64);
status = STATUS_SUCCESS;
break;
}
case IOCTL_FORT_STACK_WALK: {
if (irpSp->Parameters.DeviceIoControl.InputBufferLength <
sizeof(STACK_WALK_REQUEST) ||
irpSp->Parameters.DeviceIoControl.OutputBufferLength <
sizeof(STACK_WALK_RESULT)) {
status = STATUS_BUFFER_TOO_SMALL;
break;
}
PSTACK_WALK_REQUEST req = (PSTACK_WALK_REQUEST)Irp-
>AssociatedIrp.SystemBuffer;
PSTACK_WALK_RESULT res = (PSTACK_WALK_RESULT)Irp->UserBuffer;
status = CaptureStackWalk(req->ThreadId, req->MaxFrames, res);
if (NT_SUCCESS(status)) {
info = sizeof(STACK_WALK_RESULT);
}
break;
}
default:
status = STATUS_INVALID_DEVICE_REQUEST;
break;
}

Irp->IoStatus.Status = status;
Irp->IoStatus.Information = info;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return status;
}

You might also like