Esempio n. 1
0
bool RAMFUNC MfSniffLogic(const uint8_t *data, uint16_t len, uint8_t *parity, uint16_t bitCnt, bool reader) {

	if (reader && (len == 1) && (bitCnt == 7)) { 		// reset on 7-Bit commands from reader
		sniffState = SNF_INIT;
	}

	switch (sniffState) {
		case SNF_INIT:{
			if ((len == 1) && (reader) && (bitCnt == 7) ) {  // REQA or WUPA from reader
				sniffUIDType = SNF_UID_4;
				memset(sniffUID, 0x00, 8);
				memset(sniffATQA, 0x00, 2);
				sniffSAK = 0;
				sniffState = SNF_WUPREQ;
			}
			break;
		}
		case SNF_WUPREQ:{
			if ((!reader) && (len == 2)) { 		// ATQA from tag
				memcpy(sniffATQA, data, 2);
				sniffState = SNF_ATQA;
			}
			break;
		}
		case SNF_ATQA:{
			if ((reader) && (len == 2) && (data[0] == 0x93) && (data[1] == 0x20)) { // Select ALL from reader
				sniffState = SNF_ANTICOL1;
			}
			break;
		}
		case SNF_ANTICOL1:{
			if ((!reader) && (len == 5) && ((data[0] ^ data[1] ^ data[2] ^ data[3]) == data[4])) {  // UID from tag (CL1) 
				memcpy(sniffUID + 3, data, 4);
				sniffState = SNF_UID1;
			}
			break;
		}
		case SNF_UID1:{
			if ((reader) && (len == 9) && (data[0] == 0x93) && (data[1] == 0x70) && (CheckCrc14443(CRC_14443_A, data, 9))) {   // Select 4 Byte UID from reader
				sniffState = SNF_SAK;
			}
			break;
		}
		case SNF_SAK:{
			if ((!reader) && (len == 3) && (CheckCrc14443(CRC_14443_A, data, 3))) { // SAK from card?
				sniffSAK = data[0];
				if (sniffUID[3] == 0x88) {			// CL2 UID part to be expected
					sniffState = SNF_ANTICOL2;
				} else {							// select completed
					sniffState = SNF_CARD_IDLE;
				}
			}
			break;
		}
		case SNF_ANTICOL2:{
			if ((!reader) && (len == 5) && ((data[0] ^ data[1] ^ data[2] ^ data[3]) == data[4])) { // CL2 UID 
				memcpy(sniffUID, sniffUID+4, 3);
				memcpy(sniffUID+3, data, 4);
				sniffUIDType = SNF_UID_7;
				sniffState = SNF_UID2;
			}
			break;
		}
		case SNF_UID2:{
			if ((reader) && (len == 9) && (data[0] == 0x95) && (data[1] == 0x70) && (CheckCrc14443(CRC_14443_A, data, 9))) {	// Select 2nd part of 7 Byte UID
				sniffState = SNF_SAK;
			}
			break;
		}
		case SNF_CARD_IDLE:{	// trace the card select sequence
			sniffBuf[0] = 0xFF;
			sniffBuf[1] = 0xFF;
			memcpy(sniffBuf + 2, sniffUID, 7);
			memcpy(sniffBuf + 9, sniffATQA, 2);
			sniffBuf[11] = sniffSAK;
			sniffBuf[12] = 0xFF;
			sniffBuf[13] = 0xFF;
			LogTrace(sniffBuf, 14, 0, 0, NULL, TRUE);
		}	// intentionally no break;
		case SNF_CARD_CMD:{		
			LogTrace(data, len, 0, 0, NULL, TRUE);
			sniffState = SNF_CARD_RESP;
			timerData = GetTickCount();
			break;
		}
		case SNF_CARD_RESP:{
			LogTrace(data, len, 0, 0, NULL, FALSE);
			sniffState = SNF_CARD_CMD;
			timerData = GetTickCount();
			break;
		}
	
		default:
			sniffState = SNF_INIT;
		break;
	}


	return FALSE;
}
Esempio n. 2
0
int mfTraceDecode(uint8_t *data_src, int len, bool wantSaveToEmlFile) {
	uint8_t data[64];

	if (traceState == TRACE_ERROR) return 1;
	if (len > 64) {
		traceState = TRACE_ERROR;
		return 1;
	}
	
	memcpy(data, data_src, len);
	if ((traceCrypto1) && ((traceState == TRACE_IDLE) || (traceState > TRACE_AUTH_OK))) {
		mf_crypto1_decrypt(traceCrypto1, data, len, 0);
		PrintAndLog("dec> %s", sprint_hex(data, len));
		AddLogHex(logHexFileName, "dec> ", data, len); 
	}
	
	switch (traceState) {
	case TRACE_IDLE: 
		// check packet crc16!
		if ((len >= 4) && (!CheckCrc14443(CRC_14443_A, data, len))) {
			PrintAndLog("dec> CRC ERROR!!!");
			AddLogLine(logHexFileName, "dec> ", "CRC ERROR!!!"); 
			traceState = TRACE_ERROR;  // do not decrypt the next commands
			return 1;
		}
		
		// AUTHENTICATION
		if ((len == 4) && ((data[0] == 0x60) || (data[0] == 0x61))) {
			traceState = TRACE_AUTH1;
			traceCurBlock = data[1];
			traceCurKey = data[0] == 60 ? 1:0;
			return 0;
		}

		// READ
		if ((len ==4) && ((data[0] == 0x30))) {
			traceState = TRACE_READ_DATA;
			traceCurBlock = data[1];
			return 0;
		}

		// WRITE
		if ((len ==4) && ((data[0] == 0xA0))) {
			traceState = TRACE_WRITE_OK;
			traceCurBlock = data[1];
			return 0;
		}

		// HALT
		if ((len ==4) && ((data[0] == 0x50) && (data[1] == 0x00))) {
			traceState = TRACE_ERROR;  // do not decrypt the next commands
			return 0;
		}
		
		return 0;
	break;
	
	case TRACE_READ_DATA: 
		if (len == 18) {
			traceState = TRACE_IDLE;

			if (isBlockTrailer(traceCurBlock)) {
				memcpy(traceCard + traceCurBlock * 16 + 6, data + 6, 4);
			} else {
				memcpy(traceCard + traceCurBlock * 16, data, 16);
			}
			if (wantSaveToEmlFile) saveTraceCard();
			return 0;
		} else {
			traceState = TRACE_ERROR;
			return 1;
		}
	break;

	case TRACE_WRITE_OK: 
		if ((len == 1) && (data[0] == 0x0a)) {
			traceState = TRACE_WRITE_DATA;

			return 0;
		} else {
			traceState = TRACE_ERROR;
			return 1;
		}
	break;

	case TRACE_WRITE_DATA: 
		if (len == 18) {
			traceState = TRACE_IDLE;

			memcpy(traceCard + traceCurBlock * 16, data, 16);
			if (wantSaveToEmlFile) saveTraceCard();
			return 0;
		} else {
			traceState = TRACE_ERROR;
			return 1;
		}
	break;

	case TRACE_AUTH1: 
		if (len == 4) {
			traceState = TRACE_AUTH2;
			nt = bytes_to_num(data, 4);
			return 0;
		} else {
			traceState = TRACE_ERROR;
			return 1;
		}
	break;

	case TRACE_AUTH2: 
		if (len == 8) {
			traceState = TRACE_AUTH_OK;

			nr_enc = bytes_to_num(data, 4);
			ar_enc = bytes_to_num(data + 4, 4);
			return 0;
		} else {
			traceState = TRACE_ERROR;
			return 1;
		}
	break;

	case TRACE_AUTH_OK: 
		if (len ==4) {
			traceState = TRACE_IDLE;

			at_enc = bytes_to_num(data, 4);
			
			//  decode key here)
			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);
			printf("Key: %012"llx"\n",key);
			AddLogUint64(logHexFileName, "key: ", key); 
			
			int blockShift = ((traceCurBlock & 0xFC) + 3) * 16;
			if (isBlockEmpty((traceCurBlock & 0xFC) + 3)) memcpy(traceCard + blockShift + 6, trailerAccessBytes, 4);
			
			if (traceCurKey) {
				num_to_bytes(key, 6, traceCard + blockShift + 10);
			} else {
				num_to_bytes(key, 6, traceCard + blockShift);
			}
			if (wantSaveToEmlFile) saveTraceCard();

			if (traceCrypto1) {
				crypto1_destroy(traceCrypto1);
			}
			
			// set cryptosystem state
			traceCrypto1 = lfsr_recovery64(ks2, ks3);
			
//	nt = crypto1_word(traceCrypto1, nt ^ uid, 1) ^ nt;

	/*	traceCrypto1 = crypto1_create(key); // key in lfsr
		crypto1_word(traceCrypto1, nt ^ uid, 0);
		crypto1_word(traceCrypto1, ar, 1);
		crypto1_word(traceCrypto1, 0, 0);
		crypto1_word(traceCrypto1, 0, 0);*/
	
			return 0;
		} else {
			traceState = TRACE_ERROR;
			return 1;
		}
	break;

	default: 
		traceState = TRACE_ERROR;
		return 1;
	}

	return 0;
}