This commit is contained in:
mwalker33
2019-07-25 21:00:41 +10:00
28 changed files with 2097 additions and 2251 deletions

View File

@@ -3,15 +3,16 @@ DEFAULT_STANDALONE=LF_SAMYRUN
HELP_EXAMPLE_STANDALONE=HF_COLIN
# (you can set explicitly STANDALONE= to disable standalone modes)
STANDALONE?=$(DEFAULT_STANDALONE)
STANDALONE_REQ_DEFS=
define KNOWN_STANDALONE_DEFINITIONS
+==========================================================+
| STANDALONE | DESCRIPTION |
+==========================================================+
| | No standalone mode |
| (empty) | No standalone mode |
+----------------------------------------------------------+
| LF_SAMYRUN (def)| HID26 read/clone/sim |
| | - Samy Kamkar |
| LF_SAMYRUN | HID26 read/clone/sim |
| (default) | - Samy Kamkar |
+----------------------------------------------------------+
| LF_ICERUN | standalone mode skeleton |
| | - iceman |
@@ -29,18 +30,26 @@ define KNOWN_STANDALONE_DEFINITIONS
| | - Matías A. Ré Medina |
+----------------------------------------------------------+
| HF_COLIN | Mifare ultra fast sniff/sim/clone |
| | - Colin Brigato |
| (RDV4 only) | - Colin Brigato |
+----------------------------------------------------------+
| HF_BOG | 14a sniff with ULC/ULEV1/NTAG auth |
| | storing in flashmem - Bogito |
| (RDV4 only) | storing in flashmem - Bogito |
+----------------------------------------------------------+
endef
STANDALONE_MODES := LF_SAMYRUN LF_ICERUN LF_PROXBRUTE LF_HIDBRUTE
STANDALONE_MODES += HF_YOUNG HF_MATTYRUN HF_COLIN HF_BOG
STANDALONE_MODES_REQ_SMARTCARD :=
STANDALONE_MODES_REQ_FLASH := HF_COLIN HF_BOG
ifneq ($(filter $(STANDALONE),$(STANDALONE_MODES)),)
STANDALONE_PLATFORM_DEFS += -DWITH_STANDALONE_$(STANDALONE)
ifneq ($(filter $(STANDALONE),$(STANDALONE_MODES_REQ_SMARTCARD)),)
STANDALONE_REQ_DEFS += -DWITH_SMARTCARD
endif
ifneq ($(filter $(STANDALONE),$(STANDALONE_MODES_REQ_FLASH)),)
STANDALONE_REQ_DEFS += -DWITH_FLASH
endif
else ifneq ($(STANDALONE),)
$(error Invalid STANDALONE: $(STANDALONE). $(KNOWN_DEFINITIONS))
endif

View File

@@ -27,35 +27,7 @@ from the client to view the stored quadlets.
// Maximum number of auth attempts per standalone session
#define MAX_PWDS_PER_SESSION 64
uint8_t FindOffsetInFlash() {
uint8_t mem[4] = { 0x00, 0x00, 0x00, 0x00 };
uint8_t eom[4] = { 0xFF, 0xFF, 0xFF, 0xFF };
uint8_t memcnt = 0;
while (memcnt < 0xFF) {
Flash_ReadData(memcnt, mem, 4);
if (memcmp(mem, eom, 4) == 0) {
return memcnt;
}
memcnt += 4;
}
return 0; // wrap-around
}
void EraseMemory() {
if (!FlashInit()) {
return;
}
Flash_CheckBusy(BUSY_TIMEOUT);
Flash_WriteEnable();
Flash_Erase4k(0, 0);
if (DBGLEVEL > 1) Dbprintf("[!] Erased flash!");
FlashStop();
SpinDelay(100);
}
#define HF_BOG_LOGFILE "hf_bog.log"
// This is actually copied from SniffIso14443a
void RAMFUNC SniffAndStore(uint8_t param) {
@@ -96,8 +68,9 @@ void RAMFUNC SniffAndStore(uint8_t param) {
UartInit(receivedCmd, receivedCmdPar);
// Setup and start DMA.
if (!FpgaSetupSscDma((uint8_t *) dmaBuf, DMA_BUFFER_SIZE)) {
if (DBGLEVEL > 1) Dbprintf("FpgaSetupSscDma failed. Exiting");
if (!FpgaSetupSscDma((uint8_t *)dmaBuf, DMA_BUFFER_SIZE)) {
if (DBGLEVEL > 1)
Dbprintf("FpgaSetupSscDma failed. Exiting");
return;
}
@@ -134,17 +107,18 @@ void RAMFUNC SniffAndStore(uint8_t param) {
Dbprintf("[!] blew circular buffer! | datalen %u", dataLen);
break;
}
if (dataLen < 1) continue;
if (dataLen < 1)
continue;
// primary buffer was stopped( <-- we lost data!
if (!AT91C_BASE_PDC_SSC->PDC_RCR) {
AT91C_BASE_PDC_SSC->PDC_RPR = (uint32_t) dmaBuf;
AT91C_BASE_PDC_SSC->PDC_RPR = (uint32_t)dmaBuf;
AT91C_BASE_PDC_SSC->PDC_RCR = DMA_BUFFER_SIZE;
//Dbprintf("[-] RxEmpty ERROR | data length %d", dataLen); // temporary
// Dbprintf("[-] RxEmpty ERROR | data length %d", dataLen); // temporary
}
// secondary buffer sets as primary, secondary buffer was stopped
if (!AT91C_BASE_PDC_SSC->PDC_RNCR) {
AT91C_BASE_PDC_SSC->PDC_RNPR = (uint32_t) dmaBuf;
AT91C_BASE_PDC_SSC->PDC_RNPR = (uint32_t)dmaBuf;
AT91C_BASE_PDC_SSC->PDC_RNCR = DMA_BUFFER_SIZE;
}
@@ -159,23 +133,24 @@ void RAMFUNC SniffAndStore(uint8_t param) {
LED_C_ON();
// check - if there is a short 7bit request from reader
if ((!triggered) && (param & 0x02) && (uart->len == 1) && (uart->bitCount == 7)) triggered = true;
if ((!triggered) && (param & 0x02) && (uart->len == 1) && (uart->bitCount == 7))
triggered = true;
if (triggered) {
if ((receivedCmd) && ((receivedCmd[0] == MIFARE_ULEV1_AUTH) || (receivedCmd[0] == MIFARE_ULC_AUTH_1))) {
if (DBGLEVEL > 1) Dbprintf("PWD-AUTH KEY: 0x%02x%02x%02x%02x", receivedCmd[1], receivedCmd[2], receivedCmd[3], receivedCmd[4]);
if ((receivedCmd) &&
((receivedCmd[0] == MIFARE_ULEV1_AUTH) || (receivedCmd[0] == MIFARE_ULC_AUTH_1))) {
if (DBGLEVEL > 1)
Dbprintf("PWD-AUTH KEY: 0x%02x%02x%02x%02x", receivedCmd[1], receivedCmd[2],
receivedCmd[3], receivedCmd[4]);
// temporarily save the captured pwd in our array
memcpy(&capturedPwds[4 * auth_attempts], receivedCmd + 1, 4);
auth_attempts++;
}
if (!LogTrace(receivedCmd,
uart->len,
uart->startTime * 16 - DELAY_READER_AIR2ARM_AS_SNIFFER,
uart->endTime * 16 - DELAY_READER_AIR2ARM_AS_SNIFFER,
uart->parity,
true)) break;
if (!LogTrace(receivedCmd, uart->len, uart->startTime * 16 - DELAY_READER_AIR2ARM_AS_SNIFFER,
uart->endTime * 16 - DELAY_READER_AIR2ARM_AS_SNIFFER, uart->parity, true))
break;
}
/* ready to receive another command. */
UartReset();
@@ -193,20 +168,18 @@ void RAMFUNC SniffAndStore(uint8_t param) {
if (ManchesterDecoding(tagdata, 0, (my_rsamples - 1) * 4)) {
LED_B_ON();
if (!LogTrace(receivedResp,
demod->len,
demod->startTime * 16 - DELAY_TAG_AIR2ARM_AS_SNIFFER,
demod->endTime * 16 - DELAY_TAG_AIR2ARM_AS_SNIFFER,
demod->parity,
false)) break;
if (!LogTrace(receivedResp, demod->len, demod->startTime * 16 - DELAY_TAG_AIR2ARM_AS_SNIFFER,
demod->endTime * 16 - DELAY_TAG_AIR2ARM_AS_SNIFFER, demod->parity, false))
break;
if ((!triggered) && (param & 0x01)) triggered = true;
if ((!triggered) && (param & 0x01))
triggered = true;
// ready to receive another response.
DemodReset();
// reset the Miller decoder including its (now outdated) input buffer
UartReset();
//UartInit(receivedCmd, receivedCmdPar);
// UartInit(receivedCmd, receivedCmdPar);
LED_C_OFF();
}
TagIsActive = (demod->state != DEMOD_UNSYNCD);
@@ -228,57 +201,25 @@ void RAMFUNC SniffAndStore(uint8_t param) {
SpinDelay(200);
// Write stuff to flash
// Write stuff to spiffs logfile
if (auth_attempts > 0) {
if (DBGLEVEL > 1) Dbprintf("[!] Authentication attempts = %u", auth_attempts);
if (DBGLEVEL > 1)
Dbprintf("[!] Authentication attempts = %u", auth_attempts);
size_t size = 4 * auth_attempts;
uint8_t *data = BigBuf_malloc(size);
// Setting the SPI Baudrate to 48MHz to avoid the bit-flip issue (https://github.com/RfidResearchGroup/proxmark3/issues/34)
FlashmemSetSpiBaudrate(48000000);
// Find the offset in flash mem to continue writing the auth attempts
uint8_t memoffset = FindOffsetInFlash();
if (DBGLEVEL > 1) Dbprintf("[!] Memory offset = %u", memoffset);
if ((memoffset + 4 * auth_attempts) > 0xFF) {
// We opt to keep the new data only
memoffset = 0;
if (DBGLEVEL > 1) Dbprintf("[!] Size of total data > 256 bytes. Discarding the old data.");
if (!exists_in_spiffs((char *)HF_BOG_LOGFILE)) {
rdv40_spiffs_write((char *)HF_BOG_LOGFILE, (uint8_t *)data, size, RDV40_SPIFFS_SAFETY_SAFE);
} else {
rdv40_spiffs_append((char *)HF_BOG_LOGFILE, (uint8_t *)data, size, RDV40_SPIFFS_SAFETY_SAFE);
}
// Get previous data from flash mem
uint8_t *previousdata = BigBuf_malloc(memoffset);
if (memoffset > 0) {
uint16_t readlen = Flash_ReadData(0, previousdata, memoffset);
if (DBGLEVEL > 1) Dbprintf("[!] Read %u bytes from flash mem", readlen);
}
// create new bigbuf to hold all data
size_t total_size = memoffset + 4 * auth_attempts;
uint8_t *total_data = BigBuf_malloc(total_size);
// Add the previousdata array into total_data array
memcpy(total_data, previousdata, memoffset);
// Copy bytes of capturedPwds immediately following bytes of previousdata
memcpy(total_data + memoffset, capturedPwds, 4 * auth_attempts);
// Erase first page of flash mem
EraseMemory();
// Write total data to flash mem
uint16_t writelen = Flash_WriteData(0, total_data, memoffset + 4 * auth_attempts);
if (DBGLEVEL > 1) Dbprintf("[!] Wrote %u bytes into flash mem", writelen);
// If pwd saved successfully, blink led A three times
if (writelen > 0) {
SpinErr(0, 200, 5); // blink led A
}
SpinDelay(100);
// Reset the SPI Baudrate to the default value (24MHz)
FlashmemSetSpiBaudrate(24000000);
}
if (DBGLEVEL > 1)
Dbprintf("[!] Wrote %u Authentification attempts into logfile", auth_attempts);
SpinErr(0, 200, 5); // blink led A
SpinDelay(100);
}
void ModInfo(void) {

View File

@@ -21,6 +21,7 @@
#include "apps.h"
#include "printf.h"
#include "parity.h"
#include "spiffs.h"
#endif /* __HF_BOG_H */

View File

@@ -27,39 +27,78 @@ int curlline;
// Colin's VIGIKPWN sniff/simulate/clone repeat routine for HF Mifare
/*
void cjPrintBigArray(const char *bigar, int len, uint8_t newlines, uint8_t debug)
{
uint32_t chunksize = (PM3_CMD_DATA_SIZE / 4);
uint8_t totalchunks = len / chunksize;
uint8_t last_chunksize = len - (totalchunks * chunksize);
char chunk[chunksize + 1];
memset(chunk, 0x00, sizeof(chunk));
if (debug > 0)
{
Dbprintf("len : %d", len);
Dbprintf("chunksize : %d bytes", chunksize);
Dbprintf("totalchunks : %d", totalchunks);
Dbprintf("last_chunksize: %d", last_chunksize);
typedef struct MFC1KSchema {
uint8_t name[32];
uint64_t trigger;
uint64_t keysA[16];
uint64_t keysB[16];
} MFC1KSchema;
#define MAX_SCHEMAS 4
MFC1KSchema Schemas[MAX_SCHEMAS];
MFC1KSchema Noralsy = {
.name = "Noralsy",
.trigger = 0x414c41524f4e,
.keysA = {
0x414c41524f4e, 0x414c41524f4e, 0x414c41524f4e, 0x414c41524f4e, 0x414c41524f4e, 0x414c41524f4e,
0x414c41524f4e, 0x414c41524f4e, 0x414c41524f4e, 0x414c41524f4e, 0x414c41524f4e, 0x414c41524f4e,
0x414c41524f4e, 0x414c41524f4e, 0x414c41524f4e, 0x414c41524f4e
},
.keysB = {
0x424c41524f4e, 0x424c41524f4e, 0x424c41524f4e, 0x424c41524f4e, 0x424c41524f4e, 0x424c41524f4e,
0x424c41524f4e, 0x424c41524f4e, 0x424c41524f4e, 0x424c41524f4e, 0x424c41524f4e, 0x424c41524f4e,
0x424c41524f4e, 0x424c41524f4e, 0x424c41524f4e, 0x424c41524f4e
}
for (uint8_t i = 0; i < totalchunks; i++)
{
memset(chunk, 0x00, sizeof(chunk));
memcpy(chunk, &bigar[i * chunksize], chunksize);
DbprintfEx(FLAG_RAWPRINT, "%s", chunk);
};
MFC1KSchema InfiHexact = {.name = "Infineon/Hexact",
.trigger = 0x484558414354,
.keysA = {0x484558414354, 0x484558414354, 0x484558414354, 0x484558414354, 0x484558414354,
0x484558414354, 0x484558414354, 0x484558414354, 0x484558414354, 0x484558414354,
0x484558414354, 0x484558414354, 0x484558414354, 0x484558414354, 0x484558414354,
0x484558414354
},
.keysB = {0xa22ae129c013, 0x49fae4e3849f, 0x38fcf33072e0, 0x8ad5517b4b18, 0x509359f131b1,
0x6c78928e1317, 0xaa0720018738, 0xa6cac2886412, 0x62d0c424ed8e, 0xe64a986a5d94,
0x8fa1d601d0a2, 0x89347350bd36, 0x66d2b7dc39ef, 0x6bc1e1ae547d, 0x22729a9bd40f
}
};
MFC1KSchema UrmetCaptive = {
.name = "Urmet Captive",
.trigger = 0x8829da9daf76,
.keysA = {
0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76,
0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76,
0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76
},
.keysB = {
0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76,
0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76,
0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76, 0x8829da9daf76
}
if (last_chunksize > 0)
{
memset(chunk, 0x00, sizeof(chunk));
memcpy(chunk, &bigar[totalchunks * chunksize], last_chunksize);
DbprintfEx(FLAG_RAWPRINT, "%s", chunk);
}
if (newlines > 0)
{
DbprintfEx(FLAG_NEWLINE, " ");
};
int total_schemas = 0;
void add_schema(MFC1KSchema *p, MFC1KSchema a, int *schemas_counter) {
if (*schemas_counter < MAX_SCHEMAS) {
p[*schemas_counter] = a;
*schemas_counter += 1;
}
}
void delete_schema(MFC1KSchema *p, int *schemas_counter, int index) {
if (*schemas_counter > 0 && index < *schemas_counter && index > -1) {
int last_index = *schemas_counter - 1;
for (int i = index; i < last_index; i++) {
p[i] = p[i + 1];
}
*schemas_counter -= 1;
}
}
*/
void cjSetCursFRight() {
vtsend_cursor_position(NULL, 98, (currfline));
@@ -81,9 +120,8 @@ void cjTabulize() { DbprintfEx(FLAG_RAWPRINT, "\t\t\t"); }
/*
void cjPrintKey(uint64_t key, uint8_t *foundKey, uint16_t sectorNo, uint8_t type) {
char tosendkey[13];
sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", foundKey[0], foundKey[1], foundKey[2], foundKey[3], foundKey[4], foundKey[5]);
cjSetCursRight();
DbprintfEx(FLAG_NEWLINE, "SEC: %02x | KEY : %s | TYP: %d", sectorNo, tosendkey, type);
sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", foundKey[0], foundKey[1], foundKey[2], foundKey[3], foundKey[4],
foundKey[5]); cjSetCursRight(); DbprintfEx(FLAG_NEWLINE, "SEC: %02x | KEY : %s | TYP: %d", sectorNo, tosendkey, type);
}
*/
@@ -101,7 +139,7 @@ void ReadLastTagFromFlash() {
uint8_t *mem = BigBuf_malloc(size);
//this one will handle filetype (symlink or not) and resolving by itself
// this one will handle filetype (symlink or not) and resolving by itself
rdv40_spiffs_read_as_filetype((char *)HFCOLIN_LASTTAG_SYMLINK, (uint8_t *)mem, len, RDV40_SPIFFS_SAFETY_SAFE);
emlSetMem(mem, 0, 64);
@@ -129,8 +167,9 @@ void WriteTagToFlash(uint32_t uid, size_t size) {
num_to_bytes(uid, 4, buid);
sprintf(dest, "hf_colin/mf_%02x%02x%02x%02x.bin", buid[0], buid[1], buid[2], buid[3]);
// TODO : by using safe function for multiple writes we are both breaking cache mecanisms and making useless and unoptimized mount operations
// we should manage at out level the mount status before and after the whole standalone mode
// TODO : by using safe function for multiple writes we are both breaking cache mecanisms and making useless and
// unoptimized mount operations we should manage at out level the mount status before and after the whole standalone
// mode
rdv40_spiffs_write((char *)dest, (uint8_t *)data, len, RDV40_SPIFFS_SAFETY_SAFE);
// lastag will only contain filename/path to last written tag file so we don't loose time or space.
rdv40_spiffs_make_symlink((char *)dest, (char *)HFCOLIN_LASTTAG_SYMLINK, RDV40_SPIFFS_SAFETY_SAFE);
@@ -141,12 +180,15 @@ void WriteTagToFlash(uint32_t uid, size_t size) {
return;
}
void ModInfo(void) {
DbpString(" HF Mifare ultra fast sniff/sim/clone - aka VIGIKPWN (Colin Brigato)");
}
void ModInfo(void) { DbpString(" HF Mifare ultra fast sniff/sim/clone - aka VIGIKPWN (Colin Brigato)"); }
void RunMod() {
StandAloneMode();
add_schema(Schemas, Noralsy, &total_schemas);
add_schema(Schemas, InfiHexact, &total_schemas);
add_schema(Schemas, UrmetCaptive, &total_schemas);
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
currline = 20;
@@ -155,7 +197,7 @@ void RunMod() {
memset(cjuid, 0, sizeof(cjuid));
cjcuid = 0;
uint8_t sectorsCnt = (MF1KSZ / MF1KSZSIZE);
uint64_t key64; // Defines current key
uint64_t key64; // Defines current key
uint8_t *keyBlock; // Where the keys will be held in memory.
/* VIGIK EXPIRED DUMP FOR STUDY
@@ -194,11 +236,11 @@ void RunMod() {
ACCBITS : 796788[00]+VALUE
*/
//----------------------------
// Set of keys to be used.
// This should cover ~98% of
// French VIGIK system @2017
//----------------------------
//----------------------------
// Set of keys to be used.
// This should cover ~98% of
// French VIGIK system @2017
//----------------------------
#define STKEYS 37
@@ -295,7 +337,7 @@ failtag:
SpinOff(50);
LED_A_ON();
uint8_t ticker = 0;
//while (!BUTTON_PRESS() && !iso14443a_select_card(cjuid, NULL, &cjcuid, true, 0, true))
// while (!BUTTON_PRESS() && !iso14443a_select_card(cjuid, NULL, &cjcuid, true, 0, true))
while (!iso14443a_select_card(cjuid, &p_card, &cjcuid, true, 0, true)) {
WDT_HIT();
@@ -377,8 +419,8 @@ failtag:
if (key == -1) {
err = 1;
allKeysFound = false;
// used in portable imlementation on microcontroller: it reports back the fail and open the standalone lock
// reply_old(CMD_CJB_FSMSTATE_MENU, 0, 0, 0, 0, 0);
// used in portable imlementation on microcontroller: it reports back the fail and open the standalone
// lock reply_old(CMD_CJB_FSMSTATE_MENU, 0, 0, 0, 0, 0);
break;
} else if (key == -2) {
err = 1; // Can't select card.
@@ -393,10 +435,10 @@ failtag:
cjSetCursRight();
DbprintfEx(FLAG_NEWLINE, "SEC: %02x ; KEY : %012" PRIx64 " ; TYP: %i", sec, key64, type);
/*reply_old(CMD_CJB_INFORM_CLIENT_KEY, 12, sec, type, tosendkey, 12);*/
switch (key64) {
/////////////////////////////////////////////////////////
// COMMON SCHEME 1 : INFINITRON/HEXACT
case 0x484558414354:
for (int i = 0; i < total_schemas; i++) {
if (key64 == Schemas[i].trigger) {
cjSetCursLeft();
DbprintfEx(FLAG_NEWLINE, "%s>>>>>>>>>>>>!*STOP*!<<<<<<<<<<<<<<%s", _XRED_, _XWHITE_);
cjSetCursLeft();
@@ -404,232 +446,36 @@ failtag:
DbprintfEx(FLAG_NEWLINE, " .TAG SEEMS %sDETERMINISTIC%s. ", _XGREEN_, _XWHITE_);
cjSetCursLeft();
DbprintfEx(FLAG_NEWLINE, "%sDetected: %s INFI_HEXACT_VIGIK_TAG%s", _XORANGE_, _XCYAN_, _XWHITE_);
DbprintfEx(FLAG_NEWLINE, "%sDetected: %s %s%s", _XORANGE_, _XCYAN_, Schemas[i].name, _XWHITE_);
cjSetCursLeft();
DbprintfEx(FLAG_NEWLINE, "...%s[%sKey_derivation_schemeTest%s]%s...", _XYELLOW_, _XGREEN_, _XYELLOW_, _XGREEN_);
DbprintfEx(FLAG_NEWLINE, "...%s[%sKey_derivation_schemeTest%s]%s...", _XYELLOW_, _XGREEN_,
_XYELLOW_, _XGREEN_);
cjSetCursLeft();
DbprintfEx(FLAG_NEWLINE, "%s>>>>>>>>>>>>!*DONE*!<<<<<<<<<<<<<<%s", _XGREEN_, _XWHITE_);
;
// Type 0 / A first
uint16_t t = 0;
for (uint16_t s = 0; s < sectorsCnt; s++) {
num_to_bytes(0x484558414354, 6, foundKey[t][s]);
sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", foundKey[t][s][0], foundKey[t][s][1], foundKey[t][s][2],
foundKey[t][s][3], foundKey[t][s][4], foundKey[t][s][5]);
num_to_bytes(Schemas[i].keysA[s], 6, foundKey[t][s]);
sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", foundKey[t][s][0], foundKey[t][s][1],
foundKey[t][s][2], foundKey[t][s][3], foundKey[t][s][4], foundKey[t][s][5]);
cjSetCursRight();
DbprintfEx(FLAG_NEWLINE, "SEC: %02x ; KEY : %s ; TYP: %d", s, tosendkey, t);
}
t = 1;
uint16_t sectorNo = 0;
num_to_bytes(0xa22ae129c013, 6, foundKey[t][sectorNo]);
sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", foundKey[t][sectorNo][0], foundKey[t][sectorNo][1], foundKey[t][sectorNo][2],
foundKey[t][sectorNo][3], foundKey[t][sectorNo][4], foundKey[t][sectorNo][5]);
cjSetCursRight();
DbprintfEx(FLAG_NEWLINE, "SEC: %02x ; KEY : %s ; TYP: %d", sectorNo, tosendkey, t);
sectorNo = 1;
num_to_bytes(0x49fae4e3849f, 6, foundKey[t][sectorNo]);
sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", foundKey[t][sectorNo][0], foundKey[t][sectorNo][1], foundKey[t][sectorNo][2],
foundKey[t][sectorNo][3], foundKey[t][sectorNo][4], foundKey[t][sectorNo][5]);
cjSetCursRight();
DbprintfEx(FLAG_NEWLINE, "SEC: %02x ; KEY : %s ; TYP: %d", sectorNo, tosendkey, t);
sectorNo = 2;
num_to_bytes(0x38fcf33072e0, 6, foundKey[t][sectorNo]);
sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", foundKey[t][sectorNo][0], foundKey[t][sectorNo][1], foundKey[t][sectorNo][2],
foundKey[t][sectorNo][3], foundKey[t][sectorNo][4], foundKey[t][sectorNo][5]);
cjSetCursRight();
DbprintfEx(FLAG_NEWLINE, "SEC: %02x ; KEY : %s ; TYP: %d", sectorNo, tosendkey, t);
sectorNo = 3;
num_to_bytes(0x8ad5517b4b18, 6, foundKey[t][sectorNo]);
sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", foundKey[t][sectorNo][0], foundKey[t][sectorNo][1], foundKey[t][sectorNo][2],
foundKey[t][sectorNo][3], foundKey[t][sectorNo][4], foundKey[t][sectorNo][5]);
cjSetCursRight();
DbprintfEx(FLAG_NEWLINE, "SEC: %02x ; KEY : %s ; TYP: %d", sectorNo, tosendkey, t);
sectorNo = 4;
num_to_bytes(0x509359f131b1, 6, foundKey[t][sectorNo]);
sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", foundKey[t][sectorNo][0], foundKey[t][sectorNo][1], foundKey[t][sectorNo][2],
foundKey[t][sectorNo][3], foundKey[t][sectorNo][4], foundKey[t][sectorNo][5]);
cjSetCursRight();
DbprintfEx(FLAG_NEWLINE, "SEC: %02x ; KEY : %s ; TYP: %d", sectorNo, tosendkey, t);
sectorNo = 5;
num_to_bytes(0x6c78928e1317, 6, foundKey[t][sectorNo]);
sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", foundKey[t][sectorNo][0], foundKey[t][sectorNo][1], foundKey[t][sectorNo][2],
foundKey[t][sectorNo][3], foundKey[t][sectorNo][4], foundKey[t][sectorNo][5]);
cjSetCursRight();
DbprintfEx(FLAG_NEWLINE, "SEC: %02x ; KEY : %s ; TYP: %d", sectorNo, tosendkey, t);
sectorNo = 6;
num_to_bytes(0xaa0720018738, 6, foundKey[t][sectorNo]);
sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", foundKey[t][sectorNo][0], foundKey[t][sectorNo][1], foundKey[t][sectorNo][2],
foundKey[t][sectorNo][3], foundKey[t][sectorNo][4], foundKey[t][sectorNo][5]);
cjSetCursRight();
DbprintfEx(FLAG_NEWLINE, "SEC: %02x ; KEY : %s ; TYP: %d", sectorNo, tosendkey, t);
sectorNo = 7;
num_to_bytes(0xa6cac2886412, 6, foundKey[t][sectorNo]);
sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", foundKey[t][sectorNo][0], foundKey[t][sectorNo][1], foundKey[t][sectorNo][2],
foundKey[t][sectorNo][3], foundKey[t][sectorNo][4], foundKey[t][sectorNo][5]);
cjSetCursRight();
DbprintfEx(FLAG_NEWLINE, "SEC: %02x ; KEY : %s ; TYP: %d", sectorNo, tosendkey, t);
sectorNo = 8;
num_to_bytes(0x62d0c424ed8e, 6, foundKey[t][sectorNo]);
sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", foundKey[t][sectorNo][0], foundKey[t][sectorNo][1], foundKey[t][sectorNo][2],
foundKey[t][sectorNo][3], foundKey[t][sectorNo][4], foundKey[t][sectorNo][5]);
cjSetCursRight();
DbprintfEx(FLAG_NEWLINE, "SEC: %02x ; KEY : %s ; TYP: %d", sectorNo, tosendkey, t);
sectorNo = 9;
num_to_bytes(0xe64a986a5d94, 6, foundKey[t][sectorNo]);
sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", foundKey[t][sectorNo][0], foundKey[t][sectorNo][1], foundKey[t][sectorNo][2],
foundKey[t][sectorNo][3], foundKey[t][sectorNo][4], foundKey[t][sectorNo][5]);
cjSetCursRight();
DbprintfEx(FLAG_NEWLINE, "SEC: %02x ; KEY : %s ; TYP: %d", sectorNo, tosendkey, t);
sectorNo = 10;
num_to_bytes(0x8fa1d601d0a2, 6, foundKey[t][sectorNo]);
sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", foundKey[t][sectorNo][0], foundKey[t][sectorNo][1], foundKey[t][sectorNo][2],
foundKey[t][sectorNo][3], foundKey[t][sectorNo][4], foundKey[t][sectorNo][5]);
cjSetCursRight();
DbprintfEx(FLAG_NEWLINE, "SEC: %02x ; KEY : %s ; TYP: %d", sectorNo, tosendkey, t);
sectorNo = 11;
num_to_bytes(0x89347350bd36, 6, foundKey[t][sectorNo]);
sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", foundKey[t][sectorNo][0], foundKey[t][sectorNo][1], foundKey[t][sectorNo][2],
foundKey[t][sectorNo][3], foundKey[t][sectorNo][4], foundKey[t][sectorNo][5]);
cjSetCursRight();
DbprintfEx(FLAG_NEWLINE, "SEC: %02x ; KEY : %s ; TYP: %d", sectorNo, tosendkey, t);
sectorNo = 12;
num_to_bytes(0x66d2b7dc39ef, 6, foundKey[t][sectorNo]);
sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", foundKey[t][sectorNo][0], foundKey[t][sectorNo][1], foundKey[t][sectorNo][2],
foundKey[t][sectorNo][3], foundKey[t][sectorNo][4], foundKey[t][sectorNo][5]);
cjSetCursRight();
DbprintfEx(FLAG_NEWLINE, "SEC: %02x ; KEY : %s ; TYP: %d", sectorNo, tosendkey, t);
sectorNo = 13;
num_to_bytes(0x6bc1e1ae547d, 6, foundKey[t][sectorNo]);
sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", foundKey[t][sectorNo][0], foundKey[t][sectorNo][1], foundKey[t][sectorNo][2],
foundKey[t][sectorNo][3], foundKey[t][sectorNo][4], foundKey[t][sectorNo][5]);
cjSetCursRight();
DbprintfEx(FLAG_NEWLINE, "SEC: %02x ; KEY : %s ; TYP: %d", sectorNo, tosendkey, t);
sectorNo = 14;
num_to_bytes(0x22729a9bd40f, 6, foundKey[t][sectorNo]);
sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", foundKey[t][sectorNo][0], foundKey[t][sectorNo][1], foundKey[t][sectorNo][2],
foundKey[t][sectorNo][3], foundKey[t][sectorNo][4], foundKey[t][sectorNo][5]);
cjSetCursRight();
DbprintfEx(FLAG_NEWLINE, "SEC: %02x ; KEY : %s ; TYP: %d", sectorNo, tosendkey, t);
sectorNo = 15;
num_to_bytes(0x484558414354, 6, foundKey[t][sectorNo]);
sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", foundKey[t][sectorNo][0], foundKey[t][sectorNo][1], foundKey[t][sectorNo][2],
foundKey[t][sectorNo][3], foundKey[t][sectorNo][4], foundKey[t][sectorNo][5]);
cjSetCursRight();
DbprintfEx(FLAG_NEWLINE, "SEC: %02x ; KEY : %s ; TYP: %d", sectorNo, tosendkey, t);
trapped = 1;
break;
////////////////END OF SCHEME 1//////////////////////////////
///////////////////////////////////////
// COMMON SCHEME 2 : URMET CAPTIVE / COGELEC!/?
case 0x8829da9daf76:
cjSetCursLeft();
DbprintfEx(FLAG_NEWLINE, "%s>>>>>>>>>>>>!*STOP*!<<<<<<<<<<<<<<%s", _XRED_, _XWHITE_);
cjSetCursLeft();
DbprintfEx(FLAG_NEWLINE, " .TAG SEEMS %sDETERMINISTIC%s. ", _XGREEN_, _XWHITE_);
cjSetCursLeft();
DbprintfEx(FLAG_NEWLINE, "%sDetected :%sURMET_CAPTIVE_VIGIK_TAG%s", _XORANGE_, _XCYAN_, _XWHITE_);
cjSetCursLeft();
DbprintfEx(FLAG_NEWLINE, "...%s[%sKey_derivation_schemeTest%s]%s...", _XYELLOW_, _XGREEN_, _XYELLOW_, _XGREEN_);
cjSetCursLeft();
DbprintfEx(FLAG_NEWLINE, "%s>>>>>>>>>>>>!*DONE*!<<<<<<<<<<<<<<%s", _XGREEN_, _XWHITE_);
cjSetCursLeft();
// emlClearMem();
// A very weak one...
for (uint16_t i = 0; i < 2; i++) {
for (uint16_t s = 0; s < sectorsCnt; s++) {
num_to_bytes(key64, 6, foundKey[i][s]);
sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x",
foundKey[i][s][0],
foundKey[i][s][1],
foundKey[i][s][2],
foundKey[i][s][3],
foundKey[i][s][4],
foundKey[i][s][5]
);
cjSetCursRight();
DbprintfEx(FLAG_NEWLINE, "SEC: %02x ; KEY : %s ; TYP: %d", s, tosendkey, i);
}
}
trapped = 1;
break;
////////////////END OF SCHEME 2//////////////////////////////
///////////////////////////////////////
// COMMON SCHEME 3 : NORALSY "A-LARON & B-LARON . . . NORAL-B & NORAL-A"
case 0x414c41524f4e: // Thumbs up to the guy who had the idea of such a "mnemotechnical" key pair
case 0x424c41524f4e:
cjSetCursLeft();
DbprintfEx(FLAG_NEWLINE, "%s>>>>>>>>>>>>!*STOP*!<<<<<<<<<<<<<<%s", _XRED_, _XWHITE_);
cjSetCursLeft();
DbprintfEx(FLAG_NEWLINE, " .TAG SEEMS %sDETERMINISTIC%s. ", _XGREEN_, _XWHITE_);
cjSetCursLeft();
DbprintfEx(FLAG_NEWLINE, "%s Detected :%sNORALSY_VIGIK_TAG %s", _XORANGE_, _XCYAN_, _XWHITE_);
cjSetCursLeft();
DbprintfEx(FLAG_NEWLINE, "...%s[%sKey_derivation_schemeTest%s]%s...", _XYELLOW_, _XGREEN_, _XYELLOW_, _XGREEN_);
cjSetCursLeft();
DbprintfEx(FLAG_NEWLINE, "%s>>>>>>>>>>>>!*DONE*!<<<<<<<<<<<<<<%s", _XGREEN_, _XWHITE_);
t = 0;
for (uint16_t s = 0; s < sectorsCnt; s++) {
num_to_bytes(0x414c41524f4e, 6, foundKey[t][s]);
sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x",
foundKey[t][s][0],
foundKey[t][s][1],
foundKey[t][s][2],
foundKey[t][s][3],
foundKey[t][s][4],
foundKey[t][s][5]);
cjSetCursRight();
DbprintfEx(FLAG_NEWLINE, "SEC: %02x ; KEY : %s ; TYP: %d", s, tosendkey, t);
}
t = 1;
for (uint16_t s = 0; s < sectorsCnt; s++) {
num_to_bytes(0x424c41524f4e, 6, foundKey[t][s]);
sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x",
foundKey[t][s][0],
foundKey[t][s][1],
foundKey[t][s][2],
foundKey[t][s][3],
foundKey[t][s][4],
foundKey[t][s][5]);
num_to_bytes(Schemas[i].keysB[s], 6, foundKey[t][s]);
sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", foundKey[t][s][0], foundKey[t][s][1],
foundKey[t][s][2], foundKey[t][s][3], foundKey[t][s][4], foundKey[t][s][5]);
cjSetCursRight();
DbprintfEx(FLAG_NEWLINE, "SEC: %02x ; KEY : %s ; TYP: %d", s, tosendkey, t);
}
trapped = 1;
break;
////////////////END OF SCHEME 3//////////////////////////////
}
}
/* etc etc for testing schemes quick schemes */
}
}
@@ -685,7 +531,8 @@ failtag:
delta_time = GetTickCountDelta(start_time);
cjSetCursLeft();
DbprintfEx(FLAG_NEWLINE, "%s>>%s Time for VIGIK break :%s%dms%s", _XGREEN_, _XWHITE_, _XYELLOW_, delta_time, _XWHITE_);
DbprintfEx(FLAG_NEWLINE, "%s>>%s Time for VIGIK break :%s%dms%s", _XGREEN_, _XWHITE_, _XYELLOW_, delta_time,
_XWHITE_);
vtsend_cursor_position_save(NULL);
vtsend_set_attribute(NULL, 1);
@@ -706,8 +553,9 @@ readysim:
DbprintfEx(FLAG_NEWLINE, "%s!> HOLD ON : %s When you'll click, simm will stop", _XRED_, _XWHITE_);
cjSetCursLeft();
DbprintfEx(FLAG_NEWLINE, "Then %s immediately %s we'll try to %s dump our emulator state%s \r\nin a %s chinese tag%s", _XRED_, _XWHITE_, _XYELLOW_, _XWHITE_,
_XCYAN_, _XWHITE_);
DbprintfEx(FLAG_NEWLINE,
"Then %s immediately %s we'll try to %s dump our emulator state%s \r\nin a %s chinese tag%s", _XRED_,
_XWHITE_, _XYELLOW_, _XWHITE_, _XCYAN_, _XWHITE_);
cjSetCursLeft();
cjSetCursLeft();
@@ -736,7 +584,7 @@ readysim:
}
// Use UID, SAK, ATQA from EMUL, if uid not defined
//if ((flags & (FLAG_4B_UID_IN_DATA | FLAG_7B_UID_IN_DATA | FLAG_10B_UID_IN_DATA)) == 0) {
// if ((flags & (FLAG_4B_UID_IN_DATA | FLAG_7B_UID_IN_DATA | FLAG_10B_UID_IN_DATA)) == 0) {
flags |= FLAG_UID_IN_EMUL;
//}
Mifare1ksim(flags | FLAG_MF_1K, 0, cjuid);
@@ -856,7 +704,8 @@ int e_MifareECardLoad(uint32_t numofsectors, uint8_t keytype) {
/* the chk function is a piwi'ed(tm) check that will try all keys for
a particular sector. also no tracing no dbg */
int cjat91_saMifareChkKeys(uint8_t blockNo, uint8_t keyType, bool clearTrace, uint8_t keyCount, uint8_t *datain, uint64_t *key) {
int cjat91_saMifareChkKeys(uint8_t blockNo, uint8_t keyType, bool clearTrace, uint8_t keyCount, uint8_t *datain,
uint64_t *key) {
DBGLEVEL = DBG_NONE;
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
set_tracing(false);
@@ -961,8 +810,7 @@ void saMifareMakeTag(void) {
}
}
//TODO : make this work either for a Gen1a or for a block 0 direct write all transparently
// TODO : make this work either for a Gen1a or for a block 0 direct write all transparently
//-----------------------------------------------------------------------------
// Matt's StandAlone mod.
// Work with "magic Chinese" card (email him: ouyangweidaxian@live.cn)
@@ -1049,7 +897,8 @@ int saMifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *data
};
}
if ((mifare_sendcmd_short(NULL, 0, 0xA0, blockNo, receivedAnswer, receivedAnswerPar, NULL) != 1) || (receivedAnswer[0] != 0x0a)) {
if ((mifare_sendcmd_short(NULL, 0, 0xA0, blockNo, receivedAnswer, receivedAnswerPar, NULL) != 1) ||
(receivedAnswer[0] != 0x0a)) {
DbprintfEx(FLAG_NEWLINE, "write block send command error");
break;
};

View File

@@ -72,6 +72,13 @@ STANDALONE_MODES := LF_SAMYRUN LF_ICERUN LF_PROXBRUTE LF_HIDBRUTE LF_FOO
STANDALONE_MODES += HF_YOUNG HF_MATTYRUN HF_COLIN HF_BOG
```
If your mode is using one of the unique features of the RDV4, add it to the proper list:
```
STANDALONE_MODES_REQ_SMARTCARD :=
STANDALONE_MODES_REQ_FLASH := HF_COLIN HF_BOG
```
## Update MAKEFILE.INC
Add your source code files like the following sample in the `Makefile.inc`

View File

@@ -104,7 +104,7 @@ typedef struct {
#endif
#ifndef CheckCrc14A
# define CheckCrc14A(data, len) check_crc(CRC_14443_A, (data), (len))
# define CheckCrc14A(data, len) check_crc(CRC_14443_A, (data), (len))
#endif
void GetParity(const uint8_t *pbtCmd, uint16_t len, uint8_t *par);

View File

@@ -11,57 +11,57 @@ INCLUDE ../common/ldscript.common
PHDRS
{
text PT_LOAD FLAGS(5);
data PT_LOAD;
bss PT_LOAD;
text PT_LOAD FLAGS(5);
data PT_LOAD;
bss PT_LOAD;
}
ENTRY(Vector)
SECTIONS
{
.start : {
*(.startos)
} >osimage :text
.start : {
*(.startos)
} >osimage :text
.text : {
KEEP(*(stage1_image))
*(.text)
*(.text.*)
*(.eh_frame)
*(.glue_7)
*(.glue_7t)
} >osimage :text
.text : {
KEEP(*(stage1_image))
*(.text)
*(.text.*)
*(.eh_frame)
*(.glue_7)
*(.glue_7t)
} >osimage :text
.rodata : {
*(.rodata)
*(.rodata.*)
*(fpga_all_bit.data)
KEEP(*(.version_information))
. = ALIGN(8);
} >osimage :text
.rodata : {
*(.rodata)
*(.rodata.*)
*(fpga_all_bit.data)
KEEP(*(.version_information))
. = ALIGN(8);
} >osimage :text
.data : {
KEEP(*(compressed_data))
*(.data)
*(.data.*)
*(.ramfunc)
. = ALIGN(4);
} >ram AT>osimage :data
.data : {
KEEP(*(compressed_data))
*(.data)
*(.data.*)
*(.ramfunc)
. = ALIGN(4);
} >ram AT>osimage :data
__data_src_start__ = LOADADDR(.data);
__data_start__ = ADDR(.data);
__data_end__ = __data_start__ + SIZEOF(.data);
__os_size__ = SIZEOF(.text) + SIZEOF(.data) + SIZEOF(.rodata);
.bss : {
__bss_start__ = .;
*(.bss)
*(.bss.*)
. = ALIGN(4);
__bss_end__ = .;
} >ram AT>ram :bss
__data_src_start__ = LOADADDR(.data);
__data_start__ = ADDR(.data);
__data_end__ = __data_start__ + SIZEOF(.data);
__os_size__ = SIZEOF(.text) + SIZEOF(.data) + SIZEOF(.rodata);
.bss : {
__bss_start__ = .;
*(.bss)
*(.bss.*)
. = ALIGN(4);
__bss_end__ = .;
} >ram AT>ram :bss
.commonarea (NOLOAD) : {
*(.commonarea)
} >commonarea :NONE
.commonarea (NOLOAD) : {
*(.commonarea)
} >commonarea :NONE
}

View File

@@ -42,30 +42,36 @@ static bool IsTrailerAccessAllowed(uint8_t blockNo, uint8_t keytype, uint8_t act
| ((sector_trailer[8] >> 7) & 0x01);
switch (action) {
case AC_KEYA_READ: {
if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("IsTrailerAccessAllowed: AC_KEYA_READ");
if (DBGLEVEL >= DBG_EXTENDED)
Dbprintf("IsTrailerAccessAllowed: AC_KEYA_READ");
return false;
}
case AC_KEYA_WRITE: {
if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("IsTrailerAccessAllowed: AC_KEYA_WRITE");
if (DBGLEVEL >= DBG_EXTENDED)
Dbprintf("IsTrailerAccessAllowed: AC_KEYA_WRITE");
return ((keytype == AUTHKEYA && (AC == 0x00 || AC == 0x01))
|| (keytype == AUTHKEYB && (AC == 0x04 || AC == 0x03)));
}
case AC_KEYB_READ: {
if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("IsTrailerAccessAllowed: AC_KEYB_READ");
if (DBGLEVEL >= DBG_EXTENDED)
Dbprintf("IsTrailerAccessAllowed: AC_KEYB_READ");
return (keytype == AUTHKEYA && (AC == 0x00 || AC == 0x02 || AC == 0x01));
}
case AC_KEYB_WRITE: {
if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("IsTrailerAccessAllowed: AC_KEYB_WRITE");
if (DBGLEVEL >= DBG_EXTENDED)
Dbprintf("IsTrailerAccessAllowed: AC_KEYB_WRITE");
return ((keytype == AUTHKEYA && (AC == 0x00 || AC == 0x01))
|| (keytype == AUTHKEYB && (AC == 0x04 || AC == 0x03)));
}
case AC_AC_READ: {
if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("IsTrailerAccessAllowed: AC_AC_READ");
if (DBGLEVEL >= DBG_EXTENDED)
Dbprintf("IsTrailerAccessAllowed: AC_AC_READ");
return ((keytype == AUTHKEYA)
|| (keytype == AUTHKEYB && !(AC == 0x00 || AC == 0x02 || AC == 0x01)));
}
case AC_AC_WRITE: {
if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("IsTrailerAccessAllowed: AC_AC_WRITE");
if (DBGLEVEL >= DBG_EXTENDED)
Dbprintf("IsTrailerAccessAllowed: AC_AC_WRITE");
return ((keytype == AUTHKEYA && (AC == 0x01))
|| (keytype == AUTHKEYB && (AC == 0x03 || AC == 0x05)));
}
@@ -93,46 +99,54 @@ static bool IsDataAccessAllowed(uint8_t blockNo, uint8_t keytype, uint8_t action
AC = ((sector_trailer[7] >> 2) & 0x04)
| ((sector_trailer[8] << 1) & 0x02)
| ((sector_trailer[8] >> 4) & 0x01);
if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("IsDataAccessAllowed: case 0x00 - %02x", AC);
if (DBGLEVEL >= DBG_EXTENDED)
Dbprintf("IsDataAccessAllowed: case 0x00 - %02x", AC);
break;
}
case 0x01: {
AC = ((sector_trailer[7] >> 3) & 0x04)
| ((sector_trailer[8] >> 0) & 0x02)
| ((sector_trailer[8] >> 5) & 0x01);
if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("IsDataAccessAllowed: case 0x01 - %02x", AC);
if (DBGLEVEL >= DBG_EXTENDED)
Dbprintf("IsDataAccessAllowed: case 0x01 - %02x", AC);
break;
}
case 0x02: {
AC = ((sector_trailer[7] >> 4) & 0x04)
| ((sector_trailer[8] >> 1) & 0x02)
| ((sector_trailer[8] >> 6) & 0x01);
if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("IsDataAccessAllowed: case 0x02 - %02x", AC);
if (DBGLEVEL >= DBG_EXTENDED)
Dbprintf("IsDataAccessAllowed: case 0x02 - %02x", AC);
break;
}
default:
if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("IsDataAccessAllowed: Error");
if (DBGLEVEL >= DBG_EXTENDED)
Dbprintf("IsDataAccessAllowed: Error");
return false;
}
switch (action) {
case AC_DATA_READ: {
if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("IsDataAccessAllowed - AC_DATA_READ: OK");
if (DBGLEVEL >= DBG_EXTENDED)
Dbprintf("IsDataAccessAllowed - AC_DATA_READ: OK");
return ((keytype == AUTHKEYA && !(AC == 0x03 || AC == 0x05 || AC == 0x07))
|| (keytype == AUTHKEYB && !(AC == 0x07)));
}
case AC_DATA_WRITE: {
if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("IsDataAccessAllowed - AC_DATA_WRITE: OK");
if (DBGLEVEL >= DBG_EXTENDED)
Dbprintf("IsDataAccessAllowed - AC_DATA_WRITE: OK");
return ((keytype == AUTHKEYA && (AC == 0x00))
|| (keytype == AUTHKEYB && (AC == 0x00 || AC == 0x04 || AC == 0x06 || AC == 0x03)));
}
case AC_DATA_INC: {
if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("IsDataAccessAllowed - AC_DATA_INC: OK");
if (DBGLEVEL >= DBG_EXTENDED)
Dbprintf("IsDataAccessAllowed - AC_DATA_INC: OK");
return ((keytype == AUTHKEYA && (AC == 0x00))
|| (keytype == AUTHKEYB && (AC == 0x00 || AC == 0x06)));
}
case AC_DATA_DEC_TRANS_REST: {
if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("AC_DATA_DEC_TRANS_REST: OK");
if (DBGLEVEL >= DBG_EXTENDED)
Dbprintf("AC_DATA_DEC_TRANS_REST: OK");
return ((keytype == AUTHKEYA && (AC == 0x00 || AC == 0x06 || AC == 0x01))
|| (keytype == AUTHKEYB && (AC == 0x00 || AC == 0x06 || AC == 0x01)));
}
@@ -160,25 +174,25 @@ static bool MifareSimInit(uint16_t flags, uint8_t *datain, tag_response_info_t *
// SAK
static uint8_t rSAK_Mini = 0x09; // mifare Mini
static uint8_t rSAK_1k = 0x08; // mifare 1k
static uint8_t rSAK_2k = 0x08; // mifare 2k with RATS support
static uint8_t rSAK_4k = 0x18; // mifare 4k
static uint8_t rSAK_1k = 0x08; // mifare 1k
static uint8_t rSAK_2k = 0x08; // mifare 2k with RATS support
static uint8_t rSAK_4k = 0x18; // mifare 4k
static uint8_t rUIDBCC1[] = {0x00, 0x00, 0x00, 0x00, 0x00}; // UID 1st cascade level
static uint8_t rUIDBCC1b4[] = {0x00, 0x00, 0x00, 0x00}; // UID 1st cascade level, last 4 bytes
static uint8_t rUIDBCC1b3[] = {0x00, 0x00, 0x00}; // UID 1st cascade level, last 3 bytes
static uint8_t rUIDBCC1b2[] = {0x00, 0x00}; // UID 1st cascade level, last 2 bytes
static uint8_t rUIDBCC1b1[] = {0x00}; // UID 1st cascade level, last byte
static uint8_t rUIDBCC2[] = {0x00, 0x00, 0x00, 0x00, 0x00}; // UID 2nd cascade level
static uint8_t rUIDBCC2b4[] = {0x00, 0x00, 0x00, 0x00}; // UID 2st cascade level, last 4 bytes
static uint8_t rUIDBCC2b3[] = {0x00, 0x00, 0x00}; // UID 2st cascade level, last 3 bytes
static uint8_t rUIDBCC2b2[] = {0x00, 0x00}; // UID 2st cascade level, last 2 bytes
static uint8_t rUIDBCC2b1[] = {0x00}; // UID 2st cascade level, last byte
static uint8_t rUIDBCC3[] = {0x00, 0x00, 0x00, 0x00, 0x00}; // UID 3nd cascade level
static uint8_t rUIDBCC3b4[] = {0x00, 0x00, 0x00, 0x00}; // UID 3st cascade level, last 4 bytes
static uint8_t rUIDBCC3b3[] = {0x00, 0x00, 0x00}; // UID 3st cascade level, last 3 bytes
static uint8_t rUIDBCC3b2[] = {0x00, 0x00}; // UID 3st cascade level, last 2 bytes
static uint8_t rUIDBCC3b1[] = {0x00}; // UID 3st cascade level, last byte
static uint8_t rUIDBCC1[] = {0x00, 0x00, 0x00, 0x00, 0x00}; // UID 1st cascade level
static uint8_t rUIDBCC1b4[] = {0x00, 0x00, 0x00, 0x00}; // UID 1st cascade level, last 4 bytes
static uint8_t rUIDBCC1b3[] = {0x00, 0x00, 0x00}; // UID 1st cascade level, last 3 bytes
static uint8_t rUIDBCC1b2[] = {0x00, 0x00}; // UID 1st cascade level, last 2 bytes
static uint8_t rUIDBCC1b1[] = {0x00}; // UID 1st cascade level, last byte
static uint8_t rUIDBCC2[] = {0x00, 0x00, 0x00, 0x00, 0x00}; // UID 2nd cascade level
static uint8_t rUIDBCC2b4[] = {0x00, 0x00, 0x00, 0x00}; // UID 2st cascade level, last 4 bytes
static uint8_t rUIDBCC2b3[] = {0x00, 0x00, 0x00}; // UID 2st cascade level, last 3 bytes
static uint8_t rUIDBCC2b2[] = {0x00, 0x00}; // UID 2st cascade level, last 2 bytes
static uint8_t rUIDBCC2b1[] = {0x00}; // UID 2st cascade level, last byte
static uint8_t rUIDBCC3[] = {0x00, 0x00, 0x00, 0x00, 0x00}; // UID 3nd cascade level
static uint8_t rUIDBCC3b4[] = {0x00, 0x00, 0x00, 0x00}; // UID 3st cascade level, last 4 bytes
static uint8_t rUIDBCC3b3[] = {0x00, 0x00, 0x00}; // UID 3st cascade level, last 3 bytes
static uint8_t rUIDBCC3b2[] = {0x00, 0x00}; // UID 3st cascade level, last 2 bytes
static uint8_t rUIDBCC3b1[] = {0x00}; // UID 3st cascade level, last byte
static uint8_t rATQA[] = {0x00, 0x00}; // Current ATQA
static uint8_t rSAK[] = {0x00, 0x00, 0x00}; // Current SAK, CRC
@@ -254,17 +268,18 @@ static bool MifareSimInit(uint16_t flags, uint8_t *datain, tag_response_info_t *
}
// Prepare UID arrays
if ((flags & FLAG_4B_UID_IN_DATA) == FLAG_4B_UID_IN_DATA) { // get UID from datain
if ((flags & FLAG_4B_UID_IN_DATA) == FLAG_4B_UID_IN_DATA) { // get UID from datain
memcpy(rUIDBCC1, datain, 4);
*uid_len = 4;
if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("MifareSimInit - FLAG_4B_UID_IN_DATA => Get UID from datain: %02X - Flag: %02X - UIDBCC1: %02X", FLAG_4B_UID_IN_DATA, flags, rUIDBCC1);
if (DBGLEVEL >= DBG_EXTENDED)
Dbprintf("MifareSimInit - FLAG_4B_UID_IN_DATA => Get UID from datain: %02X - Flag: %02X - UIDBCC1: %02X", FLAG_4B_UID_IN_DATA, flags, rUIDBCC1);
// save CUID
*cuid = bytes_to_num(rUIDBCC1, 4);
// BCC
rUIDBCC1[4] = rUIDBCC1[0] ^ rUIDBCC1[1] ^ rUIDBCC1[2] ^ rUIDBCC1[3];
if (DBGLEVEL >= DBG_NONE) {
if (DBGLEVEL >= DBG_NONE) {
Dbprintf("4B UID: %02x%02x%02x%02x", rUIDBCC1[0], rUIDBCC1[1], rUIDBCC1[2], rUIDBCC1[3]);
}
@@ -275,7 +290,8 @@ static bool MifareSimInit(uint16_t flags, uint8_t *datain, tag_response_info_t *
memcpy(&rUIDBCC1[1], datain, 3);
memcpy(rUIDBCC2, datain + 3, 4);
*uid_len = 7;
if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("MifareSimInit - FLAG_7B_UID_IN_DATA => Get UID from datain: %02X - Flag: %02X - UIDBCC1: %02X", FLAG_7B_UID_IN_DATA, flags, rUIDBCC1);
if (DBGLEVEL >= DBG_EXTENDED)
Dbprintf("MifareSimInit - FLAG_7B_UID_IN_DATA => Get UID from datain: %02X - Flag: %02X - UIDBCC1: %02X", FLAG_7B_UID_IN_DATA, flags, rUIDBCC1);
// save CUID
*cuid = bytes_to_num(rUIDBCC2, 4);
@@ -284,7 +300,7 @@ static bool MifareSimInit(uint16_t flags, uint8_t *datain, tag_response_info_t *
// BCC
rUIDBCC1[4] = rUIDBCC1[0] ^ rUIDBCC1[1] ^ rUIDBCC1[2] ^ rUIDBCC1[3];
rUIDBCC2[4] = rUIDBCC2[0] ^ rUIDBCC2[1] ^ rUIDBCC2[2] ^ rUIDBCC2[3];
if (DBGLEVEL >= DBG_NONE) {
if (DBGLEVEL >= DBG_NONE) {
Dbprintf("7B UID: %02x %02x %02x %02x %02x %02x %02x",
rUIDBCC1[1], rUIDBCC1[2], rUIDBCC1[3], rUIDBCC2[0], rUIDBCC2[1], rUIDBCC2[2], rUIDBCC2[3]);
}
@@ -297,7 +313,8 @@ static bool MifareSimInit(uint16_t flags, uint8_t *datain, tag_response_info_t *
memcpy(&rUIDBCC2[1], datain + 3, 3);
memcpy(rUIDBCC3, datain + 6, 4);
*uid_len = 10;
if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("MifareSimInit - FLAG_10B_UID_IN_DATA => Get UID from datain: %02X - Flag: %02X - UIDBCC1: %02X", FLAG_10B_UID_IN_DATA, flags, rUIDBCC1);
if (DBGLEVEL >= DBG_EXTENDED)
Dbprintf("MifareSimInit - FLAG_10B_UID_IN_DATA => Get UID from datain: %02X - Flag: %02X - UIDBCC1: %02X", FLAG_10B_UID_IN_DATA, flags, rUIDBCC1);
// save CUID
*cuid = bytes_to_num(rUIDBCC3, 4);
@@ -309,7 +326,7 @@ static bool MifareSimInit(uint16_t flags, uint8_t *datain, tag_response_info_t *
rUIDBCC2[4] = rUIDBCC2[0] ^ rUIDBCC2[1] ^ rUIDBCC2[2] ^ rUIDBCC2[3];
rUIDBCC3[4] = rUIDBCC3[0] ^ rUIDBCC3[1] ^ rUIDBCC3[2] ^ rUIDBCC3[3];
if (DBGLEVEL >= DBG_NONE) {
if (DBGLEVEL >= DBG_NONE) {
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],
@@ -347,23 +364,23 @@ static bool MifareSimInit(uint16_t flags, uint8_t *datain, tag_response_info_t *
#define TAG_RESPONSE_COUNT 18
static tag_response_info_t responses_init[TAG_RESPONSE_COUNT] = {
{ .response = rATQA, .response_n = sizeof(rATQA) }, // Answer to request - respond with card type
{ .response = rATQA, .response_n = sizeof(rATQA) }, // Answer to request - respond with card type
{ .response = rSAK, .response_n = sizeof(rSAK) }, //
{ .response = rSAKuid, .response_n = sizeof(rSAKuid) }, //
{ .response = rSAKuid, .response_n = sizeof(rSAKuid) }, //
// Do not reorder. Block used via relative index of rUIDBCC1
{ .response = rUIDBCC1, .response_n = sizeof(rUIDBCC1) }, // Anticollision cascade1 - respond with first part of uid
{ .response = rUIDBCC1, .response_n = sizeof(rUIDBCC1) }, // Anticollision cascade1 - respond with first part of uid
{ .response = rUIDBCC1b4, .response_n = sizeof(rUIDBCC1b4)},
{ .response = rUIDBCC1b3, .response_n = sizeof(rUIDBCC1b3)},
{ .response = rUIDBCC1b2, .response_n = sizeof(rUIDBCC1b2)},
{ .response = rUIDBCC1b1, .response_n = sizeof(rUIDBCC1b1)},
// Do not reorder. Block used via relative index of rUIDBCC2
{ .response = rUIDBCC2, .response_n = sizeof(rUIDBCC2) }, // Anticollision cascade2 - respond with 2nd part of uid
{ .response = rUIDBCC2, .response_n = sizeof(rUIDBCC2) }, // Anticollision cascade2 - respond with 2nd part of uid
{ .response = rUIDBCC2b4, .response_n = sizeof(rUIDBCC2b4)},
{ .response = rUIDBCC2b3, .response_n = sizeof(rUIDBCC2b3)},
{ .response = rUIDBCC2b2, .response_n = sizeof(rUIDBCC2b2)},
{ .response = rUIDBCC2b1, .response_n = sizeof(rUIDBCC2b1)},
// Do not reorder. Block used via relative index of rUIDBCC3
{ .response = rUIDBCC3, .response_n = sizeof(rUIDBCC3) }, // Anticollision cascade3 - respond with 3th part of uid
{ .response = rUIDBCC3, .response_n = sizeof(rUIDBCC3) }, // Anticollision cascade3 - respond with 3th part of uid
{ .response = rUIDBCC3b4, .response_n = sizeof(rUIDBCC3b4)},
{ .response = rUIDBCC3b3, .response_n = sizeof(rUIDBCC3b3)},
{ .response = rUIDBCC3b2, .response_n = sizeof(rUIDBCC3b2)},
@@ -407,11 +424,11 @@ static bool MifareSimInit(uint16_t flags, uint8_t *datain, tag_response_info_t *
*MIFARE 1K simulate.
*
*@param flags :
* FLAG_INTERACTIVE - In interactive mode, we are expected to finish the operation with an ACK
* FLAG_INTERACTIVE - In interactive mode, we are expected to finish the operation with an ACK
* 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
* 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 infinite ...
* (unless reader attack mode enabled then it runs util it gets enough nonces to recover all keys attmpted)
*/
@@ -421,7 +438,7 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain) {
uint8_t uid_len = 0; // 4,7, 10
uint32_t cuid = 0;
int vHf = 0; // in mV
int vHf = 0; // in mV
uint32_t selTimer = 0;
uint32_t authTimer = 0;
@@ -445,7 +462,7 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain) {
struct Crypto1State *pcs;
pcs = &mpcs;
uint32_t numReads = 0; //Counts numer of times reader reads a block
uint32_t numReads = 0; //Counts numer of times reader reads a block
uint8_t receivedCmd[MAX_MIFARE_FRAME_SIZE] = {0x00};
uint8_t receivedCmd_dec[MAX_MIFARE_FRAME_SIZE] = {0x00};
uint8_t receivedCmd_par[MAX_MIFARE_PARITY_SIZE] = {0x00};
@@ -467,11 +484,11 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain) {
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;
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
uint8_t mM = 0; //moebius_modifier for collection storage
// Authenticate response - nonce
uint8_t rAUTH_NT[4];
@@ -520,18 +537,21 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain) {
if (res == 2) { //Field is off!
LEDsoff();
cardSTATE = MFEMUL_NOFIELD;
if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("cardSTATE = MFEMUL_NOFIELD");
if (DBGLEVEL >= DBG_EXTENDED)
Dbprintf("cardSTATE = MFEMUL_NOFIELD");
continue;
} else if (res == 1) { // button pressed
button_pushed = true;
if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("Button pressed");
if (DBGLEVEL >= DBG_EXTENDED)
Dbprintf("Button pressed");
break;
}
// WUPA in HALTED state or REQA or WUPA in any other state
if (receivedCmd_len == 1 && ((receivedCmd[0] == ISO14443A_CMD_REQA && cardSTATE != MFEMUL_HALTED) || receivedCmd[0] == ISO14443A_CMD_WUPA)) {
selTimer = GetTickCount();
if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("EmSendPrecompiledCmd(&responses[ATQA]);");
if (DBGLEVEL >= DBG_EXTENDED)
Dbprintf("EmSendPrecompiledCmd(&responses[ATQA]);");
EmSendPrecompiledCmd(&responses[ATQA]);
// init crypto block
@@ -550,12 +570,15 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain) {
switch (cardSTATE) {
case MFEMUL_NOFIELD:
if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("MFEMUL_NOFIELD");
if (DBGLEVEL >= DBG_EXTENDED)
Dbprintf("MFEMUL_NOFIELD");
case MFEMUL_HALTED:
if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("MFEMUL_HALTED");
if (DBGLEVEL >= DBG_EXTENDED)
Dbprintf("MFEMUL_HALTED");
case MFEMUL_IDLE: {
LogTrace(uart->output, uart->len, uart->startTime * 16 - DELAY_AIR2ARM_AS_TAG, uart->endTime * 16 - DELAY_AIR2ARM_AS_TAG, uart->parity, true);
if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("MFEMUL_IDLE");
if (DBGLEVEL >= DBG_EXTENDED)
Dbprintf("MFEMUL_IDLE");
break;
}
@@ -649,7 +672,8 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain) {
// WORK
case MFEMUL_WORK: {
if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("[MFEMUL_WORK] Enter in case");
if (DBGLEVEL >= DBG_EXTENDED)
Dbprintf("[MFEMUL_WORK] Enter in case");
if (receivedCmd_len == 0) {
if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("[MFEMUL_WORK] NO CMD received");
@@ -799,20 +823,20 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain) {
if (IsSectorTrailer(blockNo)) {
if (!IsAccessAllowed(blockNo, cardAUTHKEY, AC_KEYA_READ)) {
memset(response, 0x00, 6); // keyA can never be read
memset(response, 0x00, 6); // keyA can never be read
if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("[MFEMUL_WORK - IsSectorTrailer] keyA can never be read - block %d (0x%02x)", blockNo, blockNo);
}
if (!IsAccessAllowed(blockNo, cardAUTHKEY, AC_KEYB_READ)) {
memset(response + 10, 0x00, 6); // keyB cannot be read
memset(response + 10, 0x00, 6); // keyB cannot be read
if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("[MFEMUL_WORK - IsSectorTrailer] keyB cannot be read - block %d (0x%02x)", blockNo, blockNo);
}
if (!IsAccessAllowed(blockNo, cardAUTHKEY, AC_AC_READ)) {
memset(response + 6, 0x00, 4); // AC bits cannot be read
memset(response + 6, 0x00, 4); // AC bits cannot be read
if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("[MFEMUL_WORK - IsAccessAllowed] AC bits cannot be read - block %d (0x%02x)", blockNo, blockNo);
}
} else {
if (!IsAccessAllowed(blockNo, cardAUTHKEY, AC_DATA_READ)) {
memset(response, 0x00, 16); // datablock cannot be read
memset(response, 0x00, 16); // datablock cannot be read
if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("[MFEMUL_WORK - IsAccessAllowed] Data block %d (0x%02x) cannot be read", blockNo, blockNo);
}
}
@@ -898,7 +922,8 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain) {
LED_C_OFF();
cardSTATE = MFEMUL_HALTED;
cardAUTHKEY = AUTHKEYNONE;
if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("[MFEMUL_WORK] cardSTATE = MFEMUL_HALTED");
if (DBGLEVEL >= DBG_EXTENDED)
Dbprintf("[MFEMUL_WORK] cardSTATE = MFEMUL_HALTED");
break;
}
@@ -911,10 +936,12 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain) {
EmSendCmdPar(response, rats_len, response_par);
} else
EmSendCmd(rats, rats_len);
if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("[MFEMUL_WORK] RCV RATS => ACK");
if (DBGLEVEL >= DBG_EXTENDED)
Dbprintf("[MFEMUL_WORK] RCV RATS => ACK");
} else {
EmSend4bit(encrypted_data ? mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA) : CARD_NACK_NA);
if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("[MFEMUL_WORK] RCV RATS => NACK");
if (DBGLEVEL >= DBG_EXTENDED)
Dbprintf("[MFEMUL_WORK] RCV RATS => NACK");
}
break;
}
@@ -929,28 +956,33 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain) {
EmSendCmdPar(response, receivedCmd_len, response_par);
} else
EmSendCmd(receivedCmd_dec, receivedCmd_len);
if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("[MFEMUL_WORK] RCV NXP DESELECT => ACK");
if (DBGLEVEL >= DBG_EXTENDED)
Dbprintf("[MFEMUL_WORK] RCV NXP DESELECT => ACK");
} else {
EmSend4bit(encrypted_data ? mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA) : CARD_NACK_NA);
if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("[MFEMUL_WORK] RCV NXP DESELECT => NACK");
if (DBGLEVEL >= DBG_EXTENDED)
Dbprintf("[MFEMUL_WORK] RCV NXP DESELECT => NACK");
}
break;
}
// case MFEMUL_WORK => command not allowed
if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("Received command not allowed, nacking");
if (DBGLEVEL >= DBG_EXTENDED)
Dbprintf("Received command not allowed, nacking");
EmSend4bit(encrypted_data ? mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA) : CARD_NACK_NA);
break;
}
// AUTH1
case MFEMUL_AUTH1: {
if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("[MFEMUL_AUTH1] Enter case");
if (DBGLEVEL >= DBG_EXTENDED)
Dbprintf("[MFEMUL_AUTH1] Enter case");
if (receivedCmd_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);
if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("MFEMUL_AUTH1: receivedCmd_len != 8 (%d) => cardSTATE_TO_IDLE())", receivedCmd_len);
if (DBGLEVEL >= DBG_EXTENDED)
Dbprintf("MFEMUL_AUTH1: receivedCmd_len != 8 (%d) => cardSTATE_TO_IDLE())", receivedCmd_len);
break;
}
@@ -1034,7 +1066,7 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain) {
, prng_successor(nonce, 64)
);
}
cardAUTHKEY = AUTHKEYNONE; // not authenticated
cardAUTHKEY = AUTHKEYNONE; // not authenticated
cardSTATE_TO_IDLE();
// Really tags not respond NACK on invalid authentication
LogTrace(uart->output, uart->len, uart->startTime * 16 - DELAY_AIR2ARM_AS_TAG, uart->endTime * 16 - DELAY_AIR2ARM_AS_TAG, uart->parity, true);
@@ -1067,21 +1099,21 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain) {
if (IsSectorTrailer(cardWRBL)) {
emlGetMem(response, cardWRBL, 1);
if (!IsAccessAllowed(cardWRBL, cardAUTHKEY, AC_KEYA_WRITE)) {
memcpy(receivedCmd_dec, response, 6); // don't change KeyA
memcpy(receivedCmd_dec, response, 6); // don't change KeyA
}
if (!IsAccessAllowed(cardWRBL, cardAUTHKEY, AC_KEYB_WRITE)) {
memcpy(receivedCmd_dec + 10, response + 10, 6); // don't change KeyA
memcpy(receivedCmd_dec + 10, response + 10, 6); // don't change KeyA
}
if (!IsAccessAllowed(cardWRBL, cardAUTHKEY, AC_AC_WRITE)) {
memcpy(receivedCmd_dec + 6, response + 6, 4); // don't change AC bits
memcpy(receivedCmd_dec + 6, response + 6, 4); // don't change AC bits
}
} else {
if (!IsAccessAllowed(cardWRBL, cardAUTHKEY, AC_DATA_WRITE)) {
memcpy(receivedCmd_dec, response, 16); // don't change anything
memcpy(receivedCmd_dec, response, 16); // don't change anything
}
}
emlSetMem(receivedCmd_dec, cardWRBL, 1);
EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_ACK)); // always ACK?
EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_ACK)); // always ACK?
cardSTATE = MFEMUL_WORK;
if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("[MFEMUL_WRITEBL2] cardSTATE = MFEMUL_WORK");
break;
@@ -1152,7 +1184,7 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain) {
// NR AR ATTACK
if (((flags & FLAG_NR_AR_ATTACK) == FLAG_NR_AR_ATTACK) && (DBGLEVEL >= DBG_INFO)) {
for (uint8_t i = 0; i < ATTACK_KEY_COUNT; i++) {
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",
@@ -1167,7 +1199,7 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain) {
}
}
for (uint8_t i = ATTACK_KEY_COUNT; i < ATTACK_KEY_COUNT * 2; i++) {
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",
@@ -1182,7 +1214,7 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain) {
}
}
if (DBGLEVEL >= DBG_ERROR) {
if (DBGLEVEL >= DBG_ERROR) {
Dbprintf("Emulator stopped. Tracing: %d trace length: %d ", get_tracing(), BigBuf_get_traceLen());
}

View File

@@ -16,7 +16,7 @@
#include <stdint.h>
#ifndef CheckCrc14A
# define CheckCrc14A(data, len) check_crc(CRC_14443_A, (data), (len))
# define CheckCrc14A(data, len) check_crc(CRC_14443_A, (data), (len))
#endif
void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain);
@@ -24,7 +24,7 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain);
#define AC_DATA_READ 0
#define AC_DATA_WRITE 1
#define AC_DATA_INC 2
#define AC_DATA_DEC_TRANS_REST 3
#define AC_DATA_DEC_TRANS_REST 3
#define AC_KEYA_READ 0
#define AC_KEYA_WRITE 1
#define AC_KEYB_READ 2

View File

@@ -11,7 +11,7 @@
#include "mifaresniff.h"
#ifndef CheckCrc14A
# define CheckCrc14A(data, len) check_crc(CRC_14443_A, (data), (len))
# define CheckCrc14A(data, len) check_crc(CRC_14443_A, (data), (len))
#endif
//static int sniffState = SNF_INIT;

View File

@@ -602,10 +602,12 @@ void emlClearMem(void) {
uint8_t SectorTrailer(uint8_t blockNo) {
if (blockNo <= MIFARE_2K_MAXBLOCK) {
if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("Sector Trailer for block %d : %d", blockNo, (blockNo | 0x03));
if (DBGLEVEL >= DBG_EXTENDED)
Dbprintf("Sector Trailer for block %d : %d", blockNo, (blockNo | 0x03));
return (blockNo | 0x03);
} else {
if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("Sector Trailer for block %d : %d", blockNo, (blockNo | 0x0f));
if (DBGLEVEL >= DBG_EXTENDED)
Dbprintf("Sector Trailer for block %d : %d", blockNo, (blockNo | 0x0f));
return (blockNo | 0x0f);
}
}

View File

@@ -56,6 +56,7 @@ int rdv40_spiffs_copy(char *src, char *dst, RDV40SpiFFSSafetyLevel level);
int rdv40_spiffs_append(char *filename, uint8_t *src, uint32_t size, RDV40SpiFFSSafetyLevel level);
int rdv40_spiffs_stat(char *filename, uint32_t *buf, RDV40SpiFFSSafetyLevel level);
uint32_t size_in_spiffs(const char *filename);
int exists_in_spiffs(const char *filename);
#define SPIFFS_OK 0
#define SPIFFS_ERR_NOT_MOUNTED -10000