mirror of
https://github.com/wh201906/Proxmark3GUI.git
synced 2026-07-14 22:55:32 +08:00
New project structure
Load translation file in the executable.
This commit is contained in:
@@ -0,0 +1,72 @@
|
||||
# This file is used to ignore files which are generated
|
||||
# ----------------------------------------------------------------------------
|
||||
|
||||
*~
|
||||
*.autosave
|
||||
*.a
|
||||
*.core
|
||||
*.moc
|
||||
*.o
|
||||
*.obj
|
||||
*.orig
|
||||
*.rej
|
||||
*.so
|
||||
*.so.*
|
||||
*_pch.h.cpp
|
||||
*_resource.rc
|
||||
.#*
|
||||
*.*#
|
||||
core
|
||||
!core/
|
||||
tags
|
||||
.DS_Store
|
||||
.directory
|
||||
*.debug
|
||||
Makefile*
|
||||
*.prl
|
||||
*.app
|
||||
moc_*.cpp
|
||||
ui_*.h
|
||||
qrc_*.cpp
|
||||
Thumbs.db
|
||||
*.res
|
||||
*.rc
|
||||
/.qmake.cache
|
||||
/.qmake.stash
|
||||
|
||||
# qtcreator generated files
|
||||
*.pro.user*
|
||||
|
||||
# xemacs temporary files
|
||||
*.flc
|
||||
|
||||
# Vim temporary files
|
||||
.*.swp
|
||||
|
||||
# Visual Studio generated files
|
||||
*.ib_pdb_index
|
||||
*.idb
|
||||
*.ilk
|
||||
*.pdb
|
||||
*.sln
|
||||
*.suo
|
||||
*.vcproj
|
||||
*vcproj.*.*.user
|
||||
*.ncb
|
||||
*.sdf
|
||||
*.opensdf
|
||||
*.vcxproj
|
||||
*vcxproj.*
|
||||
|
||||
# MinGW generated files
|
||||
*.Debug
|
||||
*.Release
|
||||
|
||||
# Python byte code
|
||||
*.pyc
|
||||
|
||||
# Binaries
|
||||
# --------
|
||||
*.dll
|
||||
*.exe
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
QT += core gui serialport
|
||||
|
||||
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
|
||||
|
||||
CONFIG += c++11
|
||||
|
||||
# The following define makes your compiler emit warnings if you use
|
||||
# any Qt feature that has been marked deprecated (the exact warnings
|
||||
# depend on your compiler). Please consult the documentation of the
|
||||
# deprecated API in order to know how to port your code away from it.
|
||||
DEFINES += QT_DEPRECATED_WARNINGS
|
||||
|
||||
# You can also make your code fail to compile if it uses deprecated APIs.
|
||||
# In order to do so, uncomment the following line.
|
||||
# You can also select to disable deprecated APIs only up to a certain version of Qt.
|
||||
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
|
||||
|
||||
SOURCES += \
|
||||
common/myeventfilter.cpp \
|
||||
main.cpp \
|
||||
common/pm3process.cpp \
|
||||
common/util.cpp \
|
||||
module/lf.cpp \
|
||||
module/mifare.cpp \
|
||||
module/t55xxtab.cpp \
|
||||
ui/mf_trailerdecoderdialog.cpp \
|
||||
ui/mf_sim_simdialog.cpp \
|
||||
ui/mf_uid_parameterdialog.cpp \
|
||||
ui/mainwindow.cpp \
|
||||
ui/mf_attack_hardnesteddialog.cpp \
|
||||
|
||||
HEADERS += \
|
||||
common/myeventfilter.h \
|
||||
common/pm3process.h \
|
||||
common/util.h \
|
||||
module/lf.h \
|
||||
module/mifare.h \
|
||||
module/t55xxtab.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/t55xxtab.ui \
|
||||
ui/mf_trailerdecoderdialog.ui \
|
||||
ui/mf_sim_simdialog.ui \
|
||||
ui/mf_uid_parameterdialog.ui \
|
||||
ui/mainwindow.ui \
|
||||
ui/mf_attack_hardnesteddialog.ui
|
||||
|
||||
TRANSLATIONS += \
|
||||
i18n/zh_CN.ts \
|
||||
i18n/en_US.ts
|
||||
|
||||
# Default rules for deployment.
|
||||
qnx: target.path = /tmp/$${TARGET}/bin
|
||||
else: unix:!android: target.path = /opt/$${TARGET}/bin
|
||||
!isEmpty(target.path): INSTALLS += target
|
||||
|
||||
VERSION = 0.2.3
|
||||
QMAKE_TARGET_PRODUCT = "Proxmark3GUI"
|
||||
QMAKE_TARGET_DESCRIPTION = "Proxmark3GUI"
|
||||
QMAKE_TARGET_COMPANY = "wh201906"
|
||||
|
||||
RESOURCES += \
|
||||
i18n/language.qrc
|
||||
@@ -0,0 +1,13 @@
|
||||
#include "myeventfilter.h"
|
||||
|
||||
MyEventFilter::MyEventFilter(QEvent::Type filter)
|
||||
{
|
||||
targetEventType = filter;
|
||||
}
|
||||
|
||||
bool MyEventFilter::eventFilter(QObject *obj, QEvent *event)
|
||||
{
|
||||
if(event->type() == targetEventType)
|
||||
emit eventHappened(obj, *event);
|
||||
return QObject::eventFilter(obj, event);
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
#ifndef MYEVENTFILTER_H
|
||||
#define MYEVENTFILTER_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QKeyEvent>
|
||||
|
||||
class MyEventFilter : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit MyEventFilter(QEvent::Type filter);
|
||||
protected:
|
||||
bool eventFilter(QObject *obj, QEvent *event) override;
|
||||
|
||||
signals:
|
||||
void eventHappened(QObject* obj_addr, QEvent& event);
|
||||
private:
|
||||
QEvent::Type targetEventType;
|
||||
};
|
||||
|
||||
#endif // MYEVENTFILTER_H
|
||||
@@ -0,0 +1,162 @@
|
||||
#include "pm3process.h"
|
||||
|
||||
PM3Process::PM3Process(QThread* thread, QObject* parent): QProcess(parent)
|
||||
{
|
||||
moveToThread(thread);
|
||||
setProcessChannelMode(PM3Process::MergedChannels);
|
||||
isRequiringOutput = false;
|
||||
requiredOutput = new QString();
|
||||
serialListener = new QTimer(); // if using new QTimer(this), the debug output will show "Cannot create children for a parent that is in a different thread."
|
||||
serialListener->moveToThread(this->thread());// I've tried many ways to creat a QTimer instance, but all of the instances are in the main thread(UI thread), so I have to move it manually
|
||||
serialListener->setInterval(1000);
|
||||
serialListener->setTimerType(Qt::VeryCoarseTimer);
|
||||
connect(serialListener, &QTimer::timeout, this, &PM3Process::onTimeout);
|
||||
connect(this, &PM3Process::readyRead, this, &PM3Process::onReadyRead);
|
||||
portInfo = nullptr;
|
||||
}
|
||||
|
||||
void PM3Process::connectPM3(const QString& path, const QStringList args)
|
||||
{
|
||||
QString result;
|
||||
Util::ClientType clientType;
|
||||
setRequiringOutput(true);
|
||||
|
||||
// stash for reconnect
|
||||
currPath = path;
|
||||
currArgs = args;
|
||||
|
||||
// using "-f" option to make the client output flushed after every print.
|
||||
start(path, args, QProcess::Unbuffered | QProcess::ReadWrite | QProcess::Text);
|
||||
if(waitForStarted(10000))
|
||||
{
|
||||
waitForReadyRead(10000);
|
||||
setRequiringOutput(false);
|
||||
result = *requiredOutput;
|
||||
if(result.indexOf("[=]") != -1)
|
||||
{
|
||||
clientType = Util::CLIENTTYPE_ICEMAN;
|
||||
setRequiringOutput(true);
|
||||
write("hw version\n");
|
||||
for(int i = 0; i < 50; i++)
|
||||
{
|
||||
waitForReadyRead(200);
|
||||
result += *requiredOutput;
|
||||
if(result.indexOf("os: ") != -1)
|
||||
break;
|
||||
}
|
||||
setRequiringOutput(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
clientType = Util::CLIENTTYPE_OFFICIAL;
|
||||
}
|
||||
if(result.indexOf("os: ") != -1) // make sure the PM3 is connected
|
||||
{
|
||||
emit changeClientType(clientType);
|
||||
result = result.mid(result.indexOf("os: "));
|
||||
result = result.left(result.indexOf("\n"));
|
||||
result = result.mid(4, result.indexOf(" ", 4) - 4);
|
||||
emit PM3StatedChanged(true, result);
|
||||
}
|
||||
else
|
||||
kill();
|
||||
}
|
||||
}
|
||||
|
||||
void PM3Process::reconnectPM3()
|
||||
{
|
||||
connectPM3(currPath, currArgs);
|
||||
}
|
||||
|
||||
void PM3Process::setRequiringOutput(bool st)
|
||||
{
|
||||
isRequiringOutput = st;
|
||||
if(isRequiringOutput)
|
||||
requiredOutput->clear();
|
||||
}
|
||||
|
||||
bool PM3Process::waitForReadyRead(int msecs)
|
||||
{
|
||||
return QProcess::waitForReadyRead(msecs);
|
||||
}
|
||||
|
||||
void PM3Process::setSerialListener(const QString& name, bool state)
|
||||
{
|
||||
if(state)
|
||||
{
|
||||
currPort = name;
|
||||
portInfo = new QSerialPortInfo(name);
|
||||
serialListener->start();
|
||||
qDebug() << serialListener->thread();
|
||||
}
|
||||
else
|
||||
{
|
||||
serialListener->stop();
|
||||
if(portInfo != nullptr)
|
||||
{
|
||||
delete portInfo;
|
||||
portInfo = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PM3Process::setSerialListener(bool state)
|
||||
{
|
||||
setSerialListener(currPort, state);
|
||||
}
|
||||
|
||||
void PM3Process::onTimeout() //when the proxmark3 client is unexpectedly terminated or the PM3 hardware is removed, the isBusy() will return false(only tested on Windows);
|
||||
{
|
||||
// isBusy() is a deprecated function because it will block the serial port when the port is not in use.
|
||||
// However, the PM3 client is supposed to use the target serial port exclusively, so it should be fine
|
||||
// isBusy() will always return false on Raspbian, in this case, check "Keep the client active" in the Settings panel.
|
||||
//
|
||||
// qDebug()<<portInfo->isBusy();
|
||||
if(!portInfo->isBusy())
|
||||
{
|
||||
killPM3();
|
||||
}
|
||||
}
|
||||
|
||||
void PM3Process::testThread()
|
||||
{
|
||||
qDebug() << "PM3:" << QThread::currentThread();
|
||||
}
|
||||
|
||||
qint64 PM3Process::write(QString data)
|
||||
{
|
||||
return QProcess::write(data.toLatin1());
|
||||
}
|
||||
|
||||
void PM3Process::onReadyRead()
|
||||
{
|
||||
QString out = readAll();
|
||||
if(isRequiringOutput)
|
||||
requiredOutput->append(out);
|
||||
if(out != "")
|
||||
{
|
||||
// qDebug() << "PM3Process::onReadyRead:" << out;
|
||||
emit newOutput(out);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void PM3Process::setProcEnv(const QStringList* env)
|
||||
{
|
||||
// qDebug() << "passed Env List" << *env;
|
||||
this->setEnvironment(*env);
|
||||
// qDebug() << "final Env List" << processEnvironment().toStringList();
|
||||
}
|
||||
|
||||
void PM3Process::setWorkingDir(const QString& dir)
|
||||
{
|
||||
// the working directory cannot be the default, or the client will failed to load the dll
|
||||
this->setWorkingDirectory(dir);
|
||||
}
|
||||
|
||||
void PM3Process::killPM3()
|
||||
{
|
||||
kill();
|
||||
emit PM3StatedChanged(false);
|
||||
setSerialListener(false);
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
#ifndef PM3PROCESS_H
|
||||
#define PM3PROCESS_H
|
||||
|
||||
#include <QProcess>
|
||||
#include <QThread>
|
||||
#include <QString>
|
||||
#include <QDebug>
|
||||
#include <QTimer>
|
||||
#include <QtSerialPort/QSerialPortInfo>
|
||||
#include <QtSerialPort/QSerialPort>
|
||||
#include <QProcessEnvironment>
|
||||
#include <QDir>
|
||||
|
||||
#include "util.h"
|
||||
|
||||
class PM3Process : public QProcess
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit PM3Process(QThread* thread, QObject* parent = nullptr);
|
||||
bool waitForReadyRead(int msecs = 2000);
|
||||
|
||||
void testThread();
|
||||
|
||||
public slots:
|
||||
void connectPM3(const QString& path, const QStringList args);
|
||||
void setSerialListener(const QString& name, bool state);
|
||||
void setSerialListener(bool state);
|
||||
qint64 write(QString data);
|
||||
void reconnectPM3();
|
||||
void setProcEnv(const QStringList* env);
|
||||
void setWorkingDir(const QString& dir);
|
||||
void killPM3();
|
||||
private slots:
|
||||
void onTimeout();
|
||||
void onReadyRead();
|
||||
private:
|
||||
bool isRequiringOutput;
|
||||
QString* requiredOutput; // It only works in this class now
|
||||
void setRequiringOutput(bool st);// It only works in this class now
|
||||
QTimer* serialListener;
|
||||
QSerialPortInfo* portInfo;
|
||||
QString currPath;
|
||||
QString currPort = "";
|
||||
QStringList currArgs;
|
||||
|
||||
signals:
|
||||
void PM3StatedChanged(bool st, const QString& info = "");
|
||||
void newOutput(const QString& output);
|
||||
void changeClientType(Util::ClientType);
|
||||
};
|
||||
|
||||
#endif // PM3PROCESS_H
|
||||
@@ -0,0 +1,147 @@
|
||||
#include "util.h"
|
||||
|
||||
Util::ClientType Util::clientType = CLIENTTYPE_OFFICIAL;
|
||||
|
||||
int Util::rawTabIndex = 0;
|
||||
QDockWidget* Util::rawDockPtr = nullptr;
|
||||
Ui::MainWindow* Util::ui = nullptr;
|
||||
|
||||
|
||||
Util::Util(QObject *parent) : QObject(parent)
|
||||
{
|
||||
isRequiringOutput = false;
|
||||
requiredOutput = new QString();
|
||||
timeStamp = QTime::currentTime();
|
||||
qRegisterMetaType<Util::ClientType>("Util::ClientType");
|
||||
}
|
||||
|
||||
|
||||
void Util::processOutput(const QString& output)
|
||||
{
|
||||
// qDebug() << "Util::processOutput:" << output;
|
||||
if(isRequiringOutput)
|
||||
{
|
||||
requiredOutput->append(output);
|
||||
timeStamp = QTime::currentTime();
|
||||
}
|
||||
emit refreshOutput(output);
|
||||
}
|
||||
|
||||
void Util::execCMD(const QString& cmd)
|
||||
{
|
||||
qDebug() << "executing: " << cmd;
|
||||
if(isRunning)
|
||||
emit write(cmd + "\n");
|
||||
}
|
||||
|
||||
QString Util::execCMDWithOutput(const QString& cmd, ReturnTrigger trigger, bool rawOutput)
|
||||
{
|
||||
// if the trigger is empty, this function will wait trigger.waitTime then return all outputs during the wait time.
|
||||
// otherwise, this function will return empty string if no trigger is detected, or return outputs if any trigger is detected.
|
||||
// the waitTime will be refreshed if the client have new outputs
|
||||
bool isResultFound = false;
|
||||
QRegularExpression re;
|
||||
re.setPatternOptions(QRegularExpression::DotMatchesEverythingOption);
|
||||
|
||||
if(!isRunning)
|
||||
return "";
|
||||
QTime currTime = QTime::currentTime();
|
||||
QTime targetTime = QTime::currentTime().addMSecs(trigger.waitTime);
|
||||
isRequiringOutput = true;
|
||||
requiredOutput->clear();
|
||||
execCMD(cmd);
|
||||
while(QTime::currentTime() < targetTime)
|
||||
{
|
||||
if(!isRunning)
|
||||
break;
|
||||
QApplication::processEvents();
|
||||
// qDebug() << "currOutput:" << *requiredOutput;
|
||||
for(QString otpt : trigger.expectedOutputs)
|
||||
{
|
||||
re.setPattern(otpt);
|
||||
isResultFound = re.match(*requiredOutput).hasMatch();
|
||||
if(isResultFound)
|
||||
{
|
||||
qDebug() << "output Matched: " << *requiredOutput;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(isResultFound)
|
||||
{
|
||||
delay(200);
|
||||
break;
|
||||
}
|
||||
if(timeStamp > currTime) //has new output
|
||||
{
|
||||
currTime = timeStamp;
|
||||
targetTime = timeStamp.addMSecs(trigger.waitTime);
|
||||
}
|
||||
}
|
||||
isRequiringOutput = false;
|
||||
return (isResultFound || trigger.expectedOutputs.isEmpty() || rawOutput ? *requiredOutput : "");
|
||||
}
|
||||
|
||||
void Util::delay(unsigned int msec)
|
||||
{
|
||||
QTime timer = QTime::currentTime().addMSecs(msec);
|
||||
while(QTime::currentTime() < timer)
|
||||
QApplication::processEvents(QEventLoop::AllEvents, 100);
|
||||
}
|
||||
|
||||
Util::ClientType Util::getClientType()
|
||||
{
|
||||
return Util::clientType;
|
||||
}
|
||||
|
||||
void Util::setClientType(Util::ClientType clientType)
|
||||
{
|
||||
Util::clientType = clientType;
|
||||
}
|
||||
|
||||
void Util::setRunningState(bool st)
|
||||
{
|
||||
this->isRunning = st;
|
||||
}
|
||||
|
||||
bool Util::chooseLanguage(QSettings* guiSettings, QMainWindow* window)
|
||||
{
|
||||
// make sure the GUISettings is not in any group
|
||||
QSettings* langSettings = new QSettings(":/i18n/languages.ini", QSettings::IniFormat);
|
||||
QMap<QString, QString> langMap;
|
||||
langSettings->setIniCodec("UTF-8");
|
||||
langSettings->beginGroup("Languages");
|
||||
QStringList langList = langSettings->allKeys();
|
||||
for(int i = 0; i < langList.size(); i++)
|
||||
langMap.insert(langSettings->value(langList[i]).toString(), langList[i]);
|
||||
langSettings->endGroup();
|
||||
delete langSettings;
|
||||
bool isOk = false;
|
||||
QString selectedText = QInputDialog::getItem(window, "", "Choose a language:", langMap.keys(), 0, false, &isOk);
|
||||
if(isOk)
|
||||
{
|
||||
guiSettings->beginGroup("lang");
|
||||
guiSettings->setValue("language", langMap[selectedText]);
|
||||
guiSettings->endGroup();
|
||||
guiSettings->sync();
|
||||
}
|
||||
return isOk;
|
||||
}
|
||||
|
||||
void Util::gotoRawTab()
|
||||
{
|
||||
Util::ui->funcTab->setCurrentIndex(Util::rawTabIndex);
|
||||
Util::rawDockPtr->setVisible(true);
|
||||
Util::rawDockPtr->raise();
|
||||
}
|
||||
|
||||
void Util::setUI(Ui::MainWindow *ui)
|
||||
{
|
||||
Util::ui = ui;
|
||||
}
|
||||
|
||||
|
||||
void Util::setRawTab(QDockWidget *dockPtr, int tabIndex)
|
||||
{
|
||||
Util::rawDockPtr = dockPtr;
|
||||
Util::rawTabIndex = tabIndex;
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
#ifndef UTIL_H
|
||||
#define UTIL_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
#include <QDebug>
|
||||
#include <QThread>
|
||||
#include <QApplication>
|
||||
#include <QTime>
|
||||
#include <QTimer>
|
||||
#include <QMetaType>
|
||||
#include <QRegularExpression>
|
||||
#include <QSettings>
|
||||
#include <QMainWindow>
|
||||
#include <QInputDialog>
|
||||
#include <QDockWidget>
|
||||
|
||||
#include "ui_mainwindow.h"
|
||||
|
||||
class Util : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum ClientType
|
||||
{
|
||||
CLIENTTYPE_OFFICIAL,
|
||||
CLIENTTYPE_ICEMAN,
|
||||
};
|
||||
|
||||
struct ReturnTrigger
|
||||
{
|
||||
unsigned long waitTime;
|
||||
QStringList expectedOutputs;
|
||||
ReturnTrigger(unsigned long time)
|
||||
{
|
||||
waitTime = time;
|
||||
expectedOutputs = QStringList();
|
||||
}
|
||||
ReturnTrigger(const QStringList& outputs)
|
||||
{
|
||||
waitTime = 10000;
|
||||
expectedOutputs = outputs;
|
||||
}
|
||||
ReturnTrigger(unsigned long time, const QStringList& outputs)
|
||||
{
|
||||
waitTime = time;
|
||||
expectedOutputs = outputs;
|
||||
}
|
||||
};
|
||||
|
||||
Q_ENUM(Util::ClientType)
|
||||
|
||||
explicit Util(QObject *parent = nullptr);
|
||||
|
||||
void execCMD(const QString& cmd);
|
||||
QString execCMDWithOutput(const QString& cmd, ReturnTrigger trigger = 10000, bool rawOutput = false);
|
||||
void delay(unsigned int msec);
|
||||
static ClientType getClientType();
|
||||
static int rawTabIndex;
|
||||
static QDockWidget* rawDockPtr;
|
||||
static bool chooseLanguage(QSettings *guiSettings, QMainWindow *window);
|
||||
public slots:
|
||||
void processOutput(const QString& output);
|
||||
static void setClientType(Util::ClientType clientType);
|
||||
void setRunningState(bool st);
|
||||
static void gotoRawTab();
|
||||
static void setUI(Ui::MainWindow *ui);
|
||||
static void setRawTab(QDockWidget* dockPtr, int tabIndex);
|
||||
private:
|
||||
bool isRequiringOutput;
|
||||
bool isRunning;
|
||||
QString* requiredOutput;
|
||||
QTime timeStamp;
|
||||
static ClientType clientType;
|
||||
static Ui::MainWindow *ui;
|
||||
signals:
|
||||
void refreshOutput(const QString& output);
|
||||
void write(QString data); // connected to PM3Process::write(QString data);
|
||||
};
|
||||
|
||||
#endif // UTIL_H
|
||||
Binary file not shown.
+1411
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,7 @@
|
||||
<RCC>
|
||||
<qresource prefix="/i18n">
|
||||
<file>en_US.qm</file>
|
||||
<file>languages.ini</file>
|
||||
<file>zh_CN.qm</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
@@ -0,0 +1,4 @@
|
||||
[Languages]
|
||||
en_US=English
|
||||
zh_CN=简体中文
|
||||
ext=Load from external file
|
||||
Binary file not shown.
+1427
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,63 @@
|
||||
#include "ui/mainwindow.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QSettings>
|
||||
#include <QTranslator>
|
||||
#include <QMessageBox>
|
||||
#include <QTextCodec>
|
||||
#include <QDir>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
// A trick to handle non-ascii path
|
||||
// The application cannot find the plugins when the path contains non ascii characters.
|
||||
// However, the plugins will be load after creating MainWindow(or QApplication?).
|
||||
// QDir will handle the path correctly.
|
||||
QDir* pluginDir = new QDir;
|
||||
if(pluginDir->cd("plugins")) // has plugins folder
|
||||
{
|
||||
qputenv("QT_PLUGIN_PATH", pluginDir->absolutePath().toLocal8Bit());
|
||||
}
|
||||
delete pluginDir;
|
||||
|
||||
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
|
||||
QTextCodec::setCodecForLocale(QTextCodec::codecForName("UTF-8"));
|
||||
QApplication a(argc, argv);
|
||||
MainWindow w;
|
||||
|
||||
QSettings* settings = new QSettings("GUIsettings.ini", QSettings::IniFormat);
|
||||
settings->setIniCodec("UTF-8");
|
||||
settings->beginGroup("lang");
|
||||
QString currLang = settings->value("language", "").toString();
|
||||
settings->endGroup();
|
||||
if(currLang == "")
|
||||
{
|
||||
if(Util::chooseLanguage(settings, &w))
|
||||
{
|
||||
settings->beginGroup("lang");
|
||||
currLang = settings->value("language", "").toString();
|
||||
settings->endGroup();
|
||||
}
|
||||
else
|
||||
currLang = "en_US";
|
||||
}
|
||||
if(currLang == "ext")
|
||||
currLang = QFileDialog::getOpenFileName(nullptr, "Select the translation file:");
|
||||
else
|
||||
currLang = ":/i18n/" + currLang + ".qm";
|
||||
QTranslator* translator = new QTranslator(&w);
|
||||
if(translator->load(currLang))
|
||||
{
|
||||
a.installTranslator(translator);
|
||||
}
|
||||
else
|
||||
{
|
||||
QMessageBox::information(&w, "Error", "Can't load " + currLang + " as translation file.");
|
||||
}
|
||||
delete settings;
|
||||
w.initUI();
|
||||
w.show();
|
||||
return a.exec();
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,158 @@
|
||||
#include "lf.h"
|
||||
#include <QJsonArray>
|
||||
|
||||
const LF::LFConfig LF::defaultLFConfig;
|
||||
|
||||
LF::LF(Ui::MainWindow *ui, Util *addr, QWidget *parent): QObject(parent)
|
||||
{
|
||||
this->parent = parent;
|
||||
util = addr;
|
||||
this->ui = ui;
|
||||
|
||||
LFconfigPattern = new QRegularExpression("(\\d+)|Yes|No");
|
||||
currLFConfig = defaultLFConfig;
|
||||
}
|
||||
|
||||
void LF::read()
|
||||
{
|
||||
QVariantMap config = configMap["read"].toMap();
|
||||
util->execCMD(config["cmd"].toString());
|
||||
Util::gotoRawTab();
|
||||
util->execCMD(config["show cmd"].toString());
|
||||
}
|
||||
|
||||
void LF::sniff()
|
||||
{
|
||||
QVariantMap config = configMap["sniff"].toMap();
|
||||
util->execCMD(config["cmd"].toString());
|
||||
Util::gotoRawTab();
|
||||
util->execCMD(config["show cmd"].toString());
|
||||
}
|
||||
|
||||
void LF::search()
|
||||
{
|
||||
QVariantMap config = configMap["search"].toMap();
|
||||
util->execCMD(config["cmd"].toString());
|
||||
Util::gotoRawTab();
|
||||
}
|
||||
|
||||
void LF::tune()
|
||||
{
|
||||
QVariantMap config = configMap["tune"].toMap();
|
||||
QString cmd = config["cmd"].toString();
|
||||
cmd.replace("<divisor>", QString::number(currLFConfig.divisor));
|
||||
util->execCMD(cmd);
|
||||
Util::gotoRawTab();
|
||||
}
|
||||
|
||||
bool LF::getLFConfig_helper(const QVariantMap& map, QString& str, int* result)
|
||||
{
|
||||
int len;
|
||||
QString flag = map["flag"].toString();
|
||||
QRegularExpressionMatch reMatch;
|
||||
if(!str.contains(flag))
|
||||
return false;
|
||||
len = str.length() - (str.indexOf(flag) + flag.length());
|
||||
str = str.right(len);
|
||||
if(map.contains("replace"))
|
||||
{
|
||||
QVariantMap table = map["replace"].toMap();
|
||||
for(auto it = table.begin(); it != table.end(); it++)
|
||||
{
|
||||
str.replace(it.key(), it.value().toString());
|
||||
}
|
||||
}
|
||||
reMatch = QRegularExpression(map["pattern"].toString()).match(str);
|
||||
if(!reMatch.hasMatch())
|
||||
return false;
|
||||
*result = reMatch.captured().toInt();
|
||||
qDebug() << *result;
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
void LF::getLFConfig()
|
||||
{
|
||||
|
||||
QRegularExpressionMatch reMatch;
|
||||
QString result;
|
||||
QStringList resultList;
|
||||
int start, end, temp;
|
||||
QVariantMap config = configMap["get config"].toMap();
|
||||
QString cmd = config["cmd"].toString();
|
||||
result = util->execCMDWithOutput(cmd, 400);
|
||||
start = result.indexOf(config["field start"].toString());
|
||||
end = result.indexOf(config["field end"].toString());
|
||||
result = result.mid(start, end - start);
|
||||
#if (QT_VERSION <= QT_VERSION_CHECK(5,14,0))
|
||||
resultList = result.split("\n", QString::SkipEmptyParts);
|
||||
#else
|
||||
resultList = result.split("\n", Qt::SkipEmptyParts);
|
||||
#endif
|
||||
qDebug() << "LF CONFIG GET\n" << resultList;
|
||||
for(auto it = resultList.begin(); it != resultList.end(); it++)
|
||||
{
|
||||
if(getLFConfig_helper(config["divisor"].toMap(), *it, &temp))
|
||||
currLFConfig.divisor = temp;
|
||||
else if(getLFConfig_helper(config["bits per sample"].toMap(), *it, &temp))
|
||||
currLFConfig.bitsPerSample = temp;
|
||||
else if(getLFConfig_helper(config["decimation"].toMap(), *it, &temp))
|
||||
currLFConfig.decimation = temp;
|
||||
else if(getLFConfig_helper(config["averaging"].toMap(), *it, &temp))
|
||||
currLFConfig.averaging = (bool)temp;
|
||||
else if(getLFConfig_helper(config["trigger threshold"].toMap(), *it, &temp))
|
||||
currLFConfig.triggerThreshold = temp;
|
||||
else if(getLFConfig_helper(config["samples to skip"].toMap(), *it, &temp))
|
||||
currLFConfig.samplesToSkip = temp;
|
||||
}
|
||||
syncWithUI();
|
||||
}
|
||||
|
||||
void LF::setLFConfig(LF::LFConfig lfconfig)
|
||||
{
|
||||
currLFConfig = lfconfig;
|
||||
QVariantMap config = configMap["set config"].toMap();
|
||||
QString cmd = config["cmd"].toString();
|
||||
cmd.replace("<divisor>", QString::number(currLFConfig.divisor));
|
||||
cmd.replace("<bits per sample>", QString::number(currLFConfig.bitsPerSample));
|
||||
cmd.replace("<decimation>", QString::number(currLFConfig.decimation));
|
||||
cmd.replace("<averaging>", currLFConfig.averaging ? "1" : "0");
|
||||
cmd.replace("<trigger threshold>", QString::number(currLFConfig.triggerThreshold));
|
||||
cmd.replace("<samples to skip>", QString::number(currLFConfig.samplesToSkip));
|
||||
util->execCMDWithOutput(cmd, 500);
|
||||
cmd = config["divisor cmd"].toString();
|
||||
cmd.replace("<divisor>", QString::number(currLFConfig.divisor));
|
||||
util->execCMDWithOutput(cmd, 500);
|
||||
}
|
||||
|
||||
void LF::resetLFConfig()
|
||||
{
|
||||
setLFConfig(defaultLFConfig);
|
||||
getLFConfig();
|
||||
}
|
||||
|
||||
float LF::divisor2Freq(uint8_t divisor)
|
||||
{
|
||||
return (12000.0 / (divisor + 1.0));
|
||||
}
|
||||
|
||||
uint8_t LF::freq2Divisor(float freq)
|
||||
{
|
||||
return ((uint16_t)(12000.0 / freq + 0.5) - 1); // uint16_t for (divisor + 1) = 256
|
||||
}
|
||||
|
||||
void LF::syncWithUI()
|
||||
{
|
||||
ui->LF_LFConf_freqDivisorBox->setValue(currLFConfig.divisor); // will trigger valueChanged()
|
||||
ui->LF_LFConf_bitsPerSampleBox->setValue(currLFConfig.bitsPerSample);
|
||||
ui->LF_LFConf_decimationBox->setValue(currLFConfig.decimation);
|
||||
ui->LF_LFConf_averagingBox->setChecked(currLFConfig.averaging);
|
||||
ui->LF_LFConf_thresholdBox->setValue(currLFConfig.triggerThreshold);
|
||||
ui->LF_LFConf_skipsBox->setValue(currLFConfig.samplesToSkip);
|
||||
}
|
||||
|
||||
void LF::setConfigMap(const QVariantMap& configMap)
|
||||
{
|
||||
this->configMap = configMap;
|
||||
qDebug() << configMap;
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
#ifndef LF_H
|
||||
#define LF_H
|
||||
|
||||
#include <QObject>
|
||||
|
||||
#include "common/util.h"
|
||||
#include "ui_mainwindow.h"
|
||||
|
||||
class LF : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit LF(Ui::MainWindow *ui, Util *addr, QWidget *parent = nullptr);
|
||||
|
||||
struct LFConfig
|
||||
{
|
||||
uint8_t divisor;
|
||||
uint8_t bitsPerSample;
|
||||
uint8_t decimation;
|
||||
bool averaging;
|
||||
uint8_t triggerThreshold;
|
||||
uint16_t samplesToSkip;
|
||||
};
|
||||
|
||||
static constexpr LFConfig defaultLFConfig =
|
||||
{
|
||||
95,
|
||||
8,
|
||||
1,
|
||||
true,
|
||||
0,
|
||||
0
|
||||
};
|
||||
|
||||
void read();
|
||||
void sniff();
|
||||
void search();
|
||||
void tune();
|
||||
void getLFConfig();
|
||||
void setLFConfig(LF::LFConfig lfconfig);
|
||||
void resetLFConfig();
|
||||
static float divisor2Freq(uint8_t divisor);
|
||||
static uint8_t freq2Divisor(float freq);
|
||||
|
||||
void setConfigMap(const QVariantMap &configMap);
|
||||
private:
|
||||
QWidget* parent;
|
||||
Ui::MainWindow *ui;
|
||||
Util* util;
|
||||
LFConfig currLFConfig;
|
||||
QRegularExpression* LFconfigPattern;
|
||||
QVariantMap configMap;
|
||||
void syncWithUI();
|
||||
bool getLFConfig_helper(const QVariantMap& map, QString& str, int* result);
|
||||
signals:
|
||||
|
||||
};
|
||||
|
||||
#endif // LF_H
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,141 @@
|
||||
#ifndef MIFARE_H
|
||||
#define MIFARE_H
|
||||
|
||||
#include "common/util.h"
|
||||
#include "ui_mainwindow.h"
|
||||
#include "ui/mf_attack_hardnesteddialog.h"
|
||||
#include "ui/mf_uid_parameterdialog.h"
|
||||
#include "ui/mf_sim_simdialog.h"
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
#include <QRegularExpression>
|
||||
#include <QMessageBox>
|
||||
#include <QJsonObject>
|
||||
class Mifare : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit Mifare(Ui::MainWindow *ui, Util *addr, QWidget *parent = nullptr);
|
||||
|
||||
enum KeyType
|
||||
{
|
||||
KEY_A = 'A',
|
||||
KEY_B = 'B',
|
||||
};
|
||||
|
||||
enum DataType
|
||||
{
|
||||
DATA_INVALID,
|
||||
DATA_WITHSPACE,
|
||||
DATA_NOSPACE,
|
||||
};
|
||||
|
||||
struct CardType
|
||||
{
|
||||
quint8 type;
|
||||
quint8 sector_size;
|
||||
quint16 block_size;
|
||||
quint8 blk[40];
|
||||
quint8 blks[40];
|
||||
QString typeText;
|
||||
};
|
||||
|
||||
enum AccessType
|
||||
{
|
||||
ACC_NEVER = 0,
|
||||
ACC_KEY_A = 1,
|
||||
ACC_KEY_B = 2,
|
||||
ACC_KEY_AB = 3,
|
||||
};
|
||||
|
||||
enum TargetType
|
||||
{
|
||||
TARGET_MIFARE,
|
||||
TARGET_UID,
|
||||
TARGET_EMULATOR,
|
||||
};
|
||||
|
||||
static const CardType card_mini;
|
||||
static const CardType card_1k;
|
||||
static const CardType card_2k;
|
||||
static const CardType card_4k;
|
||||
|
||||
static const AccessType dataCondition[8][4];
|
||||
static const AccessType trailerReadCondition[8][3];
|
||||
static const AccessType trailerWriteCondition[8][3];
|
||||
|
||||
QMap<QString, QString> info(bool isRequiringOutput = false);
|
||||
void chk();
|
||||
void nested(bool isStaticNested = false);
|
||||
void darkside();
|
||||
void hardnested();
|
||||
void sniff();
|
||||
void sniff14a();
|
||||
void list();
|
||||
void readOne(TargetType targetType = TARGET_MIFARE);
|
||||
void readSelected(TargetType targetType = TARGET_MIFARE);
|
||||
void writeOne(TargetType targetType = TARGET_MIFARE);
|
||||
void writeSelected(TargetType targetType = TARGET_MIFARE);
|
||||
void dump();
|
||||
void restore();
|
||||
|
||||
void data_clearData(bool clearAll = true);
|
||||
void data_clearKey(bool clearAll = true);
|
||||
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);
|
||||
|
||||
CardType cardType;
|
||||
Mifare::CardType getCardType();
|
||||
void setCardType(int type);
|
||||
void wipeC();
|
||||
void setParameterC();
|
||||
|
||||
bool data_loadDataFile(const QString& filename);
|
||||
bool data_loadKeyFile(const QString& filename);
|
||||
bool data_saveDataFile(const QString& filename, bool isBin);
|
||||
bool data_saveKeyFile(const QString& filename, bool isBin);
|
||||
void data_key2Data();
|
||||
void data_data2Key();
|
||||
|
||||
void data_setData(int block, const QString& data);
|
||||
void data_setKey(int sector, KeyType keyType, const QString& key);
|
||||
void lockC();
|
||||
void wipeE();
|
||||
void simulate();
|
||||
void loadSniff(const QString& file);
|
||||
void saveSniff(const QString& file);
|
||||
void data_fillKeys();
|
||||
|
||||
static QList<quint8> data_getACBits(const QString& text);
|
||||
static int data_b2s(int block);
|
||||
static bool data_isACBitsValid(const QString& text, QList<quint8> *returnHalfBytes = nullptr);
|
||||
QString data_getUID();
|
||||
quint16 getTrailerBlockId(quint8 sectorId, qint8 cardTypeId = -1); // -1: use current cardtype
|
||||
void setConfigMap(const QVariantMap& configMap);
|
||||
public slots:
|
||||
signals:
|
||||
|
||||
private:
|
||||
QWidget* parent;
|
||||
Ui::MainWindow *ui;
|
||||
Util* util;
|
||||
|
||||
QVariantMap configMap;
|
||||
|
||||
QStringList* keyAList;
|
||||
QStringList* keyBList;
|
||||
QStringList* dataList;
|
||||
QRegularExpression* dataPattern;
|
||||
QRegularExpression* keyPattern_res;
|
||||
QRegularExpression* keyPattern;
|
||||
QString bin2text(const QByteArray& buff, int start, int length);
|
||||
|
||||
QString _readblk(int blockId, KeyType keyType, const QString& key, TargetType targetType = TARGET_MIFARE, int waitTime = 300);
|
||||
QStringList _readsec(int sectorId, KeyType keyType, const QString& key, TargetType targetType = TARGET_MIFARE, int waitTime = 300);
|
||||
bool _writeblk(int blockId, KeyType keyType, const QString& key, const QString& data, TargetType targetType = TARGET_MIFARE, int waitTime = 300);
|
||||
};
|
||||
|
||||
#endif // MIFARE_H
|
||||
@@ -0,0 +1,14 @@
|
||||
#include "t55xxtab.h"
|
||||
#include "ui_t55xxtab.h"
|
||||
|
||||
T55xxTab::T55xxTab(QWidget *parent) :
|
||||
QWidget(parent),
|
||||
ui(new Ui::T55xxTab)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
}
|
||||
|
||||
T55xxTab::~T55xxTab()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
#ifndef T55XXTAB_H
|
||||
#define T55XXTAB_H
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
namespace Ui {
|
||||
class T55xxTab;
|
||||
}
|
||||
|
||||
class T55xxTab : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit T55xxTab(QWidget *parent = nullptr);
|
||||
~T55xxTab();
|
||||
|
||||
private:
|
||||
Ui::T55xxTab *ui;
|
||||
};
|
||||
|
||||
#endif // T55XXTAB_H
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,266 @@
|
||||
#ifndef MAINWINDOW_H
|
||||
#define MAINWINDOW_H
|
||||
|
||||
#include <QMainWindow>
|
||||
#include <QThread>
|
||||
#include <QProcess>
|
||||
#include <QDebug>
|
||||
#include <QMessageBox>
|
||||
#include <QListWidgetItem>
|
||||
#include <QButtonGroup>
|
||||
#include <QRadioButton>
|
||||
#include <QFileDialog>
|
||||
#include <QFontDialog>
|
||||
#include <QtSerialPort/QSerialPortInfo>
|
||||
#include <QtSerialPort/QSerialPort>
|
||||
#include <QMimeData>
|
||||
#include <QAction>
|
||||
#include <QDesktopServices>
|
||||
#include <QGroupBox>
|
||||
#include <QSizePolicy>
|
||||
#include <QSettings>
|
||||
#include <QPushButton>
|
||||
#include <QProcessEnvironment>
|
||||
#include <QScrollBar>
|
||||
#include <QTimer>
|
||||
#include <QDateTime>
|
||||
#include <QDockWidget>
|
||||
#include <QMenu>
|
||||
|
||||
#include "common/myeventfilter.h"
|
||||
#include "common/pm3process.h"
|
||||
#include "module/mifare.h"
|
||||
#include "module/lf.h"
|
||||
#include "common/util.h"
|
||||
#include "ui/mf_trailerdecoderdialog.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
namespace Ui
|
||||
{
|
||||
class MainWindow;
|
||||
}
|
||||
QT_END_NAMESPACE
|
||||
|
||||
class MainWindow : public QMainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MainWindow(QWidget *parent = nullptr);
|
||||
~MainWindow();
|
||||
|
||||
void initUI();
|
||||
bool eventFilter(QObject *watched, QEvent *event);
|
||||
public slots:
|
||||
void refreshOutput(const QString& output);
|
||||
void refreshCMD(const QString& cmd);
|
||||
void setStatusBar(QLabel* target, const QString& text);
|
||||
void onPM3StateChanged(bool st, const QString& info);
|
||||
void MF_onMFCardTypeChanged(int id, bool st);
|
||||
void on_Raw_keyPressed(QObject *obj_addr, QEvent &event);
|
||||
void on_MF_keyWidget_resized(QObject *obj_addr, QEvent &event);
|
||||
private slots:
|
||||
|
||||
void on_PM3_connectButton_clicked();
|
||||
|
||||
void on_Raw_sendCMDButton_clicked();
|
||||
|
||||
void on_PM3_disconnectButton_clicked();
|
||||
|
||||
void on_Raw_clearOutputButton_clicked();
|
||||
|
||||
void sendMSG();
|
||||
|
||||
void on_portSearchTimer_timeout();
|
||||
|
||||
void on_Raw_CMDHistoryBox_stateChanged(int arg1);
|
||||
|
||||
void on_Raw_clearHistoryButton_clicked();
|
||||
|
||||
void on_Raw_CMDHistoryWidget_itemDoubleClicked(QListWidgetItem *item);
|
||||
|
||||
void on_MF_Attack_chkButton_clicked();
|
||||
|
||||
void on_MF_Attack_nestedButton_clicked();
|
||||
|
||||
void on_MF_Attack_hardnestedButton_clicked();
|
||||
|
||||
void on_MF_Sniff_sniffButton_clicked();
|
||||
|
||||
void on_MF_Sniff_listButton_clicked();
|
||||
|
||||
void on_MF_RW_readSelectedButton_clicked();
|
||||
|
||||
void on_MF_RW_readBlockButton_clicked();
|
||||
|
||||
void on_MF_RW_writeBlockButton_clicked();
|
||||
|
||||
void on_MF_Attack_infoButton_clicked();
|
||||
|
||||
void on_MF_RW_writeSelectedButton_clicked();
|
||||
|
||||
void on_MF_RW_dumpButton_clicked();
|
||||
|
||||
void on_MF_RW_restoreButton_clicked();
|
||||
|
||||
void on_MF_UID_readSelectedButton_clicked();
|
||||
|
||||
void on_MF_UID_readBlockButton_clicked();
|
||||
|
||||
void on_MF_UID_writeSelectedButton_clicked();
|
||||
|
||||
void on_MF_UID_writeBlockButton_clicked();
|
||||
|
||||
void on_MF_File_loadButton_clicked();
|
||||
|
||||
void on_MF_File_saveButton_clicked();
|
||||
|
||||
void on_MF_data2KeyButton_clicked();
|
||||
|
||||
void on_MF_key2DataButton_clicked();
|
||||
|
||||
void on_MF_dataWidget_itemChanged(QTableWidgetItem *item);
|
||||
|
||||
void on_MF_File_clearButton_clicked();
|
||||
|
||||
void on_MF_keyWidget_itemChanged(QTableWidgetItem *item);
|
||||
|
||||
void on_MF_fontButton_clicked();
|
||||
|
||||
void on_MF_UID_wipeButton_clicked();
|
||||
|
||||
void on_MF_UID_aboutUIDButton_clicked();
|
||||
|
||||
void on_MF_UID_setParaButton_clicked();
|
||||
|
||||
void on_MF_UID_lockButton_clicked();
|
||||
|
||||
void on_MF_Sim_readSelectedButton_clicked();
|
||||
|
||||
void on_MF_Sim_writeSelectedButton_clicked();
|
||||
|
||||
void on_MF_Sim_clearButton_clicked();
|
||||
|
||||
void on_MF_Sim_simButton_clicked();
|
||||
|
||||
void on_MF_Sniff_loadButton_clicked();
|
||||
|
||||
void on_MF_Sniff_saveButton_clicked();
|
||||
|
||||
void on_GroupBox_clicked(bool checked);
|
||||
|
||||
void on_MF_selectAllBox_stateChanged(int arg1);
|
||||
|
||||
void on_MF_fillKeysButton_clicked();
|
||||
|
||||
void on_MF_14aSniff_snoopButton_clicked();
|
||||
|
||||
void on_MF_trailerDecoderButton_clicked();
|
||||
|
||||
void on_MF_selectTrailerBox_stateChanged(int arg1);
|
||||
|
||||
void on_stopButton_clicked();
|
||||
|
||||
void on_Raw_CMDEdit_textChanged(const QString &arg1);
|
||||
|
||||
void on_MF_Attack_darksideButton_clicked();
|
||||
|
||||
void on_Set_Client_startArgsEdit_editingFinished();
|
||||
|
||||
void on_Set_Client_forceEnabledBox_stateChanged(int arg1);
|
||||
|
||||
void on_Set_GUI_setLanguageButton_clicked();
|
||||
|
||||
void setButtonsEnabled(bool st);
|
||||
|
||||
void on_PM3_refreshPortButton_clicked();
|
||||
|
||||
void on_Set_Client_envScriptEdit_editingFinished();
|
||||
|
||||
void on_Set_Client_keepClientActiveBox_stateChanged(int arg1);
|
||||
|
||||
void on_LF_LFConf_freqSlider_valueChanged(int value);
|
||||
|
||||
void on_LF_LFConf_freqDivisorBox_valueChanged(int arg1);
|
||||
|
||||
void on_LF_LFConf_freq125kButton_clicked();
|
||||
|
||||
void on_LF_LFConf_freq134kButton_clicked();
|
||||
|
||||
void on_LF_Op_searchButton_clicked();
|
||||
|
||||
void on_LF_Op_readButton_clicked();
|
||||
|
||||
void on_LF_Op_tuneButton_clicked();
|
||||
|
||||
void on_LF_Op_sniffButton_clicked();
|
||||
|
||||
void on_LF_LFConf_getButton_clicked();
|
||||
|
||||
void on_LF_LFConf_setButton_clicked();
|
||||
|
||||
void on_LF_LFConf_resetButton_clicked();
|
||||
|
||||
void on_Set_Client_workingDirEdit_editingFinished();
|
||||
|
||||
void on_Set_Client_configPathEdit_editingFinished();
|
||||
|
||||
private:
|
||||
Ui::MainWindow* ui;
|
||||
QButtonGroup* MFCardTypeBtnGroup;
|
||||
QLabel* connectStatusBar;
|
||||
QLabel* programStatusBar;
|
||||
QLabel* PM3VersionBar;
|
||||
QPushButton* stopButton;
|
||||
QAction* dockAllWindows;
|
||||
QAction* myInfo;
|
||||
QAction* currVersion;
|
||||
QAction* checkUpdate;
|
||||
QSettings* settings;
|
||||
MyEventFilter* keyEventFilter;
|
||||
MyEventFilter* resizeEventFilter;
|
||||
|
||||
QString stashedCMDEditText;
|
||||
int stashedIndex = -1;
|
||||
|
||||
void uiInit();
|
||||
|
||||
PM3Process* pm3;
|
||||
bool pm3state;
|
||||
bool keepButtonsEnabled;
|
||||
bool keepClientActive;
|
||||
QThread* pm3Thread;
|
||||
QTimer* portSearchTimer;
|
||||
QStringList portList;
|
||||
QStringList clientEnv;
|
||||
QDir* clientWorkingDir;
|
||||
|
||||
Mifare* mifare;
|
||||
LF* lf;
|
||||
Util* util;
|
||||
|
||||
QList<QDockWidget*> dockList;
|
||||
QMenu* contextMenu;
|
||||
|
||||
MF_trailerDecoderDialog* decDialog;
|
||||
|
||||
void signalInit();
|
||||
void MF_widgetReset();
|
||||
void setTableItem(QTableWidget *widget, int row, int column, const QString& text);
|
||||
void setState(bool st);
|
||||
void saveClientPath(const QString& path);
|
||||
void onLFfreqConfChanged(int value, bool isCustomized);
|
||||
void dockInit();
|
||||
void loadConfig();
|
||||
protected:
|
||||
void contextMenuEvent(QContextMenuEvent *event) override;
|
||||
signals:
|
||||
void connectPM3(const QString& path, const QStringList args);
|
||||
void reconnectPM3();
|
||||
void killPM3();
|
||||
void setSerialListener(bool state);
|
||||
void setSerialListener(const QString& name, bool state);
|
||||
void setProcEnv(const QStringList *env);
|
||||
void setWorkingDir(const QString& dir);
|
||||
};
|
||||
#endif // MAINWINDOW_H
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,32 @@
|
||||
#include "mf_attack_hardnesteddialog.h"
|
||||
#include "ui_mf_attack_hardnesteddialog.h"
|
||||
|
||||
MF_Attack_hardnestedDialog::MF_Attack_hardnestedDialog(int blocks, const QVariantMap& config, QWidget *parent) :
|
||||
QDialog(parent),
|
||||
ui(new Ui::MF_Attack_hardnestedDialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
for(int i = 0; i < blocks; i++)
|
||||
{
|
||||
ui->knownKeyBlockBox->addItem(QString::number(i));
|
||||
ui->targetKeyBlockBox->addItem(QString::number(i));
|
||||
}
|
||||
this->config = config;
|
||||
|
||||
}
|
||||
|
||||
MF_Attack_hardnestedDialog::~MF_Attack_hardnestedDialog()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void MF_Attack_hardnestedDialog::on_buttonBox_accepted()
|
||||
{
|
||||
QString cmd = config["cmd"].toString();
|
||||
cmd.replace("<known key block>", ui->knownKeyBlockBox->currentText());
|
||||
cmd.replace("<known key type>", config["known key type"].toMap()[ui->knownKeyTypeBox->currentText()].toString());
|
||||
cmd.replace("<known key>", ui->knownKeyBox->text());
|
||||
cmd.replace("<target key block>", ui->targetKeyBlockBox->currentText());
|
||||
cmd.replace("<target key type>", config["target key type"].toMap()[ui->targetKeyTypeBox->currentText()].toString());
|
||||
emit sendCMD(cmd);
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
#ifndef MF_ATTACK_HARDNESTEDDIALOG_H
|
||||
#define MF_ATTACK_HARDNESTEDDIALOG_H
|
||||
|
||||
#include <QDialog>
|
||||
#include "common/util.h"
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class MF_Attack_hardnestedDialog;
|
||||
}
|
||||
|
||||
class MF_Attack_hardnestedDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit MF_Attack_hardnestedDialog(int blocks, const QVariantMap& config, QWidget *parent = nullptr);
|
||||
~MF_Attack_hardnestedDialog();
|
||||
|
||||
|
||||
private:
|
||||
Ui::MF_Attack_hardnestedDialog *ui;
|
||||
QVariantMap config;
|
||||
signals:
|
||||
void sendCMD(const QString& cmd);
|
||||
private slots:
|
||||
void on_buttonBox_accepted();
|
||||
};
|
||||
|
||||
#endif // MF_ATTACK_HARDNESTEDDIALOG_H
|
||||
@@ -0,0 +1,228 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>MF_Attack_hardnestedDialog</class>
|
||||
<widget class="QDialog" name="MF_Attack_hardnestedDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>287</width>
|
||||
<height>173</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Hardnested Attack</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Known Block:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Block:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="knownKeyBlockBox">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>60</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>60</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="editable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="knownKeyTypeBox">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>35</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>35</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>A</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>B</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="knownKeyBox">
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Courier</family>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">FFFFFFFFFFFF</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Target Block:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>Block:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="targetKeyBlockBox">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>60</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>60</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="editable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="targetKeyTypeBox">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>35</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>35</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>A</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>B</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>31</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>MF_Attack_hardnestedDialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>MF_Attack_hardnestedDialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
@@ -0,0 +1,103 @@
|
||||
#include "mf_sim_simdialog.h"
|
||||
#include "ui_mf_sim_simdialog.h"
|
||||
|
||||
MF_Sim_simDialog::MF_Sim_simDialog(int cardType, QString cardTypeText, QWidget *parent) :
|
||||
QDialog(parent),
|
||||
ui(new Ui::MF_Sim_simDialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
if(Util::getClientType() == Util::CLIENTTYPE_OFFICIAL)
|
||||
{
|
||||
ui->atqaGroupBox->setVisible(false);
|
||||
ui->atqaLine->setVisible(false);
|
||||
ui->sakGroupBox->setVisible(false);
|
||||
ui->sakLine->setVisible(false);
|
||||
ui->vGroupBox->setVisible(false);
|
||||
ui->vLine->setVisible(false);
|
||||
}
|
||||
else if(Util::getClientType() == Util::CLIENTTYPE_ICEMAN)
|
||||
{
|
||||
ui->fGroupBox->setVisible(false);
|
||||
ui->fLine->setVisible(false);
|
||||
ui->rGroupBox->setVisible(false);
|
||||
ui->rLine->setVisible(false);
|
||||
ui->uBox->setText("-u");
|
||||
ui->nBox->setText("-n");
|
||||
ui->iBox->setText("-i");
|
||||
ui->xBox->setText("--crack");
|
||||
ui->eBox->setText("-e");
|
||||
}
|
||||
this->cardType = cardType;
|
||||
this->cardTypeText = cardTypeText;
|
||||
}
|
||||
|
||||
MF_Sim_simDialog::~MF_Sim_simDialog()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void MF_Sim_simDialog::on_eBox_clicked(bool checked)
|
||||
{
|
||||
if(checked)
|
||||
{
|
||||
ui->iBox->setChecked(true);
|
||||
ui->xBox->setChecked(true);
|
||||
}
|
||||
if(!ui->eBox->isChecked() && !ui->fBox->isChecked())
|
||||
{
|
||||
ui->iBox->setEnabled(true);
|
||||
ui->xBox->setEnabled(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->iBox->setEnabled(false);
|
||||
ui->xBox->setEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
void MF_Sim_simDialog::on_fBox_clicked(bool checked)
|
||||
{
|
||||
if(checked)
|
||||
{
|
||||
ui->iBox->setChecked(true);
|
||||
ui->xBox->setChecked(true);
|
||||
}
|
||||
if(!ui->eBox->isChecked() && !ui->fBox->isChecked())
|
||||
{
|
||||
ui->iBox->setEnabled(true);
|
||||
ui->xBox->setEnabled(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->iBox->setEnabled(false);
|
||||
ui->xBox->setEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
void MF_Sim_simDialog::on_buttonBox_accepted()
|
||||
{
|
||||
QString paras;
|
||||
if(Util::getClientType() == Util::CLIENTTYPE_OFFICIAL)
|
||||
{
|
||||
paras += (ui->uBox->isChecked() ? "u " + ui->uEdit->text() + " " : "");
|
||||
paras += (ui->nBox->isChecked() ? "n " + ui->nEdit->text() + " " : "");
|
||||
paras += (ui->iBox->isChecked() ? "i " : "");
|
||||
paras += (ui->xBox->isChecked() ? "x " : "");
|
||||
paras += (ui->eBox->isChecked() ? "e " : "");
|
||||
paras += (ui->fBox->isChecked() ? "f " + ui->fEdit->text() + " " : "");
|
||||
paras += (ui->rBox->isChecked() ? "r " : "");
|
||||
emit sendCMD(QString("hf mf sim ") + "*" + QString::number(cardType) + " " + paras.trimmed());
|
||||
}
|
||||
else if(Util::getClientType() == Util::CLIENTTYPE_ICEMAN)
|
||||
{
|
||||
paras += (ui->uBox->isChecked() ? "-u " + ui->uEdit->text() + " " : "");
|
||||
paras += (ui->atqaBox->isChecked() ? "--atqa " + ui->atqaEdit->text() + " " : "");
|
||||
paras += (ui->sakBox->isChecked() ? "--sak " + ui->sakEdit->text() + " " : "");
|
||||
paras += (ui->nBox->isChecked() ? "-n " + ui->nEdit->text() + " " : "");
|
||||
paras += (ui->iBox->isChecked() ? "-i " : "");
|
||||
paras += (ui->xBox->isChecked() ? "--crack " : "");
|
||||
paras += (ui->eBox->isChecked() ? "-e " : "");
|
||||
paras += (ui->vBox->isChecked() ? "-v " : "");
|
||||
emit sendCMD(QString("hf mf sim --") + cardTypeText + " " + paras.trimmed());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
#ifndef MF_SIM_SIMDIALOG_H
|
||||
#define MF_SIM_SIMDIALOG_H
|
||||
|
||||
#include <QDialog>
|
||||
#include <QDebug>
|
||||
#include "common/util.h"
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class MF_Sim_simDialog;
|
||||
}
|
||||
|
||||
class MF_Sim_simDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit MF_Sim_simDialog(int cardType, QString cardTypeText, QWidget *parent = nullptr);
|
||||
~MF_Sim_simDialog();
|
||||
|
||||
private slots:
|
||||
void on_eBox_clicked(bool checked);
|
||||
|
||||
void on_fBox_clicked(bool checked);
|
||||
|
||||
private:
|
||||
Ui::MF_Sim_simDialog *ui;
|
||||
int cardType;
|
||||
QString cardTypeText;
|
||||
signals:
|
||||
void sendCMD(const QString& cmd);
|
||||
private slots:
|
||||
void on_buttonBox_accepted();
|
||||
};
|
||||
|
||||
#endif // MF_SIM_SIMDIALOG_H
|
||||
@@ -0,0 +1,667 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>MF_Sim_simDialog</class>
|
||||
<widget class="QDialog" name="MF_Sim_simDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>461</width>
|
||||
<height>524</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Simulate</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="uGroupBox">
|
||||
<layout class="QHBoxLayout" name="uLayout">
|
||||
<property name="spacing">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="uBox">
|
||||
<property name="text">
|
||||
<string>u</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="uEdit">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>UID 4 or 7 bytes. If not specified, the UID 4B from emulator memory will be used</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="uLine">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="atqaGroupBox">
|
||||
<layout class="QHBoxLayout" name="atqaLayout">
|
||||
<property name="spacing">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="atqaBox">
|
||||
<property name="text">
|
||||
<string>--atqa</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="atqaEdit">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_8">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Provide explicit ATQA (2 bytes)</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="atqaLine">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="sakGroupBox">
|
||||
<layout class="QHBoxLayout" name="sakLayout">
|
||||
<property name="spacing">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="sakBox">
|
||||
<property name="text">
|
||||
<string>--sak</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="sakEdit">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_9">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Provide explicit SAK (1 byte)</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="sakLine">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="nGroupBox">
|
||||
<layout class="QHBoxLayout" name="nLayout">
|
||||
<property name="spacing">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="nBox">
|
||||
<property name="text">
|
||||
<string>n</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="nEdit">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Automatically exit simulation after <numreads> blocks have been read by reader. 0 = infinite</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="nLine">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="iGroupBox">
|
||||
<layout class="QHBoxLayout" name="iLayout">
|
||||
<property name="spacing">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="iBox">
|
||||
<property name="text">
|
||||
<string>i</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Interactive, means that console will not be returned until simulation finishes or is aborted</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="iLine">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="xGroupBox">
|
||||
<layout class="QHBoxLayout" name="xLayout">
|
||||
<property name="spacing">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="xBox">
|
||||
<property name="text">
|
||||
<string>x</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Crack, performs the 'reader attack', nr/ar attack against a legitimate reader, fishes out the key(s)</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="xLine">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="eGroupBox">
|
||||
<layout class="QHBoxLayout" name="eLayout">
|
||||
<property name="spacing">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="eBox">
|
||||
<property name="text">
|
||||
<string>e</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>set keys found from 'reader attack' to emulator memory (implies x(--crack) and i)</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="eLine">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="fGroupBox">
|
||||
<layout class="QHBoxLayout" name="fLayout">
|
||||
<property name="spacing">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="fBox">
|
||||
<property name="text">
|
||||
<string>f</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="fEdit">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>get UIDs to use for 'reader attack' from file 'f <filename.txt>' (implies x and i)</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="fLine">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="rGroupBox">
|
||||
<layout class="QHBoxLayout" name="rLayout">
|
||||
<property name="spacing">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="rBox">
|
||||
<property name="text">
|
||||
<string>r</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Generate random nonces instead of sequential nonces. Standard reader attack won't work with this option, only moebius attack works</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="rLine">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="vGroupBox">
|
||||
<layout class="QHBoxLayout" name="vLayout">
|
||||
<property name="spacing">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="vBox">
|
||||
<property name="text">
|
||||
<string>-v</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_11">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>verbose output</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="vLine">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>MF_Sim_simDialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>MF_Sim_simDialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
@@ -0,0 +1,154 @@
|
||||
#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<int, bool>::of(&QButtonGroup::buttonToggled), this, &MF_trailerDecoderDialog::on_blockSizeChanged);
|
||||
connect(ui->C0Box, QOverload<int>::of(&QSpinBox::valueChanged), this, &MF_trailerDecoderDialog::on_boxChanged);
|
||||
connect(ui->C1Box, QOverload<int>::of(&QSpinBox::valueChanged), this, &MF_trailerDecoderDialog::on_boxChanged);
|
||||
connect(ui->C2Box, QOverload<int>::of(&QSpinBox::valueChanged), this, &MF_trailerDecoderDialog::on_boxChanged);
|
||||
connect(ui->C3Box, QOverload<int>::of(&QSpinBox::valueChanged), this, &MF_trailerDecoderDialog::on_boxChanged);
|
||||
|
||||
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_textChanged(const QString &arg1)
|
||||
{
|
||||
ui->C0Box->blockSignals(true);
|
||||
ui->C1Box->blockSignals(true);
|
||||
ui->C2Box->blockSignals(true);
|
||||
ui->C3Box->blockSignals(true);
|
||||
QList<quint8> ACBits = Mifare::data_getACBits(arg1);
|
||||
if(ACBits.size() == 0)
|
||||
{
|
||||
ui->isAccessBitsValidLabel->setStyleSheet("color:rgb(200, 0, 0)");
|
||||
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"));
|
||||
bool isKeyBReadable = ACBits[3] == 0 || ACBits[3] == 1 || ACBits[3] == 4;
|
||||
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++)
|
||||
{
|
||||
Mifare::AccessType type = Mifare::dataCondition[ACBits[i]][j];
|
||||
if(type == Mifare::ACC_KEY_B && isKeyBReadable)
|
||||
{
|
||||
type = Mifare::ACC_NEVER;
|
||||
}
|
||||
else if(type == Mifare::ACC_KEY_AB && isKeyBReadable)
|
||||
{
|
||||
type = Mifare::ACC_KEY_A;
|
||||
}
|
||||
setTableItem(ui->dataBlockWidget, i, j, type);
|
||||
}
|
||||
}
|
||||
}
|
||||
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)
|
||||
{
|
||||
if(st)
|
||||
{
|
||||
if(id == 4)
|
||||
{
|
||||
ui->dataBlockWidget->verticalHeaderItem(0)->setText(tr("Block") + "0");
|
||||
ui->dataBlockWidget->verticalHeaderItem(1)->setText(tr("Block") + "1");
|
||||
ui->dataBlockWidget->verticalHeaderItem(2)->setText(tr("Block") + "2");
|
||||
}
|
||||
else if(id == 16)
|
||||
{
|
||||
ui->dataBlockWidget->verticalHeaderItem(0)->setText(tr("Block") + "0~4");
|
||||
ui->dataBlockWidget->verticalHeaderItem(1)->setText(tr("Block") + "5~9");
|
||||
ui->dataBlockWidget->verticalHeaderItem(2)->setText(tr("Block") + "10~14");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void MF_trailerDecoderDialog::setTableItem(QTableWidget* widget, int row, int column, Mifare::AccessType accessType)
|
||||
{
|
||||
if(widget->item(row, column) == nullptr)
|
||||
widget->setItem(row, column, new QTableWidgetItem());
|
||||
QString text;
|
||||
if(accessType == Mifare::ACC_NEVER)
|
||||
{
|
||||
text = "X";
|
||||
}
|
||||
else if(accessType == Mifare::ACC_KEY_A)
|
||||
{
|
||||
text = tr("KeyA");
|
||||
}
|
||||
else if(accessType == Mifare::ACC_KEY_B)
|
||||
{
|
||||
text = tr("KeyB");
|
||||
}
|
||||
else if(accessType == Mifare::ACC_KEY_AB)
|
||||
{
|
||||
text = tr("KeyA+B");
|
||||
}
|
||||
widget->item(row, column)->setText(text);
|
||||
}
|
||||
|
||||
void MF_trailerDecoderDialog::on_boxChanged()
|
||||
{
|
||||
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);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
#ifndef MF_TRAILERDECODERDIALOG_H
|
||||
#define MF_TRAILERDECODERDIALOG_H
|
||||
|
||||
#include <QDialog>
|
||||
#include <QValidator>
|
||||
#include <QDebug>
|
||||
#include <QButtonGroup>
|
||||
#include <QTableWidget>
|
||||
#include "../module/mifare.h"
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class MF_trailerDecoderDialog;
|
||||
}
|
||||
|
||||
class MF_trailerDecoderDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit MF_trailerDecoderDialog(QWidget *parent = nullptr);
|
||||
~MF_trailerDecoderDialog();
|
||||
|
||||
private slots:
|
||||
|
||||
void on_accessBitsEdit_textChanged(const QString& arg1);
|
||||
|
||||
void on_blockSizeChanged(int id, bool st);
|
||||
|
||||
void on_boxChanged();
|
||||
private:
|
||||
Ui::MF_trailerDecoderDialog *ui;
|
||||
QRegularExpressionValidator* validator;
|
||||
QButtonGroup* sizeGroup;
|
||||
void setTableItem(QTableWidget *widget, int row, int column, Mifare::AccessType accessType);
|
||||
|
||||
};
|
||||
|
||||
#endif // MF_TRAILERDECODERDIALOG_H
|
||||
@@ -0,0 +1,402 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>MF_trailerDecoderDialog</class>
|
||||
<widget class="QDialog" name="MF_trailerDecoderDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>534</width>
|
||||
<height>507</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Trailer Decoder</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_7">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="sizeGroupBox">
|
||||
<property name="title">
|
||||
<string>Blocks</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QRadioButton" name="size4Button">
|
||||
<property name="text">
|
||||
<string>4</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="size16Button">
|
||||
<property name="text">
|
||||
<string>16</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_5">
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Trailer Data:
|
||||
(like "FF0780" or "FF 07 80")</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="accessBitsEdit"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="isAccessBitsValidLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::MinimumExpanding</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_6">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>Or set bits manually</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="text">
|
||||
<string>Cx0</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="C0Box">
|
||||
<property name="maximum">
|
||||
<number>7</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="text">
|
||||
<string>Cx1</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="C1Box">
|
||||
<property name="maximum">
|
||||
<number>7</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_8">
|
||||
<property name="text">
|
||||
<string>Cx2</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="C2Box">
|
||||
<property name="maximum">
|
||||
<number>7</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_5">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_9">
|
||||
<property name="text">
|
||||
<string>Cx3</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="C3Box">
|
||||
<property name="maximum">
|
||||
<number>7</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::MinimumExpanding</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Data Block Permission:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTableWidget" name="dataBlockWidget">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>4</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="editTriggers">
|
||||
<set>QAbstractItemView::NoEditTriggers</set>
|
||||
</property>
|
||||
<row>
|
||||
<property name="text">
|
||||
<string>Block0</string>
|
||||
</property>
|
||||
</row>
|
||||
<row>
|
||||
<property name="text">
|
||||
<string>Block1</string>
|
||||
</property>
|
||||
</row>
|
||||
<row>
|
||||
<property name="text">
|
||||
<string>Block2</string>
|
||||
</property>
|
||||
</row>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Read</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Write</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Increase</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Decrease/Transfer/Restore</string>
|
||||
</property>
|
||||
</column>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>Trailer Block Permission:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTableWidget" name="trailerBlockWidget">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>3</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="editTriggers">
|
||||
<set>QAbstractItemView::NoEditTriggers</set>
|
||||
</property>
|
||||
<row>
|
||||
<property name="text">
|
||||
<string>Read</string>
|
||||
</property>
|
||||
</row>
|
||||
<row>
|
||||
<property name="text">
|
||||
<string>Write</string>
|
||||
</property>
|
||||
</row>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>KeyA</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Access Bits</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>KeyB</string>
|
||||
</property>
|
||||
</column>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Reference:
|
||||
MF1S70YYX_V1 Product data sheet
|
||||
Rev. 3.2 — 23 November 2017</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_10">
|
||||
<property name="text">
|
||||
<string>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.</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>MF_trailerDecoderDialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>MF_trailerDecoderDialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
@@ -0,0 +1,27 @@
|
||||
#include "mf_uid_parameterdialog.h"
|
||||
#include "ui_mf_uid_parameterdialog.h"
|
||||
|
||||
MF_UID_parameterDialog::MF_UID_parameterDialog(const QString& uid, const QString& atqa, const QString& sak, const QVariantMap& config, QWidget *parent) :
|
||||
QDialog(parent),
|
||||
ui(new Ui::MF_UID_parameterDialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
ui->UIDLineEdit->setText(uid);
|
||||
ui->ATQALineEdit->setText(atqa);
|
||||
ui->SAKLineEdit->setText(sak);
|
||||
this->config = config;
|
||||
}
|
||||
|
||||
MF_UID_parameterDialog::~MF_UID_parameterDialog()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void MF_UID_parameterDialog::on_buttonBox_accepted()
|
||||
{
|
||||
QString cmd = config["cmd"].toString();
|
||||
cmd.replace("<uid>", ui->UIDLineEdit->text());
|
||||
cmd.replace("<atqa>", ui->ATQALineEdit->text());
|
||||
cmd.replace("<sak>", ui->SAKLineEdit->text());
|
||||
emit sendCMD(cmd);
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
#ifndef MF_UID_PARAMETERDIALOG_H
|
||||
#define MF_UID_PARAMETERDIALOG_H
|
||||
|
||||
#include <QDialog>
|
||||
#include "common/util.h"
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class MF_UID_parameterDialog;
|
||||
}
|
||||
|
||||
class MF_UID_parameterDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit MF_UID_parameterDialog(const QString& uid, const QString& atqa, const QString& sak, const QVariantMap& config, QWidget *parent = nullptr);
|
||||
~MF_UID_parameterDialog();
|
||||
|
||||
private:
|
||||
Ui::MF_UID_parameterDialog *ui;
|
||||
QVariantMap config;
|
||||
signals:
|
||||
void sendCMD(const QString& cmd);
|
||||
private slots:
|
||||
void on_buttonBox_accepted();
|
||||
};
|
||||
|
||||
#endif // MF_UID_PARAMETERDIALOG_H
|
||||
@@ -0,0 +1,111 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>MF_UID_parameterDialog</class>
|
||||
<widget class="QDialog" name="MF_UID_parameterDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>205</width>
|
||||
<height>186</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Set Parameter</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="uIDLabel">
|
||||
<property name="text">
|
||||
<string>UID:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="UIDLineEdit"/>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="ATQALabel">
|
||||
<property name="text">
|
||||
<string>ATQA:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLineEdit" name="ATQALineEdit"/>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="SAKLabel">
|
||||
<property name="text">
|
||||
<string>SAK:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLineEdit" name="SAKLineEdit"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>MF_UID_parameterDialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>MF_UID_parameterDialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
@@ -0,0 +1,21 @@
|
||||
<ui version="4.0">
|
||||
<author/>
|
||||
<comment/>
|
||||
<exportmacro/>
|
||||
<class>T55xxTab</class>
|
||||
<widget class="QWidget" name="T55xxTab">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>400</width>
|
||||
<height>300</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
</widget>
|
||||
<pixmapfunction/>
|
||||
<connections/>
|
||||
</ui>
|
||||
Reference in New Issue
Block a user