Python Scapy RTP header 操作 - 如何在 scapy 中解码 RTP?
Python Scapy RTP header manipulation - how can I decode RTP in scapy?
我需要编辑 PACP 文件中的 2 个 RTP header 字段。
我想编辑 RTP timestamp
字段和 SSRC
字段。这样一来,出于多种原因,我可以使用 tcpreplay
来操作一些捕获以进行重放以测试终端设备。
使用 Python REPL 我可以加载文件:
from scapy.all import rdpcap
pkts_list = rdpcap("foo.pcap")
我得到文件的长度
len(pkts_list)
然后我可以检查一个数据包
pkts_list[xxx].show()
如何/我可以解码/查看 RTP header 信息?抱歉,scapy 文档在这方面对我来说有点麻烦。
提前致谢
尼尔
RTP(pkts_list[xxx]['UDP'].payload).timestamp
通过反复试验完成了这项工作
我的另一个问题更 python 相关,我会在其他地方问。
更新:
发布我用于操作 RTP headers 的完整代码,因为它需要大量的试验和错误以及非常小的信息才能对其进行排序......它是一个黑客但它有效,可能会对其他人有所帮助。
### Python 2.7 Script by Neil Bernard neil@themoog.org
## This script is for editing RTP header information in PCAP files to manipulate RTP timestamp and SSRC
## for testing hardware transport stream devices and testing SMPTE 2022-2 handling
## There is some error checking for scapy network layers but try to keep capture as clean as possible
## also try to keep captures under 260Mb for performance, can take a good 20mins on an intel i7 / 16GB ram
#### Basic Scapy Tutorial
# *https://www.youtube.com/watch?v=ADDYo6CgeQY
#### Scapy cheat sheet
# https://blogs.sans.org/pen-testing/files/2016/04/ScapyCheatSheet_v0.2.pdf
#### Scapy RTP Library https://fossies.org/linux/scapy/scapy/layers/rtp.py
# import scapy
from scapy.all import rdpcap
from scapy.all import wrpcap
from scapy.all import RTP
from scapy.all import *
infile = "test_rtp.pcap"
outfile = "modified_" + infile
dest_port = 2000 # usefull to make sure you only action packets that are RTP
# load packet capture
print "Loading Packet Capture Keep <200Mb - Might take a few mins....."
pl = rdpcap(infile)
print "Loading complete!"
# print number of packets
print(len(pl))
# # print rtp timestamp
# print(RTP(pl[0][UDP].payload).timestamp)
numberofpckts = len(pl)
print numberofpckts
for pkt in range(numberofpckts):
# You cant use the [RTP] layer on a list index so you have to put it in a
# variable first. Also need to make sure its a UDP packet with .haslayer(UDP):
# https://whosebug.com/questions/48763072/scapy-getting-trailer-field-in-the-dissector
if pl[pkt].haslayer(UDP):
packet = pl[pkt][UDP]
else:
print "Probably Not a UDP / RTP Packet# {0}".format(pkt)
# You need to do the line below to force RTP detection and manipulation
# https://whosebug.com/questions/44724186/decode-rtp-over-udp-with-scapy
if pl[pkt].haslayer(UDP):
if packet["UDP"].dport==2000: # Make sure its actually RTP
packet["UDP"].payload = RTP(packet["Raw"].load)
#### un-commment and change lines below to manipulate headers
# packet[RTP].version = 0
# packet[RTP].padding = 0
# packet[RTP].extension = 0
# packet[RTP].numsync = 0
# packet[RTP].marker = 0
# packet[RTP].payload_type = 0
# packet[RTP].sequence = 0
# packet[RTP].timestamp = 0
packet[RTP].sourcesync = 0
# packet[RTP].sync = 0
### Calculate UDP Checksum or they will now be wrong!
#https://scapy.readthedocs.io/en/latest/functions.html
checksum_scapy_original = packet[UDP].chksum
# set up and calculate some stuff
packet[UDP].chksum = None ## Need to set chksum to None before starting recalc
packetchk = IP(raw(packet)) # Build packet (automatically done when sending)
checksum_scapy = packet[UDP].chksum
packet_raw = raw(packetchk)
udp_raw = packet_raw[20:]
# in4_chksum is used to automatically build a pseudo-header
chksum = in4_chksum(socket.IPPROTO_UDP, packetchk[IP], udp_raw) # For more infos, call "help(in4_chksum)"
# Set the new checksum in the packet
packet[UDP].chksum = checksum_scapy # <<<< Make sure you use the variable in checksum_scapy
# needed below to test layers before printing newts/newsourcesync etc to console
if pl[pkt].haslayer(UDP):
newts = RTP(pl[pkt][UDP].payload).timestamp
newsourcesync = RTP(pl[pkt][UDP].payload).sourcesync
else:
newts = 999
newsourcesync = 999
print("Changing packet {0} of {3} to new timestamp {1} SSRC {2} Old UDP chksum {4} >> New UDP chksum ???").format(pkt+1,newts,newsourcesync,numberofpckts,hex(checksum_scapy_original))
else:
print "Probably Not a UDP / RTP Packet# {0}".format(pkt)
# Write out new capture file
wrpcap(outfile, pl)
您可以使用此命令写入 rtp header 数据包。但是你试图在 pcap 中写入这个数据包。你会看到这个错误:
TypeError: clone_with() got multiple values for keyword argument
'payload'
所以你在写数据包之前必须改变scapy/packet.py lib。这个 link 解释得更好:
https://github.com/CJTozer/scapy/commit/d0367f2efa86e65fa2b0a82a864b7fe89222f153
我需要编辑 PACP 文件中的 2 个 RTP header 字段。
我想编辑 RTP timestamp
字段和 SSRC
字段。这样一来,出于多种原因,我可以使用 tcpreplay
来操作一些捕获以进行重放以测试终端设备。
使用 Python REPL 我可以加载文件:
from scapy.all import rdpcap
pkts_list = rdpcap("foo.pcap")
我得到文件的长度
len(pkts_list)
然后我可以检查一个数据包
pkts_list[xxx].show()
如何/我可以解码/查看 RTP header 信息?抱歉,scapy 文档在这方面对我来说有点麻烦。
提前致谢
尼尔
RTP(pkts_list[xxx]['UDP'].payload).timestamp
通过反复试验完成了这项工作
我的另一个问题更 python 相关,我会在其他地方问。
更新:
发布我用于操作 RTP headers 的完整代码,因为它需要大量的试验和错误以及非常小的信息才能对其进行排序......它是一个黑客但它有效,可能会对其他人有所帮助。
### Python 2.7 Script by Neil Bernard neil@themoog.org
## This script is for editing RTP header information in PCAP files to manipulate RTP timestamp and SSRC
## for testing hardware transport stream devices and testing SMPTE 2022-2 handling
## There is some error checking for scapy network layers but try to keep capture as clean as possible
## also try to keep captures under 260Mb for performance, can take a good 20mins on an intel i7 / 16GB ram
#### Basic Scapy Tutorial
# *https://www.youtube.com/watch?v=ADDYo6CgeQY
#### Scapy cheat sheet
# https://blogs.sans.org/pen-testing/files/2016/04/ScapyCheatSheet_v0.2.pdf
#### Scapy RTP Library https://fossies.org/linux/scapy/scapy/layers/rtp.py
# import scapy
from scapy.all import rdpcap
from scapy.all import wrpcap
from scapy.all import RTP
from scapy.all import *
infile = "test_rtp.pcap"
outfile = "modified_" + infile
dest_port = 2000 # usefull to make sure you only action packets that are RTP
# load packet capture
print "Loading Packet Capture Keep <200Mb - Might take a few mins....."
pl = rdpcap(infile)
print "Loading complete!"
# print number of packets
print(len(pl))
# # print rtp timestamp
# print(RTP(pl[0][UDP].payload).timestamp)
numberofpckts = len(pl)
print numberofpckts
for pkt in range(numberofpckts):
# You cant use the [RTP] layer on a list index so you have to put it in a
# variable first. Also need to make sure its a UDP packet with .haslayer(UDP):
# https://whosebug.com/questions/48763072/scapy-getting-trailer-field-in-the-dissector
if pl[pkt].haslayer(UDP):
packet = pl[pkt][UDP]
else:
print "Probably Not a UDP / RTP Packet# {0}".format(pkt)
# You need to do the line below to force RTP detection and manipulation
# https://whosebug.com/questions/44724186/decode-rtp-over-udp-with-scapy
if pl[pkt].haslayer(UDP):
if packet["UDP"].dport==2000: # Make sure its actually RTP
packet["UDP"].payload = RTP(packet["Raw"].load)
#### un-commment and change lines below to manipulate headers
# packet[RTP].version = 0
# packet[RTP].padding = 0
# packet[RTP].extension = 0
# packet[RTP].numsync = 0
# packet[RTP].marker = 0
# packet[RTP].payload_type = 0
# packet[RTP].sequence = 0
# packet[RTP].timestamp = 0
packet[RTP].sourcesync = 0
# packet[RTP].sync = 0
### Calculate UDP Checksum or they will now be wrong!
#https://scapy.readthedocs.io/en/latest/functions.html
checksum_scapy_original = packet[UDP].chksum
# set up and calculate some stuff
packet[UDP].chksum = None ## Need to set chksum to None before starting recalc
packetchk = IP(raw(packet)) # Build packet (automatically done when sending)
checksum_scapy = packet[UDP].chksum
packet_raw = raw(packetchk)
udp_raw = packet_raw[20:]
# in4_chksum is used to automatically build a pseudo-header
chksum = in4_chksum(socket.IPPROTO_UDP, packetchk[IP], udp_raw) # For more infos, call "help(in4_chksum)"
# Set the new checksum in the packet
packet[UDP].chksum = checksum_scapy # <<<< Make sure you use the variable in checksum_scapy
# needed below to test layers before printing newts/newsourcesync etc to console
if pl[pkt].haslayer(UDP):
newts = RTP(pl[pkt][UDP].payload).timestamp
newsourcesync = RTP(pl[pkt][UDP].payload).sourcesync
else:
newts = 999
newsourcesync = 999
print("Changing packet {0} of {3} to new timestamp {1} SSRC {2} Old UDP chksum {4} >> New UDP chksum ???").format(pkt+1,newts,newsourcesync,numberofpckts,hex(checksum_scapy_original))
else:
print "Probably Not a UDP / RTP Packet# {0}".format(pkt)
# Write out new capture file
wrpcap(outfile, pl)
您可以使用此命令写入 rtp header 数据包。但是你试图在 pcap 中写入这个数据包。你会看到这个错误:
TypeError: clone_with() got multiple values for keyword argument 'payload'
所以你在写数据包之前必须改变scapy/packet.py lib。这个 link 解释得更好:
https://github.com/CJTozer/scapy/commit/d0367f2efa86e65fa2b0a82a864b7fe89222f153