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

我在里直接总结一下内核调试引擎的几个关键标志位,也是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[];
ULONG Base;
ULONG Size;
ULONG Flags;
USHORT Index;
USHORT Unknown;
USHORT LoadCount;
USHORT ModuleNameOffset;
CHAR ImageName[];
} SYSTEM_MODULE_INFORMATION, *PSYSTEM_MODULE_INFORMATION; typedef struct _tagSysModuleList//模块链结构
{
ULONG ulCount;
SYSTEM_MODULE_INFORMATION smi[];
}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[] =
{
OP_MODRM, //
OP_MODRM, //
OP_MODRM, //
OP_MODRM, //
OP_DATA_I8, //
OP_DATA_PRE66_67, //
OP_NONE, //
OP_NONE, //
OP_MODRM, //
OP_MODRM, //
OP_MODRM, // 0A
OP_MODRM, // 0B
OP_DATA_I8, // 0C
OP_DATA_PRE66_67, // 0D
OP_NONE, // 0E
OP_NONE, // 0F
OP_MODRM, //
OP_MODRM, //
OP_MODRM, //
OP_MODRM, //
OP_DATA_I8, //
OP_DATA_PRE66_67, //
OP_NONE, //
OP_NONE, //
OP_MODRM, //
OP_MODRM, //
OP_MODRM, // 1A
OP_MODRM, // 1B
OP_DATA_I8, // 1C
OP_DATA_PRE66_67, // 1D
OP_NONE, // 1E
OP_NONE, // 1F
OP_MODRM, //
OP_MODRM, //
OP_MODRM, //
OP_MODRM, //
OP_DATA_I8, //
OP_DATA_PRE66_67, //
OP_NONE, //
OP_NONE, //
OP_MODRM, //
OP_MODRM, //
OP_MODRM, // 2A
OP_MODRM, // 2B
OP_DATA_I8, // 2C
OP_DATA_PRE66_67, // 2D
OP_NONE, // 2E
OP_NONE, // 2F
OP_MODRM, //
OP_MODRM, //
OP_MODRM, //
OP_MODRM, //
OP_DATA_I8, //
OP_DATA_PRE66_67, //
OP_NONE, //
OP_NONE, //
OP_MODRM, //
OP_MODRM, //
OP_MODRM, // 3A
OP_MODRM, // 3B
OP_DATA_I8, // 3C
OP_DATA_PRE66_67, // 3D
OP_NONE, // 3E
OP_NONE, // 3F
OP_NONE, //
OP_NONE, //
OP_NONE, //
OP_NONE, //
OP_NONE, //
OP_NONE, //
OP_NONE, //
OP_NONE, //
OP_NONE, //
OP_NONE, //
OP_NONE, // 4A
OP_NONE, // 4B
OP_NONE, // 4C
OP_NONE, // 4D
OP_NONE, // 4E
OP_NONE, // 4F
OP_NONE, //
OP_NONE, //
OP_NONE, //
OP_NONE, //
OP_NONE, //
OP_NONE, //
OP_NONE, //
OP_NONE, //
OP_NONE, //
OP_NONE, //
OP_NONE, // 5A
OP_NONE, // 5B
OP_NONE, // 5C
OP_NONE, // 5D
OP_NONE, // 5E
OP_NONE, // 5F
OP_NONE, //
OP_NONE, //
OP_MODRM, //
OP_MODRM, //
OP_NONE, //
OP_NONE, //
OP_NONE, //
OP_NONE, //
OP_DATA_PRE66_67, //
OP_MODRM | OP_DATA_PRE66_67, //
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, //
OP_DATA_I8, //
OP_DATA_I8, //
OP_DATA_I8, //
OP_DATA_I8, //
OP_DATA_I8, //
OP_DATA_I8, //
OP_DATA_I8, //
OP_DATA_I8, //
OP_DATA_I8, //
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, //
OP_MODRM | OP_DATA_PRE66_67, //
OP_MODRM | OP_DATA_I8, //
OP_MODRM | OP_DATA_I8, //
OP_MODRM, //
OP_MODRM, //
OP_MODRM, //
OP_MODRM, //
OP_MODRM, //
OP_MODRM, //
OP_MODRM, // 8A
OP_MODRM, // 8B
OP_MODRM, // 8C
OP_MODRM, // 8D
OP_MODRM, // 8E
OP_MODRM, // 8F
OP_NONE, //
OP_NONE, //
OP_NONE, //
OP_NONE, //
OP_NONE, //
OP_NONE, //
OP_NONE, //
OP_NONE, //
OP_NONE, //
OP_NONE, //
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[] =
{
OP_MODRM, //
OP_MODRM, //
OP_MODRM, //
OP_MODRM, //
OP_NONE, //
OP_NONE, //
OP_NONE, //
OP_NONE, //
OP_NONE, //
OP_NONE, //
OP_NONE, // 0A
OP_NONE, // 0B
OP_NONE, // 0C
OP_MODRM, // 0D
OP_NONE, // 0E
OP_MODRM | OP_DATA_I8, // 0F
OP_MODRM, //
OP_MODRM, //
OP_MODRM, //
OP_MODRM, //
OP_MODRM, //
OP_MODRM, //
OP_MODRM, //
OP_MODRM, //
OP_MODRM, //
OP_NONE, //
OP_NONE, // 1A
OP_NONE, // 1B
OP_NONE, // 1C
OP_NONE, // 1D
OP_NONE, // 1E
OP_NONE, // 1F
OP_MODRM, //
OP_MODRM, //
OP_MODRM, //
OP_MODRM, //
OP_MODRM, //
OP_NONE, //
OP_MODRM, //
OP_NONE, //
OP_MODRM, //
OP_MODRM, //
OP_MODRM, // 2A
OP_MODRM, // 2B
OP_MODRM, // 2C
OP_MODRM, // 2D
OP_MODRM, // 2E
OP_MODRM, // 2F
OP_NONE, //
OP_NONE, //
OP_NONE, //
OP_NONE, //
OP_NONE, //
OP_NONE, //
OP_NONE, //
OP_NONE, //
OP_NONE, //
OP_NONE, //
OP_NONE, // 3A
OP_NONE, // 3B
OP_NONE, // 3C
OP_NONE, // 3D
OP_NONE, // 3E
OP_NONE, // 3F
OP_MODRM, //
OP_MODRM, //
OP_MODRM, //
OP_MODRM, //
OP_MODRM, //
OP_MODRM, //
OP_MODRM, //
OP_MODRM, //
OP_MODRM, //
OP_MODRM, //
OP_MODRM, // 4A
OP_MODRM, // 4B
OP_MODRM, // 4C
OP_MODRM, // 4D
OP_MODRM, // 4E
OP_MODRM, // 4F
OP_MODRM, //
OP_MODRM, //
OP_MODRM, //
OP_MODRM, //
OP_MODRM, //
OP_MODRM, //
OP_MODRM, //
OP_MODRM, //
OP_MODRM, //
OP_MODRM, //
OP_MODRM, // 5A
OP_MODRM, // 5B
OP_MODRM, // 5C
OP_MODRM, // 5D
OP_MODRM, // 5E
OP_MODRM, // 5F
OP_MODRM, //
OP_MODRM, //
OP_MODRM, //
OP_MODRM, //
OP_MODRM, //
OP_MODRM, //
OP_MODRM, //
OP_MODRM, //
OP_MODRM, //
OP_MODRM, //
OP_MODRM, // 6A
OP_MODRM, // 6B
OP_MODRM, // 6C
OP_MODRM, // 6D
OP_MODRM, // 6E
OP_MODRM, // 6F
OP_MODRM | OP_DATA_I8, //
OP_MODRM | OP_DATA_I8, //
OP_MODRM | OP_DATA_I8, //
OP_MODRM | OP_DATA_I8, //
OP_MODRM, //
OP_MODRM, //
OP_MODRM, //
OP_NONE, //
OP_NONE, //
OP_NONE, //
OP_NONE, // 7A
OP_NONE, // 7B
OP_MODRM, // 7C
OP_MODRM, // 7D
OP_MODRM, // 7E
OP_MODRM, // 7F
OP_DATA_PRE66_67 | OP_REL32, //
OP_DATA_PRE66_67 | OP_REL32, //
OP_DATA_PRE66_67 | OP_REL32, //
OP_DATA_PRE66_67 | OP_REL32, //
OP_DATA_PRE66_67 | OP_REL32, //
OP_DATA_PRE66_67 | OP_REL32, //
OP_DATA_PRE66_67 | OP_REL32, //
OP_DATA_PRE66_67 | OP_REL32, //
OP_DATA_PRE66_67 | OP_REL32, //
OP_DATA_PRE66_67 | OP_REL32, //
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, //
OP_MODRM, //
OP_MODRM, //
OP_MODRM, //
OP_MODRM, //
OP_MODRM, //
OP_MODRM, //
OP_MODRM, //
OP_MODRM, //
OP_MODRM, //
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 + ) + *(ULONG*)(ulKdDisableDebugger + ) + ;
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 = ;
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 + ) return ;
}
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 >> ;
iReg = (*cPtr & 0x38) >> ;
iRM = *cPtr & ;
cPtr++; if ((Opcode == 0xF6) && !iReg) Flags |= OP_DATA_I8;
if ((Opcode == 0xF7) && !iReg) Flags |= OP_DATA_PRE66_67; SibPresent = !PFX67 & (iRM == );
switch (iMod)
{
case :
if ( PFX67 && (iRM == )) OffsetSize = ;
if (!PFX67 && (iRM == )) OffsetSize = ;
break;
case : OffsetSize = ;
break;
case : if (PFX67) OffsetSize = ; else OffsetSize = ;
break;
case : SibPresent = FALSE;
}
if (SibPresent)
{
if (((*cPtr & ) == ) && ( (!iMod) || (iMod == ) )) OffsetSize = ;
cPtr++;
}
cPtr = (PUCHAR)(ULONG)cPtr + OffsetSize;
} if (Flags & OP_DATA_I8) cPtr ++;
if (Flags & OP_DATA_I16) cPtr += ;
if (Flags & OP_DATA_I32) cPtr += ;
if (PFX66) Add = ;
else Add = ;
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 = ; do
{
Length = SizeOfCode(Proc, &pOpcode);
if ((Length == ) && (*pOpcode == 0xC3)) break;
if ((Length == ) && (*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 - ; 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 = ;
PVOID pAddress = ;
KSPIN_LOCK spinlock;
KIRQL oldirql; if (!Address) return st;
pMdl = IoAllocateMdl(Address, Size, FALSE, FALSE, );
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[] = {0xe9, , , , };//相对跳转
BYTE Jmp_Orig_Code[] = {0xea, , , , , 0x08, 0x00};//绝对地址跳转
PatchSize = GetPatchSize(Func, );//获得要Patch的字节数
//构造Proxy_Func
memcpy((PBYTE)Proxy_Func, (PBYTE)Func, PatchSize);//实现原函数头
*((PULONG)(Jmp_Orig_Code + )) = (ULONG)((PBYTE)Func + PatchSize);//原函数+N地址
memcpy((PBYTE)Proxy_Func + PatchSize, Jmp_Orig_Code, );//绝对地址跳转
*((ULONG*)(g_HookCode + )) = (ULONG)New_Func - (ULONG)Func - ;//计算JMP地址
WriteKernelMemory(Func, , g_HookCode);
} //UnHook函数
void UnHook(PVOID Func, PVOID Proxy_Func)
{
WriteKernelMemory(Func, , Proxy_Func);
} void HookIoAllocMdl(BOOLEAN bEnble)
{
if (bEnble == TRUE)
{
OldIoAllocateMdl = kmalloc();
memset(OldIoAllocateMdl, 0x90, );
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[];
ULONG i = ; while(i --)
{
RtlMoveMemory(szTemp, (char*)uAddr, uLength); if (RtlCompareMemory(pCode, szTemp, uLength) == uLength)
{
return uAddr;
} uAddr ++;
} return ;
} 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[] = {(char)0x40, (char)0x3b, (char)0xc1, (char)0x72}; ulTemp = FindCharacteristicCode(uStartSearchAddr, code, ) + 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[] = {(char)0x50, (char)0x50, (char)0xe8};
char code2[] = {(char)0x85, (char)0xc0, (char)0x0f}; uTemp = FindCharacteristicCode(uStartSearchAddr, code1, ) + ; if (!MmIsAddressValid((PVOID)uTemp))
{
KdPrint(("uTemp is invalid!\n"));
return;
} ulKdInitSystem = uTemp + *(ULONG*)(uTemp + ) + ;
KdPrint(("ulKdInitSystem: 0x%08X\n", ulKdInitSystem)); uTemp = FindCharacteristicCode(ulKdInitSystem + 0x285, code2, );
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[] = {(char)0x33, (char)0xc0, (char)0x38}; ulTemp = FindCharacteristicCode(uStartSearchAddr, code, ); ulKdDebuggerEnabled = *(ULONG*)(ulTemp + );
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[] = {(char)0x8b, (char)0xff, (char)0x55, (char)0x8b, (char)0xec}; //恢复内核变量
RecoverGlobal(); //删除回调
PsRemoveLoadImageNotifyRoutine(LoadImageRoutine);
HookIoAllocMdl(FALSE); //恢复KdpStub头部
UnInlineHookEngine(ulKdpStub, code, ); //恢复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 = ; i < ; i++)
{
if (*(pStart + i) == 0xe8 &&
*(pStart + i + ) == 0xfa)
{
retAddress = *(ULONG_PTR*)(pStart + i + ) + (ULONG_PTR)(pStart + i) + ;
return retAddress;
}
}
return ;
} 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 + ) == 0x5f)
{
retAddress = *(ULONG_PTR*)(pStart + i + ) + (ULONG_PTR)(pStart + i) + ;
return retAddress;
}
}
return ;
} 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 + ) == 0x3d &&
*(pStart + i + ) == 0x74 &&
*(pStart + i + ) == 0x64)
{
retAddress = (ULONG_PTR)(pStart + i + );
return retAddress;
}
}
return ;
} 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 + ) == 0x3d &&
*(pStart + i + ) == 0x74 &&
*(pStart + i + ) == 0x12)
{
retAddress = (ULONG_PTR)(pStart + i + );
return retAddress;
}
}
return ;
} ULONG_PTR GetKdDebuggerEnabled_3()
{
ULONG i;
PUCHAR pStart = (PUCHAR)ul_KdCheckForDebugBreak;
ULONG_PTR retAddress;
for (i = ; i < ; i++)
{
if (*(pStart + i) == 0x80 &&
*(pStart + i + ) == 0x3d &&
*(pStart + i + ) == 0x74 &&
*(pStart + i + ) == 0x10)
{
retAddress = (ULONG_PTR)(pStart + i + );
return retAddress;
}
}
return ;
} ULONG_PTR GetKdDebuggerEnabled_4()
{
ULONG i;
PUCHAR pStart = (PUCHAR)ul_KdPollBreakIn;
ULONG_PTR retAddress;
for (i = ; i < ; i++)
{
if (*(pStart + i) == 0x38 &&
*(pStart + i + ) == 0x1d &&
*(pStart + i + ) == 0x0f &&
*(pStart + i + ) == 0x84)
{
retAddress = (ULONG_PTR)(pStart + i + );
return retAddress;
}
}
return ;
} ULONG_PTR GetKdPitchDebugger_1()
{
ULONG i;
PUCHAR pStart = (PUCHAR)ul_KdCheckForDebugBreak;
ULONG_PTR retAddress;
for (i = ; i < ; i++)
{
if (*(pStart + i) == 0x80 &&
*(pStart + i + ) == 0x3d &&
*(pStart + i + ) == 0x75 &&
*(pStart + i + ) == 0x19)
{
retAddress = (ULONG_PTR)(pStart + i + );
return retAddress;
}
}
return ;
} ULONG_PTR GetKdPitchDebugger_2()
{
ULONG i;
PUCHAR pStart = (PUCHAR)ul_KdPollBreakIn;
ULONG_PTR retAddress;
for (i = ; i < ; i++)
{
if (*(pStart + i) == 0x38 &&
*(pStart + i + ) == 0x1d &&
*(pStart + i + ) == 0x74 &&
*(pStart + i + ) == 0x07)
{
retAddress = (ULONG_PTR)(pStart + i + );
return retAddress;
}
}
return ;
} //转移内核变量函数
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"));
}

WinDbg调试流程的学习及对TP反调试的探索的更多相关文章

  1. Win7 x86内核调试与TP反调试的研究

    参考  这两天对某P双机调试的学习及成果 ,非常好的一篇分析贴. 本文在Win7 x86下的分析,在虚拟机中以/DEBUG模式启动TP游戏,系统会自动重启. 0x01 内核调试全局变量  根据软件调试 ...

  2. C/C++ 程序反调试的方法

    C/C++ 要实现程序反调试有多种方法,BeingDebugged,NtGlobalFlag,ProcessHeap,CheckRemoteDebuggerPresent,STARTUPINFO,Is ...

  3. 修改Android手机内核,绕过反调试

    本文博客链接:http://blog.csdn.net/qq1084283172/article/details/57086486 0x1.手机设备环境 Model number: Nexus 5 O ...

  4. 反调试手法之CreateProcess反调试

    反调试手法之CreateProcess反调试 在学习Win32 创建进程的时候.我们发现了有一个进程信息结构体. STARTUPINFO. 这个结构体可以实现反调试. 具体CreateProcess可 ...

  5. 反调试技术常用API,用来对付检测od和自动退出程序

    在调试一些病毒程序的时候,可能会碰到一些反调试技术,也就是说,被调试的程序可以检测到自己是否被调试器附加了,如果探知自己正在被调试,肯定是有人试图反汇编啦之类的方法破解自己.为了了解如何破解反调试技术 ...

  6. 浅谈android反调试之 API判断

    反调试:利用Java层API来判断Android程序是否是处于被调试下. 1.直接调用系统的android.os.Debug.isDebuggerConnected()方法 我们进行动态调试的时候,其 ...

  7. APP加固反调试(Anti-debugging)技术点汇总

    0x00 时间相关反调试 通过计算某部分代码的执行时间差来判断是否被调试,在Linux内核下可以通过time.gettimeofday,或者直接通过sys call来获取当前时间.另外,还可以通过自定 ...

  8. 反调试代码调试死机代码禁止F12代码

    反调试代码调试死机代码禁止F12代码  // 反调试函数,参数:开关,执行代码 function siji(){    var total="";    for (var i=0; ...

  9. Vue源码学习(一):调试环境搭建

    最近开始学习Vue源码,第一步就是要把调试环境搭好,这个过程遇到小坑着实费了点功夫,在这里记下来 一.调试环境搭建过程 1.安装node.js,具体不展开 2.下载vue项目源码,git或svn等均可 ...

随机推荐

  1. [转]Gridview中实现RadioButton单选效果

    HTML <asp:TemplateField ItemStyle-Width="22px"> <ItemTemplate> <asp:RadioBu ...

  2. svn merge和branch

    http://www.cnblogs.com/cxd4321/archive/2012/07/12/2588110.html 使用svn几年了,一直对分支和合并敬而远之,一来是因为分支的管理不该我操心 ...

  3. hmmer 使用(转载)

    hmmer 使用 » 转载文章请注明,转载自:博耘生物 » <hmmer的安装与使用> » 原文链接:http://boyun.sh.cn/bio/?p=1753   从功能基因研究的角度 ...

  4. apache maven

    aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAj0AAAGXCAYAAABY/uEUAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjw ...

  5. 基于.net mvc的校友录(六、codefirst的使用以及班级模块的关键部分实现)

    通过EF将新用户存入数据库 这里,探讨一下如何使用EF的code first将数据存入数据库,以及如何对用户的密码进行md5加密与验证.下面是用户登陆的前台代码. @using (Html.Begin ...

  6. ostream类重载的operator<<()函数

    ostream类重载了operator<<()以识别不同的类型,如: int short  long unsigned int unsigned short unsigned long f ...

  7. 20145129 《Java程序设计》第3周学习总结

    20145129 <Java程序设计>第3周学习总结 教材学习内容总结 类与对象 定义类 一个原始码中可以有多个类定义,但只有一个是公开类(public),并且文档中的主文档名必须和公开类 ...

  8. 四则运算2--c++

    1.设计思路: 上篇已写,不在解释..... 2.源代码: #include<iostream.h>#include<stdlib.h>#include "time. ...

  9. 团队作业(NABC的分析)

    我们的团队课题是游戏:躲避小球. 我认为它其中的一个优点是:丰富用户的短暂闲暇时间,使用户得到身心的放松 下面我将从N,A,B,C四个方面简述理由 N(需求):现代社会逐渐步入快节奏时代,大众生活压力 ...

  10. Class.forName("com.mysql.jdbc.Driver");的作用

    对于大的项目当然我们都已经有了原有基本框架,但是对于一些新的技术探讨的时候,我们还是直接调用Class.forName("com.mysql.jdbc.Driver")连接数据库进 ...