恶意软件分析
目录
Basic knowledge
恶意软件种类划分
根据分析方法,可以将恶意软件分析分为以下四种
- 基础静态分析
- 基础动态分析
- 高级静态分析
- 高级动态分析
根据种类,可以将恶意软件分为以下九种
- Backdoor
- Botnet
- Downloader
- Launcher
- Information-stealing malware
- Rookit
- Scareware
- Spam-sending malware
- Worm or virus
PE头相关知识
导入未列出的链接函数
- LoadLibrary
- GetProcAddress
- LdrLoadDll
- LdrGetProcAddress
关于导入函数名公约
当微软更新一个和旧版本不兼容的新功能时,会在新的函数后方加入 Ex,且可以叠加如 ExEx。这代表这个函数经历了两次这种类型的更新,且旧版本会继续被支持。而 A 或 W 的后缀仅表示这个函数支持 ASCII String 或 WCHAR String 类型的输入。
- Ex
- A | W
Section 信息 ( Windows )
| Executable | Description |
|---|---|
| .text | Contains the executable code |
| .rdata | Holds read-only data that is globally accessible within the program |
| .data | Stores global data accessed throughout the program |
| .idata | Sometimes present and stores the import function information; if this section is not present, the import function information is stored in the .rdata section |
| .edata | Sometimes present and stores the export function information; if this section is not present, the export function information is stored in the .rdata section |
| .pdata | Present only in 64-bit executables and stores exception-handling information |
| .rsrc | Stores resources needed by the executable |
| .reloc | Contains information for relocation of library files |
Windows API
匈牙利表达法
匈牙利命名法是一种变量命名约定,由微软程序员 Charles Simonyi 发明,在 Windows API 和早期 Windows 编程中广泛使用。
核心思想:在变量名前面添加前缀,表示变量的数据类型或用途。
常见前缀分类
基本数据类型前缀
前缀 含义 示例 说明 b BOOL bEnabled 布尔值 c char cKey 字符 i, n int iCount, nSize 整数 l LONG lResult 长整数 dw DWORD dwSize 双字(32位无符号) w WORD wParam 字(16位无符号) f float fValue 浮点数 d double dValue 双精度浮点数 指针和引用前缀
前缀 含义 示例 说明 p pointer pBuffer 指针 lp long pointer lpFileName 长指针(历史遗留) h handle hWnd 句柄 lpfn 函数指针 lpfnCallback 回调函数指针 Windows 特定类型前缀
前缀 含义 示例 说明 h handle hWnd, hDC 窗口句柄、设备上下文句柄 sz 零终止字符串 szClassName 字符串(以NULL结尾) psz 指向字符串的指针 pszText 指向字符指针 lpsz 长指针字符串 lpszCaption 长指针字符串 str CString strName MFC字符串对象
句柄
句柄的本质
句柄是 Windows 系统中对象的引用标识符,类似于"票据"或"令牌"。
// 常见句柄类型定义 typedef void *HANDLE; // 通用句柄 typedef HANDLE HWND; // 窗口句柄 typedef HANDLE HDC; // 设备上下文句柄 typedef HANDLE HICON; // 图标句柄 typedef HANDLE HCURSOR; // 光标句柄 typedef HANDLE HMENU; // 菜单句柄 typedef HANDLE HINSTANCE; // 实例句柄 typedef HANDLE HMODULE; // 模块句柄 typedef HANDLE HFILE; // 文件句柄 typedef HANDLE HPIPE; // 管道句柄句柄的特点
- 不透明性:应用程序不知道句柄的实际值代表什么
- 进程相关:同一对象在不同进程中可能有不同的句柄值
- 类型安全:不同类型的句柄不能混用
- 需要关闭:使用后必须调用相应的关闭函数
预定义的特殊句柄值
#define INVALID_HANDLE_VALUE ((HANDLE)(LONG_PTR)-1) // 无效句柄 #define INVALID_FILE_SIZE ((DWORD)0xFFFFFFFF) // 无效文件大小 #define INVALID_SET_FILE_POINTER ((DWORD)-1) // 无效文件指针
文件系统函数
基础概念
Windows 文件系统主要基于 NTFS 架构。常见文件操作通过以下 API 实现:
- CreateFile / ReadFile / WriteFile / CloseHandle
- DeleteFile / MoveFile / CopyFile / SetFileAttributes
这些函数不仅能访问普通文件,也能操作设备、管道或隐藏数据流。
特殊文件与路径
可以使用 WinObj 显示 Windows 的 对象管理器命名空间(内核级对象树),可浏览诸如
\Device,\Global??,\BaseNamedObjects等节点,查看设备对象、符号链接、命名对象(包括部分命名管道/事件/互斥体等)。类型 示例 说明 备用数据流 (ADS) C:\test.txt:secret NTFS 支持的隐藏数据流,常用于藏 payload 设备文件 \.\PhysicalDrive0 直接访问物理磁盘或分区 命名管道 \.\pipe\mypipe 进程间通信,可被用于 C2 通道 长路径前缀 \?\C:\path\file.txt 绕过 MAX_PATH 限制 GLOBALROOT 路径 \?\GLOBALROOT\Device\HarddiskVolume1\Windows 可直接访问系统卷根目录 虚拟设备文件 NUL, CON, PRN, AUX 特殊系统设备,可能被滥用误导分析 备用数据流(ADS)
每个文件主内容是默认 $DATA 流,ADS 是附加的命名流。
示例:
echo hidden > file.txt:secret more < file.txt:secret特点:
- 不改变主文件大小或修改时间
- 通过常规目录查看不会显示
- 可被恶意代码用于隐藏脚本、配置、可执行体
分析与检测
命令行方式
# 查看文件所有数据流 Get-Item file.txt -Stream * # 递归查找含 ADS 的文件 Get-ChildItem -Recurse -Stream * | ? { $_.Stream -ne '::$DATA' } # Sysinternals 工具 streams -s C:\target动态分析重点
- 监控 CreateFile* 调用路径中包含 :、\.\、\?\ 或 \.\pipe\
- 记录对 FindFirstStreamW / FindNextStreamW 的使用
- 检查是否存在写入或读取非标准流
分析要点总结
- 发现含 : 的文件路径 → 检查是否为 ADS
- \.\ 或 \?\ 开头路径 → 可能访问设备或长路径
- 命名管道通信 (\.\pipe) → 关注 C2 或进程注入
- ADS 扫描是文件取证的常规步骤,不能仅看文件大小
注册表函数
基础概念
Windows 注册表(Registry)是系统与应用配置的集中式数据库,用于存储系统设置、驱动信息、用户配置以及软件启动项。恶意代码常利用注册表进行持久化、隐藏、通信或环境检测。
常用注册表 API
函数 作用 说明 RegOpenKeyEx 打开注册表键 常见于读取系统配置或验证持久化项是否存在 RegCreateKeyEx 创建新的注册表键 常见于持久化或配置写入 RegSetValueEx 写入键值数据 核心修改操作 RegQueryValueEx 读取键值数据 获取系统信息或配置信息 RegDeleteKey / RegDeleteValue 删除注册表项或键值 恢复清理、痕迹清除 RegEnumKeyEx / RegEnumValue 枚举键或键值 扫描系统配置,常用于探测安全软件或环境信息 RegCloseKey 关闭句柄 释放资源(配合打开函数使用) 注册表根键与路径
根键缩写 完整名称 常见用途 HKLM HKEY_LOCAL_MACHINE 系统级设置(所有用户共享) HKCU HKEY_CURRENT_USER 当前登录用户配置 HKCR HKEY_CLASSES_ROOT 文件关联与 COM 信息 HKU HKEY_USERS 所有用户配置 HKCC HKEY_CURRENT_CONFIG 当前硬件配置概要 常见恶意利用位置(重点)
目的 注册表路径 说明 持久化启动 HKLM\Software\Microsoft\Windows\CurrentVersion\Run / HKCU\Software\Microsoft\Windows\CurrentVersion\Run 启动项(最常见) 持久化服务 HKLM\SYSTEM\CurrentControlSet\Services\ 以服务形式自启动 COM 劫持 HKCR\CLSID{GUID}\InprocServer32 修改 COM 加载路径加载恶意 DLL Shell 扩展注入 HKLM\Software\Classes*\shellex\ContextMenuHandlers Explorer 插件注入点 WMI / 脚本持久化 HKLM\Software\Microsoft\Windows\CurrentVersion\WMI 注册事件触发脚本 环境检测 HKLM\Software\VMware、HKLM\Software\Wine 识别虚拟环境 对于自启动程序,微软也给出了 Autoruns 工具可以用于查看。
服务
基础概念
Windows 服务(Windows Service)是系统后台持续运行的程序组件,可在系统启动时自动加载或按需启动,通常以高权限(如 LocalSystem、NetworkService)运行。恶意代码常通过注册、篡改或伪装服务来实现 持久化启动、提权执行 或 隐藏运行。
使用如下命令可查看当前运行的服务,也可利用 Autoruns 工具分析系统启动项与服务持久化点:
net start服务的注册信息存储在注册表路径:
HKLM\SYSTEM\CurrentControlSet\Services\每个子键代表一个服务,包含
ImagePath(可执行路径)、Start(启动类型)、Type(服务类型)等关键字段。
常用 API
名称 描述 典型恶意用途 OpenSCManager 打开服务控制管理器(SCM) 获取管理权限以创建/修改服务 CreateService 创建新的服务项 建立持久化点或安装恶意驱动/组件 OpenService 打开已存在的服务句柄 修改或控制目标服务 StartService 启动指定服务 激活恶意服务执行载荷 ControlService 向服务发送控制命令 用于停止或自删除服务 DeleteService 删除服务注册信息 清理痕迹以反取证 ChangeServiceConfig / ChangeServiceConfig2 修改服务配置 替换合法服务可执行路径(劫持) RegisterServiceCtrlHandler / RegisterServiceCtrlHandlerEx 注册服务控制处理程序 监控系统事件或劫持控制流 CloseServiceHandle 关闭服务句柄 资源释放(通常配合 OpenSCManager 使用) 在恶意代码分析中,若样本导入表中出现上述函数(特别是
CreateService或ChangeServiceConfig),可初步判断其具有服务创建或持久化能力。
服务类型
服务类型字段(
Type)定义了服务的运行方式与所在层级:类型常量 含义 说明 SERVICE_WIN32_OWN_PROCESS (0x10) 独立进程服务 以单独进程运行(常见) SERVICE_WIN32_SHARE_PROCESS (0x20) 共享进程服务 多个服务共用一个进程(通常为 svchost.exe)SERVICE_KERNEL_DRIVER (0x01) 内核驱动服务 驱动类服务,运行于内核态 SERVICE_FILE_SYSTEM_DRIVER (0x02) 文件系统驱动 在引导阶段加载(极高权限) SERVICE_INTERACTIVE_PROCESS (0x100) 可与桌面交互的服务 可与用户交互(较少使用) 启动类型(
Start字段)则决定服务的启动时机:启动值 启动方式 说明 0x0 Boot Start 启动加载(内核驱动) 0x1 System Start 系统加载(驱动层) 0x2 Auto Start 自动随系统启动(常见持久化方式) 0x3 Manual Start 手动启动 0x4 Disabled 已禁用
恶意利用方式(分析要点)
- 持久化启动:通过
CreateService创建自启动服务(Start=2)实现开机运行。 - 权限提升:以
LocalSystem账户运行服务,执行高权限操作或加载驱动。 - 服务劫持:使用
ChangeServiceConfig篡改合法服务的ImagePath指向恶意程序。 - DLL 注入(svchost 伪装):恶意 DLL 作为
ServiceDll被svchost.exe加载,隐藏于系统进程中。 - 驱动加载:创建
SERVICE_KERNEL_DRIVER类型服务,加载内核态 rootkit 驱动。 - 自清理反取证:执行完后调用
DeleteService删除自身注册信息以规避检测。
- 持久化启动:通过
分析与检测建议
- 静态分析:检查导入表是否包含服务管理 API;扫描注册表中新增或异常的服务项。
- 动态分析:监控对
HKLM\SYSTEM\CurrentControlSet\Services的写入及CreateService调用。 - 取证检测:
- 查看服务路径中是否包含异常标识(如
:、\\?\、\\.\pipe\等)。 - 检查
ImagePath指向的文件是否位于非系统目录。 - 核对服务账户(
StartName)是否为高权限账户但非系统服务。 - 对比服务时间戳与系统安装时间,发现异常新增项。
- 查看服务路径中是否包含异常标识(如
组件对象模型(COM, Component Object Model)
基础概念
组件对象模型(COM) 是微软提出的一种二进制接口标准,用于在不同语言、不同进程甚至不同计算机之间进行对象交互。
简单来说,COM 允许程序以“组件”的形式调用和复用其他程序的功能,而不需要关心其底层实现语言或运行环境。例如,一个应用程序可以调用系统提供的 COM 组件(如
Shell.Application)来操作文件系统,也可以调用 IE、Office、WMI、脚本宿主(WScript.Shell)等对象接口。在恶意代码分析中,COM 常被用于:
- 绕过安全防护或白名单机制(通过调用合法 COM 对象执行恶意行为)
- 实现 无文件执行(Fileless Execution)
- 注册表中 COM 劫持(COM Hijacking) 实现持久化
- 调用系统组件实现横向移动或信息收集
COM 的核心结构
COM 的设计基于 接口(Interface) 与 GUID(全局唯一标识符) 的概念:
- CLSID(Class ID):用于标识一个 COM 类对象。例如:
HKCR\CLSID\{00021401-0000-0000-C000-000000000046}
表示 Shell 对象(Explorer 组件)。.rdata:00402058 dword_402058 dd 2DF01h ; {0002DF01- .rdata:0040205C dw 0 ; 0000- .rdata:0040205E dw 0 ; 0000- .rdata:00402060 dw 0C0h ; 00C0- .rdata:00402062 dd 0 ; 00000000 .rdata:00402066 dw 4600h ; 0046} - IID(Interface ID):标识接口类型(对象能做什么)。
- ProgID(程序标识名):面向开发者的可读字符串,例如:
系统通过 ProgID 查找对应的 CLSID,从而定位实现类。WScript.Shell Excel.Application Shell.Application
工作流程:
ProgID → CLSID → InprocServer32 (DLL 路径) → 实例化对象 → 调用接口方法COM 对象通常以 DLL 形式存在,由系统注册在注册表:
HKCR\CLSID\{GUID}\InprocServer32 = "C:\Windows\System32\xxx.dll"- CLSID(Class ID):用于标识一个 COM 类对象。例如:
- COM 的常见类型
类型 说明 示例 In-Process(进程内) 对象作为 DLL 加载到调用进程中 Shell32.dll, MSXML.dll Out-of-Process(进程外) 对象以独立 EXE 进程运行,通过 RPC 通信 Excel.Application, WMI Remote COM(DCOM) 允许跨网络调用 COM 对象 用于远程管理或攻击(如 lateral movement)
- 常用 COM 相关 API
函数 描述 说明 CoInitialize / CoUninitialize 初始化 / 释放 COM 环境 在使用 COM 对象前必须调用 CoCreateInstance 创建 COM 对象实例 根据 CLSID 创建对应对象(常用于脚本或无文件攻击) CoGetClassObject 获取类工厂接口 创建对象的底层方式 CLSIDFromProgID / ProgIDFromCLSID 在 ProgID 与 CLSID 间转换 用于动态加载 COM 对象 CoInitializeSecurity 设置 COM 安全上下文 决定远程 COM 调用权限 CoSetProxyBlanket 设置远程调用的身份认证 用于 DCOM 攻击或特权访问
COM 劫持(COM Hijacking)
定义:
COM 劫持是通过篡改注册表中 CLSID 的InprocServer32路径,让系统在加载合法 COM 对象时改为加载恶意 DLL,从而实现 持久化 或 隐蔽执行。典型注册表路径:
HKCR\CLSID\{GUID}\InprocServer32 HKCU\Software\Classes\CLSID\{GUID}\InprocServer32 ← 用户级劫持点检测与分析要点:
- 检查是否存在与系统默认不同的 CLSID 路径(尤其在 HKCU 下)
- 确认
InprocServer32指向的 DLL 是否来自非系统目录 - 比对 DLL 数字签名与系统版本
- Autoruns 工具可列出所有注册 COM 对象,快速识别异常项
COM 在恶意代码中的常见利用方式
文件操作 / 代码执行
(New-Object -ComObject "WScript.Shell").Run("calc.exe") (New-Object -ComObject "Shell.Application").ShellExecute("powershell.exe", ...)→ 通过合法 COM 对象启动进程,绕过脚本限制或白名单。
无文件攻击(Fileless) 利用
WMI或MSXML2.XMLHTTP对象下载并执行内存中的脚本,无需落地文件。持久化 通过修改
HKCU\Software\Classes\CLSID\{GUID}\InprocServer32指向恶意 DLL,系统调用该 COM 时即触发执行。权限提升 利用高权限 COM 对象(如
MMC20.Application、ShellWindows)执行命令,实现提权。横向移动 借助 DCOM(Distributed COM)远程创建对象执行命令,如:
CoCreateInstanceEx → Excel.Application on remote host常见于渗透框架(如 Cobalt Strike、Empire)模块。
IOC 报告模板
* 文件名:
* SHA256:
* 概要行为:
* 静态发现(可疑 API / URL):
* 动态行为(文件/注册表/网络):
* IOC 列表(域名/IP/注册表/计划任务/服务):
* 缓解建议(阻断域名/IP、删除持久化项、凭证更换):