86890704fd
todo: add documentation & wireshark dissector
721 lines
25 KiB
Python
Executable file
721 lines
25 KiB
Python
Executable file
# This file is part of Scapy
|
|
# See http://www.secdev.org/projects/scapy for more information
|
|
# Copyright (C) Philippe Biondi <phil@secdev.org>
|
|
# This program is published under a GPLv2 license
|
|
|
|
"""
|
|
Main module for interactive startup.
|
|
"""
|
|
|
|
from __future__ import absolute_import
|
|
from __future__ import print_function
|
|
|
|
import sys
|
|
import os
|
|
import getopt
|
|
import code
|
|
import gzip
|
|
import glob
|
|
import importlib
|
|
import io
|
|
import logging
|
|
import types
|
|
import warnings
|
|
from random import choice
|
|
|
|
# Never add any global import, in main.py, that would trigger a
|
|
# warning message before the console handlers gets added in interact()
|
|
from scapy.error import log_interactive, log_loading, log_scapy, \
|
|
Scapy_Exception, ScapyColoredFormatter
|
|
import scapy.modules.six as six
|
|
from scapy.themes import DefaultTheme, BlackAndWhite, apply_ipython_style
|
|
from scapy.consts import WINDOWS
|
|
|
|
from scapy.compat import cast, Any, Dict, List, Optional, Tuple, Union
|
|
|
|
IGNORED = list(six.moves.builtins.__dict__)
|
|
|
|
LAYER_ALIASES = {
|
|
"tls": "tls.all"
|
|
}
|
|
|
|
QUOTES = [
|
|
("Craft packets like it is your last day on earth.", "Lao-Tze"),
|
|
("Craft packets like I craft my beer.", "Jean De Clerck"),
|
|
("Craft packets before they craft you.", "Socrate"),
|
|
("Craft me if you can.", "IPv6 layer"),
|
|
("To craft a packet, you have to be a packet, and learn how to swim in "
|
|
"the wires and in the waves.", "Jean-Claude Van Damme"),
|
|
("We are in France, we say Skappee. OK? Merci.", "Sebastien Chabal"),
|
|
("Wanna support scapy? Rate it on sectools! "
|
|
"http://sectools.org/tool/scapy/", "Satoshi Nakamoto"),
|
|
("What is dead may never die!", "Python 2"),
|
|
]
|
|
|
|
|
|
def _probe_config_file(cf):
|
|
# type: (str) -> Union[str, None]
|
|
cf_path = os.path.join(os.path.expanduser("~"), cf)
|
|
try:
|
|
os.stat(cf_path)
|
|
except OSError:
|
|
return None
|
|
else:
|
|
return cf_path
|
|
|
|
|
|
def _read_config_file(cf, _globals=globals(), _locals=locals(),
|
|
interactive=True):
|
|
# type: (str, Dict[str, Any], Dict[str, Any], bool) -> None
|
|
"""Read a config file: execute a python file while loading scapy, that
|
|
may contain some pre-configured values.
|
|
|
|
If _globals or _locals are specified, they will be updated with
|
|
the loaded vars. This allows an external program to use the
|
|
function. Otherwise, vars are only available from inside the scapy
|
|
console.
|
|
|
|
params:
|
|
- _globals: the globals() vars
|
|
- _locals: the locals() vars
|
|
- interactive: specified whether or not errors should be printed
|
|
using the scapy console or raised.
|
|
|
|
ex, content of a config.py file:
|
|
'conf.verb = 42\n'
|
|
Manual loading:
|
|
>>> _read_config_file("./config.py"))
|
|
>>> conf.verb
|
|
42
|
|
|
|
"""
|
|
log_loading.debug("Loading config file [%s]", cf)
|
|
try:
|
|
with open(cf) as cfgf:
|
|
exec(
|
|
compile(cfgf.read(), cf, 'exec'),
|
|
_globals, _locals
|
|
)
|
|
except IOError as e:
|
|
if interactive:
|
|
raise
|
|
log_loading.warning("Cannot read config file [%s] [%s]", cf, e)
|
|
except Exception:
|
|
if interactive:
|
|
raise
|
|
log_loading.exception("Error during evaluation of config file [%s]",
|
|
cf)
|
|
|
|
|
|
def _validate_local(x):
|
|
# type: (str) -> bool
|
|
"""Returns whether or not a variable should be imported.
|
|
Will return False for any default modules (sys), or if
|
|
they are detected as private vars (starting with a _)"""
|
|
global IGNORED
|
|
return x[0] != "_" and x not in IGNORED
|
|
|
|
|
|
DEFAULT_PRESTART_FILE = _probe_config_file(".scapy_prestart.py")
|
|
DEFAULT_STARTUP_FILE = _probe_config_file(".scapy_startup.py")
|
|
|
|
|
|
def _usage():
|
|
# type: () -> None
|
|
print(
|
|
"Usage: scapy.py [-s sessionfile] [-c new_startup_file] "
|
|
"[-p new_prestart_file] [-C] [-P] [-H]\n"
|
|
"Args:\n"
|
|
"\t-H: header-less start\n"
|
|
"\t-C: do not read startup file\n"
|
|
"\t-P: do not read pre-startup file\n"
|
|
)
|
|
sys.exit(0)
|
|
|
|
|
|
######################
|
|
# Extension system #
|
|
######################
|
|
|
|
|
|
def _load(module, globals_dict=None, symb_list=None):
|
|
# type: (str, Optional[Dict[str, Any]], Optional[List[str]]) -> None
|
|
"""Loads a Python module to make variables, objects and functions
|
|
available globally.
|
|
|
|
The idea is to load the module using importlib, then copy the
|
|
symbols to the global symbol table.
|
|
|
|
"""
|
|
if globals_dict is None:
|
|
globals_dict = six.moves.builtins.__dict__
|
|
try:
|
|
mod = importlib.import_module(module)
|
|
if '__all__' in mod.__dict__:
|
|
# import listed symbols
|
|
for name in mod.__dict__['__all__']:
|
|
if symb_list is not None:
|
|
symb_list.append(name)
|
|
globals_dict[name] = mod.__dict__[name]
|
|
else:
|
|
# only import non-private symbols
|
|
for name, sym in six.iteritems(mod.__dict__):
|
|
if _validate_local(name):
|
|
if symb_list is not None:
|
|
symb_list.append(name)
|
|
globals_dict[name] = sym
|
|
except Exception:
|
|
log_interactive.error("Loading module %s", module, exc_info=True)
|
|
|
|
|
|
def load_module(name, globals_dict=None, symb_list=None):
|
|
# type: (str, Optional[Dict[str, Any]], Optional[List[str]]) -> None
|
|
"""Loads a Scapy module to make variables, objects and functions
|
|
available globally.
|
|
|
|
"""
|
|
_load("scapy.modules." + name,
|
|
globals_dict=globals_dict, symb_list=symb_list)
|
|
|
|
|
|
def load_layer(name, globals_dict=None, symb_list=None):
|
|
# type: (str, Optional[Dict[str, Any]], Optional[List[str]]) -> None
|
|
"""Loads a Scapy layer module to make variables, objects and functions
|
|
available globally.
|
|
|
|
"""
|
|
_load("scapy.layers." + LAYER_ALIASES.get(name, name),
|
|
globals_dict=globals_dict, symb_list=symb_list)
|
|
|
|
|
|
def load_contrib(name, globals_dict=None, symb_list=None):
|
|
# type: (str, Optional[Dict[str, Any]], Optional[List[str]]) -> None
|
|
"""Loads a Scapy contrib module to make variables, objects and
|
|
functions available globally.
|
|
|
|
If no contrib module can be found with the given name, try to find
|
|
a layer module, since a contrib module may become a layer module.
|
|
|
|
"""
|
|
try:
|
|
importlib.import_module("scapy.contrib." + name)
|
|
_load("scapy.contrib." + name,
|
|
globals_dict=globals_dict, symb_list=symb_list)
|
|
except ImportError as e:
|
|
# if layer not found in contrib, try in layers
|
|
try:
|
|
load_layer(name,
|
|
globals_dict=globals_dict, symb_list=symb_list)
|
|
except ImportError:
|
|
raise e # Let's raise the original error to avoid confusion
|
|
|
|
|
|
def list_contrib(name=None, # type: Optional[str]
|
|
ret=False, # type: bool
|
|
_debug=False # type: bool
|
|
):
|
|
# type: (...) -> Optional[List[Dict[str, Union[str, None]]]]
|
|
"""Show the list of all existing contribs.
|
|
|
|
:param name: filter to search the contribs
|
|
:param ret: whether the function should return a dict instead of
|
|
printing it
|
|
:returns: None or a dictionary containing the results if ret=True
|
|
"""
|
|
# _debug: checks that all contrib modules have correctly defined:
|
|
# # scapy.contrib.description = [...]
|
|
# # scapy.contrib.status = [...]
|
|
# # scapy.contrib.name = [...] (optional)
|
|
# or set the flag:
|
|
# # scapy.contrib.description = skip
|
|
# to skip the file
|
|
if name is None:
|
|
name = "*.py"
|
|
elif "*" not in name and "?" not in name and not name.endswith(".py"):
|
|
name += ".py"
|
|
results = [] # type: List[Dict[str, Union[str, None]]]
|
|
dir_path = os.path.join(os.path.dirname(__file__), "contrib")
|
|
if sys.version_info >= (3, 5):
|
|
name = os.path.join(dir_path, "**", name)
|
|
iterator = glob.iglob(name, recursive=True)
|
|
else:
|
|
name = os.path.join(dir_path, name)
|
|
iterator = glob.iglob(name)
|
|
for f in iterator:
|
|
mod = f.replace(os.path.sep, ".").partition("contrib.")[2]
|
|
if mod.startswith("__"):
|
|
continue
|
|
if mod.endswith(".py"):
|
|
mod = mod[:-3]
|
|
desc = {"description": None, "status": None, "name": mod}
|
|
with io.open(f, errors="replace") as fd:
|
|
for l in fd:
|
|
if l[0] != "#":
|
|
continue
|
|
p = l.find("scapy.contrib.")
|
|
if p >= 0:
|
|
p += 14
|
|
q = l.find("=", p)
|
|
key = l[p:q].strip()
|
|
value = l[q + 1:].strip()
|
|
desc[key] = value
|
|
if desc["status"] == "skip":
|
|
break
|
|
if desc["description"] and desc["status"]:
|
|
results.append(desc)
|
|
break
|
|
if _debug:
|
|
if desc["status"] == "skip":
|
|
pass
|
|
elif not desc["description"] or not desc["status"]:
|
|
raise Scapy_Exception("Module %s is missing its "
|
|
"contrib infos !" % mod)
|
|
results.sort(key=lambda x: x["name"])
|
|
if ret:
|
|
return results
|
|
else:
|
|
for desc in results:
|
|
print("%(name)-20s: %(description)-40s status=%(status)s" % desc)
|
|
return None
|
|
|
|
|
|
##############################
|
|
# Session saving/restoring #
|
|
##############################
|
|
|
|
def update_ipython_session(session):
|
|
# type: (Dict[str, Any]) -> None
|
|
"""Updates IPython session with a custom one"""
|
|
try:
|
|
from IPython import get_ipython
|
|
get_ipython().user_ns.update(session)
|
|
except Exception:
|
|
pass
|
|
|
|
|
|
def save_session(fname="", session=None, pickleProto=-1):
|
|
# type: (str, Optional[Dict[str, Any]], int) -> None
|
|
"""Save current Scapy session to the file specified in the fname arg.
|
|
|
|
params:
|
|
- fname: file to save the scapy session in
|
|
- session: scapy session to use. If None, the console one will be used
|
|
- pickleProto: pickle proto version (default: -1 = latest)"""
|
|
from scapy import utils
|
|
from scapy.config import conf, ConfClass
|
|
if not fname:
|
|
fname = conf.session
|
|
if not fname:
|
|
conf.session = fname = utils.get_temp_file(keep=True)
|
|
log_interactive.info("Use [%s] as session file" % fname)
|
|
|
|
if not session:
|
|
try:
|
|
from IPython import get_ipython
|
|
session = get_ipython().user_ns
|
|
except Exception:
|
|
session = six.moves.builtins.__dict__["scapy_session"]
|
|
|
|
to_be_saved = cast(Dict[str, Any], session).copy()
|
|
if "__builtins__" in to_be_saved:
|
|
del(to_be_saved["__builtins__"])
|
|
|
|
for k in list(to_be_saved):
|
|
i = to_be_saved[k]
|
|
if hasattr(i, "__module__") and (k[0] == "_" or
|
|
i.__module__.startswith("IPython")):
|
|
del(to_be_saved[k])
|
|
if isinstance(i, ConfClass):
|
|
del(to_be_saved[k])
|
|
elif isinstance(i, (type, type, types.ModuleType)):
|
|
if k[0] != "_":
|
|
log_interactive.error("[%s] (%s) can't be saved.", k,
|
|
type(to_be_saved[k]))
|
|
del(to_be_saved[k])
|
|
|
|
try:
|
|
os.rename(fname, fname + ".bak")
|
|
except OSError:
|
|
pass
|
|
|
|
f = gzip.open(fname, "wb")
|
|
six.moves.cPickle.dump(to_be_saved, f, pickleProto)
|
|
f.close()
|
|
|
|
|
|
def load_session(fname=None):
|
|
# type: (Optional[Union[str, None]]) -> None
|
|
"""Load current Scapy session from the file specified in the fname arg.
|
|
This will erase any existing session.
|
|
|
|
params:
|
|
- fname: file to load the scapy session from"""
|
|
from scapy.config import conf
|
|
if fname is None:
|
|
fname = conf.session
|
|
try:
|
|
s = six.moves.cPickle.load(gzip.open(fname, "rb"))
|
|
except IOError:
|
|
try:
|
|
s = six.moves.cPickle.load(open(fname, "rb"))
|
|
except IOError:
|
|
# Raise "No such file exception"
|
|
raise
|
|
|
|
scapy_session = six.moves.builtins.__dict__["scapy_session"]
|
|
scapy_session.clear()
|
|
scapy_session.update(s)
|
|
update_ipython_session(scapy_session)
|
|
|
|
log_loading.info("Loaded session [%s]" % fname)
|
|
|
|
|
|
def update_session(fname=None):
|
|
# type: (Optional[Union[str, None]]) -> None
|
|
"""Update current Scapy session from the file specified in the fname arg.
|
|
|
|
params:
|
|
- fname: file to load the scapy session from"""
|
|
from scapy.config import conf
|
|
if fname is None:
|
|
fname = conf.session
|
|
try:
|
|
s = six.moves.cPickle.load(gzip.open(fname, "rb"))
|
|
except IOError:
|
|
s = six.moves.cPickle.load(open(fname, "rb"))
|
|
scapy_session = six.moves.builtins.__dict__["scapy_session"]
|
|
scapy_session.update(s)
|
|
update_ipython_session(scapy_session)
|
|
|
|
|
|
def init_session(session_name, # type: Optional[Union[str, None]]
|
|
mydict=None # type: Optional[Union[Dict[str, Any], None]]
|
|
):
|
|
# type: (...) -> Tuple[Dict[str, Any], List[str]]
|
|
from scapy.config import conf
|
|
SESSION = {} # type: Dict[str, Any]
|
|
GLOBKEYS = [] # type: List[str]
|
|
|
|
scapy_builtins = {k: v
|
|
for k, v in six.iteritems(
|
|
importlib.import_module(".all", "scapy").__dict__
|
|
)
|
|
if _validate_local(k)}
|
|
six.moves.builtins.__dict__.update(scapy_builtins)
|
|
GLOBKEYS.extend(scapy_builtins)
|
|
GLOBKEYS.append("scapy_session")
|
|
|
|
if session_name:
|
|
try:
|
|
os.stat(session_name)
|
|
except OSError:
|
|
log_loading.info("New session [%s]" % session_name)
|
|
else:
|
|
try:
|
|
try:
|
|
SESSION = six.moves.cPickle.load(gzip.open(session_name,
|
|
"rb"))
|
|
except IOError:
|
|
SESSION = six.moves.cPickle.load(open(session_name, "rb"))
|
|
log_loading.info("Using session [%s]" % session_name)
|
|
except ValueError:
|
|
msg = "Error opening Python3 pickled session on Python2 [%s]"
|
|
log_loading.error(msg % session_name)
|
|
except EOFError:
|
|
log_loading.error("Error opening session [%s]" % session_name)
|
|
except AttributeError:
|
|
log_loading.error("Error opening session [%s]. "
|
|
"Attribute missing" % session_name)
|
|
|
|
if SESSION:
|
|
if "conf" in SESSION:
|
|
conf.configure(SESSION["conf"])
|
|
conf.session = session_name
|
|
SESSION["conf"] = conf
|
|
else:
|
|
conf.session = session_name
|
|
else:
|
|
conf.session = session_name
|
|
SESSION = {"conf": conf}
|
|
else:
|
|
SESSION = {"conf": conf}
|
|
|
|
six.moves.builtins.__dict__["scapy_session"] = SESSION
|
|
|
|
if mydict is not None:
|
|
six.moves.builtins.__dict__["scapy_session"].update(mydict)
|
|
update_ipython_session(mydict)
|
|
GLOBKEYS.extend(mydict)
|
|
return SESSION, GLOBKEYS
|
|
|
|
################
|
|
# Main #
|
|
################
|
|
|
|
|
|
def _prepare_quote(quote, author, max_len=78):
|
|
# type: (str, str, int) -> List[str]
|
|
"""This function processes a quote and returns a string that is ready
|
|
to be used in the fancy prompt.
|
|
|
|
"""
|
|
_quote = quote.split(' ')
|
|
max_len -= 6
|
|
lines = []
|
|
cur_line = [] # type: List[str]
|
|
|
|
def _len(line):
|
|
# type: (List[str]) -> int
|
|
return sum(len(elt) for elt in line) + len(line) - 1
|
|
while _quote:
|
|
if not cur_line or (_len(cur_line) + len(_quote[0]) - 1 <= max_len):
|
|
cur_line.append(_quote.pop(0))
|
|
continue
|
|
lines.append(' | %s' % ' '.join(cur_line))
|
|
cur_line = []
|
|
if cur_line:
|
|
lines.append(' | %s' % ' '.join(cur_line))
|
|
cur_line = []
|
|
lines.append(' | %s-- %s' % (" " * (max_len - len(author) - 5), author))
|
|
return lines
|
|
|
|
|
|
def interact(mydict=None, argv=None, mybanner=None, loglevel=logging.INFO):
|
|
# type: (Optional[Any], Optional[Any], Optional[Any], int) -> None
|
|
"""Starts Scapy's console."""
|
|
try:
|
|
if WINDOWS:
|
|
# colorama is bundled within IPython.
|
|
# logging.StreamHandler will be overwritten when called,
|
|
# We can't wait for IPython to call it
|
|
import colorama
|
|
colorama.init()
|
|
# Success
|
|
console_handler = logging.StreamHandler()
|
|
console_handler.setFormatter(
|
|
ScapyColoredFormatter(
|
|
"%(levelname)s: %(message)s",
|
|
)
|
|
)
|
|
except ImportError:
|
|
# Failure: ignore colors in the logger
|
|
console_handler = logging.StreamHandler()
|
|
console_handler.setFormatter(
|
|
logging.Formatter(
|
|
"%(levelname)s: %(message)s",
|
|
)
|
|
)
|
|
log_scapy.addHandler(console_handler)
|
|
|
|
# We're in interactive mode, let's throw the DeprecationWarnings
|
|
warnings.simplefilter("always")
|
|
|
|
from scapy.config import conf
|
|
conf.interactive = True
|
|
conf.color_theme = DefaultTheme()
|
|
if loglevel is not None:
|
|
conf.logLevel = loglevel
|
|
|
|
STARTUP_FILE = DEFAULT_STARTUP_FILE
|
|
PRESTART_FILE = DEFAULT_PRESTART_FILE
|
|
|
|
session_name = None
|
|
|
|
if argv is None:
|
|
argv = sys.argv
|
|
|
|
try:
|
|
opts = getopt.getopt(argv[1:], "hs:Cc:Pp:d:H")
|
|
for opt, parm in opts[0]:
|
|
if opt == "-h":
|
|
_usage()
|
|
elif opt == "-H":
|
|
conf.fancy_prompt = False
|
|
conf.verb = 30
|
|
elif opt == "-s":
|
|
session_name = parm
|
|
elif opt == "-c":
|
|
STARTUP_FILE = parm
|
|
elif opt == "-C":
|
|
STARTUP_FILE = None
|
|
elif opt == "-p":
|
|
PRESTART_FILE = parm
|
|
elif opt == "-P":
|
|
PRESTART_FILE = None
|
|
elif opt == "-d":
|
|
conf.logLevel = max(1, conf.logLevel - 10)
|
|
|
|
if len(opts[1]) > 0:
|
|
raise getopt.GetoptError(
|
|
"Too many parameters : [%s]" % " ".join(opts[1])
|
|
)
|
|
|
|
except getopt.GetoptError as msg:
|
|
log_loading.error(msg)
|
|
sys.exit(1)
|
|
|
|
# Reset sys.argv, otherwise IPython thinks it is for him
|
|
sys.argv = sys.argv[:1]
|
|
|
|
SESSION, GLOBKEYS = init_session(session_name, mydict)
|
|
|
|
if STARTUP_FILE:
|
|
_read_config_file(STARTUP_FILE, interactive=True)
|
|
if PRESTART_FILE:
|
|
_read_config_file(PRESTART_FILE, interactive=True)
|
|
|
|
if not conf.interactive_shell or conf.interactive_shell.lower() in [
|
|
"ipython", "auto"
|
|
]:
|
|
try:
|
|
import IPython
|
|
from IPython import start_ipython
|
|
except ImportError:
|
|
log_loading.warning(
|
|
"IPython not available. Using standard Python shell "
|
|
"instead.\nAutoCompletion, History are disabled."
|
|
)
|
|
if WINDOWS:
|
|
log_loading.warning(
|
|
"On Windows, colors are also disabled"
|
|
)
|
|
conf.color_theme = BlackAndWhite()
|
|
IPYTHON = False
|
|
else:
|
|
IPYTHON = True
|
|
else:
|
|
IPYTHON = False
|
|
|
|
if conf.fancy_prompt:
|
|
from scapy.utils import get_terminal_width
|
|
mini_banner = (get_terminal_width() or 84) <= 75
|
|
|
|
the_logo = [
|
|
" ",
|
|
" aSPY//YASa ",
|
|
" apyyyyCY//////////YCa ",
|
|
" sY//////YSpcs scpCY//Pp ",
|
|
" ayp ayyyyyyySCP//Pp syY//C ",
|
|
" AYAsAYYYYYYYY///Ps cY//S",
|
|
" pCCCCY//p cSSps y//Y",
|
|
" SPPPP///a pP///AC//Y",
|
|
" A//A cyP////C",
|
|
" p///Ac sC///a",
|
|
" P////YCpc A//A",
|
|
" scccccp///pSP///p p//Y",
|
|
" sY/////////y caa S//P",
|
|
" cayCyayP//Ya pY/Ya",
|
|
" sY/PsY////YCc aC//Yp ",
|
|
" sc sccaCY//PCypaapyCP//YSs ",
|
|
" spCPY//////YPSps ",
|
|
" ccaacs ",
|
|
" ",
|
|
]
|
|
|
|
# Used on mini screens
|
|
the_logo_mini = [
|
|
" .SYPACCCSASYY ",
|
|
"P /SCS/CCS ACS",
|
|
" /A AC",
|
|
" A/PS /SPPS",
|
|
" YP (SC",
|
|
" SPS/A. SC",
|
|
" Y/PACC PP",
|
|
" PY*AYC CAA",
|
|
" YYCY//SCYP ",
|
|
]
|
|
|
|
the_banner = [
|
|
"",
|
|
"",
|
|
" |",
|
|
" | Welcome to Scapy",
|
|
" | Version %s" % conf.version,
|
|
" |",
|
|
" | https://github.com/secdev/scapy",
|
|
" |",
|
|
" | Have fun!",
|
|
" |",
|
|
]
|
|
|
|
if mini_banner:
|
|
the_logo = the_logo_mini
|
|
the_banner = [x[2:] for x in the_banner[3:-1]]
|
|
the_banner = [""] + the_banner + [""]
|
|
else:
|
|
quote, author = choice(QUOTES)
|
|
the_banner.extend(_prepare_quote(quote, author, max_len=39))
|
|
the_banner.append(" |")
|
|
banner_text = "\n".join(
|
|
logo + banner for logo, banner in six.moves.zip_longest(
|
|
(conf.color_theme.logo(line) for line in the_logo),
|
|
(conf.color_theme.success(line) for line in the_banner),
|
|
fillvalue=""
|
|
)
|
|
)
|
|
else:
|
|
banner_text = "Welcome to Scapy (%s)" % conf.version
|
|
if mybanner is not None:
|
|
banner_text += "\n"
|
|
banner_text += mybanner
|
|
|
|
if IPYTHON:
|
|
banner = banner_text + " using IPython %s\n" % IPython.__version__
|
|
try:
|
|
from traitlets.config.loader import Config
|
|
except ImportError:
|
|
log_loading.warning(
|
|
"traitlets not available. Some Scapy shell features won't be "
|
|
"available."
|
|
)
|
|
try:
|
|
start_ipython(
|
|
display_banner=False,
|
|
user_ns=SESSION,
|
|
exec_lines=["print(\"\"\"" + banner + "\"\"\")"]
|
|
)
|
|
except Exception:
|
|
code.interact(banner=banner_text, local=SESSION)
|
|
else:
|
|
cfg = Config()
|
|
try:
|
|
from IPython import get_ipython
|
|
if not get_ipython():
|
|
raise ImportError
|
|
except ImportError:
|
|
# Set "classic" prompt style when launched from
|
|
# run_scapy(.bat) files Register and apply scapy
|
|
# color+prompt style
|
|
apply_ipython_style(shell=cfg.TerminalInteractiveShell)
|
|
cfg.TerminalInteractiveShell.confirm_exit = False
|
|
cfg.TerminalInteractiveShell.separate_in = u''
|
|
if int(IPython.__version__[0]) >= 6:
|
|
cfg.TerminalInteractiveShell.term_title_format = ("Scapy v%s" %
|
|
conf.version)
|
|
# As of IPython 6-7, the jedi completion module is a dumpster
|
|
# of fire that should be scrapped never to be seen again.
|
|
cfg.Completer.use_jedi = False
|
|
else:
|
|
cfg.TerminalInteractiveShell.term_title = False
|
|
cfg.HistoryAccessor.hist_file = conf.histfile
|
|
cfg.InteractiveShell.banner1 = banner
|
|
# configuration can thus be specified here.
|
|
try:
|
|
start_ipython(config=cfg, user_ns=SESSION)
|
|
except (AttributeError, TypeError):
|
|
code.interact(banner=banner_text, local=SESSION)
|
|
else:
|
|
code.interact(banner=banner_text, local=SESSION)
|
|
|
|
if conf.session:
|
|
save_session(conf.session, SESSION)
|
|
|
|
for k in GLOBKEYS:
|
|
try:
|
|
del(six.moves.builtins.__dict__[k])
|
|
except Exception:
|
|
pass
|
|
|
|
|
|
if __name__ == "__main__":
|
|
interact()
|