Created
November 23, 2018 18:02
-
-
Save tayler-king/3d6ca9cc94c541bfe5671bdfea168c18 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <ntdef.h> | |
#include <ntifs.h> | |
#include "Types.h" | |
PLOAD_IMAGE_NOTIFY_ROUTINE NotifyImageLoadCallback(PUNICODE_STRING FullImageName, HANDLE ProcessID, PIMAGE_INFO w_ImageInfo) | |
{ | |
if (wcsstr(FullImageName->Buffer, L"\\Win64\\TslGame.exe")) | |
{ | |
DbgPrintEx(0, 0, "\n[PUBG]: Hooked to %ls \n", FullImageName->Buffer); | |
DbgPrintEx(0, 0, "\n[PUBG]: Hooked Process: %d \n", ProcessID); | |
PUID = ProcessID; | |
PUBase = GetSectionBaseAddress(ProcessID); | |
} | |
} | |
NTKERNELAPI PVOID PsGetProcessSectionBaseAddress(__in PEPROCESS Process); | |
// routine to ignore the PE header and get the actual game base address | |
DWORD64 GetSectionBaseAddress(HANDLE w_pid) | |
{ | |
NTSTATUS ntStatus = STATUS_SUCCESS; | |
PEPROCESS targetProcess; | |
PVOID value = 0; | |
ntStatus = PsLookupProcessByProcessId((HANDLE)w_pid, &targetProcess); | |
if (ntStatus != STATUS_SUCCESS || !targetProcess) | |
return 0; | |
__try | |
{ | |
KeAttachProcess((PKPROCESS)targetProcess); | |
value = PsGetProcessSectionBaseAddress(targetProcess); | |
KeDetachProcess(); | |
} | |
__except (GetExceptionCode()) | |
{ | |
return 0; | |
} | |
return (DWORD64)value; | |
} | |
VOID Unload(PDRIVER_OBJECT DriverObject) { | |
PsRemoveLoadImageNotifyRoutine((PLOAD_IMAGE_NOTIFY_ROUTINE)NotifyImageLoadCallback); | |
UNICODE_STRING usDosDeviceName; | |
RtlInitUnicodeString(&usDosDeviceName, L"\\DosDevices\\PUBGMap"); | |
IoDeleteSymbolicLink(&usDosDeviceName); | |
IoDeleteDevice(DriverObject->DeviceObject); | |
} | |
NTSTATUS NTAPI MmCopyVirtualMemory ( | |
PEPROCESS SourceProcess, | |
PVOID SourceAddress, | |
PEPROCESS TargetProcess, | |
PVOID TargetAddress, | |
SIZE_T BufferSize, | |
KPROCESSOR_MODE PreviousMode, | |
PSIZE_T ReturnSize | |
); | |
NTSTATUS ReadMemOutputClient(pReadStruct w_poReadStruct) { | |
PEPROCESS hClient, hGame; | |
if (PUBase == 0 && w_poReadStruct->ProtocolMsg != PROTO_GET_BASEADDR) | |
return STATUS_UNSUCCESSFUL; | |
PsLookupProcessByProcessId(PUID, &hGame); | |
PsLookupProcessByProcessId((HANDLE)w_poReadStruct->UserPID, &hClient); | |
if (w_poReadStruct->ProtocolMsg == PROTO_GET_BASEADDR) { | |
SIZE_T Result; | |
if (NT_SUCCESS(MmCopyVirtualMemory(hGame, &PUBase, hClient, w_poReadStruct->UserBufferAdress, w_poReadStruct->ReadSize, KernelMode, &Result))) | |
return STATUS_SUCCESS; | |
else { | |
DbgPrint("\n[PUBG]: Failed to read base address\n"); | |
return STATUS_ACCESS_DENIED; | |
} | |
} | |
if (w_poReadStruct->ProtocolMsg == PROTO_NORMAL_READ) { | |
SIZE_T Result; | |
if (NT_SUCCESS(MmCopyVirtualMemory(hGame, w_poReadStruct->GameAddressOffset, hClient, w_poReadStruct->UserBufferAdress, w_poReadStruct->ReadSize, KernelMode, &Result))) | |
return STATUS_SUCCESS; | |
else { | |
DbgPrint("\n[PUBG]: Failed to read memory\n"); | |
DbgPrintEx(0, 0, "\n[PUBG]: GameAddressOffset %I64lx\n", w_poReadStruct->GameAddressOffset); | |
DbgPrintEx(0, 0, "\n[PUBG]: ReadSize %I64ld\n", w_poReadStruct->ReadSize); | |
return STATUS_ACCESS_DENIED; | |
} | |
} | |
return STATUS_SUCCESS; | |
} | |
// basic IOCTL communication routine | |
NTSTATUS WriteBufferedIO(PDEVICE_OBJECT DeviceObject, PIRP Irp) | |
{ | |
NTSTATUS NtStatus = STATUS_SUCCESS; | |
PIO_STACK_LOCATION pIoStackIrp = NULL; | |
pReadStruct readStruct; | |
pIoStackIrp = IoGetCurrentIrpStackLocation(Irp); | |
if (pIoStackIrp) | |
{ | |
// Read the struct from the IRP and store inside readStruct | |
readStruct = (pReadStruct)Irp->AssociatedIrp.SystemBuffer; | |
if (readStruct) | |
{ | |
// do the magic the client (um app) wants to | |
if (readStruct->ReadSize) | |
{ | |
ReadMemOutputClient(readStruct); | |
} | |
} | |
} | |
return NtStatus; | |
} | |
// dummy routine | |
NTSTATUS UnSupportedIrpFunction(PDEVICE_OBJECT DeviceObject, PIRP Irp) | |
{ | |
NTSTATUS NtStatus = STATUS_NOT_SUPPORTED; | |
DbgPrintEx(0, 0, "[PUBG]: Unsupported Irp Function \r\n"); | |
return NtStatus; | |
} | |
// driver entrypoint | |
NTSTATUS DriverEntry(_In_ PDRIVER_OBJECT pDriverObject, _In_ PUNICODE_STRING RegistryPath) | |
{ | |
DbgPrintEx(0, 0, "\n[PUBG]:"); | |
DbgPrintEx(0, 0, "\n[PUBG]: Driver Starting"); | |
PUBase = 0; | |
NTSTATUS status = STATUS_SUCCESS; | |
RtlInitUnicodeString(&dev, L"\\Device\\PUBGMap"); | |
RtlInitUnicodeString(&dos, L"\\DosDevices\\PUBGMap"); | |
status = IoCreateDevice(pDriverObject, 0, &dev, FILE_DEVICE_UNKNOWN, FILE_DEVICE_SECURE_OPEN, FALSE, &pDeviceObject); | |
if (status == STATUS_SUCCESS) | |
{ | |
for (UINT32 uiIndex = 0; uiIndex < IRP_MJ_MAXIMUM_FUNCTION; uiIndex++) | |
{ | |
pDriverObject->MajorFunction[uiIndex] = UnSupportedIrpFunction; | |
} | |
pDriverObject->MajorFunction[IRP_MJ_WRITE] = WriteBufferedIO; | |
pDriverObject->DriverUnload = Unload; | |
pDeviceObject->Flags |= DO_BUFFERED_IO; | |
pDeviceObject->Flags &= (~DO_DEVICE_INITIALIZING); | |
IoCreateSymbolicLink(&dos, &dev); | |
DbgPrintEx(0, 0, "\n[PUBG]: Driver Started Successfully"); | |
} | |
else | |
{ | |
return STATUS_UNSUCCESSFUL; | |
} | |
PsSetLoadImageNotifyRoutine(NotifyImageLoadCallback); | |
return STATUS_SUCCESS; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment