windows sam文件无法被直接读取,因其由lsass进程独占持有并受内核级保护;合法获取哈希需通过lsass内存提取(需sedebugprivilege且绕过ppl)或离线导出sam+system hive后用bootkey解密。

无法直接读取。Windows SAM 文件受系统内核级保护,普通用户态程序(包括 C++ 程序)即使以管理员权限运行,也无法通过 fopen、CreateFileA 等常规 API 打开 C:WindowsSystem32configSAM —— 会立即返回 ERROR_ACCESS_DENIED 或 ERROR_SHARING_VIOLATION。
为什么连 Administrator 也打不开 SAM 文件
SAM 文件在 Windows 启动后由 LSASS.exe 进程独占持有,并被标记为 FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM,且其所在注册表 hive(REGISTRYMACHINESAM)被内核通过 ObRegisterCallbacks 和对象句柄访问控制列表(DACL)严格拦截。即使你绕过文件系统层用 \.C: 原始设备读取,也会触发 CI.dll 的完整性检查或导致 BSOD。
- 调用
CreateFileW(L"\\.\C:\Windows\System32\config\SAM", ...)返回INVALID_HANDLE_VALUE,GetLastError()是5 (ACCESS_DENIED) - 尝试用
RegLoadKeyW(HKEY_LOCAL_MACHINE, L"SAM_TMP", L"C:\Windows\System32\config\SAM")会失败,错误码通常是ERROR_PRIVILEGE_NOT_HELD或ERROR_INVALID_PARAMETER - 哪怕挂载离线镜像(DISM /Mount-Image),SAM 仍处于“只读加载但不可导出”的状态,
regedit里能看到键,但无法导出子项或读取V值(即 NTLM hash 存储位置)
合法可操作的替代路径:通过 LSASS 进程内存提取(需 SeDebugPrivilege)
真正能拿到哈希的地方是 lsass.exe 内存中解密后的 _LSA_SECRET 或 _CRYPTO_KEY 结构,但这属于进程注入/调试范畴,不是“读取文件”。C++ 可实现,但必须满足:
- 进程以
SeDebugPrivilege权限启动(需AdjustTokenPrivileges) - 目标系统未启用
PPL (Protected Process Light)—— Win10 1607+ 默认开启,会阻止对lsass.exe的 OpenProcess - 使用
MiniDumpWriteDump或直接ReadProcessMemory配合 Mimikatz 类解析逻辑(如搜索lsasrv!LogonSessionList链表) - 注意:Windows Defender 等 EDR 会将此类行为标记为高危,
lsass.exe的堆内存常被加密或 obfuscated
示例片段(仅示意流程,非完整可用代码):
HANDLE hProc = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid_of_lsass); // 必须先 CheckRemoteDebuggerPresent + NtQueryInformationProcess 判断 PPL 状态 // 然后遍历内存页,定位 LSASS 的 LSA_HASH_LIST 或类似结构 // 实际解析依赖逆向分析,无公开稳定 ABI
离线场景下唯一可行方案:使用 Windows 自带工具导出 SYSTEM+SAM 组合
如果你有物理访问权限且系统已关机(或从 WinPE 启动),可借助 Windows 内置命令组合获取可解析的数据:
- 在 WinPE 中执行:
reg save HKLMSAM C: empSAM.hive && reg save HKLMSYSTEM C: empSYSTEM.hive - 这两个 hive 文件不带实时锁,C++ 可用
RegLoadKeyW加载到临时 key 下(如HKEY_CURRENT_USERTempSAM) - 但注意:
SAM.hive中的密码哈希是加密存储的,密钥来自SYSTEM.hive的ControlSet001ControlLsaJD /Skew1 /GBG /Data四个值,需实现 AES-128 解密(密钥派生算法为RC4+MD4(SYSTEM-key)) - 开源库如
mimikatz的sekurlsa::sam或 Python 的pywin32+dpapi模块已封装该逻辑;纯 C++ 实现需手动处理 RC4 密钥调度和 AES ECB 解密
真正难点不在“读文件”,而在绕过内核保护机制或正确还原加密密钥链。即便拿到原始字节,没有 SYSTEM hive 中的 bootkey,SAM 里的 V 值仍是乱码。多数人卡在这一步,而不是 fopen 失败本身。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











