from apk_wrapper import APKWrapper, APKWrapperError from common import Logger, LogLevel, TaintLogActionEnum, TaintTagEnum, Utils from taintlog_analyzer import TaintLogAnalyzer, TaintLogAnalyzerError from taintlog_json import * from optparse import OptionParser import copy import datetime import os import shutil # ================================================================================ # Analyzer # ================================================================================ class Analyzer: def __init__(self, theDirs, theMode=0, theSdkPath=None): self.dirs = theDirs self.mode = theMode self.sdkPath = theSdkPath self.latexFile = None self.baseAppDir = None self.printDictFile = None self.htmlOutputDir = None self.reportAppDir = None def getRuntime(self, theObj): startTime = datetime.datetime(int(theObj.startTime[0:4]), int(theObj.startTime[4:6]), int(theObj.startTime[6:8]), int(theObj.startTime[9:11]), int(theObj.startTime[11:13]), int(theObj.startTime[13:15])) endTime = datetime.datetime(int(theObj.endTime[0:4]), int(theObj.endTime[4:6]), int(theObj.endTime[6:8]), int(theObj.endTime[9:11]), int(theObj.endTime[11:13]), int(theObj.endTime[13:15])) timeDiff = endTime - startTime return timeDiff def getMainReport(self, theDir, theFactory): reportFileName = os.path.join(theDir, 'report.json') if os.path.exists(reportFileName): reportFile = open(reportFileName, 'r') reportJson = reportFile.read() report = theFactory.json2Py(reportJson) return report else: report = MainReportEntry() timeNow = datetime.datetime.now() report.startTime = '%s %s' % (Utils.getDateAsString(timeNow), Utils.getTimeAsString(timeNow)) report.endTime = '%s %s' % (Utils.getDateAsString(timeNow), Utils.getTimeAsString(timeNow)) fileNameList = os.listdir(theDir) for logcatFile in fileNameList: if logcatFile.endswith('_logcat.log'): logcatFileNameParts = logcatFile.split('_') apkName = '' for i in xrange(len(logcatFileNameParts) - 2): if i > 0: apkName += '_' apkName += logcatFileNameParts[i] apkName += '.apk' apk = self.getAppApk(apkName) appReportEntry = AppReportEntry() appReportEntry.id = int(logcatFileNameParts[-2]) appReportEntry.appPackage = apk.getPackage() appReportEntry.appPath = apkName appReportEntry.md5Hash = apk.getMd5Hash() appReportEntry.logcatFile = logcatFile appReportEntry.startTime = '%s %s' % (Utils.getDateAsString(timeNow), Utils.getTimeAsString(timeNow)) appReportEntry.endTime = '%s %s' % (Utils.getDateAsString(timeNow), Utils.getTimeAsString(timeNow)) report.appList.append(appReportEntry) return report def getAppTaintLog(self, theDir, theLogcatFile): logcatFileParts = theLogcatFile.split('/') if len(logcatFileParts) < 2: logcatFile = os.path.join(theDir, theLogcatFile) else: logcatFile = os.path.join(theDir, logcatFileParts[1]) logAnalyzer1 = TaintLogAnalyzer(theLogger=Logger(theLevel=LogLevel.ERROR)) try: logAnalyzer1.setLogFile(logcatFile) except IOError, ioErr: #raw_input('getAppTaintLog::IOError') return None logAnalyzer1.extractLogEntries() logAnalyzer2 = TaintLogAnalyzer(theLogger=Logger(theLevel=LogLevel.ERROR)) logAnalyzer2.setLogFile(logcatFile) logAnalyzer2.numControlChars = 2 logAnalyzer2.extractLogEntries() #print len(logAnalyzer1.getLogEntryList()) #print len(logAnalyzer1.getJson2PyFailedList()) #print '2: ', len(logAnalyzer2.getLogEntryList()) #print len(logAnalyzer2.getJson2PyFailedList()) #raw_input('xx') if len(logAnalyzer1.getLogEntryList()) > len(logAnalyzer2.getLogEntryList()) and \ len(logAnalyzer1.getJson2PyFailedList()) < len(logAnalyzer2.getJson2PyFailedList()): logAnalyzer = logAnalyzer1 else: logAnalyzer = logAnalyzer2 #if len(logAnalyzer.getLogEntryList()) == 0: # logAnalyzer.numControlChars = 2 # logAnalyzer.extractLogEntries() #if len(logAnalyzer.getLogEntryList()) == 0: #raw_input('XX') # pass logAnalyzer.postProcessLogObjects() return logAnalyzer def getAppApk(self, theAppPath): baseAppDir = '' if self.baseAppDir is None: baseAppDir = '/home/daniel/Documents/Malware/thesis_analysis' else: baseAppDir = self.baseAppDir appPathParts = theAppPath.split('/') appName = appPathParts[-1] apkWrapper = APKWrapper(os.path.join(baseAppDir, appName), theSdkPath=self.sdkPath) return apkWrapper def printToLatexFile(self, theFile, theDict): pass INITIAL_NUMBERS_DICT = {'noTag':[0,[]], 'contact':[0,[]], 'deviceInfos':[0,[]], 'userInput':[0,[]], 'incomingData':[0,[]], 'location':[0,[]], 'other':[0,[]], 'nothing':[0,[]]} def evalTagNumbers(self, theTaintLog, theApk, theBaseObj, theNumbers, theReportMode=False): oneMatch = False noTag = copy.deepcopy(theBaseObj) noTag.tag = -1 if theTaintLog.doesMatch([noTag]): if theReportMode: theNumbers['noTag'][0] += len(theTaintLog.getMatchingLogEntries([noTag])) else: theNumbers['noTag'][0] += 1 theNumbers['noTag'][1].append(theApk) oneMatch = True if isinstance(theBaseObj, CallActionLogEntry) and oneMatch: for key, value in self.INITIAL_NUMBERS_DICT.iteritems(): if key != 'noTag' and key != 'nothing': theNumbers[key][0] -= 1 contact = copy.deepcopy(theBaseObj) contact.tagList.append(TaintTagEnum.TAINT_CONTACTS) if theTaintLog.doesMatch([contact]): if theReportMode: theNumbers['contact'][0] += len(theTaintLog.getMatchingLogEntries([contact])) else: theNumbers['contact'][0] += 1 theNumbers['contact'][1].append(theApk) oneMatch = True deviceInfos = copy.deepcopy(theBaseObj) deviceInfos.tagList.append(TaintTagEnum.TAINT_PHONE_NUMBER) deviceInfos.tagList.append(TaintTagEnum.TAINT_IMEI) deviceInfos.tagList.append(TaintTagEnum.TAINT_IMSI) deviceInfos.tagList.append(TaintTagEnum.TAINT_ICCID) deviceInfos.tagList.append(TaintTagEnum.TAINT_DEVICE_SN) if theTaintLog.doesMatch([deviceInfos]): if theReportMode: theNumbers['deviceInfos'][0] += len(theTaintLog.getMatchingLogEntries([deviceInfos])) else: theNumbers['deviceInfos'][0] += 1 theNumbers['deviceInfos'][1].append(theApk) oneMatch = True userInput = copy.deepcopy(theBaseObj) userInput.tagList.append(TaintTagEnum.TAINT_USER_INPUT) if theTaintLog.doesMatch([userInput]): if theReportMode: theNumbers['userInput'][0] += len(theTaintLog.getMatchingLogEntries([userInput])) else: theNumbers['userInput'][0] += 1 theNumbers['userInput'][1].append(theApk) oneMatch = True incomingData = copy.deepcopy(theBaseObj) incomingData.tagList.append(TaintTagEnum.TAINT_INCOMING_DATA) if theTaintLog.doesMatch([incomingData]): if theReportMode: theNumbers['incomingData'][0] += len(theTaintLog.getMatchingLogEntries([incomingData])) else: theNumbers['incomingData'][0] += 1 theNumbers['incomingData'][1].append(theApk) oneMatch = True location = copy.deepcopy(theBaseObj) location.tagList.append(TaintTagEnum.TAINT_LOCATION) location.tagList.append(TaintTagEnum.TAINT_LOCATION_GPS) location.tagList.append(TaintTagEnum.TAINT_LOCATION_NET) location.tagList.append(TaintTagEnum.TAINT_LOCATION_LAST) if theTaintLog.doesMatch([location]): if theReportMode: theNumbers['location'][0] += len(theTaintLog.getMatchingLogEntries([location])) else: theNumbers['location'][0] += 1 theNumbers['location'][1].append(theApk) oneMatch = True other = copy.deepcopy(theBaseObj) other.tagList.append(TaintTagEnum.TAINT_MIC) other.tagList.append(TaintTagEnum.TAINT_CAMERA) other.tagList.append(TaintTagEnum.TAINT_ACCELEROMETER) other.tagList.append(TaintTagEnum.TAINT_HISTORY) other.tagList.append(TaintTagEnum.TAINT_MEDIA) other.tagList.append(TaintTagEnum.TAINT_SMS) if theTaintLog.doesMatch([other]): if theReportMode: theNumbers['other'][0] += len(theTaintLog.getMatchingLogEntries([other])) else: theNumbers['other'][0] += 1 theNumbers['other'][1].append(theApk) oneMatch = True if not oneMatch: theNumbers['nothing'][0] += 1 if theReportMode: theNumbers['nothing'][1].append(theApk) return oneMatch def evalSmsDestTagNumbers(self, theTaintLog, theApk, theBaseObj, theNumbers, theReportMode=False): oneMatch = False noTag = copy.deepcopy(theBaseObj) noTag.destinationTag = -1 if theTaintLog.doesMatch([noTag]): if theReportMode: theNumbers['noTag'][0] += len(theTaintLog.getMatchingLogEntries([noTag])) else: theNumbers['noTag'][0] += 1 theNumbers['noTag'][1].append(theApk) oneMatch = True contact = copy.deepcopy(theBaseObj) contact.destinationTagList.append(TaintTagEnum.TAINT_CONTACTS) if theTaintLog.doesMatch([contact]): if theReportMode: theNumbers['contact'][0] += len(theTaintLog.getMatchingLogEntries([contact])) else: theNumbers['contact'][0] += 1 theNumbers['contact'][1].append(theApk) oneMatch = True deviceInfos = copy.deepcopy(theBaseObj) deviceInfos.destinationTagList.append(TaintTagEnum.TAINT_PHONE_NUMBER) deviceInfos.destinationTagList.append(TaintTagEnum.TAINT_IMEI) deviceInfos.destinationTagList.append(TaintTagEnum.TAINT_IMSI) deviceInfos.destinationTagList.append(TaintTagEnum.TAINT_ICCID) deviceInfos.destinationTagList.append(TaintTagEnum.TAINT_DEVICE_SN) if theTaintLog.doesMatch([deviceInfos]): if theReportMode: theNumbers['deviceInfos'][0] += len(theTaintLog.getMatchingLogEntries([deviceInfos])) else: theNumbers['deviceInfos'][0] += 1 theNumbers['deviceInfos'][1].append(theApk) oneMatch = True userInput = copy.deepcopy(theBaseObj) userInput.destinationTagList.append(TaintTagEnum.TAINT_USER_INPUT) if theTaintLog.doesMatch([userInput]): if theReportMode: theNumbers['userInput'][0] += len(theTaintLog.getMatchingLogEntries([userInput])) else: theNumbers['userInput'][0] += 1 theNumbers['userInput'][1].append(theApk) oneMatch = True incomingData = copy.deepcopy(theBaseObj) incomingData.destinationTagList.append(TaintTagEnum.TAINT_INCOMING_DATA) if theTaintLog.doesMatch([incomingData]): if theReportMode: theNumbers['incomingData'][0] += len(theTaintLog.getMatchingLogEntries([incomingData])) else: theNumbers['incomingData'][0] += 1 theNumbers['incomingData'][1].append(theApk) oneMatch = True location = copy.deepcopy(theBaseObj) location.destinationTagList.append(TaintTagEnum.TAINT_LOCATION) location.destinationTagList.append(TaintTagEnum.TAINT_LOCATION_GPS) location.destinationTagList.append(TaintTagEnum.TAINT_LOCATION_NET) location.destinationTagList.append(TaintTagEnum.TAINT_LOCATION_LAST) if theTaintLog.doesMatch([location]): if theReportMode: theNumbers['location'][0] += len(theTaintLog.getMatchingLogEntries([location])) else: theNumbers['location'][0] += 1 theNumbers['location'][1].append(theApk) oneMatch = True other = copy.deepcopy(theBaseObj) other.destinationTagList.append(TaintTagEnum.TAINT_MIC) other.destinationTagList.append(TaintTagEnum.TAINT_CAMERA) other.destinationTagList.append(TaintTagEnum.TAINT_ACCELEROMETER) other.destinationTagList.append(TaintTagEnum.TAINT_HISTORY) other.destinationTagList.append(TaintTagEnum.TAINT_MEDIA) other.destinationTagList.append(TaintTagEnum.TAINT_SMS) if theTaintLog.doesMatch([other]): if theReportMode: theNumbers['other'][0] += len(theTaintLog.getMatchingLogEntries([other])) else: theNumbers['other'][0] += 1 theNumbers['other'][1].append(theApk) oneMatch = True if not oneMatch: theNumbers['nothing'][0] += 1 if theReportMode: theNumbers['nothing'][1].append(theApk) return oneMatch def printNumbers(self, theNumbers): for key, numbers in theNumbers['numbers'].iteritems(): numberStr = '' for number, value in numbers.iteritems(): numberStr += '%s: %d, ' % (number, value[0]) print '- %s: %s' % (key, numberStr) print '- Nothing at all: %d' % theNumbers['nothing'][0] print '- Errors: %d' % theNumbers['error'][0] def consolidateResultDicts(self, theResultDicts): # Init overall list resultDict = {} resultDict['appList'] = [] resultDict['numbers'] = {'sms' : copy.deepcopy(self.INITIAL_NUMBERS_DICT), 'smsDest' : copy.deepcopy(self.INITIAL_NUMBERS_DICT), 'call' : copy.deepcopy(self.INITIAL_NUMBERS_DICT), 'netRead' : copy.deepcopy(self.INITIAL_NUMBERS_DICT), 'netWrite' : copy.deepcopy(self.INITIAL_NUMBERS_DICT), 'fsRead' : copy.deepcopy(self.INITIAL_NUMBERS_DICT), 'fsWrite' : copy.deepcopy(self.INITIAL_NUMBERS_DICT), 'cipher' : copy.deepcopy(self.INITIAL_NUMBERS_DICT), 'ssl' : copy.deepcopy(self.INITIAL_NUMBERS_DICT)} resultDict['nothing'] = [0, []] resultDict['error'] = [0, []] numAnalyzeRuns = 0 overallRuntime = 0 # Analyzed apps -> Do be removed from nothing and error analyzedApps = [] # For result dicts for resultDictPart in theResultDicts: # Runtime infos numAnalyzeRuns += len(resultDictPart['mainReport'].appList) overallRuntime += self.getRuntime(resultDictPart['mainReport']).seconds # Consolidate numbers for key, numbers in resultDictPart['numbers'].iteritems(): for number, value in numbers.iteritems(): for app in value[1]: md5 = app.getMd5Hash() # Add to app list if not md5 in resultDict['appList']: resultDict['appList'].append(md5) # Add to analyzed list if not md5 in analyzedApps: analyzedApps.append(md5) # Add to numbers if not md5 in resultDict['numbers'][key][number][1]: resultDict['numbers'][key][number][0] += 1 resultDict['numbers'][key][number][1].append(md5) # Nothing for app in resultDictPart['nothing'][1]: md5 = app.getMd5Hash() if not md5 in resultDict['appList']: resultDict['appList'].append(md5) if not md5 in resultDict['nothing'][1]: resultDict['nothing'][0] += 1 resultDict['nothing'][1].append(md5) # Errors for app in resultDictPart['error'][1]: md5 = app.getMd5Hash() if not md5 in resultDict['appList']: resultDict['appList'].append(md5) if not md5 in resultDict['error'][1]: resultDict['error'][0] += 1 resultDict['error'][1].append(md5) # CleanUp nothing (dict) for key, numbers in resultDict['numbers'].iteritems(): deleteIdxList = [] idx = 0 for app in numbers['nothing'][1]: foundFlag = False for number, value in numbers.iteritems(): if number == 'nothing': continue if app in value[1]: foundFlag = True break if foundFlag: deleteIdxList.append(idx) idx += 1 deleteIdxList.sort() for i in xrange(len(deleteIdxList)): numbers['nothing'][0] -= 1 del numbers['nothing'][1][deleteIdxList[i] - i] # CleanUp nothing (main) deleteIdxList = [] idx = 0 for app in resultDict['nothing'][1]: if app in analyzedApps: deleteIdxList.append(idx) idx += 1 deleteIdxList.sort() for i in xrange(len(deleteIdxList)): resultDict['nothing'][0] -= 1 del resultDict['nothing'][1][deleteIdxList[i] - i] # CleanUp error deleteIdxList = [] idx = 0 for app in resultDict['error'][1]: if app in analyzedApps: deleteIdxList.append(idx) idx += 1 deleteIdxList.sort() for i in xrange(len(deleteIdxList)): resultDict['error'][0] -= 1 del resultDict['error'][1][deleteIdxList[i] - i] # Fill main list resultDict['avgAppRuntime'] = overallRuntime / numAnalyzeRuns return resultDict def analyzeMain(self, theDir): # Factory jsonFactory = JsonFactory() # Read main report file mainReport = self.getMainReport(theDir, jsonFactory) # Patterns filterList = [ NetworkSendLogEntry(action=0, tagList=[], destination='unknown', port=123, stackTraceStr=''), FileSystemLogEntry(action=0, tagList=[], filePath='/data/data/com.android.music/shared_prefs/Music.xml', stackTraceStr='') ] callPatterns = [ CallActionLogEntry(dialString='') # 15555218135 ] # Analyze apps numApps = 0 resultDict = {'numbers' : {'sms' : copy.deepcopy(self.INITIAL_NUMBERS_DICT), 'smsDest' : copy.deepcopy(self.INITIAL_NUMBERS_DICT), 'call' : copy.deepcopy(self.INITIAL_NUMBERS_DICT), 'netRead' : copy.deepcopy(self.INITIAL_NUMBERS_DICT), 'netWrite' : copy.deepcopy(self.INITIAL_NUMBERS_DICT), 'fsRead' : copy.deepcopy(self.INITIAL_NUMBERS_DICT), 'fsWrite' : copy.deepcopy(self.INITIAL_NUMBERS_DICT), 'cipher' : copy.deepcopy(self.INITIAL_NUMBERS_DICT), 'ssl' : copy.deepcopy(self.INITIAL_NUMBERS_DICT)}, 'nothing' : [0, []], 'error' : [0, []], 'mainReport' : mainReport} for appReport in mainReport.appList: apk = self.getAppApk(appReport.appPath) taintLog = self.getAppTaintLog(theDir, appReport.logcatFile) if not taintLog is None: numApps += 1 # increase counter #taintLog.printOverview() taintLog.filterLogObjects(filterList) # filter for recurring patterns #if taintLog.doesMatch(notInstrumentedPatterns): # check for not instrumented patters # taintLog.printOverview() # print '--------------------' # Get numbers for overview table (eval calls) oneMatch = self.evalTagNumbers(taintLog, apk, CallActionLogEntry(tagList=[]), resultDict['numbers']['call']) oneMatch |= self.evalTagNumbers(taintLog, apk, CipherUsageLogEntry(tagList=[]), resultDict['numbers']['cipher']) oneMatch |= self.evalTagNumbers(taintLog, apk, FileSystemLogEntry(actionList=[TaintLogActionEnum.FS_READ_ACTION, TaintLogActionEnum.FS_READ_DIRECT_ACTION, TaintLogActionEnum.FS_READV_ACTION], tagList=[]), resultDict['numbers']['fsRead']) oneMatch |= self.evalTagNumbers(taintLog, apk, FileSystemLogEntry(actionList=[TaintLogActionEnum.FS_WRITE_ACTION, TaintLogActionEnum.FS_WRITE_DIRECT_ACTION, TaintLogActionEnum.FS_WRITEV_ACTION], tagList=[]), resultDict['numbers']['fsWrite']) oneMatch |= self.evalTagNumbers(taintLog, apk, NetworkSendLogEntry(actionList=[TaintLogActionEnum.NET_READ_ACTION, TaintLogActionEnum.NET_READ_DIRECT_ACTION, TaintLogActionEnum.NET_RECV_ACTION, TaintLogActionEnum.NET_RECV_DIRECT_ACTION], tagList=[]), resultDict['numbers']['netRead']) oneMatch |= self.evalTagNumbers(taintLog, apk, NetworkSendLogEntry(actionList=[TaintLogActionEnum.NET_SEND_ACTION, TaintLogActionEnum.NET_SEND_DIRECT_ACTION, TaintLogActionEnum.NET_SEND_URGENT_ACTION, TaintLogActionEnum.NET_WRITE_ACTION, TaintLogActionEnum.NET_WRITE_DIRECT_ACTION], tagList=[]), resultDict['numbers']['netWrite']) oneMatch |= self.evalTagNumbers(taintLog, apk, SSLLogEntry(tagList=[]), resultDict['numbers']['ssl']) oneMatch |= self.evalTagNumbers(taintLog, apk, SendSmsLogEntry(tagList=[]), resultDict['numbers']['sms']) oneMatch |= self.evalSmsDestTagNumbers(taintLog, apk, SendSmsLogEntry(destinationTagList=[]), resultDict['numbers']['smsDest']) # Nothing happens if not oneMatch: resultDict['nothing'][0] += 1 resultDict['nothing'][1].append(apk) else: resultDict['error'][0] += 1 resultDict['error'][1].append(apk) # Return return resultDict def analyzeModeNumbers(self): # Do main analysis resultDictList = [] for directory in self.dirs: resultDict = self.analyzeMain(directory) resultDictList.append(resultDict) # Print results idx = 0 for resultDict in resultDictList: # Print overview print '\n--------------------' print 'Folder: %s' % self.dirs[idx] idx += 1 print '- %d apps were analyzed' % (len(resultDict['mainReport'].appList)) print '- Runtime report: %s - %s (%s)' % (str(resultDict['mainReport'].startTime), str(resultDict['mainReport'].endTime), self.getRuntime(resultDict['mainReport'])) avgAppRuntime = self.getRuntime(resultDict['mainReport']).seconds/len(resultDict['mainReport'].appList) avgAppRuntimeMin = avgAppRuntime / 60 avgAppRuntimeSecs = avgAppRuntime - (avgAppRuntimeMin * 60) print '- Average analyze runtime: %dsecs (%02d:%02d)' % (avgAppRuntime, avgAppRuntimeMin, avgAppRuntimeSecs) self.printNumbers(resultDict) # Consolidate results resultDict = self.consolidateResultDicts(resultDictList) # Print overview print '\n--------------------\nMain Result' print '- %d apps were analyzed' % (len(resultDict['appList'])) avgAppRuntime = resultDict['avgAppRuntime'] avgAppRuntimeMin = avgAppRuntime / 60 avgAppRuntimeSecs = avgAppRuntime - (avgAppRuntimeMin * 60) print '- Average analyze runtime: %dsecs (%02d:%02d)' % (avgAppRuntime, avgAppRuntimeMin, avgAppRuntimeSecs) self.printNumbers(resultDict) # Store in file if not self.printDictFile is None: dictFile = open(self.printDictFile, 'w') dictFile.write(str(resultDict)) def analyzeModeDetails(self): # Factory jsonFactory = JsonFactory() numberList = {} smsDestList = {} filePathList = {} networkWriteDestList = {} networkReadSourceList = {} for directory in self.dirs: # Read main report file mainReport = self.getMainReport(directory, jsonFactory) # Patterns filterList = [ NetworkSendLogEntry(action=0, tagList=[], destination='unknown', port=123, stackTraceStr=''), FileSystemLogEntry(action=0, tagList=[], filePath='/data/data/com.android.music/shared_prefs/Music.xml', stackTraceStr='') ] for appReport in mainReport.appList: apk = self.getAppApk(appReport.appPath) md5 = apk.getMd5Hash() taintLog = self.getAppTaintLog(directory, appReport.logcatFile) if not taintLog is None: taintLog.filterLogObjects(filterList) # filter for recurring patterns # Call gsmEntries = taintLog.getLogEntryList(CallActionLogEntry) for gsmEntry in gsmEntries: if not numberList.has_key(gsmEntry.dialString): numberList[gsmEntry.dialString] = [1, [md5]] else: numberList[gsmEntry.dialString][0] += 1 if not md5 in numberList[gsmEntry.dialString][1]: numberList[gsmEntry.dialString][1].append(md5) # SMS smsEntries = taintLog.getLogEntryList(SendSmsLogEntry) for smsEntry in smsEntries: if not smsDestList.has_key(smsEntry.destination): smsDestList[smsEntry.destination] = [1, [md5]] else: smsDestList[smsEntry.destination][0] += 1 if not md5 in smsDestList[smsEntry.destination][1]: smsDestList[smsEntry.destination][1].append(md5) # File paths fileEntries = taintLog.getLogEntryList(FileSystemLogEntry) for fileEntry in fileEntries: if not filePathList.has_key(fileEntry.filePath): filePathList[fileEntry.filePath] = [1, [md5]] else: filePathList[fileEntry.filePath][0] += 1 if not md5 in filePathList[fileEntry.filePath][1]: filePathList[fileEntry.filePath][1].append(md5) # Network write dest networkEntries = taintLog.getLogEntryList(NetworkSendLogEntry) for networkEntry in networkEntries: if networkEntry.doesMatch(NetworkSendLogEntry(actionList=[TaintLogActionEnum.NET_READ_ACTION, TaintLogActionEnum.NET_READ_DIRECT_ACTION, TaintLogActionEnum.NET_RECV_ACTION, TaintLogActionEnum.NET_RECV_DIRECT_ACTION], tagList=[])): if not networkReadSourceList.has_key(networkEntry.destination): networkReadSourceList[networkEntry.destination] = [1, [md5]] else: networkReadSourceList[networkEntry.destination][0] += 1 if not md5 in networkReadSourceList[networkEntry.destination][1]: networkReadSourceList[networkEntry.destination][1].append(md5) else: if not networkWriteDestList.has_key(networkEntry.destination): networkWriteDestList[networkEntry.destination] = [1, [md5]] else: networkWriteDestList[networkEntry.destination][0] += 1 if not md5 in networkWriteDestList[networkEntry.destination][1]: networkWriteDestList[networkEntry.destination][1].append(md5) sslEntries = taintLog.getLogEntryList(SSLLogEntry) for sslEntry in sslEntries: if sslEntry.action == TaintLogActionEnum.SSL_READ_ACTION: if not networkReadSourceList.has_key(sslEntry.destination): networkReadSourceList[sslEntry.destination] = [1, [md5]] else: networkReadSourceList[sslEntry.destination][0] += 1 if not md5 in networkReadSourceList[sslEntry.destination][1]: networkReadSourceList[sslEntry.destination][1].append(md5) else: if not networkWriteDestList.has_key(sslEntry.destination): networkWriteDestList[sslEntry.destination] = [1, [md5]] else: networkWriteDestList[sslEntry.destination][0] += 1 if not md5 in networkWriteDestList[sslEntry.destination][1]: networkWriteDestList[sslEntry.destination][1].append(md5) print '------------------' print 'Dial strings' for entry, value in numberList.iteritems(): print '- %s (%d, distinct: %d)' % (entry, value[0], int(len(value[1]))) print '-------------------' print 'SMS destinations' for entry, value in smsDestList.iteritems(): print '- %s (%d, distinct: %d)' % (entry, value[0], int(len(value[1]))) print '-------------------' print 'File paths' for entry, value in filePathList.iteritems(): print '- %s (%d, distinct: %d)' % (entry, value[0], int(len(value[1]))) print '-------------------' print 'Network (write) destinations' for entry, value in networkReadSourceList.iteritems(): print '- %s (%d, distinct: %d)' % (entry, value[0], int(len(value[1]))) print '-------------------' print 'Network (read) sources' for entry, value in networkWriteDestList.iteritems(): print '- %s (%d, distinct: %d)' % (entry, value[0], int(len(value[1]))) def generateList(self): alreadyVisited = [] appList = [] jsonFactory = JsonFactory() for directory in self.dirs: mainReport = self.getMainReport(directory, jsonFactory) for appReport in mainReport.appList: apk = self.getAppApk(appReport.appPath) targetName = '%s-%s.apk' % (apk.getPackage(), apk.getMd5Hash()) if not targetName in alreadyVisited: alreadyVisited.append(targetName) appList.append((targetName, apk)) return appList def generateHtmlReport(self): jsonFactory = JsonFactory() # Create folder if self.htmlOutputDir is None: raise ValueError('HTML output dir has to be provided') if not os.path.exists(self.htmlOutputDir): os.mkdir(self.htmlOutputDir) appHtmlOutputDir = os.path.join(self.htmlOutputDir, 'html') if not os.path.exists(appHtmlOutputDir): os.mkdir(appHtmlOutputDir) # Collect information of all apps result = {} # app: {} resultType = {'apk':None, 'sortName':'', 'taintLogList':[], 'taintLogFileNameList':[], 'logFileNameList':[], 'overview':copy.deepcopy(self.INITIAL_NUMBERS_DICT), 'overview2':{'sms':0, 'call':0, 'netRead':0, 'netWrite':0, 'fsRead':0, 'fsWrite':0, 'cipher':0, 'ssl':0}, 'details':{'sms' : copy.deepcopy(self.INITIAL_NUMBERS_DICT), 'smsDest' : copy.deepcopy(self.INITIAL_NUMBERS_DICT), 'call' : copy.deepcopy(self.INITIAL_NUMBERS_DICT), 'netRead' : copy.deepcopy(self.INITIAL_NUMBERS_DICT), 'netWrite' : copy.deepcopy(self.INITIAL_NUMBERS_DICT), 'fsRead' : copy.deepcopy(self.INITIAL_NUMBERS_DICT), 'fsWrite' : copy.deepcopy(self.INITIAL_NUMBERS_DICT), 'cipher' : copy.deepcopy(self.INITIAL_NUMBERS_DICT), 'ssl' : copy.deepcopy(self.INITIAL_NUMBERS_DICT)}, 'fileName':'', 'rawDirectory':[]} for directory in self.dirs: mainReport = self.getMainReport(directory, jsonFactory) for appReport in mainReport.appList: apk = self.getAppApk(appReport.appPath) md5 = apk.getMd5Hash() # Build entry in dict if not result.has_key(md5): result[md5] = copy.deepcopy(resultType) result[md5]['apk'] = apk # Taint log and appropriate file names taintLog = self.getAppTaintLog(directory, appReport.logcatFile) if taintLog is None: fileNameList = os.listdir(directory) for logFile in fileNameList: if logFile.endswith('_%s_log.log' % str(appReport.id)): result[md5]['logFileNameList'].append(logFile) break else: result[md5]['taintLogFileNameList'].append(appReport.logcatFile) result[md5]['taintLogList'].append(taintLog) result[md5]['logFileNameList'].append(appReport.logcatFile[:-7] + '.log') # Raw directory fileNameParts = directory.split('/') if len(fileNameParts) < 2: rawDir = directory else: if fileNameParts[-1] != '': rawDir = fileNameParts[-1] else: rawDir = fileNameParts[-2] result[md5]['rawDirectory'].append(rawDir) # Sort name result[md5]['sortName'] = '%s-%s' % (apk.getPackage(), md5) # Evaluate results for appMd5, appResult in result.iteritems(): for taintLog in appResult['taintLogList']: oneMatch = self.evalTagNumbers(taintLog, appResult['apk'], CallActionLogEntry(tagList=[]), appResult['details']['call'], theReportMode=True) oneMatch |= self.evalTagNumbers(taintLog, appResult['apk'], CipherUsageLogEntry(tagList=[]), appResult['details']['cipher'], theReportMode=True) oneMatch |= self.evalTagNumbers(taintLog, appResult['apk'], FileSystemLogEntry(actionList=[TaintLogActionEnum.FS_READ_ACTION, TaintLogActionEnum.FS_READ_DIRECT_ACTION, TaintLogActionEnum.FS_READV_ACTION], tagList=[]), appResult['details']['fsRead'], theReportMode=True) oneMatch |= self.evalTagNumbers(taintLog, appResult['apk'], FileSystemLogEntry(actionList=[TaintLogActionEnum.FS_WRITE_ACTION, TaintLogActionEnum.FS_WRITE_DIRECT_ACTION, TaintLogActionEnum.FS_WRITEV_ACTION], tagList=[]), appResult['details']['fsWrite'], theReportMode=True) oneMatch |= self.evalTagNumbers(taintLog, appResult['apk'], NetworkSendLogEntry(actionList=[TaintLogActionEnum.NET_READ_ACTION, TaintLogActionEnum.NET_READ_DIRECT_ACTION, TaintLogActionEnum.NET_RECV_ACTION, TaintLogActionEnum.NET_RECV_DIRECT_ACTION], tagList=[]), appResult['details']['netRead'], theReportMode=True) oneMatch |= self.evalTagNumbers(taintLog, appResult['apk'], NetworkSendLogEntry(actionList=[TaintLogActionEnum.NET_SEND_ACTION, TaintLogActionEnum.NET_SEND_DIRECT_ACTION, TaintLogActionEnum.NET_SEND_URGENT_ACTION, TaintLogActionEnum.NET_WRITE_ACTION, TaintLogActionEnum.NET_WRITE_DIRECT_ACTION], tagList=[]), appResult['details']['netWrite'], theReportMode=True) oneMatch |= self.evalTagNumbers(taintLog, appResult['apk'], SSLLogEntry(tagList=[]), appResult['details']['ssl'], theReportMode=True) oneMatch |= self.evalTagNumbers(taintLog, appResult['apk'], SendSmsLogEntry(tagList=[]), appResult['details']['sms'], theReportMode=True) oneMatch |= self.evalSmsDestTagNumbers(taintLog, appResult['apk'], SendSmsLogEntry(destinationTagList=[]), appResult['details']['smsDest'], theReportMode=True) # Nothing happens if not oneMatch: pass # Get numbers of several actions appResult['overview2']['sms'] += taintLog.getNumLogEntries(theType=SendSmsLogEntry) appResult['overview2']['ssl'] += taintLog.getNumLogEntries(theType=SSLLogEntry) appResult['overview2']['call'] += taintLog.getNumLogEntries(theType=CallActionLogEntry) appResult['overview2']['cipher'] += taintLog.getNumLogEntries(theType=CipherUsageLogEntry) appResult['overview2']['netRead'] += len(taintLog.getMatchingLogEntries([NetworkSendLogEntry(actionList=[TaintLogActionEnum.NET_READ_ACTION, TaintLogActionEnum.NET_READ_DIRECT_ACTION, TaintLogActionEnum.NET_RECV_ACTION, TaintLogActionEnum.NET_RECV_DIRECT_ACTION], tagList=[])])) appResult['overview2']['netWrite'] += len(taintLog.getMatchingLogEntries([NetworkSendLogEntry(actionList=[TaintLogActionEnum.NET_SEND_ACTION, TaintLogActionEnum.NET_SEND_DIRECT_ACTION, TaintLogActionEnum.NET_SEND_URGENT_ACTION, TaintLogActionEnum.NET_WRITE_ACTION, TaintLogActionEnum.NET_WRITE_DIRECT_ACTION], tagList=[])])) appResult['overview2']['fsRead'] += len(taintLog.getMatchingLogEntries([FileSystemLogEntry(actionList=[TaintLogActionEnum.FS_READ_ACTION, TaintLogActionEnum.FS_READ_DIRECT_ACTION, TaintLogActionEnum.FS_READV_ACTION], tagList=[])])) appResult['overview2']['fsWrite'] += len(taintLog.getMatchingLogEntries([FileSystemLogEntry(actionList=[TaintLogActionEnum.FS_WRITE_ACTION, TaintLogActionEnum.FS_WRITE_DIRECT_ACTION, TaintLogActionEnum.FS_WRITEV_ACTION], tagList=[])])) # Add numbers to overview table for tag, overviewNumbers in appResult['overview'].iteritems(): for action, actionEntry in appResult['details'].iteritems(): if actionEntry[tag][0] > 0: overviewNumbers[0] += 1 # Print report (per app) descrDict = {'call':'Call', 'cipher':'Cipher Usage', 'fsRead':'File System Read', 'fsWrite':'File System Write', 'netRead':'Network Read', 'netWrite':'Network Write', 'ssl':'SSL', 'sms':'SMS Text', 'smsDest':'SMS Destination'} tagTypeList = ['deviceInfos', 'contact', 'location', 'incomingData', 'userInput', 'other', 'noTag'] actionList = ['call', 'cipher', 'fsRead', 'fsWrite', 'netRead', 'netWrite', 'ssl', 'sms', 'smsDest'] for appMd5, appResult in result.iteritems(): appReportFileName = '%s_%s.html' % (appResult['apk'].getPackage(), appMd5) appResult['fileName'] = os.path.join('html', appReportFileName) appReport = open(os.path.join(appHtmlOutputDir, appReportFileName), 'w') if appResult['apk'].getPackage() != '': appReport.write('<html><head><title>TaintDroid Runner Report for %s</title></head><body><p>' % appResult['apk'].getPackage()) appReport.write('<h1>TaintDroid Runner Report for %s</h1>' % appResult['apk'].getPackage()) else: # appResult['apk'].getPackage() == '' appReport.write('<html><head><title>TaintDroid Runner Report for %s</title></head><body><p>' % appMd5) appReport.write('<h1>TaintDroid Runner Report for %s</h1>' % appMd5) appReport.write('<br /><h2>Application</h2>') appReport.write('<li><b>APK</b>: <a href="../../%s/%s-%s.apk">%s-%s.apk</a></li>' % (self.reportAppDir, appResult['apk'].getPackage(), appMd5, appResult['apk'].getPackage(), appMd5)) appReport.write('<li><b>Package</b>: %s (<a href="http://www.google.com/#sclient=psy-ab&hl=de&source=hp&q=Android+%s" target="_blank">Search Google</a>)</li>' % (appResult['apk'].getPackage(), appResult['apk'].getPackage())) appReport.write('<li><b>MD5</b>: %s (<a href="http://www.google.com/#sclient=psy-ab&hl=de&source=hp&q=Android+%s" target="_blank">Search Google</a>)</li>' % (appResult['apk'].getMd5Hash(), appResult['apk'].getMd5Hash())) appReport.write('<li><b>Sha256</b>: %s</li>' % (appResult['apk'].getSha256Hash())) appReport.write('<li><b>Number of analysis runs</b>: %d</li>' % len(appResult['logFileNameList'])) appReport.write('<li><b>Number of successful analysis runs</b>: %d</li>' % len(appResult['taintLogList'])) appReport.write('<br /><h2>Overview</h2>') appReport.write('<table border="1" rules="groups">') appReport.write("""<thead><tr><th></th> <th align="center">Dev. Info</th> <th align="center">Contact</th> <th align="center">Location</th> <th align="center">Incoming</th> <th align="center">User Input</th> <th align="center">Other</th> <th align="center">W/O Tag</th></tr></thead>""") sumDict = {} appReport.write('<tbody>') for action in actionList: appReport.write('<tr>') appReport.write('<td><b>%s</b></td>' % (descrDict[action])) for tagType in tagTypeList: appReport.write('<td align="center">%d</td>' % (appResult['details'][action][tagType][0])) if sumDict.has_key(tagType): sumDict[tagType] += appResult['details'][action][tagType][0] else: sumDict[tagType] = appResult['details'][action][tagType][0] appReport.write('</tr>') appReport.write('</tbody>') #appReport.write('<tfoot><tr><td></td>') #for tagType in tagTypeList: # appReport.write('<td align="center">%d</td>' % (sumDict[tagType])) #appReport.write('</tr></tfoot>') appReport.write('</table>') appReport.write('<br /><h2>Details (Filtered)</h2>') for action in actionList[:-1]: foundFlag = False for tagType in tagTypeList: if appResult['details'][action][tagType][0] > 0: foundFlag = True break if not foundFlag: continue appReport.write('<h3>%s</h3>' % (descrDict[action])) relevantLogEntries = [] for taintLog in appResult['taintLogList']: if action == 'call': relevantLogEntries.extend(taintLog.getLogEntryList(theType=CallActionLogEntry)) columnList = ['Tag', 'DialString'] elif action == 'cipher': relevantLogEntries.extend(taintLog.getLogEntryList(theType=CipherUsageLogEntry)) columnList = ['Tag', 'Mode', 'Data'] elif action == 'fsRead': relevantLogEntries.extend(taintLog.getMatchingLogEntries([FileSystemLogEntry(actionList=[TaintLogActionEnum.FS_READ_ACTION, TaintLogActionEnum.FS_READ_DIRECT_ACTION, TaintLogActionEnum.FS_READV_ACTION], tagList=[])])) columnList = ['Tag', 'Action', 'File Path', 'Data'] elif action == 'fsWrite': relevantLogEntries.extend(taintLog.getMatchingLogEntries([FileSystemLogEntry(actionList=[TaintLogActionEnum.FS_WRITE_ACTION, TaintLogActionEnum.FS_WRITE_DIRECT_ACTION, TaintLogActionEnum.FS_WRITEV_ACTION], tagList=[])])) columnList = ['Tag', 'Action', 'File Path', 'Data'] elif action == 'netRead': relevantLogEntries.extend(taintLog.getMatchingLogEntries([NetworkSendLogEntry(actionList=[TaintLogActionEnum.NET_READ_ACTION, TaintLogActionEnum.NET_READ_DIRECT_ACTION, TaintLogActionEnum.NET_RECV_ACTION, TaintLogActionEnum.NET_RECV_DIRECT_ACTION], tagList=[])])) columnList = ['Tag', 'Action', 'Destination', 'Data'] elif action == 'netWrite': relevantLogEntries.extend(taintLog.getMatchingLogEntries([NetworkSendLogEntry(actionList=[TaintLogActionEnum.NET_SEND_ACTION, TaintLogActionEnum.NET_SEND_DIRECT_ACTION, TaintLogActionEnum.NET_SEND_URGENT_ACTION, TaintLogActionEnum.NET_WRITE_ACTION, TaintLogActionEnum.NET_WRITE_DIRECT_ACTION], tagList=[])])) columnList = ['Tag', 'Action', 'Destination', 'Data'] elif action == 'ssl': relevantLogEntries.extend(taintLog.getLogEntryList(theType=SSLLogEntry)) columnList = ['Tag', 'Action', 'Destination/Source', 'Data'] elif action == 'sms': relevantLogEntries.extend(taintLog.getLogEntryList(theType=SendSmsLogEntry)) columnList = ['Tag (Text)', 'Action', 'Source Addr', 'Destination', 'Tag Destination', 'Text'] appReport.write('<table>') appReport.write('<tr>') for col in columnList: appReport.write('<th align="left">%s</th>' % col) appReport.write('</tr>') for relevantLogEntry in relevantLogEntries: appReport.write('<tr>') for col in relevantLogEntry.getHtmlReportColumnList(False): appReport.write('<td>') if not col is None: try: appReport.write(col) except: pass appReport.write('</td>') appReport.write('</tr>') appReport.write('</table>') appReport.write('<br /><h2>Raw Files</h2>') for i in xrange(len(appResult['taintLogFileNameList'])): fileNameParts = appResult['taintLogFileNameList'][i].split('/') if len(fileNameParts) < 2: fileName = appResult['taintLogFileNameList'][i] else: fileName = fileNameParts[1] hrefPath = os.path.join('raw', appResult['rawDirectory'][i], fileName) appReport.write('<li>Logcat output (%d): <a href="../%s">%s</a></li>' % ((i+1), hrefPath, fileName)) for i in xrange(len(appResult['logFileNameList'])): fileNameParts = appResult['logFileNameList'][i].split('/') if len(fileNameParts) < 2: fileName = appResult['logFileNameList'][i] else: fileName = fileNameParts[1] hrefPath = os.path.join('raw', appResult['rawDirectory'][i], fileName) appReport.write('<li>Log output (%d): <a href="../%s">%s</a></li>' % ((i+1), hrefPath, fileName)) appReport.write('</p></body></html>') # Print main report mainReport = open(os.path.join(self.htmlOutputDir, 'index.html'), 'w') mainReport.write('<html><head><title>TaintDroid Runner Report</title></head><body><p>') mainReport.write('<h1>TaintDroid Runner Report</h1>') mainReport.write('[<a href="#tag">By Tag</a>] [<a href="#action">By Action</a>]') mainReport.write('<h2><a name="tag">Overview by Tag</a></h2>') mainReport.write('<table border="1" rules="rows">') mainReport.write("""<thead><tr><th></th> <th align="center">Dev. Info</th> <th align="center">Contact</th> <th align="center">Location</th> <th align="center">Incoming</th> <th align="center">User Input</th> <th align="center">Other</th> <th align="center">W/O Tag</th></tr></thead>""") sumDict = {} mainReport.write('<tbody>') for appMd5, appResult in result.iteritems(): mainReport.write('<tr>') if appResult['apk'].getPackage() != '': mainReport.write('<td><a href="%s">%s</a> (%s)</td>' % (appResult['fileName'], appResult['apk'].getPackage(), appMd5)) else: # appResult['apk'].getPackage() == '' mainReport.write('<td>(<a href="%s">%s</a>)</td>' % (appResult['fileName'], appMd5)) for tagType in tagTypeList: mainReport.write('<td align="center">%d</td>' % (appResult['overview'][tagType][0])) if sumDict.has_key(tagType): sumDict[tagType] += appResult['overview'][tagType][0] else: sumDict[tagType] = appResult['overview'][tagType][0] mainReport.write('</tr>') mainReport.write('</tbody>') #mainReport.write('<tfoot><tr><td></td>') #for tagType in tagTypeList: # mainReport.write('<td align="center">%d</td>' % (sumDict[tagType])) #mainReport.write('</tr></tfoot>') mainReport.write('</table>') mainReport.write('<h2><a name="action">Overview by Action</a></h2>') mainReport.write('<table border="1" rules="rows">') mainReport.write('<thead><tr><th></th>') for action in actionList[:-1]: mainReport.write('<th align="center">%s</th>' % descrDict[action]) mainReport.write('</tr></thead>') sumDict = {} mainReport.write('<tbody>') for appMd5, appResult in result.iteritems(): mainReport.write('<tr>') if appResult['apk'].getPackage() != '': mainReport.write('<td><a href="%s">%s</a> (%s)</td>' % (appResult['fileName'], appResult['apk'].getPackage(), appMd5)) else: # appResult['apk'].getPackage() == '' mainReport.write('<td>(<a href="%s">%s</a>)</td>' % (appResult['fileName'], appMd5)) for action in actionList[:-1]: mainReport.write('<td align="center">%d</td>' % (appResult['overview2'][action])) if sumDict.has_key(action): sumDict[action] += appResult['overview2'][action] else: sumDict[action] = appResult['overview2'][action] mainReport.write('</tbody>') #mainReport.write('<tfoot><tr><td></td>') #for action in actionList[:-1]: # mainReport.write('<td align="center">%d</td>' % (sumDict[action])) #mainReport.write('</tr></tfoot>') mainReport.write('</table></p></body></html>') def findNotInstrumentedPatterns(self): notInstrumentedPatterns = [ NetworkSendLogEntry(action=0, actionList=[TaintLogActionEnum.NET_READ_DIRECT_ACTION, TaintLogActionEnum.NET_WRITE_DIRECT_ACTION, TaintLogActionEnum.NET_RECV_DIRECT_ACTION, TaintLogActionEnum.NET_SEND_DIRECT_ACTION], tagList=[], destination='', stackTraceStr=''), FileSystemLogEntry(action=0, actionList=[TaintLogActionEnum.FS_READ_DIRECT_ACTION, TaintLogActionEnum.FS_WRITE_DIRECT_ACTION, TaintLogActionEnum.FS_READV_ACTION, TaintLogActionEnum.FS_WRITEV_ACTION], tagList=[], filePath='', stackTraceStr='') ] jsonFactory = JsonFactory() for directory in self.dirs: print 'Look in %s' % directory mainReport = self.getMainReport(directory, jsonFactory) for appReport in mainReport.appList: apk = self.getAppApk(appReport.appPath) taintLog = self.getAppTaintLog(directory, appReport.logcatFile) if not taintLog is None: if taintLog.doesMatch(notInstrumentedPatterns): # check for not instrumented patters print '--------------------' taintLog.printOverview() raw_input('FOUND NOT INSTRUMENTED PATTERN (!)') def findPatterns(self): patterns = [] appList = [] jsonFactory = JsonFactory() for directory in self.dirs: print 'Look in %s' % directory mainReport = self.getMainReport(directory, jsonFactory) for appReport in mainReport.appList: apk = self.getAppApk(appReport.appPath) taintLog = self.getAppTaintLog(directory, appReport.logcatFile) if not taintLog is None: if taintLog.doesMatch(patterns): # check for not instrumented patters appList.append(apk) print '--------------------' for app in appList: print '- %s (%s)' % (app.getPackage(), app.getMd5Hash()) def analyze(self): if int(self.mode) == 0: self.analyzeModeNumbers() elif int(self.mode) == 1: self.analyzeModeDetails() elif int(self.mode) == 2: self.generateList() elif int(self.mode) == 3: self.generateHtmlReport() elif int(self.mode) == 4: self.findNotInstrumentedPatterns() elif int(self.mode) == 5: self.findPatterns() # ================================================================================ # Main method # ================================================================================ if __name__ == '__main__': # Get directory parser = OptionParser(usage='usage: %prog [options] reportDir') parser.add_option('-m', '--mode', metavar='<int>', default=0, help='Set mode') parser.add_option('', '--sdkPath', metavar='<path>', default='', help='Set path to Android SDK') parser.add_option('', '--latexFile', metavar='<path>', default=None, help='Set path to Latex file') parser.add_option('', '--baseAppDir', metavar='<path>', default=None, help='Set path to dicrectory in which applications are stored') parser.add_option('', '--printDictFile', metavar='<path>', default=None, help='Set path to file in which output dict should be printed') parser.add_option('', '--htmlOutputDir', metavar='<path>', default=None, help='Output directory for generated HTML report') parser.add_option('', '--reportAppDir', metavar='<path>', default=None, help='Default app directory on USB stick') (options, args) = parser.parse_args() # Get report dir if len(args) < 1: raise ValueError('Provide a directory') reportDirs = [] for arg in args: reportDirs.append(arg) # Analyze analyzer = Analyzer(reportDirs, theMode=options.mode, theSdkPath=options.sdkPath) analyzer.latexFile = options.latexFile analyzer.baseAppDir = options.baseAppDir analyzer.printDictFile = options.printDictFile analyzer.htmlOutputDir = options.htmlOutputDir analyzer.reportAppDir = options.reportAppDir analyzer.analyze() # malware full: python helper_analyzer.py -m 0 --baseAppDir /home/daniel/Documents/Malware/thesis_analysis/ ~/Documents/Malware/reports/mw_nb_1_20120112-213037/ ~/Documents/Malware/reports/mw_nb_2_20120122-111827/ ~/Documents/Malware/reports/mw_nb_3_20120122-143747/ ~/Documents/Malware/reports/mw_nb_4_20120123-215147/ ~/Documents/Malware/reports/mw_rub_full_20120123-214357/ ~/Documents/Malware/reports/mw_desk_full/ # goodware full: python helper_analyzer.py -m 0 --baseAppDir /home/daniel/Documents/MarketApps/apps/ ~/Documents/Malware/reports/gw_nb_1_20120124-064525/ ~/Documents/Malware/reports/gw_nb_2_20120124-204758/ ~/Documents/Malware/reports/gw_nb_3_20120125-210805/ ~/Documents/Malware/reports/gw_nb_4_20120126-223959/ ~/Documents/Malware/reports/gw_nb_5_20120127-195917/ ~/Documents/Malware/reports/gw_nb_6_20120129-115712/ ~/Documents/Malware/reports/gw_nb_7_20120204-195305/ ~/Documents/Malware/reports/gw_nb_8_20120205-192907/ ~/Documents/Malware/reports/gw_nb_9_20120206-194602/ ~/Documents/Malware/reports/gw_nb_10_20120207-201340/ ~/Documents/Malware/reports/gw_nb_11_20120208-192600/ ~/Documents/Malware/reports/gw_nb_12_20120209-202213/ ~/Documents/Malware/reports/gw_nb_13_20120210-205101/ ~/Documents/Malware/reports/gw_rub_1_20120125-210650/ # python helper_analyzer.py -m 3 --htmlOutputDir html_goodware --reportAppDir marketApps --baseAppDir /home/daniel/Documents/MarketApps/apps/ ~/Documents/Malware/reports/gw_nb_1_20120124-064525/ ~/Documents/Malware/reports/gw_nb_2_20120124-204758/ ~/Documents/Malware/reports/gw_nb_3_20120125-210805/ ~/Documents/Malware/reports/gw_nb_4_20120126-223959/ ~/Documents/Malware/reports/gw_nb_5_20120127-195917/ ~/Documents/Malware/reports/gw_nb_6_20120129-115712/ ~/Documents/Malware/reports/gw_nb_7_20120204-195305/ ~/Documents/Malware/reports/gw_nb_8_20120205-192907/ ~/Documents/Malware/reports/gw_nb_9_20120206-194602/ ~/Documents/Malware/reports/gw_nb_10_20120207-201340/ ~/Documents/Malware/reports/gw_nb_11_20120208-192600/ ~/Documents/Malware/reports/gw_nb_12_20120209-202213/ ~/Documents/Malware/reports/gw_nb_13_20120210-205101/ ~/Documents/Malware/reports/gw_rub_1_20120125-210650/