From 83c54bb174c981a48c5da952f5ec6beb487604be Mon Sep 17 00:00:00 2001 From: zinongli <131403964+zinongli@users.noreply.github.com> Date: Fri, 25 Jul 2025 23:47:00 -0400 Subject: [PATCH] initial working for single node --- client/src/cmdhffelica.c | 74 ++++++++++++++++++++++++++++++++++++++-- client/src/cmdhffelica.h | 1 + include/iso18.h | 5 +++ 3 files changed, 77 insertions(+), 3 deletions(-) diff --git a/client/src/cmdhffelica.c b/client/src/cmdhffelica.c index 619f09da2..a498d492c 100644 --- a/client/src/cmdhffelica.c +++ b/client/src/cmdhffelica.c @@ -531,6 +531,28 @@ int send_rd_plain(uint8_t flags, uint16_t datalen, uint8_t *data, bool verbose, } } +/** + * Sends a dump_service frame to the pm3 and prints response. + * @param flags to use for pm3 communication. + * @param datalen frame length. + * @param data frame to be send. + * @param verbose display additional output. + * @param dump_sv_resp frame in which the response will be saved. + * @param is_area true if the service is an area, false if it is a service. + * @return success if response was received. + */ +int send_dump_sv_plain(uint8_t flags, uint16_t datalen, uint8_t *data, bool verbose, felica_service_dump_response_t *dump_sv_resp, bool is_area) { + clear_and_send_command(flags, datalen, data, verbose); + PacketResponseNG resp; + if (waitCmdFelica(false, &resp, verbose) == false) { + PrintAndLogEx(ERR, "No response from card"); + return PM3_ERFTRANS; + } else { + memcpy(dump_sv_resp, (felica_service_dump_response_t *)resp.data.asBytes, sizeof(felica_service_dump_response_t)); + return PM3_SUCCESS; + } +} + /** * Checks if last known card can be added to data and adds it if possible. * @param custom_IDm @@ -1743,18 +1765,64 @@ static int CmdHFFelicaRequestService(const char *Cmd) { return PM3_SUCCESS; } -static int CmdHFFelicaNotImplementedYet(const char *Cmd) { +static int CmdHFFelicaDumpServiceArea(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf felica scsvcode", - "Feature not implemented yet. Feel free to contribute!", + "Dump all existing Area Code and Service Code.\n", "hf felica scsvcode" ); void *argtable[] = { arg_param_begin, arg_param_end }; - CLIExecWithReturn(ctx, Cmd, argtable, false); + + CLIExecWithReturn(ctx, Cmd, argtable, true); CLIParserFree(ctx); + + + uint8_t data[PM3_CMD_DATA_SIZE]; + memset(data, 0, sizeof(data)); + data[0] = 0x0C; // Static length + data[1] = 0x0A; // Command ID + + uint16_t datalen = 12; // Length (1), Command ID (1), IDm (8), Cursor Node (2) + if (check_last_idm(data, datalen) == false) { + return PM3_EINVARG; + } + + uint8_t flags = (FELICA_APPEND_CRC | FELICA_RAW); + + // for each cursor stuff RFU + data[10] = 0x00; // Cursor Node + data[11] = 0x00; // Cursor Node + + AddCrc(data, datalen); + + felica_service_dump_response_t dump_sv_resp; + bool is_area = false; + + if ((send_dump_sv_plain(flags, datalen + 2, data, 0, &dump_sv_resp, is_area) == PM3_SUCCESS)) { + if (dump_sv_resp.frame_response.cmd_code[0] != 0x0B) { + PrintAndLogEx(ERR, "Return command wrong. \nExpected 0x0B, got 0x%02X", dump_sv_resp.frame_response.cmd_code[0]); + return PM3_ERFTRANS; + } else { + if (dump_sv_resp.frame_response.length[0] == 0x0C) { + // service code read + PrintAndLogEx(SUCCESS, "Service Code Read 0x%02X%02X", dump_sv_resp.payload[0], dump_sv_resp.payload[1]); + } else if (dump_sv_resp.frame_response.length[0] == 0x0E) { + // service code read with area (this current parsing is wrong.) + PrintAndLogEx(SUCCESS, "Service Code Read 0x%02X%02X Area 0x%02X%02X", dump_sv_resp.payload[0], dump_sv_resp.payload[1], dump_sv_resp.payload[2], dump_sv_resp.payload[3]); + } else { + PrintAndLogEx(ERR, "Something went wrong, check your card"); + return PM3_ERFTRANS; + + } + } + } else { + PrintAndLogEx(ERR, "Something went wrong, check your card"); + return PM3_ERFTRANS; + } + return PM3_SUCCESS; } diff --git a/client/src/cmdhffelica.h b/client/src/cmdhffelica.h index 9cb524814..6ab42aa36 100644 --- a/client/src/cmdhffelica.h +++ b/client/src/cmdhffelica.h @@ -26,5 +26,6 @@ int CmdHFFelica(const char *Cmd); int read_felica_uid(bool loop, bool verbose); int send_request_service(uint8_t flags, uint16_t datalen, uint8_t *data, bool verbose); int send_rd_plain(uint8_t flags, uint16_t datalen, uint8_t *data, bool verbose, felica_read_without_encryption_response_t *rd_noCry_resp); +int send_dump_sv_plain(uint8_t flags, uint16_t datalen, uint8_t *data, bool verbose, felica_service_dump_response_t *dump_sv_resp, bool is_area); #endif diff --git a/include/iso18.h b/include/iso18.h index 377f864d0..5446c74eb 100644 --- a/include/iso18.h +++ b/include/iso18.h @@ -124,4 +124,9 @@ typedef struct { uint8_t PMi[8]; } PACKED felica_auth2_response_t; +typedef struct { + felica_frame_response_t frame_response; + uint8_t payload[4]; +} PACKED felica_service_dump_response_t; + #endif // _ISO18_H_