Svenskithesource / PyArmor-Unpacker

A deobfuscator for PyArmor.
GNU General Public License v3.0
536 stars 75 forks source link

handle_armor_enter ValueError #40

Closed hkhj326 closed 1 year ago

hkhj326 commented 1 year ago

Python 3.8.10 Windows10

use Method2 unpack throw this error:

Traceback (most recent call last): File "", line 4, in File "", line 457, in File "", line 233, in output_code File "", line 233, in File "", line 245, in output_code File "", line 330, in handle_armor_enter ValueError: byte must be in range(0, 256)

Svenskithesource commented 1 year ago

Hello, could you please print the byte that's trying to add/change?

AI-M-BOT commented 1 year ago

-26 using python 3.8.0 64bit

Svenskithesource commented 1 year ago

This could be because the script detects the fake_exit wrong. You can change this to fake_exit = 6 in the code. From experience that is the most common fake exit.

AI-M-BOT commented 1 year ago
fake 78

fake 84

fake 174
-26

fake 78

fake 62

fake 128

fake 170
-26

fake 62
-26
-26

fake 92
-26
-26

fake 122

fake 748

It seems like only some of the fake_exit value will cause wrong bytes if i just change fake_exit to 6, pycdc will stop at here:

...
def protect_pytransform():
    import pytransform

    def assert_builtin(func):
        type = ''.__class__.__class__
        builtin_function = type(''.join)
        if type(func) is not builtin_function:
            raise RuntimeError('%s() is not a builtin' % func.__name__)

    def check_obfuscated_script():
Svenskithesource commented 1 year ago

Can you show me the changes you made? Also, you cannot rely on pycdc as it is unstable. Even if the unpacking is perfect there is still a high chance of failure.

w1redch4d commented 1 year ago
if argument == fake_exit:
                raw_code[i] = opcode.opmap[
                    "RETURN_VALUE"
                ]  # Got to use this because the variable is converted to bytes
                continue

to

if argument < try_start + 2:
                raw_code[i] = opcode.opmap["RETURN_VALUE"] # Got to use this because the variable is converted to bytes
                continue

should work, works atleast for me , havent looked at the source code for a year now prolly

OwnerCM commented 1 year ago
if argument == fake_exit:
                raw_code[i] = opcode.opmap[
                    "RETURN_VALUE"
                ]  # Got to use this because the variable is converted to bytes
                continue

to

if argument < try_start + 2:
                raw_code[i] = opcode.opmap["RETURN_VALUE"] # Got to use this because the variable is converted to bytes
                continue

should work, works atleast for me , havent looked at the source code for a year now prolly

I have the same problem, but I cannot modify argument < try_start + 2. This will cause an error in the unpacked pyc. Are there any other solutions? @Svenskithesource

Svenskithesource commented 1 year ago

Have you tried setting fake_exit to 6 like I showed above?

OwnerCM commented 1 year ago

Have you tried setting fake_exit to 6 like I showed above?

Yes, I have tried it too, but the output pyc has return value exceptions, as follows: L.3439 546 LOAD_FAST 'qlines' 548 RETURN_VALUE 550 SETUP_EXCEPT 768 'to 768'

L.1041 632 LOAD_CONST True 634 RETURN_VALUE
636 <41>

Svenskithesource commented 1 year ago

This is a known issue that it leaves an extra opcode behind, but it doesn't matter. The code will still work just fine.