游戏保护大放送之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) 打赏
取消

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

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

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

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

评论

    暂无评论...