[模仿]对双机调试的学习
首先要谢谢 zfdyq我是看了他的帖子还有代码一步步验证过来的。
当然在调试的过程中间出了很多问题,但是都一个个解决了,收获还是蛮多的。
我的大体思路都是跟着zfdyq来的,就是关于kdptrap这一块在代码里面没有看到(是我太笨了,没能领略其它的奥妙

),我用搜索栈的方法改变这个值。其他地方可以说基本没做多少变动,不要打我,我太懒了
,回头研究内核重载时候一定自己写代码。。。。
我还是新手,才学会windbg这些玩意

,大神一笑而过就可以了

进入正题吧
一、对三个部分的个人理解
1.关于KdEnteredDebugger
我根据大牛写的这个帖子http://bbs.pediy.com/showthread.php?t=186091将错误都重现了一遍。我感觉搞这个调试,最重要的能力是重现错误。一开始我是在xp下研究的,但是后来保护过了,却下不了断,而且我回溯栈然后搜索只有两处用到KdDeBuggerEnable,没有看到对KdCheckForDebugBreak的调用,所以没法搜索到KdPitchDebugger。但是有一次,竟然出现了KdCheckForDebugBreak的断点,好吧,那时候我还不会栈回溯,直接跳过,然后蓝屏。以后再没遇到过
只好放弃了xp,昨天重装的win7 32.
解决方法就是用大牛提供的思路,Hook这个函数IoAllocateMdl,代码就不贴了。实现原理,我猜是返回一个虚拟地址,映射到KdEnteredDebugger所在物理地址,这样*P就可以按照自己的方式操纵这个变量,不用遵循内核的保护。
2.关于绕过 kdsendpacket KdReceivePacket
先上图,大概解释一下我的理解

本人能力有限,不知道童鞋们能看懂不。主要就是,搜索导出表,找到最初 kdsendpacket KdReceivePacket地址,给我们的全局变量,然后用我们自己的全局变量替换那个中转变量imp_KdSendPacket imp_KdReceivePacket。。。
3.让*P自己把kdptrap地址写入KiDebugRoutine
还是上图

*P是在第二次调用KdDisableDebugger时候要将KiDebugRoutine写成kdpstub,然后我们就是在hook函数里面通过栈上面的返回地址,得到*P改写的那一段代码,在那段代码中得到保存kdpstub的地址,然后将kdptrap地址写入就好了。
二、简单叙述一下流程
1.关于恢复断点功能,如何得知要转移哪些变量
我一开始在ida里面搜索KdDeBuggerEnable,好家伙,一大排

。。。
后来经请教得知,要栈回溯。。一语惊醒梦中人啊。
就是要看看正常情况一个断点经过哪些函数,然后再搜索就可以。。。一层窗户纸,不点不破

可以看到断点信息包的处理流程。在xp下死活搜不到KdCheckForDebugBreak。。。ida里面显示调用KdCheckForDebugBreak的函数都是一些io函数,好奇怪
后面会附上搜索到的相关数据
2.对于*P调用KdDisableDebugger的处理
开始在测试的时候,不知道游戏开始前提前给KdDisableDebugger下断,等游戏开始后一直没法和vm建立联系了。。。都怀疑帖子里面怎么可能做到下断点呢

先下好断点,填上nop 和ret

开始游戏,第一次断下来了,单步步过,回到调用函数,发现里面的edi存的是KdDebuggerEnabled,不能直接改代码,我怕有校验,就改了edi指向的数据



继续,第二次断下来就是*P对KiDebugRoutine的赋值了,直接得到kdptrap的地址,覆盖过去就好了,前面已经解释过了。



ok,到此,已经可以进入游戏了。
3.在验证过程中遇到的些问题
先上一张导出表

1.在导出表里面没有KeUpdateSystemTimeAssist,但是用KeUpdateSystemTime竟然可以得到前者的地址,我开始还沾沾自喜的以为发现了学长的错误,后来一直蓝屏蓝屏。。。。

可以看到dd ul_KeUpdateSystemTime得到的是KeUpdateSystemTimeAssist,我又不得不用学长原来被我注释掉的那行代码

2.导出表里面也没有KeUpdateRunTime,但是可以获取到。。。好吧,我也不知道哪里没理解透彻
三、贴一些数据和代码
1.找那几个用来判断是否处于内核调试状态变量的数据
KeUpdateSystemTimeAssist nt!KeUpdateSystemTimeAssist: 83eb9e00 64ff05c4050000 inc dword ptr fs:[5C4h] 83eb9e07 ff3424 push dword ptr [esp] 83eb9e0a 8bcd mov ecx,ebp 83eb9e0c 8bd0 mov edx,eax 83eb9e0e e8da010000 call nt!KeUpdateSystemTime (83eb9fed) 83eb9e13 fa cli KeUpdateSystemTime 83eb9fed 83eba410 803d4c4afa8300 cmp byte ptr [nt!KdDebuggerEnabled (83fa4a4c)],0 83eba417 7464 je nt!KeUpdateSystemTime+0x48a (83eba47d) 83eba607 8b4c241c mov ecx,dword ptr [esp+1Ch] 83eba60b e80e000000 call nt!KeUpdateRunTime (83eba61e) 83eba610 5f pop edi KeUpdateRunTime 83eba767 803d4c4afa8300 cmp byte ptr [nt!KdDebuggerEnabled (83fa4a4c)],0 83eba76e 7412 je nt!KeUpdateRunTime+0x164 (83eba782) 83eba77b 7505 jne nt!KeUpdateRunTime+0x164 (83eba782) 83eba77d e80c000000 call nt!KdCheckForDebugBreak (83eba78e) 83eba782 5f pop edi nt!KdCheckForDebugBreak: 83eba78e 803d278df68300 cmp byte ptr [nt!KdPitchDebugger (83f68d27)],0 83eba795 7519 jne nt!KdCheckForDebugBreak+0x22 (83eba7b0) 83eba797 803d4c4afa8300 cmp byte ptr [nt!KdDebuggerEnabled (83fa4a4c)],0 83eba79e 7410 je nt!KdCheckForDebugBreak+0x22 (83eba7b0) 83eba7a0 e822000000 call nt!KdPollBreakIn (83eba7c7) 83eba7a5 84c0 test al,al 83eba7a7 7407 je nt!KdCheckForDebugBreak+0x22 (83eba7b0) 83eba7a9 6a01 push 1 83eba7ab e804000000 call nt!DbgBreakPointWithStatus (83eba7b4) nt!KdPollBreakIn: 83eba7ce 33db xor ebx,ebx 83eba7d0 381d278df683 cmp byte ptr [nt!KdPitchDebugger (83f68d27)],bl 83eba7d6 7407 je nt!KdPollBreakIn+0x18 (83eba7df) 83eba7d8 32c0 xor al,al 83eba7da e9d2000000 jmp nt!KdPollBreakIn+0xea (83eba8b1) 83eba7df 885dff mov byte ptr [ebp-1],bl 83eba7e2 381d4c4afa83 cmp byte ptr [nt!KdDebuggerEnabled (83fa4a4c)],bl 83eba7e8 0f84c0000000 je nt!KdPollBreakIn+0xe7 (83eba8ae)
2.代码
ul_KdPollBreakIn = (ULONG_PTR)GetFuncAddress(L"KdPollBreakIn");
KdpTrapAddress = ul_KdPollBreakIn + 0x2b2d2b;
...
else if (bl_FirstInto_KdDsiableDebugger == 1){
//现在是第二次进来,此时要把kdptrap的值覆盖过去
//在这里获取kdptrap地址,
__asm
{
push eax;
push ebx;
mov eax, esp;//此时esp减少了14,单步试出来的
add eax, 14h;
mov eax, [eax]
add eax, 31h;
mov eax, [eax];
mov ebx, KdpTrapAddress;
mov [eax], ebx;
pop ebx;
pop eax;
}
bl_FirstInto_KdDsiableDebugger = -1;
//KdBreakPoint();
return 0;
最后上个图

代码我就不上传了吧, 大部分都是 zfdyq的代码。该休息一段时间了,要不然一研究起来,中午睡不着,晚上睡不着,吃饭想,走路想。。。连看妹子的心情都没有了



身体最重要啊。
最后的最后,学无止境,大家一定要多看书。
