GPK也没有啥特别。龙之谷多开检测和别的不一样。
#include "struct.h"
#include "FGPK.h" ////////////////////////////////////////////////////////////////////////// char g_pFindOrigCode[];
ULONG KiSystemService_hack_address=;
PULONG pSSDTKernel;
PSERVICE_DESCRIPTOR_TABLE_SHADOW _KeServiceDescriptorTable;
PSERVICE_DESCRIPTOR_TABLE_SHADOW ShadowTable;
unsigned long SSDT_reentry_address,SSDTDW_reentry_address; ULONG g_Dra_count=;
ULONG g_Sem_count=; //////////////////////////////////////////////////////////////////////////
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,
,
&ustrDevName,
FILE_DEVICE_UNKNOWN,
,
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 = ; 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 = ; 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 = ; /////////////////////////////////////
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=;
PUCHAR strSysenter; __asm{
mov ecx,0x176
rdmsr
mov uSysenter,eax //得到KiFastCallEntry地址
}
strSysenter=(PUCHAR)uSysenter;
for (i=;i<0x100;i++)
{
if (
findcode[]==strSysenter[i] &&
findcode[]==strSysenter[i+] &&
findcode[]==strSysenter[i+] &&
findcode[]==strSysenter[i+] )
{
break;
} } KiSystemService_hack_address=uSysenter+i; }
ULONG HookSysCall()
{
KIRQL oldIrql; unsigned char newcode[] = { 0xE9, 0x44, 0x33, 0x22, 0x11}; char *actual_function; int i = ; FindHackAddr(); if (KiSystemService_hack_address==)
{
dprintf("find hack address error!\n");
return ;
} actual_function =(char*) KiSystemService_hack_address; SSDT_reentry_address = KiSystemService_hack_address+0x20;
SSDTDW_reentry_address = KiSystemService_hack_address+0x5; *( (unsigned long *)(&newcode[]) ) = (ULONG)my_function_detour_KiFastCallEntry-KiSystemService_hack_address-; WPOFF();
oldIrql = KeRaiseIrqlToDpcLevel();
for(i=;i < ;i++)
{
g_pFindOrigCode[i] = actual_function[i];
actual_function[i] = newcode[i];
}
KeLowerIrql(oldIrql);
WPON(); return ;
} 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 ;
}
memset( (PVOID)pSSDTKernel, , 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)*); WPOFF();
RtlCopyMemory((PVOID)&_KeServiceDescriptorTable->NotUse1.ServiceTableBase, &pSSDTKernel, sizeof(ULONG)); RtlCopyMemory((PVOID)&ShadowTable->NotUse1.ServiceTableBase, &pSSDTKernel, sizeof(ULONG)); WPON(); return ;
} 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=;i < ;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 = {};
ULONG TempReturnLength; pObjectInformation=ExAllocatePool(PagedPool,0x100);
RtlZeroMemory(pObjectInformation,0x100); __try
{
nTstatus = ObReferenceObjectByHandle( Objecthandle,
,
NULL,
,
&Object,
&HandleInformation ); if (NT_SUCCESS( nTstatus ))
{
nTstatus = ObQueryNameString( Object,
(POBJECT_NAME_INFORMATION)pObjectInformation,
0x100,
&TempReturnLength
); RtlCopyUnicodeString(filename,(PUNICODE_STRING)&(pObjectInformation->Name));
return ;
} }
__except()
{
dprintf("GetObjectNameFromHandle error!\n");
} return -; }
//******************************************************************************************************************** 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(),"DragonNest.exe")==)
{
//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()
{
dprintf("MyNtQueryObject error!\n");
} return nTstatus;
} ULONG Pass_NtQueryObject()
{
KIRQL oldIrql;
ULONG Address=; Address = (ULONG)_KeServiceDescriptorTable->NotUse1.ServiceTableBase + * ; (ULONG)OrgNtQueryObject = *(ULONG*)Address; //保存此地址 WPOFF();
oldIrql = KeRaiseIrqlToDpcLevel();
*((ULONG*)Address) = (ULONG)MyNtQueryObject; //HOOK SSDT
KeLowerIrql(oldIrql);
WPON();
return ;
} //反补丁,用于最后恢复用
VOID UnDetour_NtQueryObject()
{
KIRQL oldIrql;
ULONG Address=; Address = (ULONG)_KeServiceDescriptorTable->NotUse1.ServiceTableBase + * ; 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[];
UNICODE_STRING tmpunicodestring; if (!strcmp(GetProcessNameFromEProc(),"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,*sizeof(WCHAR));
wzCount[]=(WCHAR)(0x30+g_Dra_count);
g_Dra_count++;
if(g_Dra_count==) g_Dra_count=; 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()
{
dprintf("MyZwCreateMutant error\n");
} }
} }
} return OrgZwCreateMutant(MutantHandle,DesiredAccess,ObjectAttributes,InitialOwner);
} ULONG Pass_NtCreateMutant()
{
KIRQL oldIrql;
ULONG Address=; Address = (ULONG)_KeServiceDescriptorTable->NotUse1.ServiceTableBase + * ; (ULONG)OrgZwCreateMutant = *(ULONG*)Address; //保存此地址 WPOFF();
oldIrql = KeRaiseIrqlToDpcLevel();
*((ULONG*)Address) = (ULONG)MyZwCreateMutant; //HOOK SSDT
KeLowerIrql(oldIrql);
WPON();
return ;
} //反补丁,用于最后恢复用
VOID UnDetour_NtCreateMutant()
{
KIRQL oldIrql;
ULONG Address=; Address = (ULONG)_KeServiceDescriptorTable->NotUse1.ServiceTableBase + * ; 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[];
PVOID Reserved2[];
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(),"DragonNest.exe") || !_stricmp(GetProcessNameFromEProc(),"dnlauncher.exe"))
{ if( NT_SUCCESS(ntStatus))
{ if(SystemInformationClass == )
{ 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 = ;
}
}
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=; Address = (ULONG)_KeServiceDescriptorTable->NotUse1.ServiceTableBase + * ; (ULONG)OldNtQuerySystemInformation = *(ULONG*)Address; //保存此地址 WPOFF();
oldIrql = KeRaiseIrqlToDpcLevel();
*((ULONG*)Address) = (ULONG)NewNtQuerySystemInformation; //HOOK SSDT
KeLowerIrql(oldIrql);
WPON();
return ;
} //反补丁,用于最后恢复用
VOID UnDetour_NtQuerySystemInformation()
{
KIRQL oldIrql;
ULONG Address=; Address = (ULONG)_KeServiceDescriptorTable->NotUse1.ServiceTableBase + * ; 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={};
BOOLEAN ObjectNamePresent;
BOOLEAN ClientIdPresent;
ACCESS_STATE AccessState;
AUX_ACCESS_DATA AuxData;
ULONG Attributes;
LUID SeDebugPrivilege = {}; PEPROCESS tempeprocess; if (!strcmp("DragonNest.exe",GetProcessNameFromEProc()) || !strcmp("dnlauncher.exe",GetProcessNameFromEProc()))
{
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=; Address = (ULONG)_KeServiceDescriptorTable->NotUse1.ServiceTableBase + 0x7A * ; OldNtProcessAdd = *(ULONG*)Address; WPOFF();
oldIrql = KeRaiseIrqlToDpcLevel(); *((ULONG*)Address) = (ULONG)NewNtOpenProcess; //HOOK SSDT
KeLowerIrql(oldIrql);
WPON(); return ;
} VOID UnDetour_NtOpenProcess()
{
KIRQL oldIrql;
ULONG Address=; Address = (ULONG)_KeServiceDescriptorTable->NotUse1.ServiceTableBase + 0x7A * ; 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=;
char* proname=; if (!strcmp("DragonNest.exe",GetProcessNameFromEProc()))
{
if (!ProcessHandle)
{
return ; } status = ObReferenceObjectByHandle(ProcessHandle,PROCESS_ALL_ACCESS,NULL,,&pEProcess,NULL); if(!NT_SUCCESS(status))
{
dprintf("ObReferenceObjectByHandle fail! %08x \n",status);
return ; }
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=; Address = (ULONG)_KeServiceDescriptorTable->NotUse1.ServiceTableBase + 0xBA * ; //得到NtReadVirtualMemory的服务地址 (ULONG)OldNtReadVirtualMemoryAdd = *(ULONG*)Address; //保存此地址 WPOFF();
oldIrql = KeRaiseIrqlToDpcLevel();
*((ULONG*)Address) = (ULONG)NewNtReadVirtualMemory; //HOOK SSDT KeLowerIrql(oldIrql);
WPON();
return ;
} //反补丁,用于最后恢复用
VOID UnDetour_NtReadVirtualMemory()
{
KIRQL oldIrql;
ULONG Address=; Address = (ULONG)_KeServiceDescriptorTable->NotUse1.ServiceTableBase + 0xBA * ; 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=; 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={};
// WCHAR wzCount[3]; NTSTATUS nTstatus;
__try
{
if (!strcmp(GetProcessNameFromEProc(),"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()
{
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==) g_Sem_count=;
uni_count.Buffer=(PWSTR)ExAllocatePool(PagedPool,BUFFER_SIZE);
uni_count.MaximumLength=BUFFER_SIZE;
nTstatus=RtlIntegerToUnicodeString(g_Sem_count,,&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()
{
dprintf("MyNtCreateSemaphore error\n");
}
return OrgNtCreateSemaphore(SemaphoreHandle,DesiredAccess,ObjectAttributes,InitialCount,MaximumCount);
} ULONG Pass_NtCreateSemaphore()
{
KIRQL oldIrql;
ULONG Address=; Address = (ULONG)_KeServiceDescriptorTable->NotUse1.ServiceTableBase + * ; (ULONG)OrgNtCreateSemaphore = *(ULONG*)Address; //保存此地址 WPOFF();
oldIrql = KeRaiseIrqlToDpcLevel();
*((ULONG*)Address) = (ULONG)MyNtCreateSemaphore; //HOOK SSDT
KeLowerIrql(oldIrql);
WPON();
return ;
} //反补丁,用于最后恢复用
VOID UnDetour_NtCreateSemaphore()
{
KIRQL oldIrql;
ULONG Address=; Address = (ULONG)_KeServiceDescriptorTable->NotUse1.ServiceTableBase + * ; 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(),"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()
{
dprintf("MyNtReleaseSemaphore error!\n");
}
return OrgNtReleaseSemaphore(SemaphoreHandle,ReleaseCount,PreviousCount);
} ULONG Pass_NtReleaseSemaphore()
{
KIRQL oldIrql;
ULONG Address=; Address = (ULONG)_KeServiceDescriptorTable->NotUse1.ServiceTableBase + * ; (ULONG)OrgNtReleaseSemaphore = *(ULONG*)Address; //保存此地址 WPOFF();
oldIrql = KeRaiseIrqlToDpcLevel();
*((ULONG*)Address) = (ULONG)MyNtReleaseSemaphore; //HOOK SSDT
KeLowerIrql(oldIrql);
WPON();
return ;
} //反补丁,用于最后恢复用
VOID UnDetour_NtReleaseSemaphore()
{
KIRQL oldIrql;
ULONG Address=; Address = (ULONG)_KeServiceDescriptorTable->NotUse1.ServiceTableBase + * ; 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(),"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()
{
dprintf("MyNtOpenSemaphore error!\n");
}
return OrgNtOpenSemaphore(SemaphoreHandle,DesiredAccess,ObjectAttributes);
} ULONG Pass_NtOpenSemaphore()
{
KIRQL oldIrql;
ULONG Address=; Address = (ULONG)_KeServiceDescriptorTable->NotUse1.ServiceTableBase + * ; (ULONG)OrgNtOpenSemaphore = *(ULONG*)Address; //保存此地址 WPOFF();
oldIrql = KeRaiseIrqlToDpcLevel();
*((ULONG*)Address) = (ULONG)MyNtOpenSemaphore; //HOOK SSDT
KeLowerIrql(oldIrql);
WPON();
return ;
} //反补丁,用于最后恢复用
VOID UnDetour_NtOpenSemaphore()
{
KIRQL oldIrql;
ULONG Address=; Address = (ULONG)_KeServiceDescriptorTable->NotUse1.ServiceTableBase + * ; 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(),"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()
{
dprintf("MyNtOpenSemaphore error!\n");
}
return OrgNtWaitForSingleObject(ObjectHandle,Alertable,TimeOut);
} ULONG Pass_NtWaitForSingleObject()
{
KIRQL oldIrql;
ULONG Address=; Address = (ULONG)_KeServiceDescriptorTable->NotUse1.ServiceTableBase + * ; (ULONG)OrgNtWaitForSingleObject = *(ULONG*)Address; //保存此地址 WPOFF();
oldIrql = KeRaiseIrqlToDpcLevel();
*((ULONG*)Address) = (ULONG)MyNtWaitForSingleObject; //HOOK SSDT
KeLowerIrql(oldIrql);
WPON();
return ;
} //反补丁,用于最后恢复用
VOID UnDetour_NtWaitForSingleObject()
{
KIRQL oldIrql;
ULONG Address=; Address = (ULONG)_KeServiceDescriptorTable->NotUse1.ServiceTableBase + * ; 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[];
} _SYSTEM_HANDLE_INFORMATION_EX, *PSYSTEM_HANDLE_INFORMATION_EX; ////////////////////////////////////////////////////////////////////////// typedef UINT_PTR (*NTUSERQUERYWINDOW)(
IN ULONG WindowHandle,
IN ULONG TypeInformation); NTUSERQUERYWINDOW OldNtUserQueryWindow; NTSTATUS FindNtUserQueryWindow()
{
NTSTATUS status=; KeAttachProcess(crsEProc); __try
{
if (KeServiceDescriptorTableShadow!=NULL)
{
OldNtUserQueryWindow = (NTUSERQUERYWINDOW)KeServiceDescriptorTableShadow[].ServiceTableBase[0x1E3]; }
}
__finally
{
KeDetachProcess();
} return status ; } ////////////////////////////////////////////////////////////////////////// unsigned int getAddressOfShadowTable()
{
unsigned int i;
unsigned char *p;
unsigned int dwordatbyte; p = (unsigned char*) KeAddSystemServiceTable; for(i = ; i < ; i++, p++)
{
__try
{
dwordatbyte = *(unsigned int*)p;
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
return ;
} if(MmIsAddressValid((PVOID)dwordatbyte))
{
if(memcmp((PVOID)dwordatbyte, &KeServiceDescriptorTable, ) == )
{
if((PVOID)dwordatbyte == &KeServiceDescriptorTable)
{
continue;
} return dwordatbyte;
}
}
} return ;
} 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[].NumberOfServices);
return TRUE;
}
} PVOID GetInfoTable(ULONG ATableType)
{
ULONG mSize = 0x4000;
PVOID mPtr = NULL;
NTSTATUS St;
do
{
mPtr = ExAllocatePool(PagedPool, mSize);
memset(mPtr, , mSize);
if (mPtr)
{
St = ZwQuerySystemInformation(ATableType, mPtr, mSize, NULL);
} else return NULL;
if (St == STATUS_INFO_LENGTH_MISMATCH)
{
ExFreePool(mPtr);
mSize = mSize * ;
}
} while (St == STATUS_INFO_LENGTH_MISMATCH);
if (St == STATUS_SUCCESS) return mPtr;
ExFreePool(mPtr);
return NULL;
} HANDLE GetCsrPid()
{
HANDLE Process, hObject;
HANDLE CsrId = (HANDLE);
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 = ; r < Handles->NumberOfHandles; r++)
{
if (Handles->Information[r].ObjectTypeNumber == ) //Port object
{
InitializeObjectAttributes(&obj, NULL, OBJ_KERNEL_HANDLE, NULL, NULL); cid.UniqueProcess = (HANDLE)Handles->Information[r].ProcessId;
cid.UniqueThread = ; if (NT_SUCCESS(NtOpenProcess(&Process, PROCESS_DUP_HANDLE, &obj, &cid)))
{
if (NT_SUCCESS(ZwDuplicateObject(Process, (HANDLE)Handles->Information[r].Handle,NtCurrentProcess(), &hObject, , , DUPLICATE_SAME_ACCESS)))
{
if (NT_SUCCESS(ZwQueryObject(hObject, ObjectNameInformation, ObjName, 0x100, NULL)))
{
if (ObjName->Name.Buffer && !wcsncmp(L"\\Windows\\ApiPort", ObjName->Name.Buffer, ))
{
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[]; __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 ; } 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()))
{ ProcessID = OldNtUserQueryWindow(result, ); if (ProcessID!=(ULONG)PsGetCurrentProcessId())
{ if (pstrClassName!=)
{
RtlInitUnicodeString(&CLASSNAME,L"DRAGONNEST");
if (!RtlCompareUnicodeString(pstrClassName,&CLASSNAME,FALSE))
{ return ; }
}
if (pstrWindowName!=)
{
RtlInitUnicodeString(&CLASSNAME,L"龙之谷");
if (!RtlCompareUnicodeString(pstrWindowName,&CLASSNAME,FALSE))
{ return ; }
RtlInitUnicodeString(&CLASSNAME,L"DML");
if (!RtlCompareUnicodeString(pstrWindowName,&CLASSNAME,FALSE))
{ return ; }
} } } return result;
} typedef NTSTATUS (*NTUSERFINDWINDOWEX)(
HANDLE hwndParent,
HANDLE hwndChild,
PUNICODE_STRING pstrClassName ,
PUNICODE_STRING pstrWindowName ,
DWORD dwType); NTUSERFINDWINDOWEX g_OriginalNtUserFindWindowEx; NTSTATUS HookFindWindow()
{
NTSTATUS status=; unsigned char newcode[] = { 0xE9, 0x44, 0x33, 0x22, 0x11,0x90,0x90}; KeAttachProcess(crsEProc); __try
{
if (KeServiceDescriptorTableShadow!=NULL)
{
g_OriginalNtUserFindWindowEx = (NTUSERFINDWINDOWEX)KeServiceDescriptorTableShadow[].ServiceTableBase[0x17A];
memcpy(g_oldcode_ntuserfindwind,(UCHAR*)g_OriginalNtUserFindWindowEx,);
reentry_ntuserfinwind=(unsigned long)g_OriginalNtUserFindWindowEx+;
*( (unsigned long *)(&newcode[]) ) = (unsigned long)MyNtUserFindWindowEx-(unsigned long)g_OriginalNtUserFindWindowEx-; }
else
KeServiceDescriptorTableShadow=NULL; WPOFF();
if (KeServiceDescriptorTableShadow!=NULL )
{ memcpy((UCHAR*)g_OriginalNtUserFindWindowEx,newcode,);
} WPON();
}
__finally
{
KeDetachProcess();
} return status ;
} NTSTATUS UnHookFindWindow()
{
NTSTATUS status; KeAttachProcess(crsEProc); __try
{
WPOFF(); if (KeServiceDescriptorTableShadow!=NULL)
{
memcpy((UCHAR*)g_OriginalNtUserFindWindowEx,g_oldcode_ntuserfindwind,); } WPON();
}
__finally
{
KeDetachProcess();
Sleep();
}
return ;
} //////////////////////////////////////////////////////////////////////////