From 85ea3fd74430098dd0826a443aad98d6a8008196 Mon Sep 17 00:00:00 2001 From: wh201906 Date: Sun, 19 Sep 2021 21:00:23 +0800 Subject: [PATCH] Config file _readsec(), hardnested(), _writeblk(), lockC(), setParameterC() --- configs_official.json | 56 +++++++ configs_rrgv4.13.json | 58 ++++++++ module/mifare.cpp | 237 +++++++++++++++--------------- ui/mf_attack_hardnesteddialog.cpp | 36 ++--- ui/mf_attack_hardnesteddialog.h | 3 +- ui/mf_attack_hardnesteddialog.ui | 4 +- ui/mf_uid_parameterdialog.cpp | 22 +-- ui/mf_uid_parameterdialog.h | 3 +- 8 files changed, 259 insertions(+), 160 deletions(-) diff --git a/configs_official.json b/configs_official.json index 65d5dc3..cc671c4 100644 --- a/configs_official.json +++ b/configs_official.json @@ -78,6 +78,62 @@ }, "load sniff": { "cmd": "hf list mf -l " + }, + "hardnested": { + "cmd": "hf mf hardnested ", + "known key type": { + "A": "A", + "B": "B" + }, + "target key type": { + "A": "A", + "B": "B" + } + }, + "normal read sector": { + "cmd": "hf mf rdsc ", + "key type": { + "A": "A", + "B": "B" + }, + "data pattern": "([0-9a-fA-F]{2} ){15}[0-9a-fA-F]{2}" + }, + "Magic Card read sector": { + "cmd": "hf mf cgetsc ", + "data pattern": "([0-9a-fA-F]{2} ){15}[0-9a-fA-F]{2}" + }, + "normal write block": { + "cmd": "hf mf wrbl ", + "key type": { + "A": "A", + "B": "B" + }, + "failed flag": [ + "isOk:00" + ] + }, + "Magic Card write block": { + "cmd": "hf mf csetblk ", + "failed flag": [ + "No chinese magic" + ] + }, + "emulator write block": { + "cmd": "hf mf eset " + }, + "Magic Card lock": { + "cmd": "hf 14a raw ", + "sequence": [ + "-pa -b7 40", + "-pa 43", + "-pa E0 00 39 F7", + "-pa E1 00 E1 EE", + "-pa 85 00 00 00 00 00 00 00 00 00 00 00 00 00 00 08 18 47", + "-a 52" + ] + }, + "Magic Card set parameter": { + "cmd": "hf mf csetuid " } } } \ No newline at end of file diff --git a/configs_rrgv4.13.json b/configs_rrgv4.13.json index 6b705a4..ced4a21 100644 --- a/configs_rrgv4.13.json +++ b/configs_rrgv4.13.json @@ -78,6 +78,64 @@ "load sniff": { "cmd": "trace load -f ", "show cmd": "trace list --buffer -t mf" + }, + "hardnested": { + "cmd": "hf mf hardnested --blk - -k --tblk --t", + "known key type": { + "A": "a", + "B": "b" + }, + "target key type": { + "A": "a", + "B": "b" + } + }, + "normal read sector": { + "cmd": "hf mf rdsc --sec - -k ", + "key type": { + "A": "a", + "B": "b" + }, + "data pattern": "([0-9a-fA-F]{2} ){15}[0-9a-fA-F]{2}" + }, + "Magic Card read sector": { + "cmd": "hf mf cgetsc --sec ", + "data pattern": "([0-9a-fA-F]{2} ){15}[0-9a-fA-F]{2}" + }, + "normal write block": { + "cmd": "hf mf wrbl --blk - -k -d ", + "key type": { + "A": "a", + "B": "b" + }, + "failed flag": [ + "fail", + "error" + ] + }, + "Magic Card write block": { + "cmd": "hf mf csetblk --blk -d ", + "failed flag": [ + "fail", + "error" + ] + }, + "emulator write block": { + "cmd": "hf mf esetblk --blk -d " + }, + "Magic Card lock": { + "cmd": "hf 14a raw ", + "sequence": [ + "-ak -b 7 40", + "-ak 43", + "-ak E0 00 39 F7", + "-ak E1 00 E1 EE", + "-ak 85 00 00 00 00 00 00 00 00 00 00 00 00 00 00 08 18 47", + "-a 52" + ] + }, + "Magic Card set parameter": { + "cmd": "hf mf csetuid --uid --atqa --sak " } } } \ No newline at end of file diff --git a/module/mifare.cpp b/module/mifare.cpp index 03041d7..0cdb019 100644 --- a/module/mifare.cpp +++ b/module/mifare.cpp @@ -1,4 +1,5 @@ #include "mifare.h" +#include const Mifare::CardType Mifare::card_mini = { @@ -246,7 +247,8 @@ void Mifare::nested(bool isStaticNested) void Mifare::hardnested() { - MF_Attack_hardnestedDialog dialog(cardType.block_size); + QVariantMap config = configMap["hardnested"].toMap(); + MF_Attack_hardnestedDialog dialog(cardType.block_size, config); connect(&dialog, &MF_Attack_hardnestedDialog::sendCMD, util, &Util::execCMD); if(dialog.exec() == QDialog::Accepted) Util::gotoRawTab(); @@ -363,6 +365,7 @@ QString Mifare::_readblk(int blockId, KeyType keyType, const QString& key, Targe QStringList Mifare::_readsec(int sectorId, KeyType keyType, const QString& key, TargetType targetType, int waitTime) { + QVariantMap config; QStringList data; QString result, tmp; QRegularExpressionMatch reMatch; @@ -373,83 +376,81 @@ QStringList Mifare::_readsec(int sectorId, KeyType keyType, const QString& key, data.append(""); } - if(Util::getClientType() == Util::CLIENTTYPE_OFFICIAL || Util::getClientType() == Util::CLIENTTYPE_ICEMAN) + // try to read all blocks together + if(targetType == TARGET_MIFARE) { - // try to read all blocks together - if(targetType == TARGET_MIFARE) - { - if(!data_isKeyValid(key)) - { - return data; - } - result = util->execCMDWithOutput( - "hf mf rdsc " - + QString::number(sectorId) - + " " - + (char)keyType - + " " - + key, - waitTime); - } - else if(targetType == TARGET_UID) - { - result = util->execCMDWithOutput( - "hf mf cgetsc " - + QString::number(sectorId), - waitTime); - } - else if(targetType == TARGET_EMULATOR) + if(!data_isKeyValid(key)) { - for(int i = 0; i < cardType.blk[sectorId]; i++) - data[i] = _readblk(cardType.blks[sectorId] + i, keyType, key, targetType, waitTime); return data; } + config = configMap["normal read sector"].toMap(); + QString cmd = config["cmd"].toString(); + cmd.replace("", QString::number(sectorId)); + cmd.replace("", config["key type"].toMap()[QString((char)keyType)].toString()); + cmd.replace("", key); + result = util->execCMDWithOutput(cmd, waitTime); + } + else if(targetType == TARGET_UID) + { + config = configMap["Magic Card read sector"].toMap(); + QString cmd = config["cmd"].toString(); + cmd.replace("", QString::number(sectorId)); + result = util->execCMDWithOutput(cmd, waitTime); + } + else if(targetType == TARGET_EMULATOR) + { + for(int i = 0; i < cardType.blk[sectorId]; i++) + data[i] = _readblk(cardType.blks[sectorId] + i, keyType, key, targetType, waitTime); + return data; + } - // for TARGET_MIFARE and TARGET_UID - reMatch = dataPattern->match(result); - offset = reMatch.capturedStart(); - if(reMatch.hasMatch()) // read successful + // for TARGET_MIFARE and TARGET_UID + // if targetType == TARGET_EMULATOR, this function has returned + QRegularExpression dataPattern = QRegularExpression(config["data pattern"].toString()); + reMatch = dataPattern.match(result); + offset = reMatch.capturedStart(); + if(reMatch.hasMatch()) // read successful + { + for(int i = 0; i < cardType.blk[sectorId]; i++) { - for(int i = 0; i < cardType.blk[sectorId]; i++) + reMatch = dataPattern.match(result, offset); + offset = reMatch.capturedStart(); + if(reMatch.hasMatch()) { - reMatch = dataPattern->match(result, offset); - offset = reMatch.capturedStart(); - if(reMatch.hasMatch()) - { - tmp = reMatch.captured().toUpper(); - offset += tmp.length(); - tmp.remove(" "); - data[i] = tmp; - } + tmp = reMatch.captured().toUpper(); + offset += tmp.length(); + tmp.remove(" "); + data[i] = tmp; } } - // when one of the block cannot be read, the rdsc will return nothing, so you need to read the rest of blocks manually - // the following rdbl operation is not handled there, for better speed(rdsc_A->rdsc_B->rdbl0~3) - else if(targetType == TARGET_UID) // treat as MIFARE - data = _readsec(sectorId, keyType, key, TARGET_MIFARE, waitTime); + } + // when one of the block cannot be read, the rdsc will return nothing, so you need to read the rest of blocks manually + // the following rdbl operation is not handled there, for better speed(rdsc_A->rdsc_B->rdbl0~3) + else if(targetType == TARGET_UID) // treat as MIFARE + data = _readsec(sectorId, keyType, key, TARGET_MIFARE, waitTime); - //process trailer(like _readblk()) - QString trailer = data[cardType.blk[sectorId] - 1]; - if(trailer != "" && targetType == TARGET_MIFARE) + //process trailer(like _readblk()) + QString trailer = data[cardType.blk[sectorId] - 1]; + if(trailer != "" && targetType == TARGET_MIFARE) + { + if(keyType == KEY_A) // in this case, the Access Bits is always accessible { - if(keyType == KEY_A) // in this case, the Access Bits is always accessible + trailer.replace(0, 12, key); + QList ACBits = data_getACBits(trailer.mid(12, 8)); + if(ACBits[3] == 2 || ACBits[3] == 3 || ACBits[3] == 5 || ACBits[3] == 6 || ACBits[3] == 7) // in these cases, the KeyB cannot be read by KeyA { - trailer.replace(0, 12, key); - QList ACBits = data_getACBits(trailer.mid(12, 8)); - if(ACBits[3] == 2 || ACBits[3] == 3 || ACBits[3] == 5 || ACBits[3] == 6 || ACBits[3] == 7) // in these cases, the KeyB cannot be read by KeyA - { - trailer.replace(20, 12, "????????????"); - } + trailer.replace(20, 12, "????????????"); } - else if(keyType == KEY_B) - { - trailer.replace(20, 12, key);; - trailer.replace(0, 12, "????????????"); // fill the keyA part with ? - } - data[cardType.blk[sectorId] - 1] = trailer; } + else if(keyType == KEY_B) + { + trailer.replace(20, 12, key);; + trailer.replace(0, 12, "????????????"); // fill the keyA part with ? + } + data[cardType.blk[sectorId] - 1] = trailer; } + return data; } @@ -578,45 +579,57 @@ bool Mifare::_writeblk(int blockId, KeyType keyType, const QString& key, const Q if(data_isDataValid(input) != DATA_NOSPACE) return false; - if(Util::getClientType() == Util::CLIENTTYPE_OFFICIAL || Util::getClientType() == Util::CLIENTTYPE_ICEMAN) + if(targetType == TARGET_MIFARE) { - if(targetType == TARGET_MIFARE) + if(!data_isKeyValid(key)) + return false; + QVariantMap config = configMap["normal write block"].toMap(); + QString cmd = config["cmd"].toString(); + cmd.replace("", QString::number(blockId)); + cmd.replace("", config["key type"].toMap()[QString((char)keyType)].toString()); + cmd.replace("", key); + cmd.replace("", input); + result = util->execCMDWithOutput(cmd, waitTime); + if(result.isEmpty()) + return false; + + QVariantList failedFlag = config["failed flag"].toJsonArray().toVariantList(); + for(auto flag = failedFlag.begin(); flag != failedFlag.end(); flag++) { - if(!data_isKeyValid(key)) + if(result.contains(flag->toString())) return false; - result = util->execCMDWithOutput( - "hf mf wrbl " - + QString::number(blockId) - + " " - + (char)keyType - + " " - + key - + " " - + input, - waitTime); - return (result.indexOf("isOk:01") != -1); } - else if(targetType == TARGET_UID) - { - result = util->execCMDWithOutput( - "hf mf csetblk " - + QString::number(blockId) - + " " - + input, - waitTime); - return (result.indexOf("error") == -1); // failed flag - } - else if(targetType == TARGET_EMULATOR) + return true; + } + else if(targetType == TARGET_UID) + { + QVariantMap config = configMap["Magic Card write block"].toMap(); + QString cmd = config["cmd"].toString(); + cmd.replace("", QString::number(blockId)); + cmd.replace("", input); + result = util->execCMDWithOutput(cmd, waitTime); + if(result.isEmpty()) + return false; + + QVariantList failedFlag = config["failed flag"].toJsonArray().toVariantList(); + for(auto flag = failedFlag.begin(); flag != failedFlag.end(); flag++) { - util->execCMD( - "hf mf eset " - + QString::number(blockId) - + " " - + input); - util->delay(5); - return true; + if(result.contains(flag->toString())) + return false; } + return true; + } + else if(targetType == TARGET_EMULATOR) + { + QVariantMap config = configMap["emulator write block"].toMap(); + QString cmd = config["cmd"].toString(); + cmd.replace("", QString::number(blockId)); + cmd.replace("", input); + util->execCMD(cmd); + util->delay(5); + return true; } + return false; } @@ -754,6 +767,7 @@ void Mifare::wipeC() void Mifare::setParameterC() { + QVariantMap config = configMap["Magic Card set parameter"].toMap(); QMap result = info(true); if(result.isEmpty()) { @@ -762,7 +776,7 @@ void Mifare::setParameterC() } else { - MF_UID_parameterDialog dialog(result["UID"].toUpper(), result["ATQA"].toUpper(), result["SAK"].toUpper()); + MF_UID_parameterDialog dialog(result["UID"].toUpper(), result["ATQA"].toUpper(), result["SAK"].toUpper(), config); connect(&dialog, &MF_UID_parameterDialog::sendCMD, util, &Util::execCMD); if(dialog.exec() == QDialog::Accepted) Util::gotoRawTab(); @@ -771,23 +785,13 @@ void Mifare::setParameterC() void Mifare::lockC() { - if(Util::getClientType() == Util::CLIENTTYPE_OFFICIAL) - { - util->execCMD("hf 14a raw -pa -b7 40"); - util->execCMD("hf 14a raw -pa 43"); - util->execCMD("hf 14a raw -pa E0 00 39 F7"); - util->execCMD("hf 14a raw -pa E1 00 E1 EE"); - util->execCMD("hf 14a raw -pa 85 00 00 00 00 00 00 00 00 00 00 00 00 00 00 08 18 47"); - util->execCMD("hf 14a raw -a 52"); - } - else if(Util::getClientType() == Util::CLIENTTYPE_ICEMAN) + QVariantMap config = configMap["Magic Card lock"].toMap(); + QString cmd = config["cmd"].toString(); + QVariantList list = config["sequence"].toJsonArray().toVariantList(); + for(auto item = list.begin(); item != list.end(); item++) { - util->execCMD("hf 14a raw -ak -b 7 40"); - util->execCMD("hf 14a raw -ak 43"); - util->execCMD("hf 14a raw -ak E0 00 39 F7"); - util->execCMD("hf 14a raw -ak E1 00 E1 EE"); - util->execCMD("hf 14a raw -ak 85 00 00 00 00 00 00 00 00 00 00 00 00 00 00 08 18 47"); - util->execCMD("hf 14a raw -a 52"); + qDebug() << cmd + item->toString(); + util->execCMD(cmd + item->toString()); } } @@ -844,11 +848,11 @@ void Mifare::data_syncWithDataWidget(bool syncAll, int block) tmp = ""; if(dataList->at(i) != "") { - tmp += dataList->at(i).mid(0, 2); + tmp += dataList->at(i).midRef(0, 2); for(int j = 1; j < 16; j++) { tmp += " "; - tmp += dataList->at(i).mid(j * 2, 2); + tmp += dataList->at(i).midRef(j * 2, 2); } } ui->MF_dataWidget->item(i, 2)->setText(tmp); @@ -859,11 +863,11 @@ void Mifare::data_syncWithDataWidget(bool syncAll, int block) tmp = ""; if(dataList->at(block) != "") { - tmp += dataList->at(block).mid(0, 2); + tmp += dataList->at(block).midRef(0, 2); for(int j = 1; j < 16; j++) { tmp += " "; - tmp += dataList->at(block).mid(j * 2, 2); + tmp += dataList->at(block).midRef(j * 2, 2); } } ui->MF_dataWidget->item(block, 2)->setText(tmp); @@ -1217,7 +1221,7 @@ void Mifare::data_key2Data() if(dataList->at(getTrailerBlockId(i)) == "") tmp += "FF078069"; // default control bytes else - tmp += dataList->at(getTrailerBlockId(i)).mid(12, 8); + tmp += dataList->at(getTrailerBlockId(i)).midRef(12, 8); if(data_isKeyValid(keyBList->at(i))) tmp += keyBList->at(i); @@ -1332,6 +1336,7 @@ QString Mifare::data_getUID() else return ""; } + quint16 Mifare::getTrailerBlockId(quint8 sectorId, qint8 cardTypeId) { if(cardTypeId == 0) diff --git a/ui/mf_attack_hardnesteddialog.cpp b/ui/mf_attack_hardnesteddialog.cpp index 79b01c6..c08906d 100644 --- a/ui/mf_attack_hardnesteddialog.cpp +++ b/ui/mf_attack_hardnesteddialog.cpp @@ -1,16 +1,17 @@ #include "mf_attack_hardnesteddialog.h" #include "ui_mf_attack_hardnesteddialog.h" -MF_Attack_hardnestedDialog::MF_Attack_hardnestedDialog(int blocks, QWidget *parent) : +MF_Attack_hardnestedDialog::MF_Attack_hardnestedDialog(int blocks, const QVariantMap& config, QWidget *parent) : QDialog(parent), ui(new Ui::MF_Attack_hardnestedDialog) { ui->setupUi(this); for(int i = 0; i < blocks; i++) { - ui->knownKeySectorBox->addItem(QString::number(i)); - ui->targetKeySectorBox->addItem(QString::number(i)); + ui->knownKeyBlockBox->addItem(QString::number(i)); + ui->targetKeyBlockBox->addItem(QString::number(i)); } + this->config = config; } @@ -21,26 +22,11 @@ MF_Attack_hardnestedDialog::~MF_Attack_hardnestedDialog() void MF_Attack_hardnestedDialog::on_buttonBox_accepted() { - if(Util::getClientType() == Util::CLIENTTYPE_OFFICIAL) - emit sendCMD("hf mf hardnested " - + ui->knownKeySectorBox->currentText() - + " " - + ui->knownKeyTypeBox->currentText() - + " " - + ui->knownKeyBox->text() - + " " - + ui->targetKeySectorBox->currentText() - + " " - + ui->targetKeyTypeBox->currentText()); - else if(Util::getClientType() == Util::CLIENTTYPE_ICEMAN) // same format in v4.9237 - emit sendCMD("hf mf hardnested " - + ui->knownKeySectorBox->currentText() - + " " - + ui->knownKeyTypeBox->currentText() - + " " - + ui->knownKeyBox->text() - + " " - + ui->targetKeySectorBox->currentText() - + " " - + ui->targetKeyTypeBox->currentText()); + QString cmd = config["cmd"].toString(); + cmd.replace("", ui->knownKeyBlockBox->currentText()); + cmd.replace("", config["known key type"].toMap()[ui->knownKeyTypeBox->currentText()].toString()); + cmd.replace("", ui->knownKeyBox->text()); + cmd.replace("", ui->targetKeyBlockBox->currentText()); + cmd.replace("", config["target key type"].toMap()[ui->targetKeyTypeBox->currentText()].toString()); + emit sendCMD(cmd); } diff --git a/ui/mf_attack_hardnesteddialog.h b/ui/mf_attack_hardnesteddialog.h index 785cb75..ee1d03b 100644 --- a/ui/mf_attack_hardnesteddialog.h +++ b/ui/mf_attack_hardnesteddialog.h @@ -14,12 +14,13 @@ class MF_Attack_hardnestedDialog : public QDialog Q_OBJECT public: - explicit MF_Attack_hardnestedDialog(int blocks, QWidget *parent = nullptr); + explicit MF_Attack_hardnestedDialog(int blocks, const QVariantMap& config, QWidget *parent = nullptr); ~MF_Attack_hardnestedDialog(); private: Ui::MF_Attack_hardnestedDialog *ui; + QVariantMap config; signals: void sendCMD(const QString& cmd); private slots: diff --git a/ui/mf_attack_hardnesteddialog.ui b/ui/mf_attack_hardnesteddialog.ui index 9463564..de7fb4b 100644 --- a/ui/mf_attack_hardnesteddialog.ui +++ b/ui/mf_attack_hardnesteddialog.ui @@ -31,7 +31,7 @@ - + 60 @@ -106,7 +106,7 @@ - + 60 diff --git a/ui/mf_uid_parameterdialog.cpp b/ui/mf_uid_parameterdialog.cpp index 030d3b1..4e722d2 100644 --- a/ui/mf_uid_parameterdialog.cpp +++ b/ui/mf_uid_parameterdialog.cpp @@ -1,7 +1,7 @@ #include "mf_uid_parameterdialog.h" #include "ui_mf_uid_parameterdialog.h" -MF_UID_parameterDialog::MF_UID_parameterDialog(const QString& uid, const QString& atqa, const QString& sak, QWidget *parent) : +MF_UID_parameterDialog::MF_UID_parameterDialog(const QString& uid, const QString& atqa, const QString& sak, const QVariantMap& config, QWidget *parent) : QDialog(parent), ui(new Ui::MF_UID_parameterDialog) { @@ -9,6 +9,7 @@ MF_UID_parameterDialog::MF_UID_parameterDialog(const QString& uid, const QString ui->UIDLineEdit->setText(uid); ui->ATQALineEdit->setText(atqa); ui->SAKLineEdit->setText(sak); + this->config = config; } MF_UID_parameterDialog::~MF_UID_parameterDialog() @@ -18,18 +19,9 @@ MF_UID_parameterDialog::~MF_UID_parameterDialog() void MF_UID_parameterDialog::on_buttonBox_accepted() { - if(Util::getClientType() == Util::CLIENTTYPE_OFFICIAL) - emit sendCMD("hf mf csetuid " - + ui->UIDLineEdit->text() - + " " - + ui->ATQALineEdit->text() - + " " - + ui->SAKLineEdit->text()); - else if(Util::getClientType() == Util::CLIENTTYPE_ICEMAN) // same format in v4.9237 - emit sendCMD("hf mf csetuid " - + ui->UIDLineEdit->text() - + " " - + ui->ATQALineEdit->text() - + " " - + ui->SAKLineEdit->text()); + QString cmd = config["cmd"].toString(); + cmd.replace("", ui->UIDLineEdit->text()); + cmd.replace("", ui->ATQALineEdit->text()); + cmd.replace("", ui->SAKLineEdit->text()); + emit sendCMD(cmd); } diff --git a/ui/mf_uid_parameterdialog.h b/ui/mf_uid_parameterdialog.h index 8812168..734d8a7 100644 --- a/ui/mf_uid_parameterdialog.h +++ b/ui/mf_uid_parameterdialog.h @@ -14,11 +14,12 @@ class MF_UID_parameterDialog : public QDialog Q_OBJECT public: - explicit MF_UID_parameterDialog(const QString& uid, const QString& atqa, const QString& sak, QWidget *parent = nullptr); + explicit MF_UID_parameterDialog(const QString& uid, const QString& atqa, const QString& sak, const QVariantMap& config, QWidget *parent = nullptr); ~MF_UID_parameterDialog(); private: Ui::MF_UID_parameterDialog *ui; + QVariantMap config; signals: void sendCMD(const QString& cmd); private slots: