[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, 0, 32, l + 2); key_array[l] -= (signed int)((unsigned __int64)sumChars(email, l + 1, 32, l + 2) * v5) % 10000; v6 = sumChars(name, 0, 32, 2); key_array[l] += 4 * (v6 - (unsigned __int64)sumChars(name, 1, 32, 2)); } swapArr((__int64)key_array, 3, 4); swapArr((__int64)key_array, 2, 5); swapArr((__int64)key_array, 1, 5); swapArr((__int64)key_array, 2, 3); swapArr((__int64)key_array, 0, 5); swapArr((__int64)key_array, 4, 5); for ( m = 0; m <= 5; ++m ) { key_array[m] += sumChars(name, 0, 32, 1); key_array[m] += sumChars(email, 0, 32, 1); } for ( n = 0; n <= 5; ++n ) { v7 = sumChars(email, 4 * n, 4 * n + 1, 1); key_array[n] += v7 % (signed int)sumChars(name, 4 * n + 2, 4 * n + 3, 1); } v25 = 2; v26 = 4; v27 = 6; v28 = 8; v29 = 7; v30 = 5; v31 = sumChars(email, 0, 10, 1); v32 = sumChars(email, 10, 25, 1); v33 = sumChars(email, 25, 32, 1); v34 = sumChars(name, 0, 13, 1); v35 = sumChars(name, 13, 20, 1); v36 = sumChars(name, 20, 32, 1); 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 = [0x7f8, 0x1780, 0xb94, 0x1f8, 0xb4b, 0x11f8] 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 = [0x22, 0xf, 0x24, 0x2, 0x73, 0x59, 0x67, 0x64, 0x21, 0x73, 0x17, 0x1e, 0x6d, 0x5b, 0x4, 0x66, 0x65, 0x51] 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, 0, 32, i + 2) key[i] -= ((sumchar(email, i + 1, 32, i + 2) * v5) & 0x7fffffff) % 10000 v6 = sumchar(name, 0, 32, 2) key[i] += 4 * (v6 - sumchar(name, 1, 32, 2)) swap(key, 3, 4) swap(key, 2, 5) swap(key, 1, 5) swap(key, 2, 3) swap(key, 0, 5) swap(key, 4, 5) for i in range(6): key[i] += sumchar(name, 0, 32, 1) key[i] += sumchar(email, 0, 32, 1) for i in range(6): v7 = sumchar(email, 4 * i, 4 * i + 1, 1) key[i] += v7 % sumchar(name, 4 * i + 2, 4 * i + 3, 1) # 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 |