记得以前我的一位大哥做出了山寨版Winobj,当时不知怎么实现的,以为是有什么接口函数,现在终于知道是怎么做的了.
其实跟SSDT的原理差不多,也是有一个全局变量,通过它沿着复杂的路径找到一张树状结构.
kd> !object /
Object: 8148e210 Type: (814c5820) Directory
ObjectHeader: 8148e1f8
HandleCount: 0 PointerCount: 39
Directory Object: 00000000 Name: /
99 symbolic links snapped through this directory
HashBucket[ 00 ]: 8148a350 Directory 'ArcName'
814a8f10 Device 'Ntfs'
HashBucket[ 01 ]: e2390040 Port 'SeLsaCommandPort'
HashBucket[ 03 ]: e1012030 Key '/REGISTRY'
HashBucket[ 06 ]: e1394560 Port 'XactSrvLpcPort'
HashBucket[ 07 ]: e13682e0 Port 'DbgUiApiPort'
HashBucket[ 09 ]: 84305760 Directory 'NLS'
.
.
.
kd> !object 814a8f10
Object: 814a8f10 Type: (814b5ac0) Device
ObjectHeader: 814a8ef8
HandleCount: 0 PointerCount: 2
Directory Object: 8148e210 Name: Ntfs
实现代码如下:
//-----------------------------------------------
//
// Dump Windows 2000 Kernel Object
// Only test on Windows 2000 Server Chinese Edition
// Build 2195(Free)!Programmed By WebCrazy
// (tsu00@263.net ) on 11-04-2000!
// Welcome to http://webcrazy.yeah.net !
//
//-----------------------------------------------
ULONG ObpRootDirectoryObject=0x8148e210; //fetch from symbol file
void DumpDirectoryObject(PVOID DirectoryObject)
{
ULONG HashBucket;
ULONG *Hash;
for(HashBucket=0;HashBucket<=0x24;HashBucket++)
{
Hash=(ULONG *)((ULONG)DirectoryObject+HashBucket*4);
if(*Hash==0) continue;
DbgPrint("/n HashBucket[%02X]/n",HashBucket);
do
{
PUNICODE_STRING ObName,ObTypeName;
PVOID Object,ObPreHeader,ObStandardHeader;
Hash=(ULONG *)(*Hash);
Object=(PVOID)(*(ULONG *)((ULONG)Hash+4));
ObPreHeader=(PVOID)((ULONG)Object-0x28);
ObStandardHeader=(PVOID)((ULONG)Object-0x18);
ObName=(PUNICODE_STRING)((ULONG)ObPreHeader+4);
DbgPrint("/tDump Object:%08X/n",(ULONG)Object);
DbgPrint("/t Name:%S",ObName->Buffer);
ObTypeName=(PUNICODE_STRING)((ULONG)(*(ULONG *)((ULONG)ObStandardHeader+8))+0x40);
DbgPrint("/t Type:%S(%08X)/n",ObTypeName->Buffer,
*(ULONG *)((ULONG)ObStandardHeader+8));
DbgPrint("/t PointerCount:%d HandleCount:%d/n",*(ULONG *)ObStandardHeader,
*(ULONG *)((ULONG)ObStandardHeader+4));
}while(*Hash!=0);
}
}
void DumpObject(PVOID Object)
{
PUNICODE_STRING ObName,ObTypeName;
UNICODE_STRING temp;
PVOID ObPreHeader=(PVOID)((ULONG)Object-0x28),
ObStandardHeader=(PVOID)((ULONG)Object-0x18);
if(((USHORT)NtBuildNumber)!=2195){
DbgPrint("Only test on Windows 2000 Server Build 2195!/n");
return;
}
ObName=(PUNICODE_STRING)((ULONG)ObPreHeader+4);
DbgPrint(" Dump Object:%08X/n Name:%S",(ULONG)Object,ObName->Buffer);
ObTypeName=(PUNICODE_STRING)((ULONG)(*(ULONG *)((ULONG)ObStandardHeader+8))+0x40);
DbgPrint(" Type:%S(%08X)/n",ObTypeName->Buffer,*(ULONG *)((ULONG)ObStandardHeader+8));
DbgPrint(" PointerCount:%d HandleCount:%d/n",*(ULONG *)ObStandardHeader,
*(ULONG *)((ULONG)ObStandardHeader+4));
RtlInitUnicodeString(&temp,L"Directory");
if(!RtlCompareUnicodeString(&temp,ObTypeName,FALSE))
DumpDirectoryObject(Object);
}
void DumpRootDirectoryObject()
{
DumpObject((PVOID)ObpRootDirectoryObject);
}
这样就能将Winobj.exe中的对象名和类型全部显示出来了.
代码没有调试过,但是在Windbg中验证过.若是将/Ntfs输入找到的对象名真的是L"Ntfs",类型名真的是L"Device"