Exemplo n.º 1
0
def cfr(path, dirname):
    """
	calls the cfr decompiler from command line
	"""
    process = subprocess.Popen([
        "java", "-jar", common.rootDir + "/lib/cfr_0_115.jar", path,
        "--outputdir", dirname + "1"
    ],
                               stdout=subprocess.PIPE,
                               stderr=subprocess.STDOUT)
    try:
        while True:
            line = process.stdout.readline()
            if not line:
                break
            if "Processing" in line:
                common.counter1 = common.counter1 + 1
                pub.sendMessage('decompile',
                                cfr=round(common.counter1 * 100 /
                                          common.count))
                pub.sendMessage('decompile',
                                jdcore=round(common.counter1 * 100 /
                                             common.count))
    except Exception as e:
        logger.debug(e.message)
Exemplo n.º 2
0
def procyon(path,dirname):
	"""
	calls the procyon decompiler from command line
	"""
	process = subprocess.Popen(["java","-jar", common.rootDir + "/lib/procyon/procyon-decompiler-0.5.30.jar", path, "-o ", dirname+"2"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
	try:
		while True:
			line = process.stdout.readline()
			if not line:
				break
			if "Decompiling" in line:
				common.counter2 = common.counter2 + 1
				pub.sendMessage('decompile', procyon=round(common.counter2*100/common.count))
	except Exception as e:
		logger.debug(e.message)
Exemplo n.º 3
0
def cfr(path,dirname):
	"""
	calls the cfr decompiler from command line
	"""
	process = subprocess.Popen(["java","-jar", common.rootDir + "/lib/cfr_0_115.jar", path, "--outputdir", dirname+"1"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
	try:
		while True:
			line = process.stdout.readline()
			if not line:
				break
			if "Processing" in line:
				common.counter1 = common.counter1 + 1
				pub.sendMessage('decompile', cfr=round(common.counter1*100/common.count))
				pub.sendMessage('decompile', jdcore=round(common.counter1*100/common.count))
	except Exception as e:
		logger.debug(e.message)
Exemplo n.º 4
0
def procyon(path, dirname):
    """
	calls the procyon decompiler from command line
	"""
    process = subprocess.Popen([
        "java", "-jar",
        common.rootDir + "/lib/procyon/procyon-decompiler-0.5.30.jar", path,
        "-o ", dirname + "2"
    ],
                               stdout=subprocess.PIPE,
                               stderr=subprocess.STDOUT)
    try:
        while True:
            line = process.stdout.readline()
            if not line:
                break
            if "Decompiling" in line:
                common.counter2 = common.counter2 + 1
                pub.sendMessage('decompile',
                                procyon=round(common.counter2 * 100 /
                                              common.count))
    except Exception as e:
        logger.debug(e.message)
Exemplo n.º 5
0
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))
Exemplo n.º 6
0
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))