WinDbg调试流程的学习及对TP反调试的探索

基础知识推荐阅读《软件调试》的第十八章 内核调试引擎

我在里直接总结一下内核调试引擎的几个关键标志位,也是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(("注册回调函数成功!
"));
    HookIoAllocMdl(TRUE);
    //获得KdDisableDebugger地址
    ulKdDisableDebugger = GetFuncAddrFromName(L"KdDisableDebugger");
    KdPrint(("ulKdDisableDebugger: 0x%08X
", ulKdDisableDebugger));
    //计算KdDisableDebuggerWithLock地址
    ulKdDisableDebuggerWithLock = (ulKdDisableDebugger + 2) + *(ULONG*)(ulKdDisableDebugger + 3) + 5;
    KdPrint(("ulKdDisableDebuggerWithLock: 0x%08X
",  ulKdDisableDebuggerWithLock));
    ulKeEnterKernelDebugger = GetFuncAddrFromName(L"KeEnterKernelDebugger");
    KdPrint(("ulKeEnterKernelDebugger: 0x%08X
", 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
", 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!
");
    }
    else
    {
        UnHook(IoAllocateMdl, OldIoAllocateMdl);
        ExFreePool(OldIoAllocateMdl);
        DbgPrint("IoAllocateMdl unhooked!
");
    }
}

//模块加载回调函数例程
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!
"));
        KdPrint(("TesSafe.sys ImageBase: 0x%08X
", (ULONG)ImageInfo->ImageBase));
        KdPrint(("TesSafe.sys ImageSize: 0x%08X
", (ULONG)ImageInfo->ImageSize));
        KdPrint(("断点命令: ba e 1 0x%08X
", (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!
"));
        return;
    }

    ulKdpStub = *(ULONG*)ulTemp;

    KdPrint(("ulKdpStub: 0x%08X
", 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!
"));
        return;
    }

    ulKdInitSystem = uTemp + *(ULONG*)(uTemp + 1) + 5;
    KdPrint(("ulKdInitSystem: 0x%08X
", ulKdInitSystem));

    uTemp = FindCharacteristicCode(ulKdInitSystem + 0x285, code2, 3);
    ulKdpTrap = *(ULONG*)(uTemp + 0x15);
    KdPrint(("ulKdpTrap: 0x%08X
", 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
", 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
", &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(("内核变量转移完成
"));
}

//恢复转移的内核变量
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(("内核变量恢复完成
"));
}
原文地址:https://www.cnblogs.com/lanrenxinxin/p/4378218.html