@@ -61,18 +61,23 @@ def display_code(code_obj):
6161def get_crypto_info (all_data : bytes , code_obj ) -> dict :
6262 """Returns a dictionary with information about the ciphered region in the code object."""
6363
64- # NOTES:
64+ # NOTES (Python 3.11+) :
6565 # 1. co_code is sanitized before being given out to a script (invalid opcodes are zeroed), so it's useless for us
6666 # 2. Using _co_code_adaptive only works because we disable specialization in our custom Python build
67- code : bytes = code_obj ._co_code_adaptive
67+ if sys .version_info .major > 3 or sys .version_info .minor > 10 :
68+ code : bytes = code_obj ._co_code_adaptive
69+ else :
70+ code = code_obj .co_code
6871 code_offset_in_data = all_data .index (code )
6972
70- if code [8 ] != opcode .opmap ["LOAD_CONST" ] or code [12 ] != opcode .opmap ["CALL_FUNCTION_EX" ]:
73+ case1 = code [8 ] == opcode .opmap ["LOAD_CONST" ] and code [12 ] == opcode .opmap ["CALL_FUNCTION_EX" ]
74+ case2 = code [14 ] == opcode .opmap ["LOAD_CONST" ] and code [16 ] == opcode .opmap ["CALL_FUNCTION" ]
75+ if not case1 and not case2 :
7176 print ("Method does not seem to be encrypted" )
7277 return {}
7378
74- # Get the LOAD_CONST bytes that can be seen above at offset 8.
75- crypto_info = code_obj .co_consts [code [9 ]]
79+ # Get the constant that is loaded by LOAD_CONST at offset 8 or 14 .
80+ crypto_info = code_obj .co_consts [code [( 8 if case1 else 14 ) + 1 ]]
7681
7782 if not isinstance (crypto_info , bytes ):
7883 raise Exception (f"Expected LOAD_CONST to load bytes, got { type (crypto_info )} " )
0 commit comments