CensoredUsername / unrpyc

A ren'py script decompiler
Other
837 stars 149 forks source link

Error while decompiling .rpyc #104

Closed mattmurdock12 closed 3 years ago

mattmurdock12 commented 3 years ago

I cannot convert these files to .rpy, I used sig Corrector and unRen but failed I am waiting for your help, thank you

Rpyc.zip

jackmcbarn commented 3 years ago

What game are these from? Can you zip and attach the renpy folder from it? Also, are the files you uploaded from before or after you ran sigCorrector? If after, can you also upload the original ones?

mattmurdock12 commented 3 years ago

Files.zip

Renpy and .rpyc files in zip package,(Original files not use sigCorrector) Game name (Stay True, Stay You v0.2.1) I downloaded the game from a Turkish site, I want to convert these files to .rpy and edit

but when i try sigCorrector the rpyc file is 15gb :)

jackmcbarn commented 3 years ago

I need the .py files from the renpy folder. You left them out.

mattmurdock12 commented 3 years ago

I am sorry, i cannot access the .py files because it was packaged as .exe, I pulled the .rpyc files from android

jackmcbarn commented 3 years ago

This is basically unsolvable then. Try looking for a more official source of the game, and I bet it doesn't have the same problem.

mattmurdock12 commented 3 years ago

Okay :) Thank you very much for your answers.

CensoredUsername commented 3 years ago

I took a quick look at a file and there doesn't seem to be an altered signature. Have you tested running unrpyc on it directly without sigCorrector? A 15 GB .rpyc file doesn't sound right.

jackmcbarn commented 3 years ago

I took a quick look at a file and there doesn't seem to be an altered signature. Have you tested running unrpyc on it directly without sigCorrector? A 15 GB .rpyc file doesn't sound right.

I tried this myself on the non-sigCorrector version of the files in Files.zip, and got this for all of them:

    raw_contents = raw_contents.decode('zlib')
  File "/usr/lib/python2.7/encodings/zlib_codec.py", line 43, in zlib_decode
    output = zlib.decompress(input)
error: Error -5 while decompressing data: incomplete or truncated stream

I made this change to see what was going on:

diff --git a/unrpyc.py b/unrpyc.py
index 2a783e8..6cf4e81 100755
--- a/unrpyc.py
+++ b/unrpyc.py
@@ -95,6 +95,7 @@ def read_ast_from_file(in_file):
         chunks = {}
         while True:
             slot, start, length = struct.unpack("III", raw_contents[position: position + 12])
+            print((slot, start, length))
             if slot == 0:
                 break
             position += 12

And for options.rpyc, it gave me this:

(1, 1207959598, 33554688)
(1633643008, 16842752, 39531777)
(3735552, 1, 74)
(3622, 2, 3696)
(3622, 0, 0)
(0, 1502452856, 1252161373)

For a "normal" options.rpyc from a different game, I got this:

(1, 46, 2638)
(2, 2684, 2638)
(0, 0, 0)

If I had the .py files, I could solve this easily. If the place he got this from really went to all the trouble to build a .exe instead of shipping .py files (which the official distribution of this game does not do, by the way), I'd suspect that it's the pirate site he got it from trying to hide malware in them.

CensoredUsername commented 3 years ago

hah. The contents table is indeed spoofed. The spoof just starts like a normal signature but then contains some binary garbage. But the actual contents table is still there. Whoever made this was probably aware of the existence of that signature corrector tool (or whatever it's called) and from what I've seen here I guess that tool just looks for the first word matching 0x00000001. So they just put in a fake 0x00000001 in their header to spoof it, amusing. Shenanigans like that are easily revealed by just comparing two files though.

(1, 1207959598, 33554688)
(1633643008, 16842752, 39531777)
(3735552, 1, 74)
(3622, 2, 3696)
(3622, 0, 0)
(0, 1502452856, 1252161373)

If we look closely the actual header is in there, hiding in plain sight:

    1, 74)
(3622, 2, 3696)
(3622, 0, 0)
(0
(1, 74, 3622),
(2, 3696, 3622)
(0, 0, 0)

So basically just start parsing the header from byte 38 instead of byte 10 and it should decode fine.

Ooh but now we're getting into fun stuff. They messed around with the pickle implementation used as well I think. Diving in deeper, there are some proper shenanigans here.

CensoredUsername commented 3 years ago

Ok those further shenanigans were less interesting than I'd hoped. The actual contents were just base64-encoded before they were compressed. This edit to unrpyc.py will decode everything just fine.

diff --git a/unrpyc.py b/unrpyc.py
index 70b1a87..b359402 100755
--- a/unrpyc.py
+++ b/unrpyc.py
@@ -91,19 +91,21 @@ def read_ast_from_file(in_file):
     raw_contents = in_file.read()
     if raw_contents.startswith("RENPY RPC2"):
         # parse the archive structure
-        position = 10
+        position = 38
         chunks = {}
         while True:
             slot, start, length = struct.unpack("III", raw_contents[position: position + 12])
             if slot == 0:
                 break
             position += 12
-
             chunks[slot] = raw_contents[start: start + length]

         raw_contents = chunks[1]

     raw_contents = raw_contents.decode('zlib')
+    import base64
+    raw_contents = base64.b64decode(raw_contents)
+
     data, stmts = magic.safe_loads(raw_contents, class_factory, {"_ast", "collections"})
     return stmts
mattmurdock12 commented 3 years ago

sorry i replied late but i found all .py files @jackmcbarn

Files.zip

CensoredUsername commented 3 years ago

@mattmurdock12 the above diff should solve your issue, please test it. It's game specific so it won't be merged in the mainline decompiler (I'll move it to a branch).

mattmurdock12 commented 3 years ago

I have a unRen.bat, how can i edit this code ?

CensoredUsername commented 3 years ago

No idea. This is the issue tracker for unrpyc. You can try using it directly using the instructions in the README. I was able to decompile the files you sent with these changes, I'd like your confirmation that it works so I can finish this by branching it off on a game support branch.

mattmurdock12 commented 3 years ago

new error

I did change unrpyc.py and i have new error

CensoredUsername commented 3 years ago

The -'ses and +'ses are to indicate removed/added lines in the diff. So you need to change that part of the file to say this:

    raw_contents = in_file.read()
    if raw_contents.startswith("RENPY RPC2"):
        # parse the archive structure

        position = 38
        chunks = {}
        while True:
            slot, start, length = struct.unpack("III", raw_contents[position: position + 12])
            if slot == 0:
                break
            position += 12
            chunks[slot] = raw_contents[start: start + length]

        raw_contents = chunks[1]

    raw_contents = raw_contents.decode('zlib')
    import base64
    raw_contents = base64.b64decode(raw_contents)

    data, stmts = magic.safe_loads(raw_contents, class_factory, {"_ast", "collections"})
    return stmts
mattmurdock12 commented 3 years ago

New error :( hata

mattmurdock12 commented 3 years ago

Successfully decompiled after the first 47 letters were deleted, thank you.

CensoredUsername commented 3 years ago

I'll close this soon then. Might add a command line argument to adjust the location that we expect the table to be at. Shenanigans beget shenanigans.

mattmurdock12 commented 3 years ago

And , ı want ask you someting else , I find this code in other game .py files "encode('string-escape').encode('hex').encode('zlib')"

And I cant open this game rpyc files

CensoredUsername commented 3 years ago

it's doing something dumb to encode file contents in a different way. Just mod unrpyc to reverse the operation when unrpyc tries loading it.

CensoredUsername commented 3 years ago

As these shenanigans are getting a bit more common I've added some scaffolding code that tries to figure out if it's a known method on the dev branch. You can use it with the --try-harder option.

mattmurdock12 commented 2 years ago

renpy.zip

Hello, I have a new problem. I added the renpy folder, I can't convert files from .rpyc to .rpy. And I can't open .rpa archive.

please help :) @CensoredUsername

CensoredUsername commented 2 years ago

@mattmurdock12 please create a new issue, and follow the issue reporting guides listed in the README.