From a7e112f124c66c1d05b2a2439091df6894da6313 Mon Sep 17 00:00:00 2001 From: wh201906 Date: Mon, 13 Feb 2023 09:27:38 +0800 Subject: [PATCH] Better Trailer Decoder Fix the decoding of isKeyBReadable Show every Access Bits Show isKeyBReadable Add comment for the decoding process Better UI Remove unnecessary debug output --- src/module/mifare.cpp | 60 +++++++++++--------- src/ui/mf_trailerdecoderdialog.cpp | 47 ++++++++++++++-- src/ui/mf_trailerdecoderdialog.h | 2 +- src/ui/mf_trailerdecoderdialog.ui | 88 ++++++++++++++++++++++++++++++ 4 files changed, 167 insertions(+), 30 deletions(-) diff --git a/src/module/mifare.cpp b/src/module/mifare.cpp index ee6898c..e2b0552 100644 --- a/src/module/mifare.cpp +++ b/src/module/mifare.cpp @@ -40,36 +40,39 @@ const Mifare::CardType Mifare::card_4k = const Mifare::AccessType Mifare::dataCondition[8][4] = { - {ACC_KEY_AB, ACC_KEY_AB, ACC_KEY_AB, ACC_KEY_AB}, - {ACC_KEY_AB, ACC_KEY_B, ACC_NEVER, ACC_NEVER}, - {ACC_KEY_AB, ACC_NEVER, ACC_NEVER, ACC_NEVER}, - {ACC_KEY_AB, ACC_KEY_B, ACC_KEY_B, ACC_KEY_AB}, - {ACC_KEY_AB, ACC_NEVER, ACC_NEVER, ACC_KEY_AB}, - {ACC_KEY_B, ACC_NEVER, ACC_NEVER, ACC_NEVER}, - {ACC_KEY_B, ACC_KEY_B, ACC_NEVER, ACC_NEVER}, - {ACC_NEVER, ACC_NEVER, ACC_NEVER, ACC_NEVER}, + // {read, write, increment, decrement/transfer/restore} + {ACC_KEY_AB, ACC_KEY_AB, ACC_KEY_AB, ACC_KEY_AB}, // {C3x, C2x, C1x} = 0 + {ACC_KEY_AB, ACC_KEY_B, ACC_NEVER, ACC_NEVER}, // {C3x, C2x, C1x} = 1 + {ACC_KEY_AB, ACC_NEVER, ACC_NEVER, ACC_NEVER}, // {C3x, C2x, C1x} = 2 + {ACC_KEY_AB, ACC_KEY_B, ACC_KEY_B, ACC_KEY_AB}, // {C3x, C2x, C1x} = 3 + {ACC_KEY_AB, ACC_NEVER, ACC_NEVER, ACC_KEY_AB}, // {C3x, C2x, C1x} = 4 + {ACC_KEY_B, ACC_NEVER, ACC_NEVER, ACC_NEVER}, // {C3x, C2x, C1x} = 5 + {ACC_KEY_B, ACC_KEY_B, ACC_NEVER, ACC_NEVER}, // {C3x, C2x, C1x} = 6 + {ACC_NEVER, ACC_NEVER, ACC_NEVER, ACC_NEVER}, // {C3x, C2x, C1x} = 7 }; const Mifare::AccessType Mifare::trailerReadCondition[8][3] = { - {ACC_NEVER, ACC_KEY_A, ACC_KEY_A}, - {ACC_NEVER, ACC_KEY_AB, ACC_NEVER}, - {ACC_NEVER, ACC_KEY_A, ACC_KEY_A}, - {ACC_NEVER, ACC_KEY_AB, ACC_NEVER}, - {ACC_NEVER, ACC_KEY_A, ACC_KEY_A}, - {ACC_NEVER, ACC_KEY_AB, ACC_NEVER}, - {ACC_NEVER, ACC_KEY_AB, ACC_NEVER}, - {ACC_NEVER, ACC_KEY_AB, ACC_NEVER}, + // {KEYA, Access bits, KEYB} + {ACC_NEVER, ACC_KEY_A, ACC_KEY_A}, // {C33, C23, C13} = 0 + {ACC_NEVER, ACC_KEY_AB, ACC_NEVER}, // {C33, C23, C13} = 1 + {ACC_NEVER, ACC_KEY_A, ACC_KEY_A}, // {C33, C23, C13} = 2 + {ACC_NEVER, ACC_KEY_AB, ACC_NEVER}, // {C33, C23, C13} = 3 + {ACC_NEVER, ACC_KEY_A, ACC_KEY_A}, // {C33, C23, C13} = 4 + {ACC_NEVER, ACC_KEY_AB, ACC_NEVER}, // {C33, C23, C13} = 5 + {ACC_NEVER, ACC_KEY_AB, ACC_NEVER}, // {C33, C23, C13} = 6 + {ACC_NEVER, ACC_KEY_AB, ACC_NEVER}, // {C33, C23, C13} = 7 }; const Mifare::AccessType Mifare::trailerWriteCondition[8][3] = { - {ACC_KEY_A, ACC_NEVER, ACC_KEY_A}, - {ACC_KEY_B, ACC_NEVER, ACC_KEY_B}, - {ACC_NEVER, ACC_NEVER, ACC_NEVER}, - {ACC_NEVER, ACC_NEVER, ACC_NEVER}, - {ACC_KEY_A, ACC_KEY_A, ACC_KEY_A}, - {ACC_NEVER, ACC_KEY_B, ACC_NEVER}, - {ACC_KEY_B, ACC_KEY_B, ACC_KEY_B}, - {ACC_NEVER, ACC_NEVER, ACC_NEVER}, + // {KEYA, Access bits, KEYB} + {ACC_KEY_A, ACC_NEVER, ACC_KEY_A}, // {C33, C23, C13} = 0 + {ACC_KEY_B, ACC_NEVER, ACC_KEY_B}, // {C33, C23, C13} = 1 + {ACC_NEVER, ACC_NEVER, ACC_NEVER}, // {C33, C23, C13} = 2 + {ACC_NEVER, ACC_NEVER, ACC_NEVER}, // {C33, C23, C13} = 3 + {ACC_KEY_A, ACC_KEY_A, ACC_KEY_A}, // {C33, C23, C13} = 4 + {ACC_NEVER, ACC_KEY_B, ACC_NEVER}, // {C33, C23, C13} = 5 + {ACC_KEY_B, ACC_KEY_B, ACC_KEY_B}, // {C33, C23, C13} = 6 + {ACC_NEVER, ACC_NEVER, ACC_NEVER}, // {C33, C23, C13} = 7 }; Mifare::Mifare(Ui::MainWindow *ui, Util *addr, QWidget *parent): QObject(parent) @@ -1312,9 +1315,13 @@ bool Mifare::data_isACBitsValid(const QString& text, QList* returnHalfBy QList halfBytes; for(int i = 0; i < 6; i++) { + // 6 7 8 + // AB CD EF-> + // {0xA, 0xB, 0xC, 0xD, 0xE, 0xF} + // {~C2x, ~C1x, C1x, ~C3x, C3, C2} halfBytes.append((val >> ((5 - i) * 4)) & 0xf); } - qDebug() << val; + // qDebug() << val; if((~halfBytes[0] & 0xf) == halfBytes[5] && (~halfBytes[1] & 0xf) == halfBytes[2] && (~halfBytes[3] & 0xf) == halfBytes[4]) { if(returnHalfBytes != nullptr) @@ -1330,9 +1337,12 @@ QList Mifare::data_getACBits(const QString& text) //return empty QList i QList halfBytes, result; if(data_isACBitsValid(text, &halfBytes)) { + // data in halfbits: + // {~C2x, ~C1x, C1x, ~C3x, C3, C2} for(int i = 0; i < 4; i++) { result.append((((halfBytes[4] >> i) & 1) << 2) | (((halfBytes[5] >> i) & 1) << 1) | (((halfBytes[2] >> i) & 1) << 0)); + // {Cx0, Cx1, Cx2, Cx3} (Cx0={C30, C20, C10}) } } return result; diff --git a/src/ui/mf_trailerdecoderdialog.cpp b/src/ui/mf_trailerdecoderdialog.cpp index 9e9f8bc..904cd39 100644 --- a/src/ui/mf_trailerdecoderdialog.cpp +++ b/src/ui/mf_trailerdecoderdialog.cpp @@ -22,8 +22,10 @@ MF_trailerDecoderDialog::MF_trailerDecoderDialog(QWidget *parent) : ui->dataBlockWidget->setRowCount(3); ui->dataBlockWidget->setColumnCount(4); + ui->dataBlockWidget->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents); ui->trailerBlockWidget->setRowCount(2); ui->trailerBlockWidget->setColumnCount(3); + ui->trailerBlockWidget->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents); } MF_trailerDecoderDialog::~MF_trailerDecoderDialog() @@ -39,23 +41,26 @@ void MF_trailerDecoderDialog::on_accessBitsEdit_textChanged(const QString &arg1) QList ACBits = Mifare::data_getACBits(arg1); if(ACBits.size() == 0) { - ui->isAccessBitsValidLabel->setStyleSheet("color:rgb(200, 0, 0)"); + ui->isAccessBitsValidLabel->setStyleSheet("color:rgb(200, 20, 20)"); ui->isAccessBitsValidLabel->setText(tr("Invalid!\nIt could make the whole sector blocked irreversibly!")); } else { + // if keyB may be read by keyA, it cannot serve for authentication. + // {C33, C23, C13}=3'b000, 3'b010 or 3'b100 + bool isKeyBReadable = ACBits[3] == 0 || ACBits[3] == 2 || ACBits[3] == 4; + 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")); - bool isKeyBReadable = ACBits[3] == 0 || ACBits[3] == 1 || ACBits[3] == 4; + showCBits(); for(int j = 0; j < 3; j++) { setTableItem(ui->trailerBlockWidget, 0, j, Mifare::trailerReadCondition[ACBits[3]][j]); setTableItem(ui->trailerBlockWidget, 1, j, Mifare::trailerWriteCondition[ACBits[3]][j]); } + for(int i = 0; i < 3; i++) { for(int j = 0; j < 4; j++) @@ -72,6 +77,18 @@ void MF_trailerDecoderDialog::on_accessBitsEdit_textChanged(const QString &arg1) setTableItem(ui->dataBlockWidget, i, j, type); } } + ui->isAccessBitsValidLabel->setStyleSheet("color:rgb(20, 200, 20)"); + if(isKeyBReadable) + { + ui->isAccessBitsValidLabel->setText(tr("Valid") + "\n" + tr("KeyB cannot serve for authentication")); + ui->trailerBlockWidget->item(0, 2)->setBackground(QBrush(Qt::lightGray)); + } + else + { + ui->isAccessBitsValidLabel->setText(tr("Valid")); + ui->trailerBlockWidget->item(0, 2)->setBackground(QBrush(QColor(1, 0, 0, 0), Qt::NoBrush)); // default Background + } + } ui->C0Box->blockSignals(false); ui->C1Box->blockSignals(false); @@ -150,5 +167,27 @@ void MF_trailerDecoderDialog::on_boxChanged() } result = result.toUpper(); ui->accessBitsEdit->setText(result); + showCBits(); +} +void MF_trailerDecoderDialog::showCBits() +{ + const QSpinBox* CxBox[4] = + { + ui->C0Box, + ui->C1Box, + ui->C2Box, + ui->C3Box + }; + for(int i = 0; i < 4; i++) + { + quint8 val = CxBox[i]->value(); + for(int j = 0; j < 3; j++) + { + if((val >> j) & 0x1) + ui->CBitsGridLayout->itemAtPosition(j, i)->widget()->setStyleSheet("background-color:rgb(20, 200, 20)"); + else + ui->CBitsGridLayout->itemAtPosition(j, i)->widget()->setStyleSheet(""); + } + } } diff --git a/src/ui/mf_trailerdecoderdialog.h b/src/ui/mf_trailerdecoderdialog.h index 5442ee5..8a83f50 100644 --- a/src/ui/mf_trailerdecoderdialog.h +++ b/src/ui/mf_trailerdecoderdialog.h @@ -33,7 +33,7 @@ private: QRegularExpressionValidator* validator; QButtonGroup* sizeGroup; void setTableItem(QTableWidget *widget, int row, int column, Mifare::AccessType accessType); - + void showCBits(); }; #endif // MF_TRAILERDECODERDIALOG_H diff --git a/src/ui/mf_trailerdecoderdialog.ui b/src/ui/mf_trailerdecoderdialog.ui index 00bd86a..3d3aa63 100644 --- a/src/ui/mf_trailerdecoderdialog.ui +++ b/src/ui/mf_trailerdecoderdialog.ui @@ -209,6 +209,94 @@ + + + + + + C10 + + + + + + + C11 + + + + + + + C12 + + + + + + + C13 + + + + + + + C20 + + + + + + + C21 + + + + + + + C22 + + + + + + + C23 + + + + + + + C30 + + + + + + + C31 + + + + + + + C32 + + + + + + + C33 + + + + +