コード例 #1
0
ファイル: SAPEnqueue.py プロジェクト: CoreSecurity/pysap
    def recv(self):
        """Receive a packet at the Enqueue layer, performing reassemble of
        fragmented packets if necessary.

        :return: received :class:`SAPEnqueue` packet
        :rtype: :class:`SAPEnqueue`

        :raise socket.error: if the connection was close
        """
        # Receive the NI packet
        packet = SAPNIStreamSocket.recv(self)

        if SAPEnqueue in packet and packet[SAPEnqueue].more_frags:
            log_sapenqueue.debug("Received Enqueue fragmented packet")

            head = str(packet[SAPEnqueue])[:20]
            data = str(packet[SAPEnqueue])[20:]
            total_length = packet[SAPEnqueue].len - 20
            recvd_length = len(packet[SAPEnqueue]) - 20
            log_sapenqueue.debug("Received %d up to %d bytes", recvd_length, total_length)
            while recvd_length < total_length and packet[SAPEnqueue].more_frags == 1:
                response = SAPNIStreamSocket.recv(self)[SAPEnqueue]
                data += str(response)[20:]
                recvd_length += len(response) - 20
                log_sapenqueue.debug("Received %d up to %d bytes", recvd_length, total_length)

            packet = SAPEnqueue(head + data)

        return packet
コード例 #2
0
def main():
    options = parse_options()

    if not has_fau_timer:
        print ("[-] Required library not found. Please install it from https://github.com/seecurity/mona-timing-lib")
        return

    if options.verbose:
        logging.basicConfig(level=logging.DEBUG)

    # Initiate the connection
    conn = SAPNIStreamSocket.get_nisocket(options.remote_host, options.remote_port)
    print("[*] Connected to the SAP Router %s:%d" % (options.remote_host, options.remote_port))

    # Retrieve the router version used by the server if not specified
    if options.router_version is None:
        options.router_version = get_router_version(conn)

    print("[*] Using SAP Router version %d" % options.router_version)

    print("[*] Checking if the server is vulnerable to a timing attack (CVE-2014-0984) ...")

    with open(options.output, "w") as f:

        c = 0
        for i in range(0, len(options.password) + 1):
            password = options.password[:i] + "X" * (len(options.password) - i)
            print("[*] Trying with password (%s) len %d" % (password, len(password)))
            for _ in range(0, options.tries):
                try_password(options, password, f, c)
                c += 1
コード例 #3
0
ファイル: ms_listener.py プロジェクト: jcmuniz/pysap
def main():
    options = parse_options()

    if options.verbose:
        logging.basicConfig(level=logging.DEBUG)

    # Initiate the connection
    conn = SAPNIStreamSocket.get_nisocket(options.remote_host, options.remote_port)
    print "[*] Connected to the message server %s:%d" % (options.remote_host, options.remote_port)

    client_string = options.client

    # Send MS_LOGIN_2 packet
    p = SAPMS(flag=0x00, iflag=0x08, toname=client_string, fromname=client_string)

    print "[*] Sending login packet"
    response = conn.sr(p)[SAPMS]

    print "[*] Login performed, server string: %s" % response.fromname

    print "[*] Listening to server messages"
    try:
        while (True):
            # Send MS_SERVER_LST packet
            response = conn.recv()[SAPMS]

            print "[*] Message received !"
            response.show()

    except SocketError:
        print "[*] Connection error"
    except KeyboardInterrupt:
        print "[*] Cancelled by the user"
コード例 #4
0
ファイル: ms_messager.py プロジェクト: jcmuniz/pysap
def main():
    options = parse_options()

    if options.verbose:
        logging.basicConfig(level=logging.DEBUG)

    # Initiate the connection
    conn = SAPNIStreamSocket.get_nisocket(options.remote_host, options.remote_port)
    print "[*] Connected to the message server %s:%d" % (options.remote_host, options.remote_port)

    client_string = options.client

    # Send MS_LOGIN_2 packet
    p = SAPMS(flag=0x00, iflag=0x08, toname=client_string, fromname=client_string)

    print "[*] Sending login packet"
    response = conn.sr(p)[SAPMS]

    print "[*] Login performed, server string: %s" % response.fromname

    # Sends a message to another client
    p = SAPMS(flag=0x02, iflag=0x01, toname=options.target, fromname=client_string, opcode=1)
    p /= Raw(options.message)

    print "[*] Sending packet to: %s" % options.target
    conn.send(p)
コード例 #5
0
def main():
    options = parse_options()

    if options.verbose:
        logging.basicConfig(level=logging.DEBUG)

    # Initiate the connection
    conn = SAPNIStreamSocket.get_nisocket(options.remote_host, options.remote_port)
    print "[*] Connected to the SAP Router %s:%d" % (options.remote_host, options.remote_port)

    # Retrieve the router version used by the server if not specified
    if options.router_version is None:
        options.router_version = get_router_version(conn)

    print "[*] Using SAP Router version %d" % options.router_version

    print "[*] Checking if the server is vulnerable to a timing attack (CVE-2014-0984) ..."

    with open(options.output, "w") as f:

        c = 0
        for i in range(0, len(options.password) + 1):
            password = options.password[:i] + "X" * (len(options.password) - i)
            print "[*] Trying with password (%s) len %d" % (password, len(password))
            for _ in range(0, options.tries):
                try_password(options, password, f, c)
                c += 1
コード例 #6
0
ファイル: ms_monitor.py プロジェクト: jcmuniz/pysap
    def do_connect(self, args):
        """ Initiate the connection to the Message Server service. The
        connection is registered using the client_string runtime option. """

        # Create the socket connection
        try:
            self.connection = SAPNIStreamSocket.get_nisocket(self.options.remote_host, self.options.remote_port)
        except SocketError as e:
            self._error("Error connecting with the Message Server")
            self._error(str(e))
            return

        self._print("Attached to %s / %d" % (self.options.remote_host, self.options.remote_port))

        # Send MS_LOGIN_2 packet
        p = SAPMS(flag=0x00, iflag=0x08, toname=self.runtimeoptions["client_string"], fromname=self.runtimeoptions["client_string"])

        self._debug("Sending login packet")
        response = self.connection.sr(p)[SAPMS]

        if response.errorno == 0:
            self.runtimeoptions["server_string"] = response.fromname
            self._debug("Login performed, server string: %s" % response.fromname)
            self._print("pysap's Message Server monitor, connected to %s / %d" % (self.options.remote_host, self.options.remote_port))
            self.connected = True
        else:
            if response.errorno in ms_errorno_values:
                self._error("Error performing login: %s" % ms_errorno_values[response.errorno])
            else:
                self._error("Unknown error performing login: %d" % response.errorno)
コード例 #7
0
ファイル: router_scanner.py プロジェクト: jcmuniz/pysap
def route_test(rhost, rport, thost, tport):

    print "[*] Routing connections to %s:%s" % (thost, tport)

    # Initiate the connection. We don't want the NI Stream Socket to handle
    # keep-alive messages, as the response to connect requests are NI_PONG
    conn = SAPNIStreamSocket.get_nisocket(rhost, rport, keep_alive=False)

    router_string = [SAPRouterRouteHop(hostname=rhost,
                                       port=rport),
                     SAPRouterRouteHop(hostname=thost,
                                       port=tport)]

    router_string_lens = map(len, map(str, router_string))

    p = SAPRouter(type=SAPRouter.SAPROUTER_ROUTE,
                  route_entries=len(router_string),
                  route_talk_mode=1,
                  route_rest_nodes=1,
                  route_length=sum(router_string_lens),
                  route_offset=router_string_lens[0],
                  route_string=router_string,
                  )

    response = conn.sr(p)

    if router_is_error(response):
        status = 'error'
    elif router_is_pong(response):
        status = 'open'

    conn.close()

    return status
コード例 #8
0
ファイル: router_scanner.py プロジェクト: aolihu/pysap
def main():
    options = parse_options()

    if options.verbose:
        logging.basicConfig(level=logging.DEBUG)

    print("[*] Connecting to SAP Router %s:%d (talk mode %s)" % (options.remote_host,
                                                                 options.remote_port,
                                                                 options.talk_mode))

    # Retrieve the router version used by the server if not specified
    if options.router_version is None:
        conn = SAPNIStreamSocket.get_nisocket(options.remote_host,
                                              options.remote_port,
                                              keep_alive=False)
        options.router_version = get_router_version(conn)
        conn.close()
    print("[*] Using SAP Router version %d" % options.router_version)

    options.talk_mode = {"raw": 1,
                         "ni": 0}[options.talk_mode]

    results = []
    for (host, port) in parse_target_hosts(options.target_hosts, options.target_ports):
        status = route_test(options.remote_host, options.remote_port, host, port,
                            options.talk_mode, options.router_version)
        if options.verbose:
            print("[*] Status of %s:%s: %s" % (host, port, status))
        if status == "open":
            results.append((host, port))

    print("[*] Host/Ports found open:")
    for (host, port) in results:
        print("\tHost: %s\tPort:%s" % (host, port))
コード例 #9
0
    def get_nisocket(cls, host=None, port=None, route=None, password=None,
                     talk_mode=None, router_version=None, **kwargs):
        """Helper function to obtain a :class:`SAPRoutedStreamSocket`.

        :param host: target host to connect to if not specified in the route
        :type host: C{string}

        :param port: target port to connect to if not specified in the route
        :type port: ``int``

        :param route: route to use for determining the SAP Router to connect
        :type route: C{string} or ``list`` of :class:`SAPRouterRouteHop`

        :param password: target password if not specified in the route
        :type password: C{string}

        :param talk_mode: the talk mode to use for requesting the route
        :type talk_mode: ``int``

        :param router_version: the router version to use for requesting the
            route
        :type router_version: ``int``

        :keyword kwargs: arguments to pass to :class:`SAPRoutedStreamSocket`
            constructor

        :return: connected socket through the specified route
        :rtype: :class:`SAPRoutedStreamSocket`

        :raise SAPRouteException: if the route request to the target host/port
            was not accepted by the SAP Router

        :raise socket.error: if the connection to the target host/port failed
            or the SAP Router returned an error
        """
        # If no route was provided, use the standard SAPNIStreamSocket
        # get_nisocket method
        if route is None:
            return SAPNIStreamSocket.get_nisocket(host, port, **kwargs)

        # If the route was provided using a route string, convert it to a
        # list of hops
        if isinstance(route, str):
            route = SAPRouterRouteHop.from_string(route)

        # If the host and port were specified, we need to add a new hop to
        # the route
        if host is not None and port is not None:
            route.append(SAPRouterRouteHop(hostname=host,
                                           port=port,
                                           password=password))

        # Connect to the first hop in the route (it should be the SAP Router)
        sock = socket.create_connection((route[0].hostname, int(route[0].port)))

        # Create a SAPRoutedStreamSocket instance specifying the route
        return cls(sock, route, talk_mode, router_version, **kwargs)
コード例 #10
0
    def __init__(self, sock, route, talk_mode=None, router_version=None,
                 keep_alive=True, base_cls=None):
        """Initialize the routed stream socket. It should receive a socket
        connected with the SAP Router, and a route to specify to it. After
        initialization and if the route is accepted all calls to send() and
        recv() would be made to the target host/service trough the SAP
        Router.

        :param sock: a socket connected to the SAP Router
        :type sock: C{socket}

        :param route: a route to specify to the SAP Router
        :type route: ``list`` of :class:`SAPRouterRouteHop`

        :param talk_mode: the talk mode to use when routing
        :type talk_mode: ``int``

        :param router_version: the router version to use for requesting the
            route. If no router version is provided, it will be obtained from
            the SAP Router by means of a control packet.
        :type router_version: ``int``

        :param keep_alive: if true, the socket will automatically respond to
            keep-alive request messages. Otherwise, the keep-alive messages
            are passed to the caller in :class:`recv` and :class:`sr` calls.
        :type keep_alive: ``bool``

        :param base_cls: the base class to use when receiving packets, it uses
            SAPNI as default if no class specified
        :type base_cls: :class:`Packet` class

        """
        self.routed = False
        self.talk_mode = talk_mode
        self.router_version = router_version
        # Connect to the SAP Router
        SAPNIStreamSocket.__init__(self, sock, keep_alive=keep_alive,
                                   base_cls=base_cls)
        # Now that we've a NIStreamSocket, retrieve the router version if
        # was not specified
        if self.router_version is None:
            self.router_version = get_router_version(self)
        self.route_to(route, talk_mode)
コード例 #11
0
ファイル: SAPRouter.py プロジェクト: aolihu/pysap
    def route(self):
        """Requests a route to forward the traffic through the remote SAP
        Router.

        @raise SAPRouteException: if the route request is denied
        @raise Exception: if an error occurred when requesting the route
        """
        log_saprouter.debug("Routing to %s:%d" % (self.target_address,
                                                  self.target_port))

        # Creates the connection with the SAP Router
        (remote_address, remote_port) = self.remote_host
        router = SAPNIStreamSocket.get_nisocket(remote_address, remote_port,
                                                keep_alive=self.keep_alive)

        # Build the Route request packet
        router_string = [SAPRouterRouteHop(hostname=remote_address,
                                           port=remote_port),
                         SAPRouterRouteHop(hostname=self.target_address,
                                           port=self.target_port,
                                           password=self.target_pass)]
        router_string_lens = list(map(len, list(map(str, router_string))))
        p = SAPRouter(type=SAPRouter.SAPROUTER_ROUTE,
                      route_entries=len(router_string),
                      route_talk_mode=self.talk_mode,
                      route_rest_nodes=1,
                      route_length=sum(router_string_lens),
                      route_offset=router_string_lens[0],
                      route_string=router_string)

        # Send the request and grab the response
        response = router.sr(p)

        if SAPRouter in response:
            response = response[SAPRouter]
            if router_is_pong(response):
                log_saprouter.debug("Route request to %s:%d accepted by %s:%d" %
                                    (self.target_address, self.target_port,
                                     remote_address, remote_port))
                self.routed = True
            elif router_is_error(response) and response.return_code == -94:
                log_saprouter.debug("Route request to %s:%d not accepted by %s:%d" %
                                    (self.target_address, self.target_port,
                                     remote_address, remote_port))
                raise SAPRouteException("Route request not accepted")
            else:
                log_saprouter.error("Router send error: %s" % response.err_text_value)
                raise Exception("Router error: %s", response.err_text_value)
        else:
            log_saprouter.error("Wrong response received")
            raise Exception("Wrong response received")

        return router
コード例 #12
0
ファイル: sapni_test.py プロジェクト: HPxpat/pysap
    def test_sapnistreamsocket_close(self):
        """Test SAPNIStreamSocket with a server that closes the connection"""
        self.start_server(SAPNITestHandlerClose)

        sock = socket.socket()
        sock.connect((self.test_address, self.test_port))

        self.client = SAPNIStreamSocket(sock, keep_alive=False)

        with self.assertRaises(socket.error):
            self.client.sr(self.test_string)

        self.stop_server()
コード例 #13
0
 def recv(self):
     """Receive a packet from the target host. If the talk mode in use is
     native and we've already set the route, the packet received is a raw
     packet. Otherwise, the packet received is a NI layer packet in the same
     way the :class:`SAPNIStreamSocket` works.
     """
     # If we're working on native mode and the route was accepted, we don't
     # need the NI layer anymore. Just use the plain socket inside the
     # NIStreamSockets.
     if self.routed and self.talk_mode == 1:
         return StreamSocket.recv(self)
     # If the route was not accepted yet or we're working on non-native talk
     # mode, we need the NI layer.
     return SAPNIStreamSocket.recv(self)
コード例 #14
0
ファイル: SAPRouter.py プロジェクト: CoreSecurity/pysap
    def send(self, packet):
        """Send a packet. If the talk mode in use is native the packet sent is
        a raw packet. Otherwise, the packet is a NI layer packet in the same way
        the :class:`SAPNIStreamSocket` works.

        :param packet: packet to send
        :type packet: Packet
        """
        # If we're working on native mode and the route was accepted, we don't
        # need the NI layer anymore. Just use the plain socket inside the
        # NIStreamSockets.
        if self.routed and self.talk_mode == 1:
            return StreamSocket.send(self, packet)
        # If the route was not accepted yet or we're working on non-native talk
        # mode, we need the NI layer.
        return SAPNIStreamSocket.send(self, packet)
コード例 #15
0
ファイル: sapni_test.py プロジェクト: HPxpat/pysap
    def test_sapnistreamsocket_getnisocket(self):
        """Test SAPNIStreamSocket get nisocket class method"""
        self.start_server(SAPNITestHandler)

        self.client = SAPNIStreamSocket.get_nisocket(self.test_address,
                                                     self.test_port)

        packet = self.client.sr(self.test_string)
        packet.decode_payload_as(Raw)
        self.client.close()

        self.assertIn(SAPNI, packet)
        self.assertEqual(packet[SAPNI].length, len(self.test_string))
        self.assertEqual(packet.payload.load, self.test_string)

        self.stop_server()
コード例 #16
0
ファイル: sapni_test.py プロジェクト: HPxpat/pysap
    def test_sapnistreamsocket_without_keep_alive(self):
        """Test SAPNIStreamSocket without keep alive"""
        self.start_server(SAPNITestHandlerKeepAlive)

        sock = socket.socket()
        sock.connect((self.test_address, self.test_port))

        self.client = SAPNIStreamSocket(sock, keep_alive=False)
        packet = self.client.sr(self.test_string)
        packet.decode_payload_as(Raw)
        self.client.close()

        # We should receive a PING instead of our packet
        self.assertIn(SAPNI, packet)
        self.assertEqual(packet[SAPNI].length, len(SAPNI.SAPNI_PING))
        self.assertEqual(packet.payload.load, SAPNI.SAPNI_PING)

        self.stop_server()
コード例 #17
0
ファイル: sapni_test.py プロジェクト: HPxpat/pysap
    def test_sapnistreamsocket_with_keep_alive(self):
        """Test SAPNIStreamSocket with keep alive"""
        self.start_server(SAPNITestHandlerKeepAlive)

        sock = socket.socket()
        sock.connect((self.test_address, self.test_port))

        self.client = SAPNIStreamSocket(sock, keep_alive=True)
        packet = self.client.sr(self.test_string)
        packet.decode_payload_as(Raw)
        self.client.close()

        # We should receive our packet, the PING should be handled by the
        # stream socket
        self.assertIn(SAPNI, packet)
        self.assertEqual(packet[SAPNI].length, len(self.test_string))
        self.assertEqual(packet.payload.load, self.test_string)

        self.stop_server()
コード例 #18
0
ファイル: sapni_test.py プロジェクト: HPxpat/pysap
    def test_sapnistreamsocket_base_cls(self):
        """Test SAPNIStreamSocket handling of custom base packet classes"""
        self.start_server(SAPNITestHandler)

        class SomeClass(Packet):
            fields_desc = [StrField("text", None)]

        sock = socket.socket()
        sock.connect((self.test_address, self.test_port))

        self.client = SAPNIStreamSocket(sock, base_cls=SomeClass)
        packet = self.client.sr(self.test_string)
        self.client.close()

        self.assertIn(SAPNI, packet)
        self.assertIn(SomeClass, packet)
        self.assertEqual(packet[SAPNI].length, len(self.test_string))
        self.assertEqual(packet[SomeClass].text, self.test_string)

        self.stop_server()
コード例 #19
0
ファイル: router_niping.py プロジェクト: CoreSecurity/pysap
def server_mode(options):
    """"Implements the niping server running mode

    :param options: option set from the command line
    :type options: Values
    """

    if not options.host:
        options.host = "0.0.0.0"

    sock = socket()
    try:
        sock.bind((options.host, options.port))
        sock.listen(0)
        print("")
        print(datetime.today().ctime())
        print("ready for connect from client ...")

        while True:
            sc, sockname = sock.accept()
            client = SAPNIStreamSocket(sc)

            print("")
            print(datetime.today().ctime())
            print("connect from host '{}', client hdl {} o.k.".format(sockname[0], client.fileno()))

            try:
                while True:
                    r = client.recv()
                    client.send(r.payload)

            except SocketError:
                pass

            finally:
                print("")
                print(datetime.today().ctime())
                print("client hdl {} disconnected ...".format(client.fileno()))

    except SocketError:
        print("[*] Connection error")
    except KeyboardInterrupt:
        print("[*] Cancelled by the user")

    finally:
        sock.shutdown(SHUT_RDWR)
        sock.close()
コード例 #20
0
ファイル: ms_dump_info.py プロジェクト: jcmuniz/pysap
def main():
    options = parse_options()

    if options.verbose:
        logging.basicConfig(level=logging.DEBUG)

    # Initiate the connection
    conn = SAPNIStreamSocket.get_nisocket(options.remote_host, options.remote_port)
    print "[*] Connected to the message server %s:%d" % (options.remote_host, options.remote_port)

    client_string = options.client

    # Send MS_LOGIN_2 packet
    p = SAPMS(flag=0x00, iflag=0x08, toname=client_string, fromname=client_string)

    print "[*] Sending login packet:"
    response = conn.sr(p)[SAPMS]

    print "[*] Login OK, Server string: %s" % response.fromname
    server_string = response.fromname

    # Send a Dump Info packet for each possible Dump
    for i in ms_dump_command_values.keys():

        # Skip MS_DUMP_MSADM and MS_DUMP_COUNTER commands as the info
        # is included in other dump commands
        if i in [1, 12]:
            continue

        p = SAPMS(flag=0x02, iflag=0x01, toname=server_string,
                  fromname=client_string, opcode=0x1e, dump_dest=0x02,
                  dump_command=i)

        print "[*] Sending dump info", ms_dump_command_values[i]
        response = conn.sr(p)[SAPMS]

        if (response.opcode_error != 0):
            print "Error:", ms_opcode_error_values[response.opcode_error]
        print response.opcode_value
コード例 #21
0
ファイル: router_admin.py プロジェクト: jcmuniz/pysap
def main():
    options = parse_options()

    if options.verbose:
        logging.basicConfig(level=logging.DEBUG)

    response = False

    p = SAPRouter(type=SAPRouter.SAPROUTER_ADMIN)

    if options.stop:
        p.adm_command = 5
        print "[*] Requesting stop of the remote SAP Router"

    elif options.soft:
        p.adm_command = 9
        print "[*] Requesting a soft shutdown of the remote SAP Router"
        response = True

    elif options.info:
        p.adm_command = 2
        if options.info_password:
            if len(options.info_password) > 19:
                print "[*] Password too long, truncated at 19 characters"
            p.adm_password = options.info_password
            print "[*] Requesting info using password", p.adm_password
        else:
            print "[*] Requesting info"
        response = True

    elif options.new_route:
        p.adm_command = 3
        print "[*] Requesting a refresh of the router table"

    elif options.trace:
        p.adm_command = 4
        print "[*] Requesting a toggle on the trace settings"

    elif options.cancel:
        p.adm_command = 6
        p.adm_client_ids = map(int, options.cancel.split(","))
        print "[*] Requesting a cancel of the route(s) with client id(s) %s" % p.adm_client_ids
        response = True

    elif options.dump:
        p.adm_command = 7
        print "[*] Requesting a dump of the buffers"

    elif options.flush:
        p.adm_command = 8
        print "[*] Requesting a flush of the buffers"

    elif options.hide:
        p.adm_command = 14
        print "[*] Requesting a hide on the errors to clients"
        response = True

    elif options.set_peer:
        p.adm_command = 10
        p.adm_address_mask = options.set_peer
        print "[*] Request a set peer trace for the address mask %s" % p.adm_address_mask
        response = True

    elif options.clear_peer:
        p.adm_command = 11
        p.adm_address_mask = options.clear_peer
        print "[*] Request a clear peer trace for the address mask %s" % p.adm_address_mask
        response = True

    elif options.trace_conn:
        p.adm_command = 12
        p.adm_client_ids = map(int, options.trace_conn.split(","))
        print "[*] Requesting a connection trace with client id(s) %s" % p.adm_client_ids
        response = True

    else:
        print "[*] No command specified !"
        return

    # Initiate the connection
    conn = SAPNIStreamSocket.get_nisocket(options.remote_host, options.remote_port)
    print "[*] Connected to the SAP Router %s:%d" % (options.remote_host, options.remote_port)

    # Retrieve the router version used by the server if not specified
    if options.router_version:
        p.version = options.router_version
    else:
        p.version = get_router_version(conn) or p.version
    print "[*] Using SAP Router version %d" % p.version

    # Send the router admin request
    print "[*] Sending Router Admin packet"
    if options.verbose:
        p.show2()
    conn.send(p)

    # Grab the response if required
    if response:

        # Some responses has no SAPRouter's packet format and are raw strings,
        # we need to get the SAP NI layer first and then check if we could go
        # down to the SAPRouter layer.
        response = conn.recv()[SAPNI]
        if SAPRouter in response and response[SAPRouter].payload:
            response = response[SAPRouter]

        # If the response is an error, print and exit
        if router_is_error(response):
            print "[*] Error requesting info:"
            if options.verbose:
                response.show2()
            else:
                print response.err_text_value

        # Otherwise, print all the packets sent by the SAP Router
        else:
            print "[*] Response:"
            try:
                while (response):
                    print response.payload
                    response = conn.recv()
            except:
                pass
コード例 #22
0
ファイル: sapni_test.py プロジェクト: HPxpat/pysap
class PySAPNIStreamSocketTest(unittest.TestCase):

    test_port = 8005
    test_address = "127.0.0.1"
    test_string = "TEST" * 10

    def start_server(self, handler_cls):
        self.server = ThreadingTCPServer((self.test_address, self.test_port),
                                         handler_cls,
                                         bind_and_activate=False)
        self.server.allow_reuse_address = True
        self.server.server_bind()
        self.server.server_activate()
        self.server_thread = Thread(target=self.server.serve_forever)
        self.server_thread.start()

    def stop_server(self):
        self.server.shutdown()
        self.server.server_close()
        self.server_thread.join()

    def test_sapnistreamsocket(self):
        """Test SAPNIStreamSocket"""
        self.start_server(SAPNITestHandler)

        sock = socket.socket()
        sock.connect((self.test_address, self.test_port))

        self.client = SAPNIStreamSocket(sock)
        packet = self.client.sr(self.test_string)
        packet.decode_payload_as(Raw)
        self.client.close()

        self.assertIn(SAPNI, packet)
        self.assertEqual(packet[SAPNI].length, len(self.test_string))
        self.assertEqual(packet.payload.load, self.test_string)

        self.stop_server()

    def test_sapnistreamsocket_base_cls(self):
        """Test SAPNIStreamSocket handling of custom base packet classes"""
        self.start_server(SAPNITestHandler)

        class SomeClass(Packet):
            fields_desc = [StrField("text", None)]

        sock = socket.socket()
        sock.connect((self.test_address, self.test_port))

        self.client = SAPNIStreamSocket(sock, base_cls=SomeClass)
        packet = self.client.sr(self.test_string)
        self.client.close()

        self.assertIn(SAPNI, packet)
        self.assertIn(SomeClass, packet)
        self.assertEqual(packet[SAPNI].length, len(self.test_string))
        self.assertEqual(packet[SomeClass].text, self.test_string)

        self.stop_server()

    def test_sapnistreamsocket_getnisocket(self):
        """Test SAPNIStreamSocket get nisocket class method"""
        self.start_server(SAPNITestHandler)

        self.client = SAPNIStreamSocket.get_nisocket(self.test_address,
                                                     self.test_port)

        packet = self.client.sr(self.test_string)
        packet.decode_payload_as(Raw)
        self.client.close()

        self.assertIn(SAPNI, packet)
        self.assertEqual(packet[SAPNI].length, len(self.test_string))
        self.assertEqual(packet.payload.load, self.test_string)

        self.stop_server()

    def test_sapnistreamsocket_without_keep_alive(self):
        """Test SAPNIStreamSocket without keep alive"""
        self.start_server(SAPNITestHandlerKeepAlive)

        sock = socket.socket()
        sock.connect((self.test_address, self.test_port))

        self.client = SAPNIStreamSocket(sock, keep_alive=False)
        packet = self.client.sr(self.test_string)
        packet.decode_payload_as(Raw)
        self.client.close()

        # We should receive a PING instead of our packet
        self.assertIn(SAPNI, packet)
        self.assertEqual(packet[SAPNI].length, len(SAPNI.SAPNI_PING))
        self.assertEqual(packet.payload.load, SAPNI.SAPNI_PING)

        self.stop_server()

    def test_sapnistreamsocket_with_keep_alive(self):
        """Test SAPNIStreamSocket with keep alive"""
        self.start_server(SAPNITestHandlerKeepAlive)

        sock = socket.socket()
        sock.connect((self.test_address, self.test_port))

        self.client = SAPNIStreamSocket(sock, keep_alive=True)
        packet = self.client.sr(self.test_string)
        packet.decode_payload_as(Raw)
        self.client.close()

        # We should receive our packet, the PING should be handled by the
        # stream socket
        self.assertIn(SAPNI, packet)
        self.assertEqual(packet[SAPNI].length, len(self.test_string))
        self.assertEqual(packet.payload.load, self.test_string)

        self.stop_server()

    def test_sapnistreamsocket_close(self):
        """Test SAPNIStreamSocket with a server that closes the connection"""
        self.start_server(SAPNITestHandlerClose)

        sock = socket.socket()
        sock.connect((self.test_address, self.test_port))

        self.client = SAPNIStreamSocket(sock, keep_alive=False)

        with self.assertRaises(socket.error):
            self.client.sr(self.test_string)

        self.stop_server()
コード例 #23
0
ファイル: router_fingerprint.py プロジェクト: habhacker/pysap
def main():
    options = parse_options()

    level = logging.INFO
    if options.verbose:
        level = logging.DEBUG
    logging.basicConfig(level=level, format='%(message)s')

    logging.info("[*] Loading fingerprint database")
    fingerprint_db = FingerprintDB(options.fingerprints)

    # Check if we were asked to add a new fingerprint
    if options.add_fingerprint:
        if not options.version_info:
            logging.info(
                "[-] You must provide version info to add new entries to the fingerprint database !"
            )
            return
        logging.info("[*] Adding a new entry to the fingerprint database")
        fingerprint_db.add_fingerprint(options.new_fingerprint_file,
                                       options.version_info)
        return

    misses = []
    matches = []
    logging.info("[*] Trying to fingerprint version using %d packets" %
                 (len(fingerprint_targets)))

    # Trigger some errors and check with fingerprint db
    l = len(fingerprint_targets)
    i = 1
    for (target, packet) in list(fingerprint_targets.items()):

        logging.info("[*] (%d/%d) Fingerprint for packet '%s'" %
                     (i, l, target))

        # Initiate the connection and send the packet
        conn = SAPNIStreamSocket.get_nisocket(options.remote_host,
                                              options.remote_port,
                                              keep_alive=False)
        if packet is None:  # Timeout error
            error_text = conn.recv().err_text_value
        else:
            error_text = conn.sr(packet).err_text_value

        matched = fingerprint_db.match_fingerprint(target, error_text)

        if matched:
            logging.info("[*] (%d/%d) Fingerprint for packet '%s' matched !" %
                         (i, l, target))
            matches.append((target, matched))
        else:
            logging.info(
                "[*] (%d/%d) Fingerprint for packet '%s' not matched" %
                (i, l, target))
            misses.append((target, error_text))

        i += 1

    if matches:
        versions = []
        counts = {}
        logging.info("\n[*] Matched fingerprints (%d/%d):" % (len(matches), l))
        for (target, fingerprints) in matches:
            logging.info("[+] Request: %s" % target)
            for fingerprint in fingerprints:
                match = {}
                for field in version_info_fields:
                    if field in fingerprint:
                        match[field] = fingerprint[field]
                if match not in versions:
                    counts[str(match)] = 0
                    versions.append(match)
                counts[str(match)] += 1

        logging.info("\n[*] Probable versions (%d):" % len(versions))
        for version in versions:
            msg = " ".join([
                "%s: \"%s\"" % (field, version[field])
                for field in version_info_fields if version[field] != ""
            ])
            logging.info("[*]\tHits: %d Version: %s" %
                         (counts[str(version)], msg))

    if misses:
        logging.info("\n[*] Non matched fingerprints (%d/%d):" %
                     (len(misses), l))
        for (target, _) in misses:
            logging.info("[-] Request: %s" % target)

        logging.info(
            "\n[-] Some error values where not found in the fingerprint database. "
            "If you want to contribute submit a issue to https://github.com/SecureAuthCorp/pysap "
            "or write an email to [email protected] with the following information along "
            "with the SAP Router file information and how it was configured.\n"
        )
        options.new_entries = True

    # Build new entries for the fingerprint database
    if options.new_entries:
        new_fingerprint = {}
        for (target, error_text) in misses:
            new_fingerprint[target] = [{}]
            for field in fingerprint_fields:
                new_fingerprint[target][0][field] = getattr(error_text, field)
        # Expand with matched targets also
        for (target, fingerprint) in matches:
            new_fingerprint[target] = fingerprint

        logging.info("\nNew fingerprint saved to: %s" %
                     options.new_fingerprint_file)
        with open(options.new_fingerprint_file, 'w') as f:
            json.dump(new_fingerprint, f)

        version_info = {
            "patch_number": "",
            "source_id": "",
            "update_level": "",
            "file_version": "",
            "platform": "",
            "submitted_by": "",
            "comment": "",
        }
        logging.info("\n\nVersion information to complete and submit:")
        logging.info("%s" % json.dumps(version_info, indent=4))
コード例 #24
0
ファイル: ms_impersonator.py プロジェクト: jcmuniz/pysap
def main():
    options = parse_options()

    if options.verbose:
        logging.basicConfig(level=logging.DEBUG)

    # Initiate the connection
    conn = SAPNIStreamSocket.get_nisocket(options.remote_host, options.remote_port)
    print "[*] Connected to the message server %s:%d" % (options.remote_host, options.remote_port)

    # Set release information
    prop = SAPMSProperty(id=7, release="720", patchno=70, supplvl=0, platform=0)
    p = SAPMS(flag=0x01, iflag=0x01, toname="MSG_SERVER", fromname=options.client, opcode=0x43, property=prop)
    print "[*] Setting release information"
    conn.send(p)

    # Perform the login enabling the DIA+BTC+ICM services
    p = SAPMS(flag=0x08, iflag=0x08, msgtype=0x89, toname="-", fromname=options.client)
    print "[*] Sending login packet"
    conn.sr(p)[SAPMS]
    print "[*] Login performed"

    # Changing the status to starting
    p = SAPMS(flag=0x01, iflag=0x09, msgtype=0x05, toname="-", fromname=options.client)
    print "[*] Changing server's status to starting"
    conn.send(p)

    # Set IP address
    p = SAPMS(
        flag=0x01,
        iflag=0x01,
        toname="MSG_SERVER",
        fromname=options.client,
        opcode=0x06,
        opcode_version=0x01,
        change_ip_addressv4=options.logon_address,
    )
    print "[*] Setting IP address"
    response = conn.sr(p)[SAPMS]
    print "[*] IP address set"
    response.show()

    # Set logon information
    l = SAPMSLogon(type=2, port=3200, address=options.logon_address, host=options.client, misc="LB=3")
    p = SAPMS(flag=0x01, iflag=0x01, msgtype=0x01, toname="MSG_SERVER", fromname=options.client, opcode=0x2B, logon=l)
    print "[*] Setting logon information"
    response = conn.sr(p)[SAPMS]
    print "[*] Logon information set"
    response.show()

    # Set the IP Address property
    prop = SAPMSProperty(client=options.client, id=0x03, address=options.logon_address)
    p = SAPMS(flag=0x02, iflag=0x01, toname="-", fromname=options.client, opcode=0x43, property=prop)
    print "[*] Setting IP address property"
    response = conn.sr(p)[SAPMS]
    print "[*] IP Address property set"
    response.show()

    # Changing the status to active
    p = SAPMS(flag=0x01, iflag=0x09, msgtype=0x01, toname="-", fromname=options.client)
    print "[*] Changing server's status to active"
    conn.send(p)

    # Wait for connections
    try:
        while True:
            response = conn.recv()[SAPMS]
            response.show()

    except KeyboardInterrupt:
        print "[*] Cancelled by the user !"

    # Send MS_LOGOUT packet
    p = SAPMS(flag=0x00, iflag=0x04, toname="MSG_SERVER", fromname=options.client)
    print "[*] Sending logout packet"
    conn.send(p)
コード例 #25
0
def main():
    options = parse_options()

    if options.verbose:
        logging.basicConfig(level=logging.DEBUG)

    print("[*] Loading fingerprint database")
    fingerprint_db = FingerprintDB(options.fingerprints)

    # Check if we were asked to add a new fingerprint
    if options.add_fingerprint:
        if not options.version_info:
            print("[-] You must provide version info to add new entries to the fingerprint database !")
            return
        print("[*] Adding a new entry to the fingerprint database")
        fingerprint_db.add_fingerprint(options.new_fingerprint_file, options.version_info)
        return

    misses = []
    matches = []
    print("[*] Trying to fingerprint version using %d packets" % (len(fingerprint_targets)))

    # Trigger some errors and check with fingerprint db
    l = len(fingerprint_targets)
    i = 1
    for (target, packet) in list(fingerprint_targets.items()):

        print("[*] (%d/%d) Fingerprint for packet '%s'" % (i, l, target))

        # Initiate the connection and send the packet
        conn = SAPNIStreamSocket.get_nisocket(options.remote_host,
                                              options.remote_port,
                                              keep_alive=False)
        if packet is None:  # Timeout error
            error_text = conn.recv().err_text_value
        else:
            error_text = conn.sr(packet).err_text_value

        matched = fingerprint_db.match_fingerprint(target, error_text)

        if matched:
            print("[*] (%d/%d) Fingerprint for packet '%s' matched !" % (i, l, target))
            matches.append((target, matched))
        else:
            print("[*] (%d/%d) Fingerprint for packet '%s' not matched" % (i, l, target))
            misses.append((target, error_text))

        i += 1

    if matches:
        versions = []
        counts = {}
        print("\n[*] Matched fingerprints (%d/%d):" % (len(matches), l))
        for (target, fingerprints) in matches:
            print("[+] Request: %s" % target)
            for fingerprint in fingerprints:
                match = {}
                for field in version_info_fields:
                    if field in fingerprint:
                        match[field] = fingerprint[field]
                if match not in versions:
                    counts[str(match)] = 0
                    versions.append(match)
                counts[str(match)] += 1

        print("\n[*] Probable versions (%d):" % len(versions))
        for version in versions:
            msg = " ".join(["%s: \"%s\"" % (field, version[field]) for field in version_info_fields
                            if version[field] != ""])
            print("[*]\tHits: %d Version: %s" % (counts[str(version)], msg))

    if misses:
        print("\n[*] Non matched fingerprints (%d/%d):" % (len(misses), l))
        for (target, _) in misses:
            print("[-] Request: %s" % target)

        print("\n[-] Some error values where not found in the fingerprint database. "
              "If you want to contribute submit a issue to https://github.com/SecureAuthCorp/pysap "
              "or write an email to [email protected] with the following information along "
              "with the SAP Router file information and how it was configured.\n")
        options.new_entries = True

    # Build new entries for the fingerprint database
    if options.new_entries:
        new_fingerprint = {}
        for (target, error_text) in misses:
            new_fingerprint[target] = [{}]
            for field in fingerprint_fields:
                new_fingerprint[target][0][field] = getattr(error_text, field)
        # Expand with matched targets also
        for (target, fingerprint) in matches:
            new_fingerprint[target] = fingerprint

        print("\nNew fingerprint saved to: %s" % options.new_fingerprint_file)
        with open(options.new_fingerprint_file, 'w') as f:
            json.dump(new_fingerprint, f)

        version_info = {"patch_number": "",
                        "source_id": "",
                        "update_level": "",
                        "file_version": "",
                        "platform": "",
                        "submitted_by": "",
                        "comment": "",
                        }
        print("\n\nVersion information to complete and submit:")
        print("%s" % json.dumps(version_info, indent=4))
コード例 #26
0
def main():
    options = parse_options()

    if options.verbose:
        logging.basicConfig(level=logging.DEBUG)

    response = False

    p = SAPRouter(type=SAPRouter.SAPROUTER_ADMIN)

    if options.stop:
        p.adm_command = 5
        print("[*] Requesting stop of the remote SAP Router")

    elif options.soft:
        p.adm_command = 9
        print("[*] Requesting a soft shutdown of the remote SAP Router")
        response = True

    elif options.info:
        p.adm_command = 2
        if options.info_password:
            if len(options.info_password) > 19:
                print("[*] Password too long, truncated at 19 characters")
            p.adm_password = options.info_password
            print("[*] Requesting info using password %s" % p.adm_password)
        else:
            print("[*] Requesting info")
        response = True

    elif options.new_route:
        p.adm_command = 3
        print("[*] Requesting a refresh of the router table")

    elif options.trace:
        p.adm_command = 4
        print("[*] Requesting a toggle on the trace settings")

    elif options.cancel:
        p.adm_command = 6
        p.adm_client_ids = list(map(int, options.cancel.split(",")))
        print("[*] Requesting a cancel of the route(s) with client id(s) %s" % p.adm_client_ids)
        response = True

    elif options.dump:
        p.adm_command = 7
        print("[*] Requesting a dump of the buffers")

    elif options.flush:
        p.adm_command = 8
        print("[*] Requesting a flush of the buffers")

    elif options.hide:
        p.adm_command = 14
        print("[*] Requesting a hide on the errors to clients")
        response = True

    elif options.set_peer:
        p.adm_command = 10
        p.adm_address_mask = options.set_peer
        print("[*] Request a set peer trace for the address mask %s" % p.adm_address_mask)
        response = True

    elif options.clear_peer:
        p.adm_command = 11
        p.adm_address_mask = options.clear_peer
        print("[*] Request a clear peer trace for the address mask %s" % p.adm_address_mask)
        response = True

    elif options.trace_conn:
        p.adm_command = 12
        p.adm_client_ids = list(map(int, options.trace_conn.split(",")))
        print("[*] Requesting a connection trace with client id(s) %s" % p.adm_client_ids)
        response = True

    else:
        print("[*] No command specified !")
        return

    # Initiate the connection
    conn = SAPNIStreamSocket.get_nisocket(options.remote_host, options.remote_port)
    print("[*] Connected to the SAP Router %s:%d" % (options.remote_host, options.remote_port))

    # Retrieve the router version used by the server if not specified
    if options.router_version:
        p.version = options.router_version
    else:
        p.version = get_router_version(conn) or p.version
    print("[*] Using SAP Router version %d" % p.version)

    # Send the router admin request
    print("[*] Sending Router Admin packet")
    if options.verbose:
        p.show2()
    conn.send(p)

    # Grab the response if required
    if response:

        # Some responses has no SAPRouter's packet format and are raw strings,
        # we need to get the SAP NI layer first and then check if we could go
        # down to the SAPRouter layer.
        raw_response = conn.recv()[SAPNI]
        if SAPRouter in raw_response:
            router_response = raw_response[SAPRouter]

        # If the response was null, just return
        elif raw_response.length == 0:
            return

        # If the response is an error, print and exit
        if router_is_error(router_response):
            print("[*] Error requesting info:")
            if options.verbose:
                router_response.show2()
            else:
                print(router_response.err_text_value.error)

        # Otherwise, print the packets sent by the SAP Router
        else:
            print("[*] Response:\n")

            if options.info:
                # Decode the first packet as a list of info client
                raw_response.decode_payload_as(SAPRouterInfoClients)

                clients = []
                clients.append("\t".join(["ID", "Client", "Partner", "Service", "Connected on"]))
                clients.append("-" * 60)
                for client in raw_response.clients:

                    # If the trace flag is set, add a mark
                    flag = "(*)" if client.flag_traced else "(+)" if client.flag_routed else ""

                    fields = [str(client.id),
                              client.address,
                              "%s%s" % (flag, client.partner) if client.flag_routed else "(no partner)",
                              client.service if client.flag_routed else "",
                              datetime.fromtimestamp(client.connected_on).ctime()]
                    clients.append("\t".join(fields))

                # Decode the second packet as server info
                raw_response = conn.recv()
                raw_response.decode_payload_as(SAPRouterInfoServer)

                print("SAP Network Interface Router running on port %d (PID = %d)\n"
                      "Started on: %s\n"
                      "Parent process: PID = %d, port = %d\n" % (raw_response.port, raw_response.pid,
                                                                 datetime.fromtimestamp(raw_response.started_on).ctime(),
                                                                 raw_response.ppid, raw_response.pport))

                print("\n".join(clients))
                print("(*) Connections being traced")

            # Show the plain packets returned
            try:
                raw_response = conn.recv()
                while raw_response:
                    print(raw_response.payload)
                    raw_response = conn.recv()
            except error:
                pass
コード例 #27
0
    def get_nisocket(cls,
                     host=None,
                     port=None,
                     route=None,
                     password=None,
                     talk_mode=None,
                     router_version=None,
                     **kwargs):
        """Helper function to obtain a :class:`SAPRoutedStreamSocket`. If no
        route is specified, it returns a plain `SAPNIStreamSocket`. If no
        route is specified and the talk mode is raw, it returns a plain
        `StreamSocket` as it's assumed that the NI layer is not desired.

        :param host: target host to connect to if not specified in the route
        :type host: C{string}

        :param port: target port to connect to if not specified in the route
        :type port: ``int``

        :param route: route to use for determining the SAP Router to connect
        :type route: C{string} or ``list`` of :class:`SAPRouterRouteHop`

        :param password: target password if not specified in the route
        :type password: C{string}

        :param talk_mode: the talk mode to use for requesting the route
        :type talk_mode: ``int``

        :param router_version: the router version to use for requesting the
            route
        :type router_version: ``int``

        :keyword kwargs: arguments to pass to :class:`SAPRoutedStreamSocket`
            constructor

        :return: connected socket through the specified route
        :rtype: :class:`SAPRoutedStreamSocket`

        :raise SAPRouteException: if the route request to the target host/port
            was not accepted by the SAP Router

        :raise socket.error: if the connection to the target host/port failed
            or the SAP Router returned an error
        """
        # If no route was provided, check the talk mode
        if route is None:
            # If talk mode is raw, create a new StreamSocket and get rid of the
            # NI layer completely and force the base class to Raw.
            if talk_mode == 1:
                sock = socket.create_connection((host, port))
                if "base_cls" in kwargs:
                    kwargs["base_cls"] = Raw
                return StreamSocket(sock, **kwargs)

            # Otherwise use the standard SAPNIStreamSocket get_nisocket method
            else:
                return SAPNIStreamSocket.get_nisocket(host, port, **kwargs)

        # If the route was provided using a route string, convert it to a
        # list of hops
        if isinstance(route, str):
            route = SAPRouterRouteHop.from_string(route)

        # If the host and port were specified, we need to add a new hop to
        # the route
        if host is not None and port is not None:
            route.append(
                SAPRouterRouteHop(hostname=host, port=port, password=password))

        # Connect to the first hop in the route (it should be the SAP Router)
        sock = socket.create_connection(
            (route[0].hostname, int(route[0].port)))

        # Create a SAPRoutedStreamSocket instance specifying the route
        return cls(sock, route, talk_mode, router_version, **kwargs)
コード例 #28
0
def main():
    options = parse_options()

    if options.verbose:
        logging.basicConfig(level=logging.DEBUG)

    response = False

    p = SAPRouter(type=SAPRouter.SAPROUTER_ADMIN)

    if options.stop:
        p.adm_command = 5
        print("[*] Requesting stop of the remote SAP Router")

    elif options.soft:
        p.adm_command = 9
        print("[*] Requesting a soft shutdown of the remote SAP Router")
        response = True

    elif options.info:
        p.adm_command = 2
        if options.info_password:
            if len(options.info_password) > 19:
                print("[*] Password too long, truncated at 19 characters")
            p.adm_password = options.info_password
            print("[*] Requesting info using password %s" % p.adm_password)
        else:
            print("[*] Requesting info")
        response = True

    elif options.new_route:
        p.adm_command = 3
        print("[*] Requesting a refresh of the router table")

    elif options.trace:
        p.adm_command = 4
        print("[*] Requesting a toggle on the trace settings")

    elif options.cancel:
        p.adm_command = 6
        p.adm_client_ids = list(map(int, options.cancel.split(",")))
        print("[*] Requesting a cancel of the route(s) with client id(s) %s" %
              p.adm_client_ids)
        response = True

    elif options.dump:
        p.adm_command = 7
        print("[*] Requesting a dump of the buffers")

    elif options.flush:
        p.adm_command = 8
        print("[*] Requesting a flush of the buffers")

    elif options.hide:
        p.adm_command = 14
        print("[*] Requesting a hide on the errors to clients")
        response = True

    elif options.set_peer:
        p.adm_command = 10
        p.adm_address_mask = options.set_peer
        print("[*] Request a set peer trace for the address mask %s" %
              p.adm_address_mask)
        response = True

    elif options.clear_peer:
        p.adm_command = 11
        p.adm_address_mask = options.clear_peer
        print("[*] Request a clear peer trace for the address mask %s" %
              p.adm_address_mask)
        response = True

    elif options.trace_conn:
        p.adm_command = 12
        p.adm_client_ids = list(map(int, options.trace_conn.split(",")))
        print("[*] Requesting a connection trace with client id(s) %s" %
              p.adm_client_ids)
        response = True

    else:
        print("[*] No command specified !")
        return

    # Initiate the connection
    conn = SAPNIStreamSocket.get_nisocket(options.remote_host,
                                          options.remote_port)
    print("[*] Connected to the SAP Router %s:%d" %
          (options.remote_host, options.remote_port))

    # Retrieve the router version used by the server if not specified
    if options.router_version:
        p.version = options.router_version
    else:
        p.version = get_router_version(conn) or p.version
    print("[*] Using SAP Router version %d" % p.version)

    # Send the router admin request
    print("[*] Sending Router Admin packet")
    if options.verbose:
        p.show2()
    conn.send(p)

    # Grab the response if required
    if response:

        # Some responses has no SAPRouter's packet format and are raw strings,
        # we need to get the SAP NI layer first and then check if we could go
        # down to the SAPRouter layer.
        raw_response = conn.recv()[SAPNI]
        if SAPRouter in raw_response:
            router_response = raw_response[SAPRouter]

        # If the response was null, just return
        elif raw_response.length == 0:
            return

        # If the response is an error, print and exit
        if router_is_error(router_response):
            print("[*] Error requesting info:")
            if options.verbose:
                router_response.show2()
            else:
                print(router_response.err_text_value.error)

        # Otherwise, print the packets sent by the SAP Router
        else:
            print("[*] Response:\n")

            if options.info:
                # Decode the first packet as a list of info client
                raw_response.decode_payload_as(SAPRouterInfoClients)

                clients = []
                clients.append("\t".join(
                    ["ID", "Client", "Partner", "Service", "Connected on"]))
                clients.append("-" * 60)
                for client in raw_response.clients:

                    # If the trace flag is set, add a mark
                    flag = "(*)" if client.flag_traced else "(+)" if client.flag_routed else ""

                    fields = [
                        str(client.id), client.address,
                        "%s%s" % (flag, client.partner)
                        if client.flag_routed else "(no partner)",
                        client.service if client.flag_routed else "",
                        datetime.fromtimestamp(client.connected_on).ctime()
                    ]
                    clients.append("\t".join(fields))

                # Decode the second packet as server info
                raw_response = conn.recv()
                raw_response.decode_payload_as(SAPRouterInfoServer)

                print(
                    "SAP Network Interface Router running on port %d (PID = %d)\n"
                    "Started on: %s\n"
                    "Parent process: PID = %d, port = %d\n" %
                    (raw_response.port, raw_response.pid,
                     datetime.fromtimestamp(raw_response.started_on).ctime(),
                     raw_response.ppid, raw_response.pport))

                print("\n".join(clients))
                print("(*) Connections being traced")

            # Show the plain packets returned
            try:
                raw_response = conn.recv()
                while (raw_response):
                    print(raw_response.payload)
                    raw_response = conn.recv()
            except error:
                pass
コード例 #29
0
ファイル: ms_change_param.py プロジェクト: jcmuniz/pysap
def main():
    options = parse_options()

    if options.verbose:
        logging.basicConfig(level=logging.DEBUG)

    # Initiate the connection
    conn = SAPNIStreamSocket.get_nisocket(options.remote_host, options.remote_port)
    print "[*] Connected to the message server %s:%d" % (options.remote_host, options.remote_port)

    client_string = options.client

    # Build MS_LOGIN_2 packet
    p = SAPMS(flag=0x00, iflag=0x08, toname=client_string, fromname=client_string)

    # Send MS_LOGIN_2 packet
    print "[*] Sending login packet"
    response = conn.sr(p)[SAPMS]

    print "[*] Login performed, server string: %s" % response.fromname
    server_string = response.fromname

    print "[*] Retrieving current value of parameter: %s" % options.param_name

    # Send ADM AD_PROFILE request
    adm = SAPMSAdmRecord(opcode=0x1, parameter=options.param_name)
    p = SAPMS(toname=server_string, fromname=client_string, version=4,
              flag=0x04, iflag=0x05, adm_records=[adm])

    print "[*] Sending packet"
    response = conn.sr(p)[SAPMS]

    if options.verbose:
        print "[*] Response:"
        response.show()

    param_old_value = response.adm_records[0].parameter
    print "[*] Parameter %s" % param_old_value

    # If a parameter change was requested, send an ADM AD_SHARED_PARAMETER request
    if options.param_value:
        print "[*] Changing parameter value from: %s to: %s" % (param_old_value,
                                                                options.param_value)

        # Build the packet
        adm = SAPMSAdmRecord(opcode=0x2e,
                             parameter="%s=%s" % (options.param_name,
                                                  options.param_value))
        p = SAPMS(toname=server_string, fromname=client_string, version=4,
                  iflag=5, flag=4, adm_records=[adm])

        # Send the packet
        print "[*] Sending packet"
        response = conn.sr(p)[SAPMS]

        if options.verbose:
            print "[*] Response:"
            response.show()

        if response.adm_records[0].errorno != 0:
            print "[*] Error requesting parameter change (error number %d)" % response.adm_records[0].errorno
        else:
            print "[*] Parameter changed for the current session !"
コード例 #30
0
class PySAPNIStreamSocketTest(unittest.TestCase):

    test_port = 8005
    test_address = "127.0.0.1"
    test_string = "TEST" * 10

    def start_server(self, handler_cls):
        self.server = ThreadingTCPServer((self.test_address, self.test_port),
                                         handler_cls,
                                         bind_and_activate=False)
        self.server.allow_reuse_address = True
        self.server.server_bind()
        self.server.server_activate()
        self.server_thread = Thread(target=self.server.serve_forever)
        self.server_thread.start()

    def stop_server(self):
        self.server.shutdown()
        self.server.server_close()
        self.server_thread.join()

    def test_sapnistreamsocket(self):
        """Test SAPNIStreamSocket"""
        self.start_server(SAPNITestHandler)

        sock = socket.socket()
        sock.connect((self.test_address, self.test_port))

        self.client = SAPNIStreamSocket(sock)
        packet = self.client.sr(self.test_string)
        packet.decode_payload_as(Raw)
        self.client.close()

        self.assertIn(SAPNI, packet)
        self.assertEqual(packet[SAPNI].length, len(self.test_string))
        self.assertEqual(packet.payload.load, self.test_string)

        self.stop_server()

    def test_sapnistreamsocket_base_cls(self):
        """Test SAPNIStreamSocket handling of custom base packet classes"""
        self.start_server(SAPNITestHandler)

        class SomeClass(Packet):
            fields_desc = [StrField("text", None)]

        sock = socket.socket()
        sock.connect((self.test_address, self.test_port))

        self.client = SAPNIStreamSocket(sock, base_cls=SomeClass)
        packet = self.client.sr(self.test_string)
        self.client.close()

        self.assertIn(SAPNI, packet)
        self.assertIn(SomeClass, packet)
        self.assertEqual(packet[SAPNI].length, len(self.test_string))
        self.assertEqual(packet[SomeClass].text, self.test_string)

        self.stop_server()

    def test_sapnistreamsocket_getnisocket(self):
        """Test SAPNIStreamSocket get nisocket class method"""
        self.start_server(SAPNITestHandler)

        self.client = SAPNIStreamSocket.get_nisocket(self.test_address,
                                                     self.test_port)

        packet = self.client.sr(self.test_string)
        packet.decode_payload_as(Raw)
        self.client.close()

        self.assertIn(SAPNI, packet)
        self.assertEqual(packet[SAPNI].length, len(self.test_string))
        self.assertEqual(packet.payload.load, self.test_string)

        self.stop_server()

    def test_sapnistreamsocket_without_keep_alive(self):
        """Test SAPNIStreamSocket without keep alive"""
        self.start_server(SAPNITestHandlerKeepAlive)

        sock = socket.socket()
        sock.connect((self.test_address, self.test_port))

        self.client = SAPNIStreamSocket(sock, keep_alive=False)
        packet = self.client.sr(self.test_string)
        packet.decode_payload_as(Raw)
        self.client.close()

        # We should receive a PING instead of our packet
        self.assertIn(SAPNI, packet)
        self.assertEqual(packet[SAPNI].length, len(SAPNI.SAPNI_PING))
        self.assertEqual(packet.payload.load, SAPNI.SAPNI_PING)

        self.stop_server()

    def test_sapnistreamsocket_with_keep_alive(self):
        """Test SAPNIStreamSocket with keep alive"""
        self.start_server(SAPNITestHandlerKeepAlive)

        sock = socket.socket()
        sock.connect((self.test_address, self.test_port))

        self.client = SAPNIStreamSocket(sock, keep_alive=True)
        packet = self.client.sr(self.test_string)
        packet.decode_payload_as(Raw)
        self.client.close()

        # We should receive our packet, the PING should be handled by the
        # stream socket
        self.assertIn(SAPNI, packet)
        self.assertEqual(packet[SAPNI].length, len(self.test_string))
        self.assertEqual(packet.payload.load, self.test_string)

        self.stop_server()

    def test_sapnistreamsocket_close(self):
        """Test SAPNIStreamSocket with a server that closes the connection"""
        self.start_server(SAPNITestHandlerClose)

        sock = socket.socket()
        sock.connect((self.test_address, self.test_port))

        self.client = SAPNIStreamSocket(sock, keep_alive=False)

        with self.assertRaises(socket.error):
            self.client.sr(self.test_string)

        self.stop_server()
コード例 #31
0
ファイル: SAPEnqueue.py プロジェクト: CoreSecurity/pysap
 def __init__(self, sock, keep_alive=True, base_cls=None):
     """Initialization defaults to SAPEnqueue as base class"""
     if base_cls is None:
         base_cls = SAPEnqueue
     SAPNIStreamSocket.__init__(self, sock, keep_alive=keep_alive, base_cls=base_cls)
コード例 #32
0
ファイル: SAPDiagClient.py プロジェクト: jcmuniz/pysap
 def connect(self):
     """
     Creates a L{SAPNIStreamSocket} connection to the host/port
     """
     self._connection = SAPNIStreamSocket.get_nisocket(self.host, self.port)