2014-03-03 05:48:07 +01:00
|
|
|
|
#include "stdafx.h"
|
|
|
|
|
|
#include "utils.h"
|
|
|
|
|
|
|
|
|
|
|
|
// Endian swap auxiliary functions.
|
|
|
|
|
|
u16 swap16(u16 i)
|
|
|
|
|
|
{
|
|
|
|
|
|
return ((i & 0xFF00) >> 8) | ((i & 0xFF) << 8);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
u32 swap32(u32 i)
|
|
|
|
|
|
{
|
|
|
|
|
|
return ((i & 0xFF000000) >> 24) | ((i & 0xFF0000) >> 8) | ((i & 0xFF00) << 8) | ((i & 0xFF) << 24);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
u64 swap64(u64 i)
|
|
|
|
|
|
{
|
|
|
|
|
|
return ((i & 0x00000000000000ff) << 56) | ((i & 0x000000000000ff00) << 40) |
|
|
|
|
|
|
((i & 0x0000000000ff0000) << 24) | ((i & 0x00000000ff000000) << 8) |
|
|
|
|
|
|
((i & 0x000000ff00000000) >> 8) | ((i & 0x0000ff0000000000) >> 24) |
|
|
|
|
|
|
((i & 0x00ff000000000000) >> 40) | ((i & 0xff00000000000000) >> 56);
|
|
|
|
|
|
}
|
2014-03-30 22:09:49 +02:00
|
|
|
|
|
2014-03-31 09:55:27 +02:00
|
|
|
|
void xor_(unsigned char *dest, unsigned char *src1, unsigned char *src2, int size)
|
2014-03-30 22:09:49 +02:00
|
|
|
|
{
|
|
|
|
|
|
int i;
|
|
|
|
|
|
for(i = 0; i < size; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
dest[i] = src1[i] ^ src2[i];
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2014-03-03 05:48:07 +01:00
|
|
|
|
|
|
|
|
|
|
// Hex string conversion auxiliary functions.
|
|
|
|
|
|
u64 hex_to_u64(const char* hex_str)
|
|
|
|
|
|
{
|
|
|
|
|
|
u32 length = strlen(hex_str);
|
|
|
|
|
|
u64 tmp = 0;
|
|
|
|
|
|
u64 result = 0;
|
|
|
|
|
|
char c;
|
|
|
|
|
|
|
|
|
|
|
|
while (length--)
|
|
|
|
|
|
{
|
|
|
|
|
|
c = *hex_str++;
|
|
|
|
|
|
if((c >= '0') && (c <= '9'))
|
|
|
|
|
|
tmp = c - '0';
|
|
|
|
|
|
else if((c >= 'a') && (c <= 'f'))
|
|
|
|
|
|
tmp = c - 'a' + 10;
|
|
|
|
|
|
else if((c >= 'A') && (c <= 'F'))
|
|
|
|
|
|
tmp = c - 'A' + 10;
|
|
|
|
|
|
else
|
|
|
|
|
|
tmp = 0;
|
|
|
|
|
|
result |= (tmp << (length * 4));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void hex_to_bytes(unsigned char *data, const char *hex_str)
|
|
|
|
|
|
{
|
|
|
|
|
|
u32 str_length = strlen(hex_str);
|
|
|
|
|
|
u32 data_length = str_length / 2;
|
|
|
|
|
|
char tmp_buf[3] = {0, 0, 0};
|
|
|
|
|
|
|
|
|
|
|
|
// Don't convert if the string length is odd.
|
|
|
|
|
|
if (!(str_length % 2))
|
|
|
|
|
|
{
|
|
|
|
|
|
u8 *out = (u8 *) malloc (str_length * sizeof(u8));
|
|
|
|
|
|
u8 *pos = out;
|
|
|
|
|
|
|
|
|
|
|
|
while (str_length--)
|
|
|
|
|
|
{
|
|
|
|
|
|
tmp_buf[0] = *hex_str++;
|
|
|
|
|
|
tmp_buf[1] = *hex_str++;
|
|
|
|
|
|
|
|
|
|
|
|
*pos++ = (u8)(hex_to_u64(tmp_buf) & 0xFF);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Copy back to our array.
|
|
|
|
|
|
memcpy(data, out, data_length);
|
|
|
|
|
|
}
|
2014-03-30 22:09:49 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Crypto functions (AES128-CBC, AES128-ECB, SHA1-HMAC and AES-CMAC).
|
|
|
|
|
|
void aescbc128_decrypt(unsigned char *key, unsigned char *iv, unsigned char *in, unsigned char *out, int len)
|
|
|
|
|
|
{
|
|
|
|
|
|
aes_context ctx;
|
|
|
|
|
|
aes_setkey_dec(&ctx, key, 128);
|
|
|
|
|
|
aes_crypt_cbc(&ctx, AES_DECRYPT, len, iv, in, out);
|
|
|
|
|
|
|
|
|
|
|
|
// Reset the IV.
|
|
|
|
|
|
memset(iv, 0, 0x10);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void aesecb128_encrypt(unsigned char *key, unsigned char *in, unsigned char *out)
|
|
|
|
|
|
{
|
|
|
|
|
|
aes_context ctx;
|
|
|
|
|
|
aes_setkey_enc(&ctx, key, 128);
|
|
|
|
|
|
aes_crypt_ecb(&ctx, AES_ENCRYPT, in, out);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool hmac_hash_compare(unsigned char *key, int key_len, unsigned char *in, int in_len, unsigned char *hash)
|
|
|
|
|
|
{
|
|
|
|
|
|
unsigned char *out = new unsigned char[key_len];
|
|
|
|
|
|
|
|
|
|
|
|
sha1_hmac(key, key_len, in, in_len, out);
|
|
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < 0x10; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (out[i] != hash[i])
|
|
|
|
|
|
{
|
|
|
|
|
|
delete[] out;
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
delete[] out;
|
|
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool cmac_hash_compare(unsigned char *key, int key_len, unsigned char *in, int in_len, unsigned char *hash)
|
|
|
|
|
|
{
|
|
|
|
|
|
unsigned char *out = new unsigned char[key_len];
|
|
|
|
|
|
|
|
|
|
|
|
aes_context ctx;
|
|
|
|
|
|
aes_setkey_enc(&ctx, key, 128);
|
|
|
|
|
|
aes_cmac(&ctx, in_len, in, out);
|
|
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < key_len; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (out[i] != hash[i])
|
|
|
|
|
|
{
|
|
|
|
|
|
delete[] out;
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
delete[] out;
|
|
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Reverse-engineered custom Lempel<65>Ziv<69>Markov based compression (unknown variant of LZRC).
|
|
|
|
|
|
int lz_decompress(unsigned char *out, unsigned char *in, unsigned int size)
|
|
|
|
|
|
{
|
|
|
|
|
|
char *tmp = new char[3272];
|
|
|
|
|
|
char *p;
|
|
|
|
|
|
char *p2;
|
|
|
|
|
|
char *sub;
|
|
|
|
|
|
char *sub2;
|
|
|
|
|
|
char *sub3;
|
|
|
|
|
|
int offset;
|
|
|
|
|
|
int index;
|
|
|
|
|
|
int index2;
|
|
|
|
|
|
int unk;
|
|
|
|
|
|
|
|
|
|
|
|
int flag;
|
|
|
|
|
|
int flag2;
|
|
|
|
|
|
unsigned int c;
|
|
|
|
|
|
int cc;
|
|
|
|
|
|
int sp;
|
|
|
|
|
|
unsigned int sc;
|
|
|
|
|
|
int scc;
|
|
|
|
|
|
char st;
|
|
|
|
|
|
char t;
|
|
|
|
|
|
unsigned int n_size;
|
|
|
|
|
|
unsigned int r_size;
|
|
|
|
|
|
signed int f_size;
|
|
|
|
|
|
signed int b_size;
|
|
|
|
|
|
signed int diff;
|
|
|
|
|
|
signed int diff_pad;
|
|
|
|
|
|
|
|
|
|
|
|
bool adjust;
|
|
|
|
|
|
int pos;
|
|
|
|
|
|
int end;
|
|
|
|
|
|
int n_end;
|
|
|
|
|
|
signed int end_size;
|
|
|
|
|
|
int chunk_size;
|
|
|
|
|
|
char pad;
|
|
|
|
|
|
unsigned int remainder;
|
|
|
|
|
|
int result;
|
|
|
|
|
|
|
|
|
|
|
|
adjust = true;
|
|
|
|
|
|
offset = 0;
|
|
|
|
|
|
index = 0;
|
|
|
|
|
|
remainder = -1;
|
|
|
|
|
|
end = (int)((char *)out + size);
|
|
|
|
|
|
pos = (int)in;
|
|
|
|
|
|
pad = *in;
|
|
|
|
|
|
chunk_size = (*(in + 1) << 24) | (*(in + 2) << 16) | (*(in + 3) << 8) | *(in + 4);
|
|
|
|
|
|
|
|
|
|
|
|
if (*in >= 0) // Check if we have a valid starting byte.
|
|
|
|
|
|
{
|
|
|
|
|
|
memset(tmp, 128, 0xCA8u);
|
|
|
|
|
|
end_size = 0;
|
|
|
|
|
|
while (1)
|
|
|
|
|
|
{
|
|
|
|
|
|
while (1)
|
|
|
|
|
|
{
|
|
|
|
|
|
p = &tmp[offset];
|
|
|
|
|
|
c = (unsigned char)tmp[offset + 2920];
|
|
|
|
|
|
|
|
|
|
|
|
if (!(remainder >> 24))
|
|
|
|
|
|
{
|
|
|
|
|
|
int add = *(unsigned char *)(pos + 5);
|
|
|
|
|
|
remainder <<= 8;
|
|
|
|
|
|
++pos;
|
|
|
|
|
|
chunk_size = (chunk_size << 8) + add;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
cc = c - (c >> 3);
|
|
|
|
|
|
r_size = c * (remainder >> 8);
|
|
|
|
|
|
f_size = (unsigned int)chunk_size < r_size;
|
|
|
|
|
|
|
|
|
|
|
|
if ((unsigned int)chunk_size < r_size)
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
remainder -= r_size;
|
|
|
|
|
|
chunk_size -= r_size;
|
|
|
|
|
|
p[2920] = cc;
|
|
|
|
|
|
offset = (offset - 1) & ((u64)~(offset - 1) >> 32);
|
|
|
|
|
|
|
|
|
|
|
|
if (out == (void *)end)
|
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
|
|
|
|
sub = &tmp[255 * ((((((unsigned char)out & 7) << 8) | index & 0xFFFFF8FFu) >> pad) & 7)];
|
|
|
|
|
|
index = 1;
|
|
|
|
|
|
|
|
|
|
|
|
do
|
|
|
|
|
|
{
|
|
|
|
|
|
sp = (int)&sub[index];
|
|
|
|
|
|
sc = (unsigned char)sub[index - 1];
|
|
|
|
|
|
|
|
|
|
|
|
if (!(remainder >> 24))
|
|
|
|
|
|
{
|
|
|
|
|
|
int add = *(unsigned char *)(pos++ + 5);
|
|
|
|
|
|
remainder <<= 8;
|
|
|
|
|
|
chunk_size = (chunk_size << 8) + add;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
index *= 2;
|
|
|
|
|
|
n_size = sc * (remainder >> 8);
|
|
|
|
|
|
scc = sc - (sc >> 3);
|
|
|
|
|
|
st = scc;
|
|
|
|
|
|
|
|
|
|
|
|
if ((unsigned int)chunk_size < n_size)
|
|
|
|
|
|
{
|
|
|
|
|
|
remainder = n_size;
|
|
|
|
|
|
++index;
|
|
|
|
|
|
st = scc + 31;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
remainder -= n_size;
|
|
|
|
|
|
chunk_size -= n_size;
|
|
|
|
|
|
}
|
|
|
|
|
|
*(unsigned char *)(sp - 1) = st;
|
|
|
|
|
|
}
|
|
|
|
|
|
while (index <= 255);
|
|
|
|
|
|
|
|
|
|
|
|
out += 1;
|
|
|
|
|
|
++end_size;
|
|
|
|
|
|
*(out - 1) = index;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
remainder = c * (remainder >> 8);
|
|
|
|
|
|
p[2920] = cc + 31;
|
|
|
|
|
|
index = -1;
|
|
|
|
|
|
|
|
|
|
|
|
while (1)
|
|
|
|
|
|
{
|
|
|
|
|
|
c = (unsigned char)p[2928];
|
|
|
|
|
|
|
|
|
|
|
|
if (!(r_size >> 24))
|
|
|
|
|
|
{
|
|
|
|
|
|
int add = *(unsigned char *)(pos++ + 5);
|
|
|
|
|
|
remainder = r_size << 8;
|
|
|
|
|
|
chunk_size = (chunk_size << 8) + add;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
p += 8;
|
|
|
|
|
|
r_size = c * (remainder >> 8);
|
|
|
|
|
|
cc = c - (c >> 3);
|
|
|
|
|
|
|
|
|
|
|
|
if ((unsigned int)chunk_size >= r_size)
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
remainder = r_size;
|
|
|
|
|
|
p[2920] = cc + 31;
|
|
|
|
|
|
++index;
|
|
|
|
|
|
|
|
|
|
|
|
if (index == 6)
|
|
|
|
|
|
{
|
|
|
|
|
|
adjust = false;
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (adjust)
|
|
|
|
|
|
{
|
|
|
|
|
|
remainder -= r_size;
|
|
|
|
|
|
chunk_size -= r_size;
|
|
|
|
|
|
p[2920] = cc;
|
|
|
|
|
|
}
|
|
|
|
|
|
adjust = true;
|
|
|
|
|
|
|
|
|
|
|
|
p2 = &tmp[index];
|
|
|
|
|
|
if (index >= 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
sub3 = &tmp[offset & 7 | 8 * (((unsigned int)out << index) & 3) | 32 * index];
|
|
|
|
|
|
flag = index - 3;
|
|
|
|
|
|
c = (unsigned char)sub3[2984];
|
|
|
|
|
|
|
|
|
|
|
|
if (!(remainder >> 24))
|
|
|
|
|
|
{
|
|
|
|
|
|
int add = *(unsigned char *)(pos++ + 5);
|
|
|
|
|
|
remainder <<= 8;
|
|
|
|
|
|
chunk_size = (chunk_size << 8) + add;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
n_size = c * (remainder >> 8);
|
|
|
|
|
|
cc = c - (c >> 3);
|
|
|
|
|
|
t = cc;
|
|
|
|
|
|
index2 = 2;
|
|
|
|
|
|
|
|
|
|
|
|
if ((unsigned int)chunk_size >= n_size)
|
|
|
|
|
|
{
|
|
|
|
|
|
remainder -= n_size;
|
|
|
|
|
|
chunk_size -= n_size;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
remainder = n_size;
|
|
|
|
|
|
index2 = 3;
|
|
|
|
|
|
t = cc + 31;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (flag < 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
sub3[2984] = t;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
if (flag <= 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
sub3[2984] = t;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
c = (unsigned char)t;
|
|
|
|
|
|
|
|
|
|
|
|
if (!(remainder >> 24))
|
|
|
|
|
|
{
|
|
|
|
|
|
int add = *(unsigned char *)(pos++ + 5);
|
|
|
|
|
|
remainder <<= 8;
|
|
|
|
|
|
chunk_size = (chunk_size << 8) + add;
|
|
|
|
|
|
}
|
|
|
|
|
|
index2 *= 2;
|
|
|
|
|
|
n_size = c * (remainder >> 8);
|
|
|
|
|
|
cc = c - (c >> 3);
|
|
|
|
|
|
t = cc;
|
|
|
|
|
|
|
|
|
|
|
|
if ((unsigned int)chunk_size >= n_size)
|
|
|
|
|
|
{
|
|
|
|
|
|
remainder -= n_size;
|
|
|
|
|
|
chunk_size -= n_size;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
remainder = n_size;
|
|
|
|
|
|
++index2;
|
|
|
|
|
|
t = cc + 31;
|
|
|
|
|
|
}
|
|
|
|
|
|
sub3[2984] = t;
|
|
|
|
|
|
|
|
|
|
|
|
if (flag != 1)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!(remainder >> 24))
|
|
|
|
|
|
{
|
|
|
|
|
|
int add = *(unsigned char *)(pos + 5);
|
|
|
|
|
|
remainder <<= 8;
|
|
|
|
|
|
++pos;
|
|
|
|
|
|
chunk_size = (chunk_size << 8) + add;
|
|
|
|
|
|
}
|
|
|
|
|
|
do
|
|
|
|
|
|
{
|
|
|
|
|
|
remainder >>= 1;
|
|
|
|
|
|
index2 = ((unsigned int)chunk_size < remainder) + 2 * index2;
|
|
|
|
|
|
|
|
|
|
|
|
if ((unsigned int)chunk_size >= remainder)
|
|
|
|
|
|
chunk_size -= remainder;
|
|
|
|
|
|
|
|
|
|
|
|
--flag;
|
|
|
|
|
|
}
|
|
|
|
|
|
while (flag != 1);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
c = (unsigned char)sub3[3008];
|
|
|
|
|
|
|
|
|
|
|
|
if (!(remainder >> 24))
|
|
|
|
|
|
{
|
|
|
|
|
|
int add = *(unsigned char *)(pos + 5);
|
|
|
|
|
|
remainder <<= 8;
|
|
|
|
|
|
++pos;
|
|
|
|
|
|
chunk_size = (chunk_size << 8) + add;
|
|
|
|
|
|
}
|
|
|
|
|
|
index2 *= 2;
|
|
|
|
|
|
n_size = c * (remainder >> 8);
|
|
|
|
|
|
cc = c - (c >> 3);
|
|
|
|
|
|
t = cc;
|
|
|
|
|
|
|
|
|
|
|
|
if ((unsigned int)chunk_size >= n_size)
|
|
|
|
|
|
{
|
|
|
|
|
|
remainder -= n_size;
|
|
|
|
|
|
chunk_size -= n_size;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
remainder = n_size;
|
|
|
|
|
|
++index2;
|
|
|
|
|
|
t = cc + 31;
|
|
|
|
|
|
}
|
|
|
|
|
|
sub3[3008] = t;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (index > 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
c = (unsigned char)sub3[2992];
|
|
|
|
|
|
|
|
|
|
|
|
if (!(remainder >> 24))
|
|
|
|
|
|
{
|
|
|
|
|
|
int add = *(unsigned char *)(pos++ + 5);
|
|
|
|
|
|
remainder <<= 8;
|
|
|
|
|
|
chunk_size = (chunk_size << 8) + add;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
index2 *= 2;
|
|
|
|
|
|
n_size = c * (remainder >> 8);
|
|
|
|
|
|
cc = c - (c >> 3);
|
|
|
|
|
|
t = cc;
|
|
|
|
|
|
|
|
|
|
|
|
if ((unsigned int)chunk_size >= n_size)
|
|
|
|
|
|
{
|
|
|
|
|
|
remainder -= n_size;
|
|
|
|
|
|
chunk_size -= n_size;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
remainder = n_size;
|
|
|
|
|
|
++index2;
|
|
|
|
|
|
t = cc + 31;
|
|
|
|
|
|
}
|
|
|
|
|
|
sub3[2992] = t;
|
|
|
|
|
|
|
|
|
|
|
|
if (index != 1)
|
|
|
|
|
|
{
|
|
|
|
|
|
c = (unsigned char)sub3[3000];
|
|
|
|
|
|
|
|
|
|
|
|
if (!(remainder >> 24))
|
|
|
|
|
|
{
|
|
|
|
|
|
int add = *(unsigned char *)(pos + 5);
|
|
|
|
|
|
remainder <<= 8;
|
|
|
|
|
|
++pos;
|
|
|
|
|
|
chunk_size = (chunk_size << 8) + add;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
index2 *= 2;
|
|
|
|
|
|
n_size = c * (remainder >> 8);
|
|
|
|
|
|
cc = c - (c >> 3);
|
|
|
|
|
|
t = cc;
|
|
|
|
|
|
|
|
|
|
|
|
if ((unsigned int)chunk_size >= n_size)
|
|
|
|
|
|
{
|
|
|
|
|
|
remainder -= n_size;
|
|
|
|
|
|
chunk_size -= n_size;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
remainder = n_size;
|
|
|
|
|
|
++index2;
|
|
|
|
|
|
t = cc + 31;
|
|
|
|
|
|
}
|
|
|
|
|
|
sub3[3000] = t;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
f_size = index2;
|
|
|
|
|
|
|
|
|
|
|
|
if (index2 == 255)
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
index = 8;
|
|
|
|
|
|
b_size = 352;
|
|
|
|
|
|
|
|
|
|
|
|
if (f_size <= 2)
|
|
|
|
|
|
{
|
|
|
|
|
|
p2 += 248;
|
|
|
|
|
|
b_size = 64;
|
|
|
|
|
|
}
|
|
|
|
|
|
do
|
|
|
|
|
|
{
|
|
|
|
|
|
unk = (int)&p2[index];
|
|
|
|
|
|
|
|
|
|
|
|
if (!(remainder >> 24))
|
|
|
|
|
|
{
|
|
|
|
|
|
int add = *(unsigned char *)(pos++ + 5);
|
|
|
|
|
|
remainder <<= 8;
|
|
|
|
|
|
chunk_size = (chunk_size << 8) + add;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
c = *(unsigned char *)(unk + 2033);
|
|
|
|
|
|
index *= 2;
|
|
|
|
|
|
n_size = c * (remainder >> 8);
|
|
|
|
|
|
cc = c - (c >> 3);
|
|
|
|
|
|
t = cc;
|
|
|
|
|
|
|
|
|
|
|
|
if ((unsigned int)chunk_size < n_size)
|
|
|
|
|
|
{
|
|
|
|
|
|
remainder = n_size;
|
|
|
|
|
|
t = cc + 31;
|
|
|
|
|
|
index += 8;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
remainder -= n_size;
|
|
|
|
|
|
chunk_size -= n_size;
|
|
|
|
|
|
}
|
|
|
|
|
|
*(unsigned char *)(unk + 2033) = t;
|
|
|
|
|
|
diff = index - b_size;
|
|
|
|
|
|
}
|
|
|
|
|
|
while ((index - b_size) < 0);
|
|
|
|
|
|
|
|
|
|
|
|
if (index != b_size)
|
|
|
|
|
|
{
|
|
|
|
|
|
diff_pad = diff >> 3;
|
|
|
|
|
|
flag = diff_pad - 1;
|
|
|
|
|
|
flag2 = diff_pad - 4;
|
|
|
|
|
|
sub2 = &tmp[32 * (diff_pad - 1)];
|
|
|
|
|
|
c = (unsigned char)sub2[2344];
|
|
|
|
|
|
|
|
|
|
|
|
if (!(remainder >> 24))
|
|
|
|
|
|
{
|
|
|
|
|
|
int add = *(unsigned char *)(pos + 5);
|
|
|
|
|
|
remainder <<= 8;
|
|
|
|
|
|
++pos;
|
|
|
|
|
|
chunk_size = (chunk_size << 8) + add;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
n_size = c * (remainder >> 8);
|
|
|
|
|
|
cc = c - (c >> 3);
|
|
|
|
|
|
t = cc;
|
|
|
|
|
|
index2 = 2;
|
|
|
|
|
|
|
|
|
|
|
|
if ((unsigned int)chunk_size >= n_size)
|
|
|
|
|
|
{
|
|
|
|
|
|
remainder -= n_size;
|
|
|
|
|
|
chunk_size -= n_size;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
remainder = n_size;
|
|
|
|
|
|
index2 = 3;
|
|
|
|
|
|
t = cc + 31;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (flag2 < 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
sub2[2344] = t;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
if (flag2 <= 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
sub2[2344] = t;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
c = (unsigned char)t;
|
|
|
|
|
|
|
|
|
|
|
|
if (!(remainder >> 24))
|
|
|
|
|
|
{
|
|
|
|
|
|
int add = *(unsigned char *)(pos++ + 5);
|
|
|
|
|
|
remainder <<= 8;
|
|
|
|
|
|
chunk_size = (chunk_size << 8) + add;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
index2 *= 2;
|
|
|
|
|
|
n_size = c * (remainder >> 8);
|
|
|
|
|
|
cc = c - (c >> 3);
|
|
|
|
|
|
t = cc;
|
|
|
|
|
|
|
|
|
|
|
|
if ((unsigned int)chunk_size >= n_size)
|
|
|
|
|
|
{
|
|
|
|
|
|
remainder -= n_size;
|
|
|
|
|
|
chunk_size -= n_size;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
remainder = n_size;
|
|
|
|
|
|
++index2;
|
|
|
|
|
|
t = cc + 31;
|
|
|
|
|
|
}
|
|
|
|
|
|
sub2[2344] = t;
|
|
|
|
|
|
|
|
|
|
|
|
if (flag2 != 1)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!(remainder >> 24))
|
|
|
|
|
|
{
|
|
|
|
|
|
int add = *(unsigned char *)(pos + 5);
|
|
|
|
|
|
remainder <<= 8;
|
|
|
|
|
|
++pos;
|
|
|
|
|
|
chunk_size = (chunk_size << 8) + add;
|
|
|
|
|
|
}
|
|
|
|
|
|
do
|
|
|
|
|
|
{
|
|
|
|
|
|
remainder >>= 1;
|
|
|
|
|
|
index2 = ((unsigned int)chunk_size < remainder) + 2 * index2;
|
|
|
|
|
|
|
|
|
|
|
|
if ((unsigned int)chunk_size >= remainder)
|
|
|
|
|
|
chunk_size -= remainder;
|
|
|
|
|
|
|
|
|
|
|
|
--flag2;
|
|
|
|
|
|
}
|
|
|
|
|
|
while (flag2 != 1);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
c = (unsigned char)sub2[2368];
|
|
|
|
|
|
|
|
|
|
|
|
if (!(remainder >> 24))
|
|
|
|
|
|
{
|
|
|
|
|
|
int add = *(unsigned char *)(pos + 5);
|
|
|
|
|
|
remainder <<= 8;
|
|
|
|
|
|
++pos;
|
|
|
|
|
|
chunk_size = (chunk_size << 8) + add;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
index2 *= 2;
|
|
|
|
|
|
n_size = c * (remainder >> 8);
|
|
|
|
|
|
cc = c - (c >> 3);
|
|
|
|
|
|
t = cc;
|
|
|
|
|
|
|
|
|
|
|
|
if ((unsigned int)chunk_size >= n_size)
|
|
|
|
|
|
{
|
|
|
|
|
|
remainder -= n_size;
|
|
|
|
|
|
chunk_size -= n_size;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
remainder = n_size;
|
|
|
|
|
|
++index2;
|
|
|
|
|
|
t = cc + 31;
|
|
|
|
|
|
}
|
|
|
|
|
|
sub2[2368] = t;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (flag > 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
c = (unsigned char)sub2[2352];
|
|
|
|
|
|
if (!(remainder >> 24))
|
|
|
|
|
|
{
|
|
|
|
|
|
int add = *(unsigned char *)(pos++ + 5);
|
|
|
|
|
|
remainder <<= 8;
|
|
|
|
|
|
chunk_size = (chunk_size << 8) + add;
|
|
|
|
|
|
}
|
|
|
|
|
|
index2 *= 2;
|
|
|
|
|
|
n_size = c * (remainder >> 8);
|
|
|
|
|
|
cc = c - (c >> 3);
|
|
|
|
|
|
t = cc;
|
|
|
|
|
|
if ((unsigned int)chunk_size >= n_size)
|
|
|
|
|
|
{
|
|
|
|
|
|
remainder -= n_size;
|
|
|
|
|
|
chunk_size -= n_size;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
remainder = n_size;
|
|
|
|
|
|
++index2;
|
|
|
|
|
|
t = cc + 31;
|
|
|
|
|
|
}
|
|
|
|
|
|
sub2[2352] = t;
|
|
|
|
|
|
if (flag != 1)
|
|
|
|
|
|
{
|
|
|
|
|
|
c = (unsigned char)sub2[2360];
|
|
|
|
|
|
if (!(remainder >> 24))
|
|
|
|
|
|
{
|
|
|
|
|
|
int add = *(unsigned char *)(pos + 5);
|
|
|
|
|
|
remainder <<= 8;
|
|
|
|
|
|
++pos;
|
|
|
|
|
|
chunk_size = (chunk_size << 8) + add;
|
|
|
|
|
|
}
|
|
|
|
|
|
index2 *= 2;
|
|
|
|
|
|
n_size = c * (remainder >> 8);
|
|
|
|
|
|
cc = c - (c >> 3);
|
|
|
|
|
|
t = cc;
|
|
|
|
|
|
|
|
|
|
|
|
if ((unsigned int)chunk_size >= n_size)
|
|
|
|
|
|
{
|
|
|
|
|
|
remainder -= n_size;
|
|
|
|
|
|
chunk_size -= n_size;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
remainder = n_size;
|
|
|
|
|
|
++index2;
|
|
|
|
|
|
t = cc + 31;
|
|
|
|
|
|
}
|
|
|
|
|
|
sub2[2360] = t;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
diff = index2 - 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (end_size <= diff)
|
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
|
|
|
|
index = *(out - diff - 1);
|
|
|
|
|
|
n_end = (int)(out + f_size);
|
|
|
|
|
|
offset = (((unsigned char)f_size + (unsigned char)out) & 1) + 6;
|
|
|
|
|
|
|
|
|
|
|
|
if ((unsigned int)(out + f_size) >= (unsigned int)end)
|
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
|
|
|
|
do
|
|
|
|
|
|
{
|
|
|
|
|
|
out += 1;
|
|
|
|
|
|
++end_size;
|
|
|
|
|
|
*(out - 1) = index;
|
|
|
|
|
|
index = *(out - diff - 1);
|
|
|
|
|
|
}
|
|
|
|
|
|
while (out != (void *)n_end);
|
|
|
|
|
|
|
|
|
|
|
|
out += 1;
|
|
|
|
|
|
++end_size;
|
|
|
|
|
|
*((unsigned char *)out - 1) = index;
|
|
|
|
|
|
}
|
|
|
|
|
|
result = end_size;
|
|
|
|
|
|
}
|
|
|
|
|
|
else // Starting byte is invalid.
|
|
|
|
|
|
{
|
|
|
|
|
|
result = -1;
|
|
|
|
|
|
if (chunk_size <= (int)size)
|
|
|
|
|
|
{
|
|
|
|
|
|
memcpy(out, (const void *)(in + 5), chunk_size);
|
|
|
|
|
|
result = chunk_size;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
delete[] tmp;
|
|
|
|
|
|
|
|
|
|
|
|
return result;
|
2014-03-31 09:55:27 +02:00
|
|
|
|
}
|