mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-03-20 12:07:05 +08:00
Merge pull request #233 from ViRb3/master
Add hitag2 write password auth
This commit is contained in:
commit
c388f66b81
3 changed files with 88 additions and 59 deletions
139
armsrc/hitag2.c
139
armsrc/hitag2.c
|
@ -331,64 +331,6 @@ size_t blocknr;
|
||||||
// Hitag2 operations
|
// Hitag2 operations
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
static bool hitag2_password(uint8_t *rx, const size_t rxlen, uint8_t *tx, size_t *txlen) {
|
|
||||||
// Reset the transmission frame length
|
|
||||||
*txlen = 0;
|
|
||||||
|
|
||||||
// Try to find out which command was send by selecting on length (in bits)
|
|
||||||
switch (rxlen) {
|
|
||||||
// No answer, try to resurrect
|
|
||||||
case 0: {
|
|
||||||
// Stop if there is no answer (after sending password)
|
|
||||||
if (bPwd) {
|
|
||||||
DbpString("Password failed!");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
*txlen = 5;
|
|
||||||
memcpy(tx, "\xC0", nbytes(*txlen));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
// Received UID, tag password
|
|
||||||
case 32: {
|
|
||||||
if (!bPwd) {
|
|
||||||
*txlen = 32;
|
|
||||||
memcpy(tx, password, 4);
|
|
||||||
bPwd = true;
|
|
||||||
memcpy(tag.sectors[blocknr], rx, 4);
|
|
||||||
blocknr++;
|
|
||||||
} else {
|
|
||||||
|
|
||||||
if (blocknr == 1) {
|
|
||||||
//store password in block1, the TAG answers with Block3, but we need the password in memory
|
|
||||||
memcpy(tag.sectors[blocknr], tx, 4);
|
|
||||||
} else {
|
|
||||||
memcpy(tag.sectors[blocknr], rx, 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
blocknr++;
|
|
||||||
if (blocknr > 7) {
|
|
||||||
DbpString("Read succesful!");
|
|
||||||
bSuccessful = true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
*txlen = 10;
|
|
||||||
tx[0] = 0xC0 | (blocknr << 3) | ((blocknr ^ 7) >> 2);
|
|
||||||
tx[1] = ((blocknr ^ 7) << 6);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
// Unexpected response
|
|
||||||
default: {
|
|
||||||
Dbprintf("Uknown frame length: %d", rxlen);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool hitag2_write_page(uint8_t *rx, const size_t rxlen, uint8_t *tx, size_t *txlen) {
|
static bool hitag2_write_page(uint8_t *rx, const size_t rxlen, uint8_t *tx, size_t *txlen) {
|
||||||
switch (writestate) {
|
switch (writestate) {
|
||||||
case WRITE_STATE_START:
|
case WRITE_STATE_START:
|
||||||
|
@ -431,6 +373,71 @@ static bool hitag2_write_page(uint8_t *rx, const size_t rxlen, uint8_t *tx, size
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool hitag2_password(uint8_t *rx, const size_t rxlen, uint8_t *tx, size_t *txlen, bool write) {
|
||||||
|
// Reset the transmission frame length
|
||||||
|
*txlen = 0;
|
||||||
|
|
||||||
|
if (bPwd && write) {
|
||||||
|
if (!hitag2_write_page(rx, rxlen, tx, txlen)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Try to find out which command was send by selecting on length (in bits)
|
||||||
|
switch (rxlen) {
|
||||||
|
// No answer, try to resurrect
|
||||||
|
case 0: {
|
||||||
|
// Stop if there is no answer (after sending password)
|
||||||
|
if (bPwd) {
|
||||||
|
DbpString("Password failed!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*txlen = 5;
|
||||||
|
memcpy(tx, "\xC0", nbytes(*txlen));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Received UID, tag password
|
||||||
|
case 32: {
|
||||||
|
if (!bPwd) {
|
||||||
|
*txlen = 32;
|
||||||
|
memcpy(tx, password, 4);
|
||||||
|
bPwd = true;
|
||||||
|
memcpy(tag.sectors[blocknr], rx, 4);
|
||||||
|
blocknr++;
|
||||||
|
} else {
|
||||||
|
|
||||||
|
if (blocknr == 1) {
|
||||||
|
//store password in block1, the TAG answers with Block3, but we need the password in memory
|
||||||
|
memcpy(tag.sectors[blocknr], tx, 4);
|
||||||
|
} else {
|
||||||
|
memcpy(tag.sectors[blocknr], rx, 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
blocknr++;
|
||||||
|
if (blocknr > 7) {
|
||||||
|
DbpString("Read succesful!");
|
||||||
|
bSuccessful = true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*txlen = 10;
|
||||||
|
tx[0] = 0xC0 | (blocknr << 3) | ((blocknr ^ 7) >> 2);
|
||||||
|
tx[1] = ((blocknr ^ 7) << 6);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Unexpected response
|
||||||
|
default: {
|
||||||
|
Dbprintf("Uknown frame length: %d", rxlen);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static bool hitag2_crypto(uint8_t *rx, const size_t rxlen, uint8_t *tx, size_t *txlen, bool write) {
|
static bool hitag2_crypto(uint8_t *rx, const size_t rxlen, uint8_t *tx, size_t *txlen, bool write) {
|
||||||
// Reset the transmission frame length
|
// Reset the transmission frame length
|
||||||
*txlen = 0;
|
*txlen = 0;
|
||||||
|
@ -1217,7 +1224,7 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) {
|
||||||
tx = txbuf;
|
tx = txbuf;
|
||||||
switch (htf) {
|
switch (htf) {
|
||||||
case RHT2F_PASSWORD: {
|
case RHT2F_PASSWORD: {
|
||||||
bStop = !hitag2_password(rx, rxlen, tx, &txlen);
|
bStop = !hitag2_password(rx, rxlen, tx, &txlen, false);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case RHT2F_AUTHENTICATE: {
|
case RHT2F_AUTHENTICATE: {
|
||||||
|
@ -1391,6 +1398,16 @@ void WriterHitag(hitag_function htf, hitag_data *htd, int page) {
|
||||||
writestate = WRITE_STATE_START;
|
writestate = WRITE_STATE_START;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case WHT2F_PASSWORD: {
|
||||||
|
DbpString("Authenticating using password:");
|
||||||
|
memcpy(password, htd->pwd.password, 4);
|
||||||
|
memcpy(writedata, htd->crypto.data, 4);
|
||||||
|
Dbhexdump(4, password, false);
|
||||||
|
blocknr = page;
|
||||||
|
bPwd = false;
|
||||||
|
writestate = WRITE_STATE_START;
|
||||||
|
}
|
||||||
|
break;
|
||||||
default: {
|
default: {
|
||||||
Dbprintf("Error, unknown function: %d", htf);
|
Dbprintf("Error, unknown function: %d", htf);
|
||||||
StartTicks();
|
StartTicks();
|
||||||
|
@ -1480,6 +1497,10 @@ void WriterHitag(hitag_function htf, hitag_data *htd, int page) {
|
||||||
bStop = !hitag2_crypto(rx, rxlen, tx, &txlen, true);
|
bStop = !hitag2_crypto(rx, rxlen, tx, &txlen, true);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case WHT2F_PASSWORD: {
|
||||||
|
bStop = !hitag2_password(rx, rxlen, tx, &txlen, true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
default: {
|
default: {
|
||||||
Dbprintf("Error, unknown function: %d", htf);
|
Dbprintf("Error, unknown function: %d", htf);
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -106,6 +106,7 @@ static int usage_hitag_writer(void) {
|
||||||
PrintAndLogEx(NORMAL, " Hitag1 (1*)");
|
PrintAndLogEx(NORMAL, " Hitag1 (1*)");
|
||||||
PrintAndLogEx(NORMAL, " Hitag2 (2*)");
|
PrintAndLogEx(NORMAL, " Hitag2 (2*)");
|
||||||
PrintAndLogEx(NORMAL, " 24 <key> (set to 0 if no authentication is needed) <page> <byte0...byte3> write page on a Hitag2 tag");
|
PrintAndLogEx(NORMAL, " 24 <key> (set to 0 if no authentication is needed) <page> <byte0...byte3> write page on a Hitag2 tag");
|
||||||
|
PrintAndLogEx(NORMAL, " 27 <password> <page> <byte0...byte3> write page on a Hitag2 tag");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
static int usage_hitag_checkchallenges(void) {
|
static int usage_hitag_checkchallenges(void) {
|
||||||
|
@ -659,6 +660,12 @@ static int CmdLFHitagWriter(const char *Cmd) {
|
||||||
num_to_bytes(param_get32ex(Cmd, 3, 0, 16), 4, htd.crypto.data);
|
num_to_bytes(param_get32ex(Cmd, 3, 0, 16), 4, htd.crypto.data);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case WHT2F_PASSWORD: {
|
||||||
|
num_to_bytes(param_get64ex(Cmd, 1, 0, 16), 4, htd.pwd.password);
|
||||||
|
arg2 = param_get32ex(Cmd, 2, 0, 10);
|
||||||
|
num_to_bytes(param_get32ex(Cmd, 3, 0, 16), 4, htd.crypto.data);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case RHTSF_CHALLENGE:
|
case RHTSF_CHALLENGE:
|
||||||
case RHTSF_KEY:
|
case RHTSF_KEY:
|
||||||
case RHT2F_PASSWORD:
|
case RHT2F_PASSWORD:
|
||||||
|
|
|
@ -31,6 +31,7 @@ typedef enum {
|
||||||
WHT2F_CRYPTO = 24,
|
WHT2F_CRYPTO = 24,
|
||||||
RHT2F_TEST_AUTH_ATTEMPTS = 25,
|
RHT2F_TEST_AUTH_ATTEMPTS = 25,
|
||||||
RHT2F_UID_ONLY = 26,
|
RHT2F_UID_ONLY = 26,
|
||||||
|
WHT2F_PASSWORD = 27,
|
||||||
} hitag_function;
|
} hitag_function;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|
Loading…
Add table
Reference in a new issue