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 ;
} 是原创的吗?如果是的话, 您再发一篇就能进核心会员了。 半原创吧,看了人家的思路后自己写的。。。。 不求进核心。。。
感觉和你们相差太多了。。。我只有继续学习。。。
ps:Tesla.Angela,看了你在黑客防线的文章,感觉真的很厉害呀。。。所以是来膜拜你的! 回复 nbboy 的帖子
进核心会员跟技术无关,是对热心者的一种奖励。
另外我的技术也不怎么样,只是没事爱写点程序来锻炼一下自己的编程水平而已。 回复 nbboy 的帖子
看了人家的思路后自己写的。。。。
很好,算一篇。 本帖最后由 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了。。。这里我也找不到保护模式下的中断表。。。。 楼主真爱研究技术,加分支持!!!
希望楼主再接再厉! 楼主发一下获得real irp地址的方法吧
谢谢分享
页:
[1]