예제 #1
0
def query_report(args):
    """
    all file type 
    """

    # default for vt
    resource = args.resource
    name = args.name  # vendor's name : VT threatbook
    bsize = 65536
    buff = None
    if input_file is not None and os.path.isfile(resource):
        sha256 = hashlib.sha256()
        while True:
            with open(resource, 'rb') as fp:
                buff = fp.read(bsize)
                if buff is None:
                    break
                sha256.update(buff)

        resource = sha256.hexdigest()

    if resource is None or resource == '':
        echo("error",
             "query_report resouroce must be empty or None",
             color="red")
        return
    if name is not None and name == 'threatbook':
        ThreatbookSandbox(resource).analysis()
        return
    # query all online
    online_sandboxies = [ThreatbookSandbox(resource), VT(resource)]
    for sb in online_sandboxies:
        sb.analysis()
예제 #2
0
def extract_android_manifest_info(args):

    input_file = args.manifest
    entry = args.entry
    acs = args.activities
    rs = args.receivers
    ss = args.services
    ps = args.providers
    both = args.both
    exported = args.exported
    pm = args.permission

    if not os.path.isfile(input_file):
        echo("error", "need apk or AndroidManifest.xml as input file!!", 'red')
        return
    elif input_file.endswith('.xml'):
        axml = AndroidManifestXmlParser(input_file)
        axml.show_manifest(acs, rs, ss, ps, entry, both, exported, pm)
    elif input_file.endswith('apk') or input_file.endswith('bin'):
        # for some reason,we can alse  check sample.bin
        apk_parser = ApkPaser(input_file)
        if apk_parser.ok():
            apk_parser.show_manifest(acs, rs, ss, ps, entry, both, exported,
                                     pm)
            # echo("info", "\n"+str(apk_parser.mainifest_info()))
    else:
        echo("error", "unknow {} filtype ".format(input_file), 'red')
예제 #3
0
 def __analyzer_string(self):
     """
     need pattern or rule file
     """
     for rule in self.rules:
         ss = self.apk_parser.all_strings(rule['patters'])
         if len(ss) > 0:
             echo("info", "rule: {}  {} ".format(rule['name'],
                                                 self.filename))
             return True
     return False
예제 #4
0
    def analyzer(self):
        if not self.ok:
            return False
        elif not os.path.isfile(self.rule):
            echo("error", "need rule file!!", 'red')
            return False
        elif not self.apk_parser.ok:
            echo("error", " {} is not a apk file !!!", 'red')
            return False
        self.rules = self.__read_rule()

        return self.__analyzer_string()\
            or self.__analyzer_method()\
            or self._online_sandbox()
예제 #5
0
        def show_result(rsult, susp):

            for name in self.yara_namespace:
                if rsult.get(name, None) is None:
                    continue
                for r in rsult[name]:
                    tag = r['tags'][0]

                    if r['matches']:
                        echo(
                            "rule", " %s/%s %s\t%s" %
                            (tag, r['rule'], self.yara_namespace[name], susp),
                            'yellow')
                        return
예제 #6
0
def dex_info(args):

    input_file = args.dex
    pattern = args.string
    method_name_arg = args.method
    pkg = args.pkgname
    clazz_name = args.clazz
    dump = args.print_ins

    if input_file is None:
        echo("error", "need a dex file!! ", "red")
        parser.print_help()
        sys.exit(1)

    patters = []
    # if pkg is None:
    #     echo("warning", "pkg is None and will retrive all methods in dex file.", 'yellow')
    # if pattern is None or pattern == '':
    #     pattern = "://"

    patters.append(pattern)

    def scan_dex(dex):
        echo("dex", "analyzer " + dex)
        with open(dex, 'rb') as f:

            vm = DexFileVM(pkgname=pkg, buff=f.read())
            if not vm.ok():
                echo("error",
                     "{} is not a dex format file.".format(input_file), 'red')
                return
            if pattern is not None:
                # if pattern is not None will show string
                for i, s in enumerate(vm.all_strings(patters)):
                    echo("%d" % (i), "%s" % (s))
            if method_name_arg is not None:
                echo("warning", " methodName is empty ,show all methods",
                     'yellow')

                vm.analysis_dex(clazz_name, method_name_arg, dump)

    if os.path.isdir(input_file):
        for root, _, fs in os.walk(input_file):
            for f in fs:
                if f.endswith('.dex'):
                    dex = os.path.join(root, f)
                    scan_dex(dex)
    elif os.path.isfile(input_file):
        scan_dex(input_file)
예제 #7
0
    def get_export_components(self):
        """
        Return All export components info
        """
        # return self.
        exported_all = ["activity", 'service', 'provider', 'receiver']
        # activities = list(self.get_all_attribute_value(
        #     "activity", "name", {"exported": "true"}))
        # exported_all.append(activities)

        echo("exportedComponents", "**" * 20, "yellow")
        for k in exported_all:
            exported = list(
                self.get_all_attribute_value(k, "name", {"exported": "true"}))
            print("--" * 15 + " " + k + " " + "--" * 15)
            for i, item in enumerate(exported):
                echo("%d" % (i), item)
예제 #8
0
    def is_target_clazz(self, pkg, clazz):

        # return True if pkg in clazz else False
        need_filter_classes = [
            '.R$attr', '.R$drawable', '.R$id', '.R$layout', '.R$string', '.R',
            '.BuildConfig'
        ]
        android_s = [
            "^(Landroid/support|Landroid/arch|Landroidx/versionedparcelable|Landroidx/core|Lkotlin/|Lkotlinx/).+",
            ".*(R\$.+)$",
            ".+(/BuildConfig;|/R;)$",
        ]

        if isinstance(clazz, bytes):
            # print(clazz)
            try:
                clazz = str(clazz, encoding="utf-8")
            except UnicodeDecodeError as e:
                echo("dexparse",
                     "faile to decode string : {} ,error {} ".format(clazz, e),
                     color="red")
                return False
        if clazz == '':
            return False

        for a in android_s:
            expr = re.compile(a)
            if expr.search(clazz):
                return False
        # print("--> check %s  class: %s" % (pkg, clazz))
        # return True
        if pkg is None or pkg == '':
            return True
        clazz = clazz.replace("L", "").replace("/", '.').replace(";", "")

        # filter thridpart class ,like google's code etc
        suffix = clazz[clazz.rfind('.'):]
        if suffix in need_filter_classes:
            return False
        # #
        # target = re.compile(pkg)
        # if target.match(clazz):
        #     return True
        return True
예제 #9
0
    def show_info(parser, dexname, vm):
        echo("dexname", "--> %s" % (dexname))
        if save:
            f = os.getcwd() + os.sep + "%s.txt" % (dexname)
            files.append(f)
            if os.path.isfile(f):
                os.remove(f)

        if pattern is not None:
            # default all dex data
            for s in parser.all_strings([pattern], dex_vm=vm):

                if save:
                    save_file(f, s)
                else:
                    try:
                        echo("string", "%s" % (s), 'yellow')
                    except UnicodeDecodeError as e:
                        print("--> Unicode error ,string type {}".format(
                            type(s)))
                        raise e

        if method_name_arg is not None:

            apk_parser.analysis_dex(clazz_name,
                                    method_name_arg,
                                    dump,
                                    dex_vm=dex_vm)
        if save:
            for f in files:
                echo("save", "data save at " + f)
예제 #10
0
def yara_scan(args):
    rule = args.rule
    f = args.file
    if rule is None or f is None:
        echo("error", "yara rule or apk file must be include", 'red')
        return
    if not os.path.isfile(rule) and not os.path.isdir(rule):
        echo("error", "yara rule file not exists", 'red')
        return
    if not os.path.isfile(f) and not os.path.isdir(f):
        echo("error", "apk file or apk directory need", 'red')
        return
    echo("yara_scan", "------YARA SCAN -------", 'yellow')
    if rule.startswith("."):
        rule = os.getcwd() + rule[1:]
    YaraMatcher(rule, f).yara_scan()
예제 #11
0
    def scan_dex(dex):
        echo("dex", "analyzer " + dex)
        with open(dex, 'rb') as f:

            vm = DexFileVM(pkgname=pkg, buff=f.read())
            if not vm.ok():
                echo("error",
                     "{} is not a dex format file.".format(input_file), 'red')
                return
            if pattern is not None:
                # if pattern is not None will show string
                for i, s in enumerate(vm.all_strings(patters)):
                    echo("%d" % (i), "%s" % (s))
            if method_name_arg is not None:
                echo("warning", " methodName is empty ,show all methods",
                     'yellow')

                vm.analysis_dex(clazz_name, method_name_arg, dump)
예제 #12
0
    def print_ins(self, offset, show=True):
        ins_ = ' '
        instrus = self.dex_header.read_code_instrs(offset)

        if show:

            echo("instructions", "--" * 20, 'yellow')
            #  red, green, yellow, blue, magenta, cyan, white.
            echo("codeoff", " %s" % (hex(instrus[0])), "yellow")
            echo("codesize", " %s" % (hex(instrus[1])), "yellow")
            print("")

            # 格式化输出
            print(" " + " 0 " + " " + "" + " 1 " + " " + " 2 " + " " + "" +
                  " 3 " + "  " + " 4 " + " " + "" + " 5 " + " " + " 6 " + " " +
                  "" + " 7 " + "  " + " 8 " + " " + "" + " 9 " + " " + " A " +
                  " " + "" + " B " + "  " + " C " + " " + "" + " D " + " " +
                  " E " + " " + "" + " F ")

            print("-" * 16 + " " + "-" * 16 + " " + "-" * 16 + " " + "-" * 16)
        save = []
        for i, ins in enumerate(instrus[2:]):
            if show:
                if i > 0 and i % 16 == 0:
                    print("%s" % (ins_))
                    print("")
                    ins_ = ""
                if i > 0 and i % 4 == 0:
                    ins_ += " "
                ins_ += "%.2x " % (ins) + " "
            save.append("%.2x " % (ins))
        if show:
            print(ins_)
            # print("")
            # echo("info", "all instructions ", )
            echo("shellcode", "\n" + " ".join(save), 'yellow')
        return " ".join(save)
예제 #13
0
    def show_manifest(self, ac, rs, ss, ps, entry, both, exported, pm):

        manifest = {
            "activities": self.get_all_activities,
            "receviers": self.get_receivers,
            "providers": self.get_providers,
            "services": self.get_all_services,
            "both": self.__str__,
        }

        def show(key):
            echo('%s' % (key), "--" * 15, 'yellow')
            cnt = 1
            for a in manifest[key]():
                echo("%d" % (cnt), a)
                cnt += 1

        if ac:
            show("activities")
        elif rs:
            show("receviers")
        elif ss:
            show("services")
        elif ps:
            show("providers")
        elif entry:
            # show("entry")
            echo("entryinfo", "**" * 20)
            self.entry_info()
        elif exported:
            self.get_export_components()
        elif pm:
            for p in self.permissions:
                echo("permission", p)
        elif both:
            echo("all", "\n" + manifest['both']())
예제 #14
0
    def entry_info(self):

        echo("pkgname", self.get_package_name())
        echo("application", self.get_application())
        echo("MainActivity", self.get_main_activity())
예제 #15
0
def apk_info(args):
    """
    默认输出apk内的基本信息
    apk的指纹信息
    AndroidManifest.xml内的信息
    使用-z --zipinfo 读取apk内的所有文件名信息
    """

    input_file = args.apk
    zip_info = args.zipinfo
    dex_num = args.dexnum
    info = args.info
    suffix = args.suffix  # like .apk,.APK,.bin
    if suffix is None:
        suffix = ".apk,.APK"

    if input_file is None or not os.path.isfile(input_file):
        echo("error", "need a apk file as input.", "red")
        sys.exit(1)
    # 可以是任意文件,内部如果读取失败,则会直接异常
    # found = False
    # for s in suffix.split(","):
    #     if input_file.endswith(s):
    #         #echo("error", "need a apk file", 'red')
    #         # return
    #         found = True
    # if found is False:
    #     echo("error", "need a apk file", 'red')
    #     return

    start = time.time()
    apk_parser = ApkPaser(input_file)
    if dex_num:
        for dexname in apk_parser.get_all_dexs(name=True):
            echo("dexname", dexname)
        print("costs: {}".format(time.time() - start))

    if info:
        base_info = apk_parser.apk_base_info()
        print("")
        echo("AppName", base_info['app_name'])
        if base_info['packer_name'] != "N/A":
            echo("packer",
                 "App may be packed by {}".format(base_info['packer_name']),
                 color="red")
        print("")
        echo("apkInfo", "\n{}".format(json.dumps(base_info, indent=2)),
             "yellow")
        print("--" * 20)
        print("costs: {}".format(time.time() - start))

    if zip_info:
        for f in apk_parser.get_file_names():
            echo("info", "-> %s" % (f))
예제 #16
0
 def show(key):
     echo('%s' % (key), "--" * 15, 'yellow')
     cnt = 1
     for a in manifest[key]():
         echo("%d" % (cnt), a)
         cnt += 1
예제 #17
0
 def scan(file):
     try:
         self.match(file)
     except Exception as e:
         echo("yara_scan", "error {} ".format(e), 'red')
예제 #18
0
 def _online_sandbox(self):
     result = self.vt.analysis()
     if result is None:
         return False
     echo("info", "VT query reult:")
     echo("positives", result['positives'], "magenta")
     echo("virusName", result['virusName'], "red")
     echo("link", result['link'], "green")
     echo("scanDate", result['scanDate'], "yellow")
     echo("path", self.filename, "white")
     return True
예제 #19
0
    def analysis_dex(self, clazz_name, method_name, show_ins=False):
        """
        Analyzer dex .This function mainly is  use to show dex class_defs

        eg.
        if clazz_name or method_name is None or empty, default show all 
        class->method
        else if method_name is not none ,show the matched method info ,include 

        class_name->method 
        method_instructions

        else if class_name and method are not none or empty ,this means to specific class_def's method info 

        """
        if clazz_name is None:
            # class_name = "com.demo.Test"
            clazz_name = ''
        if method_name is None:
            method_name = ''

        marker = '.java -> '
        query = clazz_name + marker + method_name

        for class_def in self.all_class_defs():
            clzz_name = byte2str(class_def['class_name'])

            clzz_name = clzz_name.replace("L",
                                          '').replace("/",
                                                      '.').replace(";", '')

            for method_ in class_def['code_item']:
                _method_name = byte2str(method_['method_name'])
                signature = byte2str(method_['signature'])

                _x = clzz_name + marker + _method_name + signature

                if clazz_name != marker and method_name != '' and query == _x:
                    # show class.method(signature)
                    print("**" * 20)
                    echo("className", " %s" % (clzz_name), "yellow")
                    echo("methodName", " %s" % (_method_name), "yellow")
                    echo("signature", " %s" % (signature), "yellow")
                    self.print_ins(method_['code_off'], show=show_ins)

                elif method_name == '':
                    echo("info", "-> %s" % (_x), "blue")

                elif method_name == _method_name:
                    print("**" * 20)
                    echo("className", "%s" % (clzz_name), "blue")
                    echo("methodName", "%s" % (_method_name), "blue")
                    echo("signature", " %s" % (signature), "blue")
                    self.print_ins(method_['code_off'], show=show_ins)
예제 #20
0
def extract_apk_info(args):
    input_file = args.apk
    pattern = args.string
    method_name_arg = args.method
    clazz_name = args.clazz
    dump = args.print_ins
    save = args.save  # save strings or methods
    # if save:
    #     echo("save", "date save at "+f)
    executor = ThreadPoolExecutor(max_workers=4)
    files = []

    def show_info(parser, dexname, vm):
        echo("dexname", "--> %s" % (dexname))
        if save:
            f = os.getcwd() + os.sep + "%s.txt" % (dexname)
            files.append(f)
            if os.path.isfile(f):
                os.remove(f)

        if pattern is not None:
            # default all dex data
            for s in parser.all_strings([pattern], dex_vm=vm):

                if save:
                    save_file(f, s)
                else:
                    try:
                        echo("string", "%s" % (s), 'yellow')
                    except UnicodeDecodeError as e:
                        print("--> Unicode error ,string type {}".format(
                            type(s)))
                        raise e

        if method_name_arg is not None:

            apk_parser.analysis_dex(clazz_name,
                                    method_name_arg,
                                    dump,
                                    dex_vm=dex_vm)
        if save:
            for f in files:
                echo("save", "data save at " + f)

    if input_file is None or not os.path.isfile(input_file):
        echo("error", "need a apk file : %s" % (input_file), 'red')
        return
    if pattern is None:
        echo("warning", "no string specificed", 'yellow')
        # pattern = ''

    apk_parser = ApkPaser(input_file)
    if not apk_parser.ok():
        return

    workers = []
    for dexname, dex_vm in apk_parser.all_dex_vms():
        workers.append(
            executor.submit(fn=show_info,
                            parser=apk_parser,
                            dexname=dexname,
                            vm=dex_vm))
    #   pass
    for t in as_completed(workers):
        t.result()