Skip to content

Instantly share code, notes, and snippets.

@ifahadone
Last active November 22, 2023 05:58
Show Gist options
  • Save ifahadone/2a38a4332b09da855fcb22354124be48 to your computer and use it in GitHub Desktop.
Save ifahadone/2a38a4332b09da855fcb22354124be48 to your computer and use it in GitHub Desktop.
Maintains directory structure while decompiling ".pyc" to ".py" recursively
# --------- USAGE -----------
# USE THIS FILE IF YOU WANT TO MAINTAIN DIRECTORY STRUCTURE WHILE DECOMPILING ".PYC" TO ".PY" RECURSIVELY
# Install Python
# Run -> pip install uncompyle6
# Run -> python decompile_pyc_recursively.py -p [PATH-OF-PYC-DIR]
# ----------------------------
import argparse
import os
import glob
import subprocess
FROM_EXTENSION = "pyc"
TO_EXTENSION = "py"
parser = argparse.ArgumentParser(
description='Decompile .pyc files recursively. '
'It takes a directory in --path argument to scan for .pyc files to uncompile')
parser.add_argument('-p', '--path', dest='path',
default=os.path.abspath("."),
help="Specify root directory to scan pyc files from")
class uncompyle6:
def __init__(self):
pass
@staticmethod
def check_uncompyle():
try:
subprocess.call(["uncompyle6", "--version"])
except OSError as e:
print("[ERROR] - uncompyle6 or any of its dependencies are not installed")
print(
"[ERROR] - refer to https://pypi.org/project/uncompyle6/ to install uncompyle6 and try again")
exit(e.errno)
@staticmethod
def swap_extension(compiled):
"""
Swap file extension from .pyc to .py
:param compiled:
:return:
"""
metadata = os.path.splitext(compiled)
return "{0}.{1}".format(metadata[0], TO_EXTENSION)
def normalize_path(self, paths):
"""
Normalize paths
:param paths:
:return:
"""
clean = [] # hold clean list of normalized matching paths
prefix = os.path.commonprefix(paths)
for i in paths:
source = i
base = self.swap_extension(i.replace(prefix, ""))
clean.append({"source": source, "dirname": os.path.dirname(
base), "name": os.path.basename(base)})
return clean
@staticmethod
def search_pyc(use_directory):
"""
Search .pyc files
:param use_directory:
:return:
"""
return glob.glob("/".join([use_directory, "*." + FROM_EXTENSION]))
@staticmethod
def setup_directories(directories, parent):
"""
Mimic file organization
:param directories:
:param parent:
:return:
"""
for i in directories:
if i["dirname"]:
directory_name = os.path.join(parent, i["dirname"])
if os.path.exists(directory_name):
continue
os.mkdir(directory_name)
print("[INFO] - Done creating %s directory" % directory_name)
@staticmethod
def uncompyle(locations, parent):
for i in locations:
uncompyle_source = i["source"]
uncompyle_to = os.path.join(parent, i["dirname"], i["name"])
subprocess.call(
["uncompyle6", "-o", uncompyle_to, uncompyle_source])
print(
"[INFO] - {0} decompiled at {1}".format(uncompyle_source, uncompyle_to))
if __name__ == "__main__":
matches = []
args = parser.parse_args()
path = args.path
os.mkdir('decompiled')
cwd = os.path.abspath("./decompiled")
uncompyler = uncompyle6()
uncompyler.check_uncompyle()
for root, dirs, files in os.walk(path):
for result in uncompyler.search_pyc(root):
matches.append(result)
normalized = uncompyler.normalize_path(matches)
uncompyler.setup_directories(normalized, cwd)
uncompyler.uncompyle(normalized, cwd)
exit(0)

⚠️ USE THIS FILE IF YOU WANT TO DECOMPILE SINGLE ".PYC" TO ".PY".

  • INSTALL PYTHON
  • INSTALL UNCOMPLYLE -> pip install uncompyle6
  • RUN THIS TO DECOMPILE SINGLE FILE FROM THE SOURCE FILE DIRECTORY -> python -m uncompyle6 -o . <fileName.pyc>
@ifahadone
Copy link
Author

ifahadone commented Apr 24, 2021

USEAGE

pip install uncompyle6
python decompile_pyc_recursively.py -p [PATH]

OUTPUT

  • It will produce uncompiled files in a decompiled named folder.

@praveenpgeb
Copy link

hi its not working for python 3.9 plz update

@ifahadone
Copy link
Author

hi its not working for python 3.9 plz update

Could you please explain the error in more detail?

@ideamartin
Copy link

Unsupported Python version, 3.10.0, for decompilation

@ifahadone
Copy link
Author

@praveenpgeb @ideamartin
Please retry; this is still effective with any python 3.0 and above versions.

image

Please, stick to the above steps. -> steps

@praveenpgeb
Copy link

@praveenpgeb @ideamartin Please retry; this is still effective with any python 3.0 and above versions.

image

Please, stick to the above steps. -> steps

Untitled

plz check

@ideamartin
Copy link

image
only shows the version

@ifahadone
Copy link
Author

@praveenpgeb @ideamartin
I believe you are both attempting to decompile only one file; in that case, follow this one.-> single .pyc decompile

@ideamartin
Copy link

@praveenpgeb @ideamartin I believe you are both attempting to decompile only one file; in that case, follow this one.-> single .pyc decompile

image
a file created. but nothing compiled

@Abhi5033
Copy link

I'm trying to decompile a single pyc file of 3.9 version
And I ran this command "python -m uncompyle6 -o main.pyc"
It is showing this error sir
ImportError: cannot import name 'iscode' from 'xdis'

@ifahadone
Copy link
Author

I'm trying to decompile a single pyc file of 3.9 version And I ran this command "python -m uncompyle6 -o main.pyc" It is showing this error sir ImportError: cannot import name 'iscode' from 'xdis'

Let me look into it over the weekend and get back to you. 

@Abhi5033
Copy link

I'm trying to decompile a single pyc file of 3.9 version And I ran this command "python -m uncompyle6 -o main.pyc" It is showing this error sir ImportError: cannot import name 'iscode' from 'xdis'

Let me look into it over the weekend and get back to you.

Sir I need your help
I have contacted you in instagram.. please check sir

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment