Pr0dk3y 의 기본 소스는 IDA의 Hexray로 재구성하였다.
필요한 Data도 긁어서 선언하였고 직접적인 바이너리와 같은값을 주어서 함수를 빠져나왔을때 같은결과가 나오는지로 비교해가면서 소스를 완성시켰다.
#include <windows.h>
#include <stdio.h>
/*
8f2 26
case 0xFFFFF8B3://16BB
var7=a1[i]-65;
break;
case 0xFFFFF8C8:
var7=a1[i]-66;
break;
case 0xFFFFF8DD:
var7=a1[i]-67;*/
BYTE table[] = "ABCDEFGHJKLMNPQRSTUVWXYZ23456789";
DWORD dword_1E08[41] = { 0xFFFFF8F2, 0xFFFFF8F2, 0xFFFFF8F2, 0xFFFFF8F2, 0xFFFFF8F2, 0xFFFFF8F2, 0xFFFFF8F2, 0xFFFFF8F2,
0xFFFFF907, 0xFFFFF907, 0xFFFFF907, 0xFFFFF907, 0xFFFFF907, 0xFFFFF907, 0xFFFFF907,
0xFFFFF8B3, 0xFFFFF8B3, 0xFFFFF8B3, 0xFFFFF8B3, 0xFFFFF8B3, 0xFFFFF8B3, 0xFFFFF8B3, 0xFFFFF8B3,
0xFFFFF907,//i
0xFFFFF8C8, 0xFFFFF8C8, 0xFFFFF8C8, 0xFFFFF8C8, 0xFFFFF8C8, 0xFFFFF907, 0xFFFFF8DD, 0xFFFFF8DD, 0xFFFFF8DD,
0xFFFFF8DD, 0xFFFFF8DD, 0xFFFFF8DD, 0xFFFFF8DD, 0xFFFFF8DD, 0xFFFFF8DD, 0xFFFFF8DD, 0xFFFFF8DD };
BYTE byte_2030B0[] = { 0, 1, 3, 2, 6, 7, 5, 4, 0x0C, 0x0D, 0x0F, 0x0E, 0x0A, 0x0B, 9, 8 };
const char byte_1FC0[] = "\x00\x01\x01\x02\x01\x02\x02\x03\x01\x02\x02\x03\x02\x03\x03\x04"
"\x01\x02\x02\x03\x02\x03\x03\x04\x02\x03\x03\x04\x03\x04\x04\x05"
"\x01\x02\x02\x03\x02\x03\x03\x04\x02\x03\x03\x04\x03\x04\x04\x05"
"\x02\x03\x03\x04\x03\x04\x04\x05\x03\x04\x04\x05\x04\x05\x05\x06"
"\x01\x02\x02\x03\x02\x03\x03\x04\x02\x03\x03\x04\x03\x04\x04\x05"
"\x02\x03\x03\x04\x03\x04\x04\x05\x03\x04\x04\x05\x04\x05\x05\x06"
"\x02\x03\x03\x04\x03\x04\x04\x05\x03\x04\x04\x05\x04\x05\x05\x06"
"\x03\x04\x04\x05\x04\x05\x05\x06\x04\x05\x05\x06\x05\x06\x06\x07"
"\x01\x02\x02\x03\x02\x03\x03\x04\x02\x03\x03\x04\x03\x04\x04\x05"
"\x02\x03\x03\x04\x03\x04\x04\x05\x03\x04\x04\x05\x04\x05\x05\x06"
"\x02\x03\x03\x04\x03\x04\x04\x05\x03\x04\x04\x05\x04\x05\x05\x06"
"\x03\x04\x04\x05\x04\x05\x05\x06\x04\x05\x05\x06\x05\x06\x06\x07"
"\x02\x03\x03\x04\x03\x04\x04\x05\x03\x04\x04\x05\x04\x05\x05\x06"
"\x03\x04\x04\x05\x04\x05\x05\x06\x04\x05\x05\x06\x05\x06\x06\x07"
"\x03\x04\x04\x05\x04\x05\x05\x06\x04\x05\x05\x06\x05\x06\x06\x07"
"\x04\x05\x05\x06\x05\x06\x06\x07\x05\x06\x06\x07\x06\x07\x07\x08";
BYTE s[25] = "";
__int64 __fastcall sub_FCB(unsigned __int8 a1)
{
__int64 result;
__int64 v2;
BYTE v3[] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 };
result = v3[a1 & 0xF];
return result;
}
__int64 __fastcall sub_1D20(unsigned __int64 a1)
{
__int64 result;
int v2;
unsigned __int64 v3;
result = 0;
v2 = 0;
do
{
v3 = a1 >> v2;
v2 += 8;
result = byte_1FC0[(unsigned __int8)v3] + (unsigned int)result;
} while (v2 != 64);
return result;
}
signed __int64 __fastcall sub_C15(unsigned int a1)
{
signed __int64 result;
unsigned int v2;
int i;
if (a1 == 2)
{
result = 1LL;
}
else if (a1 & 1)
{
if (a1 > 0xFFFFFE)
{
v2 = 3;
for (i = 9; i < a1; i = v2 * v2)
{
if (!(a1 % v2))
return 0LL;
v2 += 2;
}
result = i != a1;
}
else
{
result = 0LL;
}
}
else
{
result = 0LL;
}
return result;
}
__int64 __fastcall sub_D51(unsigned int a1)
{
return a1 >> 24 == (unsigned __int8)(a1 >> 16)
|| !((unsigned __int8)(a1 >> 16) ^ a1)
|| !((unsigned __int8)a1 ^ a1);
}
__int64 __fastcall sub_E10(__int16 a1)
{
return HIBYTE(a1) == (BYTE)a1;
}
__int64 __fastcall sub_DA2(unsigned __int16 a1)
{
return !(((a1 >> 12) ^ HIBYTE(a1)) & 0xF)
|| !((HIBYTE(a1) ^ (unsigned __int8)(a1 >> 4)) & 0xF)
|| !(((unsigned __int8)(a1 >> 4) ^ (unsigned __int8)a1) & 0xF);
}
__int64 __fastcall sub_E40(int a1, int a2, unsigned int a3)
{
int v3;
int v4;
int v5;
int v6;
int v7;
int v8;
int v9;
v3 = (a3 >> 13) ^ (a1 - a2 - a3);
v4 = (v3 << 8) ^ (a2 - a3 - v3);
v5 = ((unsigned int)v4 >> 13) ^ (a3 - v3 - v4);
v6 = ((unsigned int)v5 >> 12) ^ (v3 - v4 - v5);
v7 = (v6 << 16) ^ (v4 - v5 - v6);
v8 = ((unsigned int)v7 >> 5) ^ (v5 - v6 - v7);
v9 = ((unsigned int)v8 >> 3) ^ (v6 - v7 - v8);
return (((v9 << 10) ^ (unsigned int)(v7 - v8 - v9)) >> 15) ^ (v8 - v9 - ((v9 << 10) ^ (v7 - v8 - v9)));
}
__int64 __fastcall sub_1846(unsigned int a1)
{
unsigned __int16 v2;
unsigned __int16 i;
signed int v4;
v2 = 0;
v4 = 15;
for (i = 0; i < 16; ++i)
v2 = (a1 >> (2 * v4-- + 1)) & 1 | 2 * v2;
return v2 == 13 * ((unsigned __int16)(0x4EC5 * (DWORD)v2 >> 16) >> 2);
}
__int64 __fastcall sub_1061(unsigned int a1, unsigned int a2)
{
signed __int16 v2;
signed __int16 v3;
signed __int16 v4;
signed __int16 v5;
signed __int16 v6;
signed __int16 v7;
signed __int16 v8;
signed __int16 v9;
signed __int16 v10;
signed __int16 v11;
signed __int16 v12;
signed __int16 v13;
signed __int16 v14;
signed __int16 v15;
signed __int16 v16;
__int16 v18;
__int16 v19;
__int16 v20;
__int16 v21;
__int16 v22;
__int16 v23;
__int16 v24;
__int16 v25;
__int16 v26;
__int16 v27;
__int16 v28;
__int16 v29;
__int16 v30;
__int16 v31;
__int16 v32;
v18 = (unsigned __int8)sub_FCB(byte_2030B0[a1 >> 28]) == 2;
if ((unsigned __int8)sub_FCB((unsigned __int8)(byte_2030B0[a1 >> 28] ^ byte_2030B0[(a1 >> 24) & 0xF])) == 2)
v2 = 2;
else
v2 = 0;
v19 = v18 | v2;
if ((unsigned __int8)sub_FCB((unsigned __int8)(byte_2030B0[(a1 >> 24) & 0xF] ^ byte_2030B0[(a1 >> 20) & 0xF])) == 2)
v3 = 4;
else
v3 = 0;
v20 = v19 | v3;
if ((unsigned __int8)sub_FCB((unsigned __int8)(byte_2030B0[(a1 >> 20) & 0xF] ^ byte_2030B0[(a1 >> 16) & 0xF])) == 2)
v4 = 8;
else
v4 = 0;
v21 = v20 | v4;
if ((unsigned __int8)sub_FCB((unsigned __int8)(byte_2030B0[(a1 >> 16) & 0xF] ^ byte_2030B0[(unsigned __int16)a1 >> 12])) == 2)
v5 = 16;
else
v5 = 0;
v22 = v21 | v5;
if ((unsigned __int8)sub_FCB((unsigned __int8)(byte_2030B0[(unsigned __int16)a1 >> 12] ^ byte_2030B0[(a1 >> 8) & 0xF])) == 2)
v6 = 32;
else
v6 = 0;
v23 = v22 | v6;
if ((unsigned __int8)sub_FCB((unsigned __int8)(byte_2030B0[(a1 >> 8) & 0xF] ^ byte_2030B0[(unsigned __int8)a1 >> 4])) == 2)
v7 = 64;
else
v7 = 0;
v24 = v23 | v7;
if ((unsigned __int8)sub_FCB((unsigned __int8)(byte_2030B0[(unsigned __int8)a1 >> 4] ^ byte_2030B0[a1 & 0xF])) == 2)
v8 = 128;
else
v8 = 0;
v25 = v24 | v8;
if ((unsigned __int8)sub_FCB((unsigned __int8)(byte_2030B0[a1 & 0xF] ^ byte_2030B0[a2 >> 28])) == 2)
v9 = 256;
else
v9 = 0;
v26 = v25 | v9;
if ((unsigned __int8)sub_FCB((unsigned __int8)(byte_2030B0[a2 >> 28] ^ byte_2030B0[(a2 >> 24) & 0xF])) == 2)
v10 = 512;
else
v10 = 0;
v27 = v26 | v10;
if ((unsigned __int8)sub_FCB((unsigned __int8)(byte_2030B0[(a2 >> 24) & 0xF] ^ byte_2030B0[(a2 >> 20) & 0xF])) == 2)
v11 = 1024;
else
v11 = 0;
v28 = v27 | v11;
if ((unsigned __int8)sub_FCB((unsigned __int8)(byte_2030B0[(a2 >> 20) & 0xF] ^ byte_2030B0[(a2 >> 16) & 0xF])) == 2)
v12 = 2048;
else
v12 = 0;
v29 = v28 | v12;
if ((unsigned __int8)sub_FCB((unsigned __int8)(byte_2030B0[(a2 >> 16) & 0xF] ^ byte_2030B0[(unsigned __int16)a2 >> 12])) == 2)
v13 = 4096;
else
v13 = 0;
v30 = v29 | v13;
if ((unsigned __int8)sub_FCB((unsigned __int8)(byte_2030B0[(unsigned __int16)a2 >> 12] ^ byte_2030B0[(a2 >> 8) & 0xF])) == 2)
v14 = 0x2000;
else
v14 = 0;
v31 = v30 | v14;
if ((unsigned __int8)sub_FCB((unsigned __int8)(byte_2030B0[(a2 >> 8) & 0xF] ^ byte_2030B0[(unsigned __int8)a2 >> 4])) == 2)
v15 = 0x4000;
else
v15 = 0;
v32 = v31 | v15;
if ((unsigned __int8)sub_FCB((unsigned __int8)(byte_2030B0[(unsigned __int8)a2 >> 4] ^ byte_2030B0[a2 & 0xF])) == 2)
v16 = 0x8000;
else
v16 = 0;
return (unsigned __int16)(v32 | v16);
}
__int64 __fastcall sub_18D2(unsigned int a1, unsigned int a2, int a3)
{
__int64 result;
int v4;
unsigned __int16 v5;
unsigned __int16 v6;
unsigned __int16 i;
unsigned __int16 j;
signed int v9;
signed int v10;
v4 = a3;
v5 = 0;
v6 = 0;
v9 = 15;
for (i = 0; i <= 0xFu; ++i)
v5 = (a1 >> 2 * v9--) & 1 | 2 * v5;
if ((signed int)sub_1D20(v5) > 2)
{
v10 = 15;
for (j = 0; j <= 0xFu; ++j)
v6 = (a2 >> 2 * v10--) & 1 | 2 * v6;
if ((signed int)sub_1D20(v6) > 3)
result = v4 + 1 == v5 * v6;
else
result = 0LL;
}
else
{
result = 0LL;
}
return result;
}
__int64 __fastcall sub_1566(unsigned int a1)
{
if (!((a1 >> 16) - 391 * (a1 / 0x1870000) == (BYTE)a1))
return false;
if (!((a1 >> 16) & (0xFFFF % (((a1 & 0xFF00) >> 8) + 1) == 0)))
return false;
if (!(sub_1D20(a1) > 8))
return false;
return true;
}
__int64 __fastcall sub_17B5(unsigned int a1)
{
unsigned __int16 v2;
unsigned __int16 i;
signed int v4;
v2 = 0;
v4 = 15;
for (i = 0; i <= 0xFu; ++i)
{
v2 = (a1 >> (2 * v4-- + 1)) & 1 | 2 * v2;
}
return v2 == 7 * (v2 / 7u);
}
__int64 __fastcall sub_CA0(unsigned int a1)
{
return a1 >> 28 == ((a1 >> 24) & 0xF)
|| !((BYTE(a1) ^ (unsigned __int8)(a1 >> 20)) & 0xF)
|| !(((unsigned __int8)(a1 >> 20) ^ (unsigned __int8)(a1 >> 16)) & 0xF)
|| !(((unsigned __int8)(a1 >> 16) ^ (unsigned __int8)(a1 >> 12)) & 0xF)
|| !(((unsigned __int8)(a1 >> 12) ^ BYTE(a1)) & 0xF)
|| !((BYTE(a1) ^ (unsigned __int8)(a1 >> 4)) & 0xF)
|| !(((unsigned __int8)a1 ^ (unsigned __int8)(a1 >> 4)) & 0xF);
}
__int64 __fastcall sub_F0F(__int64 a1, int a2)
{
signed int v2;
unsigned __int16 v4;
unsigned __int16 v5;
int i;
v4 = 0;
v5 = 0;
for (i = 0; i < a2; ++i)
{
v2 = v4 + *(BYTE *)(i + a1);
v4 = v2 - 255 * (((signed int)(v2 + ((unsigned __int64)(0xFFFFFFFF80808081LL * v2) >> 32)) >> 7) - (v2 >> 31));
v5 = (v5 + v4) % 255;
}
return (v5 << 8) | (unsigned int)v4;
}
__int64 __fastcall Auth(__int64 a1)
{
__int64 result;
unsigned __int16 v2;
unsigned int v3;
unsigned int v4;
unsigned int v5;
int v6;
unsigned int v7;
v3 = *(DWORD *)a1;
v4 = *(DWORD *)(a1 + 4);
v5 = *(DWORD *)(a1 + 8);
v6 = *(DWORD *)(a1 + 12);
v7 = *(DWORD *)(a1 + 16);
v2 = *(WORD *)(a1+20);
if (sub_E10(v2) || sub_DA2(v2))
{
result = 0;
}
else if ( (sub_F0F(a1, 20) & 0x7FFF) == v2 )
{
if ((unsigned int)sub_E40(v3, v4, v5) == v6)
{
if ((unsigned int)sub_1566(v7))
{
if ((unsigned int)sub_CA0(v3))
{
result = 0LL;
}
else if (sub_D51(v3))
{
result = 0LL;
}
else if (sub_C15(v3))
{
if (sub_17B5((unsigned int)v4))
{
if (sub_1846(v5))
{
if (sub_18D2((unsigned int)v4, v5, v3))
{
result = (unsigned __int16)sub_1061((unsigned int)v4, v5) == v2;
return result;
}
else
{
result = 0;
}
}
else
{
result = 0;
}
}
else
{
result = 0;
}
}
else
{
result = 0;
}
}
else
{
result = 0;
}
}
else
{
result = 0;
}
}
else
{
result = 0LL;
}
return result;
}
__int64 __fastcall MakeTable(const char *a1)
{
__int64 result;
int v2;
unsigned int i;
WORD var6 = 0;
BYTE var7 = 0;
BYTE CNT = 0;
BYTE var9 = 0;
if (strlen(a1) > 0x28)
{
for (i = 0; i <= 40; ++i)
{
C1638:
if (i != 5 && i != 11 && i != 17 && i != 23 && i != 29 && i != 35)
goto C167C;
if (a1[i] != '-')
{
printf("not serial error:(\n");
return 0LL;
}
C167C:
v2 = a1[i] - 50;
if ((unsigned int)v2 <= 40)
{
switch (dword_1E08[v2]) //Hexray로는 이부분이 Jumpout 으로 제대로분석이안됩니다. 어셈블리로 보셔야 구현가능합니다.
{
case 0xFFFFF8F2:
var7 = a1[i] - 26;
break;
case 0xFFFFF907:
return 0;
break;
case 0xFFFFF8B3://16BB
var7 = a1[i] - 65;
break;
case 0xFFFFF8C8:
var7 = a1[i] - 66;
break;
case 0xFFFFF8DD:
var7 = a1[i] - 67;
break;
}
var6 = var7 | (var6 << 5);
var9 = var9 + 5;
if (var9>7)
{
var9 = var9 - 8;
s[CNT++] = (BYTE)((var6 >> (var9)));
var6 = var6&((1 << (var9)) - 1);
}
}
}
if (var9 != 7)
{
printf("문제\n");
return 0;
}
else
{
s[CNT] = (BYTE)var6;
return 1;
}
}
else
{
return 0;
}
}
int main()
{
int chk = 0;
for (;;)
{
chk=MakeTable("BR2H6-K7SR4-KKD5N-KDWRZ-29CQW-YGAEN-PSA2Q");
if(chk)
{
printf("Calc....\n");
if (Auth((int)s) == 1)
{
printf("GooD!\n");
}
else
{
printf("Fail!\n");
}
break;
}
}
}
위의 Auth함수의 인증을 거쳐야함을 토대로 Auth함수에서
사용하는 사용자함수들을 분석해서 인증에 실패하지않는값들을 만들어냈으며
최종적으로는 sub_FOF에서 CRC를 브루트포싱을 하여 결과를 뽑아냈다.
#include <Windows.h>
#include <stdio.h>
void DisTable(BYTE a1[]);
BYTE table[] = "ABCDEFGHJKLMNPQRSTUVWXYZ23456789";
DWORD combo[40];
DWORD dword_1E08[41] = { 0xFFFFF8F2, 0xFFFFF8F2, 0xFFFFF8F2, 0xFFFFF8F2, 0xFFFFF8F2, 0xFFFFF8F2, 0xFFFFF8F2, 0xFFFFF8F2,
0xFFFFF907, 0xFFFFF907, 0xFFFFF907, 0xFFFFF907, 0xFFFFF907, 0xFFFFF907, 0xFFFFF907,
0xFFFFF8B3, 0xFFFFF8B3, 0xFFFFF8B3, 0xFFFFF8B3, 0xFFFFF8B3, 0xFFFFF8B3, 0xFFFFF8B3, 0xFFFFF8B3,
0xFFFFF907,//i
0xFFFFF8C8, 0xFFFFF8C8, 0xFFFFF8C8, 0xFFFFF8C8, 0xFFFFF8C8, 0xFFFFF907, 0xFFFFF8DD, 0xFFFFF8DD, 0xFFFFF8DD,
0xFFFFF8DD, 0xFFFFF8DD, 0xFFFFF8DD, 0xFFFFF8DD, 0xFFFFF8DD, 0xFFFFF8DD, 0xFFFFF8DD, 0xFFFFF8DD };
BYTE byte_2030B0[] = { 0, 1, 3, 2, 6, 7, 5, 4, 0x0C, 0x0D, 0x0F, 0x0E, 0x0A, 0x0B, 9, 8 };
const char byte_1FC0[] = "\x00\x01\x01\x02\x01\x02\x02\x03\x01\x02\x02\x03\x02\x03\x03\x04"
"\x01\x02\x02\x03\x02\x03\x03\x04\x02\x03\x03\x04\x03\x04\x04\x05"
"\x01\x02\x02\x03\x02\x03\x03\x04\x02\x03\x03\x04\x03\x04\x04\x05"
"\x02\x03\x03\x04\x03\x04\x04\x05\x03\x04\x04\x05\x04\x05\x05\x06"
"\x01\x02\x02\x03\x02\x03\x03\x04\x02\x03\x03\x04\x03\x04\x04\x05"
"\x02\x03\x03\x04\x03\x04\x04\x05\x03\x04\x04\x05\x04\x05\x05\x06"
"\x02\x03\x03\x04\x03\x04\x04\x05\x03\x04\x04\x05\x04\x05\x05\x06"
"\x03\x04\x04\x05\x04\x05\x05\x06\x04\x05\x05\x06\x05\x06\x06\x07"
"\x01\x02\x02\x03\x02\x03\x03\x04\x02\x03\x03\x04\x03\x04\x04\x05"
"\x02\x03\x03\x04\x03\x04\x04\x05\x03\x04\x04\x05\x04\x05\x05\x06"
"\x02\x03\x03\x04\x03\x04\x04\x05\x03\x04\x04\x05\x04\x05\x05\x06"
"\x03\x04\x04\x05\x04\x05\x05\x06\x04\x05\x05\x06\x05\x06\x06\x07"
"\x02\x03\x03\x04\x03\x04\x04\x05\x03\x04\x04\x05\x04\x05\x05\x06"
"\x03\x04\x04\x05\x04\x05\x05\x06\x04\x05\x05\x06\x05\x06\x06\x07"
"\x03\x04\x04\x05\x04\x05\x05\x06\x04\x05\x05\x06\x05\x06\x06\x07"
"\x04\x05\x05\x06\x05\x06\x06\x07\x05\x06\x06\x07\x06\x07\x07\x08";
BYTE s2[25];
//이것도비트수 근데 BYTE
__int64 __fastcall sub_FCB(unsigned __int8 a1)
{
__int64 result;
__int64 v2;
BYTE v3[] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 };
result = v3[a1 & 0xF];
return result;
}
//켜진 bit 수 리턴
__int64 __fastcall sub_1D20(unsigned __int64 a1)
{
__int64 result;
int v2;
unsigned __int64 v3;
result = 0;
v2 = 0;
do
{
v3 = a1 >> v2;
v2 += 8;
result = byte_1FC0[(unsigned __int8)v3] + (unsigned int)result;
} while (v2 != 64);
return result;
}
//일단 1리턴되야함 이건
signed __int64 __fastcall sub_C15(unsigned int a1)
{
signed __int64 result;
unsigned int v2;
int i;
if (a1 == 2)
{
result = 1LL;
}
else if (a1 & 1)
{
if (a1 > 0xFFFFFE)
{
v2 = 3;
for (i = 9; i < a1; i = v2 * v2)
{
if (!(a1 % v2))
return 0LL;
v2 += 2;
}
result = i != a1;
}
else
{
result = 0LL;
}
}
else
{
result = 0LL;
}
return result;
}
__int64 __fastcall sub_D51(unsigned int a1)
{
return a1 >> 24 == (unsigned __int8)(a1 >> 16)
|| !((unsigned __int8)(a1 >> 16) ^ a1)
|| !((unsigned __int8)a1 ^ a1);
}
//별로 필요없지만 al ah 같으면 Fail
__int64 __fastcall sub_E10(__int16 a1)
{
return HIBYTE(a1) == (BYTE)a1;
}
//별로 필요없지만 al과 ah를 각각 앞뒤 4bit씩 같은지 검사함 (말이 더 어렵네)
__int64 __fastcall sub_DA2(unsigned __int16 a1)
{
return !(((a1 >> 12) ^ HIBYTE(a1)) & 0xF)
|| !((HIBYTE(a1) ^ (unsigned __int8)(a1 >> 4)) & 0xF)
|| !(((unsigned __int8)(a1 >> 4) ^ (unsigned __int8)a1) & 0xF);
}
//리턴값이 v6과 같아야만된다는점만 유념
__int64 __fastcall sub_E40(int a1, int a2, unsigned int a3)
{
int v3;
int v4;
int v5;
int v6;
int v7;
int v8;
int v9;
v3 = (a3 >> 13) ^ (a1 - a2 - a3);
v4 = (v3 << 8) ^ (a2 - a3 - v3);
v5 = ((unsigned int)v4 >> 13) ^ (a3 - v3 - v4);
v6 = ((unsigned int)v5 >> 12) ^ (v3 - v4 - v5);
v7 = (v6 << 16) ^ (v4 - v5 - v6);
v8 = ((unsigned int)v7 >> 5) ^ (v5 - v6 - v7);
v9 = ((unsigned int)v8 >> 3) ^ (v6 - v7 - v8);
return (((v9 << 10) ^ (unsigned int)(v7 - v8 - v9)) >> 15) ^ (v8 - v9 - ((v9 << 10) ^ (v7 - v8 - v9)));
}
//인자의 left비트를 특정하게 체크
__int64 __fastcall sub_1846(unsigned int a1)
{
unsigned __int16 v2;
unsigned __int16 i;
signed int v4;
v2 = 0;
v4 = 15;
for (i = 0; i < 16; ++i)
v2 = (a1 >> (2 * v4-- + 1)) & 1 | 2 * v2;
return v2 == 13 * ((unsigned __int16)(0x4EC5 * (DWORD)v2 >> 16) >> 2);
}
//존나 분석 싫어 리턴값이 v2하고같아야된다는점만 유념
__int64 __fastcall sub_1061(unsigned int a1, unsigned int a2)
{
signed __int16 v2;
signed __int16 v3;
signed __int16 v4;
signed __int16 v5;
signed __int16 v6;
signed __int16 v7;
signed __int16 v8;
signed __int16 v9;
signed __int16 v10;
signed __int16 v11;
signed __int16 v12;
signed __int16 v13;
signed __int16 v14;
signed __int16 v15;
signed __int16 v16;
__int16 v18;
__int16 v19;
__int16 v20;
__int16 v21;
__int16 v22;
__int16 v23;
__int16 v24;
__int16 v25;
__int16 v26;
__int16 v27;
__int16 v28;
__int16 v29;
__int16 v30;
__int16 v31;
__int16 v32;
v18 = (unsigned __int8)sub_FCB(byte_2030B0[a1 >> 28]) == 2;
if ((unsigned __int8)sub_FCB((unsigned __int8)(byte_2030B0[a1 >> 28] ^ byte_2030B0[(a1 >> 24) & 0xF])) == 2)
v2 = 2;
else
v2 = 0;
v19 = v18 | v2;
if ((unsigned __int8)sub_FCB((unsigned __int8)(byte_2030B0[(a1 >> 24) & 0xF] ^ byte_2030B0[(a1 >> 20) & 0xF])) == 2)
v3 = 4;
else
v3 = 0;
v20 = v19 | v3;
if ((unsigned __int8)sub_FCB((unsigned __int8)(byte_2030B0[(a1 >> 20) & 0xF] ^ byte_2030B0[(a1 >> 16) & 0xF])) == 2)
v4 = 8;
else
v4 = 0;
v21 = v20 | v4;
if ((unsigned __int8)sub_FCB((unsigned __int8)(byte_2030B0[(a1 >> 16) & 0xF] ^ byte_2030B0[(unsigned __int16)a1 >> 12])) == 2)
v5 = 16;
else
v5 = 0;
v22 = v21 | v5;
if ((unsigned __int8)sub_FCB((unsigned __int8)(byte_2030B0[(unsigned __int16)a1 >> 12] ^ byte_2030B0[(a1 >> 8) & 0xF])) == 2)
v6 = 32;
else
v6 = 0;
v23 = v22 | v6;
if ((unsigned __int8)sub_FCB((unsigned __int8)(byte_2030B0[(a1 >> 8) & 0xF] ^ byte_2030B0[(unsigned __int8)a1 >> 4])) == 2)
v7 = 64;
else
v7 = 0;
v24 = v23 | v7;
if ((unsigned __int8)sub_FCB((unsigned __int8)(byte_2030B0[(unsigned __int8)a1 >> 4] ^ byte_2030B0[a1 & 0xF])) == 2)
v8 = 128;
else
v8 = 0;
v25 = v24 | v8;
if ((unsigned __int8)sub_FCB((unsigned __int8)(byte_2030B0[a1 & 0xF] ^ byte_2030B0[a2 >> 28])) == 2)
v9 = 256;
else
v9 = 0;
v26 = v25 | v9;
if ((unsigned __int8)sub_FCB((unsigned __int8)(byte_2030B0[a2 >> 28] ^ byte_2030B0[(a2 >> 24) & 0xF])) == 2)
v10 = 512;
else
v10 = 0;
v27 = v26 | v10;
if ((unsigned __int8)sub_FCB((unsigned __int8)(byte_2030B0[(a2 >> 24) & 0xF] ^ byte_2030B0[(a2 >> 20) & 0xF])) == 2)
v11 = 1024;
else
v11 = 0;
v28 = v27 | v11;
if ((unsigned __int8)sub_FCB((unsigned __int8)(byte_2030B0[(a2 >> 20) & 0xF] ^ byte_2030B0[(a2 >> 16) & 0xF])) == 2)
v12 = 2048;
else
v12 = 0;
v29 = v28 | v12;
if ((unsigned __int8)sub_FCB((unsigned __int8)(byte_2030B0[(a2 >> 16) & 0xF] ^ byte_2030B0[(unsigned __int16)a2 >> 12])) == 2)
v13 = 4096;
else
v13 = 0;
v30 = v29 | v13;
if ((unsigned __int8)sub_FCB((unsigned __int8)(byte_2030B0[(unsigned __int16)a2 >> 12] ^ byte_2030B0[(a2 >> 8) & 0xF])) == 2)
v14 = 0x2000;
else
v14 = 0;
v31 = v30 | v14;
if ((unsigned __int8)sub_FCB((unsigned __int8)(byte_2030B0[(a2 >> 8) & 0xF] ^ byte_2030B0[(unsigned __int8)a2 >> 4])) == 2)
v15 = 0x4000;
else
v15 = 0;
v32 = v31 | v15;
if ((unsigned __int8)sub_FCB((unsigned __int8)(byte_2030B0[(unsigned __int8)a2 >> 4] ^ byte_2030B0[a2 & 0xF])) == 2)
v16 = 0x8000;
else
v16 = 0;
return (unsigned __int16)(v32 | v16);
}
//첫번째 인자는 right 비트 체크 3개이상이어야하고 두번쨰인자는 right비트 체크 4개이상이어야함 그리고 그두개 right비트 모은거 곱한후 -1하면 3번쟤인자(v4)값!
__int64 __fastcall sub_18D2(unsigned int a1, unsigned int a2, int a3)
{
__int64 result; // rax@5
int v4; // [sp+4h] [bp-1Ch]@1
unsigned __int16 v5; // [sp+10h] [bp-10h]@1
unsigned __int16 v6; // [sp+12h] [bp-Eh]@1
unsigned __int16 i; // [sp+14h] [bp-Ch]@1
unsigned __int16 j; // [sp+14h] [bp-Ch]@6
signed int v9; // [sp+18h] [bp-8h]@1
signed int v10; // [sp+18h] [bp-8h]@6
v4 = a3;
v5 = 0;
v6 = 0;
v9 = 15;
for (i = 0; i <= 0xFu; ++i)
v5 = (a1 >> 2 * v9--) & 1 | 2 * v5;
if ((signed int)sub_1D20(v5) > 2)
{
v10 = 15;
for (j = 0; j <= 0xFu; ++j)
v6 = (a2 >> 2 * v10--) & 1 | 2 * v6;
if ((signed int)sub_1D20(v6) > 3)
result = v4 + 1 == v5 * v6;
else
result = 0LL;
}
else
{
result = 0LL;
}
return result;
}
//v7 제너레이트! CRC돌릴때 하나하나연산하면 속도가 매우오래 걸릴것같으므로 수십개 미리 뽑아놓자!
__int64 __fastcall sub_1566(unsigned int a1)
{
if (!((a1 >> 16) - 391 * (a1 / 0x1870000) == (BYTE)a1))
return false;
if (!((a1 >> 16) & (0xFFFF % (((a1 & 0xFF00) >> 8) + 1) == 0)))
return false;
if (!(sub_1D20(a1) > 8))
return false;
return true;
}
//v2는 left 비트
__int64 __fastcall sub_17B5(unsigned int a1) //v4
{
unsigned __int16 v2;
unsigned __int16 i;
signed int v4;
v2 = 0;
v4 = 15;
for (i = 0; i <= 0xFu; ++i)
{
v2 = (a1 >> (2 * v4-- + 1)) & 1 | 2 * v2;
}
return v2 == 7 * (v2 / 7u);
}
//그냥 1만리턴안되면 된다고생각하자..
__int64 __fastcall sub_CA0(unsigned int a1)
{
return a1 >> 28 == ((a1 >> 24) & 0xF)
|| !((BYTE(a1) ^ (unsigned __int8)(a1 >> 20)) & 0xF)
|| !(((unsigned __int8)(a1 >> 20) ^ (unsigned __int8)(a1 >> 16)) & 0xF)
|| !(((unsigned __int8)(a1 >> 16) ^ (unsigned __int8)(a1 >> 12)) & 0xF)
|| !(((unsigned __int8)(a1 >> 12) ^ BYTE(a1)) & 0xF)
|| !((BYTE(a1) ^ (unsigned __int8)(a1 >> 4)) & 0xF)
|| !(((unsigned __int8)a1 ^ (unsigned __int8)(a1 >> 4)) & 0xF);
}
//CRC.. 0x7FFF 극혐
__int64 __fastcall sub_F0F(__int64 a1, int a2)
{
signed int v2; // ecx@2
unsigned __int16 v4; // [sp+14h] [bp-8h]@1
unsigned __int16 v5; // [sp+16h] [bp-6h]@1
int i; // [sp+18h] [bp-4h]@1
v4 = 0;
v5 = 0;
for (i = 0; i < a2; ++i)
{
v2 = v4 + *(BYTE *)(i + a1);
v4 = v2 - 255 * (((signed int)(v2 + ((unsigned __int64)(0xFFFFFFFF80808081LL * v2) >> 32)) >> 7) - (v2 >> 31));
v5 = (v5 + v4) % 255;
}
return (v5 << 8) | (unsigned int)v4;
}
//C rand 너무구림 srand의 유연성을 보여줘!
int randseed()
{
int result = 0;
__asm
{
rdtsc;
xor eax,edx
mov result,eax
}
return result;
}
int Auth()
{
__int64 result;
WORD v4r = 0;
WORD v5r = 0;
WORD v4l = 0;
WORD v5l = 0;
DWORD v3 = 0;
DWORD v4 = 0;
DWORD v5 = 0;
DWORD v6 = 0;
DWORD v7 = 0;
WORD v2 = 0;
for (;;)
{
v4r = ((rand() & 0xFF) | ((rand() & 0xFF) << 8)); //아 랜덤함수 C에선 0x7FFF가 최대값인것때문에 -- 이렇게해야 원하는대로 랜덤함
v5r = ((rand() & 0xFF) | ((rand() & 0xFF) << 8));
v3 = (v4r*v5r) - 1; //sub_18D2에서 v4와 v5의 오른쪽비트들을 곱한뒤 -1을한게 v3임을 알 수 있음.
if (sub_1D20(v4r)>2) //켜진비트가 3이상이어야함.
{
if (sub_1D20(v5r)>3) //켜진비트가 4이상이어야하고!
{
if (!sub_CA0(v3))//몰라 Brute Force!
{
if (!sub_D51(v3))//몰라 Brute Force!
{
if (sub_C15(v3))//몰라 Brute Force!
{
break;
}
}
}
}
}
}
v4l = ((rand() & 0xFF) | (rand() & 0xFF) << 8);
v4l = v4l / 7 * 7;//sub_17B5 보면 v4의 왼쪽비트들을 이렇게검사함
v5l = ((rand() & 0xFF) | (rand() & 0xFF) << 8);
int temp = 13 * ((WORD)(0x4EC5 * (DWORD)v5l >> 16) >> 2); //sub_1846 보면 v5의 왼쪽비트들을 이렇게검사함
v5l = temp;
for (int i = 0; i<16; i++) // l r 을 각각 왼쪽비트 오른쪽비트로 채워넣음
{
v4 = ((v4l & 1) << (2 * i + 1)) | ((v4r & 1) << (2 * i)) | v4;
v4l = v4l >> 1;
v4r = v4r >> 1;
v5 = ((v5l & 1) << (2 * i + 1)) | ((v5r & 1) << (2 * i)) | v5;
v5l = v5l >> 1;
v5r = v5r >> 1;
}
v2 = (WORD)sub_1061((DWORD)v4, v5); //알지? 패스
if (v2 > 0x7fff) //7fff이상이면 나중에 sub_F0F 체크섬할때 당연히 안맞겠지? 속도생각해서 여기서한번검사해주자.
{
return 0;
}
if (sub_DA2(v2) || sub_E10(v2)) //v2들 체크해봄 굳이 체크안해봐도 될듯 ㅋ
return 0;
if (!sub_18D2(v4, v5, v3)) //v4,v5,v3 관계 체크
{
return 0;
}
v6 = (DWORD)sub_E40(v3, v4, v5); // 아니까 패스
for (int c = 0; c<40;) //v7미리 수십개 뽑아놓자 (40개)
{
DWORD temp = 0;
temp = ((rand() & 0xFF) | (rand() & 0xFF) << 8 | (rand() & 0xFF) << 16 | (rand() & 0xFF) << 24);
if (sub_1566(temp))
{
combo[c] = temp;
c++;
}
}
s2[0] = v3 & 0xFF; s2[1] = (v3 & 0xFF00) >> 8; s2[2] = (v3 & 0xFF0000) >> 16; s2[3] = (v3 & 0xFF000000) >> 24;
s2[4] = v4 & 0xFF; s2[5] = (v4 & 0xFF00) >> 8; s2[6] = (v4 & 0xFF0000) >> 16; s2[7] = (v4 & 0xFF000000) >> 24;
s2[8] = v5 & 0xFF; s2[9] = (v5 & 0xFF00) >> 8; s2[10] = (v5 & 0xFF0000) >> 16; s2[11] = (v5 & 0xFF000000) >> 24;
s2[12] = v6 & 0xFF; s2[13] = (v6 & 0xFF00) >> 8; s2[14] = (v6 & 0xFF0000) >> 16; s2[15] = (v6 & 0xFF000000) >> 24;
//s2[16]=v7&0xFF;s2[17]=(v7&0xFF00)>>8;s2[18]=(v7&0xFF0000)>>16;s2[19]=(v7&0xFF000000)>>24; -> v7 은 40개를 미리뽑아놨음
s2[20] = v2 & 0xFF; s2[21] = (v2 & 0xFF00) >> 8;
for (int c = 0; c<40; c++) //40개를 sub_FOF(CRC)를 검사함
{
v7 = combo[c];
s2[16] = v7 & 0xFF; s2[17] = (v7 & 0xFF00) >> 8; s2[18] = (v7 & 0xFF0000) >> 16; s2[19] = (v7 & 0xFF000000) >> 24;
DWORD temp = (sub_F0F((DWORD)s2, 20) & 0x7FFF);
if (temp == v2)
{
return 1;
}
}
srand(~randseed()); //Ultra Random
return 0;
}
void DisTable(BYTE a1[])
{
WORD var6 = 0;
BYTE var7 = 0;
BYTE var9 = 0;
for (int i = 0; i<20; i = i + 5){
printf("%c", table[a1[i] / 8]);
if (i == 15)
printf("-");
printf("%c", table[((a1[i] % 8) * 256 + a1[i + 1]) / 64]);
if (i == 5)
printf("-");
printf("%c", table[(a1[i + 1] % 64) / 2]);
printf("%c", table[((a1[i + 1] % 2) * 256 + a1[i + 2]) / 16]);
if (i == 10)
printf("-");
printf("%c", table[((a1[i + 2] % 16) * 256 + a1[i + 3]) / 128]);
if (i == 0)
printf("-");
printf("%c", table[(a1[i + 3] % 128) / 4]);
if (i == 15)
printf("-");
printf("%c", table[((a1[i + 3] % 4) * 256 + a1[i + 4]) / 32]);
if (i == 5)
printf("-");
printf("%c", table[(a1[i + 4] % 32)]);
}
printf("%c", table[a1[20] / 8]);
printf("%c", table[((a1[20] % 8) * 128 + a1[21]) / 32]);
printf("%c", table[(a1[21] % 32)]);
printf("\n");
}
int main()
{
int chk = 0;
int i = 0;
srand(12341234);
for (;;)
{
if (Auth() == 1)
{
printf("GooD!\n");
DisTable(s2); //key 출력
}
}
}
빈곤한 관계로 Pwnable.kr서버로..
질문은 감사하게받을게요~!
반응형
'Write-up' 카테고리의 다른 글
| [Crypto] 2019 CTFZONE CSES : CBC모드에서 KEY=IV 일때, 발생하는 취약점 (2) | 2019.12.02 |
|---|---|
| [Crypto] 2019 CTFZONE agents : OFB 모드에서 값을 조작해야하는 문제 (0) | 2019.12.02 |
| HISCHALL 2013 문제 풀이 Write up (5) | 2013.11.17 |
| [HUST] 7. 수학 암호 (2) | 2012.12.03 |
| [순천향대 2012 정보보호 페스티벌 본선 사회공학적 해킹] (0) | 2012.09.17 |
댓글