关于CloseHandle函数的反调试作用

发布时间:2013年12月23日 作者:未知 查看次数:1925

关于CloseHandle函数的反调试作用


关于CloseHandle函数的反调试作用

Windows博大精深,人的发掘力也高深莫测,普通的Api函数也可以用作反调试。

使用CloseHandle对抗调试器
http://blog.csdn.net/yangbostar/article/details/6107169


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


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


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

方法二:硬编码一个的句柄值
    用procexp.exe看一下就会发现进程里的句柄值很少大于1000h,因此赌一下也是可以的。同时我们知道句柄值,实际上是句柄表索引,因此句柄值都是4的倍数,所以可以故意避开这些个值。

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

 

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


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

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

以下反调试摘要:
kernel32!CloseHandle 和NtClose
APIs 让ZwClose syscall (例如CloseHandle, 非直接地) 的使用者能用于检测调试器. 当进程被调试, 使用一个无效的句柄调用 ZwClose 将会产生一个STATUS_INVALID_HANDLE (0xC0000008) 异常.
As with all anti-debugs that rely on information made directly available from the kernel (therefore involving a syscall), 唯一合适绕过"CloseHandle"这个反调试的办法就是要么在它被调用之前从ring3修改syscall 数据 , 要么安装内核钩子.
这个反调试尽管非常的强悍,但还没见广泛用于恶意软件.
例子:
push offset @not_debugged
push dword fs:[0]
mov fs:[0], esp
push 1234h ;invalid handle
call CloseHandle
; if fall here, process is debugged
;...
@not_debugged:
;...


可是对现在版本的OD都已经不起作用了,用其它的调试器还可以看到效果。
OD忽略了它,那就建双进程自己调试自己吧,不让异常产生就不能正确执行好了,让OD忽略吧。



版权所有!www.sieye.cn
E.Mail:sieye@sohu.com QQ:66697110