【模仿】对双机调试的学习

首先要谢谢 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
先上图,大概解释一下我的理解
点击图片以查看大图图片名称: 19.png查看次数: 17文件大小: 45.6 KB文件 ID : 99371

本人能力有限,不知道童鞋们能看懂不。主要就是,搜索导出表,找到最初 kdsendpacket   KdReceivePacket地址,给我们的全局变量,然后用我们自己的全局变量替换那个中转变量imp_KdSendPacket   imp_KdReceivePacket。。。
3.让*P自己把kdptrap地址写入KiDebugRoutine
还是上图
点击图片以查看大图图片名称: 20.png查看次数: 8文件大小: 36.9 KB文件 ID : 99372

*P是在第二次调用KdDisableDebugger时候要将KiDebugRoutine写成kdpstub,然后我们就是在hook函数里面通过栈上面的返回地址,得到*P改写的那一段代码,在那段代码中得到保存kdpstub的地址,然后将kdptrap地址写入就好了。

二、简单叙述一下流程
1.关于恢复断点功能,如何得知要转移哪些变量
我一开始在ida里面搜索KdDeBuggerEnable,好家伙,一大排。。。
后来经请教得知,要栈回溯。。一语惊醒梦中人啊。
就是要看看正常情况一个断点经过哪些函数,然后再搜索就可以。。。一层窗户纸,不点不破

点击图片以查看大图图片名称: 1.png查看次数: 6文件大小: 6.7 KB文件 ID : 99373

可以看到断点信息包的处理流程。在xp下死活搜不到KdCheckForDebugBreak。。。ida里面显示调用KdCheckForDebugBreak的函数都是一些io函数,好奇怪
后面会附上搜索到的相关数据

2.对于*P调用KdDisableDebugger的处理
开始在测试的时候,不知道游戏开始前提前给KdDisableDebugger下断,等游戏开始后一直没法和vm建立联系了。。。都怀疑帖子里面怎么可能做到下断点呢
先下好断点,填上nop 和ret

名称:  8.png查看次数: 2文件大小:  5.3 KB

开始游戏,第一次断下来了,单步步过,回到调用函数,发现里面的edi存的是KdDebuggerEnabled,不能直接改代码,我怕有校验,就改了edi指向的数据
名称:  9.png查看次数: 2文件大小:  5.4 KB
名称:  10.png查看次数: 2文件大小:  1.2 KB
名称:  11.png查看次数: 0文件大小:  807 字节

继续,第二次断下来就是*P对KiDebugRoutine的赋值了,直接得到kdptrap的地址,覆盖过去就好了,前面已经解释过了。
名称:  12.png查看次数: 1文件大小:  13.8 KB
名称:  13.png查看次数: 0文件大小:  3.5 KB
名称:  14.png查看次数: 0文件大小:  3.3 KB
ok,到此,已经可以进入游戏了。

3.在验证过程中遇到的些问题
先上一张导出表
名称:  4.png查看次数: 1文件大小:  8.0 KB
1.在导出表里面没有KeUpdateSystemTimeAssist,但是用KeUpdateSystemTime竟然可以得到前者的地址,我开始还沾沾自喜的以为发现了学长的错误,后来一直蓝屏蓝屏。。。。
点击图片以查看大图图片名称: 5.png查看次数: 29文件大小: 22.3 KB文件 ID : 99369

可以看到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;
最后上个图
点击图片以查看大图图片名称: 22.png查看次数: 26文件大小: 510.2 KB文件 ID : 99370

代码我就不上传了吧, 大部分都是 zfdyq的代码。该休息一段时间了,要不然一研究起来,中午睡不着,晚上睡不着,吃饭想,走路想。。。连看妹子的心情都没有了
身体最重要啊。
最后的最后,学无止境,大家一定要多看书。 
展开阅读全文

没有更多推荐了,返回首页