Skip to content

Instantly share code, notes, and snippets.

@AmiZya
Last active October 24, 2022 16:57
Show Gist options
  • Save AmiZya/1e0ffee26a3a95e9beb1646f0d40c092 to your computer and use it in GitHub Desktop.
Save AmiZya/1e0ffee26a3a95e9beb1646f0d40c092 to your computer and use it in GitHub Desktop.
Parsing python bytecode for fun (work in progress)
opmap = {'POP_TOP': 1, 'ROT_TWO': 2, 'ROT_THREE': 3, 'DUP_TOP': 4, 'DUP_TOP_TWO': 5, 'ROT_FOUR': 6, 'NOP': 9, 'UNARY_POSITIVE': 10, 'UNARY_NEGATIVE': 11, 'UNARY_NOT': 12, 'UNARY_INVERT': 15, 'BINARY_MATRIX_MULTIPLY': 16, 'INPLACE_MATRIX_MULTIPLY': 17, 'BINARY_POWER': 19, 'BINARY_MULTIPLY': 20, 'BINARY_MODULO': 22, 'BINARY_ADD': 23, 'BINARY_SUBTRACT': 24, 'BINARY_SUBSCR': 25, 'BINARY_FLOOR_DIVIDE': 26, 'BINARY_TRUE_DIVIDE': 27, 'INPLACE_FLOOR_DIVIDE': 28, 'INPLACE_TRUE_DIVIDE': 29, 'RERAISE': 48, 'WITH_EXCEPT_START': 49, 'GET_AITER': 50, 'GET_ANEXT': 51, 'BEFORE_ASYNC_WITH': 52, 'END_ASYNC_FOR': 54, 'INPLACE_ADD': 55, 'INPLACE_SUBTRACT': 56, 'INPLACE_MULTIPLY': 57, 'INPLACE_MODULO': 59, 'STORE_SUBSCR': 60, 'DELETE_SUBSCR': 61, 'BINARY_LSHIFT': 62, 'BINARY_RSHIFT': 63, 'BINARY_AND': 64, 'BINARY_XOR': 65, 'BINARY_OR': 66, 'INPLACE_POWER': 67, 'GET_ITER': 68, 'GET_YIELD_FROM_ITER': 69, 'PRINT_EXPR': 70, 'LOAD_BUILD_CLASS': 71, 'YIELD_FROM': 72, 'GET_AWAITABLE': 73, 'LOAD_ASSERTION_ERROR': 74, 'INPLACE_LSHIFT': 75, 'INPLACE_RSHIFT': 76, 'INPLACE_AND': 77, 'INPLACE_XOR': 78, 'INPLACE_OR': 79, 'LIST_TO_TUPLE': 82, 'RETURN_VALUE': 83, 'IMPORT_STAR': 84, 'SETUP_ANNOTATIONS': 85, 'YIELD_VALUE': 86, 'POP_BLOCK': 87, 'POP_EXCEPT': 89, 'STORE_NAME': 90, 'DELETE_NAME': 91, 'UNPACK_SEQUENCE': 92, 'FOR_ITER': 93, 'UNPACK_EX': 94, 'STORE_ATTR': 95, 'DELETE_ATTR': 96, 'STORE_GLOBAL': 97, 'DELETE_GLOBAL': 98, 'LOAD_CONST': 100, 'LOAD_NAME': 101, 'BUILD_TUPLE': 102, 'BUILD_LIST': 103, 'BUILD_SET': 104, 'BUILD_MAP': 105, 'LOAD_ATTR': 106, 'COMPARE_OP': 107, 'IMPORT_NAME': 108, 'IMPORT_FROM': 109, 'JUMP_FORWARD': 110, 'JUMP_IF_FALSE_OR_POP': 111, 'JUMP_IF_TRUE_OR_POP': 112, 'JUMP_ABSOLUTE': 113, 'POP_JUMP_IF_FALSE': 114, 'POP_JUMP_IF_TRUE': 115, 'LOAD_GLOBAL': 116, 'IS_OP': 117, 'CONTAINS_OP': 118, 'JUMP_IF_NOT_EXC_MATCH': 121, 'SETUP_FINALLY': 122, 'LOAD_FAST': 124, 'STORE_FAST': 125, 'DELETE_FAST': 126, 'RAISE_VARARGS': 130, 'CALL_FUNCTION': 131, 'MAKE_FUNCTION': 132, 'BUILD_SLICE': 133, 'LOAD_CLOSURE': 135, 'LOAD_DEREF': 136, 'STORE_DEREF': 137, 'DELETE_DEREF': 138, 'CALL_FUNCTION_KW': 141, 'CALL_FUNCTION_EX': 142, 'SETUP_WITH': 143, 'LIST_APPEND': 145, 'SET_ADD': 146, 'MAP_ADD': 147, 'LOAD_CLASSDEREF': 148, 'EXTENDED_ARG': 144, 'SETUP_ASYNC_WITH': 154, 'FORMAT_VALUE': 155, 'BUILD_CONST_KEY_MAP': 156, 'BUILD_STRING': 157, 'LOAD_METHOD': 160, 'CALL_METHOD': 161, 'LIST_EXTEND': 162, 'SET_UPDATE': 163, 'DICT_MERGE': 164, 'DICT_UPDATE': 165}
def get(arg):
if type(arg) == str:
return opmap[arg]
elif type(arg) == int:
for k,v in opmap.items():
if v == arg:
return k
raise KeyError('Opcode not found')
import struct, marshal, time, sys
import opcodes
file_path = "__pycache__/main.cpython-39.pyc"
HAVE_ARGUMENT = 90
with open(file_path, 'rb') as f:
magic = f.read(4).hex()
bit_field = int.from_bytes(f.read(4), 'little')
print(opcodes.get(144))
if bit_field != 0:
assert False, "Non traditional timestamp is not implemented yet!"
modified = f.read(4)
size = f.read(4)
modtime = time.asctime(time.localtime(struct.unpack('=L', modified)[0]))
code = marshal.load(f)
print(code.co_code)
for byte in code.co_code:
print(byte)
while True:
opcode = f.read(1)
oparg = f.read(1)
print(int.from_bytes(opcode, 'little'))
if not opcode:
print("Reached the end of file")
break
print("--------------")
print("magic: ", magic)
print("bit field: ", bit_field)
print("modified: ", modified)
print("modified readable:", modtime)
print("size: ", int.from_bytes(size, "little"))
#print(help(code))
print("--------------")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment