get the udp packets payload readable in python - python

I am developing a python sniffer which sniff the udp packets. I use this code to receive and get the payload of the received packet in human readable format, but the printed payload is not human readable! I searched about converting this format to human readable, but I got nothing.
packet = recv_socket.recvfrom(65565)
packet = packet[0]
ip_header = packet[0:20]
iph = struct.unpack('!BBHHHBBH4s4s', ip_header)
data = packet[28:]
payload = ":".join("{:02x}".format(ord(c)) for c in data)
print payload.decode("utf-8", "ignore")
print payload
Right now, the out put of print commands are as follow:
.*###[ DNS ]###
id = 1382
qr = 0L
opcode = 12L
aa = 0L
tc = 0L
rd = 1L
ra = 0L
z = 1L
ad = 1L
cd = 0L
rcode = 12L
qdcount = 30062
ancount = 867
nscount = 28525
arcount = 0
qd = ''
an = ''
ns = ''
ar = None
###[ Raw ]###
load = '\x01\x00\x01\xc0\x0c\x00\x01\x00\x01\x00\x00\x00<\x00\x04\x80w\xf3\x86'
05:66:61:6c:75:6e:03:63:6f:6d:00:00:01:00:01:c0:0c:00:01:00:01:00:00:00:3c:00:04:80:77:f3:86

Related

How to get payload from a packet with dpkt?

I am getting the payload of tcp packet using scapy easily :
def handle_pkt(pkt):
try :
pay_load_tcp = pkt[IP].load
except :
pay_load_tcp = ""
for packet in PcapReader(filename):
if TCP in packet and packet[IP].dst == '192.168.1.1':
handle_pkt(packet)
How can I get the same payload(Just the text info on the packet) using dpkt library?
Maybe not the perfect way, but we can get the payload using the dpkt library as follows:
f = open(pcap_file,'rb')
pcap = dpkt.pcap.Reader(f)
for _, buf in pcap:
eth = dpkt.ethernet.Ethernet(buf)
if not isinstance(eth.data,dpkt.ip.IP):
#print("NOT IP Packet")
continue
ip = eth.data
if isinstance(ip.data, dpkt.tcp.TCP):
if inet_to_str(ip.src)!='192.168.1.2' :
continue
tcp = ip.data
counter = counter + 1
#seq_num = tcp.seq
payload = bytes(ip.data)
print("counter = {} , Payload = {} ".format(counter,payload[32:]))
#if seq_num > cur_seq and
if payload[32:] != b'':
#cur_seq = seq_num
handle_pkt(payload[32:])

How to depickle the object same as it was sent from socket in python?

I am trying to serialize the object (using pickle) of type scapy.layers.l2.Ether (please refer scapy import statement of code). But while deserializing that object, it is not being retrieved properly (also shown in output). How can I fix this ? and get the object as same as it was serialized ?
import socket
import time
import pickle #serialize the object
import sys # for command line argument
from scapy.all import * # for packet sniffing
HEADERSIZE = 10
clientsocket = 1
address = 1
#for serialization
def pkt_callback(pkt):
pkt.show()
msg = pickle.dumps(pkt)
print(12)
clientsocket.send(msg)
#check whether ip and port number provided or not
if len(sys.argv) != 3:
print ("Correct usage: script, IP address, port number", flush = True)
exit(0)
IP_address = str(sys.argv[1])
Port = int(sys.argv[2])
#socket creation ipv6
s = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
s.bind((IP_address, Port))
s.listen(5)
while True:
# now our endpoint knows about the OTHER endpoint.
clientsocket, address = s.accept()
print(f"Connection from {address} has been established.",flush=True)
sniff(iface="wlp3s0", prn=pkt_callback, filter="tcp", store=0)
clientsocket.close()
print('Data sent to server')
The above code serializes the object to be sent at pkt_callback
Now below code is from receiving side which deserializes the object
import socket
import pickle
import sys
from scapy.all import * # for packet sniffing
HEADERSIZE = 10
#check whether address and port number given or not
if len(sys.argv) != 3:
print ("Correct usage: script, IP address, port number",flush = True)
exit(0)
IP_address = str(sys.argv[1])
Port = int(sys.argv[2])
#create ipv6 socket
s = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
s.connect((IP_address, Port))
while True:
data = s.recv(4096)
data_recved = pickle.loads(data)
(scapy.layers.l2.Ether(data_recved)).show()
s.close()
The 1st code which serializes the object works fine and shows output as expected.
The 2nd code which deserializes the object works but gives wrong output as below
###[ Raw ]###
load = '\xb0\xfc6`\xe5\xe3\xe4\xa7\xc5I,\x1c\x08\x00E(\x004%\xd4#\x00h\x06s!o\xdd\x1d\xfe\xc0\xa8+#\x01\xbb\xda\xb4\xf5 \x05\xfbv\xac\xccj\x80\x10\x04\x02\xb6z\x00\x00\x01\x01\x08\n!\x84\xf3\xa3\x066\x0c\x99'
###[ Raw ]###
load = "\xb0\xfc6`\xe5\xe3\xe4\xa7\xc5I,\x1c\x08\x00E(\x01o%\xd5#\x00h\x06q\xe5o\xdd\x1d\xfe\xc0\xa8+#\x01\xbb\xda\xb4\xf5 \x05\xfbv\xac\xccj\x80\x19\x04\x02B\xbf\x00\x00\x01\x01\x08\n!\x84\xf3\xfd\x066\x0c\x99\x17\x03\x03\x016\x00\x00\x00\x00\x00\x00\x00\x01n\xb3\x18\x93\xd2xT\x00\xe3Xh\xa7\xc0?|\xb3n\xf6?g\x00\xdf\xcf\x97wx\xccw\x04\x08\xbfM\xf2L1^\x84\xa1\xb0\x06\xaas\xdb\xc9\xb1\xed\x99\x8cz\x9a5P\xa3{\x04y\xbb\xc38\xcfT\\\x98f\xf1z/F\x1e\xd6tD\x90pN\x92\xe1\xf9\xee#\xbc\x1a(\x89{x\xf2\\\xd1\x14\x1d?\x02\x07\x16N\xe4\x017\x140\xc5\x81\xb4\xcd\t\x8ai\x1a\xe7PZ\x01\xbek\xba \x84[\\\xcc\xf0\xecs\xc8^\xff!\xce\x19z,\x13\xbd\xa3\x0c\x0fq\xca=\xbc\x1a834\xee\xf9hC\x0b\xb4\x85\x114'5W\xee\xed&\x93Y0\xd1\x85\xc3(\xb3\x0e0u\\\x9d\xa7\xb5g\xb0\xb4C_S\xe7\xf8\xbaH\t\x94\x84\xaf\xa9\tS\xb6\xf4XYD\tM\xf8=`\xbd\x04\xeeo\x1f\xd3\x7f*\xef\x8e\xd2\x00\x8f\xfb\x8c\xfemB\x02\xc0\x12\x8a\r\x14\xdco\\K\xfd\x97%\xbc\x15}\xb1\xe2<\xdei\x15\x17\xeec>=\xa0\xc0]\xfaa\xeal`\x10c\xe8\x86B\xff'w\xe3\xe4\xce\x9d\xbf0\xdc\xb0F\x12\x8b{;9\xa1\xce\xfdf\x1c\x8b\x8f\xc4\xc0F\xf3\\\x86\xbd\xcdu\xdb\xb8>t\xf6\xff.~h"
###[ Raw ]###
load = "\xe4\xa7\xc5I,\x1c\xb0\xfc6`\xe5\xe3\x08\x00E\x00\x00SP\xcb#\x00#\x06p3\xc0\xa8+#o\xdd\x1d\xfe\xda\xb4\x01\xbbv\xac\xccj\xf5 \x077\x80\x18\x01>\x93\x10\x00\x00\x01\x01\x08\n\x066\r\xb7!\x84\xf3\xfd\x15\x03\x03\x00\x1a\x00\x00\x00\x00\x00\x00\x00\x02Nkk'T\xcdv$\xb7e\xe00\xc9\x9f\xf2\xffw4"
###[ Raw ]###
load = '\xe4\xa7\xc5I,\x1c\xb0\xfc6`\xe5\xe3\x08\x00E\x00\x004P\xcc#\x00#\x06pQ\xc0\xa8+#o\xdd\x1d\xfe\xda\xb4\x01\xbbv\xac\xcc\x89\xf5 \x077\x80\x11\x01>\xb6j\x00\x00\x01\x01\x08\n\x066\r\xb7!\x84\xf3\xfd'
but it should be like
###[ Ethernet ]###
dst = e4:a7:c5:49:2c:1c
src = b0:fc:36:60:e5:e3
type = IPv6
###[ IPv6 ]###
version = 6
tc = 0
fl = 630855
plen = 32
nh = TCP
hlim = 255
src = 2409:4042:2ea4:752f:cd15:9fe5:6dc1:1575
dst = 2404:6800:4009:810::200e
###[ TCP ]###
sport = 36318
dport = https
seq = 3279176249
ack = 3388920021
dataofs = 8
reserved = 0
flags = A
window = 254
chksum = 0xf7e7
urgptr = 0
options = [('NOP', None), ('NOP', None), ('Timestamp', (427468701, 3715875499))]
How can I fix it ?
I have recently found the solution. Actually in second code snippet, the object show function on object was called by doing unnecessary typecasting. The line (scapy.layers.l2.Ether(data_recved)).show() should be simply like data_recved.show(). And then we can get desired output

Scapy RA flag showing although port http is open (80)

I have made a program with Scapy that checks for open ports and for some reason when I check for port 80 for example (scan other computer's port) it says it's closed (RA instead of SA) why is that??
or maybe I have confused SA and RA?
import sys
i, o, e = sys.stdin, sys.stdout, sys.stderr
from scapy.all import *
sys.stdin, sys.stdout, sys.stderr = i, o, e
TARGET_IP = '192.168.1.150'
def main():
packet1 = sr1(IP(dst=TARGET_IP)/TCP(dport=80, seq=123, flags="S"), timeout=1, verbose=0)
packet1.show()
if __name__ == '__main__':
main()
and the output is
###[ TCP ]###
sport = http
dport = ftp_data
seq = 0
ack = 124
dataofs = 5L
reserved = 0L
flags = RA
window = 0
chksum = 0x2aef
urgptr = 0
options = {}
What am I doing incorrect that makes this port closed? I have opened the chrome browser in the other computer and I'm guessing it should work...
Thanks for any help!

Scapy fails to filter certain packets

I have got a simple sniff function set up with scapy which forwards the packet to a handshake function (I have a webserver set up on port 102. However some weird errors have come by, then I decided to print pkt.show(), what I discovered was that some packages DID come through the filter somehow.
My sniff function:
a=sniff(filter="port 102", count=10, prn=handshake)
This packet manages to come through:
###[ Ethernet ]###
dst = 84:8f:69:f5:fe:ac
src = b8:27:eb:92:a3:3b
type = 0x800
###[ IP ]###
version = 4L
ihl = 5L
tos = 0x0
len = 44
id = 1
flags =
frag = 0L
ttl = 64
proto = tcp
chksum = 0xe6c6
src = 192.168.137.178
dst = 192.168.137.1
\options \
###[ TCP ]###
sport = iso_tsap
dport = 2426
seq = 605952828
ack = 605952829
dataofs = 6L
reserved = 0L
flags = SA
window = 8192
chksum = 0x5b7c
urgptr = 0
options = [('MSS', 1460)]
As you can see the destination port is 2426, which is definetely not port 102.
Have I done something dumb?
The source port in the enclosed packet is iso_tsap which is 102. If you want to filter by the destination port try the filter "dst port 102". If you need something a bit more sophisticated, here is the syntax of BPF, which is used by scapy.

How to calculate a packet checksum without sending it?

I'm using scapy, and I want to create a packet and calculate its' checksum without sending it. Is there a way to do it?
Thanks.
I've also tried to avoid show2() because it print the packet.
I've found in the source a better solution:
del packet.chksum
packet = packet.__class__(bytes(packet))
This code regenerate the packet with the correct checksum without any print and actually is what show2() run in the background before printing.
You need to delete the .chksum value from the packet after you create it; then call .show2()
>>> from scapy.layers.inet import IP
>>> from scapy.layers.inet import ICMP
>>> from scapy.layers.inet import TCP
>>> target = "10.9.8.7"
>>> ttl = 64
>>> id = 32711
>>> sport = 2927
>>> dport = 80
>>> pak = IP(dst=target, src = "100.99.98.97", ttl=ttl, flags="DF", id=id, len=1200, chksum = 0)/TCP(flags="S", sport=sport, dport=int(dport), options=[('Timestamp',(0,0))], chksum = 0)
>>> del pak[IP].chksum
>>> del pak[TCP].chksum
>>> pak.show2()
###[ IP ]###
version = 4L
ihl = 5L
tos = 0x0
len = 1200
id = 32711
flags = DF
frag = 0L
ttl = 64
proto = tcp
chksum = 0x9afd
src = 100.99.98.97
dst = 10.9.8.7
\options \
###[ TCP ]###
sport = 2927
dport = www
seq = 0
ack = 0
dataofs = 8L
reserved = 0L
flags = S
window = 8192
chksum = 0x2c0e
urgptr = 0
options = [('Timestamp', (0, 0)), ('EOL', None)]
>>>
Add this patch to scapy/packet.py:
+ def checksum_silent(self):
+ """
+ Internal method that recalcs checksum without the annoying prints
+ **AFTER old checksums are deleted.**
+ """
+
+ for f in self.fields_desc:
+ if isinstance(f, ConditionalField) and not f._evalcond(self):
+ continue
+ fvalue = self.getfieldval(f.name)
+ if isinstance(fvalue, Packet) or (f.islist and f.holds_packets and type(fvalue) is list):
+ fvalue_gen = SetGen(fvalue,_iterpacket=0)
+ for fvalue in fvalue_gen:
+ fvalue.checksum_silent()
+ if self.payload:
+ self.payload.checksum_silent()
Then instead of calling pkt.show2(), just call this function
pkt.checksum_silent(). (Remember to first do del pkt[IP].chksum and del pkt[UDP].chksum, etc.) as shown in the previous answer.
This function should be faster and be silent. (There may be additional things to trim as well; I hacked this code together and only tested to make sure it was silent with correct checksum.)
Indeed, the show2() function calculates the checksum for you, but it also prints the contents of the packet once it is finished with its work. However, show2() has a helpful little parameter named dump. The source describes it as such:
:param dump: determine if it prints or returns the string value
So by setting dump=True, you can avoid the pesky output that the function provides by default, and still get the calculations that you want.
You can also use packet.build() which returns raw bytes with correct checksum. Then convert the bytes to a packet.
>>> import scapy.all as sp
>>> packet = sp.IP(src='127.0.0.1', dst='8.8.8.8')
>>> packet
<IP src=127.0.0.1 dst=8.8.8.8 |>
>>> sp.IP(packet.build())
<IP version=4 ihl=5 tos=0x0 len=20 id=1 flags= frag=0 ttl=64
proto=hopopt chksum=0xebd8 src=127.0.0.1 dst=8.8.8.8 |>

Categories

Resources