ntfs备用数据流(ads)不是独立文件,而是通过路径扩展语法(如secret.txt:secret_stream)访问的主文件附属数据流,需用createfile配合正确路径和open_existing标志打开,且受权限、加密、安全软件等多重限制。

NTFS备用数据流在C++中不是文件,而是文件路径的扩展语法
Windows API不提供独立的“打开ADS”的函数,CreateFile 是唯一入口,但必须把ADS当作文件名的一部分来构造路径。比如 secret.txt:secret_stream 才是合法的ADS路径,而 secret.txt 本身只是主数据流。直接对 secret.txt 调用 GetFileSize 或 ReadFile 拿不到ADS内容。
常见错误是试图先用 FindFirstStreamW 枚举流名,再拼错路径——比如漏掉冒号、用正斜杠、或在Unicode路径里混入ANSI字符。ADS名称区分大小写,但Windows资源管理器不显示,容易误判是否存在。
- ADS路径必须用完整UNC或驱动器绝对路径,相对路径(如
./a.txt:stream)会失败 - 流名不能含
\ / : * ? " |,但可以是空格、点、甚至控制字符(需正确编码) -
CreateFile的dwCreationDisposition必须设为OPEN_EXISTING;CREATE_ALWAYS会清空主数据流
用CreateFile + ReadFile读取ADS内容要绕过三类权限检查
即使路径语法正确,CreateFile 仍可能返回 INVALID_HANDLE_VALUE 并报错 ERROR_ACCESS_DENIED。这不是因为没权限读文件,而是ADS触发了额外校验:
- 调用者进程需启用
SE_SECURITY_NAME权限(普通用户默认无),否则无法访问带安全描述符的ADS - 目标文件若被设置为加密(EFS),ADS默认继承加密属性,
CreateFile会静默失败(不报错但句柄无效) - 杀毒软件或EDR常挂钩
NtCreateFile,对ADS路径做拦截,尤其当流名含exe、ps1等敏感后缀时
实操建议:先用 GetLastError() 判断具体错误码;若为 ERROR_ACCESS_DENIED,尝试以管理员身份运行,或改用 BackupRead(需 SE_BACKUP_NAME 权限)绕过部分ACL检查。
BackupRead比ReadFile更适合读取未知长度的ADS
ReadFile 要求预先知道ADS大小,但 GetFileSize 对ADS返回的是主数据流长度。虽然可用 GetCompressedFileSize 获取ADS真实大小,但它在ADS不存在时也返回0,无法区分“空流”和“不存在”。BackupRead 则天然支持流式探测:
HANDLE h = CreateFile(L"test.txt:payload", GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, 0, nullptr);
if (h != INVALID_HANDLE_VALUE) {
BYTE buf[4096];
DWORD read;
while (BackupRead(h, buf, sizeof(buf), &read, FALSE, FALSE, nullptr) && read > 0) {
// 处理buf中read字节
}
CloseHandle(h);
}
注意:BackupRead 需要进程有 SE_BACKUP_NAME 权限(可通过 AdjustTokenPrivileges 启用),且不支持异步I/O。它对已删除但未回收的ADS也有效——这是取证场景的关键优势。
ADS路径解析失败时优先检查符号链接与重解析点
如果 CreateFile 对 a.txt:stream 返回 ERROR_PATH_NOT_FOUND,未必是流不存在。NTFS中符号链接、目录交接点、卷挂载点都可能干扰ADS路径解析:
- 目标文件若位于符号链接指向的目录下,ADS路径必须相对于链接目标,而非链接路径本身
- 某些备份工具会在文件末尾写入重解析点(Reparse Point),导致
CreateFile解析ADS前先跳转到其他位置 -
GetFinalPathNameByHandle可展开路径,但对ADS无效;需先用OpenFileById+FILE_ID_BOTH_DIR_INFO定位原始文件ID,再重建ADS路径
调试时用 fsutil reparsepoint query 和 fsutil usn readdata 查看底层结构,比盲目重试更可靠。
ADS不是隐藏文件夹,它的存在本身依赖路径语法和系统级API行为。任何想绕过Windows安全机制的尝试,都会撞上权限模型、反病毒策略或内核过滤驱动——这些不是技术细节,而是设计前提。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











