nbboy 发表于 2011-1-13 22:34:19

IRP HOOK检测

被大牛们刺激的差不多了,静下心态来后打算写一个ark,告诉自己慢慢来,今天写写一个IRPHook检测部分static        CHAR *Major_Information[]=
{
        "IRP_MJ_CREATE"//+0
        ,"IRP_MJ_CREATE_NAMED_PIPE"//+1
        ,"IRP_MJ_CLOSE"//+2
        ,"IRP_MJ_READ"//+3
        ,"IRP_MJ_WRITE"//+4
        ,"IRP_MJ_QUERY_INFORMATION"//+5
        ,"IRP_MJ_SET_INFORMATION"//+6
        ,"IRP_MJ_QUERY_EA"//+7
        ,"IRP_MJ_SET_EA"//+8
        ,"IRP_MJ_FLUSH_BUFFERS"//+9
        ,"IRP_MJ_QUERY_VOLUME_INFORMATION"//+a
        ,"IRP_MJ_SET_VOLUME_INFORMATION"//b
        ,"IRP_MJ_DIRECTORY_CONTROL"//+c
        ,"IRP_MJ_FILE_SYSTEM_CONTROL"//+d
        ,"IRP_MJ_DEVICE_CONTROL"//+e
        ,"IRP_MJ_INTERNAL_DEVICE_CONTROL"//+f
        ,"IRP_MJ_SHUTDOWN"//+10
        ,"IRP_MJ_LOCK_CONTROL"//+11
        ,"IRP_MJ_CLEANUP"//+12
        ,"IRP_MJ_CREATE_MAILSLOT"//+13
        ,"IRP_MJ_QUERY_SECURITY"
        ,"IRP_MJ_SET_SECURITY"
        ,"IRP_MJ_POWER"
        ,"IRP_MJ_SYSTEM_CONTROL"
        ,"IRP_MJ_DEVICE_CHANGE"
        ,"IRP_MJ_QUERY_QUOTA"
        ,"IRP_MJ_SET_QUOTA"
        ,"IRP_MJ_PNP"
//        ,""

};
VOID        ListIrpHook(PUNICODE_STRING                pDriverName)
{
        PSYSTEM_MODULE_INFORMATION        pSysbuffer;
        PVOID        pMem=NULL;
        ULONG        tmp=0,num,i,j;
        PDRIVER_OBJECT        pDriObj;
        NTSTATUS        ntstatus;
        CHAR        pMyDriver={0};
        ObReferenceObjectByName(pDriverName        ,OBJ_CASE_INSENSITIVE,0,0,IoDriverObjectType        ,KernelMode,NULL,&pDriObj);
       
        ZwQuerySystemInformation(SystemModuleInformation        ,pMem        ,0        ,&tmp);
        if(tmp        >0)
        {
                pMem        =(PSYSTEM_MODULE_INFORMATION)ExAllocatePool(PagedPool        ,tmp);
                ntstatus        =        ZwQuerySystemInformation(SystemModuleInformation        ,pMem        ,tmp        ,&tmp);
                if (NT_SUCCESS(ntstatus))
                {
                        pSysbuffer        =        (PSYSTEM_MODULE_INFORMATION)((ULONG)pMem+4);
                        num        =*(PULONG)pMem;
                        for (i=0;i<num;i++)
                        {
                                if ((ULONG)pDriObj->DriverStart>(ULONG)pSysbuffer.Base        &&        (ULONG)pDriObj->DriverStart<(ULONG)pSysbuffer.Base        +        pSysbuffer.Size)
                                {
                                        strcpy(pMyDriver        ,(CHAR*)(pSysbuffer.ImageName+pSysbuffer.ModuleNameOffset));       
                                        break;
                                }
                        }
                        for (i=0;i<28;i++)
                        {
                                        for (j=0;j<num;j++)
                                        {
                                                if(j        ==        0)
                                                        continue;
                                                if ((ULONG)pDriObj->MajorFunction>(ULONG)pSysbuffer.Base        &&        (ULONG)pDriObj->MajorFunction<(ULONG)pSysbuffer.Base        +pSysbuffer.Size)
                                                {
                                                        //命中模块
                                                        if (_strnicmp((CHAR*)(pSysbuffer.ImageName        +        pSysbuffer.ModuleNameOffset),pMyDriver        ,sizeof(pMyDriver))        !=        0)
                                                                DbgPrint("%s\n",Major_Information);
                                                }
                                        }
                        }
                        ExFreePool(pMem);
                }
        }
        return        ;
}

VOID        ScanIrpHook()
{
        WCHAR        uRoot[]        =L"\\Driver";
        WCHAR        uTmp={0};
        OBJECT_DIRECTORY_INFORMATION        *pDir;
        ULONG        nLength=0x400;
        UNICODE_STRING        unRoot;
        OBJECT_ATTRIBUTES        attrobj;
        HANDLE        pDirectory;
        NTSTATUS        ntstatus;
        //CHAR                pBuffer        =        {0};
        ULONG                tmp=0,temp=0;
        RtlInitUnicodeString(&unRoot        ,        uRoot);
        InitializeObjectAttributes(&attrobj        ,&unRoot        ,OBJ_CASE_INSENSITIVE ,NULL        ,NULL);
        ntstatus        =        ZwOpenDirectoryObject(&pDirectory        ,DIRECTORY_QUERY        ,&attrobj);
        if (NT_SUCCESS(ntstatus))
        {
                       
                        do
                        {
                                pDir                =(POBJECT_DIRECTORY_INFORMATION)ExAllocatePool(PagedPool        ,nLength);
                                ntstatus        =        ZwQueryDirectoryObject(pDirectory        ,        pDir,nLength        ,FALSE        ,TRUE                ,&temp        ,&tmp);
                                if(ntstatus        ==STATUS_MORE_ENTRIES ||        ntstatus        ==STATUS_BUFFER_TOO_SMALL )
                                {
                                        nLength*=2;
                                        ExFreePool((PVOID)pDir);
                                }
                                else        if(ntstatus        ==STATUS_SUCCESS)
                                {
                                        break;
                                }
                                else
                                {
                                        ExFreePool(pDir);
                                        DbgPrint("Error\n");
                                        return;
                                }
                        } while (1);
                        //DbgPrint("~~~%S\n",pDir->Name.Buffer);
                        while(pDir->Name.Length        &&        pDir->TypeName.Length)
                        {
                                        wcscpy(uTmp,L"\\Driver\\");
                                        wcscat(uTmp,pDir->Name.Buffer);
                                        DbgPrint("%S\n",uTmp);
                                        RtlInitUnicodeString(&unRoot        ,uTmp);
                                        ListIrpHook(&unRoot);
                                       
                                        pDir++;
                        }
                       
        }
        else
                        DbgPrint("Don't        Dump!\n");
        return        ;
}

Tesla.Angela 发表于 2011-1-13 23:20:08

是原创的吗?如果是的话, 您再发一篇就能进核心会员了。

nbboy 发表于 2011-1-14 10:15:54

半原创吧,看了人家的思路后自己写的。。。。

nbboy 发表于 2011-1-14 10:17:53

不求进核心。。。
感觉和你们相差太多了。。。我只有继续学习。。。
ps:Tesla.Angela,看了你在黑客防线的文章,感觉真的很厉害呀。。。所以是来膜拜你的!

Tesla.Angela 发表于 2011-1-14 11:16:50

回复 nbboy 的帖子

进核心会员跟技术无关,是对热心者的一种奖励。
另外我的技术也不怎么样,只是没事爱写点程序来锻炼一下自己的编程水平而已。

Tesla.Angela 发表于 2011-1-14 11:23:05

回复 nbboy 的帖子


看了人家的思路后自己写的。。。。

很好,算一篇。

nbboy 发表于 2011-1-14 18:37:37

本帖最后由 nbboy 于 2011-1-14 18:47 编辑

承蒙Tesla.Angela 的厚爱。。。。。本帖算是一篇。。。但是我感觉。。。。
又因为这篇和上篇的原理都是一样的。还是没有考虑隐藏驱动的问题。。。用最简单的
方法来获得驱动列表。如果别人这里坐下文章,那我的代码就瞎眼了。。。。:dizzy:
在写ark的过程中接受了很多新知识,昨晚写了IRPHOOK检测之后仔细想想。。。
IDT&GDT也可以这样检测?:D
今天没课就把代码实现了下基本和xuetr检测出来的差不多。。。那我猜它的原理也差不多吧。。。。过段时间反正也要a它的。到时候就知道了!;P//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>IDT        Hook        Scan        Struct
#define MAKELONG(a, b) ((unsigned long) (((unsigned short) (a)) | ((unsigned long) ((unsigned short) (b))) << 16))

#define MAX_IDT_ENTRIES 0xFF
#pragma pack(1)

// entry in the IDT, this is sometimes called
// an "interrupt gate"
typedef struct
{
        unsigned short LowOffset;
        unsigned short selector;
        unsigned char unused_lo;
        unsigned char segment_type:4;   //0x0E is an interrupt gate
        unsigned char system_segment_flag:1;
        unsigned char DPL:2;          // descriptor privilege level
        unsigned char P:1;             /* present */
        unsigned short HiOffset;
} IDTENTRY;

/* sidt returns idt in this format */
typedef struct
{
        unsigned short IDTLimit;
        unsigned short LowIDTbase;
        unsigned short HiIDTbase;
} IDTINFO;

#pragma pack()

typedef                struct        _IDT_HOOK_TYPE_
{
                CHAR        ImageName;
                ULONG        ModAddress;
                ULONG        FunAddress;
                BOOLEAN        IsHook;//是否被Hook的标志,默认是被Hook了,下面会填写
}IDT_HOOK_TYPE,*PIDT_HOOK_TYPE;

IDT_HOOK_TYPE        g_IdtHookInfo;
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>IDT                Hook        Scan        End
BOOLEAN                DumpIdtHook()
//把模块信息填写HookType结构
{
                IDTINFO                IdtHeader;
                IDTENTRY        *pIdtEntry;
                NTSTATUS        ntstatus;
                BOOLEAN                IsHook        =        TRUE;
                ULONG                i,tmp,pRoutineAddr,j,num;
                //ANSI_STRING        ansiStr;
                PSYSTEM_MODULE_INFORMATION                        pModuleInfo;
                PVOID                pMem;
                memset(g_IdtHookInfo        ,0        ,sizeof(IDT_HOOK_TYPE)*MAX_IDT_ENTRIES);
                _asm
                {
                        sidt IdtHeader                //主要这条指令,可以从系统中获取IDT表的信息
                }
                pIdtEntry        =(IDTENTRY*)        MAKELONG(IdtHeader.LowIDTbase        ,IdtHeader.HiIDTbase        );
                ZwQuerySystemInformation(SystemModuleInformation        ,pMem        ,0        ,&tmp);
                if(tmp        >0)
                {
                        pMem        =(PSYSTEM_MODULE_INFORMATION)ExAllocatePool(PagedPool        ,tmp);
                        ntstatus        =        ZwQuerySystemInformation(SystemModuleInformation        ,pMem        ,tmp        ,&tmp);
                        pModuleInfo        =        (PSYSTEM_MODULE_INFORMATION)((ULONG)pMem        +        4);
                        num                        =        *(PULONG)pMem        ;
                                for (i=0        ;i<MAX_IDT_ENTRIES        ;i++)
                                {
                                        IsHook        =        TRUE        ;
                                        pRoutineAddr        =(ULONG)        MAKELONG(pIdtEntry.LowOffset,pIdtEntry.HiOffset);
                                        if(pRoutineAddr        !=        0)
                                        {
                                                for (j=0        ;j<num        ;j++)
                                                {
                                                        if (pRoutineAddr >        (ULONG)pModuleInfo.Base&&pRoutineAddr        <(ULONG)pModuleInfo.Base        +        pModuleInfo.Size)
                                                        {
                                                               
                                                                strcpy(g_IdtHookInfo.ImageName,(CHAR*)(pModuleInfo.ImageName+pModuleInfo.ModuleNameOffset));
                                                                g_IdtHookInfo.ModAddress        =        (ULONG)pModuleInfo.Base;
                                                                g_IdtHookInfo.FunAddress        =        pRoutineAddr        ;
                                                                IsHook        =        FALSE;
                                                                break        ;
                                                        }
                                                }
                                                if (IsHook        ==        TRUE)
                                                {
                                                        DbgPrint("Module        Start        Address                %.8x\n",SearchModule(pRoutineAddr));
                                                        g_IdtHookInfo.FunAddress=pRoutineAddr;
                                                        g_IdtHookInfo.IsHook        =TRUE;
                                                }
                                        }
                                        else
                                        {
                                        g_IdtHookInfo.ModAddress=        0;
                                        g_IdtHookInfo.FunAddress=        0;
                                        g_IdtHookInfo.IsHook        =        0;//本来就没有Routine的
                                        }
                                }
                                return                TRUE        ;
                }
                return        FALSE        ;
}

BOOLEAN                ScanIdtHook()
{
        ULONG        i;
        CHAR        *tmp={"Hook"        ,"        "};
        if(DumpIdtHook()        ==        TRUE)
        {
                        for (i=0        ;i<MAX_IDT_ENTRIES        ;i++)
                        {
                                DbgPrint("%d:        %s       %.8x                %s\n",i        ,g_IdtHookInfo.ImageName,g_IdtHookInfo.ModAddress,(g_IdtHookInfo.IsHook        ==        TRUE?tmp        :tmp));
                        }
                        return        TRUE        ;
        }
        return        FALSE        ;
}

ULONG        SearchModule(ULONG                pFunAddr)
{
                ULONG        pPageTest,pNoPageTest,tmp;
                ULONG        peheader        ,i;
                if(pFunAddr        ==        0)
                        return        0;
                pPageTest        =        (ULONG)ExAllocatePoolWithTag(PagedPool        ,4        ,'Nb');
                //        有可能函数地址是在堆中分配的,这样的情况我们就不向前遍历
                //pNoPageTest        =        (ULONG)ExAllocatePoolWithTag(NonPagedPool        ,4        ,'Nb');
                //DbgPrint("PagePool        %x,NoPagePool        %x\n",(ULONG)pPageTest        ,(ULONG)pNoPageTest);
                pPageTest        =        pPageTest        &        0xf0000000;
                tmp                        =        pFunAddr        &        0xf0000000;
                if(tmp        ==        pPageTest)
                        return        1;
                __try
                {
                        i=0;
                        do
                        {
                                i++;
                                if(i        ==        0x80000)
                                {
                                        //DbgPrint("没有搜索到\n");
                                        break;
                                }
                                if(MmIsAddressValid((PVOID)(pFunAddr        +        i))        ==        TRUE)
                                {
                                        if(*(PSHORT)(pFunAddr+i)        ==        IMAGE_DOS_SIGNATURE)
                                        {       
                                                if(MmIsAddressValid((PVOID)(pFunAddr        +        i+0x3c))        ==        TRUE)
                                                {
                                                        peheader        =*(PULONG)(pFunAddr        +        i+0x3c)+(pFunAddr        +        i);
                                                        if(MmIsAddressValid((PVOID)peheader))
                                                        {
                                                                if(*(PULONG)(peheader)        ==        IMAGE_NT_SIGNATURE)
                                                                        return        (pFunAddr+i);
                                                        }
                                                }
                                        }
                                }
                        } while (1);
                }
                __except(EXCEPTION_EXECUTE_HANDLER)
                {
                        ;;
                        DbgPrint("Exception                \n");
                        DbgBreakPoint();
                }
               
                return        0;
}当然这里还要提一个问题,xuetr没有提供从恶意模块的函数得到恶意模块的地址的功能。。。。

所以这里它,写着未知模块!但是想想从函数得到模块的情况的却很复杂,,,因为这个函数可以是堆中分配的。。。
或是不是。。。那得到这个模块的地址可行吗?上面的SearchModule我试图得到它的模块,结构很多情况下奔溃了
:dizzy:

另外如果要提供一个信息对比的话。那显然要分析下ntoskrnl.exe了。。。这里我也找不到保护模式下的中断表。。。。

Tesla.Angela 发表于 2011-1-14 19:08:22

楼主真爱研究技术,加分支持!!!
希望楼主再接再厉!

jiedengye 发表于 2011-1-18 16:30:35

楼主发一下获得real irp地址的方法吧

sku__ 发表于 2015-1-10 10:27:05

谢谢分享
页: [1]
查看完整版本: IRP HOOK检测