I am reading packets from pcap files and sending them on my network. The trouble is I keep getting invalid checksum errors. I have set the packets to have a checksum of None in the IP layer (as Scapy auto generates any missing data) however I can't seem to do it for the Protocol Layer (TCP,UDP etc). Thus the checksum errors still occur.
Example
###[ IP ]###
version = 4
ihl = 5
tos = 0x20
len = 436
id = 50116
flags =
frag = 0
ttl = 107
proto = udp
chksum = None --- Correct as Scapy will Autogen
src = 169.254.162.71
dst = 169.254.208.208
\options \
###[ UDP ]###
sport = 23616
dport = 23575
len = 416
chksum = 0x5f4a ---Incorrect Checksum
I have looked online and have found this:
pkt.payload.chksum = None
However that did not work.
pkt[Ether].src = "00:E0:4C:00:02:42"
pkt[Ether].dst = "00:E0:4C:01:08:99"
pkt[IP].src = "169.254.162.71" # i.e new_src_ip="255.255.255.255"
pkt[IP].dst = "169.254.208.208"
pkt[IP].chksum = None
pkt.payload.chksum = None
pkt.show()
Example Output
###[ Ethernet ]###
dst = 00:E0:4C:01:08:99
src = 00:E0:4C:00:02:42
type = IPv4
###[ IP ]###
version = 4
ihl = 5
tos = 0x20
len = 436
id = 50116
flags =
frag = 0
ttl = 107
proto = udp
chksum = None
src = 169.254.162.71
dst = 169.254.208.208
\options \
###[ UDP ]###
sport = 23616
dport = 23575
len = 416
chksum = 0x5f4a ---Not set to None
Do note that the file I'm reading from uses all different types of protocols, so the solution should be generic if possible.
pkt.payload is the IP layer. You're performing the same operation twice.
You should do:
pkt[IP].payload.chksum = None
Related
I'm trying to code a python script through which I want to send packets from one host (desktop ubuntu) to a server (Ubuntu server) using multiple source addresses. I decided that would be best to use raw sockets and define my own TCP and IP header. I succeed to send the SYN packet and also get a response with the SYN-ACK packet but then my host doesn't respond with the ACK packet but with the RST packet. This is the first problem with I met in my solution. After the beginning of a three-way handshake I would like to send an HTTP GET keep-alive request. Does anyone know how to do it? Or does anyone know a better solution or library to use?
def send_raw_socket():
s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_TCP)
s.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1)
version_ihl_type_of_service = b'\x45\x00'
total_length = b'\x00\x3c'
Indentification = b'\xab\xcd'
flags_fragment_offset = b'\x00\x00'
TTL_protocol = b'\x40\x06'
Dest_add = b'\x0a\x0a'
Dest_add2 = b'\x1e\x03'
Src_add = b'\x0a\x0a'
src_add2 =b'\x0a\x0a'
Header_Checksum = my_ip_header_checksum(version_ihl_type_of_service, total_length, Indentification, flags_fragment_offset, TTL_protocol, Src_add,src_add2, Dest_add, Dest_add2)
IP_protocol = b'\x00\x06'
TCP_header_lenght = b'\x00\x14'
src_port = (int(src_port.hex(), 16)+49607).to_bytes(2, byteorder='big')
dest_port = b'\x1f\x95' # Source Port | Destination Port
seq_n1 = b'\x00\x00'
seq_n2 = b'\x00\x00' # Sequence Number
ack_n1 = b'\x00\x00'
ack_n2 = b'\x00\x00' # Acknowledgement Number
do_res = b'\x50\x02'
flags_win_s = b'\x71\x10' # Data Offset, Reserved, Flags | Window Size
checksum= tcp_header_checksum(IP_protocol, Src_add, src_add2, Dest_add, Dest_add2, TCP_header_lenght, src_port, dest_port, seq_n1, seq_n2, ack_n1, ack_n2, do_res, flags_win_s)
u_pinter= b'\x00\x00' # Checksum | Urgent Pointer
packet = version_ihl_type_of_service+total_length+Indentification+flags_fragment_offset+TTL_protocol+Header_Checksum+Src_add+src_add2+Dest_add+Dest_add2+src_port+dest_port+seq_n1+seq_n2+ack_n1+ack_n2+do_res+flags_win_s+checksum+u_pinter
s.sendto(packet, ('10.10.30.3',8085))
Wireshark three-way handshake
I am trying to set up a socket server on a linux machine using python , as a side project for my networking team.
the machine will listen to port 53, and will respond to dns queries using scapy.
Now, the asking part is all working great, atleast i think, i didnt really get to the part when i set the server as my dns server and try to use the internet yet, but when i try tcpdump it looks like a normal packet.
Anyway, when i respond from the server to the client, the packet is being sent with all the headers that i need, of DNS,DNSQR and DNSRR, as i saw in tcpdump.
But, when the client receive the packet, it only has IP,and UDP headers, as the rest is being sent as Raw data.
As i previously mentioned, i tried looking at wireshark and tcpdump and saw the difference that is being sent between the server and the client, and i saw that from the server side, the reply packet is being marked as malformed packet
Im not completely sure if this is the case, as i saw on the internet that its just because i didnt spoof it complettly.
code:
Client packet:
pkt = IP(dst='<Server IP>')/UDP(dport=53,sport=RandShort())/DNS(rd=1,qd=DNSQR(qname='dns.google'))
Server packet:
def build_dns_response(src_addr,og_sport,dns_qtype,dns_qname,response_type=True,response_name=None):
'''
a function that will build a DNS response packet back to the sender, according to the parameters that are recieved.
dns_qname = url/ip that the sender asked for.
og_sport = original source port, will be used as the dport of this packet
src_addr = source address of the original packet, will be used as the destination of this packet.
dns_qtype = the question type of the original request, 1 stands for type A, and 12 for PTR
response_type = will indicate if the server responds with an answer of 'ok' or 'name-error' on the 'rcode' field,True for ok,False for name-error
response_name = the response that the server will send as a result of the dns request, in case that a request matches to a database query.
'''
if response_type is True:
pkt = IP(src='<Server IP>',dst=src_addr)/\
UDP(sport=53,dport=og_sport)/\
DNS(opcode=0,rd=1,rcode='ok',nscount=1,ancount=1,qd=DNSQR(qname=dns_qname,qtype=dns_qtype),an=DNSRR(rrname=dns_qname,type=dns_qtype,rdata=response_name))
packet being sent by server:
###[ IP ]###
version = 4
ihl = None
tos = 0x0
len = None
id = 1
flags =
frag = 0
ttl = 64
proto = udp
chksum = None
src = <Server IP>
dst = <client IP >
\options \
###[ UDP ]###
sport = domain
dport = 25151
len = None
chksum = None
###[ DNS ]###
id = 0
qr = 0
opcode = QUERY
aa = 0
tc = 0
rd = 1
ra = 0
z = 0
ad = 0
cd = 0
rcode = ok
qdcount = 1
ancount = 1
nscount = 1
arcount = 0
\qd \
|###[ DNS Question Record ]###
| qname = 'dns.google.'
| qtype = A
| qclass = IN
\an \
|###[ DNS Resource Record ]###
| rrname = 'dns.google.'
| type = A
| rclass = IN
| ttl = 0
| rdlen = None
| rdata = 8.8.8.8
ns = None
ar = None
packet that is received by the client:
###[ IP ]###
version = 4
ihl = 5
tos = 0x0
len = 82
id = 1
flags =
frag = 0
ttl = 64
proto = udp
chksum = 0x6686
src = <Server IP>
dst = <Client IP>
\options \
###[ UDP ]###
sport = domain
dport = 25151
len = 62
chksum = 0xf99
###[ Raw ]###
load = '\x00\x00\x01\x00\x00\x01\x00\x01\x00\x01\x00\x00\x03dns\x06google\x00\x00\x01\x00\x01\x03dns\x06google\x00\x00\x01\x00\x01\x00\x00\x00\x00\x00\x04\x08\x08\x08\x08'
I guess its worth mentioning that the entire conversation is from Host PC to vm being hosted on it.
Thanks in advance for any help!
i created a new layer using scapy and i succeeded to send the new layer to another computer and show the new layer. My problen is when i send the layers all the data from all fields appear in the first fields and deleted from the another fields.
import sys
i, o, e = sys.stdin, sys.stdout, sys.stderr
from scapy.all import *
sys.stdin, sys.stdout, sys.stderr = i, o, e
from scapy.packet import *
from scapy.fields import *
from scapy.layers.inet import UDP, IP
from scapy.layers.dns import DNS
from scapy.layers.l2 import Ether
class ID(Packet):
name = "ID secret Traffic"
fields_desc = [StrField("ID",""),StrField("LastName",""),StrField("FirstName",""),StrField("FatherName",""),
StrField("MomName",""),StrField("BdayLo",""),StrField("BdayHi",""),StrField("BirthLocation",""),
StrField("Gender",""),StrField("LocationOfIssuingID",""),StrField("Image","")]
bind_layers(UDP,ID,sport=217,dport=217)
bind_layers(ID,Raw,sport=217,dport=217)
bind_layers(UDP,Raw,sport=217,dport=217)
p = IP(dst='192.168.1.28')/UDP()/ID(ID='111111111',LastName="Kazo Cohen",FirstName="Omer",FatherName="Yaqqov",MomName="Irit",BdayLo="6121999",BdayHi="Kislev",BirthLocation="RamatGan",Gender="M",LocationOfIssuingID=" Tel Aviv",Image="fvvsgsgsfzfszvsfvfs")/Raw("KEEPALIVE")
p.show2()
send(p)
OUTPUT
###[ IP ]###
version = 4L
ihl = 5L
tos = 0x0
len = 120
id = 1
flags =
frag = 0L
ttl = 64
proto = udp
chksum = 0xf6e9
src = 192.168.1.30
dst = 192.168.1.28
\options \
###[ UDP ]###
sport = 217
dport = 217
len = 100
chksum = 0xf332
###[ ID secret Traffic ]###
ID = '111111111Kazo CohenOmerYaqqovIrit6121999KislevRamatGanM Tel AvivfvvsgsgsfzfszvsfvfsKEEPALIVE'
LastName = ''
FirstName = ''
FatherName= ''
MomName = ''
BdayLo = ''
BdayHi = ''
BirthLocation= ''
Gender = ''
LocationOfIssuingID= ''
Image = ''
Your protocol is weird: how is the program (Scapy, or another program able to "talk" your protocol) supposed to guess that the ID field only contains "111111111", and that the rest is to be used for the next fields?
Usually, you have either a known "end-of-field" character (a null-byte can be an example), or a fixed length (it is known that the ID field is 9 characters long), or a field is used to get the length of the string.
Scapy can work with any of these options, using StrNullField or StrStopField for the first case, StrFixedLenField for the second, and StrLenField together with FieldLenField for the third.
I would like to get the ntp_monlist response of my NTP server.
Actually the packet is send but I don't receive anything.
Someone can tell me why ?
Code :
#!/usr/bin/env python
from scapy.all import *
import threading
import os
import sys
import socket
#Data to send
ntpip = "xxx.xx.xxx.xx"
packet = IP(dst=ntpip)/UDP(dport=123)/Raw(load=str("\x17\x00\x03\x2a")+ str("\x00")*4)
packet.show()
rep,non_rep = srp(packet)
rep.show()
Reponse :
###[ IP ]###
version = 4
ihl = None
tos = 0x0
len = None
id = 1
flags =
frag = 0
ttl = 64
proto = udp
chksum = None
src = xxx.xxx.xxx.xxx
dst = xxx.xxx.xxx.xxx
\options \
###[ UDP ]###
sport = domain
dport = ntp
len = None
chksum = None
###[ Raw ]###
load = '\x17\x00\x03*\x00\x00\x00\x00'
Begin emission:
Finished to send 1 packets.
......................................................................................................................
Received XXX packets, got 0 answers, remaining 1 packets
As you can see, I never receive any response.
You have multiple issues:
you're sending a layer 3 packet, so you need to use sr, not srp;
you need to specify a UDP source port;
your NTP payload is malformed.
There are two issues with your NTP payload. First of all, the first word of the NTP packet is defined as follows (RFC 5905):
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|LI | VN |Mode | Stratum | Poll | Precision |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
You want LI to be 0, VN to be 3, and Mode to be 3, so this gives a first octet of 0 + (3 * 8) + 3, or 0x1b.
Second, the minimum NTP packet is 12*4 octets.
So you need to say:
packet = IP(dst=ntpip)/UDP(dport=123,sport=50000)/("\x1b\x00\x00\x00"+"\x00"*11*4)
rep,non_rep = sr(packet)
I'm trying to parse a pcap file with scapy (in python), and getting raw data at the layer above TCP.
on wireshark, all the layers are shown correctly:
but on scapy all i'm seeing is just a Raw layer...
i'm thinking maybe it didn't parsed the packet well?
maybe the NetBIOS moduled did not load? or maybe i didn't import the module right?
(i tryied:
import scapy.all, import scapy, import scapy.layers.smb )
how do i make scapy load the layers of the packet correctly?
thanks!
If someone has a similar problem…
You need something like
packet[TCP].decode_payload_as(NBTSession)
And then you Will get the decoded layers by scapy:
packet[TCP].show()
[ TCP ]
sport = microsoft_ds
…
options = []
[ NBT Session Packet ]###
TYPE = Session Message
RESERVED = 0
LENGTH = 4873
[ SMBNegociate Protocol Request Header ]###
Start = '\xfeSMB'
Command = 64
Error_Class= 0
Reserved = 1
Error_code= 0
Flags = 0
Flags2 = 0
PIDHigh = 5
Signature = 0
Unused = 0
TID = 183
PID = 0
UID = 0
MID = 0
WordCount = 0
ByteCount = 0
[ SMB Negotiate Protocol Request Tail ]###
BufferFormat= 0
BufferData= '\x03'
Also you can try after that to decode the packet with the different clases:
packet.decode_payload_as(SMBNegociate Protocol Request Header)