Merge pull request #185 from marshmellow42/master

some lf fixes and hf mf sim attack mode add-ons
This commit is contained in:
Iceman 2016-08-12 13:55:09 +02:00 committed by GitHub
commit 7669409547
30 changed files with 1466 additions and 401 deletions

View file

@ -5,6 +5,8 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac
## [unreleased][unreleased]
### Added
- Added lf pyramid commands (iceman)
- Added lf presco commands - some bits not fully understood... (iceman)
- Added experimental HitagS support (Oguzhan Cicek, Hendrik Schwartke, Ralf Spenneberg)
see https://media.ccc.de/v/32c3-7166-sicherheit_von_125khz_transpondern_am_beispiel_hitag_s
English video available
@ -16,8 +18,7 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac
- `lf t55xx wipe` - sets t55xx back to factory defaults
- Added viking demod to `lf search` (marshmellow)
- `data askvikingdemod` demod viking id tag from graphbuffer (marshmellow)
- `lf t55xx resetread` added reset then read command - should allow determining start
of stream transmissions (marshmellow)
- `lf t55xx resetread` added reset then read command - should allow determining start of stream transmissions (marshmellow)
- `lf t55xx wakeup` added wake with password (AOR) to allow lf search or standard lf read after (iceman, marshmellow)
- `hf iclass managekeys` to save, load and manage iclass keys. (adjusted most commands to accept a loaded key in memory) (marshmellow)
- `hf iclass readblk` to select, authenticate, and read 1 block from an iclass card (marshmellow)
@ -36,21 +37,29 @@ of stream transmissions (marshmellow)
- Added option `l` or `h` to `hw tune` to save time and unnecessary fpga writes if you are only interested in lf or hf.
### Changed
- Added `[l] <length>` option to data printdemodbuffer
- Adjusted lf awid clone to optionally clone to Q5 tags
- Adjusted lf t55xx detect to find Q5 tags (t5555) instead of just t55x7
- Adjusted all lf NRZ demods - works more accurately and consistently (as long as you have strong signal)
- Adjusted lf pskindalademod to reduce false positive reads.
- Small adjustments to psk, nrz, and ask clock detect routines - more reliable.
- Adjusted lf em410x em410xsim to accept a clock argument
- Fixed bug in lf biphase sim - `lf simask b` (and any tagtype that relies on it - gproxii...) (marshmellow)
- Fixed bug in lf viking clone/sim (iceman)
- Fixed broken `data askedgedetect` (marshmellow)
- Adjusted hf mf sim command (marshmellow)
added auto run mfkey32 to extract all keys
also added f parameter to allow attacking with UIDs from a file (implies x and i parameters)
also added e parameter to allow adding the extracted keys to emulator memory for the next simulation
added 10 byte uid option
- Added `[l] <length>` option to data printdemodbuffer (marshmellow)
- Adjusted lf awid clone to optionally clone to Q5 tags (marshmellow)
- Adjusted lf t55xx detect to find Q5 tags (t5555) instead of just t55x7 (marshmellow)
- Adjusted all lf NRZ demods - works more accurately and consistently (as long as you have strong signal) (marshmellow)
- Adjusted lf pskindalademod to reduce false positive reads. (marshmellow)
- Small adjustments to psk, nrz, and ask clock detect routines - more reliable. (marshmellow)
- Adjusted lf em410x em410xsim to accept a clock argument (marshmellow)
- Adjusted lf t55xx dump to allow overriding the safety check and warning text (marshmellow)
- Adjusted lf t55xx write input variables (marshmellow)
- Adjusted lf t55xx read with password safety check and warning text and adjusted the input variables (marshmellow & iceman)
- Adjusted LF FSK demod to account for cross threshold fluctuations (898 count waves will adjust the 9 to 8 now...) more accurate.
- Adjusted LF FSK demod to account for cross threshold fluctuations (898 count waves will adjust the 9 to 8 now...) more accurate. (marshmellow)
- Adjusted timings for t55xx commands. more reliable now. (marshmellow & iceman)
- `lf cmdread` adjusted input methods and added help text (marshmellow & iceman)
- changed `lf config t <threshold>` to be 0 - 128 and will trigger on + or - threshold value (marshmellow)
- `hf iclass dump` cli options - can now dump AA1 and AA2 with different keys in one run (does not go to multiple pages for the larger tags yet)
- `hf iclass dump` cli options - can now dump AA1 and AA2 with different keys in one run (does not go to multiple pages for the larger tags yet) (marshmellow)
- Revised workflow for StandAloneMode14a (Craig Young)
- EPA functions (`hf epa`) now support both ISO 14443-A and 14443-B cards (frederikmoellers)
- 'hw version' only talks to ARM at startup, after that the info is cached. (pwpiwi)

View file

@ -12,6 +12,8 @@
#ifndef __BIGBUF_H
#define __BIGBUF_H
#include <stdbool.h> // for bool
#include "common.h" // for ramfunc
#define BIGBUF_SIZE 40000
#define MAX_FRAME_SIZE 256 // maximum allowed ISO14443 frame

View file

@ -37,8 +37,6 @@
#include "iso14443a.h"
#endif
#define abs(x) ( ((x)<0) ? -(x) : (x) )
//=============================================================================
// A buffer where we can queue things up to be sent through the FPGA, for
// any purpose (fake tag, as reader, whatever). We go MSB first, since that
@ -867,7 +865,7 @@ void ListenReaderField(int limit)
if (limit != HF_ONLY) {
if(mode == 1) {
if (abs(lf_av - lf_baseline) > REPORT_CHANGE)
if (ABS(lf_av - lf_baseline) > REPORT_CHANGE)
LED_D_ON();
else
LED_D_OFF();
@ -875,7 +873,7 @@ void ListenReaderField(int limit)
lf_av_new = AvgAdc(ADC_CHAN_LF);
// see if there's a significant change
if(abs(lf_av - lf_av_new) > REPORT_CHANGE) {
if(ABS(lf_av - lf_av_new) > REPORT_CHANGE) {
Dbprintf("LF 125/134kHz Field Change: %5dmV", (MAX_ADC_LF_VOLTAGE * lf_av_new) >> 10);
lf_av = lf_av_new;
if (lf_av > lf_max)
@ -885,7 +883,7 @@ void ListenReaderField(int limit)
if (limit != LF_ONLY) {
if (mode == 1){
if (abs(hf_av - hf_baseline) > REPORT_CHANGE)
if (ABS(hf_av - hf_baseline) > REPORT_CHANGE)
LED_B_ON();
else
LED_B_OFF();
@ -893,7 +891,7 @@ void ListenReaderField(int limit)
hf_av_new = AvgAdc(ADC_CHAN_HF);
// see if there's a significant change
if(abs(hf_av - hf_av_new) > REPORT_CHANGE) {
if(ABS(hf_av - hf_av_new) > REPORT_CHANGE) {
Dbprintf("HF 13.56MHz Field Change: %5dmV", (MAX_ADC_HF_VOLTAGE * hf_av_new) >> 10);
hf_av = hf_av_new;
if (hf_av > hf_max)

View file

@ -15,12 +15,13 @@
#include "util.h"
#include "string.h"
#include "cmd.h"
#include "iso14443crc.h"
#include "iso14443a.h"
#include "crapto1.h"
#include "mifareutil.h"
#include "BigBuf.h"
#include "protocols.h"
static uint32_t iso14a_timeout;
int rsamples = 0;
uint8_t trigger = 0;
@ -2307,20 +2308,34 @@ void ReaderMifare(bool first_try)
set_tracing(FALSE);
}
typedef struct {
uint32_t cuid;
uint8_t sector;
uint8_t keytype;
uint32_t nonce;
uint32_t ar;
uint32_t nr;
uint32_t nonce2;
uint32_t ar2;
uint32_t nr2;
} nonces_t;
/**
*MIFARE 1K simulate.
*
*@param flags :
* FLAG_INTERACTIVE - In interactive mode, we are expected to finish the operation with an ACK
* 4B_FLAG_UID_IN_DATA - means that there is a 4-byte UID in the data-section, we're expected to use that
* 7B_FLAG_UID_IN_DATA - means that there is a 7-byte UID in the data-section, we're expected to use that
* FLAG_4B_UID_IN_DATA - means that there is a 4-byte UID in the data-section, we're expected to use that
* FLAG_7B_UID_IN_DATA - means that there is a 7-byte UID in the data-section, we're expected to use that
* FLAG_10B_UID_IN_DATA - use 10-byte UID in the data-section not finished
* FLAG_NR_AR_ATTACK - means we should collect NR_AR responses for bruteforcing later
*@param exitAfterNReads, exit simulation after n blocks have been read, 0 is inifite
*@param exitAfterNReads, exit simulation after n blocks have been read, 0 is infinite ...
* (unless reader attack mode enabled then it runs util it gets enough nonces to recover all keys attmpted)
*/
void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t *datain)
{
int cardSTATE = MFEMUL_NOFIELD;
int _7BUID = 0;
int _UID_LEN = 0; // 4, 7, 10
int vHf = 0; // in mV
int res;
uint32_t selTimer = 0;
@ -2344,20 +2359,32 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t *
uint8_t response[MAX_MIFARE_FRAME_SIZE];
uint8_t response_par[MAX_MIFARE_PARITY_SIZE];
uint8_t rATQA[] = {0x04, 0x00}; // Mifare classic 1k 4BUID
uint8_t rATQA[] = {0x04, 0x00}; // Mifare classic 1k 4BUID
uint8_t rUIDBCC1[] = {0xde, 0xad, 0xbe, 0xaf, 0x62};
uint8_t rUIDBCC2[] = {0xde, 0xad, 0xbe, 0xaf, 0x62}; // !!!
uint8_t rSAK[] = {0x08, 0xb6, 0xdd};
uint8_t rSAK1[] = {0x04, 0xda, 0x17};
uint8_t rUIDBCC3[] = {0xde, 0xad, 0xbe, 0xaf, 0x62};
uint8_t rSAKfinal[]= {0x08, 0xb6, 0xdd}; // mifare 1k indicated
uint8_t rSAK1[] = {0x04, 0xda, 0x17}; // indicate UID not finished
uint8_t rAUTH_NT[] = {0x01, 0x02, 0x03, 0x04};
uint8_t rAUTH_AT[] = {0x00, 0x00, 0x00, 0x00};
//Here, we collect UID,NT,AR,NR,UID2,NT2,AR2,NR2
// This can be used in a reader-only attack.
// (it can also be retrieved via 'hf 14a list', but hey...
uint32_t ar_nr_responses[] = {0,0,0,0,0,0,0,0};
uint8_t ar_nr_collected = 0;
//Here, we collect UID,sector,keytype,NT,AR,NR,NT2,AR2,NR2
// This will be used in the reader-only attack.
//allow collecting up to 8 sets of nonces to allow recovery of up to 8 keys
#define ATTACK_KEY_COUNT 8 // keep same as define in cmdhfmf.c -> readerAttack()
nonces_t ar_nr_resp[ATTACK_KEY_COUNT*2]; //*2 for 2 separate attack types (nml, moebius)
memset(ar_nr_resp, 0x00, sizeof(ar_nr_resp));
uint8_t ar_nr_collected[ATTACK_KEY_COUNT*2]; //*2 for 2nd attack type (moebius)
memset(ar_nr_collected, 0x00, sizeof(ar_nr_collected));
uint8_t nonce1_count = 0;
uint8_t nonce2_count = 0;
uint8_t moebius_n_count = 0;
bool gettingMoebius = false;
uint8_t mM = 0; //moebius_modifier for collection storage
// Authenticate response - nonce
uint32_t nonce = bytes_to_num(rAUTH_NT, 4);
@ -2370,45 +2397,96 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t *
// 4B uid comes from data-portion of packet
memcpy(rUIDBCC1,datain,4);
rUIDBCC1[4] = rUIDBCC1[0] ^ rUIDBCC1[1] ^ rUIDBCC1[2] ^ rUIDBCC1[3];
_UID_LEN = 4;
} else if (flags & FLAG_7B_UID_IN_DATA) {
// 7B uid comes from data-portion of packet
memcpy(&rUIDBCC1[1],datain,3);
memcpy(rUIDBCC2, datain+3, 4);
_7BUID = true;
_UID_LEN = 7;
} else if (flags & FLAG_10B_UID_IN_DATA) {
memcpy(&rUIDBCC1[1], datain, 3);
memcpy(&rUIDBCC2[1], datain+3, 3);
memcpy( rUIDBCC3, datain+6, 4);
_UID_LEN = 10;
} else {
// get UID from emul memory
// get UID from emul memory - guess at length
emlGetMemBt(receivedCmd, 7, 1);
_7BUID = !(receivedCmd[0] == 0x00);
if (!_7BUID) { // ---------- 4BUID
if (receivedCmd[0] == 0x00) { // ---------- 4BUID
emlGetMemBt(rUIDBCC1, 0, 4);
_UID_LEN = 4;
} else { // ---------- 7BUID
emlGetMemBt(&rUIDBCC1[1], 0, 3);
emlGetMemBt(rUIDBCC2, 3, 4);
_UID_LEN = 7;
}
}
/*
* Regardless of what method was used to set the UID, set fifth byte and modify
* the ATQA for 4 or 7-byte UID
*/
rUIDBCC1[4] = rUIDBCC1[0] ^ rUIDBCC1[1] ^ rUIDBCC1[2] ^ rUIDBCC1[3];
if (_7BUID) {
rATQA[0] = 0x44;
rUIDBCC1[0] = 0x88;
rUIDBCC1[4] = rUIDBCC1[0] ^ rUIDBCC1[1] ^ rUIDBCC1[2] ^ rUIDBCC1[3];
rUIDBCC2[4] = rUIDBCC2[0] ^ rUIDBCC2[1] ^ rUIDBCC2[2] ^ rUIDBCC2[3];
}
switch (_UID_LEN) {
case 4:
// save CUID
cuid = bytes_to_num(rUIDBCC1, 4);
// BCC
rUIDBCC1[4] = rUIDBCC1[0] ^ rUIDBCC1[1] ^ rUIDBCC1[2] ^ rUIDBCC1[3];
if (MF_DBGLEVEL >= 2) {
Dbprintf("4B UID: %02x%02x%02x%02x",
rUIDBCC1[0],
rUIDBCC1[1],
rUIDBCC1[2],
rUIDBCC1[3]
);
}
break;
case 7:
rATQA[0] |= 0x40;
// save CUID
cuid = bytes_to_num(rUIDBCC2, 4);
// CascadeTag, CT
rUIDBCC1[0] = 0x88;
// BCC
rUIDBCC1[4] = rUIDBCC1[0] ^ rUIDBCC1[1] ^ rUIDBCC1[2] ^ rUIDBCC1[3];
rUIDBCC2[4] = rUIDBCC2[0] ^ rUIDBCC2[1] ^ rUIDBCC2[2] ^ rUIDBCC2[3];
if (MF_DBGLEVEL >= 2) {
Dbprintf("7B UID: %02x %02x %02x %02x %02x %02x %02x",
rUIDBCC1[1],
rUIDBCC1[2],
rUIDBCC1[3],
rUIDBCC2[0],
rUIDBCC2[1],
rUIDBCC2[2],
rUIDBCC2[3]
);
}
break;
case 10:
rATQA[0] |= 0x80;
//sak_10[0] &= 0xFB;
// save CUID
cuid = bytes_to_num(rUIDBCC3, 4);
// CascadeTag, CT
rUIDBCC1[0] = 0x88;
rUIDBCC2[0] = 0x88;
// BCC
rUIDBCC1[4] = rUIDBCC1[0] ^ rUIDBCC1[1] ^ rUIDBCC1[2] ^ rUIDBCC1[3];
rUIDBCC2[4] = rUIDBCC2[0] ^ rUIDBCC2[1] ^ rUIDBCC2[2] ^ rUIDBCC2[3];
rUIDBCC3[4] = rUIDBCC3[0] ^ rUIDBCC3[1] ^ rUIDBCC3[2] ^ rUIDBCC3[3];
if (MF_DBGLEVEL >= 1) {
if (!_7BUID) {
Dbprintf("4B UID: %02x%02x%02x%02x",
rUIDBCC1[0], rUIDBCC1[1], rUIDBCC1[2], rUIDBCC1[3]);
} else {
Dbprintf("7B UID: (%02x)%02x%02x%02x%02x%02x%02x%02x",
rUIDBCC1[0], rUIDBCC1[1], rUIDBCC1[2], rUIDBCC1[3],
rUIDBCC2[0], rUIDBCC2[1] ,rUIDBCC2[2], rUIDBCC2[3]);
}
if (MF_DBGLEVEL >= 2) {
Dbprintf("10B UID: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x",
rUIDBCC1[1],
rUIDBCC1[2],
rUIDBCC1[3],
rUIDBCC2[1],
rUIDBCC2[2],
rUIDBCC2[3],
rUIDBCC3[0],
rUIDBCC3[1],
rUIDBCC3[2],
rUIDBCC3[3]
);
}
break;
default:
break;
}
// We need to listen to the high-frequency, peak-detected path.
@ -2421,9 +2499,9 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t *
clear_trace();
set_tracing(TRUE);
bool finished = FALSE;
while (!BUTTON_PRESS() && !finished) {
bool button_pushed = BUTTON_PRESS();
while (!button_pushed && !finished && !usb_poll_validate_length()) {
WDT_HIT();
// find reader field
@ -2433,11 +2511,10 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t *
cardSTATE_TO_IDLE();
LED_A_ON();
}
}
if(cardSTATE == MFEMUL_NOFIELD) continue;
}
if (cardSTATE == MFEMUL_NOFIELD) continue;
//Now, get data
res = EmGetCmd(receivedCmd, &len, receivedCmd_par);
if (res == 2) { //Field is off!
cardSTATE = MFEMUL_NOFIELD;
@ -2446,11 +2523,11 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t *
} else if (res == 1) {
break; //return value 1 means button press
}
// REQ or WUP request in ANY state and WUP in HALTED state
if (len == 1 && ((receivedCmd[0] == 0x26 && cardSTATE != MFEMUL_HALTED) || receivedCmd[0] == 0x52)) {
if (len == 1 && ((receivedCmd[0] == ISO14443A_CMD_REQA && cardSTATE != MFEMUL_HALTED) || receivedCmd[0] == ISO14443A_CMD_WUPA)) {
selTimer = GetTickCount();
EmSendCmdEx(rATQA, sizeof(rATQA), (receivedCmd[0] == 0x52));
EmSendCmdEx(rATQA, sizeof(rATQA), (receivedCmd[0] == ISO14443A_CMD_WUPA));
cardSTATE = MFEMUL_SELECT1;
// init crypto block
@ -2469,59 +2546,137 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t *
break;
}
case MFEMUL_SELECT1:{
// select all
if (len == 2 && (receivedCmd[0] == 0x93 && receivedCmd[1] == 0x20)) {
// select all - 0x93 0x20
if (len == 2 && (receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT && receivedCmd[1] == 0x20)) {
if (MF_DBGLEVEL >= 4) Dbprintf("SELECT ALL received");
EmSendCmd(rUIDBCC1, sizeof(rUIDBCC1));
break;
}
if (MF_DBGLEVEL >= 4 && len == 9 && receivedCmd[0] == 0x93 && receivedCmd[1] == 0x70 )
{
Dbprintf("SELECT %02x%02x%02x%02x received",receivedCmd[2],receivedCmd[3],receivedCmd[4],receivedCmd[5]);
}
// select card
if (len == 9 &&
(receivedCmd[0] == 0x93 && receivedCmd[1] == 0x70 && memcmp(&receivedCmd[2], rUIDBCC1, 4) == 0)) {
EmSendCmd(_7BUID?rSAK1:rSAK, _7BUID?sizeof(rSAK1):sizeof(rSAK));
cuid = bytes_to_num(rUIDBCC1, 4);
if (!_7BUID) {
cardSTATE = MFEMUL_WORK;
LED_B_ON();
if (MF_DBGLEVEL >= 4) Dbprintf("--> WORK. anticol1 time: %d", GetTickCount() - selTimer);
break;
} else {
cardSTATE = MFEMUL_SELECT2;
// select card - 0x93 0x70 ...
if (len == 9 &&
(receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT && receivedCmd[1] == 0x70 && memcmp(&receivedCmd[2], rUIDBCC1, 4) == 0)) {
if (MF_DBGLEVEL >= 4)
Dbprintf("SELECT %02x%02x%02x%02x received",receivedCmd[2],receivedCmd[3],receivedCmd[4],receivedCmd[5]);
switch(_UID_LEN) {
case 4:
cardSTATE = MFEMUL_WORK;
LED_B_ON();
if (MF_DBGLEVEL >= 4) Dbprintf("--> WORK. anticol1 time: %d", GetTickCount() - selTimer);
EmSendCmd(rSAKfinal, sizeof(rSAKfinal));
break;
case 7:
cardSTATE = MFEMUL_SELECT2;
EmSendCmd(rSAK1, sizeof(rSAK1));
break;
case 10:
cardSTATE = MFEMUL_SELECT2;
EmSendCmd(rSAK1, sizeof(rSAK1));
break;
default:break;
}
} else {
cardSTATE_TO_IDLE();
}
break;
}
case MFEMUL_SELECT3:{
if (!len) {
LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, TRUE);
break;
}
// select all cl3 - 0x97 0x20
if (len == 2 && (receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_3 && receivedCmd[1] == 0x20)) {
EmSendCmd(rUIDBCC3, sizeof(rUIDBCC3));
break;
}
// select card cl3 - 0x97 0x70
if (len == 9 &&
(receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_3 &&
receivedCmd[1] == 0x70 &&
memcmp(&receivedCmd[2], rUIDBCC3, 4) == 0) ) {
EmSendCmd(rSAKfinal, sizeof(rSAKfinal));
cardSTATE = MFEMUL_WORK;
LED_B_ON();
if (MF_DBGLEVEL >= 4) Dbprintf("--> WORK. anticol3 time: %d", GetTickCount() - selTimer);
break;
}
cardSTATE_TO_IDLE();
break;
}
case MFEMUL_AUTH1:{
if( len != 8)
{
if( len != 8) {
cardSTATE_TO_IDLE();
LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, TRUE);
break;
}
uint32_t ar = bytes_to_num(receivedCmd, 4);
uint32_t nr = bytes_to_num(&receivedCmd[4], 4);
//Collect AR/NR
if(ar_nr_collected < 2){
if(ar_nr_responses[2] != ar)
{// Avoid duplicates... probably not necessary, ar should vary.
ar_nr_responses[ar_nr_collected*4] = cuid;
ar_nr_responses[ar_nr_collected*4+1] = nonce;
ar_nr_responses[ar_nr_collected*4+2] = ar;
ar_nr_responses[ar_nr_collected*4+3] = nr;
ar_nr_collected++;
uint32_t nr = bytes_to_num(receivedCmd, 4);
uint32_t ar = bytes_to_num(&receivedCmd[4], 4);
// Collect AR/NR per keytype & sector
if(flags & FLAG_NR_AR_ATTACK) {
for (uint8_t i = 0; i < ATTACK_KEY_COUNT; i++) {
if ( ar_nr_collected[i+mM]==0 || ((cardAUTHSC == ar_nr_resp[i+mM].sector) && (cardAUTHKEY == ar_nr_resp[i+mM].keytype) && (ar_nr_collected[i+mM] > 0)) ) {
// if first auth for sector, or matches sector and keytype of previous auth
if (ar_nr_collected[i+mM] < 2) {
// if we haven't already collected 2 nonces for this sector
if (ar_nr_resp[ar_nr_collected[i+mM]].ar != ar) {
// Avoid duplicates... probably not necessary, ar should vary.
if (ar_nr_collected[i+mM]==0) {
// first nonce collect
ar_nr_resp[i+mM].cuid = cuid;
ar_nr_resp[i+mM].sector = cardAUTHSC;
ar_nr_resp[i+mM].keytype = cardAUTHKEY;
ar_nr_resp[i+mM].nonce = nonce;
ar_nr_resp[i+mM].nr = nr;
ar_nr_resp[i+mM].ar = ar;
nonce1_count++;
// add this nonce to first moebius nonce
ar_nr_resp[i+ATTACK_KEY_COUNT].cuid = cuid;
ar_nr_resp[i+ATTACK_KEY_COUNT].sector = cardAUTHSC;
ar_nr_resp[i+ATTACK_KEY_COUNT].keytype = cardAUTHKEY;
ar_nr_resp[i+ATTACK_KEY_COUNT].nonce = nonce;
ar_nr_resp[i+ATTACK_KEY_COUNT].nr = nr;
ar_nr_resp[i+ATTACK_KEY_COUNT].ar = ar;
ar_nr_collected[i+ATTACK_KEY_COUNT]++;
} else { // second nonce collect (std and moebius)
ar_nr_resp[i+mM].nonce2 = nonce;
ar_nr_resp[i+mM].nr2 = nr;
ar_nr_resp[i+mM].ar2 = ar;
if (!gettingMoebius) {
nonce2_count++;
// check if this was the last second nonce we need for std attack
if ( nonce2_count == nonce1_count ) {
// done collecting std test switch to moebius
// first finish incrementing last sample
ar_nr_collected[i+mM]++;
// switch to moebius collection
gettingMoebius = true;
mM = ATTACK_KEY_COUNT;
nonce = nonce*7;
break;
}
} else {
moebius_n_count++;
// if we've collected all the nonces we need - finish.
if (nonce1_count == moebius_n_count) finished = true;
}
}
ar_nr_collected[i+mM]++;
}
}
// we found right spot for this nonce stop looking
break;
}
}
}
// --- crypto
crypto1_word(pcs, ar , 1);
cardRr = nr ^ crypto1_word(pcs, 0, 0);
crypto1_word(pcs, nr , 1);
cardRr = ar ^ crypto1_word(pcs, 0, 0);
// test if auth OK
if (cardRr != prng_successor(nonce, 64)){
@ -2537,6 +2692,7 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t *
break;
}
//auth successful
ans = prng_successor(nonce, 96) ^ crypto1_word(pcs, 0, 0);
num_to_bytes(ans, 4, rAUTH_AT);
@ -2553,20 +2709,29 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t *
if (!len) {
LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, TRUE);
break;
}
if (len == 2 && (receivedCmd[0] == 0x95 && receivedCmd[1] == 0x20)) {
}
// select all cl2 - 0x95 0x20
if (len == 2 && (receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_2 && receivedCmd[1] == 0x20)) {
EmSendCmd(rUIDBCC2, sizeof(rUIDBCC2));
break;
}
// select 2 card
// select cl2 card - 0x95 0x70 xxxxxxxxxxxx
if (len == 9 &&
(receivedCmd[0] == 0x95 && receivedCmd[1] == 0x70 && memcmp(&receivedCmd[2], rUIDBCC2, 4) == 0)) {
EmSendCmd(rSAK, sizeof(rSAK));
cuid = bytes_to_num(rUIDBCC2, 4);
cardSTATE = MFEMUL_WORK;
LED_B_ON();
if (MF_DBGLEVEL >= 4) Dbprintf("--> WORK. anticol2 time: %d", GetTickCount() - selTimer);
(receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_2 && receivedCmd[1] == 0x70 && memcmp(&receivedCmd[2], rUIDBCC2, 4) == 0)) {
switch(_UID_LEN) {
case 7:
EmSendCmd(rSAKfinal, sizeof(rSAKfinal));
cardSTATE = MFEMUL_WORK;
LED_B_ON();
if (MF_DBGLEVEL >= 4) Dbprintf("--> WORK. anticol2 time: %d", GetTickCount() - selTimer);
break;
case 10:
EmSendCmd(rSAK1, sizeof(rSAK1));
cardSTATE = MFEMUL_SELECT3;
break;
default:break;
}
break;
}
@ -2594,11 +2759,22 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t *
}
if (len == 4 && (receivedCmd[0] == 0x60 || receivedCmd[0] == 0x61)) {
// if authenticating to a block that shouldn't exist - as long as we are not doing the reader attack
if (receivedCmd[1] >= 16 * 4 && !(flags & FLAG_NR_AR_ATTACK)) {
//is this the correct response to an auth on a out of range block? marshmellow
EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA));
if (MF_DBGLEVEL >= 2) Dbprintf("Reader tried to operate (0x%02x) on out of range block: %d (0x%02x), nacking",receivedCmd[0],receivedCmd[1],receivedCmd[1]);
break;
}
authTimer = GetTickCount();
cardAUTHSC = receivedCmd[1] / 4; // received block num
cardAUTHKEY = receivedCmd[0] - 0x60;
crypto1_destroy(pcs);//Added by martin
crypto1_create(pcs, emlGetKey(cardAUTHSC, cardAUTHKEY));
//uint64_t key=emlGetKey(cardAUTHSC, cardAUTHKEY);
//Dbprintf("key: %04x%08x",(uint32_t)(key>>32)&0xFFFF,(uint32_t)(key&0xFFFFFFFF));
if (!encrypted_data) { // first authentication
if (MF_DBGLEVEL >= 4) Dbprintf("Reader authenticating for block %d (0x%02x) with key %d",receivedCmd[1] ,receivedCmd[1],cardAUTHKEY );
@ -2775,45 +2951,48 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t *
break;
}
}
button_pushed = BUTTON_PRESS();
}
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
LEDsoff();
if(flags & FLAG_INTERACTIVE)// Interactive mode flag, means we need to send ACK
{
//May just aswell send the collected ar_nr in the response aswell
cmd_send(CMD_ACK,CMD_SIMULATE_MIFARE_CARD,0,0,&ar_nr_responses,ar_nr_collected*4*4);
}
if(flags & FLAG_NR_AR_ATTACK)
{
if(ar_nr_collected > 1) {
Dbprintf("Collected two pairs of AR/NR which can be used to extract keys from reader:");
Dbprintf("../tools/mfkey/mfkey32 %08x %08x %08x %08x %08x %08x",
ar_nr_responses[0], // UID
ar_nr_responses[1], //NT
ar_nr_responses[2], //AR1
ar_nr_responses[3], //NR1
ar_nr_responses[6], //AR2
ar_nr_responses[7] //NR2
);
} else {
Dbprintf("Failed to obtain two AR/NR pairs!");
if(ar_nr_collected >0) {
Dbprintf("Only got these: UID=%08x, nonce=%08x, AR1=%08x, NR1=%08x",
ar_nr_responses[0], // UID
ar_nr_responses[1], //NT
ar_nr_responses[2], //AR1
ar_nr_responses[3] //NR1
if(flags & FLAG_NR_AR_ATTACK && MF_DBGLEVEL >= 1) {
for ( uint8_t i = 0; i < ATTACK_KEY_COUNT; i++) {
if (ar_nr_collected[i] == 2) {
Dbprintf("Collected two pairs of AR/NR which can be used to extract %s from reader for sector %d:", (i<ATTACK_KEY_COUNT/2) ? "keyA" : "keyB", ar_nr_resp[i].sector);
Dbprintf("../tools/mfkey/mfkey32 %08x %08x %08x %08x %08x %08x",
ar_nr_resp[i].cuid, //UID
ar_nr_resp[i].nonce, //NT
ar_nr_resp[i].nr, //NR1
ar_nr_resp[i].ar, //AR1
ar_nr_resp[i].nr2, //NR2
ar_nr_resp[i].ar2 //AR2
);
}
}
for ( uint8_t i = ATTACK_KEY_COUNT; i < ATTACK_KEY_COUNT*2; i++) {
if (ar_nr_collected[i] == 2) {
Dbprintf("Collected two pairs of AR/NR which can be used to extract %s from reader for sector %d:", (i<ATTACK_KEY_COUNT/2) ? "keyA" : "keyB", ar_nr_resp[i].sector);
Dbprintf("../tools/mfkey/mfkey32v2 %08x %08x %08x %08x %08x %08x %08x",
ar_nr_resp[i].cuid, //UID
ar_nr_resp[i].nonce, //NT
ar_nr_resp[i].nr, //NR1
ar_nr_resp[i].ar, //AR1
ar_nr_resp[i].nonce2,//NT2
ar_nr_resp[i].nr2, //NR2
ar_nr_resp[i].ar2 //AR2
);
}
}
}
if (MF_DBGLEVEL >= 1) Dbprintf("Emulator stopped. Tracing: %d trace length: %d ", tracing, BigBuf_get_traceLen());
}
if(flags & FLAG_INTERACTIVE) { // Interactive mode flag, means we need to send ACK
//Send the collected ar_nr in the response
cmd_send(CMD_ACK,CMD_SIMULATE_MIFARE_CARD,button_pushed,0,&ar_nr_resp,sizeof(ar_nr_resp));
}
}
//-----------------------------------------------------------------------------

View file

@ -547,15 +547,20 @@ static RAMFUNC int Handle14443bSamplesDemod(int ci, int cq)
}
*/
// Subcarrier amplitude v = sqrt(ci^2 + cq^2), approximated here by max(abs(ci),abs(cq)) + 1/2*min(abs(ci),abs(cq)))
//note: couldn't we just use MAX(ABS(ci),ABS(cq)) + (MIN(ABS(ci),ABS(cq))/2) from common.h - marshmellow
#define CHECK_FOR_SUBCARRIER() { \
v = MAX(ABS(ci),ABS(cq)) + (MIN(ABS(ci),ABS(cq))/2); \
}
/*
if(ci < 0) { \
if(cq < 0) { /* ci < 0, cq < 0 */ \
if(cq < 0) { \ // ci < 0, cq < 0
if (cq < ci) { \
v = -cq - (ci >> 1); \
} else { \
v = -ci - (cq >> 1); \
} \
} else { /* ci < 0, cq >= 0 */ \
} else { \ // ci < 0, cq >= 0
if (cq < -ci) { \
v = -ci + (cq >> 1); \
} else { \
@ -563,13 +568,13 @@ static RAMFUNC int Handle14443bSamplesDemod(int ci, int cq)
} \
} \
} else { \
if(cq < 0) { /* ci >= 0, cq < 0 */ \
if(cq < 0) { \ // ci >= 0, cq < 0
if (-cq < ci) { \
v = ci - (cq >> 1); \
} else { \
v = -cq + (ci >> 1); \
} \
} else { /* ci >= 0, cq >= 0 */ \
} else { \ // ci >= 0, cq >= 0
if (cq < ci) { \
v = ci + (cq >> 1); \
} else { \
@ -578,6 +583,7 @@ static RAMFUNC int Handle14443bSamplesDemod(int ci, int cq)
} \
} \
}
*/
switch(Demod.state) {
case DEMOD_UNSYNCD:

View file

@ -319,18 +319,7 @@ static int GetIso15693AnswerFromTag(uint8_t *receivedResponse, int maxLen, int *
// every other is Q. We just want power, so abs(I) + abs(Q) is
// close to what we want.
if(getNext) {
int8_t r;
if(b < 0) {
r = -b;
} else {
r = b;
}
if(prev < 0) {
r -= prev;
} else {
r += prev;
}
int8_t r = ABS(b) + ABS(prev);
dest[c++] = (uint8_t)r;
@ -468,18 +457,7 @@ static int GetIso15693AnswerFromSniff(uint8_t *receivedResponse, int maxLen, int
// every other is Q. We just want power, so abs(I) + abs(Q) is
// close to what we want.
if(getNext) {
int8_t r;
if(b < 0) {
r = -b;
} else {
r = b;
}
if(prev < 0) {
r -= prev;
} else {
r += prev;
}
int8_t r = ABS(b) + ABS(prev);
dest[c++] = (uint8_t)r;
@ -648,18 +626,7 @@ void AcquireRawAdcSamplesIso15693(void)
// every other is Q. We just want power, so abs(I) + abs(Q) is
// close to what we want.
if(getNext) {
int8_t r;
if(b < 0) {
r = -b;
} else {
r = b;
}
if(prev < 0) {
r -= prev;
} else {
r += prev;
}
int8_t r = ABS(b) + ABS(prev);
dest[c++] = (uint8_t)r;
@ -713,18 +680,7 @@ void RecordRawAdcSamplesIso15693(void)
// every other is Q. We just want power, so abs(I) + abs(Q) is
// close to what we want.
if(getNext) {
int8_t r;
if(b < 0) {
r = -b;
} else {
r = b;
}
if(prev < 0) {
r -= prev;
} else {
r += prev;
}
int8_t r = ABS(b) + ABS(prev);
dest[c++] = (uint8_t)r;

View file

@ -379,7 +379,7 @@ void WriteTItag(uint32_t idhi, uint32_t idlo, uint16_t crc)
AcquireTiType();
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
DbpString("Now use tiread to check");
DbpString("Now use `lf ti read` to check");
}
void SimulateTagLowFrequency(int period, int gap, int ledcontrol)
@ -642,6 +642,19 @@ static void biphaseSimBit(uint8_t c, int *n, uint8_t clock, uint8_t *phase)
memset(dest+(*n), c ^ *phase, clock);
*phase ^= 1;
}
*n += clock;
}
static void stAskSimBit(int *n, uint8_t clock) {
uint8_t *dest = BigBuf_get_addr();
uint8_t halfClk = clock/2;
//ST = .5 high .5 low 1.5 high .5 low 1 high
memset(dest+(*n), 1, halfClk);
memset(dest+(*n) + halfClk, 0, halfClk);
memset(dest+(*n) + clock, 1, clock + halfClk);
memset(dest+(*n) + clock*2 + halfClk, 0, halfClk);
memset(dest+(*n) + clock*3, 1, clock);
*n += clock*4;
}
// args clock, ask/man or askraw, invert, transmission separator
@ -659,7 +672,7 @@ void CmdASKsimTag(uint16_t arg1, uint16_t arg2, size_t size, uint8_t *BitStream)
for (i=0; i<size; i++){
biphaseSimBit(BitStream[i]^invert, &n, clk, &phase);
}
if (BitStream[0]==BitStream[size-1]){ //run a second set inverted to keep phase in check
if (phase==1) { //run a second set inverted to keep phase in check
for (i=0; i<size; i++){
biphaseSimBit(BitStream[i]^invert, &n, clk, &phase);
}
@ -674,8 +687,10 @@ void CmdASKsimTag(uint16_t arg1, uint16_t arg2, size_t size, uint8_t *BitStream)
}
}
}
if (separator==1) Dbprintf("sorry but separator option not yet available");
if (separator==1 && encoding == 1)
stAskSimBit(&n, clk);
else if (separator==1)
Dbprintf("sorry but separator option not yet available");
Dbprintf("Simulating with clk: %d, invert: %d, encoding: %d, separator: %d, n: %d",clk, invert, encoding, separator, n);
//DEBUG
@ -685,7 +700,7 @@ void CmdASKsimTag(uint16_t arg1, uint16_t arg2, size_t size, uint8_t *BitStream)
//Dbprintf("%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d", dest[i],dest[i+1],dest[i+2],dest[i+3],dest[i+4],dest[i+5],dest[i+6],dest[i+7],dest[i+8],dest[i+9],dest[i+10],dest[i+11],dest[i+12],dest[i+13],dest[i+14],dest[i+15]);
//i+=16;
//Dbprintf("%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d", dest[i],dest[i+1],dest[i+2],dest[i+3],dest[i+4],dest[i+5],dest[i+6],dest[i+7],dest[i+8],dest[i+9],dest[i+10],dest[i+11],dest[i+12],dest[i+13],dest[i+14],dest[i+15]);
if (ledcontrol) LED_A_ON();
SimulateTagLowFrequency(n, 0, ledcontrol);
if (ledcontrol) LED_A_OFF();
@ -1415,7 +1430,7 @@ void WriteEM410x(uint32_t card, uint32_t id_hi, uint32_t id_lo) {
LED_D_ON();
// Write EM410x ID
uint32_t data[] = {0, id>>32, id & 0xFFFFFFFF};
uint32_t data[] = {0, (uint32_t)(id>>32), (uint32_t)(id & 0xFFFFFFFF)};
clock = (card & 0xFF00) >> 8;
clock = (clock == 0) ? 64 : clock;

View file

@ -42,14 +42,15 @@ extern int MF_DBGLEVEL;
#define MFEMUL_IDLE 1
#define MFEMUL_SELECT1 2
#define MFEMUL_SELECT2 3
#define MFEMUL_AUTH1 4
#define MFEMUL_AUTH2 5
#define MFEMUL_WORK 6
#define MFEMUL_WRITEBL2 7
#define MFEMUL_INTREG_INC 8
#define MFEMUL_INTREG_DEC 9
#define MFEMUL_INTREG_REST 10
#define MFEMUL_HALTED 11
#define MFEMUL_SELECT3 4
#define MFEMUL_AUTH1 5
#define MFEMUL_AUTH2 6
#define MFEMUL_WORK 7
#define MFEMUL_WRITEBL2 8
#define MFEMUL_INTREG_INC 9
#define MFEMUL_INTREG_DEC 10
#define MFEMUL_INTREG_REST 11
#define MFEMUL_HALTED 12
#define cardSTATE_TO_IDLE() cardSTATE = MFEMUL_IDLE; LED_B_OFF(); LED_C_OFF();

View file

@ -7,9 +7,6 @@
#define T0_PCF 8 //period for the pcf7931 in us
#define ALLOC 16
#define abs(x) ( ((x)<0) ? -(x) : (x) )
#define max(x,y) ( x<y ? y:x)
int DemodPCF7931(uint8_t **outBlocks) {
uint8_t bits[256] = {0x00};
@ -72,7 +69,7 @@ int DemodPCF7931(uint8_t **outBlocks) {
// Switch depending on lc length:
// Tolerance is 1/8 of clock rate (arbitrary)
if (abs(lc-clock/4) < tolerance) {
if (ABS(lc-clock/4) < tolerance) {
// 16T0
if((i - pmc) == lc) { /* 16T0 was previous one */
/* It's a PMC ! */
@ -84,7 +81,7 @@ int DemodPCF7931(uint8_t **outBlocks) {
else {
pmc = i;
}
} else if (abs(lc-clock/2) < tolerance) {
} else if (ABS(lc-clock/2) < tolerance) {
// 32TO
if((i - pmc) == lc) { /* 16T0 was previous one */
/* It's a PMC ! */
@ -99,7 +96,7 @@ int DemodPCF7931(uint8_t **outBlocks) {
}
else
half_switch++;
} else if (abs(lc-clock) < tolerance) {
} else if (ABS(lc-clock) < tolerance) {
// 64TO
bits[bitidx++] = 1;
} else {
@ -204,7 +201,7 @@ void ReadPCF7931() {
Blocks[0][ALLOC] = 1;
memcpy(Blocks[1], tmpBlocks[i+1], 16);
Blocks[1][ALLOC] = 1;
max_blocks = max((Blocks[1][14] & 0x7f), Blocks[1][15]) + 1;
max_blocks = MAX((Blocks[1][14] & 0x7f), Blocks[1][15]) + 1;
// Debug print
Dbprintf("(dbg) Max blocks: %d", max_blocks);
num_blocks = 2;

View file

@ -99,6 +99,8 @@ CMDSRCS = nonce2key/crapto1.c\
cmdlft55xx.c \
cmdlfpcf7931.c\
cmdlfviking.c\
cmdlfpresco.c\
cmdlfpyramid.c\
pm3_binlib.c\
scripting.c\
cmdscript.c\

View file

@ -8,23 +8,22 @@
// Data and Graph commands
//-----------------------------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include "proxmark3.h"
#include "data.h"
#include "ui.h"
#include "graph.h"
#include "cmdparser.h"
#include <stdio.h> // also included in util.h
#include <string.h> // also included in util.h
#include <limits.h> // for CmdNorm INT_MIN && INT_MAX
#include "data.h" // also included in util.h
#include "cmddata.h"
#include "util.h"
#include "cmdmain.h"
#include "cmddata.h"
#include "lfdemod.h"
#include "usb_cmd.h"
#include "crc.h"
#include "crc16.h"
#include "loclass/cipherutils.h"
#include "proxmark3.h"
#include "ui.h" // for show graph controls
#include "graph.h" // for graph data
#include "cmdparser.h"// already included in cmdmain.h
#include "usb_cmd.h" // already included in cmdmain.h and proxmark3.h
#include "lfdemod.h" // for demod code
#include "crc.h" // for pyramid checksum maxim
#include "crc16.h" // for FDXB demod checksum
#include "loclass/cipherutils.h" // for decimating samples in getsamples
uint8_t DemodBuffer[MAX_DEMOD_BUF_LEN];
uint8_t g_debugMode=0;
@ -592,7 +591,7 @@ int Cmdaskbiphdemod(const char *Cmd)
int CmdG_Prox_II_Demod(const char *Cmd)
{
if (!ASKbiphaseDemod(Cmd, FALSE)){
if (g_debugMode) PrintAndLog("ASKbiphaseDemod failed 1st try");
if (g_debugMode) PrintAndLog("Error gProxII: ASKbiphaseDemod failed 1st try");
return 0;
}
size_t size = DemodBufferLen;
@ -602,46 +601,32 @@ int CmdG_Prox_II_Demod(const char *Cmd)
if (g_debugMode) PrintAndLog("Error gProxII_Demod");
return 0;
}
//got a good demod
uint32_t ByteStream[65] = {0x00};
//got a good demod of 96 bits
uint8_t ByteStream[8] = {0x00};
uint8_t xorKey=0;
uint8_t keyCnt=0;
uint8_t bitCnt=0;
uint8_t ByteCnt=0;
size_t startIdx = ans + 6; //start after preamble
for (size_t idx = 0; idx<size-6; idx++){
if ((idx+1) % 5 == 0){
//spacer bit - should be 0
if (DemodBuffer[startIdx+idx] != 0) {
if (g_debugMode) PrintAndLog("Error spacer not 0: %u, pos: %u", (unsigned int)DemodBuffer[startIdx+idx],(unsigned int)(startIdx+idx));
return 0;
}
continue;
}
if (keyCnt<8){ //lsb first
xorKey = xorKey | (DemodBuffer[startIdx+idx]<<keyCnt);
keyCnt++;
if (keyCnt==8 && g_debugMode) PrintAndLog("xorKey Found: %02x", (unsigned int)xorKey);
continue;
}
//lsb first
ByteStream[ByteCnt] = ByteStream[ByteCnt] | (DemodBuffer[startIdx+idx]<<bitCnt);
bitCnt++;
if (bitCnt % 8 == 0){
if (g_debugMode) PrintAndLog("byte %u: %02x", (unsigned int)ByteCnt, ByteStream[ByteCnt]);
bitCnt=0;
ByteCnt++;
}
size_t startIdx = ans + 6; //start after 6 bit preamble
uint8_t bits_no_spacer[90];
//so as to not mess with raw DemodBuffer copy to a new sample array
memcpy(bits_no_spacer, DemodBuffer + startIdx, 90);
// remove the 18 (90/5=18) parity bits (down to 72 bits (96-6-18=72))
size_t bitLen = removeParity(bits_no_spacer, 0, 5, 3, 90); //source, startloc, paritylen, ptype, length_to_run
if (bitLen != 72) {
if (g_debugMode) PrintAndLog("Error gProxII: spacer removal did not produce 72 bits: %u, start: %u", bitLen, startIdx);
return 0;
}
for (uint8_t i = 0; i < ByteCnt; i++){
ByteStream[i] ^= xorKey; //xor
if (g_debugMode) PrintAndLog("byte %u after xor: %02x", (unsigned int)i, ByteStream[i]);
// get key and then get all 8 bytes of payload decoded
xorKey = (uint8_t)bytebits_to_byteLSBF(bits_no_spacer, 8);
for (size_t idx = 0; idx < 8; idx++) {
ByteStream[idx] = ((uint8_t)bytebits_to_byteLSBF(bits_no_spacer+8 + (idx*8),8)) ^ xorKey;
if (g_debugMode) PrintAndLog("byte %u after xor: %02x", (unsigned int)idx, ByteStream[idx]);
}
//now ByteStream contains 64 bytes of decrypted raw tag data
//now ByteStream contains 8 Bytes (64 bits) of decrypted raw tag data
//
uint8_t fmtLen = ByteStream[0]>>2;
uint32_t FC = 0;
uint32_t Card = 0;
//get raw 96 bits to print
uint32_t raw1 = bytebits_to_byte(DemodBuffer+ans,32);
uint32_t raw2 = bytebits_to_byte(DemodBuffer+ans+32, 32);
uint32_t raw3 = bytebits_to_byte(DemodBuffer+ans+64, 32);
@ -649,13 +634,14 @@ int CmdG_Prox_II_Demod(const char *Cmd)
if (fmtLen==36){
FC = ((ByteStream[3] & 0x7F)<<7) | (ByteStream[4]>>1);
Card = ((ByteStream[4]&1)<<19) | (ByteStream[5]<<11) | (ByteStream[6]<<3) | (ByteStream[7]>>5);
PrintAndLog("G-Prox-II Found: FmtLen %d, FC %d, Card %d", fmtLen, FC, Card);
PrintAndLog("G-Prox-II Found: FmtLen %d, FC %u, Card %u", (int)fmtLen, FC, Card);
} else if(fmtLen==26){
FC = ((ByteStream[3] & 0x7F)<<1) | (ByteStream[4]>>7);
Card = ((ByteStream[4]&0x7F)<<9) | (ByteStream[5]<<1) | (ByteStream[6]>>7);
PrintAndLog("G-Prox-II Found: FmtLen %d, FC %d, Card %d",(unsigned int)fmtLen,FC,Card);
PrintAndLog("G-Prox-II Found: FmtLen %d, FC %u, Card %u", (int)fmtLen, FC, Card);
} else {
PrintAndLog("Unknown G-Prox-II Fmt Found: FmtLen %d",(int)fmtLen);
PrintAndLog("Decoded Raw: %s", sprint_hex(ByteStream, 8));
}
PrintAndLog("Raw: %08x%08x%08x", raw1,raw2,raw3);
setDemodBuf(DemodBuffer+ans, 96, 0);
@ -848,16 +834,18 @@ int CmdUndec(const char *Cmd)
uint8_t factor = param_get8ex(Cmd, 0,2, 10);
//We have memory, don't we?
int swap[MAX_GRAPH_TRACE_LEN] = { 0 };
uint32_t g_index = 0 ,s_index = 0;
while(g_index < GraphTraceLen && s_index < MAX_GRAPH_TRACE_LEN)
uint32_t g_index = 0, s_index = 0;
while(g_index < GraphTraceLen && s_index + factor < MAX_GRAPH_TRACE_LEN)
{
int count = 0;
for(count = 0; count < factor && s_index+count < MAX_GRAPH_TRACE_LEN; count ++)
for(count = 0; count < factor && s_index + count < MAX_GRAPH_TRACE_LEN; count++)
swap[s_index+count] = GraphBuffer[g_index];
s_index+=count;
s_index += count;
g_index++;
}
memcpy(GraphBuffer,swap, s_index * sizeof(int));
memcpy(GraphBuffer, swap, s_index * sizeof(int));
GraphTraceLen = s_index;
RepaintGraphWindow();
return 0;
@ -891,13 +879,15 @@ int CmdGraphShiftZero(const char *Cmd)
int CmdAskEdgeDetect(const char *Cmd)
{
int thresLen = 25;
int Last = 0;
sscanf(Cmd, "%i", &thresLen);
for(int i = 1; i<GraphTraceLen; i++){
if (GraphBuffer[i]-GraphBuffer[i-1]>=thresLen) //large jump up
GraphBuffer[i-1] = 127;
Last = 127;
else if(GraphBuffer[i]-GraphBuffer[i-1]<=-1*thresLen) //large jump down
GraphBuffer[i-1] = -127;
Last = -127;
GraphBuffer[i-1] = Last;
}
RepaintGraphWindow();
return 0;
@ -1276,7 +1266,7 @@ int CmdFSKdemodAWID(const char *Cmd)
//get binary from fsk wave
int idx = AWIDdemodFSK(BitStream, &size);
if (idx<=0){
if (g_debugMode==1){
if (g_debugMode){
if (idx == -1)
PrintAndLog("DEBUG: Error - not enough samples");
else if (idx == -2)
@ -1314,7 +1304,7 @@ int CmdFSKdemodAWID(const char *Cmd)
size = removeParity(BitStream, idx+8, 4, 1, 88);
if (size != 66){
if (g_debugMode==1) PrintAndLog("DEBUG: Error - at parity check-tag size does not match AWID format");
if (g_debugMode) PrintAndLog("DEBUG: Error - at parity check-tag size does not match AWID format");
return 0;
}
// ok valid card found!
@ -1374,7 +1364,7 @@ int CmdFSKdemodPyramid(const char *Cmd)
//get binary from fsk wave
int idx = PyramiddemodFSK(BitStream, &size);
if (idx < 0){
if (g_debugMode==1){
if (g_debugMode){
if (idx == -5)
PrintAndLog("DEBUG: Error - not enough samples");
else if (idx == -1)
@ -1430,7 +1420,7 @@ int CmdFSKdemodPyramid(const char *Cmd)
size = removeParity(BitStream, idx+8, 8, 1, 120);
if (size != 105){
if (g_debugMode==1)
if (g_debugMode)
PrintAndLog("DEBUG: Error at parity check - tag size does not match Pyramid format, SIZE: %d, IDX: %d, hi3: %x",size, idx, rawHi3);
return 0;
}
@ -1653,21 +1643,21 @@ int CmdIndalaDecode(const char *Cmd)
}
if (!ans){
if (g_debugMode==1)
if (g_debugMode)
PrintAndLog("Error1: %d",ans);
return 0;
}
uint8_t invert=0;
size_t size = DemodBufferLen;
size_t startIdx = indala26decode(DemodBuffer, &size, &invert);
if (startIdx < 1 || size > 224) {
if (g_debugMode==1)
int startIdx = indala26decode(DemodBuffer, &size, &invert);
if (startIdx < 0 || size > 224) {
if (g_debugMode)
PrintAndLog("Error2: %d",ans);
return -1;
}
setDemodBuf(DemodBuffer, size, startIdx);
setDemodBuf(DemodBuffer, size, (size_t)startIdx);
if (invert)
if (g_debugMode==1)
if (g_debugMode)
PrintAndLog("Had to invert bits");
PrintAndLog("BitLen: %d",DemodBufferLen);
@ -2344,9 +2334,8 @@ int Cmdbin2hex(const char *Cmd)
return 0;
}
int usage_data_hex2bin(){
PrintAndLog("Usage: data bin2hex <binary_digits>");
int usage_data_hex2bin() {
PrintAndLog("Usage: data hex2bin <hex_digits>");
PrintAndLog(" This function will ignore all non-hexadecimal characters (but stop reading on whitespace)");
return 0;

View file

@ -11,6 +11,12 @@
#ifndef CMDDATA_H__
#define CMDDATA_H__
#include <stdlib.h> //size_t
#include <stdint.h> //uint_32+
#include <stdbool.h> //bool
#include "cmdparser.h" // for command_t
command_t * CmdDataCommands();
int CmdData(const char *Cmd);

View file

@ -9,6 +9,7 @@
//-----------------------------------------------------------------------------
#include "cmdhfmf.h"
#include "./nonce2key/nonce2key.h"
static int CmdHelp(const char *Cmd);
@ -28,7 +29,7 @@ int CmdHF14AMifare(const char *Cmd)
printf("-------------------------------------------------------------------------\n");
start:
start:
clearCommandBuffer();
SendCommand(&c);
@ -1015,72 +1016,273 @@ int CmdHF14AMfChk(const char *Cmd)
return 0;
}
int CmdHF14AMf1kSim(const char *Cmd)
{
uint8_t uid[7] = {0, 0, 0, 0, 0, 0, 0};
void readerAttack(nonces_t ar_resp[], bool setEmulatorMem) {
#define ATTACK_KEY_COUNT 8 // keep same as define in iso14443a.c -> Mifare1ksim()
uint64_t key = 0;
typedef struct {
uint64_t keyA;
uint64_t keyB;
} st_t;
st_t sector_trailer[ATTACK_KEY_COUNT];
memset(sector_trailer, 0x00, sizeof(sector_trailer));
uint8_t stSector[ATTACK_KEY_COUNT];
memset(stSector, 0x00, sizeof(stSector));
uint8_t key_cnt[ATTACK_KEY_COUNT];
memset(key_cnt, 0x00, sizeof(key_cnt));
for (uint8_t i = 0; i<ATTACK_KEY_COUNT; i++) {
if (ar_resp[i].ar2 > 0) {
//PrintAndLog("DEBUG: Trying sector %d, cuid %08x, nt %08x, ar %08x, nr %08x, ar2 %08x, nr2 %08x",ar_resp[i].sector, ar_resp[i].cuid,ar_resp[i].nonce,ar_resp[i].ar,ar_resp[i].nr,ar_resp[i].ar2,ar_resp[i].nr2);
if (mfkey32(ar_resp[i], &key)) {
PrintAndLog(" Found Key%s for sector %02d: [%04x%08x]", (ar_resp[i].keytype) ? "B" : "A", ar_resp[i].sector, (uint32_t) (key>>32), (uint32_t) (key &0xFFFFFFFF));
for (uint8_t ii = 0; ii<ATTACK_KEY_COUNT; ii++) {
if (key_cnt[ii]==0 || stSector[ii]==ar_resp[i].sector) {
if (ar_resp[i].keytype==0) {
//keyA
sector_trailer[ii].keyA = key;
stSector[ii] = ar_resp[i].sector;
key_cnt[ii]++;
break;
} else {
//keyB
sector_trailer[ii].keyB = key;
stSector[ii] = ar_resp[i].sector;
key_cnt[ii]++;
break;
}
}
}
}
}
}
//set emulator memory for keys
if (setEmulatorMem) {
for (uint8_t i = 0; i<ATTACK_KEY_COUNT; i++) {
if (key_cnt[i]>0) {
uint8_t memBlock[16];
memset(memBlock, 0x00, sizeof(memBlock));
char cmd1[36];
memset(cmd1,0x00,sizeof(cmd1));
snprintf(cmd1,sizeof(cmd1),"%04x%08xFF078069%04x%08x",(uint32_t) (sector_trailer[i].keyA>>32), (uint32_t) (sector_trailer[i].keyA &0xFFFFFFFF),(uint32_t) (sector_trailer[i].keyB>>32), (uint32_t) (sector_trailer[i].keyB &0xFFFFFFFF));
PrintAndLog("Setting Emulator Memory Block %02d: [%s]",stSector[i]*4+3, cmd1);
if (param_gethex(cmd1, 0, memBlock, 32)) {
PrintAndLog("block data must include 32 HEX symbols");
return;
}
UsbCommand c = {CMD_MIFARE_EML_MEMSET, {(stSector[i]*4+3), 1, 0}};
memcpy(c.d.asBytes, memBlock, 16);
clearCommandBuffer();
SendCommand(&c);
}
}
}
/*
//un-comment to use as well moebius attack
for (uint8_t i = ATTACK_KEY_COUNT; i<ATTACK_KEY_COUNT*2; i++) {
if (ar_resp[i].ar2 > 0) {
if (tryMfk32_moebius(ar_resp[i], &key)) {
PrintAndLog("M-Found Key%s for sector %02d: [%04x%08x]", (ar_resp[i].keytype) ? "B" : "A", ar_resp[i].sector, (uint32_t) (key>>32), (uint32_t) (key &0xFFFFFFFF));
}
}
}*/
}
int usage_hf14_mf1ksim(void) {
PrintAndLog("Usage: hf mf sim h u <uid (8, 14, or 20 hex symbols)> n <numreads> i x");
PrintAndLog("options:");
PrintAndLog(" h this help");
PrintAndLog(" u (Optional) UID 4,7 or 10 bytes. If not specified, the UID 4B from emulator memory will be used");
PrintAndLog(" n (Optional) Automatically exit simulation after <numreads> blocks have been read by reader. 0 = infinite");
PrintAndLog(" i (Optional) Interactive, means that console will not be returned until simulation finishes or is aborted");
PrintAndLog(" x (Optional) Crack, performs the 'reader attack', nr/ar attack against a legitimate reader, fishes out the key(s)");
PrintAndLog(" e (Optional) set keys found from 'reader attack' to emulator memory (implies x and i)");
PrintAndLog(" f (Optional) get UIDs to use for 'reader attack' from file 'f <filename.txt>' (implies x and i)");
PrintAndLog("samples:");
PrintAndLog(" hf mf sim u 0a0a0a0a");
PrintAndLog(" hf mf sim u 11223344556677");
PrintAndLog(" hf mf sim u 112233445566778899AA");
PrintAndLog(" hf mf sim f uids.txt");
PrintAndLog(" hf mf sim u 0a0a0a0a e");
return 0;
}
int CmdHF14AMf1kSim(const char *Cmd) {
UsbCommand resp;
uint8_t uid[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
uint8_t exitAfterNReads = 0;
uint8_t flags = 0;
uint8_t cmdp = param_getchar(Cmd, 0);
if (cmdp == 'h' || cmdp == 'H') {
PrintAndLog("Usage: hf mf sim u <uid (8 hex symbols)> n <numreads> i x");
PrintAndLog(" h this help");
PrintAndLog(" u (Optional) UID. If not specified, the UID from emulator memory will be used");
PrintAndLog(" n (Optional) Automatically exit simulation after <numreads> blocks have been read by reader. 0 = infinite");
PrintAndLog(" i (Optional) Interactive, means that console will not be returned until simulation finishes or is aborted");
PrintAndLog(" x (Optional) Crack, performs the 'reader attack', nr/ar attack against a legitimate reader, fishes out the key(s)");
PrintAndLog("");
PrintAndLog(" sample: hf mf sim u 0a0a0a0a ");
return 0;
}
int uidlen = 0;
uint8_t pnr = 0;
if (param_getchar(Cmd, pnr) == 'u') {
if(param_gethex(Cmd, pnr+1, uid, 8) == 0)
{
flags |= FLAG_4B_UID_IN_DATA; // UID from packet
} else if(param_gethex(Cmd,pnr+1,uid,14) == 0) {
flags |= FLAG_7B_UID_IN_DATA;// UID from packet
} else {
PrintAndLog("UID, if specified, must include 8 or 14 HEX symbols");
bool setEmulatorMem = false;
bool attackFromFile = false;
FILE *f;
char filename[FILE_PATH_SIZE];
memset(filename, 0x00, sizeof(filename));
int len = 0;
char buf[64];
uint8_t cmdp = 0;
bool errors = false;
while(param_getchar(Cmd, cmdp) != 0x00) {
switch(param_getchar(Cmd, cmdp)) {
case 'e':
case 'E':
setEmulatorMem = true;
//implies x and i
flags |= FLAG_INTERACTIVE;
flags |= FLAG_NR_AR_ATTACK;
cmdp++;
break;
case 'f':
case 'F':
len = param_getstr(Cmd, cmdp+1, filename);
if (len < 1) {
PrintAndLog("error no filename found");
return 0;
}
attackFromFile = true;
//implies x and i
flags |= FLAG_INTERACTIVE;
flags |= FLAG_NR_AR_ATTACK;
cmdp += 2;
break;
case 'h':
case 'H':
return usage_hf14_mf1ksim();
case 'i':
case 'I':
flags |= FLAG_INTERACTIVE;
cmdp++;
break;
case 'n':
case 'N':
exitAfterNReads = param_get8(Cmd, pnr+1);
cmdp += 2;
break;
case 'u':
case 'U':
param_gethex_ex(Cmd, cmdp+1, uid, &uidlen);
switch(uidlen) {
case 20: flags = FLAG_10B_UID_IN_DATA; break; //not complete
case 14: flags = FLAG_7B_UID_IN_DATA; break;
case 8: flags = FLAG_4B_UID_IN_DATA; break;
default: return usage_hf14_mf1ksim();
}
cmdp += 2;
break;
case 'x':
case 'X':
flags |= FLAG_NR_AR_ATTACK;
cmdp++;
break;
default:
PrintAndLog("Unknown parameter '%c'", param_getchar(Cmd, cmdp));
errors = true;
break;
}
if(errors) break;
}
//Validations
if(errors) return usage_hf14_mf1ksim();
//get uid from file
if (attackFromFile) {
int count = 0;
// open file
f = fopen(filename, "r");
if (f == NULL) {
PrintAndLog("File %s not found or locked", filename);
return 1;
}
pnr +=2;
}
if (param_getchar(Cmd, pnr) == 'n') {
exitAfterNReads = param_get8(Cmd,pnr+1);
pnr += 2;
}
if (param_getchar(Cmd, pnr) == 'i' ) {
//Using a flag to signal interactiveness, least significant bit
flags |= FLAG_INTERACTIVE;
pnr++;
}
PrintAndLog("Loading file and simulating. Press keyboard to abort");
while(!feof(f) && !ukbhit()){
memset(buf, 0, sizeof(buf));
memset(uid, 0, sizeof(uid));
if (param_getchar(Cmd, pnr) == 'x' ) {
//Using a flag to signal interactiveness, least significant bit
flags |= FLAG_NR_AR_ATTACK;
}
PrintAndLog(" uid:%s, numreads:%d, flags:%d (0x%02x) ",
if (fgets(buf, sizeof(buf), f) == NULL) {
if (count > 0) break;
PrintAndLog("File reading error.");
fclose(f);
return 2;
}
if(!strlen(buf) && feof(f)) break;
uidlen = strlen(buf)-1;
switch(uidlen) {
case 20: flags |= FLAG_10B_UID_IN_DATA; break; //not complete
case 14: flags |= FLAG_7B_UID_IN_DATA; break;
case 8: flags |= FLAG_4B_UID_IN_DATA; break;
default:
PrintAndLog("uid in file wrong length at %d (length: %d) [%s]",count, uidlen, buf);
fclose(f);
return 2;
}
for (uint8_t i = 0; i < uidlen; i += 2) {
sscanf(&buf[i], "%02x", (unsigned int *)&uid[i / 2]);
}
PrintAndLog("mf 1k sim uid: %s, numreads:%d, flags:%d (0x%02x) - press button to abort",
flags & FLAG_4B_UID_IN_DATA ? sprint_hex(uid,4):
flags & FLAG_7B_UID_IN_DATA ? sprint_hex(uid,7):
flags & FLAG_10B_UID_IN_DATA ? sprint_hex(uid,10): "N/A"
, exitAfterNReads, flags, flags);
UsbCommand c = {CMD_SIMULATE_MIFARE_CARD, {flags, exitAfterNReads,0}};
memcpy(c.d.asBytes, uid, sizeof(uid));
clearCommandBuffer();
SendCommand(&c);
while(! WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
//We're waiting only 1.5 s at a time, otherwise we get the
// annoying message about "Waiting for a response... "
}
//got a response
nonces_t ar_resp[ATTACK_KEY_COUNT*2];
memcpy(ar_resp, resp.d.asBytes, sizeof(ar_resp));
readerAttack(ar_resp, setEmulatorMem);
if ((bool)resp.arg[1]) {
PrintAndLog("Device button pressed - quitting");
fclose(f);
return 4;
}
count++;
}
fclose(f);
} else { //not from file
PrintAndLog("mf 1k sim uid: %s, numreads:%d, flags:%d (0x%02x) ",
flags & FLAG_4B_UID_IN_DATA ? sprint_hex(uid,4):
flags & FLAG_7B_UID_IN_DATA ? sprint_hex(uid,7): "N/A"
, exitAfterNReads, flags,flags);
flags & FLAG_7B_UID_IN_DATA ? sprint_hex(uid,7):
flags & FLAG_10B_UID_IN_DATA ? sprint_hex(uid,10): "N/A"
, exitAfterNReads, flags, flags);
UsbCommand c = {CMD_SIMULATE_MIFARE_CARD, {flags, exitAfterNReads,0}};
memcpy(c.d.asBytes, uid, sizeof(uid));
clearCommandBuffer();
SendCommand(&c);
UsbCommand c = {CMD_SIMULATE_MIFARE_CARD, {flags, exitAfterNReads,0}};
memcpy(c.d.asBytes, uid, sizeof(uid));
SendCommand(&c);
if(flags & FLAG_INTERACTIVE)
{
UsbCommand resp;
PrintAndLog("Press pm3-button to abort simulation");
while(! WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
//We're waiting only 1.5 s at a time, otherwise we get the
// annoying message about "Waiting for a response... "
if(flags & FLAG_INTERACTIVE) {
PrintAndLog("Press pm3-button to abort simulation");
while(! WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
//We're waiting only 1.5 s at a time, otherwise we get the
// annoying message about "Waiting for a response... "
}
//got a response
if (flags & FLAG_NR_AR_ATTACK) {
nonces_t ar_resp[ATTACK_KEY_COUNT*2];
memcpy(ar_resp, resp.d.asBytes, sizeof(ar_resp));
readerAttack(ar_resp, setEmulatorMem);
}
}
}
return 0;
}

View file

@ -13,24 +13,26 @@
#include <string.h>
#include <limits.h>
#include "proxmark3.h"
#include "data.h"
#include "graph.h"
#include "ui.h"
#include "cmdparser.h"
#include "cmdmain.h"
#include "cmddata.h"
#include "util.h"
#include "cmdlf.h"
#include "cmdlfhid.h"
#include "cmdlfawid.h"
#include "cmdlfti.h"
#include "cmdlfem4x.h"
#include "cmdlfhitag.h"
#include "cmdlft55xx.h"
#include "cmdlfpcf7931.h"
#include "cmdlfio.h"
#include "cmdlfviking.h"
#include "lfdemod.h"
#include "lfdemod.h" // for psk2TOpsk1
#include "util.h" // for parsing cli command utils
#include "ui.h" // for show graph controls
#include "graph.h" // for graph data
#include "cmdparser.h" // for getting cli commands included in cmdmain.h
#include "cmdmain.h" // for sending cmds to device
#include "data.h" // for GetFromBigBuf
#include "cmddata.h" // for `lf search`
#include "cmdlfawid.h" // for awid menu
#include "cmdlfem4x.h" // for em4x menu
#include "cmdlfhid.h" // for hid menu
#include "cmdlfhitag.h" // for hitag menu
#include "cmdlfio.h" // for ioprox menu
#include "cmdlft55xx.h" // for t55xx menu
#include "cmdlfti.h" // for ti menu
#include "cmdlfpresco.h" // for presco menu
#include "cmdlfpcf7931.h"// for pcf7931 menu
#include "cmdlfpyramid.h"// for pyramid menu
#include "cmdlfviking.h" // for viking menu
static int CmdHelp(const char *Cmd);
@ -538,7 +540,7 @@ int CmdLFSetConfig(const char *Cmd)
return usage_lf_config();
}
//Bps is limited to 8, so fits in lower half of arg1
if(bps >> 8) bps = 8;
if(bps >> 4) bps = 8;
sample_config config = {
decimation,bps,averaging,divisor,trigger_threshold
@ -662,7 +664,7 @@ int usage_lf_simask(void)
PrintAndLog(" b sim ask/biphase");
PrintAndLog(" m sim ask/manchester - Default");
PrintAndLog(" r sim ask/raw");
PrintAndLog(" s TBD- -to enable a gap between playback repetitions - default: no gap");
PrintAndLog(" s add t55xx Sequence Terminator gap - default: no gaps (only manchester)");
PrintAndLog(" d <hexdata> Data to sim as hex - omit to sim from DemodBuffer");
return 0;
}
@ -1219,7 +1221,9 @@ static command_t CommandTable[] =
{"hid", CmdLFHID, 1, "{ HID RFIDs... }"},
{"hitag", CmdLFHitag, 1, "{ Hitag tags and transponders... }"},
{"io", CmdLFIO, 1, "{ ioProx tags... }"},
{"presco", CmdLFPresco, 1, "{ Presco RFIDs... }"},
{"pcf7931", CmdLFPCF7931, 1, "{ PCF7931 RFIDs... }"},
{"pyramid", CmdLFPyramid, 1, "{ Farpointe/Pyramid RFIDs... }"},
{"t55xx", CmdLFT55XX, 1, "{ T55xx RFIDs... }"},
{"ti", CmdLFTI, 1, "{ TI RFIDs... }"},
{"viking", CmdLFViking, 1, "{ Viking tags... }"},

263
client/cmdlfpresco.c Normal file
View file

@ -0,0 +1,263 @@
//-----------------------------------------------------------------------------
//
// 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.
//-----------------------------------------------------------------------------
// Low frequency Presco tag commands
//-----------------------------------------------------------------------------
#include <string.h>
#include <inttypes.h>
#include "cmdlfpresco.h"
#include "proxmark3.h"
#include "ui.h"
#include "util.h"
#include "graph.h"
#include "cmdparser.h"
#include "cmddata.h"
#include "cmdmain.h"
#include "cmdlf.h"
#include "protocols.h" // for T55xx config register definitions
#include "lfdemod.h" // parityTest
static int CmdHelp(const char *Cmd);
int usage_lf_presco_clone(void){
PrintAndLog("clone a Presco tag to a T55x7 tag.");
PrintAndLog("Usage: lf presco clone d <Card-ID> H <hex-ID> <Q5>");
PrintAndLog("Options :");
PrintAndLog(" d <Card-ID> : 9 digit presco card ID");
PrintAndLog(" H <hex-ID> : 8 digit hex card number");
PrintAndLog(" <Q5> : specify write to Q5 (t5555 instead of t55x7)");
PrintAndLog("");
PrintAndLog("Sample : lf presco clone d 123456789");
return 0;
}
int usage_lf_presco_sim(void) {
PrintAndLog("Enables simulation of presco card with specified card number.");
PrintAndLog("Simulation runs until the button is pressed or another USB command is issued.");
PrintAndLog("Per presco format, the card number is 9 digit number and can contain *# chars. Larger values are truncated.");
PrintAndLog("");
PrintAndLog("Usage: lf presco sim d <Card-ID> or H <hex-ID>");
PrintAndLog("Options :");
PrintAndLog(" d <Card-ID> : 9 digit presco card number");
PrintAndLog(" H <hex-ID> : 8 digit hex card number");
PrintAndLog("");
PrintAndLog("Sample : lf presco sim d 123456789");
return 0;
}
// convert base 12 ID to sitecode & usercode & 8 bit other unknown code
int GetWiegandFromPresco(const char *Cmd, uint32_t *sitecode, uint32_t *usercode, uint32_t *fullcode, bool *Q5) {
uint8_t val = 0;
bool hex = false, errors = false;
uint8_t cmdp = 0;
char id[11];
int stringlen = 0;
while(param_getchar(Cmd, cmdp) != 0x00) {
switch(param_getchar(Cmd, cmdp)) {
case 'h':
return -1;
case 'H':
hex = true;
//get hex
*fullcode = param_get32ex(Cmd, cmdp+1, 0, 10);
cmdp+=2;
break;
case 'P':
case 'p':
//param get string int param_getstr(const char *line, int paramnum, char * str)
stringlen = param_getstr(Cmd, cmdp+1, id);
if (stringlen < 2) return -1;
cmdp+=2;
break;
case 'Q':
case 'q':
*Q5 = true;
cmdp++;
break;
default:
PrintAndLog("Unknown parameter '%c'", param_getchar(Cmd, cmdp));
errors = 1;
break;
}
if(errors) break;
}
// No args
if(cmdp == 0) errors = 1;
//Validations
if(errors) return -1;
if (!hex) {
for (int index =0; index < strlen(id); ++index) {
// Get value from number string.
if ( id[index] == '*' ) val = 10;
if ( id[index] == '#') val = 11;
if ( id[index] >= 0x30 && id[index] <= 0x39 )
val = id[index] - 0x30;
*fullcode += val;
// last digit is only added, not multipled.
if ( index < strlen(id)-1 )
*fullcode *= 12;
}
}
*usercode = *fullcode & 0x0000FFFF; //% 65566
*sitecode = (*fullcode >> 24) & 0x000000FF; // /= 16777216;
return 0;
}
// calc not certain - intended to get bitstream for programming / sim
int GetPrescoBits(uint32_t fullcode, uint8_t *prescoBits) {
num_to_bytebits(0x10D00000, 32, prescoBits);
num_to_bytebits(0x00000000, 32, prescoBits+32);
num_to_bytebits(0x00000000, 32, prescoBits+64);
num_to_bytebits(fullcode , 32, prescoBits+96);
return 1;
}
//see ASKDemod for what args are accepted
int CmdPrescoDemod(const char *Cmd) {
if (!ASKDemod(Cmd, false, false, 1)) {
if (g_debugMode) PrintAndLog("ASKDemod failed");
return 0;
}
size_t size = DemodBufferLen;
//call lfdemod.c demod for Viking
int ans = PrescoDemod(DemodBuffer, &size);
if (ans < 0) {
if (g_debugMode) PrintAndLog("Error Presco_Demod %d", ans);
return 0;
}
//got a good demod
uint32_t raw1 = bytebits_to_byte(DemodBuffer+ans, 32);
uint32_t raw2 = bytebits_to_byte(DemodBuffer+ans+32, 32);
uint32_t raw3 = bytebits_to_byte(DemodBuffer+ans+64, 32);
uint32_t raw4 = bytebits_to_byte(DemodBuffer+ans+96, 32);
uint32_t cardid = raw4;
PrintAndLog("Presco Tag Found: Card ID %08X", cardid);
PrintAndLog("Raw: %08X%08X%08X%08X", raw1,raw2,raw3,raw4);
setDemodBuf(DemodBuffer+ans, 128, 0);
uint32_t sitecode = 0, usercode = 0, fullcode = 0;
bool Q5=false;
char cmd[12] = {0};
sprintf(cmd, "H %08X", cardid);
GetWiegandFromPresco(cmd, &sitecode, &usercode, &fullcode, &Q5);
PrintAndLog("SiteCode %u, UserCode %u, FullCode, %08X", sitecode, usercode, fullcode);
return 1;
}
//see ASKDemod for what args are accepted
int CmdPrescoRead(const char *Cmd) {
// Presco Number: 123456789 --> Sitecode 30 | usercode 8665
// read lf silently
CmdLFRead("s");
// get samples silently
getSamples("30000",false);
// demod and output Presco ID
return CmdPrescoDemod(Cmd);
}
// takes base 12 ID converts to hex
// Or takes 8 digit hex ID
int CmdPrescoClone(const char *Cmd) {
bool Q5 = false;
uint32_t sitecode=0, usercode=0, fullcode=0;
uint32_t blocks[5] = {T55x7_MODULATION_MANCHESTER | T55x7_BITRATE_RF_32 | 4<<T55x7_MAXBLOCK_SHIFT | T55x7_ST_TERMINATOR, 0, 0, 0, 5};
// get wiegand from printed number.
if (GetWiegandFromPresco(Cmd, &sitecode, &usercode, &fullcode, &Q5) == -1) return usage_lf_presco_clone();
if (Q5)
blocks[0] = T5555_MODULATION_MANCHESTER | 32<<T5555_BITRATE_SHIFT | 4<<T5555_MAXBLOCK_SHIFT | T5555_ST_TERMINATOR;
if ((sitecode & 0xFF) != sitecode) {
sitecode &= 0xFF;
PrintAndLog("Facility-Code Truncated to 8-bits (Presco): %u", sitecode);
}
if ((usercode & 0xFFFF) != usercode) {
usercode &= 0xFFFF;
PrintAndLog("Card Number Truncated to 16-bits (Presco): %u", usercode);
}
blocks[1] = 0x10D00000; //preamble
blocks[2] = 0x00000000;
blocks[3] = 0x00000000;
blocks[4] = fullcode;
PrintAndLog("Preparing to clone Presco to T55x7 with SiteCode: %u, UserCode: %u, FullCode: %08x", sitecode, usercode, fullcode);
PrintAndLog("Blk | Data ");
PrintAndLog("----+------------");
PrintAndLog(" 00 | 0x%08x", blocks[0]);
PrintAndLog(" 01 | 0x%08x", blocks[1]);
PrintAndLog(" 02 | 0x%08x", blocks[2]);
PrintAndLog(" 03 | 0x%08x", blocks[3]);
PrintAndLog(" 04 | 0x%08x", blocks[4]);
UsbCommand resp;
UsbCommand c = {CMD_T55XX_WRITE_BLOCK, {0,0,0}};
for (int i=4; i>=0; i--) {
c.arg[0] = blocks[i];
c.arg[1] = i;
clearCommandBuffer();
SendCommand(&c);
if (!WaitForResponseTimeout(CMD_ACK, &resp, 1000)){
PrintAndLog("Error occurred, device did not respond during write operation.");
return -1;
}
}
return 0;
}
// takes base 12 ID converts to hex
// Or takes 8 digit hex ID
int CmdPrescoSim(const char *Cmd) {
uint32_t sitecode=0, usercode=0, fullcode=0;
bool Q5=false;
// get wiegand from printed number.
if (GetWiegandFromPresco(Cmd, &sitecode, &usercode, &fullcode, &Q5) == -1) return usage_lf_presco_sim();
uint8_t clk = 32, encoding = 1, separator = 1, invert = 0;
uint16_t arg1, arg2;
size_t size = 128;
arg1 = clk << 8 | encoding;
arg2 = invert << 8 | separator;
PrintAndLog("Simulating Presco - SiteCode: %u, UserCode: %u, FullCode: %08X",sitecode, usercode, fullcode);
UsbCommand c = {CMD_ASK_SIM_TAG, {arg1, arg2, size}};
GetPrescoBits(fullcode, c.d.asBytes);
clearCommandBuffer();
SendCommand(&c);
return 0;
}
static command_t CommandTable[] = {
{"help", CmdHelp, 1, "This help"},
{"read", CmdPrescoRead, 0, "Attempt to read and Extract tag data"},
{"clone", CmdPrescoClone, 0, "d <9 digit ID> or h <hex> [Q5] clone presco tag"},
{"sim", CmdPrescoSim, 0, "d <9 digit ID> or h <hex> simulate presco tag"},
{NULL, NULL, 0, NULL}
};
int CmdLFPresco(const char *Cmd) {
clearCommandBuffer();
CmdsParse(CommandTable, Cmd);
return 0;
}
int CmdHelp(const char *Cmd) {
CmdsHelp(CommandTable);
return 0;
}

24
client/cmdlfpresco.h Normal file
View file

@ -0,0 +1,24 @@
//-----------------------------------------------------------------------------
//
// 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.
//-----------------------------------------------------------------------------
// Low frequency T55xx commands
//-----------------------------------------------------------------------------
#ifndef CMDLFPRESCO_H__
#define CMDLFPRESCO_H__
#include <stdint.h> //uint_32+
#include <stdbool.h> //bool
int CmdLFPresco(const char *Cmd);
int CmdPrescoClone(const char *Cmd);
int CmdPrescoSim(const char *Cmd);
int GetWiegandFromPresco(const char *id, uint32_t *sitecode, uint32_t *usercode, uint32_t *fullcode, bool *Q5);
int usage_lf_presco_clone(void);
int usage_lf_presco_sim(void);
#endif

199
client/cmdlfpyramid.c Normal file
View file

@ -0,0 +1,199 @@
//-----------------------------------------------------------------------------
//
// 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.
//-----------------------------------------------------------------------------
// Low frequency Farpoint / Pyramid tag commands
//-----------------------------------------------------------------------------
#include <string.h>
#include <inttypes.h>
#include "cmdlfpyramid.h"
#include "proxmark3.h"
#include "ui.h"
#include "util.h"
#include "graph.h"
#include "cmdparser.h"
#include "cmddata.h"
#include "cmdmain.h"
#include "cmdlf.h"
#include "protocols.h" // for T55xx config register definitions
#include "lfdemod.h" // parityTest
#include "crc.h"
static int CmdHelp(const char *Cmd);
int usage_lf_pyramid_clone(void){
PrintAndLog("clone a Farpointe/Pyramid tag to a T55x7 tag.");
PrintAndLog("The facility-code is 8-bit and the card number is 16-bit. Larger values are truncated. ");
PrintAndLog("Currently work only on 26bit");
PrintAndLog("");
PrintAndLog("Usage: lf pyramid clone <Facility-Code> <Card-Number>");
PrintAndLog("Options :");
PrintAndLog(" <Facility-Code> : 8-bit value facility code");
PrintAndLog(" <Card Number> : 16-bit value card number");
PrintAndLog(" Q5 : optional - clone to Q5 (T5555) instead of T55x7 chip");
PrintAndLog("");
PrintAndLog("Sample : lf pyramid clone 123 11223");
return 0;
}
int usage_lf_pyramid_sim(void) {
PrintAndLog("Enables simulation of Farpointe/Pyramid card with specified card number.");
PrintAndLog("Simulation runs until the button is pressed or another USB command is issued.");
PrintAndLog("The facility-code is 8-bit and the card number is 16-bit. Larger values are truncated.");
PrintAndLog("Currently work only on 26bit");
PrintAndLog("");
PrintAndLog("Usage: lf pyramid sim <Card-Number>");
PrintAndLog("Options :");
PrintAndLog(" <Facility-Code> : 8-bit value facility code");
PrintAndLog(" <Card Number> : 16-bit value card number");
PrintAndLog("");
PrintAndLog("Sample : lf pyramid sim 123 11223");
return 0;
}
// Works for 26bits.
int GetPyramidBits(uint32_t fc, uint32_t cn, uint8_t *pyramidBits) {
uint8_t pre[128];
memset(pre, 0x00, sizeof(pre));
// format start bit
pre[79] = 1;
// Get 26 wiegand from FacilityCode, CardNumber
uint8_t wiegand[24];
memset(wiegand, 0x00, sizeof(wiegand));
num_to_bytebits(fc, 8, wiegand);
num_to_bytebits(cn, 16, wiegand+8);
// add wiegand parity bits (dest, source, len)
wiegand_add_parity(pre+80, wiegand, 24);
// add paritybits (bitsource, dest, sourcelen, paritylen, parityType (odd, even,)
addParity(pre+8, pyramidBits+8, 102, 8, 1);
// add checksum
uint8_t csBuff[13];
for (uint8_t i = 0; i < 13; i++)
csBuff[i] = bytebits_to_byte(pyramidBits + 16 + (i*8), 8);
uint32_t crc = CRC8Maxim(csBuff, 13);
num_to_bytebits(crc, 8, pyramidBits+120);
return 1;
}
int CmdPyramidRead(const char *Cmd) {
CmdLFRead("s");
getSamples("30000",false);
return CmdFSKdemodPyramid("");
}
int CmdPyramidClone(const char *Cmd) {
char cmdp = param_getchar(Cmd, 0);
if (strlen(Cmd) == 0 || cmdp == 'h' || cmdp == 'H') return usage_lf_pyramid_clone();
uint32_t facilitycode=0, cardnumber=0, fc = 0, cn = 0;
uint32_t blocks[5];
uint8_t i;
uint8_t bs[128];
memset(bs, 0x00, sizeof(bs));
if (sscanf(Cmd, "%u %u", &fc, &cn ) != 2) return usage_lf_pyramid_clone();
facilitycode = (fc & 0x000000FF);
cardnumber = (cn & 0x0000FFFF);
if ( !GetPyramidBits(facilitycode, cardnumber, bs)) {
PrintAndLog("Error with tag bitstream generation.");
return 1;
}
//Pyramid - compat mode, FSK2a, data rate 50, 4 data blocks
blocks[0] = T55x7_MODULATION_FSK2a | T55x7_BITRATE_RF_50 | 4<<T55x7_MAXBLOCK_SHIFT;
if (param_getchar(Cmd, 3) == 'Q' || param_getchar(Cmd, 3) == 'q')
blocks[0] = T5555_MODULATION_FSK2 | T5555_INVERT_OUTPUT | 50<<T5555_BITRATE_SHIFT | 4<<T5555_MAXBLOCK_SHIFT;
blocks[1] = bytebits_to_byte(bs,32);
blocks[2] = bytebits_to_byte(bs+32,32);
blocks[3] = bytebits_to_byte(bs+64,32);
blocks[4] = bytebits_to_byte(bs+96,32);
PrintAndLog("Preparing to clone Farpointe/Pyramid to T55x7 with Facility Code: %u, Card Number: %u", facilitycode, cardnumber);
PrintAndLog("Blk | Data ");
PrintAndLog("----+------------");
for ( i = 0; i<5; ++i )
PrintAndLog(" %02d | %08" PRIx32, i, blocks[i]);
UsbCommand resp;
UsbCommand c = {CMD_T55XX_WRITE_BLOCK, {0,0,0}};
for ( i = 0; i<5; ++i ) {
c.arg[0] = blocks[i];
c.arg[1] = i;
clearCommandBuffer();
SendCommand(&c);
if (!WaitForResponseTimeout(CMD_ACK, &resp, 1000)){
PrintAndLog("Error occurred, device did not respond during write operation.");
return -1;
}
}
return 0;
}
int CmdPyramidSim(const char *Cmd) {
char cmdp = param_getchar(Cmd, 0);
if (strlen(Cmd) == 0 || cmdp == 'h' || cmdp == 'H') return usage_lf_pyramid_sim();
uint32_t facilitycode = 0, cardnumber = 0, fc = 0, cn = 0;
uint8_t bs[128];
size_t size = sizeof(bs);
memset(bs, 0x00, size);
// Pyramid uses: fcHigh: 10, fcLow: 8, clk: 50, invert: 0
uint64_t arg1, arg2;
arg1 = (10 << 8) + 8;
arg2 = 50 | 0;
if (sscanf(Cmd, "%u %u", &fc, &cn ) != 2) return usage_lf_pyramid_sim();
facilitycode = (fc & 0x000000FF);
cardnumber = (cn & 0x0000FFFF);
if ( !GetPyramidBits(facilitycode, cardnumber, bs)) {
PrintAndLog("Error with tag bitstream generation.");
return 1;
}
PrintAndLog("Simulating Farpointe/Pyramid - Facility Code: %u, CardNumber: %u", facilitycode, cardnumber );
UsbCommand c = {CMD_FSK_SIM_TAG, {arg1, arg2, size}};
memcpy(c.d.asBytes, bs, size);
clearCommandBuffer();
SendCommand(&c);
return 0;
}
static command_t CommandTable[] = {
{"help", CmdHelp, 1, "This help"},
{"read", CmdPyramidRead, 0, "Attempt to read and extract tag data"},
{"clone", CmdPyramidClone, 0, "<Facility-Code> <Card Number> clone pyramid tag"},
{"sim", CmdPyramidSim, 0, "<Facility-Code> <Card Number> simulate pyramid tag"},
{NULL, NULL, 0, NULL}
};
int CmdLFPyramid(const char *Cmd) {
clearCommandBuffer();
CmdsParse(CommandTable, Cmd);
return 0;
}
int CmdHelp(const char *Cmd) {
CmdsHelp(CommandTable);
return 0;
}

19
client/cmdlfpyramid.h Normal file
View file

@ -0,0 +1,19 @@
//-----------------------------------------------------------------------------
//
// 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.
//-----------------------------------------------------------------------------
// Low frequency T55xx commands
//-----------------------------------------------------------------------------
#ifndef CMDLFPYRAMID_H__
#define CMDLFPYRAMID_H__
int CmdLFPyramid(const char *Cmd);
int CmdPyramidClone(const char *Cmd);
int CmdPyramidSim(const char *Cmd);
int usage_lf_pyramid_clone(void);
int usage_lf_pyramid_sim(void);
#endif

View file

@ -76,7 +76,7 @@ int usage_t55xx_read(){
return 0;
}
int usage_t55xx_write(){
PrintAndLog("Usage: lf t55xx wr [b <block>] [d <data>] [p <password>] [1]");
PrintAndLog("Usage: lf t55xx write [b <block>] [d <data>] [p <password>] [1]");
PrintAndLog("Options:");
PrintAndLog(" b <block> - block number to write. Between 0-7");
PrintAndLog(" d <data> - 4 bytes of data to write (8 hex characters)");
@ -84,8 +84,8 @@ int usage_t55xx_write(){
PrintAndLog(" 1 - OPTIONAL write Page 1 instead of Page 0");
PrintAndLog("");
PrintAndLog("Examples:");
PrintAndLog(" lf t55xx wr b 3 d 11223344 - write 11223344 to block 3");
PrintAndLog(" lf t55xx wr b 3 d 11223344 p feedbeef - write 11223344 to block 3 password feedbeef");
PrintAndLog(" lf t55xx write b 3 d 11223344 - write 11223344 to block 3");
PrintAndLog(" lf t55xx write b 3 d 11223344 p feedbeef - write 11223344 to block 3 password feedbeef");
PrintAndLog("");
return 0;
}

View file

@ -47,8 +47,8 @@ int usage_lf_viking_sim(void) {
uint64_t getVikingBits(uint32_t id) {
//calc checksum
uint8_t checksum = (id>>24) ^ ((id>>16) & 0xFF) ^ ((id>>8) & 0xFF) ^ (id & 0xFF) ^ 0xF2 ^ 0xA8;
return ((uint64_t)0xF2 << 56) | (id << 8) | checksum;
uint8_t checksum = ((id>>24) & 0xFF) ^ ((id>>16) & 0xFF) ^ ((id>>8) & 0xFF) ^ (id & 0xFF) ^ 0xF2 ^ 0xA8;
return ((uint64_t)0xF2 << 56) | ((uint64_t)id << 8) | checksum;
}
//by marshmellow
//see ASKDemod for what args are accepted

View file

@ -149,3 +149,140 @@ int nonce2key(uint32_t uid, uint32_t nt, uint32_t nr, uint64_t par_info, uint64_
return 1;
}
// 32 bit recover key from 2 nonces
bool mfkey32(nonces_t data, uint64_t *outputkey) {
struct Crypto1State *s,*t;
uint64_t outkey = 0;
uint64_t key=0; // recovered key
uint32_t uid = data.cuid;
uint32_t nt = data.nonce; // first tag challenge (nonce)
uint32_t nr0_enc = data.nr; // first encrypted reader challenge
uint32_t ar0_enc = data.ar; // first encrypted reader response
uint32_t nr1_enc = data.nr2; // second encrypted reader challenge
uint32_t ar1_enc = data.ar2; // second encrypted reader response
clock_t t1 = clock();
bool isSuccess = FALSE;
uint8_t counter=0;
s = lfsr_recovery32(ar0_enc ^ prng_successor(nt, 64), 0);
for(t = s; t->odd | t->even; ++t) {
lfsr_rollback_word(t, 0, 0);
lfsr_rollback_word(t, nr0_enc, 1);
lfsr_rollback_word(t, uid ^ nt, 0);
crypto1_get_lfsr(t, &key);
crypto1_word(t, uid ^ nt, 0);
crypto1_word(t, nr1_enc, 1);
if (ar1_enc == (crypto1_word(t, 0, 0) ^ prng_successor(nt, 64))) {
//PrintAndLog("Found Key: [%012"llx"]",key);
outkey = key;
counter++;
if (counter==20) break;
}
}
isSuccess = (counter == 1);
t1 = clock() - t1;
//if ( t1 > 0 ) PrintAndLog("Time in mfkey32: %.0f ticks \nFound %d possible keys", (float)t1, counter);
*outputkey = ( isSuccess ) ? outkey : 0;
crypto1_destroy(s);
/* //un-comment to save all keys to a stats.txt file
FILE *fout;
if ((fout = fopen("stats.txt","ab")) == NULL) {
PrintAndLog("Could not create file name stats.txt");
return 1;
}
fprintf(fout, "mfkey32,%d,%08x,%d,%s,%04x%08x,%.0Lf\r\n", counter, data.cuid, data.sector, (data.keytype) ? "B" : "A", (uint32_t)(outkey>>32) & 0xFFFF,(uint32_t)(outkey&0xFFFFFFFF),(long double)t1);
fclose(fout);
*/
return isSuccess;
}
bool tryMfk32_moebius(nonces_t data, uint64_t *outputkey) {
struct Crypto1State *s, *t;
uint64_t outkey = 0;
uint64_t key = 0; // recovered key
uint32_t uid = data.cuid;
uint32_t nt0 = data.nonce; // first tag challenge (nonce)
uint32_t nr0_enc = data.nr; // first encrypted reader challenge
uint32_t ar0_enc = data.ar; // first encrypted reader response
uint32_t nt1 = data.nonce2; // second tag challenge (nonce)
uint32_t nr1_enc = data.nr2; // second encrypted reader challenge
uint32_t ar1_enc = data.ar2; // second encrypted reader response
bool isSuccess = FALSE;
int counter = 0;
//PrintAndLog("Enter mfkey32_moebius");
clock_t t1 = clock();
s = lfsr_recovery32(ar0_enc ^ prng_successor(nt0, 64), 0);
for(t = s; t->odd | t->even; ++t) {
lfsr_rollback_word(t, 0, 0);
lfsr_rollback_word(t, nr0_enc, 1);
lfsr_rollback_word(t, uid ^ nt0, 0);
crypto1_get_lfsr(t, &key);
crypto1_word(t, uid ^ nt1, 0);
crypto1_word(t, nr1_enc, 1);
if (ar1_enc == (crypto1_word(t, 0, 0) ^ prng_successor(nt1, 64))) {
//PrintAndLog("Found Key: [%012"llx"]",key);
outkey=key;
++counter;
if (counter==20)
break;
}
}
isSuccess = (counter == 1);
t1 = clock() - t1;
//if ( t1 > 0 ) PrintAndLog("Time in mfkey32_moebius: %.0f ticks \nFound %d possible keys", (float)t1,counter);
*outputkey = ( isSuccess ) ? outkey : 0;
crypto1_destroy(s);
/* // un-comment to output all keys to stats.txt
FILE *fout;
if ((fout = fopen("stats.txt","ab")) == NULL) {
PrintAndLog("Could not create file name stats.txt");
return 1;
}
fprintf(fout, "moebius,%d,%08x,%d,%s,%04x%08x,%0.Lf\r\n", counter, data.cuid, data.sector, (data.keytype) ? "B" : "A", (uint32_t) (outkey>>32),(uint32_t)(outkey&0xFFFFFFFF),(long double)t1);
fclose(fout);
*/
return isSuccess;
}
int tryMfk64_ex(uint8_t *data, uint64_t *outputkey){
uint32_t uid = le32toh(data);
uint32_t nt = le32toh(data+4); // tag challenge
uint32_t nr_enc = le32toh(data+8); // encrypted reader challenge
uint32_t ar_enc = le32toh(data+12); // encrypted reader response
uint32_t at_enc = le32toh(data+16); // encrypted tag response
return tryMfk64(uid, nt, nr_enc, ar_enc, at_enc, outputkey);
}
int tryMfk64(uint32_t uid, uint32_t nt, uint32_t nr_enc, uint32_t ar_enc, uint32_t at_enc, uint64_t *outputkey){
uint64_t key = 0; // recovered key
uint32_t ks2; // keystream used to encrypt reader response
uint32_t ks3; // keystream used to encrypt tag response
struct Crypto1State *revstate;
PrintAndLog("Enter mfkey64");
clock_t t1 = clock();
// Extract the keystream from the messages
ks2 = ar_enc ^ prng_successor(nt, 64);
ks3 = at_enc ^ prng_successor(nt, 96);
revstate = lfsr_recovery64(ks2, ks3);
lfsr_rollback_word(revstate, 0, 0);
lfsr_rollback_word(revstate, 0, 0);
lfsr_rollback_word(revstate, nr_enc, 1);
lfsr_rollback_word(revstate, uid ^ nt, 0);
crypto1_get_lfsr(revstate, &key);
PrintAndLog("Found Key: [%012"llx"]", key);
crypto1_destroy(revstate);
*outputkey = key;
t1 = clock() - t1;
if ( t1 > 0 ) PrintAndLog("Time in mfkey64: %.0f ticks \n", (float)t1);
return 0;
}

View file

@ -17,7 +17,26 @@
#include <stdlib.h>
#include "crapto1.h"
#include "common.h"
//#include <stdbool.h> //for bool
typedef struct {
uint32_t cuid;
uint8_t sector;
uint8_t keytype;
uint32_t nonce;
uint32_t ar;
uint32_t nr;
uint32_t nonce2;
uint32_t ar2;
uint32_t nr2;
} nonces_t;
int nonce2key(uint32_t uid, uint32_t nt, uint32_t nr, uint64_t par_info, uint64_t ks_info, uint64_t * key);
bool mfkey32(nonces_t data, uint64_t *outputkey);
bool tryMfk32_moebius(nonces_t data, uint64_t *outputkey);
int tryMfk64_ex(uint8_t *data, uint64_t *outputkey);
int tryMfk64(uint32_t uid, uint32_t nt, uint32_t nr_enc, uint32_t ar_enc, uint32_t at_enc, uint64_t *outputkey);
//uint64_t mfkey32(uint32_t uid, uint32_t nt, uint32_t nr0_enc, uint32_t ar0_enc, uint32_t nr1_enc, uint32_t ar1_enc);
#endif

View file

@ -19,7 +19,7 @@ void MainGraphics(void);
void InitGraphics(int argc, char **argv);
void ExitGraphics(void);
#define MAX_GRAPH_TRACE_LEN (1024*128)
#define MAX_GRAPH_TRACE_LEN (40000*8)
extern int GraphBuffer[MAX_GRAPH_TRACE_LEN];
extern int GraphTraceLen;
extern double CursorScaleFactor;

View file

@ -498,6 +498,9 @@ void xor(unsigned char *dst, unsigned char *src, size_t len) {
int32_t le24toh (uint8_t data[3]) {
return (data[2] << 16) | (data[1] << 8) | data[0];
}
uint32_t le32toh (uint8_t *data) {
return (uint32_t)( (data[3]<<24) | (data[2]<<16) | (data[1]<<8) | data[0]);
}
// RotateLeft - Ultralight, Desfire, works on byte level
// 00-01-02 >> 01-02-00

View file

@ -9,13 +9,12 @@
//-----------------------------------------------------------------------------
#include <stdio.h>
#include <stdint.h>
#include <stdio.h>
#include <stdint.h> //included in data.h
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <time.h>
#include "data.h"
#include "data.h" //for FILE_PATH_SIZE
#ifndef ROTR
# define ROTR(x,n) (((uintmax_t)(x) >> (n)) | ((uintmax_t)(x) << ((sizeof(x) * 8) - (n))))
@ -71,4 +70,5 @@ void wiegand_add_parity(uint8_t *target, uint8_t *source, uint8_t length);
void xor(unsigned char *dst, unsigned char *src, size_t len);
int32_t le24toh(uint8_t data[3]);
uint32_t le32toh (uint8_t *data);
void rol(uint8_t *data, const size_t len);

View file

@ -68,7 +68,7 @@ uint8_t parityTest(uint32_t bits, uint8_t bitLen, uint8_t pType)
// by marshmellow
// takes a array of binary values, start position, length of bits per parity (includes parity bit),
// Parity Type (1 for odd; 0 for even; 2 Always 1's), and binary Length (length to run)
// Parity Type (1 for odd; 0 for even; 2 for Always 1's; 3 for Always 0's), and binary Length (length to run)
size_t removeParity(uint8_t *BitStream, size_t startIdx, uint8_t pLen, uint8_t pType, size_t bLen)
{
uint32_t parityWd = 0;
@ -80,10 +80,11 @@ size_t removeParity(uint8_t *BitStream, size_t startIdx, uint8_t pLen, uint8_t p
}
j--; // overwrite parity with next data
// if parity fails then return 0
if (pType == 2) { // then marker bit which should be a 1
if (!BitStream[j]) return 0;
} else {
if (parityTest(parityWd, pLen, pType) == 0) return 0;
switch (pType) {
case 3: if (BitStream[j]==1) return 0; break; //should be 0 spacer bit
case 2: if (BitStream[j]==0) return 0; break; //should be 1 spacer bit
default: //test parity
if (parityTest(parityWd, pLen, pType) == 0) return 0; break;
}
bitCnt+=(pLen-1);
parityWd = 0;
@ -95,7 +96,8 @@ size_t removeParity(uint8_t *BitStream, size_t startIdx, uint8_t pLen, uint8_t p
// by marshmellow
// takes a array of binary values, length of bits per parity (includes parity bit),
// Parity Type (1 for odd; 0 for even; 2 Always 1's), and binary Length (length to run)
// Parity Type (1 for odd; 0 for even; 2 Always 1's; 3 Always 0's), and binary Length (length to run)
// Make sure *dest is long enough to store original sourceLen + #_of_parities_to_be_added
size_t addParity(uint8_t *BitSource, uint8_t *dest, uint8_t sourceLen, uint8_t pLen, uint8_t pType)
{
uint32_t parityWd = 0;
@ -106,10 +108,12 @@ size_t addParity(uint8_t *BitSource, uint8_t *dest, uint8_t sourceLen, uint8_t p
dest[j++] = (BitSource[word+bit]);
}
// if parity fails then return 0
if (pType == 2) { // then marker bit which should be a 1
dest[j++]=1;
} else {
dest[j++] = parityTest(parityWd, pLen-1, pType) ^ 1;
switch (pType) {
case 3: dest[j++]=0; break; // marker bit which should be a 0
case 2: dest[j++]=1; break; // marker bit which should be a 1
default:
dest[j++] = parityTest(parityWd, pLen-1, pType) ^ 1;
break;
}
bitCnt += pLen;
parityWd = 0;
@ -256,11 +260,14 @@ int cleanAskRawDemod(uint8_t *BinStream, size_t *size, int clk, int invert, int
//by marshmellow
void askAmp(uint8_t *BitStream, size_t size)
{
uint8_t Last = 128;
for(size_t i = 1; i<size; i++){
if (BitStream[i]-BitStream[i-1]>=30) //large jump up
BitStream[i]=127;
else if(BitStream[i]-BitStream[i-1]<=-20) //large jump down
BitStream[i]=-127;
Last = 255;
else if(BitStream[i-1]-BitStream[i]>=20) //large jump down
Last = 0;
BitStream[i-1] = Last;
}
return;
}
@ -460,10 +467,10 @@ int gProxII_Demod(uint8_t BitStream[], size_t *size)
//return start position
return (int) startIdx;
}
return -5;
return -5; //spacer bits not found - not a valid gproxII
}
//translate wave to 11111100000 (1 for each short wave 0 for each long wave)
//translate wave to 11111100000 (1 for each short wave [higher freq] 0 for each long wave [lower freq])
size_t fsk_wave_demod(uint8_t * dest, size_t size, uint8_t fchigh, uint8_t fclow)
{
size_t last_transition = 0;
@ -487,6 +494,7 @@ size_t fsk_wave_demod(uint8_t * dest, size_t size, uint8_t fchigh, uint8_t fclow
// count cycles between consecutive lo-hi transitions, there should be either 8 (fc/8)
// or 10 (fc/10) cycles but in practice due to noise etc we may end up with anywhere
// between 7 to 11 cycles so fuzz it by treat anything <9 as 8 and anything else as 10
// (could also be fc/5 && fc/7 for fsk1 = 4-9)
for(idx = 161; idx < size-20; idx++) {
// threshold current value
@ -494,23 +502,24 @@ size_t fsk_wave_demod(uint8_t * dest, size_t size, uint8_t fchigh, uint8_t fclow
else dest[idx] = 1;
// Check for 0->1 transition
if (dest[idx-1] < dest[idx]) { // 0 -> 1 transition
if (dest[idx-1] < dest[idx]) {
preLastSample = LastSample;
LastSample = currSample;
currSample = idx-last_transition;
if (currSample < (fclow-2)){ //0-5 = garbage noise (or 0-3)
if (currSample < (fclow-2)) { //0-5 = garbage noise (or 0-3)
//do nothing with extra garbage
} else if (currSample < (fchigh-1)) { //6-8 = 8 sample waves or 3-6 = 5
} else if (currSample < (fchigh-1)) { //6-8 = 8 sample waves (or 3-6 = 5)
//correct previous 9 wave surrounded by 8 waves (or 6 surrounded by 5)
if (LastSample > (fchigh-2) && (preLastSample < (fchigh-1) || preLastSample == 0 )){
dest[numBits-1]=1; //correct previous 9 wave surrounded by 8 waves
dest[numBits-1]=1;
}
dest[numBits++]=1;
} else if (currSample > (fchigh) && !numBits) { //12 + and first bit = garbage
} else if (currSample > (fchigh) && !numBits) { //12 + and first bit = unusable garbage
//do nothing with beginning garbage
} else if (currSample == (fclow+1) && LastSample == (fclow-1)) { // had a 7 then a 9 should be two 8's
} else if (currSample == (fclow+1) && LastSample == (fclow-1)) { // had a 7 then a 9 should be two 8's (or 4 then a 6 should be two 5's)
dest[numBits++]=1;
} else { //9+ = 10 sample waves
} else { //9+ = 10 sample waves (or 6+ = 7)
dest[numBits++]=0;
}
last_transition = idx;
@ -520,6 +529,7 @@ size_t fsk_wave_demod(uint8_t * dest, size_t size, uint8_t fchigh, uint8_t fclow
}
//translate 11111100000 to 10
//rfLen = clock, fchigh = larger field clock, fclow = smaller field clock
size_t aggregate_bits(uint8_t *dest, size_t size, uint8_t rfLen,
uint8_t invert, uint8_t fchigh, uint8_t fclow)
{
@ -529,8 +539,9 @@ size_t aggregate_bits(uint8_t *dest, size_t size, uint8_t rfLen,
uint32_t n=1;
for( idx=1; idx < size; idx++) {
n++;
if (dest[idx]==lastval) continue;
if (dest[idx]==lastval) continue; //skip until we hit a transition
//find out how many bits (n) we collected
//if lastval was 1, we have a 1->0 crossing
if (dest[idx-1]==1) {
n = (n * fclow + rfLen/2) / rfLen;
@ -539,6 +550,7 @@ size_t aggregate_bits(uint8_t *dest, size_t size, uint8_t rfLen,
}
if (n == 0) n = 1;
//add to our destination the bits we collected
memset(dest+numBits, dest[idx-1]^invert , n);
numBits += n;
n=0;
@ -680,6 +692,19 @@ int VikingDemod_AM(uint8_t *dest, size_t *size) {
return (int) startIdx;
}
// find presco preamble 0x10D in already demoded data
int PrescoDemod(uint8_t *dest, size_t *size) {
//make sure buffer has data
if (*size < 64*2) return -2;
size_t startIdx = 0;
uint8_t preamble[] = {1,0,0,0,0,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0};
uint8_t errChk = preambleSearch(dest, preamble, sizeof(preamble), size, &startIdx);
if (errChk == 0) return -4; //preamble not found
//return start position
return (int) startIdx;
}
// Ask/Biphase Demod then try to locate an ISO 11784/85 ID
// BitStream must contain previously askrawdemod and biphasedemoded data
int FDXBdemodBI(uint8_t *dest, size_t *size)
@ -1478,8 +1503,8 @@ int pskRawDemod(uint8_t dest[], size_t *size, int *clock, int *invert)
numBits += (firstFullWave / *clock);
//set start of wave as clock align
lastClkBit = firstFullWave;
//PrintAndLog("DEBUG: firstFullWave: %d, waveLen: %d",firstFullWave,fullWaveLen);
//PrintAndLog("DEBUG: clk: %d, lastClkBit: %d", *clock, lastClkBit);
if (g_debugMode==2) prnt("DEBUG PSK: firstFullWave: %u, waveLen: %u",firstFullWave,fullWaveLen);
if (g_debugMode==2) prnt("DEBUG: clk: %d, lastClkBit: %u, fc: %u", *clock, lastClkBit,(unsigned int) fc);
waveStart = 0;
dest[numBits++] = curPhase; //set first read bit
for (i = firstFullWave + fullWaveLen - 1; i < *size-3; i++){
@ -1662,7 +1687,7 @@ bool DetectST(uint8_t buffer[], size_t *size, int *foundclock) {
i=0;
// warning - overwriting buffer given with raw wave data with ST removed...
while ( dataloc < bufsize-(clk/2) ) {
//compensate for long high at end of ST not being high... (we cut out the high part)
//compensate for long high at end of ST not being high due to signal loss... (and we cut out the start of wave high part)
if (buffer[dataloc]<high && buffer[dataloc]>low && buffer[dataloc+3]<high && buffer[dataloc+3]>low) {
for(i=0; i < clk/2-tol; ++i) {
buffer[dataloc+i] = high+5;
@ -1677,7 +1702,7 @@ bool DetectST(uint8_t buffer[], size_t *size, int *foundclock) {
}
}
newloc += i;
//skip next ST
//skip next ST - we just assume it will be there from now on...
dataloc += clk*4;
}
*size = newloc;

View file

@ -13,8 +13,8 @@
#ifndef LFDEMOD_H__
#define LFDEMOD_H__
#include <stdint.h>
#include "common.h" //for bool
#include <stdint.h> // for uint_32+
#include <stdbool.h> // for bool
//generic
size_t addParity(uint8_t *BitSource, uint8_t *dest, uint8_t sourceLen, uint8_t pLen, uint8_t pType);
@ -54,5 +54,5 @@ int indala26decode(uint8_t *bitStream, size_t *size, uint8_t *invert);
int ParadoxdemodFSK(uint8_t *dest, size_t *size, uint32_t *hi2, uint32_t *hi, uint32_t *lo);
int PyramiddemodFSK(uint8_t *dest, size_t *size);
int VikingDemod_AM(uint8_t *dest, size_t *size);
int PrescoDemod(uint8_t *dest, size_t *size);
#endif

View file

@ -109,20 +109,25 @@ NXP/Philips CUSTOM COMMANDS
#define ISO14443A_CMD_WUPA 0x52
#define ISO14443A_CMD_ANTICOLL_OR_SELECT 0x93
#define ISO14443A_CMD_ANTICOLL_OR_SELECT_2 0x95
#define ISO14443A_CMD_ANTICOLL_OR_SELECT_3 0x97
#define ISO14443A_CMD_WRITEBLOCK 0xA0 // or 0xA2 ?
#define ISO14443A_CMD_HALT 0x50
#define ISO14443A_CMD_RATS 0xE0
#define MIFARE_AUTH_KEYA 0x60
#define MIFARE_AUTH_KEYB 0x61
#define MIFARE_MAGICWUPC1 0x40
#define MIFARE_MAGICWUPC2 0x43
#define MIFARE_MAGICWIPEC 0x41
#define MIFARE_AUTH_KEYA 0x60
#define MIFARE_AUTH_KEYB 0x61
#define MIFARE_MAGICWUPC1 0x40
#define MIFARE_MAGICWUPC2 0x43
#define MIFARE_MAGICWIPEC 0x41
#define MIFARE_CMD_INC 0xC0
#define MIFARE_CMD_DEC 0xC1
#define MIFARE_CMD_RESTORE 0xC2
#define MIFARE_CMD_TRANSFER 0xB0
#define MIFARE_EV1_PERSONAL_UID 0x40
#define MIFARE_EV1_SETMODE 0x43
#define MIFARE_ULC_WRITE 0xA2
//#define MIFARE_ULC__COMP_WRITE 0xA0
#define MIFARE_ULC_AUTH_1 0x1A

View file

@ -24,6 +24,10 @@ typedef unsigned char byte_t;
#ifndef MAX
# define MAX(a, b) (((a) > (b)) ? (a) : (b))
#endif
#ifndef ABS
# define ABS(a) ( ((a)<0) ? -(a) : (a) )
#endif
#define RAMFUNC __attribute((long_call, section(".ramfunc")))

View file

@ -212,10 +212,11 @@ typedef struct{
//Mifare simulation flags
#define FLAG_INTERACTIVE 0x01
#define FLAG_4B_UID_IN_DATA 0x02
#define FLAG_7B_UID_IN_DATA 0x04
#define FLAG_NR_AR_ATTACK 0x08
#define FLAG_INTERACTIVE 0x01
#define FLAG_4B_UID_IN_DATA 0x02
#define FLAG_7B_UID_IN_DATA 0x04
#define FLAG_10B_UID_IN_DATA 0x08
#define FLAG_NR_AR_ATTACK 0x10
//Iclass reader flags