首页
社区
课程
招聘
[原创]KCTF2022春季赛第三题:解题过程
发表于: 2022-5-16 00:19 7420

[原创]KCTF2022春季赛第三题:解题过程

2022-5-16 00:19
7420

1.初步流程分析

题目流程比较简洁,初步判断该exe定义了一个大的结构体进行操作,简单根据偏移量进行了结构体判断。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
struct context{
    int iterator1;   //0
    int unknow1;     //1
    unsigned int md5[5];       //2-6
    int unknow7;    //7
    int unknow8;    //8
    byte keys[16];  //9-12
    int unknow13;    //13
    int unknow14;    //14
    int unknow15;    //15
    int iterator2;   //16
    int unknow17;    //17
    unsigned int cipher[10];      //18-27
    int unknow28;    //28
    int unknow29;    //29
    char sn[4000];
    int a3;
    int a4;
};

重新对main进行解析,比较友好了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
int __cdecl main_0(int argc, const char **argv, const char **envp)
{
  void *v3; // esp
  int result; // eax
  char v7; // [esp-10h] [ebp-1048h]
  context ctx; // [esp+0h] [ebp-1038h] BYREF
  CPPEH_RECORD ms_exc; // [esp+1020h] [ebp-18h]
 
  v3 = alloca(4128);
  memset(&ctx, 0xCCu, sizeof(ctx));
 
  ms_exc.registration.ScopeTable = (ms_exc.registration.ScopeTable ^ __security_cookie);
 
  memset(ctx.sn, 0, sizeof(ctx.sn));
 
  ctx.cipher[0] = 0;
  ctx.cipher[1] = 0;
  ctx.cipher[2] = 0;
  ctx.cipher[3] = 0;
  ctx.cipher[4] = 0;
  ctx.cipher[5] = 0;
  ctx.cipher[6] = 0;
  ctx.cipher[7] = 0;
  ctx.cipher[8] = 0;
  ctx.cipher[9] = 0;
 
  gets_s(ctx.sn, 4000u);
 
  if ( strlen(ctx.sn) == 32 )
  {
    for ( ctx.iterator2 = 0; ctx.iterator2 < 512; ++ctx.iterator2 )
    {
      ctx.unknow15 = 0;
      MEMORY[0] = ctx.iterator2;
      ms_exc.registration.TryLevel = 0xFFFFFFFE;
    }
 
    strcpy(ctx.keys, "Enj0y_1t_4_fuuuN");       // 16bytes
    _DX = 0x5F00;
    *(&ctx.unknow13 + 1) = 0;
    HIBYTE(ctx.unknow13) = 0;
 
    ctx.md5[0] = 0;
    ctx.md5[1] = 0;
    ctx.md5[2] = 0;
    ctx.md5[3] = 0;
    ctx.md5[4] = 0;
 
    for ( ctx.iterator1 = 0; ctx.iterator1 < 512; ++ctx.iterator1 )
    {
      __asm { insb }
      ms_exc.registration.TryLevel = -2;
      _DX = LOWORD(ctx.iterator1) + 1;
    }
 
    j_MD5_402DB0(ctx.keys, 0x10u, ctx.md5);
 
    j_aes_402070(ctx.md5, 0x10u, ctx.sn, ctx.cipher, 32);
 
    if ( !memcmp(ctx.cipher, byte_40B200, 0x20u) )
      printf_401037("OK\n", v7);
    else
      printf_401037("NO\n", v7);
    result = 0;
  }
  else
  {
    printf_401037("NO\n", v7);
    result = 0;
  }
  return result;
}

存在较多的反调试。

 

流程较为清晰:
1、keys = MD5(Enj0y_1t_4_fuuuN)
2、AES(keys , 16bytes , plain , cipher , 32bytes) == byte_40B200[0:20]

 

直接进行解密计算发现是乱码,判断算法进行了改变。

2.算法分析

2.1 MD5分析

直接使用MD5(Enj0y_1t_4_fuuuN)结果。并未具体分析过程,因为是固定值。

2.2 AES分析

整个AES算法结构比较标准,在正常的128bit密钥流程中增加了对16字节输入输出的转置操作。

 

需要找一份类似的代码实现。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
int __cdecl aes_402070(void *Src, size_t KeySize, unsigned __int8 input[], unsigned __int8 uccipher[], int iLen)
{
  int j; // [esp+4h] [ebp-1C8h]
  unsigned int i; // [esp+8h] [ebp-1C4h]
  int state[6]; // [esp+10h] [ebp-1BCh] BYREF
  int key[11]; // [esp+28h] [ebp-1A4h] BYREF
  unsigned int *iKeyOffset; // [esp+54h] [ebp-178h]
  unsigned __int8 *__attribute__((__org_arrdim(0,0))) output; // [esp+58h] [ebp-174h]
  unsigned int KeyExtend[90]; // [esp+60h] [ebp-16Ch] BYREF
 
  output = uccipher;
  iKeyOffset = KeyExtend;
  key[6] = 0;
  key[7] = 0;
  key[8] = 0;
  key[9] = 0;
  key[0] = 0;
  key[1] = 0;
  key[2] = 0;
  key[3] = 0;
  state[0] = 0;
  state[1] = 0;
  state[2] = 0;
  state[3] = 0;
 
  if ( !Src || !input || !uccipher )
    return -1;
  if ( KeySize > 0x10 )
    return -1;
  if ( iLen % 0x10u )
    return -1;
 
  memcpy(key, Src, KeySize);
 
  KeyExtend_4010BE(key, 16, KeyExtend);
 
  for ( i = 0; i < iLen; i += 16 )
  {
    input_transpose_401145(state, input);
    AddRoundKey_401186(state, iKeyOffset);
 
    for ( j = 1; j < 10; ++j )
    {
      iKeyOffset += 4;
      ByteSub_401172(state);
      ShiftRow_40122B(state);
      MixColumn_40100F(state);
      AddRoundKey_401186(state, iKeyOffset);
    }
    ByteSub_401172(state);
    ShiftRow_40122B(state);
    AddRoundKey_401186(state, iKeyOffset + 4);
 
    output_transpose_40125D(state, output);
 
    output += 16;
    input += 16;
    iKeyOffset = KeyExtend;
  }
  return 0;
}

2.2.1 KeyExtend_4010BE

密钥扩展函数正常。

2.2.2 ByteSub_401172


[招生]科锐逆向工程师培训(2025年3月11日实地,远程教学同时开班, 第52期)!

最后于 2022-5-16 20:49 被kanxue编辑 ,原因:
收藏
免费 3
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回