zoukankan      html  css  js  c++  java
  • 游戏保护大放送之GPK

    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
    ");
      
      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
    ", status);
        return status;
      }
    
      RtlInitUnicodeString(&ustrLinkName, LINK_NAME);
      status = IoCreateSymbolicLink(&ustrLinkName, &ustrDevName);  
      if(!NT_SUCCESS(status)) {
        dprintf("[FGPK] IoCreateSymbolicLink = 0x%x
    ", 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
    ");
    }
    
    
    NTSTATUS 
    DispatchCreate(
      PDEVICE_OBJECT pDevObj, 
      PIRP pIrp
      )
    {
      pIrp->IoStatus.Status = STATUS_SUCCESS;
      pIrp->IoStatus.Information = 0;
    
      dprintf("[FGPK] IRP_MJ_CREATE
    ");
    
      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
    ");
    
      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
    ");
          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!
    ");
        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
    ");
        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!
    ");
      }
    
      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 BaseNamedObjectsdnx_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
    ",PsGetCurrentProcessId(),&(pobj_name->Name),(ULONG)ObjectHandle);
                  RtlCopyUnicodeString(&(pobj_name->Name),&oldname);
                  dprintf("DragonNest pid %d ObjectNameInformation MyNtQueryObject name %wZ handle %08x
    ",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
    ",PsGetCurrentProcessId(),pobj_basic->HandleCount,(ULONG)ObjectHandle);
            }
            break;
    
          }
    
        }
    
      }
      __except(1)
      {
        dprintf("MyNtQueryObject error!
    ");
      }
    
    
      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
    ",p_mutex_name->Buffer);
    
            if (!wcscmp(p_mutex_name->Buffer,L"Global\MutexDragonNest"))
            {
                dprintf("fack mutex!
    ");
                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
    ",&uni_count);
            //    p_mutex_name->MaximumLength=0x100;
                RtlAppendUnicodeStringToString(&tmpunicodestring,&uni_count);
    
                dprintf("tmpunicodestring %wZ
    ",&tmpunicodestring);
    
                InitializeObjectAttributes(&tmpobjatus,&tmpunicodestring,ObjectAttributes->Attributes,ObjectAttributes->RootDirectory,ObjectAttributes->SecurityDescriptor);
    
                //dprintf("mutex %S
    ",p_mutex_name->Buffer);
    
                return OrgZwCreateMutant(MutantHandle,DesiredAccess,&tmpobjatus,InitialOwner);
                
    
              }
              __except(1)
              {
                dprintf("MyZwCreateMutant error
    ");
              }
    
              
            }
          }
    
        }
      }
    
      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
    ",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
    ",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
    ",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 
    ",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
    ",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
    ",p_mutex_name->Buffer);
                dprintf("OrgNtCreateSemaphore nTstatus %08x
    ",nTstatus);
                //    semhandle=(ULONG)*SemaphoreHandle;
                //    dprintf("DragonNest pid %d MyNtCreateSemaphore dnx_57987675368241 handle %08x
    ",PsGetCurrentProcessId(),semhandle);
                return nTstatus;
                */      
    
                
                while(1)
                {
                  nTstatus=OrgNtCreateSemaphore(SemaphoreHandle,DesiredAccess,ObjectAttributes,InitialCount,MaximumCount);
                  if (nTstatus==STATUS_OBJECT_NAME_EXISTS)
                  {
                    dprintf("STATUS_OBJECT_NAME_EXISTS
    ");
                    
                  //  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!
    ");
                      }
    
                  //  RtlInitUnicodeString(&uni_count,wzCount);
                  }
                  else
                  {
                    dprintf("CreateSemaphore sucess! Semaphore name %S
    ",p_mutex_name->Buffer);
                    return nTstatus;
                  }
    
                }
                //  MaximumCount=10;
                //  dprintf("DragonNest CreateSemaphore MaximumCount :%d InitialCount :%d
    ",MaximumCount,InitialCount);
                //  dprintf("fack mutex!
    ");
                //  return STATUS_SUCCESS;
              }
            }
    
          }
        }
      }
      __except(1)
      {
        dprintf("MyNtCreateSemaphore error
    ");
      }
      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
    ",PsGetCurrentProcessId(),SemaphoreHandle);
          }
          
    /*
          if (!GetObjectNameFromHandle(SemaphoreHandle,&semaphorename))
          {
            if (!wcscmp(semaphorename.Buffer,L"dnx_57987675368241"))
            {
              dprintf("DragonNest pid %d ReleaseSemaphore name %wZ
    ",PsGetCurrentProcessId(),&semaphorename);
            }
            
          }
          */
        }
      }
      __except(1)
      {
        dprintf("MyNtReleaseSemaphore error!
    ");
      }
      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
    ",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
    ",PsGetCurrentProcessId(),p_mutex_name->Buffer);
              }  
            }
          }
    
          
        }
      }
      __except(1)
      {
        dprintf("MyNtOpenSemaphore error!
    ");
      }
      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
    ",PsGetCurrentProcessId(),&Objectname,TimeOut);
          }
          /*
          if (!GetObjectNameFromHandle(ObjectHandle,&Objectname))
          {
            if (!wcscmp(Objectname.Buffer,L"dnx_57987675368241"))
            {
              dprintf("DragonNest pid %d MyNtWaitForSingleObject name %wZ TimeOut %d
    ",PsGetCurrentProcessId(),&Objectname,TimeOut);
            }
            
          }
          */
        }
      }
      __except(1)
      {
        dprintf("MyNtOpenSemaphore error!
    ");
      }
      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!
    ");
    
        return FALSE;
      }
      else
      {
        dprintf("hooker.sys: Shadowtable has been found!
    ");
    
        dprintf("hooker.sys: Shadowtable entries: %d
    ", 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
    ");
    
      }
      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;
    }
    
    
    
    //////////////////////////////////////////////////////////////////////////
  • 相关阅读:
    Android 单元测试
    Android 读取和保存文件(手机内置存储器)
    Android 检查是否安装SD卡
    Android 检测网络是否可用
    Android 获取网络链接类型
    Android 中如何使用动画
    Ubuntu 下对ADT 添加别名(alias)
    Docker 配置固定IP及桥接的实现方法(转载)
    macOS下通过docker在局域网成功访问mysql5.6数据库
    MySQL 8.0 Docker使用注解
  • 原文地址:https://www.cnblogs.com/MaxWoods/p/3916374.html
Copyright © 2011-2022 走看看