基于Python3的scapy解析SSL报文

        scapy对于SSL的支持个人觉得不太好,至少在构造报文方面没有HTTP或者DNS这种常见的报文有效方便,但是scapy对于SSL的解析还是可以的。下面我们以一个典型的HTTPS的报文为例,展示scapy解析SSL报文。

基于Python3的scapy解析SSL报文_第1张图片

一:解析ClientHello报文

基于Python3的scapy解析SSL报文_第2张图片

from scapy.all import *
from scapy.layers.tls import *

load_layer("tls") 
srcpcap = rdpcap("https_standerd.pcapng")
srcpcap[3].show2()

首先我们读取报文,用rdpcap,然后取ClientHello报文,我们通过索引去获取(从0开始)。需要注意的是我们用Scapy解析SSL需要load_layer(‘tls’),不然就没法解析SSL层的字段

以下是解析的结果

###[ Ethernet ]### 
  dst       = 58:f9:87:b9:6c:92
  src       = 40:b0:76:82:0a:16
  type      = IPv4
###[ IP ]### 
     version   = 4
     ihl       = 5
     tos       = 0x0
     len       = 557
     id        = 17598
     flags     = DF
     frag      = 0
     ttl       = 64
     proto     = tcp
     chksum    = 0x0
     src       = 192.168.1.7
     dst       = 36.152.44.96
     \options   \
###[ TCP ]### 
        sport     = 54402
        dport     = https
        seq       = 1487137542
        ack       = 3503406465
        dataofs   = 5
        reserved  = 0
        flags     = PA
        window    = 1025
        chksum    = 0x14c7
        urgptr    = 0
        options   = []
###[ TLS ]### 
           type      = handshake
           version   = TLS 1.0
           len       = 512    [deciphered_len= 512]
           iv        = b''
           \msg       \
            |###[ TLS Handshake - Client Hello ]### 
            |  msgtype   = client_hello
            |  msglen    = 508
            |  version   = TLS 1.2
            |  gmt_unix_time= Wed, 11 Oct 2062 17:54:57 +0800 (2927814897)
            |  random_bytes= 81fd99aef9407de45a94a6058080ba52474f28033827cc8a149e0e92
            |  sidlen    = 32
            |  sid       = '\\x88\\x9d\u07b9\\xa4U{\\x82\x11[\x1c4\\xdaiA\\xbf.291\\xfe\\xf6*\\xd5C\\xe7\\xe19Y\\x89ٰ'
            |  cipherslen= 34
            |  ciphers   = [0xa0a, TLS_AES_128_GCM_SHA256, TLS_AES_256_GCM_SHA384, TLS_CHACHA20_POLY1305_SHA256, TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, TLS_RSA_WITH_AES_128_GCM_SHA256, TLS_RSA_WITH_AES_256_GCM_SHA384, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_AES_256_CBC_SHA, TLS_RSA_WITH_3DES_EDE_CBC_SHA]
            |  complen   = 1
            |  comp      = null
            |  extlen    = 401
            |  \ext       \
            |   |###[ TLS Extension - Scapy Unknown ]### 
            |   |  type      = 19018
            |   |  len       = 0
            |   |  val       = ''
            |   |###[ TLS Extension - Server Name ]### 
            |   |  type      = server_name
            |   |  len       = 18
            |   |  servernameslen= 16
            |   |  servernames= [b'www.baidu.com']
            |   |###[ TLS Extension - Extended Master Secret ]### 
            |   |  type      = extended_master_secret
            |   |  len       = 0
            |   |###[ TLS Extension - Renegotiation Indication ]### 
            |   |  type      = renegotiation_info
            |   |  len       = 1
            |   |  reneg_conn_len= 0
            |   |  renegotiated_connection= ''
            |   |###[ TLS Extension - Supported Groups ]### 
            |   |  type      = supported_groups
            |   |  len       = 10
            |   |  groupslen = 8
            |   |  groups    = [60138, x25519, secp256r1, secp384r1]
            |   |###[ TLS Extension - Supported Point Format ]### 
            |   |  type      = ec_point_formats
            |   |  len       = 2
            |   |  ecpllen   = 1
            |   |  ecpl      = [uncompressed]
            |   |###[ TLS Extension - Session Ticket ]### 
            |   |  type      = session_ticket
            |   |  len       = 160
            |   |  ticket    = '\\xd0j\\x93\\xcf\x01\\xd4LN\\xf4\\xd1\x10y\\xfeӢ皥%m\\x94똲J\\xfa?\\xd1K\\xfb\\xe5\\xd4b3\\xcbF\x11\\xbcX*\\xd9\\xe1\\xaf\x11-;()\\xc0\x04Ъ\\xff!\x10\\x88\\xab\\xec\\xc0\x03\\xb1\ni\\xe2\\xeb\x19\\xd7\\xd7\\xe5\x19\\xd2l߈\\xf8\\xd5s\\xe3\\xd0sYU-\x7f\\xb3\\xb7X\\xc3+\\xe4\\x96e^\\xeb\\xeb\\xb59A\\xcb\x00\x1c)V\\x8an=\\xb9j\\x91\\xf1"\\xb42\\xb6\\x9cd\\xf8ȋ\\xa4\x02\\xbaL\x14\\xac\\xff\x7f\\xc0w\x0cvO7M\\xe1I\x07*"\\xcd\x17\x10\\x96q\\xd4%\x19G\\xebO\\xa8lnX\\xdc\\xf8\\x93|(\\xfa'
            |   |###[ TLS Extension - Application Layer Protocol Negotiation ]### 
            |   |  type      = alpn
            |   |  len       = 14
            |   |  protocolslen= 12
            |   |  protocols = [b'h2', b'http/1.1']
            |   |###[ TLS Extension - Certificate Status Request ]### 
            |   |  type      = status_request
            |   |  len       = 5
            |   |  stype     = ocsp
            |   |  \req       \
            |   |   |###[ OCSPStatusRequest structure ]### 
            |   |   |  respidlen = 0
            |   |   |  \respid    \
            |   |   |  reqextlen = 0
            |   |   |  reqext    = ''
            |   |###[ TLS Extension - Signature Algorithms ]### 
            |   |  type      = signature_algorithms
            |   |  len       = 20
            |   |  sig_algs_len= 18
            |   |  sig_algs  = [sha256+ecdsa, sha256+rsaepss, sha256+rsa, sha384+ecdsa, sha384+rsaepss, sha384+rsa, sha512+rsaepss, sha512+rsa, sha1+rsa]
            |   |###[ TLS Extension - Scapy Unknown ]### 
            |   |  type      = signed_certificate_timestamp
            |   |  len       = 0
            |   |  val       = ''
            |   |###[ TLS Extension - Key Share (for ClientHello) ]### 
            |   |  type      = key_share
            |   |  len       = 43
            |   |  client_shares_len= 41
            |   |  \client_shares\
            |   |   |###[ Key Share Entry ]### 
            |   |   |  group     = 60138
            |   |   |  kxlen     = 1
            |   |   |  key_exchange= 00
            |   |   |###[ Key Share Entry ]### 
            |   |   |  group     = x25519
            |   |   |  kxlen     = 32
            |   |   |  key_exchange= 914e643fa99e7c4c0a063941936df104be236e16126fc266ad03303353933e05
            |   |###[ TLS Extension - PSK Key Exchange Modes ]### 
            |   |  type      = psk_key_exchange_modes
            |   |  len       = 2
            |   |  kxmodeslen= 1
            |   |  kxmodes   = [psk_dhe_ke]
            |   |###[ TLS Extension - Supported Versions (for ClientHello) ]### 
            |   |  type      = supported_versions
            |   |  len       = 11
            |   |  versionslen= 10
            |   |  versions  = [2570, TLS 1.3, TLS 1.2, TLS 1.1, TLS 1.0]
            |   |###[ TLS Extension - Scapy Unknown ]### 
            |   |  type      = 27
            |   |  len       = 3
            |   |  val       = '\x02\x00\x02'
            |   |###[ TLS Extension - Scapy Unknown ]### 
            |   |  type      = 23130
            |   |  len       = 1
            |   |  val       = '\x00'
            |   |###[ TLS Extension - Padding ]### 
            |   |  type      = padding
            |   |  len       = 43
            |   |  padding   = '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
           mac       = b''
           pad       = b''
           padlen    = None

可以看到SSL协商的字段都能解析出来。我们如果加load_layer("tls") 效果如下

基于Python3的scapy解析SSL报文_第3张图片

Scapy能解析出来的字段,我们当然也能读取出来,比如我们想要提取Server Name字段

基于Python3的scapy解析SSL报文_第4张图片

from scapy.all import *
from scapy.layers.tls import *

load_layer("tls") 
srcpcap = rdpcap("https_standerd.pcapng")
tlsLayer = srcpcap[3][TLS]
print(tlsLayer.layers)
#print(help(tlsLayer))
#clientHelloPart = tlsLayer['TLS Handshake - Client Hello']
clientHelloPart = tlsLayer[TLSClientHello]
#serverNamePart = clientHelloPart['TLS Extension - Server Name']
serverNamePart = clientHelloPart[TLS_Ext_ServerName][ServerName]

print(dir(serverNamePart))

print(f"serverName={serverNamePart.servername}")
print(f"serverNameLen={serverNamePart.namelen}")

提取结果如下: 

在上面的代码中给出了两个方法去一层一层获取我们想要字段,第一种方法可以根据上述解析的层级根据字符串去获取,依此类推找到我们字段所在的层级

基于Python3的scapy解析SSL报文_第5张图片

第二个方法就是打印出tlslayer的层级结构,根据结构的索引字段去获取

基于Python3的scapy解析SSL报文_第6张图片

, , , , , , , , ] |>, , , , ] |>, , , , , ] |>] padlen=None |>>

当然两种方法在取字段的时候还是有细微差别的

from scapy.all import *
from scapy.layers.tls import *
#from scapy_ssl_tls.ssl_tls import *

load_layer("tls") 
srcpcap = rdpcap("https_standerd.pcapng")
tlsLayer = srcpcap[3][TLS]
#print(tlsLayer.layers)
#print(help(tlsLayer))
clientHelloPart = tlsLayer['TLS Handshake - Client Hello']
#clientHelloPart = tlsLayer[TLSClientHello]
serverNamePart = clientHelloPart['TLS Extension - Server Name']
serverLayers = serverNamePart.servernames
#serverNamePart = clientHelloPart[TLS_Ext_ServerName][ServerName]

print(serverLayers)


print(f"serverName={serverLayers[0].servername}")
print(f"serverNameLen={serverLayers[0].namelen}")
print(f"serverNamesLen={serverNamePart.servernameslen}")
#print(f"serverNameLen={serverNamePart.name}")

基于Python3的scapy解析SSL报文_第7张图片

要善于利用help和dir去查找我们想要的方法和函数。 

你可能感兴趣的:(Python,ssl,scapy)