본문 바로가기

CTF

[angstromctf 2017] Product Key

[angstromctf 2017] Product Key - Re 200pt

문제 내용을 보면 

이름이 Artemis Tosini 일때와 이메일이 artemis.tosini@example.com 일때의 key를 구하라고 한다.


[source]

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
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
int __cdecl main(int argc, const char **argv, const char **envp)
{
  int result; // eax
  char name[48]; // [rsp+10h] [rbp-90h]
  char email[48]; // [rsp+40h] [rbp-60h]
  char key[40]; // [rsp+70h] [rbp-30h]
  unsigned __int64 v7; // [rsp+98h] [rbp-8h]
  v7 = __readfsqword(0x28u);
  printf("Name: ", argv, envp, argv);
  fflush(_bss_start);
  fgets(name, 33, stdin);
  name[strcspn(name, "\n")] = 0;
  printf("Email: ""\n");
  fflush(_bss_start);
  fgets(email, 33, stdin);
  email[strcspn(email, "\n")] = 0;
  printf("Product key: ""\n");
  fflush(_bss_start);
  fgets(key, 33, stdin);
  key[strcspn(key, "\n")] = 0;
  if ( (unsigned __int8)verify_key((__int64)name, (__int64)email, key) )
  {
    puts("Windows has been activated");
    result = 0;
  }
  else
  {
    puts("Invalid product key");
    result = -1;
  }
  return result;
}
 
__int64 __fastcall verify_key(__int64 name, __int64 email, char *key)
{
  int v3; // ebx
  int v5; // ST58_4
  int v6; // ebx
  int v7; // ebx
  unsigned __int8 v8; // [rsp+27h] [rbp-C9h]
  int v9; // [rsp+28h] [rbp-C8h]
  int v10; // [rsp+2Ch] [rbp-C4h]
  signed int i; // [rsp+30h] [rbp-C0h]
  int j; // [rsp+34h] [rbp-BCh]
  signed int k; // [rsp+38h] [rbp-B8h]
  signed int l; // [rsp+3Ch] [rbp-B4h]
  signed int m; // [rsp+40h] [rbp-B0h]
  signed int n; // [rsp+44h] [rbp-ACh]
  signed int ii; // [rsp+48h] [rbp-A8h]
  signed int jj; // [rsp+4Ch] [rbp-A4h]
  signed int v19; // [rsp+50h] [rbp-A0h]
  const char *nptr; // [rsp+60h] [rbp-90h]
  char *v21; // [rsp+68h] [rbp-88h]
  __int64 emil; // [rsp+70h] [rbp-80h]
  __int64 name1; // [rsp+78h] [rbp-78h]
  int key_array[8]; // [rsp+80h] [rbp-70h]
  int v25; // [rsp+A0h] [rbp-50h]
  int v26; // [rsp+A4h] [rbp-4Ch]
  int v27; // [rsp+A8h] [rbp-48h]
  int v28; // [rsp+ACh] [rbp-44h]
  int v29; // [rsp+B0h] [rbp-40h]
  int v30; // [rsp+B4h] [rbp-3Ch]
  int v31; // [rsp+C0h] [rbp-30h]
  int v32; // [rsp+C4h] [rbp-2Ch]
  int v33; // [rsp+C8h] [rbp-28h]
  int v34; // [rsp+CCh] [rbp-24h]
  int v35; // [rsp+D0h] [rbp-20h]
  int v36; // [rsp+D4h] [rbp-1Ch]
  unsigned __int64 v37; // [rsp+D8h] [rbp-18h]
 
  v37 = __readfsqword(0x28u);
  v9 = 0;
  for ( nptr = strtok(key, "-"); nptr; nptr = strtok(0LL, "-") )// - 5
  {
    v3 = v9++;
    key_array[v3] = atoi(nptr);
  }
  if ( v9 != 6 )
    return 0LL;
  v10 = 0;
  emil = email;
  name1 = name;
  for ( i = 0; i <= 1++i )
  {
    v21 = (char *)*(&emil + i);
    v19 = strlen((const char *)*(&emil + i));
    if ( v19 <= 31 )
    {
      for ( j = 0; j < 32 - v19; ++j )
        v21[v19 + j] = pad[v10 + j];
      v10 = 32 - v19;
      v21[32= 0;
    }
  }
  for ( k = 0; k <= 31++k )
  {
    *(_BYTE *)(k + email) ^= 5u;
    *(_BYTE *)(k + name) ^= 0xFu;
  }
  for ( l = 0; l <= 5++l )
  {
    v5 = sumChars(email, 032, l + 2);
    key_array[l] -= (signed int)((unsigned __int64)sumChars(email, l + 132, l + 2* v5) % 10000;
    v6 = sumChars(name, 0322);
    key_array[l] += 4 * (v6 - (unsigned __int64)sumChars(name, 1322));
  }
  swapArr((__int64)key_array, 34);
  swapArr((__int64)key_array, 25);
  swapArr((__int64)key_array, 15);
  swapArr((__int64)key_array, 23);
  swapArr((__int64)key_array, 05);
  swapArr((__int64)key_array, 45);
  for ( m = 0; m <= 5++m )
  {
    key_array[m] += sumChars(name, 0321);
    key_array[m] += sumChars(email, 0321);
  }
  for ( n = 0; n <= 5++n )
  {
    v7 = sumChars(email, 4 * n, 4 * n + 11);
    key_array[n] += v7 % (signed int)sumChars(name, 4 * n + 24 * n + 31);
  }
  v25 = 2;
  v26 = 4;
  v27 = 6;
  v28 = 8;
  v29 = 7;
  v30 = 5;
  v31 = sumChars(email, 0101);
  v32 = sumChars(email, 10251);
  v33 = sumChars(email, 25321);
  v34 = sumChars(name, 0131);
  v35 = sumChars(name, 13201);
  v36 = sumChars(name, 20321);
  for ( ii = 0; ii <= 5++ii )
    *(&v31 + ii) = *(&v31 + ii) * *(&v25 + ii) % 10000;
  v8 = 1;
  for ( jj = 0; jj <= 5++jj )
  {
    if ( key_array[jj] != *(&v31 + jj) )
      v8 = 0;
  }
  return v8;
}
 
_DWORD *__fastcall swapArr(__int64 a1, int a2, int a3)
{
  _DWORD *result; // rax
 
  *(_DWORD *)(4LL * a2 + a1) ^= *(_DWORD *)(4LL * a3 + a1);
  *(_DWORD *)(4LL * a3 + a1) ^= *(_DWORD *)(4LL * a2 + a1);
  result = (_DWORD *)(4LL * a2 + a1);
  *result ^= *(_DWORD *)(4LL * a3 + a1);
  return result;
}
 
__int64 __fastcall sumChars(__int64 a1, int a2, int a3, int a4)
{
  unsigned int v5; // [rsp+1Ch] [rbp-8h]
  int i; // [rsp+20h] [rbp-4h]
 
  v5 = 0;
  for ( i = a2; i < a3; i += a4 )
    v5 += *(char *)(i + a1);
  return v5;
}
cs

IDA로 본 해당문제 소스인데 name, email, key 입력받고 name이랑 email 로 사용자가 만든 sumpArr, sumChars 함수들을 이용해서 입력한 key값과 섞고 마지막에 값 비교한다.

마지막에 값 비교하는 부분에서 &v31 부분은 그냥 gdb로 까서 값 추출하였다.

그 다음에 key값을 구해야하는데 swap 부분땜에 브포는 힘들거같아서 z3 써서 해결했다.


[Solve]

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
from z3 import *
 
 
def sumchar(a, a1, a2, a3):
    sum = 0
    for i in range(a1, a2, a3):
        sum += a[i]
    return sum
 
 
def swap(a, a1, a2):
    a[a1], a[a2] = a[a2], a[a1]
    return a
 
 
def main():
    s = Solver()
    key = [Int('key[%d]' % i) for i in range(6)]
    name = []
    email = []
    name0 = bytearray("Artemis Tosini")
    email0 = bytearray("artemis.tosini@example.com")
    num = [0x7f80x17800xb940x1f80xb4b0x11f8]
 
    for i in range(32):
        if len(name0) <= i:
            tmp = 0
        else:
            tmp = name0[i]
        name.append(tmp)
 
        if len(email0) <= i:
            tmp = 0
        else:
            tmp = email0[i]
        email.append(tmp)
 
    gar = [0x220xf0x240x20x730x590x670x640x210x730x170x1e0x6d0x5b0x40x660x650x51]
    for i in range(len('Artemis Tosini'), 32):
        name[i] = gar[i - 14]
 
    for i in range(32):
        email[i] ^= 5
        name[i] ^= 0xf
    email[31= 0x16
    email[30= 0x3c
    email[29= 0x6e
    email[28= 0x1b
    email[27= 0x39
    email[26= 0x72
 
    for i in range(6):
        v5 = sumchar(email, 032, i + 2)
        key[i] -= ((sumchar(email, i + 132, i + 2* v5) & 0x7fffffff) % 10000
        v6 = sumchar(name, 0322)
        key[i] += 4 * (v6 - sumchar(name, 1322))
 
    swap(key, 34)
    swap(key, 25)
    swap(key, 15)
    swap(key, 23)
    swap(key, 05)
    swap(key, 45)
 
    for i in range(6):
        key[i] += sumchar(name, 0321)
        key[i] += sumchar(email, 0321)
 
    for i in range(6):
        v7 = sumchar(email, 4 * i, 4 * i + 11)
        key[i] += v7 % sumchar(name, 4 * i + 24 * i + 31)
    # key[i] &= 0xffffffff
 
    for i in range(6):
        s.add(num[i] == key[i])
    print s.check()
    print s.model()
 
 
if __name__ == "__main__":
    main()
 
cs

아; 그리고 name 값과 email 을 입력하고 32byte에서 남는 byte는 pad 배열로 채워진다.

이부분은 그냥 gdb로 값만 추출해서 넣어줬다.


1
2
3
4
5
gyeongje@ubuntu:~/Desktop$ ./activate 
Name: Artemis Tosini
Email: artemis.tosini@example.com
Product key: 3914-6104-4611-1711-1243-4699
Windows has been activated
cs


'CTF' 카테고리의 다른 글

[Codegate final 2018] betting  (0) 2018.04.06
[Codegate 2017] Goversing  (0) 2018.03.29
[White Hacker League 2017] Medic  (0) 2018.03.09
[White Hacker League 2017] Ghost  (0) 2018.03.05
[Codegate 2016] floppy  (0) 2018.03.03