首页
社区
课程
招聘
[讨论]一种新思路来过TP双机调试但是结果很雷
发表于: 2013-4-29 02:39 9936

[讨论]一种新思路来过TP双机调试但是结果很雷

2013-4-29 02:39
9936
KdDisableDebugger 长度70
804f7602 8bff            mov     edi,edi
804f7604 55              push    ebp
804f7605 8bec            mov     ebp,esp
804f7607 51              push    ecx
804f7608 b102            mov     cl,2
804f760a ff15f4864d80    call    dword ptr [nt!_imp_KfRaiseIrql (804d86f4)]
804f7610 8845ff          mov     byte ptr [ebp-1],al
804f7613 e81c010000      call    nt!KdpPortLock (804f7734)                        //进入这个里面的函数进行HOOK,直接JMP到下面的804f7670
804f7618 833dc8c8548000  cmp     dword ptr [nt!KdDisableCount (8054c8c8)],0
804f761f 753a            jne     nt!KdDisableDebugger+0x59 (804f765b)
804f7621 a0c1c85480      mov     al,byte ptr [nt!KdDebuggerEnabled (8054c8c1)]
804f7626 84c0            test    al,al
804f7628 7410            je      nt!KdDisableDebugger+0x38 (804f763a)
804f762a 803dfc62548000  cmp     byte ptr [nt!KdPitchDebugger (805462fc)],0
804f7631 c605ccc8548001  mov     byte ptr [nt!KdPreviouslyEnabled (8054c8cc)],1
804f7638 7407            je      nt!KdDisableDebugger+0x3f (804f7641)
804f763a c605ccc8548000  mov     byte ptr [nt!KdPreviouslyEnabled (8054c8cc)],0
804f7641 84c0            test    al,al
804f7643 7416            je      nt!KdDisableDebugger+0x59 (804f765b)
804f7645 e8d47a1600      call    nt!KdpSuspendAllBreakpoints (8065f11e)                  //当执行到这里的时候双机调试会直接断掉
804f764a c705e4325580ec7a4f80 mov dword ptr [nt!KiDebugRoutine (805532e4)],offset nt!KdpStub (804f7aec)
804f7654 c605c1c8548000  mov     byte ptr [nt!KdDebuggerEnabled (8054c8c1)],0
804f765b ff05c8c85480    inc     dword ptr [nt!KdDisableCount (8054c8c8)]
804f7661 e8de000000      call    nt!KdpPortUnlock (804f7744)
804f7666 8a4dff          mov     cl,byte ptr [ebp-1]
804f7669 ff151c874d80    call    dword ptr [nt!_imp_KfLowerIrql (804d871c)]
804f766f c9              leave
804f7670 c3              ret //准备从子函数跳转到这个位置来

思路如下:

下面是call KdpPortLock里面的实现代码
804f78ce b94cbe5480      mov     ecx,offset nt!IoStatisticsLock+0x4 (8054be4c)
804f78d3 e988620400      jmp     nt!KiAcquireSpinLock (8053db60) nt!KiAcquireSpinLock里面第一行就是一个ret;
没有任何作用

将  jmp     nt!KiAcquireSpinLock (8053db60)
改成jmp    804f7670
直接跳转到KdDisableDebugger 里面804f7670 地址,相当于直接返回;
这样应该就可以无视别人去检测KdDisableDebugger里面的代码了
但是……
当我HOOK后,还没直接调用就黑屏
为什么是黑屏,不是蓝屏!!!为什么会黑屏?这问题出的好有个性……

直接贴代码吧!这是一种新的思路,但不知道这种方式是否可行,忘大牛指教,本人技术比较菜,代码可能有点乱,所以随便喷吧……
ULONG JMP_RETADDR = 0;//上一层函数返回的地址
BYTE ByteBuff[4] = {0,0,0,0};//需要恢复的数据
ULONG UlongBuff;
ULONG nWriteAddr;//写入的地址
void __declspec(naked) my_function_detour_Shuangji()
{
//获得调用者的EPROCESS
        ANSI_STRING str_1;
        ANSI_STRING str_Name;
        processEPROCESSB = IoGetCurrentProcess();
        //将调用者的进程名保存到str1中
        ULONG aaabb;
        int naa;
        char *pch;
        aaabb = (ULONG)processEPROCESSB;
        aaabb += 0x174;
        pch = (char*)aaabb;
        naa = UlongBuff;
        //DbgPrint("%s\n",pch);
//改成这样都会直接黑屏
        _asm
        {
                ret
        }
        //将我们要比对的进程名放入str1和str2
        //RtlInitAnsiString(&str_1,TP_EXE);//说明是TP进程访问了这里
        ////这里判断ESP的值是多少
        //ULONG ESPAddr;
        //_asm
        //{
        //        mov ESPAddr,esp-4
        //}
        //if (RtlCompareString(&str_Name,&str_1,TRUE) == 0)
        //{
        //        _asm
        //        {
        //                mov eax,JMP_RETADDR
        //                jmp eax;
        //        }
        //}
        //else
        //{
        //        _asm
        //        {
        //                mov eax,UlongBuff
        //                jmp eax;
        //        }
        //}
}

void Pass_Shuangji()
{
        BYTE* KdDisableDebuggerAddr = (BYTE*)GetNt_OldAddr(L"KdDisableDebugger");;
        PULONG KdpPortLockAddr = NULL;
        if(KdDisableDebuggerAddr == NULL)
        {
                DbgPrint("没有找到KdDisableDebugger地址\n");
                return;
        }
        KdPrint(("KdDisableDebuggerAddr = %X\n"),KdDisableDebuggerAddr);
        BYTE* i = NULL;
        //找到KdpPortLock的函数地址
        for(i = KdDisableDebuggerAddr;i < KdDisableDebuggerAddr+0x70;i++)
        {
                if( ( *(i-1) == 0xE8 ) &&
                        ( *(i+4) == 0x83 ) &&
                        ( *(i-2) == 0xff ) &&
                        ( *(i-3) == 0x45 ) &&
                        ( *(i-4) == 0x88 )
                        )
                {
                        int n1  = *(PULONG)i;
                        KdpPortLockAddr = (PULONG)(i + n1);
                        KdpPortLockAddr++; //加上*i所占的4字节
                        DbgPrint("KdpPortLockAddr = %X\n",KdpPortLockAddr);
                        break;

                }
        }
        if(KdpPortLockAddr == NULL)
        {
                DbgPrint("没有找到KdpPortLockAddr地址\n");
                return;
        }
        BOOL b = TRUE;
        for(i = KdDisableDebuggerAddr;i < KdDisableDebuggerAddr+0x70;i++)
        {
                if( ( *(i) == 0xC3 ) &&
                        ( *(i-1) == 0xC9 ) &&
                        ( *(i-10) == 0x8A ))
                {
                        DbgPrint("RET的地址 = %X\n",i);
                        JMP_RETADDR = (ULONG)(i);
                        b =FALSE;
                        break;

                }
        }
        if(b)
        {
                DbgPrint("RET的地址没有找到\n");
                return;
        }
        //要写入的字节
        BYTE    JmpAddress[4] = {0,0,0,0};
        KIRQL    Irql;
        nWriteAddr = (ULONG)((ULONG)KdpPortLockAddr+6);
        ULONG n = ((ULONG)my_function_detour_Shuangji - (ULONG )(nWriteAddr+4));
        DbgPrint("nWriteAddr = %X\n",nWriteAddr);
        DbgPrint("my_function_detour_Shuangji = %X\n",my_function_detour_Shuangji);
        *(PULONG)JmpAddress = n;
        //获得原来需要跳转的地址
        ULONG m =  *(PULONG)nWriteAddr;
        UlongBuff = (nWriteAddr + m) + 4;

        WPOFF();//去掉页面保护
        Irql=KeRaiseIrqlToDpcLevel();
        //记录原来的值,用于恢复HOOK
        RtlCopyMemory(ByteBuff,(void*)nWriteAddr,4);
        //写入
        RtlCopyMemory((void*)nWriteAddr,JmpAddress,4);
        //恢复Irql
        KeLowerIrql(Irql);
        WPON();//恢复页面保护
}
void UnShuangji()
{
        KIRQL    Irql;
        WPOFF();//去掉页面保护
        Irql=KeRaiseIrqlToDpcLevel();
        //恢复原来的值
        RtlCopyMemory((void*)nWriteAddr,ByteBuff,4);
        //恢复Irql
        KeLowerIrql(Irql);
        WPON();//恢复页面保护

}

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 0
支持
分享
最新回复 (8)
雪    币: 115
活跃值: (46)
能力值: ( LV4,RANK:40 )
在线值:
发帖
回帖
粉丝
2
黑屏分两种,重启后自检卡在硬盘那里一会儿,说明是你的代码把系统弄黑的
第二种,TP直接写键盘端口导致的直接重启

个人喜欢修改ntoskrnl.exe过调试,但MS有校验,非要开启调试模式才可以用
2013-4-29 09:25
0
雪    币: 141
活跃值: (318)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
感觉有点高深,只有看到这在学吧
2013-4-29 10:43
0
雪    币: 257
活跃值: (67)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
4
这样改,有2个很严重的错误
一是堆栈不平衡
804f7613    e81c010000    call    nt!KdpPortLock (804f7734)
从这个call的内部直接跳转到KdDisableDebugger的ret,未做堆栈处理
再是中断请求级前后不匹配
前面提高了中断请求级
804f760a    ff15f4864d80    call    dword ptr [nt!_imp_KfRaiseIrql (804d86f4)]
LZ这样改代码会跳过后面的call    dword ptr [nt!_imp_KfLowerIrql (804d871c)]
居然还没有BSOD,表示很惊奇...
2013-4-29 11:59
0
雪    币: 32
活跃值: (13)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
额,我看了这两个调用的函数,都是没有参数,这样还是会堆栈不平衡吗?那个直接ret只是测试一下;假如我没有HOOK之前,在那里下断发现没有任何函数来调用,当我HOOK后,就马上中断在我函数里面的_asm int3;里面了,然后go的话就黑屏了,而且中断的时候发现当前调用者是system这个进程名,这也是不平衡的原因吗?我应该怎么看堆栈是否平衡?
2013-4-29 13:13
0
雪    币: 32
活跃值: (13)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
……这还没测试TP,只是HOOK后就直接黑屏……
2013-4-29 13:15
0
雪    币: 32
活跃值: (13)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
现在hook正常
但是当运行禁用双机调试的函数,运行HOOK函数里面的JMP 804f7670 这个地址
又ret回了HOOK函数my_function_detour_Shuangji();
然后一直这样死循环,然后蓝屏,将esp +4;或者+8都会蓝屏,求讲解下
谢谢
2013-4-29 16:02
0
雪    币: 32
活跃值: (13)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
纠结了
计算了esp调用前的值
重新修改后还是不行……
ret失败了、、
这种方法貌似不可行,不知道会不会有高手知道怎么完成这种思路,作为菜鸟,飘过了
最终用了另外一种方法完成了KdDisableDebugger的HOOK
无视了这个函数的调用了
2013-4-29 17:47
0
雪    币: 508
活跃值: (202)
能力值: ( LV9,RANK:160 )
在线值:
发帖
回帖
粉丝
9
KdDisableDebugger
下个
ba r4 KdDisableDebugger
找到保护的CRC较验Kill掉CRC的函数就OK
2013-4-30 17:15
0
游客
登录 | 注册 方可回帖
返回
//