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 |
댓글