KCTF-CCG CrackMe crypto 1.0

发布于:2025-05-23 ⋅ 阅读:(21) ⋅ 点赞:(0)

继续分享一个KCTF里面的题,也是比较古老的题。

首先查壳

提示是tElock壳,下面提示工具RL!detElock,

提示成功了,但运行不了,拖入IDA,发现逻辑正常,估计是加了保护,也懒得看,直接分析源码

int __stdcall WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
  dword_4171EC = (int)hInstance;
  dword_413118(hInstance, 101, 0, sub_401230, 101);
  return 0;
}

WinMain显示,事件回调为sub_401230

int __stdcall sub_401230(int a1, int a2, int a3, int a4)
{
  int v4; // ebx
  int v5; // esi
  int v6; // ebp
  int v8; // eax
  int v9; // eax
  int v10; // eax
  int v11; // ebx
  char v12[64]; // [esp+60h] [ebp-7Ch] BYREF
  int v13[4]; // [esp+A0h] [ebp-3Ch] BYREF
  char v14[4]; // [esp+B0h] [ebp-2Ch] BYREF
  int v15; // [esp+B4h] [ebp-28h]
  int v16; // [esp+B8h] [ebp-24h]

  switch ( a2 )
  {
    case 272:
      sub_401490(a1);
      v8 = dword_41314C(a1, 1008);
      dword_413114(v8);
      v9 = dword_41311C(dword_4171EC, 103);
      dword_4171E8 = v9;
      if ( v9 )
      {
        dword_413140(a1, 128, 1, v9);
        dword_413140(a1, 128, 0, dword_4171E8);
      }
      v10 = dword_413158(a1, 0);
      v11 = v10;
      if ( v10 )
      {
        dword_413154(v10, 2048, 0, 0);
        dword_413154(v11, 0, 1148, aAbout);
      }
      break;
    case 273:
      if ( (unsigned __int16)a3 == 1002 )
        goto LABEL_8;
      if ( (unsigned __int16)a3 != 1003 )
      {
LABEL_9:
        dword_413144(a1, a2, a3, a4);
        return 0;
      }
      if ( dword_413150(a1, 1008, &unk_417180, 101) && dword_413150(a1, 1007, &unk_417100, 128) )
      {
        if ( (unsigned __int8)sub_401610(&unk_417180, &unk_417100) )
          dword_413124(a1, aSuccessfullyRe, aGreat, 64);
        else
          dword_413124(a1, aIncorrectSeria, aFailed, 16);
      }
      break;
    case 15:
      v4 = dword_413130(a1, v12);
      dword_413128(a1, v13);
      v5 = dword_413120(dword_4171EC, 105);
      dword_413014(v5, 24, v14);
      v6 = dword_413004(v4);
      dword_413010(v6, v5);
      dword_413000(v4, 0, 0, v13[2] - v13[0], v16, v6, 0, 0, v15, v16, 13369376);
      dword_413008(v6);
      dword_41312C(a1, v12);
      dword_41300C(v5);
      return 0;
    case 274:
      if ( a3 == 1148 )
        dword_413124(a1, aCcgCryptoCrack, aAboutThisKeyge, 0);
      return 0;
    case 16:
LABEL_8:
      dword_413148(a1, 0);
      return 0;
    default:
      goto LABEL_9;
  }
  return 0;
}

消息273为register按钮点击事件,首先判断Name和Serial都不为空,然后获取输入值,再调用sub_401610检查

int __cdecl sub_401610(int a1, int a2)
{
  int v2; // esi
  char *v3; // ebx
  unsigned __int16 v4; // ax
  int v5; // esi
  char v6; // dl
  int v7; // eax
  char v9[4]; // [esp+0h] [ebp-1CCh] BYREF
  char v10[88]; // [esp+4h] [ebp-1C8h] BYREF
  char v11[8]; // [esp+5Ch] [ebp-170h] BYREF
  char v12[8]; // [esp+64h] [ebp-168h] BYREF
  char v13[5]; // [esp+6Ch] [ebp-160h] BYREF
  char v14[3]; // [esp+71h] [ebp-15Bh] BYREF
  char v15[260]; // [esp+74h] [ebp-158h] BYREF
  int v16; // [esp+178h] [ebp-54h] BYREF
  int v17; // [esp+17Ch] [ebp-50h] BYREF
  int v18; // [esp+180h] [ebp-4Ch] BYREF
  int v19; // [esp+184h] [ebp-48h] BYREF
  char v20[32]; // [esp+188h] [ebp-44h] BYREF
  int v21[6]; // [esp+1A8h] [ebp-24h] BYREF
  int v22; // [esp+1C8h] [ebp-4h]

  v21[5] = (int)v9;
  sub_401000(v9);
  v22 = 0;
  v2 = dword_413094(a2);
  v3 = (char *)operator new(v2);
  v4 = sub_401020(a2, v3, v2);
  if ( v4 < 8u )
    goto LABEL_12;
  v3[v4] = 0;
  v5 = 8;
  if ( v4 > 8u )
  {
    do
    {
      v6 = v3[v5];
      if ( v6 < 48 || v6 > 57 )
        goto LABEL_12;
    }
    while ( ++v5 < v4 );
  }
  sub_408310(v10);
  v7 = dword_413094(&unk_417180);
  sub_408340(v10, &unk_417180, v7);
  sub_4085F0(v10);
  qmemcpy(v13, ")G\a", 3);
  v13[3] = -123;
  v13[4] = -121;
  qmemcpy(v14, "3%D", sizeof(v14));
  sub_408FF0(v13, 8, v15);
  sub_4090F0(v3, 8, v15);
  if ( memcmp(v11, v3, 8u) )
  {
LABEL_12:
    sub_4092DC(v3);
    v22 = -1;
    nullsub_1(v9);
    return 0;
  }
  v16 = 0;
  v17 = 0;
  v18 = 0;
  v19 = 0;
  sub_4071D0(v3 + 8, (int)&v16);
  sub_4092DC(v3);
  sub_4071D0(a65537, (int)&v17);
  sub_406ED0(aB80a90bf53c6c9, (int)&v18);
  sub_405E40(v16, v17, v18, &v19);
  sub_4014F0(v12, 8, v20);
  v21[0] = 0;
  sub_406ED0(v20, (int)v21);
  if ( sub_402290(v21[0], v19) )
  {
    v22 = -1;
    nullsub_1(v9);
    return 0;
  }
  else
  {
    v22 = -1;
    nullsub_1(v9);
    return 1;
  }
}

dword_413094=strlen, sub_401020查看代码

int __stdcall sub_401020(int a1, int a2, unsigned __int16 a3)
{
  int v3; // esi
  int v4; // ecx
  __int16 v5; // ax
  int v6; // ebx
  char v9; // [esp+10h] [ebp-24h]
  char v10; // [esp+11h] [ebp-23h]
  char v11; // [esp+12h] [ebp-22h]
  int v12; // [esp+14h] [ebp-20h]
  char v13; // [esp+18h] [ebp-1Ch]

  v3 = a3;
  if ( (a3 & 3) != 0 )
    return 0;
  v4 = a1;
  v5 = a3 / 4;
  v6 = 0;
  if ( a3 )
  {
    v12 = 0;
    do
    {
      v9 = sub_4011A0(*(_BYTE *)(a1 + v12));
      v10 = sub_4011A0(*(_BYTE *)(a1 + v12 + 1));
      v11 = sub_4011A0(*(_BYTE *)(a1 + v12 + 2));
      v13 = sub_4011A0(*(_BYTE *)(a1 + v12 + 3));
      *(_BYTE *)((unsigned __int16)v6 + a2) = (v10 >> 4) | (4 * v9);
      *(_BYTE *)((unsigned __int16)(v6 + 1) + a2) = (v11 >> 2) | (16 * v10);
      *(_BYTE *)((unsigned __int16)(v6 + 2) + a2) = v13 | (v11 << 6);
      v12 = (unsigned __int16)(v12 + 4);
      v6 += 3;
    }
    while ( v12 < a3 );
    v5 = a3 / 4;
    v4 = a1;
    v3 = a3;
  }
  if ( *(_BYTE *)(v3 + v4 - 1) != 61 )
    return (unsigned __int16)(3 * v5);
  if ( *(_BYTE *)(v3 + v4 - 2) == 61 )
    return (unsigned __int16)(3 * v5 - 2);
  else
    return (unsigned __int16)(3 * v5 - 1);
}

明显的base64解码特征,即为base64解码Serial并返回解码后字符串长度。由此可知,Serial是一个base64编码的字符串。

解码后,检查解码后长度是否小于8,小于8则报错。

长度大于等于8时,检查第9位后面是否全是数字,有不是数字的报错。

char __cdecl sub_408340(int a1, char *a2, unsigned int a3)
{
  char result; // al
  int v5; // edx
  unsigned int v6; // ecx
  unsigned int v7; // esi
  int v8[19]; // [esp+10h] [ebp-4Ch] BYREF

  result = a3;
  v5 = (*(_DWORD *)a1 >> 3) & 0x3F;
  v6 = *(_DWORD *)a1 + 8 * a3;
  if ( v6 < *(_DWORD *)a1 )
    ++*(_DWORD *)(a1 + 4);
  *(_DWORD *)a1 = v6;
  *(_DWORD *)(a1 + 4) += a3 >> 29;
  v7 = a3 - 1;
  if ( a3 )
  {
    do
    {
      result = *a2;
      *(_BYTE *)(v5 + a1 + 24) = *a2++;
      ++v5;
      --v7;
      if ( v5 == 64 )
      {
        v8[0] = *(unsigned __int8 *)(a1 + 24) | (*(unsigned __int8 *)(a1 + 25) << 8) | (*(unsigned __int8 *)(a1 + 26) << 16) | (*(unsigned __int8 *)(a1 + 27) << 24);
        v8[1] = *(unsigned __int8 *)(a1 + 28) | (*(unsigned __int8 *)(a1 + 29) << 8) | (*(unsigned __int8 *)(a1 + 30) << 16) | (*(unsigned __int8 *)(a1 + 31) << 24);
        v8[2] = *(unsigned __int8 *)(a1 + 32) | (*(unsigned __int8 *)(a1 + 33) << 8) | (*(unsigned __int8 *)(a1 + 34) << 16) | (*(unsigned __int8 *)(a1 + 35) << 24);
        v8[3] = *(unsigned __int8 *)(a1 + 36) | (*(unsigned __int8 *)(a1 + 37) << 8) | (*(unsigned __int8 *)(a1 + 38) << 16) | (*(unsigned __int8 *)(a1 + 39) << 24);
        v8[4] = *(unsigned __int8 *)(a1 + 40) | (*(unsigned __int8 *)(a1 + 41) << 8) | (*(unsigned __int8 *)(a1 + 42) << 16) | (*(unsigned __int8 *)(a1 + 43) << 24);
        v8[5] = *(unsigned __int8 *)(a1 + 44) | (*(unsigned __int8 *)(a1 + 45) << 8) | (*(unsigned __int8 *)(a1 + 46) << 16) | (*(unsigned __int8 *)(a1 + 47) << 24);
        v8[6] = *(unsigned __int8 *)(a1 + 48) | (*(unsigned __int8 *)(a1 + 49) << 8) | (*(unsigned __int8 *)(a1 + 50) << 16) | (*(unsigned __int8 *)(a1 + 51) << 24);
        v8[7] = *(unsigned __int8 *)(a1 + 52) | (*(unsigned __int8 *)(a1 + 53) << 8) | (*(unsigned __int8 *)(a1 + 54) << 16) | (*(unsigned __int8 *)(a1 + 55) << 24);
        v8[8] = *(unsigned __int8 *)(a1 + 56) | (*(unsigned __int8 *)(a1 + 57) << 8) | (*(unsigned __int8 *)(a1 + 58) << 16) | (*(unsigned __int8 *)(a1 + 59) << 24);
        v8[9] = *(unsigned __int8 *)(a1 + 60) | (*(unsigned __int8 *)(a1 + 61) << 8) | (*(unsigned __int8 *)(a1 + 62) << 16) | (*(unsigned __int8 *)(a1 + 63) << 24);
        v8[10] = *(unsigned __int8 *)(a1 + 64) | (*(unsigned __int8 *)(a1 + 65) << 8) | (*(unsigned __int8 *)(a1 + 66) << 16) | (*(unsigned __int8 *)(a1 + 67) << 24);
        v8[11] = *(unsigned __int8 *)(a1 + 68) | (*(unsigned __int8 *)(a1 + 69) << 8) | (*(unsigned __int8 *)(a1 + 70) << 16) | (*(unsigned __int8 *)(a1 + 71) << 24);
        v8[12] = *(unsigned __int8 *)(a1 + 72) | (*(unsigned __int8 *)(a1 + 73) << 8) | (*(unsigned __int8 *)(a1 + 74) << 16) | (*(unsigned __int8 *)(a1 + 75) << 24);
        v8[13] = *(unsigned __int8 *)(a1 + 76) | (*(unsigned __int8 *)(a1 + 77) << 8) | (*(unsigned __int8 *)(a1 + 78) << 16) | (*(unsigned __int8 *)(a1 + 79) << 24);
        v8[14] = *(unsigned __int8 *)(a1 + 80) | (*(unsigned __int8 *)(a1 + 81) << 8) | (*(unsigned __int8 *)(a1 + 82) << 16) | (*(unsigned __int8 *)(a1 + 83) << 24);
        v8[15] = *(unsigned __int8 *)(a1 + 84) | (*(unsigned __int8 *)(a1 + 85) << 8) | (*(unsigned __int8 *)(a1 + 86) << 16) | (*(unsigned __int8 *)(a1 + 87) << 24);
        result = sub_4088A0(a1 + 8, v8);
        v5 = 0;
      }
    }
    while ( v7 != -1 );
  }
  return result;
}
int __cdecl sub_4088A0(_DWORD *a1, _DWORD *a2)
{
  int v2; // edx
  int v3; // edi
  int v4; // esi
  int v5; // ebx
  int v6; // ebp
  int v7; // ecx
  int v8; // edx
  int v9; // ebx
  int v10; // ebp
  int v11; // esi
  int v12; // ecx
  int v13; // ebx
  int v14; // edx
  int v15; // edi
  int v16; // eax
  int v17; // ecx
  int v18; // ebp
  int v19; // edx
  int v20; // ebx
  int v21; // ecx
  int v22; // eax
  int v23; // edx
  int v24; // esi
  int v25; // edi
  int v26; // eax
  int v27; // ebx
  int v28; // ecx
  int v29; // edx
  int v30; // eax
  int v31; // ebx
  int v32; // ecx
  int v33; // esi
  int v34; // eax
  int v35; // edx
  int v36; // ebx
  int v37; // esi
  int v38; // eax
  int v39; // edx
  int v40; // ebp
  int v41; // esi
  int v42; // eax
  int v43; // edx
  int v44; // ebp
  int v45; // edi
  int v46; // esi
  int v47; // eax
  int v48; // ebp
  int v49; // edx
  int v50; // esi
  int v51; // eax
  int v52; // ebx
  int v53; // ecx
  int v54; // edx
  int v55; // eax
  int v56; // edi
  int v57; // esi
  int v58; // ebp
  int v59; // ebx
  int v60; // ecx
  int v61; // eax
  int v62; // edx
  int v63; // ebp
  int v64; // ecx
  int result; // eax
  int v66; // [esp+8h] [ebp-68h]
  int v67; // [esp+Ch] [ebp-64h]
  int v68; // [esp+10h] [ebp-60h]
  int v69; // [esp+14h] [ebp-5Ch]
  int v70; // [esp+18h] [ebp-58h]
  int v71; // [esp+20h] [ebp-50h]
  int v72; // [esp+24h] [ebp-4Ch]
  int v73; // [esp+28h] [ebp-48h]
  int v74; // [esp+2Ch] [ebp-44h]
  int v75; // [esp+30h] [ebp-40h]
  int v76; // [esp+34h] [ebp-3Ch]
  int v77; // [esp+38h] [ebp-38h]
  int v78; // [esp+3Ch] [ebp-34h]
  int v79; // [esp+40h] [ebp-30h]
  int v80; // [esp+44h] [ebp-2Ch]
  int v81; // [esp+48h] [ebp-28h]
  int v82; // [esp+4Ch] [ebp-24h]
  int v83; // [esp+50h] [ebp-20h]
  int v84; // [esp+58h] [ebp-18h]

  v82 = a1[1];
  v70 = a1[2];
  v66 = a1[3];
  v2 = v82 + __ROL4__(*a1 + *a2 + (v66 & ~v82 | v70 & v82) - 680876936, 7);
  v72 = a2[1];
  v3 = v2 + __ROL4__(v72 + (v70 & ~v2 | v2 & v82) + v66 - 389564586, 12);
  v67 = a2[2];
  v4 = v3 + __ROL4__(v70 + v67 + (v82 & ~v3 | v3 & v2) + 606105819, 17);
  v75 = a2[3];
  v5 = v4 + __ROL4__(v82 + v75 + (v2 & ~v4 | v3 & v4) - 1044525330, 22);
  v68 = a2[4];
  v6 = v5 + __ROL4__(v68 + v2 + (v3 & ~v5 | v4 & v5) - 176418897, 7);
  v76 = a2[5];
  v7 = v6 + __ROL4__(v76 + (v4 & ~v6 | v6 & v5) + v3 + 1200080426, 12);
  v69 = a2[6];
  v8 = v7 + __ROL4__(v69 + v4 + (v5 & ~v7 | v7 & v6) - 1473231341, 17);
  v79 = a2[7];
  v9 = v8 + __ROL4__(v79 + v5 + (v6 & ~v8 | v7 & v8) - 45705983, 22);
  v71 = a2[8];
  v10 = v9 + __ROL4__(v71 + v6 + (v7 & ~v9 | v8 & v9) + 1770035416, 7);
  v73 = a2[9];
  v11 = v10 + __ROL4__(v73 + (v8 & ~v10 | v10 & v9) + v7 - 1958414417, 12);
  v74 = a2[10];
  v12 = v11 + __ROL4__(v74 + v8 + (v9 & ~v11 | v11 & v10) - 42063, 17);
  v78 = a2[11];
  v13 = __ROL4__(v78 + v9 + (v10 & ~v12 | v11 & v12) - 1990404162, 22);
  v77 = a2[12];
  v84 = v12 + v13 + __ROL4__(v77 + v10 + (v11 & ~(v12 + v13) | v12 & (v12 + v13)) + 1804603682, 7);
  v80 = a2[13];
  v14 = v84 + __ROL4__(v80 + (v12 & ~v84 | v84 & (v12 + v13)) + v11 - 40341101, 12);
  v81 = a2[14];
  v15 = v14 + __ROL4__(v81 + v12 + (~v14 & (v12 + v13) | v14 & v84) - 1502002290, 17);
  v83 = a2[15];
  v16 = v15 + __ROL4__(v83 + v12 + v13 + (~v15 & v84 | v14 & v15) + 1236535329, 22);
  v17 = v16 + __ROL4__(v72 + v84 + (v15 & ~v14 | v14 & v16) - 165796510, 5);
  v18 = v17 + __ROL4__(v69 + (v16 & ~v15 | v17 & v15) + v14 - 1069501632, 9);
  v19 = v18 + __ROL4__(v78 + v15 + (v17 & ~v16 | v18 & v16) + 643717713, 14);
  v20 = v19 + __ROL4__(*a2 + v16 + (v18 & ~v17 | v17 & v19) - 373897302, 20);
  v21 = v20 + __ROL4__(v76 + v17 + (v19 & ~v18 | v18 & v20) - 701558691, 5);
  v22 = v21 + __ROL4__(v74 + (v20 & ~v19 | v21 & v19) + v18 + 38016083, 9);
  v23 = v22 + __ROL4__(v83 + v19 + (v21 & ~v20 | v22 & v20) - 660478335, 14);
  v24 = v23 + __ROL4__(v68 + v20 + (v22 & ~v21 | v21 & v23) - 405537848, 20);
  v25 = v24 + __ROL4__(v73 + v21 + (v23 & ~v22 | v22 & v24) + 568446438, 5);
  v26 = v25 + __ROL4__(v81 + (v24 & ~v23 | v25 & v23) + v22 - 1019803690, 9);
  v27 = v26 + __ROL4__(v75 + v23 + (v25 & ~v24 | v26 & v24) - 187363961, 14);
  v28 = v27 + __ROL4__(v71 + v24 + (v26 & ~v25 | v25 & v27) + 1163531501, 20);
  v29 = v28 + __ROL4__(v80 + v25 + (v27 & ~v26 | v26 & v28) - 1444681467, 5);
  v30 = v29 + __ROL4__(v67 + (v28 & ~v27 | v29 & v27) + v26 - 51403784, 9);
  v31 = v30 + __ROL4__(v79 + v27 + (v29 & ~v28 | v30 & v28) + 1735328473, 14);
  v32 = v31 + __ROL4__(v77 + v28 + (v30 & ~v29 | v29 & v31) - 1926607734, 20);
  v33 = v32 + __ROL4__(v76 + v29 + (v30 ^ v31 ^ v32) - 378558, 4);
  v34 = v33 + __ROL4__(v71 + (v31 ^ v32 ^ v33) + v30 - 2022574463, 11);
  v35 = v34 + __ROL4__(v78 + v31 + (v32 ^ v33 ^ v34) + 1839030562, 16);
  v36 = v35 + __ROL4__(v81 + v32 + (v33 ^ v34 ^ v35) - 35309556, 23);
  v37 = v36 + __ROL4__(v72 + v33 + (v34 ^ v35 ^ v36) - 1530992060, 4);
  v38 = v37 + __ROL4__(v68 + (v35 ^ v36 ^ v37) + v34 + 1272893353, 11);
  v39 = v38 + __ROL4__(v79 + v35 + (v36 ^ v37 ^ v38) - 155497632, 16);
  v40 = v39 + __ROL4__(v74 + v36 + (v37 ^ v38 ^ v39) - 1094730640, 23);
  v41 = v40 + __ROL4__(v80 + v37 + (v38 ^ v39 ^ v40) + 681279174, 4);
  v42 = v41 + __ROL4__(*a2 + (v39 ^ v40 ^ v41) + v38 - 358537222, 11);
  v43 = v42 + __ROL4__(v75 + v39 + (v40 ^ v41 ^ v42) - 722521979, 16);
  v44 = v43 + __ROL4__(v69 + v40 + (v41 ^ v42 ^ v43) + 76029189, 23);
  v45 = v44 + __ROL4__(v73 + v41 + (v42 ^ v43 ^ v44) - 640364487, 4);
  v46 = v45 + __ROL4__(v77 + (v43 ^ v44 ^ v45) + v42 - 421815835, 11);
  v47 = v46 + __ROL4__(v83 + v43 + (v44 ^ v45 ^ v46) + 530742520, 16);
  v48 = v47 + __ROL4__(v67 + v44 + (v45 ^ v46 ^ v47) - 995338651, 23);
  v49 = v48 + __ROL4__(*a2 + v45 + (v47 ^ (v48 | ~v46)) - 198630844, 6);
  v50 = v49 + __ROL4__((v48 ^ (v49 | ~v47)) + v79 + v46 + 1126891415, 10);
  v51 = v50 + __ROL4__(v81 + v47 + (v49 ^ (v50 | ~v48)) - 1416354905, 15);
  v52 = v51 + __ROL4__(v76 + v48 + (v50 ^ (v51 | ~v49)) - 57434055, 21);
  v53 = v52 + __ROL4__(v77 + v49 + (v51 ^ (v52 | ~v50)) + 1700485571, 6);
  v54 = v53 + __ROL4__((v52 ^ (v53 | ~v51)) + v75 + v50 - 1894986606, 10);
  v55 = v54 + __ROL4__(v74 + v51 + (v53 ^ (v54 | ~v52)) - 1051523, 15);
  v56 = v55 + __ROL4__(v72 + v52 + (v54 ^ (v55 | ~v53)) - 2054922799, 21);
  v57 = v56 + __ROL4__(v71 + v53 + (v55 ^ (v56 | ~v54)) + 1873313359, 6);
  v58 = v57 + __ROL4__((v56 ^ (v57 | ~v55)) + v83 + v54 - 30611744, 10);
  v59 = v58 + __ROL4__(v69 + v55 + (v57 ^ (v58 | ~v56)) - 1560198380, 15);
  v60 = v59 + __ROL4__(v80 + v56 + (v58 ^ (v59 | ~v57)) + 1309151649, 21);
  v61 = v60 + __ROL4__(v68 + v57 + (v59 ^ (v60 | ~v58)) - 145523070, 6);
  v62 = v61 + __ROL4__((v60 ^ (v61 | ~v59)) + v78 + v58 - 1120210379, 10);
  v63 = v62 + __ROL4__(v67 + v59 + (v61 ^ (v62 | ~v60)) + 718787259, 15);
  v64 = __ROL4__(v73 + v60 + (v62 ^ (v63 | ~v61)) - 343485551, 21);
  result = *a1 + v61;
  *a1 = result;
  a1[1] = v82 + v63 + v64;
  a1[2] = v70 + v63;
  a1[3] = v66 + v62;
  return result;
}

sub_4088A0就是未修改的MD5Transform,可以看出,sub_408340和 sub_4085F0计算了Name的MD5.

int __cdecl sub_408FF0(int a1, int a2, int a3)
{
  int v3; // edx
  int v4; // eax
  int v5; // ebx
  int v6; // edi
  int v7; // ebp
  __int64 v8; // rax
  int result; // eax
  int v10; // [esp+18h] [ebp-1Ch]
  int v11; // [esp+1Ch] [ebp-18h]
  int v12; // [esp+1Ch] [ebp-18h]
  int v13; // [esp+20h] [ebp-14h]

  v13 = 0;
  v3 = 1;
  v4 = 3;
  v11 = 0;
  v10 = 2;
  do
  {
    *(_BYTE *)(v11 + a3) = v13;
    *(_BYTE *)((__int16)v3 + a3) = v3;
    *(_BYTE *)((__int16)v10 + a3) = v10;
    *(_BYTE *)((__int16)v4 + a3) = v4;
    v3 += 4;
    v10 += 4;
    v4 += 4;
    v13 += 4;
    v11 = (__int16)v13;
  }
  while ( (__int16)v13 < 256 );
  *(_BYTE *)(a3 + 256) = 0;
  *(_BYTE *)(a3 + 257) = 0;
  v5 = 0;
  v6 = 0;
  v12 = 0;
  v7 = a3;
  do
  {
    v8 = v12 + *(unsigned __int8 *)(v5 + a1) + *(unsigned __int8 *)(v6 + a3);
    v12 = (unsigned __int8)((BYTE4(v8) ^ ((BYTE4(v8) ^ v8) - BYTE4(v8))) - BYTE4(v8));
    sub_4091C0(v7, a3 + v12);
    result = (unsigned int)(v5 + 1) / (__int64)a2;
    v5 = (unsigned __int8)((unsigned int)(v5 + 1) % (__int64)a2);
    ++v7;
    ++v6;
  }
  while ( v6 < 256 );
  return result;
}
int __cdecl sub_4090F0(int a1, int a2, int a3)
{
  int v3; // ebx
  int result; // eax
  __int64 v5; // rax
  __int64 v6; // rax
  int v7; // [esp+10h] [ebp-1Ch]
  int v8; // [esp+14h] [ebp-18h]
  int v9; // [esp+18h] [ebp-14h]

  LOBYTE(v3) = *(_BYTE *)(a3 + 256);
  result = *(unsigned __int8 *)(a3 + 257);
  if ( a2 > 0 )
  {
    v7 = 0;
    v8 = 0;
    v9 = *(unsigned __int8 *)(a3 + 257);
    do
    {
      v3 = (unsigned __int8)(v3 + 1);
      v5 = v9 + *(unsigned __int8 *)(a3 + v3);
      v9 = (unsigned __int8)((BYTE4(v5) ^ ((BYTE4(v5) ^ v5) - BYTE4(v5))) - BYTE4(v5));
      sub_4091C0(v3 + a3, a3 + v9);
      v6 = *(unsigned __int8 *)(v9 + a3) + *(unsigned __int8 *)(a3 + v3);
      *(_BYTE *)(v7 + a1) ^= *(_BYTE *)((unsigned __int8)((BYTE4(v6) ^ ((BYTE4(v6) ^ v6) - BYTE4(v6))) - BYTE4(v6)) + a3);
      v7 = (__int16)++v8;
    }
    while ( a2 > (__int16)v8 );
    result = v9;
  }
  *(_BYTE *)(a3 + 256) = v3;
  *(_BYTE *)(a3 + 257) = result;
  return result;
}

sub_408FF0、sub_4090F0符合明显的RC4加密特点,秘钥为V13。

之后判断MD5的前8个字节,与Serial解码后的前8个字节RC4加密后相同。

sub_4071D0为10进制字符串转大整数,sub_406ED0为16进制字符串转大整数。sub_405E40为大整数模运算。最后,sub_405E40运算结果与MD5的后8字节相等。标准的已知e,n,c求m模型。

到这里,逻辑分析完了,破解思路就是先计算Name的MD5,然后将前8个字节进行RC4解密,得到未编码的serial的前8字节,再根据已知e,n,c求出第9字节开始的数字,最后进行base64编码。

写exp如下

from Crypto.Util.number import *
from gmpy2 import *
from Crypto.Cipher import ARC4 as rc4cipher
import base64
import hashlib

def fermat_attack(n):
    a = isqrt(n)
    b2 = a*a - n
    b = isqrt(n)
    count = 0
    while b*b != b2:
        a = a + 1
        b2 = a*a - n
        b = math.isqrt(b2)
        count += 1
    p = a+b
    q = a-b
    assert n == p * q
    return p, q

md5 = hashlib.md5(b'KCTF').hexdigest()
#print(md5)

key = b')G\x07\x85\x873%D'
enc = rc4cipher.new(key)
res = enc.decrypt(bytes.fromhex(md5[:16]))
#print(res.hex())

n = 0xB80A90BF53C6C979
e = 65537
c = int(md5[16:32], 16)

p, q = fermat_attack(n)
phi = (p-1)*(q-1)
d = invert(e, phi)

m = pow(c, d, n)
#print(m)
fullvalue = res + str(m).encode()
flag = base64.b64encode(fullvalue).decode()
print(flag)


网站公告

今日签到

点亮在社区的每一天
去签到