示例#1
0
    def show_dyncode(self):
        if analysis.is_dyn_code(self.x) is False:
            self.__logger.log(Logger.WARNING,"No dynamic code was found!")
            return

        paths = []
        paths.extend(self.x.get_tainted_packages().search_methods("Ldalvik/system/BaseDexClassLoader;",
                                                    "<init>",
                                                    "."))

        paths.extend(self.x.get_tainted_packages().search_methods("Ldalvik/system/PathClassLoader;",
                                                    "<init>",
                                                    "."))

        paths.extend(self.x.get_tainted_packages().search_methods("Ldalvik/system/DexClassLoader;",
                                                    "<init>",
                                                    "."))

        paths.extend(self.x.get_tainted_packages().search_methods("Ldalvik/system/DexFile;",
                                                    "<init>",
                                                    "."))

        paths.extend(self.x.get_tainted_packages().search_methods("Ldalvik/system/DexFile;",
                                                    "loadDex",
                                                    "."))
        str_info_dyn="\t"
        for path in paths:
            str_info_dyn += (self.show_Path(self.x.get_vm(), path )+"\n\n\t")
        self.__logger.log_with_title("Usage of Dynamic Code",str_info_dyn)
示例#2
0
    def analyze(self, d):

        ret = False
        dvmx = analysis.VMAnalysis(d)

        if analysis.is_native_code(dvmx):
            ret = True
            self.extra += "NativeCodeFound; "

        if analysis.is_dyn_code(dvmx):
            ret = True
            self.extra += "DynCodeFound; "

        if analysis.is_reflection_code(dvmx):
            ret = True
            self.extra += "ReflexionCodeFound; "

        #if analysis.is_ascii_obfuscation(d):
        #ret = True
        #self.extra + "AsciiObfuscationCodeFound; "

        #if analysis.is_crypto_code(d):
        #ret = True
        #self.extra + "AsciiObfuscationCodeFound; "

        return ret
示例#3
0
    def run(self):
        """Run androguard to extract static android information
                @return: list of static features
        """
        self.key = "apkinfo"
        apkinfo = {}

        if "file" not in self.task["category"]:
            return

        from androguard.core.bytecodes.apk import APK
        from androguard.core.bytecodes.dvm import DalvikVMFormat
        from androguard.core.analysis.analysis import uVMAnalysis
        from androguard.core.analysis import analysis

        f = File(self.task["target"])
        if f.get_name().endswith((".zip", ".apk")) or "zip" in f.get_type():
            if not os.path.exists(self.file_path):
                raise CuckooProcessingError("Sample file doesn't exist: \"%s\"" % self.file_path)

            try:
                a = APK(self.file_path)
                if a.is_valid_APK():
                    manifest = {}
                    apkinfo["files"] = self._apk_files(a)
                    manifest["package"] = a.get_package()
                    # manifest["permissions"]=a.get_details_permissions_new()
                    manifest["main_activity"] = a.get_main_activity()
                    manifest["activities"] = a.get_activities()
                    manifest["services"] = a.get_services()
                    manifest["receivers"] = a.get_receivers()
                    # manifest["receivers_actions"]=a.get__extended_receivers()
                    manifest["providers"] = a.get_providers()
                    manifest["libraries"] = a.get_libraries()
                    apkinfo["manifest"] = manifest
                    # apkinfo["certificate"] = a.get_certificate()
                    static_calls = {}
                    if self.check_size(apkinfo["files"]):
                        vm = DalvikVMFormat(a.get_dex())
                        vmx = uVMAnalysis(vm)

                        static_calls["all_methods"] = self.get_methods(vmx)
                        static_calls["is_native_code"] = analysis.is_native_code(vmx)
                        static_calls["is_dynamic_code"] = analysis.is_dyn_code(vmx)
                        static_calls["is_reflection_code"] = analysis.is_reflection_code(vmx)

                        # static_calls["dynamic_method_calls"]= analysis.get_show_DynCode(vmx)
                        # static_calls["reflection_method_calls"]= analysis.get_show_ReflectionCode(vmx)
                        # static_calls["permissions_method_calls"]= analysis.get_show_Permissions(vmx)
                        # static_calls["crypto_method_calls"]= analysis.get_show_CryptoCode(vmx)
                        # static_calls["native_method_calls"]= analysis.get_show_NativeMethods(vmx)
                    else:
                        log.warning("Dex size bigger than: %s",
                                    self.options.decompilation_threshold)
                    apkinfo["static_method_calls"] = static_calls
            except (IOError, OSError, zipfile.BadZipfile) as e:
                raise CuckooProcessingError("Error opening file %s" % e)

        return apkinfo
示例#4
0
    def run(self):
        """Run androguard to extract static android information
                @return: list of static features
        """
        self.key = "apkinfo"
        apkinfo = {}

        if "file" not in self.task["category"] or not HAVE_ANDROGUARD:
            return

        f = File(self.task["target"])
        if f.get_name().endswith((".zip", ".apk")) or "zip" in f.get_type():
            if not os.path.exists(self.file_path):
                raise CuckooProcessingError(
                    "Sample file doesn't exist: \"%s\"" % self.file_path)

            try:
                a = APK(self.file_path)
                if a.is_valid_APK():
                    manifest = {}
                    apkinfo["files"] = self._apk_files(a)
                    manifest["package"] = a.get_package()
                    # manifest["permissions"]=a.get_details_permissions_new()
                    manifest["main_activity"] = a.get_main_activity()
                    manifest["activities"] = a.get_activities()
                    manifest["services"] = a.get_services()
                    manifest["receivers"] = a.get_receivers()
                    # manifest["receivers_actions"]=a.get__extended_receivers()
                    manifest["providers"] = a.get_providers()
                    manifest["libraries"] = a.get_libraries()
                    apkinfo["manifest"] = manifest
                    # apkinfo["certificate"] = a.get_certificate()
                    static_calls = {}
                    if self.check_size(apkinfo["files"]):
                        vm = DalvikVMFormat(a.get_dex())
                        vmx = uVMAnalysis(vm)

                        static_calls["all_methods"] = self.get_methods(vmx)
                        static_calls[
                            "is_native_code"] = analysis.is_native_code(vmx)
                        static_calls["is_dynamic_code"] = analysis.is_dyn_code(
                            vmx)
                        static_calls[
                            "is_reflection_code"] = analysis.is_reflection_code(
                                vmx)

                        # static_calls["dynamic_method_calls"]= analysis.get_show_DynCode(vmx)
                        # static_calls["reflection_method_calls"]= analysis.get_show_ReflectionCode(vmx)
                        # static_calls["permissions_method_calls"]= analysis.get_show_Permissions(vmx)
                        # static_calls["crypto_method_calls"]= analysis.get_show_CryptoCode(vmx)
                        # static_calls["native_method_calls"]= analysis.get_show_NativeMethods(vmx)
                    else:
                        log.warning("Dex size bigger than: %s",
                                    self.options.decompilation_threshold)
                    apkinfo["static_method_calls"] = static_calls
            except (IOError, OSError, BadZipfile) as e:
                raise CuckooProcessingError("Error opening file %s" % e)

        return apkinfo
示例#5
0
    def getObf(self):

        self.ObfDic['REFLECTION'] = int(analysis.is_reflection_code(self.dx))
        self.ObfDic['NATIVE'] = int(analysis.is_native_code(self.dx))
        self.ObfDic['DYNAMIC'] = int(analysis.is_dyn_code(self.dx))
        self.ObfDic['CRYPTO'] = int(analysis.is_crypto_code(self.dx))

        return self.ObfDic
示例#6
0
    def load_app_info_table(self):
        self.info = {}
        self.info["Application Name"] = self.apk.get_app_name()
        self.info["Application Size"] = util.sizeof_fmt(
            os.path.getsize(self.apk_path))
        self.info["Android Version Name"] = self.apk.get_androidversion_name()
        self.info["Android Version Code"] = self.apk.get_androidversion_code()
        self.info["Android Package Name"] = self.apk.get_package()
        self.info["Signature Name"] = self.apk.get_signature_name()
        self.info["Uses Dynamic Code Loading"] = str(
            analysis.is_dyn_code(self.x))
        self.info["Uses Reflection"] = str(analysis.is_reflection_code(self.x))
        self.info["Uses Crypto"] = str(analysis.is_crypto_code(self.x))
        self.info["Privacy Leaks"] = str(len(self.get_privacy_leaks()))
        self.info["Number of Providers"] = str(len(self.apk.get_providers()))
        self.info["Number of Activities"] = str(len(self.apk.get_activities()))
        self.info["Number of Services"] = str(len(self.apk.get_services()))
        self.info["Number of Libraries"] = str(len(self.apk.get_libraries()))
        self.info["Number of Permissions"] = str(
            len(self.get_uses_permissions()))

        self.info_actions = {}
        self.info_actions["Application Name"] = None
        self.info_actions["Application Size"] = None
        self.info_actions["Android Version Name"] = None
        self.info_actions["Android Version Code"] = None
        self.info_actions["Android Package Name"] = None
        self.info_actions["Signature Name"] = self.show_signature
        self.info_actions["Uses Dynamic Code Loading"] = self.show_dyncode
        self.info_actions["Uses Reflection"] = self.show_reflection
        self.info_actions["Uses Crypto"] = self.show_cryptocode
        self.info_actions["Privacy Leaks"] = self.show_privacy_leaks
        self.info_actions["Number of Providers"] = self.show_providers
        self.info_actions["Number of Activities"] = self.show_activities
        self.info_actions["Number of Services"] = self.show_services
        self.info_actions["Number of Libraries"] = self.show_libraries
        self.info_actions["Number of Permissions"] = self.show_permissions
        info_table = self.ui.appInfoTable
        info_table.setRowCount(len(self.info))
        info_table.setColumnWidth(1, 200)
        info_table.horizontalHeader().setResizeMode(0,
                                                    QtGui.QHeaderView.Stretch)
        row = 0
        for key in sorted(self.info):
            action = self.info_actions[key]
            action_button = None
            if action is not None:
                action_button = QtGui.QPushButton()
                action_button.setText("Show")
                action_button.clicked.connect(action)
            key_item = QtGui.QTableWidgetItem(key)
            value_item = QtGui.QTableWidgetItem(self.info[key])
            info_table.setItem(row, 0, key_item)
            info_table.setItem(row, 1, value_item)
            if action_button is not None:
                info_table.setCellWidget(row, 2, action_button)
            row += 1
示例#7
0
    def do_build_apk_report(self, a):
        output = StringIO()

        a.get_files_types()

        output.write("[FILES] \n")
        for i in a.get_files():
            try:
                output.write("\t%s %s %x\n" % (i, a.files[i], a.files_crc32[i], ))
            except KeyError:
                output.write("\t%s %x\n" % (i, a.files_crc32[i], ))

        output.write("\n[PERMISSIONS] \n")
        details_permissions = a.get_details_permissions()
        for i in details_permissions:
            output.write("\t%s %s\n" % (i, details_permissions[i], ))

        output.write("\n[MAIN ACTIVITY]\n\t%s\n" % (a.get_main_activity(), ))

        output.write("\n[ACTIVITIES] \n")
        activities = a.get_activities()
        for i in activities:
            filters = a.get_intent_filters("activity", i)
            output.write("\t%s %s\n" % (i, filters or "", ))

        output.write("\n[SERVICES] \n")
        services = a.get_services()
        for i in services:
            filters = a.get_intent_filters("service", i)
            output.write("\t%s %s\n" % (i, filters or "", ))

        output.write("\n[RECEIVERS] \n")
        receivers = a.get_receivers()
        for i in receivers:
            filters = a.get_intent_filters("receiver", i)
            output.write("\t%s %s\n" % (i, filters or "", ))

        output.write("\n[PROVIDERS]\n\t%s\n\n" % (a.get_providers(), ))

        vm  = dvm.DalvikVMFormat(a.get_dex())
        vmx = analysis.uVMAnalysis(vm)

        output.write("Native code      : %s\n"   % (analysis.is_native_code(vmx), ))
        output.write("Dynamic code     : %s\n"   % (analysis.is_dyn_code(vmx), ))
        output.write("Reflection code  : %s\n"   % (analysis.is_reflection_code(vmx), ))
        output.write("ASCII Obfuscation: %s\n\n" % (analysis.is_ascii_obfuscation(vm), ))

        for i in vmx.get_methods():
            i.create_tags()
            if not i.tags.empty():
                output.write("%s %s %s\n" % (i.method.get_class_name(),
                                             i.method.get_name(),
                                             i.tags, ))

        return output
示例#8
0
    def do_build_apk_report(self, a):
        output = StringIO()

        a.get_files_types()

        output.write("[FILES] \n")
        for i in a.get_files():
            try: 
                output.write("\t%s %s %x\n" % (i, a.files[i], a.files_crc32[i], ))
            except KeyError:
                output.write("\t%s %x\n" % (i, a.files_crc32[i], ))

        output.write("\n[PERMISSIONS] \n")
        details_permissions = a.get_details_permissions()
        for i in details_permissions:
            output.write("\t%s %s\n" % (i, details_permissions[i], ))

        output.write("\n[MAIN ACTIVITY]\n\t%s\n" % (a.get_main_activity(), ))

        output.write("\n[ACTIVITIES] \n")
        activities = a.get_activities()
        for i in activities:
            filters = a.get_intent_filters("activity", i)
            output.write("\t%s %s\n" % (i, filters or "", ))

        output.write("\n[SERVICES] \n")
        services = a.get_services()
        for i in services:
            filters = a.get_intent_filters("service", i)
            output.write("\t%s %s\n" % (i, filters or "", ))

        output.write("\n[RECEIVERS] \n")
        receivers = a.get_receivers()
        for i in receivers:
            filters = a.get_intent_filters("receiver", i)
            output.write("\t%s %s\n" % (i, filters or "", ))

        output.write("\n[PROVIDERS]\n\t%s\n\n" % (a.get_providers(), ))

        vm  = dvm.DalvikVMFormat(a.get_dex())
        vmx = analysis.uVMAnalysis(vm)

        output.write("Native code      : %s\n"   % (analysis.is_native_code(vmx), ))
        output.write("Dynamic code     : %s\n"   % (analysis.is_dyn_code(vmx), ))
        output.write("Reflection code  : %s\n"   % (analysis.is_reflection_code(vmx), ))
        output.write("ASCII Obfuscation: %s\n\n" % (analysis.is_ascii_obfuscation(vm), ))

        for i in vmx.get_methods():
            i.create_tags()
            if not i.tags.empty():
                output.write("%s %s %s\n" % (i.method.get_class_name(),
                                             i.method.get_name(),
                                             i.tags, ))

        return output
示例#9
0
def display_dvm_info(apk) :
    vm = dvm.DalvikVMFormat( apk.get_dex() )
    vmx = analysis.uVMAnalysis( vm )

    print "Native code:", analysis.is_native_code(vmx)
    print "Dynamic code:", analysis.is_dyn_code(vmx)
    print "Reflection code:", analysis.is_reflection_code(vmx)

    for i in vmx.get_methods() :
      i.create_tags()
      if not i.tags.empty() :
        print i.method.get_class_name(), i.method.get_name(), i.tags
示例#10
0
def display_dvm_info(apk):
    vm = dvm.DalvikVMFormat(apk.get_dex())
    vmx = analysis.uVMAnalysis(vm)

    print "Native code:", analysis.is_native_code(vmx)
    print "Dynamic code:", analysis.is_dyn_code(vmx)
    print "Reflection code:", analysis.is_reflection_code(vmx)

    for i in vmx.get_methods():
        i.create_tags()
        if not i.tags.empty():
            print i.method.get_class_name(), i.method.get_name(), i.tags
示例#11
0
    def load_app_info_table(self):
        self.info = {}
        self.info["Application Name"]            = self.apk.get_app_name()
        self.info["Application Size"]            = util.sizeof_fmt(os.path.getsize(self.apk_path))
        self.info["Android Version Name"]        = self.apk.get_androidversion_name()
        self.info["Android Version Code"]        = self.apk.get_androidversion_code()
        self.info["Android Package Name"]        = self.apk.get_package()
        self.info["Signature Name"]              = self.apk.get_signature_name()
        self.info["Uses Dynamic Code Loading"]   = str(analysis.is_dyn_code(self.x))
        self.info["Uses Reflection"]             = str(analysis.is_reflection_code(self.x))
        self.info["Uses Crypto"]                 = str(analysis.is_crypto_code(self.x))
        self.info["Privacy Leaks"]               = str(len(self.get_privacy_leaks()))
        self.info["Number of Providers"]         = str(len(self.apk.get_providers()))
        self.info["Number of Activities"]        = str(len(self.apk.get_activities()))
        self.info["Number of Services"]          = str(len(self.apk.get_services()))
        self.info["Number of Libraries"]         = str(len(self.apk.get_libraries()))
        self.info["Number of Permissions"]       = str(len(self.get_uses_permissions()))

        self.info_actions = {}
        self.info_actions["Application Name"]            = None
        self.info_actions["Application Size"]            = None
        self.info_actions["Android Version Name"]        = None
        self.info_actions["Android Version Code"]        = None
        self.info_actions["Android Package Name"]        = None
        self.info_actions["Signature Name"]              = self.show_signature
        self.info_actions["Uses Dynamic Code Loading"]   = self.show_dyncode
        self.info_actions["Uses Reflection"]             = self.show_reflection
        self.info_actions["Uses Crypto"]                 = self.show_cryptocode
        self.info_actions["Privacy Leaks"]               = self.show_privacy_leaks
        self.info_actions["Number of Providers"]         = self.show_providers
        self.info_actions["Number of Activities"]        = self.show_activities
        self.info_actions["Number of Services"]          = self.show_services
        self.info_actions["Number of Libraries"]         = self.show_libraries
        self.info_actions["Number of Permissions"]       = self.show_permissions
        info_table = self.ui.appInfoTable
        info_table.setRowCount(len(self.info))
        info_table.setColumnWidth(1, 200)
        info_table.horizontalHeader().setResizeMode(0, QtGui.QHeaderView.Stretch)
        row = 0
        for key in sorted(self.info):
            action = self.info_actions[key]
            action_button = None
            if action is not None:
                action_button = QtGui.QPushButton()
                action_button.setText("Show")
                action_button.clicked.connect(action)
            key_item = QtGui.QTableWidgetItem(key)
            value_item = QtGui.QTableWidgetItem(self.info[key])
            info_table.setItem(row,0,key_item)
            info_table.setItem(row,1,value_item)
            if action_button is not None:
                info_table.setCellWidget(row,2,action_button)
            row += 1
示例#12
0
def main(options, args) :
    print options.input
    print options.output
    if options.input == None or options.output == None :
        print "static_analysis.py -i <inputfile> -o <outputfolder>"
        sys.exit(2)
    else :
        ret_type = androconf.is_android( options.input ) 

        if ret_type == "APK" :
            try :
                a = apk.APK(options.input, zipmodule=2)
                if a.is_valid_APK() :

                    vm = dvm.DalvikVMFormat(a.get_dex())
                    vmx = analysis.uVMAnalysis(vm)

                    data = {
                        'mainActivity'       : a.get_main_activity(),
                        'activities'         : a.get_activities(),
                        'providers'          : a.get_providers(),
                        'receivers'          : a.get_receivers(),
                        'services'           : a.get_services(),
                        'androidVersion'     : a.get_androidversion_code(),
                        'maxSdkVersion'      : a.get_max_sdk_version(),
                        'minSdkVersion'      : a.get_min_sdk_version(),
                        'targetSdkVersion'   : a.get_target_sdk_version(),
                        'package'            : a.get_package(),
                        'libraries'          : a.get_libraries(),
                        'isCryptoCode'       : analysis.is_crypto_code(vmx),
                        'isDynamicCode'      : analysis.is_dyn_code(vmx),
                        'isNativeCode'       : analysis.is_native_code(vmx),
                        'nativeMethodCount'  : native_method_count(vm),
                        'isReflectionCode'   : analysis.is_reflection_code(vmx),
                        'reflectionCount'    : len(vmx.get_tainted_packages().search_methods("Ljava/lang/reflect/Method;", ".", ".")),
                        'isAsciiObfuscation' : analysis.is_ascii_obfuscation(vm),
                        'permissions'        : a.get_permissions(),
                        'actualPermissions'  : actual_permissions(vm, vmx),
                        #'internalMethodCalls' : get_methods(vm.get_class_manager(), vmx.get_tainted_packages().get_internal_packages(), {}),
                        'externalMethodCalls' : get_methods(vm.get_class_manager(), vmx.get_tainted_packages().get_external_packages(), {})
                    }

                    with io.open(options.output + "/" + hashfile(options.input) + ".json", 'w', encoding='utf-8') as f:
                        f.write(unicode(json.dumps(data, sort_keys=False, indent=2, separators=(',', ': '), ensure_ascii=False)))

                else :
                    print "INVALID APK"
            except Exception, e :
                print "ERROR", e
                import traceback
                traceback.print_exc()
示例#13
0
    def show_dyncode(self):
        if analysis.is_dyn_code(self.x) is False:
            self.__logger.log(Logger.WARNING, "No dynamic code was found!")
            return

        paths = []
        paths.extend(self.x.get_tainted_packages().search_methods(
            "Ldalvik/system/BaseDexClassLoader;", "<init>", "."))

        paths.extend(self.x.get_tainted_packages().search_methods(
            "Ldalvik/system/PathClassLoader;", "<init>", "."))

        paths.extend(self.x.get_tainted_packages().search_methods(
            "Ldalvik/system/DexClassLoader;", "<init>", "."))

        paths.extend(self.x.get_tainted_packages().search_methods(
            "Ldalvik/system/DexFile;", "<init>", "."))

        paths.extend(self.x.get_tainted_packages().search_methods(
            "Ldalvik/system/DexFile;", "loadDex", "."))
        str_info_dyn = "\t"
        for path in paths:
            str_info_dyn += (self.show_Path(self.x.get_vm(), path) + "\n\n\t")
        self.__logger.log_with_title("Usage of Dynamic Code", str_info_dyn)
示例#14
0
def performAnalysis(apkPath):

    # Perform the analysis by recalling public method of androlyze.py
    a, d, dx = androlyze.AnalyzeAPK(apkPath)

    if not a.is_valid_APK():
        print "[Exit] The selected resource is not a valid APK!"
        return sys.exit(FAILURE)

    if not analysis.is_dyn_code(dx):
        print "[Exit] No DexClassLoader use in this APK and so there is nothing to patch!"
        return sys.exit(SUCCESS)

    print "[In progress] Analyze target APK.."

    # Store app permissions (used later on while patching Android Manifest)
    app_permissions = set(a.get_permissions())

    # app_permissions.add('android.permission.ACCESS_NETWORK_STATE')
    # app_permissions.add('android.permission.BLABLABLA')

    # Reference to global variable
    missing_permissions = list()

    for current_perm in required_permissions:
        if not (current_perm in app_permissions):
            missing_permissions.append(current_perm)

            # print missing_permissions

            # Flag variable for later use
    dynamicCallsWhereTraced = False

    # Save a reference for standard output
    stdout = sys.stdout

    # Redirect output to an helper variable
    # sys.stdout = open('./dynamicCalls', 'w')
    dynamicCallsFilePath = os.curdir + os.sep + "dynamicCalls"

    with open(dynamicCallsFilePath, "w") as dynamicCallsFile:
        # Redirect output to an helper variable
        sys.stdout = dynamicCallsFile

        # Highlight dynamic calls linked to a DexClassLoader.
        analysis.show_DynCode(dx)

        # Set back usual stdout
        sys.stdout = stdout

    with open(dynamicCallsFilePath, "r") as dynamicCallsFile:

        # print INTEGER.parseString("1")
        # print CLASS_STRING.parseString("Lcom/example/extractapp/MainActivity;")
        # print METHOD_DECL.parseString("setUpNormal()V")
        # print NUMBER_EXA.parseString("(0x66)")
        # print CLASS_STRING.parseString("Ldalvik/system/DexClassLoader;")

        # Define a grammar to parse line of the input file.
        parsing_format = (
            INTEGER + CLASS_STRING + "->" + METHOD_DECL + NUMBER_EXA + "--->" + CLASS_STRING + "->" + METHOD_DECL
        )

        # Reference to global variable
        classesWithDynCodeLoad = list()

        for line in dynamicCallsFile:
            # print line
            tokens = parsing_format.parseString(line)

            # This is a sort specific parsing constant(magic numbers)..
            className = tokens[1][1]

            # Extract only name of classes to patch which are not the ones of Grab'n Run
            if className != "it/necst/grabnrun/SecureDexClassLoader":
                classesWithDynCodeLoad.append(className)

                # In the end remove duplicates from this list (use a set)
        classesWithDynCodeLoad = set(classesWithDynCodeLoad)

        # print classesWithDynCodeLoad

        # Raise flag variable
        print "[In progress] Dynamic calls have been detected.."
        dynamicCallsWhereTraced = True

        # Now the helper file should be closed and erased.
    os.remove(dynamicCallsFilePath)

    if dynamicCallsWhereTraced:
        # This APK should be patched!
        return missing_permissions, classesWithDynCodeLoad

        # Something went wrong..
    print "[Exit] Dynamic calls have not been detected!"
    return sys.exit(FAILURE)
示例#15
0
文件: risk.py 项目: hetykai/works
 def analyze_dex(self, d, dx, flags):
     flags["REFLECTION"] = int(analysis.is_reflection_code(dx))
     flags["NATIVE"] = int(analysis.is_native_code(dx))
     flags["DYNAMIC"] = int(analysis.is_dyn_code(dx))
     flags["CRYPTO"] = int(analysis.is_crypto_code(dx))
示例#16
0
 def analyze_dex(self, d, dx, flags):
     flags["REFLECTION"] = int(analysis.is_reflection_code(dx))
     flags["NATIVE"] = int(analysis.is_native_code(dx))
     flags["DYNAMIC"] = int(analysis.is_dyn_code(dx))
     flags["CRYPTO"] = int(analysis.is_crypto_code(dx))
示例#17
0
    def execute(self):
        AndroCommand.execute(self)
        
        if self.options.all_options:
            self.options.dynamic = True
            self.options.native = True
            self.options.obfuscation = True
            self.options.reflection = True
        
        dalvik_options= [self.options.dynamic, self.options.native, self.options.obfuscation, self.options.reflection]

        a = apk.APK(self.options.apk, zipmodule=2)

        if not a.is_valid_APK():
            sys.stderr.write("Not a valid APK file.")
            exit(1)

        if not any(dalvik_options):
            sys.stderr.write("No output option selected.")
            exit(1)
            

        # create a session, get the underlying app and use a transaction to update 
        # the values
        session = self.db.session()

        try:
            app = session.query(App).filter(App.id==self.options.index).first()

            if not app:
                sys.stderr.write("Could not find app by index.")
                exit(1)

            #print 'Doing vm analysis'
            dex = a.get_dex()
            vm = dvm.DalvikVMFormat(dex)
            vmx = analysis.uVMAnalysis(vm)

            if self.options.dynamic:
                print 'Checking if application uses dynamic code...'
                app.dynamic = analysis.is_dyn_code(vmx)
                session.flush()

            if self.options.native:
                print 'Checking if application uses native code...'
                app.native = analysis.is_native_code(vmx)
                session.flush()

            # androguard 1.9 no longer supports this
            """
            if self.options.obfuscation:
                print 'Checking if application uses obfuscation...'
                app.obfuscation = analysis.is_ascii_obfuscation(vm)
                session.flush()
            """

            if self.options.reflection:
                print 'Checking if application uses reflection...'
                app.reflection = analysis.is_reflection_code(vmx)
                session.flush()

            session.commit()
            print 'Success'
        except:
            session.rollback()
            exit(1)

        exit(0)
示例#18
0
def print_dynLoad(dx, cm):
	if analysis.is_dyn_code(dx) == True:
		OutStream.write("***dynamic code loading***\n")
		paths = dx.get_tainted_packages().search_methods( "Ldalvik/system/DexClassLoader;", ".", ".")
		write_Paths(paths, cm, OutStream)
示例#19
0
    def run(self):
        """Run androguard to extract static android information
                @return: list of static features
        """
        self.key = "apkinfo"
        apkinfo = {}

        if "file" not in self.task["category"] or not HAVE_ANDROGUARD:
            return

        f = File(self.task["target"])
        #if f.get_name().endswith((".zip", ".apk")) or "zip" in f.get_type():
        if not os.path.exists(self.file_path):
            raise CuckooProcessingError("Sample file doesn't exist: \"%s\"" % self.file_path)

        try:
            a = APK(self.file_path)
            if a.is_valid_APK():
                manifest = {}

                apkinfo["files"] = self._apk_files(a)
                manifest["package"] = a.get_package()
                apkinfo["hidden_payload"] = []

                for file in apkinfo["files"]:
                    if self.file_type_check(file):
                       apkinfo["hidden_payload"].append(file)

                apkinfo["files_flaged"] = self.files_name_map

                manifest["permissions"]= get_permissions(a)
                manifest["main_activity"] = a.get_main_activity()
                manifest["activities"] = a.get_activities()
                manifest["services"] = a.get_services()
                manifest["receivers"] = a.get_receivers()
                manifest["receivers_actions"] = get_extended_receivers(a)
                manifest["providers"] = a.get_providers()
                manifest["libraries"] = a.get_libraries()
                apkinfo["manifest"] = manifest

                apkinfo["icon"] = get_apk_icon(self.file_path)
                certificate = get_certificate(self.file_path)
                if certificate:
                    apkinfo["certificate"] = certificate


                #vm = DalvikVMFormat(a.get_dex())
                #strings = vm.get_strings()
                strings = self._get_strings(self.file_path)
                apkinfo["interesting_strings"] = find_strings(strings)
                apkinfo["dex_strings"] = strings

                static_calls = {}
                if self.options.decompilation:
                    if self.check_size(apkinfo["files"]):
                        vm = DalvikVMFormat(a.get_dex())
                        vmx = uVMAnalysis(vm)

                        static_calls["all_methods"] = get_methods(vmx)
                        static_calls["is_native_code"] = analysis.is_native_code(vmx)
                        static_calls["is_dynamic_code"] = analysis.is_dyn_code(vmx)
                        static_calls["is_reflection_code"] = analysis.is_reflection_code(vmx)
                        static_calls["is_crypto_code"] = is_crypto_code(vmx)

                        static_calls["dynamic_method_calls"] = get_show_DynCode(vmx)
                        static_calls["reflection_method_calls"] = get_show_ReflectionCode(vmx)
                        static_calls["permissions_method_calls"] = get_show_Permissions(vmx)
                        static_calls["crypto_method_calls"] = get_show_CryptoCode(vmx)
                        static_calls["native_method_calls"] = get_show_NativeMethods(vmx)

                        classes = list()
                        for cls in vm.get_classes():
                            classes.append(cls.name)

                        static_calls["classes"] = classes

                else:
                    log.warning("Dex size bigger than: %s",
                                self.options.decompilation_threshold)

                apkinfo["static_method_calls"] = static_calls

        except (IOError, OSError, BadZipfile) as e:
            raise CuckooProcessingError("Error opening file %s" % e)

        return apkinfo
示例#20
0
def print_dynLoad(dx, cm):
    if analysis.is_dyn_code(dx) == True:
        OutStream.write("***dynamic code loading***\n")
        paths = dx.get_tainted_packages().search_methods(
            "Ldalvik/system/DexClassLoader;", ".", ".")
        write_Paths(paths, cm, OutStream)
示例#21
0
def performAnalysis(apkPath):

    # Perform the analysis by recalling public method of androlyze.py
    a, d, dx = androlyze.AnalyzeAPK(apkPath)

    if not a.is_valid_APK():
        print "[Exit] The selected resource is not a valid APK!"
        return sys.exit(FAILURE)

    if not analysis.is_dyn_code(dx):
        print "[Exit] No DexClassLoader use in this APK and so there is nothing to patch!"
        return sys.exit(SUCCESS)

    print "[In progress] Analyze target APK.."

    # Store app permissions (used later on while patching Android Manifest)
    app_permissions = set(a.get_permissions())

    #app_permissions.add('android.permission.ACCESS_NETWORK_STATE')
    #app_permissions.add('android.permission.BLABLABLA')

    # Reference to global variable
    missing_permissions = list()

    for current_perm in required_permissions:
        if not (current_perm in app_permissions):
            missing_permissions.append(current_perm)

    #print missing_permissions

    # Flag variable for later use
    dynamicCallsWhereTraced = False

    # Save a reference for standard output
    stdout = sys.stdout

    # Redirect output to an helper variable
    # sys.stdout = open('./dynamicCalls', 'w')
    dynamicCallsFilePath = os.curdir + os.sep + "dynamicCalls"

    with open(dynamicCallsFilePath, 'w') as dynamicCallsFile:
        # Redirect output to an helper variable
        sys.stdout = dynamicCallsFile

        # Highlight dynamic calls linked to a DexClassLoader.
        analysis.show_DynCode(dx)

        # Set back usual stdout
        sys.stdout = stdout

    with open(dynamicCallsFilePath, 'r') as dynamicCallsFile:

        #print INTEGER.parseString("1")
        #print CLASS_STRING.parseString("Lcom/example/extractapp/MainActivity;")
        #print METHOD_DECL.parseString("setUpNormal()V")
        #print NUMBER_EXA.parseString("(0x66)")
        #print CLASS_STRING.parseString("Ldalvik/system/DexClassLoader;")

        # Define a grammar to parse line of the input file.
        parsing_format = INTEGER + CLASS_STRING + "->" + METHOD_DECL + NUMBER_EXA + "--->" + CLASS_STRING + "->" + METHOD_DECL

        # Reference to global variable
        classesWithDynCodeLoad = list()

        for line in dynamicCallsFile:
            # print line
            tokens = parsing_format.parseString(line)

            # This is a sort specific parsing constant(magic numbers)..
            className = tokens[1][1]

            # Extract only name of classes to patch which are not the ones of Grab'n Run
            if className != "it/necst/grabnrun/SecureDexClassLoader":
                classesWithDynCodeLoad.append(className)

        # In the end remove duplicates from this list (use a set)
        classesWithDynCodeLoad = set(classesWithDynCodeLoad)

        # print classesWithDynCodeLoad

        # Raise flag variable
        print "[In progress] Dynamic calls have been detected.."
        dynamicCallsWhereTraced = True

    # Now the helper file should be closed and erased.
    os.remove(dynamicCallsFilePath)

    if dynamicCallsWhereTraced:
        # This APK should be patched!
        return missing_permissions, classesWithDynCodeLoad

    # Something went wrong..
    print "[Exit] Dynamic calls have not been detected!"
    return sys.exit(FAILURE)
示例#22
0
def extract_features(file_path):
    result = {}
    try:
        a = APK(file_path)
        d = DalvikVMFormat(a.get_dex())
        dx = VMAnalysis(d)
        vm = dvm.DalvikVMFormat(a.get_dex())
        vmx = analysis.uVMAnalysis(vm)
        d.set_vmanalysis(dx)
        d.set_decompiler(DecompilerDAD(d, dx))
    except:
        return None

    result['android_version_code'] = a.get_androidversion_code()
    result['android_version_name'] = a.get_androidversion_name()
    result['max_sdk'] = a.get_max_sdk_version()
    result['min_sdk'] = a.get_min_sdk_version()
    result['libraries'] = a.get_libraries()
    result['filename'] = a.get_filename()
    result['target_sdk'] = a.get_target_sdk_version()
    result['md5'] = hashlib.md5(a.get_raw()).hexdigest()
    result['sha256'] = hashlib.sha256(a.get_raw()).hexdigest()
    result['permissions'] = a.get_permissions()
    result['activities'] = a.get_activities()
    result['providers'] = a.get_providers()
    result['services'] = a.get_services()
    result['strings'] = d.get_strings()
    result['class_names'] = [c.get_name() for c in d.get_classes()]
    result['method_names'] = [m.get_name() for m in d.get_methods()]
    result['field_names'] = [f.get_name() for f in d.get_fields()]
    result['is_native_code'] = 1 if analysis.is_native_code(dx) else 0
    result['is_obfuscation'] = 1 if analysis.is_ascii_obfuscation(d) else 0
    result['is_crypto_code'] = 1 if analysis.is_crypto_code(dx) else 0
    result['is_dyn_code'] = 1 if analysis.is_dyn_code(dx) else 0
    result['is_reflection_code'] = 1 if analysis.is_reflection_code(vmx) else 0
    result['is_database'] = 1 if d.get_regex_strings(DB_REGEX) else 0

    s_list = []
    s_list.extend(result['class_names'])
    s_list.extend(result['method_names'])
    s_list.extend(result['field_names'])
    result['entropy_rate'] = entropy_rate(s_list)

    result['feature_vectors'] = {}

    # Search for the presence of api calls in a given apk
    result['feature_vectors']['api_calls'] = []
    for call in API_CALLS:
        status = 1 if dx.tainted_packages.search_methods(".", call, ".") else 0
        result['feature_vectors']['api_calls'].append(status)

    # Search for the presence of permissions in a given apk
    result['feature_vectors']['permissions'] = []
    for permission in PERMISSIONS:
        status = 1 if permission in result['permissions'] else 0
        result['feature_vectors']['permissions'].append(status)

    result['feature_vectors']['special_strings'] = []
    for word in SPECIAL_STRINGS:
        status = 1 if d.get_regex_strings(word) else 0
        result['feature_vectors']['special_strings'].append(status)

    return result
示例#23
0
 def has_dynamic(self):
     if analysis.is_dyn_code(self.dx):
         self.risk += 1
         return True
     else:
         return False
示例#24
0
def extract_features(file_path):
    result = {}
    try:
        a = APK(file_path)
        d = DalvikVMFormat(a.get_dex())
        dx = VMAnalysis(d)
        vm = dvm.DalvikVMFormat(a.get_dex())
        vmx = analysis.uVMAnalysis(vm)
        d.set_vmanalysis(dx)
        d.set_decompiler(DecompilerDAD(d, dx))
    except:
        return None

    result['android_version_code'] = a.get_androidversion_code()
    result['android_version_name'] = a.get_androidversion_name()
    result['max_sdk'] = a.get_max_sdk_version()
    result['min_sdk'] = a.get_min_sdk_version()
    result['libraries'] = a.get_libraries()
    result['filename'] = a.get_filename()
    result['target_sdk'] = a.get_target_sdk_version()
    result['md5'] = hashlib.md5(a.get_raw()).hexdigest()
    result['sha256'] = hashlib.sha256(a.get_raw()).hexdigest()
    result['permissions'] = a.get_permissions()
    result['activities'] = a.get_activities()
    result['providers'] = a.get_providers()
    result['services'] = a.get_services()
    #result['strings'] = d.get_strings()
    #result['class_names'] = [c.get_name() for c in d.get_classes()]
    #result['method_names'] = [m.get_name() for m in d.get_methods()]
    #result['field_names'] = [f.get_name() for f in d.get_fields()]
    class_names = [c.get_name() for c in d.get_classes()]
    method_names = [m.get_name() for m in d.get_methods()]
    field_names = [ f.get_name() for f in d.get_fields()]

    result['is_native_code'] = 1 if analysis.is_native_code(dx) else 0
    result['is_obfuscation'] = 1 if analysis.is_ascii_obfuscation(d) else 0
    result['is_crypto_code'] = 1 if analysis.is_crypto_code(dx) else 0
    result['is_dyn_code'] = 1 if analysis.is_dyn_code(dx) else 0
    result['is_reflection_code'] = 1 if analysis.is_reflection_code(vmx) else 0
    result['is_database'] = 1 if d.get_regex_strings(DB_REGEX) else 0

    s_list = []
    #s_list.extend(result['class_names'])
    #s_list.extend(result['method_names'])
    #s_list.extend(result['field_names'])
    s_list.extend(class_names)
    s_list.extend(method_names)
    s_list.extend(method_names)
    result['entropy_rate'] = entropy_rate(s_list)

    result['feature_vectors'] = {}

    # Search for the presence of api calls in a given apk
    result['feature_vectors']['api_calls'] = []
    for call in API_CALLS:
        status = 1 if dx.tainted_packages.search_methods(".", call, ".") else 0
        result['feature_vectors']['api_calls'].append(status)

    # Search for the presence of permissions in a given apk        
    result['feature_vectors']['permissions'] = []
    for permission in PERMISSIONS:
        status = 1 if permission in result['permissions'] else 0
        result['feature_vectors']['permissions'].append(status)

    result['feature_vectors']['special_strings'] = []
    for word in SPECIAL_STRINGS:
        status = 1 if d.get_regex_strings(word) else 0
        result['feature_vectors']['special_strings'].append(status)

    opt_seq = []
    for m in d.get_methods():
        for i in m.get_instructions():
            opt_seq.append(i.get_name())

    optngramlist = [tuple(opt_seq[i:i+NGRAM]) for i in xrange(len(opt_seq) - NGRAM)]
    optngram = Counter(optngramlist)
    optcodes = dict()
    tmpCodes = dict(optngram)
    #for k,v in optngram.iteritems():
    #    if v>=NGRAM_THRE:
            #optcodes[str(k)] = v
    #        optcodes[str(k)] = 1
    tmpCodes = sorted(tmpCodes.items(),key =lambda d:d[1],reverse=True) 
    for value in tmpCodes[:NGRAM_THRE]:
        optcodes[str(value[0])] = 1
    result['feature_vectors']['opt_codes'] = optcodes

    return result
示例#25
0
def main(options, args) :
    print options.input

    if options.input == None or options.output == None :
        print "static_analysis.py -i <inputfile> -o <outputfolder>"
        sys.exit(2)
    elif db.static_features.find({"_id": hashfile(options.input)}, limit=1).count() == 1 :
        print "static analysis found.. skipping.."
        sys.exit(0)
    elif db.virustotal_features.find({"sha1": hashfile(options.input)}).count() == 0 :
        print "virus total metadata not found.. skipping.."
        sys.exit(0)
    elif db.virustotal_features.find({ "$or": [ { "positives": 0 }, { "positives": { "$gte": 35 } } ], "sha1": hashfile(options.input) }).count() == 0 :
        print "not clear enough benign or malicious.. skipping.."
        sys.exit(0)

    t_beginning = time.time()

    ret_type = androconf.is_android( options.input ) 
    if ret_type == "APK" :
        try :
            a = apk.APK(options.input, zipmodule=2)
            if a.is_valid_APK() :

                vm = dvm.DalvikVMFormat(a.get_dex())
                vmx = analysis.uVMAnalysis(vm)

                data = {
                    '_id'                : hashfile(options.input),
                    'validApk'           : True,
                    'mainActivity'       : a.get_main_activity(),
                    'activities'         : a.get_activities(),
                    'providers'          : a.get_providers(),
                    'receivers'          : a.get_receivers(),
                    'services'           : a.get_services(),
                    'androidVersion'     : a.get_androidversion_code(),
                    'maxSdkVersion'      : a.get_max_sdk_version(),
                    'minSdkVersion'      : a.get_min_sdk_version(),
                    'targetSdkVersion'   : a.get_target_sdk_version(),
                    'package'            : a.get_package(),
                    'libraries'          : a.get_libraries(),
                    'isCryptoCode'       : analysis.is_crypto_code(vmx),
                    'isDynamicCode'      : analysis.is_dyn_code(vmx),
                    'isNativeCode'       : analysis.is_native_code(vmx),
                    'nativeMethodCount'  : native_method_count(vm),
                    'isReflectionCode'   : analysis.is_reflection_code(vmx),
                    'reflectionCount'    : len(vmx.get_tainted_packages().search_methods("Ljava/lang/reflect/Method;", ".", ".")),
                    'isAsciiObfuscation' : analysis.is_ascii_obfuscation(vm),
                    'permissions'        : a.get_permissions(),
                    'actualPermissions'  : actual_permissions(vm, vmx),
                    'internalMethodCalls' : get_methods(vm.get_class_manager(), vmx.get_tainted_packages().get_internal_packages(), {}),
                    'externalMethodCalls' : get_methods(vm.get_class_manager(), vmx.get_tainted_packages().get_external_packages(), {})
                }

                data['duration'] = time.time() - t_beginning

                db.static_features.insert(data)

            else :
                print "INVALID APK"
                data = {
                    '_id'      : hashfile(options.input),
                    'validApk' : False
                }
                db.static_features.insert(data)
        except Exception, e :
            print "ERROR", e
            import traceback
            traceback.print_exc()
示例#26
0
    def run(self):
        """Run androguard to extract static android information
                @return: list of static features
        """
        self.key = "apkinfo"
        apkinfo = {}

        if "file" not in self.task["category"] or not HAVE_ANDROGUARD:
            return

        #f = File(self.task["target"])
        #if f.get_name().endswith((".zip", ".apk")) or "zip" in f.get_type():
        if not os.path.exists(self.file_path):
            raise CuckooProcessingError("Sample file doesn't exist: \"%s\"" % self.file_path)

        apkinfo["APKiD"] = self._scan_APKiD(self.file_path)

        try:
            a = APK(self.file_path)
            if a.is_valid_APK():
                manifest = {}

                apkinfo["files"] = self._apk_files(a)
                apkinfo["encrypted_assets"] = self.find_encrypted_assets(a)
                manifest["package"] = a.get_package()
                apkinfo["hidden_payload"] = []

                for file in apkinfo["files"]:
                    if self.file_type_check(file):
                       apkinfo["hidden_payload"].append(file)

                apkinfo["files_flaged"] = self.files_name_map

                manifest["permissions"]= get_permissions(a)
                manifest["main_activity"] = a.get_main_activity()
                manifest["activities"] = a.get_activities()
                manifest["services"] = a.get_services()
                manifest["receivers"] = a.get_receivers()
                manifest["receivers_actions"] = get_extended_receivers(a)
                manifest["receivers_info"] = get_receivers_info(a)
                manifest["providers"] = a.get_providers()
                manifest["libraries"] = a.get_libraries()
                apkinfo["manifest"] = manifest

                apkinfo["icon"] = get_apk_icon(self.file_path)
                certificate = get_certificate(self.file_path)
                if certificate:
                    apkinfo["certificate"] = certificate


                #vm = DalvikVMFormat(a.get_dex())
                #strings = vm.get_strings()

                strings = self._get_strings(self.file_path)
                for subdir, dirs, files in os.walk(self.dropped_path):
                    for file in files:
                        path = os.path.join(subdir, file)
                        try:
                            extra_strings = self._get_strings(path)
                            strings = list(set(extra_strings + strings))
                        except:
                            pass

                apkinfo["dex_strings"] = strings

                static_calls = {}
                if self.options.decompilation:
                    if self.check_size(apkinfo["files"]):
                        vm = DalvikVMFormat(a.get_dex())
                        vmx = uVMAnalysis(vm)
                        # Be less verbose about androguard logging messages.
                        logging.getLogger("andro.runtime").setLevel(logging.CRITICAL)

                        static_calls["all_methods"] = get_methods(vmx)
                        static_calls["is_native_code"] = analysis.is_native_code(vmx)
                        static_calls["is_dynamic_code"] = analysis.is_dyn_code(vmx)
                        static_calls["is_reflection_code"] = analysis.is_reflection_code(vmx)
                        static_calls["is_crypto_code"] = is_crypto_code(vmx)

                        static_calls["dynamic_method_calls"] = get_show_DynCode(vmx)
                        static_calls["reflection_method_calls"] = get_show_ReflectionCode(vmx)
                        static_calls["permissions_method_calls"] = get_show_Permissions(vmx)
                        static_calls["crypto_method_calls"] = get_show_CryptoCode(vmx)
                        static_calls["native_method_calls"] = get_show_NativeMethods(vmx)

                        classes = list()
                        for cls in vm.get_classes():
                            classes.append(cls.name)

                        static_calls["classes"] = classes

                else:
                    log.warning("Dex size bigger than: %s",
                                self.options.decompilation_threshold)

                apkinfo["static_method_calls"] = static_calls

        except (IOError, OSError, BadZipfile) as e:
            raise CuckooProcessingError("Error opening file %s" % e)

        return apkinfo