首页
社区
课程
招聘
[原创]KCTF Q3 第十三题:大圣归来
发表于: 2019-9-24 04:59 4055

[原创]KCTF Q3 第十三题:大圣归来

2019-9-24 04:59
4055
用OD在MessageBoxA下断,跟到校验代码。IDA F5一下。
int __cdecl sub_407F30(HWND hDlg)
{
  CHAR *v1; // edi
  signed int v2; // esi
  signed int v3; // eax
  const CHAR *v4; // eax
  const char *v5; // eax
  CHAR *v6; // ecx
  char v7; // al
  const CHAR *v8; // eax
  _BYTE *v9; // ecx
  char v10; // al
  char v11; // al
  _BYTE *v12; // ecx
  char v13; // al
  CHAR *v14; // ecx
  char pe; // [esp-40h] [ebp-3D8h]
  char *v17; // [esp-3Ch] [ebp-3D4h]
  int v18; // [esp-38h] [ebp-3D0h]
  int v19; // [esp-34h] [ebp-3CCh]
  char un; // [esp-30h] [ebp-3C8h]
  char *v21; // [esp-2Ch] [ebp-3C4h]
  int v22; // [esp-28h] [ebp-3C0h]
  int v23; // [esp-24h] [ebp-3BCh]
  int kx; // [esp-20h] [ebp-3B8h]
  char *v25; // [esp-1Ch] [ebp-3B4h]
  int v26; // [esp-18h] [ebp-3B0h]
  int v27; // [esp-14h] [ebp-3ACh]
  char *input; // [esp-10h] [ebp-3A8h]
  char *v29; // [esp-Ch] [ebp-3A4h]
  const CHAR *v30; // [esp-8h] [ebp-3A0h]
  void (__thiscall *v31)(void *); // [esp-4h] [ebp-39Ch]
  char v32; // [esp+13h] [ebp-385h]
  char v33; // [esp+14h] [ebp-384h]
  LPCSTR v34; // [esp+18h] [ebp-380h]
  int v35; // [esp+1Ch] [ebp-37Ch]
  int v36; // [esp+20h] [ebp-378h]
  char v37; // [esp+24h] [ebp-374h]
  int v38; // [esp+28h] [ebp-370h]
  unsigned int v39; // [esp+2Ch] [ebp-36Ch]
  int v40; // [esp+30h] [ebp-368h]
  char v41; // [esp+34h] [ebp-364h]
  int v42; // [esp+38h] [ebp-360h]
  int v43; // [esp+3Ch] [ebp-35Ch]
  int v44; // [esp+40h] [ebp-358h]
  char v45; // [esp+44h] [ebp-354h]
  const char *v46; // [esp+48h] [ebp-350h]
  unsigned int v47; // [esp+4Ch] [ebp-34Ch]
  char v48; // [esp+54h] [ebp-344h]
  LPCSTR lpText; // [esp+58h] [ebp-340h]
  int nIDDlgItem; // [esp+64h] [ebp-334h]
  int v51; // [esp+68h] [ebp-330h]
  int v52; // [esp+6Ch] [ebp-32Ch]
  char *v53; // [esp+70h] [ebp-328h]
  char *v54; // [esp+74h] [ebp-324h]
  int *v55; // [esp+78h] [ebp-320h]
  char **v56; // [esp+7Ch] [ebp-31Ch]
  int v57[3]; // [esp+80h] [ebp-318h]
  CHAR String; // [esp+8Ch] [ebp-30Ch]
  char v59; // [esp+8Dh] [ebp-30Bh]
  char v60; // [esp+18Ch] [ebp-20Ch]
  char v61; // [esp+28Ch] [ebp-10Ch]
  __int16 v62; // [esp+389h] [ebp-Fh]
  char v63; // [esp+38Bh] [ebp-Dh]
  int v64; // [esp+394h] [ebp-4h]

  String = 0;
  memset(&v59, 0, 0x2FCu);
  v62 = 0;
  v63 = 0;
  nIDDlgItem = 1005;
  v51 = 1000;
  v52 = 1001;
  v1 = &String;
  v2 = 0;
  while ( 1 )
  {
    v3 = GetDlgItemTextA(hDlg, *(int *)((char *)&nIDDlgItem + v2 * 4), v1, 255);
    v57[v2] = v3;
    if ( v3 < 1 || v3 > 100 )
      return 0;
    ++v2;
    v1 += 256;
    if ( v2 >= 3 )
    {
      `eh vector constructor iterator'(&v45, 0x10u, 2, sub_408360, sub_40B410);
      v64 = 0;
      v33 = v32;
      newstring(&v33, 0);
      strcpy(&v33, &String, strlen(&String));
      v37 = v32;
      LOBYTE(v64) = 1;
      newstring(&v37, 0);
      strcpy(&v37, &v60, strlen(&v60));
      LOBYTE(v64) = 2;
      v41 = v32;
      newstring(&v41, 0);
      strcpy(&v41, aKxctf19q3, strlen(aKxctf19q3));
      LOBYTE(v64) = 3;
      if ( !check1(&v61, (int)&v45, (int)&v48) )// 以KXCTFXXXX分割字符串并判断长度,第一部分长度需大于等于4,第二部分长度需大于等于8
      {
        v4 = lpText;
        if ( !lpText )
          v4 = (const CHAR *)&unk_419144;
        v31 = 0;
        v30 = aBadCode;
        goto LABEL_15;
      }
      v5 = v46;
      if ( !v46 )
        v5 = (const char *)&unk_419144;
      if ( !strcmp(&v37, 0, v39, v5, v47) )     // 前8位是否为username
      {
        v56 = &input;
        LOBYTE(input) = v48;
        newstring(&input, 0);
        substr_0(&input, &v48, 0, 0xFFFFFFFF);
        v55 = &kx;
        LOBYTE(v64) = 4;
        strmove(&kx, &v41);                     // KXCTF19Q3
        v53 = &un;
        LOBYTE(v64) = 5;
        strmove(&un, &v37);                     // username
        v54 = &pe;
        LOBYTE(v64) = 6;
        strmove(&pe, &v33);                     // PEDIY_CTF2019_Q3_完璧归赵_Crackme_Readyu_
        LOBYTE(v64) = 3;
        if ( !check2((int)hDlg, pe, v17, v18, v19, un, v21, v22, v23, kx, v25, v26, v27, (char)input, v29, (int)v30) )
        {
          v8 = v34;
          if ( !v34 )
            v8 = (const CHAR *)&unk_419144;
          MessageBoxA(hDlg, v8, aBadCheck, 0);
          if ( v42 )
          {
            v9 = (_BYTE *)(v42 - 1);
            v10 = *(_BYTE *)(v42 - 1);
            if ( v10 && v10 != -1 )
              *v9 = v10 - 1;
            else
              sub_40DF24(v9);
          }
          v42 = 0;
          v43 = 0;
          v44 = 0;
          if ( v38 )
          {
            v11 = *(_BYTE *)(v38 - 1);
            v12 = (_BYTE *)(v38 - 1);
            if ( v11 && v11 != -1 )
              *v12 = v11 - 1;
            else
              sub_40DF24(v12);
          }
          v38 = 0;
          v39 = 0;
          v40 = 0;
          if ( v34 )
          {
            v13 = *(v34 - 1);
            v14 = (CHAR *)(v34 - 1);
            if ( v13 && v13 != -1 )
              *v14 = v13 - 1;
            else
              sub_40DF24(v14);
          }
          v34 = 0;
          v35 = 0;
          v36 = 0;
          v64 = -1;
          goto LABEL_41;
        }
        success(hDlg);
        LOBYTE(v64) = 2;
        newstring(&v41, 1);
        LOBYTE(v64) = 1;
        newstring(&v37, 1);
        if ( v34 )
        {
          v6 = (CHAR *)(v34 - 1);
          v7 = *(v34 - 1);
          if ( v7 && v7 != -1 )
            *v6 = v7 - 1;
          else
            sub_40DF24(v6);
        }
        v31 = sub_40B410;
        v30 = (const CHAR *)2;
        v29 = (char *)16;
        v34 = 0;
        v35 = 0;
        v36 = 0;
        v64 = -1;
        input = &v45;
      }
      else
      {
        v4 = v46;
        if ( !v46 )
          v4 = (const CHAR *)&unk_419144;
        v31 = 0;
        v30 = aBadName;
LABEL_15:
        MessageBoxA(hDlg, v4, v30, (UINT)v31);
        LOBYTE(v64) = 2;
        newstring(&v41, 1);
        LOBYTE(v64) = 1;
        newstring(&v37, 1);
        LOBYTE(v64) = 0;
        newstring(&v33, 1);
        v64 = -1;
LABEL_41:
        v31 = sub_40B410;
        v30 = (const CHAR *)2;
        v29 = (char *)16;
        input = &v45;
      }
      `eh vector destructor iterator'(input, (unsigned int)v29, (int)v30, v31);
      return 0;
    }
  }
}

int __cdecl sub_407F30(HWND hDlg)
{
  CHAR *v1; // edi
  signed int v2; // esi
  signed int v3; // eax
  const CHAR *v4; // eax
  const char *v5; // eax
  CHAR *v6; // ecx
  char v7; // al
  const CHAR *v8; // eax
  _BYTE *v9; // ecx
  char v10; // al
  char v11; // al
  _BYTE *v12; // ecx
  char v13; // al
  CHAR *v14; // ecx
  char pe; // [esp-40h] [ebp-3D8h]
  char *v17; // [esp-3Ch] [ebp-3D4h]
  int v18; // [esp-38h] [ebp-3D0h]
  int v19; // [esp-34h] [ebp-3CCh]
  char un; // [esp-30h] [ebp-3C8h]
  char *v21; // [esp-2Ch] [ebp-3C4h]
  int v22; // [esp-28h] [ebp-3C0h]
  int v23; // [esp-24h] [ebp-3BCh]
  int kx; // [esp-20h] [ebp-3B8h]
  char *v25; // [esp-1Ch] [ebp-3B4h]
  int v26; // [esp-18h] [ebp-3B0h]
  int v27; // [esp-14h] [ebp-3ACh]
  char *input; // [esp-10h] [ebp-3A8h]
  char *v29; // [esp-Ch] [ebp-3A4h]
  const CHAR *v30; // [esp-8h] [ebp-3A0h]
  void (__thiscall *v31)(void *); // [esp-4h] [ebp-39Ch]
  char v32; // [esp+13h] [ebp-385h]
  char v33; // [esp+14h] [ebp-384h]
  LPCSTR v34; // [esp+18h] [ebp-380h]
  int v35; // [esp+1Ch] [ebp-37Ch]
  int v36; // [esp+20h] [ebp-378h]
  char v37; // [esp+24h] [ebp-374h]
  int v38; // [esp+28h] [ebp-370h]
  unsigned int v39; // [esp+2Ch] [ebp-36Ch]
  int v40; // [esp+30h] [ebp-368h]
  char v41; // [esp+34h] [ebp-364h]
  int v42; // [esp+38h] [ebp-360h]
  int v43; // [esp+3Ch] [ebp-35Ch]
  int v44; // [esp+40h] [ebp-358h]
  char v45; // [esp+44h] [ebp-354h]
  const char *v46; // [esp+48h] [ebp-350h]
  unsigned int v47; // [esp+4Ch] [ebp-34Ch]
  char v48; // [esp+54h] [ebp-344h]
  LPCSTR lpText; // [esp+58h] [ebp-340h]
  int nIDDlgItem; // [esp+64h] [ebp-334h]
  int v51; // [esp+68h] [ebp-330h]
  int v52; // [esp+6Ch] [ebp-32Ch]
  char *v53; // [esp+70h] [ebp-328h]
  char *v54; // [esp+74h] [ebp-324h]
  int *v55; // [esp+78h] [ebp-320h]
  char **v56; // [esp+7Ch] [ebp-31Ch]
  int v57[3]; // [esp+80h] [ebp-318h]
  CHAR String; // [esp+8Ch] [ebp-30Ch]
  char v59; // [esp+8Dh] [ebp-30Bh]
  char v60; // [esp+18Ch] [ebp-20Ch]
  char v61; // [esp+28Ch] [ebp-10Ch]
  __int16 v62; // [esp+389h] [ebp-Fh]
  char v63; // [esp+38Bh] [ebp-Dh]
  int v64; // [esp+394h] [ebp-4h]

  String = 0;
  memset(&v59, 0, 0x2FCu);
  v62 = 0;
  v63 = 0;
  nIDDlgItem = 1005;
  v51 = 1000;
  v52 = 1001;
  v1 = &String;
  v2 = 0;
  while ( 1 )
  {
    v3 = GetDlgItemTextA(hDlg, *(int *)((char *)&nIDDlgItem + v2 * 4), v1, 255);
    v57[v2] = v3;
    if ( v3 < 1 || v3 > 100 )
      return 0;
    ++v2;
    v1 += 256;
    if ( v2 >= 3 )
    {
      `eh vector constructor iterator'(&v45, 0x10u, 2, sub_408360, sub_40B410);
      v64 = 0;
      v33 = v32;
      newstring(&v33, 0);
      strcpy(&v33, &String, strlen(&String));
      v37 = v32;
      LOBYTE(v64) = 1;
      newstring(&v37, 0);
      strcpy(&v37, &v60, strlen(&v60));
      LOBYTE(v64) = 2;
      v41 = v32;
      newstring(&v41, 0);
      strcpy(&v41, aKxctf19q3, strlen(aKxctf19q3));
      LOBYTE(v64) = 3;
      if ( !check1(&v61, (int)&v45, (int)&v48) )// 以KXCTFXXXX分割字符串并判断长度,第一部分长度需大于等于4,第二部分长度需大于等于8
      {
        v4 = lpText;
        if ( !lpText )
          v4 = (const CHAR *)&unk_419144;
        v31 = 0;
        v30 = aBadCode;
        goto LABEL_15;
      }
      v5 = v46;
      if ( !v46 )
        v5 = (const char *)&unk_419144;
      if ( !strcmp(&v37, 0, v39, v5, v47) )     // 前8位是否为username
      {
        v56 = &input;
        LOBYTE(input) = v48;
        newstring(&input, 0);
        substr_0(&input, &v48, 0, 0xFFFFFFFF);
        v55 = &kx;
        LOBYTE(v64) = 4;
        strmove(&kx, &v41);                     // KXCTF19Q3
        v53 = &un;
        LOBYTE(v64) = 5;
        strmove(&un, &v37);                     // username
        v54 = &pe;
        LOBYTE(v64) = 6;
        strmove(&pe, &v33);                     // PEDIY_CTF2019_Q3_完璧归赵_Crackme_Readyu_
        LOBYTE(v64) = 3;
        if ( !check2((int)hDlg, pe, v17, v18, v19, un, v21, v22, v23, kx, v25, v26, v27, (char)input, v29, (int)v30) )
        {
          v8 = v34;
          if ( !v34 )
            v8 = (const CHAR *)&unk_419144;
          MessageBoxA(hDlg, v8, aBadCheck, 0);
          if ( v42 )
          {
            v9 = (_BYTE *)(v42 - 1);
            v10 = *(_BYTE *)(v42 - 1);
            if ( v10 && v10 != -1 )
              *v9 = v10 - 1;
            else
              sub_40DF24(v9);
          }
          v42 = 0;
          v43 = 0;
          v44 = 0;
          if ( v38 )
          {
            v11 = *(_BYTE *)(v38 - 1);
            v12 = (_BYTE *)(v38 - 1);
            if ( v11 && v11 != -1 )
              *v12 = v11 - 1;
            else
              sub_40DF24(v12);
          }
          v38 = 0;
          v39 = 0;
          v40 = 0;
          if ( v34 )
          {
            v13 = *(v34 - 1);
            v14 = (CHAR *)(v34 - 1);
            if ( v13 && v13 != -1 )
              *v14 = v13 - 1;
            else
              sub_40DF24(v14);
          }
          v34 = 0;
          v35 = 0;
          v36 = 0;
          v64 = -1;
          goto LABEL_41;
        }
        success(hDlg);
        LOBYTE(v64) = 2;
        newstring(&v41, 1);
        LOBYTE(v64) = 1;
        newstring(&v37, 1);
        if ( v34 )
        {
          v6 = (CHAR *)(v34 - 1);
          v7 = *(v34 - 1);
          if ( v7 && v7 != -1 )
            *v6 = v7 - 1;
          else
            sub_40DF24(v6);
        }
        v31 = sub_40B410;
        v30 = (const CHAR *)2;
        v29 = (char *)16;
        v34 = 0;
        v35 = 0;
        v36 = 0;
        v64 = -1;
        input = &v45;
      }
      else
      {
        v4 = v46;
        if ( !v46 )
          v4 = (const CHAR *)&unk_419144;
        v31 = 0;
        v30 = aBadName;
LABEL_15:
        MessageBoxA(hDlg, v4, v30, (UINT)v31);
        LOBYTE(v64) = 2;
        newstring(&v41, 1);
        LOBYTE(v64) = 1;
        newstring(&v37, 1);
        LOBYTE(v64) = 0;
        newstring(&v33, 1);
        v64 = -1;
LABEL_41:
        v31 = sub_40B410;
        v30 = (const CHAR *)2;
        v29 = (char *)16;
        input = &v45;
      }
      `eh vector destructor iterator'(input, (unsigned int)v29, (int)v30, v31);
      return 0;
    }
  }
}

主要是计算一些字符串的hash作为大数,用LUC算法解密两次被KXCTFXXXX分割的第二部分input转成的大数,比较结果是否为0xC4B73CB0DD1D750C69E1755B06BBAFFFF44D2600
总结一下就是
    N=0x3FBDAD083DBC11A52FA2AF1A0829C522C1492907F1B9523A17B7A8E65679BB01
    message=0x9071232E6B170092668255303E5D824F2879AD56+inputnum
    message2=LUCdecrypt(message,0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4B5843544631395133,N)
    message2+=0x249BA36000029BBE97499C03DB5A9001F6B734EC
    (LUCdecrypt(message2,N,N)+0x6DC844C73B34D6E6B8DE48DA64EF92AB2B11F461) % N==0xC4B73CB0DD1D750C69E1755B06BBAFFFF44D2600
    //(LUCdecrypt(message2,N,N)% N==0x56EEF7E9A1E89E25B1032C80A1CC1D54C93B319F

    N=0x3FBDAD083DBC11A52FA2AF1A0829C522C1492907F1B9523A17B7A8E65679BB01
    message=0x9071232E6B170092668255303E5D824F2879AD56+inputnum
    message2=LUCdecrypt(message,0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4B5843544631395133,N)
    message2+=0x249BA36000029BBE97499C03DB5A9001F6B734EC
    (LUCdecrypt(message2,N,N)+0x6DC844C73B34D6E6B8DE48DA64EF92AB2B11F461) % N==0xC4B73CB0DD1D750C69E1755B06BBAFFFF44D2600
    //(LUCdecrypt(message2,N,N)% N==0x56EEF7E9A1E89E25B1032C80A1CC1D54C93B319F

怎么得到0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4B5843544631395133的?
LUC(
                    v206,                       // input+...
                    v207,
                    big_Nadd1,
                    v209,
                    big_Index,                      // 第一轮为:hash+KXCTF19Q3
                                                // 第二轮为:~hash
                    v211,
                    big_Ncp,
                    v213,
                    (int *)v214, //U
                    (int *)v215, //V
                    (int *)v216);

LUC(
                    v206,                       // input+...
                    v207,
                    big_Nadd1,
                    v209,
                    big_Index,                      // 第一轮为:hash+KXCTF19Q3
                                                // 第二轮为:~hash
                    v211,
                    big_Ncp,
                    v213,
                    (int *)v214, //U
                    (int *)v215, //V
                    (int *)v216);

第一次解密,CM是将其分成两步来算的,第一步取得Lucas序列第 hash+KXCTF19Q3项的值,第二轮取第~hash项的值。
之后将第二轮的U,V值做72次快速递推,换算到项数上就是 ~hash * 2 ^ 0x72 = ~hash * 0x1000000000000000000。
然后再进行一次递推
                v169 = big_mul((int)&v263, (int *)v234, (int *)&v235);
                LOBYTE(v362) = 122;
                v170 = (int *)big_mul((int)&v258, (int *)&v243, (int *)v239);// v243=(input+...)^2-4
                LOBYTE(v362) = 123;
                v171 = big_mul((int)&v256, v170, (int *)&v240);
                LOBYTE(v362) = 124;
                v172 = (int *)big_add((int)&v246, v171, v169);
                LOBYTE(v362) = 125;
                v173 = (int *)big_mod((int)&v237, v172, big_hash64);
                LOBYTE(v362) = 126;
                big_cpy((int *)&v251, v173);
                LOBYTE(v362) = 125;
                free(&v237);
                LOBYTE(v362) = 124;
                free(&v246);
                LOBYTE(v362) = 123;
                free(&v256);
                LOBYTE(v362) = 122;
                free(&v258);
                LOBYTE(v362) = 18;
                free(&v263);
                big_num = (char *)&v215;
                strmove_0((int *)&v215, big_hash64);
                big_shr1((int *)&v251);
                v174 = (int *)big_add((int)&v237, (int)&v251, (int)&v271);// username

                v169 = big_mul((int)&v263, (int *)v234, (int *)&v235);
                LOBYTE(v362) = 122;
                v170 = (int *)big_mul((int)&v258, (int *)&v243, (int *)v239);// v243=(input+...)^2-4
                LOBYTE(v362) = 123;
                v171 = big_mul((int)&v256, v170, (int *)&v240);
                LOBYTE(v362) = 124;
                v172 = (int *)big_add((int)&v246, v171, v169);
                LOBYTE(v362) = 125;
                v173 = (int *)big_mod((int)&v237, v172, big_hash64);
                LOBYTE(v362) = 126;
                big_cpy((int *)&v251, v173);
                LOBYTE(v362) = 125;
                free(&v237);
                LOBYTE(v362) = 124;
                free(&v246);
                LOBYTE(v362) = 123;
                free(&v256);
                LOBYTE(v362) = 122;
                free(&v258);
                LOBYTE(v362) = 18;
                free(&v263);
                big_num = (char *)&v215;
                strmove_0((int *)&v215, big_hash64);
                big_shr1((int *)&v251);
                v174 = (int *)big_add((int)&v237, (int)&v251, (int)&v271);// username

精简一下
message2=((v243*v239*v240+v234*235 mod 0x3FBDAD083DBC11A52FA2AF1A0829C522C1492907F1B9523A17B7A8E65679BB01
)>>1)+ 0x249BA36000029BBE97499C03DB5A9001F6B734EC //username
message2=((v243*v239*v240+v234*235 mod 0x3FBDAD083DBC11A52FA2AF1A0829C522C1492907F1B9523A17B7A8E65679BB01
)>>1)+ 0x249BA36000029BBE97499C03DB5A9001F6B734EC //username
再加上一条性质


将第二轮的项数和第一轮的项数相加(hash是20字节的),就得到 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4B5843544631395133了。
之后,用LUC算法把0x56EEF7E9A1E89E25B1032C80A1CC1D54C93B319F 加密回去就行,具体步骤如下:
1.分解N(N=0x3FBDAD083DBC11A52FA2AF1A0829C522C1492907F1B9523A17B7A8E65679BB01)

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

最后于 2019-9-25 19:51 被梦游枪手编辑 ,原因:
收藏
免费 1
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回
//