Skip to content

Commit c32fd53

Browse files
committed
fix: clone a EM410x ID to Hitag S/8211 with clock
1 parent 541ef26 commit c32fd53

File tree

1 file changed

+63
-34
lines changed

1 file changed

+63
-34
lines changed

client/src/cmdlfem410x.c

Lines changed: 63 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
#include "generator.h"
4040
#include "cliparser.h"
4141
#include "cmdhw.h"
42-
#include <hitag.h>
42+
#include "hitag.h"
4343

4444
static uint64_t gs_em410xid = 0;
4545

@@ -675,7 +675,7 @@ static size_t concatbits(uint8_t *dst, size_t dstskip, const uint8_t *src, size_
675675
static int CmdEM410xClone(const char *Cmd) {
676676
CLIParserContext *ctx;
677677
CLIParserInit(&ctx, "lf em 410x clone",
678-
"clone a EM410x ID to a T55x7, Q5/T5555 or EM4305/4469 tag.",
678+
"clone a EM410x ID to a T55x7, Q5/T5555, EM4305/4469 or Hitag S/8211 tag.",
679679
"lf em 410x clone --id 0F0368568B -> encode for T55x7 tag\n"
680680
"lf em 410x clone --id 0F0368568B --q5 -> encode for Q5/T5555 tag\n"
681681
"lf em 410x clone --id 0F0368568B --em -> encode for EM4305/4469\n"
@@ -710,9 +710,15 @@ static int CmdEM410xClone(const char *Cmd) {
710710
return PM3_EINVARG;
711711
}
712712

713-
if (hs && IfPm3Hitag() == false) {
714-
PrintAndLogEx(FAILED, "Device not compiled to support Hitag");
715-
return PM3_EINVARG;
713+
if (hs) {
714+
if (IfPm3Hitag() == false) {
715+
PrintAndLogEx(FAILED, "Device not compiled to support Hitag");
716+
return PM3_EINVARG;
717+
}
718+
if (clk == 40) {
719+
PrintAndLogEx(FAILED, "supported clock rates for Hitag are " _YELLOW_("16, 32, 64"));
720+
return PM3_EINVARG;
721+
}
716722
}
717723

718724
// Allowed clock rates: 16, 32, 40 and 64
@@ -722,31 +728,14 @@ static int CmdEM410xClone(const char *Cmd) {
722728
}
723729

724730
uint64_t id = bytes_to_num(uid, uid_len);
725-
PrintAndLogEx(SUCCESS, "Preparing to clone EM4102 to " _YELLOW_("%s") " tag with EM Tag ID " _GREEN_("%010" PRIX64) " (RF/%d)", q5 ? "Q5/T5555" : (em ? "EM4305/4469" : "T55x7"), id, clk);
726-
727-
struct {
728-
bool Q5;
729-
bool EM;
730-
bool add_electra;
731-
uint8_t clock;
732-
uint32_t high;
733-
uint32_t low;
734-
} PACKED payload;
735-
736-
payload.Q5 = q5;
737-
payload.EM = em;
738-
payload.add_electra = add_electra;
739-
payload.clock = clk;
740-
payload.high = (uint32_t)(id >> 32);
741-
payload.low = (uint32_t)id;
742-
743-
744-
uint8_t data[8] = {0xFF, 0x80}; // EM410X_HEADER 9 bits of one
731+
PrintAndLogEx(SUCCESS, "Preparing to clone EM4102 to " _YELLOW_("%s") " tag with EM Tag ID " _GREEN_("%010" PRIX64) " (RF/%d)",
732+
q5 ? "Q5/T5555" : (em ? "EM4305/4469" : (hs ? "Hitag S/8211" : "T55x7")), id, clk);
733+
734+
uint8_t data[HITAG_BLOCK_SIZE * 2] = {0xFF, 0x80}; // EM410X_HEADER 9 bits of one
745735
uint32_t databits = 9;
746736
uint8_t c_parity = 0;
747737

748-
for (int i = 36; i >= 0; i -= 4)
749-
{
738+
for (int i = 36; i >= 0; i -= 4) {
750739
uint8_t r_parity = 0;
751740
uint8_t nibble = id >> i & 0xF;
752741

@@ -758,7 +747,8 @@ static int CmdEM410xClone(const char *Cmd) {
758747
c_parity ^= nibble;
759748
}
760749
data[7] |= c_parity << 1;
761-
// print_hex_noascii_break(data, 8, 10);
750+
751+
PrintAndLogEx(INFO, "Encoded to %s", sprint_hex(data, sizeof(data)));
762752

763753
clearCommandBuffer();
764754
PacketResponseNG resp;
@@ -767,14 +757,37 @@ static int CmdEM410xClone(const char *Cmd) {
767757
lf_hitag_data_t packet;
768758
memset(&packet, 0, sizeof(packet));
769759

770-
for (size_t page = 4; page <= 5; page++) {
771-
packet.cmd = WHTSF_PLAIN;
772-
packet.page = page;
773-
memcpy(packet.data, &data[(page-4)*4], 4);
760+
for (size_t steps = 0; steps < 3; steps++) {
761+
switch (steps) {
762+
case 0:
763+
packet.data[0] = 0xCA; //compatiable for 82xx, no impact on Hitag S
764+
// clk -> TTFDR1 TTFDR0
765+
// 32 -> 0x00 4 kBit/s
766+
// 16 -> 0x10 8 kBit/s
767+
// 64 -> 0x20 2 kBit/s
768+
packet.data[1] = 0x04;
769+
switch (clk) {
770+
case 32: break;
771+
case 16: packet.data[1] |= 0x10; break;
772+
case 64: packet.data[1] |= 0x20; break;
773+
}
774+
packet.data[2] = 0;
775+
packet.data[3] = 0; //TODO: keep PWDH0?
776+
packet.page = 1;
777+
break;
778+
case 1:
779+
memcpy(packet.data, &data[HITAG_BLOCK_SIZE * 0], HITAG_BLOCK_SIZE);
780+
packet.page = 4;
781+
break;
782+
case 2:
783+
memcpy(packet.data, &data[HITAG_BLOCK_SIZE * 1], HITAG_BLOCK_SIZE);
784+
packet.page = 5;
785+
break;
786+
}
774787

788+
packet.cmd = WHTSF_PLAIN;
775789
SendCommandNG(CMD_LF_HITAGS_WRITE, (uint8_t *)&packet, sizeof(packet));
776-
if (WaitForResponseTimeout(CMD_LF_HITAGS_WRITE, &resp, 4000) == false)
777-
{
790+
if (WaitForResponseTimeout(CMD_LF_HITAGS_WRITE, &resp, 4000) == false) {
778791
PrintAndLogEx(WARNING, "timeout while waiting for reply.");
779792
return PM3_ETIMEOUT;
780793
}
@@ -784,6 +797,22 @@ static int CmdEM410xClone(const char *Cmd) {
784797
}
785798
}
786799
} else {
800+
struct {
801+
bool Q5;
802+
bool EM;
803+
bool add_electra;
804+
uint8_t clock;
805+
uint32_t high;
806+
uint32_t low;
807+
} PACKED payload;
808+
809+
payload.Q5 = q5;
810+
payload.EM = em;
811+
payload.add_electra = add_electra;
812+
payload.clock = clk;
813+
payload.high = (uint32_t)(id >> 32);
814+
payload.low = (uint32_t)id;
815+
787816
SendCommandNG(CMD_LF_EM410X_CLONE, (uint8_t *)&payload, sizeof(payload));
788817
WaitForResponse(CMD_LF_EM410X_CLONE, &resp);
789818
}

0 commit comments

Comments
 (0)