diff --git a/CHANGELOG.md b/CHANGELOG.md index 0652edf2b..9867f7f70 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -36,6 +36,7 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac - Fixed `trace list -c` - annotation of CRC bytes now is colored or squared if no ansi colors is supported (@iceman1001) - Fixed `trace list -t mf` - now also finds UID if anticollision is partial captured, to be used for mfkey (@iceman1001) - Fixed `make accessrights` on Fedora (@mooey5775) + - Added standalone mode for simulatin Nedap ID ## [Radium.4.15864][2022-10-29] - Changed `lf indala sim` - now accepts fc / cn (@iceman1001) diff --git a/armsrc/Standalone/Makefile.hal b/armsrc/Standalone/Makefile.hal index 6b4510da8..afd144e5d 100644 --- a/armsrc/Standalone/Makefile.hal +++ b/armsrc/Standalone/Makefile.hal @@ -53,6 +53,9 @@ define KNOWN_STANDALONE_DEFINITIONS | LF_NEXID | LF Nexwatch collector to flashmem | | (RDV4 only) | | +----------------------------------------------------------+ +| LF_NEDAP_SIM | LF Nedap ID simple simulator | +| | | ++----------------------------------------------------------+ | LF_PROXBRUTE | HID ProxII bruteforce | | | - Brad Antoniewicz | +----------------------------------------------------------+ @@ -118,7 +121,7 @@ define KNOWN_STANDALONE_DEFINITIONS +----------------------------------------------------------+ endef -STANDALONE_MODES := LF_SKELETON LF_EM4100EMUL LF_EM4100RSWB LF_EM4100RSWW LF_EM4100RWC LF_HIDBRUTE LF_HIDFCBRUTE LF_ICEHID LF_PROXBRUTE LF_SAMYRUN LF_THAREXDE LF_NEXID +STANDALONE_MODES := LF_SKELETON LF_EM4100EMUL LF_EM4100RSWB LF_EM4100RSWW LF_EM4100RWC LF_HIDBRUTE LF_HIDFCBRUTE LF_ICEHID LF_PROXBRUTE LF_SAMYRUN LF_THAREXDE LF_NEXID LF_NEDAP_SIM STANDALONE_MODES += HF_14ASNIFF HF_14BSNIFF HF_15SNIFF HF_AVEFUL HF_BOG HF_COLIN HF_CRAFTBYTE HF_ICECLASS HF_LEGIC HF_LEGICSIM HF_MATTYRUN HF_MFCSIM HF_MSDSAL HF_TCPRST HF_TMUDFORD HF_YOUNG HF_REBLAY DANKARMULTI STANDALONE_MODES_REQ_BT := HF_REBLAY STANDALONE_MODES_REQ_SMARTCARD := diff --git a/armsrc/Standalone/Makefile.inc b/armsrc/Standalone/Makefile.inc index 05a63f1dd..1df076414 100644 --- a/armsrc/Standalone/Makefile.inc +++ b/armsrc/Standalone/Makefile.inc @@ -133,6 +133,10 @@ endif ifneq (,$(findstring WITH_STANDALONE_HF_MFCSIM,$(APP_CFLAGS))) SRC_STANDALONE = hf_mfcsim.c endif +# WITH_STANDALONE_LF_NEDAP_SIM +ifneq (,$(findstring WITH_STANDALONE_LF_NEDAP_SIM,$(APP_CFLAGS))) + SRC_STANDALONE = lf_nedap_sim.c +endif ifneq (,$(findstring WITH_STANDALONE_DANKARMULTI,$(APP_CFLAGS))) SRC_STANDALONE = dankarmulti.c diff --git a/armsrc/Standalone/lf_nedap_sim.c b/armsrc/Standalone/lf_nedap_sim.c new file mode 100644 index 000000000..491199c27 --- /dev/null +++ b/armsrc/Standalone/lf_nedap_sim.c @@ -0,0 +1,221 @@ +//----------------------------------------------------------------------------- +// Copyright (C) Proxmark3 contributors. See AUTHORS.md for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// See LICENSE.txt for the text of the license. +//----------------------------------------------------------------------------- +// This simple mode encode, then emulate a Nedap identificator until button pressed +// lots of code from client side, cmdlfnedap, util, etc. +//----------------------------------------------------------------------------- +#include "standalone.h" // standalone definitions +#include "proxmark3_arm.h" +#include "appmain.h" +#include "fpgaloader.h" +#include "lfops.h" +#include "util.h" +#include "dbprint.h" +#include "string.h" +#include "BigBuf.h" +#include "crc16.h" + +#define MODULE_LONG_NAME "LF Nedap simple simulator" + +typedef struct _NEDAP_TAG { + uint8_t subType; + uint16_t customerCode; + uint32_t id; + + uint8_t bIsLong; +} NEDAP_TAG, *PNEDAP_TAG; + +const NEDAP_TAG Tag = {.subType = 0x5, .customerCode = 0x123, .id = 42424, .bIsLong = 1}; + +static int NedapPrepareBigBuffer(const NEDAP_TAG *pTag); +static void biphaseSimBitInverted(uint8_t c, int *n, uint8_t *phase); +static void NedapGen(uint8_t subType, uint16_t customerCode, uint32_t id, bool isLong, uint8_t *data); +static uint8_t isEven_64_63(const uint8_t *data); +static inline uint32_t bitcount32(uint32_t a); +static void bytes_to_bytebits(const void *src, const size_t srclen, void *dest); + +void ModInfo(void) +{ + DbpString(" " MODULE_LONG_NAME); +} + +void RunMod(void) +{ + int n; + + StandAloneMode(); + + Dbprintf("[=] " MODULE_LONG_NAME " -- started"); + FpgaDownloadAndGo(FPGA_BITSTREAM_LF); + Dbprintf("[=] NEDAP (%s) - ID: " _GREEN_("%05u") " subtype: " _GREEN_("%1u") " customer code: " _GREEN_("%u / 0x%03X"), Tag.bIsLong ? "128b" : "64b", Tag.id, Tag.subType, Tag.customerCode, Tag.customerCode); + + n = NedapPrepareBigBuffer(&Tag); + do + { + WDT_HIT(); + + if (data_available()) + break; + + SimulateTagLowFrequency(n, 0, true); + + } while (BUTTON_HELD(1000) == BUTTON_NO_CLICK); + + Dbprintf("[=] " MODULE_LONG_NAME " -- exiting"); + + LEDsoff(); +} + +static int NedapPrepareBigBuffer(const NEDAP_TAG *pTag) +{ + int ret = 0; + uint8_t data[16], bitStream[sizeof(data) * 8], phase = 0; + uint16_t i, size = pTag->bIsLong ? sizeof(data) : (sizeof(data) / 2); + + NedapGen(pTag->subType, pTag->customerCode, pTag->id, pTag->bIsLong, data); + bytes_to_bytebits(data, size, bitStream); + size <<= 3; + + for (i = 0; i < size; i++) + { + biphaseSimBitInverted(!bitStream[i], &ret, &phase); + } + if (phase == 1) //run a second set inverted to keep phase in check + { + for (i = 0; i < size; i++) + { + biphaseSimBitInverted(!bitStream[i], &ret, &phase); + } + } + + return ret; +} + +static void biphaseSimBitInverted(uint8_t c, int *n, uint8_t *phase) +{ + uint8_t *dest = BigBuf_get_addr(); + + if (c) + { + memset(dest + (*n), c ^ 1 ^ *phase, 32); + memset(dest + (*n) + 32, c ^ *phase, 32); + } + else + { + memset(dest + (*n), c ^ *phase, 64); + *phase ^= 1; + } + *n += 64; +} + +#define FIXED_71 0x71 +#define FIXED_40 0x40 +#define UNKNOWN_A 0x00 +#define UNKNOWN_B 0x00 +static const uint8_t translateTable[10] = {8, 2, 1, 12, 4, 5, 10, 13, 0, 9}; +static void NedapGen(uint8_t subType, uint16_t customerCode, uint32_t id, bool isLong, uint8_t *data) { // 8 or 16 + uint8_t buffer[7]; + + uint8_t r1 = (uint8_t)(id / 10000); + uint8_t r2 = (uint8_t)((id % 10000) / 1000); + uint8_t r3 = (uint8_t)((id % 1000) / 100); + uint8_t r4 = (uint8_t)((id % 100) / 10); + uint8_t r5 = (uint8_t)(id % 10); + + // first part + uint8_t idxC1 = r1; + uint8_t idxC2 = (idxC1 + 1 + r2) % 10; + uint8_t idxC3 = (idxC2 + 1 + r3) % 10; + uint8_t idxC4 = (idxC3 + 1 + r4) % 10; + uint8_t idxC5 = (idxC4 + 1 + r5) % 10; + + buffer[0] = 0xc0 | (subType & 0x0F); + buffer[1] = (customerCode & 0x0FF0) >> 4; + buffer[2] = ((customerCode & 0x000F) << 4) | translateTable[idxC1]; + buffer[3] = (translateTable[idxC2] << 4) | translateTable[idxC3]; + buffer[4] = (translateTable[idxC4] << 4) | translateTable[idxC5]; + + // checksum + init_table(CRC_XMODEM); + uint16_t checksum = crc16_xmodem(buffer, 5); + + buffer[6] = ((checksum & 0x000F) << 4) | (buffer[4] & 0x0F); + buffer[5] = (checksum & 0x00F0) | ((buffer[4] & 0xF0) >> 4); + buffer[4] = ((checksum & 0x0F00) >> 4) | (buffer[3] & 0x0F); + buffer[3] = ((checksum & 0xF000) >> 8) | ((buffer[3] & 0xF0) >> 4); + + // carry calc + uint8_t carry = 0; + for (uint8_t i = 0; i < sizeof(buffer); i++) { + uint8_t tmp = buffer[sizeof(buffer) - 1 - i]; + data[7 - i] = ((tmp & 0x7F) << 1) | carry; + carry = (tmp & 0x80) >> 7; + } + data[0] = 0xFE | carry; + data[7] |= isEven_64_63(data); + + // second part + if (isLong) { + uint8_t id0 = r1; + uint8_t id1 = (r2 << 4) | r3; + uint8_t id2 = (r4 << 4) | r5; + + data[8] = (id2 >> 1); + data[9] = ((id2 & 0x01) << 7) | (id1 >> 2); + data[10] = ((id1 & 0x03) << 6) | (id0 >> 3); + data[11] = ((id0 & 0x07) << 5) | (FIXED_71 >> 4); + data[12] = ((FIXED_71 & 0x0F) << 4) | (FIXED_40 >> 5); + data[13] = ((FIXED_40 & 0x1F) << 3) | (UNKNOWN_A >> 6); + data[14] = ((UNKNOWN_A & 0x3F) << 2) | (UNKNOWN_B >> 7); + data[15] = ((UNKNOWN_B & 0x7F) << 1); + data[15] |= isEven_64_63(data + 8); + } +} + +static uint8_t isEven_64_63(const uint8_t *data) { // 8 + uint32_t tmp[2]; + memcpy(tmp, data, 8); + return (bitcount32(tmp[0]) + (bitcount32(tmp[1] & 0xfeffffff))) & 1; +} + +static void bytes_to_bytebits(const void *src, const size_t srclen, void *dest) +{ + uint8_t *s = (uint8_t *)src, *d = (uint8_t *)dest; + size_t i = srclen * 8, j = srclen; + + while (j--) + { + uint8_t b = s[j]; + d[--i] = (b >> 0) & 1; + d[--i] = (b >> 1) & 1; + d[--i] = (b >> 2) & 1; + d[--i] = (b >> 3) & 1; + d[--i] = (b >> 4) & 1; + d[--i] = (b >> 5) & 1; + d[--i] = (b >> 6) & 1; + d[--i] = (b >> 7) & 1; + } +} + +static inline uint32_t bitcount32(uint32_t a) +{ +#if defined __GNUC__ + return __builtin_popcountl(a); +#else + a = a - ((a >> 1) & 0x55555555); + a = (a & 0x33333333) + ((a >> 2) & 0x33333333); + return (((a + (a >> 4)) & 0x0f0f0f0f) * 0x01010101) >> 24; +#endif +} diff --git a/doc/md/Use_of_Proxmark/4_Advanced-compilation-parameters.md b/doc/md/Use_of_Proxmark/4_Advanced-compilation-parameters.md index 06040b59e..ee8c63465 100644 --- a/doc/md/Use_of_Proxmark/4_Advanced-compilation-parameters.md +++ b/doc/md/Use_of_Proxmark/4_Advanced-compilation-parameters.md @@ -108,6 +108,7 @@ Here are the supported values you can assign to `STANDALONE` in `Makefile.platfo | LF_HIDBRUTE | HID corporate 1000 bruteforce - Federico dotta & Maurizio Agazzini | LF_HIDFCBRUTE | LF HID facility code bruteforce - ss23 | LF_ICEHID | LF HID collector to flashmem - Iceman1001 +| LF_NEDAP_SIM | LF Nedap ID simulator | LF_NEXID | Nexwatch credentials detection mode - jrjgjk & Zolorah | LF_PROXBRUTE | HID ProxII bruteforce - Brad Antoniewicz | LF_SAMYRUN (def)| HID26 read/clone/sim - Samy Kamkar diff --git a/tools/build_all_firmwares.sh b/tools/build_all_firmwares.sh index 5e1076684..a0ef2e1dd 100755 --- a/tools/build_all_firmwares.sh +++ b/tools/build_all_firmwares.sh @@ -30,7 +30,7 @@ mkdir -p "$DEST" mv bootrom/obj/bootrom.elf "$DEST/PM3BOOTROM.elf" # cf armsrc/Standalone/Makefile.hal -STANDALONE_MODES=(LF_SKELETON LF_EM4100EMUL LF_EM4100RSWB LF_EM4100RSWW LF_EM4100RWC LF_HIDBRUTE LF_HIDFCBRUTE LF_ICEHID LF_PROXBRUTE LF_SAMYRUN LF_THAREXDE LF_NEXID) +STANDALONE_MODES=(LF_SKELETON LF_EM4100EMUL LF_EM4100RSWB LF_EM4100RSWW LF_EM4100RWC LF_HIDBRUTE LF_HIDFCBRUTE LF_ICEHID LF_PROXBRUTE LF_SAMYRUN LF_THAREXDE LF_NEXID LF_NEDAP_SIM) STANDALONE_MODES+=(HF_14ASNIFF HF_14BSNIFF HF_15SNIFF HF_AVEFUL HF_BOG HF_COLIN HF_CRAFTBYTE HF_ICECLASS HF_LEGIC HF_LEGICSIM HF_MATTYRUN HF_MFCSIM HF_MSDSAL HF_TCPRST HF_TMUDFORD HF_YOUNG HF_REBLAY DANKARMULTI) STANDALONE_MODES_REQ_BT=(HF_REBLAY) STANDALONE_MODES_REQ_SMARTCARD=()