This commit is contained in:
root 2020-03-03 11:32:57 -05:00
commit 643b2ca363
38 changed files with 504 additions and 216 deletions

1
.gitignore vendored
View file

@ -10,6 +10,7 @@
.profile .profile
*.log *.log
*.eml *.eml
*.html
*.o *.o
*.a *.a
*.d *.d

View file

@ -3,6 +3,17 @@ 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... 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] ## [unreleased][unreleased]
- Change - hint texts added to all lf clone commands (@iceman1001)
- Change `lf keri demod` - adjusted the internal id. (@mwalker33)
- Added seamless integration with cryptohelper (@iceman1001)
- Change `lf hid brute` - new params for direction (UP/DOWN); textual and main loop actually exit. (@capnkrunchy and @iceman1001)
- Fix `lf hid brute` - made it work again (@capnkrunchy)
- Fix standalone mode HF_MATTYRUN - correct logic when all keys found in printing. partial fix (@iceman1001)
- Change static nonce detection got tighter (@iceman1001)
- Improved termux notes (@msoose)
- Fix `hf mf autopwn` - works on debian 10 *nix. Bad exit commands in hardnested (@iceman1001)
- Fix `hf mf hardnested` - bad mutex strategies (@msoose)
- Change `lf hitag` - now obeys `lf config` (@iceman1001)
- Ported all python 2 scripts to python 3 (@doegox and @sigwinch28) - Ported all python 2 scripts to python 3 (@doegox and @sigwinch28)
- Removed undefined exit behaviour from `analyzesize` tool: it now exits with code 2 when called with wrong args (@sigwinch28) - Removed undefined exit behaviour from `analyzesize` tool: it now exits with code 2 when called with wrong args (@sigwinch28)
- Replaced shebangs in scripts with more portable versions which use `/usr/bin/env` (@sigwinch28) - Replaced shebangs in scripts with more portable versions which use `/usr/bin/env` (@sigwinch28)

View file

@ -323,7 +323,7 @@ void RunMod() {
Dbprintf("\tCurrent sector:%3d, block:%3d, key type: %c, key count: %i ", sec, block, type ? 'B' : 'A', mfKeysCnt); Dbprintf("\tCurrent sector:%3d, block:%3d, key type: %c, key count: %i ", sec, block, type ? 'B' : 'A', mfKeysCnt);
int key = saMifareChkKeys(block, type, true, size, &keyBlock[0], &key64); int key = saMifareChkKeys(block, type, true, size, &keyBlock[0], &key64);
if (key == -1) { if (key == -1) {
LED(LED_RED, 50); //red LED(LED_RED, 50);
Dbprintf("\t✕ Key not found for this sector!"); Dbprintf("\t✕ Key not found for this sector!");
allKeysFound = false; allKeysFound = false;
// break; // break;
@ -348,21 +348,24 @@ void RunMod() {
TODO: TODO:
- Get UID from tag and set accordingly in emulator memory and call mifaresim with right flags (iceman) - Get UID from tag and set accordingly in emulator memory and call mifaresim with right flags (iceman)
*/ */
if (!allKeysFound && keyFound) { if (allKeysFound) {
Dbprintf("\t✕ There's currently no nested attack in MattyRun, sorry!"); Dbprintf("\t✓ All keys found");
LED_C_ON(); //red
LED_A_ON(); //yellow
// no room to run nested attack on device (iceman)
// Do nested attack, set allKeysFound = true;
// allKeysFound = true;
} else { } else {
Dbprintf("\t✕ There's nothing I can do without at least a one valid key, sorry!"); if (keyFound) {
LED_C_ON(); //red Dbprintf("\t✕ There's currently no nested attack in MattyRun, sorry!");
LED_C_ON(); //red
LED_A_ON(); //yellow
// no room to run nested attack on device (iceman)
// Do nested attack, set allKeysFound = true;
// allKeysFound = true;
} else {
Dbprintf("\t✕ There's nothing I can do without at least a one valid key, sorry!");
LED_C_ON(); //red
}
} }
/* // If enabled, transfers found keys to memory and loads target content in emulator memory. Then it simulates to be the tag it has basically cloned.
If enabled, transfers found keys to memory and loads target content in emulator memory. Then it simulates to be the tag it has basically cloned.
*/
if ((transferToEml) && (allKeysFound)) { if ((transferToEml) && (allKeysFound)) {
emlClearMem(); emlClearMem();

View file

@ -94,7 +94,7 @@ uint8_t nonce[4];
bool key_no; bool key_no;
static uint64_t cipher_state; static uint64_t cipher_state;
size_t blocknr; int16_t blocknr;
size_t flipped_bit = 0; size_t flipped_bit = 0;
uint32_t byte_value = 0; uint32_t byte_value = 0;
@ -582,7 +582,7 @@ bool hitag1_authenticate(uint8_t *rx, const size_t rxlen, uint8_t *tx, size_t *t
Dbhexdump(4, logdata_1, false); Dbhexdump(4, logdata_1, false);
bSuccessful = true; bSuccessful = true;
return false; return false;
/*
// read next page of card until done // read next page of card until done
tx[0] = 0xe0 | blocknr >> 4; // RDCPAGE tx[0] = 0xe0 | blocknr >> 4; // RDCPAGE
tx[1] = blocknr << 4; tx[1] = blocknr << 4;
@ -590,6 +590,7 @@ bool hitag1_authenticate(uint8_t *rx, const size_t rxlen, uint8_t *tx, size_t *t
tx[1] |= crc >> 4; tx[1] |= crc >> 4;
tx[2] = crc << 4; tx[2] = crc << 4;
*txlen = 20; *txlen = 20;
*/
} }
} }
break; break;
@ -1288,10 +1289,10 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) {
uint8_t *tx = txbuf; uint8_t *tx = txbuf;
size_t txlen = 0; size_t txlen = 0;
int t_wait_1; int t_wait_1 = 204;
int t_wait_1_guard = 8; int t_wait_1_guard = 8;
int t_wait_2; int t_wait_2 = 128;
size_t tag_size; size_t tag_size = 48;
bool bStop = false; bool bStop = false;
// Raw demodulation/decoding by sampling edge periods // Raw demodulation/decoding by sampling edge periods
@ -1417,9 +1418,6 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) {
t_wait_2 = HITAG_T_WAIT_2_MIN; t_wait_2 = HITAG_T_WAIT_2_MIN;
tag_size = 48; tag_size = 48;
DBG DbpString("Configured for hitag2 reader"); DBG DbpString("Configured for hitag2 reader");
} else {
DBG Dbprintf("Error, unknown hitag reader type: %d", htf);
return;
} }
// init as reader // init as reader
@ -1665,10 +1663,12 @@ void WriterHitag(hitag_function htf, hitag_data *htd, int page) {
uint8_t txbuf[HITAG_FRAME_LEN]; uint8_t txbuf[HITAG_FRAME_LEN];
uint8_t *tx = txbuf; uint8_t *tx = txbuf;
size_t txlen = 0; size_t txlen = 0;
int t_wait_1;
int t_wait_1 = 204;
int t_wait_1_guard = 8; int t_wait_1_guard = 8;
int t_wait_2; int t_wait_2 = 128;
size_t tag_size; size_t tag_size = 48;
bool bStop = false; bool bStop = false;
// Raw demodulation/decoding by sampling edge periods // Raw demodulation/decoding by sampling edge periods
@ -1743,9 +1743,6 @@ void WriterHitag(hitag_function htf, hitag_data *htd, int page) {
t_wait_2 = HITAG_T_WAIT_2_MIN; t_wait_2 = HITAG_T_WAIT_2_MIN;
tag_size = 48; tag_size = 48;
DbpString("Configured for hitag2 writer"); DbpString("Configured for hitag2 writer");
} else {
DBG Dbprintf("Error, unknown hitag writer type: %d", htf);
return;
} }
uint8_t tag_modulation; uint8_t tag_modulation;

View file

@ -133,16 +133,18 @@ size_t lf_detect_gap(size_t max) {
} }
void lf_reset_counter() { void lf_reset_counter() {
// TODO: find out the correct reset settings for tag and reader mode // TODO: find out the correct reset settings for tag and reader mode
if (reader_mode) { // if (reader_mode) {
// Reset values for reader mode // Reset values for reader mode
rising_edge = false; rising_edge = false;
previous_adc_val = 0xFF; previous_adc_val = 0xFF;
} else {
// } else {
// Reset values for tag/transponder mode // Reset values for tag/transponder mode
rising_edge = false; // rising_edge = false;
previous_adc_val = 0xFF; // previous_adc_val = 0xFF;
} // }
} }
bool lf_get_tag_modulation() { bool lf_get_tag_modulation() {

View file

@ -250,7 +250,8 @@ CMDSRCS = crapto1/crapto1.c \
bucketsort.c \ bucketsort.c \
flash.c \ flash.c \
wiegand_formats.c \ wiegand_formats.c \
wiegand_formatutils.c wiegand_formatutils.c \
cardhelper.c
cpu_arch = $(shell uname -m) cpu_arch = $(shell uname -m)
ifneq ($(findstring 86, $(cpu_arch)), ) ifneq ($(findstring 86, $(cpu_arch)), )

View file

@ -1,8 +1,8 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Copyright (C) 2010 iZsh <izsh at fail0verflow.com>, Hagen Fritsch // Copyright (C) 2010 iZsh <izsh at fail0verflow.com>, Hagen Fritsch
// Copyright (C) 2011 Gerhard de Koning Gans // Copyright (C) 2011 Gerhard de Koning Gans
// Copyright (C) 2014 Midnitesnake & Andy Davies & Martin Holst Swende // Copyright (C) 2014 Midnitesnake & Andy Davies & Martin Holst Swende
// Copyright (C) 2020 Iceman
// //
// This code is licensed to you under the terms of the GNU GPL, version 2 or, // This code is licensed to you under the terms of the GNU GPL, version 2 or,
// at your option, any later version. See the LICENSE.txt file for the text of // at your option, any later version. See the LICENSE.txt file for the text of
@ -12,14 +12,11 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
#include "cmdhficlass.h" #include "cmdhficlass.h"
#include <ctype.h> #include <ctype.h>
#include "cmdparser.h" // command_t #include "cmdparser.h" // command_t
#include "commonutil.h" // ARRAYLEN #include "commonutil.h" // ARRAYLEN
#include "cmdtrace.h" #include "cmdtrace.h"
#include "util_posix.h" #include "util_posix.h"
#include "comms.h" #include "comms.h"
#include "mbedtls/des.h" #include "mbedtls/des.h"
#include "loclass/cipherutils.h" #include "loclass/cipherutils.h"
@ -28,12 +25,14 @@
#include "loclass/elite_crack.h" #include "loclass/elite_crack.h"
#include "fileutils.h" #include "fileutils.h"
#include "protocols.h" #include "protocols.h"
#include "cardhelper.h"
#include "wiegand_formats.h" #include "wiegand_formats.h"
#include "wiegand_formatutils.h" #include "wiegand_formatutils.h"
#define NUM_CSNS 9 #define NUM_CSNS 9
#define ICLASS_KEYS_MAX 8 #define ICLASS_KEYS_MAX 8
#define ICLASS_AUTH_RETRY 10 #define ICLASS_AUTH_RETRY 10
#define ICLASS_DECRYPTION_BIN "iclass_decryptionkey.bin"
static int CmdHelp(const char *Cmd); static int CmdHelp(const char *Cmd);
@ -290,16 +289,6 @@ static int usage_hf_iclass_permutekey(void) {
return PM3_SUCCESS; return PM3_SUCCESS;
} }
/*
static int xorbits_8(uint8_t val) {
uint8_t res = val ^ (val >> 1); //1st pass
res = res ^ (res >> 1); // 2nd pass
res = res ^ (res >> 2); // 3rd pass
res = res ^ (res >> 4); // 4th pass
return res & 1;
}
*/
// iclass / picopass chip config structures and shared routines // iclass / picopass chip config structures and shared routines
typedef struct { typedef struct {
uint8_t app_limit; //[8] uint8_t app_limit; //[8]
@ -311,7 +300,6 @@ typedef struct {
uint8_t fuses; //[15] uint8_t fuses; //[15]
} picopass_conf_block; } picopass_conf_block;
typedef struct { typedef struct {
uint8_t csn[8]; uint8_t csn[8];
picopass_conf_block conf; picopass_conf_block conf;
@ -321,6 +309,13 @@ typedef struct {
uint8_t app_issuer_area[8]; uint8_t app_issuer_area[8];
} picopass_hdr; } picopass_hdr;
typedef enum {
None = 0,
DES,
RFU,
TRIPLEDES
} BLOCK79ENCRYPTION;
static uint8_t isset(uint8_t val, uint8_t mask) { static uint8_t isset(uint8_t val, uint8_t mask) {
return (val & mask); return (val & mask);
} }
@ -429,18 +424,18 @@ static void mem_app_config(const picopass_hdr *hdr) {
PrintAndLogEx(NORMAL, " Credit - Kc"); PrintAndLogEx(NORMAL, " Credit - Kc");
} }
} }
static void print_picopass_info(const picopass_hdr *hdr) { static void print_picopass_info(const picopass_hdr *hdr) {
fuse_config(hdr); fuse_config(hdr);
mem_app_config(hdr); mem_app_config(hdr);
} }
static void printIclassDumpInfo(uint8_t *iclass_dump) { static void printIclassDumpInfo(uint8_t *iclass_dump) {
print_picopass_info((picopass_hdr *) iclass_dump); print_picopass_info((picopass_hdr *) iclass_dump);
} }
static int CmdHFiClassList(const char *Cmd) { static int CmdHFiClassList(const char *Cmd) {
(void)Cmd; // Cmd is not used so far (void)Cmd; // Cmd is not used so far
//PrintAndLogEx(NORMAL, "Deprecated command, use 'hf list iclass' instead");
CmdTraceList("iclass"); CmdTraceList("iclass");
return PM3_SUCCESS; return PM3_SUCCESS;
} }
@ -475,24 +470,9 @@ static int CmdHFiClassSim(const char *Cmd) {
return usage_hf_iclass_sim(); return usage_hf_iclass_sim();
} }
/* // remember to change the define NUM_CSNS to match.
// pre-defined 8 CSN by Holiman
uint8_t csns[8*NUM_CSNS] = { // pre-defined 9 CSN by iceman
0x00, 0x0B, 0x0F, 0xFF, 0xF7, 0xFF, 0x12, 0xE0,
0x00, 0x13, 0x94, 0x7E, 0x76, 0xFF, 0x12, 0xE0,
0x2A, 0x99, 0xAC, 0x79, 0xEC, 0xFF, 0x12, 0xE0,
0x17, 0x12, 0x01, 0xFD, 0xF7, 0xFF, 0x12, 0xE0,
0xCD, 0x56, 0x01, 0x7C, 0x6F, 0xFF, 0x12, 0xE0,
0x4B, 0x5E, 0x0B, 0x72, 0xEF, 0xFF, 0x12, 0xE0,
0x00, 0x73, 0xD8, 0x75, 0x58, 0xFF, 0x12, 0xE0,
0x0C, 0x90, 0x32, 0xF3, 0x5D, 0xFF, 0x12, 0xE0
};
*/
/*
pre-defined 9 CSN by iceman
only one csn depend on several others.
six depends only on the first csn, (0,1, 0x45)
*/
uint8_t csns[8 * NUM_CSNS] = { uint8_t csns[8 * NUM_CSNS] = {
0x01, 0x0A, 0x0F, 0xFF, 0xF7, 0xFF, 0x12, 0xE0, 0x01, 0x0A, 0x0F, 0xFF, 0xF7, 0xFF, 0x12, 0xE0,
0x0C, 0x06, 0x0C, 0xFE, 0xF7, 0xFF, 0x12, 0xE0, 0x0C, 0x06, 0x0C, 0xFE, 0xF7, 0xFF, 0x12, 0xE0,
@ -505,27 +485,6 @@ static int CmdHFiClassSim(const char *Cmd) {
0xD2, 0x5A, 0x82, 0xF8, 0xF7, 0xFF, 0x12, 0xE0 0xD2, 0x5A, 0x82, 0xF8, 0xF7, 0xFF, 0x12, 0xE0
//0x04, 0x08, 0x9F, 0x78, 0x6E, 0xFF, 0x12, 0xE0 //0x04, 0x08, 0x9F, 0x78, 0x6E, 0xFF, 0x12, 0xE0
}; };
/*
// pre-defined 15 CSN by Carl55
// remember to change the define NUM_CSNS to match.
uint8_t csns[8*NUM_CSNS] = {
0x00, 0x0B, 0x0F, 0xFF, 0xF7, 0xFF, 0x12, 0xE0,
0x00, 0x04, 0x0E, 0x08, 0xF7, 0xFF, 0x12, 0xE0,
0x00, 0x09, 0x0D, 0x05, 0xF7, 0xFF, 0x12, 0xE0,
0x00, 0x0A, 0x0C, 0x06, 0xF7, 0xFF, 0x12, 0xE0,
0x00, 0x0F, 0x0B, 0x03, 0xF7, 0xFF, 0x12, 0xE0,
0x00, 0x08, 0x0A, 0x0C, 0xF7, 0xFF, 0x12, 0xE0,
0x00, 0x0D, 0x09, 0x09, 0xF7, 0xFF, 0x12, 0xE0,
0x00, 0x0E, 0x08, 0x0A, 0xF7, 0xFF, 0x12, 0xE0,
0x00, 0x03, 0x07, 0x17, 0xF7, 0xFF, 0x12, 0xE0,
0x00, 0x3C, 0x06, 0xE0, 0xF7, 0xFF, 0x12, 0xE0,
0x00, 0x01, 0x05, 0x1D, 0xF7, 0xFF, 0x12, 0xE0,
0x00, 0x02, 0x04, 0x1E, 0xF7, 0xFF, 0x12, 0xE0,
0x00, 0x07, 0x03, 0x1B, 0xF7, 0xFF, 0x12, 0xE0,
0x00, 0x00, 0x02, 0x24, 0xF7, 0xFF, 0x12, 0xE0,
0x00, 0x05, 0x01, 0x21, 0xF7, 0xFF, 0x12, 0xE0
};
*/
/* DUMPFILE FORMAT: /* DUMPFILE FORMAT:
* *
@ -801,8 +760,6 @@ static int CmdHFiClassELoad(const char *Cmd) {
return PM3_SUCCESS; return PM3_SUCCESS;
} }
#define ICLASS_DECRYPTION_BIN "iclass_decryptionkey.bin"
static int CmdHFiClassDecrypt(const char *Cmd) { static int CmdHFiClassDecrypt(const char *Cmd) {
bool errors = false; bool errors = false;
@ -812,6 +769,7 @@ static int CmdHFiClassDecrypt(const char *Cmd) {
uint8_t cmdp = 0; uint8_t cmdp = 0;
uint8_t enc_data[8] = {0}; uint8_t enc_data[8] = {0};
uint8_t dec_data[8] = {0};
size_t keylen = 0; size_t keylen = 0;
uint8_t key[32] = {0}; uint8_t key[32] = {0};
@ -865,11 +823,14 @@ static int CmdHFiClassDecrypt(const char *Cmd) {
if (errors || cmdp < 1) return usage_hf_iclass_decrypt(); if (errors || cmdp < 1) return usage_hf_iclass_decrypt();
if (have_key == false) { bool use_sc = IsCryptoHelperPresent();
int res = loadFile_safe(ICLASS_DECRYPTION_BIN, "", (void **)&keyptr, &keylen);
if (res != PM3_SUCCESS)
return PM3_EINVARG;
if (have_key == false && use_sc == false) {
int res = loadFile_safe(ICLASS_DECRYPTION_BIN, "", (void **)&keyptr, &keylen);
if (res != PM3_SUCCESS) {
PrintAndLogEx(INFO, "Couldn't find any decryption methods");
return PM3_EINVARG;
}
memcpy(key, keyptr, sizeof(key)); memcpy(key, keyptr, sizeof(key));
free(keyptr); free(keyptr);
} }
@ -878,10 +839,13 @@ static int CmdHFiClassDecrypt(const char *Cmd) {
mbedtls_des3_context ctx; mbedtls_des3_context ctx;
mbedtls_des3_set2key_dec(&ctx, key); mbedtls_des3_set2key_dec(&ctx, key);
uint8_t dec_data[8] = {0};
if (have_data) { if (have_data) {
mbedtls_des3_crypt_ecb(&ctx, enc_data, dec_data);
if (use_sc) {
Decrypt(enc_data, dec_data);
} else {
mbedtls_des3_crypt_ecb(&ctx, enc_data, dec_data);
}
PrintAndLogEx(SUCCESS, "Data: %s", sprint_hex(dec_data, sizeof(dec_data))); PrintAndLogEx(SUCCESS, "Data: %s", sprint_hex(dec_data, sizeof(dec_data)));
} }
@ -898,14 +862,25 @@ static int CmdHFiClassDecrypt(const char *Cmd) {
uint8_t empty[8] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; uint8_t empty[8] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
BLOCK79ENCRYPTION aa1_encryption = (decrypted[(6 * 8) + 7] & 0x03);
for (uint16_t blocknum = 0; blocknum < applimit; ++blocknum) { for (uint16_t blocknum = 0; blocknum < applimit; ++blocknum) {
uint8_t idx = blocknum * 8; uint8_t idx = blocknum * 8;
memcpy(enc_data, decrypted + idx, 8); memcpy(enc_data, decrypted + idx, 8);
// block 7 or higher, and not empty 0xFF // block 7 or higher, and not empty 0xFF
if (blocknum > 6 && memcmp(enc_data, empty, 8) != 0) { // look inside block 6 to determine if aa1 is encrypted.
mbedtls_des3_crypt_ecb(&ctx, enc_data, decrypted + idx); if (blocknum > 6 && memcmp(enc_data, empty, 8) != 0) {
if (aa1_encryption == RFU || aa1_encryption == None)
continue;
if (use_sc) {
Decrypt(enc_data, decrypted + idx);
} else {
mbedtls_des3_crypt_ecb(&ctx, enc_data, decrypted + idx);
}
} }
} }
@ -920,15 +895,42 @@ static int CmdHFiClassDecrypt(const char *Cmd) {
printIclassDumpContents(decrypted, 1, (decryptedlen / 8), decryptedlen); printIclassDumpContents(decrypted, 1, (decryptedlen / 8), decryptedlen);
uint32_t top = 0, mid, bot;
mid = bytes_to_num(decrypted + (8*7), 4);
bot = bytes_to_num(decrypted + (8*7) + 4, 4);
PrintAndLogEx(INFO, ""); // decode block 6
PrintAndLogEx(INFO, "block 7 - Wiegand decode"); if (memcmp(decrypted + (8*6), empty, 8) != 0 ) {
wiegand_message_t packed = initialize_message_object(top, mid, bot); if (use_sc) {
HIDTryUnpack(&packed, true); DecodeBlock6(decrypted + (8*6));
PrintAndLogEx(INFO, "-----------------------------------------------------------------"); }
}
// decode block 7-8-9
if (memcmp(decrypted + (8*7), empty, 8) != 0 ) {
//todo: remove preamble/sentinal
uint32_t top = 0, mid, bot;
mid = bytes_to_num(decrypted + (8*7), 4);
bot = bytes_to_num(decrypted + (8*7) + 4, 4);
PrintAndLogEx(INFO, "Block 7 binary");
char hexstr[8+1] = {0};
hex_to_buffer((uint8_t *)hexstr, decrypted + (8*7), 8, sizeof(hexstr) - 1, 0, 0, true);
char binstr[8*8+1] = {0};
hextobinstring(binstr, hexstr);
uint8_t i=0;
while (i<strlen(binstr) && binstr[i++] == '0');
PrintAndLogEx(SUCCESS, "%s", binstr + i);
PrintAndLogEx(INFO, "Wiegand decode");
wiegand_message_t packed = initialize_message_object(top, mid, bot);
HIDTryUnpack(&packed, true);
PrintAndLogEx(INFO, "-----------------------------------------------------------------");
} else {
PrintAndLogEx(INFO, "No credential found.");
}
free(decrypted); free(decrypted);
free(fptr); free(fptr);
@ -984,7 +986,9 @@ static int CmdHFiClassEncryptBlk(const char *Cmd) {
if (errors || cmdp < 1) return usage_hf_iclass_encrypt(); if (errors || cmdp < 1) return usage_hf_iclass_encrypt();
if (have_key == false) { bool use_sc = IsCryptoHelperPresent();
if (have_key == false && use_sc == false) {
size_t keylen = 0; size_t keylen = 0;
int res = loadFile_safe(ICLASS_DECRYPTION_BIN, "", (void **)&keyptr, &keylen); int res = loadFile_safe(ICLASS_DECRYPTION_BIN, "", (void **)&keyptr, &keylen);
if (res != PM3_SUCCESS) if (res != PM3_SUCCESS)
@ -994,8 +998,11 @@ static int CmdHFiClassEncryptBlk(const char *Cmd) {
free(keyptr); free(keyptr);
} }
iClassEncryptBlkData(blk_data, key); if (use_sc) {
Encrypt(blk_data, blk_data);
} else {
iClassEncryptBlkData(blk_data, key);
}
printvar("encrypted block", blk_data, 8); printvar("encrypted block", blk_data, 8);
return PM3_SUCCESS; return PM3_SUCCESS;
} }
@ -1750,6 +1757,13 @@ static int ReadBlock(uint8_t *KEY, uint8_t blockno, uint8_t keyType, bool elite,
} }
PrintAndLogEx(SUCCESS, "block %02X: %s\n", blockno, sprint_hex(result->blockdata, sizeof(result->blockdata))); PrintAndLogEx(SUCCESS, "block %02X: %s\n", blockno, sprint_hex(result->blockdata, sizeof(result->blockdata)));
if (blockno == 6) {
if (IsCryptoHelperPresent()) {
DecodeBlock6(result->blockdata);
}
}
return PM3_SUCCESS; return PM3_SUCCESS;
} }

View file

@ -1339,10 +1339,10 @@ static command_t CommandTable[] = {
{"io", CmdLFIO, AlwaysAvailable, "{ ioProx RFIDs... }"}, {"io", CmdLFIO, AlwaysAvailable, "{ ioProx RFIDs... }"},
{"jablotron", CmdLFJablotron, AlwaysAvailable, "{ Jablotron RFIDs... }"}, {"jablotron", CmdLFJablotron, AlwaysAvailable, "{ Jablotron RFIDs... }"},
{"keri", CmdLFKeri, AlwaysAvailable, "{ KERI RFIDs... }"}, {"keri", CmdLFKeri, AlwaysAvailable, "{ KERI RFIDs... }"},
{"motorola", CmdLFMotorola, AlwaysAvailable, "{ Motorola RFIDs... }"},
{"nedap", CmdLFNedap, AlwaysAvailable, "{ Nedap RFIDs... }"}, {"nedap", CmdLFNedap, AlwaysAvailable, "{ Nedap RFIDs... }"},
{"nexwatch", CmdLFNEXWATCH, AlwaysAvailable, "{ NexWatch RFIDs... }"}, {"nexwatch", CmdLFNEXWATCH, AlwaysAvailable, "{ NexWatch RFIDs... }"},
{"noralsy", CmdLFNoralsy, AlwaysAvailable, "{ Noralsy RFIDs... }"}, {"noralsy", CmdLFNoralsy, AlwaysAvailable, "{ Noralsy RFIDs... }"},
{"motorola", CmdLFMotorola, AlwaysAvailable, "{ Motorola RFIDs... }"},
{"pac", CmdLFPac, AlwaysAvailable, "{ PAC/Stanley RFIDs... }"}, {"pac", CmdLFPac, AlwaysAvailable, "{ PAC/Stanley RFIDs... }"},
{"paradox", CmdLFParadox, AlwaysAvailable, "{ Paradox RFIDs... }"}, {"paradox", CmdLFParadox, AlwaysAvailable, "{ Paradox RFIDs... }"},
{"pcf7931", CmdLFPCF7931, AlwaysAvailable, "{ PCF7931 CHIPs... }"}, {"pcf7931", CmdLFPCF7931, AlwaysAvailable, "{ PCF7931 CHIPs... }"},

View file

@ -422,7 +422,10 @@ static int CmdAWIDClone(const char *Cmd) {
PrintAndLogEx(INFO, "Preparing to clone AWID %u to T55x7 with FC: %u, CN: %u", fmtlen, fc, cn); PrintAndLogEx(INFO, "Preparing to clone AWID %u to T55x7 with FC: %u, CN: %u", fmtlen, fc, cn);
print_blocks(blocks, ARRAYLEN(blocks)); print_blocks(blocks, ARRAYLEN(blocks));
return clone_t55xx_tag(blocks, ARRAYLEN(blocks)); int res = clone_t55xx_tag(blocks, ARRAYLEN(blocks));
PrintAndLogEx(SUCCESS, "Done");
PrintAndLogEx(INFO, "Hint: try " _YELLOW_("`lf awid read`") "to verify");
return res;
} }
static int CmdAWIDBrute(const char *Cmd) { static int CmdAWIDBrute(const char *Cmd) {

View file

@ -700,6 +700,8 @@ static int CmdEM410xWrite(const char *Cmd) {
} }
SendCommandMIX(CMD_LF_EM410X_WRITE, card, (uint32_t)(id >> 32), (uint32_t)id, NULL, 0); SendCommandMIX(CMD_LF_EM410X_WRITE, card, (uint32_t)(id >> 32), (uint32_t)id, NULL, 0);
PrintAndLogEx(SUCCESS, "Done");
PrintAndLogEx(INFO, "Hint: try " _YELLOW_("`lf em 410x_read`") "to verify");
return PM3_SUCCESS; return PM3_SUCCESS;
} }
@ -1037,6 +1039,9 @@ static int CmdEM4x50Write(const char *Cmd) {
uint8_t ctmp = tolower(param_getchar(Cmd, 0)); uint8_t ctmp = tolower(param_getchar(Cmd, 0));
if (ctmp == 'h') return usage_lf_em4x50_write(); if (ctmp == 'h') return usage_lf_em4x50_write();
PrintAndLogEx(NORMAL, "no implemented yet"); PrintAndLogEx(NORMAL, "no implemented yet");
//
// PrintAndLogEx(SUCCESS, "Done");
// PrintAndLogEx(INFO, "Hint: try " _YELLOW_("`lf em 4x50_read`") "to verify");
return PM3_SUCCESS; return PM3_SUCCESS;
} }
@ -1434,9 +1439,10 @@ static int CmdEM4x05Write(const char *Cmd) {
uint32_t dummy = 0; uint32_t dummy = 0;
int status = demodEM4x05resp(&dummy); int status = demodEM4x05resp(&dummy);
if (status == PM3_SUCCESS) if (status == PM3_SUCCESS)
PrintAndLogEx(NORMAL, "Write " _GREEN_("Verified")); PrintAndLogEx(SUCCESS, "Success writing to tag");
else
PrintAndLogEx(NORMAL, "Write could " _RED_("not") "be verified"); PrintAndLogEx(SUCCESS, "Done");
PrintAndLogEx(INFO, "Hint: try " _YELLOW_("`lf em 4x05_read`") "to verify");
return status; return status;
} }
static int CmdEM4x05Wipe(const char *Cmd) { static int CmdEM4x05Wipe(const char *Cmd) {

View file

@ -301,7 +301,10 @@ static int CmdFdxClone(const char *Cmd) {
PrintAndLogEx(INFO, "Preparing to clone FDX-B to T55x7 with animal ID: %04u-%"PRIu64, countryid, animalid); PrintAndLogEx(INFO, "Preparing to clone FDX-B to T55x7 with animal ID: %04u-%"PRIu64, countryid, animalid);
print_blocks(blocks, ARRAYLEN(blocks)); print_blocks(blocks, ARRAYLEN(blocks));
return clone_t55xx_tag(blocks, ARRAYLEN(blocks)); int res = clone_t55xx_tag(blocks, ARRAYLEN(blocks));
PrintAndLogEx(SUCCESS, "Done");
PrintAndLogEx(INFO, "Hint: try " _YELLOW_("`lf fdx read`") "to verify");
return res;
} }
static int CmdFdxSim(const char *Cmd) { static int CmdFdxSim(const char *Cmd) {

View file

@ -178,7 +178,10 @@ static int CmdGallagherClone(const char *Cmd) {
PrintAndLogEx(INFO, "Preparing to clone Gallagher to T55x7 with raw hex"); PrintAndLogEx(INFO, "Preparing to clone Gallagher to T55x7 with raw hex");
print_blocks(blocks, ARRAYLEN(blocks)); print_blocks(blocks, ARRAYLEN(blocks));
return clone_t55xx_tag(blocks, ARRAYLEN(blocks)); int res = clone_t55xx_tag(blocks, ARRAYLEN(blocks));
PrintAndLogEx(SUCCESS, "Done");
PrintAndLogEx(INFO, "Hint: try " _YELLOW_("`lf gallagher read`") "to verify");
return res;
} }
static int CmdGallagherSim(const char *Cmd) { static int CmdGallagherSim(const char *Cmd) {

View file

@ -83,16 +83,18 @@ static int usage_lf_hid_brute(void) {
PrintAndLogEx(NORMAL, "This is a attack against reader. if cardnumber is given, it starts with it and goes up / down one step"); PrintAndLogEx(NORMAL, "This is a attack against reader. if cardnumber is given, it starts with it and goes up / down one step");
PrintAndLogEx(NORMAL, "if cardnumber is not given, it starts with 1 and goes up to 65535"); PrintAndLogEx(NORMAL, "if cardnumber is not given, it starts with 1 and goes up to 65535");
PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Usage: lf hid brute [h] [v] w <format> [<field> (decimal)>] {...}"); PrintAndLogEx(NORMAL, "Usage: lf hid brute [h] [v] w <format> [<field> (decimal)>] [up|down] {...}");
PrintAndLogEx(NORMAL, "Options:"); PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " h : This help"); PrintAndLogEx(NORMAL, " h : This help");
PrintAndLogEx(NORMAL, " w <format> : see `wiegand list` for available formats"); PrintAndLogEx(NORMAL, " w <format> : see " _YELLOW_("`wiegand list`") "for available formats");
PrintAndLogEx(NORMAL, " f <facility-code> : facility code"); PrintAndLogEx(NORMAL, " f <facility-code> : facility code");
PrintAndLogEx(NORMAL, " c <cardnumber> : card number to start with"); PrintAndLogEx(NORMAL, " c <cardnumber> : card number to start with");
PrintAndLogEx(NORMAL, " i <issuelevel> : issue level"); PrintAndLogEx(NORMAL, " i <issuelevel> : issue level");
PrintAndLogEx(NORMAL, " o <oem> : OEM code"); PrintAndLogEx(NORMAL, " o <oem> : OEM code");
PrintAndLogEx(NORMAL, " d <delay> : delay betweens attempts in ms. Default 1000ms"); PrintAndLogEx(NORMAL, " d <delay> : delay betweens attempts in ms. Default 1000ms");
PrintAndLogEx(NORMAL, " v : verbose logging, show all tries"); PrintAndLogEx(NORMAL, " v : verbose logging, show all tries");
PrintAndLogEx(NORMAL, " up : direction to increment card number. (default is both directions)");
PrintAndLogEx(NORMAL, " down : direction to decrement card number. (default is both directions)");
PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, " lf hid brute w H10301 f 224"); PrintAndLogEx(NORMAL, " lf hid brute w H10301 f 224");
@ -343,7 +345,8 @@ static int CmdHIDClone(const char *Cmd) {
clearCommandBuffer(); clearCommandBuffer();
SendCommandMIX(CMD_LF_HID_CLONE, hi2, hi, lo, longid, sizeof(longid)); SendCommandMIX(CMD_LF_HID_CLONE, hi2, hi, lo, longid, sizeof(longid));
PrintAndLogEx(INFO, "Clone command sent. Try "_YELLOW_("'lf hid read'") " to verify"); PrintAndLogEx(SUCCESS, "Done");
PrintAndLogEx(INFO, "Hint: try " _YELLOW_("`lf hid read`") "to verify");
return PM3_SUCCESS; return PM3_SUCCESS;
} }
@ -365,14 +368,31 @@ static int CmdHIDClone(const char *Cmd) {
static int CmdHIDBrute(const char *Cmd) { static int CmdHIDBrute(const char *Cmd) {
bool errors = false, verbose = false; bool errors = false, verbose = false;
uint32_t delay = 1000; uint32_t delay = 1000;
uint8_t cmdp = 0; uint8_t cmdp = 0;
int format_idx = -1; int format_idx = -1;
int direction = 0;
char format[16] = {0}; char format[16] = {0};
wiegand_card_t data;
memset(&data, 0, sizeof(wiegand_card_t)); wiegand_card_t cn_hi, cn_low;
memset(&cn_hi, 0, sizeof(wiegand_card_t));
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
char s[10] = {0};
if (param_getstr(Cmd, cmdp, s, sizeof(s)) > 0) {
if (strlen(s) > 1) {
str_lower((char *)s);
if (str_startswith(s, "up")) {
direction = 1;
} else if (str_startswith(s, "do")) {
direction = 2;
}
cmdp++;
continue;
}
}
switch (tolower(param_getchar(Cmd, cmdp))) { switch (tolower(param_getchar(Cmd, cmdp))) {
case 'h': case 'h':
return usage_lf_hid_brute(); return usage_lf_hid_brute();
@ -386,7 +406,7 @@ static int CmdHIDBrute(const char *Cmd) {
cmdp += 2; cmdp += 2;
break; break;
case 'c': case 'c':
data.CardNumber = param_get32ex(Cmd, cmdp + 1, 0, 10); cn_hi.CardNumber = param_get32ex(Cmd, cmdp + 1, 0, 10);
cmdp += 2; cmdp += 2;
break; break;
case 'd': case 'd':
@ -395,15 +415,15 @@ static int CmdHIDBrute(const char *Cmd) {
cmdp += 2; cmdp += 2;
break; break;
case 'f': case 'f':
data.FacilityCode = param_get32ex(Cmd, cmdp + 1, 0, 10); cn_hi.FacilityCode = param_get32ex(Cmd, cmdp + 1, 0, 10);
cmdp += 2; cmdp += 2;
break; break;
case 'i': case 'i':
data.IssueLevel = param_get32ex(Cmd, cmdp + 1, 0, 10); cn_hi.IssueLevel = param_get32ex(Cmd, cmdp + 1, 0, 10);
cmdp += 2; cmdp += 2;
break; break;
case 'o': case 'o':
data.OEM = param_get32ex(Cmd, cmdp + 1, 0, 10); cn_hi.OEM = param_get32ex(Cmd, cmdp + 1, 0, 10);
cmdp += 2; cmdp += 2;
break; break;
case 'v': case 'v':
@ -416,13 +436,45 @@ static int CmdHIDBrute(const char *Cmd) {
break; break;
} }
} }
if (format_idx == -1) {
PrintAndLogEx(ERR, "You must select a wiegand format. See " _YELLOW_("`wiegand list`") "for available formats\n");
errors = true;
}
if (errors) return usage_lf_hid_brute(); if (errors) return usage_lf_hid_brute();
if (verbose) {
PrintAndLogEx(INFO, "Wiegand format#.. %i", format_idx);
PrintAndLogEx(INFO, "OEM#............. %u", cn_hi.OEM);
PrintAndLogEx(INFO, "ISSUE#........... %u", cn_hi.IssueLevel);
PrintAndLogEx(INFO, "Facility#........ %u", cn_hi.FacilityCode);
PrintAndLogEx(INFO, "Card#............ %" PRIu64, cn_hi.CardNumber);
switch( direction) {
case 0:
PrintAndLogEx(INFO, "Brute-forcing direction: " _YELLOW_("BOTH"));
break;
case 1:
PrintAndLogEx(INFO, "Brute-forcing direction: " _YELLOW_("UP"));
break;
case 2:
PrintAndLogEx(INFO, "Brute-forcing direction: " _YELLOW_("DOWN"));
break;
default: break;
}
}
PrintAndLogEx(INFO, "Brute-forcing HID reader"); PrintAndLogEx(INFO, "Brute-forcing HID reader");
PrintAndLogEx(INFO, "Press pm3-button to abort simulation or run another command"); PrintAndLogEx(INFO, "Press pm3-button to abort simulation or press `enter` to exit");
// copy values to low.
cn_low = cn_hi;
// main loop // main loop
for (;;) { // iceman: could add options for bruteforcing OEM, ISSUE or FC aswell..
bool exitloop = false;
bool fin_hi, fin_low;
fin_hi = fin_low = false;
do {
if (!session.pm3_present) { if (!session.pm3_present) {
PrintAndLogEx(WARNING, "Device offline\n"); PrintAndLogEx(WARNING, "Device offline\n");
@ -434,18 +486,44 @@ static int CmdHIDBrute(const char *Cmd) {
return sendPing(); return sendPing();
} }
// Do one up // do one up
if (data.CardNumber < 0xFFFF) { if (direction != 2) {
data.CardNumber++; if (cn_hi.CardNumber < 0xFFFF) {
if (sendTry(format_idx, &data, delay, verbose) != PM3_SUCCESS) return PM3_ESOFT; cn_hi.CardNumber++;
if (sendTry(format_idx, &cn_hi, delay, verbose) != PM3_SUCCESS) return PM3_ESOFT;
} else {
fin_hi = true;
}
} }
// Do one down (if cardnumber is given) // do one down
if (data.CardNumber > 1) { if (direction != 1) {
data.CardNumber--; if (cn_low.CardNumber > 0) {
if (sendTry(format_idx, &data, delay, verbose) != PM3_SUCCESS) return PM3_ESOFT; cn_low.CardNumber--;
if (sendTry(format_idx, &cn_low, delay, verbose) != PM3_SUCCESS) return PM3_ESOFT;
} else {
fin_low = true;
}
} }
}
switch (direction) {
case 0:
if (fin_hi && fin_low) {
exitloop = true;
}
break;
case 1:
exitloop = fin_hi;
break;
case 2:
exitloop = fin_low;
break;
default: break;
}
} while (exitloop == false);
PrintAndLogEx(INFO, "Brute forcing finished");
return PM3_SUCCESS; return PM3_SUCCESS;
} }

View file

@ -620,7 +620,10 @@ static int CmdIndalaClone(const char *Cmd) {
} }
print_blocks(blocks, max); print_blocks(blocks, max);
return clone_t55xx_tag(blocks, max); int res = clone_t55xx_tag(blocks, max);
PrintAndLogEx(SUCCESS, "Done");
PrintAndLogEx(INFO, "Hint: try " _YELLOW_("`lf indala read`") "to verify");
return res;
} }
static command_t CommandTable[] = { static command_t CommandTable[] = {

View file

@ -275,7 +275,10 @@ static int CmdIOProxClone(const char *Cmd) {
PrintAndLogEx(INFO, "Preparing to clone IOProx to T55x7 with Version: %u FC: %u, CN: %u", version, fc, cn); PrintAndLogEx(INFO, "Preparing to clone IOProx to T55x7 with Version: %u FC: %u, CN: %u", version, fc, cn);
print_blocks(blocks, ARRAYLEN(blocks)); print_blocks(blocks, ARRAYLEN(blocks));
return clone_t55xx_tag(blocks, ARRAYLEN(blocks)); int res = clone_t55xx_tag(blocks, ARRAYLEN(blocks));
PrintAndLogEx(SUCCESS, "Done");
PrintAndLogEx(INFO, "Hint: try " _YELLOW_("`lf io read`") "to verify");
return res;
} }
static command_t CommandTable[] = { static command_t CommandTable[] = {

View file

@ -181,7 +181,10 @@ static int CmdKeriDemod(const char *Cmd) {
uint32_t raw2 = bytebits_to_byte(DemodBuffer + 32, 32); uint32_t raw2 = bytebits_to_byte(DemodBuffer + 32, 32);
//get internal id //get internal id
uint32_t ID = bytebits_to_byte(DemodBuffer + 29, 32); // uint32_t ID = bytebits_to_byte(DemodBuffer + 29, 32);
// Due to the 3 sync bits being at the start of the capture
// We can take the last 32bits as the internal ID.
uint32_t ID = raw2;
ID &= 0x7FFFFFFF; ID &= 0x7FFFFFFF;
/* /*
@ -277,7 +280,10 @@ static int CmdKeriClone(const char *Cmd) {
print_blocks(blocks, ARRAYLEN(blocks)); print_blocks(blocks, ARRAYLEN(blocks));
return clone_t55xx_tag(blocks, ARRAYLEN(blocks)); int res = clone_t55xx_tag(blocks, ARRAYLEN(blocks));
PrintAndLogEx(SUCCESS, "Done");
PrintAndLogEx(INFO, "Hint: try " _YELLOW_("`lf keri read`") "to verify");
return res;
} }
static int CmdKeriSim(const char *Cmd) { static int CmdKeriSim(const char *Cmd) {

View file

@ -177,7 +177,10 @@ static int CmdMotorolaClone(const char *Cmd) {
blocks[2] = bytes_to_num(data + 4, 4); blocks[2] = bytes_to_num(data + 4, 4);
print_blocks(blocks, ARRAYLEN(blocks)); print_blocks(blocks, ARRAYLEN(blocks));
return clone_t55xx_tag(blocks, ARRAYLEN(blocks)); int res = clone_t55xx_tag(blocks, ARRAYLEN(blocks));
PrintAndLogEx(SUCCESS, "Done");
PrintAndLogEx(INFO, "Hint: try " _YELLOW_("`lf motorola read`") "to verify");
return res;
} }
static int CmdMotorolaSim(const char *Cmd) { static int CmdMotorolaSim(const char *Cmd) {

View file

@ -475,6 +475,8 @@ static int CmdLFNedapClone(const char *Cmd) {
} else { } else {
PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "");
} }
PrintAndLogEx(SUCCESS, "Done");
PrintAndLogEx(INFO, "Hint: try " _YELLOW_("`lf nedap read`") "to verify");
return res; return res;
} }

View file

@ -158,8 +158,10 @@ static int CmdNexWatchClone(const char *Cmd) {
PrintAndLogEx(INFO, "Preparing to clone NexWatch to T55x7 with raw hex"); PrintAndLogEx(INFO, "Preparing to clone NexWatch to T55x7 with raw hex");
print_blocks(blocks, ARRAYLEN(blocks)); print_blocks(blocks, ARRAYLEN(blocks));
return clone_t55xx_tag(blocks, ARRAYLEN(blocks)); int res = clone_t55xx_tag(blocks, ARRAYLEN(blocks));
PrintAndLogEx(SUCCESS, "Done");
PrintAndLogEx(INFO, "Hint: try " _YELLOW_("`lf nexwatch read`") "to verify");
return res;
} }
static int CmdNexWatchSim(const char *Cmd) { static int CmdNexWatchSim(const char *Cmd) {

View file

@ -169,7 +169,10 @@ static int CmdNoralsyClone(const char *Cmd) {
PrintAndLogEx(INFO, "Preparing to clone Noralsy to T55x7 with CardId: %u", id); PrintAndLogEx(INFO, "Preparing to clone Noralsy to T55x7 with CardId: %u", id);
print_blocks(blocks, ARRAYLEN(blocks)); print_blocks(blocks, ARRAYLEN(blocks));
return clone_t55xx_tag(blocks, ARRAYLEN(blocks)); int res = clone_t55xx_tag(blocks, ARRAYLEN(blocks));
PrintAndLogEx(SUCCESS, "Done");
PrintAndLogEx(INFO, "Hint: try " _YELLOW_("`lf noralsy read`") "to verify");
return res;
} }
static int CmdNoralsySim(const char *Cmd) { static int CmdNoralsySim(const char *Cmd) {

View file

@ -239,7 +239,10 @@ static int CmdPacClone(const char *Cmd) {
PrintAndLogEx(INFO, "Preparing to clone PAC/Stanley tag to T55x7 with raw hex"); PrintAndLogEx(INFO, "Preparing to clone PAC/Stanley tag to T55x7 with raw hex");
print_blocks(blocks, ARRAYLEN(blocks)); print_blocks(blocks, ARRAYLEN(blocks));
return clone_t55xx_tag(blocks, ARRAYLEN(blocks)); int res = clone_t55xx_tag(blocks, ARRAYLEN(blocks));
PrintAndLogEx(SUCCESS, "Done");
PrintAndLogEx(INFO, "Hint: try " _YELLOW_("`lf pac read`") "to verify");
return res;
} }
static int CmdPacSim(const char *Cmd) { static int CmdPacSim(const char *Cmd) {

View file

@ -36,7 +36,7 @@ static int usage_lf_paradox_clone(void) {
PrintAndLogEx(NORMAL, " b <raw hex> : raw hex data. 12 bytes max"); PrintAndLogEx(NORMAL, " b <raw hex> : raw hex data. 12 bytes max");
PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, " lf paradox clone 0f55555695596a6a9999a59a"); PrintAndLogEx(NORMAL, " lf paradox clone b 0f55555695596a6a9999a59a");
return PM3_SUCCESS; return PM3_SUCCESS;
} }
@ -169,7 +169,10 @@ static int CmdParadoxClone(const char *Cmd) {
PrintAndLogEx(INFO, "Preparing to clone Paradox to T55x7 with raw hex"); PrintAndLogEx(INFO, "Preparing to clone Paradox to T55x7 with raw hex");
print_blocks(blocks, ARRAYLEN(blocks)); print_blocks(blocks, ARRAYLEN(blocks));
return clone_t55xx_tag(blocks, ARRAYLEN(blocks)); int res = clone_t55xx_tag(blocks, ARRAYLEN(blocks));
PrintAndLogEx(SUCCESS, "Done");
PrintAndLogEx(INFO, "Hint: try " _YELLOW_("`lf paradox read`") "to verify");
return res;
} }
static int CmdParadoxSim(const char *Cmd) { static int CmdParadoxSim(const char *Cmd) {

View file

@ -11,6 +11,7 @@
#include "cmdlfpcf7931.h" #include "cmdlfpcf7931.h"
#include <string.h> #include <string.h>
#include <ctype.h>
#include "cmdparser.h" // command_t #include "cmdparser.h" // command_t
#include "comms.h" #include "comms.h"
@ -36,7 +37,7 @@ int pcf7931_resetConfig() {
configPcf.InitDelay = PCF7931_DEFAULT_INITDELAY; configPcf.InitDelay = PCF7931_DEFAULT_INITDELAY;
configPcf.OffsetWidth = PCF7931_DEFAULT_OFFSET_WIDTH; configPcf.OffsetWidth = PCF7931_DEFAULT_OFFSET_WIDTH;
configPcf.OffsetPosition = PCF7931_DEFAULT_OFFSET_POSITION; configPcf.OffsetPosition = PCF7931_DEFAULT_OFFSET_POSITION;
return 0; return PM3_SUCCESS;
} }
int pcf7931_printConfig() { int pcf7931_printConfig() {
@ -44,7 +45,7 @@ int pcf7931_printConfig() {
PrintAndLogEx(NORMAL, "Tag initialization delay : %d us", configPcf.InitDelay); PrintAndLogEx(NORMAL, "Tag initialization delay : %d us", configPcf.InitDelay);
PrintAndLogEx(NORMAL, "Offset low pulses width : %d us", configPcf.OffsetWidth); PrintAndLogEx(NORMAL, "Offset low pulses width : %d us", configPcf.OffsetWidth);
PrintAndLogEx(NORMAL, "Offset low pulses position : %d us", configPcf.OffsetPosition); PrintAndLogEx(NORMAL, "Offset low pulses position : %d us", configPcf.OffsetPosition);
return 0; return PM3_SUCCESS;
} }
static int usage_pcf7931_read() { static int usage_pcf7931_read() {
@ -54,7 +55,7 @@ static int usage_pcf7931_read() {
PrintAndLogEx(NORMAL, " h This help"); PrintAndLogEx(NORMAL, " h This help");
PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, " lf pcf7931 read"); PrintAndLogEx(NORMAL, " lf pcf7931 read");
return 0; return PM3_SUCCESS;
} }
static int usage_pcf7931_write() { static int usage_pcf7931_write() {
@ -67,7 +68,7 @@ static int usage_pcf7931_write() {
PrintAndLogEx(NORMAL, " data one byte of data (hex)"); PrintAndLogEx(NORMAL, " data one byte of data (hex)");
PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, " lf pcf7931 write 2 1 FF"); PrintAndLogEx(NORMAL, " lf pcf7931 write 2 1 FF");
return 0; return PM3_SUCCESS;
} }
static int usage_pcf7931_config() { static int usage_pcf7931_config() {
@ -87,30 +88,30 @@ static int usage_pcf7931_config() {
PrintAndLogEx(NORMAL, " lf pcf7931 config r"); PrintAndLogEx(NORMAL, " lf pcf7931 config r");
PrintAndLogEx(NORMAL, " lf pcf7931 config 11223344556677 20000"); PrintAndLogEx(NORMAL, " lf pcf7931 config 11223344556677 20000");
PrintAndLogEx(NORMAL, " lf pcf7931 config 11223344556677 17500 -10 30"); PrintAndLogEx(NORMAL, " lf pcf7931 config 11223344556677 17500 -10 30");
return 0; return PM3_SUCCESS;
} }
static int CmdLFPCF7931Read(const char *Cmd) { static int CmdLFPCF7931Read(const char *Cmd) {
uint8_t ctmp = param_getchar(Cmd, 0); uint8_t ctmp = tolower(param_getchar(Cmd, 0));
if (ctmp == 'H' || ctmp == 'h') return usage_pcf7931_read(); if (ctmp == 'h') return usage_pcf7931_read();
PacketResponseNG resp; PacketResponseNG resp;
clearCommandBuffer(); clearCommandBuffer();
SendCommandNG(CMD_LF_PCF7931_READ, NULL, 0); SendCommandNG(CMD_LF_PCF7931_READ, NULL, 0);
if (!WaitForResponseTimeout(CMD_ACK, &resp, 2500)) { if (!WaitForResponseTimeout(CMD_ACK, &resp, 2500)) {
PrintAndLogEx(WARNING, "command execution time out"); PrintAndLogEx(WARNING, "command execution time out");
return 1; return PM3_ETIMEOUT;
} }
return 0; return PM3_SUCCESS;
} }
static int CmdLFPCF7931Config(const char *Cmd) { static int CmdLFPCF7931Config(const char *Cmd) {
uint8_t ctmp = param_getchar(Cmd, 0); uint8_t ctmp = tolower(param_getchar(Cmd, 0));
if (ctmp == 0) return pcf7931_printConfig(); if (ctmp == 0) return pcf7931_printConfig();
if (ctmp == 'H' || ctmp == 'h') return usage_pcf7931_config(); if (ctmp == 'h') return usage_pcf7931_config();
if (ctmp == 'R' || ctmp == 'r') return pcf7931_resetConfig(); if (ctmp == 'r') return pcf7931_resetConfig();
if (param_gethex(Cmd, 0, configPcf.Pwd, 14)) return usage_pcf7931_config(); if (param_gethex(Cmd, 0, configPcf.Pwd, 14)) return usage_pcf7931_config();
@ -119,13 +120,13 @@ static int CmdLFPCF7931Config(const char *Cmd) {
configPcf.OffsetPosition = (int)(param_get32ex(Cmd, 3, 0, 10) & 0xFFFF); configPcf.OffsetPosition = (int)(param_get32ex(Cmd, 3, 0, 10) & 0xFFFF);
pcf7931_printConfig(); pcf7931_printConfig();
return 0; return PM3_SUCCESS;
} }
static int CmdLFPCF7931Write(const char *Cmd) { static int CmdLFPCF7931Write(const char *Cmd) {
uint8_t ctmp = param_getchar(Cmd, 0); uint8_t ctmp = tolower(param_getchar(Cmd, 0));
if (strlen(Cmd) < 1 || ctmp == 'h' || ctmp == 'H') return usage_pcf7931_write(); if (strlen(Cmd) < 1 || ctmp == 'h') return usage_pcf7931_write();
uint8_t block = 0, bytepos = 0, data = 0; uint8_t block = 0, bytepos = 0, data = 0;
@ -136,9 +137,9 @@ static int CmdLFPCF7931Write(const char *Cmd) {
data = param_get8ex(Cmd, 2, 0, 16); data = param_get8ex(Cmd, 2, 0, 16);
PrintAndLogEx(NORMAL, "Writing block: %d", block); PrintAndLogEx(INFO, "Writing block: %d", block);
PrintAndLogEx(NORMAL, " pos: %d", bytepos); PrintAndLogEx(INFO, " pos: %d", bytepos);
PrintAndLogEx(NORMAL, " data: 0x%02X", data); PrintAndLogEx(INFO, " data: 0x%02X", data);
uint32_t buf[10]; // TODO sparse struct, 7 *bytes* then words at offset 4*7! uint32_t buf[10]; // TODO sparse struct, 7 *bytes* then words at offset 4*7!
memcpy(buf, configPcf.Pwd, sizeof(configPcf.Pwd)); memcpy(buf, configPcf.Pwd, sizeof(configPcf.Pwd));
@ -147,9 +148,11 @@ static int CmdLFPCF7931Write(const char *Cmd) {
buf[9] = configPcf.InitDelay; buf[9] = configPcf.InitDelay;
clearCommandBuffer(); clearCommandBuffer();
SendCommandOLD(CMD_LF_PCF7931_WRITE, block, bytepos, data, buf, sizeof(buf)); SendCommandMIX(CMD_LF_PCF7931_WRITE, block, bytepos, data, buf, sizeof(buf));
//no ack?
return 0; PrintAndLogEx(SUCCESS, "Done");
PrintAndLogEx(INFO, "Hint: try " _YELLOW_("`lf pcf7931 read`") "to verify");
return PM3_SUCCESS;
} }
static command_t CommandTable[] = { static command_t CommandTable[] = {
@ -163,7 +166,7 @@ static command_t CommandTable[] = {
static int CmdHelp(const char *Cmd) { static int CmdHelp(const char *Cmd) {
(void)Cmd; // Cmd is not used so far (void)Cmd; // Cmd is not used so far
CmdsHelp(CommandTable); CmdsHelp(CommandTable);
return 0; return PM3_SUCCESS;
} }
int CmdLFPCF7931(const char *Cmd) { int CmdLFPCF7931(const char *Cmd) {

View file

@ -136,7 +136,10 @@ static int CmdPrescoClone(const char *Cmd) {
PrintAndLogEx(INFO, "Preparing to clone Presco to T55x7 with SiteCode: %u, UserCode: %u, FullCode: %08x", sitecode, usercode, fullcode); PrintAndLogEx(INFO, "Preparing to clone Presco to T55x7 with SiteCode: %u, UserCode: %u, FullCode: %08x", sitecode, usercode, fullcode);
print_blocks(blocks, ARRAYLEN(blocks)); print_blocks(blocks, ARRAYLEN(blocks));
return clone_t55xx_tag(blocks, ARRAYLEN(blocks)); int res = clone_t55xx_tag(blocks, ARRAYLEN(blocks));
PrintAndLogEx(SUCCESS, "Done");
PrintAndLogEx(INFO, "Hint: try " _YELLOW_("`lf presco read`") "to verify");
return res;
} }
// takes base 12 ID converts to hex // takes base 12 ID converts to hex

View file

@ -250,7 +250,10 @@ static int CmdPyramidClone(const char *Cmd) {
PrintAndLogEx(INFO, "Preparing to clone Farpointe/Pyramid to T55x7 with Facility Code: %u, Card Number: %u", facilitycode, cardnumber); PrintAndLogEx(INFO, "Preparing to clone Farpointe/Pyramid to T55x7 with Facility Code: %u, Card Number: %u", facilitycode, cardnumber);
print_blocks(blocks, ARRAYLEN(blocks)); print_blocks(blocks, ARRAYLEN(blocks));
return clone_t55xx_tag(blocks, ARRAYLEN(blocks)); int res = clone_t55xx_tag(blocks, ARRAYLEN(blocks));
PrintAndLogEx(SUCCESS, "Done");
PrintAndLogEx(INFO, "Hint: try " _YELLOW_("`lf pyramid read`") "to verify");
return res;
} }
static int CmdPyramidSim(const char *Cmd) { static int CmdPyramidSim(const char *Cmd) {

View file

@ -168,7 +168,10 @@ static int CmdSecurakeyClone(const char *Cmd) {
PrintAndLogEx(INFO, "Preparing to clone Securakey to T55x7 with raw hex"); PrintAndLogEx(INFO, "Preparing to clone Securakey to T55x7 with raw hex");
print_blocks(blocks, ARRAYLEN(blocks)); print_blocks(blocks, ARRAYLEN(blocks));
return clone_t55xx_tag(blocks, ARRAYLEN(blocks)); int res = clone_t55xx_tag(blocks, ARRAYLEN(blocks));
PrintAndLogEx(SUCCESS, "Done");
PrintAndLogEx(INFO, "Hint: try " _YELLOW_("`lf securakey read`") "to verify");
return res;
} }
static int CmdSecurakeySim(const char *Cmd) { static int CmdSecurakeySim(const char *Cmd) {

View file

@ -1028,7 +1028,6 @@ void T55xx_Print_DownlinkMode(uint8_t downlink_mode) {
PrintAndLogEx(NORMAL, msg); PrintAndLogEx(NORMAL, msg);
} }
static int CmdT55xxDetect(const char *Cmd) { static int CmdT55xxDetect(const char *Cmd) {
bool errors = false; bool errors = false;

View file

@ -296,6 +296,8 @@ static int CmdTIWrite(const char *Cmd) {
} }
clearCommandBuffer(); clearCommandBuffer();
SendCommandMIX(CMD_LF_TI_WRITE, arg0, arg1, arg2, NULL, 0); SendCommandMIX(CMD_LF_TI_WRITE, arg0, arg1, arg2, NULL, 0);
PrintAndLogEx(SUCCESS, "Done");
PrintAndLogEx(INFO, "Hint: try " _YELLOW_("`lf ti read`") "to verify");
return PM3_SUCCESS; return PM3_SUCCESS;
} }

View file

@ -121,7 +121,10 @@ static int CmdVerichipClone(const char *Cmd) {
PrintAndLogEx(INFO, "Preparing to clone Verichip to T55x7 with raw hex"); PrintAndLogEx(INFO, "Preparing to clone Verichip to T55x7 with raw hex");
print_blocks(blocks, ARRAYLEN(blocks)); print_blocks(blocks, ARRAYLEN(blocks));
return clone_t55xx_tag(blocks, ARRAYLEN(blocks)); int res = clone_t55xx_tag(blocks, ARRAYLEN(blocks));
PrintAndLogEx(SUCCESS, "Done");
PrintAndLogEx(INFO, "Hint: try " _YELLOW_("`lf verichip read`") "to verify");
return res;
} }
static int CmdVerichipSim(const char *Cmd) { static int CmdVerichipSim(const char *Cmd) {

View file

@ -117,6 +117,8 @@ static int CmdVikingClone(const char *Cmd) {
PrintAndLogEx(ERR, "Error occurred, device did not respond during write operation."); PrintAndLogEx(ERR, "Error occurred, device did not respond during write operation.");
return PM3_ETIMEOUT; return PM3_ETIMEOUT;
} }
PrintAndLogEx(SUCCESS, "Done");
PrintAndLogEx(INFO, "Hint: try " _YELLOW_("`lf viking read`") "to verify");
return resp.status; return resp.status;
} }

View file

@ -184,7 +184,10 @@ static int CmdVisa2kClone(const char *Cmd) {
PrintAndLogEx(INFO, "Preparing to clone Visa2000 to T55x7 with CardId: %"PRIu64, id); PrintAndLogEx(INFO, "Preparing to clone Visa2000 to T55x7 with CardId: %"PRIu64, id);
print_blocks(blocks, ARRAYLEN(blocks)); print_blocks(blocks, ARRAYLEN(blocks));
return clone_t55xx_tag(blocks, ARRAYLEN(blocks)); int res = clone_t55xx_tag(blocks, ARRAYLEN(blocks));
PrintAndLogEx(SUCCESS, "Done");
PrintAndLogEx(INFO, "Hint: try " _YELLOW_("`lf visa2000 read`") "to verify");
return res;
} }
static int CmdVisa2kSim(const char *Cmd) { static int CmdVisa2kSim(const char *Cmd) {

View file

@ -59,11 +59,13 @@ static int CmdScriptRun(const char *Cmd) {
if ((!str_endswith(preferredName, ".cmd")) && (searchFile(&script_path, LUA_SCRIPTS_SUBDIR, preferredName, ".lua", true) == PM3_SUCCESS)) { if ((!str_endswith(preferredName, ".cmd")) && (searchFile(&script_path, LUA_SCRIPTS_SUBDIR, preferredName, ".lua", true) == PM3_SUCCESS)) {
int error; int error;
if (luascriptfile_idx == MAX_NESTED_LUASCRIPT) { if (luascriptfile_idx == MAX_NESTED_LUASCRIPT) {
PrintAndLogEx(ERR, "Too many nested scripts, skipping %s\n", script_path); PrintAndLogEx(ERR, "too many nested scripts, skipping %s\n", script_path);
free(script_path); free(script_path);
return PM3_EMALLOC; return PM3_EMALLOC;
} }
PrintAndLogEx(SUCCESS, "Executing Lua script: %s, args '%s'\n", script_path, arguments); PrintAndLogEx(SUCCESS, "executing lua " _YELLOW_("%s"), script_path);
PrintAndLogEx(SUCCESS, "args " _YELLOW_("'%s'"), arguments);
luascriptfile_idx++; luascriptfile_idx++;
// create new Lua state // create new Lua state
@ -94,7 +96,7 @@ static int CmdScriptRun(const char *Cmd) {
if (error) { // if non-0, then an error if (error) { // if non-0, then an error
// the top of the stack should be the error string // the top of the stack should be the error string
if (!lua_isstring(lua_state, lua_gettop(lua_state))) if (!lua_isstring(lua_state, lua_gettop(lua_state)))
PrintAndLogEx(FAILED, "Error - but no error (?!)"); PrintAndLogEx(FAILED, "error - but no error (?!)");
// get the top of the stack as the error and pop it off // get the top of the stack as the error and pop it off
const char *str = lua_tostring(lua_state, lua_gettop(lua_state)); const char *str = lua_tostring(lua_state, lua_gettop(lua_state));
@ -106,17 +108,22 @@ static int CmdScriptRun(const char *Cmd) {
// close the Lua state // close the Lua state
lua_close(lua_state); lua_close(lua_state);
luascriptfile_idx--; luascriptfile_idx--;
PrintAndLogEx(SUCCESS, "\nFinished %s\n", preferredName); PrintAndLogEx(SUCCESS, "\nfinished " _YELLOW_("%s"), preferredName);
return PM3_SUCCESS; return PM3_SUCCESS;
} }
if ((!str_endswith(preferredName, ".lua")) && (searchFile(&script_path, CMD_SCRIPTS_SUBDIR, preferredName, ".cmd", true) == PM3_SUCCESS)) { if ((!str_endswith(preferredName, ".lua")) && (searchFile(&script_path, CMD_SCRIPTS_SUBDIR, preferredName, ".cmd", true) == PM3_SUCCESS)) {
PrintAndLogEx(SUCCESS, "Executing Cmd script: %s, args '%s'\n", script_path, arguments);
PrintAndLogEx(SUCCESS, "executing Cmd " _YELLOW_("%s"), script_path);
PrintAndLogEx(SUCCESS, "args " _YELLOW_("'%s'"), arguments);
int ret = push_cmdscriptfile(script_path, true); int ret = push_cmdscriptfile(script_path, true);
if (ret != PM3_SUCCESS) if (ret != PM3_SUCCESS)
PrintAndLogEx(ERR, "could not open " _YELLOW_("%s") "...", script_path); PrintAndLogEx(ERR, "could not open " _YELLOW_("%s") "...", script_path);
free(script_path); free(script_path);
return ret; return ret;
} }
// file not found, let's search again to display the error messages // file not found, let's search again to display the error messages
int ret = PM3_EUNDEF; int ret = PM3_EUNDEF;
if (!str_endswith(preferredName, ".cmd")) ret = searchFile(&script_path, LUA_SCRIPTS_SUBDIR, preferredName, ".lua", false); if (!str_endswith(preferredName, ".cmd")) ret = searchFile(&script_path, LUA_SCRIPTS_SUBDIR, preferredName, ".lua", false);
@ -141,7 +148,7 @@ static command_t CommandTable[] = {
static int CmdHelp(const char *Cmd) { static int CmdHelp(const char *Cmd) {
(void)Cmd; // Cmd is not used so far (void)Cmd; // Cmd is not used so far
PrintAndLogEx(NORMAL, "This is a feature to run Lua-scripts. You can place Lua-scripts within the luascripts/-folder. "); PrintAndLogEx(NORMAL, "This is a feature to run Lua-scripts. You can place Lua-scripts within the luascripts/-folder. ");
return 0; return PM3_SUCCESS;
} }
/** /**

View file

@ -216,23 +216,23 @@ static int PrintATR(uint8_t *atr, size_t atrlen) {
bool protocol_T15_present = false; bool protocol_T15_present = false;
if (T0 & 0x10) { if (T0 & 0x10) {
PrintAndLogEx(NORMAL, "\t- TA1 (Maximum clock frequency, proposed bit duration) [ 0x%02x ]", atr[2 + T1len]); PrintAndLogEx(INFO, "\t- TA1 (Maximum clock frequency, proposed bit duration) [ 0x%02x ]", atr[2 + T1len]);
T1len++; T1len++;
} }
if (T0 & 0x20) { if (T0 & 0x20) {
PrintAndLogEx(NORMAL, "\t- TB1 (Deprecated: VPP requirements) [ 0x%02x ]", atr[2 + T1len]); PrintAndLogEx(INFO, "\t- TB1 (Deprecated: VPP requirements) [ 0x%02x ]", atr[2 + T1len]);
T1len++; T1len++;
} }
if (T0 & 0x40) { if (T0 & 0x40) {
PrintAndLogEx(NORMAL, "\t- TC1 (Extra delay between bytes required by card) [ 0x%02x ]", atr[2 + T1len]); PrintAndLogEx(INFO, "\t- TC1 (Extra delay between bytes required by card) [ 0x%02x ]", atr[2 + T1len]);
T1len++; T1len++;
} }
if (T0 & 0x80) { if (T0 & 0x80) {
uint8_t TD1 = atr[2 + T1len]; uint8_t TD1 = atr[2 + T1len];
PrintAndLogEx(NORMAL, "\t- TD1 (First offered transmission protocol, presence of TA2..TD2) [ 0x%02x ] Protocol T%d", TD1, TD1 & 0x0f); PrintAndLogEx(INFO, "\t- TD1 (First offered transmission protocol, presence of TA2..TD2) [ 0x%02x ] Protocol T%d", TD1, TD1 & 0x0f);
protocol_T0_present = false; protocol_T0_present = false;
if ((TD1 & 0x0f) == 0) { if ((TD1 & 0x0f) == 0) {
protocol_T0_present = true; protocol_T0_present = true;
@ -244,20 +244,20 @@ static int PrintATR(uint8_t *atr, size_t atrlen) {
T1len++; T1len++;
if (TD1 & 0x10) { if (TD1 & 0x10) {
PrintAndLogEx(NORMAL, "\t- TA2 (Specific protocol and parameters to be used after the ATR) [ 0x%02x ]", atr[2 + T1len + TD1len]); PrintAndLogEx(INFO, "\t- TA2 (Specific protocol and parameters to be used after the ATR) [ 0x%02x ]", atr[2 + T1len + TD1len]);
TD1len++; TD1len++;
} }
if (TD1 & 0x20) { if (TD1 & 0x20) {
PrintAndLogEx(NORMAL, "\t- TB2 (Deprecated: VPP precise voltage requirement) [ 0x%02x ]", atr[2 + T1len + TD1len]); PrintAndLogEx(INFO, "\t- TB2 (Deprecated: VPP precise voltage requirement) [ 0x%02x ]", atr[2 + T1len + TD1len]);
TD1len++; TD1len++;
} }
if (TD1 & 0x40) { if (TD1 & 0x40) {
PrintAndLogEx(NORMAL, "\t- TC2 (Maximum waiting time for protocol T=0) [ 0x%02x ]", atr[2 + T1len + TD1len]); PrintAndLogEx(INFO, "\t- TC2 (Maximum waiting time for protocol T=0) [ 0x%02x ]", atr[2 + T1len + TD1len]);
TD1len++; TD1len++;
} }
if (TD1 & 0x80) { if (TD1 & 0x80) {
uint8_t TDi = atr[2 + T1len + TD1len]; uint8_t TDi = atr[2 + T1len + TD1len];
PrintAndLogEx(NORMAL, "\t- TD2 (A supported protocol or more global parameters, presence of TA3..TD3) [ 0x%02x ] Protocol T%d", TDi, TDi & 0x0f); PrintAndLogEx(INFO, "\t- TD2 (A supported protocol or more global parameters, presence of TA3..TD3) [ 0x%02x ] Protocol T%d", TDi, TDi & 0x0f);
if ((TDi & 0x0f) == 0) { if ((TDi & 0x0f) == 0) {
protocol_T0_present = true; protocol_T0_present = true;
} }
@ -271,20 +271,20 @@ static int PrintATR(uint8_t *atr, size_t atrlen) {
while (nextCycle) { while (nextCycle) {
nextCycle = false; nextCycle = false;
if (TDi & 0x10) { if (TDi & 0x10) {
PrintAndLogEx(NORMAL, "\t- TA%d: 0x%02x", vi, atr[2 + T1len + TD1len + TDilen]); PrintAndLogEx(INFO, "\t- TA%d: 0x%02x", vi, atr[2 + T1len + TD1len + TDilen]);
TDilen++; TDilen++;
} }
if (TDi & 0x20) { if (TDi & 0x20) {
PrintAndLogEx(NORMAL, "\t- TB%d: 0x%02x", vi, atr[2 + T1len + TD1len + TDilen]); PrintAndLogEx(INFO, "\t- TB%d: 0x%02x", vi, atr[2 + T1len + TD1len + TDilen]);
TDilen++; TDilen++;
} }
if (TDi & 0x40) { if (TDi & 0x40) {
PrintAndLogEx(NORMAL, "\t- TC%d: 0x%02x", vi, atr[2 + T1len + TD1len + TDilen]); PrintAndLogEx(INFO, "\t- TC%d: 0x%02x", vi, atr[2 + T1len + TD1len + TDilen]);
TDilen++; TDilen++;
} }
if (TDi & 0x80) { if (TDi & 0x80) {
TDi = atr[2 + T1len + TD1len + TDilen]; TDi = atr[2 + T1len + TD1len + TDilen];
PrintAndLogEx(NORMAL, "\t- TD%d [ 0x%02x ] Protocol T%d", vi, TDi, TDi & 0x0f); PrintAndLogEx(INFO, "\t- TD%d [ 0x%02x ] Protocol T%d", vi, TDi, TDi & 0x0f);
TDilen++; TDilen++;
nextCycle = true; nextCycle = true;
@ -314,7 +314,7 @@ static int PrintATR(uint8_t *atr, size_t atrlen) {
PrintAndLogEx(WARNING, "Invalid ATR length. len: %zu, T1len: %d, TD1len: %d, TDilen: %d, K: %d", atrlen, T1len, TD1len, TDilen, K); PrintAndLogEx(WARNING, "Invalid ATR length. len: %zu, T1len: %d, TD1len: %d, TDilen: %d, K: %d", atrlen, T1len, TD1len, TDilen, K);
if (K > 0) if (K > 0)
PrintAndLogEx(INFO, "\nHistorical bytes | len 0x%02d | format %02x", K, atr[2 + T1len + TD1len + TDilen]); PrintAndLogEx(INFO, "Historical bytes | len 0x%02d | format %02x", K, atr[2 + T1len + TD1len + TDilen]);
if (K > 1) { if (K > 1) {
PrintAndLogEx(INFO, "\tHistorical bytes"); PrintAndLogEx(INFO, "\tHistorical bytes");
@ -361,7 +361,9 @@ static int smart_responseEx(uint8_t *data, bool silent) {
if (needGetData) { if (needGetData) {
int len = data[datalen - 1]; int len = data[datalen - 1];
if (!silent) PrintAndLogEx(INFO, "Requesting 0x%02X bytes response", len); if (!silent) PrintAndLogEx(INFO, "Requesting 0x%02X bytes response", len);
uint8_t getstatus[] = {0x00, ISO7816_GET_RESPONSE, 0x00, 0x00, len}; uint8_t getstatus[] = {0x00, ISO7816_GET_RESPONSE, 0x00, 0x00, len};
clearCommandBuffer(); clearCommandBuffer();
SendCommandOLD(CMD_SMART_RAW, SC_RAW, sizeof(getstatus), 0, getstatus, sizeof(getstatus)); SendCommandOLD(CMD_SMART_RAW, SC_RAW, sizeof(getstatus), 0, getstatus, sizeof(getstatus));
@ -740,10 +742,9 @@ static int CmdSmartInfo(const char *Cmd) {
PrintAndLogEx(INFO, "--- Smartcard Information ---------"); PrintAndLogEx(INFO, "--- Smartcard Information ---------");
PrintAndLogEx(INFO, "-------------------------------------------------------------"); PrintAndLogEx(INFO, "-------------------------------------------------------------");
PrintAndLogEx(INFO, "ISO7618-3 ATR : %s", sprint_hex(card.atr, card.atr_len)); PrintAndLogEx(INFO, "ISO7618-3 ATR : %s", sprint_hex(card.atr, card.atr_len));
PrintAndLogEx(INFO, "\nhttp://smartcard-atr.apdu.fr/parse?ATR=%s", sprint_hex_inrow(card.atr, card.atr_len)); PrintAndLogEx(INFO, "http://smartcard-atr.apdu.fr/parse?ATR=%s", sprint_hex_inrow(card.atr, card.atr_len));
// print ATR // print ATR
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(INFO, "ATR"); PrintAndLogEx(INFO, "ATR");
PrintATR(card.atr, card.atr_len); PrintATR(card.atr, card.atr_len);
@ -756,14 +757,14 @@ static int CmdSmartInfo(const char *Cmd) {
if (GetATRTA1(card.atr, card.atr_len) == 0x11) if (GetATRTA1(card.atr, card.atr_len) == 0x11)
PrintAndLogEx(INFO, "Using default values..."); PrintAndLogEx(INFO, "Using default values...");
PrintAndLogEx(NORMAL, "\t- Di %d", Di); PrintAndLogEx(INFO, "\t- Di %d", Di);
PrintAndLogEx(NORMAL, "\t- Fi %d", Fi); PrintAndLogEx(INFO, "\t- Fi %d", Fi);
PrintAndLogEx(NORMAL, "\t- F %.1f MHz", F); PrintAndLogEx(INFO, "\t- F %.1f MHz", F);
if (Di && Fi) { if (Di && Fi) {
PrintAndLogEx(NORMAL, "\t- Cycles/ETU %d", Fi / Di); PrintAndLogEx(INFO, "\t- Cycles/ETU %d", Fi / Di);
PrintAndLogEx(NORMAL, "\t- %.1f bits/sec at 4 MHz", (float)4000000 / (Fi / Di)); PrintAndLogEx(INFO, "\t- %.1f bits/sec at 4 MHz", (float)4000000 / (Fi / Di));
PrintAndLogEx(NORMAL, "\t- %.1f bits/sec at Fmax (%.1fMHz)", (F * 1000000) / (Fi / Di), F); PrintAndLogEx(INFO, "\t- %.1f bits/sec at Fmax (%.1fMHz)", (F * 1000000) / (Fi / Di), F);
} else { } else {
PrintAndLogEx(WARNING, "\t- Di or Fi is RFU."); PrintAndLogEx(WARNING, "\t- Di or Fi is RFU.");
}; };
@ -1156,11 +1157,12 @@ int CmdSmartcard(const char *Cmd) {
return CmdsParse(CommandTable, Cmd); return CmdsParse(CommandTable, Cmd);
} }
int ExchangeAPDUSC(uint8_t *datain, int datainlen, bool activateCard, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen) { int ExchangeAPDUSC(bool silent, uint8_t *datain, int datainlen, bool activateCard, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen) {
*dataoutlen = 0; *dataoutlen = 0;
if (activateCard) if (activateCard)
smart_select(false, NULL); smart_select(true, NULL);
PrintAndLogEx(DEBUG, "APDU SC"); PrintAndLogEx(DEBUG, "APDU SC");
@ -1168,10 +1170,11 @@ int ExchangeAPDUSC(uint8_t *datain, int datainlen, bool activateCard, bool leave
if (activateCard) { if (activateCard) {
flags |= SC_SELECT | SC_CONNECT; flags |= SC_SELECT | SC_CONNECT;
} }
clearCommandBuffer(); clearCommandBuffer();
SendCommandOLD(CMD_SMART_RAW, flags, datainlen, 0, datain, datainlen); SendCommandOLD(CMD_SMART_RAW, flags, datainlen, 0, datain, datainlen);
int len = smart_responseEx(dataout, true); int len = smart_responseEx(dataout, silent);
if (len < 0) { if (len < 0) {
return 1; return 1;
@ -1189,7 +1192,7 @@ int ExchangeAPDUSC(uint8_t *datain, int datainlen, bool activateCard, bool leave
// something fishy: we have only 5 bytes but we put datainlen in arg1? // something fishy: we have only 5 bytes but we put datainlen in arg1?
SendCommandOLD(CMD_SMART_RAW, SC_RAW_T0, datainlen, 0, data, sizeof(data)); SendCommandOLD(CMD_SMART_RAW, SC_RAW_T0, datainlen, 0, data, sizeof(data));
len = smart_responseEx(dataout, true); len = smart_responseEx(dataout, silent);
} }
*dataoutlen = len; *dataoutlen = len;
@ -1204,6 +1207,7 @@ bool smart_select(bool silent, smart_card_atr_t *atr) {
SendCommandNG(CMD_SMART_ATR, NULL, 0); SendCommandNG(CMD_SMART_ATR, NULL, 0);
PacketResponseNG resp; PacketResponseNG resp;
if (!WaitForResponseTimeout(CMD_ACK, &resp, 2500)) { if (!WaitForResponseTimeout(CMD_ACK, &resp, 2500)) {
if (!silent) PrintAndLogEx(WARNING, "smart card select failed"); if (!silent) PrintAndLogEx(WARNING, "smart card select failed");
return false; return false;
} }

View file

@ -17,6 +17,6 @@
int CmdSmartcard(const char *Cmd); int CmdSmartcard(const char *Cmd);
bool smart_select(bool silent, smart_card_atr_t *atr); bool smart_select(bool silent, smart_card_atr_t *atr);
int ExchangeAPDUSC(uint8_t *datain, int datainlen, bool activateCard, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen); int ExchangeAPDUSC(bool silent, uint8_t *datain, int datainlen, bool activateCard, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen);
#endif #endif

View file

@ -305,7 +305,7 @@ static int EMVExchangeEx(EMVCommandChannel channel, bool ActivateField, bool Lea
break; break;
case ECC_CONTACT: case ECC_CONTACT:
if (IfPm3Smartcard()) if (IfPm3Smartcard())
res = ExchangeAPDUSC(data, datalen, ActivateField, LeaveFieldON, Result, (int)MaxResultLen, (int *)ResultLen); res = ExchangeAPDUSC(true, data, datalen, ActivateField, LeaveFieldON, Result, (int)MaxResultLen, (int *)ResultLen);
else else
res = 1; res = 1;
if (res) { if (res) {

View file

@ -544,8 +544,7 @@ int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo,
return -5; return -5;
} }
uint64_t t2 = msclock(); float bruteforce_per_second = (float)KEYS_IN_BLOCK / (msclock() - start_time) * 1000.0;
float bruteforce_per_second = (float)KEYS_IN_BLOCK / (float)(t2 - start_time) * 1000.0;
if ( i + 1 % 10 == 0) if ( i + 1 % 10 == 0)
PrintAndLogEx(INFO, " %6d/%u keys | %5.1f keys/sec | worst case %6.1f seconds remaining", i, keycnt , bruteforce_per_second, (keycnt-i) / bruteforce_per_second); PrintAndLogEx(INFO, " %6d/%u keys | %5.1f keys/sec | worst case %6.1f seconds remaining", i, keycnt , bruteforce_per_second, (keycnt-i) / bruteforce_per_second);
@ -676,6 +675,7 @@ int mfStaticNested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBl
//flush queue //flush queue
while (kbd_enter_pressed()) { while (kbd_enter_pressed()) {
SendCommandNG(CMD_BREAK_LOOP, NULL, 0); SendCommandNG(CMD_BREAK_LOOP, NULL, 0);
free(mem);
return PM3_EOPABORTED; return PM3_EOPABORTED;
} }
@ -695,6 +695,7 @@ int mfStaticNested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBl
res = flashmem_spiffs_load(destfn, mem, 5 + (chunk * 6) ); res = flashmem_spiffs_load(destfn, mem, 5 + (chunk * 6) );
if (res != PM3_SUCCESS) { if (res != PM3_SUCCESS) {
PrintAndLogEx(WARNING, "SPIFFS upload failed"); PrintAndLogEx(WARNING, "SPIFFS upload failed");
free(mem);
return res; return res;
} }
@ -717,11 +718,12 @@ int mfStaticNested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBl
); );
return PM3_SUCCESS; return PM3_SUCCESS;
} else if (res == PM3_ETIMEOUT || res == PM3_EOPABORTED) { } else if (res == PM3_ETIMEOUT || res == PM3_EOPABORTED) {
free(mem);
return res; return res;
} }
// if (i%10 == 0) { // if (i%10 == 0) {
float bruteforce_per_second = (float)i + max_keys_chunk / (float)(msclock() - start_time) * 1000.0; float bruteforce_per_second = (float)i + max_keys_chunk / (msclock() - start_time) * 1000.0;
PrintAndLogEx(INFO, "Chunk %6u/%u keys | %5.1f keys/sec | worst case %6.1f seconds remaining", i, keycnt, bruteforce_per_second, (keycnt-i) / bruteforce_per_second); PrintAndLogEx(INFO, "Chunk %6u/%u keys | %5.1f keys/sec | worst case %6.1f seconds remaining", i, keycnt, bruteforce_per_second, (keycnt-i) / bruteforce_per_second);
// } // }
} }

83
common/cardhelper.c Normal file
View file

@ -0,0 +1,83 @@
//-----------------------------------------------------------------------------
// Iceman, February 2020
//
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
// at your option, any later version. See the LICENSE.txt file for the text of
// the license.
//-----------------------------------------------------------------------------
// Support functions for smart card
//-----------------------------------------------------------------------------
#include "cardhelper.h"
#include <string.h>
#include <stdio.h>
#include "cmdparser.h"
#include "cmdsmartcard.h"
#include "ui.h"
#include "util.h"
#define CARD_INS_DECRYPT 0x01
#define CARD_INS_ENCRYPT 0x02
#define CARD_INS_DECODE 0x06
static uint8_t cmd[] = {0x96, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
// look for CryptoHelper
bool IsCryptoHelperPresent(void) {
if (IfPm3Smartcard()) {
int resp_len = 0;
uint8_t version[] = {0x96, 0x69, 0x00, 0x00, 0x00};
uint8_t resp[20] = {0};
ExchangeAPDUSC(true, version, sizeof(version), true, true, resp, sizeof(resp), &resp_len);
if (strstr("CryptoHelper", (char*)resp) == 0) {
PrintAndLogEx(INFO, "Found smart card helper");
return true;
} else {
return false;
}
} else {
return false;
}
}
static bool executeCrypto(uint8_t ins, uint8_t *src, uint8_t *dest) {
int resp_len = 0;
uint8_t dec[11] = {0};
cmd[1] = ins;
memcpy(cmd + 5, src, 8);
ExchangeAPDUSC(true, cmd, sizeof(cmd), false, true, dec, sizeof(dec), &resp_len);
if (resp_len == 10) {
memcpy(dest, dec, 8);
return true;
}
return false;
}
bool Decrypt(uint8_t *src, uint8_t *dest){
return executeCrypto(CARD_INS_DECRYPT, src, dest);
}
bool Encrypt(uint8_t *src, uint8_t *dest){
return executeCrypto(CARD_INS_ENCRYPT, src, dest);
}
void DecodeBlock6(uint8_t *src) {
int resp_len = 0;
uint8_t resp[254] = {0};
uint8_t c[] = {0x96, CARD_INS_DECODE, 0x00, 0x00, 0x09, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
memcpy(c + 6, src, 8);
// first part
ExchangeAPDUSC(true, c, sizeof(c), false, true, resp, sizeof(resp), &resp_len);
PrintAndLogEx(SUCCESS, "%.*s", resp_len - 11, resp + 9);
// second part
c[5] = 0x02;
ExchangeAPDUSC(true, c, sizeof(c), false, true, resp, sizeof(resp), &resp_len);
PrintAndLogEx(SUCCESS, "%.*s", resp_len - 11, resp + 9);
}

21
common/cardhelper.h Normal file
View file

@ -0,0 +1,21 @@
//-----------------------------------------------------------------------------
// Iceman, February 2020
//
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
// at your option, any later version. See the LICENSE.txt file for the text of
// the license.
//-----------------------------------------------------------------------------
// Utility functions used in many places, not specific to any piece of code.
//-----------------------------------------------------------------------------
#ifndef __CARDHELPER_H
#define __CARDHELPER_H
#include <ctype.h>
#include "common.h"
bool IsCryptoHelperPresent(void);
bool Encrypt(uint8_t *src, uint8_t *dest);
bool Decrypt(uint8_t *src, uint8_t *dest);
void DecodeBlock6(uint8_t *src);
#endif