Search code examples
pythonreplaceip-addressscapy

How to replace the IP addresses within a PCAP file using Scapy


I want to replace the IP addresses in a given PCAP file with Scapy.

The PCAP file (e.g. eth0.pcap) contains captures by Wireshark. My message is not code, it shows the data flow between 2 IP addresses. I want to replace the original 2 addresses with another 2 addresses.

Example

Given before:

message1: 192.168.10.10-->192.168.20.20

message2: 192.168.20.20-->192.168.10.10

I want to replace for all packages within the file:

  • 192.168.10.10 (source of first package) with 8.8.8.8
  • and 192.168.20.20 (destination of first package) with 1.1.1.1

So that afterwards there are:

message1: 172.10.10.10-->172.10.20.20

message2: 172.10.20.20-->172.10.10.10

How can I do this with?


Solution

  • So you want to modify packet capture output, like in PCAP file format. This format is used by libpcap library to record captured packets to a file.

    Scapy can read and write PCAP files, see the Scapy docs for PCAP.

    Read, write, print, replace

    To replace the IP addresses within this file, you have to read its packets into an object-model using the rdpcap() function.

    Then you can print the IP addresses for each packet (with desired replacement).

    Or you can also replace the IP within the object-model in memory. Then write the complete model back using the wrpcap() function.

    Example to print IP addresses

    I used the example PCAP file dhcp.pcap from PCAP to Mermaid parser on GitHub:

    from scapy.all import *
    
    # load the PCAP file using rdpcap
    packets = rdpcap('dhcp.pcap')
    
    # Let's iterate through every packet
    for packet in packets:
        source_ip = packet.getlayer(IP).src
        destination_ip = packet.getlayer(IP).dst
        print(f"{source_ip} --> {destination_ip}")
    
    # TODO: replace in model and write to PCAP file using wrpcap
    

    See also


    Update:

    How to replace in your case

    Refined talentldk's solution with some simplification and debug-prints:

    • no separate import needed (all imports all)
    • no writer needed, just use wrpcap to write the read model
    • use a replacement-dict with string's replace function where dict entry (a tuple) is passed to function using the unpack-operator * as prefix resulting in 2 separate arguments (key is replaced by value)
    • use iter over the dict's items to process all replacements (here 2 entries) where the next item can be drawn by next function
    from scapy.all import *
    
    # rdpcap loads in our pcap file
    packets = rdpcap('dhcp.pcap')
    
    # define search
    first_src_ip = packets[0][IP].src
    first_dst_ip = packets[0][IP].dst
    
    # define new ip address to use as replacement
    ip_replacement = {f"{first_src_ip}" : '8.8.8.8', f"{first_dst_ip}" : '1.1.1.1'}
    print(f"replacement: {ip_replacement}")
    
    # Let's iterate through every packet
    for i, packet in enumerate(packets):
        source_ip = packet.getlayer(IP).src
        destination_ip = packet.getlayer(IP).dst
        print(f"[{i:3}] original: {source_ip} --> {destination_ip}")
    
        # replace in model
        replacement = iter(ip_replacement.items())
        source_ip = source_ip.replace(*next(replacement))
        destination_ip = destination_ip.replace(*next(replacement))
        print(f"[{i:3}] replaced: {source_ip} --> {destination_ip}")
    
    
    wrpcap("dhcp_replaced.pcap", packets)
    

    Prints:

    replacement: {'0.0.0.0': '8.8.8.8', '255.255.255.255': '1.1.1.1'}
    [  0] original: 0.0.0.0 --> 255.255.255.255
    [  0] replaced: 8.8.8.8 --> 1.1.1.1
    [  1] original: 192.168.0.1 --> 192.168.0.10
    [  1] replaced: 192.168.0.1 --> 192.168.0.10
    [  2] original: 0.0.0.0 --> 255.255.255.255
    [  2] replaced: 8.8.8.8 --> 1.1.1.1
    [  3] original: 192.168.0.1 --> 192.168.0.10
    [  3] replaced: 192.168.0.1 --> 192.168.0.10