mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-14 10:37:23 -07:00
Add EM 4x05 Login
This commit is contained in:
parent
c86df6b83d
commit
95bf65cda9
5 changed files with 87 additions and 55 deletions
|
@ -970,6 +970,14 @@ static void PacketReceived(PacketCommandNG *packet) {
|
|||
);
|
||||
break;
|
||||
}
|
||||
case CMD_LF_EM4X_LOGIN: {
|
||||
struct p {
|
||||
uint32_t password;
|
||||
} PACKED;
|
||||
struct p *payload = (struct p *) packet->data.asBytes;
|
||||
EM4xLogin(payload->password);
|
||||
break;
|
||||
}
|
||||
case CMD_LF_EM4X_READWORD: {
|
||||
struct p {
|
||||
uint32_t password;
|
||||
|
|
|
@ -2501,7 +2501,7 @@ static void SendForward(uint8_t fwd_bit_count) {
|
|||
}
|
||||
}
|
||||
|
||||
static void EM4xLogin(uint32_t pwd) {
|
||||
static void EM4xLoginEx(uint32_t pwd) {
|
||||
forward_ptr = forwardLink_data;
|
||||
uint8_t len = Prepare_Cmd(FWD_CMD_LOGIN);
|
||||
len += Prepare_Data(pwd & 0xFFFF, pwd >> 16);
|
||||
|
@ -2512,6 +2512,29 @@ static void EM4xLogin(uint32_t pwd) {
|
|||
// 0000 0001 fail
|
||||
}
|
||||
|
||||
void EM4xLogin(uint32_t pwd) {
|
||||
|
||||
StartTicks();
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
WaitMS(20);
|
||||
|
||||
LED_A_ON();
|
||||
|
||||
// clear buffer now so it does not interfere with timing later
|
||||
BigBuf_Clear_ext(false);
|
||||
|
||||
EM4xLoginEx(pwd);
|
||||
|
||||
WaitUS(400);
|
||||
|
||||
DoPartialAcquisition(20, false, 1000, 1000);
|
||||
|
||||
StopTicks();
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
reply_ng(CMD_LF_EM4X_LOGIN, PM3_SUCCESS, NULL, 0);
|
||||
LEDsoff();
|
||||
}
|
||||
|
||||
void EM4xReadWord(uint8_t addr, uint32_t pwd, uint8_t usepwd) {
|
||||
|
||||
StartTicks();
|
||||
|
@ -2529,7 +2552,7 @@ void EM4xReadWord(uint8_t addr, uint32_t pwd, uint8_t usepwd) {
|
|||
* 0000 1010 ok
|
||||
* 0000 0001 fail
|
||||
**/
|
||||
if (usepwd) EM4xLogin(pwd);
|
||||
if (usepwd) EM4xLoginEx(pwd);
|
||||
|
||||
forward_ptr = forwardLink_data;
|
||||
uint8_t len = Prepare_Cmd(FWD_CMD_READ);
|
||||
|
@ -2564,7 +2587,7 @@ void EM4xWriteWord(uint8_t addr, uint32_t data, uint32_t pwd, uint8_t usepwd) {
|
|||
* 0000 1010 ok.
|
||||
* 0000 0001 fail
|
||||
**/
|
||||
if (usepwd) EM4xLogin(pwd);
|
||||
if (usepwd) EM4xLoginEx(pwd);
|
||||
|
||||
forward_ptr = forwardLink_data;
|
||||
uint8_t len = Prepare_Cmd(FWD_CMD_WRITE);
|
||||
|
@ -2607,7 +2630,7 @@ void EM4xProtectWord(uint32_t data, uint32_t pwd, uint8_t usepwd) {
|
|||
* 0000 1010 ok.
|
||||
* 0000 0001 fail
|
||||
**/
|
||||
if (usepwd) EM4xLogin(pwd);
|
||||
if (usepwd) EM4xLoginEx(pwd);
|
||||
|
||||
forward_ptr = forwardLink_data;
|
||||
uint8_t len = Prepare_Cmd(FWD_CMD_PROTECT);
|
||||
|
|
|
@ -56,6 +56,7 @@ void T55xxDangerousRawTest(uint8_t *data);
|
|||
|
||||
void TurnReadLFOn(uint32_t delay);
|
||||
|
||||
void EM4xLogin(uint32_t pwd);
|
||||
void EM4xReadWord(uint8_t addr, uint32_t pwd, uint8_t usepwd);
|
||||
void EM4xWriteWord(uint8_t addr, uint32_t data, uint32_t pwd, uint8_t usepwd);
|
||||
void EM4xProtectWord(uint32_t data, uint32_t pwd, uint8_t usepwd);
|
||||
|
|
|
@ -361,6 +361,29 @@ static int demodEM4x05resp(uint32_t *word, bool onlyPreamble) {
|
|||
|
||||
//////////////// 4205 / 4305 commands
|
||||
|
||||
static int EM4x05Login_ext(uint32_t pwd) {
|
||||
|
||||
struct {
|
||||
uint32_t password;
|
||||
} PACKED payload;
|
||||
|
||||
payload.password = pwd;
|
||||
|
||||
clearCommandBuffer();
|
||||
SendCommandNG(CMD_LF_EM4X_LOGIN, (uint8_t *)&payload, sizeof(payload));
|
||||
PacketResponseNG resp;
|
||||
if (!WaitForResponseTimeout(CMD_LF_EM4X_LOGIN, &resp, 10000)) {
|
||||
PrintAndLogEx(WARNING, "(EM4x05Login_ext) timeout while waiting for reply.");
|
||||
return PM3_ETIMEOUT;
|
||||
}
|
||||
|
||||
if (downloadSamplesEM() == false) {
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
uint32_t word;
|
||||
return demodEM4x05resp(&word, true);
|
||||
}
|
||||
|
||||
int EM4x05ReadWord_ext(uint8_t addr, uint32_t pwd, bool usePwd, uint32_t *word) {
|
||||
|
||||
struct {
|
||||
|
@ -438,7 +461,6 @@ int CmdEM4x05Dump(const char *Cmd) {
|
|||
if (EM4x05IsBlock0(&block0) == false)
|
||||
return PM3_ESOFT;
|
||||
|
||||
bool needReadPwd = true;
|
||||
uint8_t bytes[4] = {0};
|
||||
uint32_t data[16];
|
||||
|
||||
|
@ -456,28 +478,32 @@ int CmdEM4x05Dump(const char *Cmd) {
|
|||
em_tech_type_t card_type = em_get_card_type(block0);
|
||||
|
||||
PrintAndLogEx(INFO, "Found a " _GREEN_("%s") " tag", em_get_card_str(block0));
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
|
||||
if (usePwd) {
|
||||
// Test first if the password is correct
|
||||
status = EM4x05Login_ext(pwd);
|
||||
if (status == PM3_SUCCESS) {
|
||||
PrintAndLogEx(INFO, "Password is " _GREEN_("correct"));
|
||||
} else if (status == PM3_EFAILED) {
|
||||
PrintAndLogEx(WARNING, "Password is " _RED_("incorrect") ", will try without password");
|
||||
usePwd = false;
|
||||
} else if (status != PM3_EFAILED) {
|
||||
PrintAndLogEx(WARNING, "Login attempt: No answer from tag");
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(INFO, "Addr | data | ascii |lck| info");
|
||||
PrintAndLogEx(INFO, "-----+----------+-------+---+-----");
|
||||
|
||||
if ( card_type == EM_4205 || card_type == EM_4305 || card_type == EM_UNKNOWN) {
|
||||
|
||||
if (usePwd) {
|
||||
// Test first if a password is required
|
||||
status = EM4x05ReadWord_ext(EM4305_PROT1_BLOCK, pwd, false, &word);
|
||||
if (status == PM3_SUCCESS) {
|
||||
PrintAndLogEx(INFO, "Note that password doesn't seem to be needed");
|
||||
needReadPwd = false;
|
||||
}
|
||||
}
|
||||
|
||||
// To flag any blocks locked we need to read blocks 14 and 15 first
|
||||
// dont swap endin until we get block lock flags.
|
||||
status14 = EM4x05ReadWord_ext(EM4305_PROT1_BLOCK, pwd, usePwd, &word);
|
||||
if (status14 == PM3_SUCCESS) {
|
||||
if (!usePwd)
|
||||
needReadPwd = false;
|
||||
if ((word & 0x00008000) != 0x00) {
|
||||
lock_bits = word;
|
||||
gotLockBits = true;
|
||||
|
@ -503,14 +529,9 @@ int CmdEM4x05Dump(const char *Cmd) {
|
|||
lockbit = (lock_bits >> addr) & 1;
|
||||
if (addr == 2) {
|
||||
if (usePwd) {
|
||||
if ((needReadPwd) && (success != PM3_ESOFT)) {
|
||||
data[addr] = BSWAP_32(pwd);
|
||||
num_to_bytes(pwd, 4, bytes);
|
||||
PrintAndLogEx(INFO, " %02u | %08X | %s | %s | %s", addr, pwd, sprint_ascii(bytes, 4), gotLockBits ? (lockbit ? _RED_("x") : " ") : _YELLOW_("?"), info[addr]);
|
||||
} else {
|
||||
// The pwd is not needed for Login so we're not sure what's the actual content of that block
|
||||
PrintAndLogEx(INFO, " %02u | | | | %-10s " _YELLOW_("write only"), addr, info[addr]);
|
||||
}
|
||||
data[addr] = BSWAP_32(pwd);
|
||||
num_to_bytes(pwd, 4, bytes);
|
||||
PrintAndLogEx(INFO, " %02u | %08X | %s | %s | %s", addr, pwd, sprint_ascii(bytes, 4), gotLockBits ? (lockbit ? _RED_("x") : " ") : _YELLOW_("?"), info[addr]);
|
||||
} else {
|
||||
data[addr] = 0x00; // Unknown password, but not used to set to zeros
|
||||
PrintAndLogEx(INFO, " %02u | | | | %-10s " _YELLOW_("write only"), addr, info[addr]);
|
||||
|
@ -550,21 +571,10 @@ int CmdEM4x05Dump(const char *Cmd) {
|
|||
|
||||
} else if (card_type == EM_4X69) {
|
||||
|
||||
if (usePwd) {
|
||||
// Test first if a password is required
|
||||
status = EM4x05ReadWord_ext(EM4469_PROT_BLOCK, pwd, false, &word);
|
||||
if (status == PM3_SUCCESS) {
|
||||
PrintAndLogEx(INFO, "Note that password doesn't seem to be needed");
|
||||
needReadPwd = false;
|
||||
}
|
||||
}
|
||||
|
||||
// To flag any blocks locked we need to read blocks 14 and 15 first
|
||||
// dont swap endin until we get block lock flags.
|
||||
status14 = EM4x05ReadWord_ext(EM4469_PROT_BLOCK, pwd, usePwd, &word);
|
||||
if (status14 == PM3_SUCCESS) {
|
||||
if (!usePwd)
|
||||
needReadPwd = false;
|
||||
if ((word & 0x00008000) != 0x00) {
|
||||
lock_bits = word;
|
||||
gotLockBits = true;
|
||||
|
@ -580,14 +590,9 @@ int CmdEM4x05Dump(const char *Cmd) {
|
|||
lockbit = (lock_bits >> addr) & 1;
|
||||
if (addr == 2) {
|
||||
if (usePwd) {
|
||||
if ((needReadPwd) && (success != PM3_ESOFT)) {
|
||||
data[addr] = BSWAP_32(pwd);
|
||||
num_to_bytes(pwd, 4, bytes);
|
||||
PrintAndLogEx(INFO, " %02u | %08X | %s | %s | %s", addr, pwd, sprint_ascii(bytes, 4), gotLockBits ? (lockbit ? _RED_("x") : " ") : _YELLOW_("?"), info4x69[addr]);
|
||||
} else {
|
||||
// The pwd is not needed for Login so we're not sure what's the actual content of that block
|
||||
PrintAndLogEx(INFO, " %02u | | | | %-10s " _YELLOW_("write only"), addr, info4x69[addr]);
|
||||
}
|
||||
data[addr] = BSWAP_32(pwd);
|
||||
num_to_bytes(pwd, 4, bytes);
|
||||
PrintAndLogEx(INFO, " %02u | %08X | %s | %s | %s", addr, pwd, sprint_ascii(bytes, 4), gotLockBits ? (lockbit ? _RED_("x") : " ") : _YELLOW_("?"), info4x69[addr]);
|
||||
} else {
|
||||
data[addr] = 0x00; // Unknown password, but not used to set to zeros
|
||||
PrintAndLogEx(INFO, " %02u | | | | %-10s " _YELLOW_("write only"), addr, info4x69[addr]);
|
||||
|
@ -1095,15 +1100,6 @@ int CmdEM4x05Chk(const char *Cmd) {
|
|||
uint64_t card_id = arg_get_u64_def(ctx, 2, 0);
|
||||
CLIParserFree(ctx);
|
||||
|
||||
uint8_t addr = 4;
|
||||
uint32_t word = 0;
|
||||
// Test first if a password is required
|
||||
int status = EM4x05ReadWord_ext(addr, 0, false, &word);
|
||||
if (status == PM3_SUCCESS) {
|
||||
PrintAndLogEx(INFO, "Password doesn't seem to be needed to read the tag");
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
if (strlen(filename) == 0) {
|
||||
snprintf(filename, sizeof(filename), "t55xx_default_pwds");
|
||||
}
|
||||
|
@ -1118,10 +1114,12 @@ int CmdEM4x05Chk(const char *Cmd) {
|
|||
uint32_t pwd = lf_t55xx_white_pwdgen(card_id & 0xFFFFFFFF);
|
||||
PrintAndLogEx(INFO, "testing %08"PRIX32" generated ", pwd);
|
||||
|
||||
status = EM4x05ReadWord_ext(addr, pwd, true, &word);
|
||||
int status = EM4x05Login_ext(pwd);
|
||||
if (status == PM3_SUCCESS) {
|
||||
PrintAndLogEx(SUCCESS, "found valid password [ " _GREEN_("%08"PRIX32) " ]", pwd);
|
||||
found = true;
|
||||
} else if (status != PM3_EFAILED) {
|
||||
PrintAndLogEx(WARNING, "No answer from tag");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1131,7 +1129,6 @@ int CmdEM4x05Chk(const char *Cmd) {
|
|||
|
||||
PrintAndLogEx(INFO, "press " _YELLOW_("'enter'") " to cancel the command");
|
||||
|
||||
word = 0;
|
||||
uint32_t keycount = 0;
|
||||
|
||||
int res = loadFileDICTIONARY_safe(filename, (void **) &keyBlock, 4, &keycount);
|
||||
|
@ -1160,11 +1157,13 @@ int CmdEM4x05Chk(const char *Cmd) {
|
|||
|
||||
PrintAndLogEx(INFO, "testing %08"PRIX32, curr_password);
|
||||
|
||||
status = EM4x05ReadWord_ext(addr, curr_password, 1, &word);
|
||||
int status = EM4x05Login_ext(curr_password);
|
||||
if (status == PM3_SUCCESS) {
|
||||
PrintAndLogEx(SUCCESS, "found valid password [ " _GREEN_("%08"PRIX32) " ]", curr_password);
|
||||
found = true;
|
||||
break;
|
||||
} else if (status != PM3_EFAILED) {
|
||||
PrintAndLogEx(WARNING, "No answer from tag");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -496,6 +496,7 @@ typedef struct {
|
|||
#define CMD_LF_T55XX_RESET_READ 0x0216
|
||||
#define CMD_LF_PCF7931_READ 0x0217
|
||||
#define CMD_LF_PCF7931_WRITE 0x0223
|
||||
#define CMD_LF_EM4X_LOGIN 0x0229
|
||||
#define CMD_LF_EM4X_READWORD 0x0218
|
||||
#define CMD_LF_EM4X_WRITEWORD 0x0219
|
||||
#define CMD_LF_EM4X_PROTECTWORD 0x021B
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue