Example #1
0
 def Run(self):
     """Runs the proxy.
     Waits for a TCP connection and passes it forward to the Client class to parse
     """
     logger.Log("INFO", "Waiting for TCP connection")
     self.tcpSocket.listen(1)
     sock, addr = self.tcpSocket.accept()
     logger.Log("INFO", "Received TCP connection")
     client = Client(self.proxy, sock, self.dst)
     client.Run()
Example #2
0
def main():
    """ICMP Tunnel, send TCP over ICMP

positional arguments:
  {client,server}       client - Run the client proxy (All flags needed)
                        server - Run the server proxy (No flags needed)

optional arguments:
  -h, --help            show this help message and exit
  -p PROXY_HOST, --proxy-host PROXY_HOST
                        IP of the server tunnel
  -lh LOCAL_HOST, --local-host LOCAL_HOST
                        Local IP for incoming TCP connections
  -lp LOCAL_PORT, --local-port LOCAL_PORT
                        Local port for incoming TCP connections
  -dh DESTINATION_HOST, --destination-host DESTINATION_HOST
                        Remote IP to send TCP connection to
  -dp DESTINATION_PORT, --destination-port DESTINATION_PORT
                        Remote port to send TCP connection to
  -v, --verbose         Print debug messages
    """
    parser = argparse.ArgumentParser(formatter_class=argparse.RawTextHelpFormatter, description="ICMP Tunnel, send TCP over ICMP")

    # Add server or client
    parser.add_argument("type", choices=["client", "server"], help="client - Run the client proxy (All flags needed)\nserver - Run the server proxy (No flags needed)")
    parser.add_argument("-p", "--proxy-host", help="IP of the server tunnel")
    parser.add_argument("-lh", "--local-host", help="Local IP for incoming TCP connections")
    parser.add_argument("-lp", "--local-port", type=int, help="Local port for incoming TCP connections")
    parser.add_argument("-dh", "--destination-host", help="Remote IP to send TCP connection to")
    parser.add_argument("-dp", "--destination-port", type=int, help="Remote port to send TCP connection to")
    parser.add_argument("-v", "--verbose", default=False, action="store_true", help="Print debug messages")
    args = parser.parse_args()

    # Set the logger verbosity
    logger.SetVerbosity(args.verbose)

    if args.type == "server":
        logger.Log("INFO", "Starting server")
        Server().Run()

    else:
        # Make sure we have all params
        if  args.proxy_host is None or \
            args.local_host is None or \
            args.local_port is None or \
            args.destination_host is None or \
            args.destination_port is None:
            parser.error("client requires proxy,local and destination flags")

        logger.Log("INFO", "Starting client")
        ClientProxy(args.proxy_host, args.local_host, args.local_port, args.destination_host, args.destination_port).Run()
Example #3
0
    def CreateIcmpSocket():
        """Create a Raw ICMP socket for sending and receiving

        Returns:
            socket: Raw ICMP socket
        """
        # Doesn't handle errors, calling function should
        logger.Log("DEBUG", "ICMP socket created")
        return socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_ICMP)
Example #4
0
    def HandleIcmp(self, socket):
        """Handle a received ICMP packet (from the client).
        Reads the ICMP packet and forwards the payload as a TCP packet to the TCP server.

        Args:
            socket (socket): ICMP socket that has data to read from
        """
        # Read and parse data
        packet, address = socket.recvfrom(ICMP_BUFFER_SIZE)

        try:
            packet = Icmp.IcmpPacket.Parse(packet)
        except Exception as x:
            logger.Log("DEBUG", "Failed parsing packet")
            return

        self.src = address[0]
        self.dst = packet.dst

        # If this is not an IcmpTunnelPacket ignore it
        if packet.magic != Icmp.IcmpPacket.MAGIC:
            return

        # Skip our packets
        if packet.type == Icmp.ICMP_ECHO_REPLY and packet.code == 0:
            logger.Log("DEBUG", "Failed parsing packet")
            return

        # Close requested
        if packet.type == Icmp.ICMP_ECHO_REQUEST and packet.code == 1:
            self.sockets.remove(self.tcpSocket)
            self.tcpSocket.close()
            self.tcpSocket = None
            logger.Log("INFO", "Client closed")
            return

        # Create socket if it doesnt exist
        if not self.tcpSocket:
            self.tcpSocket = self.CreateTcpSocket(self.dst)
            self.sockets.append(self.tcpSocket)
            logger.Log("INFO", "Client joined")

        # Send the packet
        self.tcpSocket.send(packet.payload)
Example #5
0
    def HandleTcp(self, sock):
        """Handle a packet from the TCP connection.
        Reads the packet and forwards it over ICMP to the server ICMP tunnel.

        Args:
            sock (socket): Socket that we got the data from
        """
        data = sock.recv(TCP_BUFFER_SIZE)

        # Build a ICMP packet with our TCP packet as the payload and send it to the server
        code = 0 if len(data) > 0 else 1
        packet = Icmp.IcmpPacket(Icmp.ICMP_ECHO_REQUEST, code, 0, 0, 0, data, self.tcpSocket.getsockname(), self.dst)
        self.icmpSocket.sendto(packet.Create(), (self.proxy, 1))

        # Connection closed, no data
        if code == 1:
            logger.Log("INFO", "Connection closed")
            exit()
Example #6
0
    def CreateTcpSocket(dst, server=False):
        """Create a TCP socket with given destination. Binds/Connects to ip depending on params

        Args:
            dst ((IP, Port)): Destination to connect to
            server (bool, optional): If true we bind to dst instead of connecting
        """
        logger.Log("DEBUG", "TCP socket created on {}.{}".format(dst[0], dst[1]))
        # Create reusable socket
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

        # If we are a server then bind, else connect to to destination
        if server:
            sock.bind(dst)
        else:
            sock.connect(dst)

        return sock
Example #7
0
    def Parse(cls, packet):
        """Parses a received network packet into an ICMP packet

        Args:
            packet (bytearray): Network packet

        Returns:
            IcmpPacket: Parsed packet
        """
        rawIpPacket, rawIcmpPacket = packet[:IcmpPacket.
                                            IP_HEADER_SIZE], packet[
                                                IcmpPacket.IP_HEADER_SIZE:]
        ipPacket = struct.unpack(IcmpPacket.IP_HEADER, rawIpPacket)

        srcIp = ipPacket[8]

        # Get the payload
        payload = ""
        payloadSize = len(rawIcmpPacket) - IcmpPacket.ICMP_HEADER_SIZE
        if payloadSize > 0:
            payload = struct.unpack(
                "{}s".format(payloadSize),
                rawIcmpPacket[IcmpPacket.ICMP_HEADER_SIZE:])[0]

        logger.Log("DEBUG",
                   "Parsing ICMP packet, payload size {}".format(payloadSize))

        # Read the packet data
        type, code, checksum, id, sequence, dstIp, dstPort, magic = struct.unpack(
            IcmpPacket.ICMP_HEADER,
            rawIcmpPacket[:IcmpPacket.ICMP_HEADER_SIZE])

        # Convert to net data
        srcIp = socket.inet_ntoa(srcIp)
        dst = (socket.inet_ntoa(dstIp), dstPort)

        return cls(type, code, checksum, id, sequence, payload, srcIp, dst,
                   magic)
Example #8
0
    def Create(self):
        """Creates a network ready ICMP packet from the saved data

        Returns:
            bytearray: Serialized ICMP packet data
        """
        logger.Log("DEBUG", "Creating ICMP packet")

        packStr = self.ICMP_HEADER
        packArgs = [
            self.type, self.code, 0, self.id, self.sequence,
            socket.inet_aton(self.dst[0]), self.dst[1], self.magic
        ]

        # Add the payload
        if len(self.payload) > 0:
            packStr += "{}s".format(len(self.payload))
            packArgs.append(self.payload)

        # Add correct checksum
        checksum = self.Checksum(struct.pack(packStr, *packArgs))
        packArgs[2] = checksum

        return struct.pack(packStr, *packArgs)