writer1 = common.Writer((0, height-8)) pbar1 = ProgressBar(widgets=['X.509 Validation ', Percentage(), Bar()], maxval=100, fd=writer1).start() writer2 = common.Writer((0, height-6)) pbar2 = ProgressBar(widgets=['Pending Intents ', Percentage(), Bar()], maxval=100, fd=writer2).start() writer3 = common.Writer((0, height-4)) pbar3 = ProgressBar(widgets=['File Permissions (check 1) ', Percentage(), Bar()], maxval=100, fd=writer3).start() writer4 = common.Writer((0, height-2)) pbar4 = ProgressBar(widgets=['File Permissions (check 2) ', Percentage(), Bar()], maxval=100, fd=writer4).start() writer5 = common.Writer((0, height-10)) pbar5 = ProgressBar(widgets=['Webview checks ', Percentage(), Bar()], maxval=100, fd=writer5).start() writer6 = common.Writer((0, height-12)) pbar6 = ProgressBar(widgets=['Broadcast issues ', Percentage(), Bar()], maxval=100, fd=writer6).start() writer7 = common.Writer((0, height-14)) pbar7 = ProgressBar(widgets=['Crypto issues ', Percentage(), Bar()], maxval=100, fd=writer7).start() pub.subscribe(progress_bar_update, 'progress') thread0 = Thread(name='Certificate Validation', target=certValidation.validate, args=(cert_queue,height-8)) thread1 = Thread(name='Pending Intent validation', target=findPending.start, args = (pending_intents_queue,height-6)) thread2 = Thread(name='File Permission checks', target=filePermissions.start, args = (file_permission_queue,height-4)) thread3 = Thread(name='Webviews', target=webviews.validate, args = (web_view_queue,)) thread4 = Thread(name='Find Broadcasts', target=findBroadcasts.main, args = (find_broadcast_queue,)) thread5 = Thread(name='Crypto Issues', target=cryptoFlaws.main, args = (crypto_flaw_queue,)) thread0.start() thread1.start() thread2.start() thread3.start() thread4.start() thread5.start() thread0.join() thread1.join()
def decompile(path): """ Converts DEX to JAR(containing class files) and then class files to near original java code using 3 different decompilers and selecting the best available decompiled code """ common.pathToDEX = path pathToDex2jar = common.rootDir + "/lib/dex2jar/dex2jar.sh" sp = subprocess.Popen([pathToDex2jar, common.pathToDEX], shell=False, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) output, error = sp.communicate() common.pathToJar = common.pathToDEX.rsplit(".", 1)[0] + "_dex2jar.jar" dirname, extension = common.pathToJar.rsplit(".", 1) zf = zipfile.ZipFile(common.pathToJar) # Total number of class files that need to be decompiled total_files = len(zf.namelist()) report.write("totalfiles", total_files) common.count = len( [s for s in zf.namelist() if ((".class" in s) and ("$" not in s))]) pub.subscribe(decompiler_update, 'decompile') thread0 = Process(name='clear', target=clear, args=()) thread1 = Process(name='jdcore', target=jdcore, args=(zf.filename, dirname)) thread2 = Process(name='procyon', target=cfr, args=(zf.filename, dirname)) thread3 = Process(name='cfr', target=procyon, args=(zf.filename, dirname)) thread0.start() thread0.join() progressbar1.start() progressbar2.start() progressbar3.start() thread1.start() thread2.start() thread3.start() thread1.join(0) thread2.join(0) thread3.join(0) with common.term.cbreak(): val = None while val not in (u'c', u'C'): with common.term.location(0, common.term.height - 3): print "Decompilation may hang/take too long (usually happens when the source is obfuscated)." print "At any time," + common.term.bold_underline_red_on_white( 'Press C to continue' ) + " and QARK will attempt to run SCA on whatever was decompiled." val = common.term.inkey(timeout=1) if not (thread1.is_alive() or thread2.is_alive() or thread3.is_alive()): break if thread1.is_alive(): thread1.terminate() if thread2.is_alive(): thread2.terminate() if thread3.is_alive(): thread3.terminate() # Go back to the bottom of the screen with common.term.location(0, common.term.height): print "" g1 = grep_1(dirname, "// Byte code:") g2 = grep_1(dirname + "1", "// This method has failed to decompile.") g3 = grep_1(dirname + "2", "// This method could not be decompiled.") # print list(set(g1) - set(g2)) logger.info("Trying to improve accuracy of the decompiled files") restored = 0 try: for filename in g1: relative_filename = str(filename).split(dirname)[1] if any(relative_filename in s for s in g2): if any(relative_filename in s for s in g3): logger.debug("Failed to reconstruct: " + relative_filename) else: shutil.copy(dirname + "2" + relative_filename, filename) restored = restored + 1 else: shutil.copy(dirname + "1" + relative_filename, filename) restored = restored + 1 except Exception as e: print e.message report.write( "restorestats", "Restored " + str(restored) + " file(s) out of " + str(len(g1)) + " corrupt file(s)") logger.info("Restored " + str(restored) + " file(s) out of " + str(len(g1)) + " corrupt file(s)") logger.debug("Deleting redundant decompiled files") try: shutil.rmtree(dirname + "1") logger.debug("Deleted " + dirname + "1") shutil.rmtree(dirname + "2") logger.debug("Deleted " + dirname + "2") except Exception as e: logger.debug( "Unable to delete redundant decompiled files (no impact on scan results): " + str(e))
def decompile(path): """ Converts DEX to JAR(containing class files) and then class files to near original java code using 3 different decompilers and selecting the best available decompiled code """ common.pathToDEX = path pathToDex2jar = common.rootDir + "/lib/dex2jar/dex2jar.sh" sp = subprocess.Popen([pathToDex2jar, common.pathToDEX], shell=False, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) output, error = sp.communicate() common.pathToJar = common.pathToDEX.rsplit(".",1)[0] + "_dex2jar.jar" dirname, extension = common.pathToJar.rsplit(".",1) zf = zipfile.ZipFile(common.pathToJar) #Total number of class files that need to be decompiled total_files = len(zf.namelist()) report.write("totalfiles", total_files) common.count = len([s for s in zf.namelist() if ((".class" in s) and ("$" not in s))]) pub.subscribe(decompiler_update, 'decompile') thread0 = Process(name='clear', target=clear, args = ()) thread1 = Process(name='jdcore', target=jdcore, args = (zf.filename,dirname)) thread2 = Process(name='procyon', target=cfr, args = (zf.filename,dirname)) thread3 = Process(name='cfr', target=procyon, args = (zf.filename,dirname)) thread0.start() thread0.join() progressbar1.start() progressbar2.start() progressbar3.start() thread1.start() thread2.start() thread3.start() thread1.join(0) thread2.join(0) thread3.join(0) with common.term.cbreak(): val = None while val not in (u'c', u'C'): with common.term.location(0,common.term.height-3): print "Decompilation may hang/take too long (usually happens when the source is obfuscated)." print "At any time," + common.term.bold_underline_red_on_white('Press C to continue') + " and QARK will attempt to run SCA on whatever was decompiled." val = common.term.inkey(timeout=1) if not (thread1.is_alive() or thread2.is_alive() or thread3.is_alive()): break if thread1.is_alive(): thread1.terminate() if thread2.is_alive(): thread2.terminate() if thread3.is_alive(): thread3.terminate() #Go back to the bottom of the screen with common.term.location(0,common.term.height): print "" g1 = grep_1(dirname, "// Byte code:") g2 = grep_1(dirname+"1", "// This method has failed to decompile.") g3 = grep_1(dirname+"2", "// This method could not be decompiled.") #print list(set(g1) - set(g2)) logger.info("Trying to improve accuracy of the decompiled files") restored = 0 try: for filename in g1: relative_filename = str(filename).split(dirname)[1] if any(relative_filename in s for s in g2): if any(relative_filename in s for s in g3): logger.debug("Failed to reconstruct: " + relative_filename) else: shutil.copy(dirname+"2"+relative_filename, filename) restored = restored +1 else: shutil.copy(dirname+"1"+relative_filename, filename) restored = restored +1 except Exception as e: print e.message report.write("restorestats","Restored " + str(restored) + " file(s) out of " + str(len(g1)) + " corrupt file(s)") logger.info("Restored " + str(restored) + " file(s) out of " + str(len(g1)) + " corrupt file(s)") logger.debug("Deleting redundant decompiled files") try: shutil.rmtree(dirname+"1") logger.debug("Deleted " + dirname+"1") shutil.rmtree(dirname+"2") logger.debug("Deleted " + dirname+"2") except Exception as e: logger.debug("Unable to delete redundant decompiled files (no impact on scan results): " + str(e))
if common.args.apkpath is not None: common.apkPath = common.args.apkpath common.logger.debug('User selected APK %s' + common.apkPath) common.apkPath = os.path.abspath(common.apkPath) common.apkPath = re.sub("\\\\\s",' ',common.apkPath) report.write("apkpath", common.apkPath) unpackAPK.unpack() break except Exception as e: continue try: package = defaultdict(list) result = Queue() pub.subscribe(get_manifestXML, 'manifest') thread_get_manifest = Thread(name='apktool-qark', target=apktool, args=(common.apkPath,)) thread_get_manifest.start() thread_get_manifest.join() common.manifest = minidom.parseString(common.manifest).toxml() if common.interactive_mode: show=raw_input("Inspect Manifest?[y/n]") if show in ['y','Y']: common.logger.info(common.manifest) raw_input("Press ENTER key to continue") else: common.logger.info(common.manifest) report.write_manifest(common.manifest.encode( "utf-8" )) #common.manifest = mf except IOError: