mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-21 22:03:42 -07:00
Merge branch 'master' of https://github.com/RfidResearchGroup/proxmark3
This commit is contained in:
commit
643b2ca363
38 changed files with 504 additions and 216 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -10,6 +10,7 @@
|
||||||
.profile
|
.profile
|
||||||
*.log
|
*.log
|
||||||
*.eml
|
*.eml
|
||||||
|
*.html
|
||||||
*.o
|
*.o
|
||||||
*.a
|
*.a
|
||||||
*.d
|
*.d
|
||||||
|
|
11
CHANGELOG.md
11
CHANGELOG.md
|
@ -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)
|
||||||
|
|
|
@ -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,7 +348,10 @@ 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✓ All keys found");
|
||||||
|
} else {
|
||||||
|
if (keyFound) {
|
||||||
Dbprintf("\t✕ There's currently no nested attack in MattyRun, sorry!");
|
Dbprintf("\t✕ There's currently no nested attack in MattyRun, sorry!");
|
||||||
LED_C_ON(); //red
|
LED_C_ON(); //red
|
||||||
LED_A_ON(); //yellow
|
LED_A_ON(); //yellow
|
||||||
|
@ -359,10 +362,10 @@ void RunMod() {
|
||||||
Dbprintf("\t✕ There's nothing I can do without at least a one valid key, sorry!");
|
Dbprintf("\t✕ There's nothing I can do without at least a one valid key, sorry!");
|
||||||
LED_C_ON(); //red
|
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();
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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)), )
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
||||||
|
if (use_sc) {
|
||||||
|
Decrypt(enc_data, dec_data);
|
||||||
|
} else {
|
||||||
mbedtls_des3_crypt_ecb(&ctx, enc_data, dec_data);
|
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,16 +862,27 @@ 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
|
||||||
|
// look inside block 6 to determine if aa1 is encrypted.
|
||||||
if (blocknum > 6 && memcmp(enc_data, empty, 8) != 0) {
|
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);
|
mbedtls_des3_crypt_ecb(&ctx, enc_data, decrypted + idx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//Use the first block (CSN) for filename
|
//Use the first block (CSN) for filename
|
||||||
char *fptr = calloc(42, sizeof(uint8_t));
|
char *fptr = calloc(42, sizeof(uint8_t));
|
||||||
|
@ -920,15 +895,42 @@ static int CmdHFiClassDecrypt(const char *Cmd) {
|
||||||
|
|
||||||
printIclassDumpContents(decrypted, 1, (decryptedlen / 8), decryptedlen);
|
printIclassDumpContents(decrypted, 1, (decryptedlen / 8), decryptedlen);
|
||||||
|
|
||||||
|
|
||||||
|
// decode block 6
|
||||||
|
if (memcmp(decrypted + (8*6), empty, 8) != 0 ) {
|
||||||
|
if (use_sc) {
|
||||||
|
DecodeBlock6(decrypted + (8*6));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// decode block 7-8-9
|
||||||
|
if (memcmp(decrypted + (8*7), empty, 8) != 0 ) {
|
||||||
|
|
||||||
|
//todo: remove preamble/sentinal
|
||||||
|
|
||||||
uint32_t top = 0, mid, bot;
|
uint32_t top = 0, mid, bot;
|
||||||
mid = bytes_to_num(decrypted + (8*7), 4);
|
mid = bytes_to_num(decrypted + (8*7), 4);
|
||||||
bot = bytes_to_num(decrypted + (8*7) + 4, 4);
|
bot = bytes_to_num(decrypted + (8*7) + 4, 4);
|
||||||
|
|
||||||
PrintAndLogEx(INFO, "");
|
PrintAndLogEx(INFO, "Block 7 binary");
|
||||||
PrintAndLogEx(INFO, "block 7 - Wiegand decode");
|
|
||||||
|
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);
|
wiegand_message_t packed = initialize_message_object(top, mid, bot);
|
||||||
HIDTryUnpack(&packed, true);
|
HIDTryUnpack(&packed, true);
|
||||||
PrintAndLogEx(INFO, "-----------------------------------------------------------------");
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (use_sc) {
|
||||||
|
Encrypt(blk_data, blk_data);
|
||||||
|
} else {
|
||||||
iClassEncryptBlkData(blk_data, key);
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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... }"},
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -368,11 +371,28 @@ static int CmdHIDBrute(const char *Cmd) {
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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[] = {
|
||||||
|
|
|
@ -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[] = {
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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
83
common/cardhelper.c
Normal 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
21
common/cardhelper.h
Normal 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
|
Loading…
Add table
Add a link
Reference in a new issue