游戏保护大放送之GPK
GPK也没有啥特别。龙之谷多开检测和别的不一样。
#include "struct.h" #include "FGPK.h" ////////////////////////////////////////////////////////////////////////// char g_pFindOrigCode[8]; ULONG KiSystemService_hack_address=0; PULONG pSSDTKernel; PSERVICE_DESCRIPTOR_TABLE_SHADOW _KeServiceDescriptorTable; PSERVICE_DESCRIPTOR_TABLE_SHADOW ShadowTable; unsigned long SSDT_reentry_address,SSDTDW_reentry_address; ULONG g_Dra_count=0; ULONG g_Sem_count=0; ////////////////////////////////////////////////////////////////////////// void RePlaceSSDT(); void RestoreSSDT(); ULONG Pass_NtCreateMutant(); VOID UnDetour_NtCreateMutant(); ULONG Pass_NtQuerySystemInformation(); VOID UnDetour_NtQuerySystemInformation(); ULONG Pass_NtOpenProcess(); VOID UnDetour_NtOpenProcess(); NTSTATUS HookFindWindow(); NTSTATUS UnHookFindWindow(); ULONG Pass_NtReadVirtualMemory(); VOID UnDetour_NtReadVirtualMemory(); ULONG Pass_NtCreateSemaphore(); VOID UnDetour_NtCreateSemaphore(); ULONG Pass_NtReleaseSemaphore(); VOID UnDetour_NtReleaseSemaphore(); ULONG Pass_NtOpenSemaphore(); VOID UnDetour_NtOpenSemaphore(); ULONG Pass_NtQueryObject(); VOID UnDetour_NtQueryObject(); ULONG Pass_NtWaitForSingleObject(); VOID UnDetour_NtWaitForSingleObject(); NTSTATUS InitSWSSDT(); ////////////////////////////////////////////////////////////////////////// NTSTATUS DriverEntry( PDRIVER_OBJECT pDriverObj, PUNICODE_STRING pRegistryString ) { NTSTATUS status = STATUS_SUCCESS; UNICODE_STRING ustrLinkName; UNICODE_STRING ustrDevName; PDEVICE_OBJECT pDevObj; dprintf("[FGPK] DriverEntry\n"); pDriverObj->MajorFunction[IRP_MJ_CREATE] = DispatchCreate; pDriverObj->MajorFunction[IRP_MJ_CLOSE] = DispatchClose; pDriverObj->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchIoctl; pDriverObj->DriverUnload = DriverUnload; RtlInitUnicodeString(&ustrDevName, DEVICE_NAME); status = IoCreateDevice(pDriverObj, 0, &ustrDevName, FILE_DEVICE_UNKNOWN, 0, FALSE, &pDevObj); if(!NT_SUCCESS(status)) { dprintf("[FGPK] IoCreateDevice = 0x%x\n", status); return status; } RtlInitUnicodeString(&ustrLinkName, LINK_NAME); status = IoCreateSymbolicLink(&ustrLinkName, &ustrDevName); if(!NT_SUCCESS(status)) { dprintf("[FGPK] IoCreateSymbolicLink = 0x%x\n", status); IoDeleteDevice(pDevObj); return status; } // // 添加执行代码 // RePlaceSSDT(); InitSWSSDT(); Pass_NtQueryObject(); Pass_NtCreateMutant(); Pass_NtCreateSemaphore(); // Pass_NtReleaseSemaphore(); // Pass_NtOpenSemaphore(); // Pass_NtWaitForSingleObject(); Pass_NtQuerySystemInformation(); Pass_NtOpenProcess(); Pass_NtReadVirtualMemory(); HookFindWindow(); return STATUS_SUCCESS; } VOID DriverUnload( PDRIVER_OBJECT pDriverObj ) { UNICODE_STRING strLink; RtlInitUnicodeString(&strLink, LINK_NAME); // // 添加卸载代码 // // UnDetour_NtOpenSemaphore(); // UnDetour_NtWaitForSingleObject(); UnDetour_NtCreateSemaphore(); // UnDetour_NtReleaseSemaphore(); UnDetour_NtCreateMutant(); UnDetour_NtQueryObject(); UnDetour_NtQuerySystemInformation(); UnDetour_NtOpenProcess(); UnDetour_NtReadVirtualMemory(); UnHookFindWindow(); RestoreSSDT(); // Sleep(5000); IoDeleteSymbolicLink(&strLink); IoDeleteDevice(pDriverObj->DeviceObject); dprintf("[FGPK] Unloaded\n"); } NTSTATUS DispatchCreate( PDEVICE_OBJECT pDevObj, PIRP pIrp ) { pIrp->IoStatus.Status = STATUS_SUCCESS; pIrp->IoStatus.Information = 0; dprintf("[FGPK] IRP_MJ_CREATE\n"); IoCompleteRequest(pIrp, IO_NO_INCREMENT); return STATUS_SUCCESS; } NTSTATUS DispatchClose( PDEVICE_OBJECT pDevObj, PIRP pIrp ) { pIrp->IoStatus.Status = STATUS_SUCCESS; pIrp->IoStatus.Information = 0; dprintf("[FGPK] IRP_MJ_CLOSE\n"); IoCompleteRequest(pIrp, IO_NO_INCREMENT); return STATUS_SUCCESS; } NTSTATUS DispatchIoctl( PDEVICE_OBJECT pDevObj, PIRP pIrp ) { NTSTATUS status = STATUS_INVALID_DEVICE_REQUEST; PIO_STACK_LOCATION pIrpStack; ULONG uIoControlCode; PVOID pIoBuffer; ULONG uInSize; ULONG uOutSize; pIrpStack = IoGetCurrentIrpStackLocation(pIrp); uIoControlCode = pIrpStack->Parameters.DeviceIoControl.IoControlCode; pIoBuffer = pIrp->AssociatedIrp.SystemBuffer; uInSize = pIrpStack->Parameters.DeviceIoControl.InputBufferLength; uOutSize = pIrpStack->Parameters.DeviceIoControl.OutputBufferLength; switch(uIoControlCode) { case IOCTL_HELLO: { dprintf("[FGPK] Hello\n"); status = STATUS_SUCCESS; } break; // // 添加执行代码 // } if(status == STATUS_SUCCESS) pIrp->IoStatus.Information = uOutSize; else pIrp->IoStatus.Information = 0; ///////////////////////////////////// pIrp->IoStatus.Status = status; IoCompleteRequest(pIrp, IO_NO_INCREMENT); return status; } ////////////////////////////////////////////////////////////////////////// void __declspec(naked) my_function_detour_KiFastCallEntry() { __asm { cmp ecx,10h jne SSDT mov edi,KeServiceDescriptorTable sub edi,0x10 jmp [SSDTDW_reentry_address] SSDT: mov edi,KeServiceDescriptorTable add edi,0x20 jmp [SSDT_reentry_address] } } UCHAR findcode[]={0x83,0xf9,0x10,0x75}; VOID FindHackAddr() { ULONG uSysenter; ULONG i=0; PUCHAR strSysenter; __asm{ mov ecx,0x176 rdmsr mov uSysenter,eax //得到KiFastCallEntry地址 } strSysenter=(PUCHAR)uSysenter; for (i=0;i<0x100;i++) { if ( findcode[0]==strSysenter[i] && findcode[1]==strSysenter[i+1] && findcode[2]==strSysenter[i+2] && findcode[3]==strSysenter[i+3] ) { break; } } KiSystemService_hack_address=uSysenter+i; } ULONG HookSysCall() { KIRQL oldIrql; unsigned char newcode[] = { 0xE9, 0x44, 0x33, 0x22, 0x11}; char *actual_function; int i = 0; FindHackAddr(); if (KiSystemService_hack_address==0) { dprintf("find hack address error!\n"); return 0; } actual_function =(char*) KiSystemService_hack_address; SSDT_reentry_address = KiSystemService_hack_address+0x20; SSDTDW_reentry_address = KiSystemService_hack_address+0x5; *( (unsigned long *)(&newcode[1]) ) = (ULONG)my_function_detour_KiFastCallEntry-KiSystemService_hack_address-5; WPOFF(); oldIrql = KeRaiseIrqlToDpcLevel(); for(i=0;i < 5;i++) { g_pFindOrigCode[i] = actual_function[i]; actual_function[i] = newcode[i]; } KeLowerIrql(oldIrql); WPON(); return 1; } unsigned long AddMyServiceTable() { ULONG nSDTKerCallLen; __asm { pushad mov eax,KeServiceDescriptorTable mov _KeServiceDescriptorTable,eax sub eax,0x40 mov ShadowTable,eax popad } nSDTKerCallLen = _KeServiceDescriptorTable->ntoskrnl.NumberOfServices; pSSDTKernel = (PULONG)ExAllocatePool( NonPagedPool, nSDTKerCallLen*sizeof(ULONG) ); if(!pSSDTKernel) { dprintf("AddMyServiceTable alloc fail\n"); return 0; } memset( (PVOID)pSSDTKernel, 0, nSDTKerCallLen*sizeof(ULONG)); //填充新的SSDT表 // RtlCopyMemory( (PVOID)pSSDTKernel,(PVOID)_KeServiceDescriptorTable->ntoskrnl.ServiceTableBase,nSDTKerCallLen*sizeof(ULONG) ); RtlCopyMemory( (PVOID)&_KeServiceDescriptorTable->NotUse1, (PVOID)&_KeServiceDescriptorTable->ntoskrnl,sizeof(SERVICE_DESCRIPTOR_TABLE) ); RtlCopyMemory( (PVOID)&ShadowTable->NotUse1,(PVOID)&ShadowTable->ntoskrnl,sizeof(SERVICE_DESCRIPTOR_TABLE)*2); WPOFF(); RtlCopyMemory((PVOID)&_KeServiceDescriptorTable->NotUse1.ServiceTableBase, &pSSDTKernel, sizeof(ULONG)); RtlCopyMemory((PVOID)&ShadowTable->NotUse1.ServiceTableBase, &pSSDTKernel, sizeof(ULONG)); WPON(); return 1; } void RePlaceSSDT() { if (AddMyServiceTable()) { HookSysCall(); } } void RestoreSSDT() { int i; char *actual_function = (char *)(KiSystemService_hack_address); KIRQL oldIrql; WPOFF(); KeRaiseIrql( DISPATCH_LEVEL,&oldIrql ); for(i=0;i < 5;i++) { actual_function[i] = g_pFindOrigCode[i]; } KeLowerIrql( oldIrql ); ExFreePool(pSSDTKernel); WPON(); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// typedef NTSTATUS (*NTQUERYOBJECT) ( IN HANDLE ObjectHandle, IN OBJECT_INFORMATION_CLASS ObjectInformationClass, OUT PVOID ObjectInformation, IN ULONG ObjectInformationLength, OUT PULONG ReturnLength OPTIONAL ); NTQUERYOBJECT OrgNtQueryObject; //***************************************************************************************************************** NTSYSAPI NTSTATUS NTAPI ObQueryNameString( __in PVOID Object, __out_opt POBJECT_NAME_INFORMATION ObjectNameInfo, __in ULONG Length, __out PULONG ReturnLength ); NTSTATUS GetObjectNameFromHandle(HANDLE Objecthandle,PUNICODE_STRING filename) { // PFILE_OBJECT pFileObject; // OBJECT_HANDLE_INFORMATION HandleInformationObject; NTSTATUS nTstatus; POBJECT_NAME_INFORMATION pObjectInformation; PVOID Object; OBJECT_HANDLE_INFORMATION HandleInformation = {0}; ULONG TempReturnLength; pObjectInformation=ExAllocatePool(PagedPool,0x100); RtlZeroMemory(pObjectInformation,0x100); __try { nTstatus = ObReferenceObjectByHandle( Objecthandle, 0, NULL, 0, &Object, &HandleInformation ); if (NT_SUCCESS( nTstatus )) { nTstatus = ObQueryNameString( Object, (POBJECT_NAME_INFORMATION)pObjectInformation, 0x100, &TempReturnLength ); RtlCopyUnicodeString(filename,(PUNICODE_STRING)&(pObjectInformation->Name)); return 0; } } __except(1) { dprintf("GetObjectNameFromHandle error!\n"); } return -1; } //******************************************************************************************************************** NTSTATUS __stdcall MyNtQueryObject( HANDLE ObjectHandle, OBJECT_INFORMATION_CLASS ObjectInformationClass, PVOID ObjectInformation, ULONG ObjectInformationLength, PULONG ReturnLength) { NTSTATUS nTstatus; UNICODE_STRING Objectname; UNICODE_STRING oldname; __try { if(strcmp(GetProcessNameFromEProc(0),"DragonNest.exe")==0) { //DragonNest pid 3548 ObjectNameInformation MyNtQueryObject name \BaseNamedObjects\dnx_579876753682410 handle 00000614 nTstatus=OrgNtQueryObject(ObjectHandle,ObjectInformationClass,ObjectInformation,ObjectInformationLength,ReturnLength); switch (ObjectInformationClass) { case ObjectNameInformation: if(ObjectInformation!=NULL) { POBJECT_NAME_INFORMATION pobj_name=(POBJECT_NAME_INFORMATION)ObjectInformation; RtlInitUnicodeString(&oldname,L"\\BaseNamedObjects\\dnx_57987675368241"); if (pobj_name->Name.Buffer) { if (wcsstr(pobj_name->Name.Buffer,L"\\BaseNamedObjects\\dnx_57987675368241")) { dprintf("DragonNest pid %d ObjectNameInformation MyNtQueryObject name %wZ handle %08x\n",PsGetCurrentProcessId(),&(pobj_name->Name),(ULONG)ObjectHandle); RtlCopyUnicodeString(&(pobj_name->Name),&oldname); dprintf("DragonNest pid %d ObjectNameInformation MyNtQueryObject name %wZ handle %08x\n",PsGetCurrentProcessId(),&(pobj_name->Name),(ULONG)ObjectHandle); } } } break; case ObjectBasicInformation: if(ObjectInformation!=NULL) { POBJECT_BASIC_INFORMATION pobj_basic=(POBJECT_BASIC_INFORMATION)ObjectInformation; dprintf("DragonNest pid %d ObjectBasicInformation HandleCount %d handle %08x\n",PsGetCurrentProcessId(),pobj_basic->HandleCount,(ULONG)ObjectHandle); } break; } } } __except(1) { dprintf("MyNtQueryObject error!\n"); } return nTstatus; } ULONG Pass_NtQueryObject() { KIRQL oldIrql; ULONG Address=0; Address = (ULONG)_KeServiceDescriptorTable->NotUse1.ServiceTableBase + 163 * 4; (ULONG)OrgNtQueryObject = *(ULONG*)Address; //保存此地址 WPOFF(); oldIrql = KeRaiseIrqlToDpcLevel(); *((ULONG*)Address) = (ULONG)MyNtQueryObject; //HOOK SSDT KeLowerIrql(oldIrql); WPON(); return 1; } //反补丁,用于最后恢复用 VOID UnDetour_NtQueryObject() { KIRQL oldIrql; ULONG Address=0; Address = (ULONG)_KeServiceDescriptorTable->NotUse1.ServiceTableBase + 163 * 4; WPOFF(); oldIrql = KeRaiseIrqlToDpcLevel(); *((ULONG*)Address) = (ULONG)OrgNtQueryObject; //HOOK SSDT KeLowerIrql(oldIrql); WPON(); } ////////////////////////////////////////////////////////////////////////// typedef NTSYSAPI NTSTATUS (__stdcall *ZWCREATEMUTANT)( OUT PHANDLE MutantHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, IN BOOLEAN InitialOwner ); ZWCREATEMUTANT OrgZwCreateMutant; OBJECT_ATTRIBUTES tmpobjatus; NTSTATUS __stdcall MyZwCreateMutant( OUT PHANDLE MutantHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, IN BOOLEAN InitialOwner ) { PUNICODE_STRING p_mutex_name; UNICODE_STRING uni_count; WCHAR wzCount[3]; UNICODE_STRING tmpunicodestring; if (!strcmp(GetProcessNameFromEProc(0),"DragonNest.exe")) { if(ObjectAttributes==NULL) return OrgZwCreateMutant(MutantHandle,DesiredAccess,ObjectAttributes,InitialOwner); p_mutex_name=ObjectAttributes->ObjectName; if(p_mutex_name ) { if (p_mutex_name->Buffer) { // dprintf("mutex %S\n",p_mutex_name->Buffer); if (!wcscmp(p_mutex_name->Buffer,L"Global\\MutexDragonNest")) { dprintf("fack mutex!\n"); return STATUS_SUCCESS; __try { RtlInitUnicodeString(&tmpunicodestring,L"Global\\MutexDragonNest"); RtlZeroMemory(wzCount,3*sizeof(WCHAR)); wzCount[0]=(WCHAR)(0x30+g_Dra_count); g_Dra_count++; if(g_Dra_count==20) g_Dra_count=0; RtlInitUnicodeString(&uni_count,wzCount); // dprintf("uni_count %wZ\n",&uni_count); // p_mutex_name->MaximumLength=0x100; RtlAppendUnicodeStringToString(&tmpunicodestring,&uni_count); dprintf("tmpunicodestring %wZ\n",&tmpunicodestring); InitializeObjectAttributes(&tmpobjatus,&tmpunicodestring,ObjectAttributes->Attributes,ObjectAttributes->RootDirectory,ObjectAttributes->SecurityDescriptor); //dprintf("mutex %S\n",p_mutex_name->Buffer); return OrgZwCreateMutant(MutantHandle,DesiredAccess,&tmpobjatus,InitialOwner); } __except(1) { dprintf("MyZwCreateMutant error\n"); } } } } } return OrgZwCreateMutant(MutantHandle,DesiredAccess,ObjectAttributes,InitialOwner); } ULONG Pass_NtCreateMutant() { KIRQL oldIrql; ULONG Address=0; Address = (ULONG)_KeServiceDescriptorTable->NotUse1.ServiceTableBase + 43 * 4; (ULONG)OrgZwCreateMutant = *(ULONG*)Address; //保存此地址 WPOFF(); oldIrql = KeRaiseIrqlToDpcLevel(); *((ULONG*)Address) = (ULONG)MyZwCreateMutant; //HOOK SSDT KeLowerIrql(oldIrql); WPON(); return 1; } //反补丁,用于最后恢复用 VOID UnDetour_NtCreateMutant() { KIRQL oldIrql; ULONG Address=0; Address = (ULONG)_KeServiceDescriptorTable->NotUse1.ServiceTableBase + 43 * 4; WPOFF(); oldIrql = KeRaiseIrqlToDpcLevel(); *((ULONG*)Address) = (ULONG)OrgZwCreateMutant; //HOOK SSDT KeLowerIrql(oldIrql); WPON(); } ////////////////////////////////////////////////////////////////////////// typedef NTSTATUS (*NTQUERYSYSTEMINFORMATION) ( ULONG SystemInformationCLass, PVOID SystemInformation, ULONG SystemInformationLength, PULONG ReturnLength ); NTQUERYSYSTEMINFORMATION OldNtQuerySystemInformation; typedef struct _SYSTEM_BASIC_INFORMATION { BYTE Reserved1[24]; PVOID Reserved2[4]; CCHAR NumberOfProcessors; } SYSTEM_BASIC_INFORMATION; NTSTATUS NewNtQuerySystemInformation( IN ULONG SystemInformationClass, IN PVOID SystemInformation, IN ULONG SystemInformationLength, OUT PULONG ReturnLength) { NTSTATUS ntStatus; UNICODE_STRING gamename; UNICODE_STRING launchername; ntStatus = OldNtQuerySystemInformation( SystemInformationClass, SystemInformation, SystemInformationLength, ReturnLength ); if (!_stricmp(GetProcessNameFromEProc(0),"DragonNest.exe") || !_stricmp(GetProcessNameFromEProc(0),"dnlauncher.exe")) { if( NT_SUCCESS(ntStatus)) { if(SystemInformationClass == 5) { struct _SYSTEM_PROCESSES *curr = (struct _SYSTEM_PROCESSES *)SystemInformation; struct _SYSTEM_PROCESSES *prev = NULL; while(curr) { if (curr->ProcessName.Buffer != NULL) { // dprintf("processid %d\n",curr->ProcessId); RtlInitUnicodeString(&gamename,L"DragonNest.exe"); RtlInitUnicodeString(&launchername,L"dnlauncher.exe"); if((!RtlCompareUnicodeString(&(curr->ProcessName),&gamename,FALSE) && (ULONG)PsGetCurrentProcessId()!=curr->ProcessId) || !RtlCompareUnicodeString(&(curr->ProcessName),&launchername,FALSE)) { // dprintf("FIND DNF PDI %d\n",curr->ProcessId); if(prev) { if(curr->NextEntryDelta) { prev->NextEntryDelta += curr->NextEntryDelta; } else { prev->NextEntryDelta = 0; } } else { if(curr->NextEntryDelta) { (char *)SystemInformation += curr->NextEntryDelta; } else { SystemInformation = NULL; } } } else { prev = curr; } } if(curr->NextEntryDelta) { ((char *)curr += curr->NextEntryDelta); } else { curr = NULL; } } } } } return ntStatus; } ULONG Pass_NtQuerySystemInformation() { KIRQL oldIrql; ULONG Address=0; Address = (ULONG)_KeServiceDescriptorTable->NotUse1.ServiceTableBase + 173 * 4; (ULONG)OldNtQuerySystemInformation = *(ULONG*)Address; //保存此地址 WPOFF(); oldIrql = KeRaiseIrqlToDpcLevel(); *((ULONG*)Address) = (ULONG)NewNtQuerySystemInformation; //HOOK SSDT KeLowerIrql(oldIrql); WPON(); return 1; } //反补丁,用于最后恢复用 VOID UnDetour_NtQuerySystemInformation() { KIRQL oldIrql; ULONG Address=0; Address = (ULONG)_KeServiceDescriptorTable->NotUse1.ServiceTableBase + 173 * 4; WPOFF(); oldIrql = KeRaiseIrqlToDpcLevel(); *((ULONG*)Address) = (ULONG)OldNtQuerySystemInformation; //HOOK SSDT KeLowerIrql(oldIrql); WPON(); } ////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////NtOpenProcess ULONG OldNtProcessAdd; NTSTATUS NewNtOpenProcess ( __out PHANDLE ProcessHandle, __in ACCESS_MASK DesiredAccess, __in POBJECT_ATTRIBUTES ObjectAttributes, __in_opt PCLIENT_ID ClientId ) { HANDLE Handle; KPROCESSOR_MODE PreviousMode; NTSTATUS Status; PEPROCESS Process; PETHREAD Thread; CLIENT_ID CapturedCid={0}; BOOLEAN ObjectNamePresent; BOOLEAN ClientIdPresent; ACCESS_STATE AccessState; AUX_ACCESS_DATA AuxData; ULONG Attributes; LUID SeDebugPrivilege = {0}; PEPROCESS tempeprocess; if (!strcmp("DragonNest.exe",GetProcessNameFromEProc(0)) || !strcmp("dnlauncher.exe",GetProcessNameFromEProc(0))) { PsLookupProcessByProcessId(ClientId->UniqueProcess,&tempeprocess); __try { if ( !strcmp("DML.exe",GetProcessNameFromEProc(tempeprocess)) || (!strcmp("DragonNest.exe",GetProcessNameFromEProc(tempeprocess)) && PsGetCurrentProcessId()!=ClientId->UniqueProcess) /*!strcmp("DeRoX.exe",GetProcessNameFromEProc(tempeprocess))*/ ) { return STATUS_ACCESS_DENIED; } } __except (EXCEPTION_EXECUTE_HANDLER) { dprintf("GetExceptionCode %08x\n",GetExceptionCode()); return GetExceptionCode(); } } return NtOpenProcess(ProcessHandle,DesiredAccess,ObjectAttributes, ClientId); } ULONG Pass_NtOpenProcess() { KIRQL oldIrql; ULONG Address=0; Address = (ULONG)_KeServiceDescriptorTable->NotUse1.ServiceTableBase + 0x7A * 4; OldNtProcessAdd = *(ULONG*)Address; WPOFF(); oldIrql = KeRaiseIrqlToDpcLevel(); *((ULONG*)Address) = (ULONG)NewNtOpenProcess; //HOOK SSDT KeLowerIrql(oldIrql); WPON(); return 1; } VOID UnDetour_NtOpenProcess() { KIRQL oldIrql; ULONG Address=0; Address = (ULONG)_KeServiceDescriptorTable->NotUse1.ServiceTableBase + 0x7A * 4; WPOFF(); oldIrql = KeRaiseIrqlToDpcLevel(); *((ULONG*)Address) = OldNtProcessAdd; //HOOK SSDT KeLowerIrql(oldIrql); WPON(); } ////////////////////////////////////////////////////////////////////////// typedef NTSTATUS (*NTREADVIRTUALMEMORY)( IN HANDLE ProcessHandle, IN PVOID BaseAddress, OUT PVOID Buffer, IN ULONG NumberOfBytesToRead, OUT PULONG NumberOfBytesReaded OPTIONAL ); NTREADVIRTUALMEMORY OldNtReadVirtualMemoryAdd; NTSTATUS NewNtReadVirtualMemory( IN HANDLE ProcessHandle, IN PVOID BaseAddress, OUT PVOID Buffer, IN ULONG NumberOfBytesToRead, OUT PULONG NumberOfBytesReaded OPTIONAL ) { NTSTATUS status; PEPROCESS pEProcess=0; char* proname=0; if (!strcmp("DragonNest.exe",GetProcessNameFromEProc(0))) { if (!ProcessHandle) { return 0; } status = ObReferenceObjectByHandle(ProcessHandle,PROCESS_ALL_ACCESS,NULL,0,&pEProcess,NULL); if(!NT_SUCCESS(status)) { dprintf("ObReferenceObjectByHandle fail! %08x \n",status); return 0; } ObDereferenceObject(pEProcess); proname=GetProcessNameFromEProc(pEProcess); if (PsGetCurrentProcessId()!=PsGetProcessId(pEProcess)) { if (!strcmp("DragonNest.exe",proname) || !strcmp("MDL.exe",proname)) { return STATUS_ACCESS_DENIED; } } } return OldNtReadVirtualMemoryAdd(ProcessHandle,BaseAddress,Buffer,NumberOfBytesToRead,NumberOfBytesReaded); } //////////////////////////////////////////////////////////////////////////NtReadVirtualMemory ULONG Pass_NtReadVirtualMemory() { KIRQL oldIrql; ULONG Address=0; Address = (ULONG)_KeServiceDescriptorTable->NotUse1.ServiceTableBase + 0xBA * 4; //得到NtReadVirtualMemory的服务地址 (ULONG)OldNtReadVirtualMemoryAdd = *(ULONG*)Address; //保存此地址 WPOFF(); oldIrql = KeRaiseIrqlToDpcLevel(); *((ULONG*)Address) = (ULONG)NewNtReadVirtualMemory; //HOOK SSDT KeLowerIrql(oldIrql); WPON(); return 1; } //反补丁,用于最后恢复用 VOID UnDetour_NtReadVirtualMemory() { KIRQL oldIrql; ULONG Address=0; Address = (ULONG)_KeServiceDescriptorTable->NotUse1.ServiceTableBase + 0xBA * 4; WPOFF(); oldIrql = KeRaiseIrqlToDpcLevel(); *((ULONG*)Address) = (ULONG)OldNtReadVirtualMemoryAdd; //HOOK SSDT KeLowerIrql(oldIrql); WPON(); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// typedef NTSTATUS (*NTCREATESEMAPHORE)( OUT PHANDLE SemaphoreHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, IN ULONG InitialCount, IN ULONG MaximumCount ); NTCREATESEMAPHORE OrgNtCreateSemaphore; ULONG semhandle=0; NTSTATUS __stdcall MyNtCreateSemaphore( OUT PHANDLE SemaphoreHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, IN ULONG InitialCount, IN ULONG MaximumCount ) { PUNICODE_STRING p_mutex_name; UNICODE_STRING uni_count={0}; // WCHAR wzCount[3]; NTSTATUS nTstatus; __try { if (!strcmp(GetProcessNameFromEProc(0),"DragonNest.exe")) { if(ObjectAttributes==NULL) return OrgNtCreateSemaphore(SemaphoreHandle,DesiredAccess,ObjectAttributes,InitialCount,MaximumCount); p_mutex_name=ObjectAttributes->ObjectName; if(p_mutex_name ) { if (p_mutex_name->Buffer) { //dprintf("Semaphore %S\n",p_mutex_name->Buffer); //dnx_57987675368241 if (!wcscmp(p_mutex_name->Buffer,L"dnx_57987675368241")) { /* nTstatus=OrgNtCreateSemaphore(SemaphoreHandle,DesiredAccess,ObjectAttributes,InitialCount,MaximumCount); dprintf("Semaphore %S\n",p_mutex_name->Buffer); dprintf("OrgNtCreateSemaphore nTstatus %08x\n",nTstatus); // semhandle=(ULONG)*SemaphoreHandle; // dprintf("DragonNest pid %d MyNtCreateSemaphore dnx_57987675368241 handle %08x\n",PsGetCurrentProcessId(),semhandle); return nTstatus; */ while(1) { nTstatus=OrgNtCreateSemaphore(SemaphoreHandle,DesiredAccess,ObjectAttributes,InitialCount,MaximumCount); if (nTstatus==STATUS_OBJECT_NAME_EXISTS) { dprintf("STATUS_OBJECT_NAME_EXISTS\n"); // RtlZeroMemory(wzCount,3*sizeof(WCHAR)); // wzCount[0]=(WCHAR)(0x30+g_Sem_count); g_Sem_count++; if(g_Sem_count==20) g_Sem_count=0; uni_count.Buffer=(PWSTR)ExAllocatePool(PagedPool,BUFFER_SIZE); uni_count.MaximumLength=BUFFER_SIZE; nTstatus=RtlIntegerToUnicodeString(g_Sem_count,10,&uni_count); if (NT_SUCCESS(nTstatus)) { p_mutex_name->MaximumLength=0x100; RtlAppendUnicodeStringToString(p_mutex_name,&uni_count); } else { dprintf("RtlIntegerToUnicodeString error!\n"); } // RtlInitUnicodeString(&uni_count,wzCount); } else { dprintf("CreateSemaphore sucess! Semaphore name %S\n",p_mutex_name->Buffer); return nTstatus; } } // MaximumCount=10; // dprintf("DragonNest CreateSemaphore MaximumCount :%d InitialCount :%d\n",MaximumCount,InitialCount); // dprintf("fack mutex!\n"); // return STATUS_SUCCESS; } } } } } __except(1) { dprintf("MyNtCreateSemaphore error\n"); } return OrgNtCreateSemaphore(SemaphoreHandle,DesiredAccess,ObjectAttributes,InitialCount,MaximumCount); } ULONG Pass_NtCreateSemaphore() { KIRQL oldIrql; ULONG Address=0; Address = (ULONG)_KeServiceDescriptorTable->NotUse1.ServiceTableBase + 51 * 4; (ULONG)OrgNtCreateSemaphore = *(ULONG*)Address; //保存此地址 WPOFF(); oldIrql = KeRaiseIrqlToDpcLevel(); *((ULONG*)Address) = (ULONG)MyNtCreateSemaphore; //HOOK SSDT KeLowerIrql(oldIrql); WPON(); return 1; } //反补丁,用于最后恢复用 VOID UnDetour_NtCreateSemaphore() { KIRQL oldIrql; ULONG Address=0; Address = (ULONG)_KeServiceDescriptorTable->NotUse1.ServiceTableBase + 51 * 4; WPOFF(); oldIrql = KeRaiseIrqlToDpcLevel(); *((ULONG*)Address) = (ULONG)OrgNtCreateSemaphore; //HOOK SSDT KeLowerIrql(oldIrql); WPON(); } ////////////////////////////////////////////////////////////////////////// typedef NTSTATUS (*NTRELEASESEMAPHORE)( IN HANDLE SemaphoreHandle, IN ULONG ReleaseCount, OUT PULONG PreviousCount OPTIONAL ); NTRELEASESEMAPHORE OrgNtReleaseSemaphore; NTSTATUS __stdcall MyNtReleaseSemaphore( IN HANDLE SemaphoreHandle, IN ULONG ReleaseCount, OUT PULONG PreviousCount OPTIONAL ) { UNICODE_STRING semaphorename; __try { if (!strcmp(GetProcessNameFromEProc(0),"DragonNest.exe")) { if (semhandle==(ULONG)SemaphoreHandle) { dprintf("DragonNest pid %d ReleaseSemaphore handle %08x\n",PsGetCurrentProcessId(),SemaphoreHandle); } /* if (!GetObjectNameFromHandle(SemaphoreHandle,&semaphorename)) { if (!wcscmp(semaphorename.Buffer,L"dnx_57987675368241")) { dprintf("DragonNest pid %d ReleaseSemaphore name %wZ\n",PsGetCurrentProcessId(),&semaphorename); } } */ } } __except(1) { dprintf("MyNtReleaseSemaphore error!\n"); } return OrgNtReleaseSemaphore(SemaphoreHandle,ReleaseCount,PreviousCount); } ULONG Pass_NtReleaseSemaphore() { KIRQL oldIrql; ULONG Address=0; Address = (ULONG)_KeServiceDescriptorTable->NotUse1.ServiceTableBase + 189 * 4; (ULONG)OrgNtReleaseSemaphore = *(ULONG*)Address; //保存此地址 WPOFF(); oldIrql = KeRaiseIrqlToDpcLevel(); *((ULONG*)Address) = (ULONG)MyNtReleaseSemaphore; //HOOK SSDT KeLowerIrql(oldIrql); WPON(); return 1; } //反补丁,用于最后恢复用 VOID UnDetour_NtReleaseSemaphore() { KIRQL oldIrql; ULONG Address=0; Address = (ULONG)_KeServiceDescriptorTable->NotUse1.ServiceTableBase + 189 * 4; WPOFF(); oldIrql = KeRaiseIrqlToDpcLevel(); *((ULONG*)Address) = (ULONG)OrgNtReleaseSemaphore; //HOOK SSDT KeLowerIrql(oldIrql); WPON(); } ////////////////////////////////////////////////////////////////////////// typedef NTSTATUS (*NTOPENSEMAPHORE)( OUT PHANDLE SemaphoreHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes ); NTOPENSEMAPHORE OrgNtOpenSemaphore; NTSTATUS __stdcall MyNtOpenSemaphore( OUT PHANDLE SemaphoreHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes ) { PUNICODE_STRING p_mutex_name; __try { if (!strcmp(GetProcessNameFromEProc(0),"DragonNest.exe")) { // dprintf("DragonNest pid %d OpenSemaphore\n",PsGetCurrentProcessId()); p_mutex_name=ObjectAttributes->ObjectName; if(p_mutex_name ) { if (p_mutex_name->Buffer) { if (!wcscmp(p_mutex_name->Buffer,L"dnx_57987675368241")) { dprintf("DragonNest PID %d NtOpenSemaphore name %S\n",PsGetCurrentProcessId(),p_mutex_name->Buffer); } } } } } __except(1) { dprintf("MyNtOpenSemaphore error!\n"); } return OrgNtOpenSemaphore(SemaphoreHandle,DesiredAccess,ObjectAttributes); } ULONG Pass_NtOpenSemaphore() { KIRQL oldIrql; ULONG Address=0; Address = (ULONG)_KeServiceDescriptorTable->NotUse1.ServiceTableBase + 126 * 4; (ULONG)OrgNtOpenSemaphore = *(ULONG*)Address; //保存此地址 WPOFF(); oldIrql = KeRaiseIrqlToDpcLevel(); *((ULONG*)Address) = (ULONG)MyNtOpenSemaphore; //HOOK SSDT KeLowerIrql(oldIrql); WPON(); return 1; } //反补丁,用于最后恢复用 VOID UnDetour_NtOpenSemaphore() { KIRQL oldIrql; ULONG Address=0; Address = (ULONG)_KeServiceDescriptorTable->NotUse1.ServiceTableBase + 126 * 4; WPOFF(); oldIrql = KeRaiseIrqlToDpcLevel(); *((ULONG*)Address) = (ULONG)OrgNtOpenSemaphore; //HOOK SSDT KeLowerIrql(oldIrql); WPON(); } ////////////////////////////////////////////////////////////////////////// typedef NTSTATUS (*NTWAITFORSINGLEOBJECT)( IN HANDLE ObjectHandle, IN BOOLEAN Alertable, IN PLARGE_INTEGER TimeOut ); NTWAITFORSINGLEOBJECT OrgNtWaitForSingleObject; NTSTATUS __stdcall MyNtWaitForSingleObject( IN HANDLE ObjectHandle, IN BOOLEAN Alertable, IN PLARGE_INTEGER TimeOut ) { UNICODE_STRING Objectname; __try { if (!strcmp(GetProcessNameFromEProc(0),"DragonNest.exe")) { if (semhandle==(ULONG)ObjectHandle) { dprintf("DragonNest pid %d MyNtWaitForSingleObject name %wZ TimeOut %d\n",PsGetCurrentProcessId(),&Objectname,TimeOut); } /* if (!GetObjectNameFromHandle(ObjectHandle,&Objectname)) { if (!wcscmp(Objectname.Buffer,L"dnx_57987675368241")) { dprintf("DragonNest pid %d MyNtWaitForSingleObject name %wZ TimeOut %d\n",PsGetCurrentProcessId(),&Objectname,TimeOut); } } */ } } __except(1) { dprintf("MyNtOpenSemaphore error!\n"); } return OrgNtWaitForSingleObject(ObjectHandle,Alertable,TimeOut); } ULONG Pass_NtWaitForSingleObject() { KIRQL oldIrql; ULONG Address=0; Address = (ULONG)_KeServiceDescriptorTable->NotUse1.ServiceTableBase + 271 * 4; (ULONG)OrgNtWaitForSingleObject = *(ULONG*)Address; //保存此地址 WPOFF(); oldIrql = KeRaiseIrqlToDpcLevel(); *((ULONG*)Address) = (ULONG)MyNtWaitForSingleObject; //HOOK SSDT KeLowerIrql(oldIrql); WPON(); return 1; } //反补丁,用于最后恢复用 VOID UnDetour_NtWaitForSingleObject() { KIRQL oldIrql; ULONG Address=0; Address = (ULONG)_KeServiceDescriptorTable->NotUse1.ServiceTableBase + 271 * 4; WPOFF(); oldIrql = KeRaiseIrqlToDpcLevel(); *((ULONG*)Address) = (ULONG)OrgNtWaitForSingleObject; //HOOK SSDT KeLowerIrql(oldIrql); WPON(); } ////////////////////////////////////////////////////////////////////////// PEPROCESS crsEProc; NTSTATUS HookFindWindow(); NTSTATUS UnHookFindWindow(); PSERVICE_DESCRIPTOR_TABLE KeServiceDescriptorTableShadow; __declspec(dllimport) _stdcall KeAddSystemServiceTable(PVOID, PVOID, PVOID, PVOID, PVOID); #define ObjectNameInformation 1 #define SystemHandleInformation 0x10 typedef struct _SYSTEM_HANDLE_INFORMATION { ULONG ProcessId; UCHAR ObjectTypeNumber; UCHAR Flags; USHORT Handle; PVOID Object; ACCESS_MASK GrantedAccess; } _SYSTEM_HANDLE_INFORMATION, *P_SYSTEM_HANDLE_INFORMATION; typedef struct _SYSTEM_HANDLE_INformATION_EX { ULONG NumberOfHandles; _SYSTEM_HANDLE_INFORMATION Information[1]; } _SYSTEM_HANDLE_INFORMATION_EX, *PSYSTEM_HANDLE_INFORMATION_EX; ////////////////////////////////////////////////////////////////////////// typedef UINT_PTR (*NTUSERQUERYWINDOW)( IN ULONG WindowHandle, IN ULONG TypeInformation); NTUSERQUERYWINDOW OldNtUserQueryWindow; NTSTATUS FindNtUserQueryWindow() { NTSTATUS status=0; KeAttachProcess(crsEProc); __try { if (KeServiceDescriptorTableShadow!=NULL) { OldNtUserQueryWindow = (NTUSERQUERYWINDOW)KeServiceDescriptorTableShadow[1].ServiceTableBase[0x1E3]; } } __finally { KeDetachProcess(); } return status ; } ////////////////////////////////////////////////////////////////////////// unsigned int getAddressOfShadowTable() { unsigned int i; unsigned char *p; unsigned int dwordatbyte; p = (unsigned char*) KeAddSystemServiceTable; for(i = 0; i < 4096; i++, p++) { __try { dwordatbyte = *(unsigned int*)p; } __except(EXCEPTION_EXECUTE_HANDLER) { return 0; } if(MmIsAddressValid((PVOID)dwordatbyte)) { if(memcmp((PVOID)dwordatbyte, &KeServiceDescriptorTable, 16) == 0) { if((PVOID)dwordatbyte == &KeServiceDescriptorTable) { continue; } return dwordatbyte; } } } return 0; } ULONG getShadowTable() { KeServiceDescriptorTableShadow = (PSERVICE_DESCRIPTOR_TABLE) getAddressOfShadowTable(); if(KeServiceDescriptorTableShadow == NULL) { dprintf("hooker.sys: Couldnt find shadowtable!\n"); return FALSE; } else { dprintf("hooker.sys: Shadowtable has been found!\n"); dprintf("hooker.sys: Shadowtable entries: %d\n", KeServiceDescriptorTableShadow[1].NumberOfServices); return TRUE; } } PVOID GetInfoTable(ULONG ATableType) { ULONG mSize = 0x4000; PVOID mPtr = NULL; NTSTATUS St; do { mPtr = ExAllocatePool(PagedPool, mSize); memset(mPtr, 0, mSize); if (mPtr) { St = ZwQuerySystemInformation(ATableType, mPtr, mSize, NULL); } else return NULL; if (St == STATUS_INFO_LENGTH_MISMATCH) { ExFreePool(mPtr); mSize = mSize * 2; } } while (St == STATUS_INFO_LENGTH_MISMATCH); if (St == STATUS_SUCCESS) return mPtr; ExFreePool(mPtr); return NULL; } HANDLE GetCsrPid() { HANDLE Process, hObject; HANDLE CsrId = (HANDLE)0; OBJECT_ATTRIBUTES obj; CLIENT_ID cid; UCHAR Buff[0x100]; POBJECT_NAME_INFORMATION ObjName = (PVOID)&Buff; PSYSTEM_HANDLE_INFORMATION_EX Handles; ULONG r; Handles = GetInfoTable(SystemHandleInformation); if (!Handles) return CsrId; for (r = 0; r < Handles->NumberOfHandles; r++) { if (Handles->Information[r].ObjectTypeNumber == 21) //Port object { InitializeObjectAttributes(&obj, NULL, OBJ_KERNEL_HANDLE, NULL, NULL); cid.UniqueProcess = (HANDLE)Handles->Information[r].ProcessId; cid.UniqueThread = 0; if (NT_SUCCESS(NtOpenProcess(&Process, PROCESS_DUP_HANDLE, &obj, &cid))) { if (NT_SUCCESS(ZwDuplicateObject(Process, (HANDLE)Handles->Information[r].Handle,NtCurrentProcess(), &hObject, 0, 0, DUPLICATE_SAME_ACCESS))) { if (NT_SUCCESS(ZwQueryObject(hObject, ObjectNameInformation, ObjName, 0x100, NULL))) { if (ObjName->Name.Buffer && !wcsncmp(L"\\Windows\\ApiPort", ObjName->Name.Buffer, 20)) { CsrId = (HANDLE)Handles->Information[r].ProcessId; } } ZwClose(hObject); } ZwClose(Process); } } } ExFreePool(Handles); return CsrId; } //6A 30 PUSH 0x30 //68 70D898BF PUSH 0xBF98D870 unsigned long reentry_ntuserfinwind; UCHAR g_oldcode_ntuserfindwind[8]; __declspec(naked) NTSTATUS _NtUserFindWindowEx( HANDLE hwndParent, HANDLE hwndChild, PUNICODE_STRING pstrClassName , PUNICODE_STRING pstrWindowName , DWORD dwType) { __asm { push 0x30 push 0xBF98D870 jmp [reentry_ntuserfinwind] } } NTSTATUS InitSWSSDT() { NTSTATUS status; getShadowTable(); status = PsLookupProcessByProcessId((HANDLE)GetCsrPid(), &crsEProc); if (!NT_SUCCESS( status )) { dprintf("PsLookupProcessByProcessId() error\n"); } FindNtUserQueryWindow(); return status; } char* GetProcessName( ULONG nProcessId) { NTSTATUS rStutus; PEPROCESS curproc; rStutus=PsLookupProcessByProcessId((HANDLE)nProcessId,&curproc); if (!rStutus) { ObDereferenceObject(curproc); return GetProcessNameFromEProc(curproc); } return 0; } NTSTATUS MyNtUserFindWindowEx( IN HANDLE hwndParent, IN HANDLE hwndChild, IN PUNICODE_STRING pstrClassName OPTIONAL, IN PUNICODE_STRING pstrWindowName OPTIONAL, IN DWORD dwType) { ULONG result; UNICODE_STRING CLASSNAME; //UNICODE_STRING FIXCLASSNAME; ULONG FindProcessID; char* szFindProcessName; ULONG ProcessID; result = _NtUserFindWindowEx(hwndParent, hwndChild, pstrClassName, pstrWindowName, dwType); if (!_stricmp("DragonNest.exe",GetProcessNameFromEProc(0))) { ProcessID = OldNtUserQueryWindow(result, 0); if (ProcessID!=(ULONG)PsGetCurrentProcessId()) { if (pstrClassName!=0) { RtlInitUnicodeString(&CLASSNAME,L"DRAGONNEST"); if (!RtlCompareUnicodeString(pstrClassName,&CLASSNAME,FALSE)) { return 0; } } if (pstrWindowName!=0) { RtlInitUnicodeString(&CLASSNAME,L"龙之谷"); if (!RtlCompareUnicodeString(pstrWindowName,&CLASSNAME,FALSE)) { return 0; } RtlInitUnicodeString(&CLASSNAME,L"DML"); if (!RtlCompareUnicodeString(pstrWindowName,&CLASSNAME,FALSE)) { return 0; } } } } return result; } typedef NTSTATUS (*NTUSERFINDWINDOWEX)( HANDLE hwndParent, HANDLE hwndChild, PUNICODE_STRING pstrClassName , PUNICODE_STRING pstrWindowName , DWORD dwType); NTUSERFINDWINDOWEX g_OriginalNtUserFindWindowEx; NTSTATUS HookFindWindow() { NTSTATUS status=0; unsigned char newcode[] = { 0xE9, 0x44, 0x33, 0x22, 0x11,0x90,0x90}; KeAttachProcess(crsEProc); __try { if (KeServiceDescriptorTableShadow!=NULL) { g_OriginalNtUserFindWindowEx = (NTUSERFINDWINDOWEX)KeServiceDescriptorTableShadow[1].ServiceTableBase[0x17A]; memcpy(g_oldcode_ntuserfindwind,(UCHAR*)g_OriginalNtUserFindWindowEx,7); reentry_ntuserfinwind=(unsigned long)g_OriginalNtUserFindWindowEx+7; *( (unsigned long *)(&newcode[1]) ) = (unsigned long)MyNtUserFindWindowEx-(unsigned long)g_OriginalNtUserFindWindowEx-5; } else KeServiceDescriptorTableShadow=NULL; WPOFF(); if (KeServiceDescriptorTableShadow!=NULL ) { memcpy((UCHAR*)g_OriginalNtUserFindWindowEx,newcode,7); } WPON(); } __finally { KeDetachProcess(); } return status ; } NTSTATUS UnHookFindWindow() { NTSTATUS status; KeAttachProcess(crsEProc); __try { WPOFF(); if (KeServiceDescriptorTableShadow!=NULL) { memcpy((UCHAR*)g_OriginalNtUserFindWindowEx,g_oldcode_ntuserfindwind,7); } WPON(); } __finally { KeDetachProcess(); Sleep(50); } return 0; } //////////////////////////////////////////////////////////////////////////