Skip to content

Commit f93c997

Browse files
committed
hf 14a info: add ATR fingerprinting
1 parent 7a81838 commit f93c997

File tree

6 files changed

+79
-59
lines changed

6 files changed

+79
-59
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file.
33
This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log...
44

55
## [unreleased][unreleased]
6+
- Added ATR fingerprinting to `hf 14a info` (@doegox)
67

78
## [Phrack.4.20728][2025-09-11]
89
- Change `lf t55xx restore` - now skips writing block0 if its all zeros (@iceman1001)

client/atr_scrap_pcsctools.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,13 +48,16 @@
4848
4949
#define ATRS_H__
5050
#include <stddef.h>
51+
#include <stdint.h>
5152
5253
typedef struct atr_s {
5354
const char *bytes;
5455
const char *desc;
5556
} atr_t;
5657
5758
const char *getAtrInfo(const char *atr_str);
59+
void atsToEmulatedAtr(uint8_t *ats, uint8_t *atr, int *atrLen);
60+
void atqbToEmulatedAtr(uint8_t *atqb, uint8_t cid, uint8_t *atr, int *atrLen);
5861
5962
// atr_t array is expected to be NULL terminated
6063
const static atr_t AtrTable[] = {

client/src/atrs.c

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,3 +67,62 @@ const char *getAtrInfo(const char *atr_str) {
6767
return AtrTable[ARRAYLEN(AtrTable) - 1].desc;
6868
}
6969
}
70+
71+
void atsToEmulatedAtr(uint8_t *ats, uint8_t *atr, int *atrLen) {
72+
uint8_t historicalLen = 0;
73+
uint8_t offset = 2;
74+
75+
if (ats[0] < 2) {
76+
historicalLen = 0;
77+
} else {
78+
79+
if ((ats[1] & 64) != 0) {
80+
offset++;
81+
}
82+
if ((ats[1] & 32) != 0) {
83+
offset++;
84+
}
85+
if ((ats[1] & 16) != 0) {
86+
offset++;
87+
}
88+
89+
if (offset >= ats[0]) {
90+
historicalLen = 0;
91+
} else {
92+
historicalLen = ats[0] - offset;
93+
}
94+
}
95+
96+
atr[0] = 0x3B;
97+
atr[1] = 0x80 | historicalLen;
98+
atr[2] = 0x80;
99+
atr[3] = 0x01;
100+
101+
uint8_t tck = atr[1] ^ atr[2] ^ atr[3];
102+
for (uint8_t i = 0; i < historicalLen; ++i) {
103+
atr[4 + i] = ats[offset + i];
104+
tck = tck ^ ats[offset + i];
105+
}
106+
atr[4 + historicalLen] = tck;
107+
108+
*atrLen = 5 + historicalLen;
109+
}
110+
111+
void atqbToEmulatedAtr(uint8_t *atqb, uint8_t cid, uint8_t *atr, int *atrLen) {
112+
atr[0] = 0x3B;
113+
atr[1] = 0x80 | 8;
114+
atr[2] = 0x80;
115+
atr[3] = 0x01;
116+
117+
memcpy(atr + 4, atqb, 7);
118+
atr[11] = cid >> 4;
119+
120+
uint8_t tck = 0;
121+
for (int i = 1; i < 12; ++i) {
122+
tck = tck ^ atr[i];
123+
}
124+
atr[12] = tck;
125+
126+
*atrLen = 13;
127+
}
128+

client/src/atrs.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,16 @@
2323

2424
#define ATRS_H__
2525
#include <stddef.h>
26+
#include <stdint.h>
2627

2728
typedef struct atr_s {
2829
const char *bytes;
2930
const char *desc;
3031
} atr_t;
3132

3233
const char *getAtrInfo(const char *atr_str);
34+
void atsToEmulatedAtr(uint8_t *ats, uint8_t *atr, int *atrLen);
35+
void atqbToEmulatedAtr(uint8_t *atqb, uint8_t cid, uint8_t *atr, int *atrLen);
3336

3437
// atr_t array is expected to be NULL terminated
3538
const static atr_t AtrTable[] = {

client/src/cmdhf14a.c

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2946,7 +2946,7 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) {
29462946
if ((card.ats[0] > pos) && (card.ats_len >= card.ats[0] + 2)) {
29472947
uint8_t calen = card.ats[0] - pos;
29482948
PrintAndLogEx(NORMAL, "");
2949-
PrintAndLogEx(INFO, "-------------------- " _CYAN_("Historical bytes") " ----------------------------");
2949+
PrintAndLogEx(INFO, "-------------------- " _CYAN_("Historical bytes") " ---------------------------");
29502950

29512951
if (card.ats[pos] == 0xC1) {
29522952
PrintAndLogEx(INFO, " %s", sprint_hex(card.ats + pos, calen));
@@ -3024,6 +3024,18 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) {
30243024
, sprint_ascii(card.ats + pos, calen)
30253025
);
30263026
}
3027+
PrintAndLogEx(NORMAL, "");
3028+
PrintAndLogEx(INFO, "------------------ " _CYAN_("ATR fingerprinting") " ---------------------------");
3029+
uint8_t atr[256] = {0};
3030+
int atrLen = 0;
3031+
atsToEmulatedAtr(card.ats, atr, &atrLen);
3032+
char *copy = str_dup(getAtrInfo(sprint_hex_inrow(atr, atrLen)));
3033+
char *token = strtok(copy, "\n");
3034+
while (token != NULL) {
3035+
PrintAndLogEx(INFO, " %s", token);
3036+
token = strtok(NULL, "\n");
3037+
}
3038+
free(copy);
30273039
}
30283040
}
30293041
}

client/src/cmdsmartcard.c

Lines changed: 0 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -1212,64 +1212,6 @@ static int CmdSmartBruteforceSFI(const char *Cmd) {
12121212
return PM3_SUCCESS;
12131213
}
12141214

1215-
static void atsToEmulatedAtr(uint8_t *ats, uint8_t *atr, int *atrLen) {
1216-
uint8_t historicalLen = 0;
1217-
uint8_t offset = 2;
1218-
1219-
if (ats[0] < 2) {
1220-
historicalLen = 0;
1221-
} else {
1222-
1223-
if ((ats[1] & 64) != 0) {
1224-
offset++;
1225-
}
1226-
if ((ats[1] & 32) != 0) {
1227-
offset++;
1228-
}
1229-
if ((ats[1] & 16) != 0) {
1230-
offset++;
1231-
}
1232-
1233-
if (offset >= ats[0]) {
1234-
historicalLen = 0;
1235-
} else {
1236-
historicalLen = ats[0] - offset;
1237-
}
1238-
}
1239-
1240-
atr[0] = 0x3B;
1241-
atr[1] = 0x80 | historicalLen;
1242-
atr[2] = 0x80;
1243-
atr[3] = 0x01;
1244-
1245-
uint8_t tck = atr[1] ^ atr[2] ^ atr[3];
1246-
for (uint8_t i = 0; i < historicalLen; ++i) {
1247-
atr[4 + i] = ats[offset + i];
1248-
tck = tck ^ ats[offset + i];
1249-
}
1250-
atr[4 + historicalLen] = tck;
1251-
1252-
*atrLen = 5 + historicalLen;
1253-
}
1254-
1255-
static void atqbToEmulatedAtr(uint8_t *atqb, uint8_t cid, uint8_t *atr, int *atrLen) {
1256-
atr[0] = 0x3B;
1257-
atr[1] = 0x80 | 8;
1258-
atr[2] = 0x80;
1259-
atr[3] = 0x01;
1260-
1261-
memcpy(atr + 4, atqb, 7);
1262-
atr[11] = cid >> 4;
1263-
1264-
uint8_t tck = 0;
1265-
for (int i = 1; i < 12; ++i) {
1266-
tck = tck ^ atr[i];
1267-
}
1268-
atr[12] = tck;
1269-
1270-
*atrLen = 13;
1271-
}
1272-
12731215
static int CmdPCSC(const char *Cmd) {
12741216
CLIParserContext *ctx;
12751217
CLIParserInit(&ctx, "smart pcsc",

0 commit comments

Comments
 (0)