Can't extract individual fields from scapy packet - python

I've been experimenting with scapy and Python 3 and I want to use the ARP protocol to find mac addresses of computers on the network. This is my code:
>>> packet = srp(Ether(dst="ff:ff:ff:ff:ff:ff")/ARP(pdst=IP_OF_HOST))
Then to extract the data from this packet I used the following line:
>>> packet[0][Ether].src
However for some reason this produces the error:
AttributeError: 'list' object has no attribute 'src'
Every tutorial I read used the method I used for extracting field data, why wouldn't it work for me?

It has to do with the difference between the functions srp(), and srp1() (Those being for network layer 2, for layer 3 you would use sr() and sr1() respectively).
srp() sends the packet, and saves all packets, whether they are answered or not. To get say the source MAC address I'd do this:
answered_packets, unanswered_packets = packet
for packet_i_sent, packet_i_received in answered_packets:
print(packet_i_received.src)
srp1() sends a packet, and waits for one answer, and saves only the reply packet. This means the format is different, since you don't have to deal with the unanswered packets, and my previous method would work:
print(packet.src) #The [Ether] part doesn't matter,
#that's just for looking fancier when you print(packet)
So basically I used the command srp() and tried to decode the reply like I was using srp1()

Related

How to create new layer or new protocol with scapy?

I want to create a new layer using scapy. I created a new layer but when I sent it to another computer it got lost, Wireshark also couldn't recognize it. How can I solve this problem?
class OMER(Packet):
name = "OMER"
fields_desc = [StrLenField("Omer", "", None)]
When you create a new protocol or a new layer with scapy, other network tools like wireshark (and others) since they are not aware of your protocol's specifics will not be able to automatically parse it correctly.
If you want to experiment with a new protocol you will have to create your own local decoder. The following example even its minimal, it demonstrates all of the above:
#!/usr/bin/env python
from scapy.all import *
# create a simple protocol
# (example similar with the one in the scapy docs...)
class Exmpl(Packet):
name = "myprotocol"
fields_desc=[ ShortField("fld1",5),
XByteField("fld2",3) ]
from scapy.utils import PcapWriter
# write data in a pcap file to examine later with
# 1 -> scapy
# 2 -> wireshark
print '\n[+] Writing net.pcap file...'
cap = PcapWriter("net.pcap", append=True, sync=True)
for i in range(10):
packet = Exmpl(fld1=i)
cap.write(packet)
# read the data and examine them with scapy
# scapy is aware of the "Exmpl" protocol (e.g. its fields etc...)
# and how to decode it, while wireshark is not
print '[+] Examining net.pcap file...\n'
packets = rdpcap('net.pcap')
for p in packets:
Exmpl(str(p)).show()
The output of the above script will be like:
[+] Writing net.pcap file...
[+] Examining net.pcap file...
###[ myprotocol ]###
fld1 = 0
fld2 = 0x3
###[ myprotocol ]###
fld1 = 1
fld2 = 0x3
###[ myprotocol ]###
fld1 = 2
fld2 = 0x3
...skip...
As you can see scapy is aware of the protocol and thus can parse the data correctly. Now if you try to examine the "net.pcap" file with wireshark you will see the following:
wireshark is not aware of your protocol and as a result it can't parse it correctly.
Notice: As you can understand, even if you send those packets in another device (to actually do that you'll have to implement some other stuff also) then that device must also be aware of your protocol, otherwise it won't be able to parse it correctly. That is why when you tried to send the packets from one computer to another, the receiver couldn't successfully decode them.
Thinks of it as learning a foreign language. Let's say your family is speaking only english.
You learn chinese and now are able to say sentences in chinese (that's what you did by creating the layer in scapy and building packets)
Your family can hear the chinese sentences (wireshark can receive the packets)
But your family cannot understand the sentences since they will still just speak english (wireshark cannot dissects the packets as it does not know your protocol)
If you abolutely want your family to understand you when speaking chinese, then you have to teach them (implement the dissector in wireshark)
Hope that's clear :-)
Did you bind the new layer/protocol to the previous layer/protocol? E.g. bind_layers(Ether, OMER) if the OMER layer comes right after the Ether layer.
You have made your custom layer. However you shoukd keep in your mind that this custom layer wouldnt be recognized by a operating system untill you write networking at kernel level and that must be present in every operating system. So on the other host, you write another python script that tells operating system to disect the packet containing your custom layer accordingly. Write your own sniffer packet and then initliaze your custom layer class so that while sniffing you actually make use of that class while disecting the packet and then you can view the packet with your custom layer.
Note that you need to bind the layer, your new layer with the layer in froth of it. It appears as if you have constructed right packet, however when it reaches the other host it simply cannot decode untill you bind the layer. Only when you bind it, your operating system knows to disect the packet excatly after your ip layer or udp layer etc... Have been dissected .
Also in oder to squeeze your custom layer between two well known protocols, say for example udp with port 53, operating by default binds dns to udp port 53. If you ever wanted to inject your new layer between udp and dns say, u need to firstly unbind udp and dns and then say to udp that I want my custom layer to be followed instead of dns layer. Just use split_layers to unbind udp and dns and then bind your custom layer to udp and also bind your dns to your new custom layer.

Python TCP socket for a lot of data

We (as project group) are currently stuck on the issue of how to handle live data to our server.
We are getting updates on data every second, and we would like to insert this into our database (security is currently not an issue, because it is a school project). The problem is here we tried python SockerServer and AsyncIO to create a TCP server to which the data can be sent.
We got this working with different libraries etc. But we are stuck on the fact that if we keep an open connection with the client (in this case hardware which sends data every second) we can't split the different JSON or XML messages. They are all added up together.
We know why because TCP only provides order.
Any thoughts on how to handle this? So that every message sent will get split from the others.
Recreating the socket won't be the right option if I recall correctly.
What you will have to do is ensure that there is a clear delimiter for each message. For example, the first 6 characters of every message could be the length of the message - whatever reads from the socket decodes the length then reads that number of bytes, and sends the data to whatever needs it. Another way would be if there is a character/byte which never appears in the content, send it immediately before a message - for example control-A (binary value 1) could be the leadin character, and send control-B (binary value 2) as the leadout. Again the server looks for these framing a message.
If you can't change the client side (the thing sending the data), then you are going to have to parse the input. You can't just add a delimiter to something that you don't control.
An alternative is to use a header that encodes the size of the message that will be sent. Lets say you use a header of 4 bytes, The client first send the server a header with the size of the message to come. The client then sends the message (up to 4 gigs or there about). The server knows that it must first read 4 bytes (a header). It calculates the size n that the header contained then reads n bytes from the socket buffer. You are guaranteed to have read only your message. Using special delimiters is dangerous as you MUST know all possible values that a client can send.
It really depends on the type of data you are receiving. What type of connection, latency... If you have a pause of 1 second between packets and your connection is consistent, you could probably get away with first reading the entire buffer once to clear it, then as soon as there is data available - read it and clear the buffer it. not a great approach, but it might work for what you need - and no parsing involved.

scapy sr function problems

I'm having trouble receiving all related packets to a request when using scapy's sr function.
ans, unans = sr(IP(dst="172.xxx.xxx.xxx")/TCP(dport=80,flags="S"))
returns:
Received 2 packets, got 1 answers, remaining 0 packets
What happens is that I first get an ICMP redirect. Afterwards I get the answer from my local service with SA. Sometimes it tells me it received two packets, which makes sense, but when I look at it in the summary it prints the following:
<bound method SndRcvList.summary of <Results: TCP:0 UDP:0 ICMP:1 Other:0>>
and in summary() I find this:
IP / TCP 172.xxx.xxx.xxx:ftp_data > 172.zzz.zzz.zzz:http S ==> IP / ICMP 172.yyy.yyy.yyy > 172.xxx.xxx.xxx redirect host-redirect / IPerror / TCPerror
For one, I wonder where my SA flagged TCP packet is. When I look at the network dump, I definitely see it, right after the ICMP packet. I've made sure to run scapy with and without running tcpdump, just in case it would interfere, which it shouldn't.
I've also tried to set and increased timeout, just in case it didn't wait long enough to receive the TCP packet. Didn't work.
I've also tried it out on loopback interface, the local lan and systems that are located in the internet. Same result everywhere.
Any ideas on where the error could be located?
Scapy considers this ICMP packet to be response on initial TCP SYN request (which it actually is). Try using sr(..., multi = True) to get multiple response packets.

Using a sniffed packet with scapy python

Im not so new to network programming but new to working with scapy (I mainly work on c++).
So, im sniffing packets (traffic) that are coming into my computer and what I want to do is just to save one of the packets into a variable and use it later in my program.
It doesnt need to be any specific packet it can be a random packet. The only thing I want is just to insert it into a variable and use it later on.
Could someone please help me with this?
The sniff() function returns the sniffed packet. You can pass various arguments to this function. You can take the output and save it in a variable. Please see these two links:
(a) www.secdev.org/projects/scapy/files/scapydoc.pdf and (b)
and Scapy filtering with sniff() function

Decoding Simulink's UDP Packets in Python

I have a Simulink model sending data via UDP to another program (Blender) where I can receive the packets, but I have not been able to figure out how to correctly decode them.
In the Simulink model I just have it sending a value that is based upon a sine wave, nothing fancy, just a single value like 1.452 or something. In Blender I have it spitting out the data it receives from the packet, and I'm receiving stuff like:
b'<\xa6ya\x05\x93\xe3?'
I have no idea how to decode this. It seems to have some hex values, but beyond that I'm lost. I'm not even sure what all this data contains. Is it just the value from Simulink, or does it contain information regarding things like the sender and receiver IP addresses, ports, etc...?
UPDATE:
I updated the Simulink model to transmit a constant value via UDP for debugging/investigation. The value is 0.5234, and the data that my Python script is spitting out is:
b'\xab>W[\xb1\xbf\xe0?'
Which, when converted into hexadecimal reads (using hexlify):
b'ab3e575bb1bfe03f'
How would I extract/decode 0.5234 out of that?
Thanks for any help!
You can use struct to decode your binary data, in this case it seems to be a double value:
>>> import struct
>>> struct.unpack('d', b'\xab>W[\xb1\xbf\xe0?')
(0.5234,)

Categories