<?xml version="1.0" encoding="UTF-8" standalone="yes"?><oembed><version><![CDATA[1.0]]></version><provider_name><![CDATA[Krzysztof Narkowicz]]></provider_name><provider_url><![CDATA[https://knarkowicz.wordpress.com]]></provider_url><author_name><![CDATA[Krzysztof Narkowicz]]></author_name><author_url><![CDATA[https://knarkowicz.wordpress.com/author/knarkowicz/]]></author_url><title><![CDATA[PixelJunk Eden data&nbsp;extractor]]></title><type><![CDATA[link]]></type><html><![CDATA[<p>Recently Q-Games ported one of their games &#8211; PixelJunk Eden to Windows. Actually it&#8217;s their first Windows release. From tech perspective it&#8217;s not as impressive as PixelJunk Shooter series, but still it was quite interesting to poke around this game&#8217;s files. Unfortunately game data was stored in custom format and encrypted. I wonder why people waste time to encrypt game data.</p>
<p>I tried to reverse engineer data files and wrote a simple extractor program. You can download sources <a href="https://github.com/knarkowicz/extEden">here</a>. The rest of the post contains information about encryption and file formats.</p>
<p>Files are encrypted using a homemade xor encryption scheme:</p>
<pre class="brush: cpp; title: ; notranslate" title="">
int seed = fileSize + 0x006FD37D;
for ( unsigned i = 0; i &lt; fileSize; ++i )
{
    int const xorKey = seed * ( seed * seed * 0x73 - 0x1B ) + 0x0D;
    fileByteArr[ i ] ^= xorKey;
    ++seed;
}
</pre>
<p>Game data is stored in lump_x_x.pak files with description in the lump.idx file. Lump.idx consits of 1 header, multiple lump_x_x.pak descriptors and multiple packed file descriptors. All files (*.idx and *.pak) are encrypted using the mentioned above xor scheme.</p>
<p>lump.idx header:</p>
<pre class="brush: cpp; title: ; notranslate" title="">
struct IndexHeader
{
    char m_magic[ 4 ]; // &quot;PACK&quot;
    unsigned m_unknown0;
    unsigned m_unknown1;
    unsigned m_packedFileMaxID; // packed file num - 1
    unsigned m_lumpFileMaxSize;
    unsigned m_lumpFileNum;
    char m_align[ 230 ];
};
</pre>
<p>lump.idx file descriptors of lump_x_x.pak files:</p>
<pre class="brush: cpp; title: ; notranslate" title="">
struct IndexLumpDesc
{
    unsigned m_unknown;
    unsigned m_lumpSize;
    unsigned char m_lumpPartID;
    unsigned char m_lumpID;
    char m_align[ 2 ];
};
</pre>
<p>lump.idx file descriptors of packed files:</p>
<pre class="brush: cpp; title: ; notranslate" title="">
struct IndexFileDesc
{
    char m_filename[ 120 ];
    unsigned m_offset;
    unsigned m_size;
};
</pre>
<p>lump_x_x.pak files contain packed files at specified offsets. Every packed file is stored at offset aligned to 128 bytes.</p>
]]></html></oembed>