Merge pull request #51 from RfidResearchGroup/master

Update
This commit is contained in:
mwalker33 2020-10-03 18:50:16 +10:00 committed by GitHub
commit 9b7dd1cc4f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
26 changed files with 13131 additions and 459 deletions

View file

@ -3,6 +3,8 @@ All notable changes to this project will be documented in this file.
This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log...
## [unreleased][unreleased]
- Add low level support for 14b' aka Innovatron (@doegox)
- Add doc/cliparser.md (@mwalker33)
- Add `hf 14b apdu` - send APDU over ISO14443B (@iceman1001)
- Add `lf t55xx chk e <EM4100> option` - Checks calculated password based on the EM4100 id from some white cloners forumla by paleopterix (@mwalker33)
- Add `lf t55xx sniff` to allow extracting commands and passwords used be cloners. (@mwalker33)

View file

@ -34,7 +34,7 @@
|[Notes on file formats used with Proxmark3](/doc/extensions_notes.md)|[Notes on MFU binary format](/doc/mfu_binary_format_notes.md)|[Notes on FPGA & ARM](/doc/fpga_arm_notes.md)|
|[Developing standalone mode](/armsrc/Standalone/readme.md)|[Wiki about standalone mode](https://github.com/RfidResearchGroup/proxmark3/wiki/Standalone-mode)|[Notes on Magic cards](/doc/magic_cards_notes.md)|
|[Notes on Color usage](/doc/colors_notes.md)|[Makefile vs CMake](/doc/md/Development/Makefile-vs-CMake.md)|[Notes on Cloner guns](/doc/cloner_notes.md)|
|[Notes on cliparser usage](/doc/cliparser.md)|||
## Build for non-RDV4 Proxmark3 platforms

View file

@ -1126,11 +1126,10 @@ static void PacketReceived(PacketCommandNG *packet) {
break;
}
case CMD_HF_ISO14443B_SIMULATE: {
SimulateIso14443bTag(packet->oldarg[0]);
SimulateIso14443bTag(packet->data.asBytes);
break;
}
case CMD_HF_ISO14443B_COMMAND: {
//SendRawCommand14443B(packet->oldarg[0],packet->oldarg[1],packet->oldarg[2],packet->data.asBytes);
SendRawCommand14443B_Ex(packet);
break;
}

View file

@ -9,7 +9,7 @@
#include "commonutil.h"
#include "dbprint.h"
#include "ticks.h"
#include "mifare.h"
#include "iso18.h"
// FeliCa timings
// minimum time between the start bits of consecutive transfers from reader to tag: 6800 carrier (13.56MHz) cycles

View file

@ -274,8 +274,7 @@ static struct {
enum {
DEMOD_UNSYNCD,
DEMOD_PHASE_REF_TRAINING,
DEMOD_AWAITING_FALLING_EDGE_OF_SOF,
DEMOD_GOT_FALLING_EDGE_OF_SOF,
WAIT_FOR_RISING_EDGE_OF_SOF,
DEMOD_AWAITING_START_BIT,
DEMOD_RECEIVING_DATA
} state;
@ -531,7 +530,7 @@ static void TransmitFor14443b_AsTag(uint8_t *response, uint16_t len) {
// Main loop of simulated tag: receive commands from reader, decide what
// response to send, and send it.
//-----------------------------------------------------------------------------
void SimulateIso14443bTag(uint32_t pupi) {
void SimulateIso14443bTag(uint8_t *pupi) {
LED_A_ON();
// the only commands we understand is WUPB, AFI=0, Select All, N=1:
@ -554,15 +553,15 @@ void SimulateIso14443bTag(uint32_t pupi) {
0x5e, 0xd7
};
// response to HLTB and ATTRIB
static const uint8_t respOK[] = {0x00, 0x78, 0xF0};
// ...PUPI/UID supplied from user. Adjust ATQB response accordingly
if (pupi > 0) {
num_to_bytes(pupi, 4, respATQB + 1);
if (memcmp("\x00\x00\x00\x00", pupi, 4) != 0) {
memcpy(respATQB + 1, pupi, 4);
AddCrc14B(respATQB, 12);
}
// response to HLTB and ATTRIB
static const uint8_t respOK[] = {0x00, 0x78, 0xF0};
// setup device.
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
@ -724,6 +723,13 @@ void SimulateIso14443bTag(uint32_t pupi) {
// tag's response, which we leave in the buffer to be demodulated on the
// PC side.
//=============================================================================
// We support both 14b framing and 14b' framing.
// 14b framing looks like:
// xxxxxxxx1111111111111111-000000000011-0........1-0........1-0........1-1-0........1-0........1-1000000000011xxxxxx
// TR1 SOF 10*0+2*1 start-stop ^^^^^^^^byte ^ occasional stuff bit EOF 10*0+N*1
// 14b' framing looks like:
// xxxxxxxxxxxxxxxx111111111111111111111-0........1-0........1-0........1-1-0........1-0........1-000000000000xxxxxxx
// SOF? start-stop ^^^^^^^^byte ^ occasional stuff bit EOF
/*
* Handles reception of a bit from the tag
@ -774,57 +780,33 @@ static RAMFUNC int Handle14443bSamplesFromTag(int ci, int cq) {
break;
}
case DEMOD_PHASE_REF_TRAINING: {
if (Demod.posCount < 8) {
if (AMPLITUDE(ci, cq) > SUBCARRIER_DETECT_THRESHOLD) {
// set the reference phase (will code a logic '1') by averaging over 32 1/fs.
// note: synchronization time > 80 1/fs
Demod.sumI += ci;
Demod.sumQ += cq;
Demod.posCount++;
// While we get a constant signal
if (AMPLITUDE(ci, cq) > SUBCARRIER_DETECT_THRESHOLD) {
if (((ABS(Demod.sumI) > ABS(Demod.sumQ)) && (((ci > 0) && (Demod.sumI > 0)) || ((ci < 0) && (Demod.sumI < 0)))) || // signal closer to horizontal, polarity check based on on I
((ABS(Demod.sumI) <= ABS(Demod.sumQ)) && (((cq > 0) && (Demod.sumQ > 0)) || ((cq < 0) && (Demod.sumQ < 0))))) { // signal closer to vertical, polarity check based on on Q
if (Demod.posCount < 10) { // refine signal approximation during first 10 samples
Demod.sumI += ci;
Demod.sumQ += cq;
}
Demod.posCount += 1;
} else {
// subcarrier lost
Demod.state = DEMOD_UNSYNCD;
// transition
if (Demod.posCount < 10) {
// subcarrier lost
Demod.state = DEMOD_UNSYNCD;
break;
} else {
// at this point it can be start of 14b' data or start of 14b SOF
MAKE_SOFT_DECISION();
Demod.posCount = 1; // this was the first half
Demod.thisBit = v;
Demod.shiftReg = 0;
Demod.state = DEMOD_RECEIVING_DATA;
}
}
} else {
Demod.state = DEMOD_AWAITING_FALLING_EDGE_OF_SOF;
}
break;
}
case DEMOD_AWAITING_FALLING_EDGE_OF_SOF: {
MAKE_SOFT_DECISION();
if (v < 0) { // logic '0' detected
Demod.state = DEMOD_GOT_FALLING_EDGE_OF_SOF;
Demod.posCount = 0; // start of SOF sequence
} else {
if (Demod.posCount > 200/4) { // maximum length of TR1 = 200 1/fs
Demod.state = DEMOD_UNSYNCD;
}
}
Demod.posCount++;
break;
}
case DEMOD_GOT_FALLING_EDGE_OF_SOF: {
Demod.posCount++;
MAKE_SOFT_DECISION();
if (v > 0) {
if (Demod.posCount < 9 * 2) { // low phase of SOF too short (< 9 etu). Note: spec is >= 10, but FPGA tends to "smear" edges
Demod.state = DEMOD_UNSYNCD;
} else {
LED_C_ON(); // Got SOF
Demod.posCount = 0;
Demod.bitCount = 0;
Demod.len = 0;
Demod.state = DEMOD_AWAITING_START_BIT;
}
} else {
if (Demod.posCount > 12 * 2) { // low phase of SOF too long (> 12 etu)
Demod.state = DEMOD_UNSYNCD;
LED_C_OFF();
}
// subcarrier lost
Demod.state = DEMOD_UNSYNCD;
}
break;
}
@ -848,6 +830,28 @@ static RAMFUNC int Handle14443bSamplesFromTag(int ci, int cq) {
}
break;
}
case WAIT_FOR_RISING_EDGE_OF_SOF: {
Demod.posCount++;
MAKE_SOFT_DECISION();
if (v > 0) {
if (Demod.posCount < 9 * 2) { // low phase of SOF too short (< 9 etu). Note: spec is >= 10, but FPGA tends to "smear" edges
Demod.state = DEMOD_UNSYNCD;
} else {
LED_C_ON(); // Got SOF
Demod.posCount = 0;
Demod.bitCount = 0;
Demod.len = 0;
Demod.state = DEMOD_AWAITING_START_BIT;
}
} else {
if (Demod.posCount > 12 * 2) { // low phase of SOF too long (> 12 etu)
Demod.state = DEMOD_UNSYNCD;
LED_C_OFF();
}
}
break;
}
case DEMOD_RECEIVING_DATA: {
MAKE_SOFT_DECISION();
@ -874,12 +878,35 @@ static RAMFUNC int Handle14443bSamplesFromTag(int ci, int cq) {
Demod.bitCount = 0;
Demod.state = DEMOD_AWAITING_START_BIT;
} else {
Demod.state = DEMOD_AWAITING_FALLING_EDGE_OF_SOF;
LED_C_OFF();
if (s == 0x000) {
// This is EOF (start, stop and all data bits == '0'
return true;
if (Demod.len > 0) {
LED_C_OFF();
// This is EOF (start, stop and all data bits == '0'
return true;
} else {
// Zeroes but no data acquired yet?
// => Still in SOF of 14b, wait for raising edge
Demod.posCount = 10 * 2;
Demod.bitCount = 0;
Demod.len = 0;
Demod.state = WAIT_FOR_RISING_EDGE_OF_SOF;
break;
}
}
if (AMPLITUDE(ci, cq) < SUBCARRIER_DETECT_THRESHOLD) {
LED_C_OFF();
// subcarrier lost
Demod.state = DEMOD_UNSYNCD;
if (Demod.len > 0) { // no EOF but no signal anymore and we got data, e.g. ASK CTx
return true;
}
}
// we have still signal but no proper byte or EOF? this shouldn't happen
//Demod.posCount = 10 * 2;
Demod.bitCount = 0;
Demod.len = 0;
Demod.state = WAIT_FOR_RISING_EDGE_OF_SOF;
break;
}
}
Demod.posCount = 0;
@ -1230,6 +1257,79 @@ int iso14443b_apdu(uint8_t const *msg, size_t msg_len, bool send_chaining, uint8
return len;
}
/**
* ASK CTS initialise.
*/
static int iso14443b_select_cts_card(iso14b_cts_card_select_t *card) {
// INITIATE command: wake up the tag using the INITIATE
uint8_t cmdINIT[] = {ASK_REQT, 0xF9, 0xE0};
uint8_t cmdMSBUID[] = {ASK_SELECT, 0xFF, 0xFF, 0x00, 0x00};
uint8_t cmdLSBUID[] = {0xC4, 0x00, 0x00};
AddCrc14B(cmdMSBUID, 3);
AddCrc14B(cmdLSBUID, 1);
uint8_t r[8];
uint32_t start_time = 0;
uint32_t eof_time = 0;
CodeAndTransmit14443bAsReader(cmdINIT, sizeof(cmdINIT), &start_time, &eof_time);
eof_time += DELAY_ISO14443B_VCD_TO_VICC_READER;
int retlen = Get14443bAnswerFromTag(r, sizeof(r), ISO14443B_READER_TIMEOUT, &eof_time);
FpgaDisableTracing();
if (retlen != 4) {
return -1;
}
if (check_crc(CRC_14443_B, r, retlen) == false) {
return -2;
}
if (card) {
// pc. fc Product code, Facility code
card->pc = r[0];
card->fc = r[1];
}
start_time = eof_time + DELAY_ISO14443B_VICC_TO_VCD_READER;
CodeAndTransmit14443bAsReader(cmdMSBUID, sizeof(cmdMSBUID), &start_time, &eof_time);
eof_time += DELAY_ISO14443B_VCD_TO_VICC_READER;
retlen = Get14443bAnswerFromTag(r, sizeof(r), ISO14443B_READER_TIMEOUT, &eof_time);
FpgaDisableTracing();
if (retlen != 4) {
return -1;
}
if (check_crc(CRC_14443_B, r, retlen) == false) {
return -2;
}
if (card) {
memcpy(card->uid, r, 2);
}
start_time = eof_time + DELAY_ISO14443B_VICC_TO_VCD_READER;
CodeAndTransmit14443bAsReader(cmdLSBUID, sizeof(cmdLSBUID), &start_time, &eof_time);
eof_time += DELAY_ISO14443B_VCD_TO_VICC_READER;
retlen = Get14443bAnswerFromTag(r, sizeof(r), ISO14443B_READER_TIMEOUT, &eof_time);
FpgaDisableTracing();
if (retlen != 4) {
return -1;
}
if (check_crc(CRC_14443_B, r, retlen) == false) {
return -2;
}
if (card) {
memcpy(card->uid + 2, r, 2);
}
return 0;
}
/**
* SRx Initialise.
*/
@ -1248,8 +1348,9 @@ static int iso14443b_select_srx_card(iso14b_card_select_t *card) {
int retlen = Get14443bAnswerFromTag(r_init, sizeof(r_init), ISO14443B_READER_TIMEOUT, &eof_time);
FpgaDisableTracing();
if (retlen <= 0)
if (retlen <= 0) {
return -1;
}
// Randomly generated Chip ID
if (card) {
@ -1272,8 +1373,6 @@ static int iso14443b_select_srx_card(iso14b_card_select_t *card) {
if (retlen != 3) {
return -1;
}
// Check the CRC of the answer:
if (!check_crc(CRC_14443_B, r_select, retlen)) {
return -2;
}
@ -1298,8 +1397,6 @@ static int iso14443b_select_srx_card(iso14b_card_select_t *card) {
if (retlen != 10) {
return -1;
}
// The check the CRC of the answer
if (!check_crc(CRC_14443_B, r_papid, retlen)) {
return -2;
}
@ -1692,7 +1789,7 @@ void SniffIso14443b(void) {
expect_tag_answer = false;
tag_is_active = false;
} else {
tag_is_active = (Demod.state > DEMOD_GOT_FALLING_EDGE_OF_SOF);
tag_is_active = (Demod.state > WAIT_FOR_RISING_EDGE_OF_SOF);
}
}
}
@ -1770,6 +1867,15 @@ void SendRawCommand14443B_Ex(PacketCommandNG *c) {
if (status > 0) goto out;
}
if ((param & ISO14B_SELECT_CTS) == ISO14B_SELECT_CTS) {
iso14b_cts_card_select_t cts;
sendlen = sizeof(iso14b_cts_card_select_t);
status = iso14443b_select_cts_card(&cts);
reply_mix(CMD_HF_ISO14443B_COMMAND, status, sendlen, 0, (uint8_t *)&cts, sendlen);
// 0: OK 2: demod fail, 3:crc fail,
if (status > 0) goto out;
}
if ((param & ISO14B_APDU) == ISO14B_APDU) {
status = iso14443b_apdu(cmd, len, (param & ISO14B_SEND_CHAINING), buf, sizeof(buf));
sendlen = MIN(Demod.len, PM3_CMD_DATA_SIZE);

View file

@ -15,7 +15,7 @@
#include "common.h"
#include "mifare.h"
#include "iso14b.h"
#include "pm3_cmd.h"
#ifndef AddCrc14A
@ -32,7 +32,7 @@ int iso14443b_apdu(uint8_t const *msg, size_t msg_len, bool send_chaining, uint8
int iso14443b_select_card(iso14b_card_select_t *card);
int iso14443b_select_card_srx(iso14b_card_select_t *card);
void SimulateIso14443bTag(uint32_t pupi);
void SimulateIso14443bTag(uint8_t *pupi);
void AcquireRawAdcSamplesIso14443b(uint32_t parameter);
void ReadSTMemoryIso14443b(uint16_t numofblocks);
void SniffIso14443b(void);

View file

@ -236,8 +236,8 @@ static int usage_hf_14a_sim(void) {
return PM3_SUCCESS;
}
static int usage_hf_14a_sniff(void) {
PrintAndLogEx(NORMAL, "It get data from the field and saves it into command buffer.");
PrintAndLogEx(NORMAL, "Buffer accessible from command 'hf list 14a'");
PrintAndLogEx(NORMAL, "Collect data from the field and save into command buffer.");
PrintAndLogEx(NORMAL, "Buffer accessible from command 'hf 14a list'");
PrintAndLogEx(NORMAL, "Usage: hf 14a sniff [c][r]");
PrintAndLogEx(NORMAL, "c - triggered by first data from card");
PrintAndLogEx(NORMAL, "r - triggered by first 7-bit request from reader (REQ,WUP,...)");

View file

@ -11,6 +11,7 @@
#include "cmdhf14b.h"
#include <ctype.h>
#include "iso14b.h"
#include "fileutils.h"
#include "cmdparser.h" // command_t
#include "commonutil.h" // ARRAYLEN
@ -33,69 +34,6 @@ bool apdu_in_framing_enable = true;
static int CmdHelp(const char *Cmd);
static int usage_hf_14b_info(void) {
PrintAndLogEx(NORMAL, "Usage: hf 14b info [h] [s]");
PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " h this help");
PrintAndLogEx(NORMAL, " s silently");
PrintAndLogEx(NORMAL, "Example:");
PrintAndLogEx(NORMAL, _YELLOW_(" hf 14b info"));
return PM3_SUCCESS;
}
static int usage_hf_14b_reader(void) {
PrintAndLogEx(NORMAL, "Usage: hf 14b reader [h] [s]");
PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " h this help");
PrintAndLogEx(NORMAL, " s silently");
PrintAndLogEx(NORMAL, "Example:");
PrintAndLogEx(NORMAL, _YELLOW_(" hf 14b reader"));
return PM3_SUCCESS;
}
static int usage_hf_14b_raw(void) {
PrintAndLogEx(NORMAL, "Usage: hf 14b raw [-h] [-r] [-c] [-k] [-s / -ss] [-t] <0A 0B 0C ... hex>");
PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " -h this help");
PrintAndLogEx(NORMAL, " -r do not read response");
PrintAndLogEx(NORMAL, " -c calculate and append CRC");
PrintAndLogEx(NORMAL, " -k keep signal field ON after receive");
PrintAndLogEx(NORMAL, " -s active signal field ON with select");
PrintAndLogEx(NORMAL, " -ss active signal field ON with select for SRx ST Microelectronics tags");
PrintAndLogEx(NORMAL, " -t timeout in ms");
PrintAndLogEx(NORMAL, "Example:");
PrintAndLogEx(NORMAL, _YELLOW_(" hf 14b raw -s -c -k 0200a40400"));
return PM3_SUCCESS;
}
static int usage_hf_14b_sniff(void) {
PrintAndLogEx(NORMAL, "It get data from the field and saves it into command buffer.");
PrintAndLogEx(NORMAL, "Buffer accessible from command 'hf list 14b'");
PrintAndLogEx(NORMAL, "Usage: hf 14b sniff [h]");
PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " h this help");
PrintAndLogEx(NORMAL, "Example:");
PrintAndLogEx(NORMAL, _YELLOW_(" hf 14b sniff"));
return PM3_SUCCESS;
}
static int usage_hf_14b_sim(void) {
PrintAndLogEx(NORMAL, "Emulating ISO/IEC 14443 type B tag with 4 UID / PUPI");
PrintAndLogEx(NORMAL, "Usage: hf 14b sim [h] u <uid>");
PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " h this help");
PrintAndLogEx(NORMAL, " u 4byte UID/PUPI");
PrintAndLogEx(NORMAL, "Example:");
PrintAndLogEx(NORMAL, _YELLOW_(" hf 14b sim"));
PrintAndLogEx(NORMAL, _YELLOW_(" hf 14b sim u 11223344"));
return PM3_SUCCESS;
}
static int usage_hf_14b_read_srx(void) {
PrintAndLogEx(NORMAL, "Usage: hf 14b sriread [h] <1|2>");
PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " h this help");
PrintAndLogEx(NORMAL, " <1|2> 1 = SRIX4K , 2 = SRI512");
PrintAndLogEx(NORMAL, "Example:");
PrintAndLogEx(NORMAL, _YELLOW_(" hf 14b sriread 1"));
PrintAndLogEx(NORMAL, _YELLOW_(" hf 14b sriread 2"));
return PM3_SUCCESS;
}
static int usage_hf_14b_write_srx(void) {
PrintAndLogEx(NORMAL, "Usage: hf 14b [h] sriwrite <1|2> <block> <data>");
PrintAndLogEx(NORMAL, "Options:");
@ -110,21 +48,6 @@ static int usage_hf_14b_write_srx(void) {
PrintAndLogEx(NORMAL, _YELLOW_(" hf 14b sriwrite 2 FF 11223344"));
return PM3_SUCCESS;
}
static int usage_hf_14b_dump(void) {
PrintAndLogEx(NORMAL, "This command dumps the contents of a ISO-14443-B tag and save it to file\n"
"If memory size defaults to SRI4K if auto detect fails.\n"
"\n"
"Usage: hf 14b dump [h] <f filename> \n"
"Options:\n"
"\th this help\n"
"\tf <name> (optional) filename, if no <name> UID will be used as filename\n"
"\n"
"Example:\n"
_YELLOW_("\thf 14b dump\n")
_YELLOW_("\thf 14b dump f mydump")
);
return PM3_SUCCESS;
}
static int switch_off_field_14b(void) {
clearCommandBuffer();
@ -140,7 +63,7 @@ static uint16_t get_sw(uint8_t *d, uint8_t n) {
return d[n] * 0x0100 + d[n + 1];
}
static bool waitCmd14b(bool verbose) {
static bool wait_cmd_14b(bool verbose) {
PacketResponseNG resp;
if (WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND, &resp, TIMEOUT)) {
@ -161,6 +84,8 @@ static bool waitCmd14b(bool verbose) {
(crc) ? _GREEN_("ok") : _RED_("fail")
);
} else if (len == 0) {
if (verbose)
PrintAndLogEx(INFO, "no response from tag");
} else {
PrintAndLogEx(SUCCESS, "len %u | %s", len, sprint_hex(data, len));
}
@ -179,108 +104,132 @@ static int CmdHF14BList(const char *Cmd) {
}
static int CmdHF14BSim(const char *Cmd) {
char cmdp = tolower(param_getchar(Cmd, 0));
if (cmdp == 'h') return usage_hf_14b_sim();
uint32_t pupi = 0;
if (cmdp == 'u') {
pupi = param_get32ex(Cmd, 1, 0, 16);
}
CLIParserContext *ctx;
CLIParserInit(&ctx, "hf 14b sim",
"Simulate a ISO/IEC 14443 type B tag with 4 byte UID / PUPI",
"hf 14b sim\n"
"hf 14b sim -u 11AA33BB"
);
void *argtable[] = {
arg_param_begin,
arg_strx0("u", "uid", "hex", "4byte UID/PUPI"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, true);
uint8_t pupi[4];
int n = 0;
CLIParamHexToBuf(arg_get_str(ctx, 1), pupi, sizeof(pupi), &n);
CLIParserFree(ctx);
clearCommandBuffer();
SendCommandMIX(CMD_HF_ISO14443B_SIMULATE, pupi, 0, 0, NULL, 0);
SendCommandNG(CMD_HF_ISO14443B_SIMULATE, pupi, sizeof(pupi));
return PM3_SUCCESS;
}
static int CmdHF14BSniff(const char *Cmd) {
char cmdp = tolower(param_getchar(Cmd, 0));
if (cmdp == 'h') return usage_hf_14b_sniff();
CLIParserContext *ctx;
CLIParserInit(&ctx, "hf 14b sniff",
"Sniff the communication reader and tag",
"hf 14b sniff"
);
void *argtable[] = {
arg_param_begin,
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, true);
CLIParserFree(ctx);
PacketResponseNG resp;
clearCommandBuffer();
SendCommandNG(CMD_HF_ISO14443B_SNIFF, NULL, 0);
WaitForResponse(CMD_HF_ISO14443B_SNIFF, &resp);
PrintAndLogEx(HINT, "Try `" _YELLOW_("hf 14b list") "` to view captured tracelog");
PrintAndLogEx(HINT, "Try `" _YELLOW_("trace save h") "` to save tracelog for later analysing");
return PM3_SUCCESS;
}
static int CmdHF14BCmdRaw(const char *Cmd) {
bool reply = true, keep_field_on = false, select = false, hasTimeout = false;
char buf[5] = "";
int i = 0;
uint8_t data[PM3_CMD_DATA_SIZE] = {0x00};
uint16_t datalen = 0;
CLIParserContext *ctx;
CLIParserInit(&ctx, "hf 14b raw",
"Sends raw bytes to card ",
"hf 14b raw -s -c -k 0200a40400\n"
"hf 14b raw --sr -c -k 0200a40400\n"
"hf 14b raw --cts -c -k 0200a40400\n"
);
void *argtable[] = {
arg_param_begin,
arg_lit0("k", "keep", "leave the signal field ON after receive response"),
arg_lit0("s", "std", "activate field and select standard card"),
arg_lit0(NULL, "sr", "activate field and select SRx ST"),
arg_lit0(NULL, "cts", "activate field and select ASK C-ticket"),
arg_lit0("c", "crc", "calculate and append CRC"),
arg_lit0("r", "noresponse", "do not read response"),
arg_int0("t", "timeout", "decimal", "timeout in ms"),
arg_lit0("v", "verbose", "verbose"),
arg_strx0(NULL, NULL, "<data (hex)>", "bytes to send"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, false);
bool select = false;
bool keep_field_on = arg_get_lit(ctx, 1);
bool select_std = arg_get_lit(ctx, 2);
bool select_sr = arg_get_lit(ctx, 3);
bool select_cts = arg_get_lit(ctx, 4);
bool add_crc = arg_get_lit(ctx, 5);
bool read_reply = !arg_get_lit(ctx, 6);
int user_timeout = arg_get_int_def(ctx, 7, -1);
bool verbose = arg_get_lit(ctx, 8);
uint32_t flags = ISO14B_CONNECT;
uint32_t temp = 0, user_timeout = 0, time_wait = 0;
if (strlen(Cmd) < 2) return usage_hf_14b_raw();
// strip
while (*Cmd == ' ' || *Cmd == '\t') ++Cmd;
while (Cmd[i] != '\0') {
if (Cmd[i] == ' ' || Cmd[i] == '\t') { ++i; continue; }
if (Cmd[i] == '-') {
switch (tolower(Cmd[i + 1])) {
case 'h':
return usage_hf_14b_raw();
case 'r':
reply = false;
break;
case 'c':
flags |= ISO14B_APPEND_CRC;
break;
case 'k':
keep_field_on = true;
break;
case 's':
select = true;
if (tolower(Cmd[i + 2]) == 's') {
flags |= ISO14B_SELECT_SR;
++i;
} else {
flags |= ISO14B_SELECT_STD;
}
break;
case 't':
hasTimeout = true;
sscanf(Cmd + i + 2, "%d", &user_timeout);
i += 3;
while (Cmd[i] != ' ' && Cmd[i] != '\0') { i++; }
i -= 2;
break;
default:
return usage_hf_14b_raw();
}
i += 2;
continue;
}
if ((Cmd[i] >= '0' && Cmd[i] <= '9') ||
(Cmd[i] >= 'a' && Cmd[i] <= 'f') ||
(Cmd[i] >= 'A' && Cmd[i] <= 'F')) {
buf[strlen(buf) + 1] = 0;
buf[strlen(buf)] = Cmd[i];
i++;
if (strlen(buf) >= 2) {
sscanf(buf, "%x", &temp);
data[datalen++] = (uint8_t)(temp & 0xff);
*buf = 0;
memset(buf, 0x00, sizeof(buf));
}
continue;
}
PrintAndLogEx(WARNING, "unknown parameter '%c'\n", param_getchar(Cmd, i));
return PM3_EINVARG;
if (add_crc) {
flags |= ISO14B_APPEND_CRC;
}
if (hasTimeout) {
if (select_std) {
select = true;
flags |= ISO14B_SELECT_STD;
if (verbose)
PrintAndLogEx(INFO, "using standard select");
} else if (select_sr) {
select = true;
flags |= ISO14B_SELECT_SR;
if (verbose)
PrintAndLogEx(INFO, "using SRx ST select");
} else if (select_cts) {
select = true;
flags |= ISO14B_SELECT_CTS;
if (verbose)
PrintAndLogEx(INFO, "using ASK C-ticket select");
}
uint8_t data[PM3_CMD_DATA_SIZE] = {0x00};
int datalen = 0;
CLIParamHexToBuf(arg_get_str(ctx, 9), data, sizeof(data), &datalen);
CLIParserFree(ctx);
uint32_t time_wait = 0;
if (user_timeout > 0) {
#define MAX_14B_TIMEOUT 40542464 // = (2^32-1) * (8*16) / 13560000Hz * 1000ms/s
flags |= ISO14B_SET_TIMEOUT;
if (user_timeout > MAX_14B_TIMEOUT) {
user_timeout = MAX_14B_TIMEOUT;
PrintAndLogEx(INFO, "Set timeout to 40542 seconds (11.26 hours). The max we can wait for response");
PrintAndLogEx(INFO, "set timeout to 40542 seconds (11.26 hours). The max we can wait for response");
}
time_wait = 13560000 / 1000 / (8 * 16) * user_timeout; // timeout in ETUs (time to transfer 1 bit, approx. 9.4 us)
if (verbose)
PrintAndLogEx(INFO, "using timeout %u", user_timeout);
}
if (keep_field_on == 0)
@ -294,20 +243,19 @@ static int CmdHF14BCmdRaw(const char *Cmd) {
clearCommandBuffer();
SendCommandMIX(CMD_HF_ISO14443B_COMMAND, flags, datalen, time_wait, data, datalen);
if (reply == false) {
if (read_reply == false) {
return PM3_SUCCESS;
}
bool success = true;
// get back iso14b_card_select_t, don't print it.
if (select) {
success = waitCmd14b(false);
success = wait_cmd_14b(verbose);
}
// get back response from the raw bytes you sent.
if (success && datalen > 0) {
waitCmd14b(true);
wait_cmd_14b(true);
}
return PM3_SUCCESS;
@ -400,7 +348,7 @@ static int print_atqb_resp(uint8_t *data, uint8_t cid) {
}
// get SRx chip model (from UID) // from ST Microelectronics
static char *get_ST_Chip_Model(uint8_t data) {
static char *get_st_chip_model(uint8_t data) {
static char model[20];
char *retStr = model;
memset(model, 0, sizeof(model));
@ -629,15 +577,26 @@ static void print_st_general_info(uint8_t *data, uint8_t len) {
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(SUCCESS, " UID: " _GREEN_("%s"), sprint_hex(SwapEndian64(data, 8, 8), len));
PrintAndLogEx(SUCCESS, " MFG: %02X, " _YELLOW_("%s"), mfgid, getTagInfo(mfgid));
PrintAndLogEx(SUCCESS, "Chip: %02X, " _YELLOW_("%s"), chipid, get_ST_Chip_Model(chipid));
PrintAndLogEx(SUCCESS, "Chip: %02X, " _YELLOW_("%s"), chipid, get_st_chip_model(chipid));
}
// iceman, some 14B APDU break down
// print UID info from ASK CT chips
static void print_ct_general_info(void *vcard) {
iso14b_cts_card_select_t card;
memcpy(&card, (iso14b_cts_card_select_t *)vcard, sizeof(iso14b_cts_card_select_t));
uint32_t uid32 = (card.uid[0] |card.uid[1] << 8 |card.uid[2] << 16 | card.uid[3] << 24);
PrintAndLogEx(SUCCESS, "ASK C-Ticket");
PrintAndLogEx(SUCCESS, " UID: " _GREEN_("%s") " ( " _YELLOW_("%010u") " )", sprint_hex(card.uid, sizeof(card.uid)), uid32);
PrintAndLogEx(SUCCESS, " Product Code: %02X", card.pc);
PrintAndLogEx(SUCCESS, " Facility Code: %02X", card.fc);
PrintAndLogEx(NORMAL, "");
}
// iceman, calypso?
// 05 00 00 = find one tag in field
// 1d xx xx xx xx 00 08 01 00 = attrib xx=UID (resp 10 [f9 e0])
// a3 = ? (resp 03 [e2 c2])
// 02 = ? (resp 02 [6a d3])
// 022b (resp 02 67 00 [29 5b])
// 0200a40400 (resp 02 67 00 [29 5b])
// 0200a4040c07a0000002480300 (resp 02 67 00 [29 5b])
// 0200a4040c07a0000002480200 (resp 02 67 00 [29 5b])
@ -646,10 +605,6 @@ static void print_st_general_info(uint8_t *data, uint8_t len) {
// 0200a404000cd2760001354b414e4d30310000 (resp 02 6a 82 [4b 4c])
// 0200a404000ca000000063504b43532d313500 (resp 02 6a 82 [4b 4c])
// 0200a4040010a000000018300301000000000000000000 (resp 02 6a 82 [4b 4c])
// 03 = ? (resp 03 [e3 c2])
// c2 = ? (resp c2 [66 15])
// b2 = ? (resp a3 [e9 67])
// a2 = ? (resp 02 [6a d3])
// 14b get and print Full Info (as much as we know)
static bool HF14B_Std_Info(bool verbose) {
@ -719,14 +674,24 @@ static bool HF14B_ST_Info(bool verbose) {
// menu command to get and print all info known about any known 14b tag
static int CmdHF14Binfo(const char *Cmd) {
char cmdp = tolower(param_getchar(Cmd, 0));
if (cmdp == 'h') return usage_hf_14b_info();
CLIParserContext *ctx;
CLIParserInit(&ctx, "hf 14b info",
"Tag information for ISO/IEC 14443 type B based tags",
"hf 14b info\n"
);
bool verbose = !(cmdp == 's');
void *argtable[] = {
arg_param_begin,
arg_lit0("v", "verbose", "verbose"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, true);
bool verbose = arg_get_lit(ctx, 1);
CLIParserFree(ctx);
return infoHF14B(verbose);
}
static bool HF14B_ST_Reader(bool verbose) {
static bool HF14B_st_reader(bool verbose) {
bool is_success = false;
@ -751,22 +716,22 @@ static bool HF14B_ST_Reader(bool verbose) {
is_success = true;
break;
case -1:
if (verbose) PrintAndLogEx(FAILED, "ISO 14443-3 ATTRIB fail");
if (verbose) PrintAndLogEx(FAILED, "ISO 14443-3 ST ATTRIB fail");
break;
case -2:
if (verbose) PrintAndLogEx(FAILED, "ISO 14443-3 CRC fail");
if (verbose) PrintAndLogEx(FAILED, "ISO 14443-3 ST CRC fail");
break;
case -3:
if (verbose) PrintAndLogEx(FAILED, "ISO 14443-3 random chip id fail");
if (verbose) PrintAndLogEx(FAILED, "ISO 14443-3 ST random chip id fail");
break;
default:
if (verbose) PrintAndLogEx(FAILED, "ISO 14443-b card select SRx failed");
if (verbose) PrintAndLogEx(FAILED, "ISO 14443-b ST card select SRx failed");
break;
}
return is_success;
}
static bool HF14B_Std_Reader(bool verbose) {
static bool HF14B_std_reader(bool verbose) {
bool is_success = false;
@ -810,8 +775,45 @@ static bool HF14B_Std_Reader(bool verbose) {
return is_success;
}
static bool HF14B_ask_ct_reader(bool verbose) {
bool is_success = false;
// 14b get and print UID only (general info)
clearCommandBuffer();
PacketResponseNG resp;
SendCommandMIX(CMD_HF_ISO14443B_COMMAND, ISO14B_CONNECT | ISO14B_SELECT_CTS | ISO14B_DISCONNECT, 0, 0, NULL, 0);
if (WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND, &resp, TIMEOUT) == false) {
if (verbose) PrintAndLogEx(WARNING, "command execution timeout");
return false;
}
int status = resp.oldarg[0];
switch (status) {
case 0: {
print_ct_general_info(resp.data.asBytes);
is_success = true;
break;
}
case -1: {
if (verbose) PrintAndLogEx(FAILED, "ISO 14443-3 CTS wrong length");
break;
}
case -2: {
if (verbose) PrintAndLogEx(FAILED, "ISO 14443-3 CTS CRC fail");
break;
}
default: {
if (verbose) PrintAndLogEx(FAILED, "ISO 14443-b CTS card select failed");
break;
}
}
return is_success;
}
// test for other 14b type tags (mimic another reader - don't have tags to identify)
static bool HF14B_Other_Reader(bool verbose) {
static bool HF14B_other_reader(bool verbose) {
uint8_t data[] = {0x00, 0x0b, 0x3f, 0x80};
uint8_t datalen = 4;
@ -898,9 +900,20 @@ static bool HF14B_Other_Reader(bool verbose) {
// menu command to get and print general info about all known 14b chips
static int CmdHF14BReader(const char *Cmd) {
char cmdp = tolower(param_getchar(Cmd, 0));
if (cmdp == 'h') return usage_hf_14b_reader();
bool verbose = !(cmdp == 's');
CLIParserContext *ctx;
CLIParserInit(&ctx, "hf 14b reader",
"Act as a 14443B reader to identify a tag",
"hf 14b reader\n"
);
void *argtable[] = {
arg_param_begin,
arg_lit0("v", "verbose", "verbose"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, true);
bool verbose = arg_get_lit(ctx, 1);
CLIParserFree(ctx);
return readHF14B(verbose);
}
@ -909,11 +922,36 @@ static int CmdHF14BReader(const char *Cmd) {
* this command just dumps the contents of the memory/
*/
static int CmdHF14BReadSri(const char *Cmd) {
char cmdp = tolower(param_getchar(Cmd, 0));
if (strlen(Cmd) < 1 || cmdp == 'h') return usage_hf_14b_read_srx();
CLIParserContext *ctx;
CLIParserInit(&ctx, "hf 14b sriread",
"Read contents of a SRI512 | SRIX4K tag",
"hf 14b sriread\n"
);
void *argtable[] = {
arg_param_begin,
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, true);
CLIParserFree(ctx);
iso14b_card_select_t card;
if (get_14b_UID(&card) == false) {
PrintAndLogEx(WARNING, "no tag found");
return PM3_SUCCESS;
}
uint8_t tagtype = param_get8(Cmd, 0);
uint8_t blocks = (tagtype == 1) ? 0x7F : 0x0F;
if (card.uidlen != 8) {
PrintAndLogEx(FAILED, "current dump command only work with SRI4K / SRI512 tags");
return PM3_SUCCESS;
}
// detect cardsize
// 1 = 4096
// 2 = 512
uint8_t cardtype = get_st_cardsize(card.uid);
uint8_t blocks = (cardtype == 1) ? 0x7F : 0x0F;
clearCommandBuffer();
SendCommandMIX(CMD_HF_SRI_READ, blocks, 0, 0, NULL, 0);
@ -991,43 +1029,45 @@ static int CmdHF14BWriteSri(const char *Cmd) {
// need to write to file
static int CmdHF14BDump(const char *Cmd) {
uint8_t fileNameLen = 0;
CLIParserContext *ctx;
CLIParserInit(&ctx, "hf 14b dump",
"This command dumps the contents of a ISO-14443-B tag and save it to file\n"
"Tries to autodetect cardtype, memory size defaults to SRI4K",
"hf 14b dump\n"
"hf 14b dump -f myfilename\n"
);
void *argtable[] = {
arg_param_begin,
arg_strx0("f", "file", "<filename>", "(optional) filename, if no <name> UID will be used as filename"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, true);
int fnlen = 0;
char filename[FILE_PATH_SIZE] = {0};
char *fptr = filename;
bool errors = false;
uint8_t cmdp = 0, cardtype = 1;
uint16_t cardsize = 0;
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
switch (tolower(param_getchar(Cmd, cmdp))) {
case 'h':
return usage_hf_14b_dump();
case 'f':
fileNameLen = param_getstr(Cmd, cmdp + 1, filename, FILE_PATH_SIZE);
cmdp += 2;
break;
default:
PrintAndLogEx(WARNING, "Unknown parameter '%c'\n", param_getchar(Cmd, cmdp));
errors = true;
break;
}
}
//Validations
if (errors) return usage_hf_14b_dump();
CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t*)filename, FILE_PATH_SIZE, &fnlen);
CLIParserFree(ctx);
iso14b_card_select_t card;
if (get_14b_UID(&card) == false) {
PrintAndLogEx(WARNING, "No tag found.");
PrintAndLogEx(WARNING, "no tag found");
return PM3_SUCCESS;
}
if (card.uidlen != 8) {
PrintAndLogEx(FAILED, "current dump command only work with SRI4K / SRI512 tags");
return PM3_SUCCESS;
}
// detect cardsize
// 1 = 4096
// 2 = 512
cardtype = get_st_cardsize(card.uid);
uint8_t cardtype = get_st_cardsize(card.uid);
uint8_t blocks = 0;
uint16_t cardsize = 0;
switch (cardtype) {
case 2:
cardsize = (512 / 8) + 4;
@ -1040,17 +1080,17 @@ static int CmdHF14BDump(const char *Cmd) {
break;
}
if (fileNameLen < 1) {
PrintAndLogEx(INFO, "Using UID as filename");
if (fnlen < 1) {
PrintAndLogEx(INFO, "using UID as filename");
fptr += sprintf(fptr, "hf-14b-");
FillFileNameByUID(fptr, SwapEndian64(card.uid, card.uidlen, 8), "-dump", card.uidlen);
}
uint8_t chipid = get_st_chipid(card.uid);
PrintAndLogEx(SUCCESS, "Found a " _GREEN_("%s") " tag", get_ST_Chip_Model(chipid));
PrintAndLogEx(SUCCESS, "found a " _GREEN_("%s") " tag", get_st_chip_model(chipid));
// detect blocksize from card :)
PrintAndLogEx(INFO, "Reading memory from tag UID " _GREEN_("%s"), sprint_hex_inrow(SwapEndian64(card.uid, card.uidlen, 8), card.uidlen));
PrintAndLogEx(INFO, "reading tag memory from UID " _GREEN_("%s"), sprint_hex_inrow(SwapEndian64(card.uid, card.uidlen, 8), card.uidlen));
uint8_t data[cardsize];
memset(data, 0, sizeof(data));
@ -1118,7 +1158,7 @@ static int CmdHF14BDump(const char *Cmd) {
PrintAndLogEx(NORMAL, "");
if (blocknum != 0xFF) {
PrintAndLogEx(FAILED, "Dump failed");
PrintAndLogEx(FAILED, "dump failed");
goto out;
}
@ -1278,14 +1318,20 @@ static int select_card_14443b_4(bool disconnect, iso14b_card_select_t *card) {
// Anticollision + SELECT STD card
SendCommandMIX(CMD_HF_ISO14443B_COMMAND, ISO14B_CONNECT | ISO14B_SELECT_STD, 0, 0, NULL, 0);
if (WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND, &resp, TIMEOUT) == false) {
PrintAndLogEx(INFO, "Trying 14B Select SR");
PrintAndLogEx(INFO, "Trying 14B Select SRx");
// Anticollision + SELECT SR card
SendCommandMIX(CMD_HF_ISO14443B_COMMAND, ISO14B_CONNECT | ISO14B_SELECT_SR, 0, 0, NULL, 0);
if (WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND, &resp, TIMEOUT) == false) {
PrintAndLogEx(ERR, "connection timeout");
switch_off_field_14b();
return PM3_ESOFT;
PrintAndLogEx(INFO, "Trying 14B Select CTS");
// Anticollision + SELECT ASK C-Ticket card
SendCommandMIX(CMD_HF_ISO14443B_COMMAND, ISO14B_CONNECT | ISO14B_SELECT_CTS, 0, 0, NULL, 0);
if (WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND, &resp, TIMEOUT) == false) {
PrintAndLogEx(ERR, "connection timeout");
switch_off_field_14b();
return PM3_ESOFT;
}
}
}
@ -1737,16 +1783,20 @@ int infoHF14B(bool verbose) {
int readHF14B(bool verbose) {
// try std 14b (atqb)
if (HF14B_Std_Reader(verbose))
if (HF14B_std_reader(verbose))
return 1;
// try ST Microelectronics 14b
if (HF14B_ST_Reader(verbose))
if (HF14B_st_reader(verbose))
return 1;
// try ASK CT 14b
if (HF14B_ask_ct_reader(verbose))
return 1;
// try unknown 14b read commands (to be identified later)
// could be read of calypso, CEPAS, moneo, or pico pass.
if (HF14B_Other_Reader(verbose))
if (HF14B_other_reader(verbose))
return 1;
if (verbose) PrintAndLogEx(FAILED, "no 14443-B tag found");

View file

@ -19,6 +19,7 @@
#include "crc16.h"
#include "cmdhf14a.h"
#include "protocols.h" // definitions of ISO14B protocol
#include "iso14b.h"
#define TIMEOUT 2000
static int CmdHelp(const char *Cmd);

View file

@ -21,7 +21,7 @@
#include "crc16.h"
#include "util.h"
#include "ui.h"
#include "mifare.h" // felica_card_select_t struct
#include "iso18.h" // felica_card_select_t struct
#include "des.h"
#define AddCrc(data, len) compute_crc(CRC_FELICA, (data), (len), (data)+(len)+1, (data)+(len))

View file

@ -12,7 +12,7 @@
#define CMDHFFELICA_H__
#include "common.h"
#include "mifare.h"
#include "iso18.h"
int CmdHFFelica(const char *Cmd);
int readFelicaUid(bool verbose);

153
doc/cliparser.md Normal file
View file

@ -0,0 +1,153 @@
# Cliparser
The old style with mixed custom commandline parsing of user parameters or options was messy and confusing. You can find all kinds in the Proxmark3 client.
Samples
```
data xxxx h
script run x.lua -h
hf 14a raw -h
hf 14b raw -ss
lf search 1
lf config h H
```
In order to counter this and unify it, there was discussion over at the official repository a few years ago (link to issue) and there it became clear a change is needed. Among the different solutions suggested @merlokk's idea of using the lib cliparser was agreed upon. The lib was adapted and implemented for commands like
```
emv
hf fido
```
And then it fell into silence since it wasn't well documented how to use the cliparser. Looking at source code wasn't very efficient. However the need of a better cli parsing was still there. Fast forward today, where more commands has used the cliparser but it still wasn't the natural way when adding a new client command to the Proxmark3 client. After more discussions among @doegox, @iceman1001 and @mrwalker the concept became more clear on how to use the cliparser lib in the _preferred_ way. The aftermath was a design and layout specfied which lead to a simpler implemtentation of the cliparser in the client source code while still unfiy all helptexts with the new colours support and a defined layout. As seen below, the simplicity and clearness.
![sample of new style helptext](http://www.icedev.se/proxmark3/helptext.png)
## cliparser setup and use
The parser will format and color and layout as needed.
It will also add the `-h --help` option automatic.
## design comments
* where possiable all options should be lowercase.
* extended options preceeded with -- should be short
* options provided directly (without an option identifier) should be avoided.
* -vv for extra verbos should be avoided; use of debug level is prefered.
* with --options the equal is not needed (will work with and without) so dont use '='
e.g. cmd --cn 12345
## common options
-h --help : help
--cn : card number
--fn : facility number
--q5 : target is lf q5 card
--raw : raw data
-k --key : key supplied
-n --keyno : key number to use
-v --verbose : flag when output should provide more information, not conidered debug.
-1 --buffer : use the sample buffer
## How to implement in source code
### setup the parser data structure
Header file to include
#include "cliparser.h"
In the command function, setup the context
CLIParserContext *ctx;
### define the text
CLIParserInit (\<context\>, \<description\>, \<notes\n examples ... \>);
use -> to seperate example and example comment and \\n to seperate examples.
e.g. lf indala clone -r a0000000a0002021 -> this uses .....
CLIParserInit(&ctx, "lf indala clone",
"clone INDALA UID to T55x7 or Q5/T5555 tag",
"lf indala clone --heden 888\n"
"lf indala clone --fc 123 --cn 1337\n"
"lf indala clone -r a0000000a0002021\n"
"lf indala clone -l -r 80000001b23523a6c2e31eba3cbee4afb3c6ad1fcf649393928c14e5");
### define the options
void *argtable[] = {
arg_param_begin,
arg_lit0("l", "long", "optional - long UID 224 bits"),
arg_int0("c", "heden", "<decimal>", "Cardnumber for Heden 2L format"),
arg_strx0("r", "raw", "<hex>", "raw bytes"),
arg_lit0("q", "Q5", "optional - specify writing to Q5/T5555 tag"),
arg_int0(NULL, "fc", "<decimal>", "Facility Code (26 bit format)"),
arg_int0(NULL, "cn", "<decimal>", "Cardnumber (26 bit format)"),
arg_param_end
};
_All options has a parameter index, since `-h --help` is added automatic, it will be assigned index 0.
Hence all options you add will start at index 1 and upwards._
**Notes:**
booleen : arg_lit0 ("\<short option\>", "\<long option\>", \["\<format\>",\] \<"description"\>)
**integer**
optional integer : arg_int0 ("\<short option\>", "\<long option\>", \["\<format\>",\] \<"description"\>)\
required integer : arg_int1 ("\<short option\>", "\<long option\>", \["\<format\>",\] \<"description"\>)
**Strings 0 or 1**
optional string : arg_str0("\<short option\>", "\<long option\>", \["\<format\>",\] \<"description"\>)\
required string : arg_str1("\<short option\>", "\<long option\>", \["\<format\>",\] \<"description"\>)
**Strings x to 250**
optional string : arg_strx0 ("\<short option\>", "\<long option\>", \["\<format\>",\] \<"description"\>)\
required string : arg_strx1 ("\<short option\>", "\<long option\>", \["\<format\>",\] \<"description"\>)
**if an option does not have a short or long option, use NULL in its place**
### show the menu
CLIExecWithReturn(\<context\>, \<command line to parse\>, \<arg/opt table\>, \<return on error\>);
CLIExecWithReturn(ctx, Cmd, argtable, false);
### clean up
Once you have extracted the options, cleanup the context.
CLIParserFree(ctx);
### retreiving options
**bool option**
arg_get_lit(\<context\>, \<opt index\>);
is_long_uid = arg_get_lit(ctx, 1);
**int option**
arg_get_int_def(\<context\>, \<opt index\>, \<default value\>);
cardnumber = arg_get_int_def(ctx, 2, -1);
**hex option**
CLIGetHexWithReturn(\<context\>, \<opt index\>, \<store variable\>, \<ptr to stored length\>);
?? as an array of uint_8 ??
uint8_t aid[2] = {0};
int aidlen;
CLIGetHexWithReturn(ctx, 2, aid, &aidlen);
**hex option returning ???**
uint8_t key[24] = {0};
int keylen = 0;
int res_klen = CLIParamHexToBuf(arg_get_str(ctx, 3), key, 24, &keylen);
quick test : seems res_keylen == 0 when ok so not key len ???
**string option**
CLIGetStrWithReturn(\<context\>,\<opt index\>, \<unsigned char \*\>, \<int \*\>);
uint8_t Buffer[100];
int BufLen;
CLIGetStrWithReturn(ctx,7, Buffer, &BufLen);

View file

@ -92,7 +92,8 @@ module fpga_hf(
//-----------------------------------------------------------------------------
/*
Attempt to write up how its hooked up. Iceman 2020.
Attempt to write up how its hooked up.
/ Iceman, 2020
Communication between ARM / FPGA is done inside armsrc/fpgaloader.c see: function FpgaSendCommand()
Send 16 bit command / data pair to FPGA
@ -108,8 +109,9 @@ module fpga_hf(
bit | 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
-----+-------------------------------------------
cmd | x x x x
major| x x x
opt | x x x
major| x x x
opt | x x x x
sub | x x
divi | x x x x x x x x
thres| x x x x x x x x
-----+-------------------------------------------

View file

@ -100,7 +100,7 @@ module fpga_lf(
lf_ed_threshold = 8bits threshold value.
conf_word 12bits
conf_word[7:5] = 3bit major mode.
conf_word[8:6] = 3bit major mode.
conf_word[0] = 1bit lf_field
conf_word[1] = 1bit lf_ed_toggle_mode
conf_word[7:0] = 8bit divisor
@ -110,7 +110,7 @@ module fpga_lf(
bit | 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
-----+-------------------------------------------
cmd | x x x x
major| x x x
major| x x x
opt | x x
divi | x x x x x x x x
thres| x x x x x x x x

View file

@ -39,6 +39,7 @@ wire disabl = mod_type[0];
// Most off, oe4 for modulation;
// Trying reader emulation (would presumably just require switching power on, but I am not sure)
assign pwr_lo = 1'b0;
assign pwr_oe2 = 1'b0;
// 512x64/fc -wait before ts0, 32768 ticks
// tslot: 256*64/fc
@ -339,7 +340,6 @@ end
//put modulation here to maintain the correct clock. Seems that some readers are sensitive to that
reg pwr_hi;
reg pwr_oe1;
reg pwr_oe2;
reg pwr_oe3;
reg pwr_oe4;
@ -351,7 +351,6 @@ begin
begin
pwr_hi <= ck_1356meg;
pwr_oe1 <= 1'b0;//mod;
pwr_oe2 <= 1'b0;//mod;
pwr_oe3 <= 1'b0;//mod;
pwr_oe4 <= mod;//1'b0;
end
@ -359,10 +358,12 @@ begin
begin
pwr_hi <= 1'b0;
pwr_oe1 <= 1'b0;
pwr_oe2 <= 1'b0;
pwr_oe3 <= 1'b0;
pwr_oe4 <= mod;
end
end
endmodule

View file

@ -540,16 +540,14 @@ begin
bit_to_arm = sendbit;
end
assign ssp_din = bit_to_arm;
// Subcarrier (adc_clk/16, for FPGA_HF_ISO14443A_TAGSIM_MOD only).
wire sub_carrier;
assign sub_carrier = ~sub_carrier_cnt[3];
// in FPGA_HF_ISO14443A_READER_MOD: drop carrier for mod_sig_coil==1 (pause); in FPGA_HF_ISO14443A_READER_LISTEN: carrier always on; in other modes: carrier always off
// in FPGA_HF_ISO14443A_READER_MOD: drop carrier for mod_sig_coil == 1 (pause);
// in FPGA_HF_ISO14443A_READER_LISTEN: carrier always on; in other modes: carrier always off
assign pwr_hi = (ck_1356meg & (((mod_type == `FPGA_HF_ISO14443A_READER_MOD) & ~mod_sig_coil) || (mod_type == `FPGA_HF_ISO14443A_READER_LISTEN)));
@ -566,7 +564,6 @@ assign pwr_oe4 = mod_sig_coil & sub_carrier & (mod_type == `FPGA_HF_ISO14443A_TA
assign pwr_oe2 = 1'b0;
assign pwr_lo = 1'b0;
assign dbg = negedge_cnt[3];
endmodule

43
include/iso14b.h Normal file
View file

@ -0,0 +1,43 @@
//-----------------------------------------------------------------------------
// (c) 2020 Iceman
//
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
// at your option, any later version. See the LICENSE.txt file for the text of
// the license.
//-----------------------------------------------------------------------------
// ISO 14443B type prototyping
//-----------------------------------------------------------------------------
#ifndef _ISO14B_H_
#define _ISO14B_H_
#include "common.h"
typedef struct {
uint8_t uid[10];
uint8_t uidlen;
uint8_t atqb[7];
uint8_t chipid;
uint8_t cid;
} PACKED iso14b_card_select_t;
typedef struct {
uint8_t uid[4];
uint8_t pc;
uint8_t fc;
} PACKED iso14b_cts_card_select_t;
typedef enum ISO14B_COMMAND {
ISO14B_CONNECT = (1 << 0),
ISO14B_DISCONNECT = (1 << 1),
ISO14B_APDU = (1 << 2),
ISO14B_RAW = (1 << 3),
ISO14B_REQUEST_TRIGGER = (1 << 4),
ISO14B_APPEND_CRC = (1 << 5),
ISO14B_SELECT_STD = (1 << 6),
ISO14B_SELECT_SR = (1 << 7),
ISO14B_SET_TIMEOUT = (1 << 8),
ISO14B_SEND_CHAINING = (1 << 9),
ISO14B_SELECT_CTS = (1 << 10),
} iso14b_command_t;
#endif // _ISO14B_H_

33
include/iso15.h Normal file
View file

@ -0,0 +1,33 @@
//-----------------------------------------------------------------------------
// (c) 2020 Iceman
//
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
// at your option, any later version. See the LICENSE.txt file for the text of
// the license.
//-----------------------------------------------------------------------------
// ISO 15693 type prototyping
//-----------------------------------------------------------------------------
#ifndef _ISO15_H_
#define _ISO15_H_
#include "common.h"
typedef struct {
uint8_t uid[10];
uint8_t uidlen;
uint8_t atqb[7];
uint8_t chipid;
uint8_t cid;
} PACKED iso14b_card_select_t;
typedef enum ISO15_COMMAND {
ISO15_CONNECT = (1 << 0),
ISO15_NO_DISCONNECT = (1 << 1),
ISO15_RAW = (1 << 2),
ISO15_APPEND_CRC = (1 << 3),
ISO15_HIGH_SPEED = (1 << 4),
ISO15_READ_RESPONSE = (1 << 5)
} iso15_command_t;
#endif // _ISO15_H_

119
include/iso18.h Normal file
View file

@ -0,0 +1,119 @@
//-----------------------------------------------------------------------------
// (c) 2020 Iceman
//
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
// at your option, any later version. See the LICENSE.txt file for the text of
// the license.
//-----------------------------------------------------------------------------
// ISO 18002 / FeliCa type prototyping
//-----------------------------------------------------------------------------
#ifndef _ISO18_H_
#define _ISO18_H_
#include "common.h"
typedef enum FELICA_COMMAND {
FELICA_CONNECT = (1 << 0),
FELICA_NO_DISCONNECT = (1 << 1),
FELICA_RAW = (1 << 3),
FELICA_APPEND_CRC = (1 << 5),
FELICA_NO_SELECT = (1 << 6),
} felica_command_t;
//-----------------------------------------------------------------------------
// FeliCa
//-----------------------------------------------------------------------------
// IDm = ID manufacturer
// mc = manufactureCode
// mc1 mc2 u1 u2 u3 u4 u5 u6
// PMm = Product manufacturer
// icCode =
// ic1 = ROM
// ic2 = IC
// maximum response time =
// B3(request service)
// B4(request response)
// B5(authenticate)
// B6(read)
// B7(write)
// B8()
// ServiceCode 2bytes (access-rights)
// FileSystem = 1 Block = 16 bytes
typedef struct {
uint8_t IDm[8];
uint8_t code[2];
uint8_t uid[6];
uint8_t PMm[8];
uint8_t iccode[2];
uint8_t mrt[6];
uint8_t servicecode[2];
} PACKED felica_card_select_t;
typedef struct {
uint8_t sync[2];
uint8_t length[1];
uint8_t cmd_code[1];
uint8_t IDm[8];
} PACKED felica_frame_response_t;
typedef struct {
uint8_t status_flag1[1];
uint8_t status_flag2[1];
} PACKED felica_status_flags_t;
typedef struct {
felica_frame_response_t frame_response;
uint8_t node_number[1];
uint8_t node_key_versions[2];
} PACKED felica_request_service_response_t;
typedef struct {
felica_frame_response_t frame_response;
uint8_t mode[1];
} PACKED felica_request_request_response_t;
typedef struct {
felica_frame_response_t frame_response;
felica_status_flags_t status_flags;
uint8_t number_of_block[1];
uint8_t block_data[16];
uint8_t block_element_number[1];
} PACKED felica_read_without_encryption_response_t;
typedef struct {
felica_frame_response_t frame_response;
felica_status_flags_t status_flags;
} PACKED felica_status_response_t;
typedef struct {
felica_frame_response_t frame_response;
uint8_t number_of_systems[1];
uint8_t system_code_list[32];
} PACKED felica_syscode_response_t;
typedef struct {
felica_frame_response_t frame_response;
felica_status_flags_t status_flags;
uint8_t format_version[1];
uint8_t basic_version[2];
uint8_t number_of_option[1];
uint8_t option_version_list[4];
} PACKED felica_request_spec_response_t;
typedef struct {
felica_frame_response_t frame_response;
uint8_t m2c[8];
uint8_t m3c[8];
} PACKED felica_auth1_response_t;
typedef struct {
uint8_t code[1];
uint8_t IDtc[8];
uint8_t IDi[8];
uint8_t PMi[8];
} PACKED felica_auth2_response_t;
#endif // _ISO18_H_

View file

@ -94,40 +94,6 @@ typedef enum {
MFDES_ALGO_AES = 4
} mifare_des_authalgo_t;
//-----------------------------------------------------------------------------
// ISO 14443B
//-----------------------------------------------------------------------------
typedef struct {
uint8_t uid[10];
uint8_t uidlen;
uint8_t atqb[7];
uint8_t chipid;
uint8_t cid;
} PACKED iso14b_card_select_t;
typedef enum ISO14B_COMMAND {
ISO14B_CONNECT = (1 << 0),
ISO14B_DISCONNECT = (1 << 1),
ISO14B_APDU = (1 << 2),
ISO14B_RAW = (1 << 3),
ISO14B_REQUEST_TRIGGER = (1 << 4),
ISO14B_APPEND_CRC = (1 << 5),
ISO14B_SELECT_STD = (1 << 6),
ISO14B_SELECT_SR = (1 << 7),
ISO14B_SET_TIMEOUT = (1 << 8),
ISO14B_SEND_CHAINING = (1 << 9),
} iso14b_command_t;
typedef enum ISO15_COMMAND {
ISO15_CONNECT = (1 << 0),
ISO15_NO_DISCONNECT = (1 << 1),
ISO15_RAW = (1 << 2),
ISO15_APPEND_CRC = (1 << 3),
ISO15_HIGH_SPEED = (1 << 4),
ISO15_READ_RESPONSE = (1 << 5)
} iso15_command_t;
//-----------------------------------------------------------------------------
// "hf 14a sim x", "hf mf sim x" attacks
//-----------------------------------------------------------------------------
@ -158,116 +124,14 @@ typedef struct {
} PACKED smart_card_atr_t;
typedef enum SMARTCARD_COMMAND {
SC_CONNECT = (1 << 0),
SC_NO_DISCONNECT = (1 << 1),
SC_RAW = (1 << 2),
SC_SELECT = (1 << 3),
SC_RAW_T0 = (1 << 4),
SC_CLEARLOG = (1 << 5),
SC_LOG = (1 << 6),
SC_CONNECT = (1 << 0),
SC_NO_DISCONNECT = (1 << 1),
SC_RAW = (1 << 2),
SC_SELECT = (1 << 3),
SC_RAW_T0 = (1 << 4),
SC_CLEARLOG = (1 << 5),
SC_LOG = (1 << 6),
} smartcard_command_t;
//-----------------------------------------------------------------------------
// FeliCa
//-----------------------------------------------------------------------------
// IDm = ID manufacturer
// mc = manufactureCode
// mc1 mc2 u1 u2 u3 u4 u5 u6
// PMm = Product manufacturer
// icCode =
// ic1 = ROM
// ic2 = IC
// maximum response time =
// B3(request service)
// B4(request response)
// B5(authenticate)
// B6(read)
// B7(write)
// B8()
// ServiceCode 2bytes (access-rights)
// FileSystem = 1 Block = 16 bytes
typedef struct {
uint8_t IDm[8];
uint8_t code[2];
uint8_t uid[6];
uint8_t PMm[8];
uint8_t iccode[2];
uint8_t mrt[6];
uint8_t servicecode[2];
} PACKED felica_card_select_t;
typedef struct {
uint8_t sync[2];
uint8_t length[1];
uint8_t cmd_code[1];
uint8_t IDm[8];
} PACKED felica_frame_response_t;
typedef struct {
uint8_t status_flag1[1];
uint8_t status_flag2[1];
} PACKED felica_status_flags_t;
typedef struct {
felica_frame_response_t frame_response;
uint8_t node_number[1];
uint8_t node_key_versions[2];
} PACKED felica_request_service_response_t;
typedef struct {
felica_frame_response_t frame_response;
uint8_t mode[1];
} PACKED felica_request_request_response_t;
typedef struct {
felica_frame_response_t frame_response;
felica_status_flags_t status_flags;
uint8_t number_of_block[1];
uint8_t block_data[16];
uint8_t block_element_number[1];
} PACKED felica_read_without_encryption_response_t;
typedef struct {
felica_frame_response_t frame_response;
felica_status_flags_t status_flags;
} PACKED felica_status_response_t;
typedef struct {
felica_frame_response_t frame_response;
uint8_t number_of_systems[1];
uint8_t system_code_list[32];
} PACKED felica_syscode_response_t;
typedef struct {
felica_frame_response_t frame_response;
felica_status_flags_t status_flags;
uint8_t format_version[1];
uint8_t basic_version[2];
uint8_t number_of_option[1];
uint8_t option_version_list[4];
} PACKED felica_request_spec_response_t;
typedef struct {
felica_frame_response_t frame_response;
uint8_t m2c[8];
uint8_t m3c[8];
} PACKED felica_auth1_response_t;
typedef struct {
uint8_t code[1];
uint8_t IDtc[8];
uint8_t IDi[8];
uint8_t PMi[8];
} PACKED felica_auth2_response_t;
typedef enum FELICA_COMMAND {
FELICA_CONNECT = (1 << 0),
FELICA_NO_DISCONNECT = (1 << 1),
FELICA_RAW = (1 << 3),
FELICA_APPEND_CRC = (1 << 5),
FELICA_NO_SELECT = (1 << 6),
} felica_command_t;
#endif // _MIFARE_H_

View file

@ -247,6 +247,16 @@ ISO 7816-4 Basic interindustry commands. For command APDU's.
#define ISO14443B_PING 0xBA
#define ISO14443B_PONG 0xAB
// ASK C-ticket
#define ASK_REQT 0x10
#define ASK_IDENTIFY 0x0F
#define ASK_SELECT 0x9F
#define ASK_MULTREAD (0x1 << 4) // High nibble
#define ASK_UPDATE (0x3 << 4) // High nibble
#define ASK_WRITE (0x5 << 4) // High nibble
#define ASK_READ (0x6 << 4) // High nibble
#define ASK_DESACTIVATE 0xF0
// defined crypto RF commands
// only interpreting channel 1 communication

View file

@ -64,7 +64,11 @@
|filename|description|
|--------|-----------|
|hf_14b_raw_050008_resp.pm3 |Response to `hf 14b raw -c 050008`|
|hf_14b_raw_050008_resp.pm3 |Response of 14b card to `hf 14b raw -c 050008`|
|hf_14b_raw_0600_st_sri512.pm3 |Response of ST SRI512 to `hf 14b raw -c 0600`|
|hf_14b_raw_0600_st_sri512_collision.pm3 |Same but with two cards, showing the collisions in answers|
|hf_14b_raw_10_ask_ctx.pm3 |Response of ASK CTx to `hf 14b raw -c 10`|
|hf_14b_raw_010fxxxxxxxx_innovatron.pm3 |Response of 14b' card to `hf 14b raw -c -k 010fxxxxxxxx`|
## HF sniffed traces

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff