Makefile: display firmware size
[RRG-proxmark3.git] / tools / mfd_aes_brute / mfd_multi_brute.c
blob4781d384a5f94df210388ee85c7176e3b3716bf9
1 // MIFARE bruteforce tool
2 // It's Multi threaded and supports all DES/2TDEA/3TDEA/AES crypto authentication modes.
3 // also supports six different LCG random generators.
4 // as a consequece this tools also work on MIFARE Ultralight-C challenges
5 //
6 //
7 // Based upon the bruteforcer from X41 D-Sec Gmbh
8 //
9 // Copyright Iceman 2022
11 // This program is free software: you can redistribute it and/or modify
12 // it under the terms of the GNU General Public License as published by
13 // the Free Software Foundation, either version 3 of the License, or
14 // (at your option) any later version.
16 // This program is distributed in the hope that it will be useful,
17 // but WITHOUT ANY WARRANTY; without even the implied warranty of
18 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 // GNU General Public License for more details.
21 // You should have received a copy of the GNU General Public License
22 // along with this program. If not, see <https://www.gnu.org/licenses/>.
25 #define __STDC_FORMAT_MACROS
27 #include <stdio.h>
28 #include <stdint.h>
29 #include <stdlib.h>
30 #include <stdbool.h>
31 #include <limits.h>
32 #include <openssl/evp.h>
33 #include <openssl/err.h>
34 #include <string.h>
35 #include <time.h>
36 #include <pthread.h>
37 #include <unistd.h>
38 #include <inttypes.h>
39 //#include <mbedtls/aes.h>
40 #include "util_posix.h"
41 #include "randoms.h"
43 #include "aes-ni.h"
45 #if defined(__APPLE__) || defined(__MACH__)
46 #else
47 #include "detectaes.h"
48 #endif
51 #define AEND "\x1b[0m"
52 #define _RED_(s) "\x1b[31m" s AEND
53 #define _GREEN_(s) "\x1b[32m" s AEND
54 #define _YELLOW_(s) "\x1b[33m" s AEND
55 #define _CYAN_(s) "\x1b[36m" s AEND
58 static generator_t generators[] = {
59 {"Borland", make_key_borland_n},
60 {"Recipies", make_key_recipies_n},
61 {"GlibC", make_key_glibc_n},
62 {"AnsiC", make_key_ansic_n},
63 {"Turbo Pascal", make_key_turbopascal_n},
64 {"posix rand_r", make_key_posix_rand_r_n},
65 {"MS Visual/Quick C/C++", make_key_ms_rand_r_n},
66 {NULL, NULL}
69 #define ARRAYLEN(x) (sizeof(x)/sizeof((x)[0]))
71 // a global mutex to prevent interlaced printing from different threads
72 pthread_mutex_t print_lock;
74 static int global_found = 0;
75 static int thread_count = 2;
77 typedef struct thread_args {
78 int thread;
79 int idx;
80 uint8_t generator_idx;
81 uint8_t algo;
82 uint64_t starttime;
83 uint64_t stoptime;
84 uint8_t tag[16];
85 uint8_t rdr[32];
86 } targs;
89 // source https://wiki.openssl.org/index.php/EVP_Symmetric_Encryption_and_Decryption#Decrypting_the_Message
90 static void decrypt_aes(uint8_t ciphertext[], int ciphertext_len, uint8_t key[], uint8_t iv[], uint8_t plaintext[]) {
91 EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
92 EVP_DecryptInit_ex(ctx, EVP_aes_128_cbc(), NULL, key, iv);
93 // EVP_CIPHER_CTX_set_padding(ctx, 0);
94 int len = 0;
95 EVP_DecryptUpdate(ctx, plaintext, &len, ciphertext, ciphertext_len);
96 EVP_DecryptFinal_ex(ctx, plaintext + len, &len);
97 EVP_CIPHER_CTX_free(ctx);
100 static void decrypt_3kdes(uint8_t ciphertext[], int ciphertext_len, uint8_t key[], uint8_t iv[], uint8_t plaintext[]) {
101 EVP_CIPHER_CTX *ctx;
102 ctx = EVP_CIPHER_CTX_new();
104 EVP_DecryptInit_ex(ctx, EVP_des_ede3_cbc(), NULL, key, iv);
105 EVP_CIPHER_CTX_set_padding(ctx, 0);
106 int len = 0;
107 EVP_DecryptUpdate(ctx, plaintext, &len, ciphertext, ciphertext_len);
108 EVP_DecryptFinal_ex(ctx, plaintext + len, &len);
109 EVP_CIPHER_CTX_free(ctx);
112 static void decrypt_2kdes(uint8_t ciphertext[], int ciphertext_len, uint8_t key[], uint8_t iv[], uint8_t plaintext[]) {
113 EVP_CIPHER_CTX *ctx;
114 ctx = EVP_CIPHER_CTX_new();
115 EVP_DecryptInit_ex(ctx, EVP_des_ede_cbc(), NULL, key, iv);
116 EVP_CIPHER_CTX_set_padding(ctx, 0);
117 int len = 0;
118 EVP_DecryptUpdate(ctx, plaintext, &len, ciphertext, ciphertext_len);
119 EVP_DecryptFinal_ex(ctx, plaintext + len, &len);
120 EVP_CIPHER_CTX_free(ctx);
123 static void decrypt_des(uint8_t ciphertext[], int ciphertext_len, uint8_t key[], uint8_t iv[], uint8_t plaintext[]) {
124 EVP_CIPHER_CTX *ctx;
125 ctx = EVP_CIPHER_CTX_new();
126 EVP_DecryptInit_ex(ctx, EVP_des_cbc(), NULL, key, iv);
127 EVP_CIPHER_CTX_set_padding(ctx, 0);
128 int len = 0;
129 EVP_DecryptUpdate(ctx, plaintext, &len, ciphertext, ciphertext_len);
130 EVP_DecryptFinal_ex(ctx, plaintext + len, &len);
131 EVP_CIPHER_CTX_free(ctx);
134 static int hexstr_to_byte_array(char hexstr[], uint8_t bytes[], size_t byte_len) {
135 size_t hexstr_len = strlen(hexstr);
136 if (hexstr_len % 16) {
137 return 1;
140 if (byte_len < (hexstr_len / 2)) {
141 return 2;
144 char *pos = &hexstr[0];
145 for (size_t count = 0; *pos != 0; count++) {
146 sscanf(pos, "%2hhx", &bytes[count]);
147 pos += 2;
149 return 0;
152 static void print_hex(const uint8_t *data, const size_t len) {
153 if (data == NULL || len == 0) return;
155 for (size_t i = 0; i < len; i++) {
156 printf("%02X", data[i]);
159 printf("\n");
162 static void print_time(uint64_t at) {
164 time_t t = at;
165 struct tm lt;
167 #if defined(_WIN32)
168 (void)localtime_s(&lt, &t);
169 #else
170 (void)localtime_r(&t, &lt);
171 #endif
173 char res[70];
174 #if defined(__MINGW32__) || defined(__MINGW64__)
175 strftime(res, sizeof(res), "('%Y-%m-%d %H:%M:%S')", &lt);
176 #else
177 strftime(res, sizeof(res), "%s ('%Y-%m-%d %H:%M:%S')", &lt);
178 #endif
179 printf("%s\n", res);
182 static void *brute_thread(void *arguments) {
184 //const bool support_aesni = platform_aes_hw_available();
186 struct thread_args *args = (struct thread_args *) arguments;
188 uint64_t starttime = args->starttime;
189 uint64_t stoptime = args->stoptime;
190 uint8_t local_algo = args->algo;
191 uint8_t gidx = args->generator_idx;
192 uint8_t local_tag[16];
193 uint8_t local_rdr[32];
194 uint8_t keylen = 16;
196 if (local_algo == 0) {
197 memcpy(local_tag, args->tag, 8);
198 memcpy(local_rdr, args->rdr, 16);
199 keylen = 8;
200 } else if (local_algo == 1) {
201 memcpy(local_tag, args->tag, 8);
202 memcpy(local_rdr, args->rdr, 16);
203 keylen = 16;
204 } else if (local_algo == 2) {
205 memcpy(local_tag, args->tag, 16);
206 memcpy(local_rdr, args->rdr, 32);
207 keylen = 24;
208 } else if (local_algo == 3) {
209 memcpy(local_tag, args->tag, 16);
210 memcpy(local_rdr, args->rdr, 32);
211 keylen = 16;
214 for (uint64_t i = starttime + args->idx; i < stoptime; i += thread_count) {
216 if (__atomic_load_n(&global_found, __ATOMIC_ACQUIRE) == 1) {
217 break;
220 uint8_t key[keylen];
221 generators[gidx].Parse(i, key, keylen);
222 //make_key_borland_n(i, key, keylen);
224 uint8_t iv[keylen << 1];
225 memset(iv, 0, sizeof(iv));
227 uint8_t dec_tag[16] = {0x00};
228 uint8_t dec_rdr[32] = {0x00};
230 if (local_algo == 0) {
231 decrypt_des(local_tag, 8, key, iv, dec_tag);
232 decrypt_des(local_rdr, 16, key, local_tag, dec_rdr);
234 // check rol byte first
235 if (dec_tag[0] != dec_rdr[15]) continue;
237 // compare rest
238 if (dec_tag[1] != dec_rdr[8]) continue;
239 if (dec_tag[2] != dec_rdr[9]) continue;
240 if (dec_tag[3] != dec_rdr[10]) continue;
241 if (dec_tag[4] != dec_rdr[11]) continue;
242 if (dec_tag[5] != dec_rdr[12]) continue;
243 if (dec_tag[6] != dec_rdr[13]) continue;
244 if (dec_tag[7] != dec_rdr[14]) continue;
246 } else if (local_algo == 1) {
247 decrypt_2kdes(local_tag, 8, key, iv, dec_tag);
248 decrypt_2kdes(local_rdr, 16, key, local_tag, dec_rdr);
250 // check rol byte first
251 if (dec_tag[0] != dec_rdr[15]) continue;
253 // compare rest
254 if (dec_tag[1] != dec_rdr[8]) continue;
255 if (dec_tag[2] != dec_rdr[9]) continue;
256 if (dec_tag[3] != dec_rdr[10]) continue;
257 if (dec_tag[4] != dec_rdr[11]) continue;
258 if (dec_tag[5] != dec_rdr[12]) continue;
259 if (dec_tag[6] != dec_rdr[13]) continue;
260 if (dec_tag[7] != dec_rdr[14]) continue;
262 } else if (local_algo == 2) {
263 decrypt_3kdes(local_tag, 16, key, iv, dec_tag);
264 decrypt_3kdes(local_rdr, 32, key, local_tag, dec_rdr);
266 // check rol byte first
267 if (dec_tag[0] != dec_rdr[31]) continue;
269 // compare rest
270 if (dec_tag[1] != dec_rdr[16]) continue;
271 if (dec_tag[2] != dec_rdr[17]) continue;
272 if (dec_tag[3] != dec_rdr[18]) continue;
273 if (dec_tag[4] != dec_rdr[19]) continue;
274 if (dec_tag[5] != dec_rdr[20]) continue;
275 if (dec_tag[6] != dec_rdr[21]) continue;
276 if (dec_tag[7] != dec_rdr[22]) continue;
277 if (dec_tag[8] != dec_rdr[23]) continue;
278 if (dec_tag[9] != dec_rdr[24]) continue;
279 if (dec_tag[10] != dec_rdr[25]) continue;
280 if (dec_tag[11] != dec_rdr[26]) continue;
281 if (dec_tag[12] != dec_rdr[27]) continue;
282 if (dec_tag[13] != dec_rdr[28]) continue;
283 if (dec_tag[14] != dec_rdr[29]) continue;
284 if (dec_tag[15] != dec_rdr[30]) continue;
286 } else if (local_algo == 3) {
287 decrypt_aes(local_tag, 16, key, iv, dec_tag);
288 decrypt_aes(local_rdr, 32, key, local_tag, dec_rdr);
290 // check rol byte first
291 if (dec_tag[0] != dec_rdr[31]) continue;
293 // compare rest
294 if (dec_tag[1] != dec_rdr[16]) continue;
295 if (dec_tag[2] != dec_rdr[17]) continue;
296 if (dec_tag[3] != dec_rdr[18]) continue;
297 if (dec_tag[4] != dec_rdr[19]) continue;
298 if (dec_tag[5] != dec_rdr[20]) continue;
299 if (dec_tag[6] != dec_rdr[21]) continue;
300 if (dec_tag[7] != dec_rdr[22]) continue;
301 if (dec_tag[8] != dec_rdr[23]) continue;
302 if (dec_tag[9] != dec_rdr[24]) continue;
303 if (dec_tag[10] != dec_rdr[25]) continue;
304 if (dec_tag[11] != dec_rdr[26]) continue;
305 if (dec_tag[12] != dec_rdr[27]) continue;
306 if (dec_tag[13] != dec_rdr[28]) continue;
307 if (dec_tag[14] != dec_rdr[29]) continue;
308 if (dec_tag[15] != dec_rdr[30]) continue;
311 __sync_fetch_and_add(&global_found, 1);
313 // lock this section to avoid interlacing prints from different threats
314 pthread_mutex_lock(&print_lock);
315 printf("Found timestamp........ ");
316 print_time(i);
318 printf("Key.................... \x1b[32m");
319 print_hex(key, keylen);
320 printf(AEND);
322 pthread_mutex_unlock(&print_lock);
323 break;
325 free(args);
326 return NULL;
329 static int usage(const char *s) {
331 printf("\n");
332 printf(_CYAN_("Multi Brute tool\n"));
333 printf("Works on authentication challenges from MIFARE DESfire, MIFARE UL-C.\n");
334 printf("If the key was generated by taking the Unixstamp as seed to a LCG random generator this software might find it.\n");
335 printf("This version is multi-threaded, multi-crypto support and multi LCG generator support.\n");
336 printf("\n");
337 printf(_CYAN_("syntax") "\n");
338 printf(" %s <crypto algo> <generator> <unix timestamp> <16 byte tag challenge> <32 byte reader response challenge>\n\n", s);
339 printf(" crypt algo - <DES|2KDES|3KDES|AES>\n");
340 printf(" generator - <0-5>\n");
341 printf("\n");
342 printf(_CYAN_("samples") "\n");
343 printf(" %s DES 0 1599999999 118565f6e5e6c839 d570fd1578079e6b22aaa187b99f0a2a\n", s);
344 printf(" %s 2TDEA 0 1599999999 02bdc73fd33cc07d 0e2281d59686bda6a6c5ad218dbfaa8c\n", s);
345 printf(" %s 3TDEA 0 1599999999 1fe1f0330e9da5407cd2bc9294e56a7e 920037b5e02872b2fd9a070eade2b172ddc0fe6b10e5e55dd32cebdcc94747b4 \n", s);
346 printf(" %s AES 0 1599999999 bb6aea729414a5b1eff7b16328ce37fd 82f5f498dbc29f7570102397a2e5ef2b6dc14a864f665b3c54d11765af81e95c\n", s);
347 printf("\n");
348 return 1;
351 int main(int argc, char *argv[]) {
353 if (argc != 6) {
354 return usage(argv[0]);
357 char *algostr = argv[1];
358 if (strlen(algostr) > 5 || strlen(algostr) < 3) {
359 printf("No valid crypto algo\n");
360 return 1;
363 int8_t algo = -1;
364 if (strcasecmp(algostr, "des") == 0) {
365 algo = 0;
366 } else if (strcasecmp(algostr, "2tdea") == 0) {
367 algo = 1;
368 } else if (strcasecmp(algostr, "3tdea") == 0) {
369 algo = 2;
370 } else if (strcasecmp(algostr, "aes") == 0) {
371 algo = 3;
374 if (algo == -1) {
375 printf("No valid crypto algo\n");
376 return 1;
379 uint8_t g_idx = atoi(argv[2]);
381 // -2 (zero index and last item is NULL);
382 if (g_idx > ARRAYLEN(generators) - 2) {
383 printf("generator index is out-of-range\n");
384 return 1;
387 uint64_t start_time = 0;
388 sscanf(argv[3], "%"PRIu64, &start_time);
390 printf("Crypto algo............ " _GREEN_("%s") "\n", algostr);
391 printf("LCR Random generator... " _GREEN_("%s") "\n", generators[g_idx].Name);
393 #if defined(__APPLE__) || defined(__MACH__)
394 #else
395 bool support_aesni = platform_aes_hw_available();
396 printf("AES-NI detected........ " _GREEN_("%s") "\n", (support_aesni) ? "yes" : "no");
397 #endif
399 printf("Starting timestamp..... ");
400 print_time(start_time);
402 uint8_t tag_challenge[16] = {0x00};
403 uint8_t rdr_resp_challenge[32] = {0x00};
405 if (algo == 0) {
406 if (hexstr_to_byte_array(argv[4], tag_challenge, 8))
407 return 2;
408 if (hexstr_to_byte_array(argv[5], rdr_resp_challenge, 16))
409 return 3;
411 printf("Tag Challenge.......... ");
412 print_hex(tag_challenge, 8);
414 printf("Rdr Resp & Challenge... ");
415 print_hex(rdr_resp_challenge, 16);
417 } else if (algo == 1) {
418 if (hexstr_to_byte_array(argv[4], tag_challenge, 8))
419 return 2;
420 if (hexstr_to_byte_array(argv[5], rdr_resp_challenge, 16))
421 return 3;
423 printf("Tag Challenge.......... ");
424 print_hex(tag_challenge, 8);
426 printf("Rdr Resp & Challenge... ");
427 print_hex(rdr_resp_challenge, 16);
429 } else if (algo == 2) {
430 if (hexstr_to_byte_array(argv[4], tag_challenge, 16))
431 return 2;
432 if (hexstr_to_byte_array(argv[5], rdr_resp_challenge, 32))
433 return 3;
435 printf("Tag Challenge.......... ");
436 print_hex(tag_challenge, 16);
438 printf("Rdr Resp & Challenge... ");
439 print_hex(rdr_resp_challenge, 32);
441 } else if (algo == 3) {
442 if (hexstr_to_byte_array(argv[4], tag_challenge, 16))
443 return 2;
444 if (hexstr_to_byte_array(argv[5], rdr_resp_challenge, 32))
445 return 3;
447 printf("Tag Challenge.......... ");
448 print_hex(tag_challenge, 16);
450 printf("Rdr Resp & Challenge... ");
451 print_hex(rdr_resp_challenge, 32);
454 uint64_t t1 = msclock();
456 #if !defined(_WIN32) || !defined(__WIN32__)
457 thread_count = sysconf(_SC_NPROCESSORS_CONF);
458 if (thread_count < 2)
459 thread_count = 2;
460 #endif /* _WIN32 */
462 printf("\nBruteforce using " _YELLOW_("%d") " threads\n", thread_count);
464 pthread_t threads[thread_count];
465 void *res;
467 // create a mutex to avoid interlacing print commands from our different threads
468 pthread_mutex_init(&print_lock, NULL);
470 // threads
471 uint64_t stop_time = time(NULL);
472 for (int i = 0; i < thread_count; ++i) {
473 struct thread_args *a = calloc(1, sizeof(struct thread_args));
474 a->thread = i;
475 a->idx = i;
476 a->generator_idx = g_idx;
477 a->algo = (uint8_t)algo;
478 a->starttime = start_time;
479 a->stoptime = stop_time;
481 if (algo == 0) {
482 memcpy(a->tag, tag_challenge, 8);
483 memcpy(a->rdr, rdr_resp_challenge, 16);
484 } else if (algo == 1) {
485 memcpy(a->tag, tag_challenge, 8);
486 memcpy(a->rdr, rdr_resp_challenge, 16);
487 } else if (algo == 2) {
488 memcpy(a->tag, tag_challenge, 16);
489 memcpy(a->rdr, rdr_resp_challenge, 32);
490 } else if (algo == 3) {
491 memcpy(a->tag, tag_challenge, 16);
492 memcpy(a->rdr, rdr_resp_challenge, 32);
495 pthread_create(&threads[i], NULL, brute_thread, (void *)a);
498 // wait for threads to terminate:
499 for (int i = 0; i < thread_count; ++i) {
500 pthread_join(threads[i], &res);
501 free(res);
504 if (global_found == false) {
505 printf("\n" _RED_("!!!") " failed to find a key\n\n");
508 t1 = msclock() - t1;
509 if (t1 > 0) {
510 printf("Execution time " _YELLOW_("%.2f") " sec\n", (float)t1 / 1000.0);
513 // clean up mutex
514 pthread_mutex_destroy(&print_lock);
516 return 0;