利用句柄表实现反调试

白帽子社区

共 5690字,需浏览 12分钟

 · 2021-04-27

作者:Evan  编辑:白帽子社区运营团队




    "白帽子社区在线CTF靶场BMZCTF,欢迎各位在这里练习、学习,BMZCTF全身心为网络安全赛手提供优质学习环境,链接(http://www.bmzclub.cn/)

"    





句柄
句柄可以说是Windows编程的核心,当一个进程创建或者打开一个内核对象时,就会获得一个句柄,通过这个句柄可以访问内核对象

为什么要有句柄
句柄存在的目的是为了避免在应用层直接修改内核对象,句柄也就是内核对象中的一个索引,而内核对象存放在句柄表中

句柄表的位置
_EPROCESS中,有一个成员叫ObjectTableoffsetc4

其指向了一个_HANDLE_TABLE结构体
ntdll!_HANDLE_TABLE   +0x000 TableCode        : Uint4B   +0x004 QuotaProcess     : Ptr32 _EPROCESS   +0x008 UniqueProcessId  : Ptr32 Void   +0x00c HandleTableLock  : [4] _EX_PUSH_LOCK   +0x01c HandleTableList  : _LIST_ENTRY   +0x024 HandleContentionEvent : _EX_PUSH_LOCK   +0x028 DebugInfo        : Ptr32 _HANDLE_TRACE_DEBUG_INFO   +0x02c ExtraInfoPages   : Int4B   +0x030 FirstFree        : Uint4B   +0x034 LastFree         : Uint4B   +0x038 NextHandleNeedingPool : Uint4B   +0x03c HandleCount      : Int4B   +0x040 Flags            : Uint4B   +0x040 StrictFIFO      : Pos 0, 1 Bit
offset 0的地方他指向的就是句柄表

句柄表结构
而这个指针的值,最后两位代表的是多少等级的句柄表,也就是如下


句柄表中,句柄大小是4字节,但是却需要占8个字节(Windows就是这么设计的),如果是0级句柄表,那就是512个条目,如果是1级句柄表,那就是512*1024,因为一个句柄表大小为4k,然候0级句柄表的每个条目指向的也是一个句柄表,此时的0级句柄表的条目只需要4个字节,因为当成了索引

句柄表现
由于句柄大小为8字节,在内存中我们通过Handle/4得到句柄在句柄表中的序号,然后在通过TableCode+Handle/4*8得到其句柄表项,其中句柄表项的属性如下

也就是说,当我们有一个进程打开了一个进程时,他的句柄表中,会有另一个进程的句柄,此时我们遍历所有进程的句柄表,查看是否有自身,即可验证自己是否被调试

遍历句柄表实现反调试
我们已经知道句柄表了,那么如果调试器要调试程序,就肯定要打开那个程序,通过OpenProcess来获取程序的句柄,那么其对应的句柄表,肯定有这个值,所以我们可以根据这个特性来反调试
所以思路是:遍历所有其他进程句柄表,看哪个进程的句柄表中保护自己的进程,如果有,说明正在被调试。
这里我监视的是notepad.exe是否有调试程序


#include <ntddk.h>#include <ntstatus.h>
ULONG GetProcessEprocess(char* ProcessName){ PEPROCESSpEprocess,pCurEProcess; //获取进程的EProcess __asm { moveax,fs:[0x124] moveax,[eax+0x220] movpEprocess,eax }
pCurEProcess=pEprocess; do { PCHARImageFileName=(PCHAR)pCurEProcess+0x174; if(strcmp(ImageFileName,ProcessName)==0) { return (ULONG)pCurEProcess; } pCurEProcess=(PEPROCESS)(*(PULONG)((ULONG)pCurEProcess+0x88)-0x88); }while(pCurEProcess!=pEprocess); return0;}
BOOLEAN CheckProcessDebug(ULONG CheckedProcess){ PEPROCESSpEprocess,pCurEProcess; PULONG table; PEPROCESS eps; ULONG ObTable; int i,j,k; //获取进程的EProcess __asm { moveax,fs:[0x124] moveax,[eax+0x220] movpEprocess,eax } DbgPrint("开始检查\n"); pCurEProcess=pEprocess; do { PCHARImageFileName=(PCHAR)pCurEProcess+0x174; ULONGObjectTable=*(PULONG)((ULONG)pCurEProcess+0xc4);
if(ObjectTable!=0) { DbgPrint("[%s]\t[%s]\t[%x]\t[%x]\n",ImageFileName,((PCHAR)CheckedProcess+0x174),ObjectTable,CheckedProcess); ObTable=(ULONG)ObjectTable; switch(ObTable&0x3) { case0: table=(PULONG)((*(PULONG)ObTable)&0xfffffffc); for(i=0;i<512;i+=2) { eps=(PEPROCESS)((table[i]&0xfffffff8)+0x18); //DbgPrint("程序正在被 [%x] 检查!\n", (ULONG)eps); if(strcmp(ImageFileName,"csrss.exe")!=0&&eps==(PEPROCESS)CheckedProcess) { DbgPrint("程序正在被 [%s] 调试!\n", ImageFileName); return TRUE; } }
break; case1: for(i=0;i<1024;i++) { table=(PULONG)(*(PULONG)ObTable)+i; if(MmIsAddressValid((PVOID)table)) for(j=0;j<512;j++) { eps=(PEPROCESS)((ULONG)(table+j*2)&0xfffffff8+0x18); DbgPrint("程序正在被 [%s] 检查!\n", (PCHAR)eps+0x174); if(eps==(PEPROCESS)CheckedProcess) { DbgPrint("程序正在被 [%s] 调试!\n", ImageFileName); return TRUE; } } } break; case2: for(i=0;i<1024;i++) { table=(PULONG)(*(PULONG)ObTable)+i; if(MmIsAddressValid((PVOID)table)) for(j=0;j<1024;j++) { table=(PULONG)(*(PULONG)ObTable)+j; if(MmIsAddressValid((PVOID)table)) for(k=0;k<512;k++) { eps=(PEPROCESS)((ULONG)(table+k*2)&0xfffffff8+0x18); DbgPrint("程序正在被 [%s] 检查!\n", (PCHAR)eps+0x174); if(eps==(PEPROCESS)CheckedProcess) { DbgPrint("程序正在被 [%s] 调试!\n", ImageFileName); return TRUE; } } } } break; default: DbgPrint("NoPass"); }
} pCurEProcess=(PEPROCESS)(*(PULONG)((ULONG)pCurEProcess+0x88)-0x88); }while(pCurEProcess!=pEprocess); DbgPrint("Processing is not debug"); return FALSE;}VOID DriverUnload(PDRIVER_OBJECT pDriver){ DbgPrint("Driver unloaded.\n");
}


NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver,PUNICODE_STRING reg_path){ ULONG addr; pDriver->DriverUnload = DriverUnload; //获取需要保护的进程的EProcess addr=GetProcessEprocess("notepad.exe"); DbgPrint("程序正在被 [%d] 调试!\n", addr); CheckProcessDebug(addr); return STATUS_SUCCESS;}


往期精彩文章




Chrome浏览器代码执行0 day漏洞通知
虎符ctf  wp
apache ofbiz CVE-2021-26295 RMI反序列化分析
红队战术-用ssl加密你的metasploit通信




技术支持:白帽子社区团队
— 扫码关注我们 



浏览 34
点赞
评论
收藏
分享

手机扫一扫分享

举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

举报