首页
社区
课程
招聘
[求助]通过INLINEHOOK恢复IDT表导致蓝屏(现在能写了不过本世纪最奇怪的就是这个代码了)
发表于: 2009-8-28 22:00 19532

[求助]通过INLINEHOOK恢复IDT表导致蓝屏(现在能写了不过本世纪最奇怪的就是这个代码了)

2009-8-28 22:00
19532
请看代码:
/*******************************************************
*获取IDT表放入全局表中
***********************************************************/
void GetIDTAddr()
{
        unsigned long count;
        IDT_INFO idt_info;
        IDT_ENTRY *idt_entries;
       
        __asm sidt idt_info
               
                //取得idt_info中的函数地址
                idt_entries = (IDT_ENTRY*)MAKELONG(idt_info.IdtLow,idt_info.IdtHigh);
       
       
       
        for(count=0;count<256;count++)
        {
                //DbgPrint("ROOTKIT: OnUnload called\n");       
                char _t[255];
                IDT_ENTRY *i=&idt_entries[count];
                unsigned long addr=0;
                addr=MAKELONG(i->LowOffset,i->HiOffset);
                g_aIDT[count] = addr;

        }
}
/**********************************************
*函数名称:CheckIDThook
*功能:检查IDT表是否改变
************************************************/
void CheckIDThook()
{
        unsigned long count;
        IDT_INFO idt_info;
        IDT_ENTRY *idt_entries;
        unsigned long ul_Fution;
       
        __asm sidt idt_info
               
                //取得idt_info中的函数地址
        idt_entries = (IDT_ENTRY*)MAKELONG(idt_info.IdtLow,idt_info.IdtHigh);
       
        DbgPrint("ROOTKIT: IDTINTERUPT called\n");
        //g_aIDT =(int *) ExAllocatePool(PagedPool,256*4);
        for(count=0;count<256;count++)
        {
                //DbgPrint("ROOTKIT: OnUnload called\n");       
                char _t[255];
                IDT_ENTRY *i=&idt_entries[count];
                unsigned long addr=0;
                ul_Fution=MAKELONG(i->LowOffset,i->HiOffset);
               
                if(g_aIDT[count] != ul_Fution)
                {
                        if(g_aIDT[count] != 0)
                        {

                                _asm
                                {                push eax
                                                CLI //dissable interrupt
                                                MOV EAX, CR0 //move CR0 register into EAX
                                                AND EAX, 0FFFEFFFFh //disable WP bit
                                                MOV CR0, EAX //write register back
                                                pop eax
                                }
                        addr = g_aIDT[count] - ul_Fution - 5;
                        //*( (char *)(&((unsigned char *)ul_Fution)[5]) )=0x5b;
                        *( (char *)(&((unsigned char *)ul_Fution)[0]) )=0xe9;
                         *( (unsigned long *)(&((unsigned char *)ul_Fution)[1]) ) = addr;
                         _asm
                         {
                                        push eax
                                        MOV EAX, CR0 //move CR0 register into EAX
                                         OR eax,10000H //enable WP bit
                                         MOV CR0, EAX //write register back
                                         STI //enable interrupt
                                         pop eax
                        }
                         DbgPrint("writed %08x sucessful!\n",ul_Fution);
                        }

                       
                }
        }
}

用Dbgview.exe观察到输出的语句了,但是过了2-3秒后就蓝屏了,
错误PAGE_FAULT_IN_NONPAGED_AREA

这应该是内存读取的错误,但是我JMP回原来的处理函数,内存应该没有问题呀!
我不喜欢在虚拟机上测试,一直蓝一直蓝我都忙晕了

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

收藏
免费 0
支持
分享
最新回复 (37)
雪    币: 27
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
SIP
2
顶上去,希望大牛们解答
2009-8-29 19:14
0
雪    币: 284
活跃值: (16)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
内存缺页? 不能确定,可以windbg下看看卡在虾米地址~
inline hook 恢复IDT很好,很强大。
我是菜鸟,来学习的,楼下的大牛估计会解答。(*^__^*) 嘻嘻……
2009-8-29 23:19
0
雪    币: 27
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
SIP
4
能写了,不过这代码和上面蓝屏的代码没有差别,我也看不出差别,哈哈,奇怪的事年年有,这个特别奇怪!
看这个能写成功的代码!
void   TestWriteIdt()
{
        unsigned long count;
        IDT_INFO idt_info;
        IDT_ENTRY *idt_entries;
        unsigned long ul_Fution;
        unsigned long addr=0x804e089d;
        IDT_ENTRY *i;
       
        __asm sidt idt_info
               
        //取得idt_info中的函数地址
        idt_entries = (IDT_ENTRY*)MAKELONG(idt_info.IdtLow,idt_info.IdtHigh);

                i = &idt_entries[0x03];
               
                ul_Fution=MAKELONG(i->LowOffset,i->HiOffset);

                               
                                _asm
                                {                push eax
                                CLI //dissable interrupt
                                MOV EAX, CR0 //move CR0 register into EAX
                                AND EAX, 0FFFEFFFFh //disable WP bit
                                MOV CR0, EAX //write register back
                                pop eax
                                }
                                addr = addr - ul_Fution - 5;
                                *( (char *)(&((unsigned char *)ul_Fution)[0]) )=0xe9;
                                *( (unsigned long *)(&((unsigned char *)ul_Fution)[1]) ) = addr;
                                _asm
                                {
                                                push eax
                                                MOV EAX, CR0 //move CR0 register into EAX
                                                OR eax,10000H //enable WP bit
                                                MOV CR0, EAX //write register back
                                                pop eax
                                                STI //enable interrupt
                                               
                                }

                                DbgPrint("writed %08x sucessful!\n",ul_Fution);
       
               
       
}
2009-8-30 15:36
0
雪    币: 8835
活跃值: (2404)
能力值: ( LV12,RANK:760 )
在线值:
发帖
回帖
粉丝
5
因为你hook的地址未必有效,256个IDT啊~~只有几个比较固定可以做恢复的,其他的可能是动态的~
2009-8-30 17:34
0
雪    币: 27
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
SIP
6
实时证明是这样的,比如说 A,B两个中断历程我只修改了一个,那么没有问题,如果修改了两个就会蓝屏!郁闷ING
2009-8-31 01:20
0
雪    币: 45
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
差别就在你选的中断号
2009-8-31 03:30
0
雪    币: 8835
活跃值: (2404)
能力值: ( LV12,RANK:760 )
在线值:
发帖
回帖
粉丝
8
看图你就知道了~~
看到0了没~
上传的附件:
2009-8-31 19:12
0
雪    币: 27
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
SIP
9
谢谢,cvcvxk 和 vfer 的指导
接下来,我就只改了INT1和INT3中的函数
因为那驱动改了这两个IDT处理函数,
然后我发现了,如果我只改一个就正常,如果是改两个就蓝了,到底是什么原因呢?
2009-8-31 23:16
0
雪    币: 8835
活跃值: (2404)
能力值: ( LV12,RANK:760 )
在线值:
发帖
回帖
粉丝
10
因为你hook了同一个Routine~~吼吼~
比如某游戏保护的int1和int3都是xx
你int1的hook jmp到old int1
但是你hook int3时就造成了int1也jmp oldint3~~
吼吼~
2009-8-31 23:24
0
雪    币: 62
活跃值: (72)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
11
我也出现和楼主同样的问题。。。不过int 3是处理好了,就是int 1处理了 3秒过后就蓝。。。
2009-9-1 02:02
0
雪    币: 27
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
SIP
12
我先前保存了INT1原来的地址,和INT3原来的地址,然后再它修改后的函数头JMP回原来的函数,证明会HOOK同一个Routine呢,本人很菜,请大牛说详细点。
2009-9-2 07:49
0
雪    币: 13019
活跃值: (4022)
能力值: ( LV15,RANK:1673 )
在线值:
发帖
回帖
粉丝
13
原保护程序有线程会内存校验,要是检测到改了就自动蓝?
2009-9-2 14:04
0
雪    币: 27
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
SIP
14
我怎么知道是哪个线程控制它呢?
2009-9-2 17:03
0
雪    币: 27
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
SIP
15
通过YAS看见两个可以的ETHREAD,我HOOK了这两个线程,然后再修改INT1,INT3,这回好点了,居然不蓝,抽根烟.....2分钟左右,自动重启。

郁闷。。。。心情从天上坠落地狱。

看来还有线程检测,是否修改了INT1,INT3。或者是定时器
但是问题有出来了,YAS检测出的线程地址不是游戏保护的地址,如果检测驱动内的地址可以办到,如果检测的线程不是驱动内的地址,那有应该如何检测?
另一个问题:
如果是定时器检测,分为I0定时器,DPC定时器,那又当如何检测?
2009-9-16 16:50
0
雪    币: 8835
活跃值: (2404)
能力值: ( LV12,RANK:760 )
在线值:
发帖
回帖
粉丝
16
没那么复杂,搞保护何必这么复杂呢~
2009-9-16 19:35
0
雪    币: 8835
活跃值: (2404)
能力值: ( LV12,RANK:760 )
在线值:
发帖
回帖
粉丝
17
DPC是一个链,你注册一个DPC,就会获得一个LIST_ENTRY去枚举链~然后和谐DPC

估计是破坏了线程结构的线程做的
你可以hook keDelayXXX和KeWaitForxxx
然后和谐他们
2009-9-16 19:37
0
雪    币: 8835
活跃值: (2404)
能力值: ( LV12,RANK:760 )
在线值:
发帖
回帖
粉丝
18
我一般喜欢在某保护的KeDelayXXX里恢复IDT,然后Delay,Delay结束时再把hook做回~~
2009-9-16 19:38
0
雪    币: 27
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
SIP
19
cvcvxk,我HOOK的线程我根本没有给他启动,他怎么能注册DPC呢,我想应该是驱动加载时候注册的(我还不确定他是DPC定时检测还是,IO定时检测)

还有我现在HOOK了那个XX驱动创建的线程,根据判断是不是他驱动加载的地址,再加上前面YAS获得的2个线程,现在发现一共成功HOOK了3个线程,

还有就是我HOOK了线程后,就算不修改INT1,INT3计算机1分钟后还是会重启!

最后谢谢CVCVXK提供的方法,虽然还是不知云里雾里,但是给我路子!
2009-9-16 19:51
0
雪    币: 27
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
SIP
20
我想不明白为什么要HOOK KeDelayXXX和KeWaitFor 这些函数都是延时的函数,难道是让他无限时的等待下去?

哈哈,本人太菜了,想不明白先不去想了。

CVCVXK大大说注册一个DPC,就会获得LIST_ENTRY链表,
我用WINDBG看了下
KeInitializeDpc的代码
nt!KeInitializeDpc:
804e6a12 8bff             mov     edi,edi
804e6a14 55               push    ebp
804e6a15 8bec             mov     ebp,esp
804e6a17 8b4508           mov     eax,[ebp+0x8]//DPC地址
804e6a1a 8b4d0c           mov     ecx,[ebp+0xc]//DeferredRoutine参数
804e6a1d 83601c00         and     dword ptr [eax+0x1c],0x0//Dpc->Lock &0x0
804e6a21 89480c           mov     [eax+0xc],ecx
804e6a24 8b4d10           mov     ecx,[ebp+0x10]
804e6a27 66c7001300       mov     word ptr [eax],0x13
804e6a2c c6400200         mov     byte ptr [eax+0x2],0x0
804e6a30 c6400301         mov     byte ptr [eax+0x3],0x1
804e6a34 894810           mov     [eax+0x10],ecx
804e6a37 5d               pop     ebp
804e6a38 c20c00           ret     0xc
lkd> dt _KDPC
   +0x000 Type             : Int2B
   +0x002 Number           : UChar
   +0x003 Importance       : UChar
   +0x004 DpcListEntry     : _LIST_ENTRY
   +0x00c DeferredRoutine  : Ptr32   
   +0x010 DeferredContext  : Ptr32 Void
   +0x014 SystemArgument1  : Ptr32 Void
   +0x018 SystemArgument2  : Ptr32 Void
   +0x01c Lock             : Ptr32 Uint4B
、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、

那KeInitializeDpc函数的C源码就是
NTKERNELAPI VOID KeInitializeDpc ( IN PRKDPC Dpc,
                                                                        IN PKDEFERRED_ROUTINE DeferredRoutine,
                                                                        IN PVOID DeferredContext )
                            {
                Dpc->Lock &= 0;
                Dpc->DeferredRoutine= DeferredRoutine;
                Dpc->DeferredContext = DeferredContext;
                Dpc->Type = 0x13;
                Dpc->Number = 0x0;
                Dpc->Importance = 0x1;
                                 }

短短的代码,怎么获得DPC的链表。。。。
2009-9-16 22:58
0
雪    币: 62
活跃值: (72)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
21
楼主搞的是梦幻诛仙吧~~~~是有3个线程,干掉就不蓝了
2009-9-16 23:49
0
雪    币: 8835
活跃值: (2404)
能力值: ( LV12,RANK:760 )
在线值:
发帖
回帖
粉丝
22
貌似是Timer
DPC那个要用另一个办法~
// 用KeSetTimer向计时器列表插入一个Timer,再用它来获取内核中的计时器列表
PULONG GetTimerTable()
{
        KTIMER ktimer;
        KeInitializeTimer(&ktimer);
        LARGE_INTEGER duoTime = RtlConvertLongToLargeInteger(-1);
        while (!KeSetTimer(&ktimer, duoTime, NULL))
        {
                duoTime.u.LowPart --;
        }
        PULONG pBlink = reinterpret_cast<PULONG>(ktimer.TimerListEntry.Blink);
        KeCancelTimer(&ktimer);
        while (*pBlink != 0)
        {
                pBlink -= 4;
        }
        pBlink = pBlink + 4;
        return pBlink;
}
2009-9-17 01:25
0
雪    币: 8835
活跃值: (2404)
能力值: ( LV12,RANK:760 )
在线值:
发帖
回帖
粉丝
23
ULONG DoIt()
{
        // 变量声明
        ULONG uSearchCount;
        ULONG uRoutineCount;
        KIRQL NewIrql;

        GetTimerTable();
        uSearchCount  = 0;
        uRoutineCount = 0;

        // 更改IRQL
        KeRaiseIrql(2, &NewIrql);
        // 获取计时器列表
        PULONG pTimerTable = GetTimerTable();
        DbgPrint("TimerTable : %x\n", pTimerTable);

        // 取出每个TIMER
        PULONG pTimer;
        while ((pTimer = (PULONG)(*pTimerTable)) != 0)
        {
                while (pTimer != pTimerTable)
                {
                        PULONG pBuffer = pTimer - 6;
                        PULONG pTmp = (PULONG)(*(pBuffer + 8));
                        pTimer = (PULONG)(*pTimer);
                        if (pTmp != 0)
                        {
                                ULONG data = *(pTmp + 3);
                                if (data != 0 && Check(data) != 0)
                                {
                                        DbgPrint("Found DeferredRoutine %x QuadPart %lld", data, *(PLARGE_INTEGER)(pBuffer + 4));
                                        PULONG eax = (PULONG)(*(pBuffer + 6));
                                        pBuffer = (PULONG)(*(pBuffer + 7));
                                        uRoutineCount ++;
                                        *pBuffer = (ULONG)eax;
                                        *(eax + 1) = (ULONG)pBuffer;
                                }
                        }
                }
               
                uSearchCount ++;
                pTimerTable += 4;
                if (uSearchCount < 0x1F4)
                        continue;
                else
                        break;;
        }
       
        KeLowerIrql(NewIrql);       
        return uRoutineCount;
}
2009-9-17 01:26
0
雪    币: 8835
活跃值: (2404)
能力值: ( LV12,RANK:760 )
在线值:
发帖
回帖
粉丝
24
Ring3的Timer
可以看俄国鬼子的文章
http://www.wasm.ru/article.php?article=settimer_res
2009-9-17 01:28
0
雪    币: 27
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
SIP
25
呵呵,你还在呀,太谢谢你了,我先回复了,再慢慢消化
2009-9-17 02:33
0
游客
登录 | 注册 方可回帖
返回
//