From b2fa97ff18e17a67a31ed669334a7a72d8a84731 Mon Sep 17 00:00:00 2001 From: wh201906 <62299611+wh201906@users.noreply.github.com> Date: Thu, 23 Apr 2020 17:50:20 +0800 Subject: [PATCH] Store keys and data into class Mifare --- common/pm3process.cpp | 2 +- common/util.cpp | 2 +- module/mifare.cpp | 229 +++++++++++++++++++++++++++++++----------- module/mifare.h | 24 ++++- ui/mainwindow.cpp | 9 +- 5 files changed, 205 insertions(+), 61 deletions(-) diff --git a/common/pm3process.cpp b/common/pm3process.cpp index 40b12fc..6ea2492 100644 --- a/common/pm3process.cpp +++ b/common/pm3process.cpp @@ -95,7 +95,7 @@ void PM3Process::onReadyRead() requiredOutput->append(out); if(out != "") { - qDebug() << "PM3Process::onReadyRead:" << out; +// qDebug() << "PM3Process::onReadyRead:" << out; emit newOutput(out); } diff --git a/common/util.cpp b/common/util.cpp index f063835..f7f7997 100644 --- a/common/util.cpp +++ b/common/util.cpp @@ -9,7 +9,7 @@ Util::Util(QObject *parent) : QObject(parent) void Util::processOutput(QString output) { - qDebug() << "Util::processOutput:" << output; +// qDebug() << "Util::processOutput:" << output; if(isRequiringOutput) { requiredOutput->append(output); diff --git a/module/mifare.cpp b/module/mifare.cpp index aed8352..08b3037 100644 --- a/module/mifare.cpp +++ b/module/mifare.cpp @@ -4,20 +4,14 @@ Mifare::Mifare(Ui::MainWindow *ui, Util *addr, QObject *parent) : QObject(parent { util = addr; this->ui = ui; + keyAList = new QStringList(); + keyBList = new QStringList(); + dataList = new QStringList(); + data_clearKey(); // fill with blank Qstring + data_clearData(); // fill with blank Qstring } -bool Mifare::isKeyValid(const QString key) -{ - if(key.length() != 12) - return false; - for(int i = 0; i < 12; i++) - { - if(!((key[i] >= '0' && key[i] <= '9') || (key[i] >= 'A' && key[i] <= 'F'))) - return false; - } - return true; -} void Mifare::info() { @@ -32,9 +26,14 @@ void Mifare::chk() QStringList keys = result.split("\r\n"); for(int i = 0; i < 16; i++) { - ui->MF_keyWidget->setItem(i, 1, new QTableWidgetItem(keys[i + 3].mid(7, 12).trimmed().toUpper())); - ui->MF_keyWidget->setItem(i, 2, new QTableWidgetItem(keys[i + 3].mid(24, 12).trimmed().toUpper())); + keyAList->replace(i, keys[i + 3].mid(7, 12).trimmed().toUpper()); + if(keyAList->at(i) == "?") + keyAList->replace(i, ""); + keyBList->replace(i, keys[i + 3].mid(24, 12).trimmed().toUpper()); + if(keyBList->at(i) == "?") + keyBList->replace(i, ""); } + data_syncWithKeyWidget(); qDebug() << "***********\n" << keys << "***********\n"; } @@ -46,10 +45,11 @@ void Mifare::nested() for(int i = 0; i < 16; i++) { if(keys[i + 3].at(23) == '1') - ui->MF_keyWidget->setItem(i, 1, new QTableWidgetItem(keys[i + 3].mid(7, 12).trimmed().toUpper())); + keyAList->replace(i, keys[i + 3].mid(7, 12).trimmed().toUpper()); if(keys[i + 3].at(44) == '1') - ui->MF_keyWidget->setItem(i, 2, new QTableWidgetItem(keys[i + 3].mid(28, 12).trimmed().toUpper())); + keyBList->replace(i, keys[i + 3].mid(28, 12).trimmed().toUpper()); } + data_syncWithKeyWidget(); qDebug() << "***********\n" << keys << "***********\n"; } @@ -128,57 +128,59 @@ void Mifare::readAll() bool isKeyAValid; bool isKeyBValid; const int waitTime = 300; - for(int i = 0; i < 16; i++) + for(int i = 0; i < sectors; i++) { - QApplication::processEvents(); result = ""; isKeyAValid = false; isKeyBValid = false; // check keys and read the first block of each sector - if(ui->MF_keyWidget->item(i, 1) != nullptr && isKeyValid(ui->MF_keyWidget->item(i, 1)->text())) + if(data_isKeyValid(keyAList->at(i))) { result = util->execCMDWithOutput("hf mf rdbl " + QString::number(4 * i) + " A " - + ui->MF_keyWidget->item(i, 1)->text(), waitTime); + + keyAList->at(i), waitTime); if(result.indexOf("isOk:01") != -1) { isKeyAValid = true; - ui->MF_dataWidget->setItem(4 * i, 2, new QTableWidgetItem(result.mid(result.indexOf("isOk:01") + 13, 47).toUpper())); + result = result.mid(result.indexOf("isOk:01") + 13, 47).toUpper(); + result.replace(" ", ""); + dataList->replace(4 * i, result); } } - QApplication::processEvents(); - if(ui->MF_keyWidget->item(i, 2) != nullptr && isKeyValid(ui->MF_keyWidget->item(i, 2)->text())) + if(data_isKeyValid(keyBList->at(i))) { result = util->execCMDWithOutput("hf mf rdbl " + QString::number(4 * i) + " B " - + ui->MF_keyWidget->item(i, 2)->text(), waitTime); + + keyBList->at(i), waitTime); if(result.indexOf("isOk:01") != -1) { isKeyBValid = true; - ui->MF_dataWidget->setItem(4 * i, 2, new QTableWidgetItem(result.mid(result.indexOf("isOk:01") + 13, 47).toUpper())); + result = result.mid(result.indexOf("isOk:01") + 13, 47).toUpper(); + result.replace(" ", ""); + dataList->replace(4 * i, result); } } - + data_syncWithDataWidget(false, 4 * i); // read the rest blocks of a sector if(isKeyAValid || isKeyBValid) { for(int j = 1; j < 4; j++) { - QApplication::processEvents(); result = util->execCMDWithOutput("hf mf rdbl " + QString::number(4 * i + j) + " " + (isKeyAValid ? "A" : "B") + " " - + ui->MF_keyWidget->item(i, (isKeyAValid ? 1 : 2))->text(), waitTime); + + (isKeyAValid ? keyAList : keyBList)->at(i), waitTime); result = result.mid(result.indexOf("isOk:01") + 13, 47).toUpper(); - ui->MF_dataWidget->setItem(4 * i + j, 2, new QTableWidgetItem(result)); + result.replace(" ", ""); + dataList->replace(4 * i + j, result); + data_syncWithDataWidget(false, 4 * i + j); } - QApplication::processEvents(); // fill the MF_dataWidget with the known valid key // // check whether the MF_dataWidget contains the valid key, @@ -186,46 +188,44 @@ void Mifare::readAll() // // the structure is not symmetric, since you cannot get KeyA from output // this program will only process the provided KeyA(in MF_keyWidget) - result = ui->MF_dataWidget->item(4 * i + 3, 2)->text(); + result = dataList->at(4 * i + 3); if(isKeyAValid) { - for(int j = 0; j < 6; j++) - { - result = result.replace(j * 3, 2, ui->MF_keyWidget->item(i, 1)->text().mid(j * 2, 2)); - } + result.replace(0, 12, keyAList->at(i)); } else { - result = result.replace(0, 18, "?? ?? ?? ?? ?? ?? "); + result = result.replace(0, 12, "????????????"); } - ui->MF_dataWidget->setItem(4 * i + 3, 2, new QTableWidgetItem(result)); + dataList->replace(4 * i + 3, result); if(isKeyBValid) { - for(int j = 0; j < 6; j++) - { - result = result.replace(30 + j * 3, 2, ui->MF_keyWidget->item(i, 2)->text().mid(j * 2, 2)); - ui->MF_dataWidget->setItem(4 * i + 3, 2, new QTableWidgetItem(result)); - } + result.replace(20, 12, keyBList->at(i)); + dataList->replace(4 * i + 3, result); + data_syncWithDataWidget(false, 4 * i + 3); } - else + else // now isKeyAValid == true, the output might contains the KeyB { - QString tmpKey = result.right(18).replace(" ", ""); + QString tmpKey = dataList->at(4 * i + 3).right(12); result = util->execCMDWithOutput("hf mf rdbl " + QString::number(4 * i + 3) + " B " + tmpKey, waitTime); if(result.indexOf("isOk:01") != -1) { - ui->MF_keyWidget->setItem(i, 2, new QTableWidgetItem(tmpKey)); + keyBList->replace(i, tmpKey); + data_syncWithKeyWidget(false, i, false); } else { - result = ui->MF_dataWidget->item(4 * i + 3, 2)->text(); - result = result.replace(30, 17, "?? ?? ?? ?? ?? ??"); - ui->MF_dataWidget->setItem(4 * i + 3, 2, new QTableWidgetItem(result)); + result = dataList->at(4 * i + 3); + result = result.replace(20, 12, "????????????"); + dataList->replace(4 * i + 3, result); + } } + data_syncWithDataWidget(false, 4 * i + 3); } } } @@ -248,25 +248,33 @@ void Mifare::write() void Mifare::writeAll() { + const int waitTime = 300; QString result; for(int i = 0; i < 16; i++) { for(int j = 0; j < 4; j++) { - result = util->execCMDWithOutput("hf mf wrbl " - + QString::number(i * 4 + j) - + " A " - + ui->MF_keyWidget->item(i, 1)->text() - + " " - + ui->MF_dataWidget->item(2, i * 4 + j)->text().replace(" ", "")); - if(result.indexOf("isOk:01") == -1) + result = ""; // if the KeyA is invalid and the result is not empty, the KeyB will not be tested. + if(data_isDataValid(dataList->at(i * 4 + j)) != DATA_NOSPACE || dataList->at(i * 4 + j).contains('?')) + continue; + if(data_isKeyValid(keyAList->at(i))) + { + result = util->execCMDWithOutput("hf mf wrbl " + + QString::number(i * 4 + j) + + " A " + + keyAList->at(i) + + " " + + dataList->at(i * 4 + j), waitTime); + } + qDebug() << i << j << result.indexOf("isOk:01") << data_isKeyValid(keyBList->at(i)); + if(result.indexOf("isOk:01") == -1 && data_isKeyValid(keyBList->at(i))) { result = util->execCMDWithOutput("hf mf wrbl " + QString::number(i * 4 + j) + " B " - + ui->MF_keyWidget->item(i, 2)->text() + + keyBList->at(i) + " " - + ui->MF_dataWidget->item(2, i * 4 + j)->text().replace(" ", "")); + + dataList->at(i * 4 + j), waitTime); } } } @@ -283,3 +291,112 @@ void Mifare::restore() util->execCMD("hf mf restore"); ui->funcTab->setCurrentIndex(1); } + +void Mifare::data_syncWithDataWidget(bool syncAll, int block) +{ + QString tmp = ""; + if(syncAll) + { + for(int i = 0; i < blocks; i++) + { + tmp += dataList->at(i).mid(0, 2); + for(int j = 1; j < 16; j++) + { + tmp += " "; + tmp += dataList->at(i).mid(j * 2, 2); + } + ui->MF_dataWidget->item(i, 2)->setText(tmp); + } + } + else + { + tmp += dataList->at(block).mid(0, 2); + for(int j = 1; j < 16; j++) + { + tmp += " "; + tmp += dataList->at(block).mid(j * 2, 2); + } + ui->MF_dataWidget->item(block, 2)->setText(tmp); + } +} + +void Mifare::data_syncWithKeyWidget(bool syncAll, int sector, bool isKeyA) +{ + if(syncAll) + { + for(int i = 0; i < sectors; i++) + { + ui->MF_keyWidget->item(i, 1)->setText(keyAList->at(i)); + ui->MF_keyWidget->item(i, 2)->setText(keyBList->at(i)); + } + } + else + { + if(isKeyA) + ui->MF_keyWidget->item(sector, 1)->setText(keyAList->at(sector)); + else + ui->MF_keyWidget->item(sector, 2)->setText(keyBList->at(sector)); + } +} + +void Mifare::data_clearData() +{ + dataList->clear(); + for(int i = 0; i < blocks; i++) + dataList->append(""); +} + +void Mifare::data_clearKey() +{ + keyAList->clear(); + keyBList->clear(); + for(int i = 0; i < sectors; i++) + { + keyAList->append(""); + keyBList->append(""); + } +} + +bool Mifare::data_isKeyValid(const QString& key) +{ + if(key.length() != 12) + return false; + for(int i = 0; i < 12; i++) + { + if(!((key[i] >= '0' && key[i] <= '9') || (key[i] >= 'A' && key[i] <= 'F'))) + return false; + } + return true; +} + +Mifare::DataType Mifare::data_isDataValid(QString data) // "?" will not been processd there +{ + if(data.length() == 47) + { + for(int i = 0; i < 47; i++) + { + if(i % 3 != 0) + { + if(!((data[i] >= '0' && data[i] <= '9') || (data[i] >= 'A' && data[i] <= 'F') || data[i] == '?')) + return DATA_INVALID; + } + else + { + if(data[i] != ' ') + return DATA_INVALID; + } + return DATA_WITHSPACE; + } + } + else if(data.length() == 32) + { + for(int i = 0; i < 32; i++) + { + if(!((data[i] >= '0' && data[i] <= '9') || (data[i] >= 'A' && data[i] <= 'F') || data[i] == '?')) + return DATA_INVALID; + } + return DATA_NOSPACE; + } + else + return DATA_INVALID; +} diff --git a/module/mifare.h b/module/mifare.h index a7d34fa..5e2c2a4 100644 --- a/module/mifare.h +++ b/module/mifare.h @@ -6,14 +6,13 @@ #include "ui/mf_attack_hardnesteddialog.h" #include #include - +#include class Mifare : public QObject { Q_OBJECT public: explicit Mifare(Ui::MainWindow *ui, Util *addr, QObject *parent = nullptr); - bool isKeyValid(const QString key); void info(); void chk(); void nested(); @@ -26,12 +25,33 @@ public: void writeAll(); void dump(); void restore(); + + enum DataType + { + DATA_INVALID, + DATA_WITHSPACE, + DATA_NOSPACE, + }; + + void data_clearData(); + void data_clearKey(); + bool data_isKeyValid(const QString &key); + Mifare::DataType data_isDataValid(QString data); + void data_syncWithDataWidget(bool syncAll = true, int block = 0); + void data_syncWithKeyWidget(bool syncAll = true, int sector = 0, bool isKeyA = true); public slots: signals: private: Ui::MainWindow *ui; Util* util; + + QStringList* keyAList; + QStringList* keyBList; + QStringList* dataList; + + int sectors = 16; + int blocks = 64; }; #endif // MIFARE_H diff --git a/ui/mainwindow.cpp b/ui/mainwindow.cpp index f0ae812..12d1f3f 100644 --- a/ui/mainwindow.cpp +++ b/ui/mainwindow.cpp @@ -93,7 +93,7 @@ void MainWindow::on_PM3_disconnectButton_clicked() void MainWindow::refreshOutput(const QString& output) { - qDebug() << "MainWindow::refresh:" << output; +// qDebug() << "MainWindow::refresh:" << output; ui->Raw_outputEdit->insertPlainText(output); ui->Raw_outputEdit->moveCursor(QTextCursor::End); } @@ -242,7 +242,10 @@ void MainWindow::uiInit() ui->MF_dataWidget->setHorizontalHeaderItem(1, new QTableWidgetItem("Blk")); ui->MF_dataWidget->setHorizontalHeaderItem(2, new QTableWidgetItem("Data")); for(int i = 0; i < 64; i++) + { ui->MF_dataWidget->setItem(i, 1, new QTableWidgetItem(QString::number(i))); + ui->MF_dataWidget->setItem(i, 2, new QTableWidgetItem("")); + } for(int i = 0; i < 16; i++) ui->MF_dataWidget->setItem(i * 4, 0, new QTableWidgetItem(QString::number(i))); ui->MF_dataWidget->verticalHeader()->setVisible(false); @@ -256,7 +259,11 @@ void MainWindow::uiInit() ui->MF_keyWidget->setHorizontalHeaderItem(1, new QTableWidgetItem("KeyA")); ui->MF_keyWidget->setHorizontalHeaderItem(2, new QTableWidgetItem("KeyB")); for(int i = 0; i < 16; i++) + { ui->MF_keyWidget->setItem(i, 0, new QTableWidgetItem(QString::number(i))); + ui->MF_keyWidget->setItem(i, 1, new QTableWidgetItem("")); + ui->MF_keyWidget->setItem(i, 2, new QTableWidgetItem("")); + } ui->MF_keyWidget->verticalHeader()->setVisible(false); ui->MF_keyWidget->setColumnWidth(0, 35); ui->MF_keyWidget->setColumnWidth(1, 110);