Пример #1
0
    def analyzeAPK(self):
        """ Uses androguard to retrieve metadata about the app e.g. activities, permissions, intent filters, etc. """
        try:
            prettyPrint("Analyzing app")
            logEvent("Analyzing app: \"%s\"" % self.APKPath)
            # 1. Load the APK using androguard
            analysisSession = Session()
            analysisSession.add(self.APKPath, open(self.APKPath).read())
            # 2. Retrieve handles to APK and its dex code
            self.APK = analysisSession.analyzed_apk.values()[0]
            self.DEX = analysisSession.analyzed_dex.values()[0][0]
            self.VMAnalysis = analysisSession.analyzed_dex.values()[0][1]
            # 3. Retrieve information for each activity
            prettyPrint("Analyzing activities")
            self.activitiesInfo = analyzeActivities(self.APK, self.DEX)
            # 4. Do the same for services and broadcast receivers
            prettyPrint("Analyzing services")
            self.servicesInfo = analyzeServices(self.APK, self.DEX)
            prettyPrint("Analyzing broadcast receivers")
            self.receiversInfo = analyzeReceivers(self.APK, self.DEX)

        except Exception as e:
            prettyPrintError(e)
            return False

        prettyPrint("Success")
        return True
Пример #2
0
def extractStaticFeatures(apkPath):
    """Extracts static numerical features from APK using Androguard"""
    try:
        features = [[], [], [], []] # Tuples are immutable
        if os.path.exists(apkPath.replace(".apk",".static")):
            prettyPrint("Found a pre-computed static features file")
            bFeatures, pFeatures, aFeatures, allFeatures = [], [], [], []
            try:
                possibleExtensions = [".basic", ".perm", ".api", ".static"]
                for ext in possibleExtensions:
                    if os.path.exists(apkPath.replace(".apk", ext)):
                        content = open(apkPath.replace(".apk", ext)).read()
                        if len(content) > 0:
                            features[possibleExtensions.index(ext)] = [float(f) for f in content[1:-1].split(',') if len(f) > 0]

                return tuple(features)

            except Exception as e:
                prettyPrintError(e)
                prettyPrint("Could not extract features from \".static\" file. Continuing as usual", "warning")
        if verboseON():
            prettyPrint("Starting analysis on \"%s\"" % apkPath, "debug")
        analysisSession = Session()
        if not os.path.exists(apkPath):
            prettyPrint("Could not find the APK file \"%s\"" % apkPath, "warning")
            return [], [], [], []
        # 1. Analyze APK and retrieve its components
        #t = threading.Timer(300.0, returnEmptyFeatures) # Guarantees not being stuck on analyzing an APK
        #t.start()
        analysisSession.add(apkPath, open(apkPath).read())
        if type(analysisSession.analyzed_apk.values()) == list:
            apk = analysisSession.analyzed_apk.values()[0][0]
        else:
            apk = analysisSession.analyzed_apk.values()[0]
        dex = analysisSession.analyzed_dex.values()[0][0]
        vm = analysisSession.analyzed_dex.values()[0][1]
        # 2. Add features to the features vector
        basicFeatures, permissionFeatures, apiCallFeatures, allFeatures = [], [], [], []
        # 2.a. The APK-related features
        if verboseON():
            prettyPrint("Extracting basic features", "debug")
        minSDKVersion = 0.0 if not apk.get_min_sdk_version() else float(apk.get_min_sdk_version())
        maxSDKVersion = 0.0 if not apk.get_max_sdk_version() else float(apk.get_max_sdk_version())
        basicFeatures.append(minSDKVersion)
        basicFeatures.append(maxSDKVersion)
        basicFeatures.append(float(len(apk.get_activities()))) # No. of activities
        basicFeatures.append(float(len(apk.get_services()))) # No. of services
        basicFeatures.append(float(len(apk.get_receivers()))) # No. of broadcast receivers
        basicFeatures.append(float(len(apk.get_providers()))) # No. of providers
        # 2.b. Harvest permission-related features
        if verboseON():
            prettyPrint("Extracting permissions-related features", "debug")
        aospPermissions = float(len(apk.get_requested_aosp_permissions())) # Android permissions requested by the app
        declaredPermissions = float(len(apk.get_declared_permissions())) # Custom permissions declared by the app
        dangerousPermissions = float(len([p for p in apk.get_requested_aosp_permissions_details().values() if p["protectionLevel"] == "dangerous"]))
        totalPermissions = float(len(apk.get_permissions()))
        permissionFeatures.append(totalPermissions) # No. of permissions
        if totalPermissions > 0:
            permissionFeatures.append(aospPermissions/totalPermissions) # AOSP permissions : Total permissions
            permissionFeatures.append(declaredPermissions/totalPermissions) # Third-party permissions : Total permissions
            permissionFeatures.append(dangerousPermissions/totalPermissions) # Dangerous permissions : Total permissions
        else:
            permissionFeatures.append(0.0)
            permissionFeatures.append(0.0)
            permissionFeatures.append(0.0)
        # 2.c. The DEX-related features (API calls)
        if verboseON():
            prettyPrint("Extracting API calls from dex code", "debug")
        apiCallFeatures.append(float(len(dex.get_classes()))) # Total number of classes
        apiCallFeatures.append(float(len(dex.get_strings()))) # Total number of strings
        apiCategories = sensitiveAPICalls.keys()
        apiCategoryCount = [0.0] * len(apiCategories)
        for c in dex.classes.get_names():
            currentClass = dex.get_class(c)
            if not currentClass:
                continue
            code = currentClass.get_source()
            if len(code) < 1:
                continue
            for category in apiCategories:
                if code.find(category) != -1:
                    for call in sensitiveAPICalls[category]:
                        apiCategoryCount[apiCategories.index(category)] += float(len(re.findall(call, code)))

        apiCallFeatures += apiCategoryCount

    except Exception as e:
        prettyPrintError(e)
        return [], [], [], []
    
    allFeatures = basicFeatures + permissionFeatures + apiCallFeatures

    return basicFeatures, permissionFeatures, apiCallFeatures, allFeatures
Пример #3
0
    def run(self):
        """
        Runs the Droidutan test against the [processTarget] for [processDuration]
        """
        try:
            # A timer to guarante the process exits
            if verboseON():
                prettyPrint(
                    "Setting timer for %s seconds" %
                    str(float(self.processDuration) * 5.0), "debug")
            t = threading.Timer(float(self.processDuration) * 5.0, self.stop)
            t.start()
            # Step 1. Analyze APK
            #APKType = "malware" if self.processTarget.find("malware") != -1 else "goodware"
            if verboseON():
                prettyPrint("Analyzing APK: \"%s\"" % self.processTarget,
                            "debug")
            s = Session()
            s.add(self.processTarget, open(self.processTarget).read())
            if len(s.analyzed_apk.values()) > 0:
                apk = s.analyzed_apk.values()[0]
                if type(apk) == list:
                    apk = s.analyzed_apk.values()[0][0]
            else:
                prettyPrint("Could not retrieve an APK to analyze. Skipping",
                            "warning")
                return False

            # Step 2. Get the Ip address assigned to the AVD
            getAVDIPCmd = [
                "VBoxManage", "guestproperty", "enumerate", self.processVM
            ]
            avdIP = ""
            result = subprocess.Popen(
                getAVDIPCmd, stderr=subprocess.STDOUT,
                stdout=subprocess.PIPE).communicate()[0].replace(' ', '')
            if result.lower().find("error") != -1:
                prettyPrint("Unable to retrieve the IP address of the AVD",
                            "error")
                print result
                return False
            index = result.find("androvm_ip_management,value:") + len(
                "androvm_ip_management,value:")
            while result[index] != ',':
                avdIP += result[index]
                index += 1
            adbID = "%s:5555" % avdIP

            # Step 3. Define frequently-used commands
            droidbotOut = self.processTarget.replace(".apk", "_droidbot")
            droidbotCmd = [
                "droidbot", "-d", adbID, "-a", self.processTarget, "-o",
                droidbotOut, "-timeout",
                str(self.processDuration), "-random", "-keep_env",
                "-grant_perm"
            ]

            # Step 4. Test the APK using Droidbot (Assuming machine is already on)
            prettyPrint("Testing the APK \"%s\" using Droidbot" % apk.package)
            # 4.a. Start Droidbot
            status = subprocess.Popen(droidbotCmd,
                                      stderr=subprocess.STDOUT,
                                      stdout=subprocess.PIPE).communicate()[0]

            # 4.b. Check for existence of output directory
            if not os.path.exists(droidbotOut):
                prettyPrint(
                    "No output folder found for \"%s\"" % self.processTarget,
                    "warning")
                return False

            # 4.c. Filter the logcat dumped by droidbot
            logFile = open("%s/logcat_filtered.log" % droidbotOut, "w")
            catlog = subprocess.Popen(("cat", "%s/logcat.txt" % droidbotOut),
                                      stdout=subprocess.PIPE)
            output = subprocess.check_output(
                ("grep", "-i", "droidmon-apimonitor-%s" % apk.package),
                stdin=catlog.stdout)
            logFile.write(output)
            logFile.close()

        except subprocess.CalledProcessError as cpe:
            prettyPrint(
                "Unable to find the tag \"Droidmon-apimonitor-%s\" in the log file"
                % apk.package, "warning")
        except Exception as e:
            prettyPrintError(e)
            return False

        return True
Пример #4
0
def display_PERMISSION(a, x, classes):
    # Show methods used by permission
    perms_access = x.get_tainted_packages().get_permissions([])
    for perm in perms_access:
        print("PERM : ", perm)
        analysis.show_Paths(a, perms_access[perm])


def display_OBJECT_CREATED(a, x, class_name):
    print("Search object", class_name)
    analysis.show_Paths(a, x.get_tainted_packages().search_objects(class_name))


s = Session()
with open(TEST, "r") as fd:
    s.add(TEST, fd.read())

a, d, dx = s.get_objects_apk(TEST)

print(d.get_strings())
print(d.get_regex_strings("access"))
print(d.get_regex_strings("(long).*2"))
print(d.get_regex_strings(".*(t\_t).*"))

classes = d.get_classes_names()

display_CFG(d, dx, classes)
display_STRINGS(dx)
display_FIELDS(d, dx)
display_PACKAGES(d, dx)
display_PACKAGES_IE(d, dx)
Пример #5
0
def display_PERMISSION(a, x, classes):
    # Show methods used by permission
    perms_access = x.get_tainted_packages().get_permissions([])
    for perm in perms_access:
        print("PERM : ", perm)
        analysis.show_Paths(a, perms_access[perm])


def display_OBJECT_CREATED(a, x, class_name):
    print("Search object", class_name)
    analysis.show_Paths(a, x.get_tainted_packages().search_objects(class_name))


s = Session()
with open(TEST, "r") as fd:
    s.add(TEST, fd.read())

a, d, dx = s.get_objects_apk(TEST)

print(d.get_strings())
print(d.get_regex_strings("access"))
print(d.get_regex_strings("(long).*2"))
print(d.get_regex_strings(".*(t\_t).*"))

classes = d.get_classes_names()

display_CFG(d, dx, classes)
display_STRINGS(dx)
display_FIELDS(d, dx)
display_PACKAGES(d, dx)
display_PACKAGES_IE(d, dx)