def run_sniffer(self, ip, port_number, queue): """ This starts the sniffing routine @param ip: Optional, the IP address to filter by. If None, will return all messages with matching port numbers that are visible to the network card, regardless of ip. @param port_number: The port number to sniff @param queue: The queue from the main process, to send back intercepted packets @return: None """ if port_number != 80 and port_number != 8080: # scapy.layers.http (or the older scapy_http) only recognize http # traffic to port 80 or 8080. So if the user chose another port, # we have to bind it here for the packet inspection to work (see # https://github.com/invernizzi/scapy-http/blob/master/scapy_http/http.py#L260) bind_layers(TCP, HTTP, dport=port_number) bind_layers(TCP, HTTP, sport=port_number) interfaces = self.get_interfaces() if not ip: filter_string = f"dst port {port_number}" else: filter_string = f"dst port {port_number} and host {ip}" # encase the "the_packet" callback in a partial function to pass # along the queue instance. sniff(prn=partial(self.the_packet, comm_queue=queue), iface=interfaces, store=-1, filter=filter_string, lfilter=lambda x: x.haslayer(HTTPRequest))
def main(n_nodes=5, username=None): bind_layers(IP, IntSight_Report, proto=224) print('Creating sniffer threads.') sniffers = [] for i in range(n_nodes): sniffers.append(PacketSniffer('s{}-eth3'.format(i + 1))) print('Starting the sniffer threads.') for s in sniffers: s.start() # print('Waiting to finish.', end='') stop_flag = 0 while stop_flag == 0: with open('/tmp/intsight_flag') as f: stop_flag = int(f.read()) if stop_flag == 0: # print('.', end='') # sys.stdout.flush() time.sleep(2) # print('IntSight Receiver: Bye') if username is not None: os.system('chown -R {}: .'.format(username)) os._exit(0)
def _before_parsing(self): """ Before all packets are parsed we need to assure that after the UDP layer follows directly the raw payload """ from scapy.all import bind_layers bind_layers(UDP, RTP)
def __init__(self, role, host, **kwargs): self.seq = 0 self.next_seq = 1 self.ack = 1 self.received_packets = deque() self.outstanding_segments = set() self.cwnd = 1 * MSS self.ssthresh = 64 * 1024 # 64KB self.dupack = 0 self.state = "slow_start" # see [RFC 6298] on how the retransmission timer works self.retransmission_timer = None self.role = role # sender or receiver self.log_cache = None if host == 'h1': self.src_ip = H1_ADDR self.dst_ip = H2_ADDR self.src_port = H1_PORT self.dst_port = H2_PORT if host == 'h2': self.src_ip = H2_ADDR self.dst_ip = H1_ADDR self.src_port = H2_PORT self.dst_port = H1_PORT self.limit = None # stop the sender after seq_no exceeding this limit if role == 'sender': if 'limit' in kwargs: self.limit = kwargs['limit'] # list of time logs for plotting self.seq_log, self.ack_log = [], [] self.log_attacker = False # verbose flag self.verbose = kwargs['verbose'] """ [defense against DupACK spoofing and Optimistic ACKing] We use the "Singular Nonce" technique described in section 4.3. For each data segment that we send, we include a random 32-bit nonce. An ACK is only valid if it contains one of these nonces. When we receive a valid ACK, we remove the nonce it replies from the nonce pool. Therefore, DupACK spoofing or Optimistic ACKing are no longer viable because no more spoofed ACKs can be created a priori than there are actual data segments sent. """ self.nonce_pool = {} # seed the pseudorandom generator random.seed() # bind Nonce to TCP so that scapy can decode Nonce layer scp.bind_layers(scp.TCP, Nonce, dport=H1_PORT) scp.bind_layers(scp.TCP, Nonce, dport=H2_PORT)
def _update_IP_with_DSR(): """Internal method to update `IP` for DSR.""" proto = None for f in IP.fields_desc: if f.name == "proto": proto = f assert proto is not None proto.i2s[const.IP_PROTO_DSR] = "dsr" # bind protocol layers so that proto field gets set automatically bind_layers(IP, DSRPacket, frag=0, proto=const.IP_PROTO_DSR) bind_layers(DSRPacket, UDP, nextheader=const.IP_PROTO_UDP) bind_layers(DSRPacket, TCP, nextheader=const.IP_PROTO_TCP) bind_layers(DSRPacket, ICMP, nextheader=const.IP_PROTO_ICMP) bind_layers(DSRPacket, IP, nextheader=const.IP_PROTO_IP)
def main(): addr = socket.gethostbyname(sys.argv[1]) iface = 'enp0s8' bind_layers(IP, nodeCount, proto=253) pkt = Ether(src=get_if_hwaddr(iface), dst="ff:ff:ff:ff:ff:ff") / IP( dst=addr, proto=253) / nodeCount(count=0, INT=[]) #sendp(pkt, iface=iface) #pkt.show2() while True: sendp(pkt, iface=iface) pkt.show2() sleep(0.2)
def receive_from_switch(): iface = 'veth32' bind_layers(Ether, IP) bind_layers(IP, UDP) bind_layers(UDP, SAINA_hdr) bind_layers(SAINA_hdr, DATA) print("sniffing on %s" % iface) sniff(iface = iface, prn = lambda x: handle_pkt(x))
def _init_fields_desc(): """Internal method to initialize `PseudoIPv4.fields_desc`; this removes unnecessary fields from the header.""" PseudoIPv4.fields_desc = [IP.fields_desc[10], # src \ IP.fields_desc[11], # dst \ ByteField("zero", 0), # zero \ IP.fields_desc[8], # proto \ IP.fields_desc[3] ] # len bind_layers(PseudoIPv4, IP, proto=const.IP_PROTO_IP) bind_layers(PseudoIPv4, ICMP, proto=const.IP_PROTO_ICMP) bind_layers(PseudoIPv4, TCP, proto=const.IP_PROTO_TCP) bind_layers(PseudoIPv4, UDP, proto=const.IP_PROTO_UDP)
def update_template(self, packet): """Updates IPFIXData class with new data template. Registers IPFIX data layer with scapy using the new template. :param packet: Packet containing an IPFIX template. :type packet: scapy.Ether """ template_list = packet['IPFIX template'].Template template_id = packet['IPFIX template'].Template_ID IPFIXData.fields_desc = [] for item in template_list[::2]: try: IPFIXData.fields_desc.append(self.template_elements[item]) except KeyError: raise KeyError( "Unknown IPFIX template element with ID {0}".format(item)) bind_layers(IPFIXHeader, IPFIXData, Set_ID=template_id) # if the packet doesn't end here, assume it contains more data sets bind_layers(IPFIXData, IPFIXData)
def __init__(self, batch_size, sending_interval, wireless_interface, data_store): """ Initialize an aDTN instance and its respective key manager and message store, as well as a sending message pool from which the next sending batch gets generated. Define aDTNInnerPacket to be the payload of aDTNPacket. Define aDTNPacket to be the payload of Ethernet frames of type 0xcafe. Set up a scheduler to handle message sending. Define a thread to handle received messages. The wireless interface should be previously set to ad-hoc mode and its ESSID should be the same in other devices running aDTN. :param batch_size: number of packets to transmit at each sending operation :param sending_interval: number of seconds between two sending operations :param wireless_interface: wireless interface to send and receive packets """ self._batch_size = batch_size self._sending_freq = sending_interval self._wireless_interface = wireless_interface self._km = KeyManager() self.data_store = DataStore(data_store) self._sending_pool = [] self._scheduler = sched.scheduler(time, sleep) self._sending = None self._sniffing = None self._thread_send = None self._thread_receive = None self._sent_pkt_counter = None self._received_pkt_counter = None self._decrypted_pkt_counter = None self._start_time = None self._mac_address = macget(getcard(wireless_interface)) self._sending_socket = L2Socket(iface=self._wireless_interface) bind_layers(aDTNPacket, aDTNInnerPacket) bind_layers(Ether, aDTNPacket, type=ETHERTYPE) log_debug("MAC address in use: {}".format(self._mac_address)) self._stats_file_name = '{}_{}.stats'.format(batch_size, sending_interval)
def main(): iface = 'veth7' print("sniffing on %s" % iface) sys.stdout.flush() bind_layers(Ether, DDoSD, type=0x6605) bind_layers(DDoSD, IP, ethertype=0x0800) bind_layers(IP, DDoSDPayload, proto=253) sniff(filter='', iface = iface, prn = lambda x: handle_pkt(x))
def set_current_inf_hf(seg, hf, pkt): """Calculates offsets for hf-th HF in seg-th segment and saves them in the packet. """ # TODO will break when ipv4 is not hard-coded total_before = sum((1 + len(pkt.path[prev].hops)) for prev in range(seg)) pkt.curr_inf = 32 // 8 + total_before pkt.curr_hf = 32 // 8 + total_before + 1 + hf """ set correct headers """ pkt.next_hdr = scapy.IP_PROTOS.udp #pkt.ext.hdr_len = 4 + 4 + 16 scapy.bind_layers(UDP, SCION, sport=50000) scapy.bind_layers(UDP, SCION, dport=50000) scapy.bind_layers(SCION, UDP) return pkt
class tenant(Packet): name = "tenant" fields_desc = [ IntField("id", 10), IntField("enq_timestamp", 0), IntField("enq_qdepth", 0), IntField("deq_timedelta", 0), IntField("deq_qdepth", 0), IntField("total_pkt_count", 0), IntField("total_packet_length", 0), BitField("inter_packet_gap", 0x0000000000000, 48) ] bind_layers( UDP, tenant, ) def get_if(): ifs = get_if_list() iface = None # "h1-eth0" for i in get_if_list(): if "eth0" in i: iface = i break if not iface: print "Cannot find eth0 interface" exit(1) return iface
pkt._config = self._config return pkt def clone_with(self, *args, **kargs): pkt = Packet.clone_with(self, *args, **kargs) pkt._config = self._config return pkt def length(self): """Get the length of the raw data""" # Manage the length of the packet if a length is provided return self._config["length"] # Make sure an IOPS follows a data bind_layers(PNIORealTimeRawData, PNIORealTimeIOxS) ############################### # PROFINET Real-Time Fields # ############################### class LowerLayerBoundPacketListField(PacketListField): """PacketList which binds each underlayer of packets to the current pkt""" def m2i(self, pkt, m): return self.cls(m, _underlayer=pkt) class NotionalLenField(Field): """A len fields which isn't present in the machine representation, but is
IntField("egress_byte_cnt", 0), IntField("egress_drop_cnt", 0)] def extract_padding(self, p): return "", p class MRI(Packet): fields_desc = [FieldLenField("length", None, length_of="swtraces", adjust=lambda pkt,l:l*41+4), ShortField("count", 0), PacketListField("swtraces", [], SwitchTrace, count_from=lambda pkt:(pkt.count*1))] bind_layers(Ether, SourceRoute, type=0x1234) bind_layers(SourceRoute, SourceRoute, bos=0) bind_layers(SourceRoute, IPv6, bos=1) bind_layers(IPv6, MRI,nh=150) def main(): if len(sys.argv)<2: print 'pass 2 arguments: <destination>' exit(1) #addr = socket.gethostbyname(sys.argv[1]) iface = get_if() print "sending on interface %s to %s" % (iface, sys.argv[1]) while True:
scapy_all.LEIntEnumField("status", 0, {0: "success"}), scapy_all.LELongField("sender_context", 0), scapy_all.LEIntField("options", 0), ] def extract_padding(self, p): return p[:self.length], p[self.length:] def post_build(self, p, pay): if self.length is None and pay: l = len(pay) p = p[:2] + struct.pack("<H", l) + p[4:] return p + pay scapy_all.bind_layers(scapy_all.TCP, ENIP_TCP, dport=44818) scapy_all.bind_layers(scapy_all.TCP, ENIP_TCP, sport=44818) scapy_all.bind_layers(ENIP_TCP, ENIP_RegisterSession, command_id=0x0065) scapy_all.bind_layers(ENIP_TCP, ENIP_SendRRData, command_id=0x006f) scapy_all.bind_layers(ENIP_TCP, ENIP_SendUnitData, command_id=0x0070) scapy_all.bind_layers(ENIP_SendUnitData_Item, ENIP_ConnectionAddress, type_id=0x00a1) scapy_all.bind_layers(ENIP_SendUnitData_Item, ENIP_ConnectionPacket, type_id=0x00b1) if __name__ == '__main__': # Test building/dissecting packets # Build a raw packet over ENIP
BitField("out_time", 0, 48), BitField("queue_time", 0, 32)] def extract_padding(self, p): return "", p class MRI2(Packet): fields_desc = [FieldLenField("length", None, length_of="swtraces", adjust=lambda pkt,l:l*23+4), ShortField("count", 0), PacketListField("swtraces", [], SwitchTrace2, count_from=lambda pkt:(pkt.count*1))] bind_layers(Ether, SourceRoute, type=0x1234) bind_layers(SourceRoute, SourceRoute, bos=0) bind_layers(SourceRoute, IPv6, bos=1) bind_layers(IPv6, Bitmap, nh=150) bind_layers(Bitmap, MRI1, bit_label=228) bind_layers(Bitmap, MRI2, bit_label=255) def main(): if len(sys.argv)<2: print 'pass 2 arguments: <destination>' exit(1) #addr = socket.gethostbyname(sys.argv[1]) iface = get_if() print "sending on interface %s to %s" % (iface, sys.argv[1])
BitField("epoch", 1, 16), IntField("seg_number", 0), BitField("pool_version", 1, 8), IntField("pool_index", 1), ] class ENTRY(Packet): name = "ENTRY" fields_desc = [SignedIntField("value", 0)] def guess_payload_class(self, payload): return ENTRY bind_layers(UDP, frame_type) bind_layers(frame_type, preamble) bind_layers(preamble, ENTRY) def get_if(): ifs = get_if_list() iface = None for i in get_if_list(): if iface in i: iface = i break if not iface: print("Cannot find %s interface" % (iface)) exit(1) return iface
b'\xff\xff\xff\xff\x00\x00\x00\x00' + b'\xff\xff\xff\xff\x00\x00\x00\x00' + b'\xff\xff\xff\xff\x00\x00\x00\x00') # Moved ENIP_UDP_SequencedAddress() to enip_cpf file with new name CPF_SequencedAddressItem # Moved ENIP_UDP_ITEM into enip_cpf file as new class CPF_ITEM # ENIP_UDP moved to new file enip.py --> Keeps all EtherNet/IP Level # processing in the same file rather than splitting based on upper layer - MED # Port 44818 - Utilizes command_id structure rather than CPF structure # scapy_all.bind_layers(scapy_all.UDP, enip.ENIP_PACKET, sport=2222, dport=2222) scapy_all.bind_layers(scapy_all.UDP, enip.ENIP_PACKET, dport=44818) scapy_all.bind_layers(scapy_all.UDP, enip.ENIP_PACKET, sport=44818) # Added additional binding options for ENIP_UDP - MED; needed for scy-phy test case # # Port 2222 - Utilizes CPF structure rather than command_id structure scapy_all.bind_layers(scapy_all.UDP, enip.ENIP_UDP, sport=2222, dport=2222) # scapy_all.bind_layerports(scapy_all.UDP, enip.ENIP_UDP, dport=44818) # scapy_all.bind_layers(scapy_all.UDP, enip.ENIP_UDP, sport=44818) # RegisterSession, SendRRData, SendUnitData only sent via TCP # scapy_all.bind_layers(enip.ENIP_UDP, enip.ENIP_RegisterSession, command_id=0x0065) # scapy_all.bind_layers(enip.ENIP_UDP, enip.ENIP_SendRRData, command_id=0x006f) # scapy_all.bind_layers(enip.ENIP_UDP, enip.ENIP_SendUnitData, command_id=0x0070) scapy_all.bind_layers(enip.ENIP_UDP, enip.ENIP_ListServices, command_id=0x0004) scapy_all.bind_layers(enip.ENIP_UDP, enip.ENIP_ListIdentity, command_id=0x0063)
2: 'Variable Length'}), ByteEnumField('NextProto', 3, {1: 'IPv4', 2: 'IPv6', 3: 'Ethernet', 4: 'NSH', 5: 'MPLS'}), X3BytesField('NSP', 0), ByteField('NSI', 1), ConditionalField(XIntField('NPC', 0), lambda pkt: pkt.MDType == 1), ConditionalField(XIntField('NSC', 0), lambda pkt: pkt.MDType == 1), ConditionalField(XIntField('SPC', 0), lambda pkt: pkt.MDType == 1), ConditionalField(XIntField('SSC', 0), lambda pkt: pkt.MDType == 1), ConditionalField(PacketListField("ContextHeaders", None, NSHTLV, count_from="Length"), lambda pkt: pkt.MDType == 2) ] def mysummary(self): return self.sprintf("NSP: %NSP% - NSI: %NSI%") bind_layers(Ether, NSH, {'type': 0x894F}, type=0x894F) bind_layers(VXLAN, NSH, {'flags': 0xC, 'NextProtocol': 4}, NextProtocol=4) bind_layers(GRE, NSH, {'proto': 0x894F}, proto=0x894F) bind_layers(NSH, IP, {'NextProto': 1}, NextProto=1) bind_layers(NSH, IPv6, {'NextProto': 2}, NextProto=2) bind_layers(NSH, Ether, {'NextProto': 3}, NextProto=3) bind_layers(NSH, NSH, {'NextProto': 4}, NextProto=4) bind_layers(NSH, MPLS, {'NextProto': 5}, NextProto=5)
class Set(Packet): name = "Set" fields_desc = [ShortField("setID", 256), ShortField("length", None)] def guess_payload_class(self, payload): if self.setID == 2: return Template elif self.setID > 255: return Data else: return Packet.guess_payload_class(self, payload) bind_layers(IPFIX, Set) bind_layers(UDP, IPFIX, dport=4739) class IPFIXDecoder(object): """ IPFIX data set decoder """ def __init__(self): self._templates = [] def add_template(self, template): """ Add IPFIX template :param template: IPFIX template """
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. """Ethernet/IP over TCP scapy dissector""" import struct from scapy import all as scapy_all import enip import enip_cpf # Moved all ENIP classes to file enip.py --> Keeps all EtherNet/IP Level # processing in the same file rather than splitting based on upper layer - MED scapy_all.bind_layers(scapy_all.TCP, enip.ENIP_PACKET, dport=44818) scapy_all.bind_layers(scapy_all.TCP, enip.ENIP_PACKET, sport=44818) scapy_all.bind_layers(enip_cpf.CPF_AddressDataItem, enip.ENIP_ConnectionAddress, type_id=0xA1) scapy_all.bind_layers(enip_cpf.CPF_DataItem, enip.ENIP_ConnectionPacket, type_id=0xB1) scapy_all.bind_layers(enip_cpf.CPF_Item, enip.ENIP_ConnectionAddress, type_id=0x00A1) scapy_all.bind_layers(enip_cpf.CPF_Item, enip.ENIP_ConnectionPacket, type_id=0x00B1) if __name__ == '__main__': # Test building/dissecting packets # Build a raw packet over ENIP pkt = scapy_all.Ether(src='01:23:45:67:89:ab', dst='ba:98:76:54:32:10') pkt /= scapy_all.IP(src='192.168.1.1', dst='192.168.1.42') pkt /= scapy_all.TCP(sport=10000, dport=44818) # Modified to reflect changes in code names and locations - MED pkt /= enip.ENIP_PACKET()
name = "SWAT_P1_RIO_AI" fields_desc = [ scapy_all.LEShortField('counter', 0), scapy_all.LEIntField('padding', 0), scapy_all.LEShortField('level', 0), scapy_all.LEShortField('flow', 0), scapy_all.FieldListField("spare", [], scapy_all.LEShortField("", 0), length_from=lambda p: p.underlayer.length - 10), ] class SWAT_P1_WRIO_AI(scapy_all.Packet): name = "SWAT_P1_WRIO_AI" fields_desc = [ scapy_all.LEShortField('counter', 0), scapy_all.LEIntField('padding', 0), scapy_all.LEShortField('level', 0), scapy_all.LEShortField('flow', 0), scapy_all.FieldListField("spare", [], scapy_all.LEShortField("", 0), length_from=lambda p: p.underlayer.length - 10), ] scapy_all.bind_layers(scapy_all.TCP, enip_cpf.ENIP_CPF, dport=2222) scapy_all.bind_layers(scapy_all.UDP, enip_cpf.ENIP_CPF, sport=2222) scapy_all.bind_layers(enip_cpf.CPF_AddressDataItem, SWAT_P1_RIO_AI, length=32) scapy_all.bind_layers(enip_cpf.CPF_AddressDataItem, SWAT_P1_RIO_DI, length=10) scapy_all.bind_layers(enip_cpf.CPF_AddressDataItem, SWAT_P1_RIO_DO, length=22) scapy_all.bind_layers(enip_cpf.CPF_AddressDataItem, SWAT_P1_PLC, length=8) # Comment for WRIO # scapy_all.bind_layers(enip_cpf.CPF_AddressDataItem, SWAT_P1_WRIO_AI, length=10) # Uncomment for WRIO
PNIO_FRAME_IDS[i] = "RT_CLASS_1" for i in range(0xC000, 0xFC00): PNIO_FRAME_IDS[i] = "RT_CLASS_UDP" for i in range(0xFF80, 0xFF90): PNIO_FRAME_IDS[i] = "FragmentationFrameID" ################# ## PROFINET IO ## ################# class ProfinetIO(Packet): """Basic PROFINET IO dispatcher""" fields_desc = [XShortEnumField("frameID", 0, PNIO_FRAME_IDS)] overload_fields = { Ether: {"type": 0x8892}, UDP: {"dport": 0x8892}, } def guess_payload_class(self, payload): # For frameID in the RT_CLASS_* range, use the RTC packet as payload if (self.frameID >= 0x0100 and self.frameID < 0x1000) or \ (self.frameID >= 0x8000 and self.frameID < 0xFC00): from scapy.contrib.pnio_rtc import PNIORealTime return PNIORealTime else: return Packet.guess_payload_class(self, payload) bind_layers(Ether, ProfinetIO, type=0x8892) bind_layers(UDP, ProfinetIO, dport=0x8892)
return _self_build(self, field_pos_list) class HTTP(Packet): name = "HTTP" def do_dissect(self, s): return s def guess_payload_class(self, payload): """ Decides if the payload is an HTTP Request or Response, or something else """ try: prog = re.compile(r"^(?:OPTIONS|GET|HEAD|POST|PUT|DELETE|TRACE|CONNECT) " r"(?:.+?) " r"HTTP/\d\.\d$") req = payload[: payload.index("\r\n")] result = prog.match(req) if result: return HTTPRequest else: prog = re.compile(r"^HTTP/\d\.\d \d\d\d .+?$") result = prog.match(req) if result: return HTTPResponse except: pass return Packet.guess_payload_class(self, payload) bind_layers(TCP, HTTP)
class EAPOLKeyDot11(Packet): name = "EAPOL - Key Descriptor - 802.11" fields_desc = [ FlagsField("flags", 0, 13, ["KeyType", "res4", "res5", "Install", "ACK", "MIC", "Secure", "Error", "Request", "Encrypted", "SMK", "res14", "res15"]), BitEnumField("version", 1, 3, {1: "MD5/RC4", 2: "SHA1/AES"}), ShortField("keylen", 0), LongField("replay", 0), StrFixedLenField("nonce", "\x00" * 32, 32), StrFixedLenField("iv", "\x00" * 16, 16), StrFixedLenField("rsc", "\x00" * 8, 8), LongField("res", 0), StrFixedLenField("mic", "\x00" * 16, 16), FieldLenField("keydatalen", None, length_of="keydata", fmt="H"), StrLenField("keydata", "", length_from=lambda x: x.keydatalen) ] bind_layers( Ether, EAPOL, type=0x888E) bind_layers( EAPOL, EAP, type=0) bind_layers( EAPOL, EAPOLKey, type=3) bind_layers( EAPOLKey, EAPOLKeyDot11, desc_type=254) bind_layers( EAPOLKey, EAPOLKeyDot11, desc_type=2) class CredentialSniffer(AirScannerPlugin, AirHostPlugin, AirInjectorPlugin): """ A plugin that can be used by any module to look for WPA-PSK Handshakes and WPA-EAP credentials. """ def __init__(self, config): super(CredentialSniffer, self).__init__(config, "credentialsniffer") self.running_interface = self.config["sniffing_interface"] self.running_bssid = self.config["bssid"] self.running_ssid = self.config["ssid"]
class ENIP_UDP(scapy_all.Packet): """Ethernet/IP packet over UDP""" name = "ENIP_UDP" fields_desc = [ utils.LEShortLenField("count", None, count_of="items"), scapy_all.PacketListField("items", [], ENIP_UDP_Item, count_from=lambda p: p.count), ] def extract_padding(self, p): return "", p scapy_all.bind_layers(scapy_all.UDP, ENIP_UDP, sport=2222, dport=2222) scapy_all.bind_layers(ENIP_UDP_Item, ENIP_UDP_SequencedAddress, type_id=0x8002) if __name__ == '__main__': # Test building/dissecting packets # Build a keep-alive packet pkt = scapy_all.Ether(src='00:1d:9c:c8:13:37', dst='01:00:5e:40:12:34') pkt /= scapy_all.IP(src='192.168.1.42', dst='239.192.18.52') pkt /= scapy_all.UDP(sport=2222, dport=2222) pkt /= ENIP_UDP(items=[ ENIP_UDP_Item() / ENIP_UDP_SequencedAddress(connection_id=1337, sequence=42), ENIP_UDP_Item(type_id=0x00b1) / scapy_all.Raw(load=ENIP_UDP_KEEPALIVE), ]) # Build! data = str(pkt)
BitField('NextProtocol', 0, 1), BitField('Reserved', 0, 1), BitField('OAM', 0, 1), ConditionalField(BitField('Reserved', 0, 16), lambda pkt: pkt.NextProtocol == 1), ConditionalField(ByteField('NextProtocolID', 0), lambda pkt: pkt.NextProtocol == 1), ConditionalField(X3BytesField('Reserved', 0), lambda pkt: pkt.NextProtocol == 0), X3BytesField('VNI', 0), ByteField('Reserved', 0)] def mysummary(self): s = self.sprintf("VNI:%VNI%") return s # IANA VxLAN+NSH dport is defined to 6633, but also attach to 4789 bind_layers(UDP, VxLAN, dport=6633) bind_layers(UDP, VxLAN, dport=4789) class NSH(Packet): name = "NSH" fields_desc = [BitField('Ver', 0, 2), BitField('OAM', 0, 1), BitField('Critical Metadata', 0, 1), BitField('Reserved', 0, 6), BitField('Length', 0, 6), ByteEnumField('MDType', 1, {1: 'Fixed Length', 2: 'Variable Length'}), ByteEnumField('NextProto', 3, {1: 'IPv4', 2: 'IPv6', 3: 'Ethernet'}), BitField('ServicePath', 0, 24), ByteField('ServiceIndex', 255), ConditionalField(XIntField('NPC', 0), lambda pkt: pkt.MDType == 1),
ConditionalField(BitField("auth_reserved", 0, 8), bfd_is_md5_or_sha1_used), ConditionalField(BitField("auth_seq_num", 0, 32), bfd_is_md5_or_sha1_used), ConditionalField(StrField("auth_key_hash", "0" * 16), bfd_is_md5_used), ConditionalField(StrField("auth_key_hash", "0" * 20), bfd_is_sha1_used), ] def mysummary(self): return self.sprintf("BFD(my_disc=%BFD.my_discriminator%," "your_disc=%BFD.your_discriminator%)") # glue the BFD packet class to scapy parser bind_layers(UDP, BFD, dport=BFD.udp_dport) class BFD_vpp_echo(Packet): """ BFD echo packet as used by VPP (non-rfc, as rfc doesn't define one) """ udp_dport = 3785 #: BFD echo destination port per RFC 5881 name = "BFD_VPP_ECHO" fields_desc = [ BitField("discriminator", 0, 32), BitField("expire_time_clocks", 0, 64), BitField("checksum", 0, 64) ] def mysummary(self):
def bind_layers(): from scapy.all import bind_layers from scapy.layers.inet import TCP from .iso_8327_1 import ISO_8327_1_Session_Dummy from ._internal import Pseudo_Layer # TPKT is nowadays above tcp and usually on port 102 bind_layers(TCP, TPKT, sport=tpkt.TPKT_ISO_TSAP_PORT) bind_layers(TCP, TPKT, dport=tpkt.TPKT_ISO_TSAP_PORT) # cotp bind_layers(TPKT, COTP) # ISO 8327_1, Session establishment should be in a COTP Data PDU # YET!! MMS may be layered right on top of COTP in a minimized network stack... so bind the next layer to a # pseudo-layer that guesses the right class. bind_layers(COTP_Data, Pseudo_Layer) # ISO 8823, this is where it gets tricky... bind_layers(ISO_8327_1_Session_Accept, ISO_8823_Presentation_CPA_Type) bind_layers(ISO_8327_1_Session_Dummy, ISO_8823_Presentation_CPC_Type) bind_layers(ISO_8327_1_Session_Connect, ISO_8823_Presentation_CP_Type)
class ECMP(Packet): name = "ECMP" fields_desc = [ ShortField("is_load_balance", 1), ShortField("type", 0), ShortField("is_track", 0), IntField("port2_bytes", 0), IntField("port3_bytes", 0), IntField("seq", 0) ] # bind ECMP class with other layers bind_layers(Ether, ECMP, type=0x1234) bind_layers(ECMP, IP, type=0x1234) flowDict = collections.defaultdict(list) localInversionDict = collections.defaultdict(int) def get_if(): ifs = get_if_list() iface = None for i in get_if_list(): if "eth0" in i: iface = i break if not iface: print "Cannot find eth0 interface"
fields_desc = [ _IPOption_HDR, FieldLenField("length", None, fmt="B", length_of="swtraces", adjust=lambda pkt, l: l * 2 + 4), ShortField("count", 0), IntField("pathid", 0), IntField("pcount", 0), PacketListField("swtraces", [], SwitchTrace, count_from=lambda pkt: (pkt.count * 1)) ] bind_layers(Ether, SourceRoute, type=0x1234) bind_layers(SourceRoute, SourceRoute, bos=0) bind_layers(SourceRoute, SourceRoutingTail, bos=1) def main(): iface = 'h2-eth0' print "sniffing on %s" % iface sys.stdout.flush() sniff(filter="udp and port 4321", iface=iface, prn=lambda x: handle_pkt(x)) if __name__ == '__main__': main()
3: 'Ethernet', 4: 'NSH', 5: 'MPLS' }), X3BytesField('NSP', 0), ByteField('NSI', 1), ConditionalField(XIntField('NPC', 0), lambda pkt: pkt.MDType == 1), ConditionalField(XIntField('NSC', 0), lambda pkt: pkt.MDType == 1), ConditionalField(XIntField('SPC', 0), lambda pkt: pkt.MDType == 1), ConditionalField(XIntField('SSC', 0), lambda pkt: pkt.MDType == 1), ConditionalField( PacketListField("ContextHeaders", None, NSHTLV, count_from="Length"), lambda pkt: pkt.MDType == 2) ] def mysummary(self): return self.sprintf("NSP: %NSP% - NSI: %NSI%") bind_layers(Ether, NSH, {'type': 0x894F}, type=0x894F) bind_layers(VXLAN, NSH, {'flags': 0xC, 'NextProtocol': 4}, NextProtocol=4) bind_layers(GRE, NSH, {'proto': 0x894F}, proto=0x894F) bind_layers(NSH, IP, {'NextProto': 1}, NextProto=1) bind_layers(NSH, IPv6, {'NextProto': 2}, NextProto=2) bind_layers(NSH, Ether, {'NextProto': 3}, NextProto=3) bind_layers(NSH, NSH, {'NextProto': 4}, NextProto=4) bind_layers(NSH, MPLS, {'NextProto': 5}, NextProto=5)
PNIO_FRAME_IDS[i] = "RT_CLASS_UDP" for i in range(0xFF80, 0xFF90): PNIO_FRAME_IDS[i] = "FragmentationFrameID" ################# ## PROFINET IO ## ################# class ProfinetIO(Packet): """Basic PROFINET IO dispatcher""" fields_desc = [XShortEnumField("frameID", 0, PNIO_FRAME_IDS)] overload_fields = { Ether: {"type": 0x8892}, UDP: {"dport": 0x8892}, } def guess_payload_class(self, payload): # For frameID in the RT_CLASS_* range, use the RTC packet as payload if (self.frameID >= 0x0100 and self.frameID < 0x1000) or \ (self.frameID >= 0x8000 and self.frameID < 0xFC00): from scapy.contrib.pnio_rtc import PNIORealTime return PNIORealTime else: return Packet.guess_payload_class(self, payload) bind_layers(Ether, ProfinetIO, type=0x8892) bind_layers(UDP, ProfinetIO, dport=0x8892)
pkt._config = self._config return pkt def clone_with(self, *args, **kargs): pkt = Packet.clone_with(self, *args, **kargs) pkt._config = self._config return pkt def length(self): """Get the length of the raw data""" # Manage the length of the packet if a length is provided return self._config["length"] # Make sure an IOPS follows a data bind_layers(PNIORealTimeRawData, PNIORealTimeIOxS) ############################### ## PROFINET Real-Time Fields ## ############################### class LowerLayerBoundPacketListField(PacketListField): """PacketList which binds each underlayer of packets to the current pkt""" def m2i(self, pkt, m): return self.cls(m, _underlayer=pkt) class NotionalLenField(Field): """A len fields which isn't present in the machine representation, but is computed from a given lambda"""
0x00b2: "Unconnected Message", 0x0100: "ListServices response", 0x8002: 'Sequenced Address Item', }), scapy_all.LEShortField("length", None), ] def extract_padding(self, p): return p[:self.length], p[self.length:] def post_build(self, p, pay): if self.length is None and pay: l = len(pay) p = p[:2] + struct.pack("<H", l) + p[4:] return p + pay class ENIP_CPF(scapy_all.Packet): name = "ENIP_CPF" fields_desc = [ utils.LEShortLenField("count", 2, count_of="items"), scapy_all.PacketListField("items", [CPF_AddressDataItem('', 0, 0), CPF_AddressDataItem('', 0, 0)], CPF_AddressDataItem, count_from=lambda p: p.count), ] def extract_padding(self, p): return '', p scapy_all.bind_layers(CPF_AddressDataItem, CPF_SequencedAddressItem, type_id=0x8002)
#!/usr/bin/env python import argparse import sys import socket import random import struct from scapy.all import sendp, send, get_if_list, get_if_hwaddr, bind_layers from scapy.all import Packet from scapy.all import Ether, IP, UDP from scapy.fields import * import readline class SourceRoute(Packet): fields_desc = [BitField("bos", 0, 1), BitField("port", 0, 15)] class SourceData(Packet): fields_desc = [ByteField("data", 0)] bind_layers(Ether, SourceRoute, type=0x1234) bind_layers(SourceRoute, SourceRoute, bos=0) bind_layers(SourceData, Ether) bind_layers(SourceRoute, IP, bos=1)
if match: ts.append(Token('num', match.group(1))) return i + match.end(), ts raise OpParseError("Expected binary operator '-', '+', '&', '|', or '^'.") def make_seq(p1, p2): def parse(s, i, ts): i, ts2 = p1(s, i, ts) return p2(s, i, ts2) return parse if __name__ == '__main__': bind_layers(Ether, P4calc, type=0x1234) parser = make_seq(num_parser, make_seq(op_parser, num_parser)) while True: user_input = input('> ') if user_input == "quit": break print(user_input) try: i, ts = parser(user_input, 0, []) pkt = Ether(dst='08:00:00:00:02:00', type=0x1234) pkt /= P4calc(op=ts[1].value, operand_a=int(ts[0].value), operand_b=int(ts[2].value)) pkt /= ' '
def extract_padding(self, p): return p[:self.length], p[self.length:] def post_build(self, p, pay): if self.length is None and pay: l = len(pay) p = p[:2] + struct.pack("<H", l) + p[4:] return p + pay # From enip_udp.py; same name and structure, just relocated class ENIP_UDP(scapy_all.Packet): """Ethernet/IP packet over UDP""" name = "ENIP_UDP" fields_desc = [ utils.LEShortLenField("count", None, count_of="items"), scapy_all.PacketListField("items", [], enip_cpf.CPF_Item, count_from=lambda p: p.count), ] def extract_padding(self, p): return "", p scapy_all.bind_layers(ENIP_PACKET, ENIP_ListServices, command_id=0x0004) scapy_all.bind_layers(ENIP_PACKET, ENIP_RegisterSession, command_id=0x0065) scapy_all.bind_layers(ENIP_PACKET, ENIP_SendRRData, command_id=0x006f) scapy_all.bind_layers(ENIP_PACKET, ENIP_SendUnitData, command_id=0x0070) scapy_all.bind_layers(ENIP_PACKET, ENIP_ListIdentity, command_id=0x0063) scapy_all.bind_layers(ENIP_SendUnitData_Item, ENIP_ConnectionAddress, type_id=0x00a1) scapy_all.bind_layers(ENIP_SendUnitData_Item, ENIP_ConnectionPacket, type_id=0x00b1)
""" Receives all data available during timeout from DTLS connection """ resp = [] if timeout: self._sock.settimeout(timeout) while True: try: data = self._sock.recvfrom(size) if not data: break resp.append(data[0]) except socket.timeout: break return DTLS("".join(resp)) bind_layers(DTLSRecord, DTLSAlert, {"content_type": TLSContentType.ALERT}) def show_dtls_packet(packet): """"Displays DTLS packet.""" if packet.getlayer(Raw): dtls = DTLSRecord(packet[Raw].load) print (dtls) # raw DTLS 1.0 Client Hello message DTLS_PING = ( "450000e63b1040004011e95d6a78b8116a788897e26b115c00d2167d16feff0000000000000" "00000bd010000b100000000000000b1feffbf00446ba28fda327463b4fcac60e7908e46920e046a4508" "b7623f89efc3ed2000000056c014c00a00390038003700360088008700860085c00fc00500350084c01" "3c0090033003200310030009a0099009800970045004400430042c00ec004002f00960041c012c00800"
if command != None: if command in IRC.commands: # to check if it's a irc command return IRC return Packet.guess_payload_class(self, payload) #return default guess '''this is no use because I implemented the dynamic proto detection, so it's now independent from port number :-) for port in IRC_Port: try: bind_layers(TCP, IRCRequest, dport = port) bind_layers(TCP, IRCResponse, sport = port) except: raise Exception("Scapy Binding Error!") ''' try: bind_layers(TCP, IRCDetector) #independent from port number except: raise Exception("Scapy Binding Error!") if __name__ == '__main__': try: t = rdpcap('one_irc.pcap') except: raise Exception("Pcap Reading Error!") t.show() for pkt in t: print '=' * 70 pkt.show()
def handle_pkt(pkt): print("got a packet") pkt.show2() # hexdump(pkt) sys.stdout.flush() class SourceRoute(Packet): fields_desc = [BitField("last_header", 0, 1), BitField("swid", 0, 7)] class SourceRoutingTail(Packet): fields_desc = [XShortField("etherType", 0x800)] bind_layers(Ether, SourceRoute, type=0x1111) bind_layers(SourceRoute, SourceRoute, last_header=0) bind_layers(SourceRoute, SourceRoutingTail, last_header=1) def main(): iface = 'h2-eth0' print("sniffing on %s" % iface) sys.stdout.flush() sniff(filter="udp and port 4321", iface=iface, prn=lambda x: handle_pkt(x)) if __name__ == '__main__': main()
scapy_all.StrLenField("message_padding", None, length_from=lambda pkt: pkt.message_size % 2), scapy_all.ByteField("route_path_size", 1), # TODO: size in words scapy_all.ByteField("reserved2", 0), scapy_all.ByteField("route_path_size_port", 1), scapy_all.ByteField("route_path_size_addr", 0), ] def post_build(self, p, pay): # Autofill the padding if len(p) % 2: p = p[:-4] + b"\0" + p[-4:] return p + pay scapy_all.bind_layers(enip_tcp.ENIP_ConnectionPacket, CIP) scapy_all.bind_layers(enip_tcp.ENIP_SendUnitData_Item, CIP, type_id=0x00b2) scapy_all.bind_layers(CIP, CIP_RespAttributesAll, direction=1, service=0x01) scapy_all.bind_layers(CIP, CIP_ReqGetAttributeList, direction=0, service=0x03) scapy_all.bind_layers(CIP, CIP_RespAttributesList, direction=1, service=0x03) scapy_all.bind_layers(CIP, CIP_MultipleServicePacket, service=0x0a) scapy_all.bind_layers(CIP, CIP_RespSingleAttribute, direction=1, service=0x0e) scapy_all.bind_layers(CIP, CIP_ReqReadOtherTag, direction=0, service=0x4c) scapy_all.bind_layers(CIP, CIP_ReqReadOtherTag, direction=0, service=0x4f) scapy_all.bind_layers(CIP, CIP_ReqForwardOpen, direction=0, service=0x54) scapy_all.bind_layers(CIP, CIP_RespForwardOpen, direction=1, service=0x54) # TODO: this is much imprecise :( # Need class in path to be 6 (Connection Manager) scapy_all.bind_layers(CIP, CIP_ReqConnectionManager, direction=0, service=0x52)
def main(): """Send IP ICMP packet from one traffic generator interface to the other. :raises RuntimeError: If the received packet is not correct.""" args = TrafficScriptArg([ u"tg_src_mac", u"tg_dst_mac", u"src_ip", u"dst_ip", u"dut_if1_mac", u"dut_if2_mac", u"src_rloc", u"dst_rloc" ], [u"ot_mode"]) tx_src_mac = args.get_arg(u"tg_src_mac") tx_dst_mac = args.get_arg(u"dut_if1_mac") rx_dst_mac = args.get_arg(u"tg_dst_mac") rx_src_mac = args.get_arg(u"dut_if2_mac") src_ip = args.get_arg(u"src_ip") dst_ip = args.get_arg(u"dst_ip") src_rloc = args.get_arg(u"src_rloc") dst_rloc = args.get_arg(u"dst_rloc") tx_if = args.get_arg(u"tx_if") rx_if = args.get_arg(u"rx_if") ot_mode = args.get_arg(u"ot_mode") rxq = RxQueue(rx_if) txq = TxQueue(tx_if) pkt_raw = Ether(src=tx_src_mac, dst=tx_dst_mac) if valid_ipv4(src_ip) and valid_ipv4(dst_ip): pkt_raw /= IP(src=src_ip, dst=dst_ip) pkt_raw /= ICMP() ip_format = IP elif valid_ipv6(src_ip) and valid_ipv6(dst_ip): pkt_raw /= IPv6(src=src_ip, dst=dst_ip) pkt_raw /= ICMPv6EchoRequest() ip_format = IPv6 else: raise ValueError(u"IP not in correct format") bind_layers(UDP, LispGPEHeader, dport=4341) pkt_raw /= Raw() sent_packets = list() sent_packets.append(pkt_raw) txq.send(pkt_raw) while True: if tx_if == rx_if: ether = rxq.recv(2, ignore=sent_packets) else: ether = rxq.recv(2) if ether is None: raise RuntimeError(u"ICMP echo Rx timeout") if ether.haslayer(ICMPv6ND_NS): # read another packet in the queue if the current one is ICMPv6ND_NS continue if ether.haslayer(ICMPv6ND_RA): # read another packet in the queue if the current one is ICMPv6ND_RA continue elif ether.haslayer(ICMPv6MLReport2): # read another packet in the queue if the current one is # ICMPv6MLReport2 continue # otherwise process the current packet break if rx_dst_mac == ether[Ether].dst and rx_src_mac == ether[Ether].src: print(u"MAC addresses match.") else: raise RuntimeError(f"Matching packet unsuccessful: {ether!r}") ip = ether.payload if ot_mode == u"6to4": if not isinstance(ip, IP): raise RuntimeError(f"Not an IP packet received {ip!r}") elif ot_mode == u"4to6": if not isinstance(ip, IPv6): raise RuntimeError(f"Not an IP packet received {ip!r}") elif not isinstance(ip, ip_format): raise RuntimeError(f"Not an IP packet received {ip!r}") lisp = ether.getlayer(LispGPEHeader).underlayer if not lisp: raise RuntimeError(u"Lisp layer not present or parsing failed.") # Compare data from packets if src_ip == lisp.src: print(u"Source IP matches source EID.") else: raise RuntimeError( f"Matching Src IP unsuccessful: {src_ip} != {lisp.src}") if dst_ip == lisp.dst: print(u"Destination IP matches destination EID.") else: raise RuntimeError( f"Matching Dst IP unsuccessful: {dst_ip} != {lisp.dst}") if src_rloc == ip.src: print(u"Source RLOC matches configuration.") else: raise RuntimeError( f"Matching Src RLOC unsuccessful: {src_rloc} != {ip.src}") if dst_rloc == ip.dst: print(u"Destination RLOC matches configuration.") else: raise RuntimeError( f"Matching dst RLOC unsuccessful: {dst_rloc} != {ip.dst}") sys.exit(0)
0x2: 'tag2', 0x3: 'tag3', 0x4: 'tag4', 0x5: 'tag5', 0x6: 'purge_valve', 0x7: 'tag7', 0x8: 'tag8', 0x9: 'tag9', 0xA: 'reactor_cooling_water_flow', 0xB: 'tag11', 0xC: 'tag12' } class TE_FCN_CONTROLS(scapy_all.Packet): name = "TE_FCN_CONTROLS" fields_desc = [ scapy_all.IntField('constant', 0), LEIEEEFloatField('value', 0), ] def extend_cip_bindings(self, payload): if self.direction == 1 and self.service == 0x4c and len(payload) >= 488: return TE_FCN_SENSORS return scapy_all.Packet.guess_payload_class(self, payload) cip.CIP.guess_payload_class = extend_cip_bindings scapy_all.bind_layers(cip.CIP, TE_FCN_CONTROLS, direction=0, service=0x4d)
scapy_all.LEIntEnumField("status", 0, {0: "success"}), scapy_all.LELongField("sender_context", 0), scapy_all.LEIntField("options", 0), ] def extract_padding(self, p): return p[: self.length], p[self.length :] def post_build(self, p, pay): if self.length is None and pay: l = len(pay) p = p[:2] + struct.pack("<H", l) + p[4:] return p + pay scapy_all.bind_layers(scapy_all.TCP, ENIP_TCP, dport=44818) scapy_all.bind_layers(scapy_all.TCP, ENIP_TCP, sport=44818) scapy_all.bind_layers(ENIP_TCP, ENIP_RegisterSession, command_id=0x0065) scapy_all.bind_layers(ENIP_TCP, ENIP_SendRRData, command_id=0x006F) scapy_all.bind_layers(ENIP_TCP, ENIP_SendUnitData, command_id=0x0070) scapy_all.bind_layers(ENIP_SendUnitData_Item, ENIP_ConnectionAddress, type_id=0x00A1) scapy_all.bind_layers(ENIP_SendUnitData_Item, ENIP_ConnectionPacket, type_id=0x00B1) if __name__ == "__main__": # Test building/dissecting packets # Build a raw packet over ENIP pkt = scapy_all.Ether(src="01:23:45:67:89:ab", dst="ba:98:76:54:32:10") pkt /= scapy_all.IP(src="192.168.1.1", dst="192.168.1.42") pkt /= scapy_all.TCP(sport=10000, dport=44818)
s.IntField("streamID1", None), s.IntField("ptpTimestamp", None), s.IntField("gateway", None), s.ShortField("pktDataLength", None), s.XByteField("pkt1394format", None), s.XByteField("pkt1394tcode", None), s.XByteField("sourceId", None), s.XByteField("dataBlockSize", None), s.XByteField("packing", None), s.XByteField("DBC", None), s.XByteField("formatId", None), s.XByteField("SYT", None), s.IntField("ptpUpper", None), s.IntField("ptpLower", None), ] s.bind_layers(s.Ether, AVTP, type=0x22f0) def pkt_avtp(pkt, fout, pkt_count): global wraps, prev_pkt_ts, ts_count, ts_accum, seq n = 0 avtp = pkt[AVTP] if avtp.controlData == 0x0: if seq['init'] == False: seq['last'] = avtp.sequence seq['init'] = True else: if avtp.sequence < seq['last']: if avtp.sequence != 0: print "Sequence wrap error at packet number %d" % (pkt_count) else:
# -*- coding: utf-8 -*- # Copyright (c) 2015 David I. Urbina, [email protected] # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. """Scapy Dissector for Ethernet/IP Implicit I/O messages of PLC 1.""" from scapy import all as scapy_all import enip_cpf scapy_all.bind_layers(scapy_all.TCP, enip_cpf.ENIP_CPF, dport=2222) scapy_all.bind_layers(scapy_all.UDP, enip_cpf.ENIP_CPF, sport=2222) # Comment for WRIO # scapy_all.bind_layers(enip_cpf.CPF_AddressDataItem, SWAT_P1_WRIO_AI, length=10) # Uncomment for WRIO
return _self_build(self, field_pos_list) class ICAP(Packet): name = "ICAP" def do_dissect(self, s): return s def guess_payload_class(self, payload): ''' Decides if the payload is an ICAP Request or Response, or something else ''' try: icap_req = payload[:payload.index("\r\n")] s1,s2,s3 = icap_req.split(" ") # @UnusedVariable s2 except: return Packet.guess_payload_class(self, payload) icap_versions = ["ICAP/0.9","ICAP/1.0","ICAP/1.1"] for icap_version in icap_versions: if s3 == icap_version: return ICAPRequest if s1 == icap_version: return ICAPResponse return Packet.guess_payload_class(self, payload) #bind_layers(TCP, ICAP) #bind_layers(TCP, ICAP) bind_layers(TCP, ICAP, dport=1344) bind_layers(TCP, ICAP, sport=1344)
from scapy.all import bind_layers import sys, os TYPE_MYTUNNEL = 0x1212 TYPE_IPV4 = 0x0800 class MyTunnel(Packet): name = "MyTunnel" fields_desc = [ShortField("pid", 0), ShortField("dst_id", 0)] def mysummary(self): return self.sprintf("pid=%pid%, dst_id=%dst_id%") bind_layers(Ether, MyTunnel, type=TYPE_MYTUNNEL) bind_layers(MyTunnel, IP, pid=TYPE_IPV4)
scapy_all.ConditionalField( scapy_all.LELongField("value32bit", 0), lambda p: p.logical_format == 0x2 ), ] def extract_padding(self, p): # print self.__class__.__name__ + ": P=" + str(p) # magic_value = 5: logic_value < 5 have no payload --> go to previous layer again; logic_value >=5 have payload --> process if self.logical_type < 5: return '',p else: return p, '' scapy_all.bind_layers(CIP_LogicalSegmentPadded, CIP_Logical_SpecialSegment, logical_type=5) # Logical Key Segment # # # class A_8bitValue(scapy_all.Packet): # fields_desc = [ # scapy_all.ByteField("value", 0), # ] # # def extract_padding(self, p): # # print self.__class__.__name__ + ": P=" + str(p) # return (), p # # # class A_16bitValue(scapy_all.Packet):
}), ] class SWAT_P4_RIO_AI(scapy_all.Packet): name = "SWAT_P4_RIO_AI" fields_desc = [ scapy_all.LEShortField('counter', 0), scapy_all.LEIntField('padding', 0), scapy_all.LEShortField('LIT401_Level', 0), scapy_all.LEShortField('AIT401_Hardness', 0), scapy_all.LEShortField('FIT401_Flow', 0), scapy_all.LEShortField('AIT402_ORP', 0), scapy_all.LEShortField('spare', 0), scapy_all.LEShortField('spare', 0), scapy_all.LEShortField('spare', 0), scapy_all.LEShortField('spare', 0), scapy_all.LEShortField('spare', 0), scapy_all.LEShortField('spare', 0), scapy_all.LEShortField('spare', 0), scapy_all.LEShortField('spare', 0), ] scapy_all.bind_layers(scapy_all.TCP, enip_cpf.ENIP_CPF, dport=2222) scapy_all.bind_layers(scapy_all.UDP, enip_cpf.ENIP_CPF, sport=2222) scapy_all.bind_layers(enip_cpf.CPF_AddressDataItem, SWAT_P4_RIO_AI, length=32) scapy_all.bind_layers(enip_cpf.CPF_AddressDataItem, SWAT_P4_RIO_DI, length=10) scapy_all.bind_layers(enip_cpf.CPF_AddressDataItem, SWAT_P4_RIO_DO, length=22)
from scapy.all import sendp, send, srp1 from scapy.all import Packet, hexdump from scapy.all import Ether, StrFixedLenField, XByteField, IntField from scapy.all import bind_layers class P4calc(Packet): name = "P4calc" fields_desc = [ StrFixedLenField("P", "P", length=1), StrFixedLenField("Four", "4", length=1), XByteField("version", 0x01), StrFixedLenField("op", "+", length=1), IntField("operand_a", 0), IntField("operand_b", 0), IntField("result", 0xDEADBABE)] bind_layers(Ether, P4calc, type=0x1234) class NumParseError(Exception): pass class OpParseError(Exception): pass class Token: def __init__(self,type,value = None): self.type = type self.value = value def num_parser(s, i, ts): pattern = "^\s*([0-9]+)\s*" match = re.match(pattern,s[i:])