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")
Example #2
0
#!/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()
Example #3
0
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
Example #4
0
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()
Example #8
0
 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)
Example #9
0
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