hf mf c* commands for gen1b

This commit is contained in:
Fl0-0 2017-07-06 16:44:20 +02:00
commit 481a8bbc34
4 changed files with 417 additions and 298 deletions

View file

@ -1179,6 +1179,7 @@ void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai
// bit 2 - need HALT after sequence // bit 2 - need HALT after sequence
// bit 3 - need init FPGA and field before sequence // bit 3 - need init FPGA and field before sequence
// bit 4 - need reset FPGA and LED // bit 4 - need reset FPGA and LED
// bit 6 - gen1b backdoor type
uint8_t workFlags = arg1; uint8_t workFlags = arg1;
uint8_t blockNo = arg2; uint8_t blockNo = arg2;
@ -1211,15 +1212,18 @@ void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai
// get UID from chip // get UID from chip
if (workFlags & 0x01) { if (workFlags & 0x01) {
if(!iso14443a_select_card(uid, NULL, &cuid, true, 0)) { // do no get UID for gen1b magic tag
if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card"); if (!(workFlags & 0x40)) {
break; if(!iso14443a_select_card(uid, NULL, &cuid, true, 0)) {
}; if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card");
break;
};
if(mifare_classic_halt(NULL, cuid)) { if(mifare_classic_halt(NULL, cuid)) {
if (MF_DBGLEVEL >= 1) Dbprintf("Halt error"); if (MF_DBGLEVEL >= 1) Dbprintf("Halt error");
// Continue, some magic tags misbehavies and send an answer to it. // Continue, some magic tags misbehavies and send an answer to it.
// break; // break;
};
}; };
}; };
@ -1252,11 +1256,14 @@ void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai
break; break;
}; };
ReaderTransmit(wupC2, sizeof(wupC2), NULL); // do no issue for gen1b magic tag
if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) { if (!(workFlags & 0x40)) {
if (MF_DBGLEVEL >= 1) Dbprintf("wupC2 error"); ReaderTransmit(wupC2, sizeof(wupC2), NULL);
break; if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {
}; if (MF_DBGLEVEL >= 1) Dbprintf("wupC2 error");
break;
};
}
} }
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)) {
@ -1304,6 +1311,7 @@ void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai
// bit 3 - need init FPGA and field before sequence // bit 3 - need init FPGA and field before sequence
// bit 4 - need reset FPGA and LED // bit 4 - need reset FPGA and LED
// bit 5 - need to set datain instead of issuing USB reply (called via ARM for StandAloneMode14a) // bit 5 - need to set datain instead of issuing USB reply (called via ARM for StandAloneMode14a)
// bit 6 - gen1b backdoor type
uint8_t workFlags = arg0; uint8_t workFlags = arg0;
uint8_t blockNo = arg2; uint8_t blockNo = arg2;
@ -1335,14 +1343,16 @@ void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai
if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) { if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {
if (MF_DBGLEVEL >= 1) Dbprintf("wupC1 error"); if (MF_DBGLEVEL >= 1) Dbprintf("wupC1 error");
break; break;
}; };
// do no issue for gen1b magic tag
ReaderTransmit(wupC2, sizeof(wupC2), NULL); if (!(workFlags & 0x40)) {
if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) { ReaderTransmit(wupC2, sizeof(wupC2), NULL);
if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {
if (MF_DBGLEVEL >= 1) Dbprintf("wupC2 error"); if (MF_DBGLEVEL >= 1) Dbprintf("wupC2 error");
break; break;
}; };
} }
}
// read block // read block
if ((mifare_sendcmd_short(NULL, 0, 0x30, blockNo, receivedAnswer, receivedAnswerPar, NULL) != 18)) { if ((mifare_sendcmd_short(NULL, 0, 0x30, blockNo, receivedAnswer, receivedAnswerPar, NULL) != 18)) {

View file

@ -28,7 +28,6 @@
#define NESTED_SECTOR_RETRY 10 // how often we try mfested() until we give up #define NESTED_SECTOR_RETRY 10 // how often we try mfested() until we give up
static int CmdHelp(const char *Cmd); static int CmdHelp(const char *Cmd);
int CmdHF14AMifare(const char *Cmd) int CmdHF14AMifare(const char *Cmd)
@ -1738,7 +1737,6 @@ int CmdHF14AMfECFill(const char *Cmd)
return 0; return 0;
} }
int CmdHF14AMfEKeyPrn(const char *Cmd) int CmdHF14AMfEKeyPrn(const char *Cmd)
{ {
int i; int i;
@ -1783,7 +1781,6 @@ int CmdHF14AMfEKeyPrn(const char *Cmd)
return 0; return 0;
} }
int CmdHF14AMfCSetUID(const char *Cmd) int CmdHF14AMfCSetUID(const char *Cmd)
{ {
uint8_t wipeCard = 0; uint8_t wipeCard = 0;
@ -1858,7 +1855,7 @@ int CmdHF14AMfCSetBlk(const char *Cmd)
uint8_t memBlock[16] = {0x00}; uint8_t memBlock[16] = {0x00};
uint8_t blockNo = 0; uint8_t blockNo = 0;
bool wipeCard = false; bool wipeCard = false;
int res; int res, gen = 0;
if (strlen(Cmd) < 1 || param_getchar(Cmd, 0) == 'h') { if (strlen(Cmd) < 1 || param_getchar(Cmd, 0) == 'h') {
PrintAndLog("Usage: hf mf csetblk <block number> <block data (32 hex symbols)> [w]"); PrintAndLog("Usage: hf mf csetblk <block number> <block data (32 hex symbols)> [w]");
@ -1868,6 +1865,8 @@ int CmdHF14AMfCSetBlk(const char *Cmd)
return 0; return 0;
} }
gen = mfCIdentify();
blockNo = param_get8(Cmd, 0); blockNo = param_get8(Cmd, 0);
if (param_gethex(Cmd, 1, memBlock, 32)) { if (param_gethex(Cmd, 1, memBlock, 32)) {
@ -1879,7 +1878,14 @@ int CmdHF14AMfCSetBlk(const char *Cmd)
wipeCard = (ctmp == 'w' || ctmp == 'W'); wipeCard = (ctmp == 'w' || ctmp == 'W');
PrintAndLog("--block number:%2d data:%s", blockNo, sprint_hex(memBlock, 16)); PrintAndLog("--block number:%2d data:%s", blockNo, sprint_hex(memBlock, 16));
res = mfCSetBlock(blockNo, memBlock, NULL, wipeCard, CSETBLOCK_SINGLE_OPER); if (gen == 2) {
/* generation 1b magic card */
res = mfCSetBlock(blockNo, memBlock, NULL, wipeCard, CSETBLOCK_SINGLE_OPER | CSETBLOCK_MAGIC_1B);
} else {
/* generation 1a magic card by default */
res = mfCSetBlock(blockNo, memBlock, NULL, wipeCard, CSETBLOCK_SINGLE_OPER);
}
if (res) { if (res) {
PrintAndLog("Can't write block. error=%d", res); PrintAndLog("Can't write block. error=%d", res);
return 1; return 1;
@ -1896,7 +1902,7 @@ int CmdHF14AMfCLoad(const char *Cmd)
char buf[64] = {0x00}; char buf[64] = {0x00};
uint8_t buf8[64] = {0x00}; uint8_t buf8[64] = {0x00};
uint8_t fillFromEmulator = 0; uint8_t fillFromEmulator = 0;
int i, len, blockNum, flags=0; int i, len, blockNum, flags = 0, gen = 0;
if (param_getchar(Cmd, 0) == 'h' || param_getchar(Cmd, 0)== 0x00) { if (param_getchar(Cmd, 0) == 'h' || param_getchar(Cmd, 0)== 0x00) {
PrintAndLog("It loads magic Chinese card from the file `filename.eml`"); PrintAndLog("It loads magic Chinese card from the file `filename.eml`");
@ -1910,6 +1916,8 @@ int CmdHF14AMfCLoad(const char *Cmd)
char ctmp = param_getchar(Cmd, 0); char ctmp = param_getchar(Cmd, 0);
if (ctmp == 'e' || ctmp == 'E') fillFromEmulator = 1; if (ctmp == 'e' || ctmp == 'E') fillFromEmulator = 1;
gen = mfCIdentify();
if (fillFromEmulator) { if (fillFromEmulator) {
for (blockNum = 0; blockNum < 16 * 4; blockNum += 1) { for (blockNum = 0; blockNum < 16 * 4; blockNum += 1) {
if (mfEmlGetMem(buf8, blockNum, 1)) { if (mfEmlGetMem(buf8, blockNum, 1)) {
@ -1920,6 +1928,9 @@ int CmdHF14AMfCLoad(const char *Cmd)
if (blockNum == 1) flags = 0; // just write if (blockNum == 1) flags = 0; // just write
if (blockNum == 16 * 4 - 1) flags = CSETBLOCK_HALT + CSETBLOCK_RESET_FIELD; // Done. Magic Halt and switch off field. if (blockNum == 16 * 4 - 1) flags = CSETBLOCK_HALT + CSETBLOCK_RESET_FIELD; // Done. Magic Halt and switch off field.
if (gen == 2)
/* generation 1b magic card */
flags += CSETBLOCK_MAGIC_1B;
if (mfCSetBlock(blockNum, buf8, NULL, 0, flags)) { if (mfCSetBlock(blockNum, buf8, NULL, 0, flags)) {
PrintAndLog("Cant set magic card block: %d", blockNum); PrintAndLog("Cant set magic card block: %d", blockNum);
return 3; return 3;
@ -1967,6 +1978,9 @@ int CmdHF14AMfCLoad(const char *Cmd)
if (blockNum == 1) flags = 0; // just write if (blockNum == 1) flags = 0; // just write
if (blockNum == 16 * 4 - 1) flags = CSETBLOCK_HALT + CSETBLOCK_RESET_FIELD; // Done. Switch off field. if (blockNum == 16 * 4 - 1) flags = CSETBLOCK_HALT + CSETBLOCK_RESET_FIELD; // Done. Switch off field.
if (gen == 2)
/* generation 1b magic card */
flags += CSETBLOCK_MAGIC_1B;
if (mfCSetBlock(blockNum, buf8, NULL, 0, flags)) { if (mfCSetBlock(blockNum, buf8, NULL, 0, flags)) {
PrintAndLog("Can't set magic card block: %d", blockNum); PrintAndLog("Can't set magic card block: %d", blockNum);
fclose(f); fclose(f);
@ -1991,7 +2005,7 @@ int CmdHF14AMfCLoad(const char *Cmd)
int CmdHF14AMfCGetBlk(const char *Cmd) { int CmdHF14AMfCGetBlk(const char *Cmd) {
uint8_t memBlock[16]; uint8_t memBlock[16];
uint8_t blockNo = 0; uint8_t blockNo = 0;
int res; int res, gen = 0;
memset(memBlock, 0x00, sizeof(memBlock)); memset(memBlock, 0x00, sizeof(memBlock));
if (strlen(Cmd) < 1 || param_getchar(Cmd, 0) == 'h') { if (strlen(Cmd) < 1 || param_getchar(Cmd, 0) == 'h') {
@ -2001,11 +2015,19 @@ int CmdHF14AMfCGetBlk(const char *Cmd) {
return 0; return 0;
} }
gen = mfCIdentify();
blockNo = param_get8(Cmd, 0); blockNo = param_get8(Cmd, 0);
PrintAndLog("--block number:%2d ", blockNo); PrintAndLog("--block number:%2d ", blockNo);
res = mfCGetBlock(blockNo, memBlock, CSETBLOCK_SINGLE_OPER); if (gen == 2) {
/* generation 1b magic card */
res = mfCGetBlock(blockNo, memBlock, CSETBLOCK_SINGLE_OPER | CSETBLOCK_MAGIC_1B);
} else {
/* generation 1a magic card by default */
res = mfCGetBlock(blockNo, memBlock, CSETBLOCK_SINGLE_OPER);
}
if (res) { if (res) {
PrintAndLog("Can't read block. error=%d", res); PrintAndLog("Can't read block. error=%d", res);
return 1; return 1;
@ -2015,11 +2037,10 @@ int CmdHF14AMfCGetBlk(const char *Cmd) {
return 0; return 0;
} }
int CmdHF14AMfCGetSc(const char *Cmd) { int CmdHF14AMfCGetSc(const char *Cmd) {
uint8_t memBlock[16] = {0x00}; uint8_t memBlock[16] = {0x00};
uint8_t sectorNo = 0; uint8_t sectorNo = 0;
int i, res, flags; int i, res, flags, gen = 0;
if (strlen(Cmd) < 1 || param_getchar(Cmd, 0) == 'h') { if (strlen(Cmd) < 1 || param_getchar(Cmd, 0) == 'h') {
PrintAndLog("Usage: hf mf cgetsc <sector number>"); PrintAndLog("Usage: hf mf cgetsc <sector number>");
@ -2036,11 +2057,16 @@ int CmdHF14AMfCGetSc(const char *Cmd) {
PrintAndLog("--sector number:%d ", sectorNo); PrintAndLog("--sector number:%d ", sectorNo);
gen = mfCIdentify();
flags = CSETBLOCK_INIT_FIELD + CSETBLOCK_WUPC; flags = CSETBLOCK_INIT_FIELD + CSETBLOCK_WUPC;
for (i = 0; i < 4; i++) { for (i = 0; i < 4; i++) {
if (i == 1) flags = 0; if (i == 1) flags = 0;
if (i == 3) flags = CSETBLOCK_HALT + CSETBLOCK_RESET_FIELD; if (i == 3) flags = CSETBLOCK_HALT + CSETBLOCK_RESET_FIELD;
if (gen == 2)
/* generation 1b magic card */
flags += CSETBLOCK_MAGIC_1B;
res = mfCGetBlock(sectorNo * 4 + i, memBlock, flags); res = mfCGetBlock(sectorNo * 4 + i, memBlock, flags);
if (res) { if (res) {
PrintAndLog("Can't read block. %d error=%d", sectorNo * 4 + i, res); PrintAndLog("Can't read block. %d error=%d", sectorNo * 4 + i, res);
@ -2060,7 +2086,7 @@ int CmdHF14AMfCSave(const char *Cmd) {
char * fnameptr = filename; char * fnameptr = filename;
uint8_t fillFromEmulator = 0; uint8_t fillFromEmulator = 0;
uint8_t buf[64] = {0x00}; uint8_t buf[64] = {0x00};
int i, j, len, flags; int i, j, len, flags, gen = 0;
// memset(filename, 0, sizeof(filename)); // memset(filename, 0, sizeof(filename));
// memset(buf, 0, sizeof(buf)); // memset(buf, 0, sizeof(buf));
@ -2078,6 +2104,8 @@ int CmdHF14AMfCSave(const char *Cmd) {
char ctmp = param_getchar(Cmd, 0); char ctmp = param_getchar(Cmd, 0);
if (ctmp == 'e' || ctmp == 'E') fillFromEmulator = 1; if (ctmp == 'e' || ctmp == 'E') fillFromEmulator = 1;
gen = mfCIdentify();
if (fillFromEmulator) { if (fillFromEmulator) {
// put into emulator // put into emulator
flags = CSETBLOCK_INIT_FIELD + CSETBLOCK_WUPC; flags = CSETBLOCK_INIT_FIELD + CSETBLOCK_WUPC;
@ -2085,6 +2113,10 @@ int CmdHF14AMfCSave(const char *Cmd) {
if (i == 1) flags = 0; if (i == 1) flags = 0;
if (i == 16 * 4 - 1) flags = CSETBLOCK_HALT + CSETBLOCK_RESET_FIELD; if (i == 16 * 4 - 1) flags = CSETBLOCK_HALT + CSETBLOCK_RESET_FIELD;
if (gen == 2)
/* generation 1b magic card */
flags += CSETBLOCK_MAGIC_1B;
if (mfCGetBlock(i, buf, flags)) { if (mfCGetBlock(i, buf, flags)) {
PrintAndLog("Cant get block: %d", i); PrintAndLog("Cant get block: %d", i);
break; break;
@ -2102,7 +2134,12 @@ int CmdHF14AMfCSave(const char *Cmd) {
if (len < 1) { if (len < 1) {
// get filename // get filename
if (mfCGetBlock(0, buf, CSETBLOCK_SINGLE_OPER)) {
flags = CSETBLOCK_SINGLE_OPER;
if (gen == 2)
/* generation 1b magic card */
flags += CSETBLOCK_MAGIC_1B;
if (mfCGetBlock(0, buf, flags)) {
PrintAndLog("Cant get block: %d", 0); PrintAndLog("Cant get block: %d", 0);
len = sprintf(fnameptr, "dump"); len = sprintf(fnameptr, "dump");
fnameptr += len; fnameptr += len;
@ -2132,6 +2169,9 @@ int CmdHF14AMfCSave(const char *Cmd) {
if (i == 1) flags = 0; if (i == 1) flags = 0;
if (i == 16 * 4 - 1) flags = CSETBLOCK_HALT + CSETBLOCK_RESET_FIELD; if (i == 16 * 4 - 1) flags = CSETBLOCK_HALT + CSETBLOCK_RESET_FIELD;
if (gen == 2)
/* generation 1b magic card */
flags += CSETBLOCK_MAGIC_1B;
if (mfCGetBlock(i, buf, flags)) { if (mfCGetBlock(i, buf, flags)) {
PrintAndLog("Cant get block: %d", i); PrintAndLog("Cant get block: %d", i);
break; break;

View file

@ -23,6 +23,8 @@
#include "util.h" #include "util.h"
#include "iso14443crc.h" #include "iso14443crc.h"
#include "mifare.h"
// mifare tracer flags used in mfTraceDecode() // mifare tracer flags used in mfTraceDecode()
#define TRACE_IDLE 0x00 #define TRACE_IDLE 0x00
#define TRACE_AUTH1 0x01 #define TRACE_AUTH1 0x01
@ -452,8 +454,18 @@ int mfCSetBlock(uint8_t blockNo, uint8_t *data, uint8_t *uid, bool wantWipe, uin
int mfCSetUID(uint8_t *uid, uint8_t *atqa, uint8_t *sak, uint8_t *oldUID, bool wantWipe) { int mfCSetUID(uint8_t *uid, uint8_t *atqa, uint8_t *sak, uint8_t *oldUID, bool wantWipe) {
uint8_t oldblock0[16] = {0x00}; uint8_t oldblock0[16] = {0x00};
uint8_t block0[16] = {0x00}; uint8_t block0[16] = {0x00};
int old, gen = 0;
gen = mfCIdentify();
if (gen == 2) {
/* generation 1b magic card */
old = mfCGetBlock(0, oldblock0, CSETBLOCK_SINGLE_OPER | CSETBLOCK_MAGIC_1B);
} else {
/* generation 1a magic card by default */
old = mfCGetBlock(0, oldblock0, CSETBLOCK_SINGLE_OPER);
}
int old = mfCGetBlock(0, oldblock0, CSETBLOCK_SINGLE_OPER);
if (old == 0) { if (old == 0) {
memcpy(block0, oldblock0, 16); memcpy(block0, oldblock0, 16);
PrintAndLog("old block 0: %s", sprint_hex(block0,16)); PrintAndLog("old block 0: %s", sprint_hex(block0,16));
@ -474,7 +486,14 @@ int mfCSetUID(uint8_t *uid, uint8_t *atqa, uint8_t *sak, uint8_t *oldUID, bool w
block0[7]=atqa[0]; block0[7]=atqa[0];
} }
PrintAndLog("new block 0: %s", sprint_hex(block0,16)); PrintAndLog("new block 0: %s", sprint_hex(block0,16));
return mfCSetBlock(0, block0, oldUID, wantWipe, CSETBLOCK_SINGLE_OPER);
if (gen == 2) {
/* generation 1b magic card */
return mfCSetBlock(0, block0, oldUID, wantWipe, CSETBLOCK_SINGLE_OPER | CSETBLOCK_MAGIC_1B);
} else {
/* generation 1a magic card by default */
return mfCSetBlock(0, block0, oldUID, wantWipe, CSETBLOCK_SINGLE_OPER);
}
} }
// SNIFFER // SNIFFER
@ -820,3 +839,50 @@ int tryDecryptWord(uint32_t nt, uint32_t ar_enc, uint32_t at_enc, uint8_t *data,
crypto1_destroy(traceCrypto1); crypto1_destroy(traceCrypto1);
return 0; return 0;
} }
int mfCIdentify()
{
UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_CONNECT | ISO14A_NO_DISCONNECT, 0, 0}};
SendCommand(&c);
UsbCommand resp;
WaitForResponse(CMD_ACK,&resp);
iso14a_card_select_t card;
memcpy(&card, (iso14a_card_select_t *)resp.d.asBytes, sizeof(iso14a_card_select_t));
uint64_t select_status = resp.arg[0]; // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS, 3: proprietary Anticollision
if(select_status != 0) {
uint8_t rats[] = { 0xE0, 0x80 }; // FSDI=8 (FSD=256), CID=0
c.arg[0] = ISO14A_RAW | ISO14A_APPEND_CRC | ISO14A_NO_DISCONNECT;
c.arg[1] = 2;
c.arg[2] = 0;
memcpy(c.d.asBytes, rats, 2);
SendCommand(&c);
WaitForResponse(CMD_ACK,&resp);
}
c.cmd = CMD_MIFARE_CIDENT;
c.arg[0] = 0;
c.arg[1] = 0;
c.arg[2] = 0;
SendCommand(&c);
WaitForResponse(CMD_ACK,&resp);
uint8_t isGeneration = resp.arg[0] & 0xff;
switch( isGeneration ){
case 1: PrintAndLog("Chinese magic backdoor commands (GEN 1a) detected"); break;
case 2: PrintAndLog("Chinese magic backdoor command (GEN 1b) detected"); break;
default: PrintAndLog("No chinese magic backdoor command detected"); break;
}
// disconnect
c.cmd = CMD_READER_ISO_14443a;
c.arg[0] = 0;
c.arg[1] = 0;
c.arg[2] = 0;
SendCommand(&c);
return (int) isGeneration;
}

View file

@ -16,12 +16,13 @@
#include "data.h" #include "data.h"
// mfCSetBlock work flags // mfCSetBlock work flags
#define CSETBLOCK_UID 0x01 #define CSETBLOCK_UID 0x01
#define CSETBLOCK_WUPC 0x02 #define CSETBLOCK_WUPC 0x02
#define CSETBLOCK_HALT 0x04 #define CSETBLOCK_HALT 0x04
#define CSETBLOCK_INIT_FIELD 0x08 #define CSETBLOCK_INIT_FIELD 0x08
#define CSETBLOCK_RESET_FIELD 0x10 #define CSETBLOCK_RESET_FIELD 0x10
#define CSETBLOCK_SINGLE_OPER 0x1F #define CSETBLOCK_SINGLE_OPER 0x1F
#define CSETBLOCK_MAGIC_1B 0x40
extern char logHexFileName[FILE_PATH_SIZE]; extern char logHexFileName[FILE_PATH_SIZE];
@ -46,4 +47,6 @@ extern int loadTraceCard(uint8_t *tuid);
extern int saveTraceCard(void); extern int saveTraceCard(void);
extern int tryDecryptWord(uint32_t nt, uint32_t ar_enc, uint32_t at_enc, uint8_t *data, int len); extern int tryDecryptWord(uint32_t nt, uint32_t ar_enc, uint32_t at_enc, uint8_t *data, int len);
extern int mfCIdentify();
#endif #endif