基础知识推荐阅读《软件调试》的第十八章 内核调试引擎
我在里直接总结一下内核调试引擎的几个关键标志位,也是TP进行反调试检测的关键位。
KdPitchDebugger : Boolean 用来表示是否显示的抑制内核调试, 当启动项中包含 /NODEBUG选项时,这个变量会被置为 TRUE
KdDebuggerEnabled : Boolean 用来表示内核调试是否被启用。当启动项中包含 /DEBUG 或者/ DEBUGPORT 而且不包含/NODEBUG时,这个变量置为TRUE
kiDebugRoutine : 函数指针类型 ,用来记录内核调试引擎的异常处理回调函数,当内核调试引擎活动时,指向KdpTrap函数,否则指向KdpStub函数
KdpBreakpointTable : 结构体数组类型,用来记录代码断点。每一个元素为BREAKPOINT_ENTRY结构,用来描述一个断点,包括断点地址。
然后开始动手,打开Windbg,调试虚拟机(Win7 x86 sp1) Ctrl+Break 断下来,输入k 命令观察断点的栈回溯,观察到最后的几个函数:
KeUpdateRunTime-->àKdCheckForDebugBreak--->àRtlpBreakWithStatusInstruction.
用ida 反汇编查看KeUpdateRunTime函数,看到对KdDebuggerEnabled标识位的检测,如果为0则直接返回,不对KdCheckForDebugBreak函数进行调用。
然后继续反汇编KdCheckForDebugBreak函数,可以看到最KdDebuggerEnabled和 KdPitchDebugger的检测
可以看到调用了KdPollBreakIn() 函数,我们继续跟进kdPollBreakIn()函数,可以看到主要也是对KdPitchDebugger和KdDebuggerEnabled的检测,如果为0就直接退出,返回0
接着跟入DbgBreakPointWithStatus() 函数可以发现并没有做什么处理,直接向下执行RtlpBreakWithStatusInstruction() 可以看到我们的int 3 ,俗称CC断点
对KdDebuggerEnabled进行检测的函数有:
KdUpdateRunTime
KdCheckForDebugBreak
kdPollBreakIn
对KdPitchDubbger进行检测的函数:
KdCheckForDebugBreak
KdPollBreakIn
大致的思路如下:
我们要做的就是把这几个全局变量置换成未调试时的状态,但是在Windows自己的调试引擎中检测的几个全局变量替换成我们自己的全局变量,而且对于TP的TenSa**.sys可以查看导入表,存在IoAllocMdl(),猜测TP对于几个全局变量的访问应该是采用MDL的方式来访问,可以考虑hook掉 IoAllocMdl这个函数,让他检测到其他地方。
然后就是针对TP不停的调用KdDisableDebugger来反调试的问题,直接hook掉KdDisableDebugger,让其直接返回。
还有处理关于kiDebugRoutine 的问题,当内核调试引擎处于活动的时候,KiDebugRoutine这个函数指针是指向的KdpTrap,来处理我们调试是产生的异常,当我们将KiDebugRoutine指向了KdpStub之后,可以绕过对KiDebugRoutine的检测,但是内核调试引擎来处理我们触发的异常时,调用的不是KdpTrap,而变成了KdpStub,很显然不能继续进项调试,所以我们还需要做的一项工作就是hook KdpTrap,让他跳转到KdpTrap,这个内核引擎可以正常工作,也可以绕过TP的检测。
下面可以利用WinDbg对这个手动对这几个全局变量进行简单的处理。
kd> dd KdPitchDebugger 80546efc 00000000 00000000 00000000 00000000 kd> dd KdDebuggerEnabled 8054d4c1 01000001 00000000 00000000 01000000 kd> dd kiDebugRoutine 80553f04 80661a06 00000000 7c92e4a8 7c92e45c kd> u 80661a06 nt!KdpTrap: 80661a06 8bff mov edi,edi 80661a08 55 push ebp 80661a09 8bec mov ebp,esp 80661a0b 51 push ecx 80661a0c 51 push ecx 80661a0d 8b4510 mov eax,dword ptr [ebp+10h] 80661a10 813803000080 cmp dword ptr [eax],80000003h 80661a16 56 push esi
先将KdPitchDebugger 置为1 kd> ed KdPitchDebugger 1 kd> dd KdPitchDebugger 80546efc 00000001 00000000 00000000 00000000 然后设置KiDebugRoutine 指向的指针 从KdpTrap 改成 KdpStub kd> dd KiDebugRoutine 80553f04 80661a06 00000000 7c92e4a8 7c92e45c kd> u 80661a06 nt!KdpTrap: 80661a06 8bff mov edi,edi 80661a08 55 push ebp 80661a09 8bec mov ebp,esp 80661a0b 51 push ecx 80661a0c 51 push ecx 80661a0d 8b4510 mov eax,dword ptr [ebp+10h] 80661a10 813803000080 cmp dword ptr [eax],80000003h 80661a16 56 push esi kd> u KdpStub nt!KdpStub: 804f7c76 8bff mov edi,edi 804f7c78 55 push ebp 804f7c79 8bec mov ebp,esp 804f7c7b 8b4510 mov eax,dword ptr [ebp+10h] 804f7c7e 813803000080 cmp dword ptr [eax],80000003h 804f7c84 7525 jne nt!KdpStub+0x35 (804f7cab) 804f7c86 83781000 cmp dword ptr [eax+10h],0 804f7c8a 761f jbe nt!KdpStub+0x35 (804f7cab) kd> ed KiDebugRoutine 804f7c76 kd> dd KiDebugRoutine 80553f04 804f7c76 00000000 7c92e4a8 7c92e45c 最后恢复KdDebuggerEnabled 为 0 kd> ed KdDebuggerEnabled 0
现在会发生什么,对,就是WinDbg接受不到调试消息包了,就是因为KdDebuggerEnabled 置为0 了,内核调试引擎在关键校验的地方不通过,不发送调试信息。
然后就是代码上的问题,完成上诉的功能就可以达到双机调试TP了。下面放出代码,就是按照上诉的思路来解决的,因为一些函数的定位和关键值的确定都是采用的针对的Win 7 Ultimate x86 sp1硬编码,如果想过其他的系统就要改改硬编码了,而且TP经常的更新,掌握了原理才是正道,强烈推荐《软件调试》这本书。
#ifndef CXX_TPWDG_H #define CXX_TPWDG_H #include <ntifs.h> #include <devioctl.h> #include <ntimage.h> #define kmalloc(_s) ExAllocatePoolWithTag(NonPagedPool, _s, 'Lanren') #define OP_NONE 0x00 #define OP_MODRM 0x01 #define OP_DATA_I8 0x02 #define OP_DATA_I16 0x04 #define OP_DATA_I32 0x08 #define OP_DATA_PRE66_67 0x10 #define OP_WORD 0x20 #define OP_REL32 0x40 #define SystemModuleInformation 11 typedef unsigned char BYTE; typedef BYTE *PBYTE; typedef struct _SYSTEM_MODULE_INFORMATION//系统模块信息 { ULONG Reserved[2]; ULONG Base; ULONG Size; ULONG Flags; USHORT Index; USHORT Unknown; USHORT LoadCount; USHORT ModuleNameOffset; CHAR ImageName[256]; } SYSTEM_MODULE_INFORMATION, *PSYSTEM_MODULE_INFORMATION; typedef struct _tagSysModuleList//模块链结构 { ULONG ulCount; SYSTEM_MODULE_INFORMATION smi[1]; }MODULES, *PMODULES; NTSTATUS __stdcall ZwQuerySystemInformation( ULONG_PTR SystemInformationClass, PVOID SystemInformation, ULONG SystemInformationLength, PULONG ReturnLength ); typedef PMDL(__stdcall *_MyIoAllocateMdl)( PVOID VirtualAddress, ULONG Length, BOOLEAN SecondaryBuffer, BOOLEAN ChargeQuota, PIRP Irp ); SIZE_T GetKdEnteredDebuggerAddr(); PMDL MyIoAllocateMdl(PVOID VirtualAddress,ULONG Length, BOOLEAN SecondaryBuffer,BOOLEAN ChargeQuota, PIRP Irp ); unsigned long __fastcall SizeOfCode(void *Code, unsigned char **pOpcode); unsigned long GetPatchSize(void *Proc, unsigned long dwNeedSize); VOID WpOffAndToDpcLevel(); VOID WpOn(); VOID WritableClose(); VOID InlineHookEngine(ULONG uHookPoint, ULONG uNewFuncAddr); VOID UnInlineHookEngine(ULONG uHookPoint, char* pCode, ULONG uLength); NTSTATUS WriteKernelMemory(PVOID Address, ULONG Size, PVOID InBuffer); void Hook(PVOID Func, PVOID New_Func, PVOID Proxy_Func); void UnHook(PVOID Func, PVOID Proxy_Func); void HookIoAllocMdl(BOOLEAN bEnble); VOID LoadImageRoutine( IN PUNICODE_STRING FullImageName, IN HANDLE ProcessId,//where image is mapped IN PIMAGE_INFO ImageInfo ); ULONG FindCharacteristicCode(ULONG uAddr, char* pCode, ULONG uLength); VOID GetKdpStubAddr(ULONG uStartSearchAddr); VOID GetKdpTrapAddr(ULONG uStartSearchAddr); VOID GetKdDebuggerEnabledAddr(ULONG uStartSearchAddr); ULONG GetFuncAddrFromName(IN PCWSTR FunctionName); VOID DriverUnload(PDRIVER_OBJECT pDriverObject); void WPOFF(); void WPON(); PVOID GetFuncAddress(LPWSTR lpFuncName); ULONG_PTR GetKeUpdateSystemTimeAddr(); ULONG_PTR GetKdCheckForDebugBreak(); ULONG_PTR GetKdDebuggerEnabled_1(); ULONG_PTR GetKdDebuggerEnabled_2(); ULONG_PTR GetKdDebuggerEnabled_3(); ULONG_PTR GetKdDebuggerEnabled_4(); ULONG_PTR GetKdPitchDebugger_1(); ULONG_PTR GetKdPitchDebugger_2(); void MoveGlobal(); void RecoverGlobal(); #endif //全局变量 static KIRQL OldIrql; ULONG ulKdpStub, ulKdpTrap; ULONG ulKdDisableDebugger; ULONG ulKdDisableDebuggerWithLock; ULONG ulKdInitSystem; ULONG ulKiDebugRoutine; ULONG ulKeEnterKernelDebugger; ULONG ulKdDebuggerEnabled; extern SIZE_T KdEnteredDebugger; _MyIoAllocateMdl OldIoAllocateMdl; UCHAR OpcodeFlags[256] = { OP_MODRM, // 00 OP_MODRM, // 01 OP_MODRM, // 02 OP_MODRM, // 03 OP_DATA_I8, // 04 OP_DATA_PRE66_67, // 05 OP_NONE, // 06 OP_NONE, // 07 OP_MODRM, // 08 OP_MODRM, // 09 OP_MODRM, // 0A OP_MODRM, // 0B OP_DATA_I8, // 0C OP_DATA_PRE66_67, // 0D OP_NONE, // 0E OP_NONE, // 0F OP_MODRM, // 10 OP_MODRM, // 11 OP_MODRM, // 12 OP_MODRM, // 13 OP_DATA_I8, // 14 OP_DATA_PRE66_67, // 15 OP_NONE, // 16 OP_NONE, // 17 OP_MODRM, // 18 OP_MODRM, // 19 OP_MODRM, // 1A OP_MODRM, // 1B OP_DATA_I8, // 1C OP_DATA_PRE66_67, // 1D OP_NONE, // 1E OP_NONE, // 1F OP_MODRM, // 20 OP_MODRM, // 21 OP_MODRM, // 22 OP_MODRM, // 23 OP_DATA_I8, // 24 OP_DATA_PRE66_67, // 25 OP_NONE, // 26 OP_NONE, // 27 OP_MODRM, // 28 OP_MODRM, // 29 OP_MODRM, // 2A OP_MODRM, // 2B OP_DATA_I8, // 2C OP_DATA_PRE66_67, // 2D OP_NONE, // 2E OP_NONE, // 2F OP_MODRM, // 30 OP_MODRM, // 31 OP_MODRM, // 32 OP_MODRM, // 33 OP_DATA_I8, // 34 OP_DATA_PRE66_67, // 35 OP_NONE, // 36 OP_NONE, // 37 OP_MODRM, // 38 OP_MODRM, // 39 OP_MODRM, // 3A OP_MODRM, // 3B OP_DATA_I8, // 3C OP_DATA_PRE66_67, // 3D OP_NONE, // 3E OP_NONE, // 3F OP_NONE, // 40 OP_NONE, // 41 OP_NONE, // 42 OP_NONE, // 43 OP_NONE, // 44 OP_NONE, // 45 OP_NONE, // 46 OP_NONE, // 47 OP_NONE, // 48 OP_NONE, // 49 OP_NONE, // 4A OP_NONE, // 4B OP_NONE, // 4C OP_NONE, // 4D OP_NONE, // 4E OP_NONE, // 4F OP_NONE, // 50 OP_NONE, // 51 OP_NONE, // 52 OP_NONE, // 53 OP_NONE, // 54 OP_NONE, // 55 OP_NONE, // 56 OP_NONE, // 57 OP_NONE, // 58 OP_NONE, // 59 OP_NONE, // 5A OP_NONE, // 5B OP_NONE, // 5C OP_NONE, // 5D OP_NONE, // 5E OP_NONE, // 5F OP_NONE, // 60 OP_NONE, // 61 OP_MODRM, // 62 OP_MODRM, // 63 OP_NONE, // 64 OP_NONE, // 65 OP_NONE, // 66 OP_NONE, // 67 OP_DATA_PRE66_67, // 68 OP_MODRM | OP_DATA_PRE66_67, // 69 OP_DATA_I8, // 6A OP_MODRM | OP_DATA_I8, // 6B OP_NONE, // 6C OP_NONE, // 6D OP_NONE, // 6E OP_NONE, // 6F OP_DATA_I8, // 70 OP_DATA_I8, // 71 OP_DATA_I8, // 72 OP_DATA_I8, // 73 OP_DATA_I8, // 74 OP_DATA_I8, // 75 OP_DATA_I8, // 76 OP_DATA_I8, // 77 OP_DATA_I8, // 78 OP_DATA_I8, // 79 OP_DATA_I8, // 7A OP_DATA_I8, // 7B OP_DATA_I8, // 7C OP_DATA_I8, // 7D OP_DATA_I8, // 7E OP_DATA_I8, // 7F OP_MODRM | OP_DATA_I8, // 80 OP_MODRM | OP_DATA_PRE66_67, // 81 OP_MODRM | OP_DATA_I8, // 82 OP_MODRM | OP_DATA_I8, // 83 OP_MODRM, // 84 OP_MODRM, // 85 OP_MODRM, // 86 OP_MODRM, // 87 OP_MODRM, // 88 OP_MODRM, // 89 OP_MODRM, // 8A OP_MODRM, // 8B OP_MODRM, // 8C OP_MODRM, // 8D OP_MODRM, // 8E OP_MODRM, // 8F OP_NONE, // 90 OP_NONE, // 91 OP_NONE, // 92 OP_NONE, // 93 OP_NONE, // 94 OP_NONE, // 95 OP_NONE, // 96 OP_NONE, // 97 OP_NONE, // 98 OP_NONE, // 99 OP_DATA_I16 | OP_DATA_PRE66_67,// 9A OP_NONE, // 9B OP_NONE, // 9C OP_NONE, // 9D OP_NONE, // 9E OP_NONE, // 9F OP_DATA_PRE66_67, // A0 OP_DATA_PRE66_67, // A1 OP_DATA_PRE66_67, // A2 OP_DATA_PRE66_67, // A3 OP_NONE, // A4 OP_NONE, // A5 OP_NONE, // A6 OP_NONE, // A7 OP_DATA_I8, // A8 OP_DATA_PRE66_67, // A9 OP_NONE, // AA OP_NONE, // AB OP_NONE, // AC OP_NONE, // AD OP_NONE, // AE OP_NONE, // AF OP_DATA_I8, // B0 OP_DATA_I8, // B1 OP_DATA_I8, // B2 OP_DATA_I8, // B3 OP_DATA_I8, // B4 OP_DATA_I8, // B5 OP_DATA_I8, // B6 OP_DATA_I8, // B7 OP_DATA_PRE66_67, // B8 OP_DATA_PRE66_67, // B9 OP_DATA_PRE66_67, // BA OP_DATA_PRE66_67, // BB OP_DATA_PRE66_67, // BC OP_DATA_PRE66_67, // BD OP_DATA_PRE66_67, // BE OP_DATA_PRE66_67, // BF OP_MODRM | OP_DATA_I8, // C0 OP_MODRM | OP_DATA_I8, // C1 OP_DATA_I16, // C2 OP_NONE, // C3 OP_MODRM, // C4 OP_MODRM, // C5 OP_MODRM | OP_DATA_I8, // C6 OP_MODRM | OP_DATA_PRE66_67, // C7 OP_DATA_I8 | OP_DATA_I16, // C8 OP_NONE, // C9 OP_DATA_I16, // CA OP_NONE, // CB OP_NONE, // CC OP_DATA_I8, // CD OP_NONE, // CE OP_NONE, // CF OP_MODRM, // D0 OP_MODRM, // D1 OP_MODRM, // D2 OP_MODRM, // D3 OP_DATA_I8, // D4 OP_DATA_I8, // D5 OP_NONE, // D6 OP_NONE, // D7 OP_WORD, // D8 OP_WORD, // D9 OP_WORD, // DA OP_WORD, // DB OP_WORD, // DC OP_WORD, // DD OP_WORD, // DE OP_WORD, // DF OP_DATA_I8, // E0 OP_DATA_I8, // E1 OP_DATA_I8, // E2 OP_DATA_I8, // E3 OP_DATA_I8, // E4 OP_DATA_I8, // E5 OP_DATA_I8, // E6 OP_DATA_I8, // E7 OP_DATA_PRE66_67 | OP_REL32, // E8 OP_DATA_PRE66_67 | OP_REL32, // E9 OP_DATA_I16 | OP_DATA_PRE66_67,// EA OP_DATA_I8, // EB OP_NONE, // EC OP_NONE, // ED OP_NONE, // EE OP_NONE, // EF OP_NONE, // F0 OP_NONE, // F1 OP_NONE, // F2 OP_NONE, // F3 OP_NONE, // F4 OP_NONE, // F5 OP_MODRM, // F6 OP_MODRM, // F7 OP_NONE, // F8 OP_NONE, // F9 OP_NONE, // FA OP_NONE, // FB OP_NONE, // FC OP_NONE, // FD OP_MODRM, // FE OP_MODRM | OP_REL32 // FF }; UCHAR OpcodeFlagsExt[256] = { OP_MODRM, // 00 OP_MODRM, // 01 OP_MODRM, // 02 OP_MODRM, // 03 OP_NONE, // 04 OP_NONE, // 05 OP_NONE, // 06 OP_NONE, // 07 OP_NONE, // 08 OP_NONE, // 09 OP_NONE, // 0A OP_NONE, // 0B OP_NONE, // 0C OP_MODRM, // 0D OP_NONE, // 0E OP_MODRM | OP_DATA_I8, // 0F OP_MODRM, // 10 OP_MODRM, // 11 OP_MODRM, // 12 OP_MODRM, // 13 OP_MODRM, // 14 OP_MODRM, // 15 OP_MODRM, // 16 OP_MODRM, // 17 OP_MODRM, // 18 OP_NONE, // 19 OP_NONE, // 1A OP_NONE, // 1B OP_NONE, // 1C OP_NONE, // 1D OP_NONE, // 1E OP_NONE, // 1F OP_MODRM, // 20 OP_MODRM, // 21 OP_MODRM, // 22 OP_MODRM, // 23 OP_MODRM, // 24 OP_NONE, // 25 OP_MODRM, // 26 OP_NONE, // 27 OP_MODRM, // 28 OP_MODRM, // 29 OP_MODRM, // 2A OP_MODRM, // 2B OP_MODRM, // 2C OP_MODRM, // 2D OP_MODRM, // 2E OP_MODRM, // 2F OP_NONE, // 30 OP_NONE, // 31 OP_NONE, // 32 OP_NONE, // 33 OP_NONE, // 34 OP_NONE, // 35 OP_NONE, // 36 OP_NONE, // 37 OP_NONE, // 38 OP_NONE, // 39 OP_NONE, // 3A OP_NONE, // 3B OP_NONE, // 3C OP_NONE, // 3D OP_NONE, // 3E OP_NONE, // 3F OP_MODRM, // 40 OP_MODRM, // 41 OP_MODRM, // 42 OP_MODRM, // 43 OP_MODRM, // 44 OP_MODRM, // 45 OP_MODRM, // 46 OP_MODRM, // 47 OP_MODRM, // 48 OP_MODRM, // 49 OP_MODRM, // 4A OP_MODRM, // 4B OP_MODRM, // 4C OP_MODRM, // 4D OP_MODRM, // 4E OP_MODRM, // 4F OP_MODRM, // 50 OP_MODRM, // 51 OP_MODRM, // 52 OP_MODRM, // 53 OP_MODRM, // 54 OP_MODRM, // 55 OP_MODRM, // 56 OP_MODRM, // 57 OP_MODRM, // 58 OP_MODRM, // 59 OP_MODRM, // 5A OP_MODRM, // 5B OP_MODRM, // 5C OP_MODRM, // 5D OP_MODRM, // 5E OP_MODRM, // 5F OP_MODRM, // 60 OP_MODRM, // 61 OP_MODRM, // 62 OP_MODRM, // 63 OP_MODRM, // 64 OP_MODRM, // 65 OP_MODRM, // 66 OP_MODRM, // 67 OP_MODRM, // 68 OP_MODRM, // 69 OP_MODRM, // 6A OP_MODRM, // 6B OP_MODRM, // 6C OP_MODRM, // 6D OP_MODRM, // 6E OP_MODRM, // 6F OP_MODRM | OP_DATA_I8, // 70 OP_MODRM | OP_DATA_I8, // 71 OP_MODRM | OP_DATA_I8, // 72 OP_MODRM | OP_DATA_I8, // 73 OP_MODRM, // 74 OP_MODRM, // 75 OP_MODRM, // 76 OP_NONE, // 77 OP_NONE, // 78 OP_NONE, // 79 OP_NONE, // 7A OP_NONE, // 7B OP_MODRM, // 7C OP_MODRM, // 7D OP_MODRM, // 7E OP_MODRM, // 7F OP_DATA_PRE66_67 | OP_REL32, // 80 OP_DATA_PRE66_67 | OP_REL32, // 81 OP_DATA_PRE66_67 | OP_REL32, // 82 OP_DATA_PRE66_67 | OP_REL32, // 83 OP_DATA_PRE66_67 | OP_REL32, // 84 OP_DATA_PRE66_67 | OP_REL32, // 85 OP_DATA_PRE66_67 | OP_REL32, // 86 OP_DATA_PRE66_67 | OP_REL32, // 87 OP_DATA_PRE66_67 | OP_REL32, // 88 OP_DATA_PRE66_67 | OP_REL32, // 89 OP_DATA_PRE66_67 | OP_REL32, // 8A OP_DATA_PRE66_67 | OP_REL32, // 8B OP_DATA_PRE66_67 | OP_REL32, // 8C OP_DATA_PRE66_67 | OP_REL32, // 8D OP_DATA_PRE66_67 | OP_REL32, // 8E OP_DATA_PRE66_67 | OP_REL32, // 8F OP_MODRM, // 90 OP_MODRM, // 91 OP_MODRM, // 92 OP_MODRM, // 93 OP_MODRM, // 94 OP_MODRM, // 95 OP_MODRM, // 96 OP_MODRM, // 97 OP_MODRM, // 98 OP_MODRM, // 99 OP_MODRM, // 9A OP_MODRM, // 9B OP_MODRM, // 9C OP_MODRM, // 9D OP_MODRM, // 9E OP_MODRM, // 9F OP_NONE, // A0 OP_NONE, // A1 OP_NONE, // A2 OP_MODRM, // A3 OP_MODRM | OP_DATA_I8, // A4 OP_MODRM, // A5 OP_NONE, // A6 OP_NONE, // A7 OP_NONE, // A8 OP_NONE, // A9 OP_NONE, // AA OP_MODRM, // AB OP_MODRM | OP_DATA_I8, // AC OP_MODRM, // AD OP_MODRM, // AE OP_MODRM, // AF OP_MODRM, // B0 OP_MODRM, // B1 OP_MODRM, // B2 OP_MODRM, // B3 OP_MODRM, // B4 OP_MODRM, // B5 OP_MODRM, // B6 OP_MODRM, // B7 OP_NONE, // B8 OP_NONE, // B9 OP_MODRM | OP_DATA_I8, // BA OP_MODRM, // BB OP_MODRM, // BC OP_MODRM, // BD OP_MODRM, // BE OP_MODRM, // BF OP_MODRM, // C0 OP_MODRM, // C1 OP_MODRM | OP_DATA_I8, // C2 OP_MODRM, // C3 OP_MODRM | OP_DATA_I8, // C4 OP_MODRM | OP_DATA_I8, // C5 OP_MODRM | OP_DATA_I8, // C6 OP_MODRM, // C7 OP_NONE, // C8 OP_NONE, // C9 OP_NONE, // CA OP_NONE, // CB OP_NONE, // CC OP_NONE, // CD OP_NONE, // CE OP_NONE, // CF OP_MODRM, // D0 OP_MODRM, // D1 OP_MODRM, // D2 OP_MODRM, // D3 OP_MODRM, // D4 OP_MODRM, // D5 OP_MODRM, // D6 OP_MODRM, // D7 OP_MODRM, // D8 OP_MODRM, // D9 OP_MODRM, // DA OP_MODRM, // DB OP_MODRM, // DC OP_MODRM, // DD OP_MODRM, // DE OP_MODRM, // DF OP_MODRM, // E0 OP_MODRM, // E1 OP_MODRM, // E2 OP_MODRM, // E3 OP_MODRM, // E4 OP_MODRM, // E5 OP_MODRM, // E6 OP_MODRM, // E7 OP_MODRM, // E8 OP_MODRM, // E9 OP_MODRM, // EA OP_MODRM, // EB OP_MODRM, // EC OP_MODRM, // ED OP_MODRM, // EE OP_MODRM, // EF OP_MODRM, // F0 OP_MODRM, // F1 OP_MODRM, // F2 OP_MODRM, // F3 OP_MODRM, // F4 OP_MODRM, // F5 OP_MODRM, // F6 OP_MODRM, // F7 OP_MODRM, // F8 OP_MODRM, // F9 OP_MODRM, // FA OP_MODRM, // FB OP_MODRM, // FC OP_MODRM, // FD OP_MODRM, // FE OP_NONE // FF }; //1. KeUpdateSystemTime // //nt!KeUpdateSystemTime + 0x417: //84096d65 33c9 xor ecx, ecx //84096d67 8d542420 lea edx, [esp + 20h] // //nt!KeUpdateSystemTime + 0x41d : //84096d6b 803d2c1d188400 cmp byte ptr[nt!KdDebuggerEnabled(84181d2c)], 0 <--ul_KdDebuggerEnabled_1 //84096d72 7464 je nt!KeUpdateSystemTime + 0x48a (84096dd8) // // //2. KeUpdateRunTime // //nt!KeUpdateRunTime + 0x149: //840970c2 803d2c1d188400 cmp byte ptr[nt!KdDebuggerEnabled(84181d2c)], 0 <--ul_KdDebuggerEnabled_2 //840970c9 7412 je nt!KeUpdateRunTime + 0x164 (840970dd) // //3. KdCheckForDebugBreak // //kd > uf kdcheckfordebugbreak //nt!KdCheckForDebugBreak: //840970e9 803d275d148400 cmp byte ptr[nt!KdPitchDebugger(84145d27)], 0 <--ul_KdPitchDebugger_1 //840970f0 7519 jne nt!KdCheckForDebugBreak + 0x22 (8409710b) // //nt!KdCheckForDebugBreak + 0x9 : //840970f2 803d2c1d188400 cmp byte ptr[nt!KdDebuggerEnabled(84181d2c)], 0 <--ul_KdDebuggerEnabled_3 //840970f9 7410 je nt!KdCheckForDebugBreak + 0x22 (8409710b) // // //4. KdPollBreakIn // //kd > uf KdPollBreakIn //nt!KdPollBreakIn: //8409711f 8bff mov edi, edi //84097121 55 push ebp //84097122 8bec mov ebp, esp //84097124 51 push ecx //84097125 53 push ebx //84097126 33db xor ebx, ebx //84097128 381d275d1484 cmp byte ptr[nt!KdPitchDebugger(84145d27)], bl <--ul_KdPitchDebugger_2 //8409712e 7407 je nt!KdPollBreakIn + 0x18 (84097137) // //nt!KdPollBreakIn + 0x11: //84097130 32c0 xor al, al //84097132 e9d2000000 jmp nt!KdPollBreakIn + 0xea (84097209) // //nt!KdPollBreakIn + 0x18 : //84097137 885dff mov byte ptr[ebp - 1], bl //8409713a 381d2c1d1884 cmp byte ptr[nt!KdDebuggerEnabled(84181d2c)], bl <--ul_KdDebuggerEnabled_4 //84097140 0f84c0000000 je nt!KdPollBreakIn + 0xe7 (84097206) ULONG_PTR ul_KeUpdateSystemTimeAssist; ULONG_PTR ul_KeUpdateSystemTime; ULONG_PTR ul_KeUpdateRunTime; ULONG_PTR ul_KdCheckForDebugBreak; ULONG_PTR ul_KdPollBreakIn; //顺序按照上面注释的顺序 ULONG_PTR ul_KdDebuggerEnabled_1; ULONG_PTR ul_KdDebuggerEnabled_2; ULONG_PTR ul_KdDebuggerEnabled_3; ULONG_PTR ul_KdDebuggerEnabled_4; ULONG_PTR ul_KdPitchDebugger_1; ULONG_PTR ul_KdPitchDebugger_2; //用来保存原来内核变量地址 ULONG_PTR ul_oldKdDebuggerEnabled; ULONG_PTR ul_oldKdPitchDebugger; //自己定义的全局变量 BOOLEAN bool_myKdDebuggerEnabled = TRUE; BOOLEAN bool_myKdPitchDebugger = FALSE; NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING pRegistryPath) { NTSTATUS status; //转移内核变量 MoveGlobal(); //注册回调 status = PsSetLoadImageNotifyRoutine(LoadImageRoutine); if (!NT_SUCCESS(status)) { return status; } KdPrint(("注册回调函数成功!\n")); HookIoAllocMdl(TRUE); //获得KdDisableDebugger地址 ulKdDisableDebugger = GetFuncAddrFromName(L"KdDisableDebugger"); KdPrint(("ulKdDisableDebugger: 0x%08X\n", ulKdDisableDebugger)); //计算KdDisableDebuggerWithLock地址 ulKdDisableDebuggerWithLock = (ulKdDisableDebugger + 2) + *(ULONG*)(ulKdDisableDebugger + 3) + 5; KdPrint(("ulKdDisableDebuggerWithLock: 0x%08X\n", ulKdDisableDebuggerWithLock)); ulKeEnterKernelDebugger = GetFuncAddrFromName(L"KeEnterKernelDebugger"); KdPrint(("ulKeEnterKernelDebugger: 0x%08X\n", ulKeEnterKernelDebugger)); //函数内部搜索特征码 GetKdpStubAddr(ulKdDisableDebuggerWithLock); GetKdpTrapAddr(ulKeEnterKernelDebugger); //Hook KdpStub头部直接跳转到KdpTrap InlineHookEngine(ulKdpStub, ulKdpTrap); GetKdDebuggerEnabledAddr(ulKeEnterKernelDebugger); //改写KdDisableDebugger头部直接返回 WritableOpen(); __asm { pushad pushfd mov eax, ulKdDisableDebugger mov byte ptr ds:[eax], 0x90//nop mov byte ptr ds:[eax + 0x1], 0xc3//ret popfd popad } //改写KdDebuggerEnabled为0 __asm { pushad pushfd mov eax, ulKdDebuggerEnabled mov dword ptr ds:[eax], 0x0 popfd popad } WritableClose(); pDriverObject->DriverUnload = DriverUnload; return STATUS_SUCCESS; } SIZE_T GetKdEnteredDebuggerAddr() { return KdEnteredDebugger; } PMDL MyIoAllocateMdl( PVOID VirtualAddress, ULONG Length, BOOLEAN SecondaryBuffer, BOOLEAN ChargeQuota, PIRP Irp ) { PVOID pKdEnteredDebugger; pKdEnteredDebugger = (PVOID)GetKdEnteredDebuggerAddr(); if (pKdEnteredDebugger == VirtualAddress) { VirtualAddress = (PVOID)((SIZE_T)pKdEnteredDebugger + 0x4);//+0x4是让它读到其他的位置 } return OldIoAllocateMdl(VirtualAddress, Length, SecondaryBuffer, ChargeQuota, Irp); } unsigned long __fastcall SizeOfCode(void *Code, unsigned char **pOpcode) { PUCHAR cPtr; UCHAR Flags; BOOLEAN PFX66, PFX67; BOOLEAN SibPresent; UCHAR iMod, iRM, iReg; UCHAR OffsetSize, Add; UCHAR Opcode; OffsetSize = 0; PFX66 = FALSE; PFX67 = FALSE; cPtr = (PUCHAR)Code; while ((*cPtr == 0x2E) || (*cPtr == 0x3E) || (*cPtr == 0x36) || (*cPtr == 0x26) || (*cPtr == 0x64) || (*cPtr == 0x65) || (*cPtr == 0xF0) || (*cPtr == 0xF2) || (*cPtr == 0xF3) || (*cPtr == 0x66) || (*cPtr == 0x67)) { if (*cPtr == 0x66) PFX66 = TRUE; if (*cPtr == 0x67) PFX67 = TRUE; cPtr++; if (cPtr > (PUCHAR)Code + 16) return 0; } Opcode = *cPtr; if (pOpcode) *pOpcode = cPtr; if (*cPtr == 0x0F) { cPtr++; Flags = OpcodeFlagsExt[*cPtr]; } else { Flags = OpcodeFlags[Opcode]; if (Opcode >= 0xA0 && Opcode <= 0xA3) PFX66 = PFX67; } cPtr++; if (Flags & OP_WORD) cPtr++; if (Flags & OP_MODRM) { iMod = *cPtr >> 6; iReg = (*cPtr & 0x38) >> 3; iRM = *cPtr & 7; cPtr++; if ((Opcode == 0xF6) && !iReg) Flags |= OP_DATA_I8; if ((Opcode == 0xF7) && !iReg) Flags |= OP_DATA_PRE66_67; SibPresent = !PFX67 & (iRM == 4); switch (iMod) { case 0: if ( PFX67 && (iRM == 6)) OffsetSize = 2; if (!PFX67 && (iRM == 5)) OffsetSize = 4; break; case 1: OffsetSize = 1; break; case 2: if (PFX67) OffsetSize = 2; else OffsetSize = 4; break; case 3: SibPresent = FALSE; } if (SibPresent) { if (((*cPtr & 7) == 5) && ( (!iMod) || (iMod == 2) )) OffsetSize = 4; cPtr++; } cPtr = (PUCHAR)(ULONG)cPtr + OffsetSize; } if (Flags & OP_DATA_I8) cPtr ++; if (Flags & OP_DATA_I16) cPtr += 2; if (Flags & OP_DATA_I32) cPtr += 4; if (PFX66) Add = 2; else Add = 4; if (Flags & OP_DATA_PRE66_67) cPtr += Add; return (ULONG)cPtr - (ULONG)Code; } unsigned long GetPatchSize(void *Proc, unsigned long dwNeedSize) { ULONG Length; PUCHAR pOpcode; ULONG PatchSize = 0; do { Length = SizeOfCode(Proc, &pOpcode); if ((Length == 1) && (*pOpcode == 0xC3)) break; if ((Length == 3) && (*pOpcode == 0xC2)) break; Proc = (PVOID)((ULONG)Proc + Length); PatchSize += Length; if (PatchSize >= dwNeedSize) { break; } } while (Length); return PatchSize; } VOID WpOffAndToDpcLevel() { OldIrql = KeRaiseIrqlToDpcLevel(); __asm { cli push eax mov eax, cr0 and eax, 0FFFEFFFFh mov cr0, eax pop eax } } VOID WpOn() { __asm { push eax mov eax, cr0 or eax, 10000h mov cr0, eax pop eax sti } KeLowerIrql(OldIrql); } VOID WritableOpen() { __asm { cli mov eax, cr0 and eax, not 0x10000 mov cr0, eax } } VOID WritableClose() { __asm { mov eax, cr0 or eax, 0x10000 mov cr0, eax sti } } VOID InlineHookEngine(ULONG uHookPoint, ULONG uNewFuncAddr) { ULONG uJmp = uNewFuncAddr - uHookPoint - 5; WritableOpen(); __asm { mov eax, uHookPoint mov byte ptr ds:[eax], 0xe9 mov ebx, uJmp mov dword ptr ds:[eax + 0x1], ebx } WritableClose(); } VOID UnInlineHookEngine(ULONG uHookPoint, char* pCode, ULONG uLength) { WritableOpen(); RtlCopyMemory((char*)uHookPoint, pCode, uLength); WritableClose(); } NTSTATUS WriteKernelMemory(PVOID Address, ULONG Size, PVOID InBuffer) { NTSTATUS st = STATUS_UNSUCCESSFUL; PMDL pMdl = 0; PVOID pAddress = 0; KSPIN_LOCK spinlock; KIRQL oldirql; if (!Address) return st; pMdl = IoAllocateMdl(Address, Size, FALSE, FALSE, 0); if (pMdl) { MmBuildMdlForNonPagedPool(pMdl); pAddress = MmGetSystemAddressForMdlSafe(pMdl, NormalPagePriority); KdPrint(("pAddress: 0x%08x\n", pAddress)); if (pAddress) { __try { KeInitializeSpinLock(&spinlock); KeAcquireSpinLock(&spinlock, &oldirql); WpOffAndToDpcLevel(); RtlCopyMemory(pAddress, InBuffer, Size); WpOn(); KeReleaseSpinLock(&spinlock, oldirql); st = STATUS_SUCCESS; } __except (EXCEPTION_EXECUTE_HANDLER) { } } IoFreeMdl(pMdl); } return st; } void Hook(PVOID Func, PVOID New_Func, PVOID Proxy_Func) { ULONG PatchSize; BYTE g_HookCode[5] = {0xe9, 0, 0, 0, 0};//相对跳转 BYTE Jmp_Orig_Code[7] = {0xea, 0, 0, 0, 0, 0x08, 0x00};//绝对地址跳转 PatchSize = GetPatchSize(Func, 5);//获得要Patch的字节数 //构造Proxy_Func memcpy((PBYTE)Proxy_Func, (PBYTE)Func, PatchSize);//实现原函数头 *((PULONG)(Jmp_Orig_Code + 1)) = (ULONG)((PBYTE)Func + PatchSize);//原函数+N地址 memcpy((PBYTE)Proxy_Func + PatchSize, Jmp_Orig_Code, 7);//绝对地址跳转 *((ULONG*)(g_HookCode + 1)) = (ULONG)New_Func - (ULONG)Func - 5;//计算JMP地址 WriteKernelMemory(Func, 5, g_HookCode); } //UnHook函数 void UnHook(PVOID Func, PVOID Proxy_Func) { WriteKernelMemory(Func, 5, Proxy_Func); } void HookIoAllocMdl(BOOLEAN bEnble) { if (bEnble == TRUE) { OldIoAllocateMdl = kmalloc(20); memset(OldIoAllocateMdl, 0x90, 20); Hook(IoAllocateMdl, MyIoAllocateMdl, (PVOID)OldIoAllocateMdl); DbgPrint("IoAllocateMdl hooked!\n"); } else { UnHook(IoAllocateMdl, OldIoAllocateMdl); ExFreePool(OldIoAllocateMdl); DbgPrint("IoAllocateMdl unhooked!\n"); } } //模块加载回调函数例程 VOID LoadImageRoutine( IN PUNICODE_STRING FullImageName, IN HANDLE ProcessId,//where image is mapped IN PIMAGE_INFO ImageInfo ) { UNREFERENCED_PARAMETER(ProcessId); if (wcsstr(FullImageName->Buffer, L"TesSafe.sys") != NULL) { KdPrint(("TesSafe.sys Loaded!\n")); KdPrint(("TesSafe.sys ImageBase: 0x%08X\n", (ULONG)ImageInfo->ImageBase)); KdPrint(("TesSafe.sys ImageSize: 0x%08X\n", (ULONG)ImageInfo->ImageSize)); KdPrint(("断点命令: ba e 1 0x%08X\n", (ULONG)ImageInfo->ImageBase)); //KdBreakPoint(); } return; } ULONG FindCharacteristicCode(ULONG uAddr, char* pCode, ULONG uLength) { char szTemp[256]; ULONG i = 5000; while(i --) { RtlMoveMemory(szTemp, (char*)uAddr, uLength); if (RtlCompareMemory(pCode, szTemp, uLength) == uLength) { return uAddr; } uAddr ++; } return 0; } VOID GetKdpStubAddr(ULONG uStartSearchAddr) { /* kd> u KdDisableDebugger nt!KdDisableDebugger: 83f32846 6a01 push 1 83f32848 e806ffffff call nt!KdDisableDebuggerWithLock (83f32753) 83f3284d c3 ret kd> nt!KdDisableDebuggerWithLock+0x68: 83f1b7bb 8b0d6c89fa83 mov ecx,dword ptr [nt!KeNumberProcessors (83fa896c)] 83f1b7c1 33c0 xor eax,eax 83f1b7c3 85c9 test ecx,ecx 83f1b7c5 761a jbe nt!KdDisableDebuggerWithLock+0x8e (83f1b7e1) 83f1b7c7 8b0c85c088fa83 mov ecx,dword ptr nt!KiProcessorBlock (83fa88c0)[eax*4] 83f1b7ce 389908030000 cmp byte ptr [ecx+308h],bl 83f1b7d4 7551 jne nt!KdDisableDebuggerWithLock+0xd4 (83f1b827) 83f1b7d6 8b0d6c89fa83 mov ecx,dword ptr [nt!KeNumberProcessors (83fa896c)] kd> nt!KdDisableDebuggerWithLock+0x89: 83f1b7dc 40 inc eax 83f1b7dd 3bc1 cmp eax,ecx 83f1b7df 72e6 jb nt!KdDisableDebuggerWithLock+0x74 (83f1b7c7) 83f1b7e1 381d2c3dfa83 cmp byte ptr [nt!KdDebuggerEnabled (83fa3d2c)],bl 83f1b7e7 741b je nt!KdDisableDebuggerWithLock+0xb1 (83f1b804) 83f1b7e9 e8021a2500 call nt!KdpSuspendAllBreakpoints (8416d1f0) 83f1b7ee 881d2c3dfa83 mov byte ptr [nt!KdDebuggerEnabled (83fa3d2c)],bl 83f1b7f4 c705bc89fa83afb9f183 mov dword ptr [nt!KiDebugRoutine (83fa89bc)],offset nt!KdpStub (83f1b9af) */ ULONG ulTemp; char code[4] = {(char)0x40, (char)0x3b, (char)0xc1, (char)0x72}; ulTemp = FindCharacteristicCode(uStartSearchAddr, code, 4) + 0x1e; if (!MmIsAddressValid((PVOID)ulTemp)) { KdPrint(("ulTemp is invalid!\n")); return; } ulKdpStub = *(ULONG*)ulTemp; KdPrint(("ulKdpStub: 0x%08X\n", ulKdpStub)); } VOID GetKdpTrapAddr(ULONG uStartSearchAddr) { /* kd> nt!KeEnterKernelDebugger+0x2f: 83f2efc0 8731 xchg esi,dword ptr [ecx] 83f2efc2 85f6 test esi,esi 83f2efc4 7507 jne nt!KeEnterKernelDebugger+0x3c (83f2efcd) 83f2efc6 50 push eax 83f2efc7 50 push eax 83f2efc8 e83dc12400 call nt!KdInitSystem (8417b10a) 83f2efcd 6a05 push 5 83f2efcf e893f0ffff call nt!KiBugCheckDebugBreak (83f2e067) kd> nt!KdInitSystem+0x285: 8417b38f 99 cdq 8417b390 a3109cf783 mov dword ptr [nt!KdVersionBlock+0x10 (83f79c10)],eax 8417b395 8915149cf783 mov dword ptr [nt!KdVersionBlock+0x14 (83f79c14)],edx 8417b39b c644241101 mov byte ptr [esp+11h],1 8417b3a0 a1109cf783 mov eax,dword ptr [nt!KdVersionBlock+0x10 (83f79c10)] 8417b3a5 33f6 xor esi,esi 8417b3a7 807c241100 cmp byte ptr [esp+11h],0 8417b3ac a3409cf783 mov dword ptr [nt!KdDebuggerDataBlock+0x18 (83f79c40)],eax kd> nt!KdInitSystem+0x2a7: 8417b3b1 8935449cf783 mov dword ptr [nt!KdDebuggerDataBlock+0x1c (83f79c44)],esi 8417b3b7 0f8428010000 je nt!KdInitSystem+0x3db (8417b4e5) 8417b3bd 53 push ebx 8417b3be e8977acdff call nt!KdDebuggerInitialize0 (83e52e5a) 8417b3c3 85c0 test eax,eax 8417b3c5 0f8c1a010000 jl nt!KdInitSystem+0x3db (8417b4e5) 8417b3cb 803d18801c8400 cmp byte ptr [nt!KdpDebuggerStructuresInitialized (841c8018)],0 8417b3d2 c705bc99fb83f2c41784 mov dword ptr [nt!KiDebugRoutine (83fb99bc)],offset nt!KdpTrap (8417c4f2) */ ULONG uTemp; char code1[3] = {(char)0x50, (char)0x50, (char)0xe8}; char code2[3] = {(char)0x85, (char)0xc0, (char)0x0f}; uTemp = FindCharacteristicCode(uStartSearchAddr, code1, 3) + 2; if (!MmIsAddressValid((PVOID)uTemp)) { KdPrint(("uTemp is invalid!\n")); return; } ulKdInitSystem = uTemp + *(ULONG*)(uTemp + 1) + 5; KdPrint(("ulKdInitSystem: 0x%08X\n", ulKdInitSystem)); uTemp = FindCharacteristicCode(ulKdInitSystem + 0x285, code2, 3); ulKdpTrap = *(ULONG*)(uTemp + 0x15); KdPrint(("ulKdpTrap: 0x%08X\n", ulKdpTrap)); } VOID GetKdDebuggerEnabledAddr(ULONG uStartSearchAddr) { /* kd> u nt!KeEnterKernelDebugger+0xd: 83ee2f9e 8935fcc1f383 mov dword ptr [nt!KiHardwareTrigger (83f3c1fc)],esi 83ee2fa4 e8dbd9f9ff call nt!KeDisableInterrupts (83e80984) 83ee2fa9 33c0 xor eax,eax 83ee2fab 38052c8df683 cmp byte ptr [nt!KdDebuggerEnabled (83f68d2c)],al 83ee2fb1 751a jne nt!KeEnterKernelDebugger+0x3c (83ee2fcd) 83ee2fb3 380527cdf283 cmp byte ptr [nt!KdPitchDebugger (83f2cd27)],al 83ee2fb9 7512 jne nt!KeEnterKernelDebugger+0x3c (83ee2fcd) 83ee2fbb b980c1f383 mov ecx,offset nt!KiBugCheckDriver+0x4 (83f3c180) */ ULONG ulTemp; char code[3] = {(char)0x33, (char)0xc0, (char)0x38}; ulTemp = FindCharacteristicCode(uStartSearchAddr, code, 3); ulKdDebuggerEnabled = *(ULONG*)(ulTemp + 4); KdPrint(("ulKdDebuggerEnabled: 0x%08X\n", ulKdDebuggerEnabled)); } ULONG GetFuncAddrFromName(IN PCWSTR FunctionName) { UNICODE_STRING FuncName; RtlInitUnicodeString(&FuncName, FunctionName); return (ULONG)MmGetSystemRoutineAddress(&FuncName); } VOID DriverUnload(PDRIVER_OBJECT pDriverObject) { //KdpStub头部5个字节 char code[5] = {(char)0x8b, (char)0xff, (char)0x55, (char)0x8b, (char)0xec}; //恢复内核变量 RecoverGlobal(); //删除回调 PsRemoveLoadImageNotifyRoutine(LoadImageRoutine); HookIoAllocMdl(FALSE); //恢复KdpStub头部 UnInlineHookEngine(ulKdpStub, code, 5); //恢复KdDisableDebugger头部 WritableOpen(); __asm { pushad pushfd mov eax, ulKdDisableDebugger mov byte ptr ds:[eax], 0x6a mov byte ptr ds:[eax + 0x1], 0x01 popfd popad } //改写KdDebuggerEnabled为1 __asm { pushad pushfd mov eax, ulKdDebuggerEnabled mov dword ptr ds:[eax], 0x1 popfd popad } WritableClose(); } //查找函数地址 PVOID GetFuncAddress(LPWSTR lpFuncName) { PVOID pFuncName; UNICODE_STRING usFuncName; RtlInitUnicodeString(&usFuncName, lpFuncName); KdPrint(("%wZ\n", &usFuncName)); pFuncName = MmGetSystemRoutineAddress(&usFuncName); return pFuncName; } void WPOFF() { //选择性编译,是给编译器看的 #ifdef _WIN64 _disable(); __writecr0(__readcr0() & (~(0x10000))); #else __asm { CLI; MOV EAX, CR0; AND EAX, NOT 10000H; MOV CR0, EAX; } #endif } void WPON() { #ifdef _WIN64 __writecr0(__readcr0() ^ 0x10000); _enable(); #else __asm { MOV EAX, CR0; OR EAX, 10000H; MOV CR0, EAX; STI; } #endif } ULONG_PTR GetKeUpdateSystemTimeAddr() { ULONG i; PUCHAR pStart = (PUCHAR)ul_KeUpdateSystemTimeAssist; ULONG_PTR retAddress; for (i = 0; i < 100; i++) { if (*(pStart + i) == 0xe8 && *(pStart + i + 5) == 0xfa) { retAddress = *(ULONG_PTR*)(pStart + i + 1) + (ULONG_PTR)(pStart + i) + 5; return retAddress; } } return 0; } ULONG_PTR GetKdCheckForDebugBreak() { ULONG i; PUCHAR pStart = (PUCHAR)ul_KeUpdateRunTime; ULONG_PTR retAddress; for (i = 0x100; i < 0x200; i++) { if (*(pStart + i) == 0xe8 && *(pStart + i + 5) == 0x5f) { retAddress = *(ULONG_PTR*)(pStart + i + 1) + (ULONG_PTR)(pStart + i) + 5; return retAddress; } } return 0; } ULONG_PTR GetKdDebuggerEnabled_1() { ULONG i; PUCHAR pStart = (PUCHAR)ul_KeUpdateSystemTime; ULONG_PTR retAddress; for (i = 0x400; i < 0x500; i++) { if (*(pStart + i) == 0x80 && *(pStart + i + 1) == 0x3d && *(pStart + i + 7) == 0x74 && *(pStart + i + 8) == 0x64) { retAddress = (ULONG_PTR)(pStart + i + 2); return retAddress; } } return 0; } ULONG_PTR GetKdDebuggerEnabled_2() { ULONG i; PUCHAR pStart = (PUCHAR)ul_KeUpdateRunTime; ULONG_PTR retAddress; for (i = 0x100; i < 0x200; i++) { if (*(pStart + i) == 0x80 && *(pStart + i + 1) == 0x3d && *(pStart + i + 7) == 0x74 && *(pStart + i + 8) == 0x12) { retAddress = (ULONG_PTR)(pStart + i + 2); return retAddress; } } return 0; } ULONG_PTR GetKdDebuggerEnabled_3() { ULONG i; PUCHAR pStart = (PUCHAR)ul_KdCheckForDebugBreak; ULONG_PTR retAddress; for (i = 0; i < 100; i++) { if (*(pStart + i) == 0x80 && *(pStart + i + 1) == 0x3d && *(pStart + i + 7) == 0x74 && *(pStart + i + 8) == 0x10) { retAddress = (ULONG_PTR)(pStart + i + 2); return retAddress; } } return 0; } ULONG_PTR GetKdDebuggerEnabled_4() { ULONG i; PUCHAR pStart = (PUCHAR)ul_KdPollBreakIn; ULONG_PTR retAddress; for (i = 0; i < 50; i++) { if (*(pStart + i) == 0x38 && *(pStart + i + 1) == 0x1d && *(pStart + i + 6) == 0x0f && *(pStart + i + 7) == 0x84) { retAddress = (ULONG_PTR)(pStart + i + 2); return retAddress; } } return 0; } ULONG_PTR GetKdPitchDebugger_1() { ULONG i; PUCHAR pStart = (PUCHAR)ul_KdCheckForDebugBreak; ULONG_PTR retAddress; for (i = 0; i < 100; i++) { if (*(pStart + i) == 0x80 && *(pStart + i + 1) == 0x3d && *(pStart + i + 7) == 0x75 && *(pStart + i + 8) == 0x19) { retAddress = (ULONG_PTR)(pStart + i + 2); return retAddress; } } return 0; } ULONG_PTR GetKdPitchDebugger_2() { ULONG i; PUCHAR pStart = (PUCHAR)ul_KdPollBreakIn; ULONG_PTR retAddress; for (i = 0; i < 100; i++) { if (*(pStart + i) == 0x38 && *(pStart + i + 1) == 0x1d && *(pStart + i + 6) == 0x74 && *(pStart + i + 7) == 0x07) { retAddress = (ULONG_PTR)(pStart + i + 2); return retAddress; } } return 0; } //转移内核变量函数 void MoveGlobal() { ul_KeUpdateSystemTimeAssist = (ULONG_PTR)GetFuncAddress(L"KeUpdateSystemTime"); ul_KeUpdateSystemTime = GetKeUpdateSystemTimeAddr(); ul_KdDebuggerEnabled_1 = GetKdDebuggerEnabled_1(); ul_KeUpdateRunTime = (ULONG_PTR)GetFuncAddress(L"KeUpdateRunTime"); ul_KdDebuggerEnabled_2 = GetKdDebuggerEnabled_2(); ul_KdCheckForDebugBreak = GetKdCheckForDebugBreak(); ul_KdDebuggerEnabled_3 = GetKdDebuggerEnabled_3(); ul_KdPitchDebugger_1 = GetKdPitchDebugger_1(); ul_KdPollBreakIn = (ULONG_PTR)GetFuncAddress(L"KdPollBreakIn"); ul_KdDebuggerEnabled_4 = GetKdDebuggerEnabled_4(); ul_KdPitchDebugger_2 = GetKdPitchDebugger_2(); //保存原始内核变量 ul_oldKdDebuggerEnabled = *(ULONG_PTR*)ul_KdDebuggerEnabled_1; ul_oldKdPitchDebugger = *(ULONG_PTR*)ul_KdPitchDebugger_1; WPOFF(); //开始转移内核变量 *(ULONG_PTR*)ul_KdDebuggerEnabled_1 = (ULONG_PTR)&bool_myKdDebuggerEnabled; *(ULONG_PTR*)ul_KdDebuggerEnabled_2 = (ULONG_PTR)&bool_myKdDebuggerEnabled; *(ULONG_PTR*)ul_KdDebuggerEnabled_3 = (ULONG_PTR)&bool_myKdDebuggerEnabled; *(ULONG_PTR*)ul_KdDebuggerEnabled_4 = (ULONG_PTR)&bool_myKdDebuggerEnabled; *(ULONG_PTR*)ul_KdPitchDebugger_1 = (ULONG_PTR)&bool_myKdPitchDebugger; *(ULONG_PTR*)ul_KdPitchDebugger_2 = (ULONG_PTR)&bool_myKdPitchDebugger; WPON(); KdPrint(("内核变量转移完成\n")); } //恢复转移的内核变量 void RecoverGlobal() { //恢复原来内核变量 WPOFF(); *(ULONG_PTR*)ul_KdDebuggerEnabled_1 = ul_oldKdDebuggerEnabled; *(ULONG_PTR*)ul_KdDebuggerEnabled_2 = ul_oldKdDebuggerEnabled; *(ULONG_PTR*)ul_KdDebuggerEnabled_3 = ul_oldKdDebuggerEnabled; *(ULONG_PTR*)ul_KdDebuggerEnabled_4 = ul_oldKdDebuggerEnabled; *(ULONG_PTR*)ul_KdPitchDebugger_1 = ul_oldKdPitchDebugger; *(ULONG_PTR*)ul_KdPitchDebugger_2 = ul_oldKdPitchDebugger; WPON(); KdPrint(("内核变量恢复完成\n")); }