首页
社区
课程
招聘
[原创]使用CloseHandle欺骗和对抗调试器
发表于: 2010-12-30 14:54 8752

[原创]使用CloseHandle欺骗和对抗调试器

2010-12-30 14:54
8752

我最近调试程序才发觉,CloseHandle这个函数的一个怪异的行为。我突然想到可以利用这个行为来欺骗或者对抗调试器。
    这个怪异的行为是这样的,调用CloseHandle释放一个无效句柄,如果进程在调试器之外,那么函数返回FALSE,而GetLastError得到ERROR_INVALID_HANDLE;但是如果进程在调试器内,那么系统将抛出异常C0000008H。

一、首先说如何得到一个无效句柄呢?

方法一:一个句柄释放多次次
    这个方法看似没问题,但实际有很大的隐患。因为新创建的内核对象是总是寻找句柄表的空白记录,因此有可能存在已经释放过的句柄又被利用,而这时再次释放会很不安全。

方法二:硬编码一个足够大的句柄值
    用procexp.exe看一下就会发现进程里的句柄值很少大于1000h,因此赌一下也是可以的

方法三:释放一个不可关闭的句柄
   这个我认为是最安全的一种方法,首先自己随便调用一个CreateXXX得到一个句柄h1,再调用SetHandleInformation将句柄h1设为不可关闭的,最后调用CloseHandle释放它就行了

二、再说如何利用这个行为

方法一:利用SEH欺骗
     这样利用CloseHandle根据调试器抛出异常,就可以通过SEH使得程序内外有不同的行为

方法二:隐式调用CloseHandle引发调试异常
    关于方法范围比较广泛,大家八仙过海各显神通吧

偶然发现而已,文章发的比较匆忙,现在只是发现FindClose有相同的现象,我估计很多带Close字段都有这种现象,也不知道其它API是否有相似的现象,希望大家不吝指教。


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

收藏
免费 7
支持
分享
最新回复 (13)
雪    币: 1981
活跃值: (771)
能力值: ( LV13,RANK:420 )
在线值:
发帖
回帖
粉丝
2
我以前也试过,将一个句添加 HANDLE_FLAG_PROTECT_FROM_CLOSE 属性再关闭。不过有SOD在,这些小伎俩都没什么作用了
2010-12-30 15:16
0
雪    币: 400
活跃值: (1314)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
3
from ob\Obclose.c
if (PreviousMode != KernelMode) {

                if ((NtGlobalFlag & ***_ENABLE_CLOSE_EXCEPTIONS) ||
                    (CurrentProcess->DebugPort != NULL) ||
                    (ObjectTable->DebugInfo != NULL)) {

                    if (!KeIsAttachedProcess()) {
                        return KeRaiseUserException (STATUS_INVALID_HANDLE);
                    } else {
                        return STATUS_INVALID_HANDLE;
                    }

                }
2010-12-30 15:26
0
雪    币: 431
活跃值: (259)
能力值: ( LV9,RANK:230 )
在线值:
发帖
回帖
粉丝
4
非常好,受教了
2010-12-30 15:31
0
雪    币: 8835
活跃值: (2404)
能力值: ( LV12,RANK:760 )
在线值:
发帖
回帖
粉丝
5
忽略一切异常之后,还有什么能对抗?
2010-12-30 17:35
0
雪    币: 78
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
看不懂,过来膜拜!
2010-12-30 17:40
0
雪    币: 431
活跃值: (259)
能力值: ( LV9,RANK:230 )
在线值:
发帖
回帖
粉丝
7
有些壳就是靠SEH解密的,都忽略了,看你怎么解
2010-12-30 17:41
0
雪    币: 1981
活跃值: (771)
能力值: ( LV13,RANK:420 )
在线值:
发帖
回帖
粉丝
8
想靠CloseHandle异常来解密那应该是不可能的,因为在没有调试器的情况下,根本不会抛出异常。
你所说的靠SEH来解密的壳是指那些利用读写非法内存或者除零之类的异常吧,这些异常即使在OD里选择忽略了,handler依然会执行,只是没有通知你而已。所以不会有无法解密的情况。
2010-12-30 18:51
0
雪    币: 431
活跃值: (259)
能力值: ( LV9,RANK:230 )
在线值:
发帖
回帖
粉丝
9
壳利用这个跑飞了,这怎么办?是不是这样我也不太清楚。

偶,对不起,那里的“解”,我是说脱壳的意思
2010-12-30 18:54
0
雪    币: 431
活跃值: (259)
能力值: ( LV9,RANK:230 )
在线值:
发帖
回帖
粉丝
10
这个我知道,文章里开头不是写了嘛,我是说的是那些加密壳壳
2010-12-30 18:59
0
雪    币: 8209
活跃值: (4518)
能力值: ( LV15,RANK:2473 )
在线值:
发帖
回帖
粉丝
11
放bin出来看看谁的调试器跑不了
2010-12-30 20:00
0
雪    币: 7318
活跃值: (3793)
能力值: (RANK:1130 )
在线值:
发帖
回帖
粉丝
12
code from fengyue.sys

NTSTATUS 
Hooked_NtClose(	IN HANDLE Handle)
{
	NTSTATUS status;
	PVOID  pObject = NULL;

	if(!bInBlackListByEProcess(PsGetCurrentProcess()))	//不是黑名单
		return ((pfnNtClose)fiNtClose.uRealAddr)(Handle);

	if(NT_SUCCESS(ObReferenceObjectByHandle(Handle, GENERIC_READ, 0, KernelMode, &pObject, NULL)))
	{
		ObDereferenceObject(pObject);
		status = ((pfnNtClose)fiNtClose.uRealAddr)(Handle);
	}
	else
	{
		status = STATUS_INVALID_HANDLE;
	}
	return status;
}
2010-12-30 21:38
0
雪    币: 695
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
求楼上代码。。
2010-12-30 22:12
0
雪    币: 431
活跃值: (259)
能力值: ( LV9,RANK:230 )
在线值:
发帖
回帖
粉丝
14
这个真是釜底抽薪
2010-12-30 22:17
0
游客
登录 | 注册 方可回帖
返回
//