ObpLookupEntryDirectory(Windows内核学习笔记)

简介: ObpLookupEntryDirectory(Windows内核学习笔记)
PVOID
NTAPI
ObpLookupEntryDirectory(IN POBJECT_DIRECTORY Directory,
                        IN PUNICODE_STRING Name,
                        IN ULONG Attributes,
                        IN UCHAR SearchShadow,
                        IN POBP_LOOKUP_CONTEXT Context)
{
    BOOLEAN CaseInsensitive = FALSE;
    POBJECT_HEADER_NAME_INFO HeaderNameInfo;
    POBJECT_HEADER ObjectHeader;
    ULONG HashValue;
    ULONG HashIndex;
    LONG TotalChars;
    WCHAR CurrentChar;
    POBJECT_DIRECTORY_ENTRY *AllocatedEntry;
    POBJECT_DIRECTORY_ENTRY *LookupBucket;
    POBJECT_DIRECTORY_ENTRY CurrentEntry;
    PVOID FoundObject = NULL;
    PWSTR Buffer;
    PAGED_CODE();
    if (!ObpLUIDDeviceMapsEnabled) 
      SearchShadow = FALSE;
    /*检查输入的两个关键指针是否有效*/
    if (!(Directory) || !(Name)) 
      goto Quickie;
    /* Get name information */
    TotalChars = Name->Length / sizeof(WCHAR);//按照双字大小,计算对象名的字节数
    Buffer = Name->Buffer;//得Name名称
    /* Set up case-sensitivity */
    if (Attributes & OBJ_CASE_INSENSITIVE)
       CaseInsensitive = TRUE;//大小写不敏感
    /*不是一个命名的对象*/
    if (!(Buffer) || !(TotalChars)) 
      goto Quickie;
    /*计算hash值*/
    for (HashValue = 0; TotalChars; TotalChars--)
    {
        /* Go to the next Character */
        CurrentChar = *Buffer++;
        /* Prepare the Hash */
        HashValue += (HashValue << 1) + (HashValue >> 1);
        /* Create the rest based on the name */
        if (CurrentChar < 'a') HashValue += CurrentChar;
        else if (CurrentChar > 'z') HashValue += RtlUpcaseUnicodeChar(CurrentChar);
        else HashValue += (CurrentChar - ('a'-'A'));
    }
    /*计算hash索引*/
    HashIndex = HashValue % 37;//Hash数组的大小为37
    /*保存Hash值和Hash索引在Context中*/
    Context->HashValue = HashValue;
    Context->HashIndex = (USHORT)HashIndex;
    /*得到当前HashIndex对应在Hash列表中的首地址*/
    AllocatedEntry = &Directory->HashBuckets[HashIndex];
    LookupBucket = AllocatedEntry;
    /* Check if the directory is already locked */
    if (!Context->DirectoryLocked)
    {
        /*申请共享锁*/
        ObpAcquireDirectoryLockShared(Directory, Context);
    }
    /* Start looping */
    while ((CurrentEntry = *AllocatedEntry))
    {
        /*Hash匹配*/
        if (CurrentEntry->HashValue == HashValue)
        {
            /*对象体向对象头的转换*/
            ObjectHeader = OBJECT_TO_OBJECT_HEADER(CurrentEntry->Object);
            /* Get the name information */
            ASSERT(ObjectHeader->NameInfoOffset != 0);
            HeaderNameInfo = OBJECT_HEADER_TO_NAME_INFO(ObjectHeader);
            /*如果名字相同,长度相同*/
            if ((Name->Length == HeaderNameInfo->Name.Length) &&
                (RtlEqualUnicodeString(Name, &HeaderNameInfo->Name, CaseInsensitive)))
            {
                break;//发现目标,对象名相同
            }
        }
        /*否则继续向下遍历*/
        AllocatedEntry = &CurrentEntry->ChainLink;
    }
    /*若CurrentEntry非空,则说明找到了目标对象所在的节点 */
    if (CurrentEntry)
    {
        /*设置当前节点到队列的最前面,为了下次查找效率的提高*/
        if (AllocatedEntry != LookupBucket)
        {
            /* Check if the directory was locked or convert the lock */
            if ((Context->DirectoryLocked) ||
                (ExConvertPushLockSharedToExclusive(&Directory->Lock)))
            {
                /*当前目录项的值修改为当前目录项的下一个,因为当前目录项的内容要被放到最前面去*/
                *AllocatedEntry = CurrentEntry->ChainLink;
                /*连接之前的Hash表 */
                CurrentEntry->ChainLink = *LookupBucket;
                /*构建新的HashEntry*/
                *LookupBucket = CurrentEntry;
            }
        }
        /* 找到目标对象 */
        FoundObject = CurrentEntry->Object;
        goto Quickie;
    }
    else
    {
        /* Check if the directory was locked */
        if (!Context->DirectoryLocked)
        {
            /* Release the lock */
            ObpReleaseDirectoryLock(Directory, Context);
        }
        /* Check if we should scan the shadow directory */
        if ((SearchShadow) && (Directory->DeviceMap))
        {
            /* FIXME: We don't support this yet */
            ASSERT(FALSE);
        }
    }
Quickie:
    /* Check if we inserted an object */
    if (FoundObject)
    {
        /* Get the object name information */
        ObjectHeader = OBJECT_TO_OBJECT_HEADER(FoundObject);
        ObpReferenceNameInfo(ObjectHeader);
        /* Reference the object being looked up */
        ObReferenceObject(FoundObject);
        /* Check if the directory was locked */
        if (!Context->DirectoryLocked)
        {
            /* Release the lock */
            ObpReleaseDirectoryLock(Directory, Context);
        }
    }
    /* Check if we found an object already */
    if (Context->Object)
    {
        /* We already did a lookup, so remove this object's query reference */
        ObjectHeader = OBJECT_TO_OBJECT_HEADER(Context->Object);
        HeaderNameInfo = OBJECT_HEADER_TO_NAME_INFO(ObjectHeader);
        ObpDereferenceNameInfo(HeaderNameInfo);
        /* Also dereference the object itself */
        ObDereferenceObject(Context->Object);
    }
    /* Return the object we found */
    Context->Object = FoundObject;
    return FoundObject;
}


“You’re never really done for, as long as you’ve got a good story and someone to tell it to.”

参考资料:

《Windows内核情景分析》

《Reactos》

目录
相关文章
|
15天前
|
Windows
【Windows内核驱动函数(1)】IoCreateSymbolicLink()-----创建符号链接函数
【Windows内核驱动函数(1)】IoCreateSymbolicLink()-----创建符号链接函数
|
2月前
|
网络协议 Shell vr&ar
某教程学习笔记(一):1、windows基础
某教程学习笔记(一):1、windows基础
24 0
|
2月前
|
监控 安全 API
5.9 Windows驱动开发:内核InlineHook挂钩技术
在上一章`《内核LDE64引擎计算汇编长度》`中,`LyShark`教大家如何通过`LDE64`引擎实现计算反汇编指令长度,本章将在此基础之上实现内联函数挂钩,内核中的`InlineHook`函数挂钩其实与应用层一致,都是使用`劫持执行流`并跳转到我们自己的函数上来做处理,唯一的不同的是内核`Hook`只针对`内核API`函数,但由于其身处在`最底层`所以一旦被挂钩其整个应用层都将会受到影响,这就直接决定了在内核层挂钩的效果是应用层无法比拟的,对于安全从业者来说学会使用内核挂钩也是很重要。
60 1
5.9 Windows驱动开发:内核InlineHook挂钩技术
|
7月前
|
监控 安全 API
7.6 Windows驱动开发:内核监控FileObject文件回调
本篇文章与上一篇文章`《内核注册并监控对象回调》`所使用的方式是一样的都是使用`ObRegisterCallbacks`注册回调事件,只不过上一篇博文中`LyShark`将回调结构体`OB_OPERATION_REGISTRATION`中的`ObjectType`填充为了`PsProcessType`和`PsThreadType`格式从而实现监控进程与线程,本章我们需要将该结构填充为`IoFileObjectType`以此来实现对文件的监控,文件过滤驱动不仅仅可以用来监控文件的打开,还可以用它实现对文件的保护,一旦驱动加载则文件是不可被删除和改动的。
37 1
7.6 Windows驱动开发:内核监控FileObject文件回调
|
7月前
|
监控 安全 API
6.9 Windows驱动开发:内核枚举进线程ObCall回调
在笔者上一篇文章`《内核枚举Registry注册表回调》`中我们通过特征码定位实现了对注册表回调的枚举,本篇文章`LyShark`将教大家如何枚举系统中的`ProcessObCall`进程回调以及`ThreadObCall`线程回调,之所以放在一起来讲解是因为这两中回调在枚举是都需要使用通用结构体`_OB_CALLBACK`以及`_OBJECT_TYPE`所以放在一起来讲解最好不过。
72 1
6.9 Windows驱动开发:内核枚举进线程ObCall回调
|
7月前
|
监控 安全 API
6.8 Windows驱动开发:内核枚举Registry注册表回调
在笔者上一篇文章`《内核枚举LoadImage映像回调》`中`LyShark`教大家实现了枚举系统回调中的`LoadImage`通知消息,本章将实现对`Registry`注册表通知消息的枚举,与`LoadImage`消息不同`Registry`消息不需要解密只要找到`CallbackListHead`消息回调链表头并解析为`_CM_NOTIFY_ENTRY`结构即可实现枚举。
70 1
6.8 Windows驱动开发:内核枚举Registry注册表回调
|
7月前
|
存储 API 开发者
6.7 Windows驱动开发:内核枚举LoadImage映像回调
在笔者之前的文章`《内核特征码搜索函数封装》`中我们封装实现了特征码定位功能,本章将继续使用该功能,本次我们需要枚举内核`LoadImage`映像回调,在Win64环境下我们可以设置一个`LoadImage`映像加载通告回调,当有新驱动或者DLL被加载时,回调函数就会被调用从而执行我们自己的回调例程,映像回调也存储在数组里,枚举时从数组中读取值之后,需要进行位运算解密得到地址。
40 1
6.7 Windows驱动开发:内核枚举LoadImage映像回调
|
7月前
|
网络协议 API C++
6.6 Windows驱动开发:内核枚举Minifilter微过滤驱动
Minifilter 是一种文件过滤驱动,该驱动简称为微过滤驱动,相对于传统的`sfilter`文件过滤驱动来说,微过滤驱动编写时更简单,其不需要考虑底层RIP如何派发且无需要考虑兼容性问题,微过滤驱动使用过滤管理器`FilterManager`提供接口,由于提供了管理结构以及一系列管理API函数,所以枚举过滤驱动将变得十分容易。
73 1
6.6 Windows驱动开发:内核枚举Minifilter微过滤驱动
|
7月前
|
存储 算法 数据安全/隐私保护
6.5 Windows驱动开发:内核枚举PspCidTable句柄表
在 Windows 操作系统内核中,PspCidTable 通常是与进程(Process)管理相关的数据结构之一。它与进程的标识和管理有关,每个进程都有一个唯一的标识符,称为进程 ID(PID)。与之相关的是客户端 ID,它是一个结构,其中包含唯一标识进程的信息。这样的标识符在进程管理、线程管理和内核对象的创建等方面都起到关键作用。
41 1
6.5 Windows驱动开发:内核枚举PspCidTable句柄表
|
2月前
|
监控 Windows
7.4 Windows驱动开发:内核运用LoadImage屏蔽驱动
在笔者上一篇文章`《内核监视LoadImage映像回调》`中`LyShark`简单介绍了如何通过`PsSetLoadImageNotifyRoutine`函数注册回调来`监视驱动`模块的加载,注意我这里用的是`监视`而不是`监控`之所以是监视而不是监控那是因为`PsSetLoadImageNotifyRoutine`无法实现参数控制,而如果我们想要控制特定驱动的加载则需要自己做一些事情来实现,如下`LyShark`将解密如何实现屏蔽特定驱动的加载。
49 0
7.4 Windows驱动开发:内核运用LoadImage屏蔽驱动

相关课程

更多