首页
社区
课程
招聘
[原创]一个禁止任何ring3调试的驱动
2011-8-18 14:05 19232

[原创]一个禁止任何ring3调试的驱动

2011-8-18 14:05
19232
这个方法很简单:hook int1,int3
然后清除DebugPort,简单明了~~
代码适用于多核,多系统~~~
#include <ntddk.h>

#define MAKELONG(low, high) \
((ULONG)(((USHORT)((ULONG)(low) & 0xffff)) | ((ULONG)((USHORT)((ULONG)(high) & 0xffff))) << 16))

#define GET_LOW16_OF_32(data) \
((USHORT)(((ULONG)data) & 0xffff))

#define GET_HIGH16_OF_32(data) \
((USHORT)(((ULONG)data) >> 16))

#pragma pack(push,1)
typedef struct IDTR_
{
	USHORT limit;
	ULONG base;
} IDTR, *P_IDTR;

typedef struct IDTENTRY_
{
	USHORT offset_low;
	USHORT selector;
	UCHAR reserved;
	UCHAR type:4;
	UCHAR always0:1;
	UCHAR dpl:2;
	UCHAR present:1;
	USHORT offset_high;
} IDTENTRY, *P_IDTENTRY;
#pragma pack(pop)

ULONG Offset = 0;
ULONG HOOK_IDT_INDEX[] = {0x01, 0x03};
#define HOOK_IDT_NUM sizeof(HOOK_IDT_INDEX)/sizeof(ULONG)
VOID *g_old_entry[HOOK_IDT_NUM] = {0};

VOID *GetIdt()
{
	IDTR idtr;
	_asm sidt idtr
	return (VOID *)idtr.base;
}

VOID MyUserFilter()
{
	KdPrint(("Crurrent IRQL: %d\n",KeGetCurrentIrql()));
	if (Offset > 0)
	{
		ULONG eprocess = (ULONG)PsGetCurrentProcess();
		PULONG pDebugPort = (PULONG)(eprocess+Offset);
		if (*pDebugPort > 0)
		{
			KdPrint(("DebugObject = %x\n", pDebugPort));
			*pDebugPort = 0; //clear DebugPort
		}
	}
}

__declspec(naked) InterruptProc01()
{
	__asm
	{
		pushfd					// 保存标志寄存器
		pushad					// 保存所有的通用寄存器
		push	fs

		__asm
		{
			mov     ebx, 30H	// Set FS to PCR.
			mov     fs, bx
		}
		call MyUserFilter

		pop		fs
		popad					// 恢复通用寄存器
		popfd					// 恢复标志寄存器
		jmp	g_old_entry[0]		// 跳到原来的中断服务程序
	}
}

__declspec(naked) InterruptProc03()
{
	__asm
	{
		pushfd					// 保存标志寄存器
		pushad					// 保存所有的通用寄存器
		push	fs

		__asm
		{
			mov     ebx, 30H	// Set FS to PCR.
			mov     fs, bx
		}
		call MyUserFilter

		pop		fs
		popad					// 恢复通用寄存器
		popfd					// 恢复标志寄存器
		jmp	g_old_entry[4]		// 跳到原来的中断服务程序
	}
}

VOID *g_new_entry[HOOK_IDT_NUM] = {InterruptProc01, InterruptProc03};

VOID ModifyInterrupt(BOOLEAN hook_or_unhook)
{
	USHORT i;
	P_IDTENTRY idt_addr = (P_IDTENTRY)GetIdt();

	//SetWriteProtect(FALSE, &orgcr0);
	for (i = 0; i < HOOK_IDT_NUM; i++)
	{
		KdPrint(("the current address for index %02x = %x\n", HOOK_IDT_INDEX[i],
			(VOID *)MAKELONG(idt_addr[HOOK_IDT_INDEX[i]].offset_low, idt_addr[HOOK_IDT_INDEX[i]].offset_high)));
		if(hook_or_unhook)
		{
			KdPrint(("try to hook this interrupt\n"));
			g_old_entry[i] = (VOID *)MAKELONG(idt_addr[HOOK_IDT_INDEX[i]].offset_low, idt_addr[HOOK_IDT_INDEX[i]].offset_high);
			idt_addr[HOOK_IDT_INDEX[i]].offset_low = GET_LOW16_OF_32(g_new_entry[i]);
			idt_addr[HOOK_IDT_INDEX[i]].offset_high = GET_HIGH16_OF_32(g_new_entry[i]);
		}
		else
		{
			KdPrint(("try to recovery interrupt for index %02x\n", HOOK_IDT_INDEX[i]));
			idt_addr[HOOK_IDT_INDEX[i]].offset_low = GET_LOW16_OF_32(g_old_entry[i]);
			idt_addr[HOOK_IDT_INDEX[i]].offset_high = GET_HIGH16_OF_32(g_old_entry[i]);
		}
		KdPrint(("the current address = %x\n",
			(VOID *)MAKELONG(idt_addr[HOOK_IDT_INDEX[i]].offset_low, idt_addr[HOOK_IDT_INDEX[i]].offset_high)));
	}//for
	//SetWriteProtect(TRUE, &orgcr0);
}

VOID HookIDT(BOOLEAN hook_or_unhook)
{
	KAFFINITY     ActiveProcessors, CurrentAffinity;
	ActiveProcessors=KeQueryActiveProcessors(); 
	KdPrint(("KeActiveProcessors = %d\n", ActiveProcessors));
	for (CurrentAffinity = 1; ActiveProcessors; CurrentAffinity <<= 1) 
	{
		if (ActiveProcessors & CurrentAffinity)
		{
			ActiveProcessors &= ~CurrentAffinity;
			KeSetSystemAffinityThread(CurrentAffinity);

			KdPrint(("At %d CPU IDT:\n", CurrentAffinity));
			ModifyInterrupt(hook_or_unhook);
			KdPrint(("\n"));
		}
	}
}

VOID Unload(PDRIVER_OBJECT drv)
{
    HookIDT(FALSE);
    KdPrint (("Unload Driver\n")); 
}

NTSTATUS DriverEntry( 
                     IN PDRIVER_OBJECT DriverObject, 
                     IN PUNICODE_STRING RegistryPath 
                     ) 
{ 
	RTL_OSVERSIONINFOEXW osverinfo = {sizeof(osverinfo)};

    KdPrint (("Entering DriverEntry\n")); 
    DriverObject->DriverUnload = Unload;

	RtlGetVersion((PRTL_OSVERSIONINFOW)&osverinfo);
	KdPrint(("OSVersion NT %d.%d:%d sp%d.%d\n",
		osverinfo.dwMajorVersion, osverinfo.dwMinorVersion, osverinfo.dwBuildNumber,
		osverinfo.wServicePackMajor, osverinfo.wServicePackMinor));
	if (osverinfo.dwMajorVersion == 5 && osverinfo.dwMinorVersion == 0)
		Offset = 0x120; //WINDOWS_VERSION_2K
	else if (osverinfo.dwMajorVersion == 5 && osverinfo.dwMinorVersion == 1)
		Offset = 0xbc; //WINDOWS_VERSION_XP
	else if (osverinfo.dwMajorVersion == 5 && osverinfo.dwMinorVersion == 2)
		Offset = 0xcc; //WINDOWS_VERSION_2003
	else if (osverinfo.dwMajorVersion == 6 && osverinfo.dwMinorVersion == 0)
		Offset = 0xd4; //WINDOWS_VERSION_VISTA
	else if (osverinfo.dwMajorVersion == 6 && osverinfo.dwMinorVersion == 1)
		Offset = 0xec; //WINDOWS_VERSION_WIN7
	else
		Offset = 0;

    HookIDT(TRUE);

    return  STATUS_SUCCESS; 
}

谢谢大家!

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

收藏
免费 7
打赏
分享
最新回复 (22)
雪    币: 3035
活跃值: (1179)
能力值: ( LV8,RANK:120 )
在线值:
发帖
回帖
粉丝
zhouws 2 2011-8-18 14:11
2
0
又是拉拒战,大家抢IDT
抢不过又patch MyUserFilter,然后又加patch效验,然后又patch效验的效验。。

这方面的玩意是不是要到头了
雪    币: 71
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
mumaren 2011-8-18 15:02
3
0
mark一下

分析
雪    币: 8865
活跃值: (2379)
能力值: ( LV12,RANK:760 )
在线值:
发帖
回帖
粉丝
cvcvxk 10 2011-8-18 15:19
4
0
实际上自从有Hook SwapContext做IDT切换的手段后,IDThook就蛋碎了~
雪    币: 33
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
PEBOSS 2011-8-18 15:31
5
0
这个..这个...是怎么搞的
雪    币: 343
活跃值: (40)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
yarpee 1 2011-8-18 15:42
6
0
了解了下,mark待用
雪    币: 331
活跃值: (57)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
better 2 2011-8-18 17:25
7
0
IDT也能切换?
雪    币: 113
活跃值: (100)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
ronging 2011-8-18 22:46
8
0
__asm
    {
      mov     ebx, 30H  // Set FS to PCR.
      mov     fs, bx
    }
这段代码有什么用?内核下的FS不就是30嘛?
雪    币: 8865
活跃值: (2379)
能力值: ( LV12,RANK:760 )
在线值:
发帖
回帖
粉丝
cvcvxk 10 2011-8-19 00:41
9
0
其实任何内核物体都可以,比如LDT,GDT~~尼玛~你懂得~
雪    币: 331
活跃值: (57)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
better 2 2011-8-19 10:08
10
0
刚进ring0,但所有的段选择子都是ring3下的(详见Intel手册),因为windows下ds,es,gs是不变的,所以只改fs,上面这段asm来自WRK,有些教程都没有这个步骤是错误的。
如果你用windbg来调试,fs会被调试器自动设置为30h,所以在windbg下这个错误很难被发现(何况int1,int3是不可调试的)
雪    币: 113
活跃值: (100)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
ronging 2011-8-19 13:20
11
0
这里的“刚进”是什么意思?进ring0的时候,难道CS和SS也是ring3下的?int x/.sysenter不做这些事?内核加载驱动的时候环境已经OK了吧。
雪    币: 331
活跃值: (57)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
better 2 2011-8-19 13:40
12
0
中断后SS,ESP是从TSS获得的,不过我记得windows没有使用TSS的其它部分
sysenter有所不同,该指令更没有用到TSS,我记得是sysenter后是叫一个临时DPC栈,然后由_KiSystemCall中的指令读取TSS中的SS,ESP再切换到真正的内核栈。
我说的可能有错误,欢迎指正!
雪    币: 113
活跃值: (100)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
ronging 2011-8-19 18:59
13
0
CS,肯定已经切换过了,因为这时的代码已经在内核态了,TSS中保存了不同权限时的SS和ESP,中断门和陷阱门时会使用,上述动作应该是CPU做的,顺便看了一些KiTrap**的代码,确实是FS,DS,ES,GS的切换在代码中做的,是OS的代码完成的。

至于.sysenter,CS和SS的切换我认为还是CPU完成的,而且没有使用TSS,因为有专门的msr。其它的段切换还是由OS的代码KiFastCallEntry完成的。

刚刚想到,在你的hook程序里加一段KdPrint打它们打印出来就有答案了。
雪    币: 204
活跃值: (25)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
游戏蛀虫 2011-8-20 11:30
14
0

2009年大哥你就接触过这个问题

http://bbs.pediy.com/showthread.php?p=726505
雪    币: 204
活跃值: (25)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
游戏蛀虫 2011-8-20 11:33
15
0
看完了 这篇文章  没结果

不过貌似 V校大人 最终摸索出了东西啊。能不能放点雪啊
雪    币: 263
活跃值: (71)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
hackerxina 2011-8-24 01:19
16
0
已学会虚拟重定向IDT PASS 一切IDT HOOK
雪    币: 8865
活跃值: (2379)
能力值: ( LV12,RANK:760 )
在线值:
发帖
回帖
粉丝
cvcvxk 10 2011-8-24 07:16
17
0
话说,保护驱动已经学会Switch To V386 mode~
雪    币: 116
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
boainfall 2011-8-24 08:15
18
0
太邪恶,太强大了
雪    币: 204
活跃值: (25)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
游戏蛀虫 2011-8-24 09:23
19
0
娘的  实力差距啊.  话说每次都不怎么能看明白V大的话啊.继续努力
雪    币: 405
活跃值: (1950)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
wowocock 1 2011-8-25 09:32
20
0
邪恶无极限,嘿嘿。对内核了解的多点,发现里面可走的路太多了。旁路穿越的地方很多,哈哈。
雪    币: 156
活跃值: (86)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
robslove 2011-10-17 13:25
21
0
win7 win8 64位目前怎么搞穿越哦?
雪    币: 3466
活跃值: (3512)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
fengyunabc 1 2017-5-20 23:28
22
0
确实够邪恶!!
雪    币: 15
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
sqiwg 2017-5-29 17:02
23
0
mark
游客
登录 | 注册 方可回帖
返回