遊戲保護大放送之GPK

Max Woods發表於2014-08-16

GPK也沒有啥特別。龍之谷多開檢測和別的不一樣。

#include "struct.h"
#include "FGPK.h"

//////////////////////////////////////////////////////////////////////////

char g_pFindOrigCode[8];
ULONG KiSystemService_hack_address=0;
PULONG  pSSDTKernel;
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_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 InitSWSSDT();

//////////////////////////////////////////////////////////////////////////

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();

  HookFindWindow();

  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();

  UnHookFindWindow();

  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");
      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;
}


//////////////////////////////////////////////////////////////////////////



void __declspec(naked) my_function_detour_KiFastCallEntry()
{
  __asm
  {
    cmp     ecx,10h
      jne     SSDT
      mov    edi,KeServiceDescriptorTable
      sub    edi,0x10
      jmp    [SSDTDW_reentry_address]

SSDT:
    mov    edi,KeServiceDescriptorTable
      add    edi,0x20
      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;
}



unsigned long AddMyServiceTable()
{


  ULONG  nSDTKerCallLen;



  __asm
  {
    pushad
      mov   eax,KeServiceDescriptorTable
      mov   _KeServiceDescriptorTable,eax
      sub   eax,0x40
      mov   ShadowTable,eax
      popad
  }
  nSDTKerCallLen  =  _KeServiceDescriptorTable->ntoskrnl.NumberOfServices;


  pSSDTKernel =  (PULONG)ExAllocatePool( NonPagedPool, nSDTKerCallLen*sizeof(ULONG) );
  if(!pSSDTKernel)
  {
    dprintf("AddMyServiceTable  alloc fail\n");
    return 0;
  }
  memset( (PVOID)pSSDTKernel, 0, nSDTKerCallLen*sizeof(ULONG));


  //填充新的SSDT表
  //
  RtlCopyMemory( (PVOID)pSSDTKernel,(PVOID)_KeServiceDescriptorTable->ntoskrnl.ServiceTableBase,nSDTKerCallLen*sizeof(ULONG) );


  RtlCopyMemory( (PVOID)&_KeServiceDescriptorTable->NotUse1,
    (PVOID)&_KeServiceDescriptorTable->ntoskrnl,sizeof(SERVICE_DESCRIPTOR_TABLE) );



  RtlCopyMemory( (PVOID)&ShadowTable->NotUse1,(PVOID)&ShadowTable->ntoskrnl,sizeof(SERVICE_DESCRIPTOR_TABLE)*2);

  WPOFF();
  RtlCopyMemory((PVOID)&_KeServiceDescriptorTable->NotUse1.ServiceTableBase, &pSSDTKernel, sizeof(ULONG));

  RtlCopyMemory((PVOID)&ShadowTable->NotUse1.ServiceTableBase, &pSSDTKernel, 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);

  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;
          RtlInitUnicodeString(&oldname,L"\\BaseNamedObjects\\dnx_57987675368241");
          if (pobj_name->Name.Buffer)
          {
            if (wcsstr(pobj_name->Name.Buffer,L"\\BaseNamedObjects\\dnx_57987675368241"))
            {
              dprintf("DragonNest pid %d ObjectNameInformation MyNtQueryObject name %wZ handle %08x\n",PsGetCurrentProcessId(),&(pobj_name->Name),(ULONG)ObjectHandle);
              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;
OBJECT_ATTRIBUTES tmpobjatus;

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;
  
  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"))
        {
            dprintf("fack mutex!\n");
            return STATUS_SUCCESS;
          __try
          {
            RtlInitUnicodeString(&tmpunicodestring,L"Global\\MutexDragonNest");
            RtlZeroMemory(wzCount,3*sizeof(WCHAR));
            wzCount[0]=(WCHAR)(0x30+g_Dra_count);
            g_Dra_count++;
            if(g_Dra_count==20)  g_Dra_count=0;

            RtlInitUnicodeString(&uni_count,wzCount);
        //    dprintf("uni_count %wZ\n",&uni_count);
        //    p_mutex_name->MaximumLength=0x100;
            RtlAppendUnicodeStringToString(&tmpunicodestring,&uni_count);

            dprintf("tmpunicodestring %wZ\n",&tmpunicodestring);

            InitializeObjectAttributes(&tmpobjatus,&tmpunicodestring,ObjectAttributes->Attributes,ObjectAttributes->RootDirectory,ObjectAttributes->SecurityDescriptor);

            //dprintf("mutex %S\n",p_mutex_name->Buffer);

            return OrgZwCreateMutant(MutantHandle,DesiredAccess,&tmpobjatus,InitialOwner);
            

          }
          __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();
}

//////////////////////////////////////////////////////////////////////////


//////////////////////////////////////////////////////////////////////////NtOpenProcess


ULONG OldNtProcessAdd;


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};

  PEPROCESS tempeprocess;

  if (!strcmp("DragonNest.exe",GetProcessNameFromEProc(0)) || !strcmp("dnlauncher.exe",GetProcessNameFromEProc(0)))
  {
    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();
    }

    
  }

  return NtOpenProcess(ProcessHandle,DesiredAccess,ObjectAttributes, ClientId);
}


ULONG Pass_NtOpenProcess()
{

  KIRQL oldIrql;
  ULONG  Address=0;

  Address = (ULONG)_KeServiceDescriptorTable->NotUse1.ServiceTableBase +  0x7A * 4;

  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) = 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;

NTSTATUS NewNtReadVirtualMemory(
                IN HANDLE               ProcessHandle,
                IN PVOID                BaseAddress,
                OUT PVOID               Buffer,
                IN ULONG                NumberOfBytesToRead,
                OUT PULONG              NumberOfBytesReaded OPTIONAL
                )
{

  NTSTATUS    status;
  PEPROCESS   pEProcess=0;
  char*       proname=0;

  if (!strcmp("DragonNest.exe",GetProcessNameFromEProc(0)))
  {
    if (!ProcessHandle)
    {
      return 0;

    }

    status = ObReferenceObjectByHandle(ProcessHandle,PROCESS_ALL_ACCESS,NULL,0,&pEProcess,NULL);

    if(!NT_SUCCESS(status))
    {
      dprintf("ObReferenceObjectByHandle fail! %08x \n",status);
      return 0;

    }
    ObDereferenceObject(pEProcess);
    proname=GetProcessNameFromEProc(pEProcess);
    if (PsGetCurrentProcessId()!=PsGetProcessId(pEProcess))
    {
      if (!strcmp("DragonNest.exe",proname) || !strcmp("MDL.exe",proname))
      {
        return STATUS_ACCESS_DENIED;
      } 
    }

  } 
  return OldNtReadVirtualMemoryAdd(ProcessHandle,BaseAddress,Buffer,NumberOfBytesToRead,NumberOfBytesReaded);

}



//////////////////////////////////////////////////////////////////////////NtReadVirtualMemory



ULONG Pass_NtReadVirtualMemory()
{
  KIRQL oldIrql;
  ULONG  Address=0;

  Address = (ULONG)_KeServiceDescriptorTable->NotUse1.ServiceTableBase + 0xBA * 4;    //得到NtReadVirtualMemory的服務地址

  (ULONG)OldNtReadVirtualMemoryAdd = *(ULONG*)Address;    //儲存此地址


  WPOFF();
  oldIrql = KeRaiseIrqlToDpcLevel();
  *((ULONG*)Address) = (ULONG)NewNtReadVirtualMemory;  //HOOK SSDT

  KeLowerIrql(oldIrql);
  WPON();
  return 1;
}

//反補丁,用於最後恢復用
VOID UnDetour_NtReadVirtualMemory()
{
  KIRQL oldIrql;
  ULONG  Address=0;

  Address = (ULONG)_KeServiceDescriptorTable->NotUse1.ServiceTableBase + 0xBA * 4;

  WPOFF();
  oldIrql = KeRaiseIrqlToDpcLevel();

  *((ULONG*)Address) = (ULONG)OldNtReadVirtualMemoryAdd;  //HOOK SSDT
  KeLowerIrql(oldIrql);
  WPON();
}
//////////////////////////////////////////////////////////////////////////



//////////////////////////////////////////////////////////////////////////
 
typedef NTSTATUS (*NTCREATESEMAPHORE)(
          OUT PHANDLE             SemaphoreHandle,
          IN ACCESS_MASK          DesiredAccess,
          IN POBJECT_ATTRIBUTES   ObjectAttributes OPTIONAL,
          IN ULONG                InitialCount,
          IN ULONG                MaximumCount );

NTCREATESEMAPHORE OrgNtCreateSemaphore;

ULONG semhandle=0;

NTSTATUS __stdcall MyNtCreateSemaphore(
                     OUT PHANDLE             SemaphoreHandle,
                     IN ACCESS_MASK          DesiredAccess,
                     IN POBJECT_ATTRIBUTES   ObjectAttributes OPTIONAL,
                     IN ULONG                InitialCount,
                     IN ULONG                MaximumCount 
                     )
{
  PUNICODE_STRING p_mutex_name;
  UNICODE_STRING uni_count={0};
//  WCHAR wzCount[3];

  NTSTATUS nTstatus;
  __try
  {
    if (!strcmp(GetProcessNameFromEProc(0),"DragonNest.exe"))
    {
      if(ObjectAttributes==NULL)
        return OrgNtCreateSemaphore(SemaphoreHandle,DesiredAccess,ObjectAttributes,InitialCount,MaximumCount);

      p_mutex_name=ObjectAttributes->ObjectName;

      if(p_mutex_name  )
      {
        if (p_mutex_name->Buffer)
        {
          //dprintf("Semaphore %S\n",p_mutex_name->Buffer);
          //dnx_57987675368241

          if (!wcscmp(p_mutex_name->Buffer,L"dnx_57987675368241"))
          {      
            /*          
            nTstatus=OrgNtCreateSemaphore(SemaphoreHandle,DesiredAccess,ObjectAttributes,InitialCount,MaximumCount);
            dprintf("Semaphore %S\n",p_mutex_name->Buffer);
            dprintf("OrgNtCreateSemaphore nTstatus %08x\n",nTstatus);
            //    semhandle=(ULONG)*SemaphoreHandle;
            //    dprintf("DragonNest pid %d MyNtCreateSemaphore dnx_57987675368241 handle %08x\n",PsGetCurrentProcessId(),semhandle);
            return nTstatus;
            */      

            
            while(1)
            {
              nTstatus=OrgNtCreateSemaphore(SemaphoreHandle,DesiredAccess,ObjectAttributes,InitialCount,MaximumCount);
              if (nTstatus==STATUS_OBJECT_NAME_EXISTS)
              {
                dprintf("STATUS_OBJECT_NAME_EXISTS\n");
                
              //  RtlZeroMemory(wzCount,3*sizeof(WCHAR));
              //  wzCount[0]=(WCHAR)(0x30+g_Sem_count);
                g_Sem_count++;
                if(g_Sem_count==20)  g_Sem_count=0;
                uni_count.Buffer=(PWSTR)ExAllocatePool(PagedPool,BUFFER_SIZE);
                uni_count.MaximumLength=BUFFER_SIZE;
                nTstatus=RtlIntegerToUnicodeString(g_Sem_count,10,&uni_count);
                  if (NT_SUCCESS(nTstatus))
                  {
                    p_mutex_name->MaximumLength=0x100;
                    RtlAppendUnicodeStringToString(p_mutex_name,&uni_count);
                  }
                  else
                  {
                    dprintf("RtlIntegerToUnicodeString error!\n");
                  }

              //  RtlInitUnicodeString(&uni_count,wzCount);
              }
              else
              {
                dprintf("CreateSemaphore sucess! Semaphore name %S\n",p_mutex_name->Buffer);
                return nTstatus;
              }

            }
            //  MaximumCount=10;
            //  dprintf("DragonNest CreateSemaphore MaximumCount :%d InitialCount :%d\n",MaximumCount,InitialCount);
            //  dprintf("fack mutex!\n");
            //  return STATUS_SUCCESS;
          }
        }

      }
    }
  }
  __except(1)
  {
    dprintf("MyNtCreateSemaphore error\n");
  }
  return OrgNtCreateSemaphore(SemaphoreHandle,DesiredAccess,ObjectAttributes,InitialCount,MaximumCount);
}

ULONG Pass_NtCreateSemaphore()
{
  KIRQL oldIrql;
  ULONG  Address=0;

  Address = (ULONG)_KeServiceDescriptorTable->NotUse1.ServiceTableBase + 51 * 4;    

  (ULONG)OrgNtCreateSemaphore = *(ULONG*)Address;    //儲存此地址

  WPOFF();
  oldIrql = KeRaiseIrqlToDpcLevel();
  *((ULONG*)Address) = (ULONG)MyNtCreateSemaphore;      //HOOK SSDT
  KeLowerIrql(oldIrql);
  WPON();
  return 1;
}

//反補丁,用於最後恢復用
VOID UnDetour_NtCreateSemaphore()
{
  KIRQL oldIrql;
  ULONG  Address=0;

  Address = (ULONG)_KeServiceDescriptorTable->NotUse1.ServiceTableBase + 51 * 4;

  WPOFF();
  oldIrql = KeRaiseIrqlToDpcLevel();

  *((ULONG*)Address) = (ULONG)OrgNtCreateSemaphore;  //HOOK SSDT
  KeLowerIrql(oldIrql);
  WPON();
}
//////////////////////////////////////////////////////////////////////////

typedef NTSTATUS (*NTRELEASESEMAPHORE)(

           IN HANDLE               SemaphoreHandle,
           IN ULONG                ReleaseCount,
           OUT PULONG              PreviousCount OPTIONAL );

NTRELEASESEMAPHORE OrgNtReleaseSemaphore;

NTSTATUS __stdcall MyNtReleaseSemaphore(
                    IN HANDLE               SemaphoreHandle,
                    IN ULONG                ReleaseCount,
                    OUT PULONG              PreviousCount OPTIONAL 
                    )
{
  UNICODE_STRING semaphorename;
  __try
  {
    if (!strcmp(GetProcessNameFromEProc(0),"DragonNest.exe"))
    {

      if (semhandle==(ULONG)SemaphoreHandle)
      {
        dprintf("DragonNest pid %d ReleaseSemaphore handle %08x\n",PsGetCurrentProcessId(),SemaphoreHandle);
      }
      
/*
      if (!GetObjectNameFromHandle(SemaphoreHandle,&semaphorename))
      {
        if (!wcscmp(semaphorename.Buffer,L"dnx_57987675368241"))
        {
          dprintf("DragonNest pid %d ReleaseSemaphore name %wZ\n",PsGetCurrentProcessId(),&semaphorename);
        }
        
      }
      */
    }
  }
  __except(1)
  {
    dprintf("MyNtReleaseSemaphore error!\n");
  }
  return OrgNtReleaseSemaphore(SemaphoreHandle,ReleaseCount,PreviousCount);
}

ULONG Pass_NtReleaseSemaphore()
{
  KIRQL oldIrql;
  ULONG  Address=0;

  Address = (ULONG)_KeServiceDescriptorTable->NotUse1.ServiceTableBase + 189 * 4;    

  (ULONG)OrgNtReleaseSemaphore = *(ULONG*)Address;    //儲存此地址

  WPOFF();
  oldIrql = KeRaiseIrqlToDpcLevel();
  *((ULONG*)Address) = (ULONG)MyNtReleaseSemaphore;      //HOOK SSDT
  KeLowerIrql(oldIrql);
  WPON();
  return 1;
}

//反補丁,用於最後恢復用
VOID UnDetour_NtReleaseSemaphore()
{
  KIRQL oldIrql;
  ULONG  Address=0;

  Address = (ULONG)_KeServiceDescriptorTable->NotUse1.ServiceTableBase + 189 * 4;

  WPOFF();
  oldIrql = KeRaiseIrqlToDpcLevel();

  *((ULONG*)Address) = (ULONG)OrgNtReleaseSemaphore;  //HOOK SSDT
  KeLowerIrql(oldIrql);
  WPON();
}
//////////////////////////////////////////////////////////////////////////


typedef  NTSTATUS (*NTOPENSEMAPHORE)(

        OUT PHANDLE             SemaphoreHandle,
        IN ACCESS_MASK          DesiredAccess,
        IN POBJECT_ATTRIBUTES   ObjectAttributes );

NTOPENSEMAPHORE OrgNtOpenSemaphore;

NTSTATUS __stdcall MyNtOpenSemaphore(
                   OUT PHANDLE             SemaphoreHandle,
                   IN ACCESS_MASK          DesiredAccess,
                   IN POBJECT_ATTRIBUTES   ObjectAttributes )
{
  PUNICODE_STRING p_mutex_name;
  __try
  {
    if (!strcmp(GetProcessNameFromEProc(0),"DragonNest.exe"))
    {
  //    dprintf("DragonNest pid %d OpenSemaphore\n",PsGetCurrentProcessId());

      p_mutex_name=ObjectAttributes->ObjectName;

      if(p_mutex_name  )
      {
        if (p_mutex_name->Buffer)
        {
          if (!wcscmp(p_mutex_name->Buffer,L"dnx_57987675368241"))
          {
            dprintf("DragonNest PID %d NtOpenSemaphore name %S\n",PsGetCurrentProcessId(),p_mutex_name->Buffer);
          }  
        }
      }

      
    }
  }
  __except(1)
  {
    dprintf("MyNtOpenSemaphore error!\n");
  }
  return OrgNtOpenSemaphore(SemaphoreHandle,DesiredAccess,ObjectAttributes);
}

ULONG Pass_NtOpenSemaphore()
{
  KIRQL oldIrql;
  ULONG  Address=0;

  Address = (ULONG)_KeServiceDescriptorTable->NotUse1.ServiceTableBase + 126 * 4;    

  (ULONG)OrgNtOpenSemaphore = *(ULONG*)Address;    //儲存此地址

  WPOFF();
  oldIrql = KeRaiseIrqlToDpcLevel();
  *((ULONG*)Address) = (ULONG)MyNtOpenSemaphore;      //HOOK SSDT
  KeLowerIrql(oldIrql);
  WPON();
  return 1;
}

//反補丁,用於最後恢復用
VOID UnDetour_NtOpenSemaphore()
{
  KIRQL oldIrql;
  ULONG  Address=0;

  Address = (ULONG)_KeServiceDescriptorTable->NotUse1.ServiceTableBase + 126 * 4;

  WPOFF();
  oldIrql = KeRaiseIrqlToDpcLevel();

  *((ULONG*)Address) = (ULONG)OrgNtOpenSemaphore;  //HOOK SSDT
  KeLowerIrql(oldIrql);
  WPON();
}
//////////////////////////////////////////////////////////////////////////


 
typedef NTSTATUS (*NTWAITFORSINGLEOBJECT)(

            IN HANDLE               ObjectHandle,
            IN BOOLEAN              Alertable,
            IN PLARGE_INTEGER       TimeOut );

NTWAITFORSINGLEOBJECT OrgNtWaitForSingleObject;

NTSTATUS __stdcall MyNtWaitForSingleObject(
  IN HANDLE               ObjectHandle,
  IN BOOLEAN              Alertable,
  IN PLARGE_INTEGER       TimeOut )
{
  UNICODE_STRING Objectname;
  __try
  {
    if (!strcmp(GetProcessNameFromEProc(0),"DragonNest.exe"))
    {
      if (semhandle==(ULONG)ObjectHandle)
      {
        dprintf("DragonNest pid %d MyNtWaitForSingleObject name %wZ TimeOut %d\n",PsGetCurrentProcessId(),&Objectname,TimeOut);
      }
      /*
      if (!GetObjectNameFromHandle(ObjectHandle,&Objectname))
      {
        if (!wcscmp(Objectname.Buffer,L"dnx_57987675368241"))
        {
          dprintf("DragonNest pid %d MyNtWaitForSingleObject name %wZ TimeOut %d\n",PsGetCurrentProcessId(),&Objectname,TimeOut);
        }
        
      }
      */
    }
  }
  __except(1)
  {
    dprintf("MyNtOpenSemaphore error!\n");
  }
  return OrgNtWaitForSingleObject(ObjectHandle,Alertable,TimeOut);
}

ULONG Pass_NtWaitForSingleObject()
{
  KIRQL oldIrql;
  ULONG  Address=0;

  Address = (ULONG)_KeServiceDescriptorTable->NotUse1.ServiceTableBase + 271 * 4;    

  (ULONG)OrgNtWaitForSingleObject = *(ULONG*)Address;    //儲存此地址

  WPOFF();
  oldIrql = KeRaiseIrqlToDpcLevel();
  *((ULONG*)Address) = (ULONG)MyNtWaitForSingleObject;      //HOOK SSDT
  KeLowerIrql(oldIrql);
  WPON();
  return 1;
}

//反補丁,用於最後恢復用
VOID UnDetour_NtWaitForSingleObject()
{
  KIRQL oldIrql;
  ULONG  Address=0;

  Address = (ULONG)_KeServiceDescriptorTable->NotUse1.ServiceTableBase + 271 * 4;

  WPOFF();
  oldIrql = KeRaiseIrqlToDpcLevel();

  *((ULONG*)Address) = (ULONG)OrgNtWaitForSingleObject;  //HOOK SSDT
  KeLowerIrql(oldIrql);
  WPON();
}






//////////////////////////////////////////////////////////////////////////

PEPROCESS crsEProc;

NTSTATUS HookFindWindow();

NTSTATUS UnHookFindWindow();

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;

//////////////////////////////////////////////////////////////////////////


typedef UINT_PTR (*NTUSERQUERYWINDOW)(
                    IN ULONG WindowHandle,
                    IN ULONG TypeInformation);

NTUSERQUERYWINDOW OldNtUserQueryWindow;


NTSTATUS FindNtUserQueryWindow()
{
  NTSTATUS status=0;

  KeAttachProcess(crsEProc);

  __try
  {
    if (KeServiceDescriptorTableShadow!=NULL)
    {
      OldNtUserQueryWindow = (NTUSERQUERYWINDOW)KeServiceDescriptorTableShadow[1].ServiceTableBase[0x1E3];

    }
  }
  __finally
  {
    KeDetachProcess(); 
  }


  return status ;


}


//////////////////////////////////////////////////////////////////////////

unsigned int getAddressOfShadowTable()
{
  unsigned int i;
  unsigned char *p;
  unsigned int dwordatbyte;

  p = (unsigned char*) KeAddSystemServiceTable;

  for(i = 0; i < 4096; i++, p++)
  {
    __try
    {
      dwordatbyte = *(unsigned int*)p;
    }
    __except(EXCEPTION_EXECUTE_HANDLER)
    {
      return 0;
    }

    if(MmIsAddressValid((PVOID)dwordatbyte))
    {
      if(memcmp((PVOID)dwordatbyte, &KeServiceDescriptorTable, 16) == 0)
      {
        if((PVOID)dwordatbyte == &KeServiceDescriptorTable)
        {
          continue;
        }

        return dwordatbyte;
      }
    }
  }

  return 0;
}

ULONG getShadowTable()
{
  KeServiceDescriptorTableShadow = (PSERVICE_DESCRIPTOR_TABLE) getAddressOfShadowTable();

  if(KeServiceDescriptorTableShadow == NULL)
  {
    dprintf("hooker.sys: Couldnt find shadowtable!\n");

    return FALSE;
  }
  else
  {
    dprintf("hooker.sys: Shadowtable has been found!\n");

    dprintf("hooker.sys: Shadowtable entries: %d\n", KeServiceDescriptorTableShadow[1].NumberOfServices);
    return TRUE;
  }
} 


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;
}



//6A 30       PUSH 0x30
//68 70D898BF    PUSH 0xBF98D870

unsigned long reentry_ntuserfinwind;
UCHAR g_oldcode_ntuserfindwind[8];

__declspec(naked) NTSTATUS _NtUserFindWindowEx(
  HANDLE hwndParent, 
  HANDLE hwndChild, 
  PUNICODE_STRING pstrClassName , 
  PUNICODE_STRING pstrWindowName , 
  DWORD dwType)

{

  __asm
  {
    push 0x30
    push 0xBF98D870
    jmp  [reentry_ntuserfinwind]
  }

}

NTSTATUS InitSWSSDT()
{
  NTSTATUS status;
  getShadowTable();

  


  status = PsLookupProcessByProcessId((HANDLE)GetCsrPid(), &crsEProc);
  if (!NT_SUCCESS( status ))
  {
    dprintf("PsLookupProcessByProcessId() error\n");

  }
  FindNtUserQueryWindow();
  return status;
}
char* GetProcessName( ULONG nProcessId)
{
  NTSTATUS rStutus;

  PEPROCESS       curproc;

  rStutus=PsLookupProcessByProcessId((HANDLE)nProcessId,&curproc);
  if (!rStutus)
  {
    ObDereferenceObject(curproc);
    return GetProcessNameFromEProc(curproc);
  }
  return 0;

}

NTSTATUS MyNtUserFindWindowEx(
                IN HANDLE hwndParent, 
                IN HANDLE hwndChild, 
                IN PUNICODE_STRING pstrClassName OPTIONAL, 
                IN PUNICODE_STRING pstrWindowName OPTIONAL, 
                IN DWORD dwType)
{
  ULONG result;
  UNICODE_STRING CLASSNAME;
  //UNICODE_STRING FIXCLASSNAME;
  ULONG FindProcessID;
  char* szFindProcessName;
  ULONG ProcessID;  

  result = _NtUserFindWindowEx(hwndParent, hwndChild, pstrClassName, pstrWindowName, dwType);

  if (!_stricmp("DragonNest.exe",GetProcessNameFromEProc(0)))
  {
     
    ProcessID = OldNtUserQueryWindow(result, 0);
    
    if (ProcessID!=(ULONG)PsGetCurrentProcessId())   
    {

      if (pstrClassName!=0)
      {
        RtlInitUnicodeString(&CLASSNAME,L"DRAGONNEST");
        if (!RtlCompareUnicodeString(pstrClassName,&CLASSNAME,FALSE))
        {

          return 0;  

        }
      }
      if (pstrWindowName!=0)
      {
        RtlInitUnicodeString(&CLASSNAME,L"龍之谷");
        if (!RtlCompareUnicodeString(pstrWindowName,&CLASSNAME,FALSE))
        {

          return 0;

        }
        RtlInitUnicodeString(&CLASSNAME,L"DML");
        if (!RtlCompareUnicodeString(pstrWindowName,&CLASSNAME,FALSE))
        {

          return 0;

        }
      }

    }
    
  }


  return result;
}





typedef NTSTATUS (*NTUSERFINDWINDOWEX)(
                     HANDLE hwndParent, 
                     HANDLE hwndChild, 
                     PUNICODE_STRING pstrClassName , 
                     PUNICODE_STRING pstrWindowName , 
                     DWORD dwType);


NTUSERFINDWINDOWEX          g_OriginalNtUserFindWindowEx;




NTSTATUS HookFindWindow()
{
  NTSTATUS status=0;

  unsigned char newcode[] = { 0xE9, 0x44, 0x33, 0x22, 0x11,0x90,0x90};


  KeAttachProcess(crsEProc);

  __try
  {
    if (KeServiceDescriptorTableShadow!=NULL)
    {
      g_OriginalNtUserFindWindowEx     = (NTUSERFINDWINDOWEX)KeServiceDescriptorTableShadow[1].ServiceTableBase[0x17A];
      memcpy(g_oldcode_ntuserfindwind,(UCHAR*)g_OriginalNtUserFindWindowEx,7);
      reentry_ntuserfinwind=(unsigned long)g_OriginalNtUserFindWindowEx+7;
      *( (unsigned long *)(&newcode[1]) ) = (unsigned long)MyNtUserFindWindowEx-(unsigned long)g_OriginalNtUserFindWindowEx-5;

    }
    else
      KeServiceDescriptorTableShadow=NULL;


    WPOFF();
    if (KeServiceDescriptorTableShadow!=NULL )
    {

      memcpy((UCHAR*)g_OriginalNtUserFindWindowEx,newcode,7);
    }

    WPON();
  }
  __finally
  {
    KeDetachProcess(); 
  }



  return status ;
}

NTSTATUS UnHookFindWindow()
{
  NTSTATUS status;

  KeAttachProcess(crsEProc);

  __try
  {
    WPOFF();

    if (KeServiceDescriptorTableShadow!=NULL) 
    {
      memcpy((UCHAR*)g_OriginalNtUserFindWindowEx,g_oldcode_ntuserfindwind,7);

    }

    WPON();
  }
  __finally
  {
    KeDetachProcess();
    Sleep(50);
  }
  return 0;
}



//////////////////////////////////////////////////////////////////////////

 

相關文章