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



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