Svenskithesource / PyArmor-Unpacker

A deobfuscator for PyArmor.
GNU General Public License v3.0
493 stars 73 forks source link

IndexError: tuple index out of range (when decompiling .pyc) #16

Closed stufert closed 1 year ago

stufert commented 2 years ago

First of all many thanks for providing multiple methods for unpacking pyarmor-protected files including the detailed descriptions.

I tried out your described methods to unpack a few files. After trying out multiple python versions and having issues with the 2nd and 3rd method (either or just receiving 0 while keeping an empty dump directory), I was able to successfully unpack a file with your third method. Since the bytecode was created with version 3.9 and contains opcodes that are currently not supported in pycdc (e.g. EXTENDED_ARG) I used the internal dis module and xdis to disassemble the bytecode.

While doing this, i went into the following issue:

Traceback (most recent call last):
  File "/Users/felix/git_private/deobfuscate/python-xdis/bin/../xdis/bin/pydisasm.py", line 77, in <module>
    main(sys.argv[1:])
  File "/Users/felix/.pyenv/versions/deob_venv/lib/python3.9/site-packages/click/core.py", line 1130, in __call__
    return self.main(*args, **kwargs)
  File "/Users/felix/.pyenv/versions/deob_venv/lib/python3.9/site-packages/click/core.py", line 1055, in main
    rv = self.invoke(ctx)
  File "/Users/felix/.pyenv/versions/deob_venv/lib/python3.9/site-packages/click/core.py", line 1404, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "/Users/felix/.pyenv/versions/deob_venv/lib/python3.9/site-packages/click/core.py", line 760, in invoke
    return __callback(*args, **kwargs)
  File "/Users/felix/git_private/deobfuscate/python-xdis/bin/../xdis/bin/pydisasm.py", line 72, in main
    disassemble_file(path, sys.stdout, format)
  File "/Users/felix/git_private/deobfuscate/python-xdis/xdis/disasm.py", line 326, in disassemble_file
    disco(
  File "/Users/felix/git_private/deobfuscate/python-xdis/xdis/disasm.py", line 160, in disco
    disco_loop_asm_format(opc, version_tuple, co, real_out, {}, set([]))
  File "/Users/felix/git_private/deobfuscate/python-xdis/xdis/disasm.py", line 220, in disco_loop_asm_format
    disco_loop_asm_format(
  File "/Users/felix/git_private/deobfuscate/python-xdis/xdis/disasm.py", line 263, in disco_loop_asm_format
    real_out.write(bytecode.dis(asm_format="asm") + "\n")
  File "/Users/felix/git_private/deobfuscate/python-xdis/xdis/bytecode.py", line 327, in dis
    self.disassemble_bytes(
  File "/Users/felix/git_private/deobfuscate/python-xdis/xdis/bytecode.py", line 375, in disassemble_bytes
    for instr in get_instructions_bytes(
  File "/Users/felix/git_private/deobfuscate/python-xdis/xdis/bytecode.py", line 185, in get_instructions_bytes
    argval, argrepr = _get_const_info(arg, constants)
  File "/Users/felix/git_private/deobfuscate/python-xdis/xdis/bytecode.py", line 78, in _get_const_info
    argval = const_list[const_index]
IndexError: tuple index out of range

It doesn't only happen for the constants, but also for the name references. Just logged the issue and noticed that sometimes, apart from several opcodes with only numbers, e.g. <140>, the oparg is higher than the number of elements in co.co_varnames, co.co_names, co.co_consts. As a result, the output of two methods is nearly completely unreadable.

Do u have any ideas on how to bypass this?

Svenskithesource commented 2 years ago

Hey, this is probably due to it not actually being unpacked, can you send the file over so I can analyze it? Thanks. I also recommend you edit your dis.py package so that you can still see the invalid bytecode. Just add a try-except statement.