From 7fb5716ea346a22682b8db45ab66c1fd6e8a70c8 Mon Sep 17 00:00:00 2001 From: Antiklesys Date: Wed, 11 Jun 2025 01:06:38 +0800 Subject: [PATCH 1/2] 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 --- armsrc/sam_common.c | 83 ++++++++++++++++++++++++++++++++++++---- armsrc/sam_common.h | 3 +- armsrc/sam_picopass.c | 12 ++++-- armsrc/sam_seos.c | 2 +- client/src/cmdhficlass.c | 6 +++ 5 files changed, 94 insertions(+), 12 deletions(-) diff --git a/armsrc/sam_common.c b/armsrc/sam_common.c index d104148ff..38c2f3c1f 100644 --- a/armsrc/sam_common.c +++ b/armsrc/sam_common.c @@ -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; +} + /** diff --git a/armsrc/sam_common.h b/armsrc/sam_common.h index 1c3a88e88..4cc6e364f 100644 --- a/armsrc/sam_common.h +++ b/armsrc/sam_common.h @@ -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); diff --git a/armsrc/sam_picopass.c b/armsrc/sam_picopass.c index d22985e49..29fd1797b 100644 --- a/armsrc/sam_picopass.c +++ b/armsrc/sam_picopass.c @@ -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; diff --git a/armsrc/sam_seos.c b/armsrc/sam_seos.c index 04bc128a2..3f8c806e9 100644 --- a/armsrc/sam_seos.c +++ b/armsrc/sam_seos.c @@ -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 diff --git a/client/src/cmdhficlass.c b/client/src/cmdhficlass.c index 16899893e..a21d9c3ee 100644 --- a/client/src/cmdhficlass.c +++ b/client/src/cmdhficlass.c @@ -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", "", "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; From 5b7e013f1a8d94c0d7e453402b47e9c6552f69d1 Mon Sep 17 00:00:00 2001 From: Antiklesys Date: Wed, 11 Jun 2025 01:08:03 +0800 Subject: [PATCH 2/2] Update CHANGELOG.md --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a5b665025..5bc6c5474 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,10 +11,11 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac - Fix `hf mf eview` - now viewing 2k, 4k cards doesn't get wrong background color (@iceman1001) - Changed `hf mf info` - skip checking if it detects a MIFARE Ultralight family card (@iceman1001) - Changed `hf mf rdsc` - it now addeds the used key to the output in the sector trailer (@iceman1001) -- Added the `PM3ULTIMATE` platform in the build / docs. *untested* (@iceman1001) +- Added the `PM3ULTIMATE` platform in the build / docs. *untested* (@iceman1001) - Added fpga compilation for PM3ULTIMATE device (@n-hutton) - Updated the ATR list (@iceman1001) - Fixed fpga binary images to use fixed seed 2 (@n-hutton) +- Added `hf iclass sam --info` - option that returns sam specific details (@antiklesys) - Changed `hf iclass sim -t 7` - implemented simulation that glitches key block responses (@antiklesys) - Changed `hf iclass sim -t 6` - implemented simulation that glitches sio block (@antiklesys) - Changed `hf iclass legbrute` - implemented multithreading support (@antiklesys)