Reputation:
I'm in a game coded in python, and I can access all modules and their functions.
I wan't to get a .pyc file of some of the larger functions so that I can put it through dePython or something similar. It would be a huge pain to read these functions manually.
Say I have Module.function, what can I do to get that function into a .pyc file?
Thanks!
Upvotes: 0
Views: 1624
Reputation: 7098
The function write_pycfile()
from xasm can write a pyc file. It takes an "asm" object but it needs basically a Python interpreter version and a list of code object to write. It uses functions mostly from xdis. Here is a modified version to show basically how this works:
import xdis
from xdis import magic2int
from xdis.marsh import dumps
from xdis.magics import magics
from struct import pack
from xdis.version_info import PYTHON3, version_tuple_to_str
import time
def write_pycfile(fp, code_list, timestamp=None,version_triple=xdis.PYTHON_VERSION_TRIPLE):
version_str = version_tuple_to_str(version_triple, end=2)
magic_bytes = magics[version_str]
magic_int = magic2int(magic_bytes)
fp.write(magic_bytes)
if timestamp is None:
timestamp = int(time.time())
write_source_size = version_triple >= (3, 3)
if version_triple >= (3, 7):
if magic_int == 3393:
fp.write(pack("I", timestamp))
fp.write(pack("I", 0))
else:
# PEP 552. https://www.python.org/dev/peps/pep-0552/
# 0 in the lowest-order bit means used old-style timestamps
fp.write(pack("<I", 0))
fp.write(pack("<I", timestamp))
else:
fp.write(pack("<I", timestamp))
if write_source_size:
fp.write(pack("<I", 0)) # size mod 2**32
for co in code_list:
try:
co_obj = dumps(co, python_version=version_triple)
if PYTHON3 and version_triple < (3, 0):
co_obj = str.encode(co_obj)
pass
fp.write(co_obj)
except Exception:
pass
if PYTHON3:
file_mode = 'wb'
else:
file_mode = 'w'
pyc_file = "/tmp/test.pyc"
with open("/tmp/test_pyc", file_mode) as fp:
write_pycfile(fp, [write_pycfile.__code__])
print(f"Wrote {pyc_file}")
Now run it and disassemble:
$ python /tmp/write-pyc.py
Wrote /tmp/test_pyc.pyc
$ pydisasm /tmp/test_pyc.pyc
# pydisasm version 4.3.2
# Python bytecode 3.6 (3379)
# Disassembled from Python 3.8.2 (default, Mar 28 2020, 12:46:55)
# [GCC 7.5.0]
# Timestamp in code: 1587126086 (2020-04-17 08:21:26)
# Method Name: write_pycfile
# Filename: /tmp/write-pyc.py
# Argument count: 3
# Kw-only arguments: 0
# Number of locals: 8
# Stack size: 18
# Flags: 0x00000043 (NOFREE | NEWLOCALS | OPTIMIZED)
# First Line: 9
# Constants:
# 0: None
...
# Names:
....
10: 0 LOAD_GLOBAL 0 (PYTHON3)
2 POP_JUMP_IF_FALSE 10 (to 10)
...
Finally decompile using uncompyle6:
$ uncompyle6 /tmp/test_pyc.pyc
# uncompyle6 version 3.9.0a1
# Python bytecode version base 3.6 (3379)
# Decompiled from: Python 3.6.15 (default, Sep 21 2021, 05:10:37)
# [GCC 9.3.0]
# Embedded file name: /tmp/write-pyc.py
# Compiled at: 2022-07-24 04:23:45
# Size of source mod 2**32: 1359 bytes
import xdis
from xdis import magic2int
from xdis.marsh import dumps
from xdis.magics import magics
from struct import pack
from xdis.version_info import PYTHON3, version_tuple_to_str
import time
def write_pycfile(fp, code_list, timestamp=None, version_triple=xdis.PYTHON_VERSION_TRIPLE):
version_str = version_tuple_to_str(version_triple, end=2)
magic_bytes = magics[version_str]
magic_int = magic2int(magic_bytes)
fp.write(magic_bytes)
if timestamp is None:
timestamp = int(time.time())
else:
write_source_size = version_triple >= (3, 3)
if version_triple >= (3, 7):
if magic_int == 3393:
fp.write(pack('I', timestamp))
fp.write(pack('I', 0))
else:
fp.write(pack('<I', 0))
fp.write(pack('<I', timestamp))
else:
fp.write(pack('<I', timestamp))
if write_source_size:
fp.write(pack('<I', 0))
for co in code_list:
try:
co_obj = dumps(co, python_version=version_triple)
if PYTHON3:
if version_triple < (3, 0):
co_obj = str.encode(co_obj)
fp.write(co_obj)
except Exception:
pass
# okay decompiling /tmp/write-pyc.py
Upvotes: 3
Reputation: 5220
You can either import the module to have .pyc
automatically generated, or if you prefer to do it in a programmatic manner, use py_compile
module: http://docs.python.org/2/library/py_compile.html
Upvotes: 1