diff --git a/Proxmark3GUI.pro b/Proxmark3GUI.pro
index b01adb0..f09426d 100644
--- a/Proxmark3GUI.pro
+++ b/Proxmark3GUI.pro
@@ -20,6 +20,7 @@ SOURCES += \
common/pm3process.cpp \
common/util.cpp \
module/mifare.cpp \
+ ui/mf_trailerdecoderdialog.cpp \
ui/mf_sim_simdialog.cpp \
ui/mf_uid_parameterdialog.cpp \
ui/mainwindow.cpp \
@@ -29,12 +30,14 @@ HEADERS += \
common/pm3process.h \
common/util.h \
module/mifare.h \
+ ui/mf_trailerdecoderdialog.h \
ui/mf_sim_simdialog.h \
ui/mf_uid_parameterdialog.h \
ui/mainwindow.h \
ui/mf_attack_hardnesteddialog.h \
FORMS += \
+ ui/mf_trailerdecoderdialog.ui \
ui/mf_sim_simdialog.ui \
ui/mf_uid_parameterdialog.ui \
ui/mainwindow.ui \
diff --git a/ui/mainwindow.cpp b/ui/mainwindow.cpp
index 729aee9..f14f9e0 100644
--- a/ui/mainwindow.cpp
+++ b/ui/mainwindow.cpp
@@ -904,3 +904,9 @@ void MainWindow::on_testButton_clicked()
{
mifare->_readsec(0, Mifare::KEY_A, "FFFFFFFFFFFF");
}
+
+void MainWindow::on_MF_trailerDecoderButton_clicked()
+{
+ decDialog = new MF_trailerDecoderDialog(this);
+ decDialog->show();
+}
diff --git a/ui/mainwindow.h b/ui/mainwindow.h
index f3337b6..1327e0a 100644
--- a/ui/mainwindow.h
+++ b/ui/mainwindow.h
@@ -23,6 +23,7 @@
#include "common/pm3process.h"
#include "module/mifare.h"
#include "common/util.h"
+#include "ui/mf_trailerdecoderdialog.h"
QT_BEGIN_NAMESPACE
namespace Ui
@@ -145,6 +146,8 @@ private slots:
void on_testButton_clicked();
+ void on_MF_trailerDecoderButton_clicked();
+
private:
Ui::MainWindow* ui;
QButtonGroup* typeBtnGroup;
@@ -163,6 +166,8 @@ private:
Mifare* mifare;
Util* util;
+ MF_trailerDecoderDialog* decDialog;
+
void signalInit();
void MF_widgetReset();
diff --git a/ui/mainwindow.ui b/ui/mainwindow.ui
index a32006c..cf7518d 100644
--- a/ui/mainwindow.ui
+++ b/ui/mainwindow.ui
@@ -213,6 +213,13 @@
+ -
+
+
+ Trailer Decoder
+
+
+
-
@@ -630,14 +637,14 @@
-
- Read Checked
+ Read Selected
-
- Write Checked
+ Write Selected
@@ -722,14 +729,14 @@
-
- Read Checked
+ Read Selected
-
- Write Checked
+ Write Selected
diff --git a/ui/mf_trailerdecoderdialog.cpp b/ui/mf_trailerdecoderdialog.cpp
new file mode 100644
index 0000000..327414a
--- /dev/null
+++ b/ui/mf_trailerdecoderdialog.cpp
@@ -0,0 +1,107 @@
+#include "mf_trailerdecoderdialog.h"
+#include "ui_mf_trailerdecoderdialog.h"
+
+MF_trailerDecoderDialog::MF_trailerDecoderDialog(QWidget *parent) :
+ QDialog(parent),
+ ui(new Ui::MF_trailerDecoderDialog)
+{
+ ui->setupUi(this);
+ QRegularExpression re("(([0-9a-fA-F]{2} ){0,4})|([0-9a-fA-F]{0,8})");
+ validator = new QRegularExpressionValidator(this);
+ validator->setRegularExpression(re);
+ ui->accessBitsEdit->setValidator(validator);
+
+ sizeGroup = new QButtonGroup(this);
+ sizeGroup->addButton(ui->size4Button, 4);
+ sizeGroup->addButton(ui->size16Button, 16);
+ connect(sizeGroup, QOverload::of(&QButtonGroup::buttonToggled), this, &MF_trailerDecoderDialog::on_blockSizeChanged);
+
+ ui->dataBlockWidget->setRowCount(3);
+ ui->dataBlockWidget->setColumnCount(4);
+ ui->trailerBlockWidget->setRowCount(2);
+ ui->trailerBlockWidget->setColumnCount(3);
+}
+
+MF_trailerDecoderDialog::~MF_trailerDecoderDialog()
+{
+ delete ui;
+}
+void MF_trailerDecoderDialog::on_accessBitsEdit_textEdited(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->isAccessBitsValidLabel->setStyleSheet("color:rgb(200, 0, 0)");
+ ui->isAccessBitsValidLabel->setText(tr("Invalid! It could make the whole sector blocked irreversibly!"));
+ }
+ else
+ {
+ 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;
+ setTableItem(ui->trailerBlockWidget, 0, 0, "X");
+ }
+}
+
+void MF_trailerDecoderDialog::on_blockSizeChanged(int id, bool st)
+{
+ if(st)
+ {
+ if(id == 4)
+ {
+ ui->dataBlockWidget->verticalHeaderItem(0)->setText("Block0");
+ ui->dataBlockWidget->verticalHeaderItem(1)->setText("Block1");
+ ui->dataBlockWidget->verticalHeaderItem(2)->setText("Block2");
+ }
+ else if(id == 16)
+ {
+ ui->dataBlockWidget->verticalHeaderItem(0)->setText("Block0~4");
+ ui->dataBlockWidget->verticalHeaderItem(1)->setText("Block5~9");
+ ui->dataBlockWidget->verticalHeaderItem(2)->setText("Block10~14");
+ }
+
+ }
+}
+
+void MF_trailerDecoderDialog::setTableItem(QTableWidget* widget, int row, int column, AccessType accessType)
+{
+ if(widget->item(row, column) == nullptr)
+ widget->setItem(row, column, new QTableWidgetItem());
+ QString text;
+ if(accessType == ACC_NEVER)
+ {
+ text = "X";
+ }
+ else if(accessType == ACC_KEY_A)
+ {
+ text = "KeyA";
+ }
+ else if(accessType == ACC_KEY_B)
+ {
+ text = "KeyB";
+ }
+ else if(accessType == ACC_KEY_AB)
+ {
+ text = "KeyA+B";
+ }
+ widget->item(row, column)->setText(text);
+}
diff --git a/ui/mf_trailerdecoderdialog.h b/ui/mf_trailerdecoderdialog.h
new file mode 100644
index 0000000..5478cbd
--- /dev/null
+++ b/ui/mf_trailerdecoderdialog.h
@@ -0,0 +1,75 @@
+#ifndef MF_TRAILERDECODERDIALOG_H
+#define MF_TRAILERDECODERDIALOG_H
+
+#include
+#include
+#include
+#include
+#include
+
+namespace Ui
+{
+class MF_trailerDecoderDialog;
+}
+
+class MF_trailerDecoderDialog : public QDialog
+{
+ Q_OBJECT
+
+public:
+ explicit MF_trailerDecoderDialog(QWidget *parent = nullptr);
+ ~MF_trailerDecoderDialog();
+ enum AccessType
+ {
+ ACC_NEVER = 0,
+ ACC_KEY_A = 1,
+ ACC_KEY_B = 2,
+ ACC_KEY_AB = 3,
+ };
+
+private slots:
+
+ void on_accessBitsEdit_textEdited(const QString &arg1);
+
+ void on_blockSizeChanged(int id, bool st);
+private:
+ Ui::MF_trailerDecoderDialog *ui;
+ QRegularExpressionValidator* validator;
+ QButtonGroup* sizeGroup;
+ void setTableItem(QTableWidget *widget, int row, int column, AccessType accessType);
+ AccessType dataCondition[8][4] =
+ {
+ {ACC_KEY_AB, ACC_KEY_AB, ACC_KEY_AB, ACC_KEY_AB},
+ {ACC_KEY_AB, ACC_NEVER, ACC_NEVER, ACC_NEVER},
+ {ACC_KEY_AB, ACC_KEY_B, 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_KEY_B, ACC_NEVER, ACC_NEVER},
+ {ACC_KEY_B, ACC_NEVER, ACC_NEVER, ACC_NEVER},
+ {ACC_NEVER, ACC_NEVER, ACC_NEVER, ACC_NEVER},
+ };
+ AccessType trailerReadCondition[8][3] =
+ {
+ {ACC_NEVER, ACC_KEY_A, ACC_KEY_A},
+ {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_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},
+ };
+ AccessType trailerWriteCondition[8][3] =
+ {
+ {ACC_KEY_A, ACC_NEVER, ACC_KEY_A},
+ {ACC_NEVER, ACC_NEVER, ACC_NEVER},
+ {ACC_KEY_B, ACC_NEVER, ACC_KEY_B},
+ {ACC_NEVER, ACC_NEVER, ACC_NEVER},
+ {ACC_KEY_A, ACC_KEY_A, ACC_KEY_A},
+ {ACC_KEY_B, ACC_KEY_B, ACC_KEY_B},
+ {ACC_NEVER, ACC_KEY_B, ACC_NEVER},
+ {ACC_NEVER, ACC_NEVER, ACC_NEVER},
+ };
+};
+
+#endif // MF_TRAILERDECODERDIALOG_H
diff --git a/ui/mf_trailerdecoderdialog.ui b/ui/mf_trailerdecoderdialog.ui
new file mode 100644
index 0000000..afcc957
--- /dev/null
+++ b/ui/mf_trailerdecoderdialog.ui
@@ -0,0 +1,228 @@
+
+
+ MF_trailerDecoderDialog
+
+
+
+ 0
+ 0
+ 531
+ 436
+
+
+
+ Dialog
+
+
+ -
+
+
+ Trailer Data:(Input the Access Bits, like "FF 07 80 69" or "FF 07 80")
+
+
+
+ -
+
+
-
+
+
-
+
+
+ -
+
+
+
+
+
+
+
+
+ -
+
+
+ Blocks
+
+
+
-
+
+
+ 4
+
+
+ true
+
+
+
+ -
+
+
+ 16
+
+
+
+
+
+
+
+
+ -
+
+
+ Data Block Permission:
+
+
+
+ -
+
+
+
+ 0
+ 4
+
+
+
+ QAbstractItemView::NoEditTriggers
+
+
+
+ Block0
+
+
+
+
+ Block1
+
+
+
+
+ Block2
+
+
+
+
+ Read
+
+
+
+
+ Write
+
+
+
+
+ Increase
+
+
+
+
+ Decrease/Transfer/Restore
+
+
+
+
+ -
+
+
+ Trailer Block Permission:
+
+
+
+ -
+
+
+
+ 0
+ 3
+
+
+
+ QAbstractItemView::NoEditTriggers
+
+
+
+ Read
+
+
+
+
+ Write
+
+
+
+
+ KeyA
+
+
+
+
+ Access Bits
+
+
+
+
+ KeyB
+
+
+
+
+ -
+
+
-
+
+
+ Reference:
+MF1S70YYX_V1 Product data sheet
+Rev. 3.2 — 23 November 2017
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+ QDialogButtonBox::Ok
+
+
+
+
+
+
+
+
+
+
+ buttonBox
+ accepted()
+ MF_trailerDecoderDialog
+ accept()
+
+
+ 248
+ 254
+
+
+ 157
+ 274
+
+
+
+
+ buttonBox
+ rejected()
+ MF_trailerDecoderDialog
+ reject()
+
+
+ 316
+ 260
+
+
+ 286
+ 274
+
+
+
+
+