前两年在b站出过几期作弊原理视频,本以为会引起反作弊改革,无奈现在流行摆烂,现放出源码,源码原作者为Zer0Mem0ry所创,因测试需求,经过本人的调整,已支持对人物坐标数组的读取,实现完美重写R/Wpm
#define IO_READ_REQUEST CTL_CODE(FILE_DEVICE_UNKNOWN, 0x0701 /* Our Custom Code */, METHOD_BUFFERED, FILE_SPECIAL_ACCESS)
#define IO_WRITE_REQUEST CTL_CODE(FILE_DEVICE_UNKNOWN, 0x0702 /* Our Custom Code */, METHOD_BUFFERED, FILE_SPECIAL_ACCESS)
#define IO_GET_ID_REQUEST CTL_CODE(FILE_DEVICE_UNKNOWN, 0x0703 /* Our Custom Code */, METHOD_BUFFERED, FILE_SPECIAL_ACCESS)
#define IO_GET_MODULE_REQUEST CTL_CODE(FILE_DEVICE_UNKNOWN, 0x0704 /* Our Custom Code */, METHOD_BUFFERED, FILE_SPECIAL_ACCESS)
#define IO_GET_MODULE_REQUEST2 CTL_CODE(FILE_DEVICE_UNKNOWN, 0x0705 /* Our Custom Code */, METHOD_BUFFERED, FILE_SPECIAL_ACCESS)
#define DIRECTORY_TABLE_BASE 0x028
#pragma intrinsic(_disable)
#pragma intrinsic(_enable)
PDEVICE_OBJECT pDeviceObject;
UNICODE_STRING dev, dos;
ULONG csgoId, ClientAddress, EngineAddress;
typedef struct _KERNEL_READ_REQUEST
{
ULONG ProcessId;
ULONG Address;
PVOID pBuff;
ULONG Size;
} KERNEL_READ_REQUEST, * PKERNEL_READ_REQUEST;
typedef struct _KERNEL_WRITE_REQUEST
{
ULONG ProcessId;
ULONG Address;
PVOID pBuff;
ULONG Size;
} KERNEL_WRITE_REQUEST, * PKERNEL_WRITE_REQUEST;
NTSTATUS UnloadDriver(PDRIVER_OBJECT pDriverObject);
NTSTATUS CreateCall(PDEVICE_OBJECT DeviceObject, PIRP irp);
NTSTATUS CloseCall(PDEVICE_OBJECT DeviceObject, PIRP irp);
NTSTATUS KeReadVirtualMemory(PEPROCESS Process, PVOID SourceAddress, PVOID TargetAddress, SIZE_T Size)
{
SIZE_T Bytes;
if (NT_SUCCESS(MmCopyVirtualMemory(Process, SourceAddress, PsGetCurrentProcess(),
TargetAddress, Size, KernelMode, &Bytes)))
{
return STATUS_SUCCESS;
}
return STATUS_ACCESS_DENIED;
}
ULONG64 CheckAddressVal(PVOID p)
{
if (MmIsAddressValid(p) == FALSE)
return 0;
return *(PULONG64)p;
}
BOOLEAN CR3_ReadProcessMemory(IN PEPROCESS Process, IN PVOID Address, OUT PVOID Buffer)
{
ULONG64 pDTB = 0, OldCr3 = 0, vAddr = 0;
pDTB = CheckAddressVal((UCHAR*)Process + DIRECTORY_TABLE_BASE);
if (pDTB == 0)
{
return FALSE;
}
_disable();
OldCr3 = __readcr3();
__writecr3(pDTB);
_enable();
if (MmIsAddressValid(Address))
{
RtlCopyMemory(Buffer, Address, 16);
DbgPrint("读取数据: %ld", *(PDWORD)Buffer);
return TRUE;
}
_disable();
__writecr3(OldCr3);
_enable();
return FALSE;
}
NTSTATUS KeWriteVirtualMemory(PEPROCESS Process, PVOID SourceAddress, PVOID TargetAddress, SIZE_T Size)
{
SIZE_T Bytes;
if (NT_SUCCESS(MmCopyVirtualMemory(PsGetCurrentProcess(), SourceAddress, Process,
TargetAddress, Size, KernelMode, &Bytes)))
{
return STATUS_SUCCESS;
}
return STATUS_ACCESS_DENIED;
}
PLOAD_IMAGE_NOTIFY_ROUTINE ImageLoadCallback(PUNICODE_STRING FullImageName,
HANDLE ProcessId, PIMAGE_INFO ImageInfo)
{
if (wcsstr(FullImageName->Buffer, L"\\csgo\\bin\\client.dll")) {
DbgPrintEx(0, 0, "ClientAddressLoaded Name: %ls \n", FullImageName->Buffer);
DbgPrintEx(0, 0, "Loaded To Process: %d \n", ProcessId);
ClientAddress = ImageInfo->ImageBase;
csgoId = ProcessId;
}
else if (wcsstr(FullImageName->Buffer, L"\\Counter-Strike Global Offensive\\bin\\engine.dll")) {
DbgPrintEx(0, 0, "EngineAddressLoaded Name: %ls \n", FullImageName->Buffer);
DbgPrintEx(0, 0, "Loaded To Process: %d \n", ProcessId);
EngineAddress = ImageInfo->ImageBase;
}
}
NTSTATUS IoControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
NTSTATUS Status;
ULONG BytesIO = 0;
PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);
ULONG ControlCode = stack->Parameters.DeviceIoControl.IoControlCode;
if (ControlCode == IO_READ_REQUEST)
{
PKERNEL_READ_REQUEST ReadInput = (PKERNEL_READ_REQUEST)Irp->AssociatedIrp.SystemBuffer;
PKERNEL_READ_REQUEST ReadOutput = (PKERNEL_READ_REQUEST)Irp->AssociatedIrp.SystemBuffer;
PEPROCESS Process;
if (NT_SUCCESS(PsLookupProcessByProcessId(ReadInput->ProcessId, &Process))) {
KeReadVirtualMemory(Process, ReadInput->Address, ReadInput->pBuff, ReadInput->Size);
}
Status = STATUS_SUCCESS;
BytesIO = sizeof(KERNEL_READ_REQUEST);
}
else if (ControlCode == IO_WRITE_REQUEST)
{
/*
PKERNEL_WRITE_REQUEST WriteInput = (PKERNEL_WRITE_REQUEST)Irp->AssociatedIrp.SystemBuffer;
PEPROCESS Process;
if (NT_SUCCESS(PsLookupProcessByProcessId(WriteInput->ProcessId, &Process)))
KeWriteVirtualMemory(Process, &WriteInput->Value,
WriteInput->Address, WriteInput->Size);
DbgPrintEx(0, 0, "Write Params: %lu, %#010x \n", WriteInput->Value, WriteInput->Address);
PKERNEL_WRITE_REQUEST WriteInput = (PKERNEL_WRITE_REQUEST)Irp->AssociatedIrp.SystemBuffer;
PEPROCESS Process;
if (NT_SUCCESS(PsLookupProcessByProcessId(WriteInput->ProcessId, &Process))) {
KeWriteVirtualMemory(Process, WriteInput->pBuff, WriteInput->Address, WriteInput->Size);
}*/
Status = STATUS_SUCCESS;
BytesIO = sizeof(KERNEL_WRITE_REQUEST);
}
else if (ControlCode == IO_GET_ID_REQUEST)
{
PULONG OutPut = (PULONG)Irp->AssociatedIrp.SystemBuffer;
*OutPut = csgoId;
DbgPrintEx(0, 0, "id get %#010x", csgoId);
Status = STATUS_SUCCESS;
BytesIO = sizeof(*OutPut);
}
else if (ControlCode == IO_GET_MODULE_REQUEST)
{
PULONG OutPut = (PULONG)Irp->AssociatedIrp.SystemBuffer;
*OutPut = ClientAddress;
DbgPrintEx(0, 0, "ClientModule get %#010x", ClientAddress);
Status = STATUS_SUCCESS;
BytesIO = sizeof(*OutPut);
}
else if (ControlCode == IO_GET_MODULE_REQUEST2)
{
PULONG OutPut = (PULONG)Irp->AssociatedIrp.SystemBuffer;
*OutPut = EngineAddress;
DbgPrintEx(0, 0, "EngineModule get %#010x", EngineAddress);
Status = STATUS_SUCCESS;
BytesIO = sizeof(*OutPut);
}
else
{
Status = STATUS_INVALID_PARAMETER;
BytesIO = 0;
}
Irp->IoStatus.Status = Status;
Irp->IoStatus.Information = BytesIO;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Status;
}
VOID HideDriver(PDRIVER_OBJECT pDriverObject)
{
KIRQL irql = KeRaiseIrqlToDpcLevel();
PLDR_DATA_TABLE_ENTRY prevEntry, nextEntry, modEntry;
modEntry = (PLDR_DATA_TABLE_ENTRY)pDriverObject->DriverSection;
prevEntry = (PLDR_DATA_TABLE_ENTRY)modEntry->InLoadOrderLinks.Blink;
nextEntry = (PLDR_DATA_TABLE_ENTRY)modEntry->InLoadOrderLinks.Flink;
prevEntry->InLoadOrderLinks.Flink = modEntry->InLoadOrderLinks.Flink;
nextEntry->InLoadOrderLinks.Blink = modEntry->InLoadOrderLinks.Blink;
modEntry->InLoadOrderLinks.Flink = (PLIST_ENTRY)modEntry;
modEntry->InLoadOrderLinks.Blink = (PLIST_ENTRY)modEntry;
KeLowerIrql(irql);
}
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject,PUNICODE_STRING pRegistryPath)
{
DbgPrintEx(0, 0, "Driver Loaded改\n");
PsSetLoadImageNotifyRoutine(ImageLoadCallback);
RtlInitUnicodeString(&dev, L"\\Device\\kernelhop");
RtlInitUnicodeString(&dos, L"\\DosDevices\\kernelhop");
IoCreateDevice(pDriverObject, 0, &dev, FILE_DEVICE_UNKNOWN, FILE_DEVICE_SECURE_OPEN, FALSE, &pDeviceObject);
IoCreateSymbolicLink(&dos, &dev);
pDriverObject->MajorFunction[IRP_MJ_CREATE] = CreateCall;
pDriverObject->MajorFunction[IRP_MJ_CLOSE] = CloseCall;
pDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = IoControl;
pDriverObject->DriverUnload = UnloadDriver;
pDeviceObject->Flags |= DO_DIRECT_IO;
pDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
return STATUS_SUCCESS;
}
NTSTATUS UnloadDriver(PDRIVER_OBJECT pDriverObject)
{
DbgPrintEx(0, 0, "Unload routine called.\n");
PsRemoveLoadImageNotifyRoutine(ImageLoadCallback);
IoDeleteSymbolicLink(&dos);
IoDeleteDevice(pDriverObject->DeviceObject);
}
NTSTATUS CreateCall(PDEVICE_OBJECT DeviceObject, PIRP irp)
{
irp->IoStatus.Status = STATUS_SUCCESS;
irp->IoStatus.Information = 0;
IoCompleteRequest(irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
NTSTATUS CloseCall(PDEVICE_OBJECT DeviceObject, PIRP irp)
{
irp->IoStatus.Status = STATUS_SUCCESS;
irp->IoStatus.Information = 0;
IoCompleteRequest(irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
3环接口
#include <Windows.h>
/*
/* 驱动需要IOCTL代码 */
//定义一个值为0x800的控制码
// 从内核空间读取虚拟用户内存(程序内存)的请求
#define IO_READ_REQUEST CTL_CODE(FILE_DEVICE_UNKNOWN, 0x0701 , METHOD_BUFFERED, FILE_SPECIAL_ACCESS)
//从内核空间写入虚拟用户内存(程序内存)的请求
#define IO_WRITE_REQUEST CTL_CODE(FILE_DEVICE_UNKNOWN, 0x0702 , METHOD_BUFFERED, FILE_SPECIAL_ACCESS)
// 请求从内核空间检索csgo进程的进程id
#define IO_GET_ID_REQUEST CTL_CODE(FILE_DEVICE_UNKNOWN, 0x0703 , METHOD_BUFFERED, FILE_SPECIAL_ACCESS)
// 请求从内核空间检索csgo.exe中client.dll的基址
#define IO_GET_MODULE_REQUEST CTL_CODE(FILE_DEVICE_UNKNOWN, 0x0704 , METHOD_BUFFERED, FILE_SPECIAL_ACCESS)
#define IO_GET_MODULE_REQUEST2 CTL_CODE(FILE_DEVICE_UNKNOWN, 0x0705 , METHOD_BUFFERED, FILE_SPECIAL_ACCESS)
typedef struct _KERNEL_READ_REQUEST
{
ULONG ProcessId;
ULONG Address;
PVOID pBuff;
ULONG Size;
} KERNEL_READ_REQUEST, * PKERNEL_READ_REQUEST;
typedef struct _KERNEL_WRITE_REQUEST
{
ULONG ProcessId;
ULONG Address;
PVOID pBuff;
ULONG Size;
} KERNEL_WRITE_REQUEST, * PKERNEL_WRITE_REQUEST;
//驱动程序接口类
class KeInterface
{
public:
HANDLE hDriver; // 驱动句柄
//初始值设定项
KeInterface(LPCSTR RegistryPath)
{
hDriver = CreateFileA(RegistryPath, GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);
}
template <typename type>
type ReadVirtualMemory(ULONG ProcessId, ULONG ReadAddress, SIZE_T Size)
{
type Buffer;
DWORD Return, Bytes;
KERNEL_READ_REQUEST ReadRequest;
ReadRequest.ProcessId = ProcessId;
ReadRequest.Address = ReadAddress;
ReadRequest.pBuff = &Buffer;
ReadRequest.Size = Size;
if (DeviceIoControl(hDriver, IO_READ_REQUEST, &ReadRequest, sizeof(ReadRequest), &ReadRequest, sizeof(ReadRequest), 0, 0))
{
return Buffer;
}
return Buffer;
}
template <typename type>
bool WriteVirtualMemory(ULONG ProcessId, ULONG WriteAddress, type WriteValue, SIZE_T WriteSize)
{
if (hDriver == INVALID_HANDLE_VALUE)
return false;
DWORD Bytes;
KERNEL_WRITE_REQUEST WriteRequest;
WriteRequest.ProcessId = ProcessId;
WriteRequest.Address = WriteAddress;
WriteRequest.pBuff = &WriteValue;
WriteRequest.Size = WriteSize;
if (DeviceIoControl(hDriver, IO_WRITE_REQUEST, &WriteRequest, sizeof(WriteRequest), 0, 0, &Bytes, NULL))
{
return true;
}
return false;
}
DWORD GetTargetPid()
{
if (hDriver == INVALID_HANDLE_VALUE)
return false;
ULONG Id;
DWORD Bytes;
if (DeviceIoControl(hDriver, IO_GET_ID_REQUEST, &Id, sizeof(Id),
&Id, sizeof(Id), &Bytes, NULL))
return Id;
else
return false;
}
DWORD GetClientModule()
{
if (hDriver == INVALID_HANDLE_VALUE)
return false;
ULONG Address;
DWORD Bytes;
if (DeviceIoControl(hDriver, IO_GET_MODULE_REQUEST, &Address, sizeof(Address),
&Address, sizeof(Address), &Bytes, NULL))
return Address;
else
return false;
}
DWORD GetEngineModule()
{
if (hDriver == INVALID_HANDLE_VALUE)
return false;
ULONG Address;
DWORD Bytes;
if (DeviceIoControl(hDriver, IO_GET_MODULE_REQUEST2, &Address, sizeof(Address),
&Address, sizeof(Address), &Bytes, NULL))
return Address;
else
return false;
}
};
demo
采用“只读”方式可避免逻辑验证,对敏感数组可用指针方式读取(类杀毒软件扫描)
得到数据=Driver.ReadVirtualMemory<类型>(进程id, 模块基址 + 偏移, sizeof(类型));