虽然30min解完这些题不是人做的,给谁做的,好难猜哦,但从题目中可以学到不少

题目名为winrm,显然跟winrm流量相关

什么是winrm

Windows远程管理(WinRM) 是微软推出的一种新式的远程管理服务,全称为 Windows Remote Management。它基于 Web服务管理(WS-Management) 标准,使用 HTTPHTTPS 协议进行通信。

很显然,它是基于http(s)通信的。如下,POST请求/wsamn路由

image-20250921234547648

其载体都是加密的

image-20250921234735663

Winrm流量解密相关题目可以追溯到Hack The Box :: Keep the steam going

wp从pcap包中解密Winrm流量 | 0xfd’s blog

在NTLM提取上略有不同

解题

Winrm流量的解密需要用到用户明文密码或NTLM,而这题Winrm通过NTLMv2认证

image-20250921235752976

解密NTLMv2

那么首先就要通过这NTLMv2认证解密出明文密码

NTLMSSP认证流程

NTLMSSP NEGOTIATE  (Type 1)
NTLMSSP CHALLENGE  (Type 2)
NTLMSSP AUTHENTICATE (Type 3)

hashcat 5600模式可以解NTLMv2,需要如下格式

username::domain:ServerChallenge:NTproofstring:modifiedntlmv2response

其中ServerChallenge为一开始客户端向服务端请求后服务端返回的随机数用于后续加密,即NTLMSSP CHALLENGE

image-20250922000941521

其余需要的都在第三个包中,即NTLMSSP AUTHENTICATE

 [truncated]Authorization: Negotiate TlRMTVNTUAADAAAAGAAYAFgAAADQANAAcAAAAAAAAABAAQAAGgAaAEABAAAIAAgAWgEAABAAEABiAQAANYKJ4gAMAAAAAAAPyGFO6Eotc9LyigWux7X78QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFvrDbVNDcb0Nbj6QcHdGRcBAQAAAAAAAC3kGafAItwBABz1SynNCA
    NTLM Secure Service Provider
        NTLMSSP identifier: NTLMSSP
        NTLM Message Type: NTLMSSP_AUTH (0x00000003)
        Lan Manager Response: 000000000000000000000000000000000000000000000000
            Length: 24
            Maxlen: 24
            Offset: 88
        LMv2 Client Challenge: 0000000000000000
        NTLM Response [truncated]: 5beb0db54d0dc6f435b8fa41c1dd191701010000000000002de419a7c022dc01001cf54b29cd0804000000000200080057004900520045000100080044004300300031000400100077006900720065002e0063006f006d0003001a0044004300300031002e0077006900
            Length: 208
            Maxlen: 208
            Offset: 112
            NTLMv2 Response [truncated]: 5beb0db54d0dc6f435b8fa41c1dd191701010000000000002de419a7c022dc01001cf54b29cd0804000000000200080057004900520045000100080044004300300031000400100077006900720065002e0063006f006d0003001a0044004300300031002e00770069
                NTProofStr: 5beb0db54d0dc6f435b8fa41c1dd1917
                Response Version: 1
                Hi Response Version: 1
                Z: 000000000000
                Time: Sep 11, 2025 02:06:14.682935700 UTC
                NTLMv2 Client Challenge: 001cf54b29cd0804
                Z: 00000000
                Attribute: NetBIOS domain name: WIRE
                Attribute: NetBIOS computer name: DC01
                Attribute: DNS domain name: wire.com
                Attribute: DNS computer name: DC01.wire.com
                Attribute: DNS tree name: wire.com
                Attribute: Timestamp
                Attribute: Target Name: WSMAN/dc01.wire.com
                Attribute: Flags
                Attribute: End of list
                padding: 00000000
        Domain name: NULL
        User name: jimmy.mcnulty
            Length: 26
            Maxlen: 26
            Offset: 320
        Host name: KALI
            Length: 8
            Maxlen: 8
            Offset: 346
        Session Key: b7ab6f2695af20dd8ee5d84c0b4ced55
            Length: 16
            Maxlen: 16
            Offset: 354
        Negotiate Flags: 0xe2898235, Negotiate 56, Negotiate Key Exchange, Negotiate 128, Negotiate Version, Negotiate Target Info, Negotiate Extended Session Security, Target Type Domain, Negotiate Always Sign, Negotiate NTLM key, Negotiate Seal
        Version 0.12 (Build 0); NTLM Current Revision 15
            Major Version: 0
            Minor Version: 12
            Build Number: 0
            NTLM Current Revision: 15
        MIC: c8614ee84a2d73d2f28a05aec7b5fbf1

image-20250922001208817

其中,**NTproofstring **+ **modifiedntlmv2response **= ntlmssp.ntlmv2_response

image-20250922001337535

综上,我们可以得到

User name: jimmy.mcnulty
Domain name: NULL
NTLM Server Challenge: e48c2d24282cfdee
NTproofstring + modifiedntlmv2response: 5beb0db54d0dc6f435b8fa41c1dd191701010000000000002de419a7c022dc01001cf54b29cd0804000000000200080057004900520045000100080044004300300031000400100077006900720065002e0063006f006d0003001a0044004300300031002e00770069
NTProofStr: 5beb0db54d0dc6f435b8fa41c1dd1917

整理成hash识别的格式

username::domain:ServerChallenge:NTproofstring:modifiedntlmv2response

jimmy.mcnulty:::e48c2d24282cfdee:5beb0db54d0dc6f435b8fa41c1dd1917:01010000000000002de419a7c022dc01001cf54b29cd0804000000000200080057004900520045000100080044004300300031000400100077006900720065002e0063006f006d0003001a0044004300300031002e0077006900720065002e0063006f006d000500100077006900720065002e0063006f006d00070008002de419a7c022dc0109002600570053004d0041004e002f0064006300300031002e0077006900720065002e0063006f006d0006000400020000000000000000000000

hashcat爆破可以拿到明文密码!StephenKing!

┌──(root㉿7)-[/mnt/d/CTF/AAA比赛/ljb/winrm]
└─# hashcat -m 5600 hash /usr/share/wordlists/rockyou.txt
JIMMY.MCNULTY:::e48c2d24282cfdee:5beb0db54d0dc6f435b8fa41c1dd1917:01010000000000002de419a7c022dc01001cf54b29cd0804000000000200080057004900520045000100080044004300300031000400100077006900720065002e0063006f006d0003001a0044004300300031002e0077006900720065002e0063006f006d000500100077006900720065002e0063006f006d00070008002de419a7c022dc0109002600570053004d0041004e002f0064006300300031002e0077006900720065002e0063006f006d0006000400020000000000000000000000:!StephenKing!

解密WinRM流量

拿到明文密码后可以用h4sh5/decrypt-winrm: decrypting winrm traffic using password/ntlm hash解密winrm流量

也可以用NetA解密

image-20250922002448590

解密完以后,可以看到unwrap_initiate和unwrap_accept一来一回的报文了

其中,像这种rsp:Arguments标签包含的base64字符串一般为客户端下发的命令

<rsp:CommandLine CommandId="B520502C-0FAC-4ED9-B5B0-0A4167FF6CA7">
                        <rsp:Command/>
                        <rsp:Arguments><s:Body>
                <rsp:CommandLine CommandId="B520502C-0FAC-4ED9-B5B0-0A4167FF6CA7">
                        <rsp:Command/>
                        <rsp:Arguments>BASE64-STRING</rsp:Arguments>
                </rsp:CommandLine>
        </s:Body></rsp:Arguments>
                </rsp:CommandLine>
        </s:Body>

随后unwrap_accept中会返回服务器确认命令已接收

		<s:Body>
                <rsp:CommandResponse>
                        <rsp:CommandId>B520502C-0FAC-4ED9-B5B0-0A4167FF6CA7</rsp:CommandId>
                </rsp:CommandResponse>
        </s:Body>

然后客户端请求输出结果

        <s:Body>
                <rsp:Receive>
                        <rsp:DesiredStream CommandId="1CD830C1-E321-47C5-BD65-DDD8D7541D67">stdout</rsp:DesiredStream>
                </rsp:Receive>
        </s:Body>

服务端再以base64形式返回执行结果

        <s:Body>
                <rsp:ReceiveResponse>
                        <rsp:Stream Name="stdout" CommandId="1CD830C1-E321-47C5-BD65-DDD8D7541D67">AAAAAAAAABIAAAAAAAAAAAMAAABSAQAAAAQQBACb1RDbVdU3QZ47pGwNK9KOwTDYHCHjxUe9Zd3Y11QdZ++7vzxTPkM6XFVzZXJzXGppbW15Lm1jbnVsdHlcRG9jdW1lbnRzPC9TPg==</rsp:Stream>
                        <rsp:Stream Name="stdout" CommandId="1CD830C1-E321-47C5-BD65-DDD8D7541D67">AAAAAAAAABMAAAAAAAAAAAMAAABnAQAAAAYQBACb1RDbVdU3QZ47pGwNK9KOwTDYHCHjxUe9Zd3Y11QdZ++7vzxPYmogUmVmSWQ9IjAiPjxNUz48STMyIE49IlBpcGVsaW5lU3RhdGUiPjQ8L0kzMj48L01TPjwvT2JqPg==</rsp:Stream>
                        <rsp:CommandState CommandId="1CD830C1-E321-47C5-BD65-DDD8D7541D67" State="http://schemas.microsoft.com/wbem/wsman/1/windows/shell/CommandState/Done">
                                <rsp:ExitCode>0</rsp:ExitCode>
                        </rsp:CommandState>
                </rsp:ReceiveResponse>
        </s:Body>

其中CommandId为D31ACD39-E58C-40AB-8BB2-078368483B12发现tpye读取了flag

image-20250922003733630

stdout返回的执行结果

U2FsdGVkX19ZjF9+BEQe8OtPJ3D5JqGuSUgahDS+gJ8BtqwHl6goysY7t/JSld8tlxkd6T4vQS9yMbOxctXafQ==

image-20250922003936416

再次解密Salted__开头,显然是被加密的

image-20250922004044997

解密chunk块

再往前发现有超长的base64,解密可以发现Base64Chunk,是在base64分段传输文件

image-20250922004545324

再解密Chunk块,发现是个png

image-20250922004704865

继续解密,拼出所有chunk得到如下图片,key为Omar

download (1)

解密flag

在线解密之前的flag密文

image-20250922010738815

或者脚本解密

EVP_BytesToKey(MD5)

OpenSSL1.x老版本可以解

import base64
from Crypto.Cipher import AES
from hashlib import md5

data = base64.b64decode("U2FsdGVkX19ZjF9+BEQe8OtPJ3D5JqGuSUgahDS+gJ8BtqwHl6goysY7t/JSld8tlxkd6T4vQS9yMbOxctXafQ==")
password = b"Omar"

# 提取盐
assert data[:8] == b"Salted__"
salt = data[8:16]
ciphertext = data[16:]

# EVP_BytesToKey (MD5)
key_iv = b""
prev = b""
while len(key_iv) < 32 + 16:
    prev = md5(prev + password + salt).digest()
    key_iv += prev
key = key_iv[:32]
iv = key_iv[32:48]

cipher = AES.new(key, AES.MODE_CBC, iv)
plaintext = cipher.decrypt(ciphertext)

# 去 PKCS#7 padding
pad_len = plaintext[-1]
plaintext = plaintext[:-pad_len]

print(plaintext.decode())