Merge pull request #2741 from Donny-Guo/hidbrute
[RRG-proxmark3.git] / armsrc / Standalone / hf_aveful.c
blobf9122f031569feae645315ee4b870c476bab79c3
1 //-----------------------------------------------------------------------------
2 // Copyright (C) A. Ozkal, 2020
3 // Copyright (C) Proxmark3 contributors. See AUTHORS.md for details.
4 //
5 // This program is free software: you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation, either version 3 of the License, or
8 // (at your option) any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
15 // See LICENSE.txt for the text of the license.
16 //-----------------------------------------------------------------------------
17 // main code for HF Mifare Ultralight read/simulation by Ave Ozkal
18 //-----------------------------------------------------------------------------
20 // Several parts of this code is based on code by Craig Young from HF_YOUNG
22 // This code does not:
23 // - Account for cards with non-default keys on authentication (MFU EV1 etc)
25 // This code is designed to work with:
26 // - MIFARE Ultralight
27 // - MIFARE Ultralight EV1 (default keys)
28 // - MIFARE Ultralight Nano (untested, but should work)
29 // - Infineon My-d Move (without password set)
30 // - Infineon My-d Move Lean
31 // - Any other Ultralight clones that have no auth and MAX_DEFAULT_BLOCKS (16) blocks
33 #include "standalone.h" // standalone definitions
34 #include "proxmark3_arm.h"
35 #include "appmain.h"
36 #include "fpgaloader.h"
37 #include "util.h"
38 #include "dbprint.h"
40 #include "ticks.h" // SpinDelay
41 #include "protocols.h" // MIFARE_ULEV1_VERSION, MIFARE_ULEV1_READSIG, MIFARE_ULEV1_READ_CNT, MIFARE_ULEV1_CHECKTEAR
42 #include <string.h> // memcmp
43 #include "mifareutil.h"
44 #include "iso14443a.h"
46 #define SAK 0x00
47 #define ATQA0 0x44
48 #define ATQA1 0x00
50 #define STATE_SEARCH 0
51 #define STATE_READ 1
52 #define STATE_EMUL 2
54 // Taken from cmdhfmfu.c, increased by 01h to be 1 indexed
55 #define MAX_UL_BLOCKS 0x10
56 #define MAX_UL_NANO_40 0x0B
57 #define MAX_ULEV1a_BLOCKS 0x14
58 #define MAX_ULEV1b_BLOCKS 0x29
59 #define MAX_MY_D_MOVE 0x26
60 #define MAX_MY_D_MOVE_LEAN 0x10
61 #define MAX_DEFAULT_BLOCKS 0x10
63 typedef struct {
64 uint8_t uid[10];
65 uint8_t uidlen;
66 uint8_t atqa[2];
67 uint8_t sak;
68 } PACKED card_clone_t;
70 int get_block_count(iso14a_card_select_t card, uint8_t *version, uint16_t version_len);
71 uint16_t get_ev1_version(iso14a_card_select_t card, uint8_t *version, uint16_t version_len);
72 uint16_t get_ev1_signature(iso14a_card_select_t card, uint8_t *signature, uint16_t sign_len);
73 uint16_t get_ev1_counter(iso14a_card_select_t card, uint8_t counter, uint8_t *response, uint16_t resp_len);
74 uint16_t get_ev1_tearing(iso14a_card_select_t card, uint8_t counter, uint8_t *response, uint16_t resp_len);
76 uint16_t get_ev1_version(iso14a_card_select_t card, uint8_t *version, uint16_t version_len) {
77 return mifare_sendcmd(MIFARE_ULEV1_VERSION, NULL, 0, version, version_len, NULL, NULL);
80 uint16_t get_ev1_signature(iso14a_card_select_t card, uint8_t *signature, uint16_t sign_len) {
81 uint8_t cmd[4] = {MIFARE_ULEV1_READSIG, 0x00, 0x00, 0x00};
82 AddCrc14A(cmd, 2);
83 ReaderTransmit(cmd, sizeof(cmd), NULL);
84 return ReaderReceive(signature, sign_len, NULL);
87 uint16_t get_ev1_counter(iso14a_card_select_t card, uint8_t counter, uint8_t *response, uint16_t resp_len) {
88 uint8_t cmd[4] = {MIFARE_ULEV1_READ_CNT, counter, 0x00, 0x00};
89 AddCrc14A(cmd, 2);
90 ReaderTransmit(cmd, sizeof(cmd), NULL);
91 return ReaderReceive(response, resp_len, NULL);
94 uint16_t get_ev1_tearing(iso14a_card_select_t card, uint8_t counter, uint8_t *response, uint16_t resp_len) {
95 uint8_t cmd[4] = {MIFARE_ULEV1_CHECKTEAR, counter, 0x00, 0x00};
96 AddCrc14A(cmd, 2);
97 ReaderTransmit(cmd, sizeof(cmd), NULL);
98 return ReaderReceive(response, resp_len, NULL);
101 int get_block_count(iso14a_card_select_t card, uint8_t *version, uint16_t version_len) {
102 // Default to MAX_DEFAULT_BLOCKS blocks
103 int block_count = MAX_DEFAULT_BLOCKS;
104 // Most of this code is from cmdhfmfu.c
105 // Infineon manufacturer ID
106 if (card.uid[0] == 0x05) {
107 // Infinition MY-D tests Exam high nibble
108 uint8_t nib = (card.uid[1] & 0xf0) >> 4;
109 switch (nib) {
110 case 3:
111 block_count = MAX_MY_D_MOVE;
112 break; // or SLE 66R01P // 38 pages of 4 bytes
113 case 7:
114 block_count = MAX_MY_D_MOVE_LEAN;
115 break; // or SLE 66R01L // 16 pages of 4 bytes
117 } else {
118 // Moved this from case to if as I only care about non-ultralight ev0.
119 if (version_len == 0x0A) {
120 if (memcmp(version, "\x00\x04\x03\x01\x01\x00\x0B", 7) == 0) { block_count = MAX_ULEV1a_BLOCKS; }
121 else if (memcmp(version, "\x00\x04\x03\x01\x02\x00\x0B", 7) == 0) { block_count = MAX_UL_NANO_40; }
122 else if (memcmp(version, "\x00\x04\x03\x02\x01\x00\x0B", 7) == 0) { block_count = MAX_ULEV1a_BLOCKS; }
123 else if (memcmp(version, "\x00\x04\x03\x01\x01\x00\x0E", 7) == 0) { block_count = MAX_ULEV1b_BLOCKS; }
124 else if (memcmp(version, "\x00\x04\x03\x02\x01\x00\x0E", 7) == 0) { block_count = MAX_ULEV1b_BLOCKS; }
125 else if (memcmp(version, "\x00\x34\x21\x01\x01\x00\x0E", 7) == 0) { block_count = MAX_ULEV1b_BLOCKS; } // Mikron JSC Russia EV1 41 pages tag
126 else if (version[2] == 0x03) { block_count = MAX_ULEV1a_BLOCKS; }
130 return block_count;
133 void ModInfo(void) {
134 DbpString(" HF Mifare Ultralight read/simulation by Ave Ozkal");
137 void RunMod(void) {
138 StandAloneMode();
139 Dbprintf("AveFUL (MF Ultralight read/emul) started");
140 FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
142 // the main loop for your standalone mode
143 for (;;) {
144 WDT_HIT();
146 // exit from RunMod, send a usbcommand.
147 if (data_available()) break;
149 iso14a_card_select_t card;
151 SpinDelay(500);
152 iso14443a_setup(FPGA_HF_ISO14443A_READER_MOD);
154 // 0 = search, 1 = read, 2 = emul
155 int state = STATE_SEARCH;
157 DbpString("Scanning...");
158 int button_pressed = BUTTON_NO_CLICK;
159 for (;;) {
160 // Was our button held down or pressed?
161 button_pressed = BUTTON_HELD(1000);
163 if (button_pressed != BUTTON_NO_CLICK || data_available())
164 break;
165 else if (state == STATE_SEARCH) {
166 if (!iso14443a_select_card(NULL, &card, NULL, true, 0, true)) {
167 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
168 LED_D_OFF();
169 SpinDelay(500);
170 continue;
171 } else {
172 if (card.sak == SAK && card.atqa[0] == ATQA0 && card.atqa[1] == ATQA1 && card.uidlen == 7) {
173 DbpString("Found ultralight with UID: ");
174 Dbhexdump(card.uidlen, card.uid, 0);
175 state = STATE_READ;
176 } else {
177 DbpString("Found non-ultralight card, ignoring.");
180 } else if (state == STATE_READ) {
181 iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
182 iso14443a_select_card(NULL, NULL, NULL, true, 0, true);
183 bool read_successful = true;
185 // Get version and re-select card as UL EV0s like to shut off after a 0x60
186 uint8_t version[10] = {0x00};
187 uint16_t version_len = 0;
188 version_len = get_ev1_version(card, version, sizeof(version));
189 iso14443a_select_card(NULL, NULL, NULL, true, 0, true);
191 int block_count = get_block_count(card, version, version_len);
192 Dbprintf("Card was determined as having %d blocks.", block_count);
193 Dbprintf("Contents:");
195 for (int i = 0; i < block_count; i++) {
196 uint8_t dataout[16] = {0x00};
197 if (mifare_ultra_readblock(i, dataout)) {
198 // If there's an error reading, go back to search state
199 read_successful = false;
200 break;
202 // We're skipping 14 blocks (56 bytes) here, as that "[...] has version/signature/counter data here" according to comments on data_mfu_bin2eml
203 // When converting a bin, it's almost all 0 other than one 0x0F byte, and functionality seems to be unaffected if that byte is set to 0x00.
204 emlSetMem_xt(dataout, 14 + i, 1, 4);
205 Dbhexdump(4, dataout, 0);
208 // It's not the best way to determine this,
209 // but with what I'm trying to support It Should Be Okay
210 bool is_ev1 = (version_len != 0) && (block_count != 16);
212 if (read_successful) {
213 uint8_t signature[34] = {0x00};
214 if (is_ev1) {
215 get_ev1_signature(card, signature, sizeof(signature));
217 Dbprintf("Preparing emulator memory with:");
218 // Fill first 14 blocks with 0x00 (see comment above)
219 for (int i = 0; i < 14; i++) {
220 uint8_t dataout[4] = {0x00, 0x00, 0x00, 0x00};
222 if (is_ev1 && (i == 0 || i == 1)) {
223 // On block 0 and 1, set version on EV1
224 memcpy(dataout, version + (i * 4), 4);
225 } else if (i == 2) {
226 // On block 2, set last byte to the card's block count
227 dataout[3] = block_count;
228 } else if (is_ev1 && ((i > 2 && i < 11))) {
229 // On 3-10 add signature on EV1
230 memcpy(dataout, signature + ((i - 3) * 4), 4);
231 } else if (is_ev1 && (i > 10)) {
232 // On 11-14 read and set counter and tearing on EV1
233 uint8_t counter[5];
234 uint8_t tearing[3];
235 get_ev1_counter(card, i - 11, counter, sizeof(counter));
236 get_ev1_tearing(card, i - 11, tearing, sizeof(tearing));
237 memcpy(dataout, counter, 3);
238 memcpy(dataout + 3, tearing, 1);
241 Dbhexdump(4, dataout, 0);
242 emlSetMem_xt(dataout, i, 1, 4);
244 Dbprintf("Successfully loaded into emulator memory...");
245 state = STATE_EMUL;
246 } else {
247 Dbprintf("Read failure, going back to search state.");
248 state = STATE_SEARCH;
250 } else if (state == STATE_EMUL) {
251 uint16_t flags = 0;
252 FLAG_SET_UID_IN_DATA(flags, 7);
254 Dbprintf("Starting simulation, press " _GREEN_("pm3 button") " to stop and go back to search state.");
255 SimulateIso14443aTag(7, flags, card.uid, 0, NULL, 0);
257 // Go back to search state if user presses pm3-button
258 state = STATE_SEARCH;
261 if (button_pressed == BUTTON_HOLD) //Holding down the button
262 break;
265 DbpString("exiting");
266 LEDsoff();