def __init__(self, file_path): Cmd.__init__(self) self.prompt = 'saam > ' self.shortcuts.remove(('@', 'load')) self.shortcuts.append(('@', 'adb_cmd')) self.shortcuts.remove(('@@', '_relative_load')) self.shortcuts.append(('$', 'adb_shell_cmd')) self.shortcuts.append(('qc', 'quit_and_clean')) self.apk_path = file_path self.apk = APK(self.apk_path) self.apk_out = os.path.basename(file_path) + ".out" self.smali_files = None self.smali_dir = None self.adb = None self.smali_method_descs = [] self.java_files = [] vsmali_action = CmdLineApp.vsmali_parser.add_argument( 'sfile', help='smali file path') setattr(vsmali_action, argparse_completer.ACTION_ARG_CHOICES, ('delimiter_complete', { 'delimiter': '/', 'match_against': self.smali_method_descs })) vjava_action = CmdLineApp.vjava_parser.add_argument( 'jfile', help='java file path') setattr(vjava_action, argparse_completer.ACTION_ARG_CHOICES, ('delimiter_complete', { 'delimiter': '/', 'match_against': self.java_files }))
def retireve_info(file_in_check): proc = subprocess.Popen("{} d badging '{}'".format(AAPT, file_in_check), shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) r = (proc.communicate()[0]).decode() items = re.compile("package: name='(.*?)' versionCode='(.*?)' versionName='(.*?)'").findall(r) try: pkg, vercode, vername = items[0] except: pkg = vercode = vername = '' try: appname = re.compile("application-label:'(.*?)'").findall(r)[0] except: appname = '' try: dn,cert = APK(file_in_check).get_certs('sha1')[0] except: dn, cert = '', '' cert = cert.lower() #info = [os.path.basename(apk), sha1, pkg, vername, appname, size] # log_writer(sha1, pkg, cert, dn, vername, appname) # db_data = {"sha1": None, "pkg": None, "cert": None, "dn": None, "vername": None, "appname": None} db_data = {"sha1": getSHA1(file_in_check), "pkg": pkg, "cert": cert, "dn": dn, "vername": vername, "appname": appname} globalDB.insert_one("apk_info", db_data)
def parse_apkfile(file: str) -> Manifest: ''' Args: - file: filename Returns: Manifest(Class) ''' return Manifest(APK(file))
def test_kotlin_app(self): file_path = os.path.abspath( os.path.join(os.path.dirname(__file__), "..", 'data', 'kotlin-app.zip')) apk = APK(file_path) self.assertEqual([( 'CN=Android Debug, O=Android, C=US', '299D8DE477962C781714EAAB76A90C287BB67123CD2909DE0F743838CAD264E4') ], apk.get_certs('sha256'))
def parse_apkfile(file): ''' Args: - file: filename or file object Returns: Manifest(Class) ''' apk = APK(file) return Manifest(apk.get_org_manifest())
def main(args): if os.path.isfile(args.file): if args.T: t = Magic(args.file).get_type() if t != 'apk': return trees = APK(args.file).get_trees() nodes = trees.get(args.T, []) for node in nodes: APK.pretty_print(node) else: return if not os.path.isdir(args.file): return apks = [] for root, _, files in os.walk(args.file): for f in files: path = os.path.join(root, f) t = Magic(path).get_type() if t != 'apk': continue apks.append(APK(path)) if not apks: return ai = APK_Intersection(apks) if args.m: ai.intersect_manifest() if args.s: ai.intersect_dex_string() # TODO 相同的字符串太多了,反编译删除干扰的数据 if args.t: ai.intersect_dex_tree() if args.p: ai.intersect_apis() if args.r: ai.intersect_resources()
def __init__(self, file_path): Cmd.__init__(self) self.prompt = 'saam > ' self.shortcuts.remove(('@', 'load')) self.shortcuts.append(('@', 'adb_cmd')) self.shortcuts.remove(('@@', '_relative_load')) self.shortcuts.append(('$', 'adb_shell_cmd')) self.shortcuts.append(('qc', 'quit_and_clean')) self.apk_path = file_path self.apk = APK(self.apk_path) self.apk_out = os.path.basename(file_path) + ".out" self.smali_files = None self.smali_dir = None self.adb = None
def main(args): apk = APK(args.p) if args.m: import json if apk.get_manifest(): print(json.dumps(apk.get_manifest(), indent=1)) elif apk.get_org_manifest(): print(apk.get_org_manifest()) elif args.s: for item in apk.get_strings(): print(binascii.unhexlify(item).decode(errors='ignore')) elif args.f: for item in apk.get_files(): print(item)
def test_youtube(self): file_path = os.path.abspath( os.path.join(os.path.dirname(__file__), "..", 'data', 'youtube.zip')) apk = APK(file_path) # Check that the default (md5) is correct self.assertEqual([( 'C=US, ST=CA, L=Mountain View, O=Google, Inc, OU=Google, Inc, CN=Unknown', 'D046FC5D1FC3CD0E57C5444097CD5449')], apk.get_certs()) # Check that sha1 is correct self.assertEqual([( 'C=US, ST=CA, L=Mountain View, O=Google, Inc, OU=Google, Inc, CN=Unknown', '24BB24C05E47E0AEFA68A58A766179D9B613A600')], apk.get_certs('sha1')) # Check that sha256 is correct self.assertEqual([( 'C=US, ST=CA, L=Mountain View, O=Google, Inc, OU=Google, Inc, CN=Unknown', '3D7A1223019AA39D9EA0E3436AB7C0896BFB4FB679F4DE5FE7C23F326C8F994A') ], apk.get_certs('sha256'))
def scan_apk(apk_path, rules, timeout): td = None try: with zipfile.ZipFile(apk_path, 'r') as zf: for name in zf.namelist(): td = tempfile.mkdtemp() zf.extract(name, td) file_path = os.path.join(td, name) key_path = '{}!{}'.format(apk_path, name) match_dict = do_yara(file_path, rules, timeout) if len(match_dict) > 0: print_matches(key_path, match_dict) except Exception as e: print(e) from apkutils import APK txt = APK(apk_path).get_org_manifest() match_dict = scan_manifest(txt, rules, timeout) if len(match_dict) > 0: key_path = '{}!{}'.format(apk_path, 'AndroidManifest.xml') print_matches(key_path, match_dict)
def main(apkPath): starttime = datetime.datetime.now() """ :param apkPath: apk文件的最终路径 :return: NULL """ print("[?]Analyzing {}".format(apkPath)) if "/" in apkPath: savePath = "./result/" + apkPath.split("/")[-1].split(".")[0] else: savePath = "./result/" + apkPath.split(".")[0] try: os.mkdir(savePath) except Exception as e: # print(e) pass if dex2jar(apkPath, savePath): print("[+]Dex2jar success!") # print(savePath) ''' 先判断这个安装包是否提取过,再开始处理。 ''' if len([ lists for lists in os.listdir(savePath) if os.path.isfile(os.path.join(savePath, lists)) ]) > 5: print( "[!]The information has been extracted to {}. Please delete it if you need to extract it again" .format(savePath)) else: apk = APK(apkPath) #获取AndroidManifest.xml的字符串信息 manifestInfo = getManifestInfo(apk) xml = open("{}/AndroidManifest.xml".format(savePath), "w") xml.write(manifestInfo) xml.close() #签名信息 sign = getSignInfo(apk) print("[?]Extracting all strings in apk") stringList = getStrings(apk) try: urlList = [] ipList = [] hashlist = [] forbidStrList = [] accessKeyList = [] for string in stringList: # 保存所有的字符串 base = open("{}/strings.txt".format(savePath), "a") try: base.write(str(string) + '\n') except Exception as e: # print(e) pass base.close() ''' 下面开始提取URLs ''' # url = re.findall('https?://(?:[-\w.]|(?:%[\da-fA-F]{2}))+', string) urlStrList = ["https://", "http://"] # 提取的特征 for urlStr in urlStrList: if urlStr in string: # print(string) if string not in urlList: u = open("{}/urls.txt".format(savePath), "a") u.write(str(string) + '\n') u.close() urlList.append(string) ''' 判断是否包含IP ''' p = re.compile( '(25[0-5]|2[0-4]\d|[0-1]\d{2}|[1-9]?\d)\.(25[0-5]|2[0-4]\d|[0-1]\d{2}|[1-9]?\d)\.(25[0-5]|2[0-4]\d|[0-1]\d{2}|[1-9]?\d)\.(25[0-5]|2[0-4]\d|[0-1]\d{2}|[1-9]?\d)' ) if p.match(string): ip = open("{}/ips.txt".format(savePath), "a") ip.write(str(string) + '\n') ip.close() if string not in ipList: ipList.append(string) ''' 下面开始提取可能是base64编码以及hash的值 ''' ''' 下面开始匹配32位长度和15长度的hash ''' if len(string) == 32 or len(string) == 16: if re.match(r'^[a-z0-9]{16,32}$', string): if string not in hashlist: hashlist.append(string) hashs = open("{}/hash.txt".format(savePath), "a") hashs.write(str(string) + '\n') hashs.close() ''' 下面提取可能存在的敏感字符串 ''' # forbidStr = ["accessKey", "database","ssh","rdp","smb","mysql","sqlserver","oracle", # "ftp","mongodb","memcached","postgresql","telnet","smtp","pop3","imap", # "vnc","redis","admin","root","config","jdbc",".properties","aliyuncs", # "oss"] # 特征字典 forbidStr = ['accesskey', 'aliyuncs'] for forbid in forbidStr: if forbid in string: # print(string) if string not in forbidStrList: fb = open("{}/forbidStr.txt".format(savePath), "a") try: fb.write(str(string) + '\n') except Exception as e: print(e) pass fb.close() forbidStrList.append(string) ''' 下面开始匹配AccessKey,自己测试发现: AccessKeyId 约为24位 AccessKeySecret 约为30位 ''' if str(string).isalnum(): if re.match( r'^(?:(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])).{24,24}$', string): if string not in accessKeyList: accessKeyList.append(string) ak = open("{}/accessKey.txt".format(savePath), "a") if string.startswith("LTAI"): ak.write( "=============AccessKeyId================") ak.write("Id:{}\n".format(str(string))) ak.close() if re.match( r'^(?:(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])).{30,30}$', string): if string not in accessKeyList: accessKeyList.append(string) ak = open("{}/accessKey.txt".format(savePath), "a") ak.write("Secret:{}\n".format(str(string))) ak.close() except Exception as e: #print(e) pass print("""[*]Found: \tString:{}\tURL:{} \tIps:{}\tHash:{}\tForbidStr:{} \tMaybe it's accessKey:{}""".format(len(stringList), len(urlList), len(ipList), len(hashlist), len(forbidStrList), len(accessKeyList))) endtime = datetime.datetime.now() print("[+]Use time {}s\n".format((endtime - starttime).seconds))
import binascii import os from apkutils import APK file_path = os.path.abspath( os.path.join(os.path.dirname(__file__), "..", 'data', 'test')) apk = APK(file_path) strs = apk.get_strings() # the strings from all of classes\d*.dex for item in strs: s = binascii.unhexlify(item).decode('utf-8', errors='ignore') if 'hello' in s: print(s)
def setUp(self): file_path = os.path.abspath( os.path.join(os.path.dirname(__file__), "..", 'data', 'test_zip_fake_pwd')) self.apk = APK(file_path)
exit(-1) if not os.path.exists("./result"): os.mkdir("./result") target_path = sys.argv[1] ns = "{http://schemas.android.com/apk/res/android}" safeAttr = lambda x, y: x.attrib[y] if y in x.attrib else "" for item in glob(f"{target_path}/*.apk"): filename = Path(item).stem manifest_uuid = str(uuid.uuid4()) apk = APK(item) root = ET.fromstring(apk.get_org_manifest()) app = root.find("application") result = {} for child in list(app): if child.tag not in result: result[child.tag] = [] name = safeAttr(child, f"{ns}name") enabled = safeAttr(child, f"{ns}enabled") != "false" exported = safeAttr(child, f"{ns}exported") == "true" permission = safeAttr(child, f"{ns}permission") read_permission = safeAttr(child, f"{ns}readpermission") write_permission = safeAttr(child, f"{ns}writepermission") intents = []
def setUp(self): file_path = os.path.abspath( os.path.join(os.path.dirname(__file__), "..", 'data', 'i15.zip')) self.apk = APK(file_path)