diff --git a/armsrc/Standalone/lf_icehid.c b/armsrc/Standalone/lf_icehid.c index c490d8d68..560630dbb 100644 --- a/armsrc/Standalone/lf_icehid.c +++ b/armsrc/Standalone/lf_icehid.c @@ -11,20 +11,22 @@ #include "proxmark3_arm.h" #include "appmain.h" #include "lfops.h" +#include "lfsampling.h" +#include "BigBuf.h" #include "fpgaloader.h" #include "util.h" #include "dbprint.h" #include "printf.h" #include "spiffs.h" #include "ticks.h" - +#include "lfdemod.h" /* * `lf_hidcollect` sniffs after LF HID credentials, and stores them in internal * flash. It requires RDV4 hardware (for flash and battery). * * On entering stand-alone mode, this module will start reading/record HID credentials. - * Every found / collected credential will be written/appended to the logfile in flash - * as a text string. + * Every found / collected credential will be written/appended to the logfile in flash + * as a text string. * * LEDs: * - LED A: reading / record @@ -43,35 +45,308 @@ * This module emits debug strings during normal operation -- so try it out in * the lab connected to PM3 client before taking it into the field. * - * To delete the log file from flash: - * + * To delete the log file from flash: + * * 1. mem spiffs remove lf_hidcollect.log */ #define LF_HIDCOLLECT_LOGFILE "lf_hidcollect.log" + void DownloadLogInstructions() { Dbprintf(""); Dbprintf("[=] To get the logfile from flash and display it:"); Dbprintf("[=] " _YELLOW_("1.") "mem spiffs dump o "LF_HIDCOLLECT_LOGFILE" f "LF_HIDCOLLECT_LOGFILE); Dbprintf("[=] " _YELLOW_("2.") "exit proxmark3 client"); - Dbprintf("[=] " _YELLOW_("3.") "cat "LF_HIDCOLLECT_LOGFILE); + Dbprintf("[=] " _YELLOW_("3.") "cat "LF_HIDCOLLECT_LOGFILE); +} + +bool log_exists; + +void append(uint8_t* entry, size_t entry_len) { + + LED_B_ON(); + if (log_exists == false) { + rdv40_spiffs_write(LF_HIDCOLLECT_LOGFILE, entry, entry_len, RDV40_SPIFFS_SAFETY_SAFE); + log_exists = true; + } else { + rdv40_spiffs_append(LF_HIDCOLLECT_LOGFILE, entry, entry_len, RDV40_SPIFFS_SAFETY_SAFE); + } + LED_B_OFF(); +} + +uint32_t IceEM410xdemod() { + + uint8_t *dest = BigBuf_get_addr(); + size_t idx = 0; + int clk = 0, invert = 0, maxErr = 20; + uint32_t hi = 0; + uint64_t lo = 0; + + size_t size = MIN(16385, BigBuf_max_traceLen()); + + //askdemod and manchester decode + int errCnt = askdemod(dest, &size, &clk, &invert, maxErr, 0, 1); + + WDT_HIT(); + + if (errCnt > 50) { + BigBuf_free(); + return PM3_ESOFT; + } + + errCnt = Em410xDecode(dest, &size, &idx, &hi, &lo); + if (errCnt != 1) { + BigBuf_free(); + return PM3_ESOFT; + } + + uint8_t entry[60]; + memset(entry, 0, sizeof(entry)); + + if (size == 128) { + sprintf((char *)entry, "EM XL TAG ID: %06lx%08lx%08lx - (%05ld_%03ld_%08ld)", + hi, + (uint32_t)(lo >> 32), + (uint32_t)lo, + (uint32_t)(lo & 0xFFFF), + (uint32_t)((lo >> 16LL) & 0xFF), + (uint32_t)(lo & 0xFFFFFF)); + } else { + sprintf((char *)entry, "EM TAG ID: %02lx%08lx - (%05ld_%03ld_%08ld)", + (uint32_t)(lo >> 32), + (uint32_t)lo, + (uint32_t)(lo & 0xFFFF), + (uint32_t)((lo >> 16LL) & 0xFF), + (uint32_t)(lo & 0xFFFFFF)); + } + + append(entry, strlen((char*)entry)); + Dbprintf("strlen %d", strlen((char*)entry)); + + Dbprintf("%s", entry); + BigBuf_free(); + return PM3_SUCCESS; +} + +uint32_t IceAWIDdemod() { + + uint8_t *dest = BigBuf_get_addr(); + size_t size = MIN(12800, BigBuf_max_traceLen()); + int dummyIdx = 0; + + //askdemod and manchester decode + int idx = detectAWID(dest, &size, &dummyIdx); + + if (idx <= 0 || size != 96) { + BigBuf_free(); + return PM3_ESOFT; + } + + //get raw ID before removing parities + uint32_t rawLo = bytebits_to_byte(dest + idx + 64, 32); + uint32_t rawHi = bytebits_to_byte(dest + idx + 32, 32); + uint32_t rawHi2 = bytebits_to_byte(dest + idx, 32); + + size = removeParity(dest, idx + 8, 4, 1, 88); + if (size != 66) { + BigBuf_free(); + return PM3_ESOFT; + } + + uint8_t entry[110]; + memset(entry, 0, sizeof(entry)); + + uint8_t fmtLen = bytebits_to_byte(dest, 8); + if (fmtLen == 26) { + uint8_t fac = bytebits_to_byte(dest + 9, 8); + uint32_t cardnum = bytebits_to_byte(dest + 17, 16); + uint32_t code1 = bytebits_to_byte(dest + 8, fmtLen); + sprintf((char *)entry, "AWID bit len: %d, FC: %d, Card: %ld - Wiegand: %lx, Raw: %08lx%08lx%08lx \n", fmtLen, fac, cardnum, code1, rawHi2, rawHi, rawLo); + } else { + uint32_t cardnum = bytebits_to_byte(dest + 8 + (fmtLen - 17), 16); + if (fmtLen > 32) { + uint32_t code1 = bytebits_to_byte(dest + 8, fmtLen - 32); + uint32_t code2 = bytebits_to_byte(dest + 8 + (fmtLen - 32), 32); + sprintf((char *)entry, "AWID bit len: %d -unk bit len - Card: %ld - Wiegand: %lx%08lx, Raw: %08lx%08lx%08lx \n", fmtLen, cardnum, code1, code2, rawHi2, rawHi, rawLo); + } else { + uint32_t code1 = bytebits_to_byte(dest + 8, fmtLen); + sprintf((char *)entry, "AWID bit len: %d -unk bit len - Card: %ld - Wiegand: %lx, Raw: %08lx%08lx%08lx \n", fmtLen, cardnum, code1, rawHi2, rawHi, rawLo); + } + } + + append(entry, strlen((char*)entry)); + Dbprintf("%s", entry); + BigBuf_free(); + return PM3_SUCCESS; +} + +uint32_t IceIOdemod() { + + int dummyIdx = 0; + uint8_t version = 0, facilitycode = 0, crc = 0; + uint16_t number = 0, calccrc = 0; + uint32_t hi = 0, lo = 0; + + size_t size = MIN(12000, BigBuf_max_traceLen()); + +// uint8_t *dest = BigBuf_malloc(size); + uint8_t *dest = BigBuf_get_addr(); + + //fskdemod and get start index + int idx = detectIOProx(dest, &size, &dummyIdx); + + if (idx < 0) { + BigBuf_free(); + return PM3_ESOFT; + } + + hi = bytebits_to_byte(dest + idx, 32); + lo = bytebits_to_byte(dest + idx + 32, 32); + + version = bytebits_to_byte(dest + idx + 27, 8); //14,4 + facilitycode = bytebits_to_byte(dest + idx + 18, 8); + number = (bytebits_to_byte(dest + idx + 36, 8) << 8) | (bytebits_to_byte(dest + idx + 45, 8)); //36,9 + + crc = bytebits_to_byte(dest + idx + 54, 8); + for (uint8_t i = 1; i < 6; ++i) + calccrc += bytebits_to_byte(dest + idx + 9 * i, 8); + + calccrc &= 0xff; + calccrc = 0xff - calccrc; + + char *crcStr = (crc == calccrc) ? "ok" : "!crc"; + + uint8_t entry[64]; + memset(entry, 0, sizeof(entry)); + + sprintf((char *)entry, "IO Prox XSF(%02d)%02x:%05d (%08lx%08lx) [%02x %s] \n" + , version + , facilitycode + , number + , hi + , lo + , crc + , crcStr + ); + + append(entry, strlen((char*)entry)); + Dbprintf("%s", entry); + + BigBuf_free(); + return PM3_SUCCESS; +} + +uint32_t IceHIDDemod() { + + int dummyIdx = 0; + + uint32_t hi2 = 0, hi = 0, lo = 0; + + // large enough to catch 2 sequences of largest format + size_t size = 50 * 128 * 2; // 12800 bytes + //uint8_t *dest = BigBuf_malloc(size); + uint8_t *dest = BigBuf_get_addr(); + + // FSK demodulator + int idx = HIDdemodFSK(dest, &size, &hi2, &hi, &lo, &dummyIdx); + if (idx < 0) { + BigBuf_free(); + return PM3_ESOFT; + } + + if ((size == 96 || size == 192)) { + + uint8_t entry[80]; + memset(entry, 0, sizeof(entry)); + + // go over previously decoded manchester data and decode into usable tag ID + if (hi2 != 0) { //extra large HID tags 88/192 bits + + sprintf((char *)entry, "HID large: %lx%08lx%08lx (%ld) \n", + hi2, + hi, + lo, + (lo >> 1) & 0xFFFF + ); + + append(entry, strlen((char*)entry)); + + } else { //standard HID tags 44/96 bits + uint8_t bitlen = 0; + uint32_t fac = 0; + uint32_t cardnum = 0; + + if (((hi >> 5) & 1) == 1) { //if bit 38 is set then < 37 bit format is used + uint32_t lo2 = 0; + lo2 = (((hi & 31) << 12) | (lo >> 20)); //get bits 21-37 to check for format len bit + uint8_t idx3 = 1; + while (lo2 > 1) { //find last bit set to 1 (format len bit) + lo2 >>= 1; + idx3++; + } + bitlen = idx3 + 19; + fac = 0; + cardnum = 0; + if (bitlen == 26) { + cardnum = (lo >> 1) & 0xFFFF; + fac = (lo >> 17) & 0xFF; + } + if (bitlen == 37) { + cardnum = (lo >> 1) & 0x7FFFF; + fac = ((hi & 0xF) << 12) | (lo >> 20); + } + if (bitlen == 34) { + cardnum = (lo >> 1) & 0xFFFF; + fac = ((hi & 1) << 15) | (lo >> 17); + } + if (bitlen == 35) { + cardnum = (lo >> 1) & 0xFFFFF; + fac = ((hi & 1) << 11) | (lo >> 21); + } + } else { //if bit 38 is not set then 37 bit format is used + bitlen = 37; + cardnum = (lo >> 1) & 0x7FFFF; + fac = ((hi & 0xF) << 12) | (lo >> 20); + } + + sprintf((char *)entry, "HID: %lx%08lx (%ld) Format: %d bit FC: %ld Card: %ld \n", + hi, + lo, + (lo >> 1) & 0xFFFF, + bitlen, + fac, + cardnum + ); + + append(entry, strlen((char*)entry)); + } + + Dbprintf("%s", entry); + } + + BigBuf_free(); + return PM3_SUCCESS; } void ModInfo(void) { - DbpString(" LF HID collector mode - a.k.a IceHID (Iceman)"); + DbpString(" LF HID / IOprox / AWID / EM4100 collector mode - a.k.a IceHID (Iceman)"); } void RunMod() { FpgaDownloadAndGo(FPGA_BITSTREAM_LF); + LFSetupFPGAForADC(LF_DIVISOR_125, true); + BigBuf_Clear(); + StandAloneMode(); + Dbprintf("[=] LF HID collector a.k.a IceHID started"); - + rdv40_spiffs_lazy_mount(); - - bool log_exists = exists_in_spiffs(LF_HIDCOLLECT_LOGFILE); - + + log_exists = exists_in_spiffs(LF_HIDCOLLECT_LOGFILE); + // the main loop for your standalone mode for (;;) { WDT_HIT(); @@ -84,43 +359,45 @@ void RunMod() { if (button_pressed == BUTTON_HOLD) break; - LED_A_ON(); - // findone, high, low, - uint32_t hi = 0, lo = 0; - CmdHIDdemodFSK(1, &hi, &lo, 0); + LED_A_ON(); - LED_A_OFF(); - - //didn't collect any, loop - if (hi == 0 && lo == 0) + uint32_t res; + + // since we steal 12800 from bigbuffer, no need to sample it. + DoAcquisition_config(false, 28000); + res = IceHIDDemod(); + if (res == PM3_SUCCESS) { + LED_A_OFF(); continue; - - uint8_t entry[20]; - memset(entry, 0, sizeof(entry)); - sprintf((char *)entry, "%lx%08lx\n", hi, lo); - - LED_B_ON(); - if (!log_exists) { - rdv40_spiffs_write(LF_HIDCOLLECT_LOGFILE, entry, sizeof(entry), RDV40_SPIFFS_SAFETY_SAFE); - log_exists = true; - } else { - rdv40_spiffs_append(LF_HIDCOLLECT_LOGFILE, entry, sizeof(entry), RDV40_SPIFFS_SAFETY_SAFE); } - LED_B_OFF(); - SpinErr(LED_A, 250, 2); + DoAcquisition_config(false, 28000); + res = IceAWIDdemod(); + if (res == PM3_SUCCESS) { + LED_A_OFF(); + continue; + } + + DoAcquisition_config(false, 20000); + res = IceEM410xdemod(); + if (res == PM3_SUCCESS) { + LED_A_OFF(); + continue; + } + + DoAcquisition_config(false, 28000); + res = IceIOdemod(); + if (res == PM3_SUCCESS) { + LED_A_OFF(); + continue; + } } LED_C_ON(); rdv40_spiffs_lazy_unmount(); LED_C_OFF(); - SpinErr(LED_A, 200, 5); - SpinDelay(100); - LEDsoff(); - SpinDelay(300); DownloadLogInstructions(); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); }