欢迎来到 嗅灵易学

零基础也能上手的脚本技术课,一对一答疑带你入门

[模仿]对双机调试的学习

[模仿]对双机调试的学习

首先要谢谢 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的代码。该休息一段时间了,要不然一研究起来,中午睡不着,晚上睡不着,吃饭想,走路想。。。连看妹子的心情都没有了
身体最重要啊。
最后的最后,学无止境,大家一定要多看书。

上传的附件 9.png
10.png
11.png
12.png
13.png
14.png
4.png
5.png
22.png
19.png
20.png
1.png
8.png

注意:上传附件及图片大小不得大于30M。

⚠️ 版权声明:
本博客所有内容(含教程、源码、工具)仅供个人技术学习与研究交流使用,严禁商用、倒卖、二次分发及非法用途
未经作者书面授权,任何组织或个人不得转载、复制或用于其他平台,违者将追究相关责任。

0 0 0 举报
复制成功