我正在 python 中试验 scapy 并捕获了一个测试 pcap,其中仅包含通过 HTTP 的文件传输。文件内容是明文。
我正在尝试从根本上更改服务器字符串:
HTTP/1.0 200 OK
Server: SimpleHTTP/0.6 Python/3.11.8
对于另一位,我们可以说:
HTTP/1.0 200 OK
Server: A custom one
问题是,经过此更改后,数据包的大小发生了变化,因此许多 TCP 数据包被标记为重传,HTTP 数据包的内容显示字节丢失等。
有没有办法修改字符串 - 以及相应的大小字段 - 以便 pcap 保持没有错误?
附注我尝试更改以太网层的帧长度和捕获长度字段,但仍然出现错误。
我暂时的演示脚本是:
from scapy.all import *
def replace_user_agent(packets):
i = 0
for packet in packets:
i+=1
if packet.haslayer(Raw):
raw = packet[Raw].load
if b"SimpleHTTP/0.6 Python/3.11.8" in raw:
raw = raw.replace(b"SimpleHTTP/0.6 Python/3.11.8", b"A custom one"+ b" " * (len("SimpleHTTP/0.6 Python/3.11.8") - len("A custom one"))) # cover the missing length with spaces
packet[Raw].load = raw
# Recalculate length fields and checksums
if packet.haslayer(IP):
del packet[IP].len # Recalculate IP length
del packet[IP].chksum # Recalculate IP checksum
if packet.haslayer(TCP):
del packet[TCP].chksum # Recalculate TCP checksum
elif packet.haslayer(UDP):
del packet[UDP].len # Recalculate UDP length
del packet[UDP].chksum # Recalculate UDP checksum
return packets
if __name__ == "__main__":
input_pcap = "input.pcap"
output_pcap = "output.pcap"
packets = rdpcap(input_pcap)
modified_packets = replace_user_agent(packets)
wrpcap(output_pcap, modified_packets)
这个脚本实现了我想要实现的目标,但没有实现我想要实现的目标。它基本上用我的较短的自定义字符串替换了服务器字符串,并且对于丢失的字节,它只使用空格。
根据需要向修改后的数据包添加填充可消除警告/错误
from scapy.all import *
from scapy.utils import rdpcap
from scapy.layers.inet import TCP
from scapy.layers.http import *
def parse_pkts(pkts, write=True):
for pkt in pkts:
if Raw in pkt and pkt[Ether][TCP].sport == 8000 and 'Server: ' in pkt[Raw].fields['load'].decode('ascii'):
#print(pkt.show())
needle = "netcat.local"
new_needle= 'XXXX'
payload = pkt[Raw].fields['load'].decode('ascii').replace(needle, "XXXX")
print(pkt[Raw].fields['load'], len(pkt))
pkt[Raw].load = payload.encode('ascii') #fields['load']
pad = "\x00"*(len(pkt) - len(payload))
pkt = pkt/Padding(pad)
print(pkt[Raw].fields['load'], len(pkt))
if write:
wrpcap(f'{dstdir}/test-scapy-mangled.pcap', pkt, append=True)
dstdir = '/home/lmc/projects/forensics'
pkts=rdpcap(f"{dstdir}/test-netcat-local.pcapng")
parse_pkts(pkts)
pkts=rdpcap(f'{dstdir}/test-scapy-mangled.pcap')
parse_pkts(pkts, write=False)
输出
b'HTTP/1.1 200 OK\r\nServer: netcat.local\r\nConnection: Close\r\n\r\n\nresponse from parent.example.com:8000\n' 165
b'HTTP/1.1 200 OK\r\nServer: XXXX\r\nConnection: Close\r\n\r\n\nresponse from parent.example.com:8000\n' 223
b'HTTP/1.1 200 OK\r\nServer: XXXX\r\nConnection: Close\r\n\r\n\nresponse from parent.example.com:8000\n\x00\x00\x00\x00\x00\x00\x00\x00' 223
b'HTTP/1.1 200 OK\r\nServer: XXXX\r\nConnection: Close\r\n\r\n\nresponse from parent.example.com:8000\n\x00\x00\x00\x00\x00\x00\x00\x00' 347
tshark
不抱怨
tshark -r /home/lmc/projects/forensics/test-scapy-mangled.pcap
1 0.000000 127.0.0.1 → 127.0.0.1 TCP 74 36994 → 8000 [SYN] Seq=0 Win=65495 Len=0 MSS=65495 SACK_PERM TSval=3035651634 TSecr=0 WS=128
2 0.000017 127.0.0.1 → 127.0.0.1 TCP 74 8000 → 36994 [SYN, ACK] Seq=0 Ack=1 Win=65483 Len=0 MSS=65495 SACK_PERM TSval=3035651634 TSecr=3035651634 WS=128
3 0.000027 127.0.0.1 → 127.0.0.1 TCP 66 36994 → 8000 [ACK] Seq=1 Ack=1 Win=65536 Len=0 TSval=3035651634 TSecr=3035651634
4 0.000068 127.0.0.1 → 127.0.0.1 HTTP 143 GET / HTTP/1.1
5 0.000074 127.0.0.1 → 127.0.0.1 TCP 66 8000 → 36994 [ACK] Seq=1 Ack=78 Win=65408 Len=0 TSval=3035651634 TSecr=3035651634
6 0.000086 127.0.0.1 → 127.0.0.1 TCP 165 HTTP/1.1 200 OK [TCP segment of a reassembled PDU]
7 0.000094 127.0.0.1 → 127.0.0.1 TCP 66 36994 → 8000 [ACK] Seq=78 Ack=100 Win=65536 Len=0 TSval=3035651634 TSecr=3035651634
8 0.000104 127.0.0.1 → 127.0.0.1 HTTP 66 HTTP/1.1 200 OK
9 0.000133 127.0.0.1 → 127.0.0.1 TCP 66 36994 → 8000 [FIN, ACK] Seq=78 Ack=101 Win=65536 Len=0 TSval=3035651634 TSecr=3035651634
10 0.000140 127.0.0.1 → 127.0.0.1 TCP 66 8000 → 36994 [ACK] Seq=101 Ack=79 Win=65536 Len=0 TSval=3035651634 TSecr=3035651634
如果没有填充,tshark
会显示警告
HTTP 165 HTTP/1.1 200 OK [Packet size limited during capture]