基于Python3的scapy解析SSL报文

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

一:解析ClientHello报文

bash 复制代码
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") 效果如下

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

python 复制代码
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}")

提取结果如下:

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

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

bash 复制代码
<bound method Packet.layers of <TLS  type=handshake version=TLS 1.0 len=512    [deciphered_len= 512] iv=b'' msg=[<TLSClientHello  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_Ext_Unknown  type=19018 len=0 |>, <TLS_Ext_ServerName  type=server_name len=18 servernameslen=16 servernames=[b'www.baidu.com'] |>, <TLS_Ext_ExtendedMasterSecret  type=extended_master_secret len=0 |>, <TLS_Ext_RenegotiationInfo  type=renegotiation_info len=1 reneg_conn_len=0 |>, <TLS_Ext_SupportedGroups  type=supported_groups len=10 groupslen=8 groups=[60138, x25519, secp256r1, secp384r1] |>, <TLS_Ext_SupportedPointFormat  type=ec_point_formats len=2 ecpllen=1 ecpl=[uncompressed] |>, <TLS_Ext_SessionTicket  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_Ext_ALPN  type=alpn len=14 protocolslen=12 protocols=[b'h2', b'http/1.1'] |>, <TLS_Ext_CSR  type=status_request len=5 stype=ocsp req=[<OCSPStatusRequest  respidlen=0 reqextlen=0 |>] |>, <TLS_Ext_SignatureAlgorithms  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_Ext_Unknown  type=signed_certificate_timestamp len=0 |>, <TLS_Ext_KeyShare_CH  type=key_share len=43 client_shares_len=41 client_shares=[<KeyShareEntry  group=60138 kxlen=1 key_exchange=00 |>, <KeyShareEntry  group=x25519 kxlen=32 key_exchange=914e643fa99e7c4c0a063941936df104be236e16126fc266ad03303353933e05 |>] |>, <TLS_Ext_PSKKeyExchangeModes  type=psk_key_exchange_modes len=2 kxmodeslen=1 kxmodes=[psk_dhe_ke] |>, <TLS_Ext_SupportedVersion_CH  type=supported_versions len=11 versionslen=10 versions=[2570, TLS 1.3, TLS 1.2, TLS 1.1, TLS 1.0] |>, <TLS_Ext_Unknown  type=27 len=3 val='\x02\x00\x02' |>, <TLS_Ext_Unknown  type=23130 len=1 val='\x00' |>, <TLS_Ext_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' |>] |>] padlen=None |>>

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

bash 复制代码
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}")

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

相关推荐
呆萌的代Ma17 小时前
Linux服务使用Nginx配置域名并使用certbot提供SSL
linux·nginx·ssl
薛定谔的猫喵喵4 天前
【从 HTTP 到 HTTPS】Flask 多项目迁移到 Nginx 子路径完整实战
python·nginx·http·https·flask·ssl
BossFriday5 天前
WhatsApp抓包分析
wireshark·ssl·信息与通信
KnowSafe8 天前
2026年SSL证书市场便宜且安全的SSL证书调研
网络协议·安全·ssl
KnowSafe9 天前
如何用OpenSSL生成CSR文件?
服务器·https·ssl
w1wi9 天前
安卓抓包完全指南(一):从入门到 SSL Pinning 绕过
android·网络协议·ssl
Navicat中国10 天前
使用 SSL/TLS 安全连接数据库
数据库·安全·ssl
成空的梦想11 天前
免费 vs 付费国密 SSL 怎么选?
服务器·网络·网络协议·http·https·ssl
江上清风山间明月13 天前
RPC failed; curl 65 OpenSSL SSL_read: OpenSSL/3.1.2错误解决方法
网络协议·rpc·ssl·failed
Edward1111111115 天前
SSL/TSL配置 集群节点间通信加密还有客户端
linux·服务器·ssl