mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-21 22:03:42 -07:00
Merge pull request #459 from 7homasSutter/felica_support_sniffing
Felica support sniffing
This commit is contained in:
commit
cd9ff9e61c
7 changed files with 122 additions and 343 deletions
|
@ -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...
|
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]
|
## [unreleased][unreleased]
|
||||||
|
- Fix hf list felica and hf felica sniff (@7homasSutter)
|
||||||
|
- Added hf felica wrunencrypted (@7homasSutter)
|
||||||
- Added hf felica rdunencrypted (@7homasSutter)
|
- Added hf felica rdunencrypted (@7homasSutter)
|
||||||
- Added hf felica rqresponse (@7homasSutter)
|
- Added hf felica rqresponse (@7homasSutter)
|
||||||
- Added hf felica rqservice (@7homasSutter)
|
- Added hf felica rqservice (@7homasSutter)
|
||||||
|
|
|
@ -410,8 +410,6 @@ bool WaitForFelicaReply(uint16_t maxbytes) {
|
||||||
// clear RXRDY:
|
// clear RXRDY:
|
||||||
uint8_t b = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
|
uint8_t b = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
|
||||||
uint32_t timeout = iso18092_get_timeout();
|
uint32_t timeout = iso18092_get_timeout();
|
||||||
if (DBGLEVEL >= DBG_DEBUG)
|
|
||||||
Dbprintf("timeout set: %i", timeout);
|
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
WDT_HIT();
|
WDT_HIT();
|
||||||
|
@ -420,8 +418,8 @@ bool WaitForFelicaReply(uint16_t maxbytes) {
|
||||||
Process18092Byte(b);
|
Process18092Byte(b);
|
||||||
if (FelicaFrame.state == STATE_FULL) {
|
if (FelicaFrame.state == STATE_FULL) {
|
||||||
felica_nexttransfertime = MAX(felica_nexttransfertime,
|
felica_nexttransfertime = MAX(felica_nexttransfertime,
|
||||||
(GetCountSspClk() & 0xfffffff8) - (DELAY_AIR2ARM_AS_READER + DELAY_ARM2AIR_AS_READER) / 16 + FELICA_FRAME_DELAY_TIME
|
(GetCountSspClk() & 0xfffffff8) - (DELAY_AIR2ARM_AS_READER + DELAY_ARM2AIR_AS_READER) / 16 + FELICA_FRAME_DELAY_TIME);
|
||||||
);
|
|
||||||
LogTrace(
|
LogTrace(
|
||||||
FelicaFrame.framebytes,
|
FelicaFrame.framebytes,
|
||||||
FelicaFrame.len,
|
FelicaFrame.len,
|
||||||
|
@ -453,7 +451,7 @@ static void iso18092_setup(uint8_t fpga_minor_mode) {
|
||||||
BigBuf_Clear_ext(false);
|
BigBuf_Clear_ext(false);
|
||||||
|
|
||||||
// Initialize Demod and Uart structs
|
// Initialize Demod and Uart structs
|
||||||
//DemodInit(BigBuf_malloc(MAX_FRAME_SIZE));
|
// DemodInit(BigBuf_malloc(MAX_FRAME_SIZE));
|
||||||
FelicaFrameinit(BigBuf_malloc(FELICA_MAX_FRAME_SIZE));
|
FelicaFrameinit(BigBuf_malloc(FELICA_MAX_FRAME_SIZE));
|
||||||
|
|
||||||
felica_nexttransfertime = 2 * DELAY_ARM2AIR_AS_READER;
|
felica_nexttransfertime = 2 * DELAY_ARM2AIR_AS_READER;
|
||||||
|
@ -573,69 +571,57 @@ void felica_sendraw(PacketCommandNG *c) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void felica_sniff(uint32_t samplesToSkip, uint32_t triggersToSkip) {
|
void felica_sniff(uint32_t samplesToSkip, uint32_t triggersToSkip) {
|
||||||
|
|
||||||
int remFrames = (samplesToSkip) ? samplesToSkip : 0;
|
int remFrames = (samplesToSkip) ? samplesToSkip : 0;
|
||||||
|
Dbprintf("Sniff Felica: Getting first %d frames, Skipping after %d triggers.\n", samplesToSkip, triggersToSkip);
|
||||||
Dbprintf("Sniff FelicaLiteS: Getting first %d frames, Skipping %d triggers.\n", samplesToSkip, triggersToSkip);
|
clear_trace();
|
||||||
|
set_tracing(true);
|
||||||
iso18092_setup(FPGA_HF_ISO18092_FLAG_NOMOD);
|
iso18092_setup(FPGA_HF_ISO18092_FLAG_NOMOD);
|
||||||
|
LED_D_ON();
|
||||||
//the frame bits are slow enough.
|
uint16_t numbts = 0;
|
||||||
int n = BigBuf_max_traceLen() / sizeof(uint8_t); // take all memory
|
int trigger_cnt = 0;
|
||||||
int numbts = 0;
|
uint32_t timeout = iso18092_get_timeout();
|
||||||
uint8_t *dest = (uint8_t *)BigBuf_get_addr();
|
bool isReaderFrame = true;
|
||||||
uint8_t *destend = dest + n - 2;
|
while (!BUTTON_PRESS()) {
|
||||||
|
|
||||||
uint32_t endframe = GetCountSspClk();
|
|
||||||
|
|
||||||
while (dest <= destend) {
|
|
||||||
WDT_HIT();
|
WDT_HIT();
|
||||||
if (BUTTON_PRESS()) break;
|
|
||||||
|
|
||||||
if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) {
|
if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) {
|
||||||
uint8_t dist = (uint8_t)(AT91C_BASE_SSC->SSC_RHR);
|
uint8_t dist = (uint8_t)(AT91C_BASE_SSC->SSC_RHR);
|
||||||
Process18092Byte(dist);
|
Process18092Byte(dist);
|
||||||
|
if ((MAX(dist & 0xff, dist >> 8) >= 178) && (++trigger_cnt > triggersToSkip)) {
|
||||||
//to be sure we are in frame
|
Dbprintf("triggersToSkip kicked %d", dist);
|
||||||
if (FelicaFrame.state == STATE_GET_LENGTH) {
|
break;
|
||||||
//length is after 48 (PRE)+16 (SYNC) - 64 ticks +maybe offset? not 100%
|
|
||||||
uint16_t distance = GetCountSspClk() - endframe - 64 + (FelicaFrame.byte_offset > 0 ? (8 - FelicaFrame.byte_offset) : 0);
|
|
||||||
*dest = distance >> 8;
|
|
||||||
dest++;
|
|
||||||
*dest = (distance & 0xff);
|
|
||||||
dest++;
|
|
||||||
}
|
}
|
||||||
//crc NOT checked
|
|
||||||
if (FelicaFrame.state == STATE_FULL) {
|
if (FelicaFrame.state == STATE_FULL) {
|
||||||
endframe = GetCountSspClk();
|
if ((FelicaFrame.framebytes[3] % 2) == 0) {
|
||||||
// *dest = FelicaFrame.crc_ok; //kind of wasteful
|
isReaderFrame = true; // All Reader Frames are even and all Tag frames are odd
|
||||||
dest++;
|
} else {
|
||||||
for (int i = 0; i < FelicaFrame.len; i++) {
|
isReaderFrame = false;
|
||||||
*dest = FelicaFrame.framebytes[i];
|
|
||||||
dest++;
|
|
||||||
if (dest >= destend) break;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
remFrames--;
|
remFrames--;
|
||||||
if (remFrames <= 0) break;
|
if (remFrames <= 0) {
|
||||||
if (dest >= destend) break;
|
Dbprintf("Stop Sniffing - samplesToSkip reached!");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
LogTrace(FelicaFrame.framebytes,
|
||||||
|
FelicaFrame.len,
|
||||||
|
((GetCountSspClk() & 0xfffffff8) << 4) - DELAY_AIR2ARM_AS_READER - timeout,
|
||||||
|
((GetCountSspClk() & 0xfffffff8) << 4) - DELAY_AIR2ARM_AS_READER,
|
||||||
|
NULL,
|
||||||
|
isReaderFrame
|
||||||
|
);
|
||||||
numbts += FelicaFrame.len;
|
numbts += FelicaFrame.len;
|
||||||
|
|
||||||
FelicaFrameReset();
|
FelicaFrameReset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch_off();
|
switch_off();
|
||||||
|
|
||||||
//reset framing
|
//reset framing
|
||||||
AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(8) | AT91C_SSC_MSBF | SSC_FRAME_MODE_WORDS_PER_TRANSFER(0);
|
AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(8) | AT91C_SSC_MSBF | SSC_FRAME_MODE_WORDS_PER_TRANSFER(0);
|
||||||
set_tracelen(numbts);
|
set_tracelen(numbts);
|
||||||
|
set_tracelen(BigBuf_max_traceLen());
|
||||||
|
|
||||||
Dbprintf("Felica sniffing done, tracelen: %i, use hf list felica for annotations", BigBuf_get_traceLen());
|
Dbprintf("Felica sniffing done, tracelen: %i, use hf list felica for annotations", BigBuf_get_traceLen());
|
||||||
reply_old(CMD_ACK, 1, numbts, 0, 0, 0);
|
reply_old(CMD_ACK, 1, numbts, 0, 0, 0);
|
||||||
|
LED_D_OFF();
|
||||||
}
|
}
|
||||||
|
|
||||||
#define R_POLL0_LEN 0x16
|
#define R_POLL0_LEN 0x16
|
||||||
|
|
|
@ -47,15 +47,19 @@ static int usage_hf_felica_sim(void) {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static int usage_hf_felica_sniff(void) {
|
static int usage_hf_felica_sniff(void) {
|
||||||
PrintAndLogEx(NORMAL, "It get data from the field and saves it into command buffer.");
|
PrintAndLogEx(NORMAL, "\nInfo: It get data from the field and saves it into command buffer. ");
|
||||||
PrintAndLogEx(NORMAL, "Buffer accessible from command 'hf list felica'");
|
PrintAndLogEx(NORMAL, " Buffer accessible from command 'hf list felica'");
|
||||||
PrintAndLogEx(NORMAL, "Usage: hf felica sniff <s> <t>");
|
PrintAndLogEx(NORMAL, "\nUsage: hf felica sniff [-h] [-s] [-t]");
|
||||||
PrintAndLogEx(NORMAL, " s samples to skip (decimal)");
|
PrintAndLogEx(NORMAL, " -h this help");
|
||||||
PrintAndLogEx(NORMAL, " t triggers to skip (decimal)");
|
PrintAndLogEx(NORMAL, " -s samples to skip (decimal) max 9999");
|
||||||
|
PrintAndLogEx(NORMAL, " -t triggers to skip (decimal) max 9999");
|
||||||
|
|
||||||
PrintAndLogEx(NORMAL, "Examples:");
|
PrintAndLogEx(NORMAL, "Examples:");
|
||||||
PrintAndLogEx(NORMAL, " hf felica sniff s 1000");
|
PrintAndLogEx(NORMAL, " hf felica sniff");
|
||||||
|
PrintAndLogEx(NORMAL, " hf felica sniff -s 10 -t 10");
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int usage_hf_felica_simlite(void) {
|
static int usage_hf_felica_simlite(void) {
|
||||||
PrintAndLogEx(NORMAL, "\n Emulating ISO/18092 FeliCa Lite tag \n");
|
PrintAndLogEx(NORMAL, "\n Emulating ISO/18092 FeliCa Lite tag \n");
|
||||||
PrintAndLogEx(NORMAL, "Usage: hf felica litesim [h] u <uid>");
|
PrintAndLogEx(NORMAL, "Usage: hf felica litesim [h] u <uid>");
|
||||||
|
@ -66,6 +70,7 @@ static int usage_hf_felica_simlite(void) {
|
||||||
PrintAndLogEx(NORMAL, " hf felica litesim 11223344556677");
|
PrintAndLogEx(NORMAL, " hf felica litesim 11223344556677");
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int usage_hf_felica_dumplite(void) {
|
static int usage_hf_felica_dumplite(void) {
|
||||||
PrintAndLogEx(NORMAL, "\n Dump ISO/18092 FeliCa Lite tag \n");
|
PrintAndLogEx(NORMAL, "\n Dump ISO/18092 FeliCa Lite tag \n");
|
||||||
PrintAndLogEx(NORMAL, "press button to abort run, otherwise it will loop for 200sec.");
|
PrintAndLogEx(NORMAL, "press button to abort run, otherwise it will loop for 200sec.");
|
||||||
|
@ -76,6 +81,7 @@ static int usage_hf_felica_dumplite(void) {
|
||||||
PrintAndLogEx(NORMAL, " hf felica litedump");
|
PrintAndLogEx(NORMAL, " hf felica litedump");
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int usage_hf_felica_raw(void) {
|
static int usage_hf_felica_raw(void) {
|
||||||
PrintAndLogEx(NORMAL, "Usage: hf felica raw [-h] [-r] [-c] [-p] [-a] <0A 0B 0C ... hex>");
|
PrintAndLogEx(NORMAL, "Usage: hf felica raw [-h] [-r] [-c] [-p] [-a] <0A 0B 0C ... hex>");
|
||||||
PrintAndLogEx(NORMAL, " -h this help");
|
PrintAndLogEx(NORMAL, " -h this help");
|
||||||
|
@ -221,8 +227,8 @@ static int usage_hf_felica_write_without_encryption() {
|
||||||
PrintAndLogEx(NORMAL, "\nUsage: hf felica wrunencrypted [-h] <01 Number of Service hex> <0A0B Service Code List (Little Endian) hex> <01 Number of Block hex> <0A0B Block List Element hex> <0A0B0C0D0E0F... Data hex (16-Byte)>");
|
PrintAndLogEx(NORMAL, "\nUsage: hf felica wrunencrypted [-h] <01 Number of Service hex> <0A0B Service Code List (Little Endian) hex> <01 Number of Block hex> <0A0B Block List Element hex> <0A0B0C0D0E0F... Data hex (16-Byte)>");
|
||||||
PrintAndLogEx(NORMAL, " -h this help");
|
PrintAndLogEx(NORMAL, " -h this help");
|
||||||
PrintAndLogEx(NORMAL, " -i <0A0B0C ... hex> set custom IDm to use\n");
|
PrintAndLogEx(NORMAL, " -i <0A0B0C ... hex> set custom IDm to use\n");
|
||||||
PrintAndLogEx(NORMAL, " hf felica wrunencrypted 01 CB10 01 8001 0102030405060708090A0B0C0D0E0F10\n\n");
|
PrintAndLogEx(NORMAL, " hf felica wrunencrypted 01 CB10 01 8001 0102030405060708090A0B0C0D0E0F10");
|
||||||
|
PrintAndLogEx(NORMAL, " hf felica wrunencrypted -i 11100910C11BC407 01 CB10 01 8001 0102030405060708090A0B0C0D0E0F10\n\n");
|
||||||
PrintAndLogEx(NORMAL, "\nExamples: ");
|
PrintAndLogEx(NORMAL, "\nExamples: ");
|
||||||
PrintAndLogEx(NORMAL, " hf felica wrunencrypted ");
|
PrintAndLogEx(NORMAL, " hf felica wrunencrypted ");
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
|
@ -466,7 +472,7 @@ static int CmdHFFelicaWriteWithoutEncryption(const char *Cmd) {
|
||||||
switch (Cmd[i + 1]) {
|
switch (Cmd[i + 1]) {
|
||||||
case 'H':
|
case 'H':
|
||||||
case 'h':
|
case 'h':
|
||||||
return usage_hf_felica_request_response();
|
return usage_hf_felica_write_without_encryption();
|
||||||
case 'i':
|
case 'i':
|
||||||
paramCount++;
|
paramCount++;
|
||||||
custom_IDm = true;
|
custom_IDm = true;
|
||||||
|
@ -476,6 +482,8 @@ static int CmdHFFelicaWriteWithoutEncryption(const char *Cmd) {
|
||||||
paramCount++;
|
paramCount++;
|
||||||
i += 16;
|
i += 16;
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
return usage_hf_felica_write_without_encryption();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
i++;
|
i++;
|
||||||
|
@ -535,7 +543,7 @@ static int CmdHFFelicaReadWithoutEncryption(const char *Cmd) {
|
||||||
switch (Cmd[i + 1]) {
|
switch (Cmd[i + 1]) {
|
||||||
case 'H':
|
case 'H':
|
||||||
case 'h':
|
case 'h':
|
||||||
return usage_hf_felica_request_response();
|
return usage_hf_felica_read_without_encryption();
|
||||||
case 'i':
|
case 'i':
|
||||||
paramCount++;
|
paramCount++;
|
||||||
custom_IDm = true;
|
custom_IDm = true;
|
||||||
|
@ -553,6 +561,8 @@ static int CmdHFFelicaReadWithoutEncryption(const char *Cmd) {
|
||||||
paramCount++;
|
paramCount++;
|
||||||
long_block_numbers = true;
|
long_block_numbers = true;
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
return usage_hf_felica_read_without_encryption();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
i++;
|
i++;
|
||||||
|
@ -641,6 +651,8 @@ static int CmdHFFelicaRequestResponse(const char *Cmd) {
|
||||||
paramCount++;
|
paramCount++;
|
||||||
i += 16;
|
i += 16;
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
return usage_hf_felica_request_response();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
i++;
|
i++;
|
||||||
|
@ -766,103 +778,57 @@ static int CmdHFFelicaNotImplementedYet(const char *Cmd) {
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// simulate iso18092 / FeliCa tag
|
|
||||||
// Commented, there is no counterpart in ARM at the moment
|
|
||||||
/*
|
|
||||||
static int CmdHFFelicaSim(const char *Cmd) {
|
|
||||||
bool errors = false;
|
|
||||||
uint8_t flags = 0;
|
|
||||||
uint8_t tagtype = 1;
|
|
||||||
uint8_t cmdp = 0;
|
|
||||||
uint8_t uid[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
|
||||||
int uidlen = 0;
|
|
||||||
bool verbose = false;
|
|
||||||
|
|
||||||
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
|
|
||||||
switch (param_getchar(Cmd, cmdp)) {
|
|
||||||
case 'h':
|
|
||||||
case 'H':
|
|
||||||
return usage_hf_felica_sim();
|
|
||||||
case 't':
|
|
||||||
case 'T':
|
|
||||||
// Retrieve the tag type
|
|
||||||
tagtype = param_get8ex(Cmd, cmdp + 1, 0, 10);
|
|
||||||
if (tagtype == 0)
|
|
||||||
errors = true;
|
|
||||||
cmdp += 2;
|
|
||||||
break;
|
|
||||||
case 'u':
|
|
||||||
case 'U':
|
|
||||||
// Retrieve the full 4,7,10 byte long uid
|
|
||||||
param_gethex_ex(Cmd, cmdp + 1, uid, &uidlen);
|
|
||||||
if (!errors) {
|
|
||||||
PrintAndLogEx(NORMAL, "Emulating ISO18092/FeliCa tag with %d byte UID (%s)", uidlen >> 1, sprint_hex(uid, uidlen >> 1));
|
|
||||||
}
|
|
||||||
cmdp += 2;
|
|
||||||
break;
|
|
||||||
case 'v':
|
|
||||||
case 'V':
|
|
||||||
verbose = true;
|
|
||||||
cmdp++;
|
|
||||||
break;
|
|
||||||
case 'e':
|
|
||||||
case 'E':
|
|
||||||
cmdp++;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp));
|
|
||||||
errors = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//Validations
|
|
||||||
if (errors || cmdp == 0) return usage_hf_felica_sim();
|
|
||||||
|
|
||||||
clearCommandBuffer();
|
|
||||||
SendCommandOLD(CMD_HF_FELICA_SIMULATE, tagtype, flags, 0, uid, uidlen >> 1);
|
|
||||||
PacketResponseNG resp;
|
|
||||||
|
|
||||||
if (verbose)
|
|
||||||
PrintAndLogEx(NORMAL, "Press pm3-button to abort simulation");
|
|
||||||
|
|
||||||
while (!kbd_enter_pressed()) {
|
|
||||||
if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) continue;
|
|
||||||
}
|
|
||||||
return PM3_SUCCESS;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
static int CmdHFFelicaSniff(const char *Cmd) {
|
static int CmdHFFelicaSniff(const char *Cmd) {
|
||||||
uint8_t cmdp = 0;
|
uint8_t paramCount = 0;
|
||||||
uint64_t samples2skip = 0;
|
uint64_t samples2skip = 0;
|
||||||
uint64_t triggers2skip = 0;
|
uint64_t triggers2skip = 0;
|
||||||
bool errors = false;
|
strip_cmds(Cmd);
|
||||||
|
int i = 0;
|
||||||
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
|
while (Cmd[i] != '\0') {
|
||||||
switch (param_getchar(Cmd, cmdp)) {
|
if (Cmd[i] == '-') {
|
||||||
case 'h':
|
switch (Cmd[i + 1]) {
|
||||||
case 'H':
|
case 'h':
|
||||||
return usage_hf_felica_sniff();
|
case 'H':
|
||||||
case 's':
|
return usage_hf_felica_sniff();
|
||||||
case 'S':
|
case 's':
|
||||||
samples2skip = param_get32ex(Cmd, cmdp + 1, 0, 10);
|
case 'S':
|
||||||
cmdp += 2;
|
paramCount++;
|
||||||
break;
|
if (param_getlength(Cmd, paramCount) < 5) {
|
||||||
case 't':
|
samples2skip = param_get32ex(Cmd, paramCount++, 0, 10);
|
||||||
case 'T':
|
} else {
|
||||||
triggers2skip = param_get32ex(Cmd, cmdp + 1, 0, 10);
|
PrintAndLogEx(ERR, "Invalid samples number!");
|
||||||
cmdp += 2;
|
return PM3_EINVARG;
|
||||||
break;
|
}
|
||||||
default:
|
break;
|
||||||
PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp));
|
case 't':
|
||||||
errors = true;
|
case 'T':
|
||||||
break;
|
paramCount++;
|
||||||
|
if (param_getlength(Cmd, paramCount) < 5) {
|
||||||
|
triggers2skip = param_get32ex(Cmd, paramCount++, 0, 10);
|
||||||
|
} else {
|
||||||
|
PrintAndLogEx(ERR, "Invalid triggers number!");
|
||||||
|
return PM3_EINVARG;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, paramCount));
|
||||||
|
return usage_hf_felica_sniff();
|
||||||
|
}
|
||||||
|
i += 2;
|
||||||
}
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
if (samples2skip <= 0) {
|
||||||
|
samples2skip = 10;
|
||||||
|
PrintAndLogEx(INFO, "Set default samples2skip: %i", samples2skip);
|
||||||
|
}
|
||||||
|
if (triggers2skip <= 0) {
|
||||||
|
triggers2skip = 5000;
|
||||||
|
PrintAndLogEx(INFO, "Set default triggers2skip: %i", triggers2skip);
|
||||||
}
|
}
|
||||||
//Validations
|
|
||||||
if (errors || cmdp == 0) return usage_hf_felica_sniff();
|
|
||||||
|
|
||||||
|
PrintAndLogEx(INFO, "Start Sniffing now. You can stop sniffing with clicking the PM3 Button");
|
||||||
|
PrintAndLogEx(INFO, "During sniffing, other pm3 commands may not response.");
|
||||||
clearCommandBuffer();
|
clearCommandBuffer();
|
||||||
SendCommandMIX(CMD_HF_FELICA_SNIFF, samples2skip, triggers2skip, 0, NULL, 0);
|
SendCommandMIX(CMD_HF_FELICA_SNIFF, samples2skip, triggers2skip, 0, NULL, 0);
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
|
|
|
@ -97,6 +97,10 @@ uint8_t iso15693_CRC_check(uint8_t *d, uint8_t n) {
|
||||||
return check_crc(CRC_15693, d, n);
|
return check_crc(CRC_15693, d, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint8_t felica_CRC_check(uint8_t *d, uint8_t n) {
|
||||||
|
return check_crc(CRC_FELICA, d, n);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief iclass_CRC_Ok Checks CRC in command or response
|
* @brief iclass_CRC_Ok Checks CRC in command or response
|
||||||
* @param isResponse
|
* @param isResponse
|
||||||
|
@ -889,8 +893,7 @@ void annotateLegic(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void annotateFelica(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize) {
|
void annotateFelica(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize) {
|
||||||
|
switch (cmd[3]) {
|
||||||
switch (cmd[0]) {
|
|
||||||
case FELICA_POLL_REQ:
|
case FELICA_POLL_REQ:
|
||||||
snprintf(exp, size, "POLLING");
|
snprintf(exp, size, "POLLING");
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -31,6 +31,7 @@ void ClearAuthData(void);
|
||||||
|
|
||||||
uint8_t iso14443A_CRC_check(bool isResponse, uint8_t *d, uint8_t n);
|
uint8_t iso14443A_CRC_check(bool isResponse, uint8_t *d, uint8_t n);
|
||||||
uint8_t iso14443B_CRC_check(uint8_t *d, uint8_t n);
|
uint8_t iso14443B_CRC_check(uint8_t *d, uint8_t n);
|
||||||
|
uint8_t felica_CRC_check(uint8_t *d, uint8_t n);
|
||||||
uint8_t mifare_CRC_check(bool isResponse, uint8_t *data, uint8_t len);
|
uint8_t mifare_CRC_check(bool isResponse, uint8_t *data, uint8_t len);
|
||||||
uint8_t iso15693_CRC_check(uint8_t *d, uint8_t n);
|
uint8_t iso15693_CRC_check(uint8_t *d, uint8_t n);
|
||||||
uint8_t iclass_CRC_check(bool isResponse, uint8_t *d, uint8_t n);
|
uint8_t iclass_CRC_check(bool isResponse, uint8_t *d, uint8_t n);
|
||||||
|
|
|
@ -243,7 +243,7 @@ static int CmdFdxDemod(const char *Cmd) {
|
||||||
|
|
||||||
uint8_t c[] = {0, 0};
|
uint8_t c[] = {0, 0};
|
||||||
compute_crc(CRC_11784, raw, sizeof(raw), &c[0], &c[1]);
|
compute_crc(CRC_11784, raw, sizeof(raw), &c[0], &c[1]);
|
||||||
PrintAndLogEx(SUCCESS, "CRC-16 0x%04X [ %s] ", crc, (crc == (c[1] << 8 | c[0]) ) ? _GREEN_("OK") : _RED_("Fail"));
|
PrintAndLogEx(SUCCESS, "CRC-16 0x%04X [ %s] ", crc, (crc == (c[1] << 8 | c[0])) ? _GREEN_("OK") : _RED_("Fail"));
|
||||||
|
|
||||||
if (g_debugMode) {
|
if (g_debugMode) {
|
||||||
PrintAndLogEx(DEBUG, "Start marker %d; Size %zu", preambleIndex, size);
|
PrintAndLogEx(DEBUG, "Start marker %d; Size %zu", preambleIndex, size);
|
||||||
|
@ -313,7 +313,7 @@ static int CmdFdxSim(const char *Cmd) {
|
||||||
|
|
||||||
countryid = param_get32ex(Cmd, 0, 0, 10);
|
countryid = param_get32ex(Cmd, 0, 0, 10);
|
||||||
animalid = param_get64ex(Cmd, 1, 0, 10);
|
animalid = param_get64ex(Cmd, 1, 0, 10);
|
||||||
extended = param_get32ex(Cmd, 2, 0 , 10);
|
extended = param_get32ex(Cmd, 2, 0, 10);
|
||||||
|
|
||||||
verify_values(&animalid, &countryid);
|
verify_values(&animalid, &countryid);
|
||||||
|
|
||||||
|
|
|
@ -257,7 +257,7 @@ static uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *tr
|
||||||
case ISO_14443B:
|
case ISO_14443B:
|
||||||
case TOPAZ:
|
case TOPAZ:
|
||||||
case FELICA:
|
case FELICA:
|
||||||
crcStatus = iso14443B_CRC_check(frame, data_len);
|
crcStatus = !felica_CRC_check(frame + 2, data_len - 4);
|
||||||
break;
|
break;
|
||||||
case PROTO_MIFARE:
|
case PROTO_MIFARE:
|
||||||
crcStatus = mifare_CRC_check(isResponse, frame, data_len);
|
crcStatus = mifare_CRC_check(isResponse, frame, data_len);
|
||||||
|
@ -301,6 +301,7 @@ static uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *tr
|
||||||
&& protocol != ISO_7816_4
|
&& protocol != ISO_7816_4
|
||||||
&& protocol != PROTO_HITAG
|
&& protocol != PROTO_HITAG
|
||||||
&& protocol != THINFILM
|
&& protocol != THINFILM
|
||||||
|
&& protocol != FELICA
|
||||||
&& (isResponse || protocol == ISO_14443A)
|
&& (isResponse || protocol == ISO_14443A)
|
||||||
&& (oddparity8(frame[j]) != ((parityBits >> (7 - (j & 0x0007))) & 0x01))) {
|
&& (oddparity8(frame[j]) != ((parityBits >> (7 - (j & 0x0007))) & 0x01))) {
|
||||||
|
|
||||||
|
@ -349,6 +350,9 @@ static uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *tr
|
||||||
if (protocol == PROTO_MIFARE)
|
if (protocol == PROTO_MIFARE)
|
||||||
annotateMifare(explanation, sizeof(explanation), frame, data_len, parityBytes, parity_len, isResponse);
|
annotateMifare(explanation, sizeof(explanation), frame, data_len, parityBytes, parity_len, isResponse);
|
||||||
|
|
||||||
|
if (protocol == FELICA)
|
||||||
|
annotateFelica(explanation, sizeof(explanation), frame, data_len);
|
||||||
|
|
||||||
if (!isResponse) {
|
if (!isResponse) {
|
||||||
switch (protocol) {
|
switch (protocol) {
|
||||||
case ICLASS:
|
case ICLASS:
|
||||||
|
@ -408,7 +412,7 @@ static uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *tr
|
||||||
sprint_hex_inrow_spaces(mfData, mfDataLen, 2),
|
sprint_hex_inrow_spaces(mfData, mfDataLen, 2),
|
||||||
(crcc == 0 ? "!crc" : (crcc == 1 ? " ok " : " ")),
|
(crcc == 0 ? "!crc" : (crcc == 1 ? " ok " : " ")),
|
||||||
explanation);
|
explanation);
|
||||||
};
|
}
|
||||||
|
|
||||||
if (is_last_record(tracepos, trace, traceLen)) return traceLen;
|
if (is_last_record(tracepos, trace, traceLen)) return traceLen;
|
||||||
|
|
||||||
|
@ -424,195 +428,6 @@ static uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *tr
|
||||||
return tracepos;
|
return tracepos;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void printFelica(uint16_t traceLen, uint8_t *trace) {
|
|
||||||
|
|
||||||
PrintAndLogEx(NORMAL, "ISO18092 / FeliCa - Timings are not as accurate");
|
|
||||||
PrintAndLogEx(NORMAL, " Gap | Src | Data | CRC | Annotation |");
|
|
||||||
PrintAndLogEx(NORMAL, "--------|-----|---------------------------------|----------|-------------------|");
|
|
||||||
uint16_t tracepos = 0;
|
|
||||||
|
|
||||||
while (tracepos < traceLen) {
|
|
||||||
|
|
||||||
if (tracepos + 3 >= traceLen) break;
|
|
||||||
|
|
||||||
|
|
||||||
uint16_t gap = *((uint16_t *)(trace + tracepos));
|
|
||||||
uint8_t crc_ok = trace[tracepos + 2];
|
|
||||||
tracepos += 3;
|
|
||||||
|
|
||||||
if (tracepos + 3 >= traceLen) break;
|
|
||||||
|
|
||||||
uint16_t len = trace[tracepos + 2];
|
|
||||||
|
|
||||||
//I am stripping SYNC
|
|
||||||
tracepos += 3; //skip SYNC
|
|
||||||
|
|
||||||
if (tracepos + len + 1 >= traceLen) break;
|
|
||||||
|
|
||||||
uint8_t cmd = trace[tracepos];
|
|
||||||
uint8_t isResponse = cmd & 1;
|
|
||||||
|
|
||||||
char line[32][110] = {{0}};
|
|
||||||
for (int j = 0; j < len + 1 && j / 8 < 32; j++) {
|
|
||||||
snprintf(line[j / 8] + ((j % 8) * 4), 110, " %02x ", trace[tracepos + j]);
|
|
||||||
}
|
|
||||||
char expbuf[50];
|
|
||||||
switch (cmd) {
|
|
||||||
case FELICA_POLL_REQ:
|
|
||||||
snprintf(expbuf, 49, "Poll Req");
|
|
||||||
break;
|
|
||||||
case FELICA_POLL_ACK:
|
|
||||||
snprintf(expbuf, 49, "Poll Resp");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case FELICA_REQSRV_REQ:
|
|
||||||
snprintf(expbuf, 49, "Request Srvc Req");
|
|
||||||
break;
|
|
||||||
case FELICA_REQSRV_ACK:
|
|
||||||
snprintf(expbuf, 49, "Request Srv Resp");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case FELICA_RDBLK_REQ:
|
|
||||||
snprintf(expbuf, 49, "Read block(s) Req");
|
|
||||||
break;
|
|
||||||
case FELICA_RDBLK_ACK:
|
|
||||||
snprintf(expbuf, 49, "Read block(s) Resp");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case FELICA_WRTBLK_REQ:
|
|
||||||
snprintf(expbuf, 49, "Write block(s) Req");
|
|
||||||
break;
|
|
||||||
case FELICA_WRTBLK_ACK:
|
|
||||||
snprintf(expbuf, 49, "Write block(s) Resp");
|
|
||||||
break;
|
|
||||||
case FELICA_SRCHSYSCODE_REQ:
|
|
||||||
snprintf(expbuf, 49, "Search syscode Req");
|
|
||||||
break;
|
|
||||||
case FELICA_SRCHSYSCODE_ACK:
|
|
||||||
snprintf(expbuf, 49, "Search syscode Resp");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case FELICA_REQSYSCODE_REQ:
|
|
||||||
snprintf(expbuf, 49, "Request syscode Req");
|
|
||||||
break;
|
|
||||||
case FELICA_REQSYSCODE_ACK:
|
|
||||||
snprintf(expbuf, 49, "Request syscode Resp");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case FELICA_AUTH1_REQ:
|
|
||||||
snprintf(expbuf, 49, "Auth1 Req");
|
|
||||||
break;
|
|
||||||
case FELICA_AUTH1_ACK:
|
|
||||||
snprintf(expbuf, 49, "Auth1 Resp");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case FELICA_AUTH2_REQ:
|
|
||||||
snprintf(expbuf, 49, "Auth2 Req");
|
|
||||||
break;
|
|
||||||
case FELICA_AUTH2_ACK:
|
|
||||||
snprintf(expbuf, 49, "Auth2 Resp");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case FELICA_RDSEC_REQ:
|
|
||||||
snprintf(expbuf, 49, "Secure read Req");
|
|
||||||
break;
|
|
||||||
case FELICA_RDSEC_ACK:
|
|
||||||
snprintf(expbuf, 49, "Secure read Resp");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case FELICA_WRTSEC_REQ:
|
|
||||||
snprintf(expbuf, 49, "Secure write Req");
|
|
||||||
break;
|
|
||||||
case FELICA_WRTSEC_ACK:
|
|
||||||
snprintf(expbuf, 49, "Secure write Resp");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case FELICA_REQSRV2_REQ:
|
|
||||||
snprintf(expbuf, 49, "Request Srvc v2 Req");
|
|
||||||
break;
|
|
||||||
case FELICA_REQSRV2_ACK:
|
|
||||||
snprintf(expbuf, 49, "Request Srvc v2 Resp");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case FELICA_GETSTATUS_REQ:
|
|
||||||
snprintf(expbuf, 49, "Get status Req");
|
|
||||||
break;
|
|
||||||
case FELICA_GETSTATUS_ACK:
|
|
||||||
snprintf(expbuf, 49, "Get status Resp");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case FELICA_OSVER_REQ:
|
|
||||||
snprintf(expbuf, 49, "Get OS Version Req");
|
|
||||||
break;
|
|
||||||
case FELICA_OSVER_ACK:
|
|
||||||
snprintf(expbuf, 49, "Get OS Version Resp");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case FELICA_RESET_MODE_REQ:
|
|
||||||
snprintf(expbuf, 49, "Reset mode Req");
|
|
||||||
break;
|
|
||||||
case FELICA_RESET_MODE_ACK:
|
|
||||||
snprintf(expbuf, 49, "Reset mode Resp");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case FELICA_AUTH1V2_REQ:
|
|
||||||
snprintf(expbuf, 49, "Auth1 v2 Req");
|
|
||||||
break;
|
|
||||||
case FELICA_AUTH1V2_ACK:
|
|
||||||
snprintf(expbuf, 49, "Auth1 v2 Resp");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case FELICA_AUTH2V2_REQ:
|
|
||||||
snprintf(expbuf, 49, "Auth2 v2 Req");
|
|
||||||
break;
|
|
||||||
case FELICA_AUTH2V2_ACK:
|
|
||||||
snprintf(expbuf, 49, "Auth2 v2 Resp");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case FELICA_RDSECV2_REQ:
|
|
||||||
snprintf(expbuf, 49, "Secure read v2 Req");
|
|
||||||
break;
|
|
||||||
case FELICA_RDSECV2_ACK:
|
|
||||||
snprintf(expbuf, 49, "Secure read v2 Resp");
|
|
||||||
break;
|
|
||||||
case FELICA_WRTSECV2_REQ:
|
|
||||||
snprintf(expbuf, 49, "Secure write v2 Req");
|
|
||||||
break;
|
|
||||||
case FELICA_WRTSECV2_ACK:
|
|
||||||
snprintf(expbuf, 49, "Secure write v2 Resp");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case FELICA_UPDATE_RNDID_REQ:
|
|
||||||
snprintf(expbuf, 49, "Update IDr Req");
|
|
||||||
break;
|
|
||||||
case FELICA_UPDATE_RNDID_ACK:
|
|
||||||
snprintf(expbuf, 49, "Update IDr Resp");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
snprintf(expbuf, 49, "Unknown");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
int num_lines = MIN((len) / 16 + 1, 16);
|
|
||||||
for (int j = 0; j < num_lines ; j++) {
|
|
||||||
if (j == 0) {
|
|
||||||
PrintAndLogEx(NORMAL, "%7d | %s |%-32s |%02x %02x %s| %s",
|
|
||||||
gap,
|
|
||||||
(isResponse ? "Tag" : "Rdr"),
|
|
||||||
line[j],
|
|
||||||
trace[tracepos + len],
|
|
||||||
trace[tracepos + len + 1],
|
|
||||||
(crc_ok) ? "OK" : "NG",
|
|
||||||
expbuf);
|
|
||||||
} else {
|
|
||||||
PrintAndLogEx(NORMAL, " | |%-32s | | ", line[j]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
tracepos += len + 1;
|
|
||||||
}
|
|
||||||
PrintAndLogEx(NORMAL, "");
|
|
||||||
}
|
|
||||||
|
|
||||||
// sanity check. Don't use proxmark if it is offline and you didn't specify useTraceBuffer
|
// sanity check. Don't use proxmark if it is offline and you didn't specify useTraceBuffer
|
||||||
/*
|
/*
|
||||||
static int SanityOfflineCheck( bool useTraceBuffer ){
|
static int SanityOfflineCheck( bool useTraceBuffer ){
|
||||||
|
@ -819,9 +634,13 @@ int CmdTraceList(const char *Cmd) {
|
||||||
|
|
||||||
PrintAndLogEx(SUCCESS, "Recorded Activity (TraceLen = %lu bytes)", traceLen);
|
PrintAndLogEx(SUCCESS, "Recorded Activity (TraceLen = %lu bytes)", traceLen);
|
||||||
PrintAndLogEx(INFO, "");
|
PrintAndLogEx(INFO, "");
|
||||||
|
|
||||||
|
/*
|
||||||
if (protocol == FELICA) {
|
if (protocol == FELICA) {
|
||||||
printFelica(traceLen, trace);
|
printFelica(traceLen, trace);
|
||||||
} else if (showHex) {
|
} */
|
||||||
|
|
||||||
|
if (showHex) {
|
||||||
while (tracepos < traceLen) {
|
while (tracepos < traceLen) {
|
||||||
tracepos = printHexLine(tracepos, traceLen, trace, protocol);
|
tracepos = printHexLine(tracepos, traceLen, trace, protocol);
|
||||||
}
|
}
|
||||||
|
@ -844,6 +663,8 @@ int CmdTraceList(const char *Cmd) {
|
||||||
PrintAndLogEx(NORMAL, "ISO7816-4 / Smartcard - Timings N/A yet");
|
PrintAndLogEx(NORMAL, "ISO7816-4 / Smartcard - Timings N/A yet");
|
||||||
if (protocol == PROTO_HITAG)
|
if (protocol == PROTO_HITAG)
|
||||||
PrintAndLogEx(NORMAL, "Hitag2 / HitagS - Timings in ETU (8us)");
|
PrintAndLogEx(NORMAL, "Hitag2 / HitagS - Timings in ETU (8us)");
|
||||||
|
if (protocol == FELICA)
|
||||||
|
PrintAndLogEx(NORMAL, "ISO18092 / FeliCa - Timings are not as accurate");
|
||||||
|
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
PrintAndLogEx(NORMAL, " Start | End | Src | Data (! denotes parity error) | CRC | Annotation");
|
PrintAndLogEx(NORMAL, " Start | End | Src | Data (! denotes parity error) | CRC | Annotation");
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue