mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-20 21:33:47 -07:00
commit
ab095cb39d
8 changed files with 73 additions and 25 deletions
|
@ -133,7 +133,7 @@ static const manufactureName manufactureMapping[] = {
|
|||
{ 0x61, "Wearlinks Technology Inc. China" },
|
||||
{ 0x62, "Userstar Information Systems Co., Ltd Taiwan" },
|
||||
{ 0x63, "Pragmatic Printing Ltd. UK" },
|
||||
{ 0x64, "Associacao do Laboratorio de Sistemas Integraveis Tecnologico – LSI-TEC Brazil" },
|
||||
{ 0x64, "Associacao do Laboratorio de Sistemas Integraveis Tecnologico - LSI-TEC Brazil" },
|
||||
{ 0x65, "Tendyron Corporation China" },
|
||||
{ 0x66, "MUTO Smart Co., Ltd. Korea" },
|
||||
{ 0x67, "ON Semiconductor USA" },
|
||||
|
|
|
@ -1983,7 +1983,50 @@ noValidKeyFound:
|
|||
// Clear the last found key
|
||||
num_to_bytes(0, 6, tmp_key);
|
||||
|
||||
if (current_key_type_i == 1) {
|
||||
if (e_sector[current_sector_i].foundKey[0] && !e_sector[current_sector_i].foundKey[1]) {
|
||||
PrintAndLogEx(INFO, "Reading B key: sector: %3d", current_sector_i);
|
||||
uint8_t sectrail = (FirstBlockOfSector(current_sector_i) + NumBlocksPerSector(current_sector_i) - 1);
|
||||
|
||||
mf_readblock_t payload;
|
||||
payload.blockno = sectrail;
|
||||
payload.keytype = 0;
|
||||
|
||||
num_to_bytes(e_sector[current_sector_i].Key[0], 6, payload.key); // KEY A
|
||||
|
||||
clearCommandBuffer();
|
||||
SendCommandNG(CMD_HF_MIFARE_READBL, (uint8_t *)&payload, sizeof(mf_readblock_t));
|
||||
|
||||
PacketResponseNG resp;
|
||||
if (!WaitForResponseTimeout(CMD_HF_MIFARE_READBL, &resp, 1500)) goto skipReadBKey;
|
||||
|
||||
if (resp.status != PM3_SUCCESS) goto skipReadBKey;
|
||||
|
||||
uint8_t *data = resp.data.asBytes;
|
||||
key64 = bytes_to_num(data + 10, 6);
|
||||
if (verbose){
|
||||
num_to_bytes(key64, 6, tmp_key);
|
||||
PrintAndLogEx(INFO, "Discovered key: sector: %3d key type: %c key: " _YELLOW_("%s"),
|
||||
current_sector_i,
|
||||
current_key_type_i ? 'B' : 'A',
|
||||
sprint_hex(tmp_key, sizeof(tmp_key))
|
||||
);
|
||||
}
|
||||
if (key64) {
|
||||
e_sector[current_sector_i].foundKey[current_key_type_i] = 7;
|
||||
e_sector[current_sector_i].Key[current_key_type_i] = key64;
|
||||
num_to_bytes(key64, 6, tmp_key);
|
||||
PrintAndLogEx(SUCCESS, "Found valid key: sector: %3d key type: %c key: " _YELLOW_("%s"),
|
||||
current_sector_i,
|
||||
current_key_type_i ? 'B' : 'A',
|
||||
sprint_hex(tmp_key, sizeof(tmp_key))
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Use the nested / hardnested attack
|
||||
skipReadBKey:
|
||||
if (e_sector[current_sector_i].foundKey[current_key_type_i] == 0) {
|
||||
if (prng_type && (! nested_failed)) {
|
||||
uint8_t retries = 0;
|
||||
|
@ -2082,6 +2125,7 @@ tryHardnested: // If the nested attack fails then we try the hardnested attack
|
|||
PrintAndLogEx(INFO, " 4: Reused");
|
||||
PrintAndLogEx(INFO, " 5: Nested");
|
||||
PrintAndLogEx(INFO, " 6: Hardnested");
|
||||
PrintAndLogEx(INFO, " 7: Read B key with A key");
|
||||
}
|
||||
|
||||
PrintAndLogEx(INFO, "\nSaving keys");
|
||||
|
|
|
@ -401,11 +401,11 @@ static const struct emv_tag emv_tags[] = {
|
|||
{ 0xdf811b, "Kernel Configuration", EMV_TAG_GENERIC, NULL },
|
||||
{ 0xdf811c, "Max Lifetime of Torn Transaction Log Record", EMV_TAG_GENERIC, NULL },
|
||||
{ 0xdf811d, "Max Number of Torn Transaction Log Records", EMV_TAG_GENERIC, NULL },
|
||||
{ 0xdf811e, "Mag-stripe CVM Capability – CVM Required", EMV_TAG_GENERIC, NULL },
|
||||
{ 0xdf811e, "Mag-stripe CVM Capability - CVM Required", EMV_TAG_GENERIC, NULL },
|
||||
{ 0xdf811f, "Security Capability", EMV_TAG_GENERIC, NULL },
|
||||
{ 0xdf8120, "Terminal Action Code – Default", EMV_TAG_GENERIC, NULL },
|
||||
{ 0xdf8121, "Terminal Action Code – Denial", EMV_TAG_GENERIC, NULL },
|
||||
{ 0xdf8122, "Terminal Action Code – Online", EMV_TAG_GENERIC, NULL },
|
||||
{ 0xdf8120, "Terminal Action Code - Default", EMV_TAG_GENERIC, NULL },
|
||||
{ 0xdf8121, "Terminal Action Code - Denial", EMV_TAG_GENERIC, NULL },
|
||||
{ 0xdf8122, "Terminal Action Code - Online", EMV_TAG_GENERIC, NULL },
|
||||
{ 0xdf8123, "Reader Contactless Floor Limit", EMV_TAG_GENERIC, NULL },
|
||||
{ 0xdf8124, "Reader Contactless Transaction Limit (No On-device CVM)", EMV_TAG_GENERIC, NULL },
|
||||
{ 0xdf8125, "Reader Contactless Transaction Limit (On-device CVM)", EMV_TAG_GENERIC, NULL },
|
||||
|
@ -415,7 +415,7 @@ static const struct emv_tag emv_tags[] = {
|
|||
{ 0xdf8129, "Outcome Parameter Set", EMV_TAG_GENERIC, NULL },
|
||||
{ 0xdf812a, "DD Card (Track1)", EMV_TAG_GENERIC, NULL },
|
||||
{ 0xdf812b, "DD Card (Track2)", EMV_TAG_GENERIC, NULL },
|
||||
{ 0xdf812c, "Mag-stripe CVM Capability – No CVM Required", EMV_TAG_GENERIC, NULL },
|
||||
{ 0xdf812c, "Mag-stripe CVM Capability - No CVM Required", EMV_TAG_GENERIC, NULL },
|
||||
{ 0xdf812d, "Message Hold Time", EMV_TAG_GENERIC, NULL },
|
||||
|
||||
{ 0xff8101, "Torn Record", EMV_TAG_GENERIC, NULL },
|
||||
|
|
|
@ -226,8 +226,8 @@ void doMAC(uint8_t *cc_nr_p, uint8_t *div_key_p, uint8_t mac[4]) {
|
|||
reverse_arraybytes(dest, sizeof(dest));
|
||||
memcpy(mac, dest, 4);
|
||||
//free(cc_nr);
|
||||
return;
|
||||
}
|
||||
|
||||
void doMAC_N(uint8_t *address_data_p, uint8_t address_data_size, uint8_t *div_key_p, uint8_t mac[4]) {
|
||||
uint8_t *address_data;
|
||||
uint8_t div_key[8];
|
||||
|
@ -245,7 +245,6 @@ void doMAC_N(uint8_t *address_data_p, uint8_t address_data_size, uint8_t *div_ke
|
|||
reverse_arraybytes(dest, sizeof(dest));
|
||||
memcpy(mac, dest, 4);
|
||||
free(address_data);
|
||||
return;
|
||||
}
|
||||
|
||||
#ifndef ON_DEVICE
|
||||
|
@ -267,8 +266,8 @@ int testMAC() {
|
|||
PrintAndLogEx(FAILED, "FAILED: MAC calculation failed:");
|
||||
printarr(" Calculated_MAC", calculated_mac, 4);
|
||||
printarr(" Correct_MAC ", correct_MAC, 4);
|
||||
return 1;
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
return 0;
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
#ifndef CIPHER_H
|
||||
#define CIPHER_H
|
||||
#include <stdint.h>
|
||||
#include "pm3_cmd.h"
|
||||
|
||||
void doMAC(uint8_t *cc_nr_p, uint8_t *div_key_p, uint8_t mac[4]);
|
||||
void doMAC_N(uint8_t *address_data_p, uint8_t address_data_size, uint8_t *div_key_p, uint8_t mac[4]);
|
||||
|
|
|
@ -127,18 +127,21 @@ uint64_t x_bytes_to_num(uint8_t *src, size_t len) {
|
|||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
uint8_t reversebytes(uint8_t b) {
|
||||
b = (b & 0xF0) >> 4 | (b & 0x0F) << 4;
|
||||
b = (b & 0xCC) >> 2 | (b & 0x33) << 2;
|
||||
b = (b & 0xAA) >> 1 | (b & 0x55) << 1;
|
||||
return b;
|
||||
}
|
||||
|
||||
void reverse_arraybytes(uint8_t *arr, size_t len) {
|
||||
uint8_t i;
|
||||
for (i = 0; i < len ; i++) {
|
||||
arr[i] = reversebytes(arr[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void reverse_arraycopy(uint8_t *arr, uint8_t *dest, size_t len) {
|
||||
uint8_t i;
|
||||
for (i = 0; i < len ; i++) {
|
||||
|
@ -202,9 +205,9 @@ static int testBitStream() {
|
|||
for (i = 0 ; i < ARRAYLEN(input) ; i++) {
|
||||
PrintAndLogEx(NORMAL, " IN %02x, OUT %02x", input[i], output[i]);
|
||||
}
|
||||
return 1;
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
return 0;
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int testReversedBitstream() {
|
||||
|
@ -232,9 +235,9 @@ static int testReversedBitstream() {
|
|||
for (i = 0 ; i < ARRAYLEN(input) ; i++) {
|
||||
PrintAndLogEx(NORMAL, " IN %02x, MIDDLE: %02x, OUT %02x", input[i], reverse[i], output[i]);
|
||||
}
|
||||
return 1;
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
return 0;
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include "pm3_cmd.h"
|
||||
|
||||
typedef struct {
|
||||
uint8_t *buffer;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue