恶意软件如何通过文件名检测反分析环境
现代恶意软件实现了大量反调试和反分析功能。如今,当恶意软件在野外传播时,很可能会被自动送入自动化分析管道和沙箱中。要在沙箱中分析样本,必须将其"复制"到沙箱中并执行。这可以是手动或自动完成的。
当人们开始分析可疑文件时,通常将其命名为"sample.exe"、“malware.exe"或"suspicious.exe”。这并不总是一个好主意,因为它可能被恶意软件检测到,使其意识到"我正在被分析"。
从恶意软件的角度来看,检测这种情况很容易。微软为开发人员提供了数千个可用于"恶意目的"的API调用。让我们来看看GetModuleFileName()[1]。这个API调用检索包含指定模块的文件的完全限定路径。该模块必须已被当前进程加载。通常,“模块"指的是DLL,但在微软生态系统中,主程序也是一个"模块”(就像DLL也是一个PE文件,但具有导出函数)。
如果仔细阅读API描述,它需要3个参数,但第一个名称可以省略(设置为NULL):
“如果此参数为NULL,GetModuleFileName将检索当前进程可执行文件的路径。”
让我们编写一个小程序:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
|
using System;
using System.Runtime.InteropServices;
class Program
{
// GetModuleFileName的调用声明
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
static extern uint GetModuleFileName(IntPtr hModule, [Out] char[] lpFilename, uint nSize);
static void Main(string[] args)
{
const int maxPath = 260;
char[] buffer = new char[maxPath];
uint length = GetModuleFileName(IntPtr.Zero, buffer, (uint)buffer.Length);
// 获取可执行文件基名
string fullPath = new string(buffer, 0, (int)length);
string exeName = System.IO.Path.GetFileName(fullPath);
// 潜在的样本名称列表
string[] allowedNames = {
"sample.exe",
"malware.exe",
"malicious.exe",
"suspicious.exe",
"test.exe",
"submitted_sample.exe",
"file.bin",
"file.exe",
"virus.exe",
"program.exe"
};
foreach (var name in allowedNames)
{
if (string.Equals(exeName, name, StringComparison.OrdinalIgnoreCase))
{
// 可执行文件名匹配,静默退出!
return;
}
}
Console.WriteLine($"I'm {exeName}, looks good! Let's infect this host! }}:->");
}
}
|
将文件命名为"ISC_20250707.exe"进行编译和执行:
一旦重命名为"malware.exe",程序就会静默退出!简单但有效!
当然,这只是一个简单的概念验证。在真实的恶意软件中,会实现更多的测试(例如:忽略大小写),并且潜在的可疑文件名列表会被混淆(或者从第三方网站加载动态列表)。
[1] https://learn.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-getmodulefilenamea
关键词:反分析 API检测 文件名 恶意软件