躲避内存查杀 - AceLdr 技术解析

admin 2023年3月8日09:18:29评论279 views字数 7759阅读25分51秒阅读模式

0. TL; DR

本文介绍常见的内存查杀工具的技术原理,分析 UDRL AceLdr[1] 躲避内存查杀的几种技术实现。

1. 内存查杀工具

以下内存查杀工具是从 AceLdr 的 README 取的,基本囊括了大部分的内存扫描工具。

1.1 Hunt-Sleeping-Beacons

Hunt-Sleeping-Beacons[2] 首先使用 NtQuerySystemInformation 枚举所有进程的所有线程,找出存在 SYSTEM_THREAD_INFORMATION::WaitReason == DelayExecution 线程的进程,因为 Sleep 的线程处于该状态。(绕过该检测可以使用 WaitForSingleObject 类似函数,等待该函数返回的线程处于 UserRequest 状态)。该库为了检测 AceLdr 使用 WaitForSingleObject 的延时,加入了新检测方法:检测由 APC 发起的 WaitForSingleObject 调用。

对上一步筛选出来的进程做以下三个检测:

一、检测函数调用栈上的模块是否有 Module Stomping 或不存在于磁盘上,源码在 checkCallstack[3]。通过 StackWalk64 枚举模块,检测该模块是否能被获取到模块信息,.text 段是否被修改)。(忽略 .NET 程序以上两种异常,忽略 NTDLL 和 KERNELBASE 的 hooks)

二、检测线程 KernelTime 和 UserTime 的比值,源码在 checkLandDiff[4]。这个检测我不太懂,不作评价,作者的解释为:

Since a beacon spends more time waiting for commands than actually executing code, it can be fingerprinted by comparing the fields KernelTime and UserTime of SYSTEM_THREAD_INFORMATION. Initially I thought that the time sleeping would count as time spent in Kernelmode, but it turned out the other way. I am not sure why :'P Additionally, both fields increase only after the operator executed some commands with the beacon. Also here, I am not sure why :'P

三、检测 KERNEL32 上的 inline hooks,源码在 checkInlineHooks[5]。目的是检测 hook KERNEL32!Sleep 的情况。

1.2 BeaconHunter

BeaconHunter[6] 和上一个类似,首先筛选存在 DelayExecution 状态线程的进程,然后通过 ETW 提供的以下行为日志进行分析,计算出可疑分值。

HTTP/HTTPS callbacksDNS queriesFile system (cd,ls,upload,rm)Process termination (kill)Shell commands (run,execute)

1.3 BeaconEye

BeaconEye[7] 大家应该很熟悉,通过读取内存数据,通过 yara 检测 Beacon的特征。

1.4 patriot

patriot[8] 检测以下特征:

一、检测线程 eip 指向 VM Protect 函数,源码见 FindSuspiciousContext[9]。该检测技术是针对 Ekko[10] 的一种很巧妙的延时函数混淆技巧。该技术来自 nighthawk,借助 Timer 线程执行一系列存储于 APC 队列的 ROP 来实现混淆的延时功能。技术细节见 NightHawk’s Attempt At Obfuscate and Sleep[11]。(检测使用的手法有点太不清真了,以8字节步长暴力搜索所有的 commit 内存)

二、检测内存中的 PE / DOS 头来检测 ProcessHollowing。

三、检测 elevated 进程中的可疑内存块,源码见 EnumerateMemory[12]。检测非 Image 且可执行且已 commit 的内存块。

四、检测 stomping / overwriting 导致的模块内容修改。源码见 ValidateIntegrity[13]

五、检测 PE 异常,如 RWX 节,PE 头或节越界。源码见 ParseHeader[14]

1.5 moneta

moneta[15] 是一个非常不错的内存扫描工具,技术原理可学习作者的文章 Masking Malicious Memory Artifacts – Part II: Blending in with False Positives[16]

moneta 的检测分以下步骤:

一、扫描动态或未知代码:

1.可执行的非 Image 内存。2.映射的 Image 中被修改的代码段。3.PEB 的 Image Base 或 线程起始地址不在 Image 的内存范围内。4.未签名 Image 中未被修改的代码(this is a soft indicator for hunting not a malware IOC)。

二、映射到内存的 PE Image 本身的可疑特征:

1.PE 节在内存中和磁盘上的保护属性不同。如磁盘上为 R,内存中为 RX。2.映射到内存中的 Image 的 PE 头被更改。3.映射的 Image 无法查询到 FILE_OBJECT,代表无法找到对应的磁盘文件。

三、进程自身的异常:

1.内存中有一个映射的 Image ,其在 PEB 中没有对应的 modules entry。2.内存中的 Image,其在 PEB entry 中记录的 name 或 path 与 FILE_OBJECT 对应的不同。

1.6 pe-sieve

pe-sieve[17] 的扫描技术非常全面,能够扫描 replaced/injected PEs, shellcodes, hooks, and other in-memory patches. Detects inline hooks, Process Hollowing, Process Doppelgänging, Reflective DLL Injection, etc.

pe-sieve 代码量较大,具体实现没有细看,简单列举检测类别:

一、scanModules[18]

1.检查映射模块的名称与磁盘名称是否相同。2.模块在磁盘上不存在。3.扫描 Hollowing,检测模块是否存在于 PEB entry 中,文件头是否被修改。4.检测 inline hooks。

二、scanModuleIATs[19],检查模块的 IAT hooks。

三、scanThreads[20],检查线程堆栈、Context 等,源码见 thread_scanner[21]

(该项目的作者我关注很久了,其开源了很多注入、反射加载一类的对抗技术,比如 Process Ghosting、Process Doppelgänging、pe_to_shellcode 等,还有防御类的如 hollows_hunter。所以 pe-sieve 是一个真正懂攻防的人做的左右互搏的东西 : )

1.7 MalMemDetect

MalMemDetect[22] 编译为 DLL 并注入进程进行检测。

它一方面检测 Hollowing,另一方面 hook RtlAllocateHeapNtWaitForSingleObjectInternetConnect 等函数,然后回溯线程调用栈寻找可疑内存。源码见 HookedInternetConnectW[23] & DetectHollowingAndHooks[24]

2. AceLdr

先看一下 AceLdr 的 features

Dynamic Memory Encryption

Creates a new heap for any allocations from Beacon and encrypts entries before sleep.

Code Obfuscation and Encryption

Changes the memory containing CS executable code to non-executable and encrypts it (FOLIAGE).

Return Address Spoofing at Execution

Certain WinAPI calls are executed with a spoofed return address (InternetConnectA, NtWaitForSingleObject, RtlAllocateHeap).

Sleep Without Sleep

Delayed execution using WaitForSingleObjectEx.

RC4 Encryption

All encryption performed with SystemFunction032.

分析它源码中的躲避内存扫描技术只需要分析几个 hook 函数就够了。

2.1 Sleep_Hook

Sleep_Hook[25] 采用了 FOLIAGE[26] 的技术,与上文讲到的 HightHawk 实现的延时混淆技术类似。

其核心是通过向单独创建的 Wait Thread 的 APC 队列插入一系列 Thread Context 组合的 ROP,依次执行 VM protect、堆栈加密( advapi32!SystemFunction032) 、延时(WaitForSingleObject)和这些步骤的逆操作。然后在主线程里使用 NtSignalAndWaitForSingleObject 触发 Wait Thread 链并等待其退出。

2.2 Heap_Hook

Heap_Hook 通过 Hook GetProcessHeap 来使 Beacon 获取到 AceLdr 初始化创建的堆,以此来使 Sleep 时能加密整个 Beacon 堆数据。


BeaconHeap = Api.ntdll.RtlCreateHeap( HEAP_GROWABLE, NULL, 0, 0, NULL, NULL );fillStub( MemoryBuffer, BeaconHeap, Reg.Full );
...
SECTION( D ) HANDLE GetProcessHeap_Hook(){ return ( ( PSTUB )OFFSET( Stub ) )->Heap;};


2.3 Spoof

Spoof[27]RtlAllocateHeapHeapAllocInternetConnectANtWaitForSingleObject 做 hook,混淆这些函数的调用堆栈。

混淆调用堆栈的原理见 x64 return address spoofing[28]

3. AceLdr 的实际测试

通读全文的读者应该心里对这些内存检测和绕过技术有了一定了解,其实 AceLdr 的内存绕过技术不够全面,所以我有一些怀疑它是否能绕过这些检测工具。例如针对可执行的私有内存检测,这是 shellcode 常见特征,AceLdr 有这样一段代码明显就过不了检测


Status = Api.ntdll.NtAllocateVirtualMemory( ( HANDLE )-1, &MemoryBuffer, 0, &Reg.Full, MEM_COMMIT, PAGE_READWRITE );if( Status == STATUS_SUCCESS ){    ...    Status = Api.ntdll.NtProtectVirtualMemory( ( HANDLE )-1, &MemoryBuffer, &Reg.Exec, PAGE_EXECUTE_READ, &OldProtection );    ...}


拿 pe-sieve 和 moneta 测试了一下,都是可以检出的:


C:Usersx>\MacHomeDownloadsMoneta64.exe -m ioc -p 9272   _____                        __  /        ____   ____   _____/  |______ /   /   /  _  /    _/ __    ____  /    Y    (  <_> )   |    ___/|  |  / __ _____|__  /____/|___|  /___  >__| (____  /        /            /     /          /
Moneta v1.0 | Forrest Orr | 2020

beacon.exe : 9272 : x64 : C:Usersxbeacon.exe 0x0000000000100000:0x00001000 | Private 0x0000000000100000:0x00001000 | RX | 0x00000000 | Abnormal private executable memory...

C:Usersx>\MacHomeDownloadspe-sieve64.exe /shellc /pid 9272 /quiet /jlvl 2---PID: 9272---SUMMARY:
Total scanned: 53Skipped: 0-Hooked: 3Replaced: 0Hdrs Modified: 52IAT Hooks: 0Implanted: 1Implanted PE: 0Implanted shc: 1Unreachable files: 0Other: 0-Total suspicious: 56---


(上面的一些误报是因为 ARM Windows 的 xtajit64。)

虽然如此,但 AceLdr 依然是一个优秀的躲避内存扫描 UDRL。通过学习本文介绍的内存检测和躲避技术,可以针对性的集成到武器库中。

References

[1] AceLdr: https://github.com/kyleavery/AceLdr
[2] Hunt-Sleeping-Beacons: https://github.com/thefLink/Hunt-Sleeping-Beacons
[3] checkCallstack: https://github.com/thefLink/Hunt-Sleeping-Beacons/blob/main/Hunt-Sleeping-Beacons.c#L58
[4] checkLandDiff: https://github.com/thefLink/Hunt-Sleeping-Beacons/blob/main/Hunt-Sleeping-Beacons.c#L305
[5] checkInlineHooks: https://github.com/thefLink/Hunt-Sleeping-Beacons/blob/main/Hunt-Sleeping-Beacons.c#L396
[6] BeaconHunter: https://github.com/3lp4tr0n/BeaconHunter
[7] BeaconEye: https://github.com/CCob/BeaconEye
[8] patriot: https://github.com/joe-desimone/patriot
[9] FindSuspiciousContext: https://github.com/joe-desimone/patriot/blob/main/patriot.cpp#L54
[10] Ekko: https://github.com/Cracked5pider/Ekko
[11] NightHawk’s Attempt At Obfuscate and Sleep: https://suspicious.actor/2022/05/05/mdsec-nighthawk-study.html
[12] EnumerateMemory: https://github.com/joe-desimone/patriot/blob/main/patriot.cpp#L157
[13] ValidateIntegrity: https://github.com/joe-desimone/patriot/blob/main/pefile.cpp#L231
[14] ParseHeader: https://github.com/joe-desimone/patriot/blob/main/pefile.cpp#L36
[15] moneta: https://github.com/forrest-orr/moneta
[16] Masking Malicious Memory Artifacts – Part II: Blending in with False Positives: https://www.forrest-orr.net/post/masking-malicious-memory-artifacts-part-ii-insights-from-moneta
[17] pe-sieve: https://github.com/hasherezade/pe-sieve
[18] scanModules: https://github.com/hasherezade/pe-sieve/blob/master/scanners/scanner.cpp#L314
[19] scanModuleIATs: https://github.com/hasherezade/pe-sieve/blob/master/scanners/scanner.cpp#L402
[20] scanThreads: https://github.com/hasherezade/pe-sieve/blob/master/scanners/scanner.cpp#L449
[21] thread_scanner: https://github.com/hasherezade/pe-sieve/blob/master/scanners/thread_scanner.cpp
[22] MalMemDetect: https://github.com/waldo-irc/MalMemDetect/
[23] HookedInternetConnectW: https://github.com/waldo-irc/MalMemDetect/blob/main/MalMemDetect/Source.cpp#L204
[24] DetectHollowingAndHooks: https://github.com/waldo-irc/MalMemDetect/blob/main/MalMemDetect/Hollow.h#L2
[25] Sleep_Hook: https://github.com/kyleavery/AceLdr/blob/main/src/hooks/delay.c#L468
[26] FOLIAGE: https://github.com/SecIdiot/FOLIAGE
[27] Spoof: https://github.com/kyleavery/AceLdr/blob/main/src/hooks/spoof.c
[28] x64 return address spoofing: https://www.unknowncheats.me/forum/anti-cheat-bypass/268039-x64-return-address-spoofing-source-explanation.html


原文始发于微信公众号(0x4d5a):躲避内存查杀 - AceLdr 技术解析

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2023年3月8日09:18:29
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   躲避内存查杀 - AceLdr 技术解析http://cn-sec.com/archives/1247119.html

发表评论

匿名网友 填写信息