针对一个红队病毒样本逆向分析

news2024/9/21 15:49:11

近日翻到一个比较新颖的样本,在最终后门载荷释放前运用了不少免杀手段,包括堆栈欺骗,实现反射性调用API,以及DLL侧加载、DLL挖空、HOOK规避等手法,对其执行流程和部分手法做详细分析记录。

样本概述

  • 初始载荷

初始载荷如下,其中loader.exe是作者编译的一个shellcode加载器。

  • 执行流程

有合法签名可执行文件(taskhost.exe)侧载恶意 DLL (sbiedll.dll)。这个恶意DLL作为中间载荷,解密密文载荷DAT文件(sbiedll.dat)获取二阶段有效负载。解密的有效负载MoonWalk充当后门,滥用Google Drive进行命令和控制(C2) 通信。流程图如下:

  • 精心构造的配置信息

样本主要使用“AES-CFB”算法解密载荷,多次使用MD5 hash算法做载荷校验或将hash值作为AES算法的KEY、IV值。主要配置信息如下:

  • 较为丰富的杀软规避
  • DLL 侧加载执行恶意载荷
  • 指定特定的执行参数,期望参数“--type driver”。
  • FNV1a hash动态解析 API。
  • 堆栈欺骗调用win API,规避win API调用过程检测(构造伪造堆栈、修改堆栈指针、调用 API、恢复原始堆栈)
  • 使用了大量的windows底层函数(如内核函数NtCreateFile等)。
  • 使用当前植入主机的GUID md5值作为AES IV值,生成唯一、绑定载荷。
  • hook规避、断点检查。
  • MD5 hash算法和AES-CFB算法进行解密,MD5hash算法进行完整性检查

样本分析

侧加载

1. “白加黑”侧加载执行初始恶意载荷。由Sandboxie签名的合法可执行文件 (taskhost.exe) 侧载恶意 DLL (sbiedll.dll)。

“sbiedll.dll”中初始化了三个导出函数,但实际上都指向相同的地址,函数名称“SbieDll_Hook”。

2. 编写一个加载器执行恶意导出函数“SbieDll_Hook”,同步虚拟内存地址,动态、静态结合调试主要功能。

配置信息解密

3. 利用MD5校验加密配置信息,确保配置的完整性。计算密文段的MD5 hash来于硬编码在样本中的正确hash值做比对。

两段密文hash值:

FE93E8E1C5C3032A26D783A78A820587
1E8EE70F02D60E389D8F721E8CE6DF1F

4. AES-CFB算法进行解密,获取解密配置信息入下,其中包括明文字符“sbiedll.dat”、“--type”以及其他配置信息或密钥供后续使用。

杀软规避

5. 执行进程是否使用正确的参数启动,验证期望参数包含“--type driver”,如果此验证检查失败,则终止进程。计参数的MD5哈希值,多次计算结果与硬编码的哈希值进行比较。

硬编码hash值:

E2D45D57C7E2941B65C6CCD64AF4223E

6. 利用加盐的FNV-1a哈希算法来逃避针对WINAPI的静态检测。在哈希计算过程中添加盐值不同样本的哈希值不同,提高了逃避静态检测的能力。

上图中伪代码通过指针运算和类型转换访问内存,还原C代码,所需API地址通过结构体成员访问。

sImportTable->ntdll_LdrLoadDll = ResolveImport(L"ntdll", 0xFE0B07B0, 0xCA7BB6AC);

函数体内部关键步骤入下:

  • 初始化哈希值。
  • 对输入字符串(DLL名或函数名)进行哈希计算。
  • 对盐值进行哈希计算。

首先,它对输入字符串(代表 DLL 或函数名称)进行哈希处理。然后,它单独对盐值进行哈希处理。此两步哈希处理过程相当于对输入字符串和盐的连接进行哈希处理。

while ( 1 )
  {
    Fun_FNV1a_Hash = 0x811C9DC5;                // FNV-1a 初始哈希值
    InputString = (unsigned __int8 *)(a1 + *v12);
    v18 = -1i64;
    do
      ++v18;
    while ( InputString[v18] );                 // 输入字符长度计算
    for ( i = &InputString[(unsigned int)v18]; InputString < i; Fun_FNV1a_Hash = 0x1000193 * (Fun_FNV1a_Hash ^ v20) )// 计算输入字符串FNV-1a哈希
      v20 = *InputString++;
    v21 = (unsigned __int8 *)&unk_7FFFBEAD7D78; // Salt value: CB 24 B4 BA
    do
    {
      v22 = *v21++;
      Fun_FNV1a_Hash = 0x1000193 * (Fun_FNV1a_Hash ^ v22);// 对盐值进行哈希计算
    }
    while ( v21 < byte_7FFFBEAD7D7C );

盐值,CB 24 B4 BA

最终将API函数地址放置与连续的内存地址中,即结构体成员变量中。下图以API函数“LookupAccountSidw”为例。

此外ResolveImport中还有内置了一些API函数调用相关功能,此样本中暂时没用到。

7. DodgeBox在完成API初始化后,它就会扫描并解除从System32目录加载的 DLL。此过程包括遍历 .pdata每个 DLL 的部分,检索每个函数的起始和结束地址,并计算每个函数字节的 FNV1a 哈希值。计算存储在磁盘上的相同函数字节的相应哈希值。如果两个哈希值不同,则可以检测到潜在的篡改,将用磁盘中的原始版本替换内存中的函数。

此过程包括遍历 .pdata每个 DLL ,步骤方法入下:

p_InMemoryOrderModuleList = &NtCurrentTeb()->ProcessEnvironmentBlock->Ldr->InMemoryOrderModuleList;

当前线程的线程环境块(TEB)->进程环境块(PEB)->已加载模块的信息链表InMemoryOrderModuleList。

获取链表信息后再循环遍历加载模块列表的每个节点。

p_InMemoryOrderModuleList = &NtCurrentTeb()->ProcessEnvironmentBlock->Ldr->InMemoryOrderModuleList;
  for ( i = p_InMemoryOrderModuleList->Flink; i != p_InMemoryOrderModuleList; i = i->Flink )
  {
    Flink = (__int64)i[2].Flink;
    v3 = (const wchar_t *)i[4].Flink;
    if ( ((__int64)i[5].Blink & 0x60000000) != 0x20000000
      && (*(_WORD *)(*(int *)(Flink + 60) + Flink + 22) & 0x2000) != 0 )
DAT文件有效载荷解密及加载

8. 在当前进程堆中开辟内存,读取“sbiedll.dat”文件流。

在完成路径等相关字符初始化后,利用NtReadFile读取文件流至当前进程的堆空间中。

9. DAT文件有效载荷解密

读取计算机唯一标识符GUID,计算MD5。检索注册表“SOFTWARE\Microsoft\Cryptography MachineGuid”值获取系统GUID,计算其MD5值,作为后续解密AES算法的IV值。

检查文件的前四个字节。如果这些字节非零,则表示 DAT载荷投递在了特定目标上,如果DAT文件不是特定于机器的,DodgeBox将继续使用 AES-CFB 加密解密文件,利用存储在配置文件中的密钥参数。从“sbiedll.dat”载荷的第五个字节开始解密,解密获取一个隐藏PE头的PE文件。

使用前机器GUID的MD5哈希作为AES IV重新加密载荷。

在完成有效载荷解密后,样本将载荷与当前植入机器绑定,使用原有的AES密钥key,但是将 GUID 的 MD5 哈希作为 AES IV。这种方法保证了解密的 DAT 文件无法在任何其他机器上解密,从而增强了有效载荷的安全性。

10. 关于堆栈调用欺骗可以再做一些更详细的说明。这里借鉴原始报告的描述。

首先设置堆栈,精心构造堆栈的内容,包括插入返回地址和所需的参数,确保API调用能按预期进行。

真实API调用,在准备好堆栈和寄存器后,执行jmp指令,将控制流重定向到目标 API。这种方式使得 API 调用看起来像是从正常位置发起的。

这种方法结合了堆栈伪造和 API 调用技术,通过控制堆栈和寄存器的状态来确保 API 调用能够成功并达到隐蔽的效果。这种复杂的技术可以有效地绕过静态分析和动态监控,增加了恶意代码的隐蔽性。

样本的加盐 FNV1a 哈希的 Python 实现如下所示:

func fnv1aSalted(data, salt []byte, seedValue uint32) uint32 {

    combinedData := append(data, salt...)

    hash := seedValue
    prime := uint32(0x01000193)

    for _, byteValue := range combinedData {
        hash ^= uint32(byteValue)
        hash *= prime
        hash &= 0xFFFFFFFF 
    }
    return hash
}

func main() {
    ntdll := []byte("n\x00t\x00d\x00l\x00l\x00") 
    salt := []byte{0xba, 0xb4, 0x24, 0xcb}

    hash1 := fnv1aSalted(ntdll, salt, 0x811c9dc5)
    fmt.Printf("Hash for ntdll: 0x%08x\n", hash1)

    ldrLoadDll := []byte("LdrLoadDll")
    hash2 := fnv1aSalted(ldrLoadDll, salt, 0x811c9dc5)
    fmt.Printf("Hash for LdrLoadDll: 0x%08x\n", hash2)
}

整体样本尤其是一些免杀首发相对复杂,因为中途快照出现了些问题,注释等信息缺失,所以记录思路显得有点混乱,不过还是基本描述清除了相关手法。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1972642.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【硬件开发】树莓派4B散热性能

树莓派4B散热性能 树莓派引脚 树莓派 40Pin 引脚对照表 rpi-pins-40-0 注&#xff1a;本表格适用于各版本&#xff0c;并且兼容26Pin的树莓派B&#xff0c;树莓派B为26Pin&#xff0c;其引脚对应于上表的前26Pin。 使用下面这款 GPIO 参考卡片&#xff0c;让引脚功能一目了…

谷粒商城实战笔记-101-分布式基础篇总结

文章目录 一、分布式基础概念二、基础开发三、环境搭建四、开发规范 分布式基础篇已经学习完成&#xff0c;包含了以下4个部分的知识&#xff1a; 1&#xff0c;分布式基础概念2&#xff0c;基础开发3&#xff0c;环境搭建4&#xff0c;开发规范 学习并掌握这部分内容&#x…

超声波眼镜清洗机是智商税吗?最好用的超声波清洗机推荐

大家知道&#xff0c;在咱们生活的环境里。到处充斥着细菌&#xff0c;像衣服上、手上等等地方都很容易被沾染上比细菌&#xff0c;很影响咱们的健康。所以大家会勤洗手&#xff0c;勤换洗衣服&#xff0c;来减少细菌病毒伤害。然而对于戒指、项链、眼镜、手表等配饰细菌&#…

软考:软件设计师 — 9.数据流图

九. 数据流图 数据流图是下午场考试中第一个题目&#xff0c;分值 15 分。通常会考察实体名、存储名、加工名的补充&#xff0c;以及找到缺失的数据流并改正等。 1. 数据平衡原则 数据流的分析依赖于数据平衡原则。 父图与子图之间的平衡 父图与子图之间平衡是指任何一张 …

mp3剪辑音乐怎么剪?手把手教会你4个音频剪辑技巧

在制作创意无限的“矿泉水瓶烟花视频”时&#xff0c;音效的选择与剪辑往往是点睛之笔。想象一下&#xff0c;那绚烂的视觉盛宴搭配上恰到好处的背景音乐&#xff0c;是否能让你的作品更加引人入胜&#xff1f; 而要精准地控制每一个音符的起承转合&#xff0c;一款强大的mp3剪…

【学习笔记】Day 1

一、进度概述 1、配置相关环境——注&#xff1a;暂未完成&#xff0c;还有部分依赖没有补充完整 2、试运行 3、《地震数据全波形反演的深度学习方法》PPT知识梳理方法地震数据全波形反演的深度学 二、详情 1、配置相关环境 深度学习环境配置参考文章如下&a…

VS+Qt+C++点云PCL三维显示编辑系统

程序示例精选 VSQtC点云PCL三维显示编辑系统 如需安装运行环境或远程调试&#xff0c;见文章底部个人QQ名片&#xff0c;由专业技术人员远程协助&#xff01; 前言 这篇博客针对《VSQtC点云PCL三维显示编辑系统》编写代码&#xff0c;代码整洁&#xff0c;规则&#xff0c;易…

HttpRequest请求对象和HttpResponse响应对象

HttpRequest请求对象 1.获取请求头 2.获取请求参数 通过请求对象获取请求头 获取GET参数&#xff08;valuerequest.GET.get(参数名称&#xff0c;默认值)&#xff09;获取POST参数valuerequest.POST.get(参数名称&#xff0c;默认值)&#xff09;获取URL参数&#xf…

C++ 预置和弃置的函数

在C11中&#xff0c;预置和弃置的函数是用于处理移动语义和完美转发的。 预置函数&#xff08;Move Constructor&#xff09;是在对象被移动时调用的构造函数。它允许将资源从一个对象转移到另一个对象&#xff0c;而不是进行复制。这可以提高性能&#xff0c;特别是在处理大型…

红酒与美食搭配:味觉的新探索

在美食的世界里&#xff0c;红酒如同一位优雅的舞者&#xff0c;与各种佳肴共舞&#xff0c;创造出无尽的味觉惊喜。当定制红酒洒派红酒&#xff08;Bold & Generous&#xff09;与各式美食相遇&#xff0c;便开启了一场味觉的新探索之旅。 一、红酒与美食的邂逅&#xff…

中国LLM研究所收集100+AI大模型资源

自ChatGPT为代表的大语言模型 (大型语言模型&#xff0c;LLM)出现以后&#xff0c;由于其惊人的类通用人工智能(AGI)的能力&#xff0c;掀起了新一轮自然语言处理领域的研究和应用的浪潮。尤其是以ChatGLM、LLaMA等平民玩家都能跑起来的较小规模的法学开源之后&#xff0c;业界…

@SchedulerLock注解使用

文章目录 Scheduled注解参数介绍建表配置类示例参考 如果服务中使用了Scheduled注解&#xff0c;且服务部署了多个节点。那么在同一时刻&#xff0c;所有节点都会执行定时任务。但有有些任务我们只需执行一次&#xff0c;这就需要使用分布式锁的方式来控制&#xff0c;如可以使…

写文案的软件有哪些,四款强大的文案生成器为你创作文案

文案&#xff0c;作为沟通和营销的桥梁&#xff0c;其重要性不言而喻。然而&#xff0c;创作出既吸引人又具有说服力的文案&#xff0c;往往需要投入大量的时间和精力。随着市场上出现了一些能够辅助甚至替代人工创作文案的生成器出现&#xff0c;它解决了大家创作文案的难题。…

(器件)ATMXT1664S1是电容式触摸屏控制器、而ATMXT2912TG-A则是maXTouch 2840节点触摸屏控制器

1、maXTouch mXT1664S电容式触摸屏控制器为大型触摸屏设备带来了S系列架构。mXT1664S得益于强大的32位AVR内核&#xff0c;并且由于S系列架构&#xff0c;它具有业界最高的信噪比(SNR)&#xff0c;提供了无与伦比的触摸性能。与S系列中的其他设备一样&#xff0c;mXT1664S包括:…

在OA系统中,飞书的设计从颜值和体验上算是天花板了吧?

书是一款优秀的企业通讯协作工具&#xff0c;在 OA 系统的设计上有很多优点&#xff0c;如用户界面友好、安全性高和协作功能丰富等。但它也有一些可以改进的地方&#xff0c;以下是一些可能的方向&#xff1a; 用户体验一致性&#xff1a;飞书的不同功能模块可能在用户体验上…

TCP的可靠机制

TCP的可靠机制 前言 要了解TCP的可靠机制&#xff0c;我们必须要先熟悉TCP的报文&#xff0c;在这篇文章中有详细介绍TCP的报文 &#xff1a; 并且确认应答机制也在该文章中提到&#xff0c;所以这篇文章就不会再介绍确认应答了。 超时重传 我们都知道&#xff0c;报文在网…

2024年【起重机司机(限桥式起重机)】最新解析及起重机司机(限桥式起重机)找解析

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 起重机司机(限桥式起重机)最新解析根据新起重机司机(限桥式起重机)考试大纲要求&#xff0c;安全生产模拟考试一点通将起重机司机(限桥式起重机)模拟考试试题进行汇编&#xff0c;组成一套起重机司机(限桥式起重机)全…

c++(模版)

目录 函数模板格式 函数模版原理 函数模板的实例化 模板参数的匹配原则 类模板 函数模板格式 template<typename T1, typename T2,......,typename Tn> 返回值类型 函数名(参数列表){} template<typename T> void Swap( T& left, T& right) { T te…

cesium的flyTo在飞行完成后渲染

viewer.camera.flyTo({}); 替换自己要渲染的labe img等 viewer.camera.flyTo({destination: Cesium.Cartesian3.fromDegrees(lon,lat,height), // 飞行目的地&#xff0c;视角高度duration: 3, // 飞行所用时间// 飞行完成后的事件complete: function() {viewer.camera.flyTo…

pytorch: cpu,cuda,tensorRt 推理对比学习

0&#xff1a;先看结果 针对resnet模型对图片做处理 原图结果 分别使用cpu&#xff0c;cuda&#xff0c;TensorRt做推理&#xff0c;所需要的时间对比 方法时间cpu13s594mscuda711mstensorRt 113ms 项目地址&#xff1a; GitHub - july1992/Pytorch-vily-study: vily 学…