Monstrofil / replays_unpack

51 stars 19 forks source link

0.10.7 BLOB problem #13

Closed imkindaprogrammermyself closed 2 years ago

imkindaprogrammermyself commented 3 years ago

It seems some BLOBs are compressed via zlib

class Blob(_DataType):
    """
    BLOB
    — Size (bytes): N+k
    Binary data. Similar to a string, but can contain NULL characters.
    Stored in base-64 encoding when in XML, e.g., in the XML database.
    N is the number of bytes in the blob, and k=4.
    """
    _DATA_SIZE = INFINITY

    def _get_value_from_stream(self, stream: BytesIO, header_size: int):
        try:
            size, = unpack('B', stream.read(1))
            # hack for arenaStateReceived
            if size == 0xff:
                size, = unpack('H', stream.read(2))
                # some dummy shit
                unpack('B', stream.read(1))
                return stream.read(size)

            data = stream.read(size)

            if data == b'\x80':
                stream.seek(0, 1)
                return zlib.decompress(stream.read(size))
            else:
                return data
        except Exception:
            stream.seek(0)
            size, = unpack('B', stream.read(1))
            return zlib.decompress(stream.read(size))

This works on 0.10.7 but onArenaStateReceived's playersStates will now be empty.

Monstrofil commented 3 years ago

Thats interesting, it is not the one argument being compressed, but the whole method payload compressed if I got the right.

Monstrofil commented 3 years ago

The issue is somewhere in exposed index generation.

This is the last methods with right index: 78 11 receiveAcousticTargetID ([unknown: , unknown: , unknown: ]) 79 11 onItemChanged ([unknown: , unknown: , unknown: , unknown: ]) 80 13 receiveVehicleDeath ([unknown: , unknown: , unknown: ])

Next methods are shifted by 1: 86 17 receive_updateMinimapSquadron ([unknown: , unknown: ]) 87 17 receive_squadronPlanesHealth ([unknown: , unknown: ])

(should be) 87 17 receive_updateMinimapSquadron ([unknown: , unknown: ]) 88 17 receive_squadronPlanesHealth ([unknown: , unknown: ])

Still looking into the code to find what is wrong...

Monstrofil commented 3 years ago

On the other hand, these are methods for Avatar with largest exposed index.. and they are still shifted by 1, so it seems like parser just missed some method in def file...

150 65537 receiveSignedCommand ([unknown: ]) 151 65537 onGameRoomStateChanged ([unknown: , unknown: ]) 152 65537 onNewPlayerSpawnedInBattle ([unknown: ])

Monstrofil commented 3 years ago

I'm wrong in last message... this one has right ID:

151 65537 onGameRoomStateChanged ([unknown: , unknown: ])

So the problem is somewhere in between 80 and 151 exposed method :(

Monstrofil commented 3 years ago

I used ollydbg and dumped some indexes from wows client memory and got following results.

image

Either updateInvisibleWavedPoint or receive_squadronDamage index is calculated wrong, still looking into details.

Monstrofil commented 3 years ago

Found the reason.

WG dev's added new method updateInvisibleWavedPoint with USER_TYPE argument of base type VECTOR3. Earlier a thought that USER_TYPE argument size is calculated as base type size, but it seems like client just assigns it size=+INF (exposed indexes of methods are calculated in the next way: list all methods from .def file, calculate their arguments size, sort using stable sorting by size; by assigning updateInvisibleWavedPoint size of VECTOR3 parser gave it index=81 while the real one is 149).

Try updated code from master branch and I guess we can close the issue.

imkindaprogrammermyself commented 3 years ago

So it wasn't the BLOB? It's weird that I got some zlib data from it, maybe it's somewhere else but thank you!

imkindaprogrammermyself commented 2 years ago

It seems they added something new again. pickle.loads(playersStates) throwing UnicodeDecodeError in onArenaStateReceived. Probably the data is shifted again just like the last time?

Monstrofil commented 2 years ago

Hi, is problem resolved? I had no time to check it myself unfortunately.