CHG: 'hf 14a antifuzz' - original implementation by @asfabw, reworked a bit - WORK IN PROGRESS -

This commit is contained in:
iceman1001 2019-01-07 09:32:16 +01:00
commit 3ae871f534
3 changed files with 92 additions and 85 deletions

View file

@ -14,7 +14,10 @@
#define MAX_ISO14A_TIMEOUT 524288 #define MAX_ISO14A_TIMEOUT 524288
static uint32_t iso14a_timeout; static uint32_t iso14a_timeout;
uint8_t colpos = 0;
int rsamples = 0; int rsamples = 0;
//int ReqCount;
//char CollisionIndicators[10*8];
uint8_t trigger = 0; uint8_t trigger = 0;
// the block number for the ISO14443-4 PCB // the block number for the ISO14443-4 PCB
@ -103,6 +106,8 @@ static uint32_t LastProxToAirDuration;
// Sequence D: 11110000 modulation with subcarrier during first half // Sequence D: 11110000 modulation with subcarrier during first half
// Sequence E: 00001111 modulation with subcarrier during second half // Sequence E: 00001111 modulation with subcarrier during second half
// Sequence F: 00000000 no modulation with subcarrier // Sequence F: 00000000 no modulation with subcarrier
// Sequence COLL: 11111111 load modulation over the full bitlenght.
// Tricks the reader to think that multiple cards answer (at least one card with 1 and at least one card with 0).
// READER TO CARD - miller // READER TO CARD - miller
// Sequence X: 00001100 drop after half a period // Sequence X: 00001100 drop after half a period
// Sequence Y: 00000000 no drop // Sequence Y: 00000000 no drop
@ -110,6 +115,7 @@ static uint32_t LastProxToAirDuration;
#define SEC_D 0xf0 #define SEC_D 0xf0
#define SEC_E 0x0f #define SEC_E 0x0f
#define SEC_F 0x00 #define SEC_F 0x00
#define SEC_COLL 0xff
#define SEC_X 0x0c #define SEC_X 0x0c
#define SEC_Y 0x00 #define SEC_Y 0x00
#define SEC_Z 0xc0 #define SEC_Z 0xc0
@ -643,7 +649,9 @@ void RAMFUNC SniffIso14443a(uint8_t param) {
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Prepare tag messages // Prepare tag messages
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
static void CodeIso14443aAsTagPar(const uint8_t *cmd, uint16_t len, uint8_t *parity) { static void CodeIso14443aAsTagPar(const uint8_t *cmd, uint16_t len, uint8_t *parity, bool collision) {
uint8_t localCol = 0;
ToSendReset(); ToSendReset();
// Correction bit, might be removed when not needed // Correction bit, might be removed when not needed
@ -651,7 +659,7 @@ static void CodeIso14443aAsTagPar(const uint8_t *cmd, uint16_t len, uint8_t *par
ToSendStuffBit(0); ToSendStuffBit(0);
ToSendStuffBit(0); ToSendStuffBit(0);
ToSendStuffBit(0); ToSendStuffBit(0);
ToSendStuffBit(1); // 1 ToSendStuffBit(1); // <-----
ToSendStuffBit(0); ToSendStuffBit(0);
ToSendStuffBit(0); ToSendStuffBit(0);
ToSendStuffBit(0); ToSendStuffBit(0);
@ -665,12 +673,15 @@ static void CodeIso14443aAsTagPar(const uint8_t *cmd, uint16_t len, uint8_t *par
// Data bits // Data bits
for(uint16_t j = 0; j < 8; j++) { for(uint16_t j = 0; j < 8; j++) {
if(b & 1) { if (collision && (localCol >= colpos)){
ToSend[++ToSendMax] = SEC_COLL;
} else if(b & 1) {
ToSend[++ToSendMax] = SEC_D; ToSend[++ToSendMax] = SEC_D;
} else { } else {
ToSend[++ToSendMax] = SEC_E; ToSend[++ToSendMax] = SEC_E;
} }
b >>= 1; b >>= 1;
localCol++;
} }
// Get the parity bit // Get the parity bit
@ -690,10 +701,13 @@ static void CodeIso14443aAsTagPar(const uint8_t *cmd, uint16_t len, uint8_t *par
ToSendMax++; ToSendMax++;
} }
static void CodeIso14443aAsTag(const uint8_t *cmd, uint16_t len) { static void CodeIso14443aAsTagEx(const uint8_t *cmd, uint16_t len, bool collision) {
uint8_t par[MAX_PARITY_SIZE] = {0}; uint8_t par[MAX_PARITY_SIZE] = {0};
GetParity(cmd, len, par); GetParity(cmd, len, par);
CodeIso14443aAsTagPar(cmd, len, par); CodeIso14443aAsTagPar(cmd, len, par, collision);
}
static void CodeIso14443aAsTag(const uint8_t *cmd, uint16_t len) {
CodeIso14443aAsTagEx(cmd, len, false);
} }
static void Code4bitAnswerAsTag(uint8_t cmd) { static void Code4bitAnswerAsTag(uint8_t cmd) {
@ -1680,9 +1694,11 @@ int EmSend4bit(uint8_t resp){
par); par);
return res; return res;
} }
int EmSendCmdPar(uint8_t *resp, uint16_t respLen, uint8_t *par) {
int EmSendCmdPar(uint8_t *resp, uint16_t respLen, uint8_t *par){ return EmSendCmdParEx(resp, respLen, par, false);
CodeIso14443aAsTagPar(resp, respLen, par); }
int EmSendCmdParEx(uint8_t *resp, uint16_t respLen, uint8_t *par, bool collision){
CodeIso14443aAsTagPar(resp, respLen, par, collision);
int res = EmSendCmd14443aRaw(ToSend, ToSendMax); int res = EmSendCmd14443aRaw(ToSend, ToSendMax);
// do the tracing for the previous reader request and this tag answer: // do the tracing for the previous reader request and this tag answer:
EmLogTrace(Uart.output, EmLogTrace(Uart.output,
@ -1697,11 +1713,13 @@ int EmSendCmdPar(uint8_t *resp, uint16_t respLen, uint8_t *par){
par); par);
return res; return res;
} }
int EmSendCmd(uint8_t *resp, uint16_t respLen){ int EmSendCmd(uint8_t *resp, uint16_t respLen){
return EmSendCmdEx(resp, respLen, false);
}
int EmSendCmdEx(uint8_t *resp, uint16_t respLen, bool collision){
uint8_t par[MAX_PARITY_SIZE] = {0x00}; uint8_t par[MAX_PARITY_SIZE] = {0x00};
GetParity(resp, respLen, par); GetParity(resp, respLen, par);
return EmSendCmdPar(resp, respLen, par); return EmSendCmdParEx(resp, respLen, par, collision);
} }
bool EmLogTrace(uint8_t *reader_data, uint16_t reader_len, uint32_t reader_StartTime, uint32_t reader_EndTime, uint8_t *reader_Parity, bool EmLogTrace(uint8_t *reader_data, uint16_t reader_len, uint32_t reader_StartTime, uint32_t reader_EndTime, uint8_t *reader_Parity,
@ -1805,45 +1823,21 @@ int ReaderReceive(uint8_t *receivedAnswer, uint8_t *parity) {
// by fooling the reader there is a collision and forceing the reader to // by fooling the reader there is a collision and forceing the reader to
// increase the uid bytes. The might be an overflow, DoS will occure. // increase the uid bytes. The might be an overflow, DoS will occure.
void iso14443a_antifuzz(uint32_t flags){ void iso14443a_antifuzz(uint32_t flags){
/*
uint8_t uidlen = 4+1+1+2;
if (( flags & 2 ) == 2 )
uidlen = 7+1+1+2;
if (( flags & 4 ) == 4 )
uidlen = 10+1+1+2;
uint8_t *uid = BigBuf_malloc(uidlen);
// The first response contains the ATQA (note: bytes are transmitted in reverse order).
// Mifare Classic 1K
uint8_t atqa[] = {0x04, 0};
if ( (flags & 2) == 2 ) {
uid[0] = 0x88; // Cascade Tag marker
uid[1] = 0x01;
// Configure the ATQA accordingly
atqa[0] |= 0x40;
} else {
memcpy(response2, data, 4);
// Configure the ATQA accordingly
atqa[0] &= 0xBF;
}
// We need to listen to the high-frequency, peak-detected path. // We need to listen to the high-frequency, peak-detected path.
iso14443a_setup(FPGA_HF_ISO14443A_TAGSIM_LISTEN); iso14443a_setup(FPGA_HF_ISO14443A_TAGSIM_LISTEN);
// allocate buffers: BigBuf_free_keep_EM();
uint8_t *received = BigBuf_malloc(MAX_FRAME_SIZE);
uint8_t *receivedPar = BigBuf_malloc(MAX_PARITY_SIZE);
uint16_t counter = 0;
int len = 0;
BigBuf_free();
clear_trace(); clear_trace();
set_tracing(true); set_tracing(true);
int len = 0;
// allocate buffers:
uint8_t *received = BigBuf_malloc(MAX_FRAME_SIZE);
uint8_t *receivedPar = BigBuf_malloc(MAX_PARITY_SIZE);
uint8_t *resp = BigBuf_malloc(8);
LED_A_ON(); LED_A_ON();
for (;;) { for (;;) {
WDT_HIT(); WDT_HIT();
@ -1853,47 +1847,47 @@ void iso14443a_antifuzz(uint32_t flags){
Dbprintf("Anti-fuzz stopped. Tracing: %d trace length: %d ", tracing, BigBuf_get_traceLen()); Dbprintf("Anti-fuzz stopped. Tracing: %d trace length: %d ", tracing, BigBuf_get_traceLen());
break; break;
} }
p_response = NULL; if ( received[0] == ISO14443A_CMD_WUPA || received[0] == ISO14443A_CMD_REQA) {
resp[0] = 0x04;
resp[1] = 0x00;
if ( (flags & FLAG_7B_UID_IN_DATA) == FLAG_7B_UID_IN_DATA ) {
resp[0] = 0x44;
}
EmSendCmd(resp, 2);
continue;
}
// look at the command now. // Received request for UID (cascade 1)
if (received[0] == ISO14443A_CMD_REQA) { // Received a REQUEST if (received[1] >= 0x20 && received[1] <= 0x57 && received[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT) {
p_response = &responses[0]; resp[0] = 0x04;
} else if (received[0] == ISO14443A_CMD_WUPA) { // Received a WAKEUP resp[1] = 0x1C;
p_response = &responses[0]; resp[2] = 0xE1;
} else if (received[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT) { // Received request for UID (cascade 1) resp[3] = 0xCE;
p_response = &responses[1]; colpos = 0;
} else if (received[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_2) { // Received request for UID (cascade 2)
p_response = &responses[2];
} else if (received[1] == 0x70 && received[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT) { // Received a SELECT (cascade 1)
p_response = &responses[3];
} else if (received[1] == 0x70 && received[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_2) { // Received a SELECT (cascade 2)
p_response = &responses[4];
}
if (p_response != NULL) {
EmSendCmd14443aRaw(p_response->modulation, p_response->modulation_n); if ( (flags & FLAG_7B_UID_IN_DATA) == FLAG_7B_UID_IN_DATA ) {
// do the tracing for the previous reader request and this tag answer: resp[0] = 0x88;
uint8_t par[MAX_PARITY_SIZE] = {0x00}; colpos = 8;
GetParity(p_response->response, p_response->response_n, par); }
EmLogTrace(Uart.output, EmSendCmdEx(resp, 4, true);
Uart.len, if (MF_DBGLEVEL >= 4) Dbprintf("ANTICOLL or SELECT %x", received[1]);
Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG,
Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, continue;
Uart.parity, } else if (received[1] == 0x20 && received[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_2) { // Received request for UID (cascade 2)
p_response->response, if (MF_DBGLEVEL >= 4) Dbprintf("ANTICOLL or SELECT_2");
p_response->response_n, } else if (received[1] == 0x70 && received[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT) { // Received a SELECT (cascade 1)
LastTimeProxToAirStart*16 + DELAY_ARM2AIR_AS_TAG, } else if (received[1] == 0x70 && received[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_2) { // Received a SELECT (cascade 2)
(LastTimeProxToAirStart + p_response->ProxToAirDuration)*16 + DELAY_ARM2AIR_AS_TAG, } else {
par); Dbprintf("unknown command %x", received[0]);
} }
counter++;
} }
cmd_send(CMD_ACK,1,0,0,0,0); cmd_send(CMD_ACK,1,0,0,0,0);
switch_off(); switch_off();
Dbprintf("-[ UID until no response [%d]", counter); BigBuf_free_keep_EM();
*/
} }
static void iso14a_set_ATS_times(uint8_t *ats) { static void iso14a_set_ATS_times(uint8_t *ats) {

View file

@ -122,8 +122,10 @@ extern void iso14a_set_trigger(bool enable);
extern int EmSendCmd14443aRaw(uint8_t *resp, uint16_t respLen); extern int EmSendCmd14443aRaw(uint8_t *resp, uint16_t respLen);
extern int EmSend4bit(uint8_t resp); extern int EmSend4bit(uint8_t resp);
extern int EmSendCmd(uint8_t *resp, uint16_t respLen); extern int EmSendCmd(uint8_t *resp, uint16_t respLen);
extern int EmSendCmdEx(uint8_t *resp, uint16_t respLen, bool collision);
extern int EmGetCmd(uint8_t *received, uint16_t *len, uint8_t *parity); extern int EmGetCmd(uint8_t *received, uint16_t *len, uint8_t *parity);
extern int EmSendCmdPar(uint8_t *resp, uint16_t respLen, uint8_t *par); extern int EmSendCmdPar(uint8_t *resp, uint16_t respLen, uint8_t *par);
extern int EmSendCmdParEx(uint8_t *resp, uint16_t respLen, uint8_t *par, bool collision);
extern int EmSendPrecompiledCmd(tag_response_info_t *response_info); extern int EmSendPrecompiledCmd(tag_response_info_t *response_info);
bool EmLogTrace(uint8_t *reader_data, uint16_t reader_len, uint32_t reader_StartTime, uint32_t reader_EndTime, uint8_t *reader_Parity, bool EmLogTrace(uint8_t *reader_data, uint16_t reader_len, uint32_t reader_StartTime, uint32_t reader_EndTime, uint8_t *reader_Parity,

View file

@ -213,11 +213,6 @@ int usage_hf_14a_info(void){
PrintAndLogEx(NORMAL, " n test for nack bug"); PrintAndLogEx(NORMAL, " n test for nack bug");
return 0; return 0;
} }
int usage_hf_14a_antifuzz(void) {
PrintAndLogEx(NORMAL, "Usage: hf 14a antifuzz [4|7|10]");
PrintAndLogEx(NORMAL, " <len> determine which anticollision phase the command will target.");
return 0;
}
int CmdHF14AList(const char *Cmd) { int CmdHF14AList(const char *Cmd) {
//PrintAndLogEx(NORMAL, "Deprecated command, use 'hf list 14a' instead"); //PrintAndLogEx(NORMAL, "Deprecated command, use 'hf list 14a' instead");
@ -1183,11 +1178,27 @@ static int waitCmd(uint8_t iSelect) {
int CmdHF14AAntiFuzz(const char *cmd) { int CmdHF14AAntiFuzz(const char *cmd) {
if (strlen(cmd) < 1) return usage_hf_14a_antifuzz(); CLIParserInit("hf 14a antifuzz",
"Tries to fuzz the ISO14443a anticollision phase",
"Usage:\n"
"\thf 14a antifuzz -4\n");
// read param length void* argtable[] = {
uint8_t arg0 = 4; arg_param_begin,
arg_lit0("4", NULL, "4 byte uid"),
arg_lit0("7", NULL, "7 byte uid"),
arg_lit0(NULL, "10", "10 byte uid"),
arg_param_end
};
CLIExecWithReturn(cmd, argtable, false);
uint8_t arg0 = FLAG_4B_UID_IN_DATA;
if (arg_get_lit(2))
arg0 = FLAG_7B_UID_IN_DATA;
if (arg_get_lit(3))
arg0 = FLAG_10B_UID_IN_DATA;
CLIParserFree();
UsbCommand c = {CMD_ANTIFUZZ_ISO_14443a, {arg0, 0, 0}}; UsbCommand c = {CMD_ANTIFUZZ_ISO_14443a, {arg0, 0, 0}};
clearCommandBuffer(); clearCommandBuffer();
SendCommand(&c); SendCommand(&c);