mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-19 04:50:12 -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;
|
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: {
|
case CMD_LF_EM4X_READWORD: {
|
||||||
struct p {
|
struct p {
|
||||||
uint32_t password;
|
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;
|
forward_ptr = forwardLink_data;
|
||||||
uint8_t len = Prepare_Cmd(FWD_CMD_LOGIN);
|
uint8_t len = Prepare_Cmd(FWD_CMD_LOGIN);
|
||||||
len += Prepare_Data(pwd & 0xFFFF, pwd >> 16);
|
len += Prepare_Data(pwd & 0xFFFF, pwd >> 16);
|
||||||
|
@ -2512,6 +2512,29 @@ static void EM4xLogin(uint32_t pwd) {
|
||||||
// 0000 0001 fail
|
// 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) {
|
void EM4xReadWord(uint8_t addr, uint32_t pwd, uint8_t usepwd) {
|
||||||
|
|
||||||
StartTicks();
|
StartTicks();
|
||||||
|
@ -2529,7 +2552,7 @@ void EM4xReadWord(uint8_t addr, uint32_t pwd, uint8_t usepwd) {
|
||||||
* 0000 1010 ok
|
* 0000 1010 ok
|
||||||
* 0000 0001 fail
|
* 0000 0001 fail
|
||||||
**/
|
**/
|
||||||
if (usepwd) EM4xLogin(pwd);
|
if (usepwd) EM4xLoginEx(pwd);
|
||||||
|
|
||||||
forward_ptr = forwardLink_data;
|
forward_ptr = forwardLink_data;
|
||||||
uint8_t len = Prepare_Cmd(FWD_CMD_READ);
|
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 1010 ok.
|
||||||
* 0000 0001 fail
|
* 0000 0001 fail
|
||||||
**/
|
**/
|
||||||
if (usepwd) EM4xLogin(pwd);
|
if (usepwd) EM4xLoginEx(pwd);
|
||||||
|
|
||||||
forward_ptr = forwardLink_data;
|
forward_ptr = forwardLink_data;
|
||||||
uint8_t len = Prepare_Cmd(FWD_CMD_WRITE);
|
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 1010 ok.
|
||||||
* 0000 0001 fail
|
* 0000 0001 fail
|
||||||
**/
|
**/
|
||||||
if (usepwd) EM4xLogin(pwd);
|
if (usepwd) EM4xLoginEx(pwd);
|
||||||
|
|
||||||
forward_ptr = forwardLink_data;
|
forward_ptr = forwardLink_data;
|
||||||
uint8_t len = Prepare_Cmd(FWD_CMD_PROTECT);
|
uint8_t len = Prepare_Cmd(FWD_CMD_PROTECT);
|
||||||
|
|
|
@ -56,6 +56,7 @@ void T55xxDangerousRawTest(uint8_t *data);
|
||||||
|
|
||||||
void TurnReadLFOn(uint32_t delay);
|
void TurnReadLFOn(uint32_t delay);
|
||||||
|
|
||||||
|
void EM4xLogin(uint32_t pwd);
|
||||||
void EM4xReadWord(uint8_t addr, uint32_t pwd, uint8_t usepwd);
|
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 EM4xWriteWord(uint8_t addr, uint32_t data, uint32_t pwd, uint8_t usepwd);
|
||||||
void EM4xProtectWord(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
|
//////////////// 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) {
|
int EM4x05ReadWord_ext(uint8_t addr, uint32_t pwd, bool usePwd, uint32_t *word) {
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
|
@ -438,7 +461,6 @@ int CmdEM4x05Dump(const char *Cmd) {
|
||||||
if (EM4x05IsBlock0(&block0) == false)
|
if (EM4x05IsBlock0(&block0) == false)
|
||||||
return PM3_ESOFT;
|
return PM3_ESOFT;
|
||||||
|
|
||||||
bool needReadPwd = true;
|
|
||||||
uint8_t bytes[4] = {0};
|
uint8_t bytes[4] = {0};
|
||||||
uint32_t data[16];
|
uint32_t data[16];
|
||||||
|
|
||||||
|
@ -456,28 +478,32 @@ int CmdEM4x05Dump(const char *Cmd) {
|
||||||
em_tech_type_t card_type = em_get_card_type(block0);
|
em_tech_type_t card_type = em_get_card_type(block0);
|
||||||
|
|
||||||
PrintAndLogEx(INFO, "Found a " _GREEN_("%s") " tag", em_get_card_str(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, "Addr | data | ascii |lck| info");
|
||||||
PrintAndLogEx(INFO, "-----+----------+-------+---+-----");
|
PrintAndLogEx(INFO, "-----+----------+-------+---+-----");
|
||||||
|
|
||||||
if ( card_type == EM_4205 || card_type == EM_4305 || card_type == EM_UNKNOWN) {
|
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
|
// To flag any blocks locked we need to read blocks 14 and 15 first
|
||||||
// dont swap endin until we get block lock flags.
|
// dont swap endin until we get block lock flags.
|
||||||
status14 = EM4x05ReadWord_ext(EM4305_PROT1_BLOCK, pwd, usePwd, &word);
|
status14 = EM4x05ReadWord_ext(EM4305_PROT1_BLOCK, pwd, usePwd, &word);
|
||||||
if (status14 == PM3_SUCCESS) {
|
if (status14 == PM3_SUCCESS) {
|
||||||
if (!usePwd)
|
|
||||||
needReadPwd = false;
|
|
||||||
if ((word & 0x00008000) != 0x00) {
|
if ((word & 0x00008000) != 0x00) {
|
||||||
lock_bits = word;
|
lock_bits = word;
|
||||||
gotLockBits = true;
|
gotLockBits = true;
|
||||||
|
@ -503,14 +529,9 @@ int CmdEM4x05Dump(const char *Cmd) {
|
||||||
lockbit = (lock_bits >> addr) & 1;
|
lockbit = (lock_bits >> addr) & 1;
|
||||||
if (addr == 2) {
|
if (addr == 2) {
|
||||||
if (usePwd) {
|
if (usePwd) {
|
||||||
if ((needReadPwd) && (success != PM3_ESOFT)) {
|
data[addr] = BSWAP_32(pwd);
|
||||||
data[addr] = BSWAP_32(pwd);
|
num_to_bytes(pwd, 4, bytes);
|
||||||
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]);
|
||||||
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]);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
data[addr] = 0x00; // Unknown password, but not used to set to zeros
|
data[addr] = 0x00; // Unknown password, but not used to set to zeros
|
||||||
PrintAndLogEx(INFO, " %02u | | | | %-10s " _YELLOW_("write only"), addr, info[addr]);
|
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) {
|
} 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
|
// To flag any blocks locked we need to read blocks 14 and 15 first
|
||||||
// dont swap endin until we get block lock flags.
|
// dont swap endin until we get block lock flags.
|
||||||
status14 = EM4x05ReadWord_ext(EM4469_PROT_BLOCK, pwd, usePwd, &word);
|
status14 = EM4x05ReadWord_ext(EM4469_PROT_BLOCK, pwd, usePwd, &word);
|
||||||
if (status14 == PM3_SUCCESS) {
|
if (status14 == PM3_SUCCESS) {
|
||||||
if (!usePwd)
|
|
||||||
needReadPwd = false;
|
|
||||||
if ((word & 0x00008000) != 0x00) {
|
if ((word & 0x00008000) != 0x00) {
|
||||||
lock_bits = word;
|
lock_bits = word;
|
||||||
gotLockBits = true;
|
gotLockBits = true;
|
||||||
|
@ -580,14 +590,9 @@ int CmdEM4x05Dump(const char *Cmd) {
|
||||||
lockbit = (lock_bits >> addr) & 1;
|
lockbit = (lock_bits >> addr) & 1;
|
||||||
if (addr == 2) {
|
if (addr == 2) {
|
||||||
if (usePwd) {
|
if (usePwd) {
|
||||||
if ((needReadPwd) && (success != PM3_ESOFT)) {
|
data[addr] = BSWAP_32(pwd);
|
||||||
data[addr] = BSWAP_32(pwd);
|
num_to_bytes(pwd, 4, bytes);
|
||||||
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]);
|
||||||
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]);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
data[addr] = 0x00; // Unknown password, but not used to set to zeros
|
data[addr] = 0x00; // Unknown password, but not used to set to zeros
|
||||||
PrintAndLogEx(INFO, " %02u | | | | %-10s " _YELLOW_("write only"), addr, info4x69[addr]);
|
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);
|
uint64_t card_id = arg_get_u64_def(ctx, 2, 0);
|
||||||
CLIParserFree(ctx);
|
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) {
|
if (strlen(filename) == 0) {
|
||||||
snprintf(filename, sizeof(filename), "t55xx_default_pwds");
|
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);
|
uint32_t pwd = lf_t55xx_white_pwdgen(card_id & 0xFFFFFFFF);
|
||||||
PrintAndLogEx(INFO, "testing %08"PRIX32" generated ", pwd);
|
PrintAndLogEx(INFO, "testing %08"PRIX32" generated ", pwd);
|
||||||
|
|
||||||
status = EM4x05ReadWord_ext(addr, pwd, true, &word);
|
int status = EM4x05Login_ext(pwd);
|
||||||
if (status == PM3_SUCCESS) {
|
if (status == PM3_SUCCESS) {
|
||||||
PrintAndLogEx(SUCCESS, "found valid password [ " _GREEN_("%08"PRIX32) " ]", pwd);
|
PrintAndLogEx(SUCCESS, "found valid password [ " _GREEN_("%08"PRIX32) " ]", pwd);
|
||||||
found = true;
|
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");
|
PrintAndLogEx(INFO, "press " _YELLOW_("'enter'") " to cancel the command");
|
||||||
|
|
||||||
word = 0;
|
|
||||||
uint32_t keycount = 0;
|
uint32_t keycount = 0;
|
||||||
|
|
||||||
int res = loadFileDICTIONARY_safe(filename, (void **) &keyBlock, 4, &keycount);
|
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);
|
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) {
|
if (status == PM3_SUCCESS) {
|
||||||
PrintAndLogEx(SUCCESS, "found valid password [ " _GREEN_("%08"PRIX32) " ]", curr_password);
|
PrintAndLogEx(SUCCESS, "found valid password [ " _GREEN_("%08"PRIX32) " ]", curr_password);
|
||||||
found = true;
|
found = true;
|
||||||
break;
|
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_T55XX_RESET_READ 0x0216
|
||||||
#define CMD_LF_PCF7931_READ 0x0217
|
#define CMD_LF_PCF7931_READ 0x0217
|
||||||
#define CMD_LF_PCF7931_WRITE 0x0223
|
#define CMD_LF_PCF7931_WRITE 0x0223
|
||||||
|
#define CMD_LF_EM4X_LOGIN 0x0229
|
||||||
#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_EM4X_PROTECTWORD 0x021B
|
#define CMD_LF_EM4X_PROTECTWORD 0x021B
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue