mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-02-22 23:24:22 +08:00
Add hf gallagher delete
command
This commit is contained in:
parent
28437f018b
commit
81da8a1317
1 changed files with 169 additions and 9 deletions
|
@ -116,6 +116,7 @@ static int authenticate(DesfireContext_t *ctx, bool verbose) {
|
|||
// TODO: do these both need to be set?
|
||||
DesfireSetCommMode(ctx, DCMPlain);
|
||||
DesfireSetCommandSet(ctx, DCCNativeISO);
|
||||
DesfireClearSession(ctx);
|
||||
|
||||
int res = DesfireAuthenticate(ctx, DACEV1, false);
|
||||
if (res != PM3_SUCCESS) {
|
||||
|
@ -295,7 +296,7 @@ static int readCard(uint32_t aid, uint8_t *sitekey, bool verbose, bool quiet) {
|
|||
numEntries = 1;
|
||||
} else {
|
||||
res = readCardApplicationDirectory(&dctx, cad, ARRAYLEN(cad), &numEntries, verbose);
|
||||
HFGAL_RET_IF_ERR_MAYBE_MSG(res, !quiet, "Failed reading card application directory");
|
||||
HFGAL_RET_IF_ERR_MAYBE_MSG(res, !quiet, "Failed reading Card Application Directory");
|
||||
}
|
||||
|
||||
// Loop through each application in the CAD
|
||||
|
@ -375,6 +376,28 @@ static int CmdGallagherReader(const char *Cmd) {
|
|||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Delete the CAD or an application that contains cardholder credentials.
|
||||
*
|
||||
* @param sitekey MIFARE site key.
|
||||
* @param aid Application ID to remove.
|
||||
*/
|
||||
static int deleteGallagherApplication(DesfireContext_t *ctx, uint8_t *sitekey, uint32_t aid, bool verbose) {
|
||||
// Select application & authenticate
|
||||
DesfireSetKeyNoClear(ctx, 0, T_AES, sitekey);
|
||||
DesfireSetKdf(ctx, MFDES_KDF_ALGO_GALLAGHER, NULL, 0);
|
||||
int res = selectAidAndAuthenticate(ctx, aid, verbose);
|
||||
HFGAL_RET_IF_ERR(res);
|
||||
|
||||
// Delete application
|
||||
DesfireSetCommMode(ctx, DCMMACed);
|
||||
res = DesfireDeleteApplication(ctx, aid);
|
||||
HFGAL_RET_IF_ERR_WITH_MSG(res, "Failed deleting AID %06X", aid);
|
||||
|
||||
PrintAndLogEx(INFO, "Successfully deleted AID %06X", aid);
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Create a new application to store Gallagher cardholder credentials.
|
||||
*
|
||||
|
@ -556,7 +579,7 @@ static int createGallagherCAD(DesfireContext_t *ctx, uint8_t *sitekey, bool verb
|
|||
* @param aid Application ID to add to the CAD.
|
||||
* @param creds Gallagher cardholder credentials (region_code & facility_code are required).
|
||||
*/
|
||||
static int updateGallagherCAD(DesfireContext_t *ctx, uint8_t *sitekey, uint32_t aid, GallagherCredentials_t *creds, bool verbose) {
|
||||
static int addToGallagherCAD(DesfireContext_t *ctx, uint8_t *sitekey, uint32_t aid, GallagherCredentials_t *creds, bool verbose) {
|
||||
// Check if CAD exists
|
||||
uint8_t cad[36 * 3] = {0};
|
||||
uint8_t numEntries = 0;
|
||||
|
@ -630,17 +653,87 @@ static int updateGallagherCAD(DesfireContext_t *ctx, uint8_t *sitekey, uint32_t
|
|||
PrintAndLogEx(INFO, "Created file %d in CAD (currently has empty contents)", fileId);
|
||||
|
||||
// Write file
|
||||
res = DesfireWriteFile(ctx, fileId, 0, 36, entry);
|
||||
} else {
|
||||
res = DesfireWriteFile(ctx, fileId, 0, 36, &cad[fileId * 36]);
|
||||
} else
|
||||
// Write file
|
||||
res = DesfireWriteFile(ctx, fileId, entryNum * 6, 6, entry);
|
||||
}
|
||||
HFGAL_RET_IF_ERR_WITH_MSG(res, "Failed writing data to file %d in CAD (AID %06X)", fileId, CAD_AID);
|
||||
|
||||
PrintAndLogEx(INFO, "Successfully added new entry for %06X to the Card Application Directory", aid);
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Remove an entry from the Gallagher Card Application Directory.
|
||||
*
|
||||
* @param sitekey MIFARE site key.
|
||||
* @param aid Application ID to add to the CAD.
|
||||
*/
|
||||
static int removeFromGallagherCAD(DesfireContext_t *ctx, uint8_t *sitekey, uint32_t aid, bool verbose) {
|
||||
// Check if CAD exists
|
||||
uint8_t cad[36 * 3] = {0};
|
||||
uint8_t numEntries = 0;
|
||||
|
||||
int res = readCardApplicationDirectory(ctx, cad, ARRAYLEN(cad), &numEntries, verbose);
|
||||
HFGAL_RET_IF_ERR(res);
|
||||
|
||||
// Check if facility already exists in CAD
|
||||
uint8_t entryNum = 0;
|
||||
for (; entryNum < numEntries; entryNum++) {
|
||||
if (aid > 0 && aid == cadAidByteToUint(&cad[entryNum * 6 + 3]))
|
||||
break;
|
||||
}
|
||||
if (entryNum >= numEntries)
|
||||
HFGAL_RET_ERR(PM3_EINVARG, "Specified facility or AID does not exist in the Card Application Directory");
|
||||
|
||||
// Remove entry (shift all entries left, then clear the last entry)
|
||||
memmove(&cad[entryNum * 6], &cad[(entryNum + 1) * 6], ARRAYLEN(cad) - (entryNum + 1) * 6);
|
||||
memset(&cad[ARRAYLEN(cad) - 6], 0, 6);
|
||||
|
||||
// Select application & authenticate
|
||||
DesfireSetKeyNoClear(ctx, 0, T_AES, sitekey);
|
||||
DesfireSetKdf(ctx, MFDES_KDF_ALGO_GALLAGHER, NULL, 0);
|
||||
res = selectAidAndAuthenticate(ctx, CAD_AID, verbose);
|
||||
HFGAL_RET_IF_ERR(res);
|
||||
|
||||
// Determine what files we need to update
|
||||
uint8_t fileIdStart = (entryNum - 1) / 6;
|
||||
uint8_t fileIdStop = (numEntries - 1) / 6;
|
||||
|
||||
for (uint8_t fileId = fileIdStart; fileId <= fileIdStop; fileId++) {
|
||||
// Write file
|
||||
res = DesfireWriteFile(ctx, fileId, 0, 36, &cad[fileId * 36]);
|
||||
HFGAL_RET_IF_ERR_WITH_MSG(res, "Failed writing data to file %d in CAD (AID %06X)", fileId, CAD_AID);
|
||||
|
||||
if (verbose)
|
||||
PrintAndLogEx(INFO, "Updated file %d in CAD", fileId);
|
||||
}
|
||||
|
||||
// Delete empty files if necessary
|
||||
if (fileIdStart != fileIdStop) {
|
||||
uint8_t fileId = fileIdStop;
|
||||
|
||||
DesfireSetCommMode(ctx, DCMMACed);
|
||||
res = DesfireDeleteFile(ctx, fileId);
|
||||
HFGAL_RET_IF_ERR_WITH_MSG(res, "Failed deleting file %d from CAD (AID %06X)", fileId, CAD_AID);
|
||||
|
||||
if (verbose)
|
||||
PrintAndLogEx(INFO, "Deleted unnecessary file %d from CAD (AID %06X)", fileId, CAD_AID);
|
||||
|
||||
// Delete the Card Application Directory if necessary (if we just deleted the last file in it)
|
||||
if (fileId == 0) {
|
||||
res = deleteGallagherApplication(ctx, sitekey, CAD_AID, verbose);
|
||||
HFGAL_RET_IF_ERR_WITH_MSG(res, "Failed deleting file %d from CAD (AID %06X)", fileId, CAD_AID);
|
||||
|
||||
if (verbose)
|
||||
PrintAndLogEx(INFO, "Removed CAD because it was empty");
|
||||
}
|
||||
}
|
||||
|
||||
PrintAndLogEx(INFO, "Successfully removed %06X from the Card Application Directory", aid);
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int CmdGallagherClone(const char *Cmd) {
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf gallagher clone",
|
||||
|
@ -737,11 +830,11 @@ static int CmdGallagherClone(const char *Cmd) {
|
|||
HFGAL_RET_ERR(PM3_EFATAL, "Could not find an available AID, card is full");
|
||||
}
|
||||
|
||||
// Update card application directory
|
||||
// Update Card Application Directory
|
||||
DesfireSetKeyNoClear(&dctx, keyNum, algo, key);
|
||||
DesfireSetKdf(&dctx, MFDES_KDF_ALGO_NONE, NULL, 0);
|
||||
res = updateGallagherCAD(&dctx, sitekey, aid, &creds, verbose);
|
||||
HFGAL_RET_IF_ERR_WITH_MSG(res, "Failed updating Gallagher card application directory");
|
||||
res = addToGallagherCAD(&dctx, sitekey, aid, &creds, verbose);
|
||||
HFGAL_RET_IF_ERR_WITH_MSG(res, "Failed updating Gallagher Card Application Directory");
|
||||
|
||||
// Create application
|
||||
DesfireSetKeyNoClear(&dctx, keyNum, algo, key);
|
||||
|
@ -759,6 +852,72 @@ static int CmdGallagherClone(const char *Cmd) {
|
|||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int CmdGallagherDelete(const char *Cmd) {
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf gallagher delete",
|
||||
"delete Gallagher application from a DESFire card",
|
||||
"hf gallagher delete --aid 2081f4 --sitekey 00112233445566778899aabbccddeeff"
|
||||
);
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_lit0(NULL, "apdu", "show APDU requests and responses"),
|
||||
arg_lit0("v", "verbose", "Verbose mode"),
|
||||
|
||||
arg_str1(NULL, "aid", "<hex>", "Application ID to delete (3 bytes)"),
|
||||
arg_str0(NULL, "sitekey", "<hex>", "Master site key to compute diversified keys (16 bytes) [default=3112B738D8862CCD34302EB299AAB456]"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||
|
||||
SetAPDULogging(arg_get_lit(ctx, 1));
|
||||
bool verbose = arg_get_lit(ctx, 2);
|
||||
|
||||
int aidLen = 0;
|
||||
uint8_t aidBuf[3] = {0};
|
||||
uint32_t aid = 0;
|
||||
CLIGetHexWithReturn(ctx, 3, aidBuf, &aidLen);
|
||||
|
||||
if (aidLen != 3)
|
||||
HFGAL_RET_ERR(PM3_EINVARG, "--aid must be 3 bytes");
|
||||
reverseAid(aidBuf); // PM3 displays AIDs backwards
|
||||
aid = DesfireAIDByteToUint(aidBuf);
|
||||
|
||||
// Check that the AID is in the expected range
|
||||
if (memcmp(aidBuf, "\xF4\x81", 2) != 0 || aidBuf[2] < 0x20 || aidBuf[2] > 0x2B)
|
||||
// TODO: this should probably be a warning, but key diversification will throw an error later even if we don't
|
||||
HFGAL_RET_ERR(PM3_EINVARG, "Invalid Gallagher AID %06X, expected 2?81F4, where 0 <= ? <= 0xB", aid);
|
||||
|
||||
int sitekeyLen = 0;
|
||||
uint8_t sitekey[16] = {0};
|
||||
memcpy(sitekey, DEFAULT_SITE_KEY, ARRAYLEN(sitekey));
|
||||
CLIGetHexWithReturn(ctx, 4, sitekey, &sitekeyLen);
|
||||
if (sitekeyLen > 0 && sitekeyLen != 16)
|
||||
HFGAL_RET_ERR(PM3_EINVARG, "--sitekey must be 16 bytes");
|
||||
CLIParserFree(ctx);
|
||||
|
||||
// Set up context
|
||||
DropField();
|
||||
DesfireContext_t dctx = {0};
|
||||
DesfireClearContext(&dctx);
|
||||
|
||||
// Get card UID (for key diversification)
|
||||
int res = DesfireGetCardUID(&dctx);
|
||||
HFGAL_RET_IF_ERR_WITH_MSG(res, "Failed retrieving card UID");
|
||||
|
||||
// Update Card Application Directory
|
||||
res = removeFromGallagherCAD(&dctx, sitekey, aid, verbose);
|
||||
HFGAL_RET_IF_ERR_WITH_MSG(res, "Failed removing %06X from the Card Application Directory");
|
||||
|
||||
// Delete application
|
||||
res = deleteGallagherApplication(&dctx, sitekey, aid, verbose);
|
||||
HFGAL_RET_IF_ERR_WITH_MSG(res, "Failed deleting Gallagher application");
|
||||
|
||||
PrintAndLogEx(SUCCESS, "Done");
|
||||
PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`hf gallagher reader`") " to verify");
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int CmdGallagherSim(const char *Cmd) {
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf gallagher sim",
|
||||
|
@ -798,7 +957,8 @@ static int CmdHelp(const char *Cmd);
|
|||
static command_t CommandTable[] = {
|
||||
{"help", CmdHelp, AlwaysAvailable, "This help"},
|
||||
{"reader", CmdGallagherReader, IfPm3Iso14443, "attempt to read and extract tag data"},
|
||||
{"clone", CmdGallagherClone, IfPm3Iso14443, "clone GALLAGHER tag to a blank DESFire card"},
|
||||
{"clone", CmdGallagherClone, IfPm3Iso14443, "add Gallagher credentials to a DESFire card"},
|
||||
{"delete", CmdGallagherDelete, IfPm3Iso14443, "delete Gallagher application from a DESFire card"},
|
||||
{"sim", CmdGallagherSim, IfPm3Iso14443, "simulate GALLAGHER tag"},
|
||||
{NULL, NULL, NULL, NULL}
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue