hf felica rdbl, wrbl, now uses cliparser. Renamed them, and hf felica raw got a bugfix to read raw bytes correct

This commit is contained in:
iceman1001 2021-04-13 16:08:58 +02:00
commit e7e43d11d0
3 changed files with 188 additions and 101 deletions

View file

@ -131,25 +131,6 @@ static int usage_hf_felica_sim(void) {
} }
*/ */
static int usage_hf_felica_write_without_encryption(void) {
PrintAndLogEx(NORMAL, "\nInfo: Use this command to write Block Data to authentication-not-required Service.");
PrintAndLogEx(NORMAL, " - Mode shall be Mode0.");
print_number_of_service_constraints();
print_number_of_block_constraints();
print_service_code_list_constraints();
print_block_list_element_constraints();
PrintAndLogEx(NORMAL, " - Un-/Successful read: Card responses with Status Flag1 and Flag2");
print_status_flag1_interpretation();
print_status_flag2_interpration();
PrintAndLogEx(NORMAL, "\nUsage: hf felica wrunencrypted [-h][-i] <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, " -i <0A0B0C ... hex> set custom IDm to use\n");
PrintAndLogEx(NORMAL, "\nExamples: ");
PrintAndLogEx(NORMAL, " hf felica wrunencrypted 01 CB10 01 8001 0102030405060708090A0B0C0D0E0F10");
PrintAndLogEx(NORMAL, " hf felica wrunencrypted -i 11100910C11BC407 01 CB10 01 8001 0102030405060708090A0B0C0D0E0F10\n\n");
return PM3_SUCCESS;
}
static int usage_hf_felica_authentication1(void) { static int usage_hf_felica_authentication1(void) {
PrintAndLogEx(NORMAL, "\nInfo: Initiate mutual authentication. This command must always be executed before Authentication2 command" PrintAndLogEx(NORMAL, "\nInfo: Initiate mutual authentication. This command must always be executed before Authentication2 command"
", and mutual authentication is achieve only after Authentication2 command has succeeded."); ", and mutual authentication is achieve only after Authentication2 command has succeeded.");
@ -202,7 +183,6 @@ static int usage_hf_felica_authentication2(void) {
return PM3_SUCCESS; return PM3_SUCCESS;
} }
/** /**
* Wait for response from pm3 or timeout. * Wait for response from pm3 or timeout.
* Checks if receveid bytes have a valid CRC. * Checks if receveid bytes have a valid CRC.
@ -212,23 +192,23 @@ static bool waitCmdFelica(uint8_t iSelect, PacketResponseNG *resp, bool verbose)
if (WaitForResponseTimeout(CMD_ACK, resp, 2000)) { if (WaitForResponseTimeout(CMD_ACK, resp, 2000)) {
uint16_t len = iSelect ? (resp->oldarg[1] & 0xffff) : (resp->oldarg[0] & 0xffff); uint16_t len = iSelect ? (resp->oldarg[1] & 0xffff) : (resp->oldarg[0] & 0xffff);
if (verbose) { if (verbose) {
PrintAndLogEx(SUCCESS, "Client Received %i octets", len); PrintAndLogEx(SUCCESS, "client received %i octets", len);
if (len == 0 || len == 1) { if (len == 0 || len == 1) {
PrintAndLogEx(ERR, "Could not receive data correctly!"); PrintAndLogEx(ERR, "Could not receive data correctly!");
return false; return false;
} }
PrintAndLogEx(SUCCESS, "%s", sprint_hex(resp->data.asBytes, len)); PrintAndLogEx(SUCCESS, "%s", sprint_hex(resp->data.asBytes, len));
if (!check_crc(CRC_FELICA, resp->data.asBytes + 2, len - 2)) { if (!check_crc(CRC_FELICA, resp->data.asBytes + 2, len - 2)) {
PrintAndLogEx(WARNING, "Wrong or no CRC bytes"); PrintAndLogEx(WARNING, "wrong or no CRC bytes");
} }
if (resp->data.asBytes[0] != 0xB2 && resp->data.asBytes[1] != 0x4D) { if (resp->data.asBytes[0] != 0xB2 && resp->data.asBytes[1] != 0x4D) {
PrintAndLogEx(ERR, "Received incorrect Frame Format!"); PrintAndLogEx(ERR, "received incorrect frame format!");
return false; return false;
} }
} }
return true; return true;
} else { } else {
PrintAndLogEx(WARNING, "Timeout while waiting for reply."); PrintAndLogEx(WARNING, "timeout while waiting for reply.");
} }
return false; return false;
} }
@ -434,7 +414,7 @@ static bool add_param(const char *Cmd, uint8_t paramCount, uint8_t *data, uint8_
* Prints read-without-encryption response. * Prints read-without-encryption response.
* @param rd_noCry_resp Response frame. * @param rd_noCry_resp Response frame.
*/ */
static void print_rd_noEncrpytion_response(felica_read_without_encryption_response_t *rd_noCry_resp) { static void print_rd_plain_response(felica_read_without_encryption_response_t *rd_noCry_resp) {
if (rd_noCry_resp->status_flags.status_flag1[0] == 00 && if (rd_noCry_resp->status_flags.status_flag1[0] == 00 &&
rd_noCry_resp->status_flags.status_flag2[0] == 00) { rd_noCry_resp->status_flags.status_flag2[0] == 00) {
@ -471,10 +451,10 @@ int send_request_service(uint8_t flags, uint16_t datalen, uint8_t *data, bool ve
memcpy(&r, (felica_request_service_response_t *)resp.data.asBytes, sizeof(felica_request_service_response_t)); memcpy(&r, (felica_request_service_response_t *)resp.data.asBytes, sizeof(felica_request_service_response_t));
if (r.frame_response.IDm[0] != 0) { if (r.frame_response.IDm[0] != 0) {
PrintAndLogEx(SUCCESS, "\nGot Service Response:"); PrintAndLogEx(SUCCESS, "Service Response:");
PrintAndLogEx(SUCCESS, "IDm: %s", sprint_hex_inrow(r.frame_response.IDm, sizeof(r.frame_response.IDm))); PrintAndLogEx(SUCCESS, "IDm... %s", sprint_hex_inrow(r.frame_response.IDm, sizeof(r.frame_response.IDm)));
PrintAndLogEx(SUCCESS, " Node number: %s", sprint_hex(r.node_number, sizeof(r.node_number))); PrintAndLogEx(SUCCESS, " Node number............. %s", sprint_hex(r.node_number, sizeof(r.node_number)));
PrintAndLogEx(SUCCESS, " Node key version list: %s\n", sprint_hex(r.node_key_versions, sizeof(r.node_key_versions))); PrintAndLogEx(SUCCESS, " Node key version list... %s\n", sprint_hex(r.node_key_versions, sizeof(r.node_key_versions)));
} }
return PM3_SUCCESS; return PM3_SUCCESS;
} }
@ -490,11 +470,11 @@ int send_request_service(uint8_t flags, uint16_t datalen, uint8_t *data, bool ve
* @param rd_noCry_resp frame in which the response will be saved. * @param rd_noCry_resp frame in which the response will be saved.
* @return success if response was received. * @return success if response was received.
*/ */
int send_rd_unencrypted(uint8_t flags, uint16_t datalen, uint8_t *data, bool verbose, felica_read_without_encryption_response_t *rd_noCry_resp) { int send_rd_plain(uint8_t flags, uint16_t datalen, uint8_t *data, bool verbose, felica_read_without_encryption_response_t *rd_noCry_resp) {
clear_and_send_command(flags, datalen, data, verbose); clear_and_send_command(flags, datalen, data, verbose);
PacketResponseNG resp; PacketResponseNG resp;
if (!waitCmdFelica(0, &resp, verbose)) { if (!waitCmdFelica(0, &resp, verbose)) {
PrintAndLogEx(ERR, "\nGot no response from card"); PrintAndLogEx(ERR, "No response from card");
return PM3_ERFTRANS; return PM3_ERFTRANS;
} else { } else {
memcpy(rd_noCry_resp, (felica_read_without_encryption_response_t *)resp.data.asBytes, sizeof(felica_read_without_encryption_response_t)); memcpy(rd_noCry_resp, (felica_read_without_encryption_response_t *)resp.data.asBytes, sizeof(felica_read_without_encryption_response_t));
@ -528,11 +508,11 @@ static bool check_last_idm(uint8_t *data, uint16_t datalen) {
* @param wr_noCry_resp frame in which the response will be saved. * @param wr_noCry_resp frame in which the response will be saved.
* @return success if response was received. * @return success if response was received.
*/ */
static int send_wr_unencrypted(uint8_t flags, uint16_t datalen, uint8_t *data, bool verbose, felica_status_response_t *wr_noCry_resp) { static int send_wr_plain(uint8_t flags, uint16_t datalen, uint8_t *data, bool verbose, felica_status_response_t *wr_noCry_resp) {
clear_and_send_command(flags, datalen, data, verbose); clear_and_send_command(flags, datalen, data, verbose);
PacketResponseNG resp; PacketResponseNG resp;
if (waitCmdFelica(0, &resp, verbose) == false) { if (waitCmdFelica(0, &resp, verbose) == false) {
PrintAndLogEx(ERR, "Got no response from card"); PrintAndLogEx(ERR, "no response from card");
return PM3_ERFTRANS; return PM3_ERFTRANS;
} }
@ -564,6 +544,8 @@ static int CmdHFFelicaAuthentication1(const char *Cmd) {
PrintAndLogEx(INFO, "INCOMPLETE / EXPERIMENTAL COMMAND!!!"); PrintAndLogEx(INFO, "INCOMPLETE / EXPERIMENTAL COMMAND!!!");
uint8_t data[PM3_CMD_DATA_SIZE]; uint8_t data[PM3_CMD_DATA_SIZE];
memset(data, 0 , sizeof(data));
bool custom_IDm = false; bool custom_IDm = false;
strip_cmds(Cmd); strip_cmds(Cmd);
uint16_t datalen = 24; // Length (1), Command ID (1), IDm (8), Number of Area (1), Area Code List (2), Number of Service (1), Service Code List (2), M1c (8) uint16_t datalen = 24; // Length (1), Command ID (1), IDm (8), Number of Area (1), Area Code List (2), Number of Service (1), Service Code List (2), M1c (8)
@ -711,6 +693,8 @@ static int CmdHFFelicaAuthentication2(const char *Cmd) {
PrintAndLogEx(INFO, "INCOMPLETE / EXPERIMENTAL COMMAND!!!"); PrintAndLogEx(INFO, "INCOMPLETE / EXPERIMENTAL COMMAND!!!");
PrintAndLogEx(INFO, "EXPERIMENTAL COMMAND - M2c/P2c will be not checked"); PrintAndLogEx(INFO, "EXPERIMENTAL COMMAND - M2c/P2c will be not checked");
uint8_t data[PM3_CMD_DATA_SIZE]; uint8_t data[PM3_CMD_DATA_SIZE];
memset(data, 0 , sizeof(data));
bool custom_IDm = false; bool custom_IDm = false;
strip_cmds(Cmd); strip_cmds(Cmd);
uint16_t datalen = 18; // Length (1), Command ID (1), IDm (8), M4c (8) uint16_t datalen = 18; // Length (1), Command ID (1), IDm (8), M4c (8)
@ -822,66 +806,162 @@ static int CmdHFFelicaAuthentication2(const char *Cmd) {
* @param Cmd input data of the user. * @param Cmd input data of the user.
* @return client result code. * @return client result code.
*/ */
static int CmdHFFelicaWriteWithoutEncryption(const char *Cmd) { static int CmdHFFelicaWritePlain(const char *Cmd) {
if (strlen(Cmd) < 5)
return usage_hf_felica_write_without_encryption(); CLIParserContext *ctx;
uint8_t data[PM3_CMD_DATA_SIZE]; CLIParserInit(&ctx, "hf felica wrbl",
bool custom_IDm = false; "Use this command to write block data to authentication-not-required Service.\n\n"
strip_cmds(Cmd); " - Mode shall be Mode0.\n"
uint16_t datalen = 32; // Length (1), Command ID (1), IDm (8), Number of Service (1), Service Code List(2), Number of Block(1), Block List(3), Block Data(16) " - Un-/Ssuccessful == Status Flag1 and Flag2",
uint8_t paramCount = 0; "hf felica wrbl --sn 01 --scl CB10 --bn 01 --ble 8001 -d 0102030405060708090A0B0C0D0E0F10\n"
uint8_t flags = 0; "hf felica wrbl -i 01100910c11bc407 --sn 01 --scl CB10 --bn 01 --ble 8001 -d 0102030405060708090A0B0C0D0E0F10\n"
int i = 0; );
while (Cmd[i] != '\0') { void *argtable[] = {
if (Cmd[i] == '-') { arg_param_begin,
switch (tolower(Cmd[i + 1])) { arg_str0("d", "data", "<hex>", "data, 16 hex bytes"),
case 'h': arg_str0("i", NULL, "<hex>", "set custom IDm"),
return usage_hf_felica_write_without_encryption(); arg_str0(NULL, "sn", "<hex>", "number of service"),
case 'i': arg_str0(NULL, "scl", "<hex>", "service code list"),
paramCount++; arg_str0(NULL, "bn", "<hex>", "number of block"),
custom_IDm = true; arg_str0(NULL, "ble", "<hex>", "block list element (def 2|3 bytes)"),
if (!add_param(Cmd, paramCount, data, 2, 16)) { arg_lit0("v", "verbose", "verbose helptext"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, true);
uint8_t userdata[16] = {0};
int udlen = 0;
int res = CLIParamHexToBuf(arg_get_str(ctx, 1), userdata, sizeof(userdata), &udlen);
if (res) {
CLIParserFree(ctx);
return PM3_EINVARG; return PM3_EINVARG;
} }
paramCount++;
i += 16; uint8_t idm[8] = {0};
break; int ilen = 0;
default: res = CLIParamHexToBuf(arg_get_str(ctx, 2), idm, sizeof(idm), &ilen);
return usage_hf_felica_write_without_encryption(); if (res) {
CLIParserFree(ctx);
return PM3_EINVARG;
} }
uint8_t sn[1] = {0};
int snlen = 0;
res = CLIParamHexToBuf(arg_get_str(ctx, 3), sn, sizeof(sn), &snlen);
if (res) {
CLIParserFree(ctx);
return PM3_EINVARG;
} }
i++;
uint8_t scl[2] = {0};
int scllen = 0;
res = CLIParamHexToBuf(arg_get_str(ctx, 4), scl, sizeof(scl), &scllen);
if (res) {
CLIParserFree(ctx);
return PM3_EINVARG;
} }
uint8_t bn[1] = {0};
int bnlen = 0;
res = CLIParamHexToBuf(arg_get_str(ctx, 5), bn, sizeof(bn), &bnlen);
if (res) {
CLIParserFree(ctx);
return PM3_EINVARG;
}
uint8_t ble[3] = {0};
int blelen = 0;
res = CLIParamHexToBuf(arg_get_str(ctx, 6), ble, sizeof(ble), &blelen);
if (res) {
CLIParserFree(ctx);
return PM3_EINVARG;
}
bool verbose = arg_get_lit(ctx, 7);
CLIParserFree(ctx);
if (verbose) {
print_number_of_service_constraints();
print_number_of_block_constraints();
print_service_code_list_constraints();
print_block_list_element_constraints();
print_status_flag1_interpretation();
print_status_flag2_interpration();
return PM3_SUCCESS;
}
uint8_t data[PM3_CMD_DATA_SIZE];
memset(data, 0 , sizeof(data));
data[0] = 0x20; // Static length data[0] = 0x20; // Static length
data[1] = 0x08; // Command ID data[1] = 0x08; // Command ID
if (!custom_IDm && !check_last_idm(data, datalen)) {
bool custom_IDm = false;
if (ilen) {
custom_IDm = true;
memcpy(data + 2, idm, sizeof(idm));
}
// Length (1)
// Command ID (1)
// IDm (8)
// Number of Service (1)
// Service Code List(2)
// Number of Block(1)
// Block List(3)
// Block Data(16)
uint16_t datalen = 32; // Length (1), Command ID (1), IDm (8), Number of Service (1), Service Code List(2), Number of Block(1), Block List(3), Block Data(16)
if (custom_IDm == false && check_last_idm(data, datalen) == false) {
return PM3_EINVARG; return PM3_EINVARG;
} }
// Number of Service 2, Service Code List 4, Number of Block 2, Block List Element 4, Data 16
uint8_t lengths[] = {2, 4, 2, 4, 32}; if (blelen == 3) {
uint8_t dataPositions[] = {10, 11, 13, 14, 16}; datalen++;
for (i = 0; i < 5; i++) {
if (add_param(Cmd, paramCount, data, dataPositions[i], lengths[i])) {
paramCount++;
} else {
return PM3_EINVARG;
} }
// Number of Service 1, Service Code List 2, Number of Block 1, Block List Element 2, Data 16
// Service Number 1 byte
if (snlen) {
data[10] = sn[0];
} }
flags |= FELICA_APPEND_CRC; // Service Code List 2 bytes
flags |= FELICA_RAW; if (scllen) {
data[11] = scl[0];
data[12] = scl[1];
}
// Block number 1 byte
if (bnlen) {
data[13] = bn[0];
}
// Block List Element 2|3 bytes
if (blelen) {
memcpy(data + 14, ble, blelen);
}
// data to be written, 16 bytes
if (udlen) {
memcpy(data + 14 + blelen, userdata, sizeof(userdata));
}
uint8_t flags = (FELICA_APPEND_CRC | FELICA_RAW);
AddCrc(data, datalen); AddCrc(data, datalen);
datalen += 2; datalen += 2;
felica_status_response_t wr_noCry_resp; felica_status_response_t wr_noCry_resp;
if (send_wr_unencrypted(flags, datalen, data, 1, &wr_noCry_resp) == PM3_SUCCESS) { if (send_wr_plain(flags, datalen, data, 1, &wr_noCry_resp) == PM3_SUCCESS) {
PrintAndLogEx(SUCCESS, "\nIDm: %s", sprint_hex(wr_noCry_resp.frame_response.IDm, sizeof(wr_noCry_resp.frame_response.IDm))); PrintAndLogEx(SUCCESS, "IDm............ %s", sprint_hex(wr_noCry_resp.frame_response.IDm, sizeof(wr_noCry_resp.frame_response.IDm)));
PrintAndLogEx(SUCCESS, "Status Flag1: %s", sprint_hex(wr_noCry_resp.status_flags.status_flag1, sizeof(wr_noCry_resp.status_flags.status_flag1))); PrintAndLogEx(SUCCESS, "Status Flag1... %s", sprint_hex(wr_noCry_resp.status_flags.status_flag1, sizeof(wr_noCry_resp.status_flags.status_flag1)));
PrintAndLogEx(SUCCESS, "Status Flag2: %s\n", sprint_hex(wr_noCry_resp.status_flags.status_flag2, sizeof(wr_noCry_resp.status_flags.status_flag2))); PrintAndLogEx(SUCCESS, "Status Flag2... %s\n", sprint_hex(wr_noCry_resp.status_flags.status_flag2, sizeof(wr_noCry_resp.status_flags.status_flag2)));
if (wr_noCry_resp.status_flags.status_flag1[0] == 0x00 && wr_noCry_resp.status_flags.status_flag2[0] == 0x00) { if (wr_noCry_resp.status_flags.status_flag1[0] == 0x00 && wr_noCry_resp.status_flags.status_flag2[0] == 0x00) {
PrintAndLogEx(SUCCESS, "Writing data successful!\n"); PrintAndLogEx(SUCCESS, "Writing data successful!");
} else { } else {
PrintAndLogEx(ERR, "Something went wrong! Check status flags.\n"); PrintAndLogEx(FAILED, "Something went wrong! Check status flags.");
} }
} }
return PM3_SUCCESS; return PM3_SUCCESS;
} }
@ -890,16 +970,16 @@ static int CmdHFFelicaWriteWithoutEncryption(const char *Cmd) {
* @param Cmd input data of the user. * @param Cmd input data of the user.
* @return client result code. * @return client result code.
*/ */
static int CmdHFFelicaReadWithoutEncryption(const char *Cmd) { static int CmdHFFelicaReadPlain(const char *Cmd) {
CLIParserContext *ctx; CLIParserContext *ctx;
CLIParserInit(&ctx, "hf felica rdunencrypted", CLIParserInit(&ctx, "hf felica rdbl",
"Use this command to read block data from authentication-not-required Service.\n\n" "Use this command to read block data from authentication-not-required Service.\n\n"
" - Mode shall be Mode0.\n" " - Mode shall be Mode0.\n"
" - Successful == block data\n" " - Successful == block data\n"
" - Unsuccessful == Status Flag1 and Flag2", " - Unsuccessful == Status Flag1 and Flag2",
"hf felica rdunencrypted --sn 01 --scl 8B00 --bn 01 --ble 8000\n" "hf felica rdbl --sn 01 --scl 8B00 --bn 01 --ble 8000\n"
"hf felica rdunencrypted --sn 01 --scl 4B18 --bn 01 --ble 8000 -b\n" "hf felica rdbl --sn 01 --scl 4B18 --bn 01 --ble 8000 -b\n"
"hf felica rdunencrypted -i 01100910c11bc407 --sn 01 --scl 8B00 --bn 01 --ble 8000\n" "hf felica rdbl -i 01100910c11bc407 --sn 01 --scl 8B00 --bn 01 --ble 8000\n"
); );
void *argtable[] = { void *argtable[] = {
arg_param_begin, arg_param_begin,
@ -972,6 +1052,7 @@ static int CmdHFFelicaReadWithoutEncryption(const char *Cmd) {
} }
uint8_t data[PM3_CMD_DATA_SIZE]; uint8_t data[PM3_CMD_DATA_SIZE];
memset(data, 0 , sizeof(data));
data[0] = 0x10; // Static length data[0] = 0x10; // Static length
data[1] = 0x06; // Command ID data[1] = 0x06; // Command ID
@ -1022,9 +1103,9 @@ static int CmdHFFelicaReadWithoutEncryption(const char *Cmd) {
AddCrc(data, datalen); AddCrc(data, datalen);
datalen += 2; datalen += 2;
felica_read_without_encryption_response_t rd_noCry_resp; felica_read_without_encryption_response_t rd_noCry_resp;
if ((send_rd_unencrypted(flags, datalen, data, 0, &rd_noCry_resp) == PM3_SUCCESS)) { if ((send_rd_plain(flags, datalen, data, 0, &rd_noCry_resp) == PM3_SUCCESS)) {
if (rd_noCry_resp.status_flags.status_flag1[0] == 0 && rd_noCry_resp.status_flags.status_flag2[0] == 0) { if (rd_noCry_resp.status_flags.status_flag1[0] == 0 && rd_noCry_resp.status_flags.status_flag2[0] == 0) {
print_rd_noEncrpytion_response(&rd_noCry_resp); print_rd_plain_response(&rd_noCry_resp);
} }
} else { } else {
break; break;
@ -1035,8 +1116,8 @@ static int CmdHFFelicaReadWithoutEncryption(const char *Cmd) {
AddCrc(data, datalen); AddCrc(data, datalen);
datalen += 2; datalen += 2;
felica_read_without_encryption_response_t rd_noCry_resp; felica_read_without_encryption_response_t rd_noCry_resp;
if (send_rd_unencrypted(flags, datalen, data, 1, &rd_noCry_resp) == PM3_SUCCESS) { if (send_rd_plain(flags, datalen, data, 1, &rd_noCry_resp) == PM3_SUCCESS) {
print_rd_noEncrpytion_response(&rd_noCry_resp); print_rd_plain_response(&rd_noCry_resp);
} }
} }
return PM3_SUCCESS; return PM3_SUCCESS;
@ -1073,6 +1154,7 @@ static int CmdHFFelicaRequestResponse(const char *Cmd) {
CLIParserFree(ctx); CLIParserFree(ctx);
uint8_t data[PM3_CMD_DATA_SIZE]; uint8_t data[PM3_CMD_DATA_SIZE];
memset(data, 0 , sizeof(data));
data[0] = 0x0A; // Static length data[0] = 0x0A; // Static length
data[1] = 0x04; // Command ID data[1] = 0x04; // Command ID
@ -1165,6 +1247,7 @@ static int CmdHFFelicaRequestSpecificationVersion(const char *Cmd) {
CLIParserFree(ctx); CLIParserFree(ctx);
uint8_t data[PM3_CMD_DATA_SIZE]; uint8_t data[PM3_CMD_DATA_SIZE];
memset(data, 0 , sizeof(data));
data[0] = 0x0C; // Static length data[0] = 0x0C; // Static length
data[1] = 0x3C; // Command ID data[1] = 0x3C; // Command ID
@ -1271,6 +1354,7 @@ static int CmdHFFelicaResetMode(const char *Cmd) {
CLIParserFree(ctx); CLIParserFree(ctx);
uint8_t data[PM3_CMD_DATA_SIZE]; uint8_t data[PM3_CMD_DATA_SIZE];
memset(data, 0 , sizeof(data));
data[0] = 0x0C; // Static length data[0] = 0x0C; // Static length
data[1] = 0x3E; // Command ID data[1] = 0x3E; // Command ID
@ -1348,6 +1432,7 @@ static int CmdHFFelicaRequestSystemCode(const char *Cmd) {
uint8_t data[PM3_CMD_DATA_SIZE]; uint8_t data[PM3_CMD_DATA_SIZE];
memset(data, 0 , sizeof(data));
data[0] = 0x0A; // Static length data[0] = 0x0A; // Static length
data[1] = 0x0C; // Command ID data[1] = 0x0C; // Command ID
@ -1448,6 +1533,8 @@ static int CmdHFFelicaRequestService(const char *Cmd) {
CLIParserFree(ctx); CLIParserFree(ctx);
uint8_t data[PM3_CMD_DATA_SIZE]; uint8_t data[PM3_CMD_DATA_SIZE];
memset(data, 0 , sizeof(data));
bool custom_IDm = false; bool custom_IDm = false;
if (ilen) { if (ilen) {
@ -1879,7 +1966,8 @@ static int CmdHFFelicaCmdRaw(const char *Cmd) {
CLIParserContext *ctx; CLIParserContext *ctx;
CLIParserInit(&ctx, "hf felica raw ", CLIParserInit(&ctx, "hf felica raw ",
"Send raw hex data to tag", "Send raw hex data to tag",
"hf felica raw -s 20" "hf felica raw -cs 20\n"
"hf felica raw -cs 2008"
); );
void *argtable[] = { void *argtable[] = {
@ -1904,7 +1992,9 @@ static int CmdHFFelicaCmdRaw(const char *Cmd) {
int datalen = 0; int datalen = 0;
uint8_t data[PM3_CMD_DATA_SIZE]; uint8_t data[PM3_CMD_DATA_SIZE];
CLIGetHexWithReturn(ctx, 6, data, &datalen); memset(data, 0 , sizeof(data));
CLIGetHexWithReturn(ctx, 7, data, &datalen);
CLIParserFree(ctx); CLIParserFree(ctx);
if (crc) { if (crc) {
@ -1961,8 +2051,8 @@ static command_t CommandTable[] = {
{"info", CmdHFFelicaInfo, IfPm3Felica, "Tag information"}, {"info", CmdHFFelicaInfo, IfPm3Felica, "Tag information"},
{"sniff", CmdHFFelicaSniff, IfPm3Felica, "Sniff ISO 18092/FeliCa traffic"}, {"sniff", CmdHFFelicaSniff, IfPm3Felica, "Sniff ISO 18092/FeliCa traffic"},
{"raw", CmdHFFelicaCmdRaw, IfPm3Felica, "Send raw hex data to tag"}, {"raw", CmdHFFelicaCmdRaw, IfPm3Felica, "Send raw hex data to tag"},
{"rdunencrypted", CmdHFFelicaReadWithoutEncryption, IfPm3Felica, "read Block Data from authentication-not-required Service."}, {"rdbl", CmdHFFelicaReadPlain, IfPm3Felica, "read block data from authentication-not-required Service."},
{"wrunencrypted", CmdHFFelicaWriteWithoutEncryption, IfPm3Felica, "write Block Data to an authentication-not-required Service."}, {"wrbl", CmdHFFelicaWritePlain, IfPm3Felica, "write block data to an authentication-not-required Service."},
{"-----------", CmdHelp, AlwaysAvailable, "----------------------- " _CYAN_("FeliCa Standard") " -----------------------"}, {"-----------", CmdHelp, AlwaysAvailable, "----------------------- " _CYAN_("FeliCa Standard") " -----------------------"},
//{"dump", CmdHFFelicaDump, IfPm3Felica, "Wait for and try dumping FeliCa"}, //{"dump", CmdHFFelicaDump, IfPm3Felica, "Wait for and try dumping FeliCa"},
{"rqservice", CmdHFFelicaRequestService, IfPm3Felica, "verify the existence of Area and Service, and to acquire Key Version."}, {"rqservice", CmdHFFelicaRequestService, IfPm3Felica, "verify the existence of Area and Service, and to acquire Key Version."},

View file

@ -7,8 +7,5 @@ hf 15 restore
hf 15 wrbl hf 15 wrbl
hf 15 writeafi hf 15 writeafi
hf 15 writedsfid hf 15 writedsfid
hf felica rdunencrypted
hf felica wrunencrypted
hf felica scsvcode
hf felica auth1 hf felica auth1
hf felica auth2 hf felica auth2

View file

@ -266,8 +266,8 @@ Check column "offline" for their availability.
|`hf felica info `|N |`Tag information` |`hf felica info `|N |`Tag information`
|`hf felica sniff `|N |`Sniff ISO 18092/FeliCa traffic` |`hf felica sniff `|N |`Sniff ISO 18092/FeliCa traffic`
|`hf felica raw `|N |`Send raw hex data to tag` |`hf felica raw `|N |`Send raw hex data to tag`
|`hf felica rdunencrypted`|N |`read Block Data from authentication-not-required Service.` |`hf felica rdbl `|N |`read block data from authentication-not-required Service.`
|`hf felica wrunencrypted`|N |`write Block Data to an authentication-not-required Service.` |`hf felica wrbl `|N |`write block data to an authentication-not-required Service.`
|`hf felica rqservice `|N |`verify the existence of Area and Service, and to acquire Key Version.` |`hf felica rqservice `|N |`verify the existence of Area and Service, and to acquire Key Version.`
|`hf felica rqresponse `|N |`verify the existence of a card and its Mode.` |`hf felica rqresponse `|N |`verify the existence of a card and its Mode.`
|`hf felica scsvcode `|N |`acquire Area Code and Service Code.` |`hf felica scsvcode `|N |`acquire Area Code and Service Code.`