Added standalone mode for simulatin Nedap ID

This commit is contained in:
Benjamin DELPY 2023-01-11 23:31:23 +01:00
commit 21de6e750c
6 changed files with 232 additions and 2 deletions

View file

@ -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)

View file

@ -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 :=

View file

@ -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

View file

@ -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
}

View file

@ -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

View file

@ -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=()