I would like to parse the first two bytes of a packets payload using Scapy. What would be the best way to accomplish this? Are offset calculations required?
First the payload needs to be parsed though the following will parse the whole PCAP file, is there a more efficient way to obtain the first two bytes of every payload? link:
>>> fp = open("payloads.dat","wb")
>>> def handler(packet):
... fp.write(str(packet.payload.payload.payload))
...
>>> sniff(offline="capture1.dump",prn=handler,filter="tcp or udp")
I see. That looks pretty efficient from here.
You might try fp.write(str(packet.payload.payload.payload)[:2]) to get just the first 2 bytes.
You could also do fp.write(str(packet[TCP].payload)[:2]) to skip past all those payloads.
Alternately, you could define an SSL Packet object, bind it to the appropriate port, then print the SSL layer.
class SSL(Packet):
name = "SSL" fields_desc = [ ShortField("firstBytes", None) ]
bind_layers( TCP, SSL, sport=443 )
bind_layers( TCP, SSL, dport=443 )
def handler(packet):
... fp.write(str(packet[SSL]))
...but this seems like overkill.
Related
I have achieved sniffing IP packets. I use the following code.
def print_summary(pkt):
print("SRC:", pkt[scapy.IP].src, "\t\tDEST:", pkt[scapy.IP].dst)
scapy.sniff( iface=interface, filter="ip", prn=print_summary)
If I try to ping a domain name say 'youtube.com' or open it using a web browser, how can I show the domain name using the above print_summary function. I have tried searching for what filters to use for dns but found nothing.
Okay, I get it now. What I did was to remove the filter argument altogether from the sniff() method.
scapy.sniff( iface=interface, prn=print_summary)
Then in the print_summary() function, I filtered according to the layer each packet had (IP or DNS).
def print_summary(pkt):
if scapy.IP in pkt:
print("SRC:", pkt[scapy.IP].src, "\t\tDEST:", pkt[scapy.IP].dst)
if scapy.DNS in pkt:
print("Domain:", pkt.[scapy.DNS].qd.qname.decode("utf-8"))
decode("utf-8") because the qname is a utf encoded byte string.
I'm coding to tcp client/server using python twisted
in order to replace for Java or C#.
I have to parse length prefixed string messages based on ANS(alpha numeric string) in connected permanent session.
like this :
message format : [alpha numeric string:4byte][message data]
example-1 : 0004ABCD ==> ABCD
example-2 : 0002AB0005HELLO ==> AB, HELLO
it can't be solved by IntNProtocol, NetStringProtocol.
And if a client send a 2kb message from application layer, the kernel split message data by MSS(maximum segment size) and send packets are splitted.
in TCP send/receive environment, it often raise like this :
example : 1000HELLO {not yet arrived 995 byte data}
so it has to wait for receiving spare data using array, queue...
in the twisted, I don't know how to parse multiple large-message.
Anybody help me to give some information or URL?
class ClientProtocol(protocol.Protocol):
def dataReceived(self, data):
# how can I code to parse multiple large message?
# is there solution to read specific size for data ?
It looks like you can implement this protocol using StatefulProtocol as a base. Your protocol basically has two states. In the first state, you're waiting for 4 bytes which you will interpret as a zero-padded base 10 integer. In the second state, you're waiting for a number of bytes equal to the integer read in the first state.
from twisted.protocols.stateful import StatefulProtocol
class ANSProtocol(StatefulProtocol):
def getInitialState(self):
return (self._state_length, 4)
def _state_length(self, length_bytes):
length = int(length_bytes)
return self._state_content, length
def _state_content(self, content):
self.application_logic(content)
return self.getInitialState()
def application_logic(self, content):
# Application logic operating on `content`
# ...
As you know sometimes we can't know what the size of the data(if there is no Content-Length in http response header).
What is the best way to receive http response data(use socket)?
The follow code can get all the data but it will blocking at buf = sock.recv(1024).
from socket import *
import sys
sock = socket(AF_INET, SOCK_STREAM)
sock.connect(('www.google.com', 80))
index = "GET / HTTP/1.1\r\nHOST:www.google.com\r\nConnection:keep-alive\r\n\r\n"
bdsock.send(index)
data = ""
while True:
buf = bdsock.recv(1024)
if not len(buf):
break
data += buf
I'm assuming you are writing the sender as well.
A classic approach is to prefix any data sent over the wire with the length of the data. On the receive side, you just greedily append all data received to a buffer, then iterate over the buffer each time new data is received.
So if I send 100 bytes of data, I would prefix an int 100 to the beginning of the packet, and then transmit. Then, the receiver knows exactly what it is looking for. IF you want to get fancy, you can use a special endline sequence like \x00\x01\x02 to indicate the proper end of packet. This is an easily implemented form of error checking.
Use a bigger size first, do a couple of tests, then see what is the lenght of those buffers, you will then have an idea about what would the maximum size be. Then just use that number +100 or so just to be sure.
Testing different scenarios will be your best bet on finding your ideal buf size.
It would also help to know what protocol you are using the sockets for, then we would have a better idea and response for you.
Today I got the same question again.
And I found the simple way is use httplib.
r = HTTPResponse(sock)
r.begin()
# now you can use HTTPResponse method to get what you want.
print r.read()
For my larger project i need to start with creating a IPv4 network packet ( for simulation )
for the same I need to write a function that creates a header out of the passed data which has the source ip , dest ip and all the necessary fields
def convertIpv4( data ):
pass
For this I need you to guide me in the right direction.
Firstly I need to store the IP in 32 bits so for that if I have a string "192.168.2.1" what is the most efficient way to convert it into bytes and that too a size of 32 ??
Also if I create first a normal class with stuff like version = 4 and sourceip and dest ip then is there a way to convert it directly into a byte array with the position of objects just like the following header
Please tell how should i proceed....
Scapy can create IP headers easily.
Here they have an example on creating IP header.
Have a look at the PyIP module.
How do I check for the presence of a particular layer in a scapy packet? For example, I need to check the src/dst fields of an IP header, how do I know that a particular packet actually has an IP header (as opposed to IPv6 for instance).
My problem is that when I go to check for an IP header field, I get an error saying that the IP layer doesn't exist. Instead of an IP header, this particular packet had IPv6.
pkt = Ether(packet_string)
if pkt[IP].dst == something:
# do this
My error occurs when I try to reference the IP layer. How do I check for that layers existence before attempting to manipulate it?
Thanks!
You should try the in operator. It returns True or False depending if the layer is present or not in the Packet.
root#u1010:~/scapy# scapy
Welcome to Scapy (2.2.0-dev)
>>> load_contrib("ospf")
>>> pkts=rdpcap("rogue_ospf_hello.pcap")
>>> p=pkts[0]
>>> IP in p
True
>>> UDP in p
False
>>>
root#u1010:~/scapy#
For completion I thought I would also mention the haslayer method.
>>> pkts=rdpcap("rogue_ospf_hello.pcap")
>>> p=pkts[0]
>>> p.haslayer(UDP)
0
>>> p.haslayer(IP)
1
Hope that helps as well.