首页
社区
课程
招聘
[求助]HOOK SwpContext 恢复IDT表怎么处理多核啊
发表于: 2013-3-25 00:41 8225

[求助]HOOK SwpContext 恢复IDT表怎么处理多核啊

2013-3-25 00:41
8225
各位大大,最近学习驱动,看教程学了一招HOOK SwpContext 来恢复IDT表的方法, 开始在虚拟机里面测试正常,带到真机里面就卡的系统什么都动不了,经过多方面的测试,发现是多核CPU的问题,请问这方面要怎么处理那? 指点一二就行,偶不是伸手党,就想学点知识,谢谢各位大大

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

收藏
免费 0
支持
分享
最新回复 (11)
雪    币: 8835
活跃值: (2404)
能力值: ( LV12,RANK:760 )
在线值:
发帖
回帖
粉丝
2
即使是多核的情况下 SwapContext的时候,切换IDT完全无压力的说~估计是你弄错了什么东西~
2013-3-25 01:14
0
雪    币: 282
活跃值: (31)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
虚拟机开始设置的是单核CPU ,运行一切正常,但是设定为多核后屏幕就卡了,啥都打不开,放到真机也是,下面是代码,为啥那?



ULONG g_SwpContext = 0;   //要HOOK的地址
ULONG g_SwpContextJmp = 0 ; //HOOK跳转到的地址
BOOLEAN g_SwpContextHook = FALSE ;  //判断HOOK成功没有
JMPCODE g_SwpContextFun ; //定义一个结构来储存原来地址的内容
ULONG g_uOldIdtBase = 0;   //保存一份原始的IDT表
ULONG g_uNewIdtBase = 0 ;   //保存新的IDT表


//这里就是我的HOOK的处理函数了 为啥多核就不行那?
void FuckSwapContext(PETHREAD pTarget, PKPCR pKpcr)
{
	//PEPROCESS pTargetProcess = (PEPROCESS)((ULONG)pTarget+0x44) ; //这里如果是多核处理器应该怎么处理那?

	//if(GuardPID((ULONG)PsGetCurrentProcess())==TRUE && (ULONG)PsGetCurrentProcess()>0) //如果是保护进程的话
	//{
 //        //IDT是原始的


	//} else   //如果不是保护进程的话
	//{ //IDT表示被HOOK的


	//}
           ///处理函数就是这个了, 恢复保存的IDT表,因为是测试,就没有加判断, 但是卡啊不蓝屏,就是什么程序都打不开
	*pKpcr->IDT=(_KIDTENTRY*)g_uNewIdtBase ;
	IDTINFO IdtInfo = {0} ;
	IdtInfo.IDTLimit = 0x7ff ;
	IdtInfo.HiIDTbase=(g_uNewIdtBase & 0xffff0000) >> 16 ;
	IdtInfo.LowIDTbase=(g_uNewIdtBase & 0x0000ffff) ;
	__asm lidt IdtInfo  ;

	DbgPrint("当前PID[%X]",(ULONG)PsGetCurrentProcess()) ;

}

__declspec(naked) void SwpContextFun()
{
	//pushad
	//	pushfd
	//	push edi
	//	push ebx
	//	push eax
	//	mov esi,GetNtFuncAddr
	//	call esi
	//	mov  dword ptr [esp+0x14],eax
	//	//call GetNtFuncAddr
	//	popfd
	//	popad

	__asm
	{
		mov     eax,dword ptr [esi+0x20]
		mov     dword ptr [ebx+0x18],eax   //ESI是目标线程  EDI是当前线程 ebx KPCR处理器控制域
			pushad
			pushfd
			push ebx
			push esi
			call FuckSwapContext 
			popfd
			popad
			push g_SwpContextJmp
			retn



	}

}

BOOLEAN HandleSwapContextHook()
{

	/*804dc8bb 83ec0c          sub     esp,0Ch
	804dc8be 89742408        mov     dword ptr [esp+8],esi
	804dc8c2 897c2404        mov     dword ptr [esp+4],edi
	804dc8c6 892c24          mov     dword ptr [esp],ebp
	804dc8c9 8bf0            mov     esi,eax
	804dc8cb 8bbb24010000    mov     edi,dword ptr [ebx+124h]
	804dc8d1 c7832801000000000000 mov dword ptr [ebx+128h],0
	804dc8db 89b324010000    mov     dword ptr [ebx+124h],esi
	804dc8e1 8bcf            mov     ecx,edi
	804dc8e3 c6475001        mov     byte ptr [edi+50h],1
	804dc8e7 e8eefdffff      call    nt!ExReleaseResourceLite+0x8a (804dc6da)
	//804dc8ec b101            mov     cl,1
	//804dc8ee e831000000      call    nt!KiDispatchInterrupt+0xb0 (804dc924)  取这里3行的特征码
	//804dc8f3 8b2c24          mov     ebp,dword ptr [esp]
	804dc8f6 8b7c2404        mov     edi,dword ptr [esp+4]
	804dc8fa 8b742408        mov     esi,dword ptr [esp+8]
	804dc8fe 83c40c          add     esp,0Ch*/
   // __asm int 3 ;

	//---------------------------------------这里保存一份原始的IDT表

	IDTINFO IdtInfo = {0} ;

	__asm sidt IdtInfo ;

	ULONG uIdtAdrr = MAKELONG(IdtInfo.LowIDTbase,IdtInfo.HiIDTbase);

	if(uIdtAdrr==0)
	{
		DbgPrint("备份IDT失败\n") ;
		return FALSE ;
	}
	g_uOldIdtBase = uIdtAdrr ;
	ULONG uSize = IdtInfo.IDTLimit ; //IDT表的大小
   g_uNewIdtBase= (ULONG)ExAllocatePool(NonPagedPool,uSize) ; //申请一个新表
   if(g_uNewIdtBase==0)
   {
	   DbgPrint("申请新的IDT表失败\n") ;
	   return FALSE ;
   }
   RtlCopyMemory((PVOID)g_uNewIdtBase,(PVOID)g_uOldIdtBase,uSize) ;  //将原始表的内容拷贝到新表



	ULONG uAddr = (ULONG)KiDispatchInterrupt ;
	DbgPrint("KiDispatchInterrupt的地址是%X",uAddr) ;
	PUCHAR p=(PUCHAR)uAddr ;
	ULONG i=0 ;
	BOOLEAN bFind = FALSE ;
	while(i<0x200)
	{
		if(*p==0xe8 && *(p+5)==0x8b && *(p+6)==0x2c && *(p+7)==0x24 && 
			*(p-1)==0x01 && *(p-2)==0xb1 && *(p+9)==0x7c && *(p+10)==0x24)
		{
         bFind = TRUE ;
		 break; 
		}
		i++ ;
		p++ ;
	}
	if(!bFind)
	{
		DbgPrint("获取SwapContext特征码失败!") ;
		return FALSE ;
	} 
	ULONG uSwapContext = (ULONG)p +5+*(PULONG)(p+1);
	/*804dc981 8d09            lea     ecx,[ecx]
	804dc983 f740e400000200  test    dword ptr [eax-1Ch],20000h
	804dc98a 7503            jne     nt!KiDispatchInterrupt+0x11b (804dc98f)
	804dc98c 83e810          sub     eax,10h
	804dc98f 8b4b40          mov     ecx,dword ptr [ebx+40h]
	804dc992 894104          mov     dword ptr [ecx+4],eax
	804dc995 8b6628          mov     esp,dword ptr [esi+28h]
	804dc998 8b4620          mov     eax,dword ptr [esi+20h]    自己感觉修改这里好像更合适点
	804dc99b 894318          mov     dword ptr [ebx+18h],eax    修改的这一行
	804dc99e fb              sti
	804dc99f 8b4744          mov     eax,dword ptr [edi+44h]  //上面的处理函数中的44来源于这里
	804dc9a2 3b4644          cmp     eax,dword ptr [esi+44h]
	804dc9a5 c6475000        mov     byte ptr [edi+50h],0
	804dc9a9 742c            je      nt!KiDispatchInterrupt+0x163 (804dc9d7)
	804dc9ab 8b7e44          mov     edi,dword ptr [esi+44h]
	804dc9ae 66f74720ffff    test    word ptr [edi+20h],0FFFFh
	804dc9b4 755b            jne     nt!KiDispatchInterrupt+0x19d (804dca11)*/

	p=(PUCHAR)uSwapContext ;
	i=0 ;
	bFind = FALSE ;
	while(i<0x200)
	{
		if(*p==0x8b && *(p+1)==0x46 && *(p+3)==0x89 && *(p+4)==0x43 &&
			*(p+6)==0xfb && *(p+7)==0x8b)
		{
			bFind = TRUE ;
			break; 
		}
		i++ ;
		p++ ;
	}
	if(!bFind)
	{
		DbgPrint("获取要HOOK的SwapContext地址失败!") ;
		return FALSE ;
	}

	g_SwpContext=(ULONG)p ;


	DbgPrint("要HOOK的地址为[%X]",(ULONG)p)  ;

	ULONG X = (ULONG)p   ;
	ULONG Y = (ULONG)SwpContextFun  ;
	g_SwpContextJmp = (ULONG)p + 6 ;    //获取HOOK后跳转到的地址
	DbgPrint("HOOK后跳转的地址为:%X",g_SwpContextJmp) ;
	PJMPCODE pcur;   //指针,指向函数当前的地址

	JMPCODE JmpCode ; //要Jmp的地址保存
	pcur=PJMPCODE(X)  ;  //当前地址的数值
	g_SwpContextFun.E9=pcur->E9 ;
	g_SwpContextFun.JMPADDR=pcur->JMPADDR  ;  //使用全部变量来保存一下原来的函数
	//CodeArr=X  ;
	JmpCode.E9=0xE9 ;
	JmpCode.JMPADDR=Y-X-5 ;
	//KdPrint(("要写入函数的地址是%X",JmpCode.JMPADDR));
	//  __asm int 3   ;
	DbgPrint("HOOK后跳转到函数地址是[%X]",JmpCode.JMPADDR) ;
	MemoryRevise() ;  //去除页面保护
	pcur->E9=0xE9 ;
	pcur->JMPADDR=JmpCode.JMPADDR  ;
	MemoryRecover() ; //恢复页面保护
	DbgPrint("HOOK执行成功,SwapContext函数已经被拦截\n");

   g_SwpContextHook=TRUE ;
	return TRUE ;
}

BOOLEAN HandleSwapContextUnHook()
{
	if(!g_SwpContextHook)
	{
		return  FALSE;

	}
	PJMPCODE pcur;   //指针,指向函数当前的地址
	MemoryRevise() ;  //去除页面保护
	pcur=PJMPCODE(g_SwpContext)  ;  //当前地址的数值
	pcur->E9=g_SwpContextFun.E9  ;
	pcur->JMPADDR=g_SwpContextFun.JMPADDR  ;
	MemoryRecover() ; //恢复页面保护
	DbgPrint("UNHOOK执行成功,SwapContext函数已经被恢复\n");
	g_SwpContextHook=FALSE ;
	return TRUE ;


}

2013-3-25 01:27
0
雪    币: 8835
活跃值: (2404)
能力值: ( LV12,RANK:760 )
在线值:
发帖
回帖
粉丝
4
...表示lidt和修改kpcr已经够亮了...
2013-3-25 02:05
0
雪    币: 282
活跃值: (31)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
额,还是不太懂,是我kpcr修改的缘故么? 呵呵
2013-3-25 03:00
0
雪    币: 65
活跃值: (112)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
6
学好基础吧,不要一来就到处hook……这种所谓的入门学习,对你没任何好处……除了提起兴趣外
2013-3-25 08:34
0
雪    币: 65
活跃值: (112)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
7
真的如你所说不是“伸手党”,确实想学东西,就不要搞hook这么急功近利的东西,一点点从基础学起
2013-3-25 08:38
0
雪    币: 3836
活跃值: (4142)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
...表示lidt和修改kpcr已经够亮了...   
/*
lidt和kpcr所获取的IDT都是当前CPU的。。。。其他核心的不能直接获取
*/
2013-3-25 08:45
0
雪    币: 282
活跃值: (31)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
谢谢各位大大的回答,其实当初我也想是这个问题,努力学习中,谢谢啦
2013-3-25 09:43
0
雪    币: 8835
活跃值: (2404)
能力值: ( LV12,RANK:760 )
在线值:
发帖
回帖
粉丝
10
其实 IDT直接memcpy去覆盖就不卡死了(覆盖前0x10个没见过出问题~~覆盖后面那些0x4X的东西很容易出问题),别用lidt去改~KPCR不需要修改~
不过你这么干还是不能躲过DPCRoutine的扫描...具体不多说了~

另外,HOOK这玩意也就适合玩玩,正规项目尽量用M$的东西~
2013-3-25 09:58
0
雪    币: 282
活跃值: (31)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
听君一席话,胜读十年书啊
2013-3-25 11:45
0
雪    币: 282
活跃值: (31)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
修改为HOOK SwpContext 后,发现是自己的线程就把当前IDT给恢复了,如果是其他的线程就把当前IDT在重新HOOK了,这样应该可以吧,哈哈
2013-3-25 13:34
0
游客
登录 | 注册 方可回帖
返回
//