Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unpacked .pyc files are invalid (with dirty solution) #14

Open
Gowee opened this issue Jan 17, 2020 · 10 comments
Open

Unpacked .pyc files are invalid (with dirty solution) #14

Gowee opened this issue Jan 17, 2020 · 10 comments

Comments

@Gowee
Copy link

Gowee commented Jan 17, 2020

When I try to decompile .pyc files generated by python-exe-unpacker, I got the following error:

Traceback (most recent call last):
  File "/usr/local/lib/python3.7/site-packages/xdis/load.py", line 209, in load_module_from_file_object
    co = marshal.loads(bytecode)
ValueError: bad marshal data (unknown type code)

And those .pyc are also treated invalid by Python interpreter:

RuntimeError: Bad code object in .pyc file

After spending two hours figuring out what's wrong, I think it is valuable to note them down here even if this project seemingly has ended:

I suppose the problem resides around
https://github.com/countercept/python-exe-unpacker/blob/6c88e9b28cb40615b680cefdb5f47ce4cab17833/pyinstxtractor.py#L322
where the appended header (incl. magic number, timestamp, size, etc) seems to mismatch with the .pyc format used by some newer Python versions (in my case 3.7).

To make uncompyle6 work well with malformed .pyc, dirty patch /usr/local/lib/python3.7/site-packages/xdis/load.py to make sure marshal.loads data starting from exactly 12th byte of original .pyc (e.g. utilizing BytesIO so that the fp can be read twice) helps.

@appieGIT
Copy link

appieGIT commented Jan 21, 2020

I'm currently experiencing the same issue, and even though you gave the solution, I cannot figure out how to implement it myself. What do I need to change exactly in the load.py for it to work?

EDIT:
Some information, I'm using Python 3.8 and also trying to decompile a .pyc file made with Python 3.8
I've been trying to make your solution work, but so far no luck.

@Gowee
Copy link
Author

Gowee commented Jan 31, 2020

@appieGIT The dirty way aforementioned is a little tricky. Here is another way I did not try but expected to work:

Adding a new line pycFile.write(b'\0' * 4) just after the line https://github.com/countercept/python-exe-unpacker/blob/6c88e9b28cb40615b680cefdb5f47ce4cab17833/pyinstxtractor.py#L323

@AlbertJanSch
Copy link

@Gowee I have tried this solution just now. It does start right now, which is something, but it keeps returning a parse error when decompyling the .pyc files with uncompyle6 or decompyle3.
I'm pretty sure this is still due to invalid .pyc files from the unpacker.

Is there any other solution you can think of?

@Gowee
Copy link
Author

Gowee commented Jan 31, 2020

@AlbertJanSch Would you mind sharing a sample .pyc?

@AlbertJanSch
Copy link

@Gowee Of course. I uploaded a sample called calendar.pyc here: https://www.sendspace.com/file/id2d1f

@Gowee
Copy link
Author

Gowee commented Jan 31, 2020

@AlbertJanSch I see
Parse error at or near 'POP_BLOCK' instruction at offset 36. But I do not think it owes to python-exe-unpacker. And I have no idea how to fix it. Open a issue in the uncompyle6 project instead?

@CopyMist
Copy link

CopyMist commented Mar 24, 2020

Gonna rephrase the solution in #14 (comment) for us, newbies. If you use rocky/python-decompile3 after extracting .pyc files and get "bad marshal data", do the following:

  1. Open the file /usr/local/lib/python3.7/site-packages/xdis/load.py
  2. Find lines:
if my_magic_int == magic_int:
    bytecode = fp.read()
    co = marshal.loads(bytecode)
  1. Replace with:
if my_magic_int == magic_int:
    fp.seek(12)
    bytecode = fp.read()
    co = marshal.loads(bytecode)

fp.seek(12) skips reading of the first 12 bytes and makes the decompiler work again.

Don't forget to revert the changes after you're done with decompilation.
Thanks to the original solution provider!

@venaxyt
Copy link

venaxyt commented Nov 2, 2021

It still doesn't works for me.. :( I tried all you have said until this message.

@ecoop3r
Copy link

ecoop3r commented Mar 7, 2022

@CopyMist solution worked great for me. Tyty

@rkbennett
Copy link

I know this is a fairly old issue, but also try skipping 16 and 8 as well. 16 worked for me in python 3.10, I've heard 8 also works potentially.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants