I'm forwarding a machine's packets through mine. I tested with tcpdump host <machine_ip> to see if everything is alright, and it is. Now I need to capture these packets. I chose to do this with Python. Right now I'm trying to filter the packets, but the ip that is printed is different from the right one. It should've been 192.168.0.8:
import socket
from struct import *
print("Started")
with socket.socket(socket.AF_PACKET,socket.SOCK_RAW, socket.ntohs(0x0003)) as s:
while True:
packet=s.recvfrom(65565)
content=packet[0]
ip_header=unpack('!BBHHHBBH4s4s', content[:20])
source_ip=socket.inet_ntoa(ip_header[8])
print(source_ip)
The printed ones are 8.0.69.0 and 8.0.69.16, which none of these matches the expected form.
This is because in front of the raw data is the MAC header.
If You change the line:
ip_header=unpack('!BBHHHBBH4s4s', content[:20])
to
ip_header=unpack('!BBHHHBBH4s4s', content[14:34])
You will probably get your ip address. I said probably becase it really depends on the link layer, as there might be a vlan tag present, thus shifting the ip header even further.
Related
I am trying to replicate the data I am seeing in Wireshark using this filter tcp.port == 25565. I have tried using socket and pyshark, however, I cannot seem to find a simple tutorial which explains how to do this.
As you can probably tell by the port, I am trying to decode Minecraft packets. Advice on how to get the payload and get a start on parsing that data would be very helpful.
So far, I have this code:
from scapy.all import *
def test(pkt):
print(pkt)
if __name__ == '__main__':
single = sniff(filter="tcp.port == 25565", prn=test)
Any help is greatly appreciated.
You want sniff(filter="tcp port 25565", prn=test).
Look at the scapy documentation.
We can add filtering to capture only packets that are interesting to us. Use standard tcpdump/libpcap syntax:
That syntax is specified in the pcap-filter man page.
qualifiers restrict the match to a particular protocol.
Possible protos are: ether, fddi, tr, wlan, ip, ip6, arp, rarp, decnet, tcp and udp. E.g., 'ether src foo', 'arp net 128.3', 'tcp port 21',
I don't think the syntax is well explained in it (or I'm not reading the right part), but as you can see, tcp port 21 is a valid filter and what you're looking for. For an alternative syntax that uses an and, you'll see this further down:
Primitives may be combined using:
A parenthesized group of primitives and operators (parentheses are special to the Shell and must be escaped).
Negation ('!' or 'not').
Concatenation ('&&' or 'and').
Alternation ('||' or 'or').
As you can see, your filter options (or primitives) should be grouped using an operator. In this case, you want both to be true, so you want tcp and port 25565, or alternatively, tcp && port 25565.
I am trying to simulate a TCP communication between two hosts with scapy.
My problem is, that I can't save the random IP addresses scapy generates for me.
This code
src_IP = RandIP()
print(src_IP)
print(src_IP)
print(src_IP)
gives me an output like this
234.200.98.20
147.3.56.17
135.102.142.49
So every time I access src_IP it has a new value.
Is there a way to save a random IP from scapy? So I could generated 2 IPs at the beginning of my function and use them as source and destination for my TCP communication.
I could generate the IPs myself, but I thought there had to be a more elegant solution to it.
BTW. non of the packets are going to be sent, they will be written into a PCAP file. Therefor I have to create both sides of the communication.
The accepted answer is a hack; it is correct (as in "it works and do what was asked"), but it is not the correct way to do that in Scapy.
The method you are looking for is ._fix(). It will work with any volatile value type.
src_IP = RandIP()._fix()
If you also need for example a random source port, you could do:
src_port = RandShort()._fix()
I found an answer.
RandIP() creates an instance of an object, and every time this object gets accessed, to print or do send a packet or something else, it generates a new IP.
So my solution is to cast it to a string
src_IP = str(RandIP())
print(src_IP)
print(src_IP)
print(src_IP)
And the output is just as intended
232.119.133.38
232.119.133.38
232.119.133.38
I am having an issue where I am trying to use Python's pyshark to read in IP addresses. I was able to print out the IP address of an LLDP packet just fine, using packet.lldp.mgn_addr_ip4. However packet.cdp... does not seem to have an equivalent, besides packet.cdp which returns a sequence of bytes.
I have tried packet.cdp.nrgyz.ip_address and nothing is printed out. I tried every other field from this link as well and nothing will return.
for packet in cap:
try:
if packet.cdp:
print(packet.cdp.nrgyz.ip_address)
elif packet.lldp:
print(packet.lldp.mgn_addr_ip4)
except AttributeError as e:
pass
I'd really appreciate any kind of guidance since not a single one of the fields that says it returns an IPv4 address will print out.
I figured it out. Apparently you can't use cdp.nrgyz(DOT)ip_address, and instead have to use cdp.nrgyz(UNDERSCORE)ip_address. So it becomes cdp.nrgyz_ip_address, even though Wireshark documentation says it should be cdp.nrgyz.ip_address
Generally I can send a ICMP packet as mentioned below
srp(Ether(src=u'd2:ff:90:c5:1f:21', dst=u'9c:22:14:4f:6c:ac', type=2048)/IP(src=u'238.166.15.14', dst=u'70.74.2.83')/ICMP(type=8)/Raw(load='UZe5ICdH'),timeout=10,iface="ens192.50")
For example to send a fragmented packet can i do it as,
srp(fragment(Ether(src=u'd2:ff:90:c5:1f:21', dst=u'9c:22:14:4f:6c:ac', type=2048)/IP(src=u'238.166.15.14', dst=u'70.74.2.83')/ICMP(type=8)/Raw(load='UZe5ICdH'),fragsize=2),timeout=10,iface="ens192.50")
I got this from one of the blogs. But am not sure whether am doing it properly or not.
fragment() should be used on an IP packet and return a list of fragments. You should change your code to send each fragment one by one:
frags = fragment(IP(src='238.166.15.14', dst='70.74.2.83')/ICMP(type=8)/Raw(load='UZe5ICdH'),fragsize=2)
l2 = Ether(src='d2:ff:90:c5:1f:21', dst='9c:22:14:4f:6c:ac', type=2048)
for f in frags:
srp(l2/f, timeout=10,iface="ens192.50")
maybe helpful for someone looking this topic, this code snippet given in question work fine.
srp(fragment(Ether(src=u'60:36:dd:3f:5f:c5', dst=u'7c:c3:85:30:8c:24', type=2048)/IP(src=u'192.168.18.24', dst=u'192.168.18.1')/ICMP(type=8)/Raw(load='UZe5ICdH'),fragsize=2),timeout=1,iface="wlp2s0")
I'm forging with Scapy the TTL value in the IP header in some data packet that I captured. Besides the checksum in both IP and transport layer headers, is there anything else I should recompute?
Right now I'm doing:
for p in myPackets:
p[IP].ttl = targetTTL
del(p[IP].chksum)
del(p[IP].payload.chksum)
for i in range(len(myPackets)):
myPackets[i] = myPackets[i].__class__(str(myPackets[i]))
I'm asking this because Scapy's sr function, which matches packets with their responses (ICMP in my case) has been returning data with a few RTTs > 1 second, which is absurd since I'm using ttl=1.
Have you tried just sending the packet? Scapy should recompute the checksums for you automatically.You could also try setting them to None, but I don't believe that's necessary.
I believe scapy will automatically recalculate the checksums if you call the show2() command on the packet. So if you have a packet at index 0 in the object pckt, you should call pckt.show2() and the checksum should be correct. At least that's my understanding.
pkt.show2() same as show but on the assembled packet (checksum is calculated, for instance) Source