mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-21 13:53:55 -07:00
commit
a1eb992fa8
56 changed files with 2032 additions and 607 deletions
|
@ -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)
|
||||||
|
|
13
appveyor.yml
13
appveyor.yml
|
@ -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) {
|
||||||
|
|
|
@ -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: {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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)), )
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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,202 +350,9 @@ 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++) {
|
PrintAndLogEx(NORMAL, " %u | %03u | %03u | %" PRIu64 " | %" PRIX64 " | %" PRIX64,
|
||||||
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,
|
|
||||||
fmtlen[i],
|
fmtlen[i],
|
||||||
oem,
|
oem,
|
||||||
fc,
|
fc,
|
||||||
|
@ -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}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
clearCommandBuffer();
|
uint8_t res = 0;
|
||||||
SendCommandMIX(CMD_LF_IO_CLONE, blocks[1], blocks[2], 0, NULL, 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();
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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, " Configure it manually " _YELLOW_("`lf t55xx config b 64 d BI i 1 o 32`"));
|
||||||
}
|
}
|
||||||
PrintAndLogEx(NORMAL, "\n");
|
|
||||||
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`"));
|
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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) {
|
|
||||||
|
if (t55xxVerifyWrite(i, 0, false, false, 0, 0xFF, blocks[i]) == false)
|
||||||
res++;
|
res++;
|
||||||
printf(" i = %d \n", i);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( res == 0 )
|
if (res == 0)
|
||||||
PrintAndLogEx(SUCCESS, "Success writing to tag");
|
PrintAndLogEx(SUCCESS, "Success writing to tag");
|
||||||
|
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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,21 +405,48 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
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) {
|
||||||
|
@ -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;
|
||||||
|
@ -1131,7 +1167,7 @@ bool tryDetectModulationEx(uint8_t downlink_mode, bool print_config, uint32_t wa
|
||||||
}
|
}
|
||||||
|
|
||||||
if (print_config)
|
if (print_config)
|
||||||
printConfiguration(tests[i]);
|
printConfiguration(tests[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return retval;
|
return retval;
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
// }
|
// }
|
||||||
|
@ -2957,7 +2992,7 @@ static int CmdT55xxDetectPage1(const char *Cmd) {
|
||||||
cmdp++;
|
cmdp++;
|
||||||
break;
|
break;
|
||||||
case 'r':
|
case 'r':
|
||||||
//ICEMAN STRANGE
|
//ICEMAN STRANGE
|
||||||
downlink_mode = param_get8ex(Cmd, cmdp + 1, 0, 10);
|
downlink_mode = param_get8ex(Cmd, cmdp + 1, 0, 10);
|
||||||
if (downlink_mode == 4)
|
if (downlink_mode == 4)
|
||||||
try_all_dl_modes = true;
|
try_all_dl_modes = true;
|
||||||
|
@ -3146,7 +3181,7 @@ static int CmdT55xxProtect(const char *Cmd) {
|
||||||
cmdp += 2;
|
cmdp += 2;
|
||||||
break;
|
break;
|
||||||
case 'r':
|
case 'r':
|
||||||
//ICEMAN STRANGE
|
//ICEMAN STRANGE
|
||||||
downlink_mode = param_get8ex(Cmd, cmdp + 1, 0, 10);
|
downlink_mode = param_get8ex(Cmd, cmdp + 1, 0, 10);
|
||||||
if (downlink_mode > 3)
|
if (downlink_mode > 3)
|
||||||
downlink_mode = 0;
|
downlink_mode = 0;
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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.");
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
205
client/cmdwiegand.c
Normal 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
20
client/cmdwiegand.h
Normal 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
|
|
@ -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) {
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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))
|
||||||
|
|
|
@ -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();
|
||||||
errors += _testBruteforce();
|
if (slowtests)
|
||||||
|
errors += _testBruteforce();
|
||||||
return errors;
|
return errors;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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\'");
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
|
@ -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
715
client/wiegand_formats.c
Normal 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
48
client/wiegand_formats.h
Normal 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
|
185
client/wiegand_formatutils.c
Normal file
185
client/wiegand_formatutils.c
Normal 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;
|
||||||
|
}
|
49
client/wiegand_formatutils.h
Normal file
49
client/wiegand_formatutils.h
Normal 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
|
|
@ -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
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
17
pm3test.sh
17
pm3test.sh
|
@ -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 ! CheckExecute "hf mf hardnested test" "./client/proxmark3 -c 'hf mf hardnested t 1 000000000000'" "found:" "repeat" "ignore"; then break; fi
|
if $SLOWTESTS; then
|
||||||
if ! CheckExecute "hf iclass test" "./client/proxmark3 -c 'hf iclass loclass t'" "verified ok"; 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 "emv test" "./client/proxmark3 -c 'emv test'" "Test(s) \[ 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
|
||||||
|
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...
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue