import subprocess import os import shutil import sys import logging logging.basicConfig(filename='analyzer.log', level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') def decompile_pyc(pyc_file, source_dir): try: pycdc_process = subprocess.Popen(['resources\pycdc.exe', pyc_file], stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE, shell=True) stdout, stderr = pycdc_process.communicate() decoded_code = stdout.decode('utf-8') pyc_filename = os.path.basename(pyc_file) py_filename = pyc_filename[:-4] + '.py' count = 2 while os.path.exists(os.path.join(source_dir, py_filename)): py_filename = pyc_filename[:-4] + f'_{count}.py' count += 1 py_filepath = os.path.join(source_dir, py_filename) with open(py_filepath, 'w') as py_file: py_file.write(decoded_code) logging.info(f"Decompiled {pyc_filename}") print(f"Decompiled {pyc_filename}") except Exception as e: logging.error(f"Error decompiling pyc: {e}") print(f"Error decompiling pyc: {e}") return def main(): logging.info("Starting analysis.") if len(sys.argv) != 2: logging.error("Usage: python script.py FILE_TO_ANALYZE.exe") print("Usage: python script.py FILE_TO_ANALYZE.exe") sys.exit(1) file_to_analyze = sys.argv[1] extracted_dir = file_to_analyze + '_extracted' source_dir = file_to_analyze + '_source' entry_points_dir = os.path.join(source_dir, 'entry_points') os.makedirs(source_dir, exist_ok=True) os.makedirs(entry_points_dir, exist_ok=True) try: pycdc_process = subprocess.Popen(['python', 'resources\pyinstxtractor.py', file_to_analyze, '-w', extracted_dir], stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE, shell=True) stdout, stderr = pycdc_process.communicate() output_lines = stdout.decode('utf-8').splitlines() entry_points = [line.split()[-1] for line in output_lines if 'Possible entry point' in line] logging.info(f"Possible entry points: {entry_points}") for root, dirs, files in os.walk(extracted_dir): for file in files: if file.endswith('.pyc'): pyc_file = os.path.join(root, file) pyc_filename = os.path.basename(pyc_file) if pyc_filename in entry_points: logging.info(f"Decompiling entry point: {pyc_filename}") decompile_pyc(pyc_file, source_dir) source_file = os.path.join(source_dir, pyc_filename[:-4] + '.py') entry_point_dest = os.path.join(entry_points_dir, pyc_filename[:-4] + '.py') shutil.move(source_file, entry_point_dest) continue_with_others = input("Do you want to continue with decompiling other files? (y/n): ").strip().lower() if continue_with_others != 'y': logging.info("Decompilation of other files cancelled.") print("Decompilation of other files cancelled.") shutil.rmtree(extracted_dir) logging.info("Analysis completed.") print("Analysis completed.") sys.exit(0) for root, dirs, files in os.walk(extracted_dir): for file in files: if file.endswith('.pyc'): pyc_file = os.path.join(root, file) pyc_filename = os.path.basename(pyc_file) if pyc_filename not in entry_points: logging.info(f"Decompiling: {pyc_filename}") decompile_pyc(pyc_file, source_dir) except subprocess.CalledProcessError as e: logging.error(f"Error extracting bytecode: {e}") print(f"Error extracting bytecode: {e}") sys.exit(1) shutil.rmtree(extracted_dir) logging.info("Analysis completed.") print("Analysis completed.") if __name__ == '__main__': main()