用于拦截 NTLMv2 哈希的 SMB1 服务器,使用 C 语言编写。
该项目旨在实现一个作为状态机的 SMB1 服务器,能够正确接受并响应客户端请求以欺骗客户端,使其完成 NTLM 身份验证,从而泄露自身的 NTLMv2 哈希(格式与 hashcat/john 兼容)。
该工具面向进攻性安全/红队活动及教育目的(研究 SMB1/NTLM 协议),仅限在您拥有或获得明确授权的环境中使用。
该服务器伪装成一个合法的 SMB1 服务器,并引导客户端通过一个包含 3 个阶段的状态机:

| 状态 | 转换 |
|---|---|
1. NEGOTIATE | 如果收到 SMB NEGOTIATE,在服务器响应后状态转换为 2. CHALLENGE |
2. CHALLENGE | 如果收到 NTLM_NEGOTIATE,在服务器响应后状态转换为 3. AUTH |
3. AUTH | 如果收到 NTLM_AUTH,在服务器响应后状态返回 1. NEGOTIATE |
在实现层面,必须考虑外层的 NetBIOS“封装”,它由 4 个字节组成,其中最后 3 个字节表示 SMB 数据包的长度(以字节为单位)。
每个客户端连接都通过一个状态结构(server.h 中的 client_t)进行跟踪,除了状态机的状态外,该结构还维护:
rx_buf)及其长度,用于缓冲从套接字读取但尚未完全处理的数据;tx_buf,带有偏移量 tx_off),用于缓冲待发送给客户端但尚未完全传输的数据;netbios_header_recv 和 netbios_msg_len 字段,用于跟踪 NetBIOS 头部。收到数据后,会检查是否已收到至少 4 个字节(NetBIOS 头部),确定 SMB 消息的长度,更新状态字段,最后处理消息,并更新客户端的状态以供下次接收。
服务器的主循环基于 poll(),以非阻塞方式同时处理多个连接:

当 NTLM 身份验证完成时,服务器会在屏幕上打印([INTERCEPTED] ...)用户名、主机名、域名以及捕获的 NTLMv2 哈希,格式如下:
username::domain:server_challenge:ntlmv2_response:blob
可直接用于 hashcat(模式 -m 5600)或 john 等破解工具。
gcc/clang)以及 POSIX 工具链(代码使用 BSD 套接字、poll()、signal() 等,因此适用于 Linux/Unix 类环境)。包含一个 Makefile:
make # 构建主服务器 -> ./impostor
make debug # 调试构建(符号、-O0、AddressSanitizer/UBSan)
make clean # 删除生成的目标文件和可执行文件
make run # 构建并运行服务器
或者,等效的手动编译命令为:
gcc -o impostor server.c smb1_parser.c spnego_decoder.c asn1_parser.c ntlm_parser.c
./impostor [port]
port(可选):服务器监听的 TCP 端口。如果省略,则使用 server.h 中定义的默认端口(SERVER_PORT,9000)。该值必须在 1 到 65535 之间。启动时,服务器会打印横幅、版本和配置信息(端口、最大客户端数),然后保持监听连接。当捕获到 NTLMv2 哈希时,拦截的数据(用户名、主机名、域名、哈希)会打印到屏幕上。服务器可通过 Ctrl+C(SIGINT)停止,由 intHandler 处理。
___ ___ _ ___
|_ _|_ __ ___ _ __ / _ \ ___| |_ / _ \ _ __
| || '_ ` _ \| '_ \| | | / __| __| | | | '__|
| || | | | | | |_) | |_| \__ \ |_| |_| | |
|___|_| |_| |_| .__/ \___/|___/\__|\___/|_|
|_| (v.1.0) by Lcky
[*] Version: 1.0
[*] Author: Lcky <luca9vinci at gmail dot com>
[*] Server Info
Port: 9090
Max Clients: 50
[*] Listening on port 9090
[*] Waiting for connections...
[INTERCEPTED] Username: test
[INTERCEPTED] Hostname: KALILINUX-2023-02
[INTERCEPTED] Domain : WORKGROUP
[INTERCEPTED] Hash : test::WORKGROUP:c4ba87a265de9e09:3482d0efa64fc09a94e44faa83d2a936:01010000000000009A3DE84B6235DD01D36FD06DFF4D64BB000000000200080038004E004900490001001E00570049004E002D00310046005800340055004D005000530034005400420004003400570049004E002D00310046005800340055004D00500053003400540042002E0038004E00490049002E004C004F00430041004C000300140038004E00490049002E004C004F00430041004C000500140038004E00490049002E004C004F00430041004C0008003000300000000000000000000000000000000CAFEB574B56CB6139E261228FBFE3075B4FA9393A3B71031AF3280F4D5A27D00A0010000000000000000000000000000000000009001C0063006900660073002F003100320037002E0030002E0030002E00310000000000
^C
[*] Stopping the server...
| 文件 | 描述 |
|---|
server.c / server.h | 入口点、TCP 监听器设置、客户端状态机、基于 poll() 的主循环、RX/TX 缓冲、拦截哈希的打印 |
smb1_parser.c / smb1_parser.h | SMB1 数据包的解析/构建(头部、NEGOTIATE、SESSION_SETUP 命令、flags/flags2 等) |
spnego_decoder.c / spnego_decoder.h | 解码 SMB 消息中包含的 SPNEGO 令牌(认证机制协商、NTLMSSP blob 提取) |
asn1_parser.c / asn1_parser.h | 极简 ASN.1 DER 解析器,供 SPNEGO 解码器用于构建 ASN.1 结构树 |
ntlm_parser.c / ntlm_parser.h | 解析 NTLMSSP 消息(NEGOTIATE、CHALLENGE、AUTHENTICATE)并提取用户名、域名、主机名和 NTLMv2 响应 |
endianness.h | 处理字节序(运行时小端/大端转换)的工具 |
test.c、test2.c | 解析器的测试/实验文件 |
docs/ | 图表和支持材料(状态机示意图、主循环) |