2017-12-13 20:40:55 +00:00
|
|
|
#!/usr/bin/env python3
|
2017-08-08 21:07:29 +00:00
|
|
|
#
|
2018-02-20 00:53:15 +00:00
|
|
|
# Copyright 2017 Ettus Research, a National Instruments Company
|
2017-08-08 21:07:29 +00:00
|
|
|
#
|
2018-02-20 00:53:15 +00:00
|
|
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
2017-08-08 21:07:29 +00:00
|
|
|
#
|
|
|
|
|
"""
|
|
|
|
|
RPC shell to debug USRP MPM capable devices
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
from __future__ import print_function
|
2019-11-19 13:43:33 +00:00
|
|
|
import re
|
2017-08-08 21:07:29 +00:00
|
|
|
import cmd
|
|
|
|
|
import time
|
|
|
|
|
import argparse
|
2018-12-13 00:53:03 +00:00
|
|
|
import multiprocessing
|
2017-08-08 21:07:29 +00:00
|
|
|
from importlib import import_module
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
from usrp_mpm.mpmtypes import MPM_RPC_PORT
|
|
|
|
|
except ImportError:
|
|
|
|
|
MPM_RPC_PORT = None
|
|
|
|
|
|
|
|
|
|
DEFAULT_MPM_RPC_PORT = 49601
|
|
|
|
|
if MPM_RPC_PORT is None:
|
|
|
|
|
MPM_RPC_PORT = DEFAULT_MPM_RPC_PORT
|
|
|
|
|
if MPM_RPC_PORT != DEFAULT_MPM_RPC_PORT:
|
|
|
|
|
print("Warning: Default encoded MPM RPC port does not match that in MPM.")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def parse_args():
|
|
|
|
|
"""
|
|
|
|
|
Parse command line args.
|
|
|
|
|
"""
|
|
|
|
|
parser = argparse.ArgumentParser(
|
|
|
|
|
description="MPM Shell",
|
|
|
|
|
)
|
|
|
|
|
parser.add_argument(
|
|
|
|
|
'host',
|
|
|
|
|
help="Specify host to connect to.", default=None,
|
|
|
|
|
)
|
|
|
|
|
parser.add_argument(
|
|
|
|
|
'-p', '--port', type=int,
|
|
|
|
|
help="Specify port to connect to.", default=MPM_RPC_PORT,
|
|
|
|
|
)
|
|
|
|
|
parser.add_argument(
|
|
|
|
|
'-c', '--claim',
|
|
|
|
|
action='store_true',
|
|
|
|
|
help="Claim device after connecting."
|
|
|
|
|
)
|
2017-11-21 06:27:54 +00:00
|
|
|
parser.add_argument(
|
|
|
|
|
'-j', '--hijack', type=str,
|
|
|
|
|
help="Hijack running session (excludes --claim)."
|
|
|
|
|
)
|
2019-11-19 13:43:33 +00:00
|
|
|
parser.add_argument(
|
|
|
|
|
'-s', '--script', type=str,
|
|
|
|
|
help="Run shell in scripting mode. Specified script contains "
|
|
|
|
|
"MPM shell commands, one per line."
|
|
|
|
|
)
|
2017-08-08 21:07:29 +00:00
|
|
|
return parser.parse_args()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def split_args(args, *default_args):
|
|
|
|
|
" Returns an array of args, space-separated "
|
|
|
|
|
args = args.split()
|
|
|
|
|
return [
|
|
|
|
|
arg_val if arg_idx < len(args) else default_args[arg_idx]
|
|
|
|
|
for arg_idx, arg_val in enumerate(args)
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class MPMClaimer(object):
|
|
|
|
|
"""
|
|
|
|
|
Holds a claim.
|
|
|
|
|
"""
|
2018-12-13 00:53:03 +00:00
|
|
|
def __init__(self, host, port):
|
2017-08-08 21:07:29 +00:00
|
|
|
self.token = None
|
2018-12-13 00:53:03 +00:00
|
|
|
self.hijacked = False
|
|
|
|
|
self._cmd_q = multiprocessing.Queue()
|
|
|
|
|
self._token_q = multiprocessing.Queue()
|
|
|
|
|
self._claim_loop = multiprocessing.Process(
|
2017-08-08 21:07:29 +00:00
|
|
|
target=self.claim_loop,
|
|
|
|
|
name="Claimer Loop",
|
2018-12-13 00:53:03 +00:00
|
|
|
args=(host, port, self._cmd_q, self._token_q)
|
2017-08-08 21:07:29 +00:00
|
|
|
)
|
|
|
|
|
self._claim_loop.start()
|
|
|
|
|
|
2018-12-13 00:53:03 +00:00
|
|
|
def claim_loop(self, host, port, cmd_q, token_q):
|
2017-08-08 21:07:29 +00:00
|
|
|
"""
|
|
|
|
|
Run a claim loop
|
|
|
|
|
"""
|
2018-12-13 00:53:03 +00:00
|
|
|
from mprpc import RPCClient
|
|
|
|
|
from mprpc.exceptions import RPCError
|
2019-11-19 13:43:33 +00:00
|
|
|
command = None
|
2018-12-13 00:53:03 +00:00
|
|
|
token = None
|
|
|
|
|
exit_loop = False
|
2017-08-08 21:07:29 +00:00
|
|
|
client = RPCClient(host, port, pack_params={'use_bin_type': True})
|
2017-08-09 17:34:04 +00:00
|
|
|
try:
|
2018-12-13 00:53:03 +00:00
|
|
|
while not exit_loop:
|
2019-11-19 13:43:33 +00:00
|
|
|
if token and not command:
|
2018-12-13 00:53:03 +00:00
|
|
|
client.call('reclaim', token)
|
2019-11-19 13:43:33 +00:00
|
|
|
elif command == 'claim':
|
2018-12-13 00:53:03 +00:00
|
|
|
if not token:
|
|
|
|
|
token = client.call('claim', 'MPM Shell')
|
|
|
|
|
else:
|
|
|
|
|
print("Already have claim")
|
|
|
|
|
token_q.put(token)
|
2019-11-19 13:43:33 +00:00
|
|
|
elif command == 'unclaim':
|
2018-12-13 00:53:03 +00:00
|
|
|
if token:
|
|
|
|
|
client.call('unclaim', token)
|
|
|
|
|
token = None
|
|
|
|
|
token_q.put(None)
|
2019-11-19 13:43:33 +00:00
|
|
|
elif command == 'exit':
|
2018-12-13 00:53:03 +00:00
|
|
|
if token:
|
|
|
|
|
client.call('unclaim', token)
|
|
|
|
|
token = None
|
|
|
|
|
token_q.put(None)
|
|
|
|
|
exit_loop = True
|
2017-08-09 17:34:04 +00:00
|
|
|
time.sleep(1)
|
2019-11-19 13:43:33 +00:00
|
|
|
command = None
|
2018-12-13 00:53:03 +00:00
|
|
|
if not cmd_q.empty():
|
2019-11-19 13:43:33 +00:00
|
|
|
command = cmd_q.get(False)
|
2017-08-09 17:34:04 +00:00
|
|
|
except RPCError as ex:
|
|
|
|
|
print("Unexpected RPC error in claimer loop!")
|
|
|
|
|
print(str(ex))
|
2017-08-08 21:07:29 +00:00
|
|
|
|
2018-12-13 00:53:03 +00:00
|
|
|
def exit(self):
|
2017-08-08 21:07:29 +00:00
|
|
|
"""
|
|
|
|
|
Unclaim device and exit claim loop.
|
|
|
|
|
"""
|
2018-12-13 00:53:03 +00:00
|
|
|
self.unclaim()
|
|
|
|
|
self._cmd_q.put('exit')
|
2017-08-08 21:07:29 +00:00
|
|
|
self._claim_loop.join()
|
|
|
|
|
|
2017-11-21 06:27:54 +00:00
|
|
|
def unclaim(self):
|
|
|
|
|
"""
|
2018-12-13 00:53:03 +00:00
|
|
|
Unclaim device.
|
|
|
|
|
"""
|
|
|
|
|
if not self.hijacked:
|
|
|
|
|
self._cmd_q.put('unclaim')
|
|
|
|
|
else:
|
|
|
|
|
self.hijacked = False
|
|
|
|
|
self.token = None
|
|
|
|
|
|
|
|
|
|
def claim(self):
|
2017-11-21 06:27:54 +00:00
|
|
|
"""
|
2018-12-13 00:53:03 +00:00
|
|
|
Claim device.
|
|
|
|
|
"""
|
|
|
|
|
self._cmd_q.put('claim')
|
|
|
|
|
self.token = self._token_q.get(True, 5.0)
|
2017-11-21 06:27:54 +00:00
|
|
|
|
2018-12-13 00:53:03 +00:00
|
|
|
def get_token(self):
|
|
|
|
|
"""
|
|
|
|
|
Get current token (if any)
|
|
|
|
|
"""
|
|
|
|
|
if not self._token_q.empty():
|
|
|
|
|
self.token = self._token_q.get(False)
|
|
|
|
|
return self.token
|
|
|
|
|
|
|
|
|
|
def hijack(self, token):
|
2019-11-19 13:43:33 +00:00
|
|
|
"""
|
|
|
|
|
Take over existing session by providing session token.
|
|
|
|
|
"""
|
2018-12-13 00:53:03 +00:00
|
|
|
if self.token:
|
|
|
|
|
print("Already have token")
|
|
|
|
|
return
|
|
|
|
|
else:
|
|
|
|
|
self.token = token
|
|
|
|
|
self.hijacked = True
|
2017-08-08 21:07:29 +00:00
|
|
|
|
|
|
|
|
class MPMShell(cmd.Cmd):
|
|
|
|
|
"""
|
|
|
|
|
RPC Shell class. See cmd module.
|
|
|
|
|
"""
|
2019-11-19 13:43:33 +00:00
|
|
|
def __init__(self, host, port, claim, hijack, script):
|
2017-08-08 21:07:29 +00:00
|
|
|
cmd.Cmd.__init__(self)
|
|
|
|
|
self.prompt = "> "
|
|
|
|
|
self.client = None
|
|
|
|
|
self.remote_methods = []
|
2018-01-24 12:54:55 +00:00
|
|
|
self._host = host
|
|
|
|
|
self._port = port
|
2017-08-08 21:07:29 +00:00
|
|
|
self._device_info = None
|
2018-12-13 00:53:03 +00:00
|
|
|
self._claimer = MPMClaimer(self._host, self._port)
|
2018-01-24 12:54:55 +00:00
|
|
|
if host is not None:
|
|
|
|
|
self.connect(host, port)
|
|
|
|
|
if claim:
|
2017-08-08 21:07:29 +00:00
|
|
|
self.claim()
|
2018-01-24 12:54:55 +00:00
|
|
|
elif hijack:
|
|
|
|
|
self.hijack(hijack)
|
2017-08-08 21:07:29 +00:00
|
|
|
self.update_prompt()
|
2019-11-19 13:43:33 +00:00
|
|
|
self._script = script
|
|
|
|
|
if self._script:
|
|
|
|
|
self.parse_script()
|
2017-08-08 21:07:29 +00:00
|
|
|
|
2017-08-09 17:34:04 +00:00
|
|
|
def _add_command(self, command, docs, requires_token=False):
|
2017-08-08 21:07:29 +00:00
|
|
|
"""
|
|
|
|
|
Add a command to the current session
|
|
|
|
|
"""
|
|
|
|
|
cmd_name = 'do_' + command
|
|
|
|
|
if not hasattr(self, cmd_name):
|
2017-08-09 17:34:04 +00:00
|
|
|
new_command = lambda args: self.rpc_template(
|
|
|
|
|
str(command), requires_token, args
|
|
|
|
|
)
|
2017-08-08 21:07:29 +00:00
|
|
|
new_command.__doc__ = docs
|
|
|
|
|
setattr(self, cmd_name, new_command)
|
|
|
|
|
self.remote_methods.append(command)
|
|
|
|
|
|
2019-11-19 13:43:33 +00:00
|
|
|
def _print_response(self, response):
|
|
|
|
|
print(re.sub("^", "< ", response, flags=re.MULTILINE))
|
|
|
|
|
|
2017-08-09 17:34:04 +00:00
|
|
|
def rpc_template(self, command, requires_token, args=None):
|
2017-08-08 21:07:29 +00:00
|
|
|
"""
|
|
|
|
|
Template function to create new RPC shell commands
|
|
|
|
|
"""
|
2018-12-13 00:53:03 +00:00
|
|
|
from mprpc.exceptions import RPCError
|
2017-08-09 17:34:04 +00:00
|
|
|
if requires_token and \
|
2018-12-13 00:53:03 +00:00
|
|
|
(self._claimer is None or self._claimer.get_token() is None):
|
2019-11-19 13:43:33 +00:00
|
|
|
self._print_response("Cannot execute `{}' -- "
|
|
|
|
|
"no claim available!".format(command))
|
|
|
|
|
return False
|
2017-08-08 21:07:29 +00:00
|
|
|
try:
|
2017-08-09 17:34:04 +00:00
|
|
|
if args or requires_token:
|
2017-08-08 21:07:29 +00:00
|
|
|
expanded_args = self.expand_args(args)
|
2017-08-09 17:34:04 +00:00
|
|
|
if requires_token:
|
2018-12-13 00:53:03 +00:00
|
|
|
expanded_args.insert(0, self._claimer.get_token())
|
2017-08-08 21:07:29 +00:00
|
|
|
response = self.client.call(command, *expanded_args)
|
|
|
|
|
else:
|
|
|
|
|
response = self.client.call(command)
|
|
|
|
|
except RPCError as ex:
|
2019-11-19 13:43:33 +00:00
|
|
|
self._print_response("RPC Command failed!\nError: {}".format(ex))
|
|
|
|
|
return False
|
2017-08-08 21:07:29 +00:00
|
|
|
except Exception as ex:
|
2019-11-19 13:43:33 +00:00
|
|
|
self._print_response("Unexpected exception!\nError: {}".format(ex))
|
|
|
|
|
return True
|
2017-08-08 21:07:29 +00:00
|
|
|
if isinstance(response, bool):
|
|
|
|
|
if response:
|
2019-11-19 13:43:33 +00:00
|
|
|
self._print_response("Command succeeded.")
|
2018-01-24 12:54:55 +00:00
|
|
|
else:
|
2019-11-19 13:43:33 +00:00
|
|
|
self._print_response("Command failed!")
|
2018-01-24 12:54:55 +00:00
|
|
|
else:
|
2019-11-19 13:43:33 +00:00
|
|
|
self._print_response(str(response))
|
|
|
|
|
|
|
|
|
|
return False
|
2017-08-08 21:07:29 +00:00
|
|
|
|
|
|
|
|
def get_names(self):
|
|
|
|
|
" We need this for tab completion. "
|
|
|
|
|
return dir(self)
|
|
|
|
|
|
|
|
|
|
###########################################################################
|
|
|
|
|
# Cmd module specific
|
|
|
|
|
###########################################################################
|
2019-11-19 13:43:33 +00:00
|
|
|
def default(self, line):
|
|
|
|
|
self._print_response("*** Unknown syntax: %s" % line)
|
|
|
|
|
|
|
|
|
|
def preloop(self):
|
|
|
|
|
"""
|
|
|
|
|
In script mode add Execution start marker to ease parsing script output
|
|
|
|
|
:return: None
|
|
|
|
|
"""
|
|
|
|
|
if self._script:
|
|
|
|
|
print("Execute %s" % self._script)
|
|
|
|
|
|
|
|
|
|
def precmd(self, line):
|
|
|
|
|
"""
|
|
|
|
|
Add command prepended by "> " in scripting mode to ease parsing script
|
|
|
|
|
output.
|
|
|
|
|
"""
|
|
|
|
|
if self.cmdqueue:
|
|
|
|
|
print("> %s" % line)
|
|
|
|
|
return line
|
2017-08-08 21:07:29 +00:00
|
|
|
|
|
|
|
|
def postcmd(self, stop, line):
|
|
|
|
|
"""
|
|
|
|
|
Is run after every command executes. Does:
|
|
|
|
|
- Update prompt
|
|
|
|
|
"""
|
|
|
|
|
self.update_prompt()
|
2019-11-19 13:43:33 +00:00
|
|
|
return stop
|
2017-08-08 21:07:29 +00:00
|
|
|
|
|
|
|
|
###########################################################################
|
|
|
|
|
# Internal methods
|
|
|
|
|
###########################################################################
|
|
|
|
|
def connect(self, host, port):
|
|
|
|
|
"""
|
|
|
|
|
Launch a connection.
|
|
|
|
|
"""
|
2018-12-13 00:53:03 +00:00
|
|
|
from mprpc import RPCClient
|
2017-08-08 21:07:29 +00:00
|
|
|
print("Attempting to connect to {host}:{port}...".format(
|
|
|
|
|
host=host, port=port
|
|
|
|
|
))
|
|
|
|
|
try:
|
|
|
|
|
self.client = RPCClient(host, port, pack_params={'use_bin_type': True})
|
|
|
|
|
print("Connection successful.")
|
|
|
|
|
except Exception as ex:
|
|
|
|
|
print("Connection refused")
|
|
|
|
|
print("Error: {}".format(ex))
|
|
|
|
|
return False
|
|
|
|
|
self._host = host
|
|
|
|
|
self._port = port
|
|
|
|
|
print("Getting methods...")
|
|
|
|
|
methods = self.client.call('list_methods')
|
|
|
|
|
for method in methods:
|
|
|
|
|
self._add_command(*method)
|
|
|
|
|
print("Added {} methods.".format(len(methods)))
|
|
|
|
|
print("Quering device info...")
|
|
|
|
|
self._device_info = self.client.call('get_device_info')
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
def disconnect(self):
|
|
|
|
|
"""
|
|
|
|
|
Clean up after a connection was closed.
|
|
|
|
|
"""
|
2018-12-13 00:53:03 +00:00
|
|
|
from mprpc.exceptions import RPCError
|
2017-08-08 21:07:29 +00:00
|
|
|
self._device_info = None
|
|
|
|
|
if self._claimer is not None:
|
2018-12-13 00:53:03 +00:00
|
|
|
self._claimer.exit()
|
2017-08-08 21:07:29 +00:00
|
|
|
if self.client:
|
|
|
|
|
try:
|
|
|
|
|
self.client.close()
|
|
|
|
|
except RPCError as ex:
|
|
|
|
|
print("Error while closing the connection")
|
|
|
|
|
print("Error: {}".format(ex))
|
|
|
|
|
for method in self.remote_methods:
|
|
|
|
|
delattr(self, "do_" + method)
|
|
|
|
|
self.remote_methods = []
|
|
|
|
|
self.client = None
|
|
|
|
|
self._host = None
|
|
|
|
|
self._port = None
|
|
|
|
|
|
|
|
|
|
def claim(self):
|
|
|
|
|
" Initialize claim "
|
|
|
|
|
print("Claiming device...")
|
2018-12-13 00:53:03 +00:00
|
|
|
self._claimer.claim()
|
2017-08-08 21:07:29 +00:00
|
|
|
return True
|
|
|
|
|
|
2017-11-21 06:27:54 +00:00
|
|
|
def hijack(self, token):
|
|
|
|
|
" Hijack running session "
|
2018-12-13 00:53:03 +00:00
|
|
|
if self._claimer.hijacked:
|
2017-11-21 06:27:54 +00:00
|
|
|
print("Claimer already active. Can't hijack.")
|
|
|
|
|
return False
|
|
|
|
|
print("Hijacking device...")
|
2018-12-13 00:53:03 +00:00
|
|
|
self._claimer.hijack(token)
|
2017-11-21 06:27:54 +00:00
|
|
|
return True
|
|
|
|
|
|
2017-08-08 21:07:29 +00:00
|
|
|
def unclaim(self):
|
|
|
|
|
"""
|
|
|
|
|
unclaim
|
|
|
|
|
"""
|
2018-12-13 00:53:03 +00:00
|
|
|
self._claimer.unclaim()
|
2017-08-08 21:07:29 +00:00
|
|
|
|
|
|
|
|
def update_prompt(self):
|
|
|
|
|
"""
|
|
|
|
|
Update prompt
|
|
|
|
|
"""
|
|
|
|
|
if self._device_info is None:
|
|
|
|
|
self.prompt = '> '
|
|
|
|
|
else:
|
2018-12-13 00:53:03 +00:00
|
|
|
token = self._claimer.get_token()
|
|
|
|
|
if token is None:
|
2017-11-21 06:27:54 +00:00
|
|
|
claim_status = ''
|
2018-12-13 00:53:03 +00:00
|
|
|
elif self._claimer.hijacked:
|
2017-11-21 06:27:54 +00:00
|
|
|
claim_status = ' [H]'
|
2018-12-13 00:53:03 +00:00
|
|
|
else:
|
|
|
|
|
claim_status = ' [C]'
|
2017-08-08 21:07:29 +00:00
|
|
|
self.prompt = '{dev_id}{claim_status}> '.format(
|
|
|
|
|
dev_id=self._device_info.get(
|
|
|
|
|
'name', self._device_info.get('serial', '?')
|
|
|
|
|
),
|
2017-11-21 06:27:54 +00:00
|
|
|
claim_status=claim_status,
|
2017-08-08 21:07:29 +00:00
|
|
|
)
|
|
|
|
|
|
2019-11-19 13:43:33 +00:00
|
|
|
def parse_script(self):
|
|
|
|
|
"""
|
|
|
|
|
Adding script command from file pointed to by self._script.
|
|
|
|
|
|
|
|
|
|
The commands are read from file one per line and added to cmdqueue of
|
|
|
|
|
parent class. This way they will be executed instead of input from
|
|
|
|
|
stdin. An EOF command is appended to the list to ensure the shell exits
|
|
|
|
|
after script execution.
|
|
|
|
|
:return: None
|
|
|
|
|
"""
|
|
|
|
|
try:
|
|
|
|
|
with open(self._script, "r") as script:
|
|
|
|
|
for command in script:
|
|
|
|
|
self.cmdqueue.append(command.strip())
|
|
|
|
|
except OSError as ex:
|
|
|
|
|
print("Failed to read script. (%s)" % ex)
|
|
|
|
|
self.cmdqueue.append("EOF") # terminate shell after script execution
|
|
|
|
|
|
2017-08-08 21:07:29 +00:00
|
|
|
def expand_args(self, args):
|
|
|
|
|
"""
|
|
|
|
|
Takes a string and returns a list
|
|
|
|
|
"""
|
2018-12-13 00:53:03 +00:00
|
|
|
if self._claimer is not None and self._claimer.get_token() is not None:
|
|
|
|
|
args = args.replace('$T', str(self._claimer.get_token()))
|
2017-08-08 21:07:29 +00:00
|
|
|
eval_preamble = '='
|
|
|
|
|
args = args.strip()
|
|
|
|
|
if args.startswith(eval_preamble):
|
|
|
|
|
parsed_args = eval(args.lstrip(eval_preamble))
|
|
|
|
|
if not isinstance(parsed_args, list):
|
|
|
|
|
parsed_args = [parsed_args]
|
|
|
|
|
else:
|
|
|
|
|
parsed_args = []
|
|
|
|
|
for arg in args.split():
|
|
|
|
|
try:
|
|
|
|
|
parsed_args.append(int(arg, 0))
|
|
|
|
|
continue
|
|
|
|
|
except ValueError:
|
|
|
|
|
pass
|
|
|
|
|
try:
|
|
|
|
|
parsed_args.append(float(arg))
|
|
|
|
|
continue
|
|
|
|
|
except ValueError:
|
|
|
|
|
pass
|
|
|
|
|
parsed_args.append(arg)
|
|
|
|
|
return parsed_args
|
|
|
|
|
|
|
|
|
|
###########################################################################
|
|
|
|
|
# Predefined commands
|
|
|
|
|
###########################################################################
|
|
|
|
|
def do_connect(self, args):
|
|
|
|
|
"""
|
|
|
|
|
Connect to a remote MPM server. See connect()
|
|
|
|
|
"""
|
|
|
|
|
host, port = split_args(args, 'localhost', MPM_RPC_PORT)
|
|
|
|
|
port = int(port)
|
|
|
|
|
self.connect(host, port)
|
|
|
|
|
|
|
|
|
|
def do_claim(self, _):
|
|
|
|
|
"""
|
|
|
|
|
Spawn a claim loop
|
|
|
|
|
"""
|
|
|
|
|
self.claim()
|
|
|
|
|
|
2017-11-21 06:27:54 +00:00
|
|
|
def do_hijack(self, token):
|
|
|
|
|
"""
|
|
|
|
|
Hijack a running session
|
|
|
|
|
"""
|
|
|
|
|
self.hijack(token)
|
|
|
|
|
|
2017-08-08 21:07:29 +00:00
|
|
|
def do_unclaim(self, _):
|
|
|
|
|
"""
|
|
|
|
|
unclaim
|
|
|
|
|
"""
|
|
|
|
|
self.unclaim()
|
|
|
|
|
|
|
|
|
|
def do_disconnect(self, _):
|
|
|
|
|
"""
|
|
|
|
|
disconnect from the RPC server
|
|
|
|
|
"""
|
|
|
|
|
self.disconnect()
|
|
|
|
|
|
|
|
|
|
def do_import(self, args):
|
|
|
|
|
"""import a python module into the global namespace"""
|
|
|
|
|
globals()[args] = import_module(args)
|
|
|
|
|
|
2019-11-19 13:43:33 +00:00
|
|
|
# pylint: disable=invalid-name
|
2017-08-08 21:07:29 +00:00
|
|
|
def do_EOF(self, _):
|
2019-11-19 13:43:33 +00:00
|
|
|
"""
|
|
|
|
|
When catching EOF, exit the program.
|
|
|
|
|
"""
|
2017-08-08 21:07:29 +00:00
|
|
|
print("Exiting...")
|
|
|
|
|
self.disconnect()
|
2019-11-19 13:43:33 +00:00
|
|
|
return True # orderly shutdown
|
2017-08-08 21:07:29 +00:00
|
|
|
|
|
|
|
|
def main():
|
|
|
|
|
" Go, go, go! "
|
2018-01-24 12:54:55 +00:00
|
|
|
args = parse_args()
|
2019-11-19 13:43:33 +00:00
|
|
|
my_shell = MPMShell(args.host, args.port, args.claim,
|
|
|
|
|
args.hijack, args.script)
|
2018-01-24 12:54:55 +00:00
|
|
|
|
2017-08-08 21:07:29 +00:00
|
|
|
try:
|
2019-11-19 13:43:33 +00:00
|
|
|
my_shell.cmdloop()
|
2017-08-09 17:34:04 +00:00
|
|
|
except KeyboardInterrupt:
|
|
|
|
|
my_shell.disconnect()
|
2019-11-19 13:43:33 +00:00
|
|
|
except Exception as ex: # pylint: disable=broad-except
|
2017-08-09 17:34:04 +00:00
|
|
|
print("Uncaught exception: " + str(ex))
|
2017-08-08 21:07:29 +00:00
|
|
|
my_shell.disconnect()
|
2019-11-19 13:43:33 +00:00
|
|
|
return False
|
2017-08-08 21:07:29 +00:00
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
|
exit(not main())
|