在本文中,我们将为读者介绍基于打印机跳板技术的新型C2及其检测方法。
在上一篇文章中,我们为读者详细介绍了基于打印作业的新型Command & Control(C2)的工作原理,以及基于C3的打印通道的实现方法。在本文中,我们将继续为读者介绍针对这种新型C2的各种检测方法。
在端点上进行检测
模块加载事件
首先我们可以看一下模块加载事件。正如我们之前所做的那样,我们可以使用b33f的SilkETW来捕获我们的ETW遥测。下面的SilkService将提供我们所需要的东西:
<SilkServiceConfig>
<ETWCollector>
<Guid>870b50e1-04c2-43e4-82ac-817444a56364</Guid>
<CollectorType>kernel</CollectorType>
<KernelKeywords>ImageLoad</KernelKeywords>
<FilterValue>Image/Load</FilterValue>
<OutputType>eventlog</OutputType>
</ETWCollector>
</SilkServiceConfig>
在启动时,我们可以看到我们的Relay加载了DLL库“winspool.drv”。查看微软的文档,可以看出这是添加了打印作业的底层模块。
模块加载事件还突出显示了C3 Relay每次试图将作业添加到打印队列中时的情况。最值得注意的是,我们可以看到每次执行打印作业时,prnfldr.dll和 PrintWorkflowProxy.dll都会被重复加载和卸载。
当然,在一个典型的企业端点上,可能会有各种各样的程序在创建打印作业。此外,作为攻击方,我们可以通过向通常会产生打印作业的进程(如Microsoft Office应用程序)中注入数据,使这一操作变得更加难以被察觉。
实际上,查找异常作业的一种方法是过滤掉通过UI调度的作业。为此,我们可以打开SysInternals Process Monitor,并在Microsoft Word中执行一个交互式打印,这时,我们就会发现prntflr.dll将再次被加载,而另一个同时加载的DLL却变成了printui.dll。
虽然通过名称就能猜出这个DLL的用途,但是为了严谨起见,我们还是查看了这个系统DLL的导出函数(在本例中我们使用的是pestudio)。其中,其中有一个名为“connecttoprintdlg”的函数,通过查阅Microsoft文档,我们了解到该函数的用途是“显示对话框,以允许用户通过该对话框来浏览并连接到网络上的打印机”。
不过,从该Relay的模块加载项以及该打印作业调度的编程属性来看,这里疑点很多。
远程过程调用
根据Microsoft的规范文档,“打印系统远程协议依赖于RPC协议。打印系统远程协议并没有指定客户端和服务器之间文件传输的方法;因此,服务器消息块(SMB)2.0版协议(Server Message Block (SMB) Version 2.0 Protocol)是所有文件传输操作的首选协议”。
因此,我们需要做的第一件事是捕获RPC日志,为此,我们可以借助于“Microsoft-Windows-RPC”ETW来完成这一任务。就这里来说,我们可以使用内置的logman实用程序。我们可以使用以下命令将RPC日志保存到名为“print-job-rpc”的文件中:
logman start Print-Job-RPC -p Microsoft-Windows-RPC 0xffffffffffffffff win:Informational -ets
执行RPC捕获操作后,我们就可以执行C3打印通道的中继操作了。建立连接后,我们可以使用以下命令停止捕获操作了:
logman stop Print-Job-RPC -ets
此外,我们还可以使用以下命令将这个ETL文件转换为与事件查看器兼容的EVTX文件:
tracerpt Print-Job-RPC.etl -o Print-Job-RPC.evtx -of EVTX
即使收集的时间很短,我们也可以立即看到正在捕获的数据量(就这里来说,20秒内大约发生了约80,000个事件!)。就本例来说,我们可以专注于EID 5,这些是RPC客户端调用。
然后,我们可以搜索与操作系统的打印服务有关的事件。根据该规范,我们可以看到打印系统远程协议(又名为MS-RPRN)的接口UUID为{12345678-1234-ABCD-EF00-0123456789AB}。在下面,展示的是Relay进程和本地打印服务之间的通信数据:
查看上面的条目,我们可以看到一些关键信息:
- 进行RPC调用的进程的ID。
- 接口UUID(可用于确定我们正在与打印服务通信)。
- OpNum可以确认针对接口调用的函数(即创建和删除打印作业)。
对于C3通道来说,还有一些值得注意的RPC函数,其中包括:
如您所见,上面的OpNum为4,表明Relay进程正在请求打印队列中当前作业的详细信息。我们还可以看到下面OpNum为24的RPC调用,表明我们的Relay正在向打印队列中添加作业。
在不深入研究打印服务系统的内部系统架构的情况下,从高层次来看,我们的“客户端应用程序(client application,即Relay)”与本地print spooler服务进行了通信,这就是我们在上面看到的——请注意这里用于本地进程之间通信的轻量级RPC(Lightweight RPC,LRPC)。
从这里开始,我们的本地spooler服务将使用RPC(通过SMB,正如我们在规范中看到的)与打印服务器的远程spooler服务进行通信。打印系统异步远程(MS-PAR)协议服务器接口由UUID {76F03F96-CDFD-44FC-A22C-64950A001209}进行标识的。在下面,我们可以看到对打印服务器的RPC调用。
注意,这里我们可以看到“DC2”,也就是我们实验室环境的打印服务器的网络地址。同时,我们还可以看到MS-PAR接口的UUID,以及OpNum为0,即 “RpcAsyncOpenPrinter”函数,它可以检索到指定打印机的句柄。正如我们所期望的那样,由于打印机系统架构的缘故,Relay的发起PID已经消失了,我们现在看到的是本地主机的print spooler服务的进程ID。
虽然我们不会进一步深入探讨这种检测方法,但我们可以在这里看到可用的原始遥测数据(尽管数量很大),使我们能够确定哪些进程正在启动打印作业。
对于希望进一步了解RPC遥测技术的读者,请参阅Jonathan Johnson、Jared Atkinson和Luke Paine的相关文章。
在网络上进行检测
如上文MS-RPRN规范中所述,我们对远程服务器的RPC调用是通过SMB进行的。从捕获的通信数据包中,我们可以看到与打印服务器的连接,特别是OpenPrinterEx 请求。
显然,离开端点后,我们就无法看到进程级别的数据,但我们仍然可以看到端点执行的打印活动。这可用于识别beaconing行为或来自一台或多台主机的大量打印流量,这表明打印机在执行跳板攻击。
在打印服务器上进行检测
最后,在打印服务器本身上面,我们可以使用“Microsoft-Windows-PrintService/Operational”日志来跟踪打印作业。为此,我们可以通过组策略以及以下命令来启用该日志:
wevutil.exe sl 'Microsoft-Windows-PrintService/Operational' /enabled:true
Microsoft-Windows-PrintService/Operational日志能够为我们提供以下重要事件ID:
- EID 308:打印文档
- EID 310:删除文档
在默认情况下,我们是看不到作业名称的长度的,而与打印有关的异常活动常常就反映在这上面。
要记录作业名称,我们需要修改组策略来启用以下选项:
Computer Configuration > Policies > Administrative Templates > Printers > Allow job name in event logs
当然,这种日志的精确度可能存在隐私问题,但我们可以在实验室环境中安全地启用它,具体如下图所示:
现在,我们可以看看生成的事件日志了:
正如我们在上面看到的,这里的EID 310(删除文档)事件为我们提供了添加到打印队列中的作业的名称。考虑到这些文件名做多可容纳1MB字节,因此,C3可以通过它来发送Base32编码的消息内容、Cobalt Strike beacon(200kb左右)或需要外泄的数据。
此外,观察上面的屏幕截图中的日志模式,我们可以看到EID 800(假脱机)、308(打印)和310(作业删除)的组合。这里至关重要的是,通过下面的截图我们可以看到EID 308事件,这表明我们的每一个作业都被设置为暂停状态。因此,两个relay之间的连续通信会产生大量的暂停打印作业和删除作业。
小结
正如我们所观察到的,检测打印机跳板攻击时,有许多方法可用。不过,最有效的线索是添加到打印队列中的文档名称的Base32编码内容,可以通过“Microsoft-Windows-PrintService/Operations”日志进行查看。然而,通过适当的遥测技术,我们也可以在端点和网络日志中搜索可疑的跳板攻击活动。
发表评论
您还未登录,请先登录。
登录