翻译: 看雪翻译小组 Nxe
校对: 看雪翻译小组 sudozhange
这篇博客所涉及的内容基于我在 Objective By the Sea 会议上的演讲"基于虚拟机管理程序对 macOS 恶意程序的分析"(Hypervisor-Based Analysis of macOS Malware) 你可以在这里获取演讲的幻灯片。
相比于 Windows,macOS 平台的恶意程序只占很小一部分,但是这种威胁在不断增长。Malwarebytes 的报告显示针对于 Mac 的恶意程序的总量在2018年第四季度上升了62%,而且新的攻击手段不断出现。尽管对于普通消费者的威胁在下降,但是对基础设施和企业的威胁却在上升。
相比于在 Windows 平台与恶意程序奋战了几十年的同行,macOS 平台的分析人员能够使用的分析与检测 macOS 恶意程序的工具就没有那么多的选择了。尽管存在工具用来监测 macOS 进程的创建与持续,文件创建,系统调用等等,但是与 Windows 平台相比还有着巨大的差距:
此外,一些 macOS 平台的恶意程序动态分析工具不能满足日益增长的扩展性与性能的要求。面对着这些限制,即便是一些科技巨头也不得不依赖一些土方法来内部分析和探测 macOS 的恶意程序。
图 1:旧限制,新需求
VMRay 正在弥补不足。随着 VMRay Analyzer 3.0 版和 3.1 版中最近的更新,我们在我们成熟的框架上增加了 macOS 动态分析和检测的功能。利用深厚的专业技能和多年保护Windows环境的经验,3.1 版解决了 macOS 的独特挑战,使得研究人员和DFIR团队能够大规模地动态分析和检测恶意软件。
主要特点包括:
VMRay 沙盒是我们 Now, Near Deep 架构 (图 2)的基础,提交的可疑 macOS 恶意程序文件会经过多层次的检测:
图 2:VMRay 的 Now, Near, Deep 架构
沙盒提供了一个 允许执行macOS 恶意程序的隔离环境,该恶意程序的行为被监视并获得严重性评分,使得安全生态环境中其他的安全工具可以基于可疑行为做出阻止/允许的决定。使用了无代理,基于虚拟机管理程序(Hypervisor)方法的沙盒在整个分析过程中不会被检测到,这是防止恶意程序逃避检测的特性。
如下图3到图6所示,VMRay 的自动化,分析人员友好的报告工具提供了恶意程序行为的即时可见性,并能轻松挖掘以获取更深的理解。以下的信息摘自 ColdRoot 的实际分析,ColdRoot 是针对 macOS 的远程访问木马。
图3中的进程图显示了运行的ColdRoot创建文件,运行脚本,提升权限等命令的高级视图。你可以看到,恶意程序把自己伪装成一个 Apple 服务以获得持久化,并在之后启用键盘记录和远程桌面访问。
图 3:进程图提供了恶意程序行为的高级视图
深入挖掘,VMRay Analyzer(图4)生成的函数日志揭示了哪个 API 调用对应着进程图中描述的某些行为。利用Accessibility API,AuthorizationExecuteWithPrivileges()
被用来启用增强的系统访问和安装一个 root 权限的持久化守护进程。
// enable Accessibility API [0050.862] AuthorizationExecuteWithPrivileges (authorization=0x539eb0, pathToTool="/usr/bin/touch", options=0x0, arguments=([0]="/private/var/db/.AccessibilityAPIEnabled"), communicationsPipe=0x0) returned 0 // run script which will add ColdRoot to the Accessibility DB [0051.460] AuthorizationExecuteWithPrivileges (authorization=0x539eb0, pathToTool="/bin/sh", options=0x0, arguments=([0]="/private/var/tmp/runme.sh"), communicationsPipe=0x0) returned 0 // copy LaunchDaemon definition [0052.844] AuthorizationExecuteWithPrivileges (authorization=0x539eb0, pathToTool="/bin/cp", options=0x0, arguments=([0]="/Users/jdoe/Downloads/com.apple.audio.driver2.app/Contents/MacOS/com.apple.audio.driver.plist", [1]="/Library/LaunchDaemons"), communicationsPipe=0x0) returned 0 // load and start LaunchDaemon [0053.218] AuthorizationExecuteWithPrivileges (authorization=0x539eb0, pathToTool="/bin/launchctl", options=0x0, arguments=([0]="load", [1]="/Library/LaunchDaemons/com.apple.audio.driver.plist"), communicationsPipe=0x0) returned 0 ... [0053.683] AuthorizationExecuteWithPrivileges (authorization=0x539eb0, pathToTool="/bin/launchctl", options=0x0, arguments=([0]="start", [1]="/Library/LaunchDaemons/com.apple.audio.driver.plist"), communicationsPipe=0x0) returned 0
图 4:函数日志为视图添加细节(添加了注释)
下面两个分析日志显示了 ColdRoot 产生的函数调用:通过安装 SLEventTap(图5)来激活键盘记录以及利用SLDisplayCreateImage()(图6)启动远程桌面访问。
// install event tap (SL == SkyLight == CoreGraphics) [0034.621] SLEventTapCreate (tap=0x1, place=0x0, options=0x0, eventsOfInterest=0x1c00, callback=0x6a3d0, userInfo=0x0) returned 0x509d50 [0034.805] CFMachPortCreateRunLoopSource (allocator=0x0, port=0x509d50, order=0) returned 0x50ff20 [0034.805] CFRunLoopGetCurrent () returned 0x5123c0 [0034.806] CFRunLoopAddSource (rl=0x5123c0, source=0x50ff20, mode="kCFRunLoopCommonModes") [0034.807] SLEventTapEnable (tap=0x509d50, enable=1) [0034.807] CFRunLoopRun () // on keypress: get keycode [0088.346] SLEventGetIntegerValueField (event=0x53a580, field=0x9) returned 36 [0088.346] SLEventKeyboardGetUnicodeString (event=0x53a580, maxStringLength=0xa, actualStringLength=0xb0579d48, unicodeString=0xb0579d4e) // write to log [0088.349] open (path="/private/var/tmp/adobe_logs.log", oflag=9) returned 3 [0088.350] __ioctl (fildes=3, request=0x402c7413) returned -1 [0088.350] bcopy (src=0x31b704c, dst=0xb0579bc0, len=0xa) [0088.350] __write_nocancel (fildes=3, buf=0xb0579bc0*, nbyte=0xa) returned 10 [0088.350] __close_nocancel (fildes=3) returned 0
图 5:键盘记录所使用的函数调用(添加了注释)
如果是远程访问,如下图所示,时间戳显示了 ColdRoot 首先开启了一个连接 C2 服务器的次级 TCP 连接,然后每隔半秒截图并利用新创建的套接字发送给 C2 服务器。要注意的是一个相当大的缓冲区("length=0x3beec")被传给了第二个 send() 调用,表明它可能是一个图像文件,经过查看发送的数据(如下所示)证实了猜测。
// take screenshot using SkyLight (aka CoreGraphics) [0038.037] SLMainDisplayID () returned 0x5b81c5c0 [0038.042] SLDisplayCreateImage (displayID=0x5b81c5c0) returned 0x53c800 [0038.155] CGImageGetHeight (image=0x53c800) returned 0x360 [0038.155] CGImageGetWidth (image=0x53c800) returned 0x480 // send to C2 [0037.851] socket (domain=2, type=1, protocol=0) returned 4 [0037.857] connect (sockfd=4, addr=0xb1189df0*(sin_len=0x10, sin_family=0x2, sin_port=0x3419, sin_addr="<redacted>"), addrlen=0x10) returned 0 <…> [0040.638] send (socket=4, buffer=0x320f028*, length=0x4, flags=0) returned 4 <…> [0040.640] send (socket=4, buffer=0x35a2d18*, length=0x3beec, flags=0) returned 245484
00000000 ff d8 ff e0 00 10 4a 46 49 46 00 01 01 00 00 01 |......JFIF......| 00000010 00 01 00 00 ff db 00 43 00 01 01 01 01 01 01 01 |.......C........| 00000020 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 |................|
图 6:远程桌面访问所使用的函数调用(添加了注释)
恶意程序动态分析在许多方面都具有挑战性,而 VMRay 是精通这些挑战的少数提供商之一。 VMRay Analyzer的 macOS 特定功能的基础是三个独立于操作系统的核心特性:
完全可见性的函数调用
利用系统 API 提供的不同级别的抽象,恶意程序可以和系统在任何级别交互(见图7)。动态分析沙盒需要监控 全部 潜在的不良行为来源,从直接的系统调用到高级别的 API 调用。否则,它就会漏检可能会造成巨大损害的恶意程序。
图 7:在 OS 的所有级别检测恶意程序的行为
VMRay 在提供完全可见性方面与其他大多数动态分析平台不同,函数调用会在最高抽象级别自动截获,通过保留高级语义,VMRay 简化了行为分析。此外,最小化被拦截的调用数量也可提高效率。
隔离和透明
为了使动态分析更加安全,恶意程序样本需要在隔离环境中运行,从而使得监视和执行潜在的恶意行为不会影响生产系统或破坏沙箱本身。此外,分析过程应该是恶意软件无法检测到的,否则其可能会隐藏其行为以阻止检查和深入分析。
为了实现这两个目标并仍然保持完全可见性,分析过程需要在比分析中的任何恶意程序样本更高的权限级别上运行。 VMRay 通过将沙箱放置在虚拟机管理程序层中来实现此目的(见图8)。这意味着不需要对操作系统进行代理或其他必要的修改,并且恶意软件无法检测到它正在被分析,即使是从内核中也是如此。
图 8:分析系统运行在虚拟机管理程序层
高效率与自动化
通过使用单个沙箱取代多个不同的工具来实现高效率,该沙箱可在更短的时间内提供更全面的结果。由于可以使用 REST API 控制VMRay Analyzer,所以可以轻松地将其集成到现有环境中以自动化工作流程。事实上,你不需要专家来分析绝大多数文件 - 它们只是被扔进沙盒中,而沙盒会返回判定 - 这是 macOS 分析和检测的重大改进。
在开发和升级 VMRay Analyzer 时,我们的团队为实现隔离和透明做出了重大贡献。VMRay 联合创始人 Carsten Willems 和 Ralf Hund 开发了一种基于二维分页的突破性方法,允许 VMRay 在函数调用级别拦截恶意软件的执行,同时能保持效率,无需修改操作系统以及不会暴露沙箱的存在。
此外,通过使用虚拟机自省技术(VMI),VMRay 可以完全从外部监控目标机器的每个级别的活动(见图9)。VMRay 作为主机操作系统顶层的虚拟机管理程序的一部分运行,而主机操作系统又在裸金属机器上运行,每个组件都是独立的,因此VMRay可以在不同的虚拟机管理程序和硬件组合上运行。
图 9:VMI 使用的过渡式监视
VMRay 的监控方法可以应用于所有操作系统和所有架构。但是,每种操作系统都有一些独特的功能,需要特殊处理才能捕获程序执行的各个方面。在 VMRay 成功解决的 macOS 的挑战中,使用了 XPC 和低级 Mach 消息来监视 Objective-C 调用和进程间通信(IPC)。
如图10所示,我们实现了对 Objective-C 编程语言的支持,因此函数日志与源代码非常相似,使得分析人员更容易阅读。
代码
NSLog(@"Hello, World!"); NSProcessInfo *processInfo = [NSProcessInfo processInfo]; NSLog(@"Process ID is: %d", [processInfo processIdentifier]); NSString *username = [processInfo userName]; NSFileManager *filemgr = [NSFileManager defaultManager]; NSString *filename = [[filemgr currentDirectoryPath] stringByAppendingPathComponent:@"user.txt"]; [username writeToFile:filename atomically:YES encoding:NSStringEncodingConversionAllowLossy error:nil]; NSLog(@"Content written to path: %@\n", filename);
分析日志
[0045.565] NSLog (format="Hello, World!") [0045.706] +[NSProcessInfo processInfo] returned 0x7f9a3740d080 [0045.706] -[NSProcessInfo<0x7f9a3740d080> processIdentifier] returned 488 [0045.706] NSLog (format="Process ID is: %d") [0045.706] -[NSProcessInfo<0x7f9a3740d080> userName] returned="xsbgsz” [0045.824] +[NSFileManager defaultManager] returned 0x7f9a37402850 [0045.824] -[NSFileManager<0x7f9a37402850> currentDirectoryPath] returned="/Users/xsbgsz" [0045.916] -[NSString<0x7f9a3740d150> stringByAppendingPathComponent:"user.txt"] returned="/Users/xsbgsz/user.txt” [0045.916] -[NSString<0x7a736762737865> writeToFile:"/Users/xsbgsz/user.txt" atomically:1 encoding:0x1 error:0x0] returned 1 [0045.923] NSLog (format="Content written to path: %@\n")
图 10:函数日志简化了分析人员的工作
如下面的图11所示,XPC 为进程定义了一种强大的方式用来交换数据,这种方式在操作系统中大量用于各种任务。但是,XPC 也被恶意软件使用,例如,在当前环境之外建立持久化或生成进程。VMRay 的独特之处在于它拦截并监视每个低级别消息,从而检测所有恶意行为。相比之下,执行不完整监控工作的沙箱将总是错过关键行为。
图 11:监控IPC消息以捕获逃避的恶意软件
在 VMRay Analyzer v3.0 中,我们引入了对 macOS 恶意程序的综合分析,使安全团队能够更好地保护各式各样的 IT 操作环境。随着3.1版最近增加的严重性分数和对 JAVA 文件的支持,VMRay 现在为 macOS 提供了和 Windows 相同的开箱即用功能。
这也是头一次安全团队能够受益于对 macOS 恶意软件行为的完全可见性,以及抵御逃避保护的 macOS 恶意软件攻击的手段。此外,高效率和自动化功能使安全团队能够处理更大的分析量,加快检测速度并提高安全人员和基础设施的生产力与效率。