mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-20 21:33:47 -07:00
Make style
This commit is contained in:
parent
7af0f07c4e
commit
82323b14e2
7 changed files with 1859 additions and 295 deletions
|
@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file.
|
|||
This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log...
|
||||
|
||||
## [unreleased][unreleased]
|
||||
- Updated 'legic.lua' and 'legic_clone.lua' script - works with current command set (@Pizza_4u)
|
||||
- Rewrote `hf mfdes` functions and added apdu debugging (@bkerler)
|
||||
- Add Mifare Desfire GetDFNames and improve HF MFDES Enum output (@bkerler)
|
||||
- Fix Mifare Desfire select appid handling (@bkerler)
|
||||
|
|
|
@ -104,7 +104,7 @@ void MifareDesfireGetInformation() {
|
|||
uint8_t versionSW[7];
|
||||
uint8_t details[14];
|
||||
} PACKED payload;
|
||||
|
||||
|
||||
/*
|
||||
1 = PCB 1
|
||||
2 = cid 2
|
||||
|
@ -179,7 +179,7 @@ void MifareDesfireGetInformation() {
|
|||
LED_B_ON();
|
||||
reply_ng(CMD_HF_DESFIRE_INFO, PM3_SUCCESS, (uint8_t *)&payload, sizeof(payload));
|
||||
LED_B_OFF();
|
||||
|
||||
|
||||
// reset the pcb_blocknum,
|
||||
pcb_blocknum = 0;
|
||||
OnSuccess();
|
||||
|
@ -314,8 +314,8 @@ void MifareDES_Auth1(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
|
|||
cmd[3] = 0x00;
|
||||
cmd[4] = 0x10;
|
||||
memcpy(cmd + 5, both, 16);
|
||||
cmd[16+5]=0x0;
|
||||
len = DesfireAPDU(cmd, 5+16+1, resp);
|
||||
cmd[16 + 5] = 0x0;
|
||||
len = DesfireAPDU(cmd, 5 + 16 + 1, resp);
|
||||
if (!len) {
|
||||
if (DBGLEVEL >= DBG_ERROR) {
|
||||
DbpString("Authentication failed. Card timeout.");
|
||||
|
@ -324,7 +324,7 @@ void MifareDES_Auth1(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
|
|||
return;
|
||||
}
|
||||
|
||||
if (resp[len-3] == 0x00) {
|
||||
if (resp[len - 3] == 0x00) {
|
||||
|
||||
struct desfire_key sessionKey = {0};
|
||||
desfirekey_t skey = &sessionKey;
|
||||
|
@ -450,8 +450,7 @@ void MifareDES_Auth1(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
|
|||
}
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
{
|
||||
case 2: {
|
||||
//SendDesfireCommand(AUTHENTICATE_ISO, &arg2, resp);
|
||||
uint8_t keybytes[16];
|
||||
uint8_t RndA[8] = {0x00};
|
||||
|
@ -540,7 +539,7 @@ void MifareDES_Auth1(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
|
|||
|
||||
cmd[0] = ADDITIONAL_FRAME;
|
||||
memcpy(cmd + 1, both, 16);
|
||||
len = DesfireAPDU(cmd, 1+16, resp);
|
||||
len = DesfireAPDU(cmd, 1 + 16, resp);
|
||||
if (!len) {
|
||||
if (DBGLEVEL >= DBG_ERROR) {
|
||||
DbpString("Authentication failed. Card timeout.");
|
||||
|
@ -580,9 +579,9 @@ void MifareDES_Auth1(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
|
|||
DbpString("Authentication failed.");
|
||||
OnError(6);
|
||||
return;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 3: {
|
||||
//defaultkey
|
||||
uint8_t keybytes[16] = {0x00};
|
||||
|
@ -655,9 +654,9 @@ void MifareDES_Auth1(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
|
|||
cmd[3] = 0x00;
|
||||
cmd[4] = 0x20;
|
||||
memcpy(cmd + 5, encBoth, 32);
|
||||
cmd[32+5]=0x0;
|
||||
cmd[32 + 5] = 0x0;
|
||||
|
||||
len = DesfireAPDU(cmd, 5+32+1, resp);
|
||||
len = DesfireAPDU(cmd, 5 + 32 + 1, resp);
|
||||
if (!len) {
|
||||
if (DBGLEVEL >= DBG_ERROR) {
|
||||
DbpString("Authentication failed. Card timeout.");
|
||||
|
@ -666,7 +665,7 @@ void MifareDES_Auth1(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
|
|||
return;
|
||||
}
|
||||
|
||||
if ((resp[1+16] == 0x91)&&(resp[1+16+1] == 0x00)) {
|
||||
if ((resp[1 + 16] == 0x91) && (resp[1 + 16 + 1] == 0x00)) {
|
||||
// Create AES Session key
|
||||
struct desfire_key sessionKey = {0};
|
||||
desfirekey_t skey = &sessionKey;
|
||||
|
@ -713,10 +712,10 @@ int DesfireAPDU(uint8_t *cmd, size_t cmd_len, uint8_t *dataout) {
|
|||
// if we received an I- or R(ACK)-Block with a block number equal to the
|
||||
// current block number, toggle the current block number
|
||||
if (len >= 4 // PCB+CID+CRC = 4 bytes
|
||||
&& ((resp[0] & 0xC0) == 0 // I-Block
|
||||
|| (resp[0] & 0xD0) == 0x80) // R-Block with ACK bit set to 0
|
||||
&& (resp[0] & 0x01) == pcb_blocknum) { // equal block numbers
|
||||
pcb_blocknum ^= 1; //toggle next block
|
||||
&& ((resp[0] & 0xC0) == 0 // I-Block
|
||||
|| (resp[0] & 0xD0) == 0x80) // R-Block with ACK bit set to 0
|
||||
&& (resp[0] & 0x01) == pcb_blocknum) { // equal block numbers
|
||||
pcb_blocknum ^= 1; //toggle next block
|
||||
}
|
||||
|
||||
memcpy(dataout, resp, len);
|
||||
|
@ -734,18 +733,18 @@ size_t CreateAPDU(uint8_t *datain, size_t len, uint8_t *dataout) {
|
|||
cmd[0] = 0x02; // 0x0A = send cid, 0x02 = no cid.
|
||||
cmd[0] |= pcb_blocknum; // OR the block number into the PCB
|
||||
|
||||
if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("pcb_blocknum %d == %d ", pcb_blocknum, cmd[0] );
|
||||
if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("pcb_blocknum %d == %d ", pcb_blocknum, cmd[0]);
|
||||
|
||||
//cmd[1] = 0x90; // CID: 0x00 //TODO: allow multiple selected cards
|
||||
|
||||
memcpy(cmd + 1, datain, len);
|
||||
AddCrc14A(cmd, len + 1);
|
||||
|
||||
/*
|
||||
hf 14a apdu -sk 90 60 00 00 00
|
||||
hf 14a apdu -k 90 AF 00 00 00
|
||||
hf 14a apdu 90AF000000
|
||||
*/
|
||||
|
||||
/*
|
||||
hf 14a apdu -sk 90 60 00 00 00
|
||||
hf 14a apdu -k 90 AF 00 00 00
|
||||
hf 14a apdu 90AF000000
|
||||
*/
|
||||
memcpy(dataout, cmd, cmdlen);
|
||||
return cmdlen;
|
||||
}
|
||||
|
|
|
@ -675,7 +675,7 @@ void annotateMfDesfire(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize) {
|
|||
|
||||
// it's basically a ISO14443a tag, so try annotation from there
|
||||
if (applyIso14443a(exp, size, cmd, cmdsize) == 0) {
|
||||
|
||||
|
||||
// S-block 11xxx010
|
||||
if ((cmd[0] & 0xC0) && (cmdsize == 3)) {
|
||||
switch ((cmd[0] & 0x30)) {
|
||||
|
@ -707,9 +707,9 @@ void annotateMfDesfire(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize) {
|
|||
|
||||
if ((cmd[0] & 0x04) == 0x04) // nad byte following
|
||||
pos++;
|
||||
|
||||
|
||||
for (uint8_t i = 0; i < 2; i++, pos++) {
|
||||
|
||||
|
||||
switch (cmd[pos]) {
|
||||
case MFDES_CREATE_APPLICATION:
|
||||
snprintf(exp, size, "CREATE APPLICATION");
|
||||
|
|
|
@ -64,6 +64,7 @@ static int CmdHelp(const char *Cmd);
|
|||
*/
|
||||
|
||||
int DESFIRESendApdu(bool activate_field, bool leavefield_on, sAPDU apdu, uint8_t *result, int max_result_len, int *result_len, uint16_t *sw) {
|
||||
|
||||
*result_len = 0;
|
||||
if (sw) *sw = 0;
|
||||
|
||||
|
@ -120,11 +121,10 @@ int DESFIRESendApdu(bool activate_field, bool leavefield_on, sAPDU apdu, uint8_t
|
|||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static char* getstatus(uint16_t * sw)
|
||||
{
|
||||
if (sw==NULL) return "--> sw argument error. This should never happen !";
|
||||
if (((*sw>>8)&0xFF)==0x91){
|
||||
switch (*sw&0xFF){
|
||||
static char *getstatus(uint16_t *sw) {
|
||||
if (sw == NULL) return "--> sw argument error. This should never happen !";
|
||||
if (((*sw >> 8) & 0xFF) == 0x91) {
|
||||
switch (*sw & 0xFF) {
|
||||
case MFDES_E_OUT_OF_EEPROM:
|
||||
return "Out of Eeprom, insufficient NV-Memory to complete command";
|
||||
case MFDES_E_ILLEGAL_COMMAND_CODE:
|
||||
|
@ -188,9 +188,8 @@ static char* getstatus(uint16_t * sw)
|
|||
return "Unknown error";
|
||||
}
|
||||
|
||||
static char* GetErrorString(int res,uint16_t* sw)
|
||||
{
|
||||
switch(res){
|
||||
static char *GetErrorString(int res, uint16_t *sw) {
|
||||
switch (res) {
|
||||
case PM3_EAPDU_FAIL:
|
||||
return getstatus(sw);
|
||||
case PM3_EUNDEF:
|
||||
|
@ -242,15 +241,14 @@ static char* GetErrorString(int res,uint16_t* sw)
|
|||
}
|
||||
|
||||
|
||||
static int send_desfire_cmd(sAPDU *apdu, bool select, uint8_t *dest, int *recv_len, uint16_t *sw, int splitbysize,bool readalldata) {
|
||||
if (g_debugMode>1)
|
||||
{
|
||||
if (apdu==NULL) PrintAndLogEx(ERR, "APDU=NULL");
|
||||
if (dest==NULL) PrintAndLogEx(ERR, "DEST=NULL");
|
||||
if (sw==NULL) PrintAndLogEx(ERR, "SW=NULL");
|
||||
if (recv_len==NULL) PrintAndLogEx(ERR, "RECV_LEN=NULL");
|
||||
static int send_desfire_cmd(sAPDU *apdu, bool select, uint8_t *dest, int *recv_len, uint16_t *sw, int splitbysize, bool readalldata) {
|
||||
if (g_debugMode > 1) {
|
||||
if (apdu == NULL) PrintAndLogEx(ERR, "APDU=NULL");
|
||||
if (dest == NULL) PrintAndLogEx(ERR, "DEST=NULL");
|
||||
if (sw == NULL) PrintAndLogEx(ERR, "SW=NULL");
|
||||
if (recv_len == NULL) PrintAndLogEx(ERR, "RECV_LEN=NULL");
|
||||
}
|
||||
if (apdu==NULL || sw==NULL || recv_len==NULL) return PM3_EINVARG;
|
||||
if (apdu == NULL || sw == NULL || recv_len == NULL) return PM3_EINVARG;
|
||||
|
||||
*sw = 0;
|
||||
uint8_t data[255 * 5] = {0x00};
|
||||
|
@ -259,7 +257,7 @@ static int send_desfire_cmd(sAPDU *apdu, bool select, uint8_t *dest, int *recv_l
|
|||
int i = 1;
|
||||
int res = DESFIRESendApdu(select, true, *apdu, data, sizeof(data), &resplen, sw);
|
||||
if (res != PM3_SUCCESS) {
|
||||
if (g_debugMode>1) GetErrorString(res,sw);
|
||||
if (g_debugMode > 1) GetErrorString(res, sw);
|
||||
return res;
|
||||
}
|
||||
if (dest != NULL) {
|
||||
|
@ -267,9 +265,8 @@ static int send_desfire_cmd(sAPDU *apdu, bool select, uint8_t *dest, int *recv_l
|
|||
}
|
||||
|
||||
pos += resplen;
|
||||
if (!readalldata)
|
||||
{
|
||||
if (*sw==status(MFDES_ADDITIONAL_FRAME)) {
|
||||
if (!readalldata) {
|
||||
if (*sw == status(MFDES_ADDITIONAL_FRAME)) {
|
||||
apdu->INS = MFDES_ABORT_TRANSACTION;
|
||||
apdu->Lc = 0;
|
||||
apdu->P1 = 0;
|
||||
|
@ -281,13 +278,13 @@ static int send_desfire_cmd(sAPDU *apdu, bool select, uint8_t *dest, int *recv_l
|
|||
}
|
||||
while (*sw == status(MFDES_ADDITIONAL_FRAME)) {
|
||||
apdu->INS = MFDES_ADDITIONAL_FRAME; //0xAF
|
||||
apdu->Lc=0;
|
||||
apdu->P1=0;
|
||||
apdu->P2=0;
|
||||
apdu->Lc = 0;
|
||||
apdu->P1 = 0;
|
||||
apdu->P2 = 0;
|
||||
|
||||
res = DESFIRESendApdu(false, true, *apdu, data, sizeof(data), &resplen, sw);
|
||||
if (res != PM3_SUCCESS){
|
||||
if (g_debugMode>1) GetErrorString(res,sw);
|
||||
if (res != PM3_SUCCESS) {
|
||||
if (g_debugMode > 1) GetErrorString(res, sw);
|
||||
return res;
|
||||
}
|
||||
if (dest != NULL) {
|
||||
|
@ -299,7 +296,7 @@ static int send_desfire_cmd(sAPDU *apdu, bool select, uint8_t *dest, int *recv_l
|
|||
}
|
||||
}
|
||||
pos += resplen;
|
||||
if (*sw!=status(MFDES_ADDITIONAL_FRAME)) break;
|
||||
if (*sw != status(MFDES_ADDITIONAL_FRAME)) break;
|
||||
}
|
||||
if (splitbysize) *recv_len = i;
|
||||
else {
|
||||
|
@ -327,29 +324,29 @@ static desfire_cardtype_t getCardType(uint8_t major, uint8_t minor) {
|
|||
|
||||
//none, verified
|
||||
static int test_desfire_authenticate() {
|
||||
uint8_t c = 0x00;
|
||||
sAPDU apdu = {0x90, MFDES_AUTHENTICATE, 0x00, 0x00, 0x01, &c}; // 0x0A, KEY 0
|
||||
uint8_t data[] = {0x00};
|
||||
sAPDU apdu = {0x90, MFDES_AUTHENTICATE, 0x00, 0x00, 0x01, data}; // 0x0A, KEY 0
|
||||
int recv_len = 0;
|
||||
uint16_t sw = 0;
|
||||
return send_desfire_cmd(&apdu, false, NULL, &recv_len, &sw, 0,false);
|
||||
return send_desfire_cmd(&apdu, false, NULL, &recv_len, &sw, 0, false);
|
||||
}
|
||||
|
||||
// none, verified
|
||||
static int test_desfire_authenticate_iso() {
|
||||
uint8_t c = 0x00;
|
||||
sAPDU apdu = {0x90, MFDES_AUTHENTICATE_ISO, 0x00, 0x00, 0x01, &c}; // 0x1A, KEY 0
|
||||
uint8_t data[] = {0x00};
|
||||
sAPDU apdu = {0x90, MFDES_AUTHENTICATE_ISO, 0x00, 0x00, 0x01, data}; // 0x1A, KEY 0
|
||||
int recv_len = 0;
|
||||
uint16_t sw = 0;
|
||||
return send_desfire_cmd(&apdu, false, NULL, &recv_len, &sw, 0,false);
|
||||
return send_desfire_cmd(&apdu, false, NULL, &recv_len, &sw, 0, false);
|
||||
}
|
||||
|
||||
//none, verified
|
||||
static int test_desfire_authenticate_aes() {
|
||||
uint8_t c = 0x00;
|
||||
sAPDU apdu = {0x90, MFDES_AUTHENTICATE_AES, 0x00, 0x00, 0x01, &c}; // 0xAA, KEY 0
|
||||
uint8_t data[] = {0x00};
|
||||
sAPDU apdu = {0x90, MFDES_AUTHENTICATE_AES, 0x00, 0x00, 0x01, data}; // 0xAA, KEY 0
|
||||
int recv_len = 0;
|
||||
uint16_t sw = 0;
|
||||
return send_desfire_cmd(&apdu, false, NULL, &recv_len, &sw, 0,false);
|
||||
return send_desfire_cmd(&apdu, false, NULL, &recv_len, &sw, 0, false);
|
||||
}
|
||||
|
||||
// --- FREE MEM, verified
|
||||
|
@ -360,13 +357,13 @@ static int desfire_print_freemem(uint32_t free_mem) {
|
|||
|
||||
// init / disconnect, verified
|
||||
static int get_desfire_freemem(uint32_t *free_mem) {
|
||||
if (free_mem==NULL) return PM3_EINVARG;
|
||||
if (free_mem == NULL) return PM3_EINVARG;
|
||||
sAPDU apdu = {0x90, MFDES_GET_FREE_MEMORY, 0x00, 0x00, 0x00, NULL}; // 0x6E
|
||||
int recv_len = 0;
|
||||
uint16_t sw = 0;
|
||||
uint8_t fmem[4] = {0};
|
||||
|
||||
int res = send_desfire_cmd(&apdu, true, fmem, &recv_len, &sw, 0,true);
|
||||
int res = send_desfire_cmd(&apdu, true, fmem, &recv_len, &sw, 0, true);
|
||||
if (res == PM3_SUCCESS) {
|
||||
*free_mem = le24toh(fmem);
|
||||
return res;
|
||||
|
@ -378,12 +375,11 @@ static int get_desfire_freemem(uint32_t *free_mem) {
|
|||
|
||||
// --- GET SIGNATURE, verified
|
||||
static int desfire_print_signature(uint8_t *uid, uint8_t *signature, size_t signature_len, desfire_cardtype_t card_type) {
|
||||
if (g_debugMode>1)
|
||||
{
|
||||
if (uid==NULL) PrintAndLogEx(ERR, "UID=NULL");
|
||||
if (signature==NULL) PrintAndLogEx(ERR, "SIGNATURE=NULL");
|
||||
if (g_debugMode > 1) {
|
||||
if (uid == NULL) PrintAndLogEx(ERR, "UID=NULL");
|
||||
if (signature == NULL) PrintAndLogEx(ERR, "SIGNATURE=NULL");
|
||||
}
|
||||
if (uid==NULL || signature==NULL) return PM3_EINVARG;
|
||||
if (uid == NULL || signature == NULL) return PM3_EINVARG;
|
||||
// DESFire Ev3 - wanted
|
||||
// ref: MIFARE Desfire Originality Signature Validation
|
||||
|
||||
|
@ -435,17 +431,16 @@ static int desfire_print_signature(uint8_t *uid, uint8_t *signature, size_t sign
|
|||
|
||||
// init / disconnect, verified
|
||||
static int get_desfire_signature(uint8_t *signature, size_t *signature_len) {
|
||||
if (g_debugMode>1)
|
||||
{
|
||||
if (signature==NULL) PrintAndLogEx(ERR, "SIGNATURE=NULL");
|
||||
if (signature_len==NULL) PrintAndLogEx(ERR, "SIGNATURE_LEN=NULL");
|
||||
if (g_debugMode > 1) {
|
||||
if (signature == NULL) PrintAndLogEx(ERR, "SIGNATURE=NULL");
|
||||
if (signature_len == NULL) PrintAndLogEx(ERR, "SIGNATURE_LEN=NULL");
|
||||
}
|
||||
if (signature==NULL || signature_len==NULL) return PM3_EINVARG;
|
||||
if (signature == NULL || signature_len == NULL) return PM3_EINVARG;
|
||||
uint8_t c = 0x00;
|
||||
sAPDU apdu = {0x90, MFDES_READSIG, 0x00, 0x00, 0x01, &c}; // 0x3C
|
||||
int recv_len = 0;
|
||||
uint16_t sw = 0;
|
||||
int res = send_desfire_cmd(&apdu, true, signature, &recv_len, &sw, 0,true);
|
||||
int res = send_desfire_cmd(&apdu, true, signature, &recv_len, &sw, 0, true);
|
||||
if (res == PM3_SUCCESS) {
|
||||
if (recv_len != 56) {
|
||||
*signature_len = 0;
|
||||
|
@ -497,17 +492,16 @@ static int desfire_print_keysetting(uint8_t key_settings, uint8_t num_keys) {
|
|||
|
||||
// none, verified
|
||||
static int get_desfire_keysettings(uint8_t *key_settings, uint8_t *num_keys) {
|
||||
if (g_debugMode>1)
|
||||
{
|
||||
if (key_settings==NULL) PrintAndLogEx(ERR, "KEY_SETTINGS=NULL");
|
||||
if (num_keys==NULL) PrintAndLogEx(ERR, "NUM_KEYS=NULL");
|
||||
if (g_debugMode > 1) {
|
||||
if (key_settings == NULL) PrintAndLogEx(ERR, "KEY_SETTINGS=NULL");
|
||||
if (num_keys == NULL) PrintAndLogEx(ERR, "NUM_KEYS=NULL");
|
||||
}
|
||||
if (key_settings==NULL || num_keys==NULL) return PM3_EINVARG;
|
||||
if (key_settings == NULL || num_keys == NULL) return PM3_EINVARG;
|
||||
sAPDU apdu = {0x90, MFDES_GET_KEY_SETTINGS, 0x00, 0x00, 0x00, NULL}; //0x45
|
||||
int recv_len = 0;
|
||||
uint16_t sw = 0;
|
||||
uint8_t data[2] = {0};
|
||||
int res = send_desfire_cmd(&apdu, false, data, &recv_len, &sw, 0,true);
|
||||
int res = send_desfire_cmd(&apdu, false, data, &recv_len, &sw, 0, true);
|
||||
if (res != PM3_SUCCESS) return res;
|
||||
|
||||
*key_settings = data[0];
|
||||
|
@ -523,31 +517,29 @@ static int desfire_print_keyversion(uint8_t key_idx, uint8_t key_version) {
|
|||
|
||||
// none, verified
|
||||
static int get_desfire_keyversion(uint8_t curr_key, uint8_t *num_versions) {
|
||||
if (g_debugMode>1)
|
||||
{
|
||||
if (num_versions==NULL) PrintAndLogEx(ERR, "NUM_VERSIONS=NULL");
|
||||
if (g_debugMode > 1) {
|
||||
if (num_versions == NULL) PrintAndLogEx(ERR, "NUM_VERSIONS=NULL");
|
||||
}
|
||||
if (num_versions==NULL) return PM3_EINVARG;
|
||||
if (num_versions == NULL) return PM3_EINVARG;
|
||||
sAPDU apdu = {0x90, MFDES_GET_KEY_VERSION, 0x00, 0x00, 0x01, &curr_key}; //0x64
|
||||
int recv_len = 0;
|
||||
uint16_t sw = 0;
|
||||
int res = send_desfire_cmd(&apdu, false, num_versions, &recv_len, &sw, 0,true);
|
||||
int res = send_desfire_cmd(&apdu, false, num_versions, &recv_len, &sw, 0, true);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
// init / disconnect, verified
|
||||
static int get_desfire_appids(uint8_t *dest, uint8_t *app_ids_len) {
|
||||
if (g_debugMode>1)
|
||||
{
|
||||
if (dest==NULL) PrintAndLogEx(ERR, "DEST=NULL");
|
||||
if (app_ids_len==NULL) PrintAndLogEx(ERR, "APP_IDS_LEN=NULL");
|
||||
if (g_debugMode > 1) {
|
||||
if (dest == NULL) PrintAndLogEx(ERR, "DEST=NULL");
|
||||
if (app_ids_len == NULL) PrintAndLogEx(ERR, "APP_IDS_LEN=NULL");
|
||||
}
|
||||
if (dest==NULL || app_ids_len==NULL) return PM3_EINVARG;
|
||||
if (dest == NULL || app_ids_len == NULL) return PM3_EINVARG;
|
||||
sAPDU apdu = {0x90, MFDES_GET_APPLICATION_IDS, 0x00, 0x00, 0x00, NULL}; //0x6a
|
||||
int recv_len = 0;
|
||||
uint16_t sw = 0;
|
||||
int res = send_desfire_cmd(&apdu, true, dest, &recv_len, &sw, 0,true);
|
||||
int res = send_desfire_cmd(&apdu, true, dest, &recv_len, &sw, 0, true);
|
||||
if (res != PM3_SUCCESS) return res;
|
||||
*app_ids_len = (uint8_t)recv_len & 0xFF;
|
||||
return res;
|
||||
|
@ -555,16 +547,15 @@ static int get_desfire_appids(uint8_t *dest, uint8_t *app_ids_len) {
|
|||
|
||||
// init, verified
|
||||
static int get_desfire_dfnames(dfname_t *dest, uint8_t *dfname_count) {
|
||||
if (g_debugMode>1)
|
||||
{
|
||||
if (dest==NULL) PrintAndLogEx(ERR, "DEST=NULL");
|
||||
if (dfname_count==NULL) PrintAndLogEx(ERR, "DFNAME_COUNT=NULL");
|
||||
if (g_debugMode > 1) {
|
||||
if (dest == NULL) PrintAndLogEx(ERR, "DEST=NULL");
|
||||
if (dfname_count == NULL) PrintAndLogEx(ERR, "DFNAME_COUNT=NULL");
|
||||
}
|
||||
if (dest==NULL || dfname_count==NULL) return PM3_EINVARG;
|
||||
if (dest == NULL || dfname_count == NULL) return PM3_EINVARG;
|
||||
sAPDU apdu = {0x90, MFDES_GET_DF_NAMES, 0x00, 0x00, 0x00, NULL}; //0x6d
|
||||
int recv_len = 0;
|
||||
uint16_t sw = 0;
|
||||
int res = send_desfire_cmd(&apdu, true, (uint8_t *)dest, &recv_len, &sw, sizeof(dfname_t),true);
|
||||
int res = send_desfire_cmd(&apdu, true, (uint8_t *)dest, &recv_len, &sw, sizeof(dfname_t), true);
|
||||
if (res != PM3_SUCCESS) return res;
|
||||
*dfname_count = recv_len;
|
||||
return res;
|
||||
|
@ -573,17 +564,16 @@ static int get_desfire_dfnames(dfname_t *dest, uint8_t *dfname_count) {
|
|||
|
||||
// init, verified
|
||||
static int get_desfire_select_application(uint8_t *aid) {
|
||||
if (g_debugMode>1)
|
||||
{
|
||||
if (aid==NULL) PrintAndLogEx(ERR, "AID=NULL");
|
||||
if (g_debugMode > 1) {
|
||||
if (aid == NULL) PrintAndLogEx(ERR, "AID=NULL");
|
||||
}
|
||||
if (aid==NULL) return PM3_EINVARG;
|
||||
if (aid == NULL) return PM3_EINVARG;
|
||||
sAPDU apdu = {0x90, MFDES_SELECT_APPLICATION, 0x00, 0x00, 0x03, aid}; //0x5a
|
||||
int recv_len = 0;
|
||||
uint16_t sw = 0;
|
||||
int res=send_desfire_cmd(&apdu, true, NULL, &recv_len, &sw, sizeof(dfname_t),true);
|
||||
int res = send_desfire_cmd(&apdu, true, NULL, &recv_len, &sw, sizeof(dfname_t), true);
|
||||
if (res != PM3_SUCCESS) {
|
||||
PrintAndLogEx(WARNING, _RED_(" Can't select AID 0x%X -> %s"),(aid[0]<<16)+(aid[1]<<8)+aid[2],GetErrorString(res,&sw));
|
||||
PrintAndLogEx(WARNING, _RED_(" Can't select AID 0x%X -> %s"), (aid[0] << 16) + (aid[1] << 8) + aid[2], GetErrorString(res, &sw));
|
||||
DropField();
|
||||
return res;
|
||||
}
|
||||
|
@ -592,19 +582,18 @@ static int get_desfire_select_application(uint8_t *aid) {
|
|||
|
||||
// none, verified
|
||||
static int get_desfire_fileids(uint8_t *dest, uint8_t *file_ids_len) {
|
||||
if (g_debugMode>1)
|
||||
{
|
||||
if (dest==NULL) PrintAndLogEx(ERR, "DEST=NULL");
|
||||
if (file_ids_len==NULL) PrintAndLogEx(ERR, "FILE_IDS_LEN=NULL");
|
||||
if (g_debugMode > 1) {
|
||||
if (dest == NULL) PrintAndLogEx(ERR, "DEST=NULL");
|
||||
if (file_ids_len == NULL) PrintAndLogEx(ERR, "FILE_IDS_LEN=NULL");
|
||||
}
|
||||
if (dest==NULL || file_ids_len==NULL) return PM3_EINVARG;
|
||||
if (dest == NULL || file_ids_len == NULL) return PM3_EINVARG;
|
||||
sAPDU apdu = {0x90, MFDES_GET_FILE_IDS, 0x00, 0x00, 0x00, NULL}; //0x6f
|
||||
int recv_len = 0;
|
||||
uint16_t sw = 0;
|
||||
*file_ids_len = 0;
|
||||
int res = send_desfire_cmd(&apdu, false, dest, &recv_len, &sw, 0,true);
|
||||
int res = send_desfire_cmd(&apdu, false, dest, &recv_len, &sw, 0, true);
|
||||
if (res != PM3_SUCCESS) {
|
||||
PrintAndLogEx(WARNING, _RED_(" Can't get file ids -> %s"),GetErrorString(res,&sw));
|
||||
PrintAndLogEx(WARNING, _RED_(" Can't get file ids -> %s"), GetErrorString(res, &sw));
|
||||
DropField();
|
||||
return res;
|
||||
}
|
||||
|
@ -614,17 +603,16 @@ static int get_desfire_fileids(uint8_t *dest, uint8_t *file_ids_len) {
|
|||
|
||||
// none, verified
|
||||
static int get_desfire_filesettings(uint8_t file_id, uint8_t *dest, int *destlen) {
|
||||
if (g_debugMode>1)
|
||||
{
|
||||
if (dest==NULL) PrintAndLogEx(ERR, "DEST=NULL");
|
||||
if (destlen==NULL) PrintAndLogEx(ERR, "DESTLEN=NULL");
|
||||
if (g_debugMode > 1) {
|
||||
if (dest == NULL) PrintAndLogEx(ERR, "DEST=NULL");
|
||||
if (destlen == NULL) PrintAndLogEx(ERR, "DESTLEN=NULL");
|
||||
}
|
||||
if (dest==NULL || destlen==NULL) return PM3_EINVARG;
|
||||
if (dest == NULL || destlen == NULL) return PM3_EINVARG;
|
||||
sAPDU apdu = {0x90, MFDES_GET_FILE_SETTINGS, 0x00, 0x00, 0x01, &file_id}; // 0xF5
|
||||
uint16_t sw = 0;
|
||||
int res=send_desfire_cmd(&apdu, false, dest, destlen, &sw, 0,true);
|
||||
int res = send_desfire_cmd(&apdu, false, dest, destlen, &sw, 0, true);
|
||||
if (res != PM3_SUCCESS) {
|
||||
PrintAndLogEx(WARNING, _RED_(" Can't get file settings -> %s"),GetErrorString(res,&sw));
|
||||
PrintAndLogEx(WARNING, _RED_(" Can't get file settings -> %s"), GetErrorString(res, &sw));
|
||||
DropField();
|
||||
return res;
|
||||
}
|
||||
|
@ -639,28 +627,28 @@ typedef struct {
|
|||
uint8_t name[16];
|
||||
} aidhdr_t;
|
||||
|
||||
static int get_desfire_createapp(aidhdr_t* aidhdr) {
|
||||
if (aidhdr==NULL) return PM3_EINVARG;
|
||||
sAPDU apdu = {0x90, MFDES_CREATE_APPLICATION, 0x00, 0x00, sizeof(aidhdr_t), (uint8_t*)aidhdr}; // 0xCA
|
||||
static int get_desfire_createapp(aidhdr_t *aidhdr) {
|
||||
if (aidhdr == NULL) return PM3_EINVARG;
|
||||
sAPDU apdu = {0x90, MFDES_CREATE_APPLICATION, 0x00, 0x00, sizeof(aidhdr_t), (uint8_t *)aidhdr}; // 0xCA
|
||||
uint16_t sw = 0;
|
||||
int recvlen=0;
|
||||
int res=send_desfire_cmd(&apdu, false, NONE, &recvlen, &sw, 0,true);
|
||||
int recvlen = 0;
|
||||
int res = send_desfire_cmd(&apdu, false, NONE, &recvlen, &sw, 0, true);
|
||||
if (res != PM3_SUCCESS) {
|
||||
PrintAndLogEx(WARNING, _RED_(" Can't create aid -> %s"),GetErrorString(res,&sw));
|
||||
PrintAndLogEx(WARNING, _RED_(" Can't create aid -> %s"), GetErrorString(res, &sw));
|
||||
DropField();
|
||||
return res;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static int get_desfire_deleteapp(uint8_t* aid) {
|
||||
if (aid==NULL) return PM3_EINVARG;
|
||||
static int get_desfire_deleteapp(uint8_t *aid) {
|
||||
if (aid == NULL) return PM3_EINVARG;
|
||||
sAPDU apdu = {0x90, MFDES_DELETE_APPLICATION, 0x00, 0x00, 3, aid}; // 0xDA
|
||||
uint16_t sw = 0;
|
||||
int recvlen=0;
|
||||
int res=send_desfire_cmd(&apdu, false, NONE, &recvlen, &sw, 0,true);
|
||||
int recvlen = 0;
|
||||
int res = send_desfire_cmd(&apdu, false, NONE, &recvlen, &sw, 0, true);
|
||||
if (res != PM3_SUCCESS) {
|
||||
PrintAndLogEx(WARNING, _RED_(" Can't delete aid -> %s"),GetErrorString(res,&sw));
|
||||
PrintAndLogEx(WARNING, _RED_(" Can't delete aid -> %s"), GetErrorString(res, &sw));
|
||||
DropField();
|
||||
return res;
|
||||
}
|
||||
|
@ -674,16 +662,16 @@ static int CmdHF14ADesCreateApp(const char *Cmd) {
|
|||
"Create Application ID",
|
||||
"Usage:\n\t-m Auth type (1=normal, 2=iso, 3=aes)\n\t-t Crypt algo (1=DES, 2=3DES, 3=3K3DES, 4=aes)\n\t-a aid (3 bytes)\n\t-n keyno\n\t-k key (8-24 bytes)\n\n"
|
||||
"Example:\n\thf mfdes createaid -a 123456 -f 1122 -k 0F -l 2E -n AppName\n"
|
||||
);
|
||||
);
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_strx0("aA", "aid", "<aid>", "App ID to create"),
|
||||
arg_strx0("fF", "fid", "<fid>", "File ID"),
|
||||
arg_strx0("kK", "keysetting1", "<keysetting1>", "Key Setting 1 (Application Master Key Settings)"),
|
||||
arg_strx0("lL", "keysetting2", "<keysetting2>", "Key Setting 2"),
|
||||
arg_str0("nN", "name", "<name>", "App ISO-4 Name"),
|
||||
arg_param_end
|
||||
arg_param_begin,
|
||||
arg_strx0("aA", "aid", "<aid>", "App ID to create"),
|
||||
arg_strx0("fF", "fid", "<fid>", "File ID"),
|
||||
arg_strx0("kK", "keysetting1", "<keysetting1>", "Key Setting 1 (Application Master Key Settings)"),
|
||||
arg_strx0("lL", "keysetting2", "<keysetting2>", "Key Setting 2"),
|
||||
arg_str0("nN", "name", "<name>", "App ISO-4 Name"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(Cmd, argtable, true);
|
||||
/* KeySetting 1 (AMK Setting):
|
||||
|
@ -719,11 +707,11 @@ static int CmdHF14ADesCreateApp(const char *Cmd) {
|
|||
uint8_t aid[3] = {0};
|
||||
uint8_t fid[2] = {0};
|
||||
uint8_t name[16] = {0};
|
||||
uint8_t keysetting1=0;
|
||||
uint8_t keysetting2=0;
|
||||
int keylen1=1;
|
||||
int keylen2=1;
|
||||
int namelen=16;
|
||||
uint8_t keysetting1 = 0;
|
||||
uint8_t keysetting2 = 0;
|
||||
int keylen1 = 1;
|
||||
int keylen2 = 1;
|
||||
int namelen = 16;
|
||||
CLIGetHexWithReturn(1, aid, &aidlength);
|
||||
CLIGetHexWithReturn(2, fid, &fidlength);
|
||||
CLIGetHexWithReturn(3, &keysetting1, &keylen1);
|
||||
|
@ -769,15 +757,15 @@ static int CmdHF14ADesCreateApp(const char *Cmd) {
|
|||
}
|
||||
|
||||
aidhdr_t aidhdr;
|
||||
memcpy(aidhdr.aid,aid,sizeof(aid));
|
||||
aidhdr.keysetting1=keysetting1;
|
||||
aidhdr.keysetting2=keysetting2;
|
||||
memcpy(aidhdr.fid,fid,sizeof(fid));
|
||||
memcpy(aidhdr.name,name,sizeof(name));
|
||||
memcpy(aidhdr.aid, aid, sizeof(aid));
|
||||
aidhdr.keysetting1 = keysetting1;
|
||||
aidhdr.keysetting2 = keysetting2;
|
||||
memcpy(aidhdr.fid, fid, sizeof(fid));
|
||||
memcpy(aidhdr.name, name, sizeof(name));
|
||||
|
||||
uint8_t rootaid[3]={0x00,0x00,0x00};
|
||||
int res=get_desfire_select_application(rootaid);
|
||||
if (res!=PM3_SUCCESS) return res;
|
||||
uint8_t rootaid[3] = {0x00, 0x00, 0x00};
|
||||
int res = get_desfire_select_application(rootaid);
|
||||
if (res != PM3_SUCCESS) return res;
|
||||
|
||||
return get_desfire_createapp(&aidhdr);
|
||||
}
|
||||
|
@ -789,12 +777,12 @@ static int CmdHF14ADesDeleteApp(const char *Cmd) {
|
|||
"Delete Application ID",
|
||||
"Usage:\n\t-a aid (3 bytes)\n\n"
|
||||
"Example:\n\thf mfdes deleteaid -a 123456\n"
|
||||
);
|
||||
);
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_strx0("aA", "aid", "<aid>", "App ID to delete"),
|
||||
arg_param_end
|
||||
arg_param_begin,
|
||||
arg_strx0("aA", "aid", "<aid>", "App ID to delete"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(Cmd, argtable, true);
|
||||
int aidlength = 3;
|
||||
|
@ -812,9 +800,9 @@ static int CmdHF14ADesDeleteApp(const char *Cmd) {
|
|||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
uint8_t rootaid[3]={0x00,0x00,0x00};
|
||||
int res=get_desfire_select_application(rootaid);
|
||||
if (res!=PM3_SUCCESS) return res;
|
||||
uint8_t rootaid[3] = {0x00, 0x00, 0x00};
|
||||
int res = get_desfire_select_application(rootaid);
|
||||
if (res != PM3_SUCCESS) return res;
|
||||
return get_desfire_deleteapp(aid);
|
||||
}
|
||||
|
||||
|
@ -825,12 +813,12 @@ static int CmdHF14ADesFormatPICC(const char *Cmd) {
|
|||
"Formats MIFARE DESFire PICC to factory state",
|
||||
"Usage:\n\t-k PICC key (8 bytes)\n\n"
|
||||
"Example:\n\thf mfdes formatpicc -k 0000000000000000\n"
|
||||
);
|
||||
);
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_str0("kK", "key", "<Key>", "Key for checking (HEX 16 bytes)"),
|
||||
arg_param_end
|
||||
arg_param_begin,
|
||||
arg_str0("kK", "key", "<Key>", "Key for checking (HEX 16 bytes)"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(Cmd, argtable, true);
|
||||
|
||||
|
@ -847,9 +835,9 @@ static int CmdHF14ADesFormatPICC(const char *Cmd) {
|
|||
|
||||
clearCommandBuffer();
|
||||
DropField();
|
||||
uint8_t aid[3]={0};
|
||||
int res=get_desfire_select_application(aid);
|
||||
if (res!=PM3_SUCCESS) return res;
|
||||
uint8_t aid[3] = {0};
|
||||
int res = get_desfire_select_application(aid);
|
||||
if (res != PM3_SUCCESS) return res;
|
||||
uint8_t data[25] = {keylen}; // max length: 1 + 24 (3k3DES)
|
||||
memcpy(data + 1, key, keylen);
|
||||
SendCommandOLD(CMD_HF_DESFIRE_AUTH1, 2, 1, 0, data, keylen + 1);
|
||||
|
@ -870,7 +858,7 @@ static int CmdHF14ADesFormatPICC(const char *Cmd) {
|
|||
DropField();
|
||||
return PM3_ETIMEOUT;
|
||||
}
|
||||
if (resp.oldarg[0]&0xFF){
|
||||
if (resp.oldarg[0] & 0xFF) {
|
||||
PrintAndLogEx(INFO, "Card successfully reset");
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
@ -973,7 +961,7 @@ static int CmdHF14ADesInfo(const char *Cmd) {
|
|||
|
||||
if (get_desfire_signature(signature, &signature_len) == PM3_SUCCESS)
|
||||
desfire_print_signature(package->uid, signature, signature_len, cardtype);
|
||||
else{
|
||||
else {
|
||||
PrintAndLogEx(WARNING, "--- " _YELLOW_("Couldn't verify signature. Unknown public key ?"));
|
||||
}
|
||||
|
||||
|
@ -1066,19 +1054,19 @@ char *getVersionStr(uint8_t major, uint8_t minor) {
|
|||
}
|
||||
|
||||
int getKeySettings(uint8_t *aid) {
|
||||
if (aid==NULL) return PM3_EINVARG;
|
||||
int res=0;
|
||||
if (aid == NULL) return PM3_EINVARG;
|
||||
int res = 0;
|
||||
if (memcmp(aid, "\x00\x00\x00", 3) == 0) {
|
||||
|
||||
// CARD MASTER KEY
|
||||
//PrintAndLogEx(INFO, "--- " _CYAN_("CMK - PICC, Card Master Key settings"));
|
||||
res=get_desfire_select_application(aid);
|
||||
if (res!=PM3_SUCCESS) return res;
|
||||
res = get_desfire_select_application(aid);
|
||||
if (res != PM3_SUCCESS) return res;
|
||||
|
||||
// KEY Settings - AMK
|
||||
uint8_t num_keys = 0;
|
||||
uint8_t key_setting = 0;
|
||||
res=get_desfire_keysettings(&key_setting, &num_keys);
|
||||
res = get_desfire_keysettings(&key_setting, &num_keys);
|
||||
if (res == PM3_SUCCESS) {
|
||||
// number of Master keys (0x01)
|
||||
PrintAndLogEx(SUCCESS, " Number of Masterkeys : " _YELLOW_("%u"), (num_keys & 0x3F));
|
||||
|
@ -1133,13 +1121,13 @@ int getKeySettings(uint8_t *aid) {
|
|||
|
||||
// AID - APPLICATION MASTER KEYS
|
||||
//PrintAndLogEx(SUCCESS, "--- " _CYAN_("AMK - Application Master Key settings"));
|
||||
res=get_desfire_select_application(aid);
|
||||
if (res!=PM3_SUCCESS) return res;
|
||||
res = get_desfire_select_application(aid);
|
||||
if (res != PM3_SUCCESS) return res;
|
||||
|
||||
// KEY Settings - AMK
|
||||
uint8_t num_keys = 0;
|
||||
uint8_t key_setting = 0;
|
||||
res=get_desfire_keysettings(&key_setting, &num_keys);
|
||||
res = get_desfire_keysettings(&key_setting, &num_keys);
|
||||
if (res == PM3_SUCCESS) {
|
||||
desfire_print_keysetting(key_setting, num_keys);
|
||||
} else {
|
||||
|
@ -1173,9 +1161,8 @@ int getKeySettings(uint8_t *aid) {
|
|||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static void DecodeFileType(uint8_t filetype){
|
||||
switch (filetype)
|
||||
{
|
||||
static void DecodeFileType(uint8_t filetype) {
|
||||
switch (filetype) {
|
||||
case 0x00:
|
||||
PrintAndLogEx(INFO, " File Type: 0x%02X -> Standard Data File", filetype);
|
||||
break;
|
||||
|
@ -1197,9 +1184,8 @@ static void DecodeFileType(uint8_t filetype){
|
|||
}
|
||||
}
|
||||
|
||||
static void DecodeComSet(uint8_t comset){
|
||||
switch (comset)
|
||||
{
|
||||
static void DecodeComSet(uint8_t comset) {
|
||||
switch (comset) {
|
||||
case 0x00:
|
||||
PrintAndLogEx(INFO, " Com.Setting: 0x%02X -> Plain", comset);
|
||||
break;
|
||||
|
@ -1215,11 +1201,10 @@ static void DecodeComSet(uint8_t comset){
|
|||
}
|
||||
}
|
||||
|
||||
static char* DecodeAccessValue(uint8_t value)
|
||||
{
|
||||
char* car=(char*)malloc(255);
|
||||
memset(car,0x0,255);
|
||||
switch(value){
|
||||
static char *DecodeAccessValue(uint8_t value) {
|
||||
char *car = (char *)malloc(255);
|
||||
memset(car, 0x0, 255);
|
||||
switch (value) {
|
||||
case 0xE:
|
||||
strcat(car, "(Free Access)");
|
||||
break;
|
||||
|
@ -1227,46 +1212,45 @@ static char* DecodeAccessValue(uint8_t value)
|
|||
strcat(car, "(Denied Access)");
|
||||
break;
|
||||
default:
|
||||
sprintf(car,"(Access Key: %d)",value);
|
||||
sprintf(car, "(Access Key: %d)", value);
|
||||
break;
|
||||
}
|
||||
return car;
|
||||
}
|
||||
|
||||
static void DecodeAccessRights(uint16_t accrights){
|
||||
int change_access_rights=accrights&0xF;
|
||||
int read_write_access=(accrights>>4)&0xF;
|
||||
int write_access=(accrights>>8)&0xF;
|
||||
int read_access=(accrights>>12)&0xF;
|
||||
char* car=DecodeAccessValue(change_access_rights);
|
||||
char* rwa=DecodeAccessValue(read_write_access);
|
||||
char* wa=DecodeAccessValue(write_access);
|
||||
char* ra=DecodeAccessValue(read_access);
|
||||
PrintAndLogEx(INFO, " Access Rights: 0x%04X - Change %s - RW %s - W %s - R %s", accrights,car,rwa,wa,ra);
|
||||
static void DecodeAccessRights(uint16_t accrights) {
|
||||
int change_access_rights = accrights & 0xF;
|
||||
int read_write_access = (accrights >> 4) & 0xF;
|
||||
int write_access = (accrights >> 8) & 0xF;
|
||||
int read_access = (accrights >> 12) & 0xF;
|
||||
char *car = DecodeAccessValue(change_access_rights);
|
||||
char *rwa = DecodeAccessValue(read_write_access);
|
||||
char *wa = DecodeAccessValue(write_access);
|
||||
char *ra = DecodeAccessValue(read_access);
|
||||
PrintAndLogEx(INFO, " Access Rights: 0x%04X - Change %s - RW %s - W %s - R %s", accrights, car, rwa, wa, ra);
|
||||
free(car);
|
||||
free(rwa);
|
||||
free(wa);
|
||||
free(ra);
|
||||
}
|
||||
|
||||
static int DecodeFileSettings(uint8_t* filesettings, int fileset_len, int maclen){
|
||||
uint8_t filetype=filesettings[0];
|
||||
uint8_t comset=filesettings[1];
|
||||
static int DecodeFileSettings(uint8_t *filesettings, int fileset_len, int maclen) {
|
||||
uint8_t filetype = filesettings[0];
|
||||
uint8_t comset = filesettings[1];
|
||||
|
||||
uint16_t accrights=(filesettings[4]<<8)+filesettings[3];
|
||||
if (fileset_len==1+1+2+3+maclen)
|
||||
{
|
||||
int filesize=(filesettings[7]<<16)+(filesettings[6]<<8)+filesettings[5];
|
||||
uint16_t accrights = (filesettings[4] << 8) + filesettings[3];
|
||||
if (fileset_len == 1 + 1 + 2 + 3 + maclen) {
|
||||
int filesize = (filesettings[7] << 16) + (filesettings[6] << 8) + filesettings[5];
|
||||
DecodeFileType(filetype);
|
||||
DecodeComSet(comset);
|
||||
DecodeAccessRights(accrights);
|
||||
PrintAndLogEx(INFO, " Filesize: %d", filesize);
|
||||
return PM3_SUCCESS;
|
||||
} else if (fileset_len==1+1+2+4+4+4+1+maclen) {
|
||||
int lowerlimit=(filesettings[8]<<24)+(filesettings[7]<<16)+(filesettings[6]<<8)+filesettings[5];
|
||||
int upperlimit=(filesettings[12]<<24)+(filesettings[11]<<16)+(filesettings[10]<<8)+filesettings[9];
|
||||
int limitcredvalue=(filesettings[16]<<24)+(filesettings[15]<<16)+(filesettings[14]<<8)+filesettings[13];
|
||||
uint8_t limited_credit_enabled=filesettings[17];
|
||||
} else if (fileset_len == 1 + 1 + 2 + 4 + 4 + 4 + 1 + maclen) {
|
||||
int lowerlimit = (filesettings[8] << 24) + (filesettings[7] << 16) + (filesettings[6] << 8) + filesettings[5];
|
||||
int upperlimit = (filesettings[12] << 24) + (filesettings[11] << 16) + (filesettings[10] << 8) + filesettings[9];
|
||||
int limitcredvalue = (filesettings[16] << 24) + (filesettings[15] << 16) + (filesettings[14] << 8) + filesettings[13];
|
||||
uint8_t limited_credit_enabled = filesettings[17];
|
||||
DecodeFileType(filetype);
|
||||
DecodeComSet(comset);
|
||||
DecodeAccessRights(accrights);
|
||||
|
@ -1287,10 +1271,10 @@ static int CmdHF14ADesEnumApplications(const char *Cmd) {
|
|||
uint8_t file_ids[33] = {0};
|
||||
uint8_t file_ids_len = 0;
|
||||
|
||||
dfname_t dfnames[255] = {0};
|
||||
dfname_t dfnames[255];
|
||||
uint8_t dfname_count = 0;
|
||||
|
||||
int res=0;
|
||||
int res = 0;
|
||||
|
||||
if (get_desfire_appids(app_ids, &app_ids_len) != PM3_SUCCESS) {
|
||||
PrintAndLogEx(ERR, "Can't get list of applications on tag");
|
||||
|
@ -1331,10 +1315,10 @@ static int CmdHF14ADesEnumApplications(const char *Cmd) {
|
|||
}
|
||||
}
|
||||
|
||||
res=getKeySettings(aid);
|
||||
if (res!=PM3_SUCCESS) return res;
|
||||
res = getKeySettings(aid);
|
||||
if (res != PM3_SUCCESS) return res;
|
||||
|
||||
res=get_desfire_select_application(aid);
|
||||
res = get_desfire_select_application(aid);
|
||||
|
||||
|
||||
// Get File IDs
|
||||
|
@ -1346,9 +1330,9 @@ static int CmdHF14ADesEnumApplications(const char *Cmd) {
|
|||
uint8_t filesettings[20] = {0};
|
||||
int fileset_len = 0;
|
||||
int res = get_desfire_filesettings(j, filesettings, &fileset_len);
|
||||
int maclen=0; // To be implemented
|
||||
int maclen = 0; // To be implemented
|
||||
if (res == PM3_SUCCESS) {
|
||||
if (DecodeFileSettings(filesettings,fileset_len,maclen)!=PM3_SUCCESS){
|
||||
if (DecodeFileSettings(filesettings, fileset_len, maclen) != PM3_SUCCESS) {
|
||||
PrintAndLogEx(INFO, " Settings [%u] %s", fileset_len, sprint_hex(filesettings, fileset_len));
|
||||
}
|
||||
}
|
||||
|
@ -1387,7 +1371,7 @@ static int CmdHF14ADesEnumApplications(const char *Cmd) {
|
|||
//
|
||||
#define BUFSIZE 256
|
||||
static int CmdHF14ADesAuth(const char *Cmd) {
|
||||
int res=0;
|
||||
int res = 0;
|
||||
DropField();
|
||||
clearCommandBuffer();
|
||||
// NR DESC KEYLENGHT
|
||||
|
@ -1498,10 +1482,10 @@ static int CmdHF14ADesAuth(const char *Cmd) {
|
|||
}
|
||||
|
||||
|
||||
res=get_desfire_select_application(aid);
|
||||
if (res!=PM3_SUCCESS) return res;
|
||||
res = get_desfire_select_application(aid);
|
||||
if (res != PM3_SUCCESS) return res;
|
||||
|
||||
if (memcmp(aid,"\x00\x00\x00",3)!=0){
|
||||
if (memcmp(aid, "\x00\x00\x00", 3) != 0) {
|
||||
uint8_t file_ids[33] = {0};
|
||||
uint8_t file_ids_len = 0;
|
||||
res = get_desfire_fileids(file_ids, &file_ids_len);
|
||||
|
|
|
@ -91,14 +91,20 @@ CRC1 = crc8 over addr 0x00..0x03+0x07..0x0E (special 'gantner crc8')
|
|||
CRC2 = MCD + MSB0..2+ addr 0x06 + addr 0x05 + addr 0x07 + Stamp (regular Master-Token-CRC)
|
||||
--]]
|
||||
|
||||
--[[
|
||||
Known issues; needs to be fixed:
|
||||
* last byte in last segment is handled incorrectly when it is the last bytes on the card itself (MIM256: => byte 256)
|
||||
--]]
|
||||
|
||||
example = "script run legic"
|
||||
author = "Mosci"
|
||||
version = "1.0.3"
|
||||
author = "Mosci, uhei"
|
||||
version = "1.0.4"
|
||||
|
||||
desc =
|
||||
[[
|
||||
|
||||
This script helps you to read, create and modify Legic Prime Tags (MIM22, MIM256, MIM1024)
|
||||
The virtual tag (and therefore the file to be saved) is always a MIM1024 tag.
|
||||
it's kinda interactive with following commands in three categories:
|
||||
|
||||
Data I/O Segment Manipulation Token-Data
|
||||
|
@ -108,8 +114,8 @@ it's kinda interactive with following commands in three categories:
|
|||
ed => edit Segment Data tk => toggle KGH-Flag
|
||||
File I/O rs => remove Segment
|
||||
----------------- cc => check Segment-CRC
|
||||
lf => load File ck => check KGH
|
||||
sf => save File ds => dump Segments
|
||||
lf => load bin File ck => check KGH
|
||||
sf => save eml/bin File ds => dump Segments
|
||||
xf => xor to File
|
||||
|
||||
|
||||
|
@ -128,8 +134,8 @@ it's kinda interactive with following commands in three categories:
|
|||
without the need of changing anything - MCD,MSN,MCC will be read from the tag
|
||||
before and applied to the output.
|
||||
|
||||
lf: 'load file' - load a (xored) file from the local Filesystem into the 'virtual inTag'
|
||||
sf: 'save file' - saves the 'virtual inTag' to the local Filesystem (xored with Tag-MCC)
|
||||
lf: 'load file' - load a (xored) binary file (*.bin) from the local Filesystem into the 'virtual inTag'
|
||||
sf: 'save file' - saves the 'virtual inTag' to the local Filesystem as eml and bin (xored with Tag-MCC)
|
||||
xf: 'xor file' - saves the 'virtual inTag' to the local Filesystem (xored with choosen MCC - use '00' for plain values)
|
||||
|
||||
ct: 'copy tag' - copy the 'virtual Tag' to a second 'virtual TAG' - not usefull yet, but inernally needed
|
||||
|
@ -242,6 +248,16 @@ function istable(t)
|
|||
return type(t) == 'table'
|
||||
end
|
||||
|
||||
---
|
||||
-- To have two char string for a byte
|
||||
local function padString(str)
|
||||
if (#str == 1) then
|
||||
return '0'..str
|
||||
end
|
||||
|
||||
return str
|
||||
end
|
||||
|
||||
---
|
||||
-- creates a 'deep copy' of a table (a=b only references)
|
||||
function deepCopy(object)
|
||||
|
@ -387,15 +403,15 @@ end
|
|||
function bytesToTag(bytes, tag)
|
||||
if istable(tag) == false then return oops("tag is no table in: bytesToTag ("..type(tag)..")") end
|
||||
|
||||
tag.MCD =bytes[1];
|
||||
tag.MSN0=bytes[2];
|
||||
tag.MSN1=bytes[3];
|
||||
tag.MSN2=bytes[4];
|
||||
tag.MCC =bytes[5];
|
||||
tag.DCFl=bytes[6];
|
||||
tag.DCFh=bytes[7];
|
||||
tag.raw =bytes[8];
|
||||
tag.SSC =bytes[9];
|
||||
tag.MCD =padString(bytes[1]);
|
||||
tag.MSN0=padString(bytes[2]);
|
||||
tag.MSN1=padString(bytes[3]);
|
||||
tag.MSN2=padString(bytes[4]);
|
||||
tag.MCC =padString(bytes[5]);
|
||||
tag.DCFl=padString(bytes[6]);
|
||||
tag.DCFh=padString(bytes[7]);
|
||||
tag.raw =padString(bytes[8]);
|
||||
tag.SSC =padString(bytes[9]);
|
||||
tag.Type=getTokenType(tag.DCFl);
|
||||
tag.OLE=bbit("0x"..tag.DCFl,7,1)
|
||||
tag.WRP=("%d"):format(bbit("0x"..bytes[8],0,4))
|
||||
|
@ -500,42 +516,26 @@ function tagToBytes(tag)
|
|||
return bytes
|
||||
end
|
||||
|
||||
|
||||
---
|
||||
--- PM3 I/O ---
|
||||
---
|
||||
-- read from pm3 into virtual-tag
|
||||
function readFromPM3()
|
||||
local tag, bytes, infile
|
||||
infile="legic.temp"
|
||||
-- core.console("hf legic reader")
|
||||
-- core.console("hf legic esave "..infile)
|
||||
core.console("hf legic dump o "..infile)
|
||||
tag=readFile(infile..".bin")
|
||||
return tag
|
||||
end
|
||||
|
||||
local function padString(str)
|
||||
if (#str == 1) then
|
||||
return '0'..str
|
||||
end
|
||||
|
||||
return str
|
||||
end
|
||||
|
||||
---
|
||||
-- write virtual Tag to real Tag
|
||||
function writeToTag(tag)
|
||||
local bytes
|
||||
local filename = 'MylegicClone.hex'
|
||||
local taglen = 22
|
||||
if(utils.confirm(acred.."\nplace the (empty) Tag onto the PM3\nand confirm writing to this Tag: "..acoff) == false) then
|
||||
local writeDCF = false
|
||||
if(utils.confirm(acred.."\nPlace the (empty) Tag onto the PM3\nand confirm writing to this Tag: "..acoff) == false) then
|
||||
return
|
||||
end
|
||||
if(utils.confirm(acred.."\nShould the decremental field (DCF) be written?: "..acoff) == true) then
|
||||
writeDCF = true
|
||||
end
|
||||
|
||||
-- get used bytes / tag-len
|
||||
if (istable(tag.SEG)) then
|
||||
if (istable(tag.Bck)) then
|
||||
for i=0, #tag.SEG do
|
||||
taglen = taglen + tag.SEG[i] . len + 5
|
||||
taglen = taglen + tag.SEG[i] . len
|
||||
end
|
||||
end
|
||||
local uid_old = tag.MCD..tag.MSN0..tag.MSN1..tag.MSN2
|
||||
|
@ -571,37 +571,32 @@ function writeToTag(tag)
|
|||
bytes[22] = calcMtCrc(bytes)
|
||||
end
|
||||
if (bytes) then
|
||||
print("write temp-file '"..filename.."'")
|
||||
print(accyan)
|
||||
writeFile(bytes, filename..".bin")
|
||||
print(acoff)
|
||||
bytes = xorBytes(bytes,tag.MCC)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-- write data to file
|
||||
if (taglen > 0) then
|
||||
WriteBytes = input(acyellow.."enter number of bytes to write?"..acoff, taglen)
|
||||
-- load file into pm3-buffer
|
||||
if (type(filename) ~= "string") then
|
||||
filename = input(acyellow.."filename to load to pm3-buffer?"..acoff, "legic.temp")
|
||||
end
|
||||
|
||||
cmd = 'hf legic eload 2 '..filename
|
||||
core.console(cmd)
|
||||
-- write pm3-buffer to Tag
|
||||
for i=0, WriteBytes do
|
||||
if (i > 6) then
|
||||
cmd = ("hf legic write o %x d %s "):format(i, padString(bytes[i]))
|
||||
for i=1, WriteBytes do
|
||||
if (i > 7) then
|
||||
cmd = ("hf legic wrbl o %02x d %s "):format(i-1, padString(bytes[i]))
|
||||
print(acgreen..cmd..acoff)
|
||||
core.console(cmd)
|
||||
core.clearCommandBuffer()
|
||||
elseif (i == 7) then
|
||||
if (writeDCF) then
|
||||
-- write DCF in reverse order (requires 'mosci-patch')
|
||||
cmd = ('hf legic wrbl o 05 d %s%s'):format(padString(bytes[i-1]), padString(bytes[i]))
|
||||
print(acgreen..cmd..acoff)
|
||||
core.console(cmd)
|
||||
core.clearCommandBuffer()
|
||||
else
|
||||
print(acgreen.."skip byte 0x05-0x06 - DCF"..acoff)
|
||||
end
|
||||
elseif (i == 6) then
|
||||
-- write DCF in reverse order (requires 'mosci-patch')
|
||||
cmd = ('hf legic write o 05 d %s%s'):format(padString(bytes[i-1]), padString(bytes[i]))
|
||||
print(acgreen..cmd..acoff)
|
||||
core.console(cmd)
|
||||
core.clearCommandBuffer()
|
||||
elseif (i == 5) then
|
||||
print(acgreen.."skip byte 0x05 - will be written next step"..acoff)
|
||||
else
|
||||
print(acgreen.."skip byte 0x00-0x04 - unwritable area"..acoff)
|
||||
|
@ -641,12 +636,12 @@ end
|
|||
local function save_BIN(data, filename)
|
||||
local outfile
|
||||
local counter = 1
|
||||
local ext = filename:match("^.+(%..+)$") or ''
|
||||
local fn = filename
|
||||
local ext = ".bin"
|
||||
local fn = filename..ext
|
||||
|
||||
-- Make sure we don't overwrite a file
|
||||
while file_check(fn) do
|
||||
fn = filename:gsub(ext, tostring(counter)..ext)
|
||||
fn = filename..ext:gsub(ext, "-"..tostring(counter)..ext)
|
||||
counter = counter + 1
|
||||
end
|
||||
|
||||
|
@ -664,26 +659,27 @@ end
|
|||
---
|
||||
-- write bytes to file
|
||||
function writeFile(bytes, filename)
|
||||
if (filename ~= 'MylegicClone.hex') then
|
||||
if (file_check(filename)) then
|
||||
local answer = confirm("\nthe output-file "..filename.." already exists!\nthis will delete the previous content!\ncontinue?")
|
||||
local emlext = ".eml"
|
||||
if (filename ~= 'MyLegicClone') then
|
||||
if (file_check(filename..emlext)) then
|
||||
local answer = confirm("\nthe output-file "..filename..emlext.." already exists!\nthis will delete the previous content!\ncontinue?")
|
||||
if not answer then return print("user abort") end
|
||||
end
|
||||
end
|
||||
local line
|
||||
local bcnt = 0
|
||||
local fho, err = io.open(filename, "w")
|
||||
local fho, err = io.open(filename..emlext, "w")
|
||||
if err then
|
||||
return oops("OOps ... failed to open output-file ".. filename)
|
||||
return oops("OOps ... failed to open output-file ".. filename..emlext)
|
||||
end
|
||||
|
||||
bytes = xorBytes(bytes, bytes[5])
|
||||
|
||||
for i = 1, #bytes do
|
||||
if (bcnt == 0) then
|
||||
line = bytes[i]
|
||||
line = padString(bytes[i])
|
||||
elseif (bcnt <= 7) then
|
||||
line = line.." "..bytes[i]
|
||||
line = line.." "..padString(bytes[i])
|
||||
end
|
||||
if (bcnt == 7) then
|
||||
-- write line to new file
|
||||
|
@ -699,7 +695,7 @@ function writeFile(bytes, filename)
|
|||
-- save binary
|
||||
local fn_bin, fn_bin_num = save_BIN(bytes, filename)
|
||||
|
||||
print("\nwrote "..acyellow..(#bytes * 3)..acoff.." bytes to " ..acyellow..filename..acoff)
|
||||
print("\nwrote "..acyellow..(#bytes * 3)..acoff.." bytes to " ..acyellow..filename..emlext..acoff)
|
||||
|
||||
if fn_bin and fn_bin_num then
|
||||
print("\nwrote "..acyellow..fn_bin_num..acoff.." bytes to BINARY file "..acyellow..fn_bin..acoff)
|
||||
|
@ -708,6 +704,21 @@ function writeFile(bytes, filename)
|
|||
return true
|
||||
end
|
||||
|
||||
---
|
||||
-- read from pm3 into virtual-tag
|
||||
function readFromPM3()
|
||||
local tag, bytes, infile
|
||||
--infile="legic.temp"
|
||||
infile=os.tmpname()
|
||||
core.console("hf legic dump f "..infile)
|
||||
tag=readFile(infile..".bin")
|
||||
os.remove(infile)
|
||||
os.remove(infile..".bin")
|
||||
os.remove(infile..".eml")
|
||||
os.remove(infile..".json")
|
||||
return tag
|
||||
end
|
||||
|
||||
--- Map related ---
|
||||
---
|
||||
-- make tagMap
|
||||
|
@ -2265,8 +2276,8 @@ function modifyHelp()
|
|||
ed => edit Segment Data tk => toggle KGH-Flag
|
||||
File I/O rs => remove Segment
|
||||
----------------- cc => check Segment-CRC
|
||||
lf => load File ck => check KGH
|
||||
sf => save File ds => dump Segments
|
||||
lf => load bin File ck => check KGH
|
||||
sf => save eml/bin File ds => dump Segments
|
||||
xf => xor to File
|
||||
|
||||
|
||||
|
@ -2352,10 +2363,10 @@ function modifyMode()
|
|||
-- save values of mainTAG to a file (xored with MCC of mainTAG)
|
||||
["sf"] = function(x)
|
||||
if istable(inTAG) then
|
||||
outfile = input("enter filename:", "legic.temp")
|
||||
outfile = input("enter filename:", "hf-legic-"..inTAG.MCD..inTAG.MSN0..inTAG.MSN1..inTAG.MSN2)
|
||||
bytes = tagToBytes(inTAG)
|
||||
--bytes=xorBytes(bytes, inTAG.MCC)
|
||||
if bytes then
|
||||
if (bytes) then
|
||||
writeFile(bytes, outfile)
|
||||
end
|
||||
end
|
||||
|
@ -2364,7 +2375,7 @@ function modifyMode()
|
|||
-- save values of mainTAG to a file (xored with 'specific' MCC)
|
||||
["xf"] = function(x)
|
||||
if istable(inTAG) then
|
||||
outfile = input("enter filename:", "legic.temp")
|
||||
outfile = input("enter filename:", "hf-legic-"..inTAG.MCD..inTAG.MSN0..inTAG.MSN1..inTAG.MSN2)
|
||||
crc = input("enter new crc: ('00' for a plain dump)", inTAG.MCC)
|
||||
print("obfuscate with: "..crc)
|
||||
bytes=tagToBytes(inTAG)
|
||||
|
|
1569
cmdhfmfdes.c
Normal file
1569
cmdhfmfdes.c
Normal file
File diff suppressed because it is too large
Load diff
|
@ -18,7 +18,7 @@ Always use the latest repository commits from *master* branch. There are always
|
|||
* [File not found](#file-not-found)
|
||||
* [Pixmap / pixbuf warnings](#pixmap--pixbuf-warnings)
|
||||
* [Usb cable](#usb-cable)
|
||||
* [WSL 2 explorer.exe . doesnt work](WSL-2)
|
||||
* [WSL 2 explorer.exe . doesnt work](#WSL-2)
|
||||
|
||||
## `pm3` or `pm3-flash*` doesn't see my Proxmark
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue