最近研究TESSAFE.SYS的驱动,GOOGLE搜索到微点也是一样的手法HOOK call ObOpenObjectByPointe,把不完整的代码给编写实现了下。未实现检测,应该是有修改我的代码或恢复HOOK call即重启或蓝屏,我为了方便没实现。unhok call摘来别处代码,在搞虚拟机里可以,主机确是老蓝屏8e代码。 //这是SSDT hook,复制NtOpenThread NtOpenProcess 两个代码到别处SSDT,但主机蓝屏,机器双核问题不知要注意什么,但虚拟机也实现双核处理不蓝,我就不知怎么回事了。 #include "ntddk.h" #include <ntdef> #define ThreadLength 0x4f0 //要保存的 NtOpenThread 原代码的长度 #define ProcessLength 0x286 //要保存的 NtOpenProcess 原代码的长度 #define DeviceLink L"\\Device\\DNFCracker" #define SymbolicLink L"\\DosDevices\\DNFCracker" #define IOCTL_RESTORE (ULONG)CTL_CODE(FILE_DEVICE_UNKNOWN, 0x886, METHOD_BUFFERED, FILE_ANY_ACCESS) typedef NTSTATUS (* NTOPENTHREAD)( OUT PHANDLE ThreadHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, IN OPTIONAL PCLIENT_ID ClientId ); typedef NTSTATUS (* NTOPENPROCESS)( OUT PHANDLE ProcessHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, IN PCLIENT_ID ClientId ); typedef struct _SERVICE_DESCRIPTOR_TABLE { PVOID ServiceTableBase; PULONG ServiceCounterTableBase; ULONG NumberOfService; ULONG ParamTableBase; } SERVICE_DESCRIPTOR_TABLE, *PSERVICE_DESCRIPTOR_TABLE; extern PSERVICE_DESCRIPTOR_TABLE KeServiceDescriptorTable; VOID Hook(); VOID Unhook(); NTOPENTHREAD OldThread; NTOPENPROCESS OldProcess; ULONG AddrRead, AddrWrite; //原 NtReadVirtualMemory/NtWriteVirtualMemory 的前 16 字节代码 ULONG OrgRead[2], OrgWrite[2]; //保存 NtOpenThread/NtOpenProcess 代码 UCHAR MyThread[ThreadLength], MyProcess[ProcessLength]; NTSTATUS MyNtOpenThread( PHANDLE ThreadHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, PCLIENT_ID ClientId) { ACCESS_MASK oDA; OBJECT_ATTRIBUTES oOA; CLIENT_ID oCID; NTSTATUS statusF, statusT; oDA = DesiredAccess; oOA = *ObjectAttributes; oCID = *ClientId; statusF = OldThread(ThreadHandle, oDA, &oOA, &oCID); statusT = ((NTOPENTHREAD)MyThread)(ThreadHandle, DesiredAccess, ObjectAttributes, ClientId); return statusT; } NTSTATUS MyNtOpenProcess( PHANDLE ProcessHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, PCLIENT_ID ClientId) { ACCESS_MASK oDA; OBJECT_ATTRIBUTES oOA; CLIENT_ID oCID; NTSTATUS statusF, statusT; oDA = DesiredAccess; oOA = *ObjectAttributes; oCID = *ClientId; statusF = OldProcess(ProcessHandle, oDA, &oOA, &oCID); statusT = ((NTOPENPROCESS)MyProcess)(ProcessHandle, DesiredAccess, ObjectAttributes, ClientId); return statusT; } VOID OnUnload(IN PDRIVER_OBJECT DriverObject) { UNICODE_STRING usLink; /*ULONG i; for (i = 0; i DriverUnload = OnUnload; Hook(); DbgPrint("DNF Cracker Loaded!"); return STATUS_SUCCESS; } // OrgRel 原相对跳转地址 // CurAbs 当前代码绝对地址 // MyAbs 替换代码绝对地址 // CodeLen 跳转代码占据的长度 // 返回值 到替换代码的相对地址 LONG GetRelAddr(LONG OrgRel, ULONG CurAbs, ULONG MyAbs) //, ULONG CodeLen) { ULONG TrgAbs; TrgAbs = CurAbs + OrgRel; // + CodeLen; //目的地址 return TrgAbs - MyAbs; } // 保存原来整个函数的代码 // pCode 用来保存代码的数组的地址 // TrgAddr 要保存的函数的地址 // BufferLength 整个函数占用的大小 VOID BufferCode(PUCHAR pCode, ULONG TrgAddr, ULONG BufferLength) { ULONG cAbs, i; LONG oRel, cRel; memset(pCode, 0x90, BufferLength); for (i = 0; i = 0x80)&&(*(PUCHAR)(cAbs + 1) TrgAddr + BufferLength)|| (oRel + cAbs + 6 0x%08X", cAbs, (ULONG)pCode + i); i += sizeof(LONG) + 1; } } break; case 0xE8: //CALL oRel = *(PLONG)(cAbs + 1); if ((oRel + cAbs + 5 > TrgAddr + BufferLength)|| (oRel + cAbs + 5 0x%08X", cAbs, (ULONG)pCode + i); i += sizeof(LONG); } break; case 0x80: //CMP BYTE PTR X if (*(PUCHAR)(cAbs + 1) == 0x7D) { memcpy(pCode + i + 1, (PVOID)(cAbs + 1), 3); i += 3; continue; } break; case 0xC2: //RET X if (*(PUSHORT)(cAbs +1) == 0x10) { memcpy(pCode + i + 1, (PVOID)(cAbs + 1), sizeof(USHORT)); i += sizeof(USHORT); } break; /*case 0xE9: //JMP oRel = *(PLONG)(cAbs + 1); if (oRel + cAbs > TrgAddr + BufferLength) { cRel = GetRelAddr(oRel, cAbs, (ULONG)pCode + i); memcpy(pCode + i + 1, &cRel, sizeof(LONG)); i += 4; }*/ } if ((*(PUCHAR)cAbs == 0x39)||(*(PUCHAR)cAbs == 0x89)||(*(PUCHAR)cAbs == 0x8D)) { memcpy(pCode + i + 1, (PVOID)(cAbs + 1), sizeof(USHORT)); i += sizeof(USHORT); continue; } /*if ((*(PUCHAR)cAbs >= 0x70)&&(*(PUCHAR)cAbs ServiceTableBase + 0xBA * 4; AddrWrite = (ULONG)KeServiceDescriptorTable->ServiceTableBase + 0x115 * 4; AddrThread = (ULONG)KeServiceDescriptorTable->ServiceTableBase + 0x80 * 4; AddrProcess = (ULONG)KeServiceDescriptorTable->ServiceTableBase + 0x7A * 4; OldThread = (NTOPENTHREAD)(*(PULONG)AddrThread); OldProcess = (NTOPENPROCESS)(*(PULONG)AddrProcess); //DbgPrint("MyThread:0x%08X OldThread:0x%08X", MyThread, OldThread); //DbgPrint("MyProcess:0x%08X OldProcess:0x%08X", MyProcess, OldProcess); __asm { cli mov eax,cr0 and eax,not 10000h mov cr0,eax } Irql=KeRaiseIrqlToDpcLevel(); //记录 NtReadVirtualMemory/NtWriteVirtualMemory 前 16 字节 OrgRead[0] = *(PULONG)(*(PULONG)AddrRead); OrgRead[1] = *(PULONG)(*(PULONG)AddrRead + 4); OrgWrite[0] = *(PULONG)(*(PULONG)AddrWrite); OrgWrite[1] = *(PULONG)(*(PULONG)AddrWrite + 4); //保存原代码 BufferCode(MyThread, (ULONG)OldThread, ThreadLength); BufferCode(MyProcess, (ULONG)OldProcess, ProcessLength); //SSDT Hook *(PULONG)AddrThread = (ULONG)MyNtOpenThread; *(PULONG)AddrProcess = (ULONG)MyNtOpenProcess; KeLowerIrql(Irql); __asm { mov eax,cr0 or eax,10000h mov cr0,eax sti } DbgPrint("Hooked!"); } VOID Unhook() { ULONG AddrProcess, AddrThread;KIRQL Irql; AddrThread = (ULONG)KeServiceDescriptorTable->ServiceTableBase + 0x80 * 4; AddrProcess = (ULONG)KeServiceDescriptorTable->ServiceTableBase + 0x7A * 4; __asm { cli mov eax,cr0 and eax,not 10000h mov cr0,eax } Irql=KeRaiseIrqlToDpcLevel(); //恢复 SSDT *(PULONG)AddrThread = (ULONG)OldThread; *(PULONG)AddrProcess = (ULONG)OldProcess; KeLowerIrql(Irql); __asm { mov eax,cr0 or eax,10000h mov cr0,eax sti } DbgPrint("Unhooked!"); } ---------------------------------------------------- 下面是 原来网上hook 深层call ObOpenObjectByPointe的实现代码及我改动后驱动文件,用来保护记事本不被OPENprocess。 #include "NTDDK.H" #include "ntimage.h" #include "windef.h" #include "LDasm.h" #define NT_DEVICE_NAME L"\\Device\\Hook" #define DOS_DEVICE_NAME L"\\DosDevices\\Hook" NTKERNELAPI PEPROCESS IoThreadToProcess (IN PETHREAD Thread); typedef NTSTATUS (*OBOPENOBJECTBYPOINTER) ( IN PVOID Object, IN ULONG HandleAttributes, IN PACCESS_STATE PassedAccessState OPTIONAL, IN ACCESS_MASK DesiredAccess OPTIONAL, IN POBJECT_TYPE ObjectType OPTIONAL, IN KPROCESSOR_MODE AccessMode, OUT PHANDLE Handle );OBOPENOBJECTBYPOINTER pObOpenObjectByPointer=NULL; PVOID pNtOpenProcess=NULL; PVOID pNtOpenThread=NULL; PEPROCESS MyProcess=(PEPROCESS)0x822ab458;//我們要保護的進程對象 自行修改 void MemOpen() { __asm { cli mov eax,cr0 and eax,not 10000h mov cr0,eax } } void MemClose() { __asm { mov eax,cr0 or eax,10000h mov cr0,eax sti } } ULONG GetFuncAddr(PWCHAR funcname) { UNICODE_STRING uniFuncName; RtlInitUnicodeString(&uniFuncName,funcname); return (ULONG)MmGetSystemRoutineAddress(&uniFuncName); } //爲NtOpenThread準備的 NTSTATUS MyObOpenObjectByPointer_forThread(IN PVOID Object,IN ULONG HandleAttributes, IN PACCESS_STATE PassedAccessState OPTIONAL, IN ACCESS_MASK DesiredAccess OPTIONAL, IN POBJECT_TYPE ObjectType OPTIONAL, IN KPROCESSOR_MODE AccessMode,OUT PHANDLE Handle) { if (IoThreadToProcess(Object)==MyProcess) { return STATUS_ACCESS_DENIED; } else { return pObOpenObjectByPointer (Object, HandleAttributes,PassedAccessState, DesiredAccess,ObjectType,AccessMode,Handle); } } //NtOpenProcess NTSTATUS MyObOpenObjectByPointer_forProcess(IN PVOID Object,IN ULONG HandleAttributes, IN PACCESS_STATE PassedAccessState OPTIONAL, IN ACCESS_MASK DesiredAccess OPTIONAL, IN POBJECT_TYPE ObjectType OPTIONAL, IN KPROCESSOR_MODE AccessMode,OUT PHANDLE Handle) { if (Object==MyProcess) { return STATUS_ACCESS_DENIED; } else { return pObOpenObjectByPointer (Object, HandleAttributes,PassedAccessState, DesiredAccess,ObjectType,AccessMode,Handle); } } // 從StartAddr地址 開始找OldAddr 替換爲NewAddr地址 長度是 SIZE BOOL CallAddrHook(PVOID StartAddr,PVOID OldAddr,PVOID NewAddr,ULONG Size) { PUCHAR cPtr, pOpcode; ULONG Length,Tmp; for (cPtr=StartAddr;(ULONG)cPtr</ntdef>