Esempio n. 1
0
    def search(self, ctext: Any) -> List[SearchLevel]:
        deadline = (datetime.now() + self._config().objs["timeout"]
                    if self._config().timeout is not None else datetime.max)

        success, expand_res = self.expand(
            [SearchLevel(name="input", result=CrackResult(value=ctext))])
        if success:
            return expand_res

        nodes = set(expand_res)

        while datetime.now() < deadline:
            # logger.trace(f"Have node tree {nodes}")

            if len(nodes) == 0:
                raise LookupError("Could not find any solutions")

            best_node = self.findBestNode(nodes)
            nodes.remove(best_node)
            success, eval_res = self.evaluate(best_node)
            if success:
                # logger.trace(f"Success with node {best_node}")
                return eval_res
            nodes.update(eval_res)

        raise TimeoutError("Search ran out of time")
Esempio n. 2
0
    def cracker(config: Config, edge_template: "Edge", result: CrackResult) -> "Node":
        if not config.cache.mark_ctext(result.value):
            raise DuplicateNode()

        checker: Checker = config.objs["checker"]
        # Edges do not directly contain containers, so this is fine
        edge = copy(edge_template)
        ret = Node(
            parent=edge,
            level=SearchLevel(name=type(edge.route).__name__.lower(), result=result),
            depth=edge.source.depth + 1,
        )
        edge.dest = ret
        check_res = checker(result.value)
        if check_res is not None:
            raise AuSearchSuccessful(target=ret, info=check_res)
        return ret
Esempio n. 3
0
    def decoding(config: Config, route: Union[Cracker, Decoder], result: Any,
                 source: "Node") -> "Node":
        if not config.cache.mark_ctext(result):
            raise DuplicateNode()

        checker: Checker = config.objs["checker"]
        ret = Node(
            parent=None,
            level=SearchLevel(name=type(route).__name__.lower(),
                              result=CrackResult(value=result)),
            depth=source.depth + 1,
        )
        edge = Edge(source=source, route=route, dest=ret)
        ret.parent = edge
        check_res = checker(result)
        if check_res is not None:
            raise AuSearchSuccessful(target=ret, info=check_res)
        return ret
Esempio n. 4
0
    def evaluate(self,
                 node: Node) -> (bool, Union[List[SearchLevel], List[Node]]):
        # logger.debug(f"Evaluating {node}")

        res = node.cracker.attemptCrack(node.parents[-1].result.value)
        # Detect if we succeeded, and if deduplication is needed
        logger.trace(f"Got {len(res)} results")

        ret = []
        for i in res:
            success, res = self.expand(node.parents + [
                SearchLevel(name=type(node.cracker).__name__.lower(), result=i)
            ])
            if success:
                return True, res
            ret.extend(res)

        return False, ret
Esempio n. 5
0
    def handleDecodings(
        self, target: Any
    ) -> (bool, Union[Tuple[SearchLevel, str], List[SearchLevel]]):
        """
            If there exists a decoding that the checker returns true on, returns (True, result).
            Otherwise, returns (False, names and successful decodings)

            The CrackResult object should only have the value field filled in

            MUST NOT recurse into decodings! evaluate does that for you!
        """
        # This tag is necessary, as we could have a list as a decoding target, which would then screw over type checks
        ret = []

        decoders = []

        for decoder_type, decoder_class in registry[Decoder][type(
                target)].items():
            for decoder in decoder_class:
                decoders.append(DecoderComparer(decoder))
        # Fun fact:
        #     with Python's glorious lists, inserting n elements into the right position (with bisect) is O(n^2)
        decoders.sort(reverse=True)

        for decoder_cmp in decoders:
            logger.trace(f"Inspecting {decoder_cmp}")
            res = self._config()(decoder_cmp.value).decode(target)
            if res is None:
                continue
            level = SearchLevel(
                name=decoder_cmp.value.__name__.lower(),
                result=CrackResult(value=res),
            )
            if type(res) == self._final_type:
                check_res = self._checker(res)
                if check_res is not None:
                    return True, (level, check_res)
            ret.append(level)
        return False, ret