mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-19 13:00:42 -07:00
Add felica request service all nodes command.
Make style.
This commit is contained in:
parent
6144e2d09b
commit
3f56116615
5 changed files with 71 additions and 45 deletions
|
@ -26,7 +26,7 @@
|
||||||
static int CmdHelp(const char *Cmd);
|
static int CmdHelp(const char *Cmd);
|
||||||
static felica_card_select_t last_known_card;
|
static felica_card_select_t last_known_card;
|
||||||
|
|
||||||
static void set_last_known_card(felica_card_select_t card){
|
static void set_last_known_card(felica_card_select_t card) {
|
||||||
last_known_card = card;
|
last_known_card = card;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -97,7 +97,10 @@ static int usage_hf_felica_request_service(void) {
|
||||||
PrintAndLogEx(NORMAL, "\nUsage: hf felica rqservice [-h] [-i] <01 Number of Node hex> <0A 0B Node Code List hex (Little Endian)>");
|
PrintAndLogEx(NORMAL, "\nUsage: hf felica rqservice [-h] [-i] <01 Number of Node hex> <0A 0B Node Code List hex (Little Endian)>");
|
||||||
PrintAndLogEx(NORMAL, " -h this help");
|
PrintAndLogEx(NORMAL, " -h this help");
|
||||||
PrintAndLogEx(NORMAL, " -i <0A 0B 0C ... hex> set custom IDm to use");
|
PrintAndLogEx(NORMAL, " -i <0A 0B 0C ... hex> set custom IDm to use");
|
||||||
PrintAndLogEx(NORMAL, "\nExample: hf felica rqservice 01 FFFF \n\n");
|
PrintAndLogEx(NORMAL, "\nExamples: hf felica rqservice 01 FF FF");
|
||||||
|
PrintAndLogEx(NORMAL, " hf felica rqservice 01 FF FF");
|
||||||
|
PrintAndLogEx(NORMAL, " hf felica rqs -a FF FF");
|
||||||
|
PrintAndLogEx(NORMAL, " hf felica rqs -i 01 10 09 10 c1 1b c4 07 01 FF FF \n\n");
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -109,7 +112,7 @@ static bool waitCmdFelica(uint8_t iSelect, PacketResponseNG *resp) {
|
||||||
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);
|
||||||
PrintAndLogEx(NORMAL, "Client Received %i octets", len);
|
PrintAndLogEx(NORMAL, "Client Received %i octets", len);
|
||||||
if (!len || len < 2){
|
if (!len || len < 2) {
|
||||||
PrintAndLogEx(ERR, "Could not receive data correctly!");
|
PrintAndLogEx(ERR, "Could not receive data correctly!");
|
||||||
}
|
}
|
||||||
PrintAndLogEx(NORMAL, "%s", sprint_hex(resp->data.asBytes, len));
|
PrintAndLogEx(NORMAL, "%s", sprint_hex(resp->data.asBytes, len));
|
||||||
|
@ -150,7 +153,7 @@ static bool is_hex_input(const char *Cmd, int i) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add crc bytes to the end of the given data.
|
* Add crc bytes to the end of the given data and increments datalen.
|
||||||
* @param datalen length of the data frame.
|
* @param datalen length of the data frame.
|
||||||
* @param data frame on which the crc is calculated.
|
* @param data frame on which the crc is calculated.
|
||||||
* @param size of the data.
|
* @param size of the data.
|
||||||
|
@ -189,7 +192,7 @@ static void get_cmd_data(const char *Cmd, uint16_t *datalen, uint8_t *data, char
|
||||||
* @param number number of hex bytes.
|
* @param number number of hex bytes.
|
||||||
* @return number as hex value.
|
* @return number as hex value.
|
||||||
*/
|
*/
|
||||||
static uint8_t int_to_hex(uint16_t *number){
|
static uint8_t int_to_hex(uint16_t *number) {
|
||||||
uint32_t hex;
|
uint32_t hex;
|
||||||
char dataLengthChar[5];
|
char dataLengthChar[5];
|
||||||
sprintf(dataLengthChar, "%x", *number);
|
sprintf(dataLengthChar, "%x", *number);
|
||||||
|
@ -203,14 +206,14 @@ static uint8_t int_to_hex(uint16_t *number){
|
||||||
* @param data frame in where the IDM is added.
|
* @param data frame in where the IDM is added.
|
||||||
* @return true if IDm was added;
|
* @return true if IDm was added;
|
||||||
*/
|
*/
|
||||||
static bool add_last_IDm(uint8_t position, uint8_t *data){
|
static bool add_last_IDm(uint8_t position, uint8_t *data) {
|
||||||
if(last_known_card.IDm[0] != 0 && last_known_card.IDm[1] != 0){
|
if (last_known_card.IDm[0] != 0 && last_known_card.IDm[1] != 0) {
|
||||||
for(int i = 0; i < 8; i++){
|
for (int i = 0; i < 8; i++) {
|
||||||
uint16_t number = (uint16_t)last_known_card.IDm[i];
|
uint16_t number = (uint16_t)last_known_card.IDm[i];
|
||||||
data[position+i] = int_to_hex(&number);
|
data[position + i] = int_to_hex(&number);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}else{
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -242,6 +245,32 @@ static int CmdHFFelicaDump(const char *Cmd) {
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends a request service frame to the pm3.
|
||||||
|
*/
|
||||||
|
void send_request_service(uint8_t flags, uint16_t datalen, uint8_t *data) {
|
||||||
|
uint16_t numbits = 0;
|
||||||
|
clearCommandBuffer();
|
||||||
|
PrintAndLogEx(NORMAL, "Send Service Request Frame: %s", sprint_hex(data, datalen));
|
||||||
|
SendCommandMIX(CMD_HF_FELICA_COMMAND, flags, (datalen & 0xFFFF) | (uint32_t)(numbits << 16), 0, data, datalen);
|
||||||
|
PacketResponseNG resp;
|
||||||
|
if (datalen > 0) {
|
||||||
|
if (!waitCmdFelica(0, &resp)) {
|
||||||
|
PrintAndLogEx(ERR, "\nGot no Response from card");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
felica_request_service_response_t rqs_response;
|
||||||
|
memcpy(&rqs_response, (felica_request_service_response_t *)resp.data.asBytes, sizeof(felica_request_service_response_t));
|
||||||
|
|
||||||
|
if (rqs_response.IDm[0] != 0) {
|
||||||
|
PrintAndLogEx(SUCCESS, "\nGot Service Response:");
|
||||||
|
PrintAndLogEx(NORMAL, "IDm: %s", sprint_hex(rqs_response.IDm, sizeof(rqs_response.IDm)));
|
||||||
|
PrintAndLogEx(NORMAL, " -Node Number: %s", sprint_hex(rqs_response.node_number, sizeof(rqs_response.node_number)));
|
||||||
|
PrintAndLogEx(NORMAL, " -Node Key Version List: %s\n", sprint_hex(rqs_response.node_key_versions, sizeof(rqs_response.node_key_versions)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Command parser for rqservice.
|
* Command parser for rqservice.
|
||||||
* @param Cmd input data of the user.
|
* @param Cmd input data of the user.
|
||||||
|
@ -252,23 +281,29 @@ static int CmdHFFelicaRequestService(const char *Cmd) {
|
||||||
int i = 0;
|
int i = 0;
|
||||||
uint8_t data[PM3_CMD_DATA_SIZE];
|
uint8_t data[PM3_CMD_DATA_SIZE];
|
||||||
bool custom_IDm = false;
|
bool custom_IDm = false;
|
||||||
|
bool all_nodes = false;
|
||||||
uint16_t datalen = 0;
|
uint16_t datalen = 0;
|
||||||
uint8_t flags = 0;
|
uint8_t flags = 0;
|
||||||
uint16_t numbits = 0;
|
|
||||||
char buf[5] = "";
|
char buf[5] = "";
|
||||||
datalen += 10; // length (1) + CMD (1) + IDm (8)
|
datalen += 10; // length (1) + CMD (1) + IDm(8)
|
||||||
strip_cmds(Cmd);
|
strip_cmds(Cmd);
|
||||||
while (Cmd[i] != '\0') {
|
while (Cmd[i] != '\0') {
|
||||||
if (Cmd[i] == '-') {
|
if (Cmd[i] == '-') {
|
||||||
switch (Cmd[i + 1]) {
|
switch (Cmd[i + 1]) {
|
||||||
case 'H':
|
case 'H':
|
||||||
case 'h':
|
case 'h':
|
||||||
return usage_hf_felica_raw();
|
return usage_hf_felica_request_service();
|
||||||
case 'i':
|
case 'i':
|
||||||
custom_IDm = true;
|
custom_IDm = true;
|
||||||
|
datalen -= 8;
|
||||||
|
break;
|
||||||
|
case 'a':
|
||||||
|
all_nodes = true;
|
||||||
|
datalen += 1;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return usage_hf_felica_raw();
|
return usage_hf_felica_request_service();
|
||||||
}
|
}
|
||||||
i += 2;
|
i += 2;
|
||||||
}
|
}
|
||||||
|
@ -290,38 +325,28 @@ static int CmdHFFelicaRequestService(const char *Cmd) {
|
||||||
flags |= FELICA_RAW;
|
flags |= FELICA_RAW;
|
||||||
}
|
}
|
||||||
datalen = (datalen > PM3_CMD_DATA_SIZE) ? PM3_CMD_DATA_SIZE : datalen;
|
datalen = (datalen > PM3_CMD_DATA_SIZE) ? PM3_CMD_DATA_SIZE : datalen;
|
||||||
if(!custom_IDm){
|
if (!custom_IDm) {
|
||||||
if(!add_last_IDm(2, data)){
|
if (!add_last_IDm(2, data)) {
|
||||||
PrintAndLogEx(ERR, "No last known card! Use reader first or set a custom IDm!");
|
PrintAndLogEx(ERR, "No last known card! Use reader first or set a custom IDm!");
|
||||||
return PM3_EINVARG;
|
return PM3_EINVARG;
|
||||||
}else{
|
} else {
|
||||||
PrintAndLogEx(INFO, "Used last known IDm.", sprint_hex(data, datalen));
|
PrintAndLogEx(INFO, "Used last known IDm.", sprint_hex(data, datalen));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
data[0] = int_to_hex(&datalen);
|
data[0] = int_to_hex(&datalen);
|
||||||
data[1] = 0x02; // Request Command ID
|
data[1] = 0x02; // Request Command ID
|
||||||
|
if (all_nodes) {
|
||||||
|
for (uint16_t y = 1; y < 32; y++) {
|
||||||
|
data[10] = int_to_hex(&y);
|
||||||
add_crc_bytes(&datalen, data, sizeof(data));
|
add_crc_bytes(&datalen, data, sizeof(data));
|
||||||
PrintAndLogEx(NORMAL, "Send Service Request Frame: %s", sprint_hex(data, datalen));
|
send_request_service(flags, datalen, data);
|
||||||
clearCommandBuffer();
|
datalen -= 2; // Remove CRC bytes before adding new ones
|
||||||
SendCommandMIX(CMD_HF_FELICA_COMMAND, flags, (datalen & 0xFFFF) | (uint32_t)(numbits << 16), 0, data, datalen);
|
|
||||||
PacketResponseNG resp;
|
|
||||||
if (custom_IDm) {
|
|
||||||
waitCmdFelica(1, &resp);
|
|
||||||
}
|
}
|
||||||
if (datalen > 0) {
|
} else {
|
||||||
if(!waitCmdFelica(0, &resp)){
|
add_crc_bytes(&datalen, data, sizeof(data));
|
||||||
return PM3_ESOFT;
|
send_request_service(flags, datalen, data);
|
||||||
}
|
}
|
||||||
felica_request_service_response_t rqs_response;
|
|
||||||
memcpy(&rqs_response, (felica_request_service_response_t *)resp.data.asBytes, sizeof(felica_request_service_response_t));
|
|
||||||
|
|
||||||
PrintAndLogEx(SUCCESS, "\nGot Service Response:");
|
|
||||||
PrintAndLogEx(NORMAL, "IDm: %s", sprint_hex(rqs_response.IDm, sizeof(rqs_response.IDm)));
|
|
||||||
PrintAndLogEx(NORMAL, " -Node Number: %s", sprint_hex(rqs_response.node_number, sizeof(rqs_response.node_number)));
|
|
||||||
PrintAndLogEx(NORMAL, " -Node Key Version List: %s\n", sprint_hex(rqs_response.node_key_versions, sizeof(rqs_response.node_key_versions)));
|
|
||||||
}else{
|
|
||||||
return PM3_ESOFT;
|
|
||||||
}
|
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,4 +15,5 @@
|
||||||
|
|
||||||
int CmdHFFelica(const char *Cmd);
|
int CmdHFFelica(const char *Cmd);
|
||||||
int readFelicaUid(bool verbose);
|
int readFelicaUid(bool verbose);
|
||||||
|
void send_request_service(uint8_t flags, uint16_t datalen, uint8_t *data);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -170,7 +170,7 @@ typedef struct {
|
||||||
} PACKED felica_card_select_t;
|
} PACKED felica_card_select_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8_t sync[4];
|
uint8_t sync[2];
|
||||||
uint8_t length[1];
|
uint8_t length[1];
|
||||||
uint8_t cmd_code[1];
|
uint8_t cmd_code[1];
|
||||||
uint8_t IDm[8];
|
uint8_t IDm[8];
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue