Search code examples
c++compressionzlibinflateworld-of-warcraft

How to decompress WoW data


I have pcap file with World of Warcraft traffic and I need to uncompress it. I know that it is compressed by Zlib: http://wiki.xentax.com/index.php/List_Of_Compressed_Games So to find the beginning of a compressed block i wrote a piece of code that iterates through raw data,tries to decompress data and checks whether some output available.

I call inflateInit2 function to initialize zlib with windowBits parameters 15(zlib format) and 30(gzip format). I tried inflate() with Z_SYNC_FLUSH and Z_FULL_FLUSH parameter. But it gives me no output.

Ip traffic looks like this

Each packet ends with 00 00 00 ff ff. But zlib manual says that it has to be 00 00 ff ff.

So what is the way to extract data from WoW stream?

My code is:

void tryZlib(unsigned __int8 *StPt, __int64 size, Deflate *zlib)
{
    z_stream_s *  stream = new z_stream_s;
    SecureZeroMemory(stream, sizeof(z_stream_s));
    bool isInit = false;

    while (size > 0)
    {
        BYTE *out_buf;
        bool isPacketLost = false;
        unsigned __int32 total_out = 0;
        Zlib::ZlibData ddata(StPt, size, *stream, isInit, isPacketLost);
        auto IsOk = zlib->Decoder(ddata, out_buf, total_out);
        zlib->Reset(*stream, isInit);
        --size;
        ++StPt;
    }
}

Inflate wrapper function:

bool Zlib::Decoder(const DeflateData & ddata, BYTE *& out_data, unsigned __int32 & size)
    {
        if (IsDllLoaded == false || ddata.PDU == nullptr || ddata.PDU_size == 0)
            return false;
        z_stream_s & strm = ddata.stream;
        if (!ddata.isInitialized)
            Init(ddata);
        strm.total_out = 0;
        strm.avail_in = ddata.PDU_size;
        strm.next_in = ddata.PDU;
        strm.avail_out = OUT_BUFFER_SIZE;
        strm.next_out = out_buffer;
        __int32 ret = 0;
        bool isWasSync = false;
        ret = ZDecompressor(&strm,  Z_SYNC_FLUSH);
        size = strm.total_out;
        if ((ret = 0) || (size > 10))
            printf("Found!!"); 
        out_data = out_buffer;
        return true;            
    }

Solution

  • You need the windowBits parameter to be -15 (negative) in order to request raw deflate.

    The stored block you are referring to is three zero bits, followed by filling the rest of that byte with enough zero bits to get to a byte boundary, followed by the four bytes 00 00 ff ff. So depending on the preceding bits in the stream, the byte before the 00 00 ff ff may not be 00.