diff --git a/configs_official.json b/configs_official.json index aedac0c..65d5dc3 100644 --- a/configs_official.json +++ b/configs_official.json @@ -8,15 +8,11 @@ "2k": "2", "4k": "4" }, - "key type": { - "A": "A", - "B": "B" - }, "key pattern": "\\|\\s*\\d{3}\\s*\\|\\s*.+?\\s*\\|\\s*.+?\\s*\\|\\s*.+?\\s*\\|\\s*.+?\\s*\\|", "key A index": 2, "key B index": 4 }, - "chk": { + "check": { "cmd": "hf mf chk * ?", "card type": { "mini": "0", @@ -46,10 +42,10 @@ "restore": { "cmd": "hf mf restore" }, - "wipe emulator": { + "emulator wipe": { "cmd": "hf mf eclr" }, - "wipe Magic Card": { + "Magic Card wipe": { "cmd": "hf mf cwipe f", "card type": { "mini": "0", @@ -57,6 +53,31 @@ "2k": "2", "4k": "4" } + }, + "emulator read block": { + "cmd": "hf mf eget ", + "data pattern": "([0-9a-fA-F]{2} ){15}[0-9a-fA-F]{2}" + }, + "Magic Card read block": { + "cmd": "hf mf cgetblk ", + "data pattern": "([0-9a-fA-F]{2} ){15}[0-9a-fA-F]{2}" + }, + "normal read block": { + "cmd": "hf mf rdbl ", + "key type": { + "A": "A", + "B": "B" + }, + "data pattern": "([0-9a-fA-F]{2} ){15}[0-9a-fA-F]{2}" + }, + "darkside": { + "cmd": "hf mf mifare" + }, + "save sniff": { + "cmd": "hf list mf -s " + }, + "load sniff": { + "cmd": "hf list mf -l " } } } \ No newline at end of file diff --git a/configs_rrgv4.13.json b/configs_rrgv4.13.json index 77ae431..6b705a4 100644 --- a/configs_rrgv4.13.json +++ b/configs_rrgv4.13.json @@ -17,7 +17,7 @@ "key A index": 2, "key B index": 4 }, - "chk": { + "check": { "cmd": "hf mf chk --", "card type": { "mini": "mini", @@ -47,11 +47,37 @@ "restore": { "cmd": "hf mf restore" }, - "wipe emulator": { + "emulator wipe": { "cmd": "hf mf eclr" }, - "wipe Magic Card": { + "Magic Card wipe": { "cmd": "hf mf cwipe" + }, + "emulator read block": { + "cmd": "hf mf egetblk --blk ", + "data pattern": "([0-9a-fA-F]{2} ){15}[0-9a-fA-F]{2}" + }, + "Magic Card read block": { + "cmd": "hf mf cgetblk --blk ", + "data pattern": "([0-9a-fA-F]{2} ){15}[0-9a-fA-F]{2}" + }, + "normal read block": { + "cmd": "hf mf rdbl --blk - -k ", + "key type": { + "A": "a", + "B": "b" + }, + "data pattern": "([0-9a-fA-F]{2} ){15}[0-9a-fA-F]{2}" + }, + "darkside": { + "cmd": "hf mf darkside" + }, + "save sniff": { + "cmd": "trace save -f " + }, + "load sniff": { + "cmd": "trace load -f ", + "show cmd": "trace list --buffer -t mf" } } } \ No newline at end of file diff --git a/module/mifare.cpp b/module/mifare.cpp index 94c7bc7..03041d7 100644 --- a/module/mifare.cpp +++ b/module/mifare.cpp @@ -126,7 +126,7 @@ void Mifare::chk() QString result; int offset = 0; QString data; - QVariantMap config = configMap["chk"].toMap(); + QVariantMap config = configMap["check"].toMap(); QString cmd = config["cmd"].toString(); int keyAindex = config["key A index"].toInt(); int keyBindex = config["key B index"].toInt(); @@ -254,10 +254,8 @@ void Mifare::hardnested() void Mifare::darkside() { - if(Util::getClientType() == Util::CLIENTTYPE_OFFICIAL) - util->execCMD("hf mf mifare"); - else if(Util::getClientType() == Util::CLIENTTYPE_ICEMAN) - util->execCMD("hf mf darkside"); + QVariantMap config = configMap["darkside"].toMap(); + util->execCMD(config["cmd"].toString()); Util::gotoRawTab(); } @@ -280,7 +278,7 @@ void Mifare::sniff14a() void Mifare::list() { - QVariantMap config = configMap["sniff 14a"].toMap(); + QVariantMap config = configMap["list"].toMap(); util->execCMD(config["cmd"].toString()); Util::gotoRawTab(); @@ -293,88 +291,73 @@ QString Mifare::_readblk(int blockId, KeyType keyType, const QString& key, Targe QRegularExpressionMatch currMatch; bool isTrailerBlock = (blockId < 128 && ((blockId + 1) % 4 == 0)) || ((blockId + 1) % 16 == 0); - if(Util::getClientType() == Util::CLIENTTYPE_OFFICIAL || Util::getClientType() == Util::CLIENTTYPE_ICEMAN) + if(targetType == TARGET_MIFARE) { - if(targetType == TARGET_MIFARE) + if(!data_isKeyValid(key)) { - if(!data_isKeyValid(key)) - { - return ""; - } - // use the given key type to read the target block - result = util->execCMDWithOutput( - "hf mf rdbl " - + QString::number(blockId) - + " " - + (char)keyType - + " " - + key, - waitTime); - currMatch = dataPattern->match(result); - if(currMatch.hasMatch()) + return ""; + } + QVariantMap config = configMap["normal read block"].toMap(); + QString cmd = config["cmd"].toString(); + QRegularExpression dataPattern = QRegularExpression(config["data pattern"].toString()); + cmd.replace("", QString::number(blockId)); + cmd.replace("", config["key type"].toMap()[QString((char)keyType)].toString()); + cmd.replace("", key); + // use the given key type to read the target block + result = util->execCMDWithOutput(cmd, waitTime); + + currMatch = dataPattern.match(result); + if(currMatch.hasMatch()) + { + data = currMatch.captured().toUpper(); + data.remove(" "); + // when the target block is a key block and the given key type is KeyA, try to check whether the KeyB is valid(by Access Bits) + // if the given key type is KeyB, it will never get the KeyA from the key block + if(isTrailerBlock && keyType == KEY_A) // in this case, the Access Bits is always accessible { - data = currMatch.captured().toUpper(); - data.remove(" "); - // when the target block is a key block and the given key type is KeyA, try to check whether the KeyB is valid(by Access Bits) - // if the given key type is KeyB, it will never get the KeyA from the key block - if(isTrailerBlock && keyType == KEY_A) // in this case, the Access Bits is always accessible - { - data.replace(0, 12, key); - QList ACBits = data_getACBits(data.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 - { - data.replace(20, 12, "????????????"); - } - } - else if(isTrailerBlock && keyType == KEY_B) + data.replace(0, 12, key); + QList ACBits = data_getACBits(data.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 { - data.replace(20, 12, key);; - data.replace(0, 12, "????????????"); // fill the keyA part with ? + data.replace(20, 12, "????????????"); } } - else - data = ""; - } - else if(targetType == TARGET_UID) - { - result = util->execCMDWithOutput( - "hf mf cgetblk " - + QString::number(blockId), - waitTime); - currMatch = dataPattern->match(result); - if(currMatch.hasMatch()) + else if(isTrailerBlock && keyType == KEY_B) { - data = currMatch.captured().toUpper(); - data.remove(" "); + data.replace(20, 12, key);; + data.replace(0, 12, "????????????"); // fill the keyA part with ? } - else - data = ""; } + else + data = ""; } - if(Util::getClientType() == Util::CLIENTTYPE_OFFICIAL) + else if(targetType == TARGET_UID) { - if(targetType == TARGET_EMULATOR) + QVariantMap config = configMap["Magic Card read block"].toMap(); + QString cmd = config["cmd"].toString(); + QRegularExpression dataPattern = QRegularExpression(config["data pattern"].toString()); + cmd.replace("", QString::number(blockId)); + result = util->execCMDWithOutput(cmd, waitTime); + currMatch = dataPattern.match(result); + if(currMatch.hasMatch()) { - result = util->execCMDWithOutput( - "hf mf eget " - + QString::number(blockId), - 150); - data = dataPattern->match(result).captured().toUpper(); + data = currMatch.captured().toUpper(); data.remove(" "); } + else + data = ""; } - else if(Util::getClientType() == Util::CLIENTTYPE_ICEMAN) + else if(targetType == TARGET_EMULATOR) { - if(targetType == TARGET_EMULATOR) - { - result = util->execCMDWithOutput( - "hf mf egetblk " - + QString::number(blockId), - 150); - data = dataPattern->match(result).captured().toUpper(); - data.remove(" "); - } + QVariantMap config = configMap["emulator read block"].toMap(); + QString cmd = config["cmd"].toString(); + QRegularExpression dataPattern = QRegularExpression(config["data pattern"].toString()); + cmd.replace("", QString::number(blockId)); + result = util->execCMDWithOutput(cmd, 150); + data = dataPattern.match(result).captured().toUpper(); + data.remove(" "); } + return data; } @@ -761,7 +744,7 @@ void Mifare::restore() void Mifare::wipeC() { - QVariantMap config = configMap["wipe Magic Card"].toMap(); + QVariantMap config = configMap["Magic Card wipe"].toMap(); QString cmd = config["cmd"].toString(); if(cmd.contains("")) cmd.replace("", config["card type"].toMap()[cardType.typeText].toString()); @@ -810,7 +793,7 @@ void Mifare::lockC() void Mifare::wipeE() { - QVariantMap config = configMap["wipe emulator"].toMap(); + QVariantMap config = configMap["emulator wipe"].toMap(); util->execCMD(config["cmd"].toString()); } @@ -824,12 +807,17 @@ void Mifare::simulate() void Mifare::loadSniff(const QString& file) { - if(Util::getClientType() == Util::CLIENTTYPE_OFFICIAL) - util->execCMD("hf list mf -l " + file); - else if(Util::getClientType() == Util::CLIENTTYPE_ICEMAN) + QVariantMap config = configMap["load sniff"].toMap(); + QString cmd = config["cmd"].toString(); + cmd.replace("", file); + if(config.contains("show cmd")) + { + if(util->execCMDWithOutput(cmd, Util::ReturnTrigger({"loaded"})) != "") + util->execCMD(config["show cmd"].toString()); + } + else { - if(util->execCMDWithOutput("trace load -f " + file, Util::ReturnTrigger({"loaded"})) != "") - util->execCMD("trace list -t mf"); + util->execCMD(cmd); } Util::gotoRawTab(); @@ -837,10 +825,10 @@ void Mifare::loadSniff(const QString& file) void Mifare::saveSniff(const QString& file) { - if(Util::getClientType() == Util::CLIENTTYPE_OFFICIAL) - util->execCMD("hf list mf -s " + file); - else if(Util::getClientType() == Util::CLIENTTYPE_ICEMAN) - util->execCMD("trace save -f " + file); + QVariantMap config = configMap["save sniff"].toMap(); + QString cmd = config["cmd"].toString(); + cmd.replace("", file); + util->execCMD(cmd); Util::gotoRawTab(); } diff --git a/ui/mainwindow.cpp b/ui/mainwindow.cpp index 9875138..b3c04a9 100644 --- a/ui/mainwindow.cpp +++ b/ui/mainwindow.cpp @@ -866,15 +866,16 @@ void MainWindow::on_MF_Sniff_loadButton_clicked() // use a tmp file to support c QString filename = ""; title = tr("Plz select the trace file:"); - filename = QFileDialog::getOpenFileName(this, title, "./", tr("Trace Files(*.trc);;All Files(*.*)")); + filename = QFileDialog::getOpenFileName(this, title, clientWorkingDir->absolutePath(), tr("Trace Files(*.trc);;All Files(*.*)")); qDebug() << filename; if(filename != "") { QString tmpFile = "tmp" + QString::number(QDateTime::currentDateTime().toTime_t()) + ".trc"; - if(QFile::copy(filename, "./" + tmpFile)) + if(QFile::copy(filename, clientWorkingDir->absolutePath() + "/" + tmpFile)) { mifare->loadSniff(tmpFile); - QFile::remove("./" + tmpFile); + util->delay(3000); + QFile::remove(clientWorkingDir->absolutePath() + "/" + tmpFile); } else { @@ -889,17 +890,23 @@ void MainWindow::on_MF_Sniff_saveButton_clicked() QString filename = ""; title = tr("Plz select the location to save trace file:"); - filename = QFileDialog::getSaveFileName(this, title, "./", tr("Trace Files(*.trc)")); + filename = QFileDialog::getSaveFileName(this, title, clientWorkingDir->absolutePath(), tr("Trace Files(*.trc)")); qDebug() << filename; if(filename != "") { QString tmpFile = "tmp" + QString::number(QDateTime::currentDateTime().toTime_t()) + ".trc"; mifare->saveSniff(tmpFile); - if(!QFile::copy("./" + tmpFile, filename)) + for(int i = 0; i < 100; i++) + { + util->delay(100); + if(QFile::exists(clientWorkingDir->absolutePath() + "/" + tmpFile)) + break; + } + if(!QFile::copy(clientWorkingDir->absolutePath() + "/" + tmpFile, filename)) { QMessageBox::information(this, tr("Info"), tr("Failed to save to") + "\n" + filename); } - QFile::remove("./" + tmpFile); + QFile::remove(clientWorkingDir->absolutePath() + "/" + tmpFile); } } diff --git a/ui/mainwindow.ui b/ui/mainwindow.ui index 068b3c1..4fc0dd5 100644 --- a/ui/mainwindow.ui +++ b/ui/mainwindow.ui @@ -136,7 +136,7 @@ - 2 + 0