【转】日服巫术online过驱动保护分析(纯工具)(工具+自写驱动)

前言:
最近在学外挂编程,基本都是利用CE,OD调试分析游戏数据,但现在游戏公司用各种保护手段防止我们调试游戏,虽然我们有CE,OD这样的利器但是仍然被游戏驱动保护挡在门外i,真可谓巧妇也难为无米之炊啊。
 不得已只好暂停学习各种找CALL技术,先了解下游戏驱动保护的门门道道。经过几天的学习,有所收获,特记录下来,以备日后查询。本贴为纯工具过掉保护,下面将用工具+自写驱动过掉它,算是最近学习驱动编程的一次实践吧,
希望本文对 跟同我一样刚入门的菜鸟有所帮助,欢迎菜鸟一起交流,与君共勉! 
这次用的游戏是日服目前仍然比较火爆的《巫术online》 记得没学驱动保护之前也分析过这个游戏,但被这个游戏保护搞的蓝屏N次,怀恨在心,这次就拿它开刀,废话不说啦,进入正题:
使用工具:Kernel_Detective_1.4.1 ,XueTr_0.45, 郁金香OD2010,VE修改器汉化版(核心也是CE,原版CE挂上进游戏就出错)
打开游戏后,用OD附加,提示错误。

用XueTr看看这个游戏都动了什么手脚吧,让我们的利器都用不上,哼哼。

这个GPP.dll就是游戏的驱动保护文件,万恶啊。。。不过我们不能直接卸载,否则就是蓝屏或者游戏退出。。

看看内核:

有2个系统回调,在未知模块,很可疑,干掉它。
其他里没有什么异常了,看看内核钩子:

果然有hook。。。 ssdt里4个hook,经测试NtAllocateVirtualMemory就是阻止我们OD附加的罪魁祸首。右键恢复一下看看,恢复掉后,OD 可以附加,但游戏直接就掉了。将NtReradVirtualMemory NtWriteVirtualMemory恢复后,游戏也跟着掉了,而且再上就上不去了,只能重启在上。现在这驱动还温和了很多,记得以前版本 一恢复直接就蓝屏了。。。
看看ShadowSSDT

看来直接恢复是不行的,想想别的办法吧。

具体看一下它是怎么HOOK的吧,在Kernel_Detective的SSDT里找到
NtWriteVirtualMemory,右键反汇编当前地址

看到以下代码:
jmp 895B6FB0
dec ebp
sub al, 8
js short 805B53CF
jmp dword ptr [ecx+24]
add dword ptr [eax], eax
add byte ptr [ebx+40878AF8], cl
add dword ptr [eax], eax
add byte ptr [eax+758BE045], cl
adc al, 84
Invalid Command

退掉游戏,看看没有HOOK过的代码是怎么样的

push 1C
push 804DAF08
call 8053CBE0
mov eax, dword ptr fs:[124]
mov edi, eax

可以看出 jmp 895B6FB0 这里就跳转到游戏的驱动保护里执行了。但是简单的jmp 0x805B53CC 是不行的,直接就蓝屏了,

在用Kernel_Detective看看别的。

 

 

找到可疑的东东,有4个线程在未知模块运行,估计他们就是驱动的监测线程,右键 暂停它们。 

在KD的SSDT里直看到NtQuerySystemInformation这个SSDT HOOK  那些重要的inline hook都看不到,而线程中这些可疑线程,xt也看不到

看来不管怎么的,有什么工具全给它招呼上还是对滴。

现在用xt恢复ssdt和shadow ssdt试试看会发生什么吧。

游戏没有掉,恢复的HOOK,也没有再被HOOK,用OD附近试试看。
 果然可以附加啦!!经测试 VE查找数据,OD下断均没问题,可以继续我们找CALL事业了 HOHO。

 

 

注:OD要将StrongOD插件选项里的 Anti Anti_Attach 勾选上,否则挂上游戏仍然退出

 

 

用XT可以看到NTReadVirtualMemory  NTWRiteVirtualMemory  NTAllocateVirtualMemory 被inline hook了,以下为函数源代码。也就是需要恢复的代码。
NTReadVirtualMemory  0x805B52C2
push 1C
push 804DAEF0
call 8053CBE0
mov eax, dword ptr fs:[124]
mov edi, eax
mov al, byte ptr [edi+140]
mov byte ptr [ebp-20], al
mov esi, dword ptr [ebp+14]
test al, al
je short 805B534C 应跳转至0X805B52E4继续执行 HOOK 32字节NTReadVirtualMemory +0x22
--------------------
NTReadVirtualMemory  HOOK后
jmp 88E52C20
dec ebp
sub al, 12
jns short 805B52C5
jmp dword ptr [ecx+24]
add dword ptr [eax], eax
add byte ptr [ebx+40878AF8], cl
add dword ptr [eax], eax
add byte ptr [eax+758BE045], cl
adc al, 84
Invalid Command
je short 805B534C
-------------------------
NTWRiteVirtualMemory  0x805B53CC
push 1C
push 804DAF08
call 8053CBE0
mov eax, dword ptr fs:[124]
mov edi, eax
mov al, byte ptr [edi+140]
mov byte ptr [ebp-20], al
mov esi, dword ptr [ebp+14]
test al, al
je short 80565456应跳转到0x805B53EE继续执行 NTWRiteVirtualMemory+0x22 
-------------------
NTWRiteVirtualMemory  HOOK后
jmp 88E52FB0
dec ebp
sub al, 8
js short 805B53CF
jmp dword ptr [ecx+24]
add dword ptr [eax], eax
add byte ptr [ebx+40878AF8], cl
add dword ptr [eax], eax
add byte ptr [eax+758BE045], cl
adc al, 84
Invalid Command
je short 805B5456 
---------------------------------
NTAllocateVirtualMemory  0x805A9ABA
push 118
push 804DACB8 应跳转到0x805A9ABF hook5字节 NTAllocateVirtualMemory +5
----------------
NTAllocateVirtualMemory  HOOK 后
jmp 88E53070
push 804DACB8

 

 

 

 

 

首先感谢论坛的crazyearl 本文代码根据他发表的过HS保护中的源码 分析编写注释 十分感谢为我们新手提供那么好的文章!
本篇文章适用于菜鸟级新手查看,分析。
该代码是我学习过程中一个实践,关于写驱动框架结构,驱动层inline hook,分析,绕过游戏驱动保护HOOK函数方法。
也是学习郁金香驱动保护部分课程的一个实践。
希望给像我一样零编程基础学驱动的菜鸟们一些分享,帮助。 期待喜欢这方面的朋友交流 ^_^  与君共勉!
前篇写了通过KD XT工具过日服巫术驱动保护 使OD CE 正常加载教程,上篇写了被驱动保护HOOK的函数具体分析,找到恢复位置,这篇写下如何写代码恢复被HOOK的函数。
思路: 找到被HOOK函数的地址,然后HOOK它前5个字节,写个jmp 自写函数   让它按照函数正常流程运行,跳过游戏检测call。
首先要做的仍然是用工具 挂起检测线程,干掉系统回调。然后加载我们自己的驱动。
加载驱动软件:DriverMonitor       调试信息查看:DebugView 
  
注意!!(本驱动在xp 32位win7 32位ddk编译通过。xp32位"系统下载吧GhostXP SP3 2011装机版V8.0"测试通过,因汇编部分有些硬编码,不同系统可能会有所不同,请加载驱动前先用Kernel_Detective或xuetr查看相关代码,适当修改,否则蓝屏是跑不了的啦 ^_^)
驱动代码中注释掉一些关于进程比较的代码,思路是如果游戏访问关键函数,让它执行自己的检测代码,其他执行我们HOOK的代码。
具体实现代码以后在补充。
 
驱动代码见下文:  
/********************************************************************
* 创建时间:  2012/03/16
* 文件名称:  ByPass.c
* 文件作者:  月夜翔龙* ===================================================================
* 功能说明:  入口文件
* -------------------------------------------------------------------
* 其他说明:  
*********************************************************************/
#include <ntddk.h>
#include "ddk_proc.h"
#include "GetAddrs.h"
#define INITCODE code_seg("INIT")
#define PAGECODE code_seg("PAGE")
#pragma INITCODE 
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject,PUNICODE_STRING B)

    hookWriteMemory(); //调用自写hook函数,恢复系统原函数,跳过游戏检测CALL
 HookReadVirtualMemory();
 HookAllocateVirtualMemory();
    //注册派遣例程 
pDriverObject->MajorFunction[IRP_MJ_CREATE]=ddk_DispatchRoutine_CONTROL; //IRP_MJ_CREATE相关IRP处理函数
pDriverObject->MajorFunction[IRP_MJ_CLOSE]=ddk_DispatchRoutine_CONTROL; //IRP_MJ_CREATE相关IRP处理函数
pDriverObject->MajorFunction[IRP_MJ_READ]=ddk_DispatchRoutine_CONTROL; //IRP_MJ_CREATE相关IRP处理函数
pDriverObject->MajorFunction[IRP_MJ_CLOSE]=ddk_DispatchRoutine_CONTROL; //IRP_MJ_CREATE相关IRP处理函数
pDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL]=ddk_DispatchRoutine_CONTROL; //IRP_MJ_CREATE相关IRP处理函数
 CreatMyDevice(pDriverObject); //创建驱动设备 
 pDriverObject->DriverUnload=ddk_unload;  //驱动卸载例程
    //return (1);
 return STATUS_SUCCESS;
}
#pragma PAGECODE
NTSTATUS ddk_DispatchRoutine_CONTROL(IN PDEVICE_OBJECT pDevobj,IN PIRP pIrp )
{
 //对相应的IPR进行处理
 pIrp->IoStatus.Information=0;//设置操作的字节数为0,这里无实际意义
 pIrp->IoStatus.Status=STATUS_SUCCESS;//返回成功
 IoCompleteRequest(pIrp,IO_NO_INCREMENT);//指示完成此IRP
 KdPrint(("离开派遣函数\n"));//调试信息
 return STATUS_SUCCESS; //返回成功
}
void ddk_unload(IN PDRIVER_OBJECT pDriverObject)
{
 UNICODE_STRING  symboName;
 PDEVICE_OBJECT pdev; //用来卸载设备
 uninstall();  //恢复HOOK
 RtlInitUnicodeString(&symboName,L"\\??\\ByPass_symlink");
    pdev=pDriverObject->DeviceObject; 
 IoDeleteSymbolicLink(&symboName);//删除符号链接
 IoDeleteDevice(pdev); //删除设备对象
 KdPrint(("驱动卸载成功。。。。。。OK\n\n"));
}
---------------------------------------------------------------------------------------
/********************************************************************
* 创建时间:  2012/03/16
* 文件名称:  ddk_proc.h 头文件
* 文件作者:  月夜翔龙
* ===================================================================
* 功能说明:  变量定义,函数声明部分
* -------------------------------------------------------------------
* 其他说明:  
*********************************************************************/
#include <windef.h>
#include <ntddk.h>
/************************************************
***              函数前置声明部分              ******
************************************************/
NTSTATUS ddk_DispatchRoutine_CONTROL(IN PDEVICE_OBJECT pDevobj,IN PIRP pIrp ); //派遣函数
extern long KeServiceDescriptorTable ; //导出SSDT表
void ddk_unload (IN PDRIVER_OBJECT pDriverObject); //前置说明 卸载历程
void wpoff(); //关闭页面保护 具体实现过程在下面
void wpon(); //开启页面保护  具体实现过程在下面
NTKERNELAPI UCHAR * PsGetProcessImageFileName(PEPROCESS Process);
NTKERNELAPI NTSTATUS PsLookupProcessByProcessId(__in   HANDLE ProcessId,__out  PEPROCESS *Process);
/**************************************************
**********         全局变量       *****************
**************************************************/
ULONG WriteMemoryAddr,writeMemory_22,writeMemory_7; //HOOK writeMemory使用
ULONG ReadMemoryAddr,readMemory_22; //HOOK readmemory 使用
ULONG AllocateMemoryAddr,AllocateMemory_5; //HOOK AllocateMemory使用
#define NAKED __declspec(naked)  //定义裸体函数
//*******************************************************************
//PEPROCESS WriteMemoryEPROCESS = NULL;  //进程比较使用 该游戏不需要 
// ULONG WriteMemoryEPROCESS_174;  //
//ANSI_STRING wm_str1,wm_str2;   //保存进程名称
//#define APPNAME "WizardryOnline"
/**********************************************************
***               函数实现部分                          ***
**********************************************************/
//////////////////////////////////////////////////////////////////////
// 名称: CreatMyDevice 
// 功能: 创建设备
// 参数: 驱动对象 在入口函数传递
// 返回: status 
//////////////////////////////////////////////////////////////////////
NTSTATUS CreatMyDevice(IN PDRIVER_OBJECT pDriverObject)
{
 NTSTATUS status;
 PDEVICE_OBJECT pDevObj; //用来返回设备
 UNICODE_STRING devName; //设备名称
 UNICODE_STRING symlinkname;
 RtlInitUnicodeString(&devName,L"\\Device\\ByPass_Devcice"); //初始化设备名称
 //创建设备
 status=IoCreateDevice(pDriverObject,0,&devName,FILE_DEVICE_UNKNOWN,0,TRUE,&pDevObj);
    if(!NT_SUCCESS(status)) //如果创建设备失败
 {
  if (status==STATUS_INSUFFICIENT_RESOURCES)
  {
   KdPrint(("驱动资源不足.....++++++++++++"));
   
  }
  if (status==STATUS_OBJECT_NAME_EXISTS)
  {
   KdPrint(("驱动对象名已存在.....++++++++++++"));
   
  }
  if (status==STATUS_OBJECT_NAME_COLLISION)
  {
   KdPrint(("驱动对象名有冲突....++++++++++++"));
   
  }
  KdPrint(("设备创建失败..........+++++++"));
  return status;
 }
 pDevObj->Flags |= DO_BUFFERED_IO ;
 //创建符号链接
    RtlInitUnicodeString(&symlinkname,L"\\??\\ByPass_symlink");
 status=IoCreateSymbolicLink(&symlinkname,&devName);
 if (!NT_SUCCESS(status))
 {
  IoDeleteDevice(pDevObj); //如果创建设备符号链接不成功则删除
  return status;
 }
 KdPrint(("设备创建成功...............++\n"));
     return STATUS_SUCCESS;
}
//////////////////////////////////////////////////////////////////////
// 名称: WPOFF
// 功能: 关闭页面保护
// 参数: 
// 返回: 
//////////////////////////////////////////////////////////////////////
void wpoff()
{
 __asm 
 {
  cli
  mov eax,cr0
  and eax,not 10000h
  mov cr0,eax
 }
}
//////////////////////////////////////////////////////////////////////
// 名称: WPON
// 功能: 开启页面保护
// 参数: 
// 返回: 
//////////////////////////////////////////////////////////////////////
void wpon()
{
 __asm 
 {
  mov eax,cr0
  or eax,10000h
  mov cr0,eax
  sti
 }
}
//////////////////////////////////////////////////////////////////////
// 名称: 卸载函数
// 功能: 处理卸载驱动要做的事情,恢复自写HOOK
// 参数: 
// 返回: 
//////////////////////////////////////////////////////////////////////
void uninstall()
{
 KIRQL Irql;
 //WriteMemoryAddr=CurNTWriteVirtualMemory();
 BYTE byWriteVirtualMemory[7] = {0x6A,0x1C,0x68,0x08,0xAF,0x4D,0x80};  //系统原WriteVirtualMemory前7字节 硬编码 请适当修改 
    BYTE byReadVirtualMemory[7]  = {0x6A,0x1C,0x68,0xF0,0xAE,0x4D,0x80}; //系统原ReadVirtualMemory前7字节 硬编码 请适当修改
 BYTE byAllocateVirtualMemory[5] = {0x68,0x18,0x01,0,0}; //系统原AllocateVirtualMemory前5字节 硬编码 请适当修改
 wpoff(); //关闭页面保护
 Irql=KeRaiseIrqlToDpcLevel(); //提升IRQ等级
 ////恢复WriteVirtualMemory
 RtlCopyMemory((BYTE*)WriteMemoryAddr,byWriteVirtualMemory,7);
 ////恢复ReadVirtualMemory
 RtlCopyMemory((BYTE*)ReadMemoryAddr,byReadVirtualMemory,7);
 ////恢复AllocateVirtualMemory
 RtlCopyMemory((BYTE*)AllocateMemoryAddr,byAllocateVirtualMemory,5);
 //恢复IRQ中断等级
 KeLowerIrql(Irql);
 //开启页面保护
 wpon();
}
 
---------------------------------------------------------------------------------------------------------
 
/********************************************************************
* 创建时间:  2012/03/16
* 文件名称:  GetAddrs.h 头文件
* 文件作者:  月夜翔龙
* ===================================================================
* 功能说明:  获得函数首地址,自写HOOK,跳过游戏检测CALL
* -------------------------------------------------------------------
* 其他说明:  
*********************************************************************/
/*********************************************************
**********功能: 获得当前ReadVirtualMemory地址 ************
**********参数:    无  ***********************************
*********返回值: 函数地址 ********************************
*********公式: 函数地址=SSDT表基地址+函数标号*4 **********
*********************************************************/
ULONG CurNTReadVirtualMemory() 
{
 ULONG ReadMemoryBase;
 __asm
 { 
  push eax //存放ssdt地址 
     push ebx //存放函数在SSDT表索引号 ReadVirtualMemory 十进制186 十六进制0XBA 不同系统索引号可能不同 KD查看SSDT表 
  mov eax,KeServiceDescriptorTable
  mov eax,[eax] //取出ssdt基地址
  mov ebx,0xBA //存放索引号
  shl ebx,2 //0xBA*4 shl ebx,2 == imul ebx,ebx,4
  add eax,ebx //KeServiceDescriptorTable+0xBA*4  
  mov eax,[eax] //取出函数地址
        mov ReadMemoryBase,eax //保存到ReadMemoryBase 
  pop eax
  pop ebx
 }
 KdPrint(("curReadMemory值为%x +++++++\n",ReadMemoryBase));
 return ReadMemoryBase;
}
/*********************************************************
**********功能: 获得当前WriteVirtualMemory地址 ************
**********参数:    无  ***********************************
*********返回值: 函数地址 ********************************
*********公式: 函数地址=SSDT表基地址+函数标号*4 **********
*********************************************************/
ULONG CurNTWriteVirtualMemory() 
{
 ULONG WriteMemoryBase;
 __asm
 { 
  push eax //存放ssdt地址 
     push ebx //存放函数在SSDT表索引号 WriteVirtualMemory 十进制277 十六进制0X115 不同系统索引号可能不同 KD查看SSDT表
  mov eax,KeServiceDescriptorTable
  mov eax,[eax] //取出ssdt基地址
  mov ebx,0x115 //存放索引号
  shl ebx,2 //0xBA*4 shl ebx,2 == imul ebx,ebx,4
  add eax,ebx //KeServiceDescriptorTable+0x115*4  
  mov eax,[eax] //取出函数地址
        mov WriteMemoryBase,eax //保存到WriteMemoryBase 
  pop eax
  pop ebx
 }
 KdPrint(("curWriteMemory值为%x +++++++\n",WriteMemoryBase));
 return WriteMemoryBase;
}
/*********************************************************
**********功能: 获得当前NTAllocateVirtualMemory地址 ******
**********参数:    无  ***********************************
*********返回值: 函数地址 ********************************
*********公式: 函数地址=SSDT表基地址+函数索引号*4 ********
*********************************************************/
ULONG CurNTAllocateVirtualMemory() 
{
 ULONG AllocateMemoryBase;
 __asm
 { 
  push eax //存放ssdt地址 
     push ebx //存放函数在SSDT表索引号 AllocateMemory  十进制17十六进制0X11 不同系统索引号可能不同 KD查看SSDT表
  mov eax,KeServiceDescriptorTable
  mov eax,[eax] //取出ssdt基地址
  mov ebx,0x11 //存放索引号
  shl ebx,2 //0x11*4    shl ebx,2 == imul ebx,ebx,4
  add eax,ebx //KeServiceDescriptorTable+0x11*4  
  mov eax,[eax] //取出函数地址
        mov AllocateMemoryBase,eax //保存到AllocateMemoryBase 
  pop eax
  pop ebx
 }
 KdPrint(("curAllocateMemory值为%x +++++++\n",AllocateMemoryBase));
 return AllocateMemoryBase;
}
/*********************************************************
**********功能: 通过MmGetSystemRoutineAddress()获取地址***
****************         演示,功能同上             ******
**********参数:    无                               ******
*********返回值: 函数地址                           ******
*********公式: 无                                   ******
**********************************************************
ULONG OldNTAllocateVirtualMemory() 
{
      ULONG OldAllocateMemoryBase;
   UNICODE_STRING S_AllocateMemory;
   RtlInitUnicodeString(&S_AllocateMemory,L"NtAllocateVirtualMemory");//初始化字串
   OldAllocateMemoryBase=(ULONG)MmGetSystemRoutineAddress(&S_AllocateMemory);//获得地址
   KdPrint(("OldAllocateMemory值为%x +++\n",OldAllocateMemoryBase));
   return OldAllocateMemoryBase;
}
*/
/*********************************************************
**********功能: 恢复WriteVirtualMemory正常流程      ******
****************      跳过游戏检测CALL              ******
**********参数:    无                               ******
*********返回值: 无                                 ******
*********公式: 无                                   ******
*********************************************************/
static NAKED void MyWriteVirtualMemory()
{
 /*进程比较代码实现,该游戏不需要
 获得调用者的EPROCESS
 WriteMemoryEPROCESS = IoGetCurrentProcess();
 KdPrint(("WriteMemoryEPROCESS值为%x ++++\n",WriteMemoryEPROCESS));
 WriteMemoryEPROCESS_174=(ULONG)WriteMemoryEPROCESS+0x174;
 KdPrint(("WriteMemoryEPROCESS+0x174值为%x ++++\n",WriteMemoryEPROCESS_174));
 将调用者的进程名保存到str1中
 RtlInitAnsiString(&wm_str1,(PCSZ)WriteMemoryEPROCESS_174);   
 将我们要比对的进程名放入str2
 RtlInitAnsiString(&wm_str2,APPNAME);
 KdPrint(("当前进程名称值为:%x ++++\n",&wm_str1));
 KdPrint(("APPNAME值为:%x ++++\n",&wm_str2));
 if (RtlCompareString(&wm_str1,&wm_str2,FALSE) == 0)
 */
 __asm 
 {
  //0x805B53CC 
  push 0x1C
  push 0x804DAF08  //硬编码,不同系统可能有所不同,请按实际修改
  mov eax,0x8053CBE0  //硬编码,不同系统可能有所不同,请按实际修改
  call eax
        mov eax, dword ptr fs:[0x124]
        mov edi, eax
        mov al, byte ptr [edi+0x140]
        mov byte ptr [ebp-0x20], al
        mov esi, dword ptr [ebp+0x14]
        test al, al
  mov eax,writeMemory_22 
  jmp eax  //恢复writememory前32字节然后跳转到writememory+0x22正常执行,跳过游戏检测call
 } //end asm 
}
/*********************************************************
**********功能: 恢复ReadVirtual Memory正常流程      ******
****************      跳过游戏检测CALL              ******
**********参数:    无                               ******
*********返回值: 无                                 ******
*********公式: 无                                   ******
*********************************************************/
static NAKED  void MyReadVirtualMemory()
{
 __asm 
 {
  //0x805B52C2
        push 0x1C
        push 0x804DAEF0 //硬编码,不同系统可能有所不同,请按实际修改
        mov  eax,0x8053CBE0 //硬编码,不同系统可能有所不同,请按实际修改
        call eax
        mov eax, dword ptr fs:[0x124]
        mov edi, eax
        mov al, byte ptr [edi+0x140]
        mov byte ptr [ebp-0x20], al
        mov esi, dword ptr [ebp+0x14]
        test al, al
  mov eax,readMemory_22 //恢复readmemory前32字节然后跳转到readmemory+0x22正常执行,跳过游戏检测call
  jmp eax
 }
}
/*********************************************************
**********功能: 恢复AllocateVirtualMemory正常流程   ******
****************      跳过游戏检测CALL              ******
**********参数:    无                               ******
*********返回值: 无                                 ******
*********公式: 无                                   ******
*********************************************************/
static NAKED  void MyAllocateVirtualMemory()
{
 __asm 
 {
        //0x805A9ABA 
        push 0x118  //硬编码,不同系统可能有所不同,请按实际修改
        mov eax,AllocateMemory_5//恢复前5字节然后跳转到allocatememory+0x5正常执行,跳过游戏检测call
        jmp eax
 }
}
/*********************************************************
**********功能:hook原函数头5个字节跳转到自写函数执行******
****************                                    ******
**********参数:    无                               ******
*********返回值: 无                                 ******
*********公式:jmp jmpaddr  jmp机器码E9              ******
*********jmpaddr公式:新地址-(原地址+5)或-原地址-5   ******
*********************************************************/
void hookWriteMemory()
{
 BYTE  JmpAddress[7] = {0xE9,0,0,0,0,0x90,0x90};
 //该数组首字节为E9,即是jmp指令,后四字节为跳转字节,故为0,
 //0x90为NOP指令,因WriteMemory汇编代码头部是两条指令7字节 故后2字节用nop填充
 KIRQL Irql;
 WriteMemoryAddr=CurNTWriteVirtualMemory();//获得当前WriteVirtualMemory地址 即原地址  
 writeMemory_22=WriteMemoryAddr+0x22; //WriteVirtualMemory+0x22 恢复前32字节然后跳转到这里继续执行  
 *(ULONG *)(JmpAddress+1)=(ULONG)MyWriteVirtualMemory - (WriteMemoryAddr+5); 
 //将jmpaddr 写入数组E9之后4字节 
 wpoff(); //关闭CR0
 Irql=KeRaiseIrqlToDpcLevel(); //提升IRQ中断等级
 //向WriteVirtualMemory首地址写入7字节,实现HOOK
 RtlCopyMemory((BYTE*)WriteMemoryAddr,JmpAddress,7);
 KeLowerIrql(Irql); //恢复Irql
 wpon();  //开启cr0
}
/*********************************************************
**********功能:hook原函数头5个字节跳转到自写函数执行******
****************                                    ******
**********参数:    无                               ******
*********返回值: 无                                 ******
*********公式:jmp jmpaddr  jmp机器码E9              ******
*********jmpaddr公式:新地址-(原地址+5)或-原地址-5   ******
*********************************************************/
void HookReadVirtualMemory()
{
 BYTE JmpAddress[7] = {0xE9,0,0,0,0,0x90,0x90};
 KIRQL Irql;
 ReadMemoryAddr=CurNTReadVirtualMemory();
 readMemory_22=ReadMemoryAddr+0x22;
 *(ULONG*)(JmpAddress+1)=(ULONG)MyReadVirtualMemory  - (ReadMemoryAddr+5);
 wpoff();
 Irql=KeRaiseIrqlToDpcLevel();
 RtlCopyMemory((BYTE*)ReadMemoryAddr,JmpAddress,7);
 KeLowerIrql(Irql);
 wpon();
}
/*********************************************************
**********功能:hook原函数头5个字节跳转到自写函数执行******
****************                                    ******
**********参数:    无                               ******
*********返回值: 无                                 ******
*********公式:jmp jmpaddr  jmp机器码E9              ******
*********jmpaddr公式:新地址-(原地址+5)或-原地址-5   ******
*********************************************************/
void HookAllocateVirtualMemory()
{
    BYTE Jmpaddress[5] = {0xE9,0,0,0,0}; 
 //因AllocateVirtualMemory汇编头部为push 118占5字节 与jmp xxxx 相同 故只需hook一条指令即可 
 KIRQL Irql;
 AllocateMemoryAddr=CurNTAllocateVirtualMemory();
 AllocateMemory_5=AllocateMemoryAddr+0x5;
 *(ULONG*)(Jmpaddress+1)=(ULONG)MyAllocateVirtualMemory - (AllocateMemoryAddr+5);
 wpoff();
 Irql=KeRaiseIrqlToDpcLevel();
 RtlCopyMemory((BYTE*)AllocateMemoryAddr,Jmpaddress,5);
 KeLowerIrql(Irql);
 wpon();
}

该驱动代码 可根据自己系统改变硬编码后 用XT KD 可以看到加载后和卸载 HOOK的几个函数代码变化,无需使用游戏。
相信新手会对inline hook有所了解

 

 

 

时间: 2024-10-05 19:08:23

【转】日服巫术online过驱动保护分析(纯工具)(工具+自写驱动)的相关文章

用Autoruns揪出流氓软件的驱动保护

一.为什么流氓软件总是删不掉? 经常有 网友发贴子说文件删除不掉,或者流氓软件清除不了,或者删除了相关的文件, 但是马上它又出现了.现在流氓软件为了保护自己,采取的手段是五花八门,无所 不用其极:进程保护,交叉感染,自启动,自我恢复,文件隐藏,进程注入,驱动保护. 到目前为止,所有流氓软件最终极.最有效的保护办法还是底层驱动级的保护,一般就是在drivers目录下增加一个或多个.sys文件(我也见过一个用rundll32来运行一个.dll作为驱动的),但本质上这个都会在Windows的HKLM\

日服大航海时代将于6月8日更新主题为七夕节

多玩游戏网讯(编译:巫妖康葛斯):光荣日服在6月8日即将为大航海时代更新新的资料片<Star Festival(星之节)>.这次更新主要为了即将到来的七夕节而做准备,内容以一个关于牛郎和织女隔海相望的爱情故事作为任务展开,玩家可以从中获得一些七夕相关的任务物品.(身为译者的巫妖就只能想起凉宫春日的竹子了). 除此之外,游戏的更新还包含了新的甲板战和商业战的调整,新版本的甲板战中需要双方都同意才能进入白兵战.海港的投资在一定时间内超过数额后占有度亦会有上升缓和的趋势. 同时,玩家所收集的宠物和收

《仙境传说》日服改版新名为“第三立场”

6月8日最新消息,<仙境传说>日服将于7月6日进行大规模的改版,新版本名为"第三立场",将添加新职业,玩家可以转职.新版的等级上限提高至150级,同时人物属性的上限也由原来的99点上升到120点.并且有新的技能追加. 除了公布新职业,还用更新用户界面,比如"扩充包裹"以及快捷键添加排序功能.让战斗更加轻松.(编辑 张澄) 大主教 暗影追踪者 游侠 宫廷乐师

萌系网游《魔法飞球》日服新角色萝莉猫女登场

多玩网讯(整理/韩菓子)韩国高尔夫网游<魔法飞球>日服公开第十款游戏角色Nell. 7月22日,<魔法飞球>日本运营商Gamepot通过日版官网公开新角色Nell艺术原画.背景故事和声优信息等,这是自2008年第四季更新添加角色之后2年再一次有新角色登场. 设定为双胞胎的Nell是养猫的萌系女角色,由出演过<铃铛猫娘>和<化物语>的日本声优泽城美雪来配音. Nell将于日服8月5日定期维护时进行更新,同时举行能获得新角色及相关道具的活动.韩国同样以8月5日更

《永恒之塔》日服更新玩家希望女角色能乳摇

NCSOFT日本分公司宣布,为纪念<永恒之塔>的2.0更新,举办线下活动,并将在11月30日进行下一个更新"2.1黄金时代". 在线下活动中,NCSOFT海外开发小组组长讲述了2.0及2.1更新相关内容.对日服务物品爆率的提升,他表示是为了提高玩家们的满意度. 此外,他还表示虽然考虑同种族的PK,但是优先级较低,目前还没确定开发相关内容.并且,日服<永恒之塔>也将会支持角色换服. 呃,摇得起来吗? 另一方面,NCSOFT日本分公司在此次活动中还收到了"

剑灵日服收费模式 可选择包月或者包季

&http://www.aliyun.com/zixun/aggregation/37954.html">nbsp; [科技讯]5月20日信息,<剑灵>在日服采用的月费制分为30天包月和90天包季两种,30天收费3000日元(约183元RMB),90天收费9000日元(约549元RMB).此外,根据此前公布的消息,选择包季付费的玩家还可获赠其他的游戏道具,比如双倍经验药剂龙凤汤等. <剑灵>日本公测版允许玩家一个账号创建四个角色,其中一名角色达到15级前都可

DNF日服2000人测试 年底进行大版本更新

DNF日服近日正在招募2000名玩家为新版本测试,可能将于年底有一次大版本更新,招募2000人进行测试还是史无前例的,可以看出日服的这次更新应该是一个巨大的革新,我们一起期待下,会有什么样的新事物与大家见面吧! &http://www.aliyun.com/zixun/aggregation/37954.html">nbsp;   DNF日服有大动作 请上千玩家测试 翻译: 我们看好的"阿拉德战记"明天,谢谢.感谢各位对"阿拉德战记(DNF,日服称DN

全新驱动人生5 让屌丝轻松上手装驱动

错误的操作或病毒.木马程序破坏会导致系统中重要文件受损出现运行错误甚至系统崩溃无法启动.高富帅们通常一套正版windows光盘外加轻松几个按键就能搞定系统重装.而不是电脑高手,却喜欢"鼓捣"电脑的屌丝们却不得不苦逼的面对各种重装系统后的问题:电脑花屏卡屏怎么办?!怎么摆弄电脑也没有声音怎么办?!--其实这些都是简单的驱动问题.全新上阵的驱动人生5,轻轻松松装驱动,让屌丝们轻松上手驱动安装. 新版本驱动人生5在驱动人生原有基础上,在性能和功能上有更大的飞跃.打开驱动人生5,可以很明显的感

驱动人生:一键为你解决苹果驱动烦恼

Windows是目前世界上用户最多,且兼容性最强的操作系统,苹果电脑的用户常常会因为工作和生活的需要在苹果电脑上安装windows系统.装好系统后,怎样简单快捷的安装驱动?驱动人生专门为苹果电脑用户设计苹果专用驱动安装包,不需要用户到苹果官网逐个查找和下载驱动,不需要用户手动逐个安装驱动,一键安装自动完成用户苹果电脑在对应windows系统环境下所有驱动的安装,方便又快捷. 首先,在驱动人生官网的驱动下载页面找到苹果驱动中心,然后按照自己苹果电脑的型号和安装windows系统版本找到对应的驱动自