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
master
wh201906 1 year ago
parent c2d3248b68
commit a7e112f124
No known key found for this signature in database

@ -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<quint8>* returnHalfBy
QList<quint8> 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<quint8> Mifare::data_getACBits(const QString& text) //return empty QList i
QList<quint8> 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;

@ -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<quint8> 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("");
}
}
}

@ -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

@ -209,6 +209,94 @@
</item>
</layout>
</item>
<item>
<layout class="QGridLayout" name="CBitsGridLayout">
<item row="0" column="0">
<widget class="QLabel" name="C10Label">
<property name="text">
<string>C10</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="C11Label">
<property name="text">
<string>C11</string>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QLabel" name="C12Label">
<property name="text">
<string>C12</string>
</property>
</widget>
</item>
<item row="0" column="3">
<widget class="QLabel" name="C13Label">
<property name="text">
<string>C13</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="C20Label">
<property name="text">
<string>C20</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLabel" name="C21Label">
<property name="text">
<string>C21</string>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QLabel" name="C22Label">
<property name="text">
<string>C22</string>
</property>
</widget>
</item>
<item row="1" column="3">
<widget class="QLabel" name="C23Label">
<property name="text">
<string>C23</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="C30Label">
<property name="text">
<string>C30</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLabel" name="C31Label">
<property name="text">
<string>C31</string>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QLabel" name="C32Label">
<property name="text">
<string>C32</string>
</property>
</widget>
</item>
<item row="2" column="3">
<widget class="QLabel" name="C33Label">
<property name="text">
<string>C33</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">

Loading…
Cancel
Save