首页
论坛
课程
招聘
[原创]小技巧大用处,让WINDBG跑起来
2010-11-23 21:39 34345

[原创]小技巧大用处,让WINDBG跑起来

2010-11-23 21:39
34345
今天和大家分享一个小心得,想必很多高手已经玩腻了~飘过吧!
最近接触了不少游戏保护,它们或多或少的都有一个特制就是在被调试机上运行游戏以后调试机上的WINDBG就接受不到信息了。起初我也困惑的很,而且在驱动当中设置int 3断点会蓝屏。后来在一个应用程序中添加了
__asm int 3这个应用程序就崩溃了。得到结论它们都是用了KdDisableDebugger函数来禁止操作系统调试了。想对应的有一个函数是KdEnableDebugger 可以允许调试,但是很多游戏仍然很操蛋。及时你使用了KdEnableDebugger 也无法调试,它们都是不停的禁止调试。
有一天我躺在床上思考,与其利用IDA分析它们的逻辑还不如直接对操作系统进行阉割算了。
假设我们系统上的KdDisableDebugger函数彻底失效了,那么任何人调用也就不可能禁用调试模式了吧。说干就干,首先在MSDN上找到了KdDisableDebugger函数的定义
NTSTATUS KdDisableDebugger(void);

看到这个函数定义以后欣喜若狂,隐约有一种感觉告诉我。我的设想完全可以实现的
首先它没有参数,在堆栈的控制上非常容易处理。其次它有一个返回值,也就是说执行的成功与否肯定有一个值来说明。
果然在下面看到它的返回值说明,执行成功则返回STATUS_SUCCESS。还有2个分别是权限不够和调试端口不存在。我们假设不管谁调用了KdDisableDebugger这个函数我们都在函数的起始处返回STATUS_SUCCESS(根据DDK中ntstatus.h的定义这个值是0),不就废除了这个函数的功能了吗。
在WINDBG里面先看一下这个函数的反汇编情况

这就足够了。下面贴上代码,大家就会一目了然了。代码的逻辑也非常简单
就不用多费口舌了
#define	FAILED_TO_OBTAIN_FUNCTION_ADDRESSES	0x00000001	//获取函数地址失败
//////////////////////////////////////////////////////////////////////
//	名称:	MyGetFunAddress
//	功能:	获取函数地址
//	参数:	函数名称字符串指针
//	返回:	函数地址
//////////////////////////////////////////////////////////////////////
ULONG MyGetFunAddress( IN PCWSTR FunctionName)
{
	UNICODE_STRING UniCodeFunctionName;
	RtlInitUnicodeString( &UniCodeFunctionName, FunctionName );
	return (ULONG)MmGetSystemRoutineAddress( &UniCodeFunctionName );   
}
//执行卸载
VOID	DriverUnload(IN PDRIVER_OBJECT	pDriverObject)
{
	
	KdPrint(("Enter DriverUnload\n"));
}
//////////////////////////////////////////////////////////////////////
//	名称:	WPOFF
//	功能:	清除CR0
//	参数:	
//	返回:	
//////////////////////////////////////////////////////////////////////
VOID WPOFF()
{
	__asm
	{
		cli
			mov eax,cr0
			and eax,not 10000h
			mov cr0,eax
	}
}

//////////////////////////////////////////////////////////////////////
//	名称:	WPON
//	功能:	恢复CR0
//	参数:	
//	返回:	
//////////////////////////////////////////////////////////////////////
VOID WPON()
{
	__asm
	{
		mov eax,cr0
			or eax,10000h
			mov cr0,eax
			sti
	}
}
//////////////////////////////////////////////////////////////////////
//	名称:	MyHook_KdDisableDebugger
//	功能:	修改KdDisableDebugger函数起始处导致所有的调用者都返回0
//	参数:	无
//	返回:	状态
//////////////////////////////////////////////////////////////////////
NTSTATUS MyHook_KdDisableDebugger()
{
	KIRQL	Irql;
	BYTE	*KdDisableDebuggerAddress = NULL;
	BYTE	No1Code[2] = {0x33,0xc0};	//xor eax,eax 这句汇编语句的机器码
	BYTE	No2Code[1] = {0xc3};		//retn 的机器码

	//获取KdDisableDebugger地址
	KdDisableDebuggerAddress	= (BYTE*)MyGetFunAddress(L"KdDisableDebugger");
	if (KdDisableDebuggerAddress == NULL)
		return	FAILED_TO_OBTAIN_FUNCTION_ADDRESSES;
	//KdPrint(("%0X\n\n",KdDisableDebuggerAddress));
	WPOFF();	//清除CR0
	//提升IRQL中断级
	Irql=KeRaiseIrqlToDpcLevel();
	//写入
	RtlCopyMemory(KdDisableDebuggerAddress,No1Code,2);
	RtlCopyMemory(KdDisableDebuggerAddress+2,No2Code,1);
	//恢复Irql
	KeLowerIrql(Irql);
	WPON();		//恢复CR0

	return	STATUS_SUCCESS;
}
//////////////////////////////////////////////////////////////////////
//	名称:	DriverEntry
//	功能:	入口函数
//	参数:	DriverObject:驱动对象
//			RegistryPath:设备服务键名称(注册表)
//	返回:	状态
//////////////////////////////////////////////////////////////////////
NTSTATUS DriverEntry( IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath )
{
	NTSTATUS status;
	//设置卸载函数
	DriverObject->DriverUnload = DriverUnload;

	status = MyHook_KdDisableDebugger();
	if (status == FAILED_TO_OBTAIN_FUNCTION_ADDRESSES)
		KdPrint(("获取函数地址失败!\n\n"));

	//status = KdDisableDebugger();
	//KdPrint(("======%0X\n",(ULONG)status));
	
	return STATUS_SUCCESS;
}

执行完毕以后效果如下

大家可以将入口函数当中被注释的两行代码开启,测试说明虽然禁止调试失败,但是仍然返回0了
我觉得过不了多久,很多游戏的保护程序就应该判断很多函数的头部是否被HOOK了。
但是斗争依然继续着,升级着……

看雪侠者千人榜,看看你上榜了吗?

上传的附件:
  • 1.jpg (27.92kb,2485次下载)
  • 2.jpg (22.69kb,2487次下载)
收藏
点赞0
打赏
分享
最新回复 (41)
雪    币: 326
活跃值: 活跃值 (15)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
快雪时晴 活跃值 4 2010-11-23 21:47
2
0
TAG:kdDisableDebugger HOOK 游戏
雪    币: 384
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
leeone 活跃值 2010-11-23 22:25
3
0
膜拜
支持
雪    币: 248
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
magicman 活跃值 2010-11-23 22:38
4
0
很强的思路,学习一下...
雪    币: 1048
活跃值: 活跃值 (96)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
天涯一鸿 活跃值 2010-11-23 22:45
5
0
一直是直接在windbg中用ed KdDisableDebugger c3 的飘过……
雪    币: 440
活跃值: 活跃值 (560)
能力值: ( LV8,RANK:120 )
在线值:
发帖
回帖
粉丝
crazyearl 活跃值 2 2010-11-23 22:48
6
0
“简约时尚”受教了。
雪    币: 1081
活跃值: 活跃值 (412)
能力值: ( LV12,RANK:480 )
在线值:
发帖
回帖
粉丝
熊猫正正 活跃值 9 2010-11-23 23:57
7
0
谢谢分享~~
雪    币: 385
活跃值: 活跃值 (28)
能力值: ( LV7,RANK:110 )
在线值:
发帖
回帖
粉丝
小小的心 活跃值 2 2010-11-23 23:58
8
0
最近在学这个,受教了
雪    币: 230
活跃值: 活跃值 (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
honffx 活跃值 2010-11-24 04:27
9
0
我觉得过不了多久,很多游戏的保护程序就应该判断很多函数的头部是否被HOOK了。
但是斗争依然继续着,升级着……

搜索所有调用KdDisableDebugger的位置CALL 全部HOOK jmp 到自己驱动处理!
雪    币: 336
活跃值: 活跃值 (11)
能力值: ( LV9,RANK:280 )
在线值:
发帖
回帖
粉丝
microdebug 活跃值 6 2010-11-24 12:19
10
0
TAG:kdDisableDebugger HOOK 游戏
雪    币: 1259
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
stu 活跃值 2010-11-24 12:50
11
0
学习了。5字
雪    币: 102
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
猥琐菜鸟 活跃值 2010-11-24 12:53
12
0
谢谢...有用
雪    币: 281
活跃值: 活跃值 (15)
能力值: ( LV7,RANK:110 )
在线值:
发帖
回帖
粉丝
kkmylove 活跃值 2 2010-11-26 12:55
13
0
谢谢分享
雪    币: 556
活跃值: 活跃值 (61)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
金罡 活跃值 1 2010-11-26 13:03
14
0
谢谢分享
雪    币: 29
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
webwizard 活跃值 2010-12-15 08:28
15
0
学习这个!
雪    币: 46
活跃值: 活跃值 (19)
能力值: ( LV6,RANK:80 )
在线值:
发帖
回帖
粉丝
长风傲天 活跃值 1 2011-3-5 16:12
16
0
我可以很负责的告诉你……有些游戏,咳咳,具体我就不点名批评了
你直接返回STATUS_SUCCESS是木有用的,而且电脑会瞬间卡死~因为我之前也这么做的
再则,如果你直接返回STATUS_ACCESS_DENIED或者STATUS_DEBUGGER_INACTIVE,OK,不会卡死,但会卡得你半死
最后还有一种,将KdDisableDebugger嫁接到KdEnableDebugger,虚拟机还能动,但是,会灰常卡
还有一种,让它成功调用KdDisableDebugger之后,再调用KdEnableDebugger,好吧,这和上一种方法木有区别的。同样,很卡,灰常tmd的卡

我电脑虽然配置不行,但是,此游戏正常和非正常调用KdDisableDebugger的两种情况下,电脑的速度区别是灰常明显的

原因嘛……俺们群里大部分人认为是死循环,为什么会产生死循环,我也不知道,IDA没看出来= =
但是12分的和这个变量有关,KdDebuggerEnabled,但是IDA我还是没找到的说~~

OK……就这么多,打酱油路过,继续纠结去了 =。 =
你要是解决了,告诉我一下哈……偷偷的告诉你,是DNF那个孙子游戏 = =
雪    币: 71
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
mumaren 活跃值 2011-3-5 16:56
17
0
解释一下这句是什么意思?
在windbg中用ed KdDisableDebugger c3
雪    币: 46
活跃值: 活跃值 (19)
能力值: ( LV6,RANK:80 )
在线值:
发帖
回帖
粉丝
长风傲天 活跃值 1 2011-3-5 17:04
18
0
c3=ret
就是在函数头直接ret = =

木用
雪    币: 71
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
mumaren 活跃值 2011-3-5 19:26
19
0
ed是什么意思?

3q
雪    币: 46
活跃值: 活跃值 (19)
能力值: ( LV6,RANK:80 )
在线值:
发帖
回帖
粉丝
长风傲天 活跃值 1 2011-3-5 19:51
20
0
ed= enter data

windbg的一条命令罢了,你F1看看就知道咯~= =
雪    币: 273
活跃值: 活跃值 (18)
能力值: ( LV8,RANK:140 )
在线值:
发帖
回帖
粉丝
代码疯子 活跃值 3 2011-3-5 23:23
21
0
谢谢分享,看完很有收获
雪    币: 169
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
maxzism 活跃值 2011-4-7 12:21
22
0
我的做法是直接修改下EAT,保护驱动启动前把KdDebuggerEnabled改到别的地方,这样保护驱动的KdDebuggerEnabled位置就是我修改后的地方,随便他怎么清零了
雪    币: 12
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
nowhy 活跃值 2011-4-7 12:52
23
0
- -
``卡死还是卡半死?? 附加调用个延时函数就不卡了- -....嘻嘻嘻嘻....
雪    币: 71
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
mumaren 活跃值 2011-4-26 22:48
24
0
在windbg中用ed KdDisableDebugger c3

这句话啥意思?
雪    币: 376
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
Music小冷 活跃值 2011-4-27 02:13
25
0
18楼有解释

不过我现在用LZ的方法和这种,在GPK下无效,TP启动后机器卡到死。。。不知道是哪做的不对?
游客
登录 | 注册 方可回帖
返回