Skip to content

Instantly share code, notes, and snippets.

@disconnect3d
Created August 1, 2018 23:59
Show Gist options
  • Save disconnect3d/0f72adf7f1f3df48eb7732b992da81f1 to your computer and use it in GitHub Desktop.
Save disconnect3d/0f72adf7f1f3df48eb7732b992da81f1 to your computer and use it in GitHub Desktop.
import marshal
import mod
print("Test code:")
print(mod.foo())
print(mod.__doc__)
PYCFILE = '__pycache__/mod.cpython-36.pyc'
with open(PYCFILE, 'rb') as f:
b = f.read()
timestamp, bytecode = b[:12], b[12:]
code = marshal.loads(bytecode)
"""
>>> dis.dis(code)
0 LOAD_CONST 0 (<code object foo at 0x7f8262da8270, file "/home/dc/fun/mod.py", line 2>)
2 LOAD_CONST 1 ('foo')
4 MAKE_FUNCTION 0
6 STORE_NAME 0 (foo)
8 LOAD_CONST 2 (None)
10 RETURN_VALUE
"""
# The foo function is in bytecode.co_consts[0]
foo_code = code.co_consts[0]
assert foo_code.co_name == 'foo'
"""
>>> dis.dis(foo_code)
0 LOAD_CONST 2 ((1, 1))
2 RETURN_VALUE
>>> foo_code.co_code
b'd\x02S\x00'
>>> foo_code.co_consts
('Function returning its docstring in a fancy way', 1, (1, 1))
"""
foo_co_code_idx = bytecode.index(
foo_code.co_code + b')\x03z/Function returning its docstring'
)
bytes_arr = bytearray(bytecode)
# bytes_arr[foo_co_code_idx+0] == 'd' == 100 == LOAD_CONST
# bytes_arr[foo_co_code_idx+1] == '\x02' == 2 == load item from .co_consts[2]
assert bytes_arr[foo_co_code_idx + 1] == 2
# The .co_consts[0] is the docstring, lets make code load [and return] it instead!
bytes_arr[foo_co_code_idx + 1] = 0
new_bytecode = bytes(bytes_arr)
with open(PYCFILE, 'wb') as f:
f.write(timestamp + new_bytecode)
print('PYC overwritten')
def foo():
"""Function returning its docstring in a fancy way"""
return 1, 1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment