DWORD xorshift32(DWORD x)
{
x ^= x << 13;
x ^= x >> 17;
x ^= x << 5;
return x;
}
// m2, m3
DWORD transform1(DWORD a, DWORD b)
{
DWORD m = a ^ (a >> 7);
DWORD n = b ^ (m << 7);
return m ^ b ^ (n << 6);
}
void swap8(BYTE& a, BYTE& b)
{
BYTE t = a;
a = b;
b = t;
}
string g_temp_data;
void one_round(DWORD id)
{
WORD v_00;
WORD v_01;
WORD v_02;
DWORD v_03;
// wait for g_h_ary[id]
if (g_thread_inited[id])
{
v_00 = (WORD)g_4045EC ^ g_rnd0[id];
v_01 = (WORD)g_4045EC ^ g_rnd1[id];
v_02 = (WORD)g_4045EC ^ g_rnd2[id];
v_03 = g_4045EC ^ g_rnd_xorshift[id];
} else
{
g_thread_inited[id] = 1;
v_00 = 3923;
v_01 = 28;
v_02 = 1;
v_03 = id + 0x1D4B42;
}
BYTE v36[16] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F };
// Wichmann–Hill
g_rnd0[id] = 171 * v_00 % 30269;
g_rnd1[id] = 172 * v_01 % 30307;
g_rnd2[id] = 170 * v_02 % 30323;
g_rnd_xorshift[id] = xorshift32(v_03);
WORD rnd_sum = (WORD)(g_rnd0[id] + g_rnd2[id] + g_rnd1[id]);
g_40402C[id] += rnd_sum;
g_404040[id] -= rnd_sum;
g_404068[id] *= rnd_sum;
g_40407C[id] -= rnd_sum;
g_404054[id] += rnd_sum;
DWORD v20;
DWORD v44;
DWORD v38;
DWORD v47 = g_404068[id];
DWORD m0 = g_404040[id];
DWORD m1 = g_40407C[id];
DWORD m2 = g_40402C[id];
DWORD m3 = g_404054[id];
DWORD v15 = g_404068[id];
for (int k = 0; k < 32; k++)
{
v20 = transform1(m2, m3);
v44 = transform1(m0, v20);
DWORD v22 = v47;
v47 = m3;
m2 = v22;
BYTE v21 = (BYTE)(v20 * ((v15 >> 2) + m0 + 1)) & 0x0F;
BYTE v26 = ((BYTE)v44 * ((BYTE)m2 + (BYTE)(m1 >> 2) + 1)) & 0xF;
swap8(v36[v26], v36[v21]);
m0 = m1;
v38 = m1;
m1 = v20;
m3 = v44;
v15 = v47;
}
g_40407C[id] = v20;
g_404054[id] = v44;
g_40402C[id] = m2;
g_404040[id] = v38;
g_404068[id] = v47;
BYTE v28 = (BYTE)g_rnd_xorshift[id];
WORD v28_2 = v28 * v28;
BYTE v33 = g_buf256[(BYTE)(v28_2 >> 8) ^ g_buf256[(BYTE)v28_2]];
BYTE sn1_idx = v36[2 * id];
BYTE sn0_idx = v36[2 * id + 1];
g_temp_data.append((char *)&v28, 1);
g_temp_data.append((char *)&sn1_idx, 1);
g_temp_data.append((char *)&sn0_idx, 1);
BYTE sn0 = g_sn[sn0_idx];
BYTE sn1 = g_sn[sn1_idx];
g_sn[sn1_idx] = sn0 + 3 * (v33 + sn1);
g_sn[sn0_idx] = (BYTE)(v33 + sn1 + g_buf256[v28] - 2 * sn0);
g_4045F8[id] = v33 ^ g_buf256[v28];
// release g_h
}
void one_round_rev(PBYTE temp_cur, int i, int k)
{
BYTE v28 = temp_cur[0];
BYTE sn1_idx = temp_cur[1];
BYTE sn0_idx = temp_cur[2];
WORD v28_2 = v28 * v28;
BYTE v33 = g_buf256[(BYTE)(v28_2 >> 8) ^ g_buf256[(BYTE)v28_2]];
BYTE new_sn0 = g_sn[sn0_idx];
BYTE new_sn1 = g_sn[sn1_idx];
g_sn[sn1_idx] = (2*new_sn1 + new_sn0 - 7*v33 - g_buf256[v28]) * 0xB7;
g_sn[sn0_idx] = (new_sn1 - 3*new_sn0 + 3*g_buf256[v28]) * 0xB7;
}
void test2()
{
string str = util::hex2bin("11121314212223243132333441424344");
memcpy(g_sn, str.c_str(), str.size());
xor_buf(g_sn, sizeof(g_sn), g_xor_key);
for (int i = 0; i < 300; i++)
{
int k;
for (k = 0; k < 5; k++)
{
one_round(k);
}
g_4045EC = 0;
for (k = 0; k < 5; k++)
{
g_4045EC += g_4045F8[k];
}
}
print_buf(g_sn, sizeof(g_sn));
// 0x21, 0x19, 0x4A, 0xB9, 0x7E, 0x63, 0x04, 0x5F, 0xEA, 0xC3, 0xFC, 0x7C, 0x70, 0xC4, 0x80, 0xB2
util::SaveFile(g_temp_data, "temp_data.dat");
}
void test2_rev()
{
BYTE buf[16] = {
0x21, 0x19, 0x4A, 0xB9, 0x7E, 0x63, 0x04, 0x5F, 0xEA, 0xC3, 0xFC, 0x7C, 0x70, 0xC4, 0x80, 0xB2
};
memcpy(g_sn, buf, sizeof(buf));
util::LoadFile(g_temp_data, "temp_data.dat");
PBYTE temp = (PBYTE)g_temp_data.c_str();
for (int i = 300 - 1; i >= 0; i--)
{
for (int k = 5 - 1; k >= 0; k--)
{
PBYTE temp_cur = temp + i * 5 * 3 + k * 3;
one_round_rev(temp_cur, i, k);
}
}
xor_buf(g_sn, sizeof(g_sn), g_xor_key);
printf("%s\n", util::bin2hex(g_sn, sizeof(g_sn)).c_str());
}