OceanLotus macOS恶意软件更新

2019年3月初,有一款来自OceanLotus的攻击macOS的恶意软件被上传到VirusTotal。研究人员分析发现该后门可执行文件与之前的macOS变种有相同的特征,但是其结构发生了变化,所以检测起来更难。但因为找不到与该样本相关的释放器,所以也不知道初始感染向量。
因为之前Trend Micro也分析过OceanLotus使用的macOS恶意软件,因此本文主要介绍与之前版本的变化。
分析
本文的分析过程使用的样本SHA-1 哈希值为E615632C9998E4D3E5ACD8851864ED09B02C77D2,ESET产品检测到该文件为OSX/OceanLotus.D。
反调试和反沙箱
与之前的OceanLotus macOS恶意软件二进制文件一样,该样本是用UPX打包的,但是大多数的解压识别工具无法识别。该特征使静态检测方法很难检测。一旦解压,就会发现程序执行的入口点(entry point)就位于.TEXT的__cfstring。该部分的flag属性如图1所示。
 

图1 __cfstring section属性
如图2所示,__cfstring部分的代码会欺骗解压工具来将代码显示为字符串。
 

图2 IDA将后门代码识别为数据
运行时,二进制文件首先创建一个线程作为反调试监视进程,作用就是持续监测反调试器是否存在。该线程会:
· 用PT_DENY_ATTACH作为请求参数来调用ptrace以分离调试器;
· 调用函数task_get_exception_ports来检查是否有意外的端口开放;
· 严重当前进程的P_TRACED flag来检查是否有调试器,如图3所示:

图3  通过sysctl函数检查是否有调试器
如果监视进程监测到有调试器,就调用exit退出函数。然后该样本会通过发布以下命令来检查环境因素:
ioreg -l | grep -e “Manufacturer” and sysctl hw.model
并检查返回的值中是否有已知的虚拟化系统相关的字符串,包括oracle, vmware, virtualbox, parallel等。
最后执行下面的命令:
system_profiler SPHardwareDataType 2>/dev/null | awk ‘/Boot ROM Version/ {split($0, line, “:”);printf(“%s”, line[2]);}
执行这些命令是为了检查机器是否是“MBP”, “MBA”, “MB”, “MM”, “IM”, “MP”或“XS”,这些代码表示系统的型号,比如MBP代表MacBook Pro。
恶意软件的更新部分
虽然新变种中后门命令没有更新,研究人员发现还是有一些变化。样本使用的C2服务器的创建日期为2018-10-22:
· daff.faybilodeau[.]com
· sarc.onteagleroad[.]com
· au.charlineopkesston[.]com
使用的URL资源被修改为/dp/B074WC4NHW/ref=gbps_img_m-9_62c3_750e6b35。
发送给C2服务器的第一个包含有许多与主机相关的信息,所有命令收集的数据包括:

因为配置发生了变化,所以样本也不再使用libcurl库进行网络窃取,而是使用了一个外部库。为了定位,后门会使用AES-256-CBC模式和key gFjMXBgyXWULmVVVzyxy 来解密当前目录中的每个文件。解密的文件会保存在/tmp/store中,并使用dlopen函数以库的方式来加载。尝试解密会调用dlopen,后门会提取导出函数Boriry和ChadylonV,这两个函数是用来与服务器进行通信的。因为无法从原始样本中找出释放器或其他文件,因此无法分析库文件。而且因为组件是加密的,基于这些字符串的YARA规则也无法找出对应的文件。
Trendmicro的分析中提到macOS后门创建了一个clientID,这是下面命令的返回值的MD5哈希值:
ioreg -rd1 -c IOPlatformExpertDevice | awk ‘/IOPlatformSerialNumber/ { split($0, line, “””); printf(“%s”, line[4]); }’
ioreg -rd1 -c IOPlatformExpertDevice | awk ‘/IOPlatformUUID/ { split($0, line, “””); printf(“%s”, line[4]); }’
ifconfig en0 | awk ’/ether /{print $2}’ (获取MAC地址)
未知命令(“x1ex72x0a“)在之前的样本中被用作uuidgen
在进行哈希计算之前,字符0或1会加到返回值中以表明root权限。如果代码以root权限运行,ClientID就会保存在/Library/Storage/File System/HFS/25cf5d02-e50b-4288-870a-528d56c3cf6e/pivtoken.appex中,或保存在~/Library/SmartCardsServices/Technology/PlugIns/drivers/snippets.ecgML中。该文件一般会通过_chflags函数隐藏,并且用touch -t命令和随机值来修改时间戳。
字符串解密
与之前的变种类似,字符串是用AES-256-CBC和十六进制编码的key 9D7274AD7BCEF0DED29BDBB428C251DF8B350B92使用CCCrypt函数来加密的。使用的key发生了变化,但是该组织仍然使用相同的算法来加密字符串,因此解密可以自动进行。
在了解了decrypt函数的原型后,解密脚本首先会找出对该函数的所有交叉应用,找到所有的参数,解密数据并将明文数据放在交叉应用的地址的注释处。为了让解密脚本正确运行,base64解码函数使用的定制的字母表必须在脚本中进行设置,并且要定义含有key长度的全局变量,如图4所示:


图4 定义全局变量key_len
在function窗口,可以右击解密函数并计点击提取和解密参数。该脚本会将解密的字符串放在注释中,如图5所示:

图5 – 解密的文本被放在注释中
在IDA中使用xrfs到Window的转换就可以列出解密的字符串了,如图6所示:

图6 – Xrefs 到 f_decrypt函数
解密脚本见GitHub:https://github.com/eset/malware-research/tree/master/oceanlotus/
结论
OceanLotus组织仍然在不断更新其工具集,这次更是改善了攻击mac用户的工具集。因为许多mac用户并没有安装安全软件,也无须绕过检测,因此攻击者并没有修改太多代码。虽然研究人员解密了用于C2通信的网络库,但是具体的网络协议仍然是未知的。