查看: 4793|回复: 2
收起左侧

[技术探讨] 【转载】Windows Defender 内存扫描功能分析

[复制链接]
ANY.LNK
发表于 2023-1-11 22:22:40 | 显示全部楼层 |阅读模式
原文地址:https://mp.weixin.qq.com/s/C6CePu9albvGTj3_9aUxeg(原作者:roadwy 219攻防实验室)

内容为适应论坛可能有所调整

正文:

Defender是Windows系统自带的反病毒软件,从Vista开始直接内置在Windows系统中,默认处于开启状态,对大部分普通用户来说是其系统安全基础保障,因此也是安全研究者一个重要的研究目标。

0x00 关于内存扫描

内存扫描也称运行时分析(Run-time Analysis)与传统的文件静态扫描类似,一般依赖一组已知的特征码对恶意代码进行识别,与静态扫描不同的是内存扫描分析的对象是内存(RAM),而不是磁盘上的文件。因为依赖特征码,内存扫描一般无法检测未知的恶意代码,但是误报率接近于零并且可以识别出恶意代码家族。
相较于静态扫描,内存扫描对攻击者更具挑战,因为在内存中混淆代码的难度更大。攻击者可以通过各类无文件攻击(Fileless Attack)、代码加密混淆、加壳等技术避免静态扫描(包括基于文件的机器学习检测)或者修改文件特征,但运行时内存特征一般不变。如各种Loader免杀方案一般是通过使用不同编程语言与编码或者加密算法组合修改恶意代码的文件特征,但执行后始终会将原始镜像在内存中解密执行。


0x01 分析目标及思路

将基于静态分析与动态调试相结合的方式对Defender的内存扫描功能进行简单分析,主要目标如下:
确定内存扫描功能具体由哪个模块实现以及实现方式;
定位内存中具体哪段内存数据是恶意代码特征码;
内存扫描如何触发的,流程是怎样的。
分析思路:
先静态看模块描述,根据模块描述对功能进行猜测;
对模块功能进行求证,微软的软件一般都有pdb,静态反编译后看下函数名,找下是否有内存扫描相关函数;
动态分析,对相关函数下断点,根据函数调用堆栈进行分析,分析具体的流程及实现。


0x02 分析过程

1. 模块分析
      根据资料已知MsMpEng.exe是Defender反病毒软件主服务进程,分析版本为4.18.2209.7-0,查看该进程加载的模块如下:



根据已有资料及模块描述猜测模块功能:
-MpRtp.dll: 运行时监控,一般通过和驱动通信获取监控信息,触发其他扫描,内存扫描如何触发应该和这个模块相关。
-MpClient.dll/MpSvc.dll: 信息较少,应该是给其他组件提供的接口,可能有内存扫描相关接口和实现。
-mpengine.dll: Defender反病毒核心引擎,特征库匹配、恶意代码判定相关,之前的研究基本都是针对这个模块进行的分析的,还包含本地脱壳、本地沙箱模拟等功能,内存扫描特征码匹配应该在这。
然后开始静态反编译分析这几个模块,与预想的不一致,这几个模块微软都没有提供pdb(后面微软又上传了mpengine.dll的pdb),暂时使用之前有pdb版本文件进行分析,通过内存扫描相关关键字及模块导入表大致罗列下这几个模块关键函数及功能猜测,方便后续通过动态分析验证。
  1. <div><div>MpRtp.dll</div></div><div><div>//通过微文件端口与WdFilter.sys进行通信获取驱动回调监控信息,可能与触发内存扫描相关</div><div>RealtimeProtection::CThreadPoolIoFilterRequest::DoOverlappedOperation</div><div>RealtimeProtection::CFilterCommunicatorBase::CommunicatorMainFunction</div><div>RealtimeProtection::CFilterCommunicatorBase::ParkFilterRequestToFilter</div><div>FilterGetMessage</div></div><div></div>
复制代码



对MpRtp.dll的静态分析主要通过微文件端口通信相关的API展开的,微文件端口是实现驱动层与应用层双向实时通信的一种方式,后续动态调试重点是什么行为触发了内存扫描,具体触发流程。

  1. MpClient.dll
  2. //通过内存扫描关键字可以找到一些内存扫描相关函数
  3. MpFastMemoryScanOpen MpClient::CMpMemoryScan::HandleScanEvents
复制代码


MpClient.dll中存在一些内存扫描相关函数,不过从函数逻辑来看并未发现实现代码,只是一些调用接口和导出函数,MpClient::CMpMemoryScan::HandleScanEvents从函数名称来看是处理内存扫描事件的,该函数中又通过NdrClientCall3函数通过RPC调用到其他模块,可以通过静态分析获取到该RPC接口的UUID c503f532-443a-4c69-8300-ccd1fbdb3839,调用的ProcNum 0x5f。



  1. MpSvc.dll
  2. OnDemandStartScan
  3. MpService::NewScanContext
  4. MpService::CMpSvcScanWorkItem::OnAction(void)
  5. MpService::CMpSvcScanWorkItem::Run(void)
  6. MpService::CGlobalEventsJob::OnAction
  7. MpService::CMpMemScanEngineVfz::vfz_Read
复制代码


静态分析MpSvc.dll时发现很多关于内存扫描相关的函数名,还在导入表中发现ReadProcessMemory函数,ReadProcessMemory功能为读取其他进程内存数据,该函数可能和内存扫描相关。除此之外MpSvc.dll实现了c503f532-443a-4c69-8300-ccd1fbdb3839 服务端接口,发现ProcNum为0x5f的函数为ServerMpRpcMemoryScanQueryNotification,函数表中还包含其他可能与动态扫描相关的函数。



  1. mpengine.dll

  2. CResmgrems::Scan
  3. CEMSContext::EmsScan
  4. CSMSProcess::ScanCompleted
  5. ProcessMemoryScanCache::ProcessMemoryScanCach
  6. eSMSMaps::ShouldSendMemoryScanReport
复制代码


mpengine.dll中存在很多与内存扫描相关函数,同时也导入了ReadProcessMemory,调用ReadProcessMemory的函数很多,从命名来看很多也与内存扫描相关。



2. 动态分析环境准备

动态分析前需要先去除Defender的自保护,详细如下:

ObProcess(PreCall): 进程对象保护回调,原理是通过注册进程对象回调对OpenProcess这类API的打开进程获取进程句柄行为进行过滤,在WdFilter.sys驱动中实现。可以使用Windows-Kernel-Explorer移除掉WdFilter.sys注册的ObProcess(PreCall)回调保护。
PPL(Protected Process Light):在PPL的保护下未经合法签名的程序不能对PPL保护的进程进行任意访问,只有非常受限的权限,可以使用PPLKiller或者mimikatz去除MsMpEng.exe进程的PPL保护。




去除Defender的自保护后即可正常附加调试,不过单机调试有时候会整个系统卡死,猜测是断点时候正好是驱动与应用层通信时候,导致System线程挂起,系统就卡死了,可以使用Windbg双机调试解决这个问题,设置好双机调试环境后使用Windbg附加调试MsMpeng.exe进程。

  1. 0: kd> !process 0 0 MsMpEng.exe
  2. PROCESS ffff8009e37ca080
  3.     SessionId: 0  Cid: 107c    Peb: e79fb62000  ParentCid: 029c
  4.     DirBase: 12dc55000  ObjectTable: ffffcc06b8867700  HandleCount: 749.
  5.     Image: MsMpEng.exe
  6. 0: kd> .process /i /p ffff8009e37ca080
  7. You need to continue execution (press 'g' <enter>) for the context
  8. to be switched. When the debugger breaks in again, you will be in
  9. the new process context.
  10. 0: kd> g
  11. Break instruction exception - code 80000003 (first chance)
  12. nt!DbgBreakPointWithStatus:
  13. fffff805`05400fc0 cc              int     3
  14. 0: kd> .reload /f /user
  15. Loading User Symbols
  16. ........
复制代码
因为需要分析Defender内存扫描逻辑,还需要一个样本来触发内存扫描,这里使用一个经过静态免杀CobaltStrike beacon作为样本,样本文件名为payload.exe,在Defender环境中静态免杀,但是启动后会被Defender拦截,显示 Behavior:Win32/CobaltStrike.E!sms。

3. 内存扫描实现模块定位及内存扫描功能实现分析

通过对静态分析列出的函数下断点反复分析,发现对ReadProcessMemory函数下断点可以获取到一个内存扫描时候的栈回溯,通过对ReadProcessMemory第一个参数检查确认该栈回溯为对payload.exe进行内存扫描的过程。

  1. 1: kd> bu KernelBase!ReadProcessMemory
  2. 1: kd> k
  3. # Child-SP          RetAddr               Call Site
  4. 00 000000e7`a017d988 00007fff`64e7da0f     KERNELBASE!ReadProcessMemory
  5. 01 000000e7`a017d990 00007fff`64e7d613     mpengine!CSMSProcess::InvokeScanner+0xb7
  6. 02 000000e7`a017da00 00007fff`64e7d384     mpengine!CSMSProcess::ScanRange+0xa7
  7. 03 000000e7`a017daa0 00007fff`64e7cb9a     mpengine!CSMSProcess::Scan1Worker+0x244
  8. 04 000000e7`a017db40 00007fff`64cecca7     mpengine!CSMSProcess::Scan+0x45e
  9. 05 000000e7`a017dc30 00007fff`654f19c0     mpengine!CEMSContext::EmsScan+0x34b
  10. 06 000000e7`a017dd00 00007fff`654f0130     mpengine!EmsEnumProcesses+0x140
  11. 07 000000e7`a017ddd0 00007fff`654f0725     mpengine!RunEMS+0x2dc
  12. 08 000000e7`a017df10 00007fff`654f01c5     mpengine!CResmgrems::ScanImpl+0x21d
  13. ...
  14. 16 000000e7`a017f9b0 00007fff`7dcd2260     mpclient!MpGetASRPerRuleExclusions+0x5f043
  15. 17 000000e7`a017fa00 00007fff`7dcc31aa     ntdll!TppWorkpExecuteCallback+0x130
  16. 18 000000e7`a017fa50 00007fff`7da67034     ntdll!TppWorkerThread+0x68a
  17. 19 000000e7`a017fd50 00007fff`7dcc26a1     KERNEL32!BaseThreadInitThunk+0x14
  18. 1a 000000e7`a017fd80 00000000`00000000     ntdll!RtlUserThreadStart+0x21
  19. 1: kd> !handle @rcx
  20. PROCESS ffff8009e37ca080
  21.     SessionId: 0  Cid: 107c    Peb: e79fb62000  ParentCid: 029c
  22.     DirBase: 12dc55000  ObjectTable: ffffcc06b8867700  HandleCount: 967.
  23.     Image: MsMpEng.exe
  24. Handle table at ffffcc06b8867700 with 967 entries in use
  25. 0a14: Object: ffff8009e6914340  GrantedAccess: 00001410 (Protected) Entry: ffffcc06aeaf8850
  26. Object: ffff8009e6914340  Type: (ffff8009dcccaf00) Process
  27.     ObjectHeader: ffff8009e6914310 (new version)
  28.         HandleCount: 10  PointerCount: 294928
  29. 1: kd> !process ffff8009e6914340 0
  30. PROCESS ffff8009e6914340
  31.     SessionId: 1  Cid: 10ec    Peb: f18504000  ParentCid: 1aa8
  32.     DirBase: 45344000  ObjectTable: ffffcc06b1110880  HandleCount: 331.
  33.     Image: payload.exe
复制代码
进一步分析函数mpengine!CSMSProcess::InvokeScanner,在调用ReadProcessMemory读取内存数据后会进入hstr_internal_search_worker函数,经分析该函数就是特征码匹配函数。hstr_internal_search_worker会调用BMMatchEx2匹配读取的内存数据中是否有病毒库中的特征码,BMMatchEx2按照函数名及函数逻辑分析应该是通过实现BM字符串匹配算法来匹配病毒库中的特征码。

  1. # Child-SP          RetAddr               Call Site
  2. 00 000000e7`a017d548 00007fff`64b4ed9b     mpengine!BMMatchEx2
  3. 01 000000e7`a017d550 00007fff`64b4e022     mpengine!hstr_internal_search_worker+0x35b
  4. 02 000000e7`a017d880 00007fff`64eaf6e1     mpengine!hstr_internal_search+0x7e
  5. 03 000000e7`a017d910 00007fff`64eaf64e     mpengine!CSMSScanner::ScanWorker+0x59
  6. 04 000000e7`a017d960 00007fff`64e7dae1     mpengine!CSMSScanner::Scan+0x3e
  7. 05 000000e7`a017d990 00007fff`64e7d613     mpengine!CSMSProcess::InvokeScanner+0x189
  8. 06 000000e7`a017da00 00007fff`64e7d384     mpengine!CSMSProcess::ScanRange+0xa7
  9. 07 000000e7`a017daa0 00007fff`64e7cb9a     mpengine!CSMSProcess::Scan1Worker+0x244
  10. 08 000000e7`a017db40 00007fff`64cecca7     mpengine!CSMSProcess::Scan+0x45e
  11. 09 000000e7`a017dc30 00007fff`654f19c0     mpengine!CEMSContext::EmsScan+0x34b
  12. ...
复制代码


4. 侧信道定位内存扫描特征码

在上一步中我们已经定位到具体的内存扫描逻辑,理论上可以通过分析hstr_internal_search_worker函数逻辑分析出内存扫描匹配的具体逻辑,进而分析出哪段内存特征码匹配成功了,但hstr_internal_search_worker函数逻辑稍微复杂了点。
猜测Defender内存扫描匹配成功和匹配失败ReadProcessMemory读取内存大小应该会不一样,可以根据这种现象判断是否匹配成功,提取特征码,类似爆破密码时可以根据爆破成功和失败返回的内容不同判断是否爆破成功。与预想一致Defender内存匹配真有这个问题,大部分情况下ReadProcessMemory读取的内存大小为0x1000,一旦ReadProcessMemory读取的内存大小是一个不常见的小数字时候就会弹出拦截信息,根据这种现象可以设置Windbg条件断点,断下后打印的栈回溯如下:

  1. 00 000000e7`a00fed80 00007fff`65592d69     mpengine!CEMSTele::Matched+0x318
  2. 01 000000e7`a00fee50 00007fff`653cf858     mpengine!CSMSScanner::EnumHSTR+0x1f9
  3. 02 000000e7`a00feee0 00007fff`653cfbb4     mpengine!CSMSProcess::Report+0x178
  4. 03 000000e7`a00ff010 00007fff`64e7ccfc     mpengine!CSMSProcess::ScanCompleted+0xd0
  5. 04 000000e7`a00ff040 00007fff`65595667     mpengine!CSMSProcess::Scan+0x5c0
  6. 05 000000e7`a00ff130 00007fff`65594a58     mpengine!CSMSContext::ScanProcess+0xc3
  7. ...
复制代码
从CEMSTele::Matched函数命名及栈回溯逻辑分析此时的栈回溯应该是内存扫描完成,然后对检测到的特征码进行上报的过程,此时会在CEMSTele::Matched中通过ReadProcessMemory重新读取目标内存中匹配成功的内存特征码。这样就可以在ReadProcessMemory返回后的第一个指令下断点并打印函数参数即可获取匹配成功的特征码信息。

  1. 1: kd> bp mpengine!CEMSTele::Matched+0x318 ".printf "Matched:\n"; db rdi+1ch L@r15"
  2. 1: kd> g
  3. Matched: 00000284`ea182166  4c 63 c2 4d 03 c0 42 0f-10 04 c0 48 8b c1 f3 0f  Lc.M..B....H....
  4. 00000284`ea182176  7f 01 c3
复制代码


其中rdi+1ch为读取的buffer地址,r15为读取的大小,这样就可以直接打印内存扫描匹配成功的特征码。

5. 曲折的分析内存扫描触发逻辑

现在还剩下内存扫描如何触发的没分析了,由于Defender内存扫描通过线程池异步操作实现并且除mpengine.dll外其他模块只有老版本pdb,导致分析过程比较曲折,不过最后还是从线程池实现逻辑分析出了内存扫描触发逻辑。Defender线程池消费者函数为CommonUtil::CMpSimpleThreadPool::AsyncDequeue,对应还有一个生产者函数CommonUtil::CMpSimpleThreadPool::Submit,可以对这个函数下断查看函数调用栈分析内存触发逻辑,需要注意mpclient.dll与mpengine.dll都使用的这套线程池,需要同时对这两个模块中的CommonUtil::CMpSimpleThreadPool::Submit函数下断点。

  1. //mpclient.dll 无pdb符号文件,需要通过类似bindiff这样的工具找到CommonUtil::CMpSimpleThreadPool::Submit函数在当前版本的偏移
  2. 0: kd> bp mpclient.dll+a7420 ".echo "mpclient::CommonUtil::CMpSimpleThreadPool::Submit";k;g"
  3. 0: kd> bp mpengine!CommonUtil::CMpSimpleThreadPool::Submit ".echo "mpengine!CommonUtil::CMpSimpleThreadPool::Submit";k;g"
复制代码
通过查看内存扫描过程中Windbg打印的函数调用栈,可以整理出内存扫描的触发过程:
-触发源头是WdFilter.sys驱动捕获到模块加载事件后通过微文件端口将信息发送给mprtp.dll,然后mprtp.dll向线程池中提交了一个ModuleLoad事件待处理。
  1. //由于没有pdb,这里调用栈中的函数名是通过bindiff对比出来的
  2. # Child-SP          RetAddr               Call Site
  3. 00 000000e7`9fcff718 00007fff`73db3ec8     mpclient!CommonUtil::CMpSimpleThreadPool::Submit                                          mpclient!MpGetASRPerRuleExclusions+0x5e9d0
  4. 01 000000e7`9fcff720 00007fff`73e1adb0     mprtp!RealtimeProtection::CMpPluginWorkItemBase::PrioritizedDispatchJob_75E833E40         mprtp!MpPluginDeviceControlValidateDataDuplicationRemoteLocationConfiguration+0x1d2b8
  5. 02 000000e7`9fcff750 00007fff`73e0cde2     mprtp!RealtimeProtection::CProcessAgent::HandleModuleLoad_75E89ACF0                       mprtp!MpPluginDeviceControlValidateDataDuplicationRemoteLocationConfiguration+0x841a0
  6. 03 000000e7`9fcff7c0 00007fff`73e2465e     mprtp!RealtimeProtection::CProcessWatcher::HandleAsynchronousRequest_75E88CCD0            mprtp!MpPluginDeviceControlValidateDataDuplicationRemoteLocationConfiguration+0x761d2
  7. 04 000000e7`9fcff810 00000000`00000000     mprtp!RealtimeProtection::CAsynchronousWatcherBase::HandleRequest_75E8A45B0bl             mprtp!MpPluginDeviceControlValidateDataDuplicationRemoteLocationConfiguration+0x8da4e
  8. 05 000000e7`a097f188 00007fff`73e08b3c     mprtp!RealtimeProtection::CFileSystemWatcher::HandleRequest_75E8886C0                     mprtp!MpPluginDeviceControlValidateDataDuplicationRemoteLocationConfiguration+0x71f2c
  9. 06 000000e7`a097f768 00007fff`73e52233     mprtp!RealtimeProtection::CFilterCommunicatorBase::CommunicatorMainFunction_75E8D1884     mprtp!MpPluginDeviceControlValidateDataDuplicationRemoteLocationConfiguration+0xbb623
复制代码
-然后会对加载的Module进行一次文件检测,检测文件是否可信,不可信的模块会被添加到MOAC中。
  1. 00 00000047`a287e338 00007ffa`1e8d2717     mpengine!MOACManager::AddUntrustedToMoac
  2. 01 00000047`a287e340 00007ffa`1e3a49d9     mpengine!CacheMgr::AddUntrustedToMoac+0x37
  3. 02 00000047`a287e370 00007ffa`1e95041d     mpengine!IsFriendlyFile+0x3fd
  4. 03 00000047`a287e4a0 00007ffa`1e6dd5bc     mpengine!VerifyIsFriendlyFile+0xe1
  5. 04 00000047`a287e580 00007ffa`1e724a81     mpengine!ProcessContext::IsFriendlyImageFile+0x13c
  6. 05 00000047`a287e640 00007ffa`1e71dec1     mpengine!SignatureHandler::ReportDetection+0x5f1
  7. 06 00000047`a287ec50 00007ffa`1e725a37     mpengine!SignatureHandler::HandleDetection+0x421
  8. 07 00000047`a287ee30 00007ffa`1e725c43     mpengine!SignatureHandler::TestForDetection+0x2a3
  9. 08 00000047`a287f2a0 00007ffa`1e7261f8     mpengine!SignatureHandler::TestForDetectionWithTokenizedPath+0x1db
  10. 09 00000047`a287f380 00007ffa`1e721185     mpengine!SignatureHandler::TestForModuleLoad+0x7c
  11. 0a 00000047`a287f3f0 00007ffa`1e70dede     mpengine!SignatureHandler::HandleNotification+0xa95
  12. ...
  13. 10 00000047`a287f9d0 00007ffa`1e82b982     mpengine!NotificationItem::OnAction+0x42
  14. 11 00000047`a287fa20 00007ffa`3c132260     mpengine!CommonUtil::CMpSimpleThreadPool::AsyncDequeue+0xde
  15. 12 00000047`a287fa60 00007ffa`3c1231aa     ntdll!TppWorkpExecuteCallback+0x130
  16. 13 00000047`a287fab0 00007ffa`3a277034     ntdll!TppWorkerThread+0x68a
  17. 14 00000047`a287fdb0 00007ffa`3c1226a1     KERNEL32!BaseThreadInitThunk+0x14
  18. 15 00000047`a287fde0 00000000`00000000     ntdll!RtlUserThreadStart+0x21
复制代码
-因为Module非可信,同时还会被提交到一个事件到检测队列QueueDetection。
  1. 00 00000047`a287e468 00007ffa`1e72c191     mpengine!CommonUtil::CMpSimpleThreadPool::Submit
  2. 01 00000047`a287e470 00007ffa`1e6ea00d     mpengine!DetectionQueue::QueueDetection+0x369
  3. 02 00000047`a287e5c0 00007ffa`1e731116     mpengine!DetectionController::QueueDetection+0x4d
  4. 03 00000047`a287e5f0 00007ffa`1e72529d     mpengine!ScanHandlerBase::ReportDetection+0xda
  5. 04 00000047`a287e640 00007ffa`1e71dec1     mpengine!SignatureHandler::ReportDetection+0xe0d
  6. 05 00000047`a287ec50 00007ffa`1e725a37     mpengine!SignatureHandler::HandleDetection+0x421
  7. 06 00000047`a287ee30 00007ffa`1e725c43     mpengine!SignatureHandler::TestForDetection+0x2a3
  8. 07 00000047`a287f2a0 00007ffa`1e7261f8     mpengine!SignatureHandler::TestForDetectionWithTokenizedPath+0x1db
  9. 08 00000047`a287f380 00007ffa`1e721185     mpengine!SignatureHandler::TestForModuleLoad+0x7c
  10. ...
复制代码
-DetectionQueue::OnAction消费检测队列中的事件,然后TriggerEmsScan会提交一个内存扫描任务到线程池。
  1. 00 00000047`a287f118 00007ffa`1e70a05e     mpengine!CommonUtil::CMpSimpleThreadPool::Submit
  2. 01 00000047`a287f120 00007ffa`1e709b8f     mpengine!TriggerScan+0x6a
  3. 02 00000047`a287f170 00007ffa`1e6c6b09     mpengine!TriggerEmsScan+0x23b
  4. 03 00000047`a287f2a0 00007ffa`1e6cb266     mpengine!DoTriggeredActions+0x2e9
  5. 04 00000047`a287f350 00007ffa`1e6cd156     mpengine!PerformDetectionActions+0x2d6
  6. 05 00000047`a287f4d0 00007ffa`1e6cb643     mpengine!DetectionItem::UpdateCharacteristics+0x8c6
  7. 06 00000047`a287f6b0 00007ffa`1e72ba54     mpengine!DetectionItem::Send+0xf7
  8. 07 00000047`a287f820 00007ffa`1e72bd53     mpengine!DetectionQueue::DispatchDetections+0x3f4
  9. 08 00000047`a287f9a0 00007ffa`1e82b982     mpengine!DetectionQueue::OnAction+0xa3
  10. 09 00000047`a287fa20 00007ffa`3c132260     mpengine!CommonUtil::CMpSimpleThreadPool::AsyncDequeue+0xde
  11. 0a 00000047`a287fa60 00007ffa`3c1231aa     ntdll!TppWorkpExecuteCallback+0x130
  12. 0b 00000047`a287fab0 00007ffa`3a277034     ntdll!TppWorkerThread+0x68a
  13. 0c 00000047`a287fdb0 00007ffa`3c1226a1     KERNEL32!BaseThreadInitThunk+0x14
  14. 0d 00000047`a287fde0 00000000`00000000     ntdll!RtlUserThreadStart+0x21
复制代码
-线程池会执行内存扫描的任务,执行内存扫描的栈回溯。
  1. //bp mpengine!CEMSContext::EmsScan+0x34 ".printf "CEMSContext::EmsScan:%mu", rax;g"
  2. CEMSContext::EmsScan:\Device\HarddiskVolume3\payload.exe  
  3. # Child-SP          RetAddr               Call Site
  4. 00 00000047`a337d6b0 00007ffa`1ebc19c0     mpengine!CEMSContext::EmsScan+0x34
  5. 01 00000047`a337d780 00007ffa`1ebc0130     mpengine!EmsEnumProcesses+0x140
  6. 02 00000047`a337d850 00007ffa`1ebc0725     mpengine!RunEMS+0x2dc
  7. 03 00000047`a337d990 00007ffa`1ebc01c5     mpengine!CResmgrems::ScanImpl+0x21d
  8. 04 00000047`a337da50 00007ffa`1e366a1f     mpengine!CResmgrems::Scan+0x15
  9. 05 00000047`a337db80 00007ffa`1e791082     mpengine!ResmgrProcessResource+0x1c7
  10. 06 00000047`a337ddb0 00007ffa`1e77656d     mpengine!ResScan+0xa36
  11. 07 00000047`a337e1f0 00007ffa`1e7797d8     mpengine!ScanOpenWithContext+0x1911
  12. 08 00000047`a337eaf0 00007ffa`1e759248     mpengine!UberScanOpen+0xa64
  13. 09 00000047`a337ec10 00007ffa`1e519c13     mpengine!ksignal+0x6a8
  14. 0a 00000047`a337ed90 00007ffa`1e518fcb     mpengine!DispatchSignalHelper+0x6f
  15. 0b 00000047`a337edf0 00007ffa`2a8070f3     mpengine!DispatchSignalOnHandle+0x9b
  16. 0c 00000047`a337f260 00000000`00000000     mpsvc!ServiceCrtMain+0x1f6e3
复制代码
因为执行内存扫描流程太长且均为异步任务,因此中间流程未具体分析,只是分析了本次扫描是由WdFilter.sys驱动监控到模块加载触发的,那如何验证分析结果是否正确呢?
这里可以采用排除法验证结果是否正确,流程如下:

-使用Windows-Kernel-Explorer移除WdFilter.sys除模块加载回调以外的其他监控回调(进程/线程/注册表),检查是否触发最终的内存扫描。这里测试结果是能触发内存扫描

-只移除WdFilter.sys模块加载回调,检查是否触发最终内存扫描。这里测试结果是不能。

使用排除法验证了本次分析结果的正确性,模块加载事件会触发内存扫描。在分析过程中同时也发现Defender中也包含其他事件的处理逻辑,mpengine!SignatureHandler::HandleNotification函数包含了不同事件的重载实现,不同的事件如下:

-ArNotification

-BootChangeNotification

-DesktopNotification

-EtwNotification

-FileNotification

-InternalNotification

-NetworkNotification2

-ProcessNotification

-RegistryNotification

-RemoteThreadCreateNotification

-VolumeMountNotification


限于时间和篇幅这里未对其他事件进行分析,不排除上面的其他事件也可能会导致触发内存扫描逻辑。

0x03 总结

本文对Defender的内存扫描功能进行了一个简单分析,最后总结回答下分析目标中提出的三个问题:

-确定内存扫描功能具体由哪个模块实现以及实现方式
内存扫描功能具体实现在mpengine.dll中实现,实现方式是通过ReadProcessMemory读取目标进程内存数据,然后通过BM字符串匹配算法对目标内存数据与特征码数据进行匹配,与文件静态检测类似,只是数据源不同。

-定位内存中具体哪段内存数据是恶意代码特征码
可以通过侧信道分析方法,利用ReadProcessMemory读取数据大小不同定位到特征码,对mpengine!CEMSTele::Matched+0x318下断点可直接打印当次检测出的恶意内存特征码。

-内存扫描如何触发的,流程是怎样的
本次分析的样本是模块加载事件触发的内存扫描,不排除其他事件也会触发内存扫描。流程比较复杂,中间会经过不同的异步检测过程最终才到内存扫描逻辑。


0x04  参考链接

https://labs.withsecure.com/publ ... er-runtime-scanning
https://learn.microsoft.com/zh-c ... ce/fileless-threats
https://github.com/AxtMueller/Windows-Kernel-Explorer

本帖子中包含更多资源

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

x

评分

参与人数 3人气 +9 收起 理由
a27573 + 3 版区有你更精彩: )
Jerry.Lin + 3 版区有你更精彩: )
fzp070 + 3 版区有你更精彩: )

查看全部评分

AEht
发表于 2023-1-13 00:07:39 | 显示全部楼层
牛的分析版区有你更精彩!
喀反
发表于 2023-1-13 15:48:15 | 显示全部楼层
看不懂
您需要登录后才可以回帖 登录 | 快速注册

本版积分规则

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

Copyright © KaFan  KaFan.cn All Rights Reserved.

Powered by Discuz! X3.4( 沪ICP备2020031077号-2 ) GMT+8, 2024-12-22 00:45 , Processed in 0.111861 second(s), 19 queries .

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

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