基于交叉引用的搜索检测object hook
Author: sudami [sudami@163.com]
Time: 08/09/12
昨天和VXK同学探讨了些关于object hook检测.基于PDB文件解析的方法虽简单见效,但不实用,因为写个普通程序就要自带符号的话很臃肿不方便.于是打算从文件搜索,下下策是暴搜(最坏的打算,不稳定通用,而且obj函数巨多,肯定搜不过来), 恰巧dummy同学去年时候放了个"通过重定位表找到对某个特定地址的所有引用地址"的代码, 在一些方面适用于搜索Object Origal Address.当然,dummy的R0代码在Load PE到内存方面有部分bug,需要自己修复.
思路如下:
1. 准备表1,存放系统当前的Object Function Address.打开"\ObjectTypes",得到RootDirectory,遍历其中的HashBuckets,根据不同的对象得到不同的地址,存到表1中
2. 准备表2,存放系统原始的Object Function Address.
把系统内核ntosxx加载一份到nonpagepool,在这块区域内进行搜索操作;
① 对于已导出的type(eg.IoDeviceObjectType、PsProcessType),遍历ntosXXEAT,得到RVA -- uAddr,再调用LookupImageXRef((ULONG)NtosCopy, uAddr, LookupXRefCallback);
在LookupXRefCallback回调函数中对地址进行搜索,若是我们要找的函数模块,判断时候进行特征匹配,举个例子:
BOOLEAN
NTAPI
LookupXRefCallback(
PULONG RefAddr
)
{
ULONG tmp, address;
PBYTE lpAddr = (PBYTE)RefAddr;
ULONG x, i;
int time = 0;
// 返回 True 继续寻找,返回 False 停止寻找
// DbgPrint("%08X --> %08X
", RefAddr, RefAddr[0]);
__try
{
//
// 因为调用的是V大的LoadPeFile,所以跟系统加载到内存中的情况是一样的
// 里面已经进行了对齐.所以 (ULONG)RefAddr - (ULONG)NtosCopy;
// 就是RVA,不需要考虑ImageBase了.很好很强大; 而RefAddr即是我们自己加载
// 文件到内存,得到的某个函数的地址,比如我要得到内核函数A开头的原始N字节
// 直接在RefAddr处往后取出便是了.哈哈,很方便~
// sudami 08/09/11 凌晨
//
tmp = (ULONG)RefAddr - (ULONG)NtosCopy; //RVA
// DbgPrint("0x%08lx
", (ULONG)ulKernelBase + tmp );
//
// 对于每个RefAddr ,地址+4开始反汇编,最终找到匹配XX函数内部调用的代码.
// 在它里面就有IopXX,PspXX,CmpXX...系列的函数原始地址啦.
// sudami 08/09/11 凌晨
//
//
// coding
//
lpAddr+=4;
switch ( g_nMethod )
{
case 1: // IopCreateObjectTypes函数
/*++ <IoDeviceObjectType>
1. C7 45 D4 B8 00 00 00 mov [ebp+var_2C], 0B8h
2. C7 45 E8 4D 57 4A 00 mov [ebp+var_18], offset IopParseDevice
C6 45 AF 01 mov byte ptr [ebp+var_54+3], 1
3. C7 45 E4 9A 71 4C 00 mov [ebp+var_1C], offset IopDeleteDevice
4. C7 45 EC 8A 90 4D 00 mov [ebp+var_14], offset IopGetSetSecurityObject
89 5D F0 mov [ebp+var_10], ebx
E8 1F 40 F2 FF call ObCreateObjectType
--*/
time = 0;
for(i=0;i<70;i++)
{
if ( !MmIsAddressValid( &lpAddr[]) ){
continue ;
}
if(lpAddr[]==0xC7 && lpAddr[+1]==0x45)
{
time+=1;
if (time==1)
{
x = *((DWORD *)((ULONG)RefAddr+i+3+4));
if(x!=0xB8)
return FALSE;
}
if(time==2)
{
x = *((DWORD *)((ULONG)RefAddr+i+3+4));
DbgPrint("IopParseDevice - Orig: 0x%08lx
",
(ULONG)x + (ULONG)ulKernelBase - (ULONG)pNtH->OptionalHeader.Image
补充:综合编程 , 安全编程 ,