游戏保护大放送之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\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;
}
 
 
 
//////////////////////////////////////////////////////////////////////////
赞(0) 打赏
取消

感谢您的支持,我会继续努力的!

扫码支持
扫码打赏,您说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

分享从这里开始,精彩与您同在

评论

    暂无评论...