这次我们来看看另一个有效载荷近期的RIG EK活动.它是烟雾装载机(Dofoil),一个几年前发明的机器人——它的一个早期版本在黑市上做广告2011年.虽然有一段时间,它没有看到相当长一段时间,它似乎没有计划退休。目前捕获的样本似乎是在2015年更新的。

这个小程序是用来下载其他恶意软件的。让机器人有趣的是它用来欺骗和自我保护的各种技巧。

我们将回顾使用过的技术,并将当前的示例与旧的示例(从2014年开始)进行比较。

分析样品

这个分析的主要焦点是下面的示例,它是由Rig EK提供的:

上面的示例下载:
有效载荷:

更新的装烟机:

在分析期间,它将与旧的样品,首次见于2014年9月

行为分析

部署完成后,装烟器将自身注入资源管理器并删除原来的可执行文件。我们可以看到它在内部建立新的连接资源管理器的过程。

安装和更新

Smoke Loader不仅安装了它原来的示例,还将其替换为一个新的版本,这是从C&C -路径下载的:http:// <数控地址> / system32.exe.这个技巧使得检测更加困难——更新的样本被不同的密码器重新包装,也可能改变他们的c&c集合。

在当前的分析中,Smoke Loader的初始样本丢失了以下一个:bc305b3260557f2be7f92cbbf9f82975

Sample被保存在一个隐藏的子文件夹中,位于%APPDATA%:

下降了

Smoke Loaded将其当前示例和所有其他下载的可执行程序添加到Windows注册表中。键的名称在现有条目的名称中随机选择:

run_key

这种持久性方法非常简单(与之相比Kovter),但针对检测主模块采取了一些对策。被丢弃的可执行文件的时间戳被更改,因此无法通过搜索最近修改的文件找到恶意软件。对该文件的访问被阻塞-对其进行读写操作是不可能的。

加载其他可执行文件

在它出现在系统中时,它会不断下载额外的模块——“插件”。首先,下载的模块以随机名称保存在%TEMP%中并运行。然后,它被移动到%APPDATA%。下面,我们可以看到有效载荷与它自己单独的C&C建立了连接:

installed_plugin

在自动启动中也有一个用于部署负载的脚本:

plugin_persistance

网络通信

为了使流量分析更加困难,加上与C&C bot的通信产生了大量冗余的流量,向合法的域发送请求。

当前样品的C&C地址:

流量部分加密。

在下面的例子中,我们可以看到bot如何从C&C的其他可执行程序下载。

1 -用一个新的烟雾装载机样本更新主机器人:

updating_bot

2 -下载附加负载(“插件”):

下载

负载流量

Smoke Loader部署下载的示例,因此在一段时间后,我们可以看到由有效负载(连接到med-global-fox.com).根据它的特点,我们可以得出结论,这一次的“插件”是一个IRC机器人:

irc_bot

内部

像大多数恶意软件一样,烟雾装载机是由一些分发包装地穴这就提供了抵御检测的第一层防御。

移除加密层后,我们可以看到主要的烟雾装载机可执行文件。然而,为了到达恶意核心,需要进行更多的解包操作。为了方便起见,我将把解压缩示例的代码部分称为阶段# 1.它的执行从主可执行文件的入口点开始,它的作用是提供额外的混淆。它也可以作为最重要的部分的加载器:阶段# 2-这是一个DLL,解压缩到一个动态分配的内存,并从那里运行。

阶段# 1

这个机器人的一个有趣的特性是,它的可执行文件通常只有一个部分,没有导入。下面你可以看到section布局的可视化(入口点标记为红色):

smoke_sections

入口点的代码很模糊,很难理解。它包含许多冗余的跳转,有时下一个跳转的地址是动态计算的——这就是静态分析工具不能解析它们的原因。此外,为了使分析更加困难,代码在执行过程中修改自己。

初始例程使用带有硬编码值的XOR对代码部分的选定部分进行解密:

xor_code

然后它调用它:

call_decrypted

这并不是Smoke Loader修改自己的唯一方式。在拆开包装的部分,我们可以看到更多的技巧。这段代码使用许多微小的跳跃,后面跟着XOR和LODS指令,在每执行几个步骤之后修改和替换代码。在此期间,添加了垃圾指令,使其可读性更差:

go_and_decrypt

机器人自己加载所有必要的导入。为了实现这一目标,它部署了一种流行方法的变体:通过计算函数名的校验和并将其与硬编码值进行比较,在加载模块中搜索函数句柄。的帮助下获取加载模块的句柄流程环境块(PEB)*:

Mov esi, fs:[30];复制到ESI手柄到PEB MOV ESI, DS:[ESI+0xC];struct _PEB_LDR_DATA *Ldr MOV ESI, DS:[ESI+0x1C];ESI = Flink = Ldr->InLoadOrderModuleList MOV EBP, DS:[ESI+0x8];EBP = Flink。DllBaseAddress

阅读更多相关信息在这里
下面我们可以看到遍历导出函数的代码片段要用到搜索函数的句柄:ZwAllocateVirtualMemory(使用它的校验和:0x976055C),然后在一个变量中保存找到的句柄:

search_in_exports

多亏了这个技巧,Smoke Loader可以在没有任何导入表的情况下操作。(采用同样的方法阶段# 2以填补其进口)。

存储句柄用于调用API并分配额外的内存:

allocated_page

在增加的内存空间中,阶段# 2正在拆包。这个新模块是一个PE文件与头删除(这是一个常见的反倾销技术)。下面,你可以看到文件开头被擦除的部分(标记为红色):

missing_part

如果我们添加缺失的部分,就可以将其解析为典型的PE文件。它原来是一个导出一个函数的DLL。以前的Dofoil版本使用了完全相同的技术。在过去,模块的名称是Stub.dll导出的函数是作品.现在这些名字被垃圾代替了。

smoke_core.dll

这部分是由内部的专用功能加载的阶段# 1它负责Windows Loader通常执行的所有操作。

首先,解压缩的内容是原始格式的(header的大小:0x400,文件对齐:0x200):

page1_raw_align

然后,将相同的内容重新排列为虚拟格式(单位大小:0x1000):

page2_virtual_align

另一个子例程解析并应用重定位。正如我们在下面所看到的,这是一个典型的重定位表,来自PE格式。条目被存储为WORDs的连续数组:

搬迁

加载器一个一个地处理它们。首先,它检查条目类型是否为“32位字段”(通过测试EAX, 0 x3000) -这是在这种情况下支持的唯一格式。然后,它获取重定位偏移量(xfff EAX, 0),获取指向地址并执行计算—通过删除旧的ImageBase(它的值是硬编码的)并将新的基偏移量应用到复制解包代码的动态分配的内存中)。

最后,可以将执行流重定向到新代码。阶段# 1的形式调用导出的函数阶段# 2DLL中有三个参数。第一个是字符串,每个示例都不一样(这次是" 00018 "):

call_unpacked

的执行阶段# 2在动态分配的区段内开始:

ep2

在这个阶段,我们可以看到一些从以前版本的烟雾装载机已知的字符串。字符串" 2015 "可能表明该版本编写于2015年(然而,示例的编译时间戳是更近的:2016年6月10日)。

字符串

阶段# 2

而前一阶段只是一个准备阶段,在阶段# 2部署恶意功能。它的入口位于具有以下头文件的导出函数中:

int __stdcall Work(char* sample_id, bool do_injection, char* file_path);

基于这些参数,可执行文件识别其当前状态和要遵循的执行路径。

在执行真正的任务之前,机器人准备伪装——将其代码注入到合法的进程中——资源管理器(关于它的更多信息将在后面解释)。无论是否应该部署该路径,它都由第二个参数指定(表示为do_injection).

do_injection

  • 如果阶段# 2被称为do_injection标志设置,它将把代码注入资源管理器.在这样做之前,要检查环境中是否存在用于恶意软件分析的工具。如果检测到任何指向样例正在受控环境中运行的症状,则应用程序将进入无限休眠循环。
  • 如果阶段# 2被称为do_injection国旗了,它开始向主路径这包括连接到C&C和下载恶意模块。

如果选择了执行的主路径,机器人继续与C&C服务器通信。众所周知,在连接到真正的C&C之前,它首先检查网络是否可达。出于测试的目的,它使用了一些非恶意地址——在本例中就是这样msn.com.只要没有得到响应,它就会继续等待和重试:

test_connection

一旦发现连接正在工作,接下来它将验证应用程序是否已经在运行(使用对特定机器具有惟一名称的互斥锁)。

smoke_main_choice

  • 如果互斥锁存在,程序向C&C服务器发送报告并退出
  • 如果互斥锁不存在(程序还没有运行),它将安装自己,然后开始主要操作。

注入到其他进程

旧版本将代码交替注入到资源管理器svchost.exe.注入资源管理器使用了一个有趣的技巧引起了研究人员的大量注意。它是基于PowerLoader注射技术(Shell_TrayWnd/NtQueueApcThread).

注入svchost.exe只是一个故障保险,遵循更经典的方式类似吗这一个.功能使用:

CreateProcessInternalA NtCreateSection NtMapViewOfSection rtlmovmemory NtUnmapViewOfSection NtQueueApcThread ResumeThread

当前的版本放弃了这个想法,取而代之的是另一种方法(类似于这一个)——向远程进程添加一个新的部分,并复制它自己的代码。功能使用:

CreateProcessInternalA NtQueryInformationProcess ReadProcessMemory NtCreateSection NtMapViewOfSection rtlmovmemory NtUnmapViewOfSection ResumeThread

现在注射的唯一目标是资源管理器

它补丁的入口点资源管理器并在那里添加重定向到新添加的部分的代码。该部分包含被注入的阶段# 2DLL以及一个小的加载器(类似于来自阶段# 1).加载器再次准备阶段# 2并使用不同的参数部署它:

call_from_explorer

通信协议

旧版本的Smoke Loader使用非常描述性的协议,命令直接指向功能。以下是旧版本使用的参数:

Cmd =getload&login= &file= &run=ok &run=fail &sel= &ver= &bits= &doubles=1 &personal=ok &removed=ok &admin= &hash=

在当前版本中,发送的信标看起来有所不同——参数由分隔符分隔,而不是遵循典型的、更冗长的键-值格式:

“2015 # D2C0431D4351DCD46E75D663AA9911B1448D3B2B # 00018 # 6.1 # 0 # 0 # 10001 # 0 #”

参数个数
读取信标,我们可以确认当前分析的版本高于之前的版本。机器人还发送它的ID,它是根据特定系统的GUID和特定样本的典型参数(即“00018”)生成的。

如果试图运行多次(互斥锁),程序也会向C&C报告:

“2015 # D2C0431D4351DCD46E75D663AA9911B1448D3B2B # 00018 # 6.1 # 0 # 0 # 10001 # 13 # 0”

if_mutex_locked

结论

在过去,Smoke Loader是通过垃圾邮件广泛分发的。现在我们遇到了它携带在一个开发工具包。

多年来,机器人的许多部分都没有改变,这使得这种恶意软件很容易被识别。它仍然使用相同的环境检查集进行防御。此外,它还以老式方式等待网络可访问性。用于它与C&C通信的协议现在描述性更少了——它没有那么多的关键字来标识它所执行的动作。和前面一样,流量是加密的。核心功能也保持不变,该恶意软件的主要作用是下载和部署其他模块。

附录

http://stopmalvertising.com/rootkits/analysis-of-smoke-loader.html

https://blog.fortinet.com/2014/11/12/the-rebirth-of-dofoil


这是一篇由Hasherezade撰写的客座文章,Hasherezade是一位对InfoSec有浓厚兴趣的独立研究员和程序员。她喜欢深入了解恶意软件的细节,并与社区分享威胁信息。看看她的推特@hasherezade还有她的个人博客:https://hshrzd.wordpress.com