bypassEDR_hashdump_V1 加固版:reg.exe 白利用导出 hash,静态指纹清零,火绒 360 双测
这是什么?
一款 Windows 下单文件离线 HashDump 工具(代号 bypassEDR_hashdump_V1)的静态加固版。在 SYSTEM 上下文一次运行,直接打印本机 SAM 本地账号 NTLM/LM 与 缓存域凭据 DCC2。
这不是原版的重发,而是做了一层专门针对 360 QVM 静态 / 火绒的混淆加固之后的新版本——在「行为面靠 reg.exe 白利用」的基础上,把 静态指纹也清零了:
核心能力:
单 EXE(约 94KB、静态去符号、带自洽 PE 资源),目标机跑一次即出可 diff 的 hash
敏感读取全由微软签名白程序 reg.exe export 完成,本进程零直读 SAM
静态面:敏感字面量 hex 低熵编码 + volatile 解码,360 QVM 无高熵字节块可抓;一次发布一换 XORKEY
不导出 SYSTEM hive——bootkey 从 Lsa 子键 class 活体读取
附带 --keep 保留 .reg 取证、--selftest 加密自检(13/13)
为什么取 Hash 这么麻烦?
红队横向 / 取证常要一台机器的本地口令哈希,目标就两类:
SAM 本地账号 的 NTLM/LM
缓存域凭据(最近登录过的域账号,存 DCC2)
经典打法 secretsdump.py 有三座大山:
得把 SAM / SYSTEM / SECURITY 三个 hive 原样取回来——Vista 后 SAM/SECURITY 只放 SYSTEM 读,取 hive 本身就是高危动作
攻击机得是 Windows + Python + impacket,Linux 攻击机还得 .reg → 还原 hive 绕一大圈
目标机有杀软/EDR 时,reg save、卷影拷贝、直读 SAM 句柄——全是必拦项
一句话:工具链越重,暴露面越大。 而常见 HashDump 工具本身往往还有一个死穴——字符串明文裸奔:reg.exe、HKLMSAM、NTPASSWORD、qwerty 常量全躺在 .rdata 里,360 QVM 的「高熵字节块 + 特征串」一拍一个准。本版把这层也补上了。
核心思路一:脏活全交给微软签名的 reg.exe(行为面)
V1 不是跟 EDR 拼特征,而是不碰 EDR 想拦的东西:
所有敏感读取,全部交给微软签名的 reg.exe export HKLMSAM / HKLMSECURITY。 我们进程拿到的只是 reg.exe 自己导出的 纯文本 .reg, 之后全程本地纯 CPU 解密——没有第二次敏感系统调用。
EDR 天天拦 reg save、拦直开 RegistryMachineSAM、拦 VSS,却很少拦管理员常用的 reg.exe export HKLMSAM——签名白程序、普通读键语义,规则引擎眼里就是日常操作。这是原版项目 AabyssZG/HashDump-BypassEDR 的核心盲点,V1 完整继承。
核心思路二:静态指纹清零,专打 360 QVM / 火绒(本版重点)
行为面再干净,产物本身若被静态一眼看穿,投递层就白做了。这一版针对 360 QVM 的静态判定习惯(高熵字节块 → "Malware.gen"、加壳 → "壳即恶意"、字符串特征 → "Trojan/PSW")做了四件事:
连错误提示、$DCC2$ 输出格式、hh8_ 临时目录前缀这些"看着无害"的串,也全部走同一张 xstr 表——二进制里没有任何一条可 grep 的提示链。整份产物约 94KB,是给杀软"一个普通小工具的观感",而不是"一个 HashDump 的观感"。
一句话:行为面交给微软白程序,静态面把指纹抹到 strings 都扫不出来。
相比原版,更近一步
原版也是"reg.exe 导出"思路,却卡在攻击机侧太重:导出 3 个 .reg 后还要在(同样得是 Windows 的)攻击机上跑 PowerShell 把文本 reg 导回注册表、再 reg save 还原成 hive,才轮到 secretsdump。V1 把解密整体搬进了目标机:
如何使用?
只需一个 EXE,以 SYSTEM 运行一次。
1. 把 hashdump.exe 投到目标机
2. 以 SYSTEM 权限运行(非 SYSTEM 会明确报错退出,不给空结果)
3. stdout 直接打印 hash 行
4. 临时 .reg 用后自删(--keep 可保留取证)

目标机拉起 SYSTEM 的常用姿势:
# PsExec
PsExec64.exe -s -accepteula hashdump.exe
# 计划任务(stdout 重定向落盘再取回)
schtasks /create /tn hd /tr "cmd /c hashdump.exe > C:windowstemph.txt" /ru SYSTEM /sc once /st 00:00
schtasks /run /tn hd && schtasks /delete /tn hd /f为什么必须 SYSTEM? Vista 后 SAM/SECURITY 对普通管理员都不放读,管理员跑 export 拿到的是空文件。工具检测到导出过小就明确退出——不会给你一份"看起来成功其实空"的结果。
输出长什么样?
# SAM 本地账号(pwdump 格式)
Administrator:500:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
# 缓存域凭据(secretsdump 的 $DCC2$ 格式)
corp.local/alice:$DCC2$10240DCC2 行对应 hashcat -m 2100,离线即可爆破,无需回连域控
stdout 直接可与 impacket secretsdump.py 对 diff,验证零成本
技术原理
整条解密链与 impacket/secretsdump.py 常量、偏移逐行对齐,可看作"把 secretsdump 从 hive 读取换成 .reg 文本读取,再内联进一个 exe"。
Bootkey —— 不用导 SYSTEM 了
bootkey 就躺在 HKLMSYSTEM...Lsa{JD,Skew1,GBG,Data} 四个键的 class 字符串里(32 个半字节按固定置乱表排布)。class 字段进不了 .reg,所以这步活体读注册表——但只读 class,无敏感内容出进程,也就没有"读 SAM"那种特征。按表反置乱即得 16 字节 bootkey。
SAM 账号 —— F 解锁、V 记账、DES 落地
DomainsAccount 的 F 值存着加密的 hashed boot key:老式 rev1 走 MD5(salt+qwerty+boot+digits) 派生 RC4 流(带校验和防 bootkey 读错);Vista+ rev2 走 AES-128-CBC
每个账号在 Users<RID>V(固定 0xCC 头)里记自己的加密 NT/LM:新式 AES、旧式 RC4(MD5(hboot+RID+"NTPASSWORD�"))
最后 16 字节再按 RID 派生两个 DES 密钥拆两半解一遍——RID 参与密钥派生,防互相套用
缓存域凭据 —— 三级派生一把 AES
PolEKList:按 SHA256(bootkey + salt×1000) 派 AES-256 key,解出 LSAKey
再按 SHA256(LSAKey + salt×1000) 解出 NL$KM,取后 16 字节当缓存记录 AES key
每条 CacheNL$N 用自己的 IV 做 AES-128-CBC 链式解密,明文前 16 字节即 hash,后按"用户名长度+pad → 短域 pad → 域名字节"布局抠出 domain/user
迭代数看 NL$IterationCount(>10240 对齐 4096 倍数,否则 ×1024,缺省 10240)——就是 $DCC2$ 里那个数
一个吃细节的坑:impacket 对 LSA 类密钥的 AES 语义是分裂的——全零 IV 逐 16 字节块独立解密,非零 IV 才跨块链式。V1 的 AES-CBC 两套语义都复刻了,分别伺候 PolEKList/NL$KM(逐块)和缓存记录(链式),少一边解出来都是花屏。
加密原语零依赖:MD5/SHA-256/RC4/DES/AES-128-CBC 全纯 C 自实现、静态链接,不引 libcrypto——省体积,也少 crypto.dll 导入特征。
免杀/查杀效果实测
设计上收敛的检测面
反面要承认的:字节层/行为层设计 ≠ 落地实锤。进程名、导出文件名、hh8_ 目录名是稳定可查的行为痕迹(--keep 还会把 .reg 留在 %TEMP%),杀软完全能对"reg export + XOR + 起 reg.exe"这类组合做规则化;360 主防盯上"SYSTEM 下读 bootkey + 导 SAM + 本地解密"这套真实行为时,任何做同样事的工具都难独善其身。所以正确用法是:产物当单次使用消耗品,投递层再做一次变异(loader 基建管这层)——不是能长期驻留的东西。本工具侧能做的,是把"看起来像一个 HashDump"这件事做到最小。