/ 学习笔记 / 2浏览

Wireshark分析RDP服务器专有证书

文章目录
  • 一、定位数据位置
  • 二、提取关键信息
  • 三、总结:快速判断的方法
  • 本文记录一次使用Wireshark分析RDP证书的过程,这次遇到的证书比较特殊,是服务器专有证书(Server Proprietary Certificate),不能直接使用X.509格式的方式查看,当时为了分析这个证书花了不少时间。

    下面记录一下分析过程,不想看过程可以直接跳到第三章节看快速判断方法

    一、定位数据位置

    1. 筛选数据包

    首先筛选RDP协议并找到ServerData Encryption

    2. 定位数据

    定位到serverCertificate字段,就是证书数据

    Remote Desktop Protocol -> serverData -> serverSecurityData -> serverCertificate

    3. 查看数据

    右键serverCertificate那一行,选择“显示分组字节”,以“原始数据”方式显示,看到的就是字段数据了。

    二、提取关键信息

    上一步得到的数据为:

    01000000010000000100000006001c01525341310801000000080000ff00000001000100ed35ff44bcce04b388cce4d949a30712111fd4a82fdde4a26245e5758a713f8b1d3cfe8cfd4393730f7b296c18df1a25b0983fb6f864b956cf6559379635b47bbf69caa76947db43e5bc4ed39299d821b7283f29c7e85555088e17616faef0fcef7902b711acbe01fabf1dd945c5a8a4f24c019a348ad2ecaf67a0ffeacf65a142ee5fa1e11e48d5d8969df007c48daa82ad4eed59276a8673e0faf5932f636d0b1e45e03d7ea2697a438fda3126cdded07944e6cc97119d0931d01726f059fa42b1597c802112d5e753571bac85359d9cd0441d5d4ba3599057eefea251c2708d3375bdb25bea8d19166f007e7f061d86b43366f15de48b679d2e59f594cac00000000000000000080048006001ac441fd87ad6978c35a093a794cb94fd32f8bce3a4ebbf2b24b0f7323eb3ecb633e57c187c4609c3a7811a4731e326e7fafd64c386badcbe5bf28e9e45010000000000000000

    参考微软官方文档:[MS-RDPBCGR]: Server Certificate (SERVER_CERTIFICATE) | Microsoft Learn

    文档中给出了每组字节的含义:

    内容如下表:

    0~31
    dwVersion
    certData (variable)

    文档解释:

    dwVersion (4 bytes): A 32-bit, unsigned integer. The format of this field is described by the following bitmask diagram.

    最开头的4个字节是dwVersion字段,之后的数据就是证书数据certData

    接着看,dwVersion又分为两部分

    内容如下表:

    0~3031
    certChainVersiont

    文档解释:

    certChainVersion (31 bits): A 31-bit, unsigned integer that contains the certificate version.

    t (1 bit): A 1-bit field that indicates whether the certificate contained in the certData field has been permanently or temporarily issued to the server.

    前31个bit是证书链版本(certChainVersion),第32个bit代表有效期类型。

    1. 判断证书链版本

    再看证书链版本的说明:

    Value (31 bits)Meaning
    CERT_CHAIN_VERSION_1
    0x00000001
    The certificate contained in the certData field is a Server Proprietary Certificate (section 2.2.1.4.3.1.1).
    CERT_CHAIN_VERSION_2
    0x00000002
    The certificate contained in the certData field is an X.509 Certificate (section 5.3.3.2).

    certChainVersion的值为0x00000001时,证书属于“服务器专有证书”,格式内容可以参考文档:[MS-RDPBCGR]: Server Proprietary Certificate (PROPRIETARYSERVERCERTIFICATE) | Microsoft Learn

    certChainVersion的值为0x00000002时,证书就属于常见的X.509格式证书。

    这里补充说明一下这个字节怎么读,涉及到一个叫“字节序”的知识点,可以自行百度了解一下,现在例子中就属于“小端序”。

    取证书中前4个字节为例,可以看到证书数据前8个字符是:

    [ 01000000 ]

    一个“字符”代表一位十六进制数,也就是4位二进制。一个字节是8位二进制,那就是2个“字符”表示一个字节,所以每两个字符分为一组,就是4个字节:

    [ 01 ; 00 ; 00 ; 00 ]

    然后以字节位单位从右往左读,得到:

    [ 00000001 ]

    也就是上面所说的0x00000001,那么表示证书属于“服务器专有证书”。

    上面例子中零太多了,不直观,再举个例子,假设Wireshark中看到的数据是:

    [ 12 ; 34 ; 56 ; 78 ]

    那么实际的数据不是87654321,而是:

    [ 78563412 ]

    2. 分析证书内容

    确定了证书版本,下一步就是按照专有证书的格式分析内容。继续参考文档:[MS-RDPBCGR]: Server Proprietary Certificate (PROPRIETARYSERVERCERTIFICATE) | Microsoft Learn

    字段的官方说明:

    dwVersion (4 bytes): A 32-bit, unsigned integer. The certificate version number. This field MUST be set to CERT_CHAIN_VERSION_1 (0x00000001).

    dwSigAlgId (4 bytes): A 32-bit, unsigned integer. The signature algorithm identifier. This field MUST be set to SIGNATURE_ALG_RSA (0x00000001).

    dwKeyAlgId (4 bytes): A 32-bit, unsigned integer. The key algorithm identifier. This field MUST be set to KEY_EXCHANGE_ALG_RSA (0x00000001).

    wPublicKeyBlobType (2 bytes): A 16-bit, unsigned integer. The type of data in the PublicKeyBlob field. This field MUST be set to BB_RSA_KEY_BLOB (0x0006).

    wPublicKeyBlobLen (2 bytes): A 16-bit, unsigned integer. The size in bytes of the PublicKeyBlob field.

    PublicKeyBlob (variable): Variable-length server public key bytes, formatted using the Rivest-Shamir-Adleman (RSA) Public Key structure (section 2.2.1.4.3.1.1.1). The length in bytes is given by the wPublicKeyBlobLen field.

    wSignatureBlobType (2 bytes): A 16-bit, unsigned integer. The type of data in the SignatureBlob field. This field is set to BB_RSA_SIGNATURE_BLOB (0x0008).

    wSignatureBlobLen (2 bytes): A 16-bit, unsigned integer. The size in bytes of the SignatureBlob field.

    SignatureBlob (variable): Variable-length signature of the certificate created with the Terminal Services Signing Key (sections 5.3.3.1.1 and 5.3.3.1.2). The length in bytes is given by the wSignatureBlobLen field.

    版本(4字节):固定值0x00000001

    签名算法ID(4字节):固定值0x00000001,代表RSA算法。

    密钥交换算法(4字节):固定值0x00000001,代表RSA算法。

    公钥类型(2字节):固定值0x0006,代表RSA类型的密钥。

    公钥长度(2字节):表示下边“PublicKeyBlob”公钥值的长度有多长,单位是字节

    公钥对象:根据上面的长度判断占用几个字节。

    签名类型(2字节):固定值0x0008,代表RSA签名。

    签名长度(2字节):表示下边“SignatureBlob签名值的长度有多长,单位是字节

    签名对象:根据上面的长度判断占用几个字节。

    算法已经定死了,所以直接看公钥长度,第13、14字节代表公钥长度,既第25~28个字符,或者直接找0600后面的4个字符:

    [ 1c ; 01 ]

    按小端序读法这个十六进制数就是:

    [ 011c ]

    转换成十进制就是284,就是说公钥对象长度是284个字节,即之后( 284 times 2 = 568 )个字符是公钥对象,注意公钥对象不等于公钥,后面还要继续分析:

    525341310801000000080000ff00000001000100ed35ff44bcce04b388cce4d949a30712111fd4a82fdde4a26245e5758a713f8b1d3cfe8cfd4393730f7b296c18df1a25b0983fb6f864b956cf6559379635b47bbf69caa76947db43e5bc4ed39299d821b7283f29c7e85555088e17616faef0fcef7902b711acbe01fabf1dd945c5a8a4f24c019a348ad2ecaf67a0ffeacf65a142ee5fa1e11e48d5d8969df007c48daa82ad4eed59276a8673e0faf5932f636d0b1e45e03d7ea2697a438fda3126cdded07944e6cc97119d0931d01726f059fa42b1597c802112d5e753571bac85359d9cd0441d5d4ba3599057eefea251c2708d3375bdb25bea8d19166f007e7f061d86b43366f15de48b679d2e59f594cac00000000000000000

    小技巧,复制到记事本里就很方便选取一定长度的字符。

    公钥对象后面必定是0800,也可以用这个帮助判断有没有选对。

    公钥对象分析参考这篇:[MS-RDPBCGR]: RSA Public Key (RSA_PUBLIC_KEY) | Microsoft Learn

    官方字段解释:

    magic (4 bytes): A 32-bit, unsigned integer. The sentinel value. This field MUST be set to 0x31415352.

    keylen (4 bytes): A 32-bit, unsigned integer. The size in bytes of the modulus field. This value is directly related to the bitlen field and MUST be ((bitlen / 8) + 8) bytes.

    bitlen (4 bytes): A 32-bit, unsigned integer. The number of bits in the public key modulus.

    datalen (4 bytes): A 32-bit, unsigned integer. The maximum number of bytes that can be encoded using the public key. This value is directly related to the bitlen field and MUST be ((bitlen / 8) – 1) bytes.

    pubExp (4 bytes): A 32-bit, unsigned integer. The public exponent of the public key.

    modulus (variable): A variable-length array of bytes containing the public key modulus. The length in bytes of this field is given by the keylen field. The modulus field contains all (bitlen / 8) bytes of the public key modulus and 8 bytes of zero padding (which MUST follow after the modulus bytes).

    一个固定值(4字节):0x31415352

    modulus字段的长度(4字节):等于((bitlen / 8) + 8) 个字节。

    bitlen(4字节):公钥的模的比特数。

    可用公钥编码的数据的最大长度(4字节):等于((bitlen / 8) – 1)个字节。

    公钥的E值(4字节):E值,通常是0x00010001,也就是65537。

    modulus字段:包含公钥的模值,即N值,最后用8个字节的零填充。

    所以进行如下操作,modulus字段去掉最后16个零,得到小端序顺序的N值:

    ed35ff44bcce04b388cce4d949a30712111fd4a82fdde4a26245e5758a713f8b1d3cfe8cfd4393730f7b296c18df1a25b0983fb6f864b956cf6559379635b47bbf69caa76947db43e5bc4ed39299d821b7283f29c7e85555088e17616faef0fcef7902b711acbe01fabf1dd945c5a8a4f24c019a348ad2ecaf67a0ffeacf65a142ee5fa1e11e48d5d8969df007c48daa82ad4eed59276a8673e0faf5932f636d0b1e45e03d7ea2697a438fda3126cdded07944e6cc97119d0931d01726f059fa42b1597c802112d5e753571bac85359d9cd0441d5d4ba3599057eefea251c2708d3375bdb25bea8d19166f007e7f061d86b43366f15de48b679d2e59f594cac0

    写了小脚本将小端序转成大端序(正常阅读顺序):

    def read_pairs(input_string):
      if len(input_string) % 2 != 0:
        raise ValueError(" 输入字符串的长度必须是偶数")
      
      pairs = [input_string[i:i+2] for i in range(0, len(input_string), 2)]
      return pairs
    
    little_endian_data = input(" 请输入字符串:")
    pairs = read_pairs(little_endian_data)
    
    integer_in_big_endian = ''
    for pair in pairs:
      integer_in_big_endian = pair + integer_in_big_endian
    
    print(integer_in_big_endian)

    最后提取签名对象的方法也是一样的。

    三、总结:快速判断的方法

    直接看serverCertificate的开头,如果是02那就是X.509的证书,去除前8个字符剩下的就是证书的十六进制数据,转成base64编码保存到文本文件(注意是十六进制转base64,不是字符转base64),重命名为cer后缀即可双击打开。

    X.509格式证书第一个字节是0x30,可以利用这点帮助判断数据正确性。

    如果serverCertificate是以01开头,那属于专有证书。密评中只需要知道用什么算法即可,那签名算法、密钥交换算法都固定是RSA了,直接看第25~28个字符(或0600后的4个字符)得到公钥长度(注意是小端序读法),以此判断是RSA2048还是RSA1024算法,完成!

    Kali系统安装EDIMAX AC1750驱动
    虚拟机加入笔记本电脑热点网段的操作方法
    Linux系统用户最小化检测方法
    企业采购模式扫盲
    安卓APP渗透基础 —— APK安装包的签名机制
    安卓APP渗透基础 —— 四大组件暴露测试

    0

    1. This post has no comment yet

    发表回复

    您的邮箱地址不会被公开。 必填项已用 * 标注