前言:
近两年比特币、以太币、门罗币等数字货币正经历着全球热潮,挖矿类病毒木马的感染量也随着虚拟货币的价格攀升逐步上涨,黑产团伙的商业嗅觉和行动力令人惊叹,类似“CoinHive”这种网页挖矿变现平台层出不穷,数百万级的网站被黑产团伙利用web漏洞植入挖矿代码;在去年我们可以看到各类挖矿木马异常活跃,从利用“永恒之蓝”漏洞传播到服务器、数据库弱口令爆破,从Struts2、Weblogic、Jboss等各大Web框架漏洞到IE/Flash 0day挂马传播,甚至包括被频繁曝光漏洞的路由器、摄像头等嵌入式设备都被黑产团伙盯上,各类挖矿木马可以说一直活跃在全球网络安全攻击事件的最前线;在挖矿暴利的引诱驱使下,之前部分用于传播垃圾邮件、敲诈者的老牌僵尸网络都开始纷纷转型加入挖矿大军,更有甚者,个别传统正牌软件厂商也都开始沉沦堕落,从我们去年挖掘曝光的“看看影音云控挖矿”、“电信天翼客户端挖矿后门”等安全事件中就可以略窥一二,不夸张地说,2017年堪称挖矿类木马病毒的爆发元年。
近期金山毒霸安全实验室监控到部分用户系统存在疑似挖矿木马活动的威胁线索,经过逐层溯源分析,一个已经成型并走向活跃的Bootkit级挖矿僵尸网络被揭开神秘面纱,Bootkit与挖矿木马的融合也将碰撞出一些不一样的火花。本次捕获的Bootkit样本从框架设计到代码细节处理上都非常完善,在隐蔽性、兼容稳定性、反分析对抗等各方面都达到了一个全新高度,病毒代码的复杂程度、专业程度也为近年所罕见。从样本模块的字符串信息中发现该Bootkit的内部项目代号为“Mellifera(蜜蜂)”,所以本次的Bootkit木马被命名为“隐蜂”,概括来说,“隐蜂”Bootkit木马的技术特点主要体现在以下几个方面:
1) 对抗分析检测,隐蔽性很强。在隐蔽性上“隐蜂”Bootkit木马近乎极致,内核模块的挂钩地址都通过NT内核模块代码间隙的Shellcode中转实现隐藏;两套磁盘驱动劫持过滤机制互相守护;通过镜像回调检测pdb、签名特征屏蔽部分安全软件;针对PCHunter、PowerTool等常见的ARK工具,挂钩其核心驱动过滤IRP请求的返回数据,过滤掉自身注册的各类回调地址;在木马的R3层工作模块中,病毒也会通过脚本实时检测当前运行环境,一旦发现ARK工具、抓包软件或者安全软件,甚至是任务管理器,病毒都会立即结束挖矿活动,小心翼翼地躲藏起来;在C&C通信升级方面,采用SSTP加密协议,并且使用DGA动态生成。除了内存中的shellcode几乎没有太多特征线索,即便是专业安全人员,检测分析“隐蜂”Bootkit都是一件很有挑战性的工作。
2) 架构设计灵活,复杂度专业度很高。从我们的分析过程中看,不管是整体框架的设计还是细节处理都非常专业,比如内核模块基础机制设计方面,多种回调接口非常灵活,而且在内核层支持扩展模块的动态加载卸载,方便随时扩充内核功能;还有用于存储病毒模块和配置信息的MRFS自定义文件系统和NE插件格式;再比如R3层集成的LUA脚本机制增加了病毒灵活性,病毒还会根据机器配置和使用场景动态调整挖矿资源占用参数;最直观的感受,我们从“隐蜂”病毒中解压出来的各类内核模块、R3插件以及配置文件多达50+,病毒代码结构的复杂程度可见一斑。
3) 系统兼任稳定性很好。系统兼容性一直都是衡量Bootkit技术的重要指标,完成一款兼容度极高的Bootkit是非常有技术挑战性的一件事情,从我们的分析过程来看,“隐蜂”在系统引导过程中的挂钩时机选择、挂钩点特征搜寻和代码细节处理上都非常完善,支持主流windows操作系统版本,同时兼容X86/X64架构。“隐蜂”Boot劫持代码中也可以看到一些Bootkit前辈的身影,堪称后辈中的集大成者。
从我们的监控数据来看,本次的“隐蜂”Bootkit木马变种从3月初开始测试传播,得益于其强悍的隐蔽性和对抗分析能力,到至今的三个多月都不曾被外界发现曝光。病毒的项目版本号也从0.1迭代至目前的1.x,在经历了几轮网页挂马和流氓捆绑的传播小高峰后,该僵尸网络已经逐渐成形,预估目前全网的感染用户50w+。病毒母体在传播渠道和技术利用上也都非常有特点,通过白利用和系统漏洞组合穿透主流安全软件的防御体系,后续有机会我们会继续展开分享。
顺便说点题外话,“隐蜂”Bootkit木马的攻击活动并不是首次被发现,在2017年活跃过一段时间,早期变种的功能模块相对简单,主要用于劫持浏览器导航主页,友商安全团队曾经捕获到并命名为“隐魂”木马,称之为“史上反侦察力最强木马”,但是比较惋惜的是分析报告中没有任何IOC信息,并且抹去了几乎所有可能被外部溯源分析的特征线索,所以在较长时间内一直没有被外界熟知,我们也是在本文发布前对近两年的Bootkit类木马进行横向对比时意外发现,出于尊重,我们延续传统将此Bootkit变种命名为“隐蜂”。对抗网络黑产任重而道远,单个团队的力量总是有限的,在基础安全情报的开放共享方面,希望我们都可以做地更多一点,否则很多披露报告就失去了它本来的意义。本次发现的“隐蜂”Bootkit样本和相关技术细节会对安全友商开放,可以通过官方邮箱发送邮件和我们联系。最后还要感谢下用户@guying195在分析取证过程中给予的极大支持配合,这样的用户对我们来说也是一种莫大幸运。
正文:
如上图,按照Bootkit类木马传统的“boot+rootkit+plugin”三层架构,我们也会分为3个章节进行讲解,上篇部分主要包含“隐蜂”木马的“Boot劫持”和“内核Rootkit”两个关键部分。成文仓促难免有疏漏之处,欢迎留言指正。
一、 Boot启动劫持阶段
1. MBR引导代码劫持
“隐蜂”bootkit木马对MBR引导代码的感染处理比较有特点,与之前其它MBR类Bootkit不同的是,它通过在正常MBR启动代码基础进行Patch,劫持活动分区表项,打断原本应该跳转到PBR(Partition Boot Record)引导系统启动的正常流程,引导至磁盘末尾的病毒代码上继续执行。
劫持分区表后,病毒从磁盘末尾病毒代码起始处读取1个扇区到0x7C00,校验扇区末尾是否为0xAA55,通过验证则继续下一个步的Loader代码,反之则恢复BP指针,保证系统正常引导启动。
2. BootCode解码与加载布局
如上段所诉,loader代码被拷贝到0x7C00继续执行,这部分loader代码主要负责将磁盘末尾的BootCode代码数据拷贝到内存进行解码、加载布局和参数填充,并且恢复7C00处的MBR引导代码备用。完成这些以后病毒代码流程就进入bootkit经典核心部分,从挂钩INT13中断直到最终注入NT内核。解码和加载布局的这部分代码不涉及技术核心部分,流程略显琐碎,不再赘述细节,关键步骤和内存布局如下图所示:
3. INT13 挂钩
挂钩INT13中断服务是bootkit使用的经典技巧之一,挂钩成功以后可以在PBR读取系统引导程序(NTLDR/BootMgr)时获得一个合适的时机进行特征搜索和Patch。“隐蜂”在这部分的处理上并没有太大差异,如下图:
INT13的挂钩代码中搜索和Patch特征码主要包括以下几点:
1) 搜索特征码“83 C4 02 E9 00 00 E9 FD FF,主要针对XP系统的Ntldr模块,针对此处的Patch主要为了绕过代码完整性校验机制。
2) 搜索特征码 “8B F0 85 F6 74 21/22 80 3D”,主要针对XP系统的OS Loader模块,通过Hook跳转到后续保护模式代码。
3) 搜索特征码 “8A 46 ?? 98 3D 00 00 75 03 E9 03 00 E9 35 00”,主要针对VISTA+版本系统的BootMgr模块,通过Hook跳转到后续保护模式代码。
4. BOOTMGR挂钩
前段中INT13的挂钩代码中针对BootMgr(16位)的Hook对X86和X64做了兼容处理,以Win7 X86系统为例,成功挂钩BootMgr(16位)后效果如下:
BootMgr(16位)的挂钩触发以后,启动流程控制权再次被病毒代码接手,随后从00400000h基址处定位代码段,通过内嵌的微型反汇编引擎对特征码进行递进搜索,继续对BootMgr(32位)的关键位置进行挂钩,首次被挂钩的函数为ImgpLoadPEImage!LdrRelocateImageWithBias,特征码搜索过程如下:
病毒代码对LdrRelocateImageWithBias被调用处的call地址进行Patch,将代码流程劫持到9AA7Eh;通过对BootMgr(32位)的模块功能和挂钩点的调用堆栈分析,就不难发现病毒选定此处作为挂钩点的原因:
5. WINLOAD.EXE挂钩
在对winload.exe的挂钩处理上,依旧选用了ImgpLoadPEImage!LdrRelocateImageWithBias这个调用点,特征码搜索过程都是相同的,另外针对winload架构不同分别处理,保证兼容X86和X64系统。通过此处的挂钩,病毒代码在winload.exe加载系统内核ntoskrnl.exe时可以再次截获代码执行权。此处细节不再赘述,如下图:
如上图所示,当winload!LdrRelocateImageWithBias处的挂钩代码被触发时,流程被引导到病毒函数9AA8Ch处,在这里病毒代码进行二次挂钩跳转,挂钩函数保存了当前模块的镜像基址,并通过覆写当前函数栈内容,等winload!LdrRelocateImageWithBias原函数执行完再次获取触发控制,完成调用后hook。
6. ntoskrnl.exe挂钩
上述挂钩点触发以后,病毒代码被引导到9AA9Ah函数处,开始对NT内核模块ntoskrnl.exe进行挂钩。首先恢复winload!LdrRelocateImageWithBias调用返回地址,保证挂钩代码执行完以后返回正常流程;然后病毒代码开始寻找ntoskrnl.exe的INIT区段,然后通过函数交叉引用和指令参数字符串特征定位到IoInitSystem!IopInitializeBootDrivers调用指令地址,在寻找到的区段间隙处拷贝shellcode,最后填充API表、设置参数并挂钩IoInitSystem!IopInitializeBootDrivers调用。细节过程入下图:
当NT内核调用IoInitSystem!IopInitializeBootDrivers时,之前区段缝隙填充的shellcode被触发,这里病毒代码首先将IopInitializeBootDrivers原地址填写到堆栈,保证原函数正常调用;然后关闭写保护恢复该处的挂钩,最后将下一阶段的hook函数地址填写堆栈,这样在BootDrivers初始化完毕以后,再次拿到内核代码控制权,最后填充原函数返回地址,加载执行后续shellcode。过程如下图:
从上图末尾的shellcode开始,病毒代码就开始进入bootkit内核驱动模块的加载过程,这部分代码包括三层的shellcode跳转处理,最终从磁盘末尾的读取后续核心模块的代码数据,解密解压处理后得到自定义文件系统(Mixed ROMFS)镜像,解析出内核loader模块“/bin/i386/bootmgr”(变异PE)装载并执行。限于篇幅这里不再赘述细节,三层shellcode跳转过程描述如下图:
至此“隐蜂”病毒的“Boot启动劫持阶段”结束,病毒代码从MBR劫持一路挂钩跳转直到进入到内核“Rootkit”阶段,后续将开始加载真正的内核模块,完成Ring3插件主模块注入、病毒磁盘数据保护回写以及杀软ARK对抗等操作。
二、 NT内核Rootkit阶段
在前段“Boot启动劫持阶段”结尾,我们提到了病毒代码使用了“Mixed ROMFS”自定义文件系统(以下简称MRFS)来存储配置信息和插件模块,而且插件模块也使用了从PE格式变异而来的NE格式,从这些精心设计的系统格式也可以从侧面窥探出“隐蜂”病毒幕后团伙的专业程度。这两类文件结构对我们后续的分析过程比较重要,在最后的Ring3层工作插件中都会多次使用到,所以在“NT内核Rootkit阶段”真正开始之前,我们先来简单了解下这两种文件格式。
1. 文件系统(Mixed ROMFS)文件结构与NE插件格式
“隐蜂”病毒使用的“MRFS”类似于linux系统下常见的ROMFS等文件系统,但目前没有找到公开资料描述过“MRFS”,所以我们暂时认定“MRFS”是病毒作者自定义的一套文件系统格式。从病毒的文件解析代码中反推出的关键字段和结构如下图:
“MRFS”的文件结构主要包括镜像头、文件信息头和文件数据三大部分,文件信息头是一个层级结构,主要包含了文件路径层级信息和对应文件块偏移信息。这个FS镜像包含了后续所有内核模块、配置信息和注入R3的主模块等文件,文件目录结构解析结果如下:
另外的“NE”模块插件格式相对简单,可以看作一种变异的PE文件格式,病毒作者抹去了PE文件的DOS头和NT头标记、区段名称等信息,进行修复以后即可还原为标准PE文件。在“NE”模块插件的代码入口或者外层调用处,一般通过导入表IAT和重定位表修复填充实现动态加载。
2. “bootmgr”解析加载“kernel”核心模块
“/bin/i386/bootmgr”模块是一个loader模块,主要负责解析加载真正的内核核心模块“/bin/i386/ kernel”,填充重定位表和IAT表完成自加载过程,随后从“MRFS”镜像中解析出kernel文件,进行重定位和导入表处理后直接调用。过程如下图:
3. 核心模块“kernel”
“kernel”是“隐蜂”病毒Rookit阶段的核心模块,从模块整体的设计架构中,可以看出“隐蜂”病毒作者在Windows内核方面的具备非常丰富的开发经验。病毒作者在“kernel”模块中设计提供了镜像通知回调、磁盘过滤回调,内核扩展模块加载等一系列基础框架机制,并导出相关的服务接口,最终完成病毒磁盘数据回写保护、杀软ARK对抗以及R3插件主模块的注入等关键操作。另外内核扩展插件机制设计也非常灵活,支持动态加载卸载,方便病毒随时扩展升级内核功能。“kernel”模块功能比较复杂,部分接口需要结合调用上下文去分析说明,但核心功能可以总结为以下几个关键点:
1) IoCreateDriver创建自定义的核心驱动对象,符号链接为随机GUID,该驱动对象用于导出内核模块的核心功能给Ring3层进行调用。比较有特点的是,驱动对象的派遣函数其实是代理中转函数,通过维护一个链表对象,指向自定义的控制派遣函数对象,这样的设计可能是为了后期扩展更灵活。这部分的接口功能比较繁杂,后续我们会在R3调用处结合上下文进行说明。
2) PsSetLoadImageNotifyRoutine注册镜像加载通知回调,与普通的镜像回调函数不同的是,病毒将一段shellcode代码拷贝到NT内核模块代码段末尾空隙,由这段shellcode引导真正的回调函数,这样将回调函数地址隐藏到NT内核镜像中;另外此处的回调函数同样是一个代理中转函数,维护一个镜像通知回调函数数组,这样可以在系统原有机制外实现灵活扩展,导出接口给其他内核扩展模块使用;
最后向链表中添加了负责注入Ring3的镜像加载回调函数,在选择合适时机创建WorkerRoutine并通过APC机制注入svchost进程。病毒代码会映射目标地址空间并预加载Loader模块“stub.bin”,填充加载关键参数,包括“subsystem”(核心模块)等,最终将病毒流程引导到Ring3层工作阶段。后续Ring3层的工作模块加载和技术细节我们会在下一章中详细阐述。
3) 另外一个重要功能就是磁盘对象劫持相关对抗机制,主要用于保护病毒MBR和存放病毒代码数据的磁盘扇区,并在关机时机进行回写感染。病毒作者在这里巧妙地设计了两套劫持过滤机制,并且在这两套劫持的派遣函数中互相守护,摘除掉一方的劫持挂钩会被另外一处劫持重新恢复。
一类是“磁盘对象劫持”技术,申请内存构造虚假设备/驱动对象并填充关键字段结构,搜寻磁盘上层设备对象扩展,再将其保存下层对象的成员填充为前面构造的虚假设备对象,这样就可以过滤磁盘驱动发送的所有IRP请求,劫持派遣函数中除了对“IRP_MJ_SCSI”请求进行过滤处理外,还有针对“IRP_MJ_POWER”(关机通知)的处理,这里主要是提供接口给其他内核扩展模块和R3,方便对病毒MBR相关代码进行关机回写;
另外一类,劫持磁盘端口驱动(ATAPI)的“IRP_MJ_SCSI”派遣函数,与镜像加载通知回调的机制类似,这里同样将劫持函数的shellcode头拷贝到NT内核代码段末尾实现隐藏,并且也是通过代理函数中转链表实现灵活扩展。
4) 加载内核扩展模块“guard.kext”和“mprot.kext”完成内核对抗扩展功能。这里需要首先说明的是,在内核扩展模块加载机制中,“kernel”模块导出了一个比较重要的功能扩展接口“mpsi.dll”。这个接口主要封装了前面“kernel”模块实现的镜像回调、磁盘过滤等机制,一共22个导出功能函数,内核扩展模块kext以序号导入的形式引入“mpsi.dll”,在动态加载kext扩展模块处理IAT的时候进行了特殊处理,将所有“mpsi.dll”的导入函数引导到“kernel”模块的一个代理中转函数上。
“guard.kext” 内核扩展模块对应的配置文件为"/etc/register.js",该模块通过前面“kernel”模块提供的接口注册镜像加载通知回调,对加载的驱动镜像进行PDB名称、数字签名、Hash等特征过滤,满足特征的则patch驱动文件入口点,直接返回错误状态码STATUS_INSUFFICIENT_RESOURCES,实现对抗安全软件与ARK工具类软件。
除了上述直接对抗安全软件和ARK工具驱动加载外,病毒还会对加载镜像的PDB、原始文件名等特征计算Hash匹配,我们分析认为主要是针对主流的ARK工具,病毒会挂钩ARK工具驱动中IofCompleteRequest等关键函数,对ARK工具交互的IRP请求进行过滤,劫持隐藏之前“kernel”模块注册的镜像加载回调和磁盘驱动派遣劫持等函数地址,防止专业安全人员通过PcHunter、PowerTool等常见的ARK工具检测发现异常挂钩。
另外一个关键的内核扩展模块是“mprot.kext”,其对应的配置文件为"/etc/sandbox.js",该模块主要负责保护病毒MBR和磁盘末尾BootCode,通过“kernel”模块提供的“IRP_MJ_POWER”过滤回调接口注册保护函数,在系统关机时重新检查回写病毒MBR和BootCode。这里病毒注册了两套关机回调函数,一套用于内核扩展自身,一套用于Ring3层触发保护。
上篇的分析到此暂告一段落,下篇中我们会针对Ring3层的挖矿模块工作机制展开分析,敬请期待。
附录(IOC):
升级URL:
sstp://*.gatedailymirror.info/upd.pkg
sstp:// *.redteamshop.info/upd.pkg
sstp:// *.wefoundsome.xyz/upd.pkg
sstp:// *.foundrosysquad.info/upd.pkg
sstp://ask.thesupporthelp.com:443/mlf_plug.zip.sig
矿池地址:
stratum+tcp://data.supportithelp.com:8080
*本文作者:猎豹渔村安全,转载请注明来自FreeBuf.COM