Merge pull request #9 from RfidResearchGroup/master

Update
This commit is contained in:
mwalker33 2019-09-22 14:42:58 +10:00 committed by GitHub
commit a1eb992fa8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
56 changed files with 2032 additions and 607 deletions

View file

@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file.
This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log...
## [unreleased][unreleased] ## [unreleased][unreleased]
- Add `wiegand list/encode/decode` - wiegand format manipulation. Adapted to fit here. (@grauerfuchs)
- Add `lf t55xx protect` - sets password and enables password protection on t55x7 tag (@iceman1001) - Add `lf t55xx protect` - sets password and enables password protection on t55x7 tag (@iceman1001)
- Chg `lf t55xx wipe` - now accepts user provided configuration block (@iceman1001) - Chg `lf t55xx wipe` - now accepts user provided configuration block (@iceman1001)
- Chg proxmark3-flasher is now merged into proxmark3 client. Add pm3-flash (@doegox) - Chg proxmark3-flasher is now merged into proxmark3 client. Add pm3-flash (@doegox)

View file

@ -376,14 +376,15 @@ test_script:
ExecTest "hf mf offline text" "hf mf" {bash -lc "cd ~/client;./proxmark3 -c 'hf mf'"} "at_enc" ExecTest "hf mf offline text" "hf mf" {bash -lc "cd ~/client;./proxmark3 -c 'hf mf'"} "at_enc"
ExecTest "hf mf hardnested" "hf mf hardnested" {bash -lc "cd ~/client;./proxmark3 -c 'hf mf hardnested t 1 000000000000'"} "found:"
ExecTest "hf mf iclass" "hf mf iclass" {bash -lc "cd ~/client;./proxmark3 -c 'hf iclass loclass t'"} "verified ok"
#proxmark crypto tests #proxmark crypto tests
ExecTest "emv test" "emv test" {bash -lc "cd ~/client;./proxmark3 -c 'emv test'"} "Test?s? ? OK" # Long tests:
# ExecTest "hf mf hardnested" "hf mf hardnested" {bash -lc "cd ~/client;./proxmark3 -c 'hf mf hardnested t 1 000000000000'"} "found:"
# ExecTest "hf mf iclass" "hf mf iclass" {bash -lc "cd ~/client;./proxmark3 -c 'hf iclass loclass t l'"} "verified ok"
# ExecTest "emv test" "emv test" {bash -lc "cd ~/client;./proxmark3 -c 'emv test -i -l'"} "Test?s? ? OK"
# Short tests:
ExecTest "hf mf iclass" "hf mf iclass" {bash -lc "cd ~/client;./proxmark3 -c 'hf iclass loclass t'"} "OK!"
ExecTest "emv test" "emv test" {bash -lc "cd ~/client;./proxmark3 -c 'emv test -i'"} "Test?s? ? OK"
if ($global:TestsPassed) { if ($global:TestsPassed) {

View file

@ -208,13 +208,13 @@ void MeasureAntennaTuning(void) {
uint16_t MeasureAntennaTuningHfData(void) { uint16_t MeasureAntennaTuningHfData(void) {
uint16_t volt = 0; // in mV uint16_t volt = 0; // in mV
volt = (MAX_ADC_HF_VOLTAGE * AvgAdc(ADC_CHAN_HF)) >> 10; uint16_t avg = AvgAdc(ADC_CHAN_HF);
volt = (MAX_ADC_HF_VOLTAGE * avg) >> 10;
bool use_high = (volt > MAX_ADC_HF_VOLTAGE - 300); bool use_high = (volt > MAX_ADC_HF_VOLTAGE - 300);
if (!use_high) { if (use_high) {
volt = (MAX_ADC_HF_VOLTAGE * AvgAdc(ADC_CHAN_HF)) >> 10;
} else {
volt = (MAX_ADC_HF_VOLTAGE_RDV40 * AvgAdc(ADC_CHAN_HF_RDV40)) >> 10; volt = (MAX_ADC_HF_VOLTAGE_RDV40 * AvgAdc(ADC_CHAN_HF_RDV40)) >> 10;
// volt = (MAX_ADC_HF_VOLTAGE * AvgAdc(ADC_CHAN_HF)) >> 10;
} }
return volt; return volt;
} }
@ -343,7 +343,7 @@ void SendStatus(void) {
Flashmem_print_info(); Flashmem_print_info();
#endif #endif
reply_old(CMD_ACK, 1, 0, 0, 0, 0); reply_ng(CMD_STATUS, PM3_SUCCESS, NULL, 0);
} }
void SendCapabilities(void) { void SendCapabilities(void) {
@ -730,10 +730,6 @@ static void PacketReceived(PacketCommandNG *packet) {
CmdIOdemodFSK(packet->oldarg[0], &high, &low, 1); CmdIOdemodFSK(packet->oldarg[0], &high, &low, 1);
break; break;
} }
case CMD_LF_IO_CLONE: {
CopyIOtoT55x7(packet->oldarg[0], packet->oldarg[1]);
break;
}
case CMD_LF_EM410X_DEMOD: { case CMD_LF_EM410X_DEMOD: {
uint32_t high; uint32_t high;
uint64_t low; uint64_t low;
@ -769,17 +765,6 @@ static void PacketReceived(PacketCommandNG *packet) {
SimulateTagLowFrequencyBidir(packet->oldarg[0], packet->oldarg[1]); SimulateTagLowFrequencyBidir(packet->oldarg[0], packet->oldarg[1]);
break; break;
} }
case CMD_LF_INDALA_CLONE: {
CopyIndala64toT55x7(packet->data.asDwords[0], packet->data.asDwords[1]);
break;
}
case CMD_LF_INDALA224_CLONE: {
CopyIndala224toT55x7(
packet->data.asDwords[0], packet->data.asDwords[1], packet->data.asDwords[2], packet->data.asDwords[3],
packet->data.asDwords[4], packet->data.asDwords[5], packet->data.asDwords[6]
);
break;
}
case CMD_LF_T55XX_READBL: { case CMD_LF_T55XX_READBL: {
struct p { struct p {
uint32_t password; uint32_t password;
@ -861,7 +846,7 @@ static void PacketReceived(PacketCommandNG *packet) {
bool Q5; bool Q5;
uint8_t blocks[8]; uint8_t blocks[8];
} PACKED; } PACKED;
struct p *payload = (struct p*)packet->data.asBytes; struct p *payload = (struct p *)packet->data.asBytes;
CopyVikingtoT55xx(payload->blocks, payload->Q5); CopyVikingtoT55xx(payload->blocks, payload->Q5);
break; break;
} }
@ -1251,22 +1236,22 @@ static void PacketReceived(PacketCommandNG *packet) {
break; break;
} }
case CMD_HF_ICLASS_READBL: { case CMD_HF_ICLASS_READBL: {
/* /*
struct p { struct p {
uint8_t blockno; uint8_t blockno;
} PACKED; } PACKED;
struct p *payload = (struct p *)packet->data.asBytes; struct p *payload = (struct p *)packet->data.asBytes;
*/ */
iClass_ReadBlk( packet->data.asBytes[0] ); iClass_ReadBlk(packet->data.asBytes[0]);
break; break;
} }
case CMD_HF_ICLASS_AUTH: { //check case CMD_HF_ICLASS_AUTH: { //check
/* /*
struct p { struct p {
uint8_t mac[4]; uint8_t mac[4];
} PACKED; } PACKED;
struct p *payload = (struct p *)packet->data.asBytes; struct p *payload = (struct p *)packet->data.asBytes;
*/ */
iClass_Authentication(packet->data.asBytes); iClass_Authentication(packet->data.asBytes);
break; break;
} }
@ -1680,7 +1665,9 @@ static void PacketReceived(PacketCommandNG *packet) {
break; break;
} }
case CMD_FLASHMEM_SET_SPIBAUDRATE: { case CMD_FLASHMEM_SET_SPIBAUDRATE: {
FlashmemSetSpiBaudrate(packet->oldarg[0]); if (packet->length != sizeof(uint32_t))
break;
FlashmemSetSpiBaudrate(packet->data.asDwords[0]);
break; break;
} }
case CMD_FLASHMEM_WRITE: { case CMD_FLASHMEM_WRITE: {

View file

@ -2044,8 +2044,7 @@ bool GetIso14443aAnswerFromTag_Thinfilm(uint8_t *receivedResponse, uint8_t *rec
} }
} }
// timeout already in ms + 10ms guard time if (GetTickCount() - receive_timer > 100)
if (GetTickCount() - receive_timer > 1160)
break; break;
} }
*received_len = Demod.len; *received_len = Demod.len;

View file

@ -918,7 +918,7 @@ void CmdHIDsimTAGEx(uint32_t hi2, uint32_t hi, uint32_t lo, uint8_t longFMT, boo
*/ */
// special start of frame marker containing invalid Manchester bit sequences // special start of frame marker containing invalid Manchester bit sequences
uint8_t bits[8+8*2+84*2] = { 0, 0, 0, 1, 1, 1, 0, 1 }; uint8_t bits[8 + 8 * 2 + 84 * 2] = { 0, 0, 0, 1, 1, 1, 0, 1 };
uint8_t bitlen = 0; uint8_t bitlen = 0;
uint16_t n = 8; uint16_t n = 8;
@ -928,9 +928,9 @@ void CmdHIDsimTAGEx(uint32_t hi2, uint32_t hi, uint32_t lo, uint8_t longFMT, boo
DbpString("Tags can only have 84 bits."); DbpString("Tags can only have 84 bits.");
return; return;
} }
bitlen = 8+8*2+84*2; bitlen = 8 + 8 * 2 + 84 * 2;
hi2 |= 0x9E00000; // 9E: long format identifier hi2 |= 0x9E00000; // 9E: long format identifier
manchesterEncodeUint32(hi2, 16+12, bits, &n); manchesterEncodeUint32(hi2, 16 + 12, bits, &n);
manchesterEncodeUint32(hi, 32, bits, &n); manchesterEncodeUint32(hi, 32, bits, &n);
manchesterEncodeUint32(lo, 32, bits, &n); manchesterEncodeUint32(lo, 32, bits, &n);
} else { } else {
@ -939,7 +939,7 @@ void CmdHIDsimTAGEx(uint32_t hi2, uint32_t hi, uint32_t lo, uint8_t longFMT, boo
DbpString("[!] tags can only have 44 bits. - USE lf simfsk for larger tags"); DbpString("[!] tags can only have 44 bits. - USE lf simfsk for larger tags");
return; return;
} }
bitlen = 8+44*2; bitlen = 8 + 44 * 2;
manchesterEncodeUint32(hi, 12, bits, &n); manchesterEncodeUint32(hi, 12, bits, &n);
manchesterEncodeUint32(lo, 32, bits, &n); manchesterEncodeUint32(lo, 32, bits, &n);
} }
@ -1712,7 +1712,7 @@ void T55xxWriteBlock(uint8_t *data) {
c->flags &= (0xff ^ 0x40); // Called for a write, so ensure it is clear/0 c->flags &= (0xff ^ 0x40); // Called for a write, so ensure it is clear/0
LED_A_ON(); LED_A_ON();
T55xx_SendCMD(c->data, c->pwd, c->flags | (c->blockno << 9)) ; //, false); T55xx_SendCMD(c->data, c->pwd, c->flags | (c->blockno << 9));
// Perform write (nominal is 5.6 ms for T55x7 and 18ms for E5550, // Perform write (nominal is 5.6 ms for T55x7 and 18ms for E5550,
// so wait a little more) // so wait a little more)
@ -1744,7 +1744,6 @@ void T55xxWriteBlock(uint8_t *data) {
// turn field off // turn field off
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
// cmd_send(CMD_ACK,0,0,0,0,0);
reply_ng(CMD_LF_T55XX_WRITEBL, PM3_SUCCESS, NULL, 0); reply_ng(CMD_LF_T55XX_WRITEBL, PM3_SUCCESS, NULL, 0);
LED_A_OFF(); LED_A_OFF();
} }
@ -2037,46 +2036,6 @@ void CopyHIDtoT55x7(uint32_t hi2, uint32_t hi, uint32_t lo, uint8_t longFMT) {
LED_D_OFF(); LED_D_OFF();
} }
void CopyIOtoT55x7(uint32_t hi, uint32_t lo) {
uint32_t data[] = {T55x7_BITRATE_RF_64 | T55x7_MODULATION_FSK2a | (2 << T55x7_MAXBLOCK_SHIFT), hi, lo};
//TODO add selection of chip for Q5 or T55x7
// data[0] = T5555_SET_BITRATE(64) | T5555_MODULATION_FSK2 | T5555_INVERT_OUTPUT | 2 << T5555_MAXBLOCK_SHIFT;
LED_D_ON();
// Program the data blocks for supplied ID
// and the block 0 config
WriteT55xx(data, 0, 3);
LED_D_OFF();
}
// Clone Indala 64-bit tag by UID to T55x7
void CopyIndala64toT55x7(uint32_t hi, uint32_t lo) {
//Program the 2 data blocks for supplied 64bit UID
// and the Config for Indala 64 format (RF/32;PSK1 with RF/2;Maxblock=2)
uint32_t data[] = { T55x7_BITRATE_RF_32 | T55x7_MODULATION_PSK1 | (2 << T55x7_MAXBLOCK_SHIFT), hi, lo};
//TODO add selection of chip for Q5 or T55x7
// data[0] = T5555_SET_BITRATE(32 | T5555_MODULATION_PSK1 | 2 << T5555_MAXBLOCK_SHIFT;
LED_D_ON();
WriteT55xx(data, 0, 3);
//Alternative config for Indala (Extended mode;RF/32;PSK1 with RF/2;Maxblock=2;Inverse data)
// T5567WriteBlock(0x603E1042,0);
LED_D_OFF();
}
// Clone Indala 224-bit tag by UID to T55x7
void CopyIndala224toT55x7(uint32_t uid1, uint32_t uid2, uint32_t uid3, uint32_t uid4, uint32_t uid5, uint32_t uid6, uint32_t uid7) {
//Program the 7 data blocks for supplied 224bit UID
uint32_t data[] = {0, uid1, uid2, uid3, uid4, uid5, uid6, uid7};
// and the block 0 for Indala224 format
//Config for Indala (RF/32;PSK2 with RF/2;Maxblock=7)
data[0] = T55x7_BITRATE_RF_32 | T55x7_MODULATION_PSK2 | (7 << T55x7_MAXBLOCK_SHIFT);
//TODO add selection of chip for Q5 or T55x7
// data[0] = T5555_SET_BITRATE(32 | T5555_MODULATION_PSK2 | 7 << T5555_MAXBLOCK_SHIFT;
LED_D_ON();
WriteT55xx(data, 0, 8);
//Alternative config for Indala (Extended mode;RF/32;PSK1 with RF/2;Maxblock=7;Inverse data)
// T5567WriteBlock(0x603E10E2,0);
LED_D_OFF();
}
// clone viking tag to T55xx // clone viking tag to T55xx
void CopyVikingtoT55xx(uint8_t *blocks, uint8_t Q5) { void CopyVikingtoT55xx(uint8_t *blocks, uint8_t Q5) {
@ -2085,7 +2044,7 @@ void CopyVikingtoT55xx(uint8_t *blocks, uint8_t Q5) {
data[0] = T5555_SET_BITRATE(32) | T5555_MODULATION_MANCHESTER | 2 << T5555_MAXBLOCK_SHIFT; data[0] = T5555_SET_BITRATE(32) | T5555_MODULATION_MANCHESTER | 2 << T5555_MAXBLOCK_SHIFT;
data[1] = bytes_to_num(blocks, 4); data[1] = bytes_to_num(blocks, 4);
data[2] = bytes_to_num(blocks +4, 4); data[2] = bytes_to_num(blocks + 4, 4);
// Program the data blocks for supplied ID and the block 0 config // Program the data blocks for supplied ID and the block 0 config
WriteT55xx(data, 0, 3); WriteT55xx(data, 0, 3);

View file

@ -42,12 +42,9 @@ void CmdHIDdemodFSK(int findone, uint32_t *high, uint32_t *low, int ledcontrol);
void CmdAWIDdemodFSK(int findone, uint32_t *high, uint32_t *low, int ledcontrol); // Realtime demodulation mode for AWID26 void CmdAWIDdemodFSK(int findone, uint32_t *high, uint32_t *low, int ledcontrol); // Realtime demodulation mode for AWID26
void CmdEM410xdemod(int findone, uint32_t *high, uint64_t *low, int ledcontrol); void CmdEM410xdemod(int findone, uint32_t *high, uint64_t *low, int ledcontrol);
void CmdIOdemodFSK(int findone, uint32_t *high, uint32_t *low, int ledcontrol); void CmdIOdemodFSK(int findone, uint32_t *high, uint32_t *low, int ledcontrol);
void CopyIOtoT55x7(uint32_t hi, uint32_t lo); // Clone an ioProx card to T5557/T5567
void CopyHIDtoT55x7(uint32_t hi2, uint32_t hi, uint32_t lo, uint8_t longFMT); // Clone an HID card to T5557/T5567 void CopyHIDtoT55x7(uint32_t hi2, uint32_t hi, uint32_t lo, uint8_t longFMT); // Clone an HID card to T5557/T5567
void CopyVikingtoT55xx(uint8_t *blocks, uint8_t Q5); void CopyVikingtoT55xx(uint8_t *blocks, uint8_t Q5);
void WriteEM410x(uint32_t card, uint32_t id_hi, uint32_t id_lo); void WriteEM410x(uint32_t card, uint32_t id_hi, uint32_t id_lo);
void CopyIndala64toT55x7(uint32_t hi, uint32_t lo); // Clone Indala 64-bit tag by UID to T55x7
void CopyIndala224toT55x7(uint32_t uid1, uint32_t uid2, uint32_t uid3, uint32_t uid4, uint32_t uid5, uint32_t uid6, uint32_t uid7); // Clone Indala 224-bit tag by UID to T55x7
void T55xxResetRead(uint8_t flags); void T55xxResetRead(uint8_t flags);
//id T55xxWriteBlock(uint32_t data, uint8_t blockno, uint32_t pwd, uint8_t flags); //id T55xxWriteBlock(uint32_t data, uint8_t blockno, uint32_t pwd, uint8_t flags);
void T55xxWriteBlock(uint8_t *data); void T55xxWriteBlock(uint8_t *data);

View file

@ -1977,11 +1977,6 @@ void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint8_t *datain) {
} }
void MifareCIdent() { void MifareCIdent() {
#define GEN_1A 1
#define GEN_1B 2
#define GEN_2 4
#define GEN_UNFUSED 5
// variables // variables
uint8_t isGen = 0; uint8_t isGen = 0;
uint8_t rec[1] = {0x00}; uint8_t rec[1] = {0x00};
@ -1997,16 +1992,13 @@ void MifareCIdent() {
// Generation 1 test // Generation 1 test
ReaderTransmitBitsPar(wupC1, 7, NULL, NULL); ReaderTransmitBitsPar(wupC1, 7, NULL, NULL);
if (ReaderReceive(rec, recpar) && (rec[0] == 0x0a)) {
if (ReaderReceive(rec, recpar) || (rec[0] != 0x0a)) {
ReaderTransmit(wupC2, sizeof(wupC2), NULL); ReaderTransmit(wupC2, sizeof(wupC2), NULL);
if (!ReaderReceive(rec, recpar) || (rec[0] != 0x0a)) { if (!ReaderReceive(rec, recpar) || (rec[0] != 0x0a)) {
isGen = GEN_1B; isGen = MAGIC_GEN_1B;
goto OUT; goto OUT;
}; };
isGen = GEN_1A; isGen = MAGIC_GEN_1A;
goto OUT; goto OUT;
} }
@ -2017,20 +2009,19 @@ void MifareCIdent() {
int res = iso14443a_select_card(uid, NULL, &cuid, true, 0, true); int res = iso14443a_select_card(uid, NULL, &cuid, true, 0, true);
if (res == 2) { if (res == 2) {
Dbprintf("cident AA55C396 == %08X", cuid);
if (cuid == 0xAA55C396) { if (cuid == 0xAA55C396) {
isGen = GEN_UNFUSED; isGen = MAGIC_GEN_UNFUSED;
goto OUT; goto OUT;
} }
ReaderTransmit(rats, sizeof(rats), NULL); ReaderTransmit(rats, sizeof(rats), NULL);
res = ReaderReceive(buf, par); res = ReaderReceive(buf, par);
if (memcmp(buf, "\x09\x78\x00\x91\x02\xDA\xBC\x19\x10\xF0\x05", 11) == 0) { if (memcmp(buf, "\x09\x78\x00\x91\x02\xDA\xBC\x19\x10\xF0\x05", 11) == 0) {
isGen = GEN_2; isGen = MAGIC_GEN_2;
goto OUT; goto OUT;
} }
if (memcmp(buf, "\x0D\x78\x00\x71\x02\x88\x49\xA1\x30\x20\x15\x06\x08\x56\x3D", 15) == 0) { if (memcmp(buf, "\x0D\x78\x00\x71\x02\x88\x49\xA1\x30\x20\x15\x06\x08\x56\x3D", 15) == 0) {
isGen = GEN_2; isGen = MAGIC_GEN_2;
} }
}; };

View file

@ -230,6 +230,7 @@ CMDSRCS = crapto1/crapto1.c \
cmdflashmemspiffs.c \ cmdflashmemspiffs.c \
cmdsmartcard.c \ cmdsmartcard.c \
cmdusart.c \ cmdusart.c \
cmdwiegand.c \
cmdparser.c \ cmdparser.c \
cmdmain.c \ cmdmain.c \
pm3_binlib.c \ pm3_binlib.c \
@ -238,7 +239,9 @@ CMDSRCS = crapto1/crapto1.c \
pm3_bitlib.c \ pm3_bitlib.c \
cmdcrc.c \ cmdcrc.c \
bucketsort.c \ bucketsort.c \
flash.c flash.c \
wiegand_formats.c \
wiegand_formatutils.c
cpu_arch = $(shell uname -m) cpu_arch = $(shell uname -m)
ifneq ($(findstring 86, $(cpu_arch)), ) ifneq ($(findstring 86, $(cpu_arch)), )

View file

@ -1676,6 +1676,8 @@ static int CmdLoad(const char *Cmd) {
int len = 0; int len = 0;
len = strlen(Cmd); len = strlen(Cmd);
if (len == 0) return PM3_EFILE;
if (len > FILE_PATH_SIZE) len = FILE_PATH_SIZE; if (len > FILE_PATH_SIZE) len = FILE_PATH_SIZE;
memcpy(filename, Cmd, len); memcpy(filename, Cmd, len);

View file

@ -117,7 +117,7 @@ static int CmdFlashmemSpiBaudrate(const char *Cmd) {
usage_flashmem_spibaud(); usage_flashmem_spibaud();
return PM3_EINVARG; return PM3_EINVARG;
} }
SendCommandMIX(CMD_FLASHMEM_SET_SPIBAUDRATE, baudrate, 0, 0, NULL, 0); SendCommandNG(CMD_FLASHMEM_SET_SPIBAUDRATE, (uint8_t*)&baudrate, sizeof(uint32_t));
return PM3_SUCCESS; return PM3_SUCCESS;
} }

View file

@ -229,10 +229,11 @@ static int usage_hf_iclass_sniff(void) {
return PM3_SUCCESS; return PM3_SUCCESS;
} }
static int usage_hf_iclass_loclass(void) { static int usage_hf_iclass_loclass(void) {
PrintAndLogEx(NORMAL, "Usage: hf iclass loclass [options]"); PrintAndLogEx(NORMAL, "Usage: hf iclass loclass [h] [t [l]] [f <filename>]");
PrintAndLogEx(NORMAL, "Options:"); PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " h Show this help"); PrintAndLogEx(NORMAL, " h Show this help");
PrintAndLogEx(NORMAL, " t Perform self-test"); PrintAndLogEx(NORMAL, " t Perform self-test");
PrintAndLogEx(NORMAL, " t l Perform self-test, including long ones");
PrintAndLogEx(NORMAL, " f <filename> Bruteforce iclass dumpfile"); PrintAndLogEx(NORMAL, " f <filename> Bruteforce iclass dumpfile");
PrintAndLogEx(NORMAL, " An iclass dumpfile is assumed to consist of an arbitrary number of"); PrintAndLogEx(NORMAL, " An iclass dumpfile is assumed to consist of an arbitrary number of");
PrintAndLogEx(NORMAL, " malicious CSNs, and their protocol responses"); PrintAndLogEx(NORMAL, " malicious CSNs, and their protocol responses");
@ -1831,10 +1832,11 @@ static int CmdHFiClass_loclass(const char *Cmd) {
return PM3_EFILE; return PM3_EFILE;
} }
} else if (opt == 't') { } else if (opt == 't') {
char opt2 = tolower(param_getchar(Cmd, 1));
int errors = testCipherUtils(); int errors = testCipherUtils();
errors += testMAC(); errors += testMAC();
errors += doKeyTests(0); errors += doKeyTests(0);
errors += testElite(); errors += testElite(opt2=='l');
if (errors) PrintAndLogEx(ERR, "There were errors!!!"); if (errors) PrintAndLogEx(ERR, "There were errors!!!");
return PM3_ESOFT; return PM3_ESOFT;
} }

View file

@ -502,7 +502,7 @@ static int CmdStatus(const char *Cmd) {
clearCommandBuffer(); clearCommandBuffer();
PacketResponseNG resp; PacketResponseNG resp;
SendCommandNG(CMD_STATUS, NULL, 0); SendCommandNG(CMD_STATUS, NULL, 0);
if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) if (WaitForResponseTimeout(CMD_STATUS, &resp, 2000) == false)
PrintAndLogEx(WARNING, "Status command failed. Communication speed test timed out"); PrintAndLogEx(WARNING, "Status command failed. Communication speed test timed out");
return PM3_SUCCESS; return PM3_SUCCESS;
} }

View file

@ -26,6 +26,7 @@
#include "cmdlf.h" // lf read #include "cmdlf.h" // lf read
#include "protocols.h" // for T55xx config register definitions #include "protocols.h" // for T55xx config register definitions
#include "util_posix.h" #include "util_posix.h"
#include "cmdlft55xx.h" // verifywrite
static int CmdHelp(const char *Cmd); static int CmdHelp(const char *Cmd);
/* /*
@ -414,6 +415,7 @@ static int CmdAWIDClone(const char *Cmd) {
PrintAndLogEx(INFO, "Preparing to clone AWID %u to T55x7 with FC: %u, CN: %u", fmtlen, fc, cn); PrintAndLogEx(INFO, "Preparing to clone AWID %u to T55x7 with FC: %u, CN: %u", fmtlen, fc, cn);
print_blocks(blocks, 4); print_blocks(blocks, 4);
uint8_t res = 0;
PacketResponseNG resp; PacketResponseNG resp;
// fast push mode // fast push mode
@ -437,7 +439,20 @@ static int CmdAWIDClone(const char *Cmd) {
PrintAndLogEx(ERR, "Error occurred, device did not respond during write operation."); PrintAndLogEx(ERR, "Error occurred, device did not respond during write operation.");
return PM3_ETIMEOUT; return PM3_ETIMEOUT;
} }
if (i == 0) {
SetConfigWithBlock0(blocks[0]);
if (t55xxAquireAndCompareBlock0(false, 0, blocks[0], false))
continue;
} }
if (t55xxVerifyWrite(i, 0, false, false, 0, 0xFF, blocks[i]) == false)
res++;
}
if (res == 0)
PrintAndLogEx(SUCCESS, "Success writing to tag");
return PM3_SUCCESS; return PM3_SUCCESS;
} }

View file

@ -821,6 +821,12 @@ int EM4x50Read(const char *Cmd, bool verbose) {
uint8_t bits[MAX_GRAPH_TRACE_LEN] = {0}; uint8_t bits[MAX_GRAPH_TRACE_LEN] = {0};
size_t size = getFromGraphBuf(bits); size_t size = getFromGraphBuf(bits);
if (size < 4000) {
if (verbose || g_debugMode) PrintAndLogEx(ERR, "Error: EM4x50 - Too little data in Graphbuffer");
return PM3_ESOFT;
}
computeSignalProperties(bits, size); computeSignalProperties(bits, size);
signal_t *sp = getSignalProperties(); signal_t *sp = getSignalProperties();

View file

@ -24,6 +24,7 @@
#include "crc16.h" // for checksum crc-16_ccitt #include "crc16.h" // for checksum crc-16_ccitt
#include "protocols.h" // for T55xx config register definitions #include "protocols.h" // for T55xx config register definitions
#include "lfdemod.h" // parityTest #include "lfdemod.h" // parityTest
#include "cmdlft55xx.h" // verifywrite
/* /*
FDX-B ISO11784/85 demod (aka animal tag) BIPHASE, inverted, rf/32, with preamble of 00000000001 (128bits) FDX-B ISO11784/85 demod (aka animal tag) BIPHASE, inverted, rf/32, with preamble of 00000000001 (128bits)
@ -296,6 +297,7 @@ static int CmdFdxClone(const char *Cmd) {
PrintAndLogEx(INFO, "Preparing to clone FDX-B to T55x7 with animal ID: %04u-%"PRIu64, countryid, animalid); PrintAndLogEx(INFO, "Preparing to clone FDX-B to T55x7 with animal ID: %04u-%"PRIu64, countryid, animalid);
print_blocks(blocks, 5); print_blocks(blocks, 5);
uint8_t res = 0;
PacketResponseNG resp; PacketResponseNG resp;
// fast push mode // fast push mode
@ -318,7 +320,20 @@ static int CmdFdxClone(const char *Cmd) {
PrintAndLogEx(ERR, "Error occurred, device did not respond during write operation."); PrintAndLogEx(ERR, "Error occurred, device did not respond during write operation.");
return PM3_ETIMEOUT; return PM3_ETIMEOUT;
} }
if (i == 0) {
SetConfigWithBlock0(blocks[0]);
if (t55xxAquireAndCompareBlock0(false, 0, blocks[0], false))
continue;
} }
if (t55xxVerifyWrite(i, 0, false, false, 0, 0xFF, blocks[i]) == false)
res++;
}
if (res == 0)
PrintAndLogEx(SUCCESS, "Success writing to tag");
return PM3_SUCCESS; return PM3_SUCCESS;
} }

View file

@ -21,6 +21,7 @@
#include "cmdlf.h" #include "cmdlf.h"
#include "protocols.h" // for T55xx config register definitions #include "protocols.h" // for T55xx config register definitions
#include "lfdemod.h" // parityTest #include "lfdemod.h" // parityTest
#include "cmdlft55xx.h" // verifywrite
static int CmdHelp(const char *Cmd); static int CmdHelp(const char *Cmd);
@ -183,6 +184,7 @@ static int CmdGuardClone(const char *Cmd) {
PrintAndLogEx(INFO, "Preparing to clone Guardall to T55x7 with Facility Code: %u, Card Number: %u", facilitycode, cardnumber); PrintAndLogEx(INFO, "Preparing to clone Guardall to T55x7 with Facility Code: %u, Card Number: %u", facilitycode, cardnumber);
print_blocks(blocks, 4); print_blocks(blocks, 4);
uint8_t res = 0;
PacketResponseNG resp; PacketResponseNG resp;
// fast push mode // fast push mode
@ -205,7 +207,20 @@ static int CmdGuardClone(const char *Cmd) {
PrintAndLogEx(ERR, "Error occurred, device did not respond during write operation."); PrintAndLogEx(ERR, "Error occurred, device did not respond during write operation.");
return PM3_ETIMEOUT; return PM3_ETIMEOUT;
} }
if (i == 0) {
SetConfigWithBlock0(blocks[0]);
if (t55xxAquireAndCompareBlock0(false, 0, blocks[0], false))
continue;
} }
if (t55xxVerifyWrite(i, 0, false, false, 0, 0xFF, blocks[i]) == false)
res++;
}
if (res == 0)
PrintAndLogEx(SUCCESS, "Success writing to tag");
return PM3_SUCCESS; return PM3_SUCCESS;
} }

View file

@ -5,7 +5,17 @@
// at your option, any later version. See the LICENSE.txt file for the text of // at your option, any later version. See the LICENSE.txt file for the text of
// the license. // the license.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Low frequency HID commands // Low frequency HID commands (known)
//
// Useful resources:
// RF interface, programming a T55x7 clone, 26-bit HID H10301 encoding:
// http://www.proxmark.org/files/Documents/125%20kHz%20-%20HID/HID_format_example.pdf
//
// "Understanding Card Data Formats"
// https://www.hidglobal.com/sites/default/files/hid-understanding_card_data_formats-wp-en.pdf
//
// "What Format Do You Need?"
// https://www.hidglobal.com/sites/default/files/resource_files/hid-prox-br-en.pdf
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
#include "cmdlfhid.h" #include "cmdlfhid.h"
@ -25,40 +35,24 @@
#include "cmdlf.h" // lf_read #include "cmdlf.h" // lf_read
#include "util_posix.h" #include "util_posix.h"
#include "lfdemod.h" #include "lfdemod.h"
#include "wiegand_formats.h"
#ifndef BITS #ifndef BITS
# define BITS 96 # define BITS 96
#endif #endif
static int CmdHelp(const char *Cmd); static int CmdHelp(const char *Cmd);
/*
static int usage_lf_hid_read(void) { static int usage_lf_hid_watch(void) {
PrintAndLogEx(NORMAL, "Enables HID compatible reader mode printing details."); PrintAndLogEx(NORMAL, "Enables HID compatible reader mode printing details.");
PrintAndLogEx(NORMAL, "By default, values are printed and logged until the button is pressed or another USB command is issued."); PrintAndLogEx(NORMAL, "By default, values are printed and logged until the button is pressed or another USB command is issued.");
PrintAndLogEx(NORMAL, "If the [1] option is provided, reader mode is exited after reading a single HID card.");
PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Usage: lf hid read [h] [1]"); PrintAndLogEx(NORMAL, "Usage: lf hid watch [h]");
PrintAndLogEx(NORMAL, "Options:"); PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " h : This help"); PrintAndLogEx(NORMAL, " h : This help");
PrintAndLogEx(NORMAL, " 1 : (optional) stop after reading a single card");
PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, " lf hid read"); PrintAndLogEx(NORMAL, " lf hid watch");
PrintAndLogEx(NORMAL, " lf hid read 1");
return PM3_SUCCESS;
}
*/
static int usage_lf_hid_wiegand(void) {
PrintAndLogEx(NORMAL, "This command converts facility code/card number to Wiegand code");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Usage: lf hid wiegand [h] [OEM] [FC] [CN]");
PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " h - This help");
PrintAndLogEx(NORMAL, " OEM - OEM number / site code");
PrintAndLogEx(NORMAL, " FC - facility code");
PrintAndLogEx(NORMAL, " CN - card number");
PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, " lf hid wiegand 0 101 2001");
return PM3_SUCCESS; return PM3_SUCCESS;
} }
static int usage_lf_hid_sim(void) { static int usage_lf_hid_sim(void) {
@ -91,19 +85,21 @@ static int usage_lf_hid_brute(void) {
PrintAndLogEx(NORMAL, "This is a attack against reader. if cardnumber is given, it starts with it and goes up / down one step"); PrintAndLogEx(NORMAL, "This is a attack against reader. if cardnumber is given, it starts with it and goes up / down one step");
PrintAndLogEx(NORMAL, "if cardnumber is not given, it starts with 1 and goes up to 65535"); PrintAndLogEx(NORMAL, "if cardnumber is not given, it starts with 1 and goes up to 65535");
PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Usage: lf hid brute [h] [v] a <format> f <facility-code> c <cardnumber> d <delay>"); PrintAndLogEx(NORMAL, "Usage: lf hid brute [h] [v] w <format> [<field> (decimal)>] {...}");
PrintAndLogEx(NORMAL, "Options:"); PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " h : This help"); PrintAndLogEx(NORMAL, " h : This help");
PrintAndLogEx(NORMAL, " a <format> : 26|33|34|35|37|40|44|84"); PrintAndLogEx(NORMAL, " w <format> : see `wiegand list` for available formats");
PrintAndLogEx(NORMAL, " f <facility-code> : 8-bit value HID facility code"); PrintAndLogEx(NORMAL, " f <facility-code> : facility code");
PrintAndLogEx(NORMAL, " c <cardnumber> : (optional) cardnumber to start with, max 65535"); PrintAndLogEx(NORMAL, " c <cardnumber> : card number to start with");
PrintAndLogEx(NORMAL, " i <issuelevel> : issue level");
PrintAndLogEx(NORMAL, " o <oem> : OEM code");
PrintAndLogEx(NORMAL, " d <delay> : delay betweens attempts in ms. Default 1000ms"); PrintAndLogEx(NORMAL, " d <delay> : delay betweens attempts in ms. Default 1000ms");
PrintAndLogEx(NORMAL, " v : verbose logging, show all tries"); PrintAndLogEx(NORMAL, " v : verbose logging, show all tries");
PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, " lf hid brute a 26 f 224"); PrintAndLogEx(NORMAL, " lf hid brute w H10301 f 224");
PrintAndLogEx(NORMAL, " lf hid brute a 26 f 21 d 2000"); PrintAndLogEx(NORMAL, " lf hid brute w H10301 f 21 d 2000");
PrintAndLogEx(NORMAL, " lf hid brute v a 26 f 21 c 200 d 2000"); PrintAndLogEx(NORMAL, " lf hid brute v w H10301 f 21 c 200 d 2000");
return PM3_SUCCESS; return PM3_SUCCESS;
} }
@ -118,17 +114,33 @@ static int sendPing(void) {
return PM3_ETIMEOUT; return PM3_ETIMEOUT;
return PM3_SUCCESS; return PM3_SUCCESS;
} }
static int sendTry(uint8_t fmtlen, uint32_t fc, uint32_t cn, uint32_t delay, uint8_t *bits, bool verbose) { static int sendTry(uint8_t format_idx, wiegand_card_t *card, uint32_t delay, bool verbose) {
wiegand_message_t packed;
memset(&packed, 0, sizeof(wiegand_message_t));
if (HIDPack(format_idx, card, &packed) == false) {
PrintAndLogEx(WARNING, "The card data could not be encoded in the selected format.");
return PM3_ESOFT;
}
// this should be optional.
if (verbose) if (verbose)
PrintAndLogEx(INFO, "Trying FC: %u; CN: %u", fc, cn); PrintAndLogEx(INFO, "Trying FC: %u; CN: %u; Issue level: %u; OEM: %u", card->FacilityCode, card->CardNumber, card->IssueLevel, card->OEM);
calcWiegand(fmtlen, fc, cn, bits, 0); lf_hidsim_t payload;
payload.hi2 = packed.Top;
payload.hi = packed.Mid;
payload.lo = packed.Bot;
clearCommandBuffer(); clearCommandBuffer();
SendCommandMIX(CMD_LF_HID_SIMULATE, bytebits_to_byte(bits, 32), bytebits_to_byte(bits + 32, 32), 0, NULL, 0);
SendCommandNG(CMD_LF_HID_SIMULATE, (uint8_t *)&payload, sizeof(payload));
/*
PacketResponseNG resp;
WaitForResponse(CMD_LF_HID_SIMULATE, &resp);
if (resp.status == PM3_EOPABORTED)
return resp.status;
*/
msleep(delay); msleep(delay);
return sendPing(); return sendPing();
} }
@ -248,18 +260,18 @@ static int CmdHIDRead(const char *Cmd) {
lf_read(true, 12000); lf_read(true, 12000);
return CmdHIDDemod(Cmd); return CmdHIDDemod(Cmd);
} }
/*
// this read loops on device side. // this read loops on device side.
// uses the demod in lfops.c // uses the demod in lfops.c
static int CmdHIDRead_device(const char *Cmd) { static int CmdHIDWatch(const char *Cmd) {
if (Cmd[0] == 'h' || Cmd[0] == 'H') return usage_lf_hid_read(); uint8_t ctmp = tolower(param_getchar(Cmd, 0));
uint8_t findone = (Cmd[0] == '1') ? 1 : 0; if ( strlen(Cmd) == 0 || ctmp == 'h') return usage_lf_hid_watch();
clearCommandBuffer(); clearCommandBuffer();
SendCommandMIX(CMD_LF_HID_DEMOD, findone, 0, 0, NULL, 0); SendCommandMIX(CMD_LF_HID_DEMOD, 0, 0, 0, NULL, 0);
return PM3_SUCCESS; return PM3_SUCCESS;
} }
*/
static int CmdHIDSim(const char *Cmd) { static int CmdHIDSim(const char *Cmd) {
lf_hidsim_t payload; lf_hidsim_t payload;
payload.longFMT = 0; payload.longFMT = 0;
@ -309,8 +321,8 @@ static int CmdHIDClone(const char *Cmd) {
uint32_t hi2 = 0, hi = 0, lo = 0; uint32_t hi2 = 0, hi = 0, lo = 0;
uint32_t n = 0, i = 0; uint32_t n = 0, i = 0;
uint8_t ctmp = param_getchar(Cmd, 0); uint8_t ctmp = tolower(param_getchar(Cmd, 0));
if (strlen(Cmd) == 0 || ctmp == 'H' || ctmp == 'h') return usage_lf_hid_clone(); if (strlen(Cmd) == 0 || ctmp == 'h') return usage_lf_hid_clone();
uint8_t longid[1] = {0}; uint8_t longid[1] = {0};
if (strchr(Cmd, 'l') != 0) { if (strchr(Cmd, 'l') != 0) {
i++; i++;
@ -338,201 +350,8 @@ static int CmdHIDClone(const char *Cmd) {
} }
/* /*
// struct to handle wiegand
typedef struct {
uint8_t FormatLen;
uint8_t SiteCode;
uint8_t FacilityCode;
uint8_t CardNumber;
uint8_t *Wiegand;
size_t Wiegand_n;
} wiegand_t;
*/
static void addHIDMarker(uint8_t fmtlen, uint8_t *out) {
// temp array
uint8_t arr[BITS];
memset(arr, 0, BITS);
// copy inpu
uint8_t pos = sizeof(arr) - fmtlen;
memcpy(arr + pos, out, fmtlen);
switch (fmtlen) {
case 26: {
// start sentinel, BITS-bit 27 = 1
arr[BITS - 27] = 1;
// fmt smaller than 37 used, bit37 = 1
arr[BITS - 38] = 1;
memcpy(out, arr, BITS);
break;
}
case 34:
// start sentinel, BITS-bit 27 = 1
arr[BITS - 35] = 1;
// fmt smaller than 37 used, bit37 = 1
arr[BITS - 38] = 1;
memcpy(out, arr, BITS);
break;
default:
break;
}
}
// static void getParity34(uint32_t *hi, uint32_t *lo){
// uint32_t result = 0;
// int i;
// // even parity
// for (i = 7;i >= 0;i--)
// result ^= (*hi >> i) & i;
// for (i = 31;i >= 24;i--)
// result ^= (*lo >> i) & 1;
// *hi |= result << 2;
// // odd parity bit
// result = 0;
// for (i = 23;i >= 1;i--)
// result ^= (*lo >> i) & 1;
// *lo |= !result;
// }
// static void getParity37H(uint32_t *hi, uint32_t *lo){
// uint32_t result = 0;
// int i;
// // even parity
// for (i = 4;i >= 0;i--)
// result ^= (*hi >> i) & 1;
// for (i = 31;i >= 20;i--)
// result ^= (*lo >> i) & 1;
// *hi |= result << 4;
// // odd parity
// result = 0;
// for (i = 19;i >= 1;i--)
// result ^= (*lo >> i) & 1;
// *lo |= result;
// }
//static void calc26(uint16_t fc, uint32_t cardno, uint8_t *out){
static void calc26(uint16_t fc, uint32_t cardno, uint8_t *out) {
uint8_t wiegand[24];
num_to_bytebits(fc, 8, wiegand);
num_to_bytebits(cardno, 16, wiegand + 8);
wiegand_add_parity(out, wiegand, sizeof(wiegand));
}
// static void calc33(uint16_t fc, uint32_t cardno, uint8_t *out){
// }
static void calc34(uint16_t fc, uint32_t cardno, uint8_t *out) {
uint8_t wiegand[32];
num_to_bytebits(fc, 16, wiegand);
num_to_bytebits(cardno, 16, wiegand + 16);
wiegand_add_parity(out, wiegand, sizeof(wiegand));
}
// static void calc35(uint16_t fc, uint32_t cardno, uint8_t *out){
// *lo = ((cardno & 0xFFFFF) << 1) | fc << 21;
// *hi = (1 << 5) | ((fc >> 11) & 1);
// }
static void calc36(uint8_t oem, uint16_t fc, uint32_t cardno, uint8_t *out) {
// FC 1 - 16 - 16 bit
// cardno 17 - 33 - 16 bit
// oem 34 - 35 - 2 bit
// Odd Parity 0th bit 1-18
// Even Parity 36th bit 19-35
uint8_t wiegand[34];
num_to_bytebits(fc, 16, wiegand);
num_to_bytebits(cardno & 0xFFFF, 16, wiegand + 16);
num_to_bytebits(oem, 2, wiegand + 32);
wiegand_add_parity_swapped(out, wiegand, sizeof(wiegand));
}
static void calc37S(uint16_t fc, uint32_t cardno, uint8_t *out) {
// FC 2 - 17 - 16 bit
// cardno 18 - 36 - 19 bit
// Even P1 1 - 19
// Odd P37 19 - 36
uint8_t wiegand[35];
num_to_bytebits(fc, 16, wiegand);
num_to_bytebits(cardno, 19, wiegand + 16);
wiegand_add_parity(out, wiegand, sizeof(wiegand));
}
static void calc37H(uint64_t cardno, uint8_t *out) {
// SC NONE
// cardno 1-35 34 bits
// Even Parity 0th bit 1-18
// Odd Parity 36th bit 19-35
uint8_t wiegand[37];
num_to_bytebits((uint32_t)(cardno >> 32), 2, wiegand);
num_to_bytebits((uint32_t)(cardno >> 0), 32, wiegand + 2);
wiegand_add_parity(out, wiegand, sizeof(wiegand));
PrintAndLogEx(NORMAL, "%x %x\n", (uint32_t)(cardno >> 32), (uint32_t)cardno);
}
// static void calc40(uint64_t cardno, uint8_t *out){
// cardno = (cardno & 0xFFFFFFFFFF);
// *lo = ((cardno & 0xFFFFFFFF) << 1 );
// *hi = (cardno >> 31);
// }
void calcWiegand(uint8_t fmtlen, uint16_t fc, uint64_t cardno, uint8_t *bits, uint8_t oem) {
uint32_t cn32 = (cardno & 0xFFFFFFFF);
switch (fmtlen) {
case 26:
calc26(fc, cn32, bits);
break;
// case 33 : calc33(fc, cn32, bits); break;
case 34:
calc34(fc, cn32, bits);
break;
// case 35 : calc35(fc, cn32, bits); break;
case 36:
calc36(oem, fc, cn32, bits);
break;
case 37:
calc37S(fc, cn32, bits);
break;
case 38:
calc37H(cardno, bits);
break;
// case 40 : calc40(cardno, bits); break;
// case 44 : { break; }
// case 84 : { break; }
default:
break;
}
}
static int CmdHIDWiegand(const char *Cmd) {
uint32_t oem = 0, fc = 0;
uint64_t cardnum = 0;
uint8_t bits[BITS] = {0};
uint8_t *bs = bits;
uint8_t ctmp = tolower(param_getchar(Cmd, 0));
if (strlen(Cmd) < 3 || ctmp == 'h') return usage_lf_hid_wiegand();
oem = param_get8(Cmd, 0);
fc = param_get32ex(Cmd, 1, 0, 10);
cardnum = param_get64ex(Cmd, 2, 0, 10);
uint8_t fmtlen[] = {26, 33, 34, 35, 36, 37, 38, 40};
PrintAndLogEx(NORMAL, "HID | OEM | FC | CN | Wiegand | HID Formatted"); PrintAndLogEx(NORMAL, "HID | OEM | FC | CN | Wiegand | HID Formatted");
PrintAndLogEx(NORMAL, "----+-----+------+---------+-----------+--------------------"); PrintAndLogEx(NORMAL, "----+-----+------+---------+-----------+--------------------");
for (uint8_t i = 0; i < ARRAYLEN(fmtlen); i++) {
memset(bits, 0x00, sizeof(bits));
calcWiegand(fmtlen[i], fc, cardnum, bs, oem);
PrintAndLogEx(NORMAL, "ice:: %s \n", sprint_bin(bs, fmtlen[i]));
uint64_t wiegand = (uint64_t)bytebits_to_byte(bs, 32) << 32 | bytebits_to_byte(bs + 32, 32);
addHIDMarker(fmtlen[i], bs);
PrintAndLogEx(NORMAL, "ice:: %s\n", sprint_bin(bs, BITS));
uint64_t blocks = (uint64_t)bytebits_to_byte(bs + 32, 32) << 32 | bytebits_to_byte(bs + 64, 32);
uint8_t shifts = 64 - fmtlen[i];
wiegand >>= shifts;
PrintAndLogEx(NORMAL, " %u | %03u | %03u | %" PRIu64 " | %" PRIX64 " | %" PRIX64, PrintAndLogEx(NORMAL, " %u | %03u | %03u | %" PRIu64 " | %" PRIX64 " | %" PRIX64,
fmtlen[i], fmtlen[i],
oem, oem,
@ -543,26 +362,33 @@ static int CmdHIDWiegand(const char *Cmd) {
); );
} }
PrintAndLogEx(NORMAL, "----+-----+-----+-------+-----------+--------------------"); PrintAndLogEx(NORMAL, "----+-----+-----+-------+-----------+--------------------");
return PM3_SUCCESS; */
}
static int CmdHIDBrute(const char *Cmd) { static int CmdHIDBrute(const char *Cmd) {
bool errors = false, verbose = false; bool errors = false, verbose = false;
uint32_t fc = 0, cn = 0, delay = 1000; uint32_t delay = 1000;
uint8_t fmtlen = 0;
uint8_t bits[96];
memset(bits, 0, sizeof(bits));
uint8_t cmdp = 0; uint8_t cmdp = 0;
int format_idx = -1;
char format[16] = {0};
wiegand_card_t data;
memset(&data, 0, sizeof(wiegand_card_t));
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
switch (tolower(param_getchar(Cmd, cmdp))) { switch (tolower(param_getchar(Cmd, cmdp))) {
case 'h': case 'h':
return usage_lf_hid_brute(); return usage_lf_hid_brute();
case 'f': case 'w':
fc = param_get32ex(Cmd, cmdp + 1, 0, 10); param_getstr(Cmd, cmdp + 1, format, sizeof(format));
if (!fc) format_idx = HIDFindCardFormat(format);
if (format_idx == -1) {
PrintAndLogEx(WARNING, "Unknown format: %s", format);
errors = true; errors = true;
}
cmdp += 2;
break;
case 'c':
data.CardNumber = param_get32ex(Cmd, cmdp + 1, 0, 10);
cmdp += 2; cmdp += 2;
break; break;
case 'd': case 'd':
@ -570,24 +396,17 @@ static int CmdHIDBrute(const char *Cmd) {
delay = param_get32ex(Cmd, cmdp + 1, 1000, 10); delay = param_get32ex(Cmd, cmdp + 1, 1000, 10);
cmdp += 2; cmdp += 2;
break; break;
case 'c': case 'f':
cn = param_get32ex(Cmd, cmdp + 1, 0, 10); data.FacilityCode = param_get32ex(Cmd, cmdp + 1, 0, 10);
// truncate cardnumber.
cn &= 0xFFFF;
cmdp += 2; cmdp += 2;
break; break;
case 'a': case 'i':
fmtlen = param_get8(Cmd, cmdp + 1); data.IssueLevel = param_get32ex(Cmd, cmdp + 1, 0, 10);
cmdp += 2;
break;
case 'o':
data.OEM = param_get32ex(Cmd, cmdp + 1, 0, 10);
cmdp += 2; cmdp += 2;
bool is_ftm_ok = false;
uint8_t ftms[] = {26, 33, 34, 35, 37};
for (uint8_t i = 0; i < ARRAYLEN(ftms); i++) {
if (ftms[i] == fmtlen) {
is_ftm_ok = true;
}
}
// negated
errors = !is_ftm_ok;
break; break;
case 'v': case 'v':
verbose = true; verbose = true;
@ -599,15 +418,11 @@ static int CmdHIDBrute(const char *Cmd) {
break; break;
} }
} }
if (fc == 0) errors = true;
if (errors) return usage_lf_hid_brute(); if (errors) return usage_lf_hid_brute();
PrintAndLogEx(INFO, "Brute-forcing HID reader"); PrintAndLogEx(INFO, "Brute-forcing HID reader");
PrintAndLogEx(INFO, "Press pm3-button to abort simulation or run another command"); PrintAndLogEx(INFO, "Press pm3-button to abort simulation or run another command");
uint16_t up = cn;
uint16_t down = cn;
// main loop // main loop
for (;;) { for (;;) {
@ -622,13 +437,16 @@ static int CmdHIDBrute(const char *Cmd) {
} }
// Do one up // Do one up
if (up < 0xFFFF) if (data.CardNumber < 0xFFFF) {
if (sendTry(fmtlen, fc, up++, delay, bits, verbose) != PM3_SUCCESS) return PM3_ESOFT; data.CardNumber++;
if (sendTry(format_idx, &data, delay, verbose) != PM3_SUCCESS) return PM3_ESOFT;
}
// Do one down (if cardnumber is given) // Do one down (if cardnumber is given)
if (cn > 1) if (data.CardNumber > 1) {
if (down > 1) data.CardNumber--;
if (sendTry(fmtlen, fc, --down, delay, bits, verbose) != PM3_SUCCESS) return PM3_ESOFT; if (sendTry(format_idx, &data, delay, verbose) != PM3_SUCCESS) return PM3_ESOFT;
}
} }
return PM3_SUCCESS; return PM3_SUCCESS;
} }
@ -639,8 +457,8 @@ static command_t CommandTable[] = {
{"read", CmdHIDRead, IfPm3Lf, "attempt to read and extract tag data"}, {"read", CmdHIDRead, IfPm3Lf, "attempt to read and extract tag data"},
{"clone", CmdHIDClone, IfPm3Lf, "clone HID to T55x7"}, {"clone", CmdHIDClone, IfPm3Lf, "clone HID to T55x7"},
{"sim", CmdHIDSim, IfPm3Lf, "simulate HID tag"}, {"sim", CmdHIDSim, IfPm3Lf, "simulate HID tag"},
{"wiegand", CmdHIDWiegand, AlwaysAvailable, "convert facility code/card number to Wiegand code"},
{"brute", CmdHIDBrute, IfPm3Lf, "bruteforce card number against reader"}, {"brute", CmdHIDBrute, IfPm3Lf, "bruteforce card number against reader"},
{"watch", CmdHIDWatch, IfPm3Lf, "continuously watch for cards. Reader mode"},
{NULL, NULL, NULL, NULL} {NULL, NULL, NULL, NULL}
}; };

View file

@ -25,6 +25,8 @@
#include "lfdemod.h" // parityTest, bitbytes_to_byte #include "lfdemod.h" // parityTest, bitbytes_to_byte
#include "cmddata.h" #include "cmddata.h"
#include "cmdlf.h" // lf_read #include "cmdlf.h" // lf_read
#include "protocols.h" // t55 defines
#include "cmdlft55xx.h" // verifywrite
static int CmdHelp(const char *Cmd); static int CmdHelp(const char *Cmd);
@ -439,10 +441,12 @@ static int CmdIndalaSim(const char *Cmd) {
return PM3_SUCCESS; return PM3_SUCCESS;
} }
// iceman - needs refactoring
static int CmdIndalaClone(const char *Cmd) { static int CmdIndalaClone(const char *Cmd) {
bool isLongUid = false; bool isLongUid = false;
uint32_t blocks[8] = {0};
uint8_t max = 0;
uint8_t data[7 * 4]; uint8_t data[7 * 4];
int datalen = 0; int datalen = 0;
@ -466,27 +470,77 @@ static int CmdIndalaClone(const char *Cmd) {
CLIGetHexWithReturn(2, data, &datalen); CLIGetHexWithReturn(2, data, &datalen);
CLIParserFree(); CLIParserFree();
/*
//TODO add selection of chip for Q5 or T55x7
// data[0] = T5555_SET_BITRATE(32 | T5555_MODULATION_PSK2 | 7 << T5555_MAXBLOCK_SHIFT;
//Alternative config for Indala (Extended mode;RF/32;PSK1 with RF/2;Maxblock=7;Inverse data)
// T5567WriteBlock(0x603E10E2,0);
// data[0] = T5555_SET_BITRATE(32 | T5555_MODULATION_PSK1 | 2 << T5555_MAXBLOCK_SHIFT;
//Alternative config for Indala (Extended mode;RF/32;PSK1 with RF/2;Maxblock=2;Inverse data)
// T5567WriteBlock(0x603E1042,0);
*/
if (isLongUid) { if (isLongUid) {
// config for Indala (RF/32;PSK2 with RF/2;Maxblock=7)
PrintAndLogEx(INFO, "Preparing to clone Indala 224bit tag with RawID %s", sprint_hex(data, datalen)); PrintAndLogEx(INFO, "Preparing to clone Indala 224bit tag with RawID %s", sprint_hex(data, datalen));
uint32_t datawords[7] = {0}; blocks[0] = T55x7_BITRATE_RF_32 | T55x7_MODULATION_PSK2 | (7 << T55x7_MAXBLOCK_SHIFT);
datawords[0] = bytes_to_num(data, 4); blocks[1] = bytes_to_num(data, 4);
datawords[1] = bytes_to_num(data + 4, 4); blocks[2] = bytes_to_num(data + 4, 4);
datawords[2] = bytes_to_num(data + 8, 4); blocks[3] = bytes_to_num(data + 8, 4);
datawords[3] = bytes_to_num(data + 12, 4); blocks[4] = bytes_to_num(data + 12, 4);
datawords[4] = bytes_to_num(data + 16, 4); blocks[5] = bytes_to_num(data + 16, 4);
datawords[5] = bytes_to_num(data + 20, 4); blocks[6] = bytes_to_num(data + 20, 4);
datawords[6] = bytes_to_num(data + 24, 4); blocks[7] = bytes_to_num(data + 24, 4);
clearCommandBuffer(); max = 8;
SendCommandOLD(CMD_LF_INDALA224_CLONE, 0, 0, 0, datawords, sizeof(datawords));
} else { } else {
// config for Indala 64 format (RF/32;PSK1 with RF/2;Maxblock=2)
PrintAndLogEx(INFO, "Preparing to clone Indala 64bit tag with RawID %s", sprint_hex(data, datalen)); PrintAndLogEx(INFO, "Preparing to clone Indala 64bit tag with RawID %s", sprint_hex(data, datalen));
uint32_t datawords[2] = {0}; blocks[0] = T55x7_BITRATE_RF_32 | T55x7_MODULATION_PSK1 | (2 << T55x7_MAXBLOCK_SHIFT);
datawords[0] = bytes_to_num(data, 4); blocks[1] = bytes_to_num(data, 4);
datawords[1] = bytes_to_num(data + 4, 4); blocks[2] = bytes_to_num(data + 4, 4);
clearCommandBuffer(); max = 3;
SendCommandOLD(CMD_LF_INDALA_CLONE, 0, 0, 0, datawords, sizeof(datawords));
} }
print_blocks(blocks, max);
uint8_t res = 0;
PacketResponseNG resp;
// fast push mode
conn.block_after_ACK = true;
for (uint8_t i = 0; i < max; i++) {
if (i == max - 1) {
// Disable fast mode on last packet
conn.block_after_ACK = false;
}
clearCommandBuffer();
t55xx_write_block_t ng;
ng.data = blocks[i];
ng.pwd = 0;
ng.blockno = i;
ng.flags = 0;
SendCommandNG(CMD_LF_T55XX_WRITEBL, (uint8_t *)&ng, sizeof(ng));
if (!WaitForResponseTimeout(CMD_LF_T55XX_WRITEBL, &resp, T55XX_WRITE_TIMEOUT)) {
PrintAndLogEx(ERR, "Error occurred, device did not respond during write operation.");
return PM3_ETIMEOUT;
}
if (i == 0) {
SetConfigWithBlock0(blocks[0]);
if (t55xxAquireAndCompareBlock0(false, 0, blocks[0], false))
continue;
}
if (t55xxVerifyWrite(i, 0, false, false, 0, 0xFF, blocks[i]) == false)
res++;
}
if (res == 0)
PrintAndLogEx(SUCCESS, "Success writing to tag");
return PM3_SUCCESS; return PM3_SUCCESS;
} }

View file

@ -24,6 +24,7 @@
#include "lfdemod.h" // parityTest, bitbytes_to_byte #include "lfdemod.h" // parityTest, bitbytes_to_byte
#include "protocols.h" // for T55xx config register definitions #include "protocols.h" // for T55xx config register definitions
#include "cmddata.h" #include "cmddata.h"
#include "cmdlft55xx.h" // verifywrite
static int CmdHelp(const char *Cmd); static int CmdHelp(const char *Cmd);
/* /*
@ -243,7 +244,6 @@ static int CmdIOProxSim(const char *Cmd) {
static int CmdIOProxClone(const char *Cmd) { static int CmdIOProxClone(const char *Cmd) {
uint32_t blocks[3] = {T55x7_MODULATION_FSK2a | T55x7_BITRATE_RF_64 | 2 << T55x7_MAXBLOCK_SHIFT, 0, 0};
uint16_t cn = 0; uint16_t cn = 0;
uint8_t version = 0, fc = 0; uint8_t version = 0, fc = 0;
uint8_t bits[64]; uint8_t bits[64];
@ -268,7 +268,9 @@ static int CmdIOProxClone(const char *Cmd) {
return PM3_ESOFT; return PM3_ESOFT;
} }
if (param_getchar(Cmd, 3) == 'Q' || param_getchar(Cmd, 3) == 'q') uint32_t blocks[3] = {T55x7_MODULATION_FSK2a | T55x7_BITRATE_RF_64 | 2 << T55x7_MAXBLOCK_SHIFT, 0, 0};
if (tolower(param_getchar(Cmd, 3) == 'q'))
blocks[0] = T5555_MODULATION_FSK2 | T5555_INVERT_OUTPUT | T5555_SET_BITRATE(64) | 2 << T5555_MAXBLOCK_SHIFT; blocks[0] = T5555_MODULATION_FSK2 | T5555_INVERT_OUTPUT | T5555_SET_BITRATE(64) | 2 << T5555_MAXBLOCK_SHIFT;
blocks[1] = bytebits_to_byte(bits, 32); blocks[1] = bytebits_to_byte(bits, 32);
@ -277,8 +279,42 @@ static int CmdIOProxClone(const char *Cmd) {
PrintAndLogEx(INFO, "Preparing to clone IOProx to T55x7 with Version: %u FC: %u, CN: %u", version, fc, cn); PrintAndLogEx(INFO, "Preparing to clone IOProx to T55x7 with Version: %u FC: %u, CN: %u", version, fc, cn);
print_blocks(blocks, 3); print_blocks(blocks, 3);
uint8_t res = 0;
PacketResponseNG resp;
// fast push mode
conn.block_after_ACK = true;
for (uint8_t i = 0; i < 3; i++) {
if (i == 2) {
// Disable fast mode on last packet
conn.block_after_ACK = false;
}
clearCommandBuffer(); clearCommandBuffer();
SendCommandMIX(CMD_LF_IO_CLONE, blocks[1], blocks[2], 0, NULL, 0); t55xx_write_block_t ng;
ng.data = blocks[i];
ng.pwd = 0;
ng.blockno = i;
ng.flags = 0;
SendCommandNG(CMD_LF_T55XX_WRITEBL, (uint8_t *)&ng, sizeof(ng));
if (!WaitForResponseTimeout(CMD_LF_T55XX_WRITEBL, &resp, T55XX_WRITE_TIMEOUT)) {
PrintAndLogEx(ERR, "Error occurred, device did not respond during write operation.");
return PM3_ETIMEOUT;
}
if (i == 0) {
SetConfigWithBlock0(blocks[0]);
if (t55xxAquireAndCompareBlock0(false, 0, blocks[0], false))
continue;
}
if (t55xxVerifyWrite(i, 0, false, false, 0, 0xFF, blocks[i]) == false)
res++;
}
if (res == 0)
PrintAndLogEx(SUCCESS, "Success writing to tag");
return PM3_SUCCESS; return PM3_SUCCESS;
} }

View file

@ -24,6 +24,7 @@
#include "cmdlf.h" #include "cmdlf.h"
#include "protocols.h" // for T55xx config register definitions #include "protocols.h" // for T55xx config register definitions
#include "lfdemod.h" // parityTest #include "lfdemod.h" // parityTest
#include "cmdlft55xx.h" // verifywrite
static int CmdHelp(const char *Cmd); static int CmdHelp(const char *Cmd);
@ -170,6 +171,7 @@ static int CmdJablotronClone(const char *Cmd) {
PrintAndLogEx(INFO, "Preparing to clone Jablotron to T55x7 with FullCode: %"PRIx64, fullcode); PrintAndLogEx(INFO, "Preparing to clone Jablotron to T55x7 with FullCode: %"PRIx64, fullcode);
print_blocks(blocks, 3); print_blocks(blocks, 3);
uint8_t res = 0;
PacketResponseNG resp; PacketResponseNG resp;
// fast push mode // fast push mode
@ -192,7 +194,20 @@ static int CmdJablotronClone(const char *Cmd) {
PrintAndLogEx(ERR, "Error occurred, device did not respond during write operation."); PrintAndLogEx(ERR, "Error occurred, device did not respond during write operation.");
return PM3_ETIMEOUT; return PM3_ETIMEOUT;
} }
if (i == 0) {
SetConfigWithBlock0(blocks[0]);
if (t55xxAquireAndCompareBlock0(false, 0, blocks[0], false))
continue;
} }
if (t55xxVerifyWrite(i, 0, false, false, 0, 0xFF, blocks[i]) == false)
res++;
}
if (res == 0)
PrintAndLogEx(SUCCESS, "Success writing to tag");
return PM3_SUCCESS; return PM3_SUCCESS;
} }

View file

@ -22,6 +22,7 @@
#include "cmdlf.h" #include "cmdlf.h"
#include "protocols.h" // for T55xx config register definitions #include "protocols.h" // for T55xx config register definitions
#include "lfdemod.h" // preamble test #include "lfdemod.h" // preamble test
#include "cmdlft55xx.h" // verifywrite
static int CmdHelp(const char *Cmd); static int CmdHelp(const char *Cmd);
@ -159,6 +160,7 @@ static int CmdKeriClone(const char *Cmd) {
blocks[2] = data & 0xFFFFFFFF; blocks[2] = data & 0xFFFFFFFF;
print_blocks(blocks, 3); print_blocks(blocks, 3);
uint8_t res = 0;
PacketResponseNG resp; PacketResponseNG resp;
// fast push mode // fast push mode
@ -181,8 +183,20 @@ static int CmdKeriClone(const char *Cmd) {
PrintAndLogEx(ERR, "Error occurred, device did not respond during write operation."); PrintAndLogEx(ERR, "Error occurred, device did not respond during write operation.");
return PM3_ETIMEOUT; return PM3_ETIMEOUT;
} }
if (i == 0) {
SetConfigWithBlock0(blocks[0]);
if (t55xxAquireAndCompareBlock0(false, 0, blocks[0], false))
continue;
} }
if (t55xxVerifyWrite(i, 0, false, false, 0, 0xFF, blocks[i]) == false)
res++;
}
if (res == 0)
PrintAndLogEx(SUCCESS, "Success writing to tag");
return PM3_SUCCESS; return PM3_SUCCESS;
} }

View file

@ -9,20 +9,6 @@
#include "cmdlfnedap.h" #include "cmdlfnedap.h"
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#include "cmdparser.h" // command_t
#include "comms.h"
#include "crc16.h"
#include "cmdlft55xx.h"
#include "ui.h"
#include "cmddata.h"
#include "cmdlf.h"
#include "lfdemod.h"
#define FIXED_71 0x71 #define FIXED_71 0x71
#define FIXED_40 0x40 #define FIXED_40 0x40
#define UNKNOWN_A 0x00 #define UNKNOWN_A 0x00
@ -469,6 +455,7 @@ int CmdLFNedapClone(const char *Cmd) {
PrintAndLogEx(SUCCESS, "Preparing to clone NEDAP to T55x7"); PrintAndLogEx(SUCCESS, "Preparing to clone NEDAP to T55x7");
print_blocks(blocks, max); print_blocks(blocks, max);
uint8_t res = 0;
PacketResponseNG resp; PacketResponseNG resp;
// fast push mode // fast push mode
@ -490,10 +477,24 @@ int CmdLFNedapClone(const char *Cmd) {
PrintAndLogEx(ERR, "Error occurred, device did not respond during write operation."); PrintAndLogEx(ERR, "Error occurred, device did not respond during write operation.");
return PM3_ETIMEOUT; return PM3_ETIMEOUT;
} }
if (i == 0) {
SetConfigWithBlock0(blocks[0]);
if (t55xxAquireAndCompareBlock0(false, 0, blocks[0], false))
continue;
} }
PrintAndLogEx(NORMAL, "\n");
if (t55xxVerifyWrite(i, 0, false, false, 0, 0xFF, blocks[i]) == false)
res++;
}
if (res == 0)
PrintAndLogEx(SUCCESS, "Success writing to tag");
else {
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(INFO, "The block 0 was changed (eXtended) which can be hard to detect."); PrintAndLogEx(INFO, "The block 0 was changed (eXtended) which can be hard to detect.");
PrintAndLogEx(INFO, " Configure it manually " _YELLOW_("`lf t55xx config b 64 d BI i 1 o 32`")); PrintAndLogEx(INFO, " Configure it manually " _YELLOW_("`lf t55xx config b 64 d BI i 1 o 32`"));
}
return PM3_SUCCESS; return PM3_SUCCESS;
} }

View file

@ -11,6 +11,19 @@
#include "common.h" #include "common.h"
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#include "cmdparser.h" // command_t
#include "comms.h"
#include "crc16.h"
#include "cmdlft55xx.h" // verifywrite
#include "ui.h"
#include "cmddata.h"
#include "cmdlf.h"
#include "lfdemod.h"
int CmdLFNedap(const char *Cmd); int CmdLFNedap(const char *Cmd);
int demodNedap(void); int demodNedap(void);

View file

@ -177,16 +177,17 @@ static int CmdNoralsyClone(const char *Cmd) {
return PM3_ETIMEOUT; return PM3_ETIMEOUT;
} }
// write block0, needs a detect. if (i == 0) {
if (i == 0) SetConfigWithBlock0(blocks[0]);
t55xxAquireAndDetect(false, 0, blocks[i], false); if (t55xxAquireAndCompareBlock0(false, 0, blocks[0], false))
continue;
}
if (t55xxVerifyWrite(i, 0, false, false, 0, 0xFF, blocks[i]) == false) if (t55xxVerifyWrite(i, 0, false, false, 0, 0xFF, blocks[i]) == false)
res++; res++;
} }
if ( res == 0 ) if (res == 0)
PrintAndLogEx(SUCCESS, "Success writing to tag"); PrintAndLogEx(SUCCESS, "Success writing to tag");
return PM3_SUCCESS; return PM3_SUCCESS;

View file

@ -144,19 +144,18 @@ static int CmdPrescoClone(const char *Cmd) {
return PM3_ETIMEOUT; return PM3_ETIMEOUT;
} }
// write block0, needs a detect.
if (i == 0) { if (i == 0) {
printf("enter detect "); SetConfigWithBlock0(blocks[0]);
bool ok = t55xxAquireAndDetect(false, 0, blocks[i], false); if (t55xxAquireAndCompareBlock0(false, 0, blocks[0], false))
printf(" b0 = '%c' \n", (ok) ? 'Y':'N'); continue;
}
if (t55xxVerifyWrite(i, 0, false, false, 0, 0xFF, blocks[i]) == false) {
res++;
printf(" i = %d \n", i);
}
} }
if ( res == 0 ) if (t55xxVerifyWrite(i, 0, false, false, 0, 0xFF, blocks[i]) == false)
res++;
}
if (res == 0)
PrintAndLogEx(SUCCESS, "Success writing to tag"); PrintAndLogEx(SUCCESS, "Success writing to tag");
return PM3_SUCCESS; return PM3_SUCCESS;

View file

@ -254,16 +254,18 @@ static int CmdPyramidClone(const char *Cmd) {
return PM3_ETIMEOUT; return PM3_ETIMEOUT;
} }
// write block0, needs a detect. if (i == 0) {
if (i == 0) SetConfigWithBlock0(blocks[0]);
t55xxAquireAndDetect(false, 0, blocks[i], false); if (t55xxAquireAndCompareBlock0(false, 0, blocks[0], false))
continue;
}
if (t55xxVerifyWrite(i, 0, false, false, 0, 0xFF, blocks[i]) == false) if (t55xxVerifyWrite(i, 0, false, false, 0, 0xFF, blocks[i]) == false)
res++; res++;
} }
if ( res == 0 ) if (res == 0)
PrintAndLogEx(SUCCESS, "Success writing to tag"); PrintAndLogEx(SUCCESS, "Success writing to tag");
return PM3_SUCCESS; return PM3_SUCCESS;

View file

@ -52,7 +52,7 @@ t55xx_conf_block_t config = {
.Q5 = false, .Q5 = false,
.usepwd = false, .usepwd = false,
.downlink_mode = refFixedBit .downlink_mode = refFixedBit
}; };
t55xx_conf_block_t Get_t55xx_Config() { t55xx_conf_block_t Get_t55xx_Config() {
return config; return config;
@ -338,7 +338,7 @@ static int usage_t55xx_protect() {
static int CmdHelp(const char *Cmd); static int CmdHelp(const char *Cmd);
static bool t55xxProtect(bool lock, bool usepwd, uint8_t override, uint32_t password, uint8_t downlink_mode, uint32_t new_password ) { static bool t55xxProtect(bool lock, bool usepwd, uint8_t override, uint32_t password, uint8_t downlink_mode, uint32_t new_password) {
PrintAndLogEx(INFO, "Checking current configuration"); PrintAndLogEx(INFO, "Checking current configuration");
@ -354,7 +354,7 @@ static bool t55xxProtect(bool lock, bool usepwd, uint8_t override, uint32_t pass
if (GetT55xxBlockData(&block0) == false) if (GetT55xxBlockData(&block0) == false)
return false; return false;
bool isPwdBitAlreadySet = (block0 >> (32-28) & 1); bool isPwdBitAlreadySet = (block0 >> (32 - 28) & 1);
if (isPwdBitAlreadySet) { if (isPwdBitAlreadySet) {
PrintAndLogEx(INFO, "PWD bit is already set"); PrintAndLogEx(INFO, "PWD bit is already set");
usepwd = true; usepwd = true;
@ -368,7 +368,7 @@ static bool t55xxProtect(bool lock, bool usepwd, uint8_t override, uint32_t pass
} }
// write new password // write new password
if ( t55xxWrite(T55x7_PWD_BLOCK, T55x7_PAGE0, usepwd, testmode, password, downlink_mode, new_password ) != PM3_SUCCESS ) { if (t55xxWrite(T55x7_PWD_BLOCK, T55x7_PAGE0, usepwd, testmode, password, downlink_mode, new_password) != PM3_SUCCESS) {
PrintAndLogEx(ERR, "Failed to write new password"); PrintAndLogEx(ERR, "Failed to write new password");
return false; return false;
} else { } else {
@ -386,7 +386,7 @@ static bool t55xxProtect(bool lock, bool usepwd, uint8_t override, uint32_t pass
} }
// write config // write config
if ( t55xxWrite(T55x7_CONFIGURATION_BLOCK, T55x7_PAGE0, usepwd, testmode, curr_password, downlink_mode, block0 ) != PM3_SUCCESS ) { if (t55xxWrite(T55x7_CONFIGURATION_BLOCK, T55x7_PAGE0, usepwd, testmode, curr_password, downlink_mode, block0) != PM3_SUCCESS) {
PrintAndLogEx(ERR, "Failed to write modified configuration block %08X", block0); PrintAndLogEx(ERR, "Failed to write modified configuration block %08X", block0);
return false; return false;
} else { } else {
@ -405,18 +405,45 @@ static bool t55xxProtect(bool lock, bool usepwd, uint8_t override, uint32_t pass
} }
} }
bool t55xxAquireAndCompareBlock0(bool usepwd, uint32_t password, uint32_t known_block0, bool verbose) {
if (verbose)
PrintAndLogEx(INFO, "Block0 write detected, running `detect` to see if validation is possible");
for (uint8_t m = 0; m < 4; m++) {
if (AquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, usepwd, password, m) == false) {
continue;
}
if (DecodeT55xxBlock() == false) {
continue;
}
for (uint16_t i = 0; DemodBufferLen - 32; i++) {
uint32_t tmp = PackBits(i, 32, DemodBuffer);
if (tmp == known_block0) {
config.offset = i;
config.downlink_mode = m;
return true;
}
}
}
return false;
}
bool t55xxAquireAndDetect(bool usepwd, uint32_t password, uint32_t known_block0, bool verbose) { bool t55xxAquireAndDetect(bool usepwd, uint32_t password, uint32_t known_block0, bool verbose) {
if (verbose) if (verbose)
PrintAndLogEx(INFO, "Block0 write detected, running `detect` to see if validation is possible"); PrintAndLogEx(INFO, "Block0 write detected, running `detect` to see if validation is possible");
for ( uint8_t m = 0; m < 4; m++) { for (uint8_t m = 0; m < 4; m++) {
if (AquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, usepwd, password, m) == false) if (AquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, usepwd, password, m) == false)
continue; continue;
if (tryDetectModulationEx(m, verbose, known_block0) == false) if (tryDetectModulationEx(m, verbose, known_block0) == false)
continue; continue;
config.downlink_mode = m;
return true; return true;
} }
return false; return false;
@ -435,7 +462,7 @@ bool t55xxVerifyWrite(uint8_t block, bool page1, bool usepwd, uint8_t override,
if (GetT55xxBlockData(&read_data) == false) if (GetT55xxBlockData(&read_data) == false)
return false; return false;
} else if ( res == PM3_EWRONGANSVER) { } else if (res == PM3_EWRONGANSVER) {
// could't decode. Lets see if this was a block 0 write and try read/detect it auto. // could't decode. Lets see if this was a block 0 write and try read/detect it auto.
// this messes up with ppls config.. // this messes up with ppls config..
@ -491,6 +518,39 @@ void printT5xxHeader(uint8_t page) {
PrintAndLogEx(SUCCESS, "----+----------+----------------------------------+-------"); PrintAndLogEx(SUCCESS, "----+----------+----------------------------------+-------");
} }
void SetConfigWithBlock0(uint32_t block0) {
SetConfigWithBlock0Ex(block0, 0, false);
}
void SetConfigWithBlock0Ex(uint32_t block0, uint8_t offset, bool Q5) {
// T55x7
uint32_t extend = (block0 >> (32 - 15)) & 0x01;
uint32_t dbr;
if (extend)
dbr = (block0 >> (32 - 14)) & 0x3F;
else
dbr = (block0 >> (32 - 14)) & 0x07;
uint32_t datamod = (block0 >> (32 - 20)) & 0x1F;
bool pwd = (bool)((block0 >> (32 - 28)) & 0x01);
bool sst = (bool)((block0 >> (32 - 29)) & 0x01);
bool inv = (bool)((block0 >> (32 - 31)) & 0x01);
config.modulation = datamod;
config.bitrate = dbr;
// FSK1a, FSK2a
if (datamod == DEMOD_FSK1a || datamod == DEMOD_FSK2a || datamod == DEMOD_BIa)
config.inverted = 1;
else
config.inverted = inv;
config.Q5 = Q5;
config.ST = sst;
config.usepwd = pwd;
config.offset = offset;
config.block0 = block0;
}
static int CmdT55xxSetConfig(const char *Cmd) { static int CmdT55xxSetConfig(const char *Cmd) {
// No args // No args
@ -619,32 +679,8 @@ static int CmdT55xxSetConfig(const char *Cmd) {
//Validations //Validations
if (errors) return usage_t55xx_config(); if (errors) return usage_t55xx_config();
if ( gotconf ) { if (gotconf) {
SetConfigWithBlock0Ex(block0, config.offset, config.Q5);
// Q5
// T55x7
uint32_t extend = (block0 >> (32 - 15)) & 0x01;
uint32_t dbr;
if (extend)
dbr = (block0 >> (32 - 14)) & 0x3F;
else
dbr = (block0 >> (32 - 14)) & 0x07;
uint32_t datamod = (block0 >> (32 - 20)) & 0x1F;
bool pwd = (bool)((block0 >> (32 - 28)) & 0x01);
bool sst = (bool)((block0 >> (32 - 29)) & 0x01);
bool inv = (bool)((block0 >> (32 - 31)) & 0x01);
config.modulation = datamod;
config.bitrate = dbr;
config.inverted = inv;
config.Q5 = 0;
config.ST = sst;
config.usepwd = pwd;
config.offset = 0;
config.block0 = block0;
} else { } else {
config.block0 = 0; config.block0 = 0;
} }
@ -893,7 +929,7 @@ static int CmdT55xxDetect(const char *Cmd) {
if (useGB == false) { if (useGB == false) {
if ( try_all_dl_modes ) { if (try_all_dl_modes) {
for (uint8_t m = downlink_mode; m < 4; m++) { for (uint8_t m = downlink_mode; m < 4; m++) {
if (AquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, usepwd, password, m) == false) if (AquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, usepwd, password, m) == false)
@ -1116,7 +1152,7 @@ bool tryDetectModulationEx(uint8_t downlink_mode, bool print_config, uint32_t wa
wanted = (wanted_conf == tests[i].block0); wanted = (wanted_conf == tests[i].block0);
retval = testKnownConfigBlock(tests[i].block0); retval = testKnownConfigBlock(tests[i].block0);
if (retval || wanted ) { if (retval || wanted) {
PrintAndLogEx(NORMAL, "--[%d]--------------- << selected this", i + 1); PrintAndLogEx(NORMAL, "--[%d]--------------- << selected this", i + 1);
config.modulation = tests[i].modulation; config.modulation = tests[i].modulation;
config.bitrate = tests[i].bitrate; config.bitrate = tests[i].bitrate;
@ -1391,7 +1427,7 @@ int printConfiguration(t55xx_conf_block_t b) {
PrintAndLogEx(NORMAL, " Offset : %d", b.offset); PrintAndLogEx(NORMAL, " Offset : %d", b.offset);
PrintAndLogEx(NORMAL, " Seq. Term. : %s", (b.ST) ? _GREEN_("Yes") : "No"); PrintAndLogEx(NORMAL, " Seq. Term. : %s", (b.ST) ? _GREEN_("Yes") : "No");
PrintAndLogEx(NORMAL, " Block0 : 0x%08X", b.block0); PrintAndLogEx(NORMAL, " Block0 : 0x%08X", b.block0);
PrintAndLogEx(NORMAL, " Downlink Mode : %s", GetDownlinkModeStr (b.downlink_mode)); PrintAndLogEx(NORMAL, " Downlink Mode : %s", GetDownlinkModeStr(b.downlink_mode));
PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "");
return PM3_SUCCESS; return PM3_SUCCESS;
} }
@ -1514,7 +1550,7 @@ static int CmdT55xxWriteBlock(const char *Cmd) {
PrintAndLogEx(INFO, "Writing page %d block: %02d data: 0x%08X %s", page1, block, data, (usepwd) ? pwdStr : ""); PrintAndLogEx(INFO, "Writing page %d block: %02d data: 0x%08X %s", page1, block, data, (usepwd) ? pwdStr : "");
if ( t55xxWrite(block, page1, usepwd, testMode, password, downlink_mode, data) != PM3_SUCCESS ) { if (t55xxWrite(block, page1, usepwd, testMode, password, downlink_mode, data) != PM3_SUCCESS) {
PrintAndLogEx(ERR, "Write failed"); PrintAndLogEx(ERR, "Write failed");
return PM3_ESOFT; return PM3_ESOFT;
} }
@ -2165,23 +2201,22 @@ char *GetModulationStr(uint32_t id, bool xmode) {
return buf; return buf;
} }
char *GetDownlinkModeStr (uint8_t downlink_mode) char *GetDownlinkModeStr(uint8_t downlink_mode) {
{
static char buf[30]; static char buf[30];
char *retStr = buf; char *retStr = buf;
switch (downlink_mode) { switch (downlink_mode) {
case T55XX_DLMODE_FIXED : case T55XX_DLMODE_FIXED :
snprintf(retStr, sizeof(buf),"default/fixed bit length"); snprintf(retStr, sizeof(buf), "default/fixed bit length");
break; break;
case T55XX_DLMODE_LLR : case T55XX_DLMODE_LLR :
snprintf(retStr, sizeof(buf),"long leading reference"); snprintf(retStr, sizeof(buf), "long leading reference");
break; break;
case T55XX_DLMODE_LEADING_ZERO : case T55XX_DLMODE_LEADING_ZERO :
snprintf(retStr, sizeof(buf),"leading zero reference"); snprintf(retStr, sizeof(buf), "leading zero reference");
break; break;
case T55XX_DLMODE_1OF4 : case T55XX_DLMODE_1OF4 :
snprintf(retStr, sizeof(buf),"1 of 4 coding reference"); snprintf(retStr, sizeof(buf), "1 of 4 coding reference");
break; break;
default: default:
snprintf(retStr, sizeof(buf), _RED_("(Unknown)")); snprintf(retStr, sizeof(buf), _RED_("(Unknown)"));
@ -2392,7 +2427,7 @@ static int CmdT55xxWipe(const char *Cmd) {
if (errors) return usage_t55xx_wipe(); if (errors) return usage_t55xx_wipe();
PrintAndLogEx(INFO, "\nBegin wiping %s", (Q5)? "Q5 / T5555 tag" : "T55x7 tag"); PrintAndLogEx(INFO, "\nBegin wiping %s", (Q5) ? "Q5 / T5555 tag" : "T55x7 tag");
// default config blocks. // default config blocks.
if (gotconf == false) { if (gotconf == false) {
@ -2579,7 +2614,7 @@ static int CmdT55xxChkPwds(const char *Cmd) {
continue; continue;
} }
found = tryDetectModulation(dl_mode,T55XX_PrintConfig); found = tryDetectModulation(dl_mode, T55XX_PrintConfig);
if (found) { if (found) {
PrintAndLogEx(SUCCESS, "Found valid password: [ " _GREEN_("%08X") " ]", curr_password); PrintAndLogEx(SUCCESS, "Found valid password: [ " _GREEN_("%08X") " ]", curr_password);
dl_mode = 4; // Exit other downlink mode checks dl_mode = 4; // Exit other downlink mode checks
@ -2697,7 +2732,7 @@ uint8_t tryOnePassword(uint32_t password, uint8_t downlink_mode) {
// if (getSignalProperties()->isnoise == false) { // if (getSignalProperties()->isnoise == false) {
// } else { // } else {
if (tryDetectModulation(dl_mode,T55XX_PrintConfig)) { if (tryDetectModulation(dl_mode, T55XX_PrintConfig)) {
return 1 + (dl_mode << 1); return 1 + (dl_mode << 1);
} }
// } // }
@ -3170,7 +3205,7 @@ static int CmdT55xxProtect(const char *Cmd) {
return PM3_ESOFT; return PM3_ESOFT;
// lock // lock
if ( t55xxProtect(true, usepwd, override, password, downlink_mode, new_password) == false ) { if (t55xxProtect(true, usepwd, override, password, downlink_mode, new_password) == false) {
PrintAndLogEx(WARNING, "Command failed. Did you run `lf t55xx detect` before?"); PrintAndLogEx(WARNING, "Command failed. Did you run `lf t55xx detect` before?");
return PM3_ESOFT; return PM3_ESOFT;
} }

View file

@ -131,6 +131,9 @@ void Set_t55xx_Config(t55xx_conf_block_t conf);
int CmdLFT55XX(const char *Cmd); int CmdLFT55XX(const char *Cmd);
void SetConfigWithBlock0(uint32_t block0);
void SetConfigWithBlock0Ex(uint32_t block0, uint8_t offset, bool Q5);
char *GetPskCfStr(uint32_t id, bool q5); char *GetPskCfStr(uint32_t id, bool q5);
char *GetBitRateStr(uint32_t id, bool xmode); char *GetBitRateStr(uint32_t id, bool xmode);
char *GetSaferStr(uint32_t id); char *GetSaferStr(uint32_t id);
@ -138,13 +141,14 @@ char *GetQ5ModulationStr(uint32_t id);
char *GetModulationStr(uint32_t id, bool xmode); char *GetModulationStr(uint32_t id, bool xmode);
char *GetModelStrFromCID(uint32_t cid); char *GetModelStrFromCID(uint32_t cid);
char *GetSelectedModulationStr(uint8_t id); char *GetSelectedModulationStr(uint8_t id);
char *GetDownlinkModeStr (uint8_t dlmode); char *GetDownlinkModeStr(uint8_t dlmode);
void printT5xxHeader(uint8_t page); void printT5xxHeader(uint8_t page);
void printT55xxBlock(uint8_t blockNum); void printT55xxBlock(uint8_t blockNum);
int printConfiguration(t55xx_conf_block_t b); int printConfiguration(t55xx_conf_block_t b);
bool t55xxAquireAndCompareBlock0(bool usepwd, uint32_t password, uint32_t known_block0, bool verbose);
bool t55xxAquireAndDetect(bool usepwd, uint32_t password, uint32_t known_block0, bool verbose); bool t55xxAquireAndDetect(bool usepwd, uint32_t password, uint32_t known_block0, bool verbose);
bool t55xxVerifyWrite( uint8_t block, bool page1, bool usepwd, uint8_t override, uint32_t password, uint8_t downlink_mode, uint32_t data); bool t55xxVerifyWrite(uint8_t block, bool page1, bool usepwd, uint8_t override, uint32_t password, uint8_t downlink_mode, uint32_t data);
int T55xxReadBlock(uint8_t block, bool page1, bool usepwd, uint8_t override, uint32_t password, uint8_t downlink_mode); int T55xxReadBlock(uint8_t block, bool page1, bool usepwd, uint8_t override, uint32_t password, uint8_t downlink_mode);
int T55xxReadBlockEx(uint8_t block, bool page1, bool usepwd, uint8_t override, uint32_t password, uint8_t downlink_mode, bool verbose); int T55xxReadBlockEx(uint8_t block, bool page1, bool usepwd, uint8_t override, uint32_t password, uint8_t downlink_mode, bool verbose);

View file

@ -97,7 +97,7 @@ static int CmdVikingClone(const char *Cmd) {
clearCommandBuffer(); clearCommandBuffer();
SendCommandNG(CMD_LF_VIKING_CLONE, (uint8_t*)&payload, sizeof(payload)); SendCommandNG(CMD_LF_VIKING_CLONE, (uint8_t *)&payload, sizeof(payload));
PacketResponseNG resp; PacketResponseNG resp;
if (!WaitForResponseTimeout(CMD_LF_VIKING_CLONE, &resp, T55XX_WRITE_TIMEOUT)) { if (!WaitForResponseTimeout(CMD_LF_VIKING_CLONE, &resp, T55XX_WRITE_TIMEOUT)) {
PrintAndLogEx(ERR, "Error occurred, device did not respond during write operation."); PrintAndLogEx(ERR, "Error occurred, device did not respond during write operation.");

View file

@ -191,15 +191,17 @@ static int CmdVisa2kClone(const char *Cmd) {
return PM3_ETIMEOUT; return PM3_ETIMEOUT;
} }
// write block0, needs a detect. if (i == 0) {
if (i == 0) SetConfigWithBlock0(blocks[0]);
t55xxAquireAndDetect(false, 0, blocks[i], false); if (t55xxAquireAndCompareBlock0(false, 0, blocks[0], false))
continue;
}
if (t55xxVerifyWrite(i, 0, false, false, 0, 0xFF, blocks[i]) == false) if (t55xxVerifyWrite(i, 0, false, false, 0, 0xFF, blocks[i]) == false)
res++; res++;
} }
if ( res == 0 ) if (res == 0)
PrintAndLogEx(SUCCESS, "Success writing to tag"); PrintAndLogEx(SUCCESS, "Success writing to tag");
return PM3_SUCCESS; return PM3_SUCCESS;

View file

@ -32,6 +32,7 @@
#include "cmdflashmem.h" // rdv40 flashmem commands #include "cmdflashmem.h" // rdv40 flashmem commands
#include "cmdsmartcard.h" // rdv40 smart card ISO7816 commands #include "cmdsmartcard.h" // rdv40 smart card ISO7816 commands
#include "cmdusart.h" // rdv40 FPC USART commands #include "cmdusart.h" // rdv40 FPC USART commands
#include "cmdwiegand.h" // wiegand commands
#include "ui.h" #include "ui.h"
#include "util_posix.h" #include "util_posix.h"
@ -98,11 +99,12 @@ static command_t CommandTable[] = {
{"mem", CmdFlashMem, IfPm3Flash, "{ Flash Memory manipulation... }"}, {"mem", CmdFlashMem, IfPm3Flash, "{ Flash Memory manipulation... }"},
{"msleep", CmdMsleep, AlwaysAvailable, "Add a pause in milliseconds"}, {"msleep", CmdMsleep, AlwaysAvailable, "Add a pause in milliseconds"},
{"rem", CmdRem, AlwaysAvailable, "Add text to row in log file"}, {"rem", CmdRem, AlwaysAvailable, "Add text to row in log file"},
{"reveng", CmdRev, AlwaysAvailable, "{ Crc calculations from the RevEng software }"}, {"reveng", CmdRev, AlwaysAvailable, "{ CRC calculations from RevEng software }"},
{"sc", CmdSmartcard, IfPm3Smartcard, "{ Smart card ISO7816 commands... }"}, {"sc", CmdSmartcard, IfPm3Smartcard, "{ Smart card ISO7816 commands... }"},
{"script", CmdScript, AlwaysAvailable, "{ Scripting commands }"}, {"script", CmdScript, AlwaysAvailable, "{ Scripting commands }"},
{"trace", CmdTrace, AlwaysAvailable, "{ Trace manipulation... }"}, {"trace", CmdTrace, AlwaysAvailable, "{ Trace manipulation... }"},
{"usart", CmdUsart, IfPm3FpcUsartFromUsb, "{ USART commands... }"}, {"usart", CmdUsart, IfPm3FpcUsartFromUsb, "{ USART commands... }"},
{"wiegand", CmdWiegand, AlwaysAvailable, "{ Wiegand format manipulation... }"},
{"quit", CmdQuit, AlwaysAvailable, ""}, {"quit", CmdQuit, AlwaysAvailable, ""},
{"exit", CmdQuit, AlwaysAvailable, "Exit program"}, {"exit", CmdQuit, AlwaysAvailable, "Exit program"},
{NULL, NULL, NULL, NULL} {NULL, NULL, NULL, NULL}

205
client/cmdwiegand.c Normal file
View file

@ -0,0 +1,205 @@
//-----------------------------------------------------------------------------
// Copyright (C) 2018 iceman <iceman at iuse.se>
//
// 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.
//-----------------------------------------------------------------------------
// Trace commands
//-----------------------------------------------------------------------------
#include "cmdwiegand.h"
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include "cmdparser.h" // command_t
#include "comms.h"
#include "pm3_cmd.h"
#include "protocols.h"
#include "parity.h" // oddparity
#include "cmdhflist.h" // annotations
#include "wiegand_formats.h"
#include "wiegand_formatutils.h"
#include "util.h"
static int CmdHelp(const char *Cmd);
static int usage_wiegand_list() {
PrintAndLogEx(NORMAL, "List available wiegand formats");
return PM3_SUCCESS;
}
static int usage_wiegand_encode() {
PrintAndLogEx(NORMAL, "Encode wiegand formatted number to raw hex");
PrintAndLogEx(NORMAL, "Usage: wiegand encode [w <format>] [<field> <value (decimal)>] {...}");
PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " w <format> see `wiegand list` for available formats");
PrintAndLogEx(NORMAL, " c <value> card number");
PrintAndLogEx(NORMAL, " f <value> facility code");
PrintAndLogEx(NORMAL, " i <value> issue Level");
PrintAndLogEx(NORMAL, " o <value> OEM code");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "samples:");
PrintAndLogEx(NORMAL, " wiegand encode w H10301 f 101 c 1337");
return PM3_SUCCESS;
}
static int usage_wiegand_decode() {
PrintAndLogEx(NORMAL, "Decode raw hex to wiegand format");
PrintAndLogEx(NORMAL, "Usage: wiegand decode [id] <p>");
PrintAndLogEx(NORMAL, " p ignore invalid parity");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Samples:");
PrintAndLogEx(NORMAL, " wiegand decode 2006f623ae");
return PM3_SUCCESS;
}
void PrintTagId(wiegand_message_t *packed) {
if (packed->Top != 0) {
PrintAndLogEx(SUCCESS, "Card ID: %X%08X%08X",
(uint32_t)packed->Top,
(uint32_t)packed->Mid,
(uint32_t)packed->Bot)
;
} else {
PrintAndLogEx(SUCCESS, "Card ID: %X%08X",
(uint32_t)packed->Mid,
(uint32_t)packed->Bot)
;
}
}
int CmdWiegandList(const char *Cmd) {
bool errors = false;
char cmdp = 0;
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
switch (tolower(param_getchar(Cmd, cmdp))) {
case 'h':
return usage_wiegand_list();
default:
PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp));
errors = true;
break;
}
}
HIDListFormats();
return PM3_SUCCESS;
}
int CmdWiegandEncode(const char *Cmd) {
int format_idx = -1;
char format[16] = {0};
wiegand_card_t data;
memset(&data, 0, sizeof(wiegand_card_t));
bool errors = false;
char cmdp = 0;
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
switch (tolower(param_getchar(Cmd, cmdp))) {
case 'h':
return usage_wiegand_encode();
case 'w':
param_getstr(Cmd, cmdp + 1, format, sizeof(format));
format_idx = HIDFindCardFormat(format);
if (format_idx == -1) {
PrintAndLogEx(WARNING, "Unknown format: %s", format);
errors = true;
}
cmdp += 2;
break;
case 'i':
data.IssueLevel = param_get32ex(Cmd, cmdp + 1, 0, 10);
cmdp += 2;
break;
case 'f':
data.FacilityCode = param_get32ex(Cmd, cmdp + 1, 0, 10);
cmdp += 2;
break;
case 'c':
data.CardNumber = param_get64ex(Cmd, cmdp + 1, 0, 10);
cmdp += 2;
break;
case 'o':
data.OEM = param_get32ex(Cmd, cmdp + 1, 0, 10);
cmdp += 2;
break;
default:
PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp));
errors = true;
break;
}
}
if (errors || cmdp == 0) return usage_wiegand_encode();
wiegand_message_t packed;
memset(&packed, 0, sizeof(wiegand_message_t));
if (HIDPack(format_idx, &data, &packed) == false) {
PrintAndLogEx(WARNING, "The card data could not be encoded in the selected format.");
return PM3_ESOFT;
}
PrintTagId(&packed);
return PM3_SUCCESS;
}
int CmdWiegandDecode(const char *Cmd) {
uint32_t top = 0, mid = 0, bot = 0;
bool ignore_parity = false, gothex = false;
bool errors = false;
char cmdp = 0;
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
uint32_t strlen = param_getlength(Cmd, cmdp);
strlen++; // null termin
if (strlen > 2) {
char *s = calloc(strlen, sizeof(uint8_t));
param_getstr(Cmd, cmdp, s, strlen);
hexstring_to_u96(&top, &mid, &bot, s);
free(s);
gothex = true;
cmdp++;
continue;
}
switch (tolower(param_getchar(Cmd, cmdp))) {
case 'h':
return usage_wiegand_decode();
case 'p':
ignore_parity = true;
cmdp++;
break;
default:
PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp));
errors = true;
break;
}
}
if (gothex == false)
errors = true;
if (errors || cmdp < 1) return usage_wiegand_decode();
wiegand_message_t packed = initialize_message_object(top, mid, bot);
HIDTryUnpack(&packed, ignore_parity);
return PM3_SUCCESS;
}
static command_t CommandTable[] = {
{"help", CmdHelp, AlwaysAvailable, "This help"},
{"list", CmdWiegandList, AlwaysAvailable, "List available wiegand formats"},
{"encode", CmdWiegandEncode, AlwaysAvailable, "Convert "},
{"decode", CmdWiegandDecode, AlwaysAvailable, "Convert raw hex to wiegand format"},
{NULL, NULL, NULL, NULL}
};
static int CmdHelp(const char *Cmd) {
(void)Cmd; // Cmd is not used so far
CmdsHelp(CommandTable);
return PM3_SUCCESS;
}
int CmdWiegand(const char *Cmd) {
clearCommandBuffer();
return CmdsParse(CommandTable, Cmd);
}

20
client/cmdwiegand.h Normal file
View file

@ -0,0 +1,20 @@
//-----------------------------------------------------------------------------
// Copyright (C) 2019 iceman <iceman at iuse.se>
//
// 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.
//-----------------------------------------------------------------------------
// Trace commands
//-----------------------------------------------------------------------------
#ifndef CMDWIEGAND_H__
#define CMDWIEGAND_H__
#include "common.h"
int CmdWiegand(const char *Cmd);
int CmdWiegandList(const char *Cmd);
int CmdWiegandEncode(const char *Cmd);
int CmdWiegandDecode(const char *Cmd);
#endif

View file

@ -1714,8 +1714,23 @@ static int CmdEMVList(const char *Cmd) {
} }
static int CmdEMVTest(const char *Cmd) { static int CmdEMVTest(const char *Cmd) {
(void)Cmd; // Cmd is not used so far CLIParserInit("emv test",
return ExecuteCryptoTests(true); "Executes tests\n",
"Usage:\n\temv test [l]\n");
void *argtable[] = {
arg_param_begin,
arg_lit0("iI", "ignore", "ignore timing tests for VM"),
arg_lit0("lL", "long", "run long tests too"),
arg_param_end
};
CLIExecWithReturn(Cmd, argtable, true);
bool ignoreTimeTest = arg_get_lit(1);
bool runSlowTests = arg_get_lit(2);
CLIParserFree();
return ExecuteCryptoTests(true, ignoreTimeTest, runSlowTests);
} }
static int CmdEMVRoca(const char *Cmd) { static int CmdEMVRoca(const char *Cmd) {

View file

@ -301,8 +301,9 @@ close_pub:
return ret; return ret;
} }
int exec_crypto_test(bool verbose) { int exec_crypto_test(bool verbose, bool include_slow_tests) {
unsigned int keylengths[] = {1024, 1152, 1408, 1984, 2048, 3072, 4096}; unsigned int keylengths[] = {1024, 2048};
unsigned int extra_keylengths[] = {1152, 1408, 1984, 3072, 4096};
int i; int i;
int ret; int ret;
fprintf(stdout, "\n"); fprintf(stdout, "\n");
@ -322,6 +323,15 @@ int exec_crypto_test(bool verbose) {
return ret; return ret;
} }
} }
if (include_slow_tests) {
for (i = 0; i < ARRAYLEN(extra_keylengths); i++) {
unsigned int kl = extra_keylengths[i];
ret = test_genkey(kl, message, kl / 8, verbose);
if (ret) {
fprintf(stderr, "Crypto generate key[%u] test: failed\n", kl);
return ret;
}
}
}
return 0; return 0;
} }

View file

@ -17,5 +17,5 @@
#define __CRYPTO_TEST_H #define __CRYPTO_TEST_H
#include <stdbool.h> #include <stdbool.h>
int exec_crypto_test(bool verbose); int exec_crypto_test(bool verbose, bool include_slow_tests);
#endif #endif

View file

@ -33,7 +33,7 @@
#include "crypto/libpcrypto.h" #include "crypto/libpcrypto.h"
#include "emv/emv_roca.h" #include "emv/emv_roca.h"
int ExecuteCryptoTests(bool verbose) { int ExecuteCryptoTests(bool verbose, bool ignore_time, bool include_slow_tests) {
int res; int res;
bool TestFail = false; bool TestFail = false;
@ -56,7 +56,7 @@ int ExecuteCryptoTests(bool verbose) {
if (res) TestFail = true; if (res) TestFail = true;
res = mbedtls_entropy_self_test(verbose); res = mbedtls_entropy_self_test(verbose);
if (res) TestFail = true; if (res && !ignore_time) TestFail = true;
// retry for CI (when resources too low) // retry for CI (when resources too low)
for (int i = 0; i < 3; i++) { for (int i = 0; i < 3; i++) {
@ -65,7 +65,7 @@ int ExecuteCryptoTests(bool verbose) {
break; break;
PrintAndLogEx(WARNING, "Repeat timing test %d", i + 1); PrintAndLogEx(WARNING, "Repeat timing test %d", i + 1);
} }
if (res) TestFail = true; if (res && !ignore_time) TestFail = true;
res = mbedtls_ctr_drbg_self_test(verbose); res = mbedtls_ctr_drbg_self_test(verbose);
if (res) TestFail = true; if (res) TestFail = true;
@ -94,7 +94,7 @@ int ExecuteCryptoTests(bool verbose) {
res = exec_cda_test(verbose); res = exec_cda_test(verbose);
if (res) TestFail = true; if (res) TestFail = true;
res = exec_crypto_test(verbose); res = exec_crypto_test(verbose, include_slow_tests);
if (res) TestFail = true; if (res) TestFail = true;
res = roca_self_test(); res = roca_self_test();

View file

@ -12,5 +12,5 @@
#define __CRYPTOTEST_H #define __CRYPTOTEST_H
#include <stdbool.h> #include <stdbool.h>
int ExecuteCryptoTests(bool verbose); int ExecuteCryptoTests(bool verbose, bool ignore_time, bool include_slow_tests);
#endif #endif

View file

@ -37,6 +37,7 @@
// Name: Yubico U2F Root CA Serial 457200631 // Name: Yubico U2F Root CA Serial 457200631
// Issued: 2014-08-01 // Issued: 2014-08-01
// https://github.com/Yubico/developers.yubico.com/tree/master/static/U2F // https://github.com/Yubico/developers.yubico.com/tree/master/static/U2F
// https://fido-mds-parser.appspot.com/?url=https://mds.fidoalliance.org/metadata/7DwVE5vbRQysYTJrf95b3a
#define YUBICO_CA \ #define YUBICO_CA \
"-----BEGIN CERTIFICATE-----\r\n" \ "-----BEGIN CERTIFICATE-----\r\n" \
"MIIDHjCCAgagAwIBAgIEG0BT9zANBgkqhkiG9w0BAQsFADAuMSwwKgYDVQQDEyNZ\r\n" \ "MIIDHjCCAgagAwIBAgIEG0BT9zANBgkqhkiG9w0BAQsFADAuMSwwKgYDVQQDEyNZ\r\n" \
@ -75,6 +76,83 @@
"jQGd7rwSZuE5RWUPVygYhUstQO9zNUOs\r\n" \ "jQGd7rwSZuE5RWUPVygYhUstQO9zNUOs\r\n" \
"-----END CERTIFICATE-----\r\n" "-----END CERTIFICATE-----\r\n"
// FEITIAN U2F
// https://fido-mds-parser.appspot.com/?url=https://mds.fidoalliance.org/metadata/eS7v8sum4jxp7kgLQ5Qqcg
#define FEITIAN_U2F_CA \
"-----BEGIN CERTIFICATE-----\r\n" \
"MIIBfjCCASWgAwIBAgIBATAKBggqhkjOPQQDAjAXMRUwEwYDVQQDDAxGVCBGSURP\r\n" \
"IDAyMDAwIBcNMTYwNTAxMDAwMDAwWhgPMjA1MDA1MDEwMDAwMDBaMBcxFTATBgNV\r\n" \
"BAMMDEZUIEZJRE8gMDIwMDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABNBmrRqV\r\n" \
"OxztTJVN19vtdqcL7tKQeol2nnM2/yYgvksZnr50SKbVgIEkzHQVOu80LVEE3lVh\r\n" \
"eO1HjggxAlT6o4WjYDBeMB0GA1UdDgQWBBRJFWQt1bvG3jM6XgmV/IcjNtO/CzAf\r\n" \
"BgNVHSMEGDAWgBRJFWQt1bvG3jM6XgmV/IcjNtO/CzAMBgNVHRMEBTADAQH/MA4G\r\n" \
"A1UdDwEB/wQEAwIBBjAKBggqhkjOPQQDAgNHADBEAiAwfPqgIWIUB+QBBaVGsdHy\r\n" \
"0s5RMxlkzpSX/zSyTZmUpQIgB2wJ6nZRM8oX/nA43Rh6SJovM2XwCCH//+LirBAb\r\n" \
"B0M=\r\n" \
"-----END CERTIFICATE-----\r\n"
// FEITIAN FIDO2
#define FEITIAN_FIDO2_CA \
"-----BEGIN CERTIFICATE-----\r\n" \
"MIIB2DCCAX6gAwIBAgIQGBUrQbdDrm20FZnDsX2CBTAKBggqhkjOPQQDAjBLMQsw\r\n" \
"CQYDVQQGEwJVUzEdMBsGA1UECgwURmVpdGlhbiBUZWNobm9sb2dpZXMxHTAbBgNV\r\n" \
"BAMMFEZlaXRpYW4gRklETyBSb290IENBMCAXDTE4MDQwMTAwMDAwMFoYDzIwNDgw\r\n" \
"MzMxMjM1OTU5WjBLMQswCQYDVQQGEwJVUzEdMBsGA1UECgwURmVpdGlhbiBUZWNo\r\n" \
"bm9sb2dpZXMxHTAbBgNVBAMMFEZlaXRpYW4gRklETyBSb290IENBMFkwEwYHKoZI\r\n" \
"zj0CAQYIKoZIzj0DAQcDQgAEsFYEEhiJuqqnMgQjSiivBjV7DGCTf4XBBH/B7uvZ\r\n" \
"sKxXShF0L8uDISWUvcExixRs6gB3oldSrjox6L8T94NOzqNCMEAwHQYDVR0OBBYE\r\n" \
"FEu9hyYRrRyJzwRYvnDSCIxrFiO3MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/\r\n" \
"BAQDAgEGMAoGCCqGSM49BAMCA0gAMEUCIDHSb2mbNDAUNXvpPU0oWKeNye0fQ2l9\r\n" \
"D01AR2+sLZdhAiEAo3wz684IFMVsCCRmuJqxH6FQRESNqezuo1E+KkGxWuM=\r\n" \
"-----END CERTIFICATE-----\r\n"
// https://hypersecu.com/support/downloads
// HyperFIDO U2F Security Key Attestation CA
// Issuer: CN=FT FIDO 0100
#define HYPERFIDO_U2F_1_CA \
"-----BEGIN CERTIFICATE-----\r\n" \
"MIIBjTCCATOgAwIBAgIBATAKBggqhkjOPQQDAjAXMRUwEwYDVQQDEwxGVCBGSURP\r\n" \
"IDAxMDAwHhcNMTQwNzAxMTUzNjI2WhcNNDQwNzAzMTUzNjI2WjAXMRUwEwYDVQQD\r\n" \
"EwxGVCBGSURPIDAxMDAwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASxdLxJx8ol\r\n" \
"S3DS5cIHzunPF0gg69d+o8ZVCMJtpRtlfBzGuVL4YhaXk2SC2gptPTgmpZCV2vbN\r\n" \
"fAPi5gOF0vbZo3AwbjAdBgNVHQ4EFgQUXt4jWlYDgwhaPU+EqLmeM9LoPRMwPwYD\r\n" \
"VR0jBDgwNoAUXt4jWlYDgwhaPU+EqLmeM9LoPROhG6QZMBcxFTATBgNVBAMTDEZU\r\n" \
"IEZJRE8gMDEwMIIBATAMBgNVHRMEBTADAQH/MAoGCCqGSM49BAMCA0gAMEUCIQC2\r\n" \
"D9o9cconKTo8+4GZPyZBJ3amc8F0/kzyidX9dhrAIAIgM9ocs5BW/JfmshVP9Mb+\r\n" \
"Joa/kgX4dWbZxrk0ioTfJZg=\r\n" \
"-----END CERTIFICATE-----\r\n"
// Issuer: CN= HYPERFIDO 0200
#define HYPERFIDO_U2F_2_CA \
"-----BEGIN CERTIFICATE-----\r\n" \
"MIIBxzCCAWygAwIBAgICEAswCgYIKoZIzj0EAwIwOjELMAkGA1UEBhMCQ0ExEjAQ\r\n" \
"BgNVBAoMCUhZUEVSU0VDVTEXMBUGA1UEAwwOSFlQRVJGSURPIDAyMDAwIBcNMTgw\r\n" \
"MTAxMDAwMDAwWhgPMjA0NzEyMzEyMzU5NTlaMDoxCzAJBgNVBAYTAkNBMRIwEAYD\r\n" \
"VQQKDAlIWVBFUlNFQ1UxFzAVBgNVBAMMDkhZUEVSRklETyAwMjAwMFkwEwYHKoZI\r\n" \
"zj0CAQYIKoZIzj0DAQcDQgAErKUI1G0S7a6IOLlmHipLlBuxTYjsEESQvzQh3dB7\r\n" \
"dvxxWWm7kWL91rq6S7ayZG0gZPR+zYqdFzwAYDcG4+aX66NgMF4wHQYDVR0OBBYE\r\n" \
"FLZYcfMMwkQAGbt3ryzZFPFypmsIMB8GA1UdIwQYMBaAFLZYcfMMwkQAGbt3ryzZ\r\n" \
"FPFypmsIMAwGA1UdEwQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMAoGCCqGSM49BAMC\r\n" \
"A0kAMEYCIQCG2/ppMGt7pkcRie5YIohS3uDPIrmiRcTjqDclKVWg0gIhANcPNDZH\r\n" \
"E2/zZ+uB5ThG9OZus+xSb4knkrbAyXKX2zm/\r\n" \
"-----END CERTIFICATE-----\r\n"
// NXP
// https://fido-mds-parser.appspot.com/?url=https://mds.fidoalliance.org/metadata/JKP5CiDehdMMPwtG5i7to5
#define NXP_U2F_CA \
"-----BEGIN CERTIFICATE-----\r\n" \
"MIIBjzCCATWgAwIBAgIJASNFZ4mrze8BMAoGCCqGSM49BAMCMCgxJjAkBgNVBAMM\r\n" \
"HU5YUCBTZW1pY29uZHVjdG9yIFUyRiBSb290IENBMB4XDTE1MTIxNjE2MDUxMFoX\r\n" \
"DTI1MTIxMzE2MDUxMFowGjEYMBYGA1UEAwwPTlhQIEZJRE8gVTJGIHYwMFkwEwYH\r\n" \
"KoZIzj0CAQYIKoZIzj0DAQcDQgAExbuQcVAAX7IPwqVVVX/ni3Ch3Zzo04WkSsr5\r\n" \
"nHXpEarB+sd846FAi/o3a7oF1+u/oV65syguDD/0FaUGuUgTpKNWMFQwDAYDVR0T\r\n" \
"AQH/BAIwADAOBgNVHQ8BAf8EBAMCB4AwHwYDVR0jBBgwFoAUpaNTDgOg8hGDmawL\r\n" \
"bDydVSoNNPgwEwYLKwYBBAGC5RwCAQEEBAMCBDAwCgYIKoZIzj0EAwIDSAAwRQIh\r\n" \
"AJlr23jig2LxRM1PpgMAQXnZJy/HnkRB9O8KD0o2oK/mAiBG5EK1S3yVHdkkVGTJ\r\n" \
"Q12ffuK8Op7Nx89cszCr0WyIhQ==\r\n" \
"-----END CERTIFICATE-----\r\n"
/* Concatenation of all additional CA certificates in PEM format if available */ /* Concatenation of all additional CA certificates in PEM format if available */
const char additional_ca_pem[] = GLOBALSIGN_CA YUBICO_CA SOLOKEY_CA; const char additional_ca_pem[] = GLOBALSIGN_CA YUBICO_CA SOLOKEY_CA \
FEITIAN_U2F_CA FEITIAN_FIDO2_CA HYPERFIDO_U2F_1_CA HYPERFIDO_U2F_2_CA NXP_U2F_CA;
const size_t additional_ca_pem_len = sizeof(additional_ca_pem); const size_t additional_ca_pem_len = sizeof(additional_ca_pem);

View file

@ -69,6 +69,40 @@ int fileExists(const char *filename) {
return result == 0; return result == 0;
} }
/**
* @brief checks if path is file.
* @param filename
* @return
*/
bool is_regular_file(const char *filename) {
#ifdef _WIN32
struct _stat st;
_stat(filename, &st);
return S_ISREG(st.st_mode) != 0;
#else
struct stat st;
stat(filename, &st);
return S_ISREG(st.st_mode) != 0;
#endif
}
/**
* @brief checks if path is directory.
* @param filename
* @return
*/
bool is_directory(const char *filename) {
#ifdef _WIN32
struct _stat st;
_stat(filename, &st);
return S_ISDIR(st.st_mode) != 0;
#else
struct stat st;
stat(filename, &st);
return S_ISDIR(st.st_mode) != 0;
#endif
}
static char *filenamemcopy(const char *preferredName, const char *suffix) { static char *filenamemcopy(const char *preferredName, const char *suffix) {
if (preferredName == NULL) return NULL; if (preferredName == NULL) return NULL;
if (suffix == NULL) return NULL; if (suffix == NULL) return NULL;
@ -1012,10 +1046,20 @@ out:
} }
int searchFile(char **foundpath, const char *pm3dir, const char *searchname, const char *suffix, bool silent) { int searchFile(char **foundpath, const char *pm3dir, const char *searchname, const char *suffix, bool silent) {
if (foundpath == NULL) if (foundpath == NULL)
return PM3_EINVARG; return PM3_EINVARG;
if (searchname == NULL || strlen(searchname) == 0)
return PM3_EINVARG;
if (is_directory(searchname))
return PM3_EINVARG;
char *filename = filenamemcopy(searchname, suffix); char *filename = filenamemcopy(searchname, suffix);
if (filename == NULL) return PM3_EMALLOC; if (filename == NULL || strlen(filename) == 0)
return PM3_EMALLOC;
int res = searchFinalFile(foundpath, pm3dir, filename, silent); int res = searchFinalFile(foundpath, pm3dir, filename, silent);
if (res != PM3_SUCCESS) { if (res != PM3_SUCCESS) {
if ((res == PM3_EFILE) && (!silent)) if ((res == PM3_EFILE) && (!silent))

View file

@ -637,7 +637,7 @@ static int _testHash1() {
return 0; return 0;
} }
int testElite() { int testElite(bool slowtests) {
PrintAndLogEx(INFO, "Testing iClass Elite functinality..."); PrintAndLogEx(INFO, "Testing iClass Elite functinality...");
PrintAndLogEx(INFO, "Testing hash2"); PrintAndLogEx(INFO, "Testing hash2");
uint8_t k_cus[8] = {0x5B, 0x7C, 0x62, 0xC4, 0x91, 0xC1, 0x1B, 0x39}; uint8_t k_cus[8] = {0x5B, 0x7C, 0x62, 0xC4, 0x91, 0xC1, 0x1B, 0x39};
@ -669,6 +669,7 @@ int testElite() {
errors += _testHash1(); errors += _testHash1();
PrintAndLogEx(INFO, "Testing key diversification ..."); PrintAndLogEx(INFO, "Testing key diversification ...");
errors += _test_iclass_key_permutation(); errors += _test_iclass_key_permutation();
if (slowtests)
errors += _testBruteforce(); errors += _testBruteforce();
return errors; return errors;
} }

View file

@ -124,7 +124,7 @@ int calculateMasterKey(uint8_t first16bytes[], uint64_t master_key[]);
* @brief Test function * @brief Test function
* @return * @return
*/ */
int testElite(void); int testElite(bool slowtests);
/** /**
Here are some pretty optimal values that can be used to recover necessary data in only Here are some pretty optimal values that can be used to recover necessary data in only

View file

@ -1033,16 +1033,16 @@ void detect_classic_magic(void) {
} }
switch (isGeneration) { switch (isGeneration) {
case 1: case MAGIC_GEN_1A:
PrintAndLogEx(SUCCESS, "Answers to magic commands (GEN 1a): " _GREEN_("YES")); PrintAndLogEx(SUCCESS, "Answers to magic commands (GEN 1a): " _GREEN_("YES"));
break; break;
case 2: case MAGIC_GEN_1B:
PrintAndLogEx(SUCCESS, "Answers to magic commands (GEN 1b): " _GREEN_("YES")); PrintAndLogEx(SUCCESS, "Answers to magic commands (GEN 1b): " _GREEN_("YES"));
break; break;
case 4: case MAGIC_GEN_2:
PrintAndLogEx(SUCCESS, "Answers to magic commands (GEN 2 / CUID): " _GREEN_("YES")); PrintAndLogEx(SUCCESS, "Answers to magic commands (GEN 2 / CUID): " _GREEN_("YES"));
break; break;
case 5: case MAGIC_GEN_UNFUSED:
PrintAndLogEx(SUCCESS, "Answers to magic commands (Write Once / FUID): " _GREEN_("YES")); PrintAndLogEx(SUCCESS, "Answers to magic commands (Write Once / FUID): " _GREEN_("YES"));
break; break;
default: default:

View file

@ -930,7 +930,7 @@ static int l_T55xx_readblock(lua_State *L) {
return returnToLuaWithError(L, "Failed to read config block"); return returnToLuaWithError(L, "Failed to read config block");
} }
if (!tryDetectModulation(0,true)) { // Default to prev. behaviour (default dl mode and print config) if (!tryDetectModulation(0, true)) { // Default to prev. behaviour (default dl mode and print config)
PrintAndLogEx(NORMAL, "Safety Check: Could not detect if PWD bit is set in config block. Exits."); PrintAndLogEx(NORMAL, "Safety Check: Could not detect if PWD bit is set in config block. Exits.");
return 0; return 0;
} else { } else {
@ -1006,7 +1006,7 @@ static int l_T55xx_detect(lua_State *L) {
} }
} }
isok = tryDetectModulation(0,true); // Default to prev. behaviour (default dl mode and print config) isok = tryDetectModulation(0, true); // Default to prev. behaviour (default dl mode and print config)
if (isok == false) { if (isok == false) {
return returnToLuaWithError(L, "Could not detect modulation automatically. Try setting it manually with \'lf t55xx config\'"); return returnToLuaWithError(L, "Could not detect modulation automatically. Try setting it manually with \'lf t55xx config\'");
} }

View file

@ -390,7 +390,7 @@ void print_blocks(uint32_t *data, size_t len) {
PrintAndLogEx(ERR, "..empty data"); PrintAndLogEx(ERR, "..empty data");
} else { } else {
for (uint8_t i = 0; i < len; i++) for (uint8_t i = 0; i < len; i++)
PrintAndLogEx(SUCCESS, " %02d | 0x%08X", i, data[i]); PrintAndLogEx(SUCCESS, " %02d | %08X", i, data[i]);
} }
} }
@ -878,3 +878,20 @@ char *strmcopy(const char *buf) {
} }
return str; return str;
} }
/**
* Converts a hex string to component "hi2", "hi" and "lo" 32-bit integers, one nibble
* at a time.
*
* Returns the number of nibbles (4 bits) entered.
*/
int hexstring_to_u96(uint32_t *hi2, uint32_t *hi, uint32_t *lo, const char *str) {
int n = 0, i = 0;
while (sscanf(&str[i++], "%1x", &n) == 1) {
*hi2 = (*hi2 << 4) | (*hi >> 28);
*hi = (*hi << 4) | (*lo >> 28);
*lo = (*lo << 4) | (n & 0xf);
}
return i - 1;
}

View file

@ -98,4 +98,5 @@ void clean_ascii(unsigned char *buf, size_t len);
void strcleanrn(char *buf, size_t len); void strcleanrn(char *buf, size_t len);
void strcreplace(char *buf, size_t len, char from, char to); void strcreplace(char *buf, size_t len, char from, char to);
char *strmcopy(const char *buf); char *strmcopy(const char *buf);
int hexstring_to_u96(uint32_t *hi2, uint32_t *hi, uint32_t *lo, const char *str);
#endif #endif

715
client/wiegand_formats.c Normal file
View file

@ -0,0 +1,715 @@
//-----------------------------------------------------------------------------
// Copyright (C) 2018 grauerfuchs
//
// 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.
//-----------------------------------------------------------------------------
// HID card format packing/unpacking routines
//-----------------------------------------------------------------------------
#include "wiegand_formats.h"
bool Pack_H10301(wiegand_card_t *card, wiegand_message_t *packed) {
memset(packed, 0, sizeof(wiegand_message_t));
if (card->FacilityCode > 0xFF) return false; // Can't encode FC.
if (card->CardNumber > 0xFFFF) return false; // Can't encode CN.
if (card->IssueLevel > 0) return false; // Not used in this format
if (card->OEM > 0) return false; // Not used in this format
packed->Length = 26; // Set number of bits
packed->Bot |= (card->CardNumber & 0xFFFF) << 1;
packed->Bot |= (card->FacilityCode & 0xFF) << 17;
packed->Bot |= oddparity32((packed->Bot >> 1) & 0xFFF) & 1;
packed->Bot |= (evenparity32((packed->Bot >> 13) & 0xFFF) & 1) << 25;
return add_HID_header(packed);
}
bool Unpack_H10301(wiegand_message_t *packed, wiegand_card_t *card) {
memset(card, 0, sizeof(wiegand_card_t));
if (packed->Length != 26) return false; // Wrong length? Stop here.
card->CardNumber = (packed->Bot >> 1) & 0xFFFF;
card->FacilityCode = (packed->Bot >> 17) & 0xFF;
card->ParityValid =
(oddparity32((packed->Bot >> 1) & 0xFFF) == (packed->Bot & 1)) &&
((evenparity32((packed->Bot >> 13) & 0xFFF) & 1) == ((packed->Bot >> 25) & 1));
return true;
}
bool Pack_Tecom27(wiegand_card_t *card, wiegand_message_t *packed) {
memset(packed, 0, sizeof(wiegand_message_t));
if (card->FacilityCode > 0x7FF) return false; // Can't encode FC.
if (card->CardNumber > 0xFFFF) return false; // Can't encode CN.
if (card->IssueLevel > 0) return false; // Not used in this format
if (card->OEM > 0) return false; // Not used in this format
packed->Length = 27;
set_nonlinear_field(packed, card->FacilityCode, 10, (uint8_t[]) {15, 19, 24, 23, 22, 18, 6, 10, 14, 3, 2});
set_nonlinear_field(packed, card->CardNumber, 16, (uint8_t[]) {0, 1, 13, 12, 9, 26, 20, 16, 17, 21, 25, 7, 8, 11, 4, 5});
return add_HID_header(packed);
}
bool Unpack_Tecom27(wiegand_message_t *packed, wiegand_card_t *card) {
memset(card, 0, sizeof(wiegand_card_t));
if (packed->Length != 27) return false; // Wrong length? Stop here.
card->CardNumber = get_nonlinear_field(packed, 16, (uint8_t[]) {0, 1, 13, 12, 9, 26, 20, 16, 17, 21, 25, 7, 8, 11, 4, 5});
card->FacilityCode = get_nonlinear_field(packed, 10, (uint8_t[]) {15, 19, 24, 23, 22, 18, 6, 10, 14, 3, 2});
return true;
}
bool Pack_2804W(wiegand_card_t *card, wiegand_message_t *packed) {
memset(packed, 0, sizeof(wiegand_message_t));
if (card->FacilityCode > 0x0FF) return false; // Can't encode FC.
if (card->CardNumber > 0x7FFF) return false; // Can't encode CN.
if (card->IssueLevel > 0) return false; // Not used in this format
if (card->OEM > 0) return false; // Not used in this format
packed->Length = 28;
set_linear_field(packed, card->FacilityCode, 4, 8);
set_linear_field(packed, card->CardNumber, 12, 15);
set_bit_by_position(packed,
oddparity32(get_nonlinear_field(packed, 16, (uint8_t[]) {4, 5, 7, 8, 10, 11, 13, 14, 16, 17, 19, 20, 22, 23, 25, 26}))
, 2);
set_bit_by_position(packed,
evenparity32(get_linear_field(packed, 1, 13))
, 0);
set_bit_by_position(packed,
oddparity32(get_linear_field(packed, 0, 27))
, 27);
return add_HID_header(packed);
}
bool Unpack_2804W(wiegand_message_t *packed, wiegand_card_t *card) {
memset(card, 0, sizeof(wiegand_card_t));
if (packed->Length != 28) return false; // Wrong length? Stop here.
card->FacilityCode = get_linear_field(packed, 4, 8);
card->CardNumber = get_linear_field(packed, 12, 15);
card->ParityValid =
(get_bit_by_position(packed, 0) == evenparity32(get_linear_field(packed, 1, 13))) &&
(get_bit_by_position(packed, 2) == oddparity32(get_nonlinear_field(packed, 16, (uint8_t[]) {4, 5, 7, 8, 10, 11, 13, 14, 16, 17, 19, 20, 22, 23, 25, 26}))) &&
(get_bit_by_position(packed, 27) == oddparity32(get_linear_field(packed, 0, 27)));
return true;
}
bool Pack_ATSW30(wiegand_card_t *card, wiegand_message_t *packed) {
memset(packed, 0, sizeof(wiegand_message_t));
if (card->FacilityCode > 0xFFF) return false; // Can't encode FC.
if (card->CardNumber > 0xFFFF) return false; // Can't encode CN.
if (card->IssueLevel > 0) return false; // Not used in this format
if (card->OEM > 0) return false; // Not used in this format
packed->Length = 30;
set_linear_field(packed, card->FacilityCode, 1, 12);
set_linear_field(packed, card->CardNumber, 13, 16);
set_bit_by_position(packed,
evenparity32(get_linear_field(packed, 1, 12))
, 0);
set_bit_by_position(packed,
oddparity32(get_linear_field(packed, 13, 16))
, 29);
return add_HID_header(packed);
}
bool Unpack_ATSW30(wiegand_message_t *packed, wiegand_card_t *card) {
memset(card, 0, sizeof(wiegand_card_t));
if (packed->Length != 30) return false; // Wrong length? Stop here.
card->FacilityCode = get_linear_field(packed, 1, 12);
card->CardNumber = get_linear_field(packed, 13, 16);
card->ParityValid =
(get_bit_by_position(packed, 0) == evenparity32(get_linear_field(packed, 1, 12))) &&
(get_bit_by_position(packed, 29) == oddparity32(get_linear_field(packed, 13, 16)));
return true;
}
bool Pack_ADT31(wiegand_card_t *card, wiegand_message_t *packed) {
memset(packed, 0, sizeof(wiegand_message_t));
if (card->FacilityCode > 0x0F) return false; // Can't encode FC.
if (card->CardNumber > 0x7FFFFF) return false; // Can't encode CN.
if (card->IssueLevel > 0) return false; // Not used in this format
if (card->OEM > 0) return false; // Not used in this format
packed->Length = 31;
set_linear_field(packed, card->FacilityCode, 1, 4);
set_linear_field(packed, card->CardNumber, 5, 23);
// Parity not known, but 4 bits are unused.
return add_HID_header(packed);
}
bool Unpack_ADT31(wiegand_message_t *packed, wiegand_card_t *card) {
memset(card, 0, sizeof(wiegand_card_t));
if (packed->Length != 31) return false; // Wrong length? Stop here.
card->FacilityCode = get_linear_field(packed, 1, 4);
card->CardNumber = get_linear_field(packed, 5, 23);
return true;
}
bool Pack_Kastle(wiegand_card_t *card, wiegand_message_t *packed) {
memset(packed, 0, sizeof(wiegand_message_t));
if (card->FacilityCode > 0x00FF) return false; // Can't encode FC.
if (card->CardNumber > 0x0000FFFF) return false; // Can't encode CN.
if (card->IssueLevel > 0x001F) return false; // IL is only 5 bits.
if (card->OEM > 0) return false; // Not used in this format
packed->Length = 32; // Set number of bits
set_bit_by_position(packed, 1, 1); // Always 1
set_linear_field(packed, card->IssueLevel, 2, 5);
set_linear_field(packed, card->FacilityCode, 7, 8);
set_linear_field(packed, card->CardNumber, 15, 16);
set_bit_by_position(packed, evenparity32(get_linear_field(packed, 1, 16)), 0);
set_bit_by_position(packed, oddparity32(get_linear_field(packed, 14, 17)), 31);
return add_HID_header(packed);
}
bool Unpack_Kastle(wiegand_message_t *packed, wiegand_card_t *card) {
memset(card, 0, sizeof(wiegand_card_t));
if (packed->Length != 32) return false; // Wrong length? Stop here.
if (get_bit_by_position(packed, 1) != 1) return false; // Always 1 in this format
card->IssueLevel = get_linear_field(packed, 2, 5);
card->FacilityCode = get_linear_field(packed, 7, 8);
card->CardNumber = get_linear_field(packed, 15, 16);
card->ParityValid =
(get_bit_by_position(packed, 0) == evenparity32(get_linear_field(packed, 1, 16))) &&
(get_bit_by_position(packed, 31) == oddparity32(get_linear_field(packed, 14, 17)));
return true;
}
bool Pack_D10202(wiegand_card_t *card, wiegand_message_t *packed) {
memset(packed, 0, sizeof(wiegand_message_t));
if (card->FacilityCode > 0x007F) return false; // Can't encode FC.
if (card->CardNumber > 0x00FFFFFF) return false; // Can't encode CN.
if (card->IssueLevel > 0) return false; // Not used in this format
if (card->OEM > 0) return false; // Not used in this format
packed->Length = 33; // Set number of bits
set_linear_field(packed, card->FacilityCode, 1, 7);
set_linear_field(packed, card->CardNumber, 8, 24);
set_bit_by_position(packed, evenparity32(get_linear_field(packed, 1, 16)), 0);
set_bit_by_position(packed, oddparity32(get_linear_field(packed, 16, 16)), 32);
return add_HID_header(packed);
}
bool Unpack_D10202(wiegand_message_t *packed, wiegand_card_t *card) {
memset(card, 0, sizeof(wiegand_card_t));
if (packed->Length != 33) return false; // Wrong length? Stop here.
card->CardNumber = get_linear_field(packed, 8, 24);
card->FacilityCode = get_linear_field(packed, 1, 7);
card->ParityValid =
(get_bit_by_position(packed, 0) == evenparity32(get_linear_field(packed, 1, 16))) &&
(get_bit_by_position(packed, 32) == oddparity32(get_linear_field(packed, 16, 16)));
return true;
}
bool Pack_H10306(wiegand_card_t *card, wiegand_message_t *packed) {
memset(packed, 0, sizeof(wiegand_message_t));
if (card->FacilityCode > 0xFFFF) return false; // Can't encode FC.
if (card->CardNumber > 0xFFFF) return false; // Can't encode CN.
if (card->IssueLevel > 0) return false; // Not used in this format
if (card->OEM > 0) return false; // Not used in this format
packed->Length = 34; // Set number of bits
packed->Bot |= (card->CardNumber & 0xFFFF) << 1;
packed->Bot |= (card->FacilityCode & 0x7FFF) << 17;
packed->Mid |= (card->FacilityCode & 0x8000) >> 15;
packed->Mid |= (evenparity32((packed->Mid & 0x00000001) ^ (packed->Bot & 0xFFFE0000)) & 1) << 1;
packed->Bot |= (oddparity32(packed->Bot & 0x0001FFFE) & 1);
return add_HID_header(packed);
}
bool Unpack_H10306(wiegand_message_t *packed, wiegand_card_t *card) {
memset(card, 0, sizeof(wiegand_card_t));
if (packed->Length != 34) return false; // Wrong length? Stop here.
card->CardNumber = (packed->Bot >> 1) & 0xFFFF;
card->FacilityCode = ((packed->Mid & 1) << 15) | ((packed->Bot >> 17) & 0xFF);
card->ParityValid =
((evenparity32((packed->Mid & 0x00000001) ^ (packed->Bot & 0xFFFE0000)) & 1) == ((packed->Mid >> 1) & 1)) &&
((oddparity32(packed->Bot & 0x0001FFFE) & 1) == ((packed->Bot & 1)));
return true;
}
bool Pack_N10002(wiegand_card_t *card, wiegand_message_t *packed) {
memset(packed, 0, sizeof(wiegand_message_t));
if (card->FacilityCode > 0xFF) return false; // Can't encode FC.
if (card->CardNumber > 0xFFFF) return false; // Can't encode CN.
if (card->IssueLevel > 0) return false; // Not used in this format
if (card->OEM > 0) return false; // Not used in this format
packed->Length = 34; // Set number of bits
set_linear_field(packed, card->FacilityCode, 9, 8);
set_linear_field(packed, card->CardNumber, 17, 16);
return add_HID_header(packed);
}
bool Unpack_N10002(wiegand_message_t *packed, wiegand_card_t *card) {
memset(card, 0, sizeof(wiegand_card_t));
if (packed->Length != 34) return false; // Wrong length? Stop here.
card->CardNumber = get_linear_field(packed, 17, 16);
card->FacilityCode = get_linear_field(packed, 9, 8);
return true;
}
bool Pack_C1k35s(wiegand_card_t *card, wiegand_message_t *packed) {
memset(packed, 0, sizeof(wiegand_message_t));
if (card->FacilityCode > 0xFFF) return false; // Can't encode FC.
if (card->CardNumber > 0xFFFFF) return false; // Can't encode CN.
if (card->IssueLevel > 0) return false; // Not used in this format
if (card->OEM > 0) return false; // Not used in this format
packed->Length = 35; // Set number of bits
packed->Bot |= (card->CardNumber & 0x000FFFFF) << 1;
packed->Bot |= (card->FacilityCode & 0x000007FF) << 21;
packed->Mid |= (card->FacilityCode & 0x00000800) >> 11;
packed->Mid |= (evenparity32((packed->Mid & 0x00000001) ^ (packed->Bot & 0xB6DB6DB6)) & 1) << 1;
packed->Bot |= (oddparity32((packed->Mid & 0x00000003) ^ (packed->Bot & 0x6DB6DB6C)) & 1);
packed->Mid |= (oddparity32((packed->Mid & 0x00000003) ^ (packed->Bot & 0xFFFFFFFF)) & 1) << 2;
return add_HID_header(packed);
}
bool Unpack_C1k35s(wiegand_message_t *packed, wiegand_card_t *card) {
memset(card, 0, sizeof(wiegand_card_t));
if (packed->Length != 35) return false; // Wrong length? Stop here.
card->CardNumber = (packed->Bot >> 1) & 0x000FFFFF;
card->FacilityCode = ((packed->Mid & 1) << 11) | ((packed->Bot >> 21));
card->ParityValid =
(evenparity32((packed->Mid & 0x00000001) ^ (packed->Bot & 0xB6DB6DB6)) == ((packed->Mid >> 1) & 1)) &&
(oddparity32((packed->Mid & 0x00000003) ^ (packed->Bot & 0x6DB6DB6C)) == ((packed->Bot >> 0) & 1)) &&
(oddparity32((packed->Mid & 0x00000003) ^ (packed->Bot & 0xFFFFFFFF)) == ((packed->Mid >> 2) & 1));
return true;
}
bool Pack_H10320(wiegand_card_t *card, wiegand_message_t *packed) {
memset(packed, 0, sizeof(wiegand_message_t));
if (card->FacilityCode > 0) return false; // Can't encode FC. (none in this format)
if (card->CardNumber > 99999999) return false; // Can't encode CN.
if (card->IssueLevel > 0) return false; // Not used in this format
if (card->OEM > 0) return false; // Not used in this format
packed->Length = 36; // Set number of bits
// This card is BCD-encoded rather than binary. Set the 4-bit groups independently.
for (uint32_t idx = 0; idx < 8; idx++) {
set_linear_field(packed, (uint64_t)(card->CardNumber / pow(10, 7 - idx)) % 10, idx * 4, 4);
}
set_bit_by_position(packed, evenparity32(
get_nonlinear_field(packed, 8, (uint8_t[]) {0, 4, 8, 12, 16, 20, 24, 28})
), 32);
set_bit_by_position(packed, oddparity32(
get_nonlinear_field(packed, 8, (uint8_t[]) {1, 5, 9, 13, 17, 21, 25, 29})
), 33);
set_bit_by_position(packed, evenparity32(
get_nonlinear_field(packed, 8, (uint8_t[]) {2, 6, 10, 14, 18, 22, 28, 30})
), 34);
set_bit_by_position(packed, evenparity32(
get_nonlinear_field(packed, 8, (uint8_t[]) {3, 7, 11, 15, 19, 23, 29, 31})
), 35);
return add_HID_header(packed);
}
bool Unpack_H10320(wiegand_message_t *packed, wiegand_card_t *card) {
memset(card, 0, sizeof(wiegand_card_t));
if (packed->Length != 36) return false; // Wrong length? Stop here.
// This card is BCD-encoded rather than binary. Get the 4-bit groups independently.
for (uint32_t idx = 0; idx < 8; idx++) {
uint64_t val = get_linear_field(packed, idx * 4, 4);
if (val > 9) {
// Violation of BCD; Zero and exit.
card->CardNumber = 0;
return false;
} else {
card->CardNumber += val * pow(10, 7 - idx);
}
}
card->ParityValid =
(get_bit_by_position(packed, 32) == evenparity32(get_nonlinear_field(packed, 8, (uint8_t[]) {0, 4, 8, 12, 16, 20, 24, 28}))) &&
(get_bit_by_position(packed, 33) == oddparity32(get_nonlinear_field(packed, 8, (uint8_t[]) {1, 5, 9, 13, 17, 21, 25, 29}))) &&
(get_bit_by_position(packed, 34) == evenparity32(get_nonlinear_field(packed, 8, (uint8_t[]) {2, 6, 10, 14, 18, 22, 28, 30}))) &&
(get_bit_by_position(packed, 35) == evenparity32(get_nonlinear_field(packed, 8, (uint8_t[]) {3, 7, 11, 15, 19, 23, 29, 31})));
return true;
}
bool Pack_S12906(wiegand_card_t *card, wiegand_message_t *packed) {
memset(packed, 0, sizeof(wiegand_message_t));
if (card->FacilityCode > 0xFF) return false; // Can't encode FC.
if (card->IssueLevel > 0x03) return false; // Can't encode IL.
if (card->CardNumber > 0x00FFFFFF) return false; // Can't encode CN.
if (card->OEM > 0) return false; // Not used in this format
packed->Length = 36; // Set number of bits
set_linear_field(packed, card->FacilityCode, 1, 8);
set_linear_field(packed, card->IssueLevel, 9, 2);
set_linear_field(packed, card->CardNumber, 11, 24);
set_bit_by_position(packed, oddparity32(get_linear_field(packed, 1, 17)), 0);
set_bit_by_position(packed, oddparity32(get_linear_field(packed, 17, 18)), 35);
return add_HID_header(packed);
}
bool Unpack_S12906(wiegand_message_t *packed, wiegand_card_t *card) {
memset(card, 0, sizeof(wiegand_card_t));
if (packed->Length != 36) return false; // Wrong length? Stop here.
card->FacilityCode = get_linear_field(packed, 1, 8);
card->IssueLevel = get_linear_field(packed, 9, 2);
card->CardNumber = get_linear_field(packed, 11, 24);
card->ParityValid =
(get_bit_by_position(packed, 0) == oddparity32(get_linear_field(packed, 1, 17))) &&
(get_bit_by_position(packed, 35) == oddparity32(get_linear_field(packed, 17, 18)));
return true;
}
bool Pack_Sie36(wiegand_card_t *card, wiegand_message_t *packed) {
memset(packed, 0, sizeof(wiegand_message_t));
if (card->FacilityCode > 0x0003FFFF) return false; // Can't encode FC.
if (card->CardNumber > 0x0000FFFF) return false; // Can't encode CN.
if (card->IssueLevel > 0) return false; // Not used in this format
if (card->OEM > 0) return false; // Not used in this format
packed->Length = 36; // Set number of bits
set_linear_field(packed, card->FacilityCode, 1, 18);
set_linear_field(packed, card->CardNumber, 19, 16);
set_bit_by_position(packed,
oddparity32(get_nonlinear_field(packed, 23, (uint8_t[]) {1, 3, 4, 6, 7, 9, 10, 12, 13, 15, 16, 18, 19, 21, 22, 24, 25, 27, 28, 30, 31, 33, 34}))
, 0);
set_bit_by_position(packed,
evenparity32(get_nonlinear_field(packed, 23, (uint8_t[]) {1, 2, 4, 5, 7, 8, 10, 11, 13, 14, 16, 17, 19, 20, 22, 23, 25, 26, 28, 29, 31, 32, 34}))
, 35);
return add_HID_header(packed);
}
bool Unpack_Sie36(wiegand_message_t *packed, wiegand_card_t *card) {
memset(card, 0, sizeof(wiegand_card_t));
if (packed->Length != 36) return false; // Wrong length? Stop here.
card->FacilityCode = get_linear_field(packed, 1, 18);
card->CardNumber = get_linear_field(packed, 19, 16);
card->ParityValid =
(get_bit_by_position(packed, 0) == oddparity32(get_nonlinear_field(packed, 23, (uint8_t[]) {1, 3, 4, 6, 7, 9, 10, 12, 13, 15, 16, 18, 19, 21, 22, 24, 25, 27, 28, 30, 31, 33, 34}))) &&
(get_bit_by_position(packed, 35) == oddparity32(get_nonlinear_field(packed, 23, (uint8_t[]) {1, 2, 4, 5, 7, 8, 10, 11, 13, 14, 16, 17, 19, 20, 22, 23, 25, 26, 28, 29, 31, 32, 34})));
return true;
}
bool Pack_C15001(wiegand_card_t *card, wiegand_message_t *packed) {
memset(packed, 0, sizeof(wiegand_message_t));
if (card->FacilityCode > 0x000000FF) return false; // Can't encode FC.
if (card->CardNumber > 0x0000FFFF) return false; // Can't encode CN.
if (card->IssueLevel > 0) return false; // Not used in this format
if (card->OEM > 0x000003FF) return false; // Can't encode OEM.
packed->Length = 36; // Set number of bits
set_linear_field(packed, card->OEM, 1, 10);
set_linear_field(packed, card->FacilityCode, 11, 8);
set_linear_field(packed, card->CardNumber, 19, 16);
set_bit_by_position(packed, evenparity32(get_linear_field(packed, 1, 17)), 0);
set_bit_by_position(packed, oddparity32(get_linear_field(packed, 18, 17)), 35);
return add_HID_header(packed);
}
bool Unpack_C15001(wiegand_message_t *packed, wiegand_card_t *card) {
memset(card, 0, sizeof(wiegand_card_t));
if (packed->Length != 36) return false; // Wrong length? Stop here.
card->OEM = get_linear_field(packed, 1, 10);
card->FacilityCode = get_linear_field(packed, 11, 8);
card->CardNumber = get_linear_field(packed, 19, 16);
card->ParityValid =
(get_bit_by_position(packed, 0) == evenparity32(get_linear_field(packed, 1, 17))) &&
(get_bit_by_position(packed, 35) == oddparity32(get_linear_field(packed, 18, 17)));
return true;
}
bool Pack_H10302(wiegand_card_t *card, wiegand_message_t *packed) {
memset(packed, 0, sizeof(wiegand_message_t));
if (card->FacilityCode > 0) return false; // Can't encode FC. (none in this format)
if (card->CardNumber > 0x00000007FFFFFFFF) return false; // Can't encode CN.
if (card->IssueLevel > 0) return false; // Not used in this format
if (card->OEM > 0) return false; // Not used in this format
packed->Length = 37; // Set number of bits
set_linear_field(packed, card->CardNumber, 1, 35);
set_bit_by_position(packed, evenparity32(get_linear_field(packed, 1, 18)), 0);
set_bit_by_position(packed, oddparity32(get_linear_field(packed, 18, 18)), 36);
return add_HID_header(packed);
}
bool Unpack_H10302(wiegand_message_t *packed, wiegand_card_t *card) {
memset(card, 0, sizeof(wiegand_card_t));
if (packed->Length != 37) return false; // Wrong length? Stop here.
card->CardNumber = get_linear_field(packed, 1, 35);
card->ParityValid =
(get_bit_by_position(packed, 0) == evenparity32(get_linear_field(packed, 1, 18))) &&
(get_bit_by_position(packed, 36) == oddparity32(get_linear_field(packed, 18, 18)));
return true;
}
bool Pack_H10304(wiegand_card_t *card, wiegand_message_t *packed) {
memset(packed, 0, sizeof(wiegand_message_t));
if (card->FacilityCode > 0x0000FFFF) return false; // Can't encode FC.
if (card->CardNumber > 0x0007FFFF) return false; // Can't encode CN.
if (card->IssueLevel > 0) return false; // Not used in this format
if (card->OEM > 0) return false; // Not used in this format
packed->Length = 37; // Set number of bits
packed->Bot |= (card->CardNumber & 0x0007FFFF) << 1;
packed->Bot |= (card->FacilityCode & 0x00000FFF) << 20;
packed->Mid |= (card->FacilityCode & 0x0000F000) >> 12;
packed->Mid |= (evenparity32((packed->Mid & 0x0000000F) ^ (packed->Bot & 0xFFFC0000)) & 1) << 4;
packed->Bot |= (oddparity32(packed->Bot & 0x0007FFFE) & 1);
return add_HID_header(packed);
}
bool Unpack_H10304(wiegand_message_t *packed, wiegand_card_t *card) {
memset(card, 0, sizeof(wiegand_card_t));
if (packed->Length != 37) return false; // Wrong length? Stop here.
card->CardNumber = (packed->Bot >> 1) & 0x0007FFFF;
card->FacilityCode = ((packed->Mid & 0xF) << 12) | ((packed->Bot >> 20));
card->ParityValid =
(evenparity32((packed->Mid & 0x0000000F) ^ (packed->Bot & 0xFFFC0000)) == ((packed->Mid >> 4) & 1)) &&
(oddparity32(packed->Bot & 0x0007FFFE) == (packed->Bot & 1));
return true;
}
bool Pack_P10001(wiegand_card_t *card, wiegand_message_t *packed) {
memset(packed, 0, sizeof(wiegand_message_t));
if (card->FacilityCode > 0xFFF) return false; // Can't encode FC.
if (card->CardNumber > 0xFFFF) return false; // Can't encode CN.
if (card->IssueLevel > 0) return false; // Not used in this format
if (card->OEM > 0) return false; // Not used in this format
packed->Length = 40; // Set number of bits
set_linear_field(packed, 0xF, 0, 4);
set_linear_field(packed, card->FacilityCode, 4, 12);
set_linear_field(packed, card->CardNumber, 16, 16);
set_linear_field(packed,
get_linear_field(packed, 0, 8) ^
get_linear_field(packed, 8, 8) ^
get_linear_field(packed, 16, 8) ^
get_linear_field(packed, 24, 8)
, 32, 8);
return add_HID_header(packed);
}
bool Unpack_P10001(wiegand_message_t *packed, wiegand_card_t *card) {
memset(card, 0, sizeof(wiegand_card_t));
if (packed->Length != 40) return false; // Wrong length? Stop here.
card->CardNumber = get_linear_field(packed, 16, 16);
card->FacilityCode = get_linear_field(packed, 4, 12);
card->ParityValid = (
get_linear_field(packed, 0, 8) ^
get_linear_field(packed, 8, 8) ^
get_linear_field(packed, 16, 8) ^
get_linear_field(packed, 24, 8)
) == get_linear_field(packed, 32, 8);
return true;
}
bool Pack_C1k48s(wiegand_card_t *card, wiegand_message_t *packed) {
memset(packed, 0, sizeof(wiegand_message_t));
if (card->FacilityCode > 0x003FFFFF) return false; // Can't encode FC.
if (card->CardNumber > 0x007FFFFF) return false; // Can't encode CN.
if (card->IssueLevel > 0) return false; // Not used in this format
if (card->OEM > 0) return false; // Not used in this format
packed->Length = 48; // Set number of bits
packed->Bot |= (card->CardNumber & 0x007FFFFF) << 1;
packed->Bot |= (card->FacilityCode & 0x000000FF) << 24;
packed->Mid |= (card->FacilityCode & 0x003FFF00) >> 8;
packed->Mid |= (evenparity32((packed->Mid & 0x00001B6D) ^ (packed->Bot & 0xB6DB6DB6)) & 1) << 14;
packed->Bot |= (oddparity32((packed->Mid & 0x000036DB) ^ (packed->Bot & 0x6DB6DB6C)) & 1);
packed->Mid |= (oddparity32((packed->Mid & 0x00007FFF) ^ (packed->Bot & 0xFFFFFFFF)) & 1) << 15;
return add_HID_header(packed);
}
bool Unpack_C1k48s(wiegand_message_t *packed, wiegand_card_t *card) {
memset(card, 0, sizeof(wiegand_card_t));
if (packed->Length != 48) return false; // Wrong length? Stop here.
card->CardNumber = (packed->Bot >> 1) & 0x007FFFFF;
card->FacilityCode = ((packed->Mid & 0x00003FFF) << 8) | ((packed->Bot >> 24));
card->ParityValid =
(evenparity32((packed->Mid & 0x00001B6D) ^ (packed->Bot & 0xB6DB6DB6)) == ((packed->Mid >> 14) & 1)) &&
(oddparity32((packed->Mid & 0x000036DB) ^ (packed->Bot & 0x6DB6DB6C)) == ((packed->Bot >> 0) & 1)) &&
(oddparity32((packed->Mid & 0x00007FFF) ^ (packed->Bot & 0xFFFFFFFF)) == ((packed->Mid >> 15) & 1));
return true;
}
static const cardformat_t FormatTable[] = {
{"H10301", Pack_H10301, Unpack_H10301, "HID H10301 26-bit", {1, 1, 0, 0, 1}}, // imported from old pack/unpack
{"Tecom27", Pack_Tecom27, Unpack_Tecom27, "Tecom 27-bit", {1, 1, 0, 0, 1}}, // from cardinfo.barkweb.com.au
{"2804W", Pack_2804W, Unpack_2804W, "2804 Wiegand", {1, 1, 0, 0, 1}}, // from cardinfo.barkweb.com.au
{"ATSW30", Pack_ATSW30, Unpack_ATSW30, "ATS Wiegand 30-bit", {1, 1, 0, 0, 1}}, // from cardinfo.barkweb.com.au
{"ADT31", Pack_ADT31, Unpack_ADT31, "HID ADT 31-bit", {1, 1, 0, 0, 1}}, // from cardinfo.barkweb.com.au
{"Kastle", Pack_Kastle, Unpack_Kastle, "Kastle 32-bit", {1, 1, 1, 0, 1}}, // from @xilni; PR #23 on RfidResearchGroup/proxmark3
{"D10202", Pack_D10202, Unpack_D10202, "HID D10202 33-bit", {1, 1, 0, 0, 1}}, // from cardinfo.barkweb.com.au
{"H10306", Pack_H10306, Unpack_H10306, "HID H10306 34-bit", {1, 1, 0, 0, 1}}, // imported from old pack/unpack
{"N10002", Pack_N10002, Unpack_N10002, "HID N10002 34-bit", {1, 1, 0, 0, 1}}, // from cardinfo.barkweb.com.au
{"C1k35s", Pack_C1k35s, Unpack_C1k35s, "HID Corporate 1000 35-bit standard layout", {1, 1, 0, 0, 1}}, // imported from old pack/unpack
{"C15001", Pack_C15001, Unpack_C15001, "HID KeySpan 36-bit", {1, 1, 0, 1, 1}}, // from Proxmark forums
{"S12906", Pack_S12906, Unpack_S12906, "HID Simplex 36-bit", {1, 1, 1, 0, 1}}, // from cardinfo.barkweb.com.au
{"Sie36", Pack_Sie36, Unpack_Sie36, "HID 36-bit Siemens", {1, 1, 0, 0, 1}}, // from cardinfo.barkweb.com.au
{"H10320", Pack_H10320, Unpack_H10320, "HID H10320 36-bit BCD", {1, 0, 0, 0, 1}}, // from Proxmark forums
{"H10302", Pack_H10302, Unpack_H10302, "HID H10302 37-bit huge ID", {1, 0, 0, 0, 1}}, // from Proxmark forums
{"H10304", Pack_H10304, Unpack_H10304, "HID H10304 37-bit", {1, 1, 0, 0, 1}}, // imported from old pack/unpack
{"P10001", Pack_P10001, Unpack_P10001, "HID P10001 Honeywell 40-bit" }, // from cardinfo.barkweb.com.au
{"C1k48s", Pack_C1k48s, Unpack_C1k48s, "HID Corporate 1000 48-bit standard layout", {1, 1, 0, 0, 1}}, // imported from old pack/unpack
{NULL, NULL, NULL, NULL, {0, 0, 0, 0, 0}} // Must null terminate array
};
void HIDListFormats() {
if (FormatTable[0].Name == NULL)
return;
PrintAndLogEx(NORMAL, "%-10s %s", "Name", "Description");
PrintAndLogEx(NORMAL, "------------------------------------------------------------");
int i = 0;
while (FormatTable[i].Name) {
PrintAndLogEx(NORMAL, _YELLOW_("%-10s")" %-30s", FormatTable[i].Name, FormatTable[i].Descrp);
++i;
}
PrintAndLogEx(NORMAL, "");
return;
}
cardformat_t HIDGetCardFormat(int idx) {
return FormatTable[idx];
}
int HIDFindCardFormat(const char *format) {
if (FormatTable[0].Name == NULL)
return -1;
int i = 0;
// str_lower
while (FormatTable[i].Name && strcmp(FormatTable[i].Name, format)) {
++i;
}
if (FormatTable[i].Name)
return i;
return -1;
}
bool HIDPack(int format_idx, wiegand_card_t *card, wiegand_message_t *packed) {
memset(packed, 0, sizeof(wiegand_message_t));
if (format_idx < 0 || format_idx >= (sizeof(FormatTable) / sizeof(FormatTable[0])))
return false;
return FormatTable[format_idx].Pack(card, packed);
}
void HIDDisplayUnpackedCard(wiegand_card_t *card, const cardformat_t format) {
/*
PrintAndLogEx(SUCCESS, " Format: %s (%s)", format.Name, format.Descrp);
if (format.Fields.hasFacilityCode)
PrintAndLogEx(SUCCESS, "Facility Code: %d",card->FacilityCode);
if (format.Fields.hasCardNumber)
PrintAndLogEx(SUCCESS, " Card Number: %d",card->CardNumber);
if (format.Fields.hasIssueLevel)
PrintAndLogEx(SUCCESS, " Issue Level: %d",card->IssueLevel);
if (format.Fields.hasOEMCode)
PrintAndLogEx(SUCCESS, " OEM Code: %d",card->OEM);
if (format.Fields.hasParity)
PrintAndLogEx(SUCCESS, " Parity: %s",card->ParityValid ? "Valid" : "Invalid");
*/
char s[80] = {0};
if (format.Fields.hasFacilityCode)
snprintf(s, sizeof(s), "FC: %d", card->FacilityCode);
if (format.Fields.hasCardNumber)
snprintf(s + strlen(s), sizeof(s) - strlen(s), " CN: %" PRIu64, card->CardNumber);
if (format.Fields.hasIssueLevel)
snprintf(s + strlen(s), sizeof(s) - strlen(s), " Issue %d", card->IssueLevel);
if (format.Fields.hasOEMCode)
snprintf(s + strlen(s), sizeof(s) - strlen(s), " OEM: %d", card->OEM);
if (format.Fields.hasParity)
snprintf(s + strlen(s), sizeof(s) - strlen(s), " parity: %s", card->ParityValid ? "valid" : "invalid");
PrintAndLogEx(SUCCESS, "%s [%s - %s]", s, format.Name, format.Descrp);
}
bool HIDTryUnpack(wiegand_message_t *packed, bool ignore_parity) {
if (FormatTable[0].Name == NULL)
return false;
bool result = false;
int i = 0;
wiegand_card_t card;
memset(&card, 0, sizeof(wiegand_card_t));
while (FormatTable[i].Name) {
if (FormatTable[i].Unpack(packed, &card)) {
if (ignore_parity || !FormatTable[i].Fields.hasParity || card.ParityValid) {
result = true;
HIDDisplayUnpackedCard(&card, FormatTable[i]);
}
}
++i;
}
if (result == false) {
PrintAndLogEx(SUCCESS, "Unknown. Bit len %d", packed->Length);
}
return result;
}

48
client/wiegand_formats.h Normal file
View file

@ -0,0 +1,48 @@
//-----------------------------------------------------------------------------
// Copyright (C) 2018 grauerfuchs
//
// 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.
//-----------------------------------------------------------------------------
// Wiegand format packing/unpacking routines
//-----------------------------------------------------------------------------
#ifndef WIEGAND_FORMATS_H__
#define WIEGAND_FORMATS_H__
#include <string.h> // memset
#include <stdbool.h>
#include <stdint.h>
#include <inttypes.h>
#include <math.h>
#include <stdio.h>
#include "cmddata.h"
#include "wiegand_formatutils.h"
#include "parity.h" // for parity
#include "ui.h"
typedef struct {
bool hasCardNumber;
bool hasFacilityCode;
bool hasIssueLevel;
bool hasOEMCode;
bool hasParity;
} cardformatdescriptor_t;
// Structure for defined Wiegand card formats available for packing/unpacking
typedef struct {
const char *Name;
bool (*Pack)(wiegand_card_t *card, wiegand_message_t *packed);
bool (*Unpack)(wiegand_message_t *packed, wiegand_card_t *card);
const char *Descrp;
cardformatdescriptor_t Fields;
} cardformat_t;
void HIDListFormats();
int HIDFindCardFormat(const char *format);
cardformat_t HIDGetCardFormat(int idx);
bool HIDPack(int FormatIndex, wiegand_card_t *card, wiegand_message_t *packed);
bool HIDTryUnpack(wiegand_message_t *packed, bool ignoreParity);
#endif

View file

@ -0,0 +1,185 @@
//-----------------------------------------------------------------------------
// Copyright (C) 2018 grauerfuchs
//
// 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.
//-----------------------------------------------------------------------------
// Wiegand card format packing/unpacking support functions
//-----------------------------------------------------------------------------
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include "wiegand_formatutils.h"
#include "ui.h"
bool get_bit_by_position(wiegand_message_t *data, uint8_t pos) {
if (pos >= data->Length) return false;
pos = (data->Length - pos) - 1; // invert ordering; Indexing goes from 0 to 1. Subtract 1 for weight of bit.
bool result = false;
if (pos > 95)
result = false;
else if (pos > 63)
result = (data->Top >> (pos - 64)) & 1;
else if (pos > 31)
result = (data->Mid >> (pos - 32)) & 1;
else
result = (data->Bot >> pos) & 1;
return result;
}
bool set_bit_by_position(wiegand_message_t *data, bool value, uint8_t pos) {
if (pos >= data->Length) return false;
pos = (data->Length - pos) - 1; // invert ordering; Indexing goes from 0 to 1. Subtract 1 for weight of bit.
if (pos > 95) {
return false;
} else if (pos > 63) {
if (value)
data->Top |= (1 << (pos - 64));
else
data->Top &= ~(1 << (pos - 64));
return true;
} else if (pos > 31) {
if (value)
data->Mid |= (1 << (pos - 32));
else
data->Mid &= ~(1 << (pos - 32));
return true;
} else {
if (value)
data->Bot |= (1 << pos);
else
data->Bot &= ~(1 << pos);
return true;
}
}
/**
* Safeguard the data by doing a manual deep copy
*
* At the time of the initial writing, the struct does not contain pointers. That doesn't
* mean it won't eventually contain one, however. To prevent memory leaks and erroneous
* aliasing, perform the copy function manually instead. Hence, this function.
*
* If the definition of the wiegand_message struct changes, this function must also
* be updated to match.
*/
void message_datacopy(wiegand_message_t *src, wiegand_message_t *dest) {
dest->Bot = src->Bot;
dest->Mid = src->Mid;
dest->Top = src->Top;
dest->Length = src->Length;
}
/**
*
* Yes, this is horribly inefficient for linear data.
* The current code is a temporary measure to have a working function in place
* until all the bugs shaken from the block/chunk version of the code.
*
*/
uint64_t get_linear_field(wiegand_message_t *data, uint8_t firstBit, uint8_t length) {
uint64_t result = 0;
for (uint8_t i = 0; i < length; i++) {
result = (result << 1) | get_bit_by_position(data, firstBit + i);
}
return result;
}
bool set_linear_field(wiegand_message_t *data, uint64_t value, uint8_t firstBit, uint8_t length) {
wiegand_message_t tmpdata;
message_datacopy(data, &tmpdata);
bool result = true;
for (int i = 0; i < length; i++) {
result &= set_bit_by_position(&tmpdata, (value >> ((length - i) - 1)) & 1, firstBit + i);
}
if (result)
message_datacopy(&tmpdata, data);
return result;
}
uint64_t get_nonlinear_field(wiegand_message_t *data, uint8_t numBits, uint8_t *bits) {
uint64_t result = 0;
for (int i = 0; i < numBits; i++) {
result = (result << 1) | (get_bit_by_position(data, *(bits + i)) & 1);
}
return result;
}
bool set_nonlinear_field(wiegand_message_t *data, uint64_t value, uint8_t numBits, uint8_t *bits) {
wiegand_message_t tmpdata;
message_datacopy(data, &tmpdata);
bool result = true;
for (int i = 0; i < numBits; i++) {
result &= set_bit_by_position(&tmpdata, (value >> ((numBits - i) - 1)) & 1, *(bits + i));
}
if (result)
message_datacopy(&tmpdata, data);
return result;
}
uint8_t get_length_from_header(wiegand_message_t *data) {
uint8_t len = 0;
uint32_t hfmt = 0; // for calculating card length
if ((data->Top & 0x000FFFFF) > 0) { // > 64 bits
hfmt = data->Top & 0x000FFFFF;
len = 64;
} else if ((data->Mid & 0xFFFFFFC0) > 0) { // < 63-38 bits
hfmt = data->Mid & 0xFFFFFFC0;
len = 32;
} else if (data->Mid && (data->Mid & 0x00000020) == 0) { // 37 bits;
hfmt = 0;
len = 37;
} else if ((data->Mid & 0x0000001F) > 0) { // 36-32 bits
printf("a\n");
hfmt = data->Mid & 0x0000001F;
len = 32;
} else if (data->Top == 0 && data->Mid == 0) { //< 32 bits
hfmt = data->Bot;
len = 0;
} else {
hfmt = data->Bot;
len = 0;
}
while (hfmt > 1) {
hfmt >>= 1;
len++;
}
return len;
}
wiegand_message_t initialize_message_object(uint32_t top, uint32_t mid, uint32_t bot) {
wiegand_message_t result;
memset(&result, 0, sizeof(wiegand_message_t));
result.Top = top;
result.Mid = mid;
result.Bot = bot;
result.Length = get_length_from_header(&result);
return result;
}
bool add_HID_header(wiegand_message_t *data) {
if (data->Length > 84 || data->Length == 0) return false; // Invalid value
if (data->Length >= 64) {
data->Top |= 1 << (data->Length - 64); // leading 1: start bit
data->Top |= 0x09e00000; // Extended-length header
} else if (data->Length > 37) {
data->Mid |= 1 << (data->Length - 32); // leading 1: start bit
data->Top |= 0x09e00000; // Extended-length header
} else if (data->Length == 37) {
// No header bits added to 37-bit cards
} else if (data->Length >= 32) {
data->Mid |= 0x20; // Bit 37; standard header
data->Mid |= 1 << (data->Length - 32); // leading 1: start bit
} else {
data->Mid |= 0x20; // Bit 37; standard header
data->Bot |= 1 << data->Length; // leading 1: start bit
}
return true;
}

View file

@ -0,0 +1,49 @@
//-----------------------------------------------------------------------------
// Copyright (C) 2018 grauerfuchs
//
// 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.
//-----------------------------------------------------------------------------
// Weigand card format packing/unpacking support functions
//-----------------------------------------------------------------------------
#ifndef WIEGAND_FORMATUTILS_H__
#define WIEGAND_FORMATUTILS_H__
#include <stdarg.h>
#include <stdint.h>
#include <stdbool.h>
// Structure for packed wiegand messages
// Always align lowest value (last transmitted) bit to ordinal position 0 (lowest valued bit bottom)
typedef struct {
uint8_t Length; // Number of encoded bits in wiegand message (excluding headers and preamble)
uint32_t Top; // Bits in x<<64 positions
uint32_t Mid; // Bits in x<<32 positions
uint32_t Bot; // Lowest ordinal positions
} wiegand_message_t;
// Structure for unpacked wiegand card, like HID prox
typedef struct {
uint32_t FacilityCode;
uint64_t CardNumber;
uint32_t IssueLevel;
uint32_t OEM;
bool ParityValid; // Only valid for responses
} wiegand_card_t;
bool get_bit_by_position(wiegand_message_t *data, uint8_t pos);
bool set_bit_by_position(wiegand_message_t *data, bool value, uint8_t pos);
uint64_t get_linear_field(wiegand_message_t *data, uint8_t firstBit, uint8_t length);
bool set_linear_field(wiegand_message_t *data, uint64_t value, uint8_t firstBit, uint8_t length);
uint64_t get_nonlinear_field(wiegand_message_t *data, uint8_t numBits, uint8_t *bits);
bool set_nonlinear_field(wiegand_message_t *data, uint64_t value, uint8_t numBits, uint8_t *bits);
wiegand_message_t initialize_message_object(uint32_t top, uint32_t mid, uint32_t bot);
bool add_HID_header(wiegand_message_t *data);
#endif

View file

@ -9,7 +9,7 @@
|[Sim Module](#Sim-Module)|[Hitag](#Hitag)|| |[Sim Module](#Sim-Module)|[Hitag](#Hitag)||
|[Lua Scripts](#Lua-Scripts)||| |[Lua Scripts](#Lua-Scripts)|||
|[Smart Card](#Smart-Card)||| |[Smart Card](#Smart-Card)|||
|[Wiegand convertion](#Wiegand-manipulation)|||
## Generic ## Generic
^[Top](#top) ^[Top](#top)
@ -62,7 +62,7 @@ Options
--- ---
k <Key> : *Access Key as 16 hex symbols or 1 hex to select key from memory k <Key> : *Access Key as 16 hex symbols or 1 hex to select key from memory
pm3 --> hf iclass dump k AFA785A7DAB33378 m3 --> hf iclass dump k 0
``` ```
Read iClass Block Read iClass Block
@ -72,7 +72,7 @@ Options
b <Block> : The block number as 2 hex symbols b <Block> : The block number as 2 hex symbols
k <Key> : Access Key as 16 hex symbols or 1 hex to select key from memory k <Key> : Access Key as 16 hex symbols or 1 hex to select key from memory
pm3 --> hf iclass readblk b 7 k AFA785A7DAB33378 pm3 --> hf iclass rdbl b 7 k 0
``` ```
Write to iClass Block Write to iClass Block
@ -83,7 +83,7 @@ b <Block> : The block number as 2 hex symbols
d <data> : Set the Data to write as 16 hex symbols d <data> : Set the Data to write as 16 hex symbols
k <Key> : Access Key as 16 hex symbols or 1 hex to select key from memory k <Key> : Access Key as 16 hex symbols or 1 hex to select key from memory
pm3 --> hf iclass writeblk b 07 d 6ce099fe7e614fd0 k AFA785A7DAB33378 pm3 --> hf iclass wrbl b 07 d 6ce099fe7e614fd0 k 0
``` ```
Print keystore Print keystore
@ -107,7 +107,7 @@ pm3 --> hf iclass managekeys n 0 k AFA785A7DAB33378
Encrypt iClass Block Encrypt iClass Block
``` ```
pm3 --> hf iclass encryptblk 0000000f2aa3dba8 pm3 --> hf iclass encrypt 0000000f2aa3dba8
``` ```
Load iClass dump into memory for simulation Load iClass dump into memory for simulation
@ -116,7 +116,7 @@ Options
--- ---
f <filename> : load iclass tag-dump filename f <filename> : load iclass tag-dump filename
pm3 --> hf iclass eload f iclass_tagdump-db883702f8ff12e0.bin pm3 --> hf iclass eload f hf-iclass-db883702f8ff12e0.bin
``` ```
Simulate iClass Simulate iClass
@ -124,6 +124,7 @@ Simulate iClass
Options Options
--- ---
0 <CSN> simulate the given CSN 0 <CSN> simulate the given CSN
2 Runs part 1 of LOCLASS attack
1 simulate default CSN 1 simulate default CSN
3 Full simulation using emulator memory (see 'hf iclass eload') 3 Full simulation using emulator memory (see 'hf iclass eload')
@ -132,14 +133,14 @@ pm3 --> hf iclass sim 3
Clone iClass Legacy Sequence Clone iClass Legacy Sequence
``` ```
pm3 --> hf iclass readblk b 7 k AFA785A7DAB33378 pm3 --> hf iclass rdbl b 7 k 0
pm3 --> hf iclass writeblk b 07 d 6ce099fe7e614fd0 k AFA785A7DAB33378 pm3 --> hf iclass wrbl b 7 d 6ce099fe7e614fd0 k 0
``` ```
Simulate iClass Sequence Simulate iClass Sequence
``` ```
pm3 --> hf iclass dump k AFA785A7DAB33378 pm3 --> hf iclass dump k 0
pm3 --> hf iclass eload f iclass_tagdump-db883702f8ff12e0.bin pm3 --> hf iclass eload f hf-iclass-db883702f8ff12e0.bin
pm3 --> hf iclass sim 3 pm3 --> hf iclass sim 3
``` ```
@ -224,6 +225,14 @@ Options
pm3 --> hf mf wrbl 0 A FFFFFFFFFFFF d3a2859f6b880400c801002000000016 pm3 --> hf mf wrbl 0 A FFFFFFFFFFFF d3a2859f6b880400c801002000000016
``` ```
Run autopwn
```
Options
---
pm3 --> hf mf autopwn
```
Run Hardnested attack Run Hardnested attack
``` ```
Options Options
@ -241,8 +250,8 @@ Options
<card memory> <file name w/o `.eml`> <card memory> <file name w/o `.eml`>
[card memory]: 0 = 320 bytes (Mifare Mini), 1 = 1K (default), 2 = 2K, 4 = 4K, u = UL [card memory]: 0 = 320 bytes (Mifare Mini), 1 = 1K (default), 2 = 2K, 4 = 4K, u = UL
pm3 --> hf mf eload 353C2AA6 pm3 --> hf mf eload hf-mf-353C2AA6
pm3 --> hf mf eload 1 353C2AA6 pm3 --> hf mf eload 1 hf-mf-353C2AA6
``` ```
Simulate Mifare Simulate Mifare
@ -268,6 +277,37 @@ pm3 --> hf mf dump
pm3 --> hf mf restore 1 u 4A6CE843 k hf-mf-A29558E4-key.bin f hf-mf-A29558E4-data.bin pm3 --> hf mf restore 1 u 4A6CE843 k hf-mf-A29558E4-key.bin f hf-mf-A29558E4-data.bin
``` ```
## Wiegand manipulation
^[Top](#top)
List all available weigand formats in client
```
pm3 --> wiegand list
```
Convert Site & Facility code to Wiegand raw hex
```
Options
---
w <format> o <OEM> f <FC> c <CN> i <issuelevel>
w : wiegand format to use
o : OEM number / site code
f : facility code
c : card number
i : issue level
pm3 --> wiegand encode 0 56 150
```
Convert Site & Facility code from Wiegand raw hex to numbers
```
Options
---
p : ignore parity errors
pm3 --> wiegand decode 2006f623ae
```
## HID Prox ## HID Prox
^[Top](#top) ^[Top](#top)
@ -281,18 +321,6 @@ Demodulate HID Prox card
pm3 --> lf hid demod pm3 --> lf hid demod
``` ```
Convert Site & Facility code to Wiegand
```
Options
---
<OEM> <FC> <CN>
OEM : OEM number / site code
FC : facility code
CN : card number
pm3 --> lf hid wiegand 0 56 150
```
Simulate Prox card Simulate Prox card
``` ```

View file

@ -242,6 +242,14 @@ typedef struct {
uint8_t keytype; uint8_t keytype;
} PACKED mfc_eload_t; } PACKED mfc_eload_t;
typedef struct {
uint8_t status;
uint8_t CSN[8];
uint8_t CONFIG[8];
uint8_t CC[8];
uint8_t AIA[8];
} PACKED iclass_reader_t;
// For the bootloader // For the bootloader
#define CMD_DEVICE_INFO 0x0000 #define CMD_DEVICE_INFO 0x0000
#define CMD_SETUP_WRITE 0x0001 #define CMD_SETUP_WRITE 0x0001
@ -345,9 +353,6 @@ typedef struct {
#define CMD_SET_ADC_MUX 0x020F #define CMD_SET_ADC_MUX 0x020F
#define CMD_LF_HID_CLONE 0x0210 #define CMD_LF_HID_CLONE 0x0210
#define CMD_LF_EM410X_WRITE 0x0211 #define CMD_LF_EM410X_WRITE 0x0211
#define CMD_LF_INDALA_CLONE 0x0212
// for 224 bits UID
#define CMD_LF_INDALA224_CLONE 0x0213
#define CMD_LF_T55XX_READBL 0x0214 #define CMD_LF_T55XX_READBL 0x0214
#define CMD_LF_T55XX_WRITEBL 0x0215 #define CMD_LF_T55XX_WRITEBL 0x0215
#define CMD_LF_T55XX_RESET_READ 0x0216 #define CMD_LF_T55XX_RESET_READ 0x0216
@ -356,7 +361,6 @@ typedef struct {
#define CMD_LF_EM4X_READWORD 0x0218 #define CMD_LF_EM4X_READWORD 0x0218
#define CMD_LF_EM4X_WRITEWORD 0x0219 #define CMD_LF_EM4X_WRITEWORD 0x0219
#define CMD_LF_IO_DEMOD 0x021A #define CMD_LF_IO_DEMOD 0x021A
#define CMD_LF_IO_CLONE 0x021B
#define CMD_LF_EM410X_DEMOD 0x021c #define CMD_LF_EM410X_DEMOD 0x021c
// Sampling configuration for LF reader/sniffer // Sampling configuration for LF reader/sniffer
#define CMD_LF_SAMPLING_SET_CONFIG 0x021d #define CMD_LF_SAMPLING_SET_CONFIG 0x021d

View file

@ -205,6 +205,11 @@ ISO 7816-4 Basic interindustry commands. For command APDU's.
#define MAGIC_WIPE 0x40 #define MAGIC_WIPE 0x40
#define MAGIC_SINGLE (MAGIC_WUPC | MAGIC_HALT | MAGIC_INIT | MAGIC_OFF) //0x1E #define MAGIC_SINGLE (MAGIC_WUPC | MAGIC_HALT | MAGIC_INIT | MAGIC_OFF) //0x1E
// by CMD_HF_MIFARE_CIDENT
#define MAGIC_GEN_1A 1
#define MAGIC_GEN_1B 2
#define MAGIC_GEN_2 4
#define MAGIC_GEN_UNFUSED 5
/** /**
06 00 = INITIATE 06 00 = INITIATE
0E xx = SELECT ID (xx = Chip-ID) 0E xx = SELECT ID (xx = Chip-ID)

View file

@ -3,6 +3,12 @@
PM3PATH=$(dirname "$0") PM3PATH=$(dirname "$0")
cd "$PM3PATH" || exit 1 cd "$PM3PATH" || exit 1
if [ "$1" == "long" ]; then
SLOWTESTS=true
else
SLOWTESTS=false
fi
C_RED='\033[0;31m' C_RED='\033[0;31m'
C_GREEN='\033[0;32m' C_GREEN='\033[0;32m'
C_YELLOW='\033[0;33m' C_YELLOW='\033[0;33m'
@ -95,9 +101,14 @@ while true; do
printf "\n${C_BLUE}Testing HF:${C_NC}\n" printf "\n${C_BLUE}Testing HF:${C_NC}\n"
if ! CheckExecute "hf mf offline text" "./client/proxmark3 -c 'hf mf'" "at_enc"; then break; fi if ! CheckExecute "hf mf offline text" "./client/proxmark3 -c 'hf mf'" "at_enc"; then break; fi
if $SLOWTESTS; then
if ! CheckExecute "hf mf hardnested test" "./client/proxmark3 -c 'hf mf hardnested t 1 000000000000'" "found:" "repeat" "ignore"; then break; fi if ! CheckExecute "hf mf hardnested test" "./client/proxmark3 -c 'hf mf hardnested t 1 000000000000'" "found:" "repeat" "ignore"; then break; fi
if ! CheckExecute "hf iclass test" "./client/proxmark3 -c 'hf iclass loclass t'" "verified ok"; then break; fi if ! CheckExecute "hf iclass test" "./client/proxmark3 -c 'hf iclass loclass t l'" "verified ok"; then break; fi
if ! CheckExecute "emv test" "./client/proxmark3 -c 'emv test -l'" "Test(s) \[ OK"; then break; fi
else
if ! CheckExecute "hf iclass test" "./client/proxmark3 -c 'hf iclass loclass t'" "OK!"; then break; fi
if ! CheckExecute "emv test" "./client/proxmark3 -c 'emv test'" "Test(s) \[ OK"; then break; fi if ! CheckExecute "emv test" "./client/proxmark3 -c 'emv test'" "Test(s) \[ OK"; then break; fi
fi
printf "\n${C_BLUE}Testing tools:${C_NC}\n" printf "\n${C_BLUE}Testing tools:${C_NC}\n"
# Need a decent example for mfkey32... # Need a decent example for mfkey32...

View file

@ -17,7 +17,7 @@ interface bcm2835gpio
# This file is meant for recent versions of Raspberry Pi # This file is meant for recent versions of Raspberry Pi
# You can check yours with: # You can check yours with:
# dd if=/proc/device-tree/soc/ranges bs=4 skip=1 count=1 2>/dev/null|xxd -p # dd if=/proc/device-tree/soc/ranges bs=4 skip=1 count=1 2>/dev/null|xxd -p
# if it returns 20000000, use interface-raspberrypi2.cfg # if it returns 20000000, use interface-raspberrypi.cfg
# if it returns 3F000000, you're fine # if it returns 3F000000, you're fine
bcm2835gpio_peripheral_base 0x3F000000 bcm2835gpio_peripheral_base 0x3F000000