示例#1
0
    def setUp(self):
        """ Setup a Manager and Monitor object

            The Katana Unit Tests can override this method, but must call the
            parent. You can use this to create special temporary target files,
            start a web server, or anything else needed to evaluate your target.
        """

        # This is a nasty hack
        os.system("rm -rf ./results 2>&1 >/dev/null")

        # Create the monitor and set the flag format
        self.monitor = Monitor()
        self.manager = Manager(monitor=self.monitor)
        self.manager["manager"]["flag-format"] = self.FLAG_FORMAT
        self.manager["manager"]["auto"] = "yes"

        # Ignore annoying resource warnings
        warnings.simplefilter("ignore", ResourceWarning)
示例#2
0
def main():

    # Setup basic logging
    logging.basicConfig(level=logging.INFO)

    # Build the argument parse object
    parser = argparse.ArgumentParser(
        prog="katana",
        description=
        "Automatically identify and solve basic Capture the Flag challenges",
        add_help=False,
    )

    # Parse config option first
    parser.add_argument("--config",
                        "-c",
                        help="configuration file",
                        default=None)
    args, remaining_args = parser.parse_known_args()

    # Build our katana monitor
    monitor = ReplMonitor()

    # Create our katana manager
    manager = Manager(monitor=monitor, config_path=args.config)

    # Build final parser
    parser = argparse.ArgumentParser(
        prog="katana",
        description=
        "Automatically identify and solve basic Capture the Flag challenges",
    )

    # Add global arguments
    parser.add_argument("--config",
                        "-c",
                        help="configuration file",
                        default=None)
    parser.add_argument(
        "--manager",
        "-m",
        default=None,
        help=
        "comma separated manager configurations (e.g. flag-format=FLAG{.*?})",
    )
    parser.add_argument(
        "--timeout",
        "-t",
        type=float,
        help="timeout for all unit evaluations in seconds",
    )
    parser.add_argument("targets",
                        nargs="*",
                        default=[],
                        help="targets to evaluate")
    parser.add_argument("--auto",
                        "-a",
                        help="shorthand for `-m auto=True`",
                        action="store_true")
    parser.add_argument(
        "--unit",
        "-u",
        help="explicitly run a unit on target",
        action="append",
        default=[],
    )
    parser.add_argument(
        "--exclude",
        "-e",
        help="exclude a unit from running",
        action="append",
        default=[],
    )
    parser.add_argument("--flag", "-f", help="set the flag format")
    parser.add_argument(
        "--force",
        action="store_true",
        help="Force execution even if results directory exists",
    )
    parser.add_argument(
        "--imagegui",
        "-i",
        action="store_true",
        help="Display images as katana finds them",
        default=False,
    )

    # Add options for all the unit specific configurations
    for unit in manager.finder.units:
        parser.add_argument(
            "--" + unit.get_name(),
            default=None,
            help="comma separated unit configuration",
        )

    # Parse arguments
    args = parser.parse_args(remaining_args)

    # Load configuration file
    if args.config is not None:
        result = manager.read(args.config)
        if len(result) == 0:
            logging.error(" {0}: no such file or directory".format(
                args.config))
            sys.exit(1)

    # Apply configurations
    if args.manager is not None:
        params = args.manager.split(",")
        for param in params:
            name, value = param.split("=")
            manager["manager"][name] = value

    # Apply auto shorthand
    if args.auto is not None:
        manager["manager"]["auto"] = "yes"

    # Apply flag format
    if args.flag is not None:
        manager["manager"]["flag-format"] = args.flag

    # Apply requested units
    units = [u
             for u in manager["manager"]["units"].split(",") if u] + args.unit
    manager["manager"]["units"] = ",".join(units)

    # Apply excluded units
    excluded = manager["manager"]["exclude"].split(",") + args.exclude
    manager["manager"]["exclude"] = ",".join(excluded)

    # Enable results removal if requested
    if args.force:
        manager["manager"]["force"] = "yes"

    # Determine whether to display images or not
    if args.imagegui:
        manager["manager"]["imagegui"] = "yes"
    else:
        manager["manager"]["imagegui"] = "no"

    # Apply unit configurations
    args_dict = vars(args)  # We need this because configs have '.'
    for unit in manager.finder.units:
        # Ignore if nothing was specified
        if args_dict[unit.get_name()] is None:
            continue

        # Initialize the unit if needed
        if unit.get_name() not in manager:
            manager[unit.get_name()] = {}

        # Parse params
        params = args_dict[unit.get_name()].split(",")
        for param in params:
            name, value = param.split("=")
            manager[unit.get_name()][name] = value

    # Queue the specified targets
    for target in args.targets:

        manager.queue_target(target, background=True)

    # Build the REPL and execute it
    sys.argv = sys.argv[:1]
    repl = Repl(manager)

    # Warn the user about missing binary dependencies
    for unit, dep in manager.finder.missing_deps:
        repl.pwarning(f"{unit}: missing binary dependency: {dep}")

    sys.exit(repl.cmdloop())
示例#3
0
from katana.monitor import Monitor

# A custom monitor which will receive notifications about units
# The default monitor prints notifications of flags with logging as well but
# this allows you to do fancier status updates if you are building an interface
# of some kind
class MyMonitor(Monitor):
    def on_flag(self, manager: Manager, unit: Unit, flag: str):
        logging.info("found a flag: {0}".format(flag))


# Create your monitor object
monitor = MyMonitor()

# Create your Manager with your monitor attached
manager = Manager(monitor, config_path="./examples/example.ini")

# Set some custom configuration parameters
manager["auto"] = True
manager["outdir"] = "./example-results-{0}".format(time.strftime("%Y%m%d-%H%M%S"))
manager["exclude"] = ["crypto"]
manager["flag-format"] = r"FLAG{.*?}"

# Optionally, manually register unit classes
# manager.finder.register(CustomChallengeUnit)
# Or load units automatically from a directory
# manager.finder.find('./customunits', 'customunits.')

# Start the manager (empty queue at the moment)
manager.start()
示例#4
0
class KatanaTest(TestCase):

    FLAG_FORMAT = "FLAG{.*?}"

    def setUp(self):
        """ Setup a Manager and Monitor object

            The Katana Unit Tests can override this method, but must call the
            parent. You can use this to create special temporary target files,
            start a web server, or anything else needed to evaluate your target.
        """

        # This is a nasty hack
        os.system("rm -rf ./results 2>&1 >/dev/null")

        # Create the monitor and set the flag format
        self.monitor = Monitor()
        self.manager = Manager(monitor=self.monitor)
        self.manager["manager"]["flag-format"] = self.FLAG_FORMAT
        self.manager["manager"]["auto"] = "yes"

        # Ignore annoying resource warnings
        warnings.simplefilter("ignore", ResourceWarning)

    def tearDown(self):
        """ Tear down any artifacts from the last run

            The Katana Unit Tests can override this method, but must call the
            parent. You can use this method to clean up any extra temporary files
            that may have been created for the target or any threads/services 
            started for unit testing.
        """

        # Tear down our object tree
        del self.monitor
        del self.manager

        # This is a nasty hack
        os.system("rm -rf ./results 2>&1 >/dev/null")

    def katana_test(
        self, config: str, target: str, correct_flag: str, timeout: float = 10
    ):
        """ Perform a test with the given configuration, target and flag

        :param config: Katana configuration file
        :type config: str
        :param target: The target for this katana test (url, filename, raw data, etc)
        :type target: str
        :param correct_flag: The correct flag which katana should find.
        :type correct_flag: str
        :param timeout: The timeout in seconds for this test, defaults to 10
        :type timeout: float, optional

        """

        if isinstance(correct_flag, bytes):
            correct_flag = correct_flag.decode("utf-8")

        # Load given configuration
        self.manager.read_file(io.StringIO(config))

        # Queue the target and begin processing
        self.manager.queue_target(target)
        self.manager.start()

        # Ensure wait for completion. Error if we time out
        self.assertTrue(self.manager.join(timeout=timeout), "manager timed out")

        # Ensure we have at least 1 flag
        self.assertGreater(len(self.monitor.flags), 0, "no flags found")

        # Ensure the flag matches expected output
        for flag in self.monitor.flags:
            if flag[1] == correct_flag:
                return

        # Fail otherwise
        self.fail(f"correct flag not found (found: {self.monitor.flags})")
示例#5
0
#!/usr/bin/env python3
import logging

from katana.manager import Manager
from katana.monitor import LoggingMonitor

# Configure basic logging
logging.basicConfig(level=logging.INFO)

# Create a basic monitor which will log results
monitor = LoggingMonitor()

# Create a manager with a default unit finder and default monitor
# and load all default units. The default monitor will using the python logging
# module to log important events to the console (or log file)
manager = Manager(monitor=monitor, config_path="./examples/example.ini")

# Begin the background work monitor
manager.start()

# Queue the target
manager.queue_target("./tests/qrcode.png")

# Wait for completion (with a 10-second timeout)
if not manager.join(timeout=10):
    logging.warning("evaluation timed out")