# # # import os import argparse import logging from subprocess import Popen, PIPE, check_call # our libs from libs import android from libs.toolbox import ToolBox from libs.fingerprint import FingerprintDB from libs.fingerprint_index import FingerprintIndex BASE_DIR = "data" FP_BASE_DIR = "fingerprints" def main(): parseArgs() # def compareFingerprint(filein, filejson): db = FingerprintDB() db.scanDBFile(filein) percent = db.compareDB(filejson) print "Percent match: {}".format(str(percent)) # def createFingerprint(filein, verbose, app_name, app_ver, notes): db = FingerprintDB() retVal = db.scanDBFile(filein) if (retVal > 0): if verbose: db.debugFingerprint() if app_name: db.setAppName(app_name) if app_ver: db.setAppVer(app_ver) if notes: db.setNotes(notes) db.writeFingerprint() else: print db.getErrorString(retVal) # def indexFingerprints(fp_dir): logging.info("fp_dir=={}".format(fp_dir)) db = FingerprintDB() fp = FingerprintIndex() fp.openIndex(fp_dir) # def compareFingerprintDir(file_in, fp_dir): db = FingerprintDB() fp = FingerprintIndex() # def androidPull(): ap = android.AndroidAppPull() isRoot = ap.isADBRoot(); if (not isRoot): print "ERROR: adb is not running as root, exec 'adb root'" return if (not mkdir(BASE_DIR)): logging.error("ERROR creating directory: {}".format(BASE_DIR)) return if (not mkdir(FP_BASE_DIR)): logging.error("ERROR creating directory: {}".format(FP_BASE_DIR)) return dir_names = ap.getAppsDir() for dir_name in dir_names: fq_dir = BASE_DIR + os.path.sep + dir_name ap.pullApp(BASE_DIR, dir_name) __createFingerprint(fq_dir, FP_BASE_DIR, dir_name) # def androidData(data_dir): dir_names = [] try: dirs = os.listdir(data_dir) except: return out_dir = FP_BASE_DIR + "_" + ToolBox.getTimestampStr() if (not mkdir(out_dir)): logging.error("ERROR creating directory: {}".format(FP_BASE_DIR)) return for ddir in dirs: in_dir = data_dir + os.path.sep + ddir __createFingerprint(in_dir, out_dir, ddir) # in_dir: fully qualified directory path to find sqlite files def __createFingerprint(in_dir, out_dir, dir_name): try: db_dir = in_dir + os.path.sep + "databases" logging.info("in_dir=={}".format(db_dir)) files = os.listdir(db_dir) except: # not finding a databases folder is normal, not all apps use sqlite return db = fingerprint.FingerprintDB() for filein in files: ddir = db_dir + os.path.sep + filein logging.info('Parsing file "{}"'.format(ddir)) retVal = db.scanDBFile(ddir) if (retVal > 0): fname = dir_name + "__" + filein + "__dbfp" + ".json" fq_name = out_dir + os.path.sep + fname db.setAppName(dir_name) db.writeFingerprintFile(fq_name) # def __getFileName(): '''standardize on a file name, use timestamp? ''' pass # def mkdir(fdir): retval = False try: check_call(["mkdir", fdir]) retval = True except: logging.error('ERROR: problem creating directory "{}"'.format(fdir)) return retval # def parseArgs(): print '***** ***** ***** *****' print ' DB Fingerprint' print '***** ***** ***** *****\n' parser = argparse.ArgumentParser(description="Fingerprint a sqlite database based on its schema") parser.add_argument('-f', '--file', required=False, help="path to file to be fingerprinted") parser.add_argument('-fd', '--fpdir', required=False, help="path to directory of fingerprint files") parser.add_argument('-fp', '--fingerprint', required=False, help="fingerprint file to use in comparison") parser.add_argument('-dd', '--data_dir', required=False, help="path to a directory with sqlite files") parser.add_argument('-idx', '--index_fingerprints', required=False, help="path to a directory with sqlite files") parser.add_argument('-an', '--app_name', required=False) parser.add_argument('-av', '--app_version', required=False) parser.add_argument('-n', '--notes', required=False) parser.add_argument('-pull', required=False, action='store_true', help="automated pull of applications from a physical android phone") parser.add_argument('-v', '--verbose', action='store_true', help="will set logging level to DEBUG") parser.add_argument('-l', '--logging', action='store_true', help="will supercede the -v option and send all logging to a file, logging.DEBUG") # parser.add_argument('-t', '--title', required=False) args = parser.parse_args() if (args.logging): logging.basicConfig(filename='dbfp.log', level=logging.DEBUG) if (args.verbose): logging.basicConfig(level=logging.DEBUG) else: logging.basicConfig(level=logging.CRITICAL) if (args.file and args.fingerprint): compareFingerprint(args.file, args.fingerprint) elif (args.file and args.fpdir): compareFingerprintDir(args.file, args.fpdir) elif (args.data_dir): androidData(args.data_dir) elif (args.index_fingerprints): indexFingerprints(args.index_fingerprints) elif (args.pull): androidPull() elif (args.file): createFingerprint(args.file, args.verbose, args.app_name, args.app_version, args.notes) else: parser.print_help() if __name__ == "__main__": main()