본문 바로가기

CTFs/CodeGate PreQual 2014

[Codegate 2014] reversing : Clone Technique

Clone Technique

This chal is win32 binary, not packed.


and it makes and kills 400 child processes.. how amazing...

 

Analyzing

To decrypt the encrypted msg, we need to make decrypt algorithm.

and below functions are the algorithms needed to decrypt

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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
int main(){
 v1 = 29 * Val1 + 7 * sub_401280(Val, 2u);
 v6 = sub_401280(v1 ^ Val2, v1 % 2 + 5);
 
 if ((unsigned int)Val1 <= 0xD0000000) {
  Val1 = v1;
  Val2 = v6;
 
  do{
   if ((unsigned int)Val3 > 0x190)
    return 0;
 
   ++Val3;
   ...
   v1 = ExitCode;
   v6 = sub_401280(ExitCode ^ v6, ExitCode % 0x1E);
 
 
  } while (ExitCode);
  result = 0;
 }
 else {  result = 13 * v1 / 0x1B ^ 0x1F2A990D; }
 return result;
}
 
BOOL sub_401160() {   
      const char *v0;
      unsigned int a, b;
      LPSTR *v5;
      int pNumArgs;
 
      v0 = GetCommandLine();
      v5 = CommandLineToArgv(v0, &pNumArgs);
      if ( pNumArgs == 4 )   {
        a = atoi(v5[1]);
        b = atoi(v5[2]);
        dword_409758 = atoi(v5[3]);
      }
      else  {
        a = 0xA8276BFA;
        b = 0x92F837ED;
        dword_409758 = 1;
      }
      memset(decode("ENCRYPTED STRING", a, b), 0, 28u);
 
      a ^= 0xB72AF098;
      b ^= b * a;
}
 
signed int sub_401280(int a1, unsigned int a2){
  unsigned int i;
  signed int v4;
 
  v4 = 1;
  for ( i = 0; i < a2; ++i )
    v4 *= a1;
  return v4;
}
 
void *sub_401070(const char *a1, int a2, int a3){
  unsigned int i;
  int v4;
  unsigned int v5;
  int j;
  void *v8;
 
  v5 = strlen(a1);
  v8 = malloc(v5);
  memset(v8, 04 * (v5 >> 2));
  for ( i = strlen(a1) & 3; i; --i )
    *(_BYTE *)v4++ = 0;
  for ( j = 0; j < (signed int)(v5 - 1); j += 2 ) {
    *((_BYTE *)v8 + j) = a2 ^ a1[j];
    a2 = sub_401050(a2) ^ 0x2F;
    if ( !a1[j + 1] )
      break;
    *((_BYTE *)v8 + j + 1= a3 ^ a1[j + 1];
    a3 = (unsigned __int8)a2 ^ sub_401060(a3);
  }
  return v8;
}
 
int  sub_401050(int a1){
  return __ROL__(a1, 5);
}
 
DWORD Rol(DWORD value, int cnt){
  int n = cnt % 32;
  DWORD result = value;
  if (value == 0) { return 0; }
  for (int i = 0; i < cnt; i++){
   DWORD msb = result >> 31;
   result = (result << 1| msb;
  }
 return result;
}
cs

Decrypting Code

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
unsigned char keytable [] = { 0x0F0x8E0x9E0x390x3D0x5E0x3F0xA80x7A0x680x0C0x3D0x8B0xAD0xC50xD00x7B0x090x340xB60xA30xA00x3E0x670x5D0xD6 };
 
DWORD Rol(DWORD value, int cnt){
    int n = cnt % 32;
    DWORD result = value;
 
    if (value == 0return 0;
    for (int i = 0; i &lt; cnt; i++){
        DWORD msb = result &gt;&gt; 31;
        result = (result &lt;&lt; 1| msb;
    }
    return result;
}
 
DWORD Decrypt_2(DWORD value, int cnt){
    DWORD result = 1;
    for (int i = 0; i &lt; cnt; i++)
        result *= value;
    return result;
}
 
void Decrypt_1(DWORD aa, DWORD ab){
    char buf[30= " ";
    DWORD a = aa, b = ab;
 
    for (int i = 0; i &lt; sizeof(keytable); i += 2){
        buf[i] = (char)(keytable[i] ^ a);
        a = Rol(a, 5) ^ 0x2F;
 
        buf[i + 1= (char)(keytable[i + 1] ^ b);
        b = Rol(b, 11) ^ (BYTE) a;
        if ((buf[i + 1&lt; 0x20 || buf[i + 1&gt; 0x7E&amp;&amp; buf[i + 1!= '\r' &amp;&amp; buf[i + 1!= '\n' &amp;&amp; buf[i + 1!= '\t'return;
    }
    printf("The Flag is %s\n", buf);
}
 
int gen(DWORD a0, DWORD a1, DWORD a2){
    DWORD a = a0 ^ 0xB72AF098, ret;
    DWORD b = (a * a1) ^ a1, c = a2;
    DWORD d = 29 * a + 7 * Decrypt_2(a, 2);
    DWORD e = Decrypt_2(d ^ b, d % 2 + 5);
    Decrypt_1(a0, a1);
 
    if (a &gt; 0xD0000000return (13 * (d / 0x1B) ^ 0x1F2A990D);
    for (; c &lt;= 0x190; c++){
        ret = gen(d, e, c);
        d = ret;
        e = Decrypt_2(d ^ e, d % 30);
    }
    return 0;
}
 
void main(int argc, char *argv []){
    gen(0xA8276BFA0x92F837ED1);
    getchar();
    return;
}
cs

The Answer


The Flag is And Now His Watch is Ended