mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2026-05-12 11:18:11 -07:00
Added secc support to jam custom payload values
This commit is contained in:
+1
-1
@@ -1853,7 +1853,7 @@ static void PacketReceived(PacketCommandNG *packet) {
|
||||
break;
|
||||
}
|
||||
case CMD_HF_HIDCONFIG_SNIFF: {
|
||||
SniffHIDConfigCard(packet->data.asBytes[0]);
|
||||
SniffHIDConfigCard((const hid_sniff_payload_t *)packet->data.asBytes);
|
||||
reply_ng(CMD_HF_HIDCONFIG_SNIFF, PM3_SUCCESS, NULL, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
+38
-12
@@ -52,6 +52,16 @@ static hid_apdu_entry_t s_apdu_table[HID_APDU_MAX_ENTRIES];
|
||||
static uint8_t s_apdu_count = 0;
|
||||
static uint8_t s_scp02_key[16] = {0};
|
||||
|
||||
// Jam config — set by SniffHIDConfigCard before entering sniff loop.
|
||||
// Length 0 means "use built-in default".
|
||||
static uint8_t s_jam_apdu[HID_JAM_MAX_APDU];
|
||||
static uint8_t s_jam_apdu_len = 0;
|
||||
static uint8_t s_jam_resp[HID_JAM_MAX_RESP];
|
||||
static uint8_t s_jam_resp_len = 0;
|
||||
|
||||
static const uint8_t s_jam_apdu_default[5] = {0xA0, 0xD4, 0x00, 0x00, 0x00};
|
||||
static const uint8_t s_jam_resp_default[4] = {0x00, 0x00, 0x90, 0x00};
|
||||
|
||||
void hid_config_card_set_apdu_table(const hid_apdu_entry_t *table, uint8_t count) {
|
||||
s_apdu_count = (count > HID_APDU_MAX_ENTRIES) ? HID_APDU_MAX_ENTRIES : count;
|
||||
memcpy(s_apdu_table, table, s_apdu_count * sizeof(hid_apdu_entry_t));
|
||||
@@ -226,22 +236,25 @@ bool hid_config_card_jam(const uint8_t *cmd, int len, uint8_t *dma_buf) {
|
||||
|
||||
int off = (pcb & 0x08) ? 2 : 1; // skip CID if present
|
||||
|
||||
if (len < off + 7)
|
||||
// Select active APDU pattern and response (custom or default)
|
||||
const uint8_t *match = (s_jam_apdu_len > 0) ? s_jam_apdu : s_jam_apdu_default;
|
||||
int match_len = (s_jam_apdu_len > 0) ? (int)s_jam_apdu_len : (int)sizeof(s_jam_apdu_default);
|
||||
const uint8_t *resp_data = (s_jam_resp_len > 0) ? s_jam_resp : s_jam_resp_default;
|
||||
int resp_data_len = (s_jam_resp_len > 0) ? (int)s_jam_resp_len : (int)sizeof(s_jam_resp_default);
|
||||
|
||||
if (len < off + match_len + 2) // off + APDU pattern + 2-byte CRC
|
||||
return false;
|
||||
|
||||
if (cmd[off] != 0xA0 || cmd[off + 1] != 0xD4 ||
|
||||
cmd[off + 2] != 0x00 || cmd[off + 3] != 0x00 || cmd[off + 4] != 0x00)
|
||||
if (memcmp(cmd + off, match, match_len) != 0)
|
||||
return false;
|
||||
|
||||
// Build jam response: PCB [CID] 00 00 90 00 CRC CRC
|
||||
uint8_t resp[8];
|
||||
// Build jam response: PCB [CID] <resp_data> CRC CRC
|
||||
uint8_t resp[2 + HID_JAM_MAX_RESP + 2]; // PCB + optional CID + payload + CRC
|
||||
int rlen = 0;
|
||||
resp[rlen++] = pcb;
|
||||
if (pcb & 0x08) resp[rlen++] = cmd[1]; // mirror CID
|
||||
resp[rlen++] = 0x00;
|
||||
resp[rlen++] = 0x00;
|
||||
resp[rlen++] = 0x90;
|
||||
resp[rlen++] = 0x00;
|
||||
memcpy(resp + rlen, resp_data, resp_data_len);
|
||||
rlen += resp_data_len;
|
||||
AddCrc14A(resp, rlen);
|
||||
rlen += 2;
|
||||
|
||||
@@ -464,9 +477,22 @@ void SimulateHIDConfigCard(const hid_sim_payload_t *payload) {
|
||||
// HID Config Card sniff with optional A0 D4 jamming
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
void SniffHIDConfigCard(uint8_t param) {
|
||||
// Delegate entirely to SniffIso14443a.
|
||||
void SniffHIDConfigCard(const hid_sniff_payload_t *payload) {
|
||||
// Configure jam pattern and response before entering the sniff loop.
|
||||
if (payload->apdu_len > 0 && payload->apdu_len <= HID_JAM_MAX_APDU) {
|
||||
memcpy(s_jam_apdu, payload->apdu, payload->apdu_len);
|
||||
s_jam_apdu_len = payload->apdu_len;
|
||||
} else {
|
||||
s_jam_apdu_len = 0; // use default A0 D4 00 00 00
|
||||
}
|
||||
if (payload->resp_len > 0 && payload->resp_len <= HID_JAM_MAX_RESP) {
|
||||
memcpy(s_jam_resp, payload->resp, payload->resp_len);
|
||||
s_jam_resp_len = payload->resp_len;
|
||||
} else {
|
||||
s_jam_resp_len = 0; // use default 00 00 90 00
|
||||
}
|
||||
// Delegate to SniffIso14443a.
|
||||
// When param bit 0x04 is set, SniffIso14443a calls hid_config_card_jam()
|
||||
// inline after each decoded reader frame (see iso14443a.c).
|
||||
SniffIso14443a(param);
|
||||
SniffIso14443a(payload->param);
|
||||
}
|
||||
|
||||
+21
-2
@@ -61,14 +61,33 @@ typedef struct {
|
||||
hid_apdu_entry_t apdu_table[HID_APDU_MAX_ENTRIES];
|
||||
} PACKED hid_sim_payload_t;
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Sniff payload (sent from client to ARM via CMD_HF_HIDCONFIG_SNIFF).
|
||||
// When apdu_len == 0 the default A0 D4 00 00 00 pattern is used.
|
||||
// When resp_len == 0 the default 00 00 90 00 response is used.
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
#define HID_JAM_MAX_APDU 32
|
||||
#define HID_JAM_MAX_RESP 32
|
||||
|
||||
typedef struct {
|
||||
uint8_t param; // sniff flags: 0x01=card-triggered, 0x02=reader-triggered, 0x04=jam
|
||||
uint8_t apdu[HID_JAM_MAX_APDU]; // APDU to jam (raw bytes after PCB/CID stripped)
|
||||
uint8_t apdu_len; // 0 = use default (A0 D4 00 00 00)
|
||||
uint8_t resp[HID_JAM_MAX_RESP]; // jam response payload (raw APDU, without PCB/CID/CRC)
|
||||
uint8_t resp_len; // 0 = use default (00 00 90 00)
|
||||
} PACKED hid_sniff_payload_t;
|
||||
|
||||
// Load a custom APDU response table into static storage (call before sim loop).
|
||||
void hid_config_card_set_apdu_table(const hid_apdu_entry_t *table, uint8_t count);
|
||||
|
||||
// Run a complete HID Config Card simulation using payload received from the client.
|
||||
void SimulateHIDConfigCard(const hid_sim_payload_t *payload);
|
||||
|
||||
// Sniff ISO 14443-A with optional jamming of A0 D4 00 00 00 (param bit 0x04).
|
||||
void SniffHIDConfigCard(uint8_t param);
|
||||
// Sniff ISO 14443-A with optional jamming (param bit 0x04).
|
||||
// When apdu_len > 0 the supplied APDU pattern overrides the default A0 D4 00 00 00.
|
||||
// When resp_len > 0 the supplied response overrides the default 00 00 90 00.
|
||||
void SniffHIDConfigCard(const hid_sniff_payload_t *payload);
|
||||
|
||||
// Handle an I-block received during HID Config Card (tagType=16) simulation.
|
||||
// Fills dynamic_response_info with the appropriate response payload (without CRC).
|
||||
|
||||
+88
-8
@@ -44,6 +44,18 @@ typedef struct {
|
||||
hid_apdu_entry_t apdu_table[HID_APDU_MAX_ENTRIES];
|
||||
} PACKED hid_sim_payload_t;
|
||||
|
||||
// Must stay in sync with hid_sniff_payload_t in armsrc/secc.h.
|
||||
#define HID_JAM_MAX_APDU 32
|
||||
#define HID_JAM_MAX_RESP 32
|
||||
|
||||
typedef struct {
|
||||
uint8_t param;
|
||||
uint8_t apdu[HID_JAM_MAX_APDU]; // APDU to jam (0-length = default A0 D4 00 00 00)
|
||||
uint8_t apdu_len;
|
||||
uint8_t resp[HID_JAM_MAX_RESP]; // jam response payload (0-length = default 00 00 90 00)
|
||||
uint8_t resp_len;
|
||||
} PACKED hid_sniff_payload_t;
|
||||
|
||||
static int CmdHelp(const char *Cmd);
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -260,17 +272,24 @@ static int CmdHFHIDConfigSniff(const char *Cmd) {
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf secc sniff",
|
||||
"Sniff the communication between a HID Config Card reader and card.\n"
|
||||
"Use `hf 14a list` to view collected data.",
|
||||
"Use `hf seos list` to view collected data.\n"
|
||||
"With -j and no -d, jams responses to APDU A0 D4 00 00 00.\n"
|
||||
"With -j -d <hex> jams responses to the specified APDU.\n"
|
||||
"Use -r <hex> to override the jam response payload (default: 00009000).",
|
||||
"hf secc sniff\n"
|
||||
"hf secc sniff -j -> jam A0 D4 00 00 00, respond 00 00 90 00\n"
|
||||
"hf secc sniff -c -r -> trigger on card or reader data");
|
||||
"hf secc sniff -j -> jam A0 D4 00 00 00, respond 00 00 90 00\n"
|
||||
"hf secc sniff -j -d A0D4000000 -> same, APDU specified explicitly\n"
|
||||
"hf secc sniff -j -d A0D4000000 -r 9000 -> jam A0D4000000, respond 90 00\n"
|
||||
"hf secc sniff -c -i -> trigger on card data, interactive");
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_lit0("c", "card", "triggered by first data from card"),
|
||||
arg_lit0("r", "reader", "triggered by first 7-bit request from reader (REQ, WUP)"),
|
||||
arg_lit0("i", "interactive", "console will not be returned until sniff finishes or is aborted"),
|
||||
arg_lit0("j", "jam", "jam APDU A0 D4 00 00 00, respond with 00 00 90 00"),
|
||||
arg_lit0("j", "jam", "jam responses to a specific APDU (see -d/-a)"),
|
||||
arg_str0("d", "apdu", "<hex>", "APDU bytes to jam (default: A0D4000000)"),
|
||||
arg_str0("a", "resp", "<hex>", "response payload when jamming (default: 00009000)"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||
@@ -285,17 +304,78 @@ static int CmdHFHIDConfigSniff(const char *Cmd) {
|
||||
|
||||
bool interactive = arg_get_lit(ctx, 3);
|
||||
bool jam = arg_get_lit(ctx, 4);
|
||||
|
||||
uint8_t apdu_buf[HID_JAM_MAX_APDU] = {0};
|
||||
int apdu_buf_len = 0;
|
||||
if (CLIParamHexToBuf(arg_get_str(ctx, 5), apdu_buf, sizeof(apdu_buf), &apdu_buf_len)) {
|
||||
CLIParserFree(ctx);
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
uint8_t resp_buf[HID_JAM_MAX_RESP] = {0};
|
||||
int resp_buf_len = 0;
|
||||
if (CLIParamHexToBuf(arg_get_str(ctx, 6), resp_buf, sizeof(resp_buf), &resp_buf_len)) {
|
||||
CLIParserFree(ctx);
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
bool has_apdu = (apdu_buf_len > 0);
|
||||
bool has_resp = (resp_buf_len > 0);
|
||||
|
||||
CLIParserFree(ctx);
|
||||
|
||||
// -d and -r only make sense with -j
|
||||
if ((has_apdu || has_resp) && !jam) {
|
||||
PrintAndLogEx(ERR, "-d and -r require -j (jam mode)");
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
if (jam) {
|
||||
param |= 0x04;
|
||||
PrintAndLogEx(INFO, "Sniff with jam of APDU " _YELLOW_("A0 D4 00 00 00") " -> " _YELLOW_("00 00 90 00"));
|
||||
if (has_apdu) {
|
||||
char apdu_hex[HID_JAM_MAX_APDU * 2 + 1] = {0};
|
||||
for (int i = 0; i < apdu_buf_len; i++)
|
||||
snprintf(apdu_hex + i * 2, sizeof(apdu_hex) - i * 2, "%02X", apdu_buf[i]);
|
||||
if (has_resp) {
|
||||
char resp_hex[HID_JAM_MAX_RESP * 2 + 1] = {0};
|
||||
for (int i = 0; i < resp_buf_len; i++)
|
||||
snprintf(resp_hex + i * 2, sizeof(resp_hex) - i * 2, "%02X", resp_buf[i]);
|
||||
PrintAndLogEx(INFO, "Sniff with jam of APDU " _YELLOW_("%s") " -> " _YELLOW_("%s"), apdu_hex, resp_hex);
|
||||
} else {
|
||||
PrintAndLogEx(INFO, "Sniff with jam of APDU " _YELLOW_("%s") " -> " _YELLOW_("00009000"), apdu_hex);
|
||||
}
|
||||
} else {
|
||||
if (has_resp) {
|
||||
char resp_hex[HID_JAM_MAX_RESP * 2 + 1] = {0};
|
||||
for (int i = 0; i < resp_buf_len; i++)
|
||||
snprintf(resp_hex + i * 2, sizeof(resp_hex) - i * 2, "%02X", resp_buf[i]);
|
||||
PrintAndLogEx(INFO, "Sniff with jam of APDU " _YELLOW_("A0D4000000") " -> " _YELLOW_("%s"), resp_hex);
|
||||
} else {
|
||||
PrintAndLogEx(INFO, "Sniff with jam of APDU " _YELLOW_("A0D4000000") " -> " _YELLOW_("00009000"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t sniff_cmd = jam ? CMD_HF_HIDCONFIG_SNIFF : CMD_HF_ISO14443A_SNIFF;
|
||||
|
||||
clearCommandBuffer();
|
||||
SendCommandNG(sniff_cmd, (uint8_t *)¶m, sizeof(uint8_t));
|
||||
if (jam) {
|
||||
hid_sniff_payload_t payload;
|
||||
memset(&payload, 0, sizeof(payload));
|
||||
payload.param = param;
|
||||
if (has_apdu) {
|
||||
memcpy(payload.apdu, apdu_buf, apdu_buf_len);
|
||||
payload.apdu_len = (uint8_t)apdu_buf_len;
|
||||
}
|
||||
if (has_resp) {
|
||||
memcpy(payload.resp, resp_buf, resp_buf_len);
|
||||
payload.resp_len = (uint8_t)resp_buf_len;
|
||||
}
|
||||
clearCommandBuffer();
|
||||
SendCommandNG(sniff_cmd, (uint8_t *)&payload, sizeof(payload));
|
||||
} else {
|
||||
clearCommandBuffer();
|
||||
SendCommandNG(sniff_cmd, (uint8_t *)¶m, sizeof(uint8_t));
|
||||
}
|
||||
|
||||
if (interactive) {
|
||||
PrintAndLogEx(INFO, "Press " _GREEN_("pm3 button") " or " _GREEN_("<Enter>") " to abort sniffing");
|
||||
@@ -314,7 +394,7 @@ static int CmdHFHIDConfigSniff(const char *Cmd) {
|
||||
}
|
||||
|
||||
PrintAndLogEx(INFO, "Done!");
|
||||
PrintAndLogEx(HINT, "Hint: Try `" _YELLOW_("hf 14a list") "` to view captured tracelog");
|
||||
PrintAndLogEx(HINT, "Hint: Try `" _YELLOW_("hf seos list") "` to view captured tracelog");
|
||||
PrintAndLogEx(HINT, "Hint: Try `" _YELLOW_("trace save -h") "` to save tracelog for later analysing");
|
||||
} else {
|
||||
PrintAndLogEx(INFO, "Press " _GREEN_("pm3 button") " to abort sniffing");
|
||||
|
||||
Reference in New Issue
Block a user