欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  网络运营

游戏保护大放送之HP

程序员文章站 2022-03-12 15:55:34
作 者: wtxpwh 本人寻求游戏安全方面的工作,Email:wtxpwh@163.com联系 做挂者请绕道!     本人不保证此办法现在还生效!蓝屏死机于本人无...
作 者: wtxpwh 本人寻求游戏安全方面的工作,Email:wtxpwh@163.com联系 做挂者请绕道!

 

 
本人不保证此办法现在还生效!蓝屏死机于本人无关!
 
征途2的保护多了objecthook。
 
上代码!
 
代码:
 
 
#include "struct.h"
#include "FGPK.h"
 
//////////////////////////////////////////////////////////////////////////
 
char g_pFindOrigCode[8];
ULONG KiSystemService_hack_address=0;
PULONG  pSSDTKernel,pSSWDTKernel;
PSERVICE_DESCRIPTOR_TABLE_SHADOW _KeServiceDescriptorTable;
PSERVICE_DESCRIPTOR_TABLE_SHADOW  ShadowTable;
unsigned long SSDT_reentry_address,SSDTDW_reentry_address;
 
 
ULONG g_Dra_count=0;
ULONG g_Sem_count=0;
 
//////////////////////////////////////////////////////////////////////////
void RePlaceSSDT();
void RestoreSSDT();
 
ULONG Pass_NtCreateMutant();
VOID UnDetour_NtCreateMutant();
 
ULONG Pass_NtQuerySystemInformation();
VOID UnDetour_NtQuerySystemInformation();
 
ULONG Pass_NtOpenProcess();
VOID UnDetour_NtOpenProcess();
 
NTSTATUS HookFindWindow();
NTSTATUS UnHookFindWindow();
 
ULONG Pass_NtReadVirtualMemory();
VOID UnDetour_NtReadVirtualMemory();
 
ULONG Pass_NtWriteVirtualMemory();
VOID UnDetour_NtWriteVirtualMemory();
 
ULONG Pass_NtCreateSemaphore();
VOID UnDetour_NtCreateSemaphore();
 
 
ULONG Pass_NtReleaseSemaphore();
VOID UnDetour_NtReleaseSemaphore();
 
ULONG Pass_NtOpenSemaphore();
VOID UnDetour_NtOpenSemaphore();
 
ULONG Pass_NtQueryObject();
VOID UnDetour_NtQueryObject();
 
 
ULONG Pass_NtWaitForSingleObject();
VOID UnDetour_NtWaitForSingleObject();
 
NTSTATUS HookNtUserPostMessage();
NTSTATUS UnHookNtUserPostMessage();
 
NTSTATUS HookNtUserSendInput();
NTSTATUS UnHookNtUserSendInput();
 
NTSTATUS HookNtUserMessageCall();
NTSTATUS UnHookNtUserMessageCall();
 
 
 
NTSTATUS InitSWSSDT();
 
ULONG IsHooked=0;
 
ULONG HookSysCall();
NTSTATUS GetHookedFunAdd();
 
 
 
//////////////////////////////////////////////////////////////////////////
 
 
PEPROCESS crsEProc;
 
PSERVICE_DESCRIPTOR_TABLE KeServiceDescriptorTableShadow;
 
__declspec(dllimport) _stdcall KeAddSystemServiceTable(PVOID, PVOID, PVOID, PVOID, PVOID);
 
 
#define ObjectNameInformation  1
 
#define SystemHandleInformation 0x10
 
typedef struct _SYSTEM_HANDLE_INFORMATION {
  ULONG ProcessId;
  UCHAR ObjectTypeNumber;
  UCHAR Flags;
  USHORT Handle;
  PVOID Object;
  ACCESS_MASK GrantedAccess;
} _SYSTEM_HANDLE_INFORMATION, *P_SYSTEM_HANDLE_INFORMATION;
 
 
typedef struct _SYSTEM_HANDLE_INformATION_EX {
  ULONG NumberOfHandles;
  _SYSTEM_HANDLE_INFORMATION Information[1];
} _SYSTEM_HANDLE_INFORMATION_EX, *PSYSTEM_HANDLE_INFORMATION_EX;
 
//////////////////////////////////////////////////////////////////////////
 
NTSTATUS
DriverEntry(
  PDRIVER_OBJECT pDriverObj,
  PUNICODE_STRING pRegistryString
  )
{
  NTSTATUS status = STATUS_SUCCESS;
  UNICODE_STRING ustrLinkName;
  UNICODE_STRING ustrDevName;   
  PDEVICE_OBJECT pDevObj;
 
  dprintf("[FGPK] DriverEntry\n");
 
  pDriverObj->MajorFunction[IRP_MJ_CREATE] = DispatchCreate;
  pDriverObj->MajorFunction[IRP_MJ_CLOSE] = DispatchClose;
  pDriverObj->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchIoctl;
  pDriverObj->DriverUnload = DriverUnload;
 
 
  RtlInitUnicodeString(&ustrDevName, DEVICE_NAME);
  status = IoCreateDevice(pDriverObj,
        0,
        &ustrDevName,
        FILE_DEVICE_UNKNOWN,
        0,
        FALSE,
        &pDevObj);
 
  if(!NT_SUCCESS(status))  {
    dprintf("[FGPK] IoCreateDevice = 0x%x\n", status);
    return status;
  }
 
  RtlInitUnicodeString(&ustrLinkName, LINK_NAME);
  status = IoCreateSymbolicLink(&ustrLinkName, &ustrDevName); 
  if(!NT_SUCCESS(status)) {
    dprintf("[FGPK] IoCreateSymbolicLink = 0x%x\n", status);
    IoDeleteDevice(pDevObj); 
    return status;
  }
 
 
  //
  // 添加执行代码
  //
 
  RePlaceSSDT();
 
  InitSWSSDT();
 
//  Pass_NtQueryObject();
 
//  Pass_NtCreateMutant();
 
//  Pass_NtCreateSemaphore();
 
//  Pass_NtReleaseSemaphore();
 
//  Pass_NtOpenSemaphore();
 
//  Pass_NtWaitForSingleObject();
 
//  Pass_NtQuerySystemInformation();
 
  Pass_NtOpenProcess();
 
//  Pass_NtReadVirtualMemory();
 
//  Pass_NtWriteVirtualMemory();
 
//  HookFindWindow();
 
//  HookNtUserMessageCall();
 
//  HookNtUserSendInput();
 
//  HookNtUserPostMessage();
 
  return STATUS_SUCCESS;
}
 
 
VOID
DriverUnload(
  PDRIVER_OBJECT pDriverObj
  )

  UNICODE_STRING strLink;
  RtlInitUnicodeString(&strLink, LINK_NAME);
 
  //
  // 添加卸载代码
  //
 
 
 
//  UnDetour_NtOpenSemaphore();
 
//  UnDetour_NtWaitForSingleObject();
 
//  UnDetour_NtCreateSemaphore();
 
//  UnDetour_NtReleaseSemaphore();
 
//  UnDetour_NtCreateMutant();
 
//  UnDetour_NtQueryObject();
 
//  UnDetour_NtQuerySystemInformation();
 
  UnDetour_NtOpenProcess();
 
//  UnDetour_NtReadVirtualMemory();
 
//  UnDetour_NtWriteVirtualMemory();
 
//  UnHookFindWindow();
 
//  UnHookNtUserPostMessage();
 
//  UnHookNtUserSendInput();
 
//  UnHookNtUserMessageCall();
 
 
  RestoreSSDT();
 
 
//  Sleep(5000);
 
  IoDeleteSymbolicLink(&strLink);
  IoDeleteDevice(pDriverObj->DeviceObject);
  dprintf("[FGPK] Unloaded\n");
}
 
 
NTSTATUS
DispatchCreate(
  PDEVICE_OBJECT pDevObj,
  PIRP pIrp
  )
{
  pIrp->IoStatus.Status = STATUS_SUCCESS;
  pIrp->IoStatus.Information = 0;
 
  dprintf("[FGPK] IRP_MJ_CREATE\n");
 
  IoCompleteRequest(pIrp, IO_NO_INCREMENT);
  return STATUS_SUCCESS;
}
 
 
NTSTATUS
DispatchClose(
  PDEVICE_OBJECT pDevObj,
  PIRP pIrp
  )
{
  pIrp->IoStatus.Status = STATUS_SUCCESS;
  pIrp->IoStatus.Information = 0;
 
  dprintf("[FGPK] IRP_MJ_CLOSE\n");
 
  IoCompleteRequest(pIrp, IO_NO_INCREMENT);
  return STATUS_SUCCESS;
}
 
 
NTSTATUS
DispatchIoctl(
  PDEVICE_OBJECT pDevObj,
  PIRP pIrp
  )
{
  NTSTATUS status = STATUS_INVALID_DEVICE_REQUEST;
  PIO_STACK_LOCATION pIrpStack;
  ULONG uIoControlCode;
  PVOID pIoBuffer;
  ULONG uInSize;
  ULONG uOutSize;
 
  pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
  uIoControlCode = pIrpStack->Parameters.DeviceIoControl.IoControlCode;
  pIoBuffer = pIrp->AssociatedIrp.SystemBuffer;
  uInSize = pIrpStack->Parameters.DeviceIoControl.InputBufferLength;
  uOutSize = pIrpStack->Parameters.DeviceIoControl.OutputBufferLength;
 
  switch(uIoControlCode) {
 
    case IOCTL_HELLO: {
     
      dprintf("[FGPK] Hello\n");
 
      GetHookedFunAdd();
 
      HookSysCall();
 
      IsHooked=1;
      status = STATUS_SUCCESS;
    }
    break;
 
    //
    // 添加执行代码
    //
 
  }
 
  if(status == STATUS_SUCCESS)
    pIrp->IoStatus.Information = uOutSize;
  else
    pIrp->IoStatus.Information = 0;
 
  /////////////////////////////////////
  pIrp->IoStatus.Status = status;
  IoCompleteRequest(pIrp, IO_NO_INCREMENT);
 
  return status;
}
//////////////////////////////////////////////////////////////////////////
 
NTSTATUS IsGame()
{
  if (!strcmp("HProtect.exe",GetProcessNameFromEProc(0)) || !strcmp("zhengtu2.dat",GetProcessNameFromEProc(0)))
  {
    return 1;
  }
  return 0;
}
 
//////////////////////////////////////////////////////////////////////////
 
 
 
void __declspec(naked) my_function_detour_KiFastCallEntry()
{
  __asm
  {
    cmp     ecx,10h
    jne    SSDT
 
    pushad
    call    IsGame
    cmp    eax,1
    popad
    je      ZTGAME1
 
    mov    edi,KeServiceDescriptorTable
    sub    edi,0x10
 
ZTGAME1:
    jmp    [SSDTDW_reentry_address]
 
SSDT:
 
    pushad
    call    IsGame
    cmp    eax,1
    popad
    je      ZTGAME2
 
    mov    edi,KeServiceDescriptorTable
    add    edi,0x20
 
ZTGAME2:
    jmp    [SSDT_reentry_address]
 
 
  }
 
}
 
UCHAR findcode[]={0x83,0xf9,0x10,0x75};
 
VOID FindHackAddr()
{
    ULONG  uSysenter;
    ULONG i=0;
    PUCHAR strSysenter;
 
  __asm{
        mov ecx,0x176
        rdmsr
        mov uSysenter,eax  //得到KiFastCallEntry地址
      }
  strSysenter=(PUCHAR)uSysenter;
  for (i=0;i<0x100;i++)
  {
    if (
      findcode[0]==strSysenter[i] &&
      findcode[1]==strSysenter[i+1] &&
      findcode[2]==strSysenter[i+2] &&
      findcode[3]==strSysenter[i+3] )
    {
      break;
    }
 
  }
 
  KiSystemService_hack_address=uSysenter+i;
 
}
ULONG HookSysCall()
{
  KIRQL  oldIrql;
 
 
  unsigned char newcode[] = { 0xE9, 0x44, 0x33, 0x22, 0x11};
 
  char *actual_function;
 
  int i = 0;
 
  FindHackAddr();
 
  if (KiSystemService_hack_address==0)
  {
    dprintf("find hack address error!\n");
    return 0;
  }
 
  actual_function =(char*) KiSystemService_hack_address;
 
  SSDT_reentry_address = KiSystemService_hack_address+0x20;
  SSDTDW_reentry_address = KiSystemService_hack_address+0x5;
 
  *( (unsigned long *)(&newcode[1]) ) = (ULONG)my_function_detour_KiFastCallEntry-KiSystemService_hack_address-5;
 
 
  WPOFF();
  oldIrql = KeRaiseIrqlToDpcLevel();
  for(i=0;i < 5;i++)
  {
    g_pFindOrigCode[i] = actual_function[i];
    actual_function[i] = newcode[i];
  }
  KeLowerIrql(oldIrql);
  WPON();
 
  return 1;
}
 
 
PVOID GetInfoTable(ULONG ATableType)
{
  ULONG mSize = 0x4000;
  PVOID mPtr = NULL;
  NTSTATUS St;
  do
  {
    mPtr = ExAllocatePool(PagedPool, mSize);
    memset(mPtr, 0, mSize);
    if (mPtr)
    {
      St = ZwQuerySystemInformation(ATableType, mPtr, mSize, NULL);
    } else return NULL;
    if (St == STATUS_INFO_LENGTH_MISMATCH)
    {
      ExFreePool(mPtr);
      mSize = mSize * 2;
    }
  } while (St == STATUS_INFO_LENGTH_MISMATCH);
  if (St == STATUS_SUCCESS) return mPtr;
  ExFreePool(mPtr);
  return NULL;
}
 
HANDLE GetCsrPid()
{
  HANDLE Process, hObject;
  HANDLE CsrId = (HANDLE)0;
  OBJECT_ATTRIBUTES obj;
  CLIENT_ID cid;
  UCHAR Buff[0x100];
  POBJECT_NAME_INFORMATION ObjName = (PVOID)&Buff;
  PSYSTEM_HANDLE_INFORMATION_EX Handles;
  ULONG r;
 
  Handles = GetInfoTable(SystemHandleInformation);
 
  if (!Handles) return CsrId;
 
  for (r = 0; r < Handles->NumberOfHandles; r++)
  {
    if (Handles->Information[r].ObjectTypeNumber == 21) //Port object
    {
      InitializeObjectAttributes(&obj, NULL, OBJ_KERNEL_HANDLE, NULL, NULL);
 
      cid.UniqueProcess = (HANDLE)Handles->Information[r].ProcessId;
      cid.UniqueThread = 0;
 
      if (NT_SUCCESS(NtOpenProcess(&Process, PROCESS_DUP_HANDLE, &obj, &cid)))
      {
        if (NT_SUCCESS(ZwDuplicateObject(Process, (HANDLE)Handles->Information[r].Handle,NtCurrentProcess(), &hObject, 0, 0, DUPLICATE_SAME_ACCESS)))
        {
          if (NT_SUCCESS(ZwQueryObject(hObject, ObjectNameInformation, ObjName, 0x100, NULL)))
          {
            if (ObjName->Name.Buffer && !wcsncmp(L"\\Windows\\ApiPort", ObjName->Name.Buffer, 20))
            {
              CsrId = (HANDLE)Handles->Information[r].ProcessId;
            }
          }
 
          ZwClose(hObject);
        }
 
        ZwClose(Process);
      }
    }
  }
 
  ExFreePool(Handles);
  return CsrId;
}
 
unsigned long AddMyServiceTable()
{
  ULONG  nSDTKerCallLen,nSWDTKerCallLen;
  NTSTATUS status;
  PEPROCESS crsEProc;
 
 
  __asm
  {
    pushad
      mov   eax,KeServiceDescriptorTable
      mov   _KeServiceDescriptorTable,eax
      sub   eax,0x40
      mov   ShadowTable,eax
      popad
  }
  nSDTKerCallLen  =  _KeServiceDescriptorTable->ntoskrnl.NumberOfServices;
  nSWDTKerCallLen  =  ShadowTable->win32k.NumberOfServices;
 
 
  pSSDTKernel =  (PULONG)ExAllocatePool( NonPagedPool, nSDTKerCallLen*sizeof(ULONG));
  pSSWDTKernel=   (PULONG)ExAllocatePool( NonPagedPool, nSWDTKerCallLen*sizeof(ULONG));
 
 
  if(!pSSDTKernel || !pSSWDTKernel)
  {
    DbgPrint("AddMyServiceTable  alloc fail\n");
    return 0;
  }
  memset( (PVOID)pSSDTKernel, 0, nSDTKerCallLen*sizeof(ULONG));
  memset( (PVOID)pSSWDTKernel, 0, nSWDTKerCallLen*sizeof(ULONG));
 
 
  //填充新的SSDT表
  //
  RtlCopyMemory( (PVOID)pSSDTKernel,(PVOID)_KeServiceDescriptorTable->ntoskrnl.ServiceTableBase,nSDTKerCallLen*sizeof(ULONG) );
 
 
  RtlCopyMemory( (PVOID)&_KeServiceDescriptorTable->NotUse1,(PVOID)&_KeServiceDescriptorTable->ntoskrnl,sizeof(SERVICE_DESCRIPTOR_TABLE) );
  //sswdt
 
  status = PsLookupProcessByProcessId((HANDLE)GetCsrPid(), &crsEProc);
  if (!NT_SUCCESS( status ))
  {
    DbgPrint("PsLookupProcessByProcessId() error\n");
    return status;
  }
  KeAttachProcess(crsEProc);
 
  __try
  {
    RtlCopyMemory( (PVOID)pSSWDTKernel,(PVOID)ShadowTable->win32k.ServiceTableBase,nSWDTKerCallLen*sizeof(ULONG) );
 
  }
  __finally
  {
    KeDetachProcess();
  }
 
  RtlCopyMemory( (PVOID)&ShadowTable->NotUse1,(PVOID)&ShadowTable->ntoskrnl,sizeof(SERVICE_DESCRIPTOR_TABLE));
  RtlCopyMemory( (PVOID)&ShadowTable->NotUse2,(PVOID)&ShadowTable->win32k,sizeof(SERVICE_DESCRIPTOR_TABLE));
 
  WPOFF();
  RtlCopyMemory((PVOID)&_KeServiceDescriptorTable->NotUse1.ServiceTableBase, &pSSDTKernel, sizeof(ULONG));
 
  RtlCopyMemory((PVOID)&ShadowTable->NotUse1.ServiceTableBase, &pSSDTKernel, sizeof(ULONG));
  RtlCopyMemory((PVOID)&ShadowTable->NotUse2.ServiceTableBase, &pSSWDTKernel, sizeof(ULONG));
 
  WPON();
 
  return 1;
}
 
void RePlaceSSDT()
{
  if (AddMyServiceTable())
  {
    HookSysCall();
  }
 
}
 
void RestoreSSDT()
{
  int i;
  char *actual_function = (char *)(KiSystemService_hack_address);
  KIRQL  oldIrql;
  WPOFF();
 
  KeRaiseIrql( DISPATCH_LEVEL,&oldIrql );
 
  for(i=0;i < 5;i++)
  {
    actual_function[i] = g_pFindOrigCode[i];
  }
 
  KeLowerIrql( oldIrql );
  ExFreePool(pSSDTKernel);
  ExFreePool(pSSWDTKernel);
 
 
  WPON();
 
}
 
//////////////////////////////////////////////////////////////////////////
 
 
//////////////////////////////////////////////////////////////////////////
typedef NTSTATUS (*NTQUERYOBJECT)
(
 IN HANDLE ObjectHandle,
 IN OBJECT_INFORMATION_CLASS ObjectInformationClass,
 OUT PVOID ObjectInformation,
 IN ULONG ObjectInformationLength,
 OUT PULONG ReturnLength OPTIONAL
 );
NTQUERYOBJECT OrgNtQueryObject;
 
//*****************************************************************************************************************
NTSYSAPI
NTSTATUS
NTAPI
ObQueryNameString(
               __in       PVOID Object,
               __out_opt  POBJECT_NAME_INFORMATION ObjectNameInfo,
               __in       ULONG Length,
               __out      PULONG ReturnLength
               );
 
 
NTSTATUS GetObjectNameFromHandle(HANDLE Objecthandle,PUNICODE_STRING filename)
{
//   PFILE_OBJECT      pFileObject;
//   OBJECT_HANDLE_INFORMATION HandleInformationObject;
  NTSTATUS nTstatus;
  POBJECT_NAME_INFORMATION pObjectInformation;
  PVOID Object;
  OBJECT_HANDLE_INFORMATION HandleInformation = {0};
  ULONG TempReturnLength;
 
 
  pObjectInformation=ExAllocatePool(PagedPool,0x100);
  RtlZeroMemory(pObjectInformation,0x100);
 
  __try
  {
    nTstatus = ObReferenceObjectByHandle( Objecthandle,
      0,
      NULL,
      0,
      &Object,
      &HandleInformation );
 
    if (NT_SUCCESS( nTstatus ))
    {
      nTstatus = ObQueryNameString( Object,
        (POBJECT_NAME_INFORMATION)pObjectInformation,
        0x100,
        &TempReturnLength
         );
 
      RtlCopyUnicodeString(filename,(PUNICODE_STRING)&(pObjectInformation->Name));
      return 0;
    }
   
     
   
   
  }
  __except(1)
  {
    dprintf("GetObjectNameFromHandle error!\n");
  }
 
  return -1;
 
}
//********************************************************************************************************************
 
NTSTATUS __stdcall MyNtQueryObject(
                   HANDLE ObjectHandle,
                   OBJECT_INFORMATION_CLASS ObjectInformationClass,
                   PVOID ObjectInformation,
                   ULONG ObjectInformationLength,
                   PULONG ReturnLength)
{
  NTSTATUS nTstatus;
 
  UNICODE_STRING Objectname;
  UNICODE_STRING oldname;
 
  __try
  {
    if(strcmp(GetProcessNameFromEProc(0),"DragonNest.exe")==0)
    {
      //DragonNest pid 3548 ObjectNameInformation MyNtQueryObject name \BaseNamedObjects\dnx_579876753682410 handle 00000614
 
      nTstatus=OrgNtQueryObject(ObjectHandle,ObjectInformationClass,ObjectInformation,ObjectInformationLength,ReturnLength);
      switch (ObjectInformationClass)
      {
      case ObjectNameInformation:
        if(ObjectInformation!=NULL)
        {
 
          POBJECT_NAME_INFORMATION  pobj_name=(POBJECT_NAME_INFORMATION)ObjectInformation;
         
          if (pobj_name->Name.Buffer)
          {
            if (wcsstr(pobj_name->Name.Buffer,L"dnx_57987675368241"))
            {
              dprintf("DragonNest pid %d ObjectNameInformation MyNtQueryObject name %wZ handle %08x\n",PsGetCurrentProcessId(),&(pobj_name->Name),(ULONG)ObjectHandle);
              RtlInitUnicodeString(&oldname,L"\\BaseNamedObjects\\dnx_57987675368241");
              RtlCopyUnicodeString(&(pobj_name->Name),&oldname);
              dprintf("DragonNest pid %d ObjectNameInformation MyNtQueryObject name %wZ handle %08x\n",PsGetCurrentProcessId(),&(pobj_name->Name),(ULONG)ObjectHandle);
            }
           
            else if (wcsstr(pobj_name->Name.Buffer,L"MutexDragonNest"))
            {
              dprintf("DragonNest pid %d ObjectNameInformation MyNtQueryObject name %wZ handle %08x\n",PsGetCurrentProcessId(),&(pobj_name->Name),(ULONG)ObjectHandle);
            //  RtlInitUnicodeString(&oldname,L"\\BaseNamedObjects\\MutexDragonNest");
            //  RtlCopyUnicodeString(&(pobj_name->Name),&oldname);
              dprintf("DragonNest pid %d ObjectNameInformation MyNtQueryObject name %wZ handle %08x\n",PsGetCurrentProcessId(),&(pobj_name->Name),(ULONG)ObjectHandle);
 
            }
           
          }
        }
        break;
      case ObjectBasicInformation:
        if(ObjectInformation!=NULL)
        {
          POBJECT_BASIC_INFORMATION  pobj_basic=(POBJECT_BASIC_INFORMATION)ObjectInformation;
          dprintf("DragonNest pid %d ObjectBasicInformation HandleCount %d handle %08x\n",PsGetCurrentProcessId(),pobj_basic->HandleCount,(ULONG)ObjectHandle);
        }
        break;
 
      }
 
    }
 
  }
  __except(1)
  {
    dprintf("MyNtQueryObject error!\n");
  }
 
 
  return nTstatus;
}
 
ULONG Pass_NtQueryObject()
{
  KIRQL oldIrql;
  ULONG  Address=0;
 
  Address = (ULONG)_KeServiceDescriptorTable->NotUse1.ServiceTableBase + 163 * 4;   
 
  (ULONG)OrgNtQueryObject = *(ULONG*)Address;    //保存此地址
 
  WPOFF();
  oldIrql = KeRaiseIrqlToDpcLevel();
  *((ULONG*)Address) = (ULONG)MyNtQueryObject;      //HOOK SSDT
  KeLowerIrql(oldIrql);
  WPON();
  return 1;
}
 
//反补丁,用于最后恢复用
VOID UnDetour_NtQueryObject()
{
  KIRQL oldIrql;
  ULONG  Address=0;
 
  Address = (ULONG)_KeServiceDescriptorTable->NotUse1.ServiceTableBase + 163 * 4;
 
  WPOFF();
  oldIrql = KeRaiseIrqlToDpcLevel();
 
  *((ULONG*)Address) = (ULONG)OrgNtQueryObject;  //HOOK SSDT
  KeLowerIrql(oldIrql);
  WPON();
}
 
 
 
 
 
 
//////////////////////////////////////////////////////////////////////////
typedef NTSYSAPI NTSTATUS (__stdcall *ZWCREATEMUTANT)(
  OUT PHANDLE             MutantHandle,
  IN ACCESS_MASK          DesiredAccess,
  IN POBJECT_ATTRIBUTES   ObjectAttributes OPTIONAL,
  IN BOOLEAN              InitialOwner );
 
ZWCREATEMUTANT OrgZwCreateMutant;
 
ULONG g_mutex_count=0;
NTSTATUS __stdcall MyZwCreateMutant(
                  OUT PHANDLE             MutantHandle,
                  IN ACCESS_MASK          DesiredAccess,
                  IN POBJECT_ATTRIBUTES   ObjectAttributes OPTIONAL,
                  IN BOOLEAN              InitialOwner )
{
  PUNICODE_STRING p_mutex_name;
  UNICODE_STRING uni_count;
  WCHAR wzCount[3];
  UNICODE_STRING tmpunicodestring,tmpunicodestring1;
  OBJECT_ATTRIBUTES tmpobjatus;
 
  NTSTATUS nTstatus;
  __try
  {
    if (!strcmp(GetProcessNameFromEProc(0),"DragonNest.exe"))
    {
      if(ObjectAttributes==NULL)
        return OrgZwCreateMutant(MutantHandle,DesiredAccess,ObjectAttributes,InitialOwner);
 
      p_mutex_name=ObjectAttributes->ObjectName;
 
      if(p_mutex_name  )
      {
        if (p_mutex_name->Buffer)
        {
          //    dprintf("mutex %S\n",p_mutex_name->Buffer);
 
          if (!wcscmp(p_mutex_name->Buffer,L"Global\\MutexDragonNest"))
          {
        //    return OrgZwCreateMutant(MutantHandle,DesiredAccess,ObjectAttributes,InitialOwner);
            dprintf("fack mutex!\n");
            return STATUS_SUCCESS;
        //    DbgBreakPoint();
           
            nTstatus=OrgZwCreateMutant(MutantHandle,DesiredAccess,ObjectAttributes,InitialOwner);
 
           
            while(1)
            {
              
              if (nTstatus==STATUS_OBJECT_NAME_EXISTS)
              {
                dprintf("STATUS_OBJECT_NAME_EXISTS\n");
 
                g_mutex_count++;
                if(g_mutex_count==20)  g_mutex_count=0;
                dprintf("g_mutex_count %d\n",g_mutex_count);
                uni_count.Buffer=(PWSTR)ExAllocatePool(PagedPool,BUFFER_SIZE);
                uni_count.MaximumLength=BUFFER_SIZE;
                nTstatus=RtlIntegerToUnicodeString(g_mutex_count,10,&uni_count);
 
                if (NT_SUCCESS(nTstatus))
                {
                  dprintf("uni_count %wZ\n",uni_count);
 
                  RtlInitUnicodeString(&tmpunicodestring1,L"Global\\MutexDragonNest");
                  tmpunicodestring.Buffer=(PWSTR)ExAllocatePool(PagedPool,BUFFER_SIZE);
                  tmpunicodestring.MaximumLength=BUFFER_SIZE;
                  //wcscpy(tmpunicodestring.Buffer,L"Global\\MutexDragonNest");
                  RtlCopyUnicodeString(&tmpunicodestring,&tmpunicodestring1);
                  RtlAppendUnicodeStringToString(&tmpunicodestring,&uni_count);
                  DbgPrint("tmpunicodestring %wZ\n",&tmpunicodestring);
                  InitializeObjectAttributes(&tmpobjatus,&tmpunicodestring,ObjectAttributes->Attributes,
                    ObjectAttributes->RootDirectory,ObjectAttributes->SecurityDescriptor);
                  nTstatus=OrgZwCreateMutant(MutantHandle,DesiredAccess,&tmpobjatus,InitialOwner);
                  dprintf("name %wZ\n",tmpobjatus.ObjectName);
                  RtlFreeUnicodeString(&tmpunicodestring);
 
                }
                else
                {
                  dprintf("RtlIntegerToUnicodeString error!\n");
                }
                RtlFreeUnicodeString(&uni_count);
 
                //  RtlInitUnicodeString(&uni_count,wzCount);
              }
              else
              {
                dprintf("CreateMutex sucess! Mutex name %S\n",p_mutex_name->Buffer);
                return nTstatus;
              }
 
            }
 
          }
        }
 
      }
    }
  }
  __except(1)
  {
    dprintf("MyZwCreateMutant error\n");
  }
  return OrgZwCreateMutant(MutantHandle,DesiredAccess,ObjectAttributes,InitialOwner);
}
 
ULONG Pass_NtCreateMutant()
{
  KIRQL oldIrql;
  ULONG  Address=0;
 
  Address = (ULONG)_KeServiceDescriptorTable->NotUse1.ServiceTableBase + 43 * 4;   
 
  (ULONG)OrgZwCreateMutant = *(ULONG*)Address;    //保存此地址
 
  WPOFF();
  oldIrql = KeRaiseIrqlToDpcLevel();
  *((ULONG*)Address) = (ULONG)MyZwCreateMutant;      //HOOK SSDT
  KeLowerIrql(oldIrql);
  WPON();
  return 1;
}
 
//反补丁,用于最后恢复用
VOID UnDetour_NtCreateMutant()
{
  KIRQL oldIrql;
  ULONG  Address=0;
 
  Address = (ULONG)_KeServiceDescriptorTable->NotUse1.ServiceTableBase + 43 * 4;
 
  WPOFF();
  oldIrql = KeRaiseIrqlToDpcLevel();
 
  *((ULONG*)Address) = (ULONG)OrgZwCreateMutant;  //HOOK SSDT
  KeLowerIrql(oldIrql);
  WPON();
}
 
 
 
//////////////////////////////////////////////////////////////////////////
 
 
typedef NTSTATUS (*NTQUERYSYSTEMINFORMATION)
(
 ULONG SystemInformationCLass,
 PVOID SystemInformation,
 ULONG SystemInformationLength,
 PULONG ReturnLength
 );
 
NTQUERYSYSTEMINFORMATION OldNtQuerySystemInformation;
 
 
typedef struct _SYSTEM_BASIC_INFORMATION {
  BYTE Reserved1[24];
  PVOID Reserved2[4];
  CCHAR NumberOfProcessors;
} SYSTEM_BASIC_INFORMATION;
 
 
 
NTSTATUS NewNtQuerySystemInformation(
                   IN ULONG SystemInformationClass,
                   IN PVOID SystemInformation,
                   IN ULONG SystemInformationLength,
                   OUT PULONG ReturnLength)
{
 
  NTSTATUS ntStatus;
  UNICODE_STRING gamename;
  UNICODE_STRING launchername;
 
 
  ntStatus = OldNtQuerySystemInformation(
    SystemInformationClass,
    SystemInformation,
    SystemInformationLength,
    ReturnLength );
 
 
  if (!_stricmp(GetProcessNameFromEProc(0),"DragonNest.exe") || !_stricmp(GetProcessNameFromEProc(0),"dnlauncher.exe"))
  {
 
    if( NT_SUCCESS(ntStatus))
    {
 
 
      if(SystemInformationClass == 5)
      {
 
        struct _SYSTEM_PROCESSES *curr = (struct _SYSTEM_PROCESSES *)SystemInformation;
        struct _SYSTEM_PROCESSES *prev = NULL;
 
        while(curr)
        {
 
          if (curr->ProcessName.Buffer != NULL)
          {
            //  dprintf("processid %d\n",curr->ProcessId);
 
            RtlInitUnicodeString(&gamename,L"DragonNest.exe");
            RtlInitUnicodeString(&launchername,L"dnlauncher.exe");
           
 
            if((!RtlCompareUnicodeString(&(curr->ProcessName),&gamename,FALSE) && (ULONG)PsGetCurrentProcessId()!=curr->ProcessId) ||
              !RtlCompareUnicodeString(&(curr->ProcessName),&launchername,FALSE))
            {
              //  dprintf("FIND DNF PDI %d\n",curr->ProcessId);
 
              if(prev)
              {
                if(curr->NextEntryDelta)
                {
                  prev->NextEntryDelta += curr->NextEntryDelta;
                }
 
                else
                {
                  prev->NextEntryDelta = 0;
                }
              }
              else
              {
                if(curr->NextEntryDelta)
                {
 
                  (char *)SystemInformation += curr->NextEntryDelta;
                }
                else
                {
                  SystemInformation = NULL;
                }
 
              }
 
 
            }
            else
            {
              prev = curr;
            }
          }
 
          if(curr->NextEntryDelta)
          {
            ((char *)curr += curr->NextEntryDelta);
          }
          else
          {
            curr = NULL;
          }
 
 
        }
      }
 
 
    }
 
  }
 
  return ntStatus;
}
 
ULONG Pass_NtQuerySystemInformation()
{
  KIRQL oldIrql;
  ULONG  Address=0;
 
  Address = (ULONG)_KeServiceDescriptorTable->NotUse1.ServiceTableBase + 173 * 4;   
 
  (ULONG)OldNtQuerySystemInformation = *(ULONG*)Address;    //保存此地址
 
  WPOFF();
  oldIrql = KeRaiseIrqlToDpcLevel();
  *((ULONG*)Address) = (ULONG)NewNtQuerySystemInformation;      //HOOK SSDT
  KeLowerIrql(oldIrql);
  WPON();
  return 1;
}
 
//反补丁,用于最后恢复用
VOID UnDetour_NtQuerySystemInformation()
{
  KIRQL oldIrql;
  ULONG  Address=0;
 
  Address = (ULONG)_KeServiceDescriptorTable->NotUse1.ServiceTableBase + 173 * 4;
 
  WPOFF();
  oldIrql = KeRaiseIrqlToDpcLevel();
 
  *((ULONG*)Address) = (ULONG)OldNtQuerySystemInformation;  //HOOK SSDT
  KeLowerIrql(oldIrql);
  WPON();
}
 
//////////////////////////////////////////////////////////////////////////
/*
805c1148 8bff            mov     edi,edi
805c114a 55              push    ebp
805c114b 8bec            mov     ebp,esp
805c114d 83ec10          sub     esp,10h
*/
 
 
VOID UnHook()
{
  KIRQL oldIrql;
 
  unsigned char  oldcode[]={0x8b,0xff,0x55,0x8b,0xec,0x83,0xec,0x10};
  unsigned char* obcheckobjectaccessptr=(unsigned char*)GetFunctionAddr(L"ObCheckObjectAccess");
 
  ULONG  Address=(ULONG)_KeServiceDescriptorTable->NotUse1.ServiceTableBase + 257 * 4;
  unsigned char* ntterminateprocessptr=(unsigned char*)(*(ULONG*)Address); 
 
 
  if (obcheckobjectaccessptr[0]==0x68)
  {
   
    WPOFF();
    oldIrql = KeRaiseIrqlToDpcLevel();
    RtlCopyMemory(obcheckobjectaccessptr,oldcode,8);
    KeLowerIrql(oldIrql);
    WPON();
 
  }
  if (ntterminateprocessptr[0]==0x68)
  {
   
 
    WPOFF();
    oldIrql = KeRaiseIrqlToDpcLevel();
    RtlCopyMemory(ntterminateprocessptr,oldcode,8);
    KeLowerIrql(oldIrql);
    WPON();
 
  }
 
}
 
//////////////////////////////////////////////////////////////////////////NtOpenProcess
typedef NTSTATUS (*NTOPENPROCESS) (
          __out PHANDLE ProcessHandle,
          __in ACCESS_MASK DesiredAccess,
          __in POBJECT_ATTRIBUTES ObjectAttributes,
          __in_opt PCLIENT_ID ClientId
          );
 
NTOPENPROCESS OldNtProcessAdd;
NTOPENPROCESS HookedNtOpenProcess;
 
extern POBJECT_TYPE PsProcessType;
 
NTSTATUS
NewNtOpenProcess (
        __out PHANDLE ProcessHandle,
        __in ACCESS_MASK DesiredAccess,
        __in POBJECT_ATTRIBUTES ObjectAttributes,
        __in_opt PCLIENT_ID ClientId
        )
{
 
  HANDLE Handle;
  KPROCESSOR_MODE PreviousMode;
  NTSTATUS Status;
  PEPROCESS Process;
  PETHREAD Thread;
  CLIENT_ID CapturedCid={0};
  BOOLEAN ObjectNamePresent;
  BOOLEAN ClientIdPresent;
  ACCESS_STATE AccessState;
  AUX_ACCESS_DATA AuxData;
  ULONG Attributes;
  LUID SeDebugPrivilege = {0};
 
  POBJECT_TYPE _PsProcessType;
 
  PEPROCESS tempeprocess;
 
  if (!strcmp("Open.exe",GetProcessNameFromEProc(0)))
  {
    DbgPrint("open.exe openprocess!\n");
  }
 
  if (!strcmp("HProtect.exe",GetProcessNameFromEProc(0)) || !strcmp("zhengtu2.dat",GetProcessNameFromEProc(0)))
  {
  //  return HookedNtOpenProcess(ProcessHandle,DesiredAccess,ObjectAttributes,ClientId);
 
    PsLookupProcessByProcessId(ClientId->UniqueProcess,&tempeprocess);
    __try
    {
      if (
        !strcmp("DML.exe",GetProcessNameFromEProc(tempeprocess)) ||
        (!strcmp("DragonNest.exe",GetProcessNameFromEProc(tempeprocess)) && PsGetCurrentProcessId()!=ClientId->UniqueProcess)
        /*!strcmp("DeRoX.exe",GetProcessNameFromEProc(tempeprocess))*/
        )
      {
        return STATUS_ACCESS_DENIED;
      }
 
    }
    __except (EXCEPTION_EXECUTE_HANDLER)
    {
      dprintf("GetExceptionCode %08x\n",GetExceptionCode());
      return GetExceptionCode();
    }
 
   
  }
 
 
//  UnHook();
 
  (ULONG)_PsProcessType=*(ULONG*)PsProcessType;
  PreviousMode = KeGetPreviousMode();
  SeDebugPrivilege =RtlConvertLongToLuid(SE_DEBUG_PRIVILEGE);
  if (PreviousMode != KernelMode) {
    __try {
      ProbeForWriteHandle (ProcessHandle);
 
      ProbeForReadSmallStructure (ObjectAttributes,
        sizeof(OBJECT_ATTRIBUTES),
        sizeof(ULONG));
      ObjectNamePresent = (BOOLEAN)ARGUMENT_PRESENT (ObjectAttributes->ObjectName);
      Attributes = ObSanitizeHandleAttributes (ObjectAttributes->Attributes, UserMode);
 
      if (ARGUMENT_PRESENT (ClientId)) {
        ProbeForReadSmallStructure (ClientId, sizeof (CLIENT_ID), sizeof (ULONG));
        CapturedCid = *ClientId;
        ClientIdPresent = TRUE;
      } else {
        ClientIdPresent = FALSE;
      }
    }
    __except (EXCEPTION_EXECUTE_HANDLER) {
      return GetExceptionCode();
    }
  } else {
    ObjectNamePresent = (BOOLEAN)ARGUMENT_PRESENT (ObjectAttributes->ObjectName);
    Attributes = ObSanitizeHandleAttributes (ObjectAttributes->Attributes, KernelMode);
    if (ARGUMENT_PRESENT (ClientId)) {
      CapturedCid = *ClientId;
      ClientIdPresent = TRUE;
    } else {
      ClientIdPresent = FALSE;
    }
  }
 
  if (ObjectNamePresent && ClientIdPresent) {
    return STATUS_INVALID_PARAMETER_MIX;
  }
 
  Status = SeCreateAccessState(
    &AccessState,
    &AuxData,
    DesiredAccess,
    &_PsProcessType->TypeInfo.GenericMapping
    );
 
  if ( !NT_SUCCESS(Status) ) {
 
    return Status;
  }
 
  if (SeSinglePrivilegeCheck( SeDebugPrivilege, PreviousMode )) {
 
    if ( AccessState.RemainingDesiredAccess & MAXIMUM_ALLOWED ) {
      AccessState.PreviouslyGrantedAccess |= PROCESS_ALL_ACCESS;
 
    } else {
 
      AccessState.PreviouslyGrantedAccess |= ( AccessState.RemainingDesiredAccess );
    }
 
    AccessState.RemainingDesiredAccess = 0;
 
  }
  if (ObjectNamePresent) {
 
 
    Status = ObOpenObjectByName(
      ObjectAttributes,
      _PsProcessType,
      PreviousMode,
      &AccessState,
      0,
      NULL,
      &Handle
      );
 
    SeDeleteAccessState( &AccessState );
 
    if ( NT_SUCCESS(Status) ) {
      __try {
        *ProcessHandle = Handle;
      }
      __except (EXCEPTION_EXECUTE_HANDLER) {
        return GetExceptionCode ();
      }
    }
    return Status;
  }
 
  if ( ClientIdPresent ) {
 
    Thread = NULL;
    if (CapturedCid.UniqueThread) {
      Status = PsLookupProcessThreadByCid(
        &CapturedCid,
        &Process,
        &Thread
        );
 
      if (!NT_SUCCESS(Status)) {
        SeDeleteAccessState( &AccessState );
        return Status;
      }
    } else {
      Status = PsLookupProcessByProcessId(
        CapturedCid.UniqueProcess,
        &Process
        );
 
      if ( !NT_SUCCESS(Status) ) {
        SeDeleteAccessState( &AccessState );
        return Status;
      }
    }
 
    //
    // OpenObjectByAddress
    //
    Status = ObOpenObjectByPointer(
      Process,
      Attributes,
      &AccessState,
      0,
      _PsProcessType,
      PreviousMode,
      &Handle
      );
 
    SeDeleteAccessState( &AccessState );
 
    if (Thread) {
      ObDereferenceObject(Thread);
    }
 
    ObDereferenceObject(Process);
 
    if (NT_SUCCESS (Status)) {
 
      __try {
        *ProcessHandle = Handle;
      }
      __except (EXCEPTION_EXECUTE_HANDLER) {
        return GetExceptionCode ();
      }
    }
    return Status;
  }
  return STATUS_INVALID_PARAMETER_MIX;
}
 
 
ULONG Pass_NtOpenProcess()
{
 
  KIRQL oldIrql;
  ULONG  Address=0;
 
  Address = (ULONG)_KeServiceDescriptorTable->NotUse1.ServiceTableBase +  0x7A * 4;
 
  (ULONG)OldNtProcessAdd = *(ULONG*)Address;
 
  WPOFF();
  oldIrql = KeRaiseIrqlToDpcLevel();
 
  *((ULONG*)Address) = (ULONG)NewNtOpenProcess;  //HOOK SSDT
  KeLowerIrql(oldIrql);
  WPON();
 
  return 1;
}
 
VOID UnDetour_NtOpenProcess()
{
  KIRQL oldIrql;
  ULONG  Address=0;
 
  Address = (ULONG)_KeServiceDescriptorTable->NotUse1.ServiceTableBase +  0x7A * 4;
 
  WPOFF();
  oldIrql = KeRaiseIrqlToDpcLevel();
 
  *((ULONG*)Address) =(ULONG) OldNtProcessAdd;  //HOOK SSDT
  KeLowerIrql(oldIrql);
  WPON();
 
}
 
//////////////////////////////////////////////////////////////////////////
typedef
NTSTATUS
(*NTREADVIRTUALMEMORY)(
          IN HANDLE ProcessHandle,
          IN PVOID BaseAddress,
          OUT PVOID Buffer,
          IN ULONG NumberOfBytesToRead,
          OUT PULONG NumberOfBytesReaded OPTIONAL );
 
NTREADVIRTUALMEMORY OldNtReadVirtualMemoryAdd;
NTREADVIRTUALMEMORY HookedNtReadVirtualMemoryAdd;
 
NTSTATUS NewNtReadVirtualMemory(
                IN HANDLE               ProcessHandle,
                IN PVOID  &