Added hf iclass sam --info

Added hf iclass sam --info command that skips any card communication command and just interacts with the SAM to return:

1- Sam Firmware Version
2- Sam Firmware ID
3- Sam Serial Number
This commit is contained in:
Antiklesys 2025-06-11 01:06:38 +08:00
parent 0a4b67bd7e
commit 7fb5716ea3
5 changed files with 94 additions and 12 deletions

View file

@ -218,7 +218,7 @@ out:
*
* @return Status code indicating success or failure of the operation.
*/
int sam_get_version(void) {
int sam_get_version(bool info) {
int res = PM3_SUCCESS;
if (g_dbglevel >= DBG_DEBUG) {
@ -268,18 +268,18 @@ int sam_get_version(void) {
}
uint8_t *sam_version_an = sam_find_asn1_node(sam_response_an, 0x80);
if (sam_version_an == NULL) {
if (g_dbglevel >= DBG_ERROR) DbpString("SAM get version failed");
if (g_dbglevel >= DBG_ERROR) DbpString(_RED_("SAM: get version failed"));
goto error;
}
uint8_t *sam_build_an = sam_find_asn1_node(sam_response_an, 0x81);
if (sam_build_an == NULL) {
if (g_dbglevel >= DBG_ERROR) DbpString("SAM get firmware ID failed");
if (g_dbglevel >= DBG_ERROR) DbpString(_RED_("SAM: get firmware ID failed"));
goto error;
}
if (g_dbglevel >= DBG_INFO) {
DbpString("SAM get version successful");
Dbprintf("Firmware version: %X.%X", sam_version_an[2], sam_version_an[3]);
Dbprintf("Firmware ID: ");
if (g_dbglevel >= DBG_INFO || info) {
DbpString(_BLUE_("-- SAM Information --"));
Dbprintf(_YELLOW_("Firmware version: ")"%X.%X", sam_version_an[2], sam_version_an[3]);
Dbprintf(_YELLOW_("Firmware ID : "));
Dbhexdump(sam_build_an[1], sam_build_an + 2, false);
}
goto out;
@ -298,6 +298,75 @@ out:
return res;
}
int sam_get_serial_number(void) {
int res = PM3_SUCCESS;
if (g_dbglevel >= DBG_DEBUG) {
DbpString("start sam_get_serial_number");
}
uint8_t *response = BigBuf_calloc(ISO7816_MAX_FRAME);
uint16_t response_len = ISO7816_MAX_FRAME;
uint8_t payload[] = {
0xa0, 0x02, // <- SAM command
0x96, 0x00 // <- get serial number
};
uint16_t payload_len = sizeof(payload);
sam_send_payload(
0x44, 0x0a, 0x44,
payload,
&payload_len,
response,
&response_len
);
//resp:
//c1 64 00 00 00
// bd 0e <- SAM response
// 8a 0c <- get serial number response
// 61 01 13 51 22 66 6e 15 3e 1b ff ff
//90 00
if (g_dbglevel >= DBG_DEBUG) {
DbpString("end sam_get_serial_number");
}
if (response[5] != 0xbd) {
Dbprintf("Invalid SAM response");
goto error;
} else {
uint8_t *sam_response_an = sam_find_asn1_node(response + 5, 0x8a);
if (sam_response_an == NULL) {
if (g_dbglevel >= DBG_ERROR) DbpString(_RED_("SAM: get response failed"));
goto error;
}
uint8_t *sam_serial_an = sam_response_an + 2;
if (sam_serial_an == NULL) {
if (g_dbglevel >= DBG_ERROR) DbpString(_RED_("SAM get serial number failed"));
goto error;
}
Dbprintf(_YELLOW_("Sam Serial Number: "));
Dbhexdump(sam_response_an[1],sam_serial_an, false);
goto out;
}
error:
res = PM3_ESOFT;
out:
BigBuf_free();
if (g_dbglevel >= DBG_DEBUG) {
DbpString("end sam_get_serial_number");
}
return res;
}
/**

View file

@ -39,7 +39,8 @@ int sam_send_payload(
uint16_t *response_len
);
int sam_get_version(void);
int sam_get_version(bool info);
int sam_get_serial_number(void);
uint8_t *sam_find_asn1_node(const uint8_t *root, const uint8_t type);
void sam_append_asn1_node(const uint8_t *root, const uint8_t *node, uint8_t type, const uint8_t *const data, uint8_t len);

View file

@ -338,11 +338,14 @@ int sam_picopass_get_pacs(PacketCommandNG *c) {
const bool breakOnNrMac = !!(flags & BITMASK(2));
const bool preventEpurseUpdate = !!(flags & BITMASK(3));
const bool shallow_mod = !!(flags & BITMASK(4));
const bool info = !!(flags & BITMASK(5));
uint8_t *cmd = c->data.asBytes + 1;
uint16_t cmd_len = c->length - 1;
int res = PM3_EFAILED;
uint8_t sam_response[ISO7816_MAX_FRAME] = { 0x00 };
uint8_t sam_response_len = 0;
clear_trace();
I2C_Reset_EnterMainProgram();
@ -351,7 +354,12 @@ int sam_picopass_get_pacs(PacketCommandNG *c) {
StartTicks();
// step 1: ping SAM
sam_get_version();
sam_get_version(info);
if(info){
sam_get_serial_number();
goto out;
}
if (!skipDetect) {
// step 2: get card information
@ -371,8 +379,6 @@ int sam_picopass_get_pacs(PacketCommandNG *c) {
}
// step 3: SamCommand RequestPACS, relay NFC communication
uint8_t sam_response[ISO7816_MAX_FRAME] = { 0x00 };
uint8_t sam_response_len = 0;
res = sam_send_request_iso15(cmd, cmd_len, sam_response, &sam_response_len, shallow_mod, breakOnNrMac, preventEpurseUpdate);
if (res != PM3_SUCCESS) {
goto err;

View file

@ -282,7 +282,7 @@ int sam_seos_get_pacs(PacketCommandNG *c) {
StartTicks();
// step 1: ping SAM
sam_get_version();
sam_get_version(false);
if (skipDetect == false) {
// step 2: get card information

View file

@ -5904,6 +5904,7 @@ static int CmdHFiClassSAM(const char *Cmd) {
arg_lit0("p", "prevent", "fake epurse update"),
arg_lit0(NULL, "shallow", "shallow mod"),
arg_strx0("d", "data", "<hex>", "DER encoded command to send to SAM"),
arg_lit0(NULL, "info", "get SAM infos (version, serial number)"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, true);
@ -5915,6 +5916,7 @@ static int CmdHFiClassSAM(const char *Cmd) {
bool break_nrmac = arg_get_lit(ctx, 5);
bool prevent = arg_get_lit(ctx, 6);
bool shallow_mod = arg_get_lit(ctx, 7);
bool info = arg_get_lit(ctx, 9);
uint8_t flags = 0;
if (disconnect_after) {
@ -5937,6 +5939,10 @@ static int CmdHFiClassSAM(const char *Cmd) {
flags |= BITMASK(4);
}
if (info) {
flags |= BITMASK(5);
}
uint8_t data[PM3_CMD_DATA_SIZE] = {0};
data[0] = flags;