From 8581fec47cdd352c924b08046149c02d69a4d980 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 26 Aug 2017 13:01:35 +0200 Subject: [PATCH] ...added the standalone folder.. --- armsrc/Standalone/hf_colin.c | 357 +++++++++++++++++++++++++++++++++ armsrc/Standalone/hf_colin.h | 21 ++ armsrc/Standalone/hf_young.c | 263 ++++++++++++++++++++++++ armsrc/Standalone/hf_young.h | 22 ++ armsrc/Standalone/lf_samyrun.c | 134 +++++++++++++ armsrc/Standalone/lf_samyrun.h | 21 ++ armsrc/Standalone/readme.md | 24 +++ armsrc/Standalone/standalone.h | 18 ++ armsrc/obj/Standalone/.dummy | 0 9 files changed, 860 insertions(+) create mode 100644 armsrc/Standalone/hf_colin.c create mode 100644 armsrc/Standalone/hf_colin.h create mode 100644 armsrc/Standalone/hf_young.c create mode 100644 armsrc/Standalone/hf_young.h create mode 100644 armsrc/Standalone/lf_samyrun.c create mode 100644 armsrc/Standalone/lf_samyrun.h create mode 100644 armsrc/Standalone/readme.md create mode 100644 armsrc/Standalone/standalone.h create mode 100644 armsrc/obj/Standalone/.dummy diff --git a/armsrc/Standalone/hf_colin.c b/armsrc/Standalone/hf_colin.c new file mode 100644 index 000000000..acbf043c1 --- /dev/null +++ b/armsrc/Standalone/hf_colin.c @@ -0,0 +1,357 @@ +//----------------------------------------------------------------------------- +// Colin Brigato, 2016,2017 +// Christian Herrmann, 2017 +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// main code for HF Mifare aka ColinRun by Colin Brigato +//----------------------------------------------------------------------------- +#include "hf_colin.h" + +// Colin's sniff and 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; + + /* know number of known keys for standalone mode */ + #define STKEYS 35 + uint64_t mfKeys[STKEYS] = { + 0xffffffffffff, // TRANSPORTS + 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 + /* . . * / + } + + /* Can remember something like that in case of Bigbuf */ + keyBlock = BigBuf_malloc(STKEYS * 6); + int mfKeysCnt = sizeof(mfKeys) / sizeof(uint64_t); + + for (int mfKeyCounter = 0; mfKeyCounter < mfKeysCnt; mfKeyCounter++) { + 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 ? */ + + int key = -1; + 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 */ + + Dbprintf("...Waiting For Tag..."); + iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); + while (!iso14443a_select_card(cjuid, NULL, &cjcuid)) { + WDT_HIT(); + } + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + SpinDelay(100); + + Dbprintf("Got tag : %02x%02x%02x%02x", at91stdio_explode(cjuid, &cjcuid)); + + uint32_t end_time; + uint32_t start_time = end_time = GetTickCount(); + + /* 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); + if (key == -1) { + err = 1; + /* 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); + 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]); + 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); + + switch (key64) { + 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_); + ; + 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); + } + 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + trapped = 1; + break; + 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_); + // emlClearMem(); + 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); + } + } + trapped = 1; + break; + case 0x414c41524f4e: + 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_); + ; + 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); + } + 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); + } + trapped = 1; + break; + } + /* etc etc for testing schemes quick schemes */ + } + } + } + + if (!allKeysFound) { + cmd_send(CMD_CJB_FSMSTATE_MENU, 0, 0, 0, 0, 0); + 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); + } + Dbprintf("%c>>%c Setting Keys->Emulator MEM...[%cOK%c]", _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_); + + /* 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); + return; + } + } +/* . . . */ + +/* 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) { + + MF_DBGLEVEL = MF_DBG_NONE; + iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); + set_tracing(FALSE); + + for (i = 0; i < keyCount; ++i) { + /* no need for anticollision. just verify tag is still here */ + if (!iso14443a_select_card(uid, NULL, &cuid)) { + cjat91_printf("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)) { + + uint8_t dummy_answer = 0; + ReaderTransmit(&dummy_answer, 1, NULL); + timeout = GetCountSspClk() + AUTHENTICATION_TIMEOUT; + + // wait for the card to become ready again + while(GetCountSspClk() < 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 new file mode 100644 index 000000000..fa419de3f --- /dev/null +++ b/armsrc/Standalone/hf_colin.h @@ -0,0 +1,21 @@ +//----------------------------------------------------------------------------- +// Colin Brigato 2016, 2017 +// Christian Herrmann, 2017 +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// StandAlone Mod +//----------------------------------------------------------------------------- + +#ifndef __HF_COLIN_H +#define __HF_COLIN_H + +#include // for bool +#include "standalone.h" // standalone definitions +#include "iso14443a.h" +#include "protocols.h" + + +#endif /* __HF_COLIN_H */ \ No newline at end of file diff --git a/armsrc/Standalone/hf_young.c b/armsrc/Standalone/hf_young.c new file mode 100644 index 000000000..5db6aa3df --- /dev/null +++ b/armsrc/Standalone/hf_young.c @@ -0,0 +1,263 @@ +//----------------------------------------------------------------------------- +// Craig Young, 2014 +// Christian Herrmann, 2017 +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// main code for HF standalone mode Mifare /sniff/emulation by Craig Young +//----------------------------------------------------------------------------- +#include "hf_young.h" + +typedef struct { + uint8_t uid[10]; + uint8_t uidlen; + uint8_t atqa[2]; + uint8_t sak; +} __attribute__((__packed__)) card_clone_t; + + +void RunMod() { + StandAloneMode(); + FpgaDownloadAndGo(FPGA_BITSTREAM_HF); + + int selected = 0, playing = 0, iGotoRecord = 0, iGotoClone = 0; + int cardRead[OPTS] = {0}; + + card_clone_t uids[OPTS]; + iso14a_card_select_t card[OPTS]; + uint8_t params = (MAGIC_SINGLE | MAGIC_DATAIN); + + LED(selected + 1, 0); + + for (;;) { + WDT_HIT(); + // exit from Standalone Mode, send a usbcommand. + if (usb_poll_validate_length()) goto out; + + SpinDelay(300); + + if (iGotoRecord == 1 || cardRead[selected] == 0) { + iGotoRecord = 0; + LEDsoff(); + LED(selected + 1, 0); + LED(LED_RED2, 0); + + // record + Dbprintf("Enabling iso14443a reader mode for [Bank: %d]...", selected); + /* need this delay to prevent catching some weird data */ + SpinDelay(500); + iso14443a_setup(FPGA_HF_ISO14443A_READER_MOD); + + for (;;) { + // exit from Standalone Mode, send a usbcommand. + if (usb_poll_validate_length()) goto out; + + if (BUTTON_PRESS()) { + if (cardRead[selected]) { + Dbprintf("Button press detected -- replaying card in bank[%d]", selected); + break; + } else if (cardRead[(selected+1) % OPTS]) { + Dbprintf("Button press detected but no card in bank[%d] so playing from bank[%d]", selected, (selected+1)%OPTS); + selected = (selected+1) % OPTS; + break; // playing = 1; + } else { + Dbprintf("Button press detected but no stored tag to play. (Ignoring button)"); + SpinDelay(300); + } + } + + if (!iso14443a_select_card(NULL, &card[selected], NULL, true, 0)) { + continue; + } else { + Dbprintf("Read UID:"); + Dbhexdump(card[selected].uidlen, card[selected].uid, 0); + + if (memcmp(uids[(selected+1)%OPTS].uid, card[selected].uid, card[selected].uidlen ) == 0 ) { + Dbprintf("Card selected has same UID as what is stored in the other bank. Skipping."); + } else { + uids[selected].sak = card[selected].sak; + uids[selected].uidlen = card[selected].uidlen; + memcpy(uids[selected].uid , card[selected].uid, uids[selected].uidlen); + memcpy(uids[selected].atqa, card[selected].atqa, 2); + + if (uids[selected].uidlen > 4) + Dbprintf("Bank[%d] received a 7-byte UID", selected); + else + Dbprintf("Bank[%d] received a 4-byte UID", selected); + break; + } + } + } + + Dbprintf("ATQA = %02X%02X", uids[selected].atqa[0], uids[selected].atqa[1]); + Dbprintf("SAK = %02X", uids[selected].sak); + LEDsoff(); + LED(LED_GREEN, 200); + LED(LED_ORANGE, 200); + LED(LED_GREEN, 200); + LED(LED_ORANGE, 200); + + LEDsoff(); + LED(selected + 1, 0); + + // Next state is replay: + playing = 1; + + cardRead[selected] = 1; + } + + /* MF Classic UID clone */ + else if (iGotoClone==1) { + iGotoClone=0; + LEDsoff(); + LED(selected + 1, 0); + LED(LED_ORANGE, 250); + + // magiccards holds 4bytes uid. *usually* + uint32_t tmpuid = bytes_to_num(uids[selected].uid, 4); + + // record + Dbprintf("Preparing to Clone card [Bank: %d]; uid: %08x", selected, tmpuid); + + // wait for button to be released + // Delay cloning until card is in place + while(BUTTON_PRESS()) + WDT_HIT(); + + Dbprintf("Starting clone. [Bank: %d]", selected); + // need this delay to prevent catching some weird data + SpinDelay(500); + // Begin clone function here: + /* Example from client/mifarehost.c for commanding a block write for "magic Chinese" cards: + UsbCommand c = {CMD_MIFARE_CSETBLOCK, {params & (0xFE | (uid == NULL ? 0:1)), blockNo, 0}}; + memcpy(c.d.asBytes, data, 16); + SendCommand(&c); + + Block read is similar: + UsbCommand c = {CMD_MIFARE_CGETBLOCK, {params, blockNo, 0}}; + We need to imitate that call with blockNo 0 to set a uid. + + The get and set commands are handled in this file: + // 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; + + mfCSetUID provides example logic for UID set workflow: + -Read block0 from card in field with MifareCGetBlock() + -Configure new values without replacing reserved bytes + memcpy(block0, uid, 4); // Copy UID bytes from byte array + // Mifare UID BCC + block0[4] = block0[0]^block0[1]^block0[2]^block0[3]; // BCC on byte 5 + Bytes 5-7 are reserved SAK and ATQA for mifare classic + -Use mfCSetBlock(0, block0, oldUID, wantWipe, MAGIC_SINGLE) to write it + */ + uint8_t oldBlock0[16] = {0}, newBlock0[16] = {0}, testBlock0[16] = {0}; + // arg0 = Flags, arg1=blockNo + MifareCGetBlock(params, 0, oldBlock0); + if (oldBlock0[0] == 0 && oldBlock0[0] == oldBlock0[1] && oldBlock0[1] == oldBlock0[2] && oldBlock0[2] == oldBlock0[3]) { + Dbprintf("No changeable tag detected. Returning to replay mode for bank[%d]", selected); + playing = 1; + } else { + Dbprintf("UID from target tag: %02X%02X%02X%02X", oldBlock0[0], oldBlock0[1], oldBlock0[2], oldBlock0[3]); + memcpy(newBlock0, oldBlock0, 16); + + // Copy uid for bank (2nd is for longer UIDs not supported if classic) + memcpy(newBlock0, uids[selected].uid, 4); + newBlock0[4] = newBlock0[0] ^ newBlock0[1] ^ newBlock0[2] ^ newBlock0[3]; + + // arg0 = workFlags, arg1 = blockNo, datain + MifareCSetBlock(params, 0, newBlock0); + MifareCGetBlock(params, 0, testBlock0); + + if (memcmp(testBlock0, newBlock0, 16)==0) { + DbpString("Cloned successfull!"); + cardRead[selected] = 0; // Only if the card was cloned successfully should we clear it + playing = 0; + iGotoRecord = 1; + selected = (selected + 1) % OPTS; + } else { + Dbprintf("Clone failed. Back to replay mode on bank[%d]", selected); + playing = 1; + } + } + LEDsoff(); + LED(selected + 1, 0); + } + + // Change where to record (or begin playing) + // button_pressed == BUTTON_SINGLE_CLICK && cardRead[selected]) + else if (playing==1) { + LEDsoff(); + LED(selected + 1, 0); + + // Begin transmitting + LED(LED_GREEN, 0); + DbpString("Playing"); + for ( ; ; ) { + // exit from Standalone Mode, send a usbcommand. + if (usb_poll_validate_length()) goto out; + + int button_action = BUTTON_HELD(1000); + if ( button_action == 0) { // No button action, proceed with sim + + uint8_t flags = FLAG_4B_UID_IN_DATA; + uint8_t data[USB_CMD_DATA_SIZE] = {0}; // in case there is a read command received we shouldn't break + + memcpy(data, uids[selected].uid, uids[selected].uidlen); + + uint64_t tmpuid = bytes_to_num(uids[selected].uid, uids[selected].uidlen); + + if ( uids[selected].uidlen == 7 ) { + flags = FLAG_7B_UID_IN_DATA; + Dbprintf("Simulating ISO14443a tag with uid: %014" PRIx64 " [Bank: %d]", tmpuid, selected); + } else { + Dbprintf("Simulating ISO14443a tag with uid: %08" PRIx64 " [Bank: %d]", tmpuid, selected); + } + + if (uids[selected].sak == 0x08 && uids[selected].atqa[0] == 0x04 && uids[selected].atqa[1] == 0) { + DbpString("Mifare Classic 1k"); + SimulateIso14443aTag(1, flags, data); + } else if (uids[selected].sak == 0x18 && uids[selected].atqa[0] == 0x02 && uids[selected].atqa[1] == 0) { + DbpString("Mifare Classic 4k (4b uid)"); + SimulateIso14443aTag(8, flags, data); + } else if (uids[selected].sak == 0x08 && uids[selected].atqa[0] == 0x44 && uids[selected].atqa[1] == 0) { + DbpString("Mifare Classic 4k (7b uid)"); + SimulateIso14443aTag(8, flags, data); + } else if (uids[selected].sak == 0x00 && uids[selected].atqa[0] == 0x44 && uids[selected].atqa[1] == 0) { + DbpString("Mifare Ultralight"); + SimulateIso14443aTag(2, flags, data); + } else if (uids[selected].sak == 0x20 && uids[selected].atqa[0] == 0x04 && uids[selected].atqa[1] == 0x03) { + DbpString("Mifare DESFire"); + SimulateIso14443aTag(3, flags, data); + } else { + Dbprintf("Unrecognized tag type -- defaulting to Mifare Classic emulation"); + SimulateIso14443aTag(1, flags, data); + } + + } else if (button_action == BUTTON_SINGLE_CLICK) { + selected = (selected + 1) % OPTS; + Dbprintf("Done playing. Switching to record mode on bank %d", selected); + iGotoRecord = 1; + break; + } else if (button_action == BUTTON_HOLD) { + Dbprintf("Playtime over. Begin cloning..."); + iGotoClone = 1; + break; + } + } + + /* We pressed a button so ignore it here with a delay */ + SpinDelay(300); + LEDsoff(); + LED(selected + 1, 0); + } + } + // time to exit standalone mode +out: +} \ No newline at end of file diff --git a/armsrc/Standalone/hf_young.h b/armsrc/Standalone/hf_young.h new file mode 100644 index 000000000..3ccd08b72 --- /dev/null +++ b/armsrc/Standalone/hf_young.h @@ -0,0 +1,22 @@ +//----------------------------------------------------------------------------- +// Craig Young 2014 +// Christian Herrmann, 2017 +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// StandAlone Mod +//----------------------------------------------------------------------------- + +#ifndef __HF_YOUNG_H +#define __HF_YOUNG_H + +#include // for bool +#include "standalone.h" // standalone definitions +#include "iso14443a.h" +#include "protocols.h" + +#define OPTS 2 + +#endif /* __HF_YOUNG_H */ \ No newline at end of file diff --git a/armsrc/Standalone/lf_samyrun.c b/armsrc/Standalone/lf_samyrun.c new file mode 100644 index 000000000..f78c7bd78 --- /dev/null +++ b/armsrc/Standalone/lf_samyrun.c @@ -0,0 +1,134 @@ +//----------------------------------------------------------------------------- +// Samy Kamkar, 2012 +// Christian Herrmann, 2017 +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// main code for LF aka SamyRun by Samy Kamkar +//----------------------------------------------------------------------------- +#include "lf_samyrun.h" + +// samy's sniff and repeat routine for LF +void RunMod() { + StandAloneMode(); + FpgaDownloadAndGo(FPGA_BITSTREAM_LF); + + int high[OPTS], low[OPTS]; + int selected = 0; + int playing = 0; + int cardRead = 0; + + // Turn on selected LED + LED(selected + 1, 0); + + for (;;) { + WDT_HIT(); + + // exit from SamyRun, send a usbcommand. + if (usb_poll_validate_length()) break; + + // Was our button held down or pressed? + int button_pressed = BUTTON_HELD(1000); + SpinDelay(300); + + // Button was held for a second, begin recording + if (button_pressed > 0 && cardRead == 0) { + LEDsoff(); + LED(selected + 1, 0); + LED(LED_RED2, 0); + + // record + DbpString("Starting recording"); + + // wait for button to be released + while(BUTTON_PRESS()) + WDT_HIT(); + + /* need this delay to prevent catching some weird data */ + SpinDelay(500); + + CmdHIDdemodFSK(1, &high[selected], &low[selected], 0); + Dbprintf("Recorded %x %x %08x", selected, high[selected], low[selected]); + + LEDsoff(); + LED(selected + 1, 0); + // Finished recording + // If we were previously playing, set playing off + // so next button push begins playing what we recorded + playing = 0; + cardRead = 1; + } + else if (button_pressed > 0 && cardRead == 1) { + LEDsoff(); + LED(selected + 1, 0); + LED(LED_ORANGE, 0); + + // record + Dbprintf("Cloning %x %x %08x", selected, high[selected], low[selected]); + + // wait for button to be released + while(BUTTON_PRESS()) + WDT_HIT(); + + /* need this delay to prevent catching some weird data */ + SpinDelay(500); + + CopyHIDtoT55x7(0, high[selected], low[selected], 0); + Dbprintf("Cloned %x %x %08x", selected, high[selected], low[selected]); + + LEDsoff(); + LED(selected + 1, 0); + // Finished recording + + // If we were previously playing, set playing off + // so next button push begins playing what we recorded + playing = 0; + cardRead = 0; + } + + // Change where to record (or begin playing) + else if (button_pressed) { + // Next option if we were previously playing + if (playing) + selected = (selected + 1) % OPTS; + playing = !playing; + + LEDsoff(); + LED(selected + 1, 0); + + // Begin transmitting + if (playing) { + LED(LED_GREEN, 0); + DbpString("Playing"); + // wait for button to be released + while(BUTTON_PRESS()) + WDT_HIT(); + + Dbprintf("%x %x %08x", selected, high[selected], low[selected]); + CmdHIDsimTAG(high[selected], low[selected], 0); + DbpString("Done playing"); + + if (BUTTON_HELD(1000) > 0) { + DbpString("Exiting"); + LEDsoff(); + return; + } + + /* We pressed a button so ignore it here with a delay */ + SpinDelay(300); + + // when done, we're done playing, move to next option + selected = (selected + 1) % OPTS; + playing = !playing; + LEDsoff(); + LED(selected + 1, 0); + } + else { + while(BUTTON_PRESS()) + WDT_HIT(); + } + } + } +} diff --git a/armsrc/Standalone/lf_samyrun.h b/armsrc/Standalone/lf_samyrun.h new file mode 100644 index 000000000..9c74ebd0a --- /dev/null +++ b/armsrc/Standalone/lf_samyrun.h @@ -0,0 +1,21 @@ +//----------------------------------------------------------------------------- +// Samy Kamkar 2012 +// Christian Herrmann, 2017 +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// StandAlone Mod +//----------------------------------------------------------------------------- + +#ifndef __LF_SAMYRUN_H +#define __LF_SAMYRUN_H + +#include // for bool +#include "standalone.h" // standalone definitions +#include "apps.h" // debugstatements, lfops? + +#define OPTS 2 + +#endif /* __LF_SAMYRUN_H */ \ No newline at end of file diff --git a/armsrc/Standalone/readme.md b/armsrc/Standalone/readme.md new file mode 100644 index 000000000..f6dbe242f --- /dev/null +++ b/armsrc/Standalone/readme.md @@ -0,0 +1,24 @@ +# StandAlone Mods + +This contains functionality for different StandAlone mods. The fullimage will be built given the correct compiler flags used. Build targets for these files are contained in `armsrc/Makefile`. + +If you want to implement a new standalone mod, you need to implement the methods provided in `standalone.h`. + +## Implementing a standalone mod + +Each standalone mod needs to have its own compiler flag to be added in `armsrc\makefile` and inside the function `AppMain` inside AppMain.c + +Use HF/LF to denote which frequence your mod is targeting. +Use you own github name/similar for perpetual honour to denote your mod + +samples: +# -DWITH_LF_ICERUN +# -DWITH_LF_SAMYRUN +# -DWITH_LF_PROXBRUTE +# -DWITH_LF_HIDCORP +# -DWITH_HF_YOUNG +# -DWITH_HF_MATTYRUN + +## Adding identification of your mod +Do please add a identification string in the function `printStandAloneModes` inside `armsrc\appmain.c` +This will enable an easy way to detect on client side which standalone mods has been installed on the device. \ No newline at end of file diff --git a/armsrc/Standalone/standalone.h b/armsrc/Standalone/standalone.h new file mode 100644 index 000000000..59b1d1a52 --- /dev/null +++ b/armsrc/Standalone/standalone.h @@ -0,0 +1,18 @@ +//----------------------------------------------------------------------------- +// Christian Herrmann, 2017 +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// StandAlone Mod header file +//----------------------------------------------------------------------------- + +#ifndef __STANDALONE_H +#define __STANDALONE_H + +#include // for bool + +extern void RunMod(); + +#endif /* __STANDALONE_H */ \ No newline at end of file diff --git a/armsrc/obj/Standalone/.dummy b/armsrc/obj/Standalone/.dummy new file mode 100644 index 000000000..e69de29bb