def connect(self): """ Method to initiate 3 way handshake """ logger = get_logger("Three Way Handshake") logger.info("Initiating Three way Handshake") try: self.my_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.my_socket.connect((self.host, self.port)) self.my_stream = StreamSocket(self.my_socket) self.my_stream.basecls = InternetPrintingProtocol except socket.error as exc: logger.critical(f"Socket Error {exc}") finally: logger.info("Three way handshake completed")
#!/usr/bin/python from scapy.all import socket, StreamSocket, Raw from modlib import * import socket sock = socket.socket() sock.connect(("217.128.188.179", 502)) s = StreamSocket(sock, basecls=ModbusADU) ans, unans = s.sr(ModbusADU() / ModbusPDU03()) ans.show()
def main(): sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sock.bind((UDP_IP, UDP_PORT)) sniff(opened_socket=StreamSocket(sock, TOP_PACKET), prn=write) return
def sendFlag(ip): s = socket.socket() s.connect((ip, 2997)) ss = StreamSocket(s, Raw) ss.send(Raw("Flag is: l0053_lips_m1ght_s1nk_sh1ps ")) s.close()
def TICKLING(self): s = socket.socket() s.connect(("127.0.0.1", self.ssh_p)) self.stream = StreamSocket(s, Raw) ssh_msg = self.stream.recv() raise self.CON(ssh_msg.load)
class Child(Core): def parse_args(self, dn, con_id, first_pkt, dbg=0, ssh_p=22): self.dn = dn self.con_id = str(con_id) self.first_pkt = first_pkt self.ssh_p = ssh_p Automaton.parse_args(self, debug=dbg) def master_filter(self, pkt): if (Core.master_filter(self, pkt) and pkt[IP].src == self.ip_client): qname = Core.parse_qname(self, pkt) if len(qname) >= 4: if qname[-2].isdigit() and qname[-3] == self.con_id: self.msg_type = qname[-4] if len(qname) == 4 and self.msg_type in [_IWT]: return True if len(qname) > 4 and self.msg_type in [ _ACK, _DATA, _FAST, _DONE ]: self.arg = qname[-5] self.payload = qname[:-5] return True return False def calculate_limit_size(self, pkt): s = self.pkt_max_size - len( pkt[DNS]) - 2 * len(DNSRR()) - 3 * len(self.dn) - len("ns.") - 10 if pkt[DNSQR].qtype == TXT: max_size = 512 s -= len(str(s)) else: max_size = self.qname_max_size return min((s, 1)[s < 1], max_size) def fragment_data(self, data, limit_size, qtype): if qtype == CNAME: qname = [] rest = data while len(rest) > 0: d = rest[:limit_size] qname.append('.'.join([ d[i:i + self.label_size] for i in range(0, len(d), self.label_size) ])) rest = rest[limit_size:] elif qtype == TXT: qname = [ data[i:i + limit_size] for i in range(0, len(data), limit_size) ] return qname def compress(self, l): """ [1,2,4,12,7,11,3,14,13] => '1-4.7.11-14' """ l.sort() temp = [[l[0]]] result = [] j = 0 for i in range(1, len(l)): if l[i] == l[i - 1] + 1: temp[j] += [l[i]] else: temp.append([l[i]]) j += 1 for r in temp: if len(r) > 1: result.append("{0}-{1}".format(r[0], r[-1])) else: result.append(str(r[0])) return ".".join(result) @ATMT.state(initial=True) def START(self): self.label_size = 63 self.qname_max_size = 253 self.pkt_max_size = 512 self.recv_data = {} self.ip_client = self.first_pkt[IP].src self.is_first_wyw_pkt = True self.iwt_pkt = None raise self.TICKLING() @ATMT.state() def TICKLING(self): s = socket.socket() s.connect(("127.0.0.1", self.ssh_p)) self.stream = StreamSocket(s, Raw) ssh_msg = self.stream.recv() raise self.CON(ssh_msg.load) @ATMT.state() def CON(self, ssh_msg): if ssh_msg == "": raise self.TICKLING() s = self.calculate_limit_size(self.first_pkt) qtype = self.first_pkt[DNSQR].qtype self.frag_reply = self.fragment_data(b64encode(ssh_msg), s, qtype) if len(self.frag_reply) == 1: pkt = Core.forge_packet( self, self.first_pkt, "{0}.{1}.0.{2}".format(_CON, self.con_id, self.frag_reply[0])) else: pkt = Core.forge_packet( self, self.first_pkt, "{0}.{1}.{2}".format(_CON, self.con_id, str(len(self.frag_reply) - 1))) send(pkt, verbose=0) raise self.WAITING() @ATMT.state() def WAITING(self): pass @ATMT.timeout(WAITING, 600) def timeout_reached(self): raise self.END() @ATMT.receive_condition(WAITING) def data_pkt(self, pkt): if self.msg_type in [_ACK, _FAST]: pkt_nb = self.arg if pkt_nb.isdigit(): raise self.DATA_RECEPTION(pkt, int(pkt_nb)) @ATMT.receive_condition(WAITING) def iwt_pkt(self, pkt): if self.msg_type == _IWT: raise self.IWT(pkt) @ATMT.receive_condition(WAITING) def ttm_pkt(self, pkt): if self.msg_type == _DATA: asked_pkt = self.arg if asked_pkt.isdigit(): raise self.DATA_EMISSION(pkt, int(asked_pkt)) @ATMT.receive_condition(WAITING) def done_pkt(self, pkt): if self.msg_type == _DONE: code = self.arg if code == _ACK or code == _DATA: raise self.DONE(pkt, code) @ATMT.state() def DATA_RECEPTION(self, pkt, pkt_nb): if not self.recv_data.has_key(pkt_nb): self.recv_data[pkt_nb] = "".join(self.payload) if self.msg_type == _ACK: ack_pkt = Core.forge_packet(self, pkt, "{0}.{1}".format(_ACK, pkt_nb)) send(ack_pkt, verbose=0) raise self.WAITING() elif self.msg_type == _FAST: self.fast_pkt = pkt self.to_ack = [pkt_nb] @ATMT.receive_condition(DATA_RECEPTION) def got_data(self, pkt): if self.msg_type == _FAST: if self.arg.isdigit(): self.fast_pkt = pkt pkt_nb = int(self.arg) if not self.recv_data.has_key(pkt_nb): self.recv_data[pkt_nb] = "".join(self.payload) if pkt_nb not in self.to_ack: self.to_ack.append(pkt_nb) @ATMT.timeout(DATA_RECEPTION, 0.5) def ack(self): #TODO check the limit size l = self.compress(self.to_ack) ack_pkt = Core.forge_packet(self, self.fast_pkt, "{0}.{1}".format(_FAST, l)) send(ack_pkt, verbose=0) raise self.WAITING() @ATMT.state() def IWT(self, pkt): """IWT (I Want This) state of the Child automaton. After receiving a WYW (What You Want) pkt from the client, the server says how many DNS pkts he needs to send the reply """ if self.iwt_pkt is not None: send(self.iwt_pkt, verbose=0) else: ssh_reply = self.stream.sniff(count=1, timeout=0.1) iwt_pkt = Core.forge_packet(self, pkt, _DONE) if len(ssh_reply) > 0: qtype = pkt[DNSQR].qtype s = self.calculate_limit_size(pkt) self.frag_reply = self.fragment_data( b64encode(ssh_reply[0].load), s, qtype) self.iwt_pkt = Core.forge_packet( self, pkt, "{0}.{1}".format(_IWT, str(len(self.frag_reply)))) iwt_pkt = self.iwt_pkt send(iwt_pkt, verbose=0) raise self.WAITING() @ATMT.state() def DATA_EMISSION(self, pkt, asked_pkt): if asked_pkt <= len(self.frag_reply): data_pkt = Core.forge_packet( self, pkt, "{0}.{1}.{2}".format(_DATA, str(asked_pkt), self.frag_reply[-(asked_pkt + 1)])) send(data_pkt, verbose=0) raise self.WAITING() @ATMT.state() def DONE(self, pkt, code): if code == _ACK: if self.recv_data.keys() == range(0, len(self.recv_data)): d = "".join(self.recv_data.values()) ssh_request = Raw(b64decode(d)) self.stream.send(ssh_request) self.recv_data.clear() send(Core.forge_packet(self, pkt, _DONE), verbose=0) elif code == _DATA: self.iwt_pkt = None send(Core.forge_packet(self, pkt, _DONE), verbose=0) raise self.WAITING() @ATMT.state(final=True) def END(self): pass
class IPP: def __init__(self, host, port=631, path="/ipp/print"): self.host = host self.port = int(port) self.path = "/" + path if path[0] != "/" else path self.my_socket = None self.my_stream = None # main ipp data field self.ipp_field = list() # all ipp attributes self.ipp_attr_group_tags = dict() self.ipp_attrs = dict() self.ipp_enums = dict() self.ipp_operations = dict() self.ipp_value_tags = dict() self.load_ipp_data() self.connect() def load_ipp_data(self): """ Method to load all ipp data """ logger = get_logger("Load ipp Data") logger.info("loading ipp required data") self.ipp_attr_group_tags = load_json_file( str(Path("protocols/ipp/ipp_data/ipp_attribute_group_tags.json"))) self.ipp_attrs = load_json_file( str(Path("protocols/ipp/ipp_data/ipp_attributes.json"))) self.ipp_operations = load_json_file( str(Path("protocols/ipp/ipp_data/ipp_operations.json"))) self.ipp_value_tags = load_json_file( str(Path("protocols/ipp/ipp_data/ipp_attributes_value_tags.json"))) self.ipp_enums = load_enum_data( str(Path("protocols/ipp/ipp_data/ipp_enum.json"))) logger.info("loading ipp required data completed") def connect(self): """ Method to initiate 3 way handshake """ logger = get_logger("Three Way Handshake") logger.info("Initiating Three way Handshake") try: self.my_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.my_socket.connect((self.host, self.port)) self.my_stream = StreamSocket(self.my_socket) self.my_stream.basecls = InternetPrintingProtocol except socket.error as exc: logger.critical(f"Socket Error {exc}") finally: logger.info("Three way handshake completed") def form_ipp_packet(self, op_type, version=1.0, **kwargs): """ Method to form ipp packets """ logger = get_logger("IPP Packet Forming") logger.info("Initiating IPP Packet Crafting") ver = str(version).split(".") ver = "".join(ver) ver = SignedShortField("Version", int(ver)) self.ipp_field.append(ver) data = "" operation_type = op_type if operation_type in self.ipp_operations.keys(): self.ipp_field.append( SignedShortField("Operation-ID", self.ipp_operations[operation_type])) self.ipp_field.append( SignedIntField("Request-ID", self.ipp_operations[operation_type])) else: logger.critical(f"Invalid operation tag : {operation_type}") print('Supported Operations') for op_rst in list(self.ipp_operations.keys()): print(f"* {op_rst}") sys.exit() delete_key = list() for delimiter_key, delimiter_value in kwargs.items(): if type(delimiter_value) != dict: data = delimiter_value delete_key.append(delimiter_key) if len(delete_key) > 0: for del_key in delete_key: del kwargs[del_key] for delimiter_key, delimiter_value in kwargs.items(): if type(delimiter_value) == dict: if delimiter_key in self.ipp_attr_group_tags.keys(): self.ipp_field.append( XByteField(delimiter_key, self.ipp_attr_group_tags[delimiter_key])) count = 0 for attr_key, attr_val in delimiter_value.items(): if attr_key in self.ipp_attrs.keys(): self.ipp_field.append( XByteField(f"key_{attr_key}_{count}", self.ipp_attrs[attr_key][1])) self.ipp_field.append( ShortField(f"Attribute_Name_Length_{count}", len(attr_key))) self.ipp_field.append( StrField( f"Attribute_Name_Value_{attr_key}_{count}", bytes(attr_key, encoding='utf8'))) self.ipp_field.append( ShortField(f"Attribute_Value_Length_{count}", len(attr_val))) self.ipp_field.append( StrField( f"Attribute_Value_Value_{attr_val}_{count}", bytes(attr_val, encoding='utf8'))) count += 1 else: logger.critical( f"Invalid Attribute tag : {attr_key}") sys.exit() else: logger.critical(f"Invalid Delimiter tag : {delimiter_key}") print("Supported Tags") for del_tag in list(self.ipp_attr_group_tags.keys()): print(f"* {del_tag}") sys.exit() else: logger.critical(f"Invalid tag : {delimiter_key}") sys.exit() self.ipp_field.append( XByteField("end-of-attributes-tag", self.ipp_attr_group_tags["end-of-attributes-tag"])) if data != "": self.ipp_field.append(StrField("Data", data)) logger.info("IPP Packet forming completed") def send(self, op_type, version, **kwargs): """ Method to send and receive ipp request """ if len(kwargs) <= 0: if op_type == "Get-Jobs": kwargs = get_jobs(self.host) else: print(f"No default templates is available for {op_type} !!!") sys.exit() self.form_ipp_packet(op_type=op_type, version=version, **kwargs) InternetPrintingProtocol.add_fields(self.ipp_field) IPP_HTTP_REQUESTS['Content_Length'] = bytes( str(len(InternetPrintingProtocol())), "utf-8") IPP_HTTP_REQUESTS['Host'] = bytes(f"{self.host}:{self.port}", "utf-8") IPP_HTTP_REQUESTS['Path'] = bytes(self.path, "utf-8") ipp_request = HTTP() / HTTPRequest( **IPP_HTTP_REQUESTS) / InternetPrintingProtocol() self.my_stream.sr(ipp_request, timeout=5, verbose=0) return InternetPrintingProtocol().get_results()
class Child(Core): def parse_args(self, dn, con_id, first_pkt, dbg=0, ssh_p=22): self.dn = dn self.con_id = str(con_id) self.first_pkt = first_pkt self.ssh_p = ssh_p Automaton.parse_args(self, debug=dbg) def master_filter(self, pkt): if (Core.master_filter(self, pkt) and pkt[IP].src == self.ip_client): qname = Core.parse_qname(self, pkt) if len(qname) >= 4: if qname[-2].isdigit() and qname[-3] == self.con_id: self.msg_type = qname[-4] if len(qname) == 4 and self.msg_type in [_IWT]: return True if len(qname) > 4 and self.msg_type in [ _ACK, _DATA, _FAST, _DONE ]: self.arg = qname[-5] self.payload = qname[:-5] return True return False def calculate_limit_size(self, pkt): s = self.pkt_max_size - len(pkt[DNS]) - 2*len( DNSRR() ) - 3*len(self.dn) - len("ns.") - 10 if pkt[DNSQR].qtype == TXT: max_size = 512 s -= len(str(s)) else: max_size = self.qname_max_size return min((s, 1)[s < 1], max_size) def fragment_data(self, data, limit_size, qtype): if qtype == CNAME: qname = [] rest = data while len(rest) > 0: d = rest[:limit_size] qname.append( '.'.join( [ d[i:i+self.label_size] for i in range( 0, len(d), self.label_size, ) ], ), ) rest = rest[limit_size:] elif qtype == TXT: qname = [ data[i:i+limit_size] for i in range(0, len(data), limit_size) ] return qname def compress(self, l): """ [1,2,4,12,7,11,3,14,13] => '1-4.7.11-14' """ l.sort() temp = [[l[0]]] result = [] j = 0 for i in range(1, len(l)): if l[i] == l[i-1]+1: temp[j] += [l[i]] else: temp.append([l[i]]) j += 1 for r in temp: if len(r) > 1: result.append("{0}-{1}".format(r[0], r[-1])) else: result.append(str(r[0])) return ".".join(result) @ATMT.state(initial=True) def START(self): self.label_size = 63 self.qname_max_size = 253 self.pkt_max_size = 512 self.recv_data = {} self.ip_client = self.first_pkt[IP].src self.is_first_wyw_pkt = True self.iwt_pkt = None raise self.TICKLING() @ATMT.state() def TICKLING(self): s = socket.socket() s.connect(("127.0.0.1", self.ssh_p)) self.stream = StreamSocket(s, Raw) ssh_msg = self.stream.recv() raise self.CON(ssh_msg.load) @ATMT.state() def CON(self, ssh_msg): if ssh_msg == "": raise self.TICKLING() s = self.calculate_limit_size(self.first_pkt) qtype = self.first_pkt[DNSQR].qtype self.frag_reply = self.fragment_data(b64encode(ssh_msg), s, qtype) if len(self.frag_reply) == 1: pkt = Core.forge_packet( self, self.first_pkt, "{0}.{1}.0.{2}".format( _CON, self.con_id, self.frag_reply[0], ), ) else: pkt = Core.forge_packet( self, self.first_pkt, "{0}.{1}.{2}".format( _CON, self.con_id, str(len(self.frag_reply)-1), ), ) send(pkt, verbose=0) raise self.WAITING() @ATMT.state() def WAITING(self): pass @ATMT.timeout(WAITING, 600) def timeout_reached(self): raise self.END() @ATMT.receive_condition(WAITING) def data_pkt(self, pkt): if self.msg_type in [_ACK, _FAST]: pkt_nb = self.arg if pkt_nb.isdigit(): raise self.DATA_RECEPTION(pkt, int(pkt_nb)) @ATMT.receive_condition(WAITING) def iwt_pkt(self, pkt): if self.msg_type == _IWT: raise self.IWT(pkt) @ATMT.receive_condition(WAITING) def ttm_pkt(self, pkt): if self.msg_type == _DATA: asked_pkt = self.arg if asked_pkt.isdigit(): raise self.DATA_EMISSION(pkt, int(asked_pkt)) @ATMT.receive_condition(WAITING) def done_pkt(self, pkt): if self.msg_type == _DONE: code = self.arg if code == _ACK or code == _DATA: raise self.DONE(pkt, code) @ATMT.state() def DATA_RECEPTION(self, pkt, pkt_nb): if pkt_nb in self.recv_data: self.recv_data[pkt_nb] = "".join(self.payload) if self.msg_type == _ACK: ack_pkt = Core.forge_packet( self, pkt, "{0}.{1}".format(_ACK, pkt_nb), ) send(ack_pkt, verbose=0) raise self.WAITING() elif self.msg_type == _FAST: self.fast_pkt = pkt self.to_ack = [pkt_nb] @ATMT.receive_condition(DATA_RECEPTION) def got_data(self, pkt): if self.msg_type == _FAST: if self.arg.isdigit(): self.fast_pkt = pkt pkt_nb = int(self.arg) if pkt_nb in self.recv_data: self.recv_data[pkt_nb] = "".join(self.payload) if pkt_nb not in self.to_ack: self.to_ack.append(pkt_nb) @ATMT.timeout(DATA_RECEPTION, 0.5) def ack(self): # TODO check the limit size l = self.compress(self.to_ack) ack_pkt = Core.forge_packet( self, self.fast_pkt, "{0}.{1}".format(_FAST, l), ) send(ack_pkt, verbose=0) raise self.WAITING() @ATMT.state() def IWT(self, pkt): """IWT (I Want This) state of the Child automaton. After receiving a WYW (What You Want) pkt from the client, the server says how many DNS pkts he needs to send the reply """ if self.iwt_pkt is not None: send(self.iwt_pkt, verbose=0) else: ssh_reply = self.stream.sniff(count=1, timeout=0.1) iwt_pkt = Core.forge_packet(self, pkt, _DONE) if len(ssh_reply) > 0: qtype = pkt[DNSQR].qtype s = self.calculate_limit_size(pkt) self.frag_reply = self.fragment_data( b64encode(ssh_reply[0].load), s, qtype, ) self.iwt_pkt = Core.forge_packet( self, pkt, "{0}.{1}".format(_IWT, str(len(self.frag_reply))), ) iwt_pkt = self.iwt_pkt send(iwt_pkt, verbose=0) raise self.WAITING() @ATMT.state() def DATA_EMISSION(self, pkt, asked_pkt): if asked_pkt <= len(self.frag_reply): data_pkt = Core.forge_packet( self, pkt, "{0}.{1}.{2}".format( _DATA, str(asked_pkt), self.frag_reply[-(asked_pkt+1)], ), ) send(data_pkt, verbose=0) raise self.WAITING() @ATMT.state() def DONE(self, pkt, code): if code == _ACK: if self.recv_data.keys() == range(0, len(self.recv_data)): d = "".join(self.recv_data.values()) ssh_request = Raw(b64decode(d)) self.stream.send(ssh_request) self.recv_data.clear() send(Core.forge_packet(self, pkt, _DONE), verbose=0) elif code == _DATA: self.iwt_pkt = None send(Core.forge_packet(self, pkt, _DONE), verbose=0) raise self.WAITING() @ATMT.state(final=True) def END(self): pass