背景
我最近感兴趣的一个方向是macOS的持久化(persistence)。具体地说,我一直在研究底层用户通过修改文件可以影响到用户交互的方法。常用的一种交互方法是Dock
。
经过研究,我注意到一个控制苹果Dock可见表示的属性表文件(Plist)。这里没有什么突破性的发现,因为最终用户通过图形用户界面(GUI)经常修改这个plist
。在检查了plist
中的值之后,我想知道是否可以更改这些值,将一个有效的应用程序替换为一个运行恶意代码的应用程序。
这项研究的结果保存在PersistentJXA项目
的DockPersist.js
文件中。它会实现用我们的恶意应用程序替换Safari或Chrome。我关注于Safari和Chrome是因为它们很有可能出现在用户的Dock中。但是,请注意,这个攻击适用于任何应用程序。一旦终端用户点击Safari或Chrome图标,它就会运行我们的恶意应用程序。这个持久性方法类似于Windows上的Link (. Lnk)文件,因为Dock图标也属于应用程序的快捷方式的一种。
这个持久化方法需要将我们的恶意应用程序上传到目标程序中。我更喜欢在Mythic
代理中使用upload函数将应用程序保存在目标上。
修改plist
后,可以立即重新加载Dock。但是这会给用户带来一次简短的屏幕闪烁。或者您可以等到重新启动时,假的恶意应用程序才出现在Dock中,因为修改过后的plist
文件在重新启动后仍然存在。
使用方法
设置
这种持久化方法需要将恶意应用程序上传到目标,有许多种方法可以绕过Gatekeeper
的保护,允许我们将恶意应用程序上传到目标程序中。您可以:
1.压缩应用程序包,在一个Mythic
代理(Apfell或Poseidon)中使用upload
命令,然后解压缩到目的地
2.压缩应用程序包,使用curl
下载压缩程序包,然后解压缩到目的地
3.压缩应用程序包,使用base64编码加密,再base64解码保存到目标上,然后解压缩到目的地
我在Automator中创建了一个PoC应用程序。它试图不产生任何提示的打开Safari,然后它运行我们的恶意有效载荷。
为了不引起终端用户的注意,我用Safari罗盘图标替换了默认的自动图标。当然,可以利用Xcode
创建更复杂的应用程序。
接下来,我压缩应用程序包并将其上传。在解压缩到/Users/Shared/
之后,我们可以在满足先决条件的情况下重点调用持久化方法。
注意:由于plist
的二进制格式,自动实现要求伪应用程序命名为Google Chrome
或“Safari”,并位于/Users/Shared/
。可以修改Safari64
和Chrome64
变量来改变这个位置。
调用的持久性
将脚本导入Apfell
代理。
调用DockPersist
函数。该函数接受三个参数:应用程序名称(Safari或Google Chrome)、Bundle ID和立即重新加载Dock的配置选项。
注意:Bundle ID在Info.plist
中。具体位置在/usr/libexec/PlistBuddy -c 'Print CFBundleIdentifier' ~/FakeApp/Safari.app/Contents/Info.plist
检测
Crescendo是一个快速捕捉单个主机上事件的好工具,它是macOS的实时事件查看器。Crescendo的一个优秀特性是它利用了苹果的端点安全框架(ESF)。ESF是系统扩展框架的一部分,它是一个API,会监视系统事件以发现潜在的恶意活动。拿那些来自Windows端的工具来说,它是一个针对macOS的Windows有限事件跟踪器(ETW)。
使用Crescendo,我们可以很容易地查看我们创建的,持久化的文件和进程。
以下ESF事件会映射到Crescendo中:
ES_EVENT_TYPE_AUTH_EXEC = process::exec
ES_EVENT_TYPE_NOTIFY_EXIT = process::exit
ES_EVENT_TYPE_NOTIFY_CREATE = file::create
ES_EVENT_TYPE_NOTIFY_KEXTLOAD = process:kext::load
ES_EVENT_TYPE_NOTIFY_MOUNT = file::mount
ES_EVENT_TYPE_NOTIFY_UNLINK = file::unlink
ES_EVENT_TYPE_NOTIFY_RENAME = file::rename
ES_EVENT_TYPE_NOTIFY_UIPC_CONNECT = network::ipcconnect
ES_EVENT_TYPE_NOTIFY_FORK = process::fork
注意:虽然Crescendo目前没有捕获ES_EVENT_TYPE_NOTIFY_MMAP``ES_EVENT_TYPE_NOTIFY_WRITE``ES_EVENT_TYPE_NOTIFY_EXEC
等事件,但是它捕获到了许多这个持久化方法的其他事件。对于其他事件的报道,我强烈建议使用Xorrior的Appmon工具。
下面的内容主要关注持久化方法的执行,实际的恶意应用程序结构将根据攻击者开发的内容而有所不同。
首先,plutil
将Dock plist
转换为XML语言。XML格式更容易操作。
此外,用temp9876
文件记录进程创建。
DockPersist.j
s在/private/tmp/
目录下创建一个随机命名的文件。脚本修改plist
转换出的XML文件版本号后,将其保存在这个随机文件中。在这个例子中,temp0wsn4p
以XML格式包含了恶意的plist
文件,因此我们用在Dock中正确加载所需的二进制格式版本覆盖了该文件。
接下来,DockPersist.js
删除位于~/Library/Preferences/com.apple.dock.plist
中现有的plist
。
ESF以二进制格式保存新的恶意plist
到 ~/Library/Preferences/com.apple.dock.plist
。
最后,由于我们在函数调用中指定了重新加载Dock,因此将调用killall
。
正常执行
您可能想知道的问题是,既然我们已经知道了ESF如何捕获已知的恶意行为,那么ESF如何表示正常的执行呢?
作为常规操作的一部分,cfprefsd
(Core Foundation Preferences Daemon)将在com.apple.dock.plist
上触发file::rename
事件。当用户通过GUI手动更改Dock时,也会触发这些事件。
躲避检测
对手可以执行plist
修改任务,并将修改后的plist上传到dock plist
,以减少攻击痕迹。但是,这仍然会导致file::rename
事件的产生,该事件不会使用我们在标准执行中确定的cfprefsd
进程。在cfprefsd
进程之外修改plist
可能是识别恶意行为的一个很好的出发点。
视觉效果
PoC的执行会导致在Dock中出现两个Safari实例。
第一个Safari是恶意应用程序,它位于plist的persistent-apps
部分,第二个Safari是真正的Safari,它位于plist的recent-apps
部分。
一些通过Osascript留下的攻击证据
在深入研究ESF日志之后,我注意到一些有趣的条目被写到SQLite
数据库中。如果对手在使用osascript
,可能会注意到osascript
有一个缓存数据库~/Library/Caches/com.apple.osascript/Cache.db
在使用SQLite的DB浏览器检查这个数据库时,我注意到cfurl_cache_response
表包含我们的Mythic
服务器IP地址和一个简短的GET
请求日志,该请求连接C2服务器。该缓存为调查取证人员提供了宝贵的证据。
使用sqlite3
命令行工具也可以查看这些条目。
结论
这篇文章展示了一个类似于Windows上的. LNK
文件的持久化方法。我希望所展示的持久化IoC能够帮助开发人员对该技术进行检测。如果您遇到这个持久化方法创建的上面没有提到的任何其他IoC,请告诉我。
参考内容
https://attack.mitre.org/techniques/T1547/009/
https://developer.apple.com/documentation/endpointsecurity?language=objc
https://github.com/SuprHackerSteve/Crescendo