zoukankan      html  css  js  c++  java
  • 实现用句柄表反调试

    句柄

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

    为什么要有句柄

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

    句柄表的位置

    在_EPROCESS中,有一个成员叫ObjectTable,offset为c4

    其指向了一个_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个字节,因为当成了索引

    遍历句柄表实现反调试

    我们已经知道句柄表了,那么如果调试器要调试程序,就肯定要打开那个程序,通过OpenProcess来获取程序的句柄,那么其对应的句柄表,肯定有这个值,所以我们可以根据这个特性来反调试

    所以思路是:遍历所有其他进程句柄表,看哪个进程的句柄表中保护自己的进程,如果有,说明正在被调试。

    这里我监视的是notepad.exe是否有调试程序

    #include <ntddk.h>
    #include <ntstatus.h>
    
    ULONG GetProcessEprocess(char* ProcessName)
    {
        PEPROCESS pEprocess,pCurEProcess;
        //获取进程的EProcess
        __asm
        {
            mov eax,fs:[0x124]
            mov eax,[eax+0x220]
            mov pEprocess,eax
        }
    
        pCurEProcess=pEprocess;
        do
        {
            PCHAR ImageFileName=(PCHAR)pCurEProcess+0x174;
            if(strcmp(ImageFileName,ProcessName)==0)
            {
                return (ULONG)pCurEProcess;
            }
            pCurEProcess=(PEPROCESS)(*(PULONG)((ULONG)pCurEProcess+0x88)-0x88);
        }while(pCurEProcess!=pEprocess);
        return 0;
    }
    
    BOOLEAN CheckProcessDebug(ULONG CheckedProcess)
    {
        PEPROCESS pEprocess,pCurEProcess;
        PULONG table;
        PEPROCESS eps;
        ULONG ObTable;
        int i,j,k;
        //获取进程的EProcess
        __asm
        {
            mov eax,fs:[0x124]
            mov eax,[eax+0x220]
            mov pEprocess,eax
        }
        DbgPrint("开始检查
    ");
        pCurEProcess=pEprocess;
        do
        {
            PCHAR ImageFileName=(PCHAR)pCurEProcess+0x174;
            ULONG ObjectTable=*(PULONG)((ULONG)pCurEProcess+0xc4);
    
            if(ObjectTable!=0)
            {
                DbgPrint("[%s]	[%s]	[%x]	[%x]
    ",ImageFileName,((PCHAR)CheckedProcess+0x174),ObjectTable,CheckedProcess);
                ObTable=(ULONG)ObjectTable;
                switch(ObTable&0x3)
                {
                case 0:
                    table=(PULONG)((*(PULONG)ObTable)&0xfffffffc);
                    for(i=0;i<512;i+=2)
                    {
                        eps=(PEPROCESS)((table[i]&0xfffffff8)+0x18);
                        //DbgPrint("程序正在被 [%x] 检查!
    ", (ULONG)eps);
                        if(strcmp(ImageFileName,"csrss.exe")!=0&&eps==(PEPROCESS)CheckedProcess)
                        {
                            DbgPrint("程序正在被 [%s] 调试!
    ", ImageFileName);
                            return TRUE;
                        }
                    }
    
                    break;
                case 1:
                    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] 检查!
    ", (PCHAR)eps+0x174);
                            if(eps==(PEPROCESS)CheckedProcess)
                            {
                                DbgPrint("程序正在被 [%s] 调试!
    ", ImageFileName);
                                return TRUE;
                            }
                        }
                    }
                    break;
                case 2:
                    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] 检查!
    ", (PCHAR)eps+0x174);
                                if(eps==(PEPROCESS)CheckedProcess)
                                {
                                    DbgPrint("程序正在被 [%s] 调试!
    ", ImageFileName);
                                    return TRUE;
                                }
                            }
                        }
                    }
                    break;
                default:
                    DbgPrint("No Pass");
                }
    
            }
            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.
    ");
        
    }
    
    
    
    NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING reg_path)
    {
        ULONG addr;
        pDriver->DriverUnload = DriverUnload;
        //获取需要保护的进程的EProcess
        addr=GetProcessEprocess("notepad.exe");
        DbgPrint("程序正在被 [%d] 调试!
    ", addr);
        CheckProcessDebug(addr);
        return STATUS_SUCCESS;
    }

  • 相关阅读:
    Bootstrap表格的使用
    [JS练习] 瀑布流照片墙
    [C#基础] 委托
    [C#基础] 泛型
    [C#基础] 继承
    [C#基础] 类
    [C#基础] 数据类型
    Unity获取手机的电量时间
    C#网络通信Socket详解
    记C#一次服务器搭建和数据库应用
  • 原文地址:https://www.cnblogs.com/pppyyyzzz/p/14277312.html
Copyright © 2011-2022 走看看