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
|
@ -101,16 +101,16 @@ static const uint8_t opt_select_LUT[256] = {
|
||||||
/********************** the table above has been generated with this code: ********
|
/********************** the table above has been generated with this code: ********
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
static void init_opt_select_LUT(void) {
|
static void init_opt_select_LUT(void) {
|
||||||
for (int r = 0; r < 256; r++) {
|
for (int r = 0; r < 256; r++) {
|
||||||
uint8_t r_ls2 = r << 2;
|
uint8_t r_ls2 = r << 2;
|
||||||
uint8_t r_and_ls2 = r & r_ls2;
|
uint8_t r_and_ls2 = r & r_ls2;
|
||||||
uint8_t r_or_ls2 = r | r_ls2;
|
uint8_t r_or_ls2 = r | r_ls2;
|
||||||
uint8_t z0 = (r_and_ls2 >> 5) ^ ((r & ~r_ls2) >> 4) ^ ( r_or_ls2 >> 3);
|
uint8_t z0 = (r_and_ls2 >> 5) ^ ((r & ~r_ls2) >> 4) ^ ( r_or_ls2 >> 3);
|
||||||
uint8_t z1 = (r_or_ls2 >> 6) ^ ( r_or_ls2 >> 1) ^ (r >> 5) ^ r;
|
uint8_t z1 = (r_or_ls2 >> 6) ^ ( r_or_ls2 >> 1) ^ (r >> 5) ^ r;
|
||||||
uint8_t z2 = ((r & ~r_ls2) >> 4) ^ (r_and_ls2 >> 3) ^ r;
|
uint8_t z2 = ((r & ~r_ls2) >> 4) ^ (r_and_ls2 >> 3) ^ r;
|
||||||
opt_select_LUT[r] = (z0 & 4) | (z1 & 2) | (z2 & 1);
|
opt_select_LUT[r] = (z0 & 4) | (z1 & 2) | (z2 & 1);
|
||||||
}
|
}
|
||||||
print_result("", opt_select_LUT, 256);
|
print_result("", opt_select_LUT, 256);
|
||||||
}
|
}
|
||||||
***********************************************************************************/
|
***********************************************************************************/
|
||||||
|
|
||||||
|
|
|
@ -133,7 +133,7 @@ static const manufactureName manufactureMapping[] = {
|
||||||
{ 0x61, "Wearlinks Technology Inc. China" },
|
{ 0x61, "Wearlinks Technology Inc. China" },
|
||||||
{ 0x62, "Userstar Information Systems Co., Ltd Taiwan" },
|
{ 0x62, "Userstar Information Systems Co., Ltd Taiwan" },
|
||||||
{ 0x63, "Pragmatic Printing Ltd. UK" },
|
{ 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" },
|
{ 0x65, "Tendyron Corporation China" },
|
||||||
{ 0x66, "MUTO Smart Co., Ltd. Korea" },
|
{ 0x66, "MUTO Smart Co., Ltd. Korea" },
|
||||||
{ 0x67, "ON Semiconductor USA" },
|
{ 0x67, "ON Semiconductor USA" },
|
||||||
|
|
|
@ -1873,7 +1873,7 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) {
|
||||||
for (int j = 0; j < 2; j++) {
|
for (int j = 0; j < 2; j++) {
|
||||||
if (e_sector[i].foundKey[j] == 1) {
|
if (e_sector[i].foundKey[j] == 1) {
|
||||||
num_to_bytes(e_sector[i].Key[j], 6, tmp_key);
|
num_to_bytes(e_sector[i].Key[j], 6, tmp_key);
|
||||||
PrintAndLogEx(SUCCESS, "Found valid key: sector:%3d key type:%c key: " _YELLOW_("%s"),
|
PrintAndLogEx(SUCCESS, "Found valid key: sector: %3d key type: %c key: " _YELLOW_("%s"),
|
||||||
i,
|
i,
|
||||||
j ? 'B' : 'A',
|
j ? 'B' : 'A',
|
||||||
sprint_hex(tmp_key, sizeof(tmp_key))
|
sprint_hex(tmp_key, sizeof(tmp_key))
|
||||||
|
@ -1983,7 +1983,50 @@ noValidKeyFound:
|
||||||
// Clear the last found key
|
// Clear the last found key
|
||||||
num_to_bytes(0, 6, tmp_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
|
// Use the nested / hardnested attack
|
||||||
|
skipReadBKey:
|
||||||
if (e_sector[current_sector_i].foundKey[current_key_type_i] == 0) {
|
if (e_sector[current_sector_i].foundKey[current_key_type_i] == 0) {
|
||||||
if (prng_type && (! nested_failed)) {
|
if (prng_type && (! nested_failed)) {
|
||||||
uint8_t retries = 0;
|
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, " 4: Reused");
|
||||||
PrintAndLogEx(INFO, " 5: Nested");
|
PrintAndLogEx(INFO, " 5: Nested");
|
||||||
PrintAndLogEx(INFO, " 6: Hardnested");
|
PrintAndLogEx(INFO, " 6: Hardnested");
|
||||||
|
PrintAndLogEx(INFO, " 7: Read B key with A key");
|
||||||
}
|
}
|
||||||
|
|
||||||
PrintAndLogEx(INFO, "\nSaving keys");
|
PrintAndLogEx(INFO, "\nSaving keys");
|
||||||
|
|
|
@ -401,11 +401,11 @@ static const struct emv_tag emv_tags[] = {
|
||||||
{ 0xdf811b, "Kernel Configuration", EMV_TAG_GENERIC, NULL },
|
{ 0xdf811b, "Kernel Configuration", EMV_TAG_GENERIC, NULL },
|
||||||
{ 0xdf811c, "Max Lifetime of Torn Transaction Log Record", 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 },
|
{ 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 },
|
{ 0xdf811f, "Security Capability", EMV_TAG_GENERIC, NULL },
|
||||||
{ 0xdf8120, "Terminal Action Code – Default", EMV_TAG_GENERIC, NULL },
|
{ 0xdf8120, "Terminal Action Code - Default", EMV_TAG_GENERIC, NULL },
|
||||||
{ 0xdf8121, "Terminal Action Code – Denial", EMV_TAG_GENERIC, NULL },
|
{ 0xdf8121, "Terminal Action Code - Denial", EMV_TAG_GENERIC, NULL },
|
||||||
{ 0xdf8122, "Terminal Action Code – Online", EMV_TAG_GENERIC, NULL },
|
{ 0xdf8122, "Terminal Action Code - Online", EMV_TAG_GENERIC, NULL },
|
||||||
{ 0xdf8123, "Reader Contactless Floor Limit", 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 },
|
{ 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 },
|
{ 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 },
|
{ 0xdf8129, "Outcome Parameter Set", EMV_TAG_GENERIC, NULL },
|
||||||
{ 0xdf812a, "DD Card (Track1)", EMV_TAG_GENERIC, NULL },
|
{ 0xdf812a, "DD Card (Track1)", EMV_TAG_GENERIC, NULL },
|
||||||
{ 0xdf812b, "DD Card (Track2)", 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 },
|
{ 0xdf812d, "Message Hold Time", EMV_TAG_GENERIC, NULL },
|
||||||
|
|
||||||
{ 0xff8101, "Torn Record", 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));
|
reverse_arraybytes(dest, sizeof(dest));
|
||||||
memcpy(mac, dest, 4);
|
memcpy(mac, dest, 4);
|
||||||
//free(cc_nr);
|
//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]) {
|
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 *address_data;
|
||||||
uint8_t div_key[8];
|
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));
|
reverse_arraybytes(dest, sizeof(dest));
|
||||||
memcpy(mac, dest, 4);
|
memcpy(mac, dest, 4);
|
||||||
free(address_data);
|
free(address_data);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef ON_DEVICE
|
#ifndef ON_DEVICE
|
||||||
|
@ -267,8 +266,8 @@ int testMAC() {
|
||||||
PrintAndLogEx(FAILED, "FAILED: MAC calculation failed:");
|
PrintAndLogEx(FAILED, "FAILED: MAC calculation failed:");
|
||||||
printarr(" Calculated_MAC", calculated_mac, 4);
|
printarr(" Calculated_MAC", calculated_mac, 4);
|
||||||
printarr(" Correct_MAC ", correct_MAC, 4);
|
printarr(" Correct_MAC ", correct_MAC, 4);
|
||||||
return 1;
|
return PM3_ESOFT;
|
||||||
}
|
}
|
||||||
return 0;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -39,6 +39,7 @@
|
||||||
#ifndef CIPHER_H
|
#ifndef CIPHER_H
|
||||||
#define CIPHER_H
|
#define CIPHER_H
|
||||||
#include <stdint.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(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]);
|
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;
|
return num;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t reversebytes(uint8_t b) {
|
uint8_t reversebytes(uint8_t b) {
|
||||||
b = (b & 0xF0) >> 4 | (b & 0x0F) << 4;
|
b = (b & 0xF0) >> 4 | (b & 0x0F) << 4;
|
||||||
b = (b & 0xCC) >> 2 | (b & 0x33) << 2;
|
b = (b & 0xCC) >> 2 | (b & 0x33) << 2;
|
||||||
b = (b & 0xAA) >> 1 | (b & 0x55) << 1;
|
b = (b & 0xAA) >> 1 | (b & 0x55) << 1;
|
||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
|
|
||||||
void reverse_arraybytes(uint8_t *arr, size_t len) {
|
void reverse_arraybytes(uint8_t *arr, size_t len) {
|
||||||
uint8_t i;
|
uint8_t i;
|
||||||
for (i = 0; i < len ; i++) {
|
for (i = 0; i < len ; i++) {
|
||||||
arr[i] = reversebytes(arr[i]);
|
arr[i] = reversebytes(arr[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void reverse_arraycopy(uint8_t *arr, uint8_t *dest, size_t len) {
|
void reverse_arraycopy(uint8_t *arr, uint8_t *dest, size_t len) {
|
||||||
uint8_t i;
|
uint8_t i;
|
||||||
for (i = 0; i < len ; i++) {
|
for (i = 0; i < len ; i++) {
|
||||||
|
@ -202,9 +205,9 @@ static int testBitStream() {
|
||||||
for (i = 0 ; i < ARRAYLEN(input) ; i++) {
|
for (i = 0 ; i < ARRAYLEN(input) ; i++) {
|
||||||
PrintAndLogEx(NORMAL, " IN %02x, OUT %02x", input[i], output[i]);
|
PrintAndLogEx(NORMAL, " IN %02x, OUT %02x", input[i], output[i]);
|
||||||
}
|
}
|
||||||
return 1;
|
return PM3_ESOFT;
|
||||||
}
|
}
|
||||||
return 0;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int testReversedBitstream() {
|
static int testReversedBitstream() {
|
||||||
|
@ -232,9 +235,9 @@ static int testReversedBitstream() {
|
||||||
for (i = 0 ; i < ARRAYLEN(input) ; i++) {
|
for (i = 0 ; i < ARRAYLEN(input) ; i++) {
|
||||||
PrintAndLogEx(NORMAL, " IN %02x, MIDDLE: %02x, OUT %02x", input[i], reverse[i], output[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 <stdint.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include "pm3_cmd.h"
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8_t *buffer;
|
uint8_t *buffer;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue