使用python计算校验和
在对数据包内容进行修改后,需要重新计算校验和。
定义源文件位置、目标文件位置
SourceFile = "E:/temp2/1.cap" NewFile = "E:/temp2/New.cap"
定义函数,用于将小端序转换为大端序
def xD(value):
BigEndian = int.from_bytes(value[::-1], byteorder='big')
HexAdecimal = hex(BigEndian)
return HexAdecimal
定义函数,用于将字节数组转换为十进制整数
def BytearrayToDecimal(ByteArray):
result = int.from_bytes(ByteArray, byteorder='big')
return result
定义函数,用于将整数转换为字节数组
指定长度为2字节
def DecimalToBytearray(Decimal):
result = Decimal.to_bytes(2, 'big')
return result
定义函数用于计算校验和
之前有大哥问我TCP校验和到底都包含哪些内容,借此机会我也做了验证,TCP的校验和计算在下面,慢慢看下去。
def CalculateChecksum(Data):
# 如果数据长度为奇数,补零使其为偶数
if len(Data) % 2 != 0:
Data += b'\x00'
# 计算
Checksum = 0
for i in range(0, len(Data), 2):
Word = (Data[i] << 8) + Data[i+1]
Checksum += Word
if Checksum > 0xffff:
Checksum = (Checksum & 0xffff) + 1
# 取反
Checksum = ~Checksum & 0xffff
# 转换为大端字节序
Checksum = Checksum.to_bytes(2, byteorder='big')
return Checksum
读取源.cap文件
SourceFile = open(SourceFile,'rb')
以字节数组的形式实例化源内容(字节数组可以直接修改)
BtArray = bytearray(SourceFile.read())
关闭源文件,节省内存空间
SourceFile.close()
定义第一个报文头位置索引
Index = 24
定义循环终止条件
DataLength = len(BtArray)
无限循环直至索引位置超出数组长度
while Index < DataLength:
## 修改报文头的时间戳高位,这里的高位数值根据实际需要修改,实现时间脱敏
BtArray[Index+1:Index+4] = b'\x00\x00\x0F'
# 实例化报文头
DataDramHeader = BtArray[Index:Index+16]
# 读取报文的捕获长度
DataDramLength = int(xD(DataDramHeader[8:12]),16)
# 报文头索引
DataDramStart = Index + 16
# 修改MAC地址自定义部分的前两个字节
BtArray[DataDramStart+3:DataDramStart+6-1] = b'\x00\x00'
BtArray[DataDramStart+6+3:DataDramStart+6+6-1] = b'\x00\x00'
# 实例化以太类型
EthType = BtArray[DataDramStart+12:DataDramStart+14]
# 二层负载索引,同时也是三层头索引
PktL2PayStart = DataDramStart + 14
# 如果是ARP报文,将报文内的MAC地址和IP地址脱敏
if EthType == b'\x08\x06':
BtArray[PktL2PayStart+8+3:PktL2PayStart+8+6-1] = b'\x00\x00'
BtArray[PktL2PayStart+8+6+1:PktL2PayStart+8+6+4-1] = b'\x00\x00'
BtArray[PktL2PayStart+8+6+4+3:PktL2PayStart+8+6+4+6-1] = b'\x00\x00'
BtArray[PktL2PayStart+8+6+4+6+1:PktL2PayStart+8+6+4+6+4-1] = b'\x00\x00'
# 如果是IP报文
elif EthType == b'\x08\x00':
L3Start = PktL2PayStart
Protocol = BtArray[L3Start+9:L3Start+10]
# IP地址脱敏
BtArray[L3Start+12+1:L3Start+12+4-1] = b'\x00\x00'
BtArray[L3Start+16+1:L3Start+20-1] = b'\x00\x00'
# 实例化IP首部长度
IPHeaderLength = (BtArray[L3Start+0] & 0x0f)*4
# 实例化IP总长度
IPTotalLength = BytearrayToDecimal(BtArray[L3Start+2:L3Start+4])
# 实例化IP首部
IPHeader = BtArray[L3Start:L3Start+IPHeaderLength]
# 将校验和字段设置为0
IPHeader[10:12] = b'\x00\x00'
# 重新计算IP校验和
NewChecksum = CalculateChecksum(IPHeader)
# 修改IP校验和
BtArray[L3Start+10:L3Start+12] = NewChecksum
# 实例化IP地址,用于构建伪首部
SrcIP = BtArray[L3Start+12:L3Start+16]
DstIP = BtArray[L3Start+16:L3Start+20]
# 如果是TCP报文
if Protocol == b'\x06':
# 定义七层数据索引
TcpDataOffset = (BtArray[L3Start + IPHeaderLength +12] & 0xf0)>>2
L7Start = L3Start + IPHeaderLength + TcpDataOffset
# 修改七层数据
# 构建伪首部,用于计算TCP校验和
# 经过实践验证,之前昂哥问的TCP校验和计算覆盖这些内容:
# 首先是伪首部:源IP + 目的IP + 一字节0 + IP协议号 + 二字节TCP分段长度(包含TCP头和TCP负载)
TcpLengthBtArray = DecimalToBytearray(IPTotalLength - IPHeaderLength)
TcpPseudoHeader = SrcIP + DstIP + b'\x00' + Protocol + TcpLengthBtArray
# 实例化分段
Segment = BtArray[L3Start+IPHeaderLength:L3Start+IPTotalLength]
# 分段校验和字段置0
Segment[16:18] = b'\x00\x00'
# 重新计算TCP校验和
## 然后是将伪首部与TCP分段拼接在一起,不要忘记先把原来的校验和置0
PseudoSegment = TcpPseudoHeader + Segment
NewChecksum = CalculateChecksum(PseudoSegment)
# 修改TCP校验和
BtArray[L3Start+IPHeaderLength+16:L3Start+IPHeaderLength+18] = NewChecksum
# 如果是UDP报文
elif Protocol == b'\x11':
# 定义七层数据索引
L7Start = L3Start + IPHeaderLength + 8
SrcPort = BtArray[L3Start+IPHeaderLength+0:L3Start+IPHeaderLength+2]
DstPort = BtArray[L3Start+IPHeaderLength+2:L3Start+IPHeaderLength+4]
# 修改七层数据
# 如果是DHCP 【TLV字段的脱敏办法容我慢慢思考】
if SrcPort == b'\x00\x44' or SrcPort == b'\x00\x43':
BtArray[L7Start+12+1:L7Start+16-1] = b'\x00\x00'
BtArray[L7Start+16+1:L7Start+20-1] = b'\x00\x00'
BtArray[L7Start+20+1:L7Start+24-1] = b'\x00\x00'
BtArray[L7Start+24+1:L7Start+28-1] = b'\x00\x00'
BtArray[L7Start+28+3:L7Start+34-1] = b'\x00\x00'
else:
pass
# 实例化UDP数据
UdpPart = BtArray[L3Start+IPHeaderLength:L3Start+IPTotalLength]
# 分段校验和字段置0
UdpPart[6:8] = b'\x00\x00'
# 构建伪首部,并重新计算UDP校验和
UdpPseudoHeader = SrcIP + DstIP + b'\x00' + Protocol + BtArray[L3Start+IPHeaderLength+4:L3Start+IPHeaderLength+6]
PseudoUdpPart = UdpPseudoHeader + UdpPart
NewChecksum = CalculateChecksum(PseudoUdpPart)
# 修改UDP校验和
BtArray[L3Start+IPHeaderLength+6:L3Start+IPHeaderLength+8] = NewChecksum
else:
pass
# 定义下一个报文头位置索引
Index = Index+DataDramLength+16
修改后的数据写入目标.cap文件
with open(NewFile,'wb') as f:
f.write(BtArray)
我就学习一下,望点赞收藏关注,谢谢。 感谢阅读!