From 41015fd1fe1c8e43a176770bbaa3f33fc1ca4cb6 Mon Sep 17 00:00:00 2001 From: wh201906 Date: Fri, 24 Apr 2020 22:11:35 +0800 Subject: [PATCH] Support Mifare MINI, 1k, 2k and 4k card --- module/mifare.cpp | 99 +++++++++++++++++++++---------- module/mifare.h | 10 +++- ui/mainwindow.cpp | 92 +++++++++++++++++++++------- ui/mainwindow.h | 19 ++++-- ui/mainwindow.ui | 34 +++++++---- ui/mf_attack_hardnesteddialog.cpp | 4 +- ui/mf_attack_hardnesteddialog.h | 2 +- ui/mf_attack_hardnesteddialog.ui | 10 ++-- 8 files changed, 190 insertions(+), 80 deletions(-) diff --git a/module/mifare.cpp b/module/mifare.cpp index 77c3453..76c63c5 100644 --- a/module/mifare.cpp +++ b/module/mifare.cpp @@ -1,7 +1,8 @@ #include "mifare.h" -Mifare::Mifare(Ui::MainWindow *ui, Util *addr, QObject *parent) : QObject(parent) +Mifare::Mifare(Ui::MainWindow *ui, Util *addr, QWidget *parent) : QObject(parent) { + this->parent = parent; util = addr; this->ui = ui; cardType = card_1k; @@ -25,7 +26,8 @@ void Mifare::info() void Mifare::chk() { - QString result = util->execCMDWithOutput("hf mf chk *" + QString::number(cardType.type) + " ?"); + QString result = util->execCMDWithOutput("hf mf chk *" + QString::number(cardType.type) + " ?", 1000 + cardType.type * 1000); + qDebug() << result; int offset = 0; QString tmp, tmp2; @@ -66,7 +68,8 @@ void Mifare::nested() void Mifare::hardnested() { - MF_Attack_hardnestedDialog dialog; + int secs = cardType.sectors; + MF_Attack_hardnestedDialog dialog(cardType.blks[secs - 1] + cardType.blk[secs - 1]); connect(&dialog, &MF_Attack_hardnestedDialog::sendCMD, util, &Util::execCMD); if(dialog.exec() == QDialog::Accepted) ui->funcTab->setCurrentIndex(1); @@ -86,16 +89,18 @@ void Mifare::list() void Mifare::read() { + int waitTime = 300; + int currblk = ui->MF_RW_blockBox->currentText().toInt(); QString result = util->execCMDWithOutput("hf mf rdbl " - + ui->MF_RW_blockBox->currentText() + + QString::number(currblk) + " " + ui->MF_RW_keyTypeBox->currentText() + " " - + ui->MF_RW_keyEdit->text()); + + ui->MF_RW_keyEdit->text(), waitTime); if(result.indexOf("isOk:01") != -1) { result = result.mid(result.indexOf(*dataPattern, 0), 47).toUpper(); - if((ui->MF_RW_blockBox->currentText().toInt() + 1) % 4 == 0) // process key block + if((currblk < 128 && ((currblk + 1) % 4 == 0)) || ((currblk + 1) % 8 == 0)) // process key block { if(ui->MF_RW_keyTypeBox->currentText() == "A") { @@ -108,7 +113,7 @@ void Mifare::read() result = util->execCMDWithOutput("hf mf rdbl " + ui->MF_RW_keyTypeBox->currentText() + " B " - + tmpKey); + + tmpKey, waitTime); if(result.indexOf("isOk:01") == -1) { result = ui->MF_RW_dataEdit->text(); @@ -167,8 +172,8 @@ void Mifare::readAll() offset += 47; qDebug() << tmp; tmp.replace(" ", ""); - dataList->replace(i * 4 + j, tmp); - data_syncWithDataWidget(false, i * 4 + j); + dataList->replace(cardType.blks[i] + j, tmp); + data_syncWithDataWidget(false, cardType.blks[i] + j); } } } @@ -183,21 +188,22 @@ void Mifare::readAll() if(offset != -1) { isKeyBValid = true; - for(int j = 0; j < 4; j++) + for(int j = 0; j < cardType.blk[i]; j++) { offset = result.indexOf(*dataPattern, offset); tmp = result.mid(offset, 47).toUpper(); offset += 47; qDebug() << tmp; tmp.replace(" ", ""); - dataList->replace(i * 4 + j, tmp); - data_syncWithDataWidget(false, i * 4 + j); + dataList->replace(cardType.blks[i] + j, tmp); + data_syncWithDataWidget(false, cardType.blks[i] + j); } } } if(isKeyAValid || isKeyBValid) { + // fill the MF_dataWidget with the known valid key // // check whether the MF_dataWidget contains the valid key, @@ -205,7 +211,7 @@ 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 = dataList->at(4 * i + 3); + result = dataList->at(cardType.blks[i] + cardType.blk[i] - 1); if(isKeyAValid) { result.replace(0, 12, keyAList->at(i)); @@ -214,19 +220,19 @@ void Mifare::readAll() { result = result.replace(0, 12, "????????????"); } - dataList->replace(4 * i + 3, result); + dataList->replace(cardType.blks[i] + cardType.blk[i] - 1, result); if(isKeyBValid) { result.replace(20, 12, keyBList->at(i)); - dataList->replace(4 * i + 3, result); - data_syncWithDataWidget(false, 4 * i + 3); + dataList->replace(cardType.blks[i] + cardType.blk[i] - 1, result); + data_syncWithDataWidget(false, cardType.blks[i] + cardType.blk[i] - 1); } else // now isKeyAValid == true, the output might contains the KeyB { - QString tmpKey = dataList->at(4 * i + 3).right(12); + QString tmpKey = dataList->at(cardType.blks[i] + cardType.blk[i] - 1).right(12); result = util->execCMDWithOutput("hf mf rdbl " - + QString::number(4 * i + 3) + + QString::number(cardType.blks[i] + cardType.blk[i] - 1) + " B " + tmpKey, waitTime); if(result.indexOf("isOk:01") != -1) @@ -236,19 +242,20 @@ void Mifare::readAll() } else { - result = dataList->at(4 * i + 3); + result = dataList->at(cardType.blks[i] + cardType.blk[i] - 1); result = result.replace(20, 12, "????????????"); - dataList->replace(4 * i + 3, result); + dataList->replace(cardType.blks[i] + cardType.blk[i] - 1, result); } } - data_syncWithDataWidget(false, 4 * i + 3); + data_syncWithDataWidget(false, cardType.blks[i] + cardType.blk[i] - 1); } } } void Mifare::write() { + int waitTime = 300; QString result = util->execCMDWithOutput("hf mf wrbl " + ui->MF_RW_blockBox->currentText() + " " @@ -256,10 +263,14 @@ void Mifare::write() + " " + ui->MF_RW_keyEdit->text() + " " - + ui->MF_RW_dataEdit->text().replace(" ", "")); + + ui->MF_RW_dataEdit->text().replace(" ", ""), waitTime); if(result.indexOf("isOk:01") != -1) { - + QMessageBox::information(parent, tr("info"), tr("Success!")); + } + else + { + QMessageBox::information(parent, tr("info"), tr("Failed!")); } } @@ -267,31 +278,31 @@ void Mifare::writeAll() { const int waitTime = 300; QString result; - for(int i = 0; i < 16; i++) + for(int i = 0; i < cardType.sectors; i++) { - for(int j = 0; j < 4; j++) + for(int j = 0; j < cardType.blk[i]; j++) { 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('?')) + if(data_isDataValid(dataList->at(cardType.blks[i] + j)) != DATA_NOSPACE || dataList->at(cardType.blks[i] + j).contains('?')) continue; if(data_isKeyValid(keyAList->at(i))) { result = util->execCMDWithOutput("hf mf wrbl " - + QString::number(i * 4 + j) + + QString::number(cardType.blks[i] + j) + " A " + keyAList->at(i) + " " - + dataList->at(i * 4 + j), waitTime); + + dataList->at(cardType.blks[i] + 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) + + QString::number(cardType.blks[i] + j) + " B " + keyBList->at(i) + " " - + dataList->at(i * 4 + j), waitTime); + + dataList->at(cardType.blks[i] + j), waitTime); } } } @@ -314,7 +325,8 @@ void Mifare::data_syncWithDataWidget(bool syncAll, int block) QString tmp = ""; if(syncAll) { - for(int i = 0; i < cardType.blk[block]; i++) + int secs = cardType.sectors; + for(int i = 0; i < cardType.blks[secs - 1] + cardType.blk[secs - 1]; i++) { tmp += dataList->at(i).mid(0, 2); for(int j = 1; j < 16; j++) @@ -358,8 +370,9 @@ void Mifare::data_syncWithKeyWidget(bool syncAll, int sector, bool isKeyA) void Mifare::data_clearData() { + int secs = cardType.sectors; dataList->clear(); - for(int i = 0; i < 40; i++) + for(int i = 0; i < cardType.blks[secs - 1] + cardType.blk[secs - 1]; i++) dataList->append(""); } @@ -417,3 +430,25 @@ Mifare::DataType Mifare::data_isDataValid(QString data) // "?" will not been pro else return DATA_INVALID; } + +Mifare::CardType Mifare::getCardType() +{ + return cardType; +} + +void Mifare::setCardType(int type) +{ + if(type == 0 || type == 1 || type == 2 || type == 4) + { + if(type == 0) + cardType = card_mini; + else if(type == 1) + cardType = card_1k; + else if(type == 2) + cardType = card_2k; + else if(type == 4) + cardType = card_4k; + data_clearKey(); + data_clearData(); + } +} diff --git a/module/mifare.h b/module/mifare.h index b4df46a..6afa996 100644 --- a/module/mifare.h +++ b/module/mifare.h @@ -8,11 +8,12 @@ #include #include #include +#include class Mifare : public QObject { Q_OBJECT public: - explicit Mifare(Ui::MainWindow *ui, Util *addr, QObject *parent = nullptr); + explicit Mifare(Ui::MainWindow *ui, Util *addr, QWidget *parent = nullptr); void info(); void chk(); @@ -77,10 +78,15 @@ public: 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); + + CardType cardType; + Mifare::CardType getCardType(); + void setCardType(int type); public slots: signals: private: + QWidget* parent; Ui::MainWindow *ui; Util* util; @@ -90,8 +96,6 @@ private: QRegExp* dataPattern; QRegExp* chkKeyPattern; QRegExp* nestedKeyPattern; - - CardType cardType; }; #endif // MIFARE_H diff --git a/ui/mainwindow.cpp b/ui/mainwindow.cpp index ec08bd1..3b3dc5e 100644 --- a/ui/mainwindow.cpp +++ b/ui/mainwindow.cpp @@ -156,6 +156,27 @@ void MainWindow::sendMSG() // send command when pressing Enter // ***************************************************** // ******************** mifare ******************** +void MainWindow::MF_onTypeChanged(int id, bool st) +{ + typeBtnGroup->blockSignals(true); + qDebug() << id << typeBtnGroup->checkedId(); + if(!st) + { + int result = QMessageBox::question(this, tr("info"), tr("When Changeing card type, the data and keys in this app will be cleard.\nContinue?"), QMessageBox::Yes | QMessageBox::No); + if(result == QMessageBox::Yes) + { + qDebug() << "Yes"; + mifare->setCardType(typeBtnGroup->checkedId()); + MF_widgetReset(); + } + else + { + qDebug() << "No"; + typeBtnGroup->button(id)->setChecked(true); + } + } + typeBtnGroup->blockSignals(false); +} void MainWindow::on_MF_Attack_infoButton_clicked() { @@ -217,6 +238,30 @@ void MainWindow::on_MF_RW_restoreButton_clicked() mifare->restore(); } +void MainWindow::MF_widgetReset() +{ + int secs = mifare->cardType.sectors; + int blks = mifare->cardType.blks[secs - 1] + mifare->cardType.blk[secs - 1]; + ui->MF_RW_blockBox->clear(); + ui->MF_keyWidget->setRowCount(secs); + ui->MF_dataWidget->setRowCount(blks); + + for(int i = 0; i < blks; i++) + { + setTableItem(ui->MF_dataWidget, i, 0, ""); + setTableItem(ui->MF_dataWidget, i, 1, QString::number(i)); + setTableItem(ui->MF_dataWidget, i, 2, ""); + ui->MF_RW_blockBox->addItem(QString::number(i)); + } + + for(int i = 0; i < secs; i++) + { + setTableItem(ui->MF_keyWidget, i, 0, QString::number(i)); + setTableItem(ui->MF_keyWidget, i, 1, ""); + setTableItem(ui->MF_keyWidget, i, 2, ""); + setTableItem(ui->MF_dataWidget, mifare->cardType.blks[i], 0, QString::number(i)); + } +} // ************************************************ @@ -237,42 +282,42 @@ void MainWindow::uiInit() ui->statusbar->addPermanentWidget(programStatusBar, 1); ui->MF_dataWidget->setColumnCount(3); - ui->MF_dataWidget->setRowCount(64); ui->MF_dataWidget->setHorizontalHeaderItem(0, new QTableWidgetItem(tr("Sec"))); ui->MF_dataWidget->setHorizontalHeaderItem(1, new QTableWidgetItem(tr("Blk"))); ui->MF_dataWidget->setHorizontalHeaderItem(2, new QTableWidgetItem(tr("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); ui->MF_dataWidget->setColumnWidth(0, 35); ui->MF_dataWidget->setColumnWidth(1, 35); ui->MF_dataWidget->setColumnWidth(2, 400); +// for(int i = 0; i < 256; i++) +// { +// ui->MF_dataWidget->setItem(i, 0, new QTableWidgetItem()); +// ui->MF_dataWidget->setItem(i, 1, new QTableWidgetItem()); +// ui->MF_dataWidget->setItem(i, 2, new QTableWidgetItem()); +// } ui->MF_keyWidget->setColumnCount(3); - ui->MF_keyWidget->setRowCount(16); ui->MF_keyWidget->setHorizontalHeaderItem(0, new QTableWidgetItem(tr("Sec"))); ui->MF_keyWidget->setHorizontalHeaderItem(1, new QTableWidgetItem(tr("KeyA"))); ui->MF_keyWidget->setHorizontalHeaderItem(2, new QTableWidgetItem(tr("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); ui->MF_keyWidget->setColumnWidth(2, 110); - - for(int i = 0; i < 64; i++) - { - ui->MF_RW_blockBox->addItem(QString::number(i)); - } +// for(int i = 0; i < 40; i++) +// { +// ui->MF_keyWidget->setItem(i, 0, new QTableWidgetItem()); +// ui->MF_keyWidget->setItem(i, 1, new QTableWidgetItem()); +// ui->MF_keyWidget->setItem(i, 2, new QTableWidgetItem()); +// } + + MF_widgetReset(); + typeBtnGroup = new QButtonGroup(this); + typeBtnGroup->addButton(ui->MF_Type_miniButton, 0); + typeBtnGroup->addButton(ui->MF_Type_1kButton, 1); + typeBtnGroup->addButton(ui->MF_Type_2kButton, 2); + typeBtnGroup->addButton(ui->MF_Type_4kButton, 4); + connect(typeBtnGroup, QOverload::of(&QButtonGroup::buttonToggled), this, &MainWindow::MF_onTypeChanged); on_Raw_CMDHistoryBox_stateChanged(Qt::Unchecked); on_PM3_refreshPortButton_clicked(); @@ -299,5 +344,12 @@ void MainWindow::setStatusBar(QLabel* target, const QString & text) else if(target == programStatusBar) target->setText(tr("State:") + text); } + +void MainWindow::setTableItem(QTableWidget* widget, int row, int column, const QString& text) +{ + if(widget->item(row, column) == nullptr) + widget->setItem(row, column, new QTableWidgetItem()); + widget->item(row, column)->setText(text); +} // *********************************************** diff --git a/ui/mainwindow.h b/ui/mainwindow.h index b6757a4..efa5e33 100644 --- a/ui/mainwindow.h +++ b/ui/mainwindow.h @@ -7,6 +7,8 @@ #include #include #include +#include +#include #include #include @@ -28,12 +30,12 @@ public: MainWindow(QWidget *parent = nullptr); ~MainWindow(); - bool MF_isKeyValid(const QString key); public slots: void refreshOutput(const QString &output); void refreshCMD(const QString &cmd); void setStatusBar(QLabel* target, const QString & text); void onPM3StateChanged(bool st, QString info); + void MF_onTypeChanged(int id, bool st); private slots: void on_PM3_connectButton_clicked(); @@ -80,16 +82,23 @@ private slots: private: Ui::MainWindow *ui; + QButtonGroup* typeBtnGroup; + QLabel* connectStatusBar; + QLabel* programStatusBar; + QLabel* PM3VersionBar; + void uiInit(); + PM3Process* pm3; bool pm3state; QThread* pm3Thread; + Mifare* mifare; Util* util; - void uiInit(); - QLabel* connectStatusBar; - QLabel* programStatusBar; - QLabel* PM3VersionBar; + + void signalInit(); + void MF_widgetReset(); + void setTableItem(QTableWidget *widget, int row, int column, const QString &text); signals: void connectPM3(const QString path, const QString port); void killPM3(); diff --git a/ui/mainwindow.ui b/ui/mainwindow.ui index bca0f3f..82ed96d 100644 --- a/ui/mainwindow.ui +++ b/ui/mainwindow.ui @@ -236,10 +236,13 @@ - + Card Type + + false + 5 @@ -248,7 +251,14 @@ 5 - + + + MINI + + + + + 1K @@ -258,14 +268,14 @@ - + 2K - + 4K @@ -275,7 +285,7 @@ - + File @@ -287,7 +297,7 @@ 5 - + 40 @@ -300,7 +310,7 @@ - + 40 @@ -313,7 +323,7 @@ - + Data @@ -323,7 +333,7 @@ - + Key @@ -439,13 +449,13 @@ - 40 + 60 0 - 40 + 60 16777215 @@ -453,7 +463,7 @@ true - 0 + -1 diff --git a/ui/mf_attack_hardnesteddialog.cpp b/ui/mf_attack_hardnesteddialog.cpp index 203c1c6..6896764 100644 --- a/ui/mf_attack_hardnesteddialog.cpp +++ b/ui/mf_attack_hardnesteddialog.cpp @@ -1,12 +1,12 @@ #include "mf_attack_hardnesteddialog.h" #include "ui_mf_attack_hardnesteddialog.h" -MF_Attack_hardnestedDialog::MF_Attack_hardnestedDialog(QWidget *parent) : +MF_Attack_hardnestedDialog::MF_Attack_hardnestedDialog(int blocks, QWidget *parent) : QDialog(parent), ui(new Ui::MF_Attack_hardnestedDialog) { ui->setupUi(this); - for(int i = 0; i < 64; i++) + for(int i = 0; i < blocks; i++) { ui->knownKeySectorBox->addItem(QString::number(i)); ui->targetKeySectorBox->addItem(QString::number(i)); diff --git a/ui/mf_attack_hardnesteddialog.h b/ui/mf_attack_hardnesteddialog.h index 74cd17b..0f13bf7 100644 --- a/ui/mf_attack_hardnesteddialog.h +++ b/ui/mf_attack_hardnesteddialog.h @@ -12,7 +12,7 @@ class MF_Attack_hardnestedDialog : public QDialog Q_OBJECT public: - explicit MF_Attack_hardnestedDialog(QWidget *parent = nullptr); + explicit MF_Attack_hardnestedDialog(int blocks, QWidget *parent = nullptr); ~MF_Attack_hardnestedDialog(); diff --git a/ui/mf_attack_hardnesteddialog.ui b/ui/mf_attack_hardnesteddialog.ui index 9d7a97a..f6144d5 100644 --- a/ui/mf_attack_hardnesteddialog.ui +++ b/ui/mf_attack_hardnesteddialog.ui @@ -11,7 +11,7 @@ - Dialog + Hardnested Attack @@ -34,13 +34,13 @@ - 40 + 60 0 - 40 + 60 16777215 @@ -109,13 +109,13 @@ - 40 + 60 0 - 40 + 60 16777215