add option in tcp with scapy - python

Upon the receive of a TCP ACK (with option experiment) like this
I want to generate a TCP SYN+ACK (with option experiment and Fast Open Cookie) as indicated below
I want to generate the TCP SYN+ACK with scapy so I added
So I added 254 : ("RFC3692-style Experiment","!HHH") in the /usr/share/pyshared/scapy/layers/inet.py like this
TCPOptions = (
{ 0 : ("EOL",None),
1 : ("NOP",None),
2 : ("MSS","!H"),
3 : ("WScale","!B"),
4 : ("SAckOK",None),
5 : ("SAck","!"),
8 : ("Timestamp","!II"),
14 : ("AltChkSum","!BH"),
15 : ("AltChkSumOpt",None),
25 : ("Mood","!p"),
254 : ("Experiment","!HHHH")
},
{ "EOL":0,
"NOP":1,
"MSS":2,
"WScale":3,
"SAckOK":4,
"SAck":5,
"Timestamp":8,
"AltChkSum":14,
"AltChkSumOpt":15,
"Mood":25,
"Experiment":254
} )
And upon the receive of the TCP ACK (with experiment option), I executhe the following scapy function:
TCP_SYNACK=TCP(sport=Ddport, dport=Ssport, flags="SA", seq=SeqNr, ack=AckNr, options=[('Experiment',0xf989,0xcafe,0x0102,0x0002),('NOP',0),('NOP',0)])
ANSWER=sr1(ip/TCP_SYNACK)
But I got a python error. It looks like I made error in the definition of the option field in the TCP packet with scapy. What I m doing wron?

I think you need to specify the optional field's value in a tuple format, as follows:
TCP_SYNACK = TCP(sport=Ddport, dport=Ssport, flags="SA", seq=SeqNr, ack=AckNr, options=[('Experiment', (0xf989, 0xcafe, 0x0102, 0x0002)), ('NOP', 0), ('NOP', 0)])

but I had the same problem. You can actually put an integer as the first element of your options tuple. I wanted to put in a hash, so I used the following code in scapy:
pkt = TCP(options=[("NOP", None), (19, "\xff\xff\xff\xff\xff\xff")])

Related

Generating a UDP message in python with a header and payload in python3

I am new to Networking and trying to implement a network calculator using python3 where the client's responsibility is to send operands and operators and the server will calculate the result and send it back to the client. Communication is through UDP messages and I am working on client side. Each message is comprised of a header and a payload and they are described as shown in the below figures.
UDP header:
I am familiar with sending string messages using sockets but having a hard-time with how to make a message with both header and payload and how to assign the bits for various attributes or how to generate message/client id's in the header and If there is any way to automatically generate the Id's. Any help or suggestions will be highly appreciated.
Thanks in advance
I will only do a portion of your homework.
I hope it will help you to find energy to work on missing parts.
import struct
import socket
CPROTO_ECODE_REQUEST, CPROTO_ECODE_SUCCESS, CPROTO_ECODE_FAIL = (0,1,2)
ver = 1 # version of protocol
mid = 0 # initial value
cid = 99 # client Id (arbitrary)
sock = socket.socket( ...) # to be customized
def sendRecv( num1, op, num2):
global mid
ocs = ("+", "-", "*", "/").index( op)
byte0 = ver + (ocs << 3) + (CPROTO_ECODE_REQUEST << 6)
hdr = struct.pack( "!BBH", byte0, mid, cid)
parts1 = (b'0000' + num1.encode() + b'0000').split(b'.')
parts2 = (b'0000' + num2.encode() + b'0000').split(b'.')
msg = hdr + parts1[0][-4:] + parts1[1][:4] + parts2[0][-4:] + parts2[1][:4]
socket.send( msg) # send request
bufr = socket.recv( 512) # get answer
# to do:
# complete socket_send and socket.recv
# unpack bufr into: verr,ecr,opr,value_i, value_f
# verify that verr, ecr, opr, are appropriate
# combine value_i and value_f into answer
mid += 1
return answer
result = sendRecv( '2.47', '+', '46.234')
There are many elements that haven't be specified by your teacher:
what should be the byte-ordering on the network (bigEndian or littleEndian)? The above example suppose it's bigEndian but you can easily modify the 'pack' statement to use littleEndian.
What should the program do if the received packet header is invalid?
What should the program do if there's no answer from server?
Payload: how should we interpret "4 most significant digits of fraction"? Does that mean that the value is in ASCII? That's not specified.
Payload: assuming the fraction is in ASCII, should it be right-justified or left-justified in the packet?
Payload: same question for integer portion.
Payload: if the values are in binary, are they signed or unsigned. It will have an affect on the unpacking statement.
In the program above, I assumed that:
values are positive and in ASCII (without sign)
integer portion is right-justified
fractional portion is left justified
Have fun!

minimalmodbus : Wrong Message being sent over Serial

So i want to send this code : 01 00 14 00 58 over ModBus RTU utilizing minimalmodbus to my VIRTUAL COM Port (COM2).
So i do get the "code" but i also get other bytes before and after the code and i can seem to know where they come from and how i can resolve it.
Terminal Output Image
I did try to use another libary called pymodbus but i got the same result
PythonCode :
import serial
import minimalmodbus as mrtu
mrtu.BYTEORDER_BIG = 1
insmrt = mrtu.Instrument('COM2',1 ,mrtu.MODE_RTU,close_port_after_each_call= False,debug=True)
insmrt.precalculate_read_size= False
insmrt.clear_buffers_before_each_transaction= True
insmrt.serial.baudrate = 38400
insmrt.serial.bytesize = 8
insmrt.serial.parity = serial.PARITY_NONE
insmrt.serial.stopbits =1
insmrt.serial.timeout = 5
insmrt.handle_local_echo = None
def inscommmand():
#insmrt.write_string = "$0100140058"
insmrt.write_registers(0,[0x01,0x14,0x58])
while 1:
try:
inscommmand()
except:
continue
I don't really know what you are trying to do or what you mean exactly by send this code by Modbus but I'm afraid what the library (minimalModbus) is doing is exactly what it is supposed to.
If you call:
insmrt.write_registers(0,[0x01,0x14,0x58])
The library will build the following Modbus frame:
01 10 0000 0003 06 0001 0014 0058 9ABE
This is what each value on this frame means:
01: The Slave Address (default is address 1)
10: The Function Code 16 (Write Multiple Holding Registers, 16 = 10 hex)
0000: The address of the first register (0000 hex = 0, +40001 offset = register #40001).
0003: Number of registers to write since you are giving a 3-element list
06: Number of data bytes that follow (3 registers x 2 bytes each = 6 bytes).
0001: Value to write to register 40001
0014: Value to write to register 40002
0058: Value to write to register 40003
9ABE: The CRC (Cyclic Redundancy Check) for error checking.
The sequence 01 00 14 00 58 is not a valid Modbus frame because there is no function code 00(only values from 1 to 6, 15, and 16 are allowed).
Maybe what you want is just to send that sequence over the serial port? Otherwise, you should think about where those values are coming from.

Python pseudonymisation of sniffed mac adresses

I have a assignment where I have to pseudonymisate the last 3 bytes of every mac adress I'm getting back as probe requests. By that I mean to format a printed mac adress like this ce:63:be:f5:04:00 to ce:63:be:aa:aa:a1everytime I'm sniffing. How can I do this in my python script?
from scapy.all import *
def PacketHandler(pkt) :
if pkt.haslayer(Dot11) :
if pkt.type == 0 and pkt.subtype == 4 :
print("Client with Mac: %s probing for SSID: %s" % (pkt.addr2, pkt.info))
sniff(iface="wlan1mon", prn = PacketHandler)
You could use Scapy's RandMAC()
>>> a = "aa:bb:cc:00:11:22"
>>> a[:9] + str(RandMAC())[:8]
'aa:bb:cc:c5:ab:23'
Or simply craft the randomization yourself.
If you don't know string slicing in Python, look it up: https://docs.python.org/3/tutorial/introduction.html#strings

Testing for delay time in a request

I am interested in being able to detect specific parameters using the loading time it took a request from when I send it to when it got to the server.
The request I am talking about is the SYN packet in a three way hand shake.
How can I do this?
Looking forward to your answer!
Of course also what language should I use...I am testing with Python + Scapy right now.
If you want to use Scapy (which seems a reasonable choice for what you want to do), you need to use the Packet.time attribute. Here is a simple example:
>>> def measure_delay(packet):
... ans, _ = sr(packet, verbose=False)
... if ans:
... return reduce(lambda x, y: y.time - x.time, ans[0])
...
>>> measure_delay(IP(dst='192.168.1.254')/TCP(dport=80))
0.07259798049926758
From a Unix command line, you can also use hping3, and look for the rtt= value:
# sudo hping3 --syn 192.168.1.254 -p 80 -c 1
HPING 192.168.1.254 (wlan0 192.168.1.254): S set, 40 headers + 0 data bytes
len=44 ip=192.168.1.254 ttl=64 DF id=0 sport=80 flags=SA seq=0 win=14600 rtt=3.1 ms
--- 192.168.1.254 hping statistic ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 3.1/3.1/3.1 ms

Trying to dynamically unpack data - python

i am trying to unpack data i receive from a packet dynamically, the main reason for this is i do not know the length of the ip addresses or the number of ip addresses in a packet, so need to unpack all
if our_or_addr_len == 4:
our_op_ip = struct.unpack(">BBBB", payload[6:10])
num_their_ips = struct.unpack(">B", payload[10])[0]
len_their_ips = struct.unpack(">B", payload[12])[0]
# Much better way to unpack the packet, does unpacking dynamically rather than set values
byte_string = '>{}'.format('b'*len_their_ips)
their_ips = []
for count in range(num_their_ips):
start = 13 + (count*len_their_ips)
end = start + len_their_ips
ip = struct.unpack(byte_string, payload[start:end])
print 'IP #{}: {}'.format(count+1, ip)
their_ips.append(ip)
return { 'tm': tm, 'our_or_ip_version': our_or_ip_version, 'our_or_addr_len': our_or_addr_len, 'our_op_ip': our_op_ip, 'num_their_ips': num_their_ips, 'len_their_ips': len_their_ips, 'their_ips': their_ips }
above is currently my code
what it should do is if my ip address is that of an ip v4 for, the for all of their ip address to unpack them for the packet starting at 13 in the payload for the length of their ip address for the number of ip addresses contained
currently it is only outputting one ip address although there is 2 ip address in the payload
shown in this output
{'our_or_addr_len': 4, 'len_their_ips': 4, 'our_op_ip': (00, 00, 00, 00), 'their_ips': [(0, 00, 00, 0)], 'tm': 1402265584, 'our_or_ip_version': 4, 'num_their_ips': 2}
how can i get both of the ip addresses returned, is there an issue with the loop as i think it should work so am confused as to why only one ip is returned
Managed to fix it it seemed my indenting was out on the their_ips.append(ip) so it was not getting assigned properly, weird how i had no errors however on complie, anyone got a good IDE program for linux and python ?

Categories

Resources