0

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?

hc_dev
  • 8,389
  • 1
  • 26
  • 38
talentldk
  • 43
  • 5
  • What do you mean by `cap`? What is your code so far, any [example]? – hc_dev Jun 14 '22 at 17:16
  • emmm, cap means pcap file captures by wireshark, like eth0.pcap. my message is not code, it shows the data flow between 2 IP address. I want to replace the orinigal 2 addresses to another 2 addresses. – talentldk Jun 15 '22 at 07:01

2 Answers2

2

hc_dev's answer guided me towards the solution. I tried to understand it and make it work in my issue.

Below is my code:

from scapy.all import *
from scapy.utils import PcapWriter

packets = rdpcap('ftp.pcap')
new_cap = PcapWriter("ftp_new.pcap")
srcIp=packets[0][IP].src
dstIP=packets[0][IP].dst

#define new ip address I want use
ip1='8.8.8.8'
ip2='1.1.1.1'

#replace orinigal address
for p in packets:
    if(p[IP].src == srcIp):
        p[IP].src = ip1
    elif(p[IP].src == dstIP):
        p[IP].src = ip2
    if(p[IP].dst == srcIp):
        p[IP].dst = ip1
    elif(p[IP].dst == dstIP):
        p[IP].dst = ip2
    new_cap.write(p)

wrpcap("ftp_new.pcap", packets)
hc_dev
  • 8,389
  • 1
  • 26
  • 38
talentldk
  • 43
  • 5
  • Good solution you developed yourself ️. See how this answer also clarified your question which I updated to be of use for future help-seekers. If you like to learn and improve, see my updated answer. – hc_dev Jun 17 '22 at 14:25
1

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
hc_dev
  • 8,389
  • 1
  • 26
  • 38
  • many thanks for your help, I solved my problem with your idea. I have post my code under your answer. – talentldk Jun 17 '22 at 08:33
  • @talentldk Glad it helped you find that solution yourself. Read [how to vote/accept in order to share feedback](https://stackoverflow.com/help/someone-answers) and take the respective actions. – hc_dev Jun 17 '22 at 14:00
  • 1
    thaks for your update. your simplification sugggestion is sure mor efficient. with the print part, it's much easier to debug. I have accepted your answer but i am still not able to upvote it for i have not enough reputation. – talentldk Jun 18 '22 at 10:53