我正在尝试为一款旧游戏反转解压算法。经过一些逆转后,我发现它读取的是位流,而不是逐字节的。它看起来像这样:
std::vector<uint32_t> TABLE_1 = {0x10, 0x11, 0x12, 0, 8, 7, 9, 6, 0x0A, 5, 0x0B, 4, 0x0C, 3, 0x0D, 2, 0x0E, 1, 0x0F};
uint32_t f1()
{
if (_stream_end < 5)
{
read_to_stream();
}
uint32_t v1 = read_from_stream(0x1F, 5) + 0x101;
std::cout << "f1:: v1 = " << v1 << std::endl;
if (_stream_end < 5)
{
read_to_stream();
}
uint32_t v2 = read_from_stream(0x1F, 5) + 1;
std::cout << "f1:: v2 = " << v2 << std::endl;
if (_stream_end < 4)
{
read_to_stream();
}
uint32_t v3 = read_from_stream(0xF, 4) + 4;
std::cout << "f1:: v3 = " << v3 << std::endl;
if (v1 > 0x11E || v2 > 0x1E)
{
std::cout << "f1:: v1 or v2 is above limit" << std::endl;
return 1;
}
std::vector<uint32_t> v4(19, 0);
if (v3 != 0)
{
for (uint32_t i = 0; i < v3; i++)
{
if (_stream_end < 3)
{
read_to_stream();
}
v4[TABLE_1[i]] = read_from_stream(0x7, 3);
}
std::cout << "v4 = [ ";
for (auto &item : v4)
{
std::cout << item << " ";
}
std::cout << "]" << std::endl;
}
// rest of the code
}
uint32_t begin(uint32_t *value)
{
if (_stream_end == 0)
{
read_to_stream();
}
*value = read_from_stream(0x1, 1);
uint32_t result = read_from_stream(0x3, 2);
if (result == 2)
{
f1();
}
if (result == 1)
{
// execute subroutine
}
if (result == 0)
{
// execute subroutine
}
// rest of code
}
uint32_t read_from_stream(uint32_t mask, uint32_t count)
{
uint32_t result = _stream & mask;
_stream = _stream >> count;
_stream_end -= count;
return result;
}
void read_to_stream()
{
uint32_t byte = static_cast<uint32_t>(read_byte() & 0xFF);
_stream = _stream | (byte << _stream_end);
_stream_end += 8;
}
char read_byte()
{
if (_buffer_cursor == _buffer.size())
{
throw new std::runtime_error("read_byte");
}
return _buffer[_buffer_cursor++];
}
我还发现它使用了两个缓冲区:A(32768 字节)和 B(4096 字节)。首先它填充 A 缓冲区,然后使用它填充 B 缓冲区。它从 B 缓冲区将数据复制到输出缓冲区,所以我猜它在这一步是未压缩的。也许您可以告诉我哪些算法使用相同类型的解压。
以下是该代码中的其他一些表格。
byte_5E00E8 db 8 dup(0), 1, 0, 1, 0, 2, 0, 2, 0, 3, 0, 3, 0, 4, 0
db 4, 0, 5, 0, 5, 0, 6, 0, 6, 0, 7, 0, 7, 0, 8, 0, 8, 0
db 9, 0, 9, 0, 0Ah, 0, 0Ah, 0, 0Bh, 0, 0Bh, 0, 0Ch, 0
db 0Ch, 0, 0Dh, 0, 0Dh, 0
word_5E00AC dw 1, 2, 3, 4, 5, 7, 9, 0Dh, 11h, 19h, 21h, 31h, 41h, 61h
dw 81h, 0C1h, 101h, 181h, 201h, 301h, 401h, 601h, 801h
dw 0C01h, 1001h, 1801h, 2001h, 3001h, 4001h, 6001h
这两个表在其中一个函数中一起使用(难以反转,因为它有点长且复杂)。我的建议可能是错误的,因为我不是逆向工程专家。
这里有两个文件:https : //www.dropbox.com/s/4km2rjmfwi2dw1e/Archive.zip?dl=0
更新。
伙计们,我检查了以前开发人员的一个游戏(已发布源代码),发现他们使用相同的库进行压缩(库链接)。
我认为问题现在没有任何意义,但让我们把它留在这里作为历史。