diff --git a/module/mifare.cpp b/module/mifare.cpp index efad23b..055b91b 100644 --- a/module/mifare.cpp +++ b/module/mifare.cpp @@ -295,19 +295,13 @@ QString Mifare::_readblk(int blockId, KeyType keyType, const QString& key, int w { data = dataPattern->match(result).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 - // if the given key type is keyB, it will never get the keyA from the key block + // 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(isKeyBlock && keyType == KEY_A) { data.replace(0, 12, key); - QString tmpKey = data.right(12); - result = util->execCMDWithOutput( - "hf mf rdbl " - + QString::number(blockId) - + " B " - + tmpKey, - waitTime); - if(result.indexOf("isOk:01") == -1) + 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, "????????????"); } @@ -852,8 +846,7 @@ bool Mifare::data_isKeyValid(const QString &key) return true; } -Mifare::DataType -Mifare::data_isDataValid(QString data) // "?" will not been processd there +Mifare::DataType Mifare::data_isDataValid(const QString& data) // "?" will not been processd there { if(data.length() == 47) { @@ -1176,3 +1169,31 @@ void Mifare::data_fillKeys() } data_syncWithKeyWidget(); } + +QList Mifare::data_getACBits(const QString& text) //return empty QList if the text is invalid +{ + QString input = text; + QList result; + input.remove(" "); + if(input.length() < 6) + { + return result; + } + input = input.left(6); + quint32 val = input.toUInt(nullptr, 16); + quint8 halfBytes[6]; + for(int i = 0; i < 6; i++) + { + halfBytes[i] = (val >> ((5 - i) * 4)) & 0xf; + } + qDebug() << val; + if((~halfBytes[0] & 0xf) == halfBytes[5] && (~halfBytes[1] & 0xf) == halfBytes[2] && (~halfBytes[3] & 0xf) == halfBytes[4]) + { + for(int i = 0; i < 4; i++) + { + result.append((((halfBytes[4] >> i) & 1) << 2) | (((halfBytes[5] >> i) & 1) << 1) | (((halfBytes[2] >> i) & 1) << 0)); + } + } + return result; +} + diff --git a/module/mifare.h b/module/mifare.h index e79829e..ac0be02 100644 --- a/module/mifare.h +++ b/module/mifare.h @@ -72,8 +72,8 @@ public: void data_clearData(); void data_clearKey(); - bool data_isKeyValid(const QString& key); - Mifare::DataType data_isDataValid(QString data); + static bool data_isKeyValid(const QString& key); + static Mifare::DataType data_isDataValid(const QString& data); void data_syncWithDataWidget(bool syncAll = true, int block = 0); void data_syncWithKeyWidget(bool syncAll = true, int sector = 0, KeyType keyType = KEY_A); @@ -107,6 +107,7 @@ public: QString _readblk(int blockId, KeyType keyType, const QString &key, int waitTime = 300); QStringList _readsec(int sectorId, KeyType keyType, const QString &key, int waitTime = 300); + static QList data_getACBits(const QString &text); public slots: signals: diff --git a/ui/mf_trailerdecoderdialog.cpp b/ui/mf_trailerdecoderdialog.cpp index 3dbd173..3b09a16 100644 --- a/ui/mf_trailerdecoderdialog.cpp +++ b/ui/mf_trailerdecoderdialog.cpp @@ -15,6 +15,10 @@ MF_trailerDecoderDialog::MF_trailerDecoderDialog(QWidget *parent) : sizeGroup->addButton(ui->size4Button, 4); sizeGroup->addButton(ui->size16Button, 16); connect(sizeGroup, QOverload::of(&QButtonGroup::buttonToggled), this, &MF_trailerDecoderDialog::on_blockSizeChanged); + connect(ui->C0Box, &QSpinBox::textChanged, this, &MF_trailerDecoderDialog::on_boxChanged); + connect(ui->C1Box, &QSpinBox::textChanged, this, &MF_trailerDecoderDialog::on_boxChanged); + connect(ui->C2Box, &QSpinBox::textChanged, this, &MF_trailerDecoderDialog::on_boxChanged); + connect(ui->C3Box, &QSpinBox::textChanged, this, &MF_trailerDecoderDialog::on_boxChanged); ui->dataBlockWidget->setRowCount(3); ui->dataBlockWidget->setColumnCount(4); @@ -26,37 +30,26 @@ MF_trailerDecoderDialog::~MF_trailerDecoderDialog() { delete ui; } -void MF_trailerDecoderDialog::on_accessBitsEdit_textEdited(const QString &arg1) +void MF_trailerDecoderDialog::on_accessBitsEdit_textChanged(const QString &arg1) { - QString input = arg1; - input.remove(" "); - if(input.length() < 6) - { - ui->isAccessBitsValidLabel->setText(""); - return; - } - input = input.left(6); - quint32 result = input.toUInt(nullptr, 16); - quint8 halfBytes[6]; - for(int i = 0; i < 6; i++) - { - halfBytes[i] = (result >> ((5 - i) * 4)) & 0xf; - } - qDebug() << result; - if((~halfBytes[0] & 0xf) != halfBytes[5] || (~halfBytes[1] & 0xf) != halfBytes[2] || (~halfBytes[3] & 0xf) != halfBytes[4]) + ui->C0Box->blockSignals(true); + ui->C1Box->blockSignals(true); + ui->C2Box->blockSignals(true); + ui->C3Box->blockSignals(true); + QList ACBits = Mifare::data_getACBits(arg1); + if(ACBits.size() == 0) { ui->isAccessBitsValidLabel->setStyleSheet("color:rgb(200, 0, 0)"); - ui->isAccessBitsValidLabel->setText(tr("Invalid! It could make the whole sector blocked irreversibly!")); + ui->isAccessBitsValidLabel->setText(tr("Invalid!\nIt could make the whole sector blocked irreversibly!")); } else { + ui->C0Box->setValue(ACBits[0]); + ui->C1Box->setValue(ACBits[1]); + ui->C2Box->setValue(ACBits[2]); + ui->C3Box->setValue(ACBits[3]); ui->isAccessBitsValidLabel->setStyleSheet("color:rgb(0, 200, 0)"); ui->isAccessBitsValidLabel->setText(tr("Valid")); - quint8 ACBits[4]; - for(int i = 0; i < 4; i++) - { - ACBits[i] = (((halfBytes[4] >> i) & 1) << 2) | (((halfBytes[5] >> i) & 1) << 1) | (((halfBytes[2] >> i) & 1) << 0); - } bool isKeyBReadable = ACBits[3] == 0 || ACBits[3] == 1 || ACBits[3] == 4; for(int j = 0; j < 3; j++) { @@ -80,6 +73,10 @@ void MF_trailerDecoderDialog::on_accessBitsEdit_textEdited(const QString &arg1) } } } + ui->C0Box->blockSignals(false); + ui->C1Box->blockSignals(false); + ui->C2Box->blockSignals(false); + ui->C3Box->blockSignals(false); } void MF_trailerDecoderDialog::on_blockSizeChanged(int id, bool st) @@ -125,3 +122,33 @@ void MF_trailerDecoderDialog::setTableItem(QTableWidget* widget, int row, int co } widget->item(row, column)->setText(text); } + +void MF_trailerDecoderDialog::on_boxChanged(const QString &arg1) +{ + quint8 ACBits[4]; + ACBits[0] = ui->C0Box->value(); + ACBits[1] = ui->C1Box->value(); + ACBits[2] = ui->C2Box->value(); + ACBits[3] = ui->C3Box->value(); + quint8 halfBytes[6] = {0, 0, 0, 0, 0, 0}; + for(int i = 0; i < 4; i++) + { + halfBytes[2] |= (((ACBits[i] >> 0) & 1) << i); + halfBytes[5] |= (((ACBits[i] >> 1) & 1) << i); + halfBytes[4] |= (((ACBits[i] >> 2) & 1) << i); + } + halfBytes[0] = (~halfBytes[5]) & 0xf; + halfBytes[1] = (~halfBytes[2]) & 0xf; + halfBytes[3] = (~halfBytes[4]) & 0xf; + + QString result; + for(int i = 0; i < 3; i++) + { + result += QString::number(halfBytes[i * 2], 16); + result += QString::number(halfBytes[i * 2 + 1], 16); + result += " "; + } + result = result.toUpper(); + ui->accessBitsEdit->setText(result); + +} diff --git a/ui/mf_trailerdecoderdialog.h b/ui/mf_trailerdecoderdialog.h index 2629cc1..93a6abd 100644 --- a/ui/mf_trailerdecoderdialog.h +++ b/ui/mf_trailerdecoderdialog.h @@ -23,9 +23,11 @@ public: private slots: - void on_accessBitsEdit_textEdited(const QString &arg1); + void on_accessBitsEdit_textChanged(const QString &arg1); void on_blockSizeChanged(int id, bool st); + + void on_boxChanged(const QString &arg1); private: Ui::MF_trailerDecoderDialog *ui; QRegularExpressionValidator* validator; diff --git a/ui/mf_trailerdecoderdialog.ui b/ui/mf_trailerdecoderdialog.ui index 83d0926..00bd86a 100644 --- a/ui/mf_trailerdecoderdialog.ui +++ b/ui/mf_trailerdecoderdialog.ui @@ -6,37 +6,16 @@ 0 0 - 531 - 436 + 534 + 507 Trailer Decoder - + - - - Trailer Data:(Input the Access Bits, like "FF 07 80 69" or "FF 07 80") - - - - - - - - - - - - - - - - - - - + @@ -63,6 +42,191 @@ + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + + Trailer Data: +(like "FF0780" or "FF 07 80") + + + + + + + + + + + 0 + 0 + + + + + 0 + 40 + + + + + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + + + + + Qt::Vertical + + + QSizePolicy::MinimumExpanding + + + + 20 + 0 + + + + + + + + + + + + Or set bits manually + + + + + + + + + 0 + + + + + Cx0 + + + + + + + 7 + + + + + + + + + 0 + + + + + Cx1 + + + + + + + 7 + + + + + + + + + 0 + + + + + Cx2 + + + + + + + 7 + + + + + + + + + 0 + + + + + Cx3 + + + + + + + 7 + + + + + + + + + + + Qt::Vertical + + + QSizePolicy::MinimumExpanding + + + + 20 + 0 + + + + + + @@ -188,6 +352,16 @@ Rev. 3.2 — 23 November 2017 + + + + Note:the Access Bits usually contains 4 bytes(8 hex symbols), but only the first 3 bytes matters. You can set the 4th byte randomly. + + + true + + +