首页
社区
课程
招聘
[原创]游戏保护大放送之GPK
发表于: 2012-5-7 21:59 31009

[原创]游戏保护大放送之GPK

2012-5-7 21:59
31009
本人不保证此办法现在还生效!蓝屏死机于本人无关!

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



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

[培训]《安卓高级研修班(网课)》月薪三万计划,掌握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法

收藏
免费 7
支持
分享
最新回复 (31)
雪    币: 120
活跃值: (160)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
我还以为遇到广告了。没想到来了一系列的过游戏保护。
2012-5-7 22:44
0
雪    币: 1015
活跃值: (235)
能力值: ( LV12,RANK:440 )
在线值:
发帖
回帖
粉丝
3
顶楼主,建议楼主采用附件形式,方便的话稍微加点注释
2012-5-7 22:47
0
雪    币: 48
活跃值: (491)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
4
版主大人,这个东西还是点到为止。只做技术交流,如果直接来附加怕别有用心的人利用,望谅解。
2012-5-7 22:49
0
雪    币: 160
活跃值: (26)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
广告贴一个  不知道有什么好发的 都是抄来抄去 重载SSDT表 基本可以过来HS TP GPK等
2012-5-7 22:51
0
雪    币: 48
活跃值: (491)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
6
怎么就没有见你发一篇呢?
2012-5-7 23:05
0
雪    币: 585
活跃值: (568)
能力值: ( LV13,RANK:290 )
在线值:
发帖
回帖
粉丝
7
看跟做可是不一样的,,顶下楼主,
2012-5-7 23:47
0
雪    币: 585
活跃值: (568)
能力值: ( LV13,RANK:290 )
在线值:
发帖
回帖
粉丝
8
看不要钱,
做可是要钱的,哈哈
2012-5-7 23:51
0
雪    币: 27
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
嘿嘿 楼上 言之有理!
2012-5-8 00:24
0
雪    币: 7039
活跃值: (4194)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
希望楼主办学校,专教写驱动
2012-5-8 01:10
0
雪    币: 123
活跃值: (50)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
站位,留名,学习,感谢!
2012-5-8 08:26
0
雪    币: 62
活跃值: (72)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
12
感谢楼主放血
2012-5-8 09:57
0
雪    币: 71
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
希望楼主办学校,专教写驱动
2012-5-8 22:18
0
雪    币: 219
活跃值: (738)
能力值: (RANK:290 )
在线值:
发帖
回帖
粉丝
14
code   code  code
2012-5-9 06:59
0
雪    币: 123
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
15
不错,很感谢楼主分享
2012-5-9 09:31
0
雪    币: 51
活跃值: (15)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
16
希望楼主找到工作啊。。牛人啊。
2012-5-9 09:34
0
雪    币: 308
活跃值: (25)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
17
支持楼主放血精神。。。。
2012-5-9 11:32
0
雪    币: 22
活跃值: (423)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
18
这是神马情况啊 这是!!
2012-5-9 18:09
0
雪    币: 51
活跃值: (61)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
19
自己写外挂算了
2012-5-9 18:42
0
雪    币: 24
活跃值: (1353)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
20
感谢楼主,对于那些白吃萝卜还嫌辣的人,就不要受他的影响,支持楼主开源精神
2012-5-9 18:59
0
雪    币: 177
活跃值: (278)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
21
GPK有个漏洞,其实可以很简单的过的
2012-5-10 16:56
0
雪    币: 235
活跃值: (25)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
22
好象R3下还有对调试器的检测,普通的OD + StringOD也不行!
2012-8-11 18:36
0
雪    币: 334
活跃值: (92)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
23
作个记号,以后回来看
2012-12-19 23:31
0
雪    币: 157
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
24
建议楼主说下思路
2013-1-5 16:59
0
雪    币: 439
活跃值: (1279)
能力值: ( LV8,RANK:120 )
在线值:
发帖
回帖
粉丝
25
支持 还少4个字
2013-1-6 08:53
0
游客
登录 | 注册 方可回帖
返回
//