编辑: 人间点评 | 2019-07-11 |
过DNF主要分为三步,也许我的思路不太正确,反正可以OD调试,下断. 程序没怎么修边幅,因为只是测试,所以一般都没有写更改内核后的恢复,不过不妨碍使用. 第一步,这也是最起码的,你必须要能够打开游戏进程和线程,能够开打进程和线程后不被检测到 第二步,能够读写进村内存 第三步,能够用OD附加游戏进程 第四步,能够下硬件断点而不被检测 跳过NtReadVirtualMemory,NtWriteVirtualMemory函数头的钩子 代码: #include typedef struct _SERVICE_DESCRIPTOR_TABLE { PVOID ServiceTableBase;
PULONG ServiceCounterTableBase;
ULONG NumberOfService;
ULONG ParamTableBase;
}SERVICE_DESCRIPTOR_TABLE,*PSERVICE_DESCRIPTOR_TABLE;
//由于KeServiceDescriptorTable只有一项,这里就简单点了 extern PSERVICE_DESCRIPTOR_TABLE KeServiceDescriptorTable;
//KeServiceDescriptorTable为导出函数 VOID Hook();
VOID Unhook();
VOID OnUnload(IN PDRIVER_OBJECT DriverObject);
ULONG JmpAddress;
//跳转到NtOpenProcess里的地址 ULONG JmpAddress1;
//跳转到NtOpenProcess里的地址 ULONG OldServiceAddress;
//原来NtOpenProcess的服务地址 ULONG OldServiceAddress1;
//原来NtOpenProcess的服务地址 __declspec(naked) NTSTATUS __stdcall MyNtReadVirtualMemory(HANDLE ProcessHandle, PVOID BaseAddress, PVOID Buffer, ULONG NumberOfBytesToRead, PULONG NumberOfBytesReaded) { //跳过去 __asm { push 0x1c push 804eb560h //共十个字节 jmp [JmpAddress] } } __declspec(naked) NTSTATUS __stdcall MyNtWriteVirtualMemory(HANDLE ProcessHandle, PVOID BaseAddress, PVOID Buffer, ULONG NumberOfBytesToWrite, PULONG NumberOfBytesReaded) { //跳过去 __asm { push 0x1c push 804eb560h //共十个字节 jmp [JmpAddress1] } } NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject,PUNICODE_STRING RegistryPath) { DriverObject->
DriverUnload = OnUnload;
DbgPrint( Unhooker load );
Hook();
return STATUS_SUCCESS;
} VOID OnUnload(IN PDRIVER_OBJECT DriverObject) { DbgPrint( Unhooker unload! );
Unhook();
} VOID Hook() { ULONG Address, Address1;
Address = (ULONG)KeServiceDescriptorTable->
ServiceTableBase + 0xBA * 4;
//0x7A为NtOpenProcess服务ID Address1 = (ULONG)KeServiceDescriptorTable->
ServiceTableBase + 0x115 * 4;
//0x7A为NtOpenProcess服务ID DbgPrint( Address:0x%08X ,Address);
OldServiceAddress = *(ULONG*)Address;
//保存原来NtOpenProcess的地址 OldServiceAddress1 = *(ULONG*)Address1;
//保存原来NtOpenProcess的地址 DbgPrint( OldServiceAddress:0x%08X ,OldServiceAddress);
DbgPrint( OldServiceAddress1:0x%08X ,OldServiceAddress1);
DbgPrint( MyNtOpenProcess:0x%08X ,MyNtReadVirtualMemory);
DbgPrint( MyNtOpenProcess:0x%08X ,MyNtWriteVirtualMemory);
JmpAddress = (ULONG)0x805b528a + 7;
//跳转到NtOpenProcess函数头+10的地方,这样在其前面写的JMP都失效了 JmpAddress1 = (ULONG)0x805b5394 + 7;
DbgPrint( JmpAddress:0x%08X ,JmpAddress);
DbgPrint( JmpAddress1:0x%08X ,JmpAddress1);
__asm { //去掉内存保护 cli mov eax,cr0 and eax,not 10000h mov cr0,eax } *((ULONG*)Address) = (ULONG)MyNtReadVirtualMemory;
//HOOK SSDT *((ULONG*)Address1) = (ULONG)MyNtWriteVirtualMemory;
__asm { //恢复内存保护 mov eax,cr0 or eax,10000h mov cr0,eax sti } } VOID Unhook() { ULONG Address, Address1;
Address = (ULONG)KeServiceDescriptorTable->
ServiceTableBase + 0xBA * 4;