]> git.zerfleddert.de Git - proxmark3-svn/blob - client/cmdhfmfu.c
Added some previous work of splitting ultralight to its own c-file, ported Pentura_Pr...
[proxmark3-svn] / client / cmdhfmfu.c
1 //-----------------------------------------------------------------------------
2 // Ultralight Code (c) 2013,2014 Midnitesnake & Andy Davies of Pentura
3 //
4 // This code is licensed to you under the terms of the GNU GPL, version 2 or,
5 // at your option, any later version. See the LICENSE.txt file for the text of
6 // the license.
7 //-----------------------------------------------------------------------------
8 // High frequency MIFARE ULTRALIGHT (C) commands
9 //-----------------------------------------------------------------------------
10
11 #include "cmdhfmf.h"
12 #include "util.h"
13 #include <openssl/des.h>
14
15 uint8_t MAX_ULTRA_BLOCKS= 0x0f;
16 uint8_t MAX_ULTRAC_BLOCKS= 0x2c;
17 uint8_t key1_blnk_data[16] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 };
18 uint8_t key2_defa_data[16] = { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f };
19 uint8_t key3_3des_data[16] = { 0x49,0x45,0x4D,0x4B,0x41,0x45,0x52,0x42,0x21,0x4E,0x41,0x43,0x55,0x4F,0x59,0x46 };
20 uint8_t key4_nfc_data[16] = { 0x42,0x52,0x45,0x41,0x4b,0x4d,0x45,0x49,0x46,0x59,0x4f,0x55,0x43,0x41,0x4e,0x21 };
21
22 static int CmdHelp(const char *Cmd);
23
24 //
25 // Mifare Ultralight Write Single Block
26 //
27 int CmdHF14AMfUWrBl(const char *Cmd){
28 uint8_t blockNo = 0;
29 bool chinese_card=0;
30 uint8_t bldata[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
31 UsbCommand resp;
32
33 if (strlen(Cmd)<3) {
34 PrintAndLog("Usage: hf mfu uwrbl <block number> <block data (8 hex symbols)> [w]");
35 PrintAndLog(" sample: hf mfu uwrbl 0 01020304");
36 return 0;
37 }
38 blockNo = param_get8(Cmd, 0);
39 if (blockNo>MAX_ULTRA_BLOCKS){
40 PrintAndLog("Error: Maximum number of blocks is 15 for Ultralight Cards!");
41 return 1;
42 }
43 if (param_gethex(Cmd, 1, bldata, 8)) {
44 PrintAndLog("Block data must include 8 HEX symbols");
45 return 1;
46 }
47 if (strchr(Cmd,'w') != 0) {
48 chinese_card=1;
49 }
50 switch(blockNo){
51 case 0:
52 if (!chinese_card){
53 PrintAndLog("Access Denied");
54 }else{
55 PrintAndLog("--specialblock no:%02x", blockNo);
56 PrintAndLog("--data: %s", sprint_hex(bldata, 4));
57 UsbCommand d = {CMD_MIFAREU_WRITEBL, {blockNo}};
58 memcpy(d.d.asBytes,bldata, 4);
59 SendCommand(&d);
60 if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
61 uint8_t isOK = resp.arg[0] & 0xff;
62 PrintAndLog("isOk:%02x", isOK);
63 } else {
64 PrintAndLog("Command execute timeout");
65 }
66 }
67 break;
68 case 1:
69 if (!chinese_card){
70 PrintAndLog("Access Denied");
71 }else{
72 PrintAndLog("--specialblock no:%02x", blockNo);
73 PrintAndLog("--data: %s", sprint_hex(bldata, 4));
74 UsbCommand d = {CMD_MIFAREU_WRITEBL, {blockNo}};
75 memcpy(d.d.asBytes,bldata, 4);
76 SendCommand(&d);
77 if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
78 uint8_t isOK = resp.arg[0] & 0xff;
79 PrintAndLog("isOk:%02x", isOK);
80 } else {
81 PrintAndLog("Command execute timeout");
82 }
83 }
84 break;
85 case 2:
86 if (!chinese_card){
87 PrintAndLog("Access Denied");
88 }else{
89 PrintAndLog("--specialblock no:%02x", blockNo);
90 PrintAndLog("--data: %s", sprint_hex(bldata, 4));
91 UsbCommand c = {CMD_MIFAREU_WRITEBL, {blockNo}};
92 memcpy(c.d.asBytes, bldata, 4);
93 SendCommand(&c);
94 if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
95 uint8_t isOK = resp.arg[0] & 0xff;
96 PrintAndLog("isOk:%02x", isOK);
97 } else {
98 PrintAndLog("Command execute timeout");
99 }
100 }
101 break;
102 case 3:
103 PrintAndLog("--specialblock no:%02x", blockNo);
104 PrintAndLog("--data: %s", sprint_hex(bldata, 4));
105 UsbCommand d = {CMD_MIFAREU_WRITEBL, {blockNo}};
106 memcpy(d.d.asBytes,bldata, 4);
107 SendCommand(&d);
108 if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
109 uint8_t isOK = resp.arg[0] & 0xff;
110 PrintAndLog("isOk:%02x", isOK);
111 } else {
112 PrintAndLog("Command execute timeout");
113 }
114 break;
115 default:
116 PrintAndLog("--block no:%02x", blockNo);
117 PrintAndLog("--data: %s", sprint_hex(bldata, 4));
118 UsbCommand e = {CMD_MIFAREU_WRITEBL, {blockNo}};
119 memcpy(e.d.asBytes,bldata, 4);
120 SendCommand(&e);
121 if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
122 uint8_t isOK = resp.arg[0] & 0xff;
123 PrintAndLog("isOk:%02x", isOK);
124 } else {
125 PrintAndLog("Command execute timeout");
126 }
127 break;
128 }
129 return 0;
130 }
131
132 //
133 // Mifare Ultralight Read Single Block
134 //
135 int CmdHF14AMfURdBl(const char *Cmd){
136
137 uint8_t blockNo = 0;
138
139 if (strlen(Cmd)<1) {
140 PrintAndLog("Usage: hf mfu urdbl <block number>");
141 PrintAndLog(" sample: hfu mf urdbl 0");
142 return 0;
143 }
144
145 blockNo = param_get8(Cmd, 0);
146 if (blockNo>MAX_ULTRA_BLOCKS){
147 PrintAndLog("Error: Maximum number of blocks is 15 for Ultralight Cards!");
148 return 1;
149 }
150 PrintAndLog("--block no:%02x", (int)blockNo);
151 UsbCommand c = {CMD_MIFAREU_READBL, {blockNo}};
152 SendCommand(&c);
153
154 UsbCommand resp;
155 if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
156 uint8_t isOK = resp.arg[0] & 0xff;
157 uint8_t * data = resp.d.asBytes;
158
159 if (isOK)
160 PrintAndLog("isOk:%02x data:%s", isOK, sprint_hex(data, 4));
161 else
162 PrintAndLog("isOk:%02x", isOK);
163 } else {
164 PrintAndLog("Command execute timeout");
165 }
166 return 0;
167 }
168
169 //
170 // Mifare Ultralight Read (Dump) Card Contents
171 //
172 int CmdHF14AMfURdCard(const char *Cmd){
173 int i;
174 uint8_t BlockNo = 0;
175 int Pages=16;
176 uint8_t *lockbytes_t=NULL;
177 uint8_t lockbytes[2]={0,0};
178 bool bit[16]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
179 bool dump=false;
180 uint8_t datatemp[5]={0,0,0,0,0};
181
182 uint8_t isOK = 0;
183 uint8_t * data = NULL;
184 FILE *fout;
185
186 if (strchr(Cmd,'x') != 0){
187 dump=true;
188 if ((fout = fopen("dump_ultralight_data.bin","wb")) == NULL) {
189 PrintAndLog("Could not create file name dumpdata.bin");
190 return 1;
191 }
192 PrintAndLog("Dumping Ultralight Card Data...");
193 }
194 PrintAndLog("Attempting to Read Ultralight... ");
195 UsbCommand c = {CMD_MIFAREU_READCARD, {BlockNo, Pages}};
196 SendCommand(&c);
197 UsbCommand resp;
198
199 if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
200 isOK = resp.arg[0] & 0xff;
201 data = resp.d.asBytes;
202 PrintAndLog("isOk:%02x", isOK);
203 if (isOK)
204 for (i = 0; i < Pages; i++) {
205 switch(i){
206 case 2:
207 //process lock bytes
208 lockbytes_t=data+(i*4);
209 lockbytes[0]=lockbytes_t[2];
210 lockbytes[1]=lockbytes_t[3];
211 for(int j=0; j<16; j++){
212 bit[j]=lockbytes[j/8] & ( 1 <<(7-j%8));
213 }
214 PrintAndLog("Block %02x:%s ", i,sprint_hex(data + i * 4, 4));
215 memcpy(datatemp,data + i * 4,4);
216 if (dump) fwrite ( datatemp, 1, 4, fout );
217 break;
218 case 3:
219 PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[4]);
220 memcpy(datatemp,data + i * 4,4);
221 if (dump) fwrite ( datatemp, 1, 4, fout );
222 break;
223 case 4:
224 PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[3]);
225 memcpy(datatemp,data + i * 4,4);
226 if (dump) fwrite ( datatemp, 1, 4, fout );
227 break;
228 case 5:
229 PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[2]);
230 memcpy(datatemp,data + i * 4,4);
231 if (dump) fwrite ( datatemp, 1, 4, fout );
232 break;
233 case 6:
234 PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[1]);
235 memcpy(datatemp,data + i * 4,4);
236 if (dump) fwrite ( datatemp, 1, 4, fout );
237 break;
238 case 7:
239 PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[0]);
240 memcpy(datatemp,data + i * 4,4);
241 if (dump) fwrite ( datatemp, 1, 4, fout );
242 break;
243 case 8:
244 PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[15]);
245 memcpy(datatemp,data + i * 4,4);
246 if (dump) fwrite ( datatemp, 1, 4, fout );
247 break;
248 case 9:
249 PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[14]);
250 memcpy(datatemp,data + i * 4,4);
251 if (dump) fwrite ( datatemp, 1, 4, fout );
252 break;
253 case 10:
254 PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[13]);
255 memcpy(datatemp,data + i * 4,4);
256 if (dump) fwrite ( datatemp, 1, 4, fout );
257 break;
258 case 11:
259 PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[12]);
260 memcpy(datatemp,data + i * 4,4);
261 if (dump) fwrite ( datatemp, 1, 4, fout );
262 break;
263 case 12:
264 PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[11]);
265 memcpy(datatemp,data + i * 4,4);
266 if (dump) fwrite ( datatemp, 1, 4, fout );
267 break;
268 case 13:
269 PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[10]);
270 memcpy(datatemp,data + i * 4,4);
271 if (dump) fwrite ( datatemp, 1, 4, fout );
272 break;
273 case 14:
274 PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[9]);
275 memcpy(datatemp,data + i * 4,4);
276 if (dump) fwrite ( datatemp, 1, 4, fout );
277 break;
278 case 15:
279 PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[8]);
280 memcpy(datatemp,data + i * 4,4);
281 if (dump) fwrite ( datatemp, 1, 4, fout );
282 break;
283 default:
284 PrintAndLog("Block %02x:%s ", i,sprint_hex(data + i * 4, 4));
285 memcpy(datatemp,data + i * 4,4);
286 if (dump) fwrite ( datatemp, 1, 4, fout );
287 break;
288 }
289 }
290 } else {
291 PrintAndLog("Command1 execute timeout");
292 }
293 if (dump) fclose(fout);
294 return 0;
295 }
296
297 int CmdHF14AMfUDump(const char *Cmd){
298 int i;
299 uint8_t BlockNo = 0;
300 int Pages=16;
301 uint8_t *lockbytes_t=NULL;
302 uint8_t lockbytes[2]={0,0};
303 bool bit[16]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
304 bool dump=false;
305 uint8_t datatemp[5]={0,0,0,0,0};
306
307 uint8_t isOK = 0;
308 uint8_t * data = NULL;
309 FILE *fout;
310
311 //if (strchr(Cmd,'x') != 0){
312 dump=true;
313 if ((fout = fopen("dump_ultralight_data.bin","wb")) == NULL) {
314 PrintAndLog("Could not create file name dumpdata.bin");
315 return 1;
316 }
317 PrintAndLog("Dumping Ultralight Card Data...");
318 //}
319 PrintAndLog("Attempting to Read Ultralight... ");
320 UsbCommand c = {CMD_MIFAREU_READCARD, {BlockNo,Pages}};
321 SendCommand(&c);
322 UsbCommand resp;
323
324 if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
325 isOK = resp.arg[0] & 0xff;
326 data = resp.d.asBytes;
327 PrintAndLog("isOk:%02x", isOK);
328 if (isOK)
329 for (i = 0; i < Pages; i++) {
330 switch(i){
331 case 2:
332 //process lock bytes
333 lockbytes_t=data+(i*4);
334 lockbytes[0]=lockbytes_t[2];
335 lockbytes[1]=lockbytes_t[3];
336 for(int j=0; j<16; j++){
337 bit[j]=lockbytes[j/8] & ( 1 <<(7-j%8));
338 }
339 PrintAndLog("Block %02x:%s ", i,sprint_hex(data + i * 4, 4));
340 memcpy(datatemp,data + i * 4,4);
341 if (dump) fwrite ( datatemp, 1, 4, fout );
342 break;
343 case 3:
344 PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[4]);
345 memcpy(datatemp,data + i * 4,4);
346 if (dump) fwrite ( datatemp, 1, 4, fout );
347 break;
348 case 4:
349 PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[3]);
350 memcpy(datatemp,data + i * 4,4);
351 if (dump) fwrite ( datatemp, 1, 4, fout );
352 break;
353 case 5:
354 PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[2]);
355 memcpy(datatemp,data + i * 4,4);
356 if (dump) fwrite ( datatemp, 1, 4, fout );
357 break;
358 case 6:
359 PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[1]);
360 memcpy(datatemp,data + i * 4,4);
361 if (dump) fwrite ( datatemp, 1, 4, fout );
362 break;
363 case 7:
364 PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[0]);
365 memcpy(datatemp,data + i * 4,4);
366 if (dump) fwrite ( datatemp, 1, 4, fout );
367 break;
368 case 8:
369 PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[15]);
370 memcpy(datatemp,data + i * 4,4);
371 if (dump) fwrite ( datatemp, 1, 4, fout );
372 break;
373 case 9:
374 PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[14]);
375 memcpy(datatemp,data + i * 4,4);
376 if (dump) fwrite ( datatemp, 1, 4, fout );
377 break;
378 case 10:
379 PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[13]);
380 memcpy(datatemp,data + i * 4,4);
381 if (dump) fwrite ( datatemp, 1, 4, fout );
382 break;
383 case 11:
384 PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[12]);
385 memcpy(datatemp,data + i * 4,4);
386 if (dump) fwrite ( datatemp, 1, 4, fout );
387 break;
388 case 12:
389 PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[11]);
390 memcpy(datatemp,data + i * 4,4);
391 if (dump) fwrite ( datatemp, 1, 4, fout );
392 break;
393 case 13:
394 PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[10]);
395 memcpy(datatemp,data + i * 4,4);
396 if (dump) fwrite ( datatemp, 1, 4, fout );
397 break;
398 case 14:
399 PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[9]);
400 memcpy(datatemp,data + i * 4,4);
401 if (dump) fwrite ( datatemp, 1, 4, fout );
402 break;
403 case 15:
404 PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[8]);
405 memcpy(datatemp,data + i * 4,4);
406 if (dump) fwrite ( datatemp, 1, 4, fout );
407 break;
408 default:
409 PrintAndLog("Block %02x:%s ", i,sprint_hex(data + i * 4, 4));
410 memcpy(datatemp,data + i * 4,4);
411 if (dump) fwrite ( datatemp, 1, 4, fout );
412 break;
413 }
414 }
415 } else {
416 PrintAndLog("Command1 execute timeout");
417 }
418 if (dump) fclose(fout);
419 return 0;
420 }
421
422 //-------------------------------------------------------------------------------
423 // Ultralight C Methods
424 //-------------------------------------------------------------------------------
425
426 //
427 // Ultralight C Authentication Demo {currently uses hard-coded key}
428 //
429 int CmdHF14AMfucAuth(const char *Cmd){
430
431 uint8_t blockNo = 0, keyNo=0;
432 uint8_t e_RndB[8];
433 uint32_t cuid=0;
434 unsigned char RndARndB[16];
435 uint8_t key[16];
436 DES_cblock RndA, RndB;
437 DES_cblock iv={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
438 DES_key_schedule ks1,ks2;
439 DES_cblock key1,key2;
440
441 if (strlen(Cmd)<1) {
442 PrintAndLog("Usage: hf mfu auth k <key number>");
443 PrintAndLog(" sample: hf mfu auth k 0");
444 return 0;
445 }
446
447 //Change key to user defined one
448 if (strchr(Cmd,'k') != 0){
449 //choose a key
450 keyNo = param_get8(Cmd, 1);
451 switch(keyNo){
452 case 0:
453 memcpy(key,key1_blnk_data,16);
454 break;
455 case 1:
456 memcpy(key,key2_defa_data,16);
457 break;
458 case 2:
459 memcpy(key,key4_nfc_data,16);
460 break;
461 default:
462 memcpy(key,key3_3des_data,16);
463 break;
464 }
465 }else{
466 memcpy(key,key3_3des_data,16);
467 }
468 memcpy(key1,key,8);
469 memcpy(key2,key+8,8);
470 DES_set_key((DES_cblock *)key1,&ks1);
471 DES_set_key((DES_cblock *)key2,&ks2);
472
473 //Auth1
474 UsbCommand c = {CMD_MIFAREUC_AUTH1, {blockNo}};
475 SendCommand(&c);
476 UsbCommand resp;
477 if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
478 uint8_t isOK = resp.arg[0] & 0xff;
479 cuid = resp.arg[1];
480 uint8_t * data= resp.d.asBytes;
481
482 if (isOK){
483 PrintAndLog("enc(RndB):%s", sprint_hex(data+1, 8));
484 memcpy(e_RndB,data+1,8);
485 }
486 } else {
487 PrintAndLog("Command execute timeout");
488 }
489
490 //Do crypto magic
491 DES_random_key(&RndA);
492 DES_ede2_cbc_encrypt(e_RndB,RndB,sizeof(e_RndB),&ks1,&ks2,&iv,0);
493 PrintAndLog(" RndB:%s",sprint_hex(RndB, 8));
494 PrintAndLog(" RndA:%s",sprint_hex(RndA, 8));
495 rol(RndB,8);
496 memcpy(RndARndB,RndA,8);
497 memcpy(RndARndB+8,RndB,8);
498 PrintAndLog(" RA+B:%s",sprint_hex(RndARndB, 16));
499 DES_ede2_cbc_encrypt(RndARndB,RndARndB,sizeof(RndARndB),&ks1,&ks2,&e_RndB,1);
500 PrintAndLog("enc(RA+B):%s",sprint_hex(RndARndB, 16));
501
502 //Auth2
503 UsbCommand d = {CMD_MIFAREUC_AUTH2, {cuid}};
504 memcpy(d.d.asBytes,RndARndB, 16);
505 SendCommand(&d);
506
507 UsbCommand respb;
508 if (WaitForResponseTimeout(CMD_ACK,&respb,1500)) {
509 uint8_t isOK = respb.arg[0] & 0xff;
510 uint8_t * data2= respb.d.asBytes;
511
512 if (isOK){
513 PrintAndLog("enc(RndA'):%s", sprint_hex(data2+1, 8));
514 }
515
516 } else {
517 PrintAndLog("Command execute timeout");
518 }
519 return 1;
520 }
521
522 //
523 // Ultralight C Read Single Block
524 //
525 int CmdHF14AMfUCRdBl(const char *Cmd)
526 {
527
528 uint8_t blockNo = 0;
529
530 if (strlen(Cmd)<1) {
531 PrintAndLog("Usage: hf mfu ucrdbl <block number>");
532 PrintAndLog(" sample: hf mfu ucrdbl 0");
533 return 0;
534 }
535
536 blockNo = param_get8(Cmd, 0);
537 if (blockNo>MAX_ULTRAC_BLOCKS){
538 PrintAndLog("Error: Maximum number of readable blocks is 44 for Ultralight Cards!");
539 return 1;
540 }
541 PrintAndLog("--block no:%02x", (int)blockNo);
542
543 //Read Block
544 UsbCommand e = {CMD_MIFAREU_READBL, {blockNo}};
545 SendCommand(&e);
546 UsbCommand resp_c;
547 if (WaitForResponseTimeout(CMD_ACK,&resp_c,1500)) {
548 uint8_t isOK = resp_c.arg[0] & 0xff;
549 uint8_t * data = resp_c.d.asBytes;
550 if (isOK)
551 PrintAndLog("isOk:%02x data:%s", isOK, sprint_hex(data, 4));
552 else
553 PrintAndLog("isOk:%02x", isOK);
554 } else {
555 PrintAndLog("Command execute timeout");
556 }
557 return 0;
558 }
559
560 //
561 // Ultralight C Read (or Dump) Card Contents
562 //
563 int CmdHF14AMfUCRdCard(const char *Cmd){
564 int i;
565 uint8_t BlockNo = 0;
566 int Pages=44;
567 uint8_t *lockbytes_t=NULL;
568 uint8_t lockbytes[2]={0,0};
569 uint8_t *lockbytes_t2=NULL;
570 uint8_t lockbytes2[2]={0,0};
571 bool bit[16]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
572 bool bit2[16]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
573 bool dump=false;
574 uint8_t datatemp[5]={0,0,0,0,0};
575
576 uint8_t isOK = 0;
577 uint8_t * data = NULL;
578 FILE *fout;
579
580 if (strchr(Cmd,'x') != 0){
581 dump=true;
582 if ((fout = fopen("dump_ultralightc_data.bin","wb")) == NULL) {
583 PrintAndLog("Could not create file name dumpdata.bin");
584 return 1;
585 }
586 PrintAndLog("Dumping Ultralight C Card Data...");
587 }
588 PrintAndLog("Attempting to Read Ultralight C... ");
589 UsbCommand c = {CMD_MIFAREUC_READCARD, {BlockNo, Pages}};
590 SendCommand(&c);
591 UsbCommand resp;
592
593 if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
594 isOK = resp.arg[0] & 0xff;
595 data = resp.d.asBytes;
596 //Pages=sizeof(data)/sizeof(data[0]);
597 PrintAndLog("isOk:%02x", isOK);
598 if (isOK)
599 for (i = 0; i < Pages; i++) {
600 switch(i){
601 case 2:
602 //process lock bytes
603 lockbytes_t=data+(i*4);
604 lockbytes[0]=lockbytes_t[2];
605 lockbytes[1]=lockbytes_t[3];
606 for(int j=0; j<16; j++){
607 bit[j]=lockbytes[j/8] & ( 1 <<(7-j%8));
608 }
609 //might as well read bottom lockbytes too
610 lockbytes_t2=data+(40*4);
611 lockbytes2[0]=lockbytes_t2[2];
612 lockbytes2[1]=lockbytes_t2[3];
613 for(int j=0; j<16; j++){
614 bit2[j]=lockbytes2[j/8] & ( 1 <<(7-j%8));
615 }
616 PrintAndLog("Block %02x:%s ", i,sprint_hex(data + i * 4, 4));
617 memcpy(datatemp,data + i * 4,4);
618 if (dump) fwrite ( datatemp, 1, 4, fout );
619 break;
620 case 3:
621 PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[4]);
622 memcpy(datatemp,data + i * 4,4);
623 if (dump) fwrite ( datatemp, 1, 4, fout );
624 break;
625 case 4:
626 PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[3]);
627 memcpy(datatemp,data + i * 4,4);
628 if (dump) fwrite ( datatemp, 1, 4, fout );
629 break;
630 case 5:
631 PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[2]);
632 memcpy(datatemp,data + i * 4,4);
633 if (dump) fwrite ( datatemp, 1, 4, fout );
634 break;
635 case 6:
636 PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[1]);
637 memcpy(datatemp,data + i * 4,4);
638 if (dump) fwrite ( datatemp, 1, 4, fout );
639 break;
640 case 7:
641 PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[0]);
642 memcpy(datatemp,data + i * 4,4);
643 if (dump) fwrite ( datatemp, 1, 4, fout );
644 break;
645 case 8:
646 PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[15]);
647 memcpy(datatemp,data + i * 4,4);
648 if (dump) fwrite ( datatemp, 1, 4, fout );
649 break;
650 case 9:
651 PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[14]);
652 memcpy(datatemp,data + i * 4,4);
653 if (dump) fwrite ( datatemp, 1, 4, fout );
654 break;
655 case 10:
656 PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[13]);
657 memcpy(datatemp,data + i * 4,4);
658 if (dump) fwrite ( datatemp, 1, 4, fout );
659 break;
660 case 11:
661 PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[12]);
662 memcpy(datatemp,data + i * 4,4);
663 if (dump) fwrite ( datatemp, 1, 4, fout );
664 break;
665 case 12:
666 PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[11]);
667 memcpy(datatemp,data + i * 4,4);
668 if (dump) fwrite ( datatemp, 1, 4, fout );
669 break;
670 case 13:
671 PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[10]);
672 memcpy(datatemp,data + i * 4,4);
673 if (dump) fwrite ( datatemp, 1, 4, fout );
674 break;
675 case 14:
676 PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[9]);
677 memcpy(datatemp,data + i * 4,4);
678 if (dump) fwrite ( datatemp, 1, 4, fout );
679 break;
680 case 15:
681 PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[8]);
682 memcpy(datatemp,data + i * 4,4);
683 if (dump) fwrite ( datatemp, 1, 4, fout );
684 break;
685 case 16:
686 case 17:
687 case 18:
688 case 19:
689 PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit2[6]);
690 memcpy(datatemp,data + i * 4,4);
691 if (dump) fwrite ( datatemp, 1, 4, fout );
692 break;
693 case 20:
694 case 21:
695 case 22:
696 case 23:
697 PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit2[5]);
698 memcpy(datatemp,data + i * 4,4);
699 if (dump) fwrite ( datatemp, 1, 4, fout );
700 break;
701 case 24:
702 case 25:
703 case 26:
704 case 27:
705 PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit2[4]);
706 memcpy(datatemp,data + i * 4,4);
707 if (dump) fwrite ( datatemp, 1, 4, fout );
708 break;
709 case 28:
710 case 29:
711 case 30:
712 case 31:
713 PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit2[2]);
714 memcpy(datatemp,data + i * 4,4);
715 if (dump) fwrite ( datatemp, 1, 4, fout );
716 break;
717 case 32:
718 case 33:
719 case 34:
720 case 35:
721 PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit2[1]);
722 memcpy(datatemp,data + i * 4,4);
723 if (dump) fwrite ( datatemp, 1, 4, fout );
724 break;
725 case 36:
726 case 37:
727 case 38:
728 case 39:
729 PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit2[0]);
730 memcpy(datatemp,data + i * 4,4);
731 if (dump) fwrite ( datatemp, 1, 4, fout );
732 break;
733 case 40:
734 PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit2[12]);
735 memcpy(datatemp,data + i * 4,4);
736 if (dump) fwrite ( datatemp, 1, 4, fout );
737 break;
738 case 41:
739 PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit2[11]);
740 memcpy(datatemp,data + i * 4,4);
741 if (dump) fwrite ( datatemp, 1, 4, fout );
742 break;
743 case 42:
744 //auth0
745 PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit2[10]);
746 memcpy(datatemp,data + i * 4,4);
747 if (dump) fwrite ( datatemp, 1, 4, fout );
748 break;
749 case 43:
750 //auth1
751 PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit2[9]);
752 memcpy(datatemp,data + i * 4,4);
753 if (dump) fwrite ( datatemp, 1, 4, fout );
754 break;
755 default:
756 PrintAndLog("Block %02x:%s ", i,sprint_hex(data + i * 4, 4));
757 memcpy(datatemp,data + i * 4,4);
758 if (dump) fwrite ( datatemp, 1, 4, fout );
759 break;
760 }
761 }
762
763 } else {
764 PrintAndLog("Command1 execute timeout");
765 }
766 if (dump) fclose(fout);
767 return 0;
768 }
769
770 //
771 // Ultralight C Dump Card Contents to file
772 //
773 int CmdHF14AMfUCDump(const char *Cmd){
774 int i;
775 uint8_t BlockNo = 0;
776 int Pages=44;
777 uint8_t *lockbytes_t=NULL;
778 uint8_t lockbytes[2]={0,0};
779 uint8_t *lockbytes_t2=NULL;
780 uint8_t lockbytes2[2]={0,0};
781 bool bit[16]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
782 bool bit2[16]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
783 bool dump=false;
784 uint8_t datatemp[5]={0,0,0,0,0};
785
786 uint8_t isOK = 0;
787 uint8_t * data = NULL;
788 FILE *fout;
789
790 //if (strchr(Cmd,'x') != 0){
791 dump=true;
792 if ((fout = fopen("dump_ultralightc_data.bin","wb")) == NULL) {
793 PrintAndLog("Could not create file name dumpdata.bin");
794 return 1;
795 }
796 PrintAndLog("Dumping Ultralight C Card Data...");
797 //}
798 PrintAndLog("Attempting to Read Ultralight C... ");
799 UsbCommand c = {CMD_MIFAREU_READCARD, {BlockNo,Pages}};
800 SendCommand(&c);
801 UsbCommand resp;
802
803 if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
804 isOK = resp.arg[0] & 0xff;
805 data = resp.d.asBytes;
806 PrintAndLog("isOk:%02x", isOK);
807 if (isOK)
808 for (i = 0; i < Pages; i++) {
809 switch(i){
810 case 2:
811 //process lock bytes
812 lockbytes_t=data+(i*4);
813 lockbytes[0]=lockbytes_t[2];
814 lockbytes[1]=lockbytes_t[3];
815 for(int j=0; j<16; j++){
816 bit[j]=lockbytes[j/8] & ( 1 <<(7-j%8));
817
818 }
819 //might as well read bottom lockbytes too
820 lockbytes_t2=data+(40*4);
821 lockbytes2[0]=lockbytes_t2[2];
822 lockbytes2[1]=lockbytes_t2[3];
823 for(int j=0; j<16; j++){
824 bit2[j]=lockbytes2[j/8] & ( 1 <<(7-j%8));
825 }
826
827 PrintAndLog("Block %02x:%s ", i,sprint_hex(data + i * 4, 4));
828 memcpy(datatemp,data + i * 4,4);
829 if (dump) fwrite ( datatemp, 1, 4, fout );
830 break;
831 case 3:
832 PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[4]);
833 memcpy(datatemp,data + i * 4,4);
834 if (dump) fwrite ( datatemp, 1, 4, fout );
835 break;
836 case 4:
837 PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[3]);
838 memcpy(datatemp,data + i * 4,4);
839 if (dump) fwrite ( datatemp, 1, 4, fout );
840 break;
841 case 5:
842 PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[2]);
843 memcpy(datatemp,data + i * 4,4);
844 if (dump) fwrite ( datatemp, 1, 4, fout );
845 break;
846 case 6:
847 PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[1]);
848 memcpy(datatemp,data + i * 4,4);
849 if (dump) fwrite ( datatemp, 1, 4, fout );
850 break;
851 case 7:
852 PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[0]);
853 memcpy(datatemp,data + i * 4,4);
854 if (dump) fwrite ( datatemp, 1, 4, fout );
855 break;
856 case 8:
857 PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[15]);
858 memcpy(datatemp,data + i * 4,4);
859 if (dump) fwrite ( datatemp, 1, 4, fout );
860 break;
861 case 9:
862 PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[14]);
863 memcpy(datatemp,data + i * 4,4);
864 if (dump) fwrite ( datatemp, 1, 4, fout );
865 break;
866 case 10:
867 PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[13]);
868 memcpy(datatemp,data + i * 4,4);
869 if (dump) fwrite ( datatemp, 1, 4, fout );
870 break;
871 case 11:
872 PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[12]);
873 memcpy(datatemp,data + i * 4,4);
874 if (dump) fwrite ( datatemp, 1, 4, fout );
875 break;
876 case 12:
877 PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[11]);
878 memcpy(datatemp,data + i * 4,4);
879 if (dump) fwrite ( datatemp, 1, 4, fout );
880 break;
881 case 13:
882 PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[10]);
883 memcpy(datatemp,data + i * 4,4);
884 if (dump) fwrite ( datatemp, 1, 4, fout );
885 break;
886 case 14:
887 PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[9]);
888 memcpy(datatemp,data + i * 4,4);
889 if (dump) fwrite ( datatemp, 1, 4, fout );
890 break;
891 case 15:
892 PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[8]);
893 memcpy(datatemp,data + i * 4,4);
894 if (dump) fwrite ( datatemp, 1, 4, fout );
895 break;
896 case 16:
897 case 17:
898 case 18:
899 case 19:
900 PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit2[6]);
901 memcpy(datatemp,data + i * 4,4);
902 if (dump) fwrite ( datatemp, 1, 4, fout );
903 break;
904 case 20:
905 case 21:
906 case 22:
907 case 23:
908 PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit2[5]);
909 memcpy(datatemp,data + i * 4,4);
910 if (dump) fwrite ( datatemp, 1, 4, fout );
911 break;
912 case 24:
913 case 25:
914 case 26:
915 case 27:
916 PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit2[4]);
917 memcpy(datatemp,data + i * 4,4);
918 if (dump) fwrite ( datatemp, 1, 4, fout );
919 break;
920 case 28:
921 case 29:
922 case 30:
923 case 31:
924 PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit2[2]);
925 memcpy(datatemp,data + i * 4,4);
926 if (dump) fwrite ( datatemp, 1, 4, fout );
927 break;
928 case 32:
929 case 33:
930 case 34:
931 case 35:
932 PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit2[1]);
933 memcpy(datatemp,data + i * 4,4);
934 if (dump) fwrite ( datatemp, 1, 4, fout );
935 break;
936 case 36:
937 case 37:
938 case 38:
939 case 39:
940 PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit2[0]);
941 memcpy(datatemp,data + i * 4,4);
942 if (dump) fwrite ( datatemp, 1, 4, fout );
943 break;
944 case 40:
945 PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit2[12]);
946 memcpy(datatemp,data + i * 4,4);
947 if (dump) fwrite ( datatemp, 1, 4, fout );
948 break;
949 case 41:
950 PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit2[11]);
951 memcpy(datatemp,data + i * 4,4);
952 if (dump) fwrite ( datatemp, 1, 4, fout );
953 break;
954 case 42:
955 //auth0
956 PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit2[10]);
957 memcpy(datatemp,data + i * 4,4);
958 if (dump) fwrite ( datatemp, 1, 4, fout );
959 break;
960 case 43:
961 //auth1
962 PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit2[9]);
963 memcpy(datatemp,data + i * 4,4);
964 if (dump) fwrite ( datatemp, 1, 4, fout );
965 break;
966 default:
967 PrintAndLog("Block %02x:%s ", i,sprint_hex(data + i * 4, 4));
968 memcpy(datatemp,data + i * 4,4);
969 if (dump) fwrite ( datatemp, 1, 4, fout );
970 break;
971 }
972 }
973
974 } else {
975 PrintAndLog("Command1 execute timeout");
976 }
977 if (dump) fclose(fout);
978 return 0;
979 }
980
981 //
982 // Mifare Ultralight C Write Single Block
983 //
984 int CmdHF14AMfUCWrBl(const char *Cmd){
985
986 uint8_t blockNo = 0;
987 bool chinese_card=0;
988 uint8_t bldata[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
989 UsbCommand resp;
990
991 if (strlen(Cmd)<3) {
992 PrintAndLog("Usage: hf mfu ucwrbl <block number> <block data (8 hex symbols)> [w]");
993 PrintAndLog(" sample: hf mfu uwrbl 0 01020304");
994 return 0;
995 }
996 blockNo = param_get8(Cmd, 0);
997 if (blockNo>(MAX_ULTRAC_BLOCKS+4)){
998 PrintAndLog("Error: Maximum number of blocks is 47 for Ultralight Cards!");
999 return 1;
1000 }
1001 if (param_gethex(Cmd, 1, bldata, 8)) {
1002 PrintAndLog("Block data must include 8 HEX symbols");
1003 return 1;
1004 }
1005 if (strchr(Cmd,'w') != 0) {
1006 chinese_card=1;
1007 }
1008 switch(blockNo){
1009 case 0:
1010 if (!chinese_card){
1011 PrintAndLog("Access Denied");
1012 }else{
1013 PrintAndLog("--specialblock no:%02x", blockNo);
1014 PrintAndLog("--data: %s", sprint_hex(bldata, 4));
1015 UsbCommand d = {CMD_MIFAREU_WRITEBL, {blockNo}};
1016 memcpy(d.d.asBytes,bldata, 4);
1017 SendCommand(&d);
1018 if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
1019 uint8_t isOK = resp.arg[0] & 0xff;
1020 PrintAndLog("isOk:%02x", isOK);
1021 } else {
1022 PrintAndLog("Command execute timeout");
1023 }
1024 }
1025 break;
1026 case 1:
1027 if (!chinese_card){
1028 PrintAndLog("Access Denied");
1029 }else{
1030 PrintAndLog("--specialblock no:%02x", blockNo);
1031 PrintAndLog("--data: %s", sprint_hex(bldata, 4));
1032 UsbCommand d = {CMD_MIFAREU_WRITEBL, {blockNo}};
1033 memcpy(d.d.asBytes,bldata, 4);
1034 SendCommand(&d);
1035 if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
1036 uint8_t isOK = resp.arg[0] & 0xff;
1037 PrintAndLog("isOk:%02x", isOK);
1038 } else {
1039 PrintAndLog("Command execute timeout");
1040 }
1041 }
1042 break;
1043 case 2:
1044 if (!chinese_card){
1045 PrintAndLog("Access Denied");
1046 }else{
1047 PrintAndLog("--specialblock no:%02x", blockNo);
1048 PrintAndLog("--data: %s", sprint_hex(bldata, 4));
1049 UsbCommand c = {CMD_MIFAREU_WRITEBL, {blockNo}};
1050 memcpy(c.d.asBytes, bldata, 4);
1051 SendCommand(&c);
1052 if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
1053 uint8_t isOK = resp.arg[0] & 0xff;
1054 PrintAndLog("isOk:%02x", isOK);
1055 } else {
1056 PrintAndLog("Command execute timeout");
1057 }
1058 }
1059 break;
1060 case 3:
1061 PrintAndLog("--specialblock no:%02x", blockNo);
1062 PrintAndLog("--data: %s", sprint_hex(bldata, 4));
1063 UsbCommand d = {CMD_MIFAREU_WRITEBL, {blockNo}};
1064 memcpy(d.d.asBytes,bldata, 4);
1065 SendCommand(&d);
1066 if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
1067 uint8_t isOK = resp.arg[0] & 0xff;
1068 PrintAndLog("isOk:%02x", isOK);
1069 } else {
1070 PrintAndLog("Command execute timeout");
1071 }
1072 break;
1073 default:
1074 PrintAndLog("--block no:%02x", blockNo);
1075 PrintAndLog("--data: %s", sprint_hex(bldata, 4));
1076 UsbCommand e = {CMD_MIFAREU_WRITEBL, {blockNo}};
1077 memcpy(e.d.asBytes,bldata, 4);
1078 SendCommand(&e);
1079 if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
1080 uint8_t isOK = resp.arg[0] & 0xff;
1081 PrintAndLog("isOk:%02x", isOK);
1082 } else {
1083 PrintAndLog("Command execute timeout");
1084 }
1085 break;
1086 }
1087 return 0;
1088 }
1089
1090 //------------------------------------
1091 // Menu Stuff
1092 //------------------------------------
1093 static command_t CommandTable[] =
1094 {
1095 {"help", CmdHelp, 1,"This help"},
1096 {"dbg", CmdHF14AMfDbg, 0,"Set default debug mode"},
1097 {"urdbl", CmdHF14AMfURdBl, 0,"Read MIFARE Ultralight block"},
1098 {"urdcard", CmdHF14AMfURdCard, 0,"Read MIFARE Ultralight Card"},
1099 {"udump", CmdHF14AMfUDump, 0,"Dump MIFARE Ultralight tag to binary file"},
1100 {"uwrbl", CmdHF14AMfUWrBl, 0,"Write MIFARE Ultralight block"},
1101 {"ucrdbl", CmdHF14AMfUCRdBl, 0,"Read MIFARE Ultralight C block"},
1102 {"ucrdcard",CmdHF14AMfUCRdCard, 0,"Read MIFARE Ultralight C Card"},
1103 {"ucdump", CmdHF14AMfUCDump, 0,"Dump MIFARE Ultralight C tag to binary file"},
1104 {"ucwrbl", CmdHF14AMfUCWrBl, 0,"Write MIFARE Ultralight C block"},
1105 {"auth", CmdHF14AMfucAuth, 0,"Ultralight C Authentication"},
1106 {NULL, NULL, 0, NULL}
1107 };
1108
1109 int CmdHFMFUltra(const char *Cmd){
1110 // flush
1111 WaitForResponseTimeout(CMD_ACK,NULL,100);
1112 CmdsParse(CommandTable, Cmd);
1113 return 0;
1114 }
1115
1116 int CmdHelp(const char *Cmd){
1117 CmdsHelp(CommandTable);
1118 return 0;
1119 }
Impressum, Datenschutz