查看: 375|回复: 1
收起左侧

[技术探讨] 【本人手动渣翻系列·其七】MDAV WdFilter分析(三)

[复制链接]
ANY.LNK
发表于 2024-11-13 01:20:14 | 显示全部楼层 |阅读模式
本帖最后由 ANY.LNK 于 2024-11-13 01:20 编辑

(接上篇,呼……已经到第三篇了呢……前文可以看目录https://bbs.kafan.cn/thread-2275641-1-1.html

此部分主要关注:

·进程和桌面句柄操作回调
·驱动信息和验证

进程和桌面句柄回调

首先的首先,对象回调初始化是如何完成的。此过程在MpObInitialize中开始,获取以下两个函数的动态地址:

·ObRegisterCallbacks(指针存储在MpData->pObRegisterCallbacks)
·ObUnRegisterCallbacks(指针存储在MpData->pObUnRegisterCallbacks)

若两个函数指针都被检索到,它将继续调用MpObAddCallback。此函数主要任务为实际注册回调并在输出参数中返回注册句柄,保存在MpData->ObRegistrationHandle中。

要注册对象回调,必须向ObRegisterCallbacks提供一个OB_CALLBACK_REGISTRATION结构。除其他外,此结构还包含一个OB_OPERATION_REGISTRATION组,将以如下方式初始化:



在上面的伪代码中可以看到两个条目(在Windows 10情况下)是如何添加到组中的。两个操作都注册了同样的PreOperation且不注册PostOperation,同时注册了处理创建和复制的功能。我们先关注PreOperation函数MpObPreOperationCallback

推荐文章https://rayanfam.com/topics/reversing-windows-internals-part1/以获取更多此结构的相关信息

MpObPreOperationCallback

如前所示,此回调同时针对PsProcessType和ExDesktopObjectType注册,因而此例程需要一种区分二者是谁触发了回调的方式。由于这是一个PreOperation例程,因此其原型必须定义为POB_PRE_OPERATION_CALLBACK,意味着它的第二个参数将会是一个包含ObjectType区域的OB_PRE_OPERATION_INFORMATION结构,此值可以用于指示哪种类型的对象触发了回调。所以总结,此函数的唯一任务就是为每种类型的对象类型重定向OperationInformation到正确的函数。
MpObHandleOpenDesktopCallback

这是用于处理桌面对象相关操作的函数,主要作为通知器使用,接收OB_PRE_OPERATION_INFORMATION作为参数。首先它将从当前进程获取ProcessCtx,并检查ProcessCtx->ProcessRules中被我命名为DoNotNotifyDesktopHandlesOp(0x8)的值是否未设置。若未设置,将从OB_PRE_OPERATION_INFORMATION获取目标对象。对象取回成功后,代码将继续通过函数ObQueryNameString获取其名称。此后将分配AsyncMessageData结构(依据对象名称的长度进行分配)。TypeOfMessage组合包含下列结构:



一旦整个AsyncMessageData填充完毕,就使用MpAsyncSendNotification发送通知。



MpObHandleOpenProcessCallback
此函数处理有关进程句柄的操作。此回调启动的必须条件是标志MpData->UnsetObAndRegCallback未设置,当前进程不同于MsMpEng,句柄不是内核句柄KernelHandle。若满足上述条件,代码将继续获取当前进程和目标进程的ProcessCtx(当前进程尝试取得目标进程的句柄)。从现在起将基于进程请求的访问类型应用不同的规则。
若进程请求如下类型的访问:

·PROCESS_VM_WRITE:写入目标进程的地址空间
·PROCESS_VM_OPERATION:修改目标进程的地址空间
·PROCESS_CREATE_THREAD:在目标进程上下文中创建新线程

则回调检查当前进程到目标进程的代码注入是否允许。此检查基于两个函数:BOOLEAN MpAllowCodeInjection(PProcessCtx CurrentProcess, PProcessCtx TargetProcess)此函数检查当前进程CurrentProcess的ProcessFlags匹配以下任何值:

·ExcludedProcess - 0x1
·MpServiceSidProcess - 0x10
·FriendlyProcess - 0x20
·SvchostProcess - 0x100

若无匹配,它将从目标进程TargetProcess获取值ProcessCtx->CodeInjectionTargetMask和当前进程CurrentProcess获取值ProcessCtx->CodeInjectionRequestMask并共同考虑二值以决定注入是否允许。



若函数返回FALSE,DesiredAccess将被修改以删除触发此检查的权限。

当我们运行Windows 10 16000或更高版本时将会进行另一个基于Windows Defender主机入侵和防御系统(HIPS)规则检查。

说实话,我对Windows Defender HIPS知道的也不多,并且很难在网上找到相关信息。所以我不知道是否有添加或检查哪些HIPS规则正在系统上运行。若有人对此有深入了解,请告知我!

用于创建句柄的HIPS规则在MpAllowAccessBasedOnHipsRule中被检查,除其他外,函数接收如下参数:

·HipsRule - @r8
·ProcessRule - @r9
·TargetRule - @rsp+20

函数还会依据对应的ProcessRules检查作为参数传入的规则——Hips规则依据当前进程规则进行检查:



对于PROCESS_VM_WRITE、PROCESS_VM_OPERATION和PROCESS_CREATE_THREAD而言,将传入如下值作为参数:

·HipsRule => AllowCodeInjectionHIPSRule - 0x8000
·ProcessRule => AllowedToInjectCode - 0x10000
·TargetRule => AllowIncomingCodeInjection - 0x80000

再次回到回调,另一组访问权限也会触发检查,如下列表:

·SYNCHRONIZE:需要使用等待函数等待进程终止
·PROCESS_TERMINATE:需要使用TerminateProcess结束进程
·PROCESS_SUSPEND_RESUME:需要暂停(挂起)或恢复进程
·PROCESS_QUERY_LIMITED_INFORMATION:需要获取进程的确切信息

此时函数将从当前进程检查值ProcessCtx->ProcessProtection以检查进程类型Type是否为PsProtectedTypeNone以及Signer级别低于PsProtectedSignerAntimalware。同先前的情况一样,这种情况也有对应的HIPS规则,传入MpAllowAccessBasedOnHipsRule的参数如下:

·HipsRule => QuerySuspendResumeHIPSRule - 0x800000
·ProcessRule => AllowedToQuerySuspendResume - 0x1000000
·TargetRule => AllowQuerySuspendResume - 0x2000000

若任意检查失败,DesiredAccess将依据情况进行适应调整。

最后,回调将发送异步通知。通知在MpObSendOpenProcessBMNotification里创建并发送,我们已经见过了很多行为类似的函数,它会创建一个AsyncMessageData,其中TypeOfMessage为ObProcessHandleMessage,是一个拥有如下定义的结构:



一旦此结构分配并填充完成,通知将被添加到AsyncNotificationsList以便由工作线程处理。



回到主函数,发送通知后在结束函数前还有最后一道检查。这种情况目标进程是MpServiceSidProcess而当前进程不是MpServiceSidProcess或FriendlyProcess中的任何一种类型,此时如下访问权限会被移除:




驱动信息和验证
此过程的第一个函数是MpInitializeDriverInfo,这是一个在DriverEntry中被调用的函数。我们已经在此系列文章中的第一篇中提到了这个函数,现在我们将查看更多它的细节以及其他参与此过程中的函数。它将分配如下结构:

  1. typedef struct _MP_DRIVERS_INFO
  2. {
  3.    INT Status;
  4.    BYTE Reserved[8];
  5.    INT ElamSignaturesMajorVer;
  6.    INT ElamSignatureMinorVer;
  7.    LIST_ENTRY LoadedDriversList;
  8.    PSLIST_ENTRY ElamRegistryEntries;
  9.    LIST_ENTRY BootProcessList;
  10.    PCALLBACK_OBJECT CallbackObject;
  11.    PVOID BootDriverCallbackRegistration;
  12.    FAST_MUTEX DriversInfoFastMutex;
  13.    INT TotalDriverEntriesLenght;
  14.    NTSTATUS (__fastcall *pSeRegisterImageVerificationCallback)(SE_IMAGE_TYPE, SE_IMAGE_VERIFICATION_CALLBACK_TYPE, PSE_IMAGE_VERIFICATION_CALLBACK_FUNCTION, PVOID, SE_IMAGE_VERIFICATION_CALLBACK_TOKEN, PVOID *);
  15.    VOID (__fastcall *pSeUnregisterImageVerificationCallback)(PVOID);
  16.    PVOID ImageVerificationCbHandle;
  17.    INT RuntimeDriversCount;
  18.    INT RuntimeDriversArrayLenght;
  19.    PVOID RuntimeDriversArray;
  20.    LIST_ENTRY RuntimeDriversList;
  21.    INT64 field_C8;
  22. } MP_DRIVERS_INFO, *PMP_DRIVERS_INFO
复制代码


初始化此结构的一些区域后,函数将获取对象\Callback\WdEbNotificationCallback的句柄并继续将MpBootDriverCallback注册为回调函数,保存注册句柄到结构组件BootDriverCallbackRegistration

MpAddDriverInfo & MpAddBootProcessEntry

在介绍引导驱动回调前我先解释一下列表条目LoadedDriversList和BootProcessList是如何填充的。前者的数据会被链入在映像加载回调中执行的MpAddDriverInfo,后者在进程创建回调时被调用的MpAddBootProcessEntry中填充。

深入MpAddDriverInfo,正如我所说,只要加载的映像是SystemModeImage,它就会在映像加载回调中被调用。此函数将会接收IMAGE_INFO和完整映像名称作为参数,并为结构MP_DRIVER_INFO分配空间。



它在此填充ImageSize,ImageBase和ImageName并链接此列表到MP_DRIVERS_INFO->LoadedDriversList



若MpAddBootProcessEntry函数在进程创建时被调用,它将对前50个加载的进程执行(计数器保存在全局变量BootProcessCounter):



再次回到先前的情况,函数的主要目标是分配并初始化一个结构。此时结构为MP_BOOT_PROCESS且定义如下:



一旦列表初始化,下一步就是链入列表MP_DRIVERS_INFO->BootProcessList



MpBootDriverCallback
我们现在已经知道两个列表条目是如何填充的了,现在是时候看下回调函数是如何在初始化中注册的了。正如我在前文MDAV ELAM分析中说的那样,此回调在ELAM驱动BDCB_CALLBACK_TYPE被设置为BdCbStatusUpdate且映像信息有设置为BdCbClassificationKnownBadImage的BDCB_CLASSIFICATION时被通知。若满足上述条件,将用Argument1(作为指向主WdBoot结构MP_EB_GLOBALS的指针)通知回调,同时Argument2被设置为常量0x28.

所以进入MpBootDriverCallback,它的首要任务是对Argument1和Argument2进行正确性检查,后者将检查是否等于0x28,前者将检查结构的Magic是否等于0xEB01。若两项检查均通过,它将继续遍历WdBoot创建的驱动列表,并为每个驱动调用MpCopyDriverEntry以复制驱动程序条目数据到一个MP_DRIVER_INFO结构,稍后会被链接到MP_DRIVERS_INFO->LoadedDriversList。

免责声明!:以下内容包含我未能实际复现的情况,因此包含一些猜测,我深表歉意。这可能与ELAM驱动可使用注册表回调或用于监控并验证配置数据的引导驱动回调有关。我在我的研究中只能复现第二种情况。

每个条目都被复制后,SLIST_ENTRY ElamRegistryEntries将被运行,并为每个条目调用MpCopyElamRegistryEntry。此函数会将条目复制到被我命名为MP_ELAM_REGISTRY_ENTRY的结构且此结构将被插入单链表MP_DRIVERS_INFO->ElamRegistryEntries中——这可能与ELAM注册表蜂巢(hive)条目有关。MP_ELAM_REGISTRY_ENTRY的大小为0x40且包含两个Unicode字符串(UNICODE_STRINGS)但我无法为此提供更多信息了,若有人知道请告诉我相关信息,我会更新此段。

最终,两个更多的值由MP_EB_GLOBALS复制到MP_DRIVERS_INFO。值的名称为ElamSignaturesMajorVer和ElamSignatureMinorVer。——这就是这个函数所有的所作所为了,简而言之,它从MP_EB_GLOBALS中复制信息(由ELAM驱动获取)到结构MP_DRIVERS_INFO。

MpSetImageVerificationCallback

这是初始化过程中最后执行的函数,此函数的目标是注册一个映像验证回调。为达成此目标,它会动态获取如下两个函数的指针:

·SeRegisterImageVerificationCallback
·SeUnregisterImageVerificationCallback

这两个函数都位于内核中,功如其名。SeRegisterImageVerificationCallback拥有一系列检查,可在下方的伪代码中查看:



回到MpSetImageVerificationCallback,除了注册函数MpImageVerificationCallback为映像验证回调例程外,它还会分配一个大小为0x800的池,RuntimeDriversArray位于其中。

MpImageVerificationCallback

此回调将被内核中的SepImageVerificationCallbackWorker通知,回调执行时的调用堆栈如下:



回调何时怎么被通知,就留给读者自己去实验了


一旦回调被通知,首要任务是调用MpAllocateDriverInfoEx分配并初始化一个MP_DRIVER_INFO_EX



如果你还记得我写的WdBoot相关的话,这是同一个我命名为MODULE_ENTRY的结构。看起来此结构同样作为MP_DRIVER_INFO的扩展版本存在,这同样联系到IMAGE_INFO_EX和IMAGE_INFO——此时不是一个整个结构包含的指针
从现在起,代码将执行和WdBoot类似的步骤。用同一个算法计算IndexHash



然后使用此IndexHash在RuntimeDriversArray使用下列算法获取索引



实际功效可以参见WdBoot的分析


最终,驱动链入MpDriversInfo.RuntimeDriversList



所有有关获取到的驱动程序信息的一切将在下一篇文章介绍到的MpQueryLoadedDrivers发挥作用。此函数可以在MsMpEng尝试获取一份MP_DRIVERS_INFO数据副本时被触发。

总结

本部分到此结束!我们已经距离驱动的过滤功能部分不远了。在下一篇中,我们将花费完整的一篇用于探讨WdFilter是如何处理注册表操作的——那里有些很酷的东西。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?快速注册

x

评分

参与人数 2魅力 +2 人气 +3 收起 理由
白露为霜 + 2 感谢提供分享
驭龙 + 3 版区有你更精彩: )

查看全部评分

驭龙
发表于 2024-11-13 15:23:34 | 显示全部楼层
这些内容感觉就是帮助某些人绕过MD而出的帮助文档啊,哈哈

评分

参与人数 1人气 +1 收起 理由
ANY.LNK + 1 wwwww确实

查看全部评分

您需要登录后才可以回帖 登录 | 快速注册

本版积分规则

手机版|杀毒软件|软件论坛| 卡饭论坛

Copyright © KaFan  KaFan.cn All Rights Reserved.

Powered by Discuz! X3.4( 沪ICP备2020031077号-2 ) GMT+8, 2024-11-21 17:58 , Processed in 0.125409 second(s), 19 queries .

卡饭网所发布的一切软件、样本、工具、文章等仅限用于学习和研究,不得将上述内容用于商业或者其他非法用途,否则产生的一切后果自负,本站信息来自网络,版权争议问题与本站无关,您必须在下载后的24小时之内从您的电脑中彻底删除上述信息,如有问题请通过邮件与我们联系。

快速回复 客服 返回顶部 返回列表