sn长度为32
.text:00401250 call ds:GetWindowTextLengthA
.text:00401256 cmp eax, 20h
.text:00401259 jz short loc_401296
.text:00401250 call ds:GetWindowTextLengthA
.text:00401256 cmp eax, 20h
.text:00401259 jz short loc_401296
hex2bin(大写的16进制)
sn = hex2bin(sn);
sn ^= key;
.text:00401299 call x_init_sn
.data:0040401C g_xor_key db 0E9h, 4Fh, 6Eh, 20h, 78h, 1Ah, 7, 0Fh, 0, 17h, 36h, 9, 0Ah, 7, 1Fh, 0Ch
.text:00401299 call x_init_sn
.data:0040401C g_xor_key db 0E9h, 4Fh, 6Eh, 20h, 78h, 1Ah, 7, 0Fh, 0, 17h, 36h, 9, 0Ah, 7, 1Fh, 0Ch
创建5个线程分别计算
5个线程的一轮都计算结束后才会进行下一轮计算, 共300轮
每个线程更新sn中的两个字节(二元一次方程)
把计算中用到的sn的2个索引值和1个中间变量保存下来, 用来做逆运算(不用管随机数什么的)
.text:00401900 x_start_check
.text:00401900 x_start_check
计算过程
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());
}
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());
}
校验sn的hash
.text:00401A39 lea edi, [esp+60h+var_31]
...
.text:00401B1B xor eax, 18000h
.text:00401B20 xor ecx, 0C00h
.text:00401B26 shld ecx, eax, 1
.text:00401B2A add eax, eax
.text:00401B2C sub edx, 1
.text:00401B2F jnz short loc_401B11
.text:00401B31 cmp eax, 38B0000h
.text:00401B36 jnz short loc_401B55
.text:00401B38 cmp ecx, 0B2A289CFh
.text:00401B3E jnz short loc_401B55
// multi -> one
__int64 hash_v(__int64 v)
{
for (int i = 0; i < 64; i++)
{
if (v < 0)
{
v ^= 0x00000C0000018000;
}
v <<= 1;
}
return v;
}
__int64 hash_sn(PBYTE sn)
{
__int64 v1 = util::byteswap64(*(__int64*)(sn));
__int64 v2 = util::byteswap64(*(__int64*)(sn+8));
__int64 v;
v = hash_v(v1);
v ^= v2;
v = hash_v(v);
return v;
}
.text:00401A39 lea edi, [esp+60h+var_31]
...
.text:00401B1B xor eax, 18000h
.text:00401B20 xor ecx, 0C00h
.text:00401B26 shld ecx, eax, 1
.text:00401B2A add eax, eax
.text:00401B2C sub edx, 1
.text:00401B2F jnz short loc_401B11
.text:00401B31 cmp eax, 38B0000h
.text:00401B36 jnz short loc_401B55
.text:00401B38 cmp ecx, 0B2A289CFh
.text:00401B3E jnz short loc_401B55
// multi -> one
__int64 hash_v(__int64 v)
{
for (int i = 0; i < 64; i++)
{
if (v < 0)
{
v ^= 0x00000C0000018000;
}
v <<= 1;
}
return v;
}
__int64 hash_sn(PBYTE sn)
{
__int64 v1 = util::byteswap64(*(__int64*)(sn));
__int64 v2 = util::byteswap64(*(__int64*)(sn+8));
__int64 v;
v = hash_v(v1);
v ^= v2;
v = hash_v(v);
return v;
}
校验通过后, 跳向sn执行弹框(界面上提示弹出Win表示正确)
.text:00401321 mov ecx, [ebp+hDlg]
.text:00401324 mov g_hDlg, ecx
.text:0040132A mov eax, offset g_sn
.text:0040132F jmp eax
.text:00401331 mov edx, [ebp+hDlg]
.text:00401334 push edx ; hWnd
.text:00401335 call ds:DestroyWindow
.text:0040133B jmp short loc_401380
.text:00401321 mov ecx, [ebp+hDlg]
.text:00401324 mov g_hDlg, ecx
.text:0040132A mov eax, offset g_sn
.text:0040132F jmp eax
.text:00401331 mov edx, [ebp+hDlg]
.text:00401334 push edx ; hWnd
.text:00401335 call ds:DestroyWindow
.text:0040133B jmp short loc_401380
尝试构造shellcode(未通过hash验证)
004044C8 83C0 0C add eax, 0C
004044CB 6A 00 push 0
004044CD 50 push eax
004044CE 50 push eax
004044CF - E9 1ECEFFFF jmp 004012F2
004044D4 Win
83 C0 0C 6A 00 50 50 E9 1E CE FF FF 57 69 6E 00
004044C8 83C0 0C add eax, 0C
004044CB 6A 00 push 0
004044CD 50 push eax
004044CE 50 push eax
004044CF - E9 1ECEFFFF jmp 004012F2
004044D4 Win
83 C0 0C 6A 00 50 50 E9 1E CE FF FF 57 69 6E 00
观察所有MessageBoxA的调用,
其中第1个参数都是mov ecx, hDlg; push ecx的形式,
而00401324处却把hDlg额外保存到了全局变量g_hDlg中
.text:004012E8 push offset Caption ; lpCaption
.text:004012ED push offset Text ; lpText
.text:004012F2 mov ecx, [ebp+hDlg]
.text:004012F5 push ecx ; hWnd
.text:004012F6 call ds:MessageBoxA
.text:00401321 mov ecx, [ebp+hDlg]
.text:00401324 mov g_hDlg, ecx
.text:0040132A mov eax, offset g_sn
.text:0040132F jmp eax
.data:004043FC g_hDlg
.text:004012E8 push offset Caption ; lpCaption
.text:004012ED push offset Text ; lpText
.text:004012F2 mov ecx, [ebp+hDlg]
.text:004012F5 push ecx ; hWnd
.text:004012F6 call ds:MessageBoxA
.text:00401321 mov ecx, [ebp+hDlg]
.text:00401324 mov g_hDlg, ecx
.text:0040132A mov eax, offset g_sn
.text:0040132F jmp eax
.data:004043FC g_hDlg
搜索g_hDlg的引用(搜索16进制FC434000)
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)
最后于 2019-6-19 02:12
被风间仁编辑
,原因: