Merge pull request #14 from wh201906/dev

V0.1.4
pull/33/head
wh201906 4 years ago committed by GitHub
commit 7f96c061dc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

1
.gitignore vendored

@ -14,7 +14,6 @@
*.so.* *.so.*
*_pch.h.cpp *_pch.h.cpp
*_resource.rc *_resource.rc
*.qm
.#* .#*
*.*# *.*#
core core

@ -16,6 +16,7 @@ DEFINES += QT_DEPRECATED_WARNINGS
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES += \ SOURCES += \
common/myeventfilter.cpp \
main.cpp \ main.cpp \
common/pm3process.cpp \ common/pm3process.cpp \
common/util.cpp \ common/util.cpp \
@ -27,6 +28,7 @@ SOURCES += \
ui/mf_attack_hardnesteddialog.cpp \ ui/mf_attack_hardnesteddialog.cpp \
HEADERS += \ HEADERS += \
common/myeventfilter.h \
common/pm3process.h \ common/pm3process.h \
common/util.h \ common/util.h \
module/mifare.h \ module/mifare.h \
@ -52,7 +54,7 @@ qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target !isEmpty(target.path): INSTALLS += target
VERSION = 0.1.3 VERSION = 0.1.4
QMAKE_TARGET_PRODUCT = "Proxmark3GUI" QMAKE_TARGET_PRODUCT = "Proxmark3GUI"
QMAKE_TARGET_DESCRIPTION = "Proxmark3GUI" QMAKE_TARGET_DESCRIPTION = "Proxmark3GUI"
QMAKE_TARGET_COMPANY = "wh201906" QMAKE_TARGET_COMPANY = "wh201906"

@ -1,5 +1,7 @@
# Proxmark3GUI # Proxmark3GUI
A GUI for [Proxmark3](https://github.com/Proxmark/proxmark3) client ![downloads](https://img.shields.io/github/downloads/wh201906/Proxmark3GUI/total)
A cross-platform GUI for [Proxmark3](https://github.com/Proxmark/proxmark3) client
[中文](README/doc/README_zh_CN.md) [中文](README/doc/README_zh_CN.md)
@ -25,32 +27,53 @@ A GUI for [Proxmark3](https://github.com/Proxmark/proxmark3) client
## Preview ## Preview
![preview](README/img/preview.png) ![preview](README/img/preview.png)
more previews [here](README/doc/previews.md) [more previews](README/doc/previews.md)
*** ***
## About Iceman fork/repo ## About Iceman fork/repo
The [Iceman fork/repo](https://github.com/RfidResearchGroup/proxmark3) has more powerful functions like offline sniff. These guys even developed a new hardware called Proxmark3 RDV4 with smart card support. But the official repo and the Iceman repo is not fully compatible. The [Iceman fork/repo](https://github.com/RfidResearchGroup/proxmark3) has more powerful functions like offline sniff. These guys even developed a new hardware called Proxmark3 RDV4 with smart card support. But the official repo and the Iceman repo is not fully compatible.
This GUI was designed for only official repo at first, but I'm trying to make it compatible with Iceman repo. This GUI is compatible with Iceman/RRG repo(tested on v4.9237)
Supported functions when using Iceman client:
[supported functions](README/doc/supported_Iceman.md)
*** ***
## About Compiled Windows clients ## About Compiled Windows clients
A cool guy [Gator96100](https://github.com/Gator96100) creates [ProxSpace](https://github.com/Gator96100/ProxSpace) and makes it possible to compile both the firmware and client on Windows. A cool guy [Gator96100](https://github.com/Gator96100) creates [ProxSpace](https://github.com/Gator96100/ProxSpace) and makes it possible to compile both the firmware and client on Windows.
Also, he makes the [pre-compiled Windows client](http://www.proxmark.org/forum/viewtopic.php?id=3975) so you can download it and run your PM3 client on Windows instantly. Also, he makes the [pre-compiled Windows client](https://www.proxmarkbuilds.org/) so you can download it and run your PM3 client on Windows instantly.
I included his compiled client in my releases so you can use the GUI on the fly, and you can also use the GUI with your prefered client. I included his compiled client in my releases so you can use the GUI on the fly, and you can also use the GUI with your prefered client.
Great thanks to him. Great thanks to him.
*** ***
## Build on Linux
cd ~
git clone https://github.com/wh201906/Proxmark3GUI.git
cd Proxmark3GUI
mkdir build
cd build
qmake ../
make
make clean
cp -r ../lang ./
./Proxmark3GUI
***
## Update Log: ## Update Log:
### V0.1.4
+ Optimize performance
+ Optimize UI
+ Search available ports automatically
+ Add High-DPI support
+ Support configuring environment variables by script
(Useful when the client requires specific environment variables)
+ All functions are compatible with Iceman/RRG repo(tested on v4.9237)
+ Fix some bugs
### V0.1.3 ### V0.1.3
+ Fix Trailer Decoder + Fix Trailer Decoder
+ Add feedback when writing selected blocks + Add feedback when writing selected blocks

@ -1,5 +1,7 @@
# Proxmark3GUI # Proxmark3GUI
一个自制的[Proxmark3](https://github.com/Proxmark/proxmark3) GUI ![downloads](https://img.shields.io/github/downloads/wh201906/Proxmark3GUI/total)
一个自制的[Proxmark3](https://github.com/Proxmark/proxmark3) GUI可在Windows/Linux系统下运行
[English](../../README.md) [English](../../README.md)
@ -30,23 +32,47 @@
*** ***
## 关于冰人版 ## 关于冰人版
这个GUI一开始是针对官方版本做的现在正在尽力让它兼容冰人版的功能 [冰人版](https://github.com/RfidResearchGroup/proxmark3)(Iceman/RRG)的客户端和固件更新更为激进,相比官方版具有更多的功能
没钱买RDV4也没钱买两台PM3测一次冰人就要烧一次固件 qwq 此GUI所有功能均兼容冰人版在v4.9237上测试通过)
[已支持功能](../doc/supported_Iceman.md)
*** ***
## 关于预编译Windows客户端 ## 关于预编译Windows客户端
国外大佬 [Gator96100](https://github.com/Gator96100) 做了个 [ProxSpace](https://github.com/Gator96100/ProxSpace) 以便在Windows平台上编译PM3固件和客户端他还把自己编译好的客户端放到了[论坛](http://www.proxmark.org/forum/viewtopic.php?id=3975)里面 国外大佬 [Gator96100](https://github.com/Gator96100) 做了个 [ProxSpace](https://github.com/Gator96100/ProxSpace) 以便在Windows平台上编译PM3固件和客户端他还把自己编译好的客户端放到了[网站](https://www.proxmarkbuilds.org/)上
文件都是放到Google Drive上面的国内网络无法访问所以我在release版本里面放了个带预编译客户端版本的GUI。这个GUI也可以搭配你自己的客户端使用 release页面中有含客户端的GUI。这个GUI也可以搭配你自己的客户端使用
(本来打算在CSDN下载里面放几个最新版客户端的结果不能把下载币改为0) (本来打算在CSDN下载里面放几个最新版客户端的结果不能把下载币改为0)
感谢大佬 感谢大佬
*** ***
## 在Linux系统下编译
cd ~
git clone https://github.com/wh201906/Proxmark3GUI.git
cd Proxmark3GUI
mkdir build
cd build
qmake ../
make
make clean
cp -r ../lang ./
./Proxmark3GUI
***
## 更新日志: ## 更新日志:
### V0.1.4
+ 优化性能
+ 优化用户界面
+ 自动搜索可用端口
+ 支持高分屏
+ 可通过外部脚本配置环境变量
(在客户端需要配置环境变量时很有用)
+ 全功能兼容冰人版在v4.9237上测试通过)
+ 修复部分bug
### V0.1.3 ### V0.1.3
+ 修复访问控制位解码器 + 修复访问控制位解码器
+ 写多个块时显示写入结果 + 写多个块时显示写入结果

@ -1,9 +0,0 @@
## About Iceman fork/repo
The [Iceman fork/repo](https://github.com/RfidResearchGroup/proxmark3) has more powerful functions like offline sniff. These guys even developed a new hardware called Proxmark3 RDV4 with smart card support. But the official repo and the Iceman repo is not fully compatible. This GUI was designed for only official repo at first, but I'm trying to make it compatible with Iceman repo.
Supported functions when using Iceman client:
+ Command Line
+ Mifare Card info
+ Mifare Check default keys
+ Mifare Nested Attack
+ Mifare Read/Write

Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 52 KiB

After

Width:  |  Height:  |  Size: 49 KiB

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

@ -14,17 +14,22 @@ PM3Process::PM3Process(QThread* thread, QObject* parent): QProcess(parent)
connect(this, &PM3Process::readyRead, this, &PM3Process::onReadyRead); connect(this, &PM3Process::readyRead, this, &PM3Process::onReadyRead);
} }
void PM3Process::connectPM3(const QString path, const QString port) void PM3Process::connectPM3(const QString& path, const QString& port, const QStringList args)
{ {
QString result; QString result;
Util::ClientType clientType = Util::CLIENTTYPE_OFFICIAL; Util::ClientType clientType;
setRequiringOutput(true); setRequiringOutput(true);
// stash for reconnect
currPath = path;
currPort = port;
currArgs = args;
// using "-f" option to make the client output flushed after every print. // using "-f" option to make the client output flushed after every print.
start(path, QStringList() << port << "-f", QProcess::Unbuffered | QProcess::ReadWrite); start(path, args, QProcess::Unbuffered | QProcess::ReadWrite);
if(waitForStarted(10000)) if(waitForStarted(10000))
{ {
waitForReadyRead(1000); waitForReadyRead(10000);
setRequiringOutput(false); setRequiringOutput(false);
result = *requiredOutput; result = *requiredOutput;
if(result.indexOf("[=]") != -1) if(result.indexOf("[=]") != -1)
@ -32,10 +37,17 @@ void PM3Process::connectPM3(const QString path, const QString port)
clientType = Util::CLIENTTYPE_ICEMAN; clientType = Util::CLIENTTYPE_ICEMAN;
setRequiringOutput(true); setRequiringOutput(true);
write("hw version\r\n"); write("hw version\r\n");
waitForReadyRead(1000); for(int i = 0; i < 10; i++)
result = *requiredOutput; {
waitForReadyRead(200);
result += *requiredOutput;
}
setRequiringOutput(false); setRequiringOutput(false);
} }
else
{
clientType = Util::CLIENTTYPE_OFFICIAL;
}
if(result.indexOf("os: ") != -1) // make sure the PM3 is connected if(result.indexOf("os: ") != -1) // make sure the PM3 is connected
{ {
emit changeClientType(clientType); emit changeClientType(clientType);
@ -50,6 +62,11 @@ void PM3Process::connectPM3(const QString path, const QString port)
} }
} }
void PM3Process::reconnectPM3()
{
connectPM3(currPath, currPort, currArgs);
}
void PM3Process::setRequiringOutput(bool st) void PM3Process::setRequiringOutput(bool st)
{ {
isRequiringOutput = st; isRequiringOutput = st;
@ -93,7 +110,6 @@ void PM3Process::testThread()
qDebug() << "PM3:" << QThread::currentThread(); qDebug() << "PM3:" << QThread::currentThread();
} }
qint64 PM3Process::write(QString data) qint64 PM3Process::write(QString data)
{ {
return QProcess::write(data.toLatin1()); return QProcess::write(data.toLatin1());
@ -111,3 +127,10 @@ void PM3Process::onReadyRead()
} }
} }
void PM3Process::setProcEnv(const QStringList* env)
{
// qDebug() << "passed Env List" << *env;
this->setEnvironment(*env);
// qDebug() << "final Env List" << processEnvironment().toStringList();
}

@ -8,6 +8,7 @@
#include <QTimer> #include <QTimer>
#include <QtSerialPort/QSerialPortInfo> #include <QtSerialPort/QSerialPortInfo>
#include <QtSerialPort/QSerialPort> #include <QtSerialPort/QSerialPort>
#include <QProcessEnvironment>
#include "util.h" #include "util.h"
@ -21,9 +22,11 @@ public:
void testThread(); void testThread();
public slots: public slots:
void connectPM3(const QString path, const QString port); void connectPM3(const QString& path, const QString& port, const QStringList args);
void setSerialListener(const QString &name, bool state); void setSerialListener(const QString& name, bool state);
qint64 write(QString data); qint64 write(QString data);
void reconnectPM3();
void setProcEnv(const QStringList* env);
private slots: private slots:
void onTimeout(); void onTimeout();
void onReadyRead(); void onReadyRead();
@ -33,9 +36,13 @@ private:
void setRequiringOutput(bool st);// It only works in this class now void setRequiringOutput(bool st);// It only works in this class now
QTimer* serialListener; QTimer* serialListener;
QSerialPortInfo* portInfo; QSerialPortInfo* portInfo;
QString currPath;
QString currPort;
QStringList currArgs;
signals: signals:
void PM3StatedChanged(bool st, QString info = ""); void PM3StatedChanged(bool st, const QString& info = "");
void newOutput(QString output); void newOutput(const QString& output);
void changeClientType(Util::ClientType); void changeClientType(Util::ClientType);
}; };

@ -1,15 +1,16 @@
#include "util.h" #include "util.h"
Util::ClientType Util::clientType = CLIENTTYPE_OFFICIAL;
Util::Util(QObject *parent) : QObject(parent) Util::Util(QObject *parent) : QObject(parent)
{ {
isRequiringOutput = false; isRequiringOutput = false;
requiredOutput = new QString(); requiredOutput = new QString();
timeStamp = QTime::currentTime(); timeStamp = QTime::currentTime();
this->clientType = CLIENTTYPE_OFFICIAL;
qRegisterMetaType<Util::ClientType>("Util::ClientType"); qRegisterMetaType<Util::ClientType>("Util::ClientType");
} }
void Util::processOutput(QString output) void Util::processOutput(const QString& output)
{ {
// qDebug() << "Util::processOutput:" << output; // qDebug() << "Util::processOutput:" << output;
if(isRequiringOutput) if(isRequiringOutput)
@ -20,30 +21,58 @@ void Util::processOutput(QString output)
emit refreshOutput(output); emit refreshOutput(output);
} }
void Util::execCMD(QString cmd) void Util::execCMD(const QString& cmd)
{ {
qDebug() << cmd; qDebug() << "executing: " << cmd;
if(isRunning)
emit write(cmd + "\r\n"); emit write(cmd + "\r\n");
} }
QString Util::execCMDWithOutput(QString cmd, unsigned long waitTime) QString Util::execCMDWithOutput(const QString& cmd, ReturnTrigger trigger)
{ {
// 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 currTime = QTime::currentTime();
QTime targetTime = QTime::currentTime().addMSecs(waitTime); QTime targetTime = QTime::currentTime().addMSecs(trigger.waitTime);
isRequiringOutput = true; isRequiringOutput = true;
requiredOutput->clear(); requiredOutput->clear();
execCMD(cmd); execCMD(cmd);
while(QTime::currentTime() < targetTime) while(QTime::currentTime() < targetTime)
{ {
if(!isRunning)
break;
QApplication::processEvents(); QApplication::processEvents();
if(timeStamp > currTime) // 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; currTime = timeStamp;
targetTime = timeStamp.addMSecs(waitTime); targetTime = timeStamp.addMSecs(trigger.waitTime);
} }
} }
isRequiringOutput = false; isRequiringOutput = false;
return *requiredOutput; return (isResultFound || trigger.expectedOutputs.isEmpty() ? *requiredOutput : "");
} }
void Util::delay(unsigned int msec) void Util::delay(unsigned int msec)
@ -52,12 +81,42 @@ void Util::delay(unsigned int msec)
while(QTime::currentTime() < timer) while(QTime::currentTime() < timer)
QApplication::processEvents(QEventLoop::AllEvents, 100); QApplication::processEvents(QEventLoop::AllEvents, 100);
} }
Util::ClientType Util::getClientType() Util::ClientType Util::getClientType()
{ {
return this->clientType; return Util::clientType;
} }
void Util::setClientType(Util::ClientType clientType) void Util::setClientType(Util::ClientType clientType)
{ {
this->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("lang/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;
} }

@ -9,6 +9,10 @@
#include <QTime> #include <QTime>
#include <QTimer> #include <QTimer>
#include <QMetaType> #include <QMetaType>
#include <QRegularExpression>
#include <QSettings>
#include <QMainWindow>
#include <QInputDialog>
class Util : public QObject class Util : public QObject
{ {
@ -20,26 +24,51 @@ public:
CLIENTTYPE_ICEMAN, 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) Q_ENUM(Util::ClientType)
explicit Util(QObject *parent = nullptr); explicit Util(QObject *parent = nullptr);
void execCMD(QString cmd); void execCMD(const QString& cmd);
QString execCMDWithOutput(QString cmd, unsigned long waitTime = 2000); QString execCMDWithOutput(const QString& cmd, ReturnTrigger trigger = 10000);
void delay(unsigned int msec); void delay(unsigned int msec);
ClientType getClientType(); static ClientType getClientType();
static const int rawTabIndex = 1;
static bool chooseLanguage(QSettings *guiSettings, QMainWindow *window);
public slots: public slots:
void processOutput(QString output); void processOutput(const QString& output);
void setClientType(Util::ClientType clientType); static void setClientType(Util::ClientType clientType);
void setRunningState(bool st);
private: private:
bool isRequiringOutput; bool isRequiringOutput;
bool isRunning;
QString* requiredOutput; QString* requiredOutput;
QTime timeStamp; QTime timeStamp;
ClientType clientType; static ClientType clientType;
signals: signals:
void refreshOutput(const QString& output); void refreshOutput(const QString& output);
void write(QString data); void write(QString data); // connected to PM3Process::write(QString data);
}; };
#endif // UTIL_H #endif // UTIL_H

Binary file not shown.

File diff suppressed because it is too large Load Diff

@ -0,0 +1,3 @@
[Languages]
en_US=English
zh_CN=简体中文

Binary file not shown.

File diff suppressed because it is too large Load Diff

@ -4,56 +4,50 @@
#include <QSettings> #include <QSettings>
#include <QTranslator> #include <QTranslator>
#include <QMessageBox> #include <QMessageBox>
#include <QInputDialog> #include <QTextCodec>
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QTextCodec::setCodecForLocale(QTextCodec::codecForName("UTF-8"));
QApplication a(argc, argv); QApplication a(argc, argv);
MainWindow w; MainWindow w;
QSettings* settings = new QSettings("GUIsettings.ini", QSettings::IniFormat); QSettings* settings = new QSettings("GUIsettings.ini", QSettings::IniFormat);
settings->setIniCodec("UTF-8");
settings->beginGroup("lang"); settings->beginGroup("lang");
QVariant lang = settings->value("language", "null"); QString currLang = settings->value("language", "").toString();
if(lang == "null") settings->endGroup();
if(currLang == "")
{ {
#ifdef Q_OS_WIN if(Util::chooseLanguage(settings, &w))
lang = "lang/en_US.qm";
#else
lang = "lang/en_US.ts";
#endif
QStringList langList;
langList.append("English");
langList.append("简体中文");
QString seletedText = QInputDialog::getItem(&w, "", "Choose a language:", langList, 0, false);
if(seletedText == "English")
{ {
#ifdef Q_OS_WIN settings->beginGroup("lang");
lang = "lang/en_US.qm"; currLang = settings->value("language", "").toString();
#else settings->endGroup();
lang = "lang/en_US.ts";
#endif
} }
else if(seletedText == "简体中文") else
{ currLang = "en_US";
}
currLang = "lang/" + currLang;
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
lang = "lang/zh_CN.qm"; currLang += ".qm";
#else #else
lang = "lang/zh_CN.ts"; currLang += ".ts";;
#endif #endif
}
}
QTranslator* translator = new QTranslator(&w); QTranslator* translator = new QTranslator(&w);
if(translator->load(lang.toString())) if(translator->load(currLang))
{ {
a.installTranslator(translator); a.installTranslator(translator);
settings->setValue("language", lang);
} }
else else
{ {
QMessageBox::information(&w, "Error", "Can't load " + lang.toString() + " as translation file."); QMessageBox::information(&w, "Error", "Can't load " + currLang + " as translation file.");
} }
settings->endGroup();
delete settings; delete settings;
w.initUI(); w.initUI();
w.show(); w.show();
return a.exec(); return a.exec();
} }

@ -6,7 +6,8 @@ const Mifare::CardType Mifare::card_mini =
5, 5,
20, 20,
{4, 4, 4, 4, 4}, {4, 4, 4, 4, 4},
{0, 4, 8, 12, 16} {0, 4, 8, 12, 16},
"mini"
}; };
const Mifare::CardType Mifare::card_1k = const Mifare::CardType Mifare::card_1k =
{ {
@ -14,7 +15,8 @@ const Mifare::CardType Mifare::card_1k =
16, 16,
64, 64,
{4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4}, {4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4},
{0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60} {0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60},
"1k"
}; };
const Mifare::CardType Mifare::card_2k = const Mifare::CardType Mifare::card_2k =
{ {
@ -22,7 +24,8 @@ const Mifare::CardType Mifare::card_2k =
32, 32,
128, 128,
{4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4}, {4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4},
{0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60, 64, 68, 72, 76, 80, 84, 88, 92, 96, 100, 104, 108, 112, 116, 120, 124} {0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60, 64, 68, 72, 76, 80, 84, 88, 92, 96, 100, 104, 108, 112, 116, 120, 124},
"2k"
}; };
const Mifare::CardType Mifare::card_4k = const Mifare::CardType Mifare::card_4k =
{ {
@ -30,7 +33,8 @@ const Mifare::CardType Mifare::card_4k =
40, 40,
256, 256,
{4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 16, 16, 16, 16, 16, 16, 16, 16}, {4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 16, 16, 16, 16, 16, 16, 16, 16},
{0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60, 64, 68, 72, 76, 80, 84, 88, 92, 96, 100, 104, 108, 112, 116, 120, 124, 128, 144, 160, 176, 192, 208, 224, 240} {0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60, 64, 68, 72, 76, 80, 84, 88, 92, 96, 100, 104, 108, 112, 116, 120, 124, 128, 144, 160, 176, 192, 208, 224, 240},
"4k"
}; };
const Mifare::AccessType Mifare::dataCondition[8][4] = const Mifare::AccessType Mifare::dataCondition[8][4] =
@ -79,26 +83,24 @@ Mifare::Mifare(Ui::MainWindow *ui, Util *addr, QWidget *parent): QObject(parent)
data_clearKey(); // fill with blank QString data_clearKey(); // fill with blank QString
data_clearData(); // fill with blank QString data_clearData(); // fill with blank QString
dataPattern = new QRegularExpression("([0-9a-fA-F]{2} ){15}[0-9a-fA-F]{2}"); dataPattern = new QRegularExpression("([0-9a-fA-F]{2} ){15}[0-9a-fA-F]{2}");
keyPattern_res = new QRegularExpression("\\|\\d{3}\\|.+?\\|.+?\\|.+?\\|.+?\\|"); keyPattern_res = new QRegularExpression("\\|\\s*\\d{3}\\s*\\|\\s*.+?\\s*\\|\\s*.+?\\s*\\|\\s*.+?\\s*\\|\\s*.+?\\s*\\|");
keyPattern = new QRegularExpression("\\|\\d{3}\\|.+?\\|.+?\\|"); keyPattern = new QRegularExpression("\\|\\s*\\d{3}\\s*\\|\\s*.+?\\s*\\|\\s*.+?\\s*\\|");
} }
QString Mifare::info(bool isRequiringOutput) QString Mifare::info(bool isRequiringOutput)
{ {
if(util->getClientType() == Util::CLIENTTYPE_OFFICIAL || util->getClientType() == Util::CLIENTTYPE_ICEMAN) if(Util::getClientType() == Util::CLIENTTYPE_OFFICIAL || Util::getClientType() == Util::CLIENTTYPE_ICEMAN)
{ {
if(isRequiringOutput) if(isRequiringOutput)
{ {
QString result = util->execCMDWithOutput("hf 14a info", 500); QString result = util->execCMDWithOutput("hf 14a info", 500);
result.replace("UID :", "|||"); int begin, end;
result.replace("ATQA :", "|||"); begin = result.indexOf("UID");
result.replace("SAK :", "|||"); if(begin != -1)
result.replace("TYPE :", "|||");
QStringList lis = result.split("|||");
if(lis.length() > 4)
{ {
qDebug() << lis[1] + lis[2] + lis[3]; end = result.indexOf("SAK", begin);
return lis[1] + lis[2] + lis[3]; end = result.indexOf("\n", end);
return result.mid(begin, end - begin + 1);
} }
else else
return ""; return "";
@ -106,7 +108,7 @@ QString Mifare::info(bool isRequiringOutput)
else else
{ {
util->execCMD("hf 14a info"); util->execCMD("hf 14a info");
ui->funcTab->setCurrentIndex(1); ui->funcTab->setCurrentIndex(Util::rawTabIndex);
return ""; return "";
} }
} }
@ -115,17 +117,17 @@ QString Mifare::info(bool isRequiringOutput)
void Mifare::chk() void Mifare::chk()
{ {
QRegularExpressionMatch reMatch; QRegularExpressionMatch reMatch;
QString result = util->execCMDWithOutput( QString result;
int offset = 0;
QString data;
if(Util::getClientType() == Util::CLIENTTYPE_OFFICIAL)
{
result = util->execCMDWithOutput(
"hf mf chk *" "hf mf chk *"
+ QString::number(cardType.type) + QString::number(cardType.type)
+ " ?", + " ?",
1000 + cardType.type * 1000); Util::ReturnTrigger(1000 + cardType.sector_size * 200, {"No valid", keyPattern->pattern()}));
qDebug() << result; qDebug() << result;
int offset = 0;
QString data;
if(util->getClientType() == Util::CLIENTTYPE_OFFICIAL)
{
for(int i = 0; i < cardType.sector_size; i++) for(int i = 0; i < cardType.sector_size; i++)
{ {
reMatch = keyPattern->match(result, offset); reMatch = keyPattern->match(result, offset);
@ -146,8 +148,13 @@ void Mifare::chk()
} }
} }
} }
else if(util->getClientType() == Util::CLIENTTYPE_ICEMAN) else if(Util::getClientType() == Util::CLIENTTYPE_ICEMAN)
{ {
result = util->execCMDWithOutput(
"hf mf chk --"
+ cardType.typeText,
Util::ReturnTrigger(1000 + cardType.sector_size * 200, {"No valid", keyPattern_res->pattern()}));
qDebug() << "mf_chk_iceman_result" << result;
for(int i = 0; i < cardType.sector_size; i++) for(int i = 0; i < cardType.sector_size; i++)
{ {
reMatch = keyPattern_res->match(result, offset); reMatch = keyPattern_res->match(result, offset);
@ -178,21 +185,22 @@ void Mifare::nested()
QString result; QString result;
int offset = 0; int offset = 0;
QString data; QString data;
if(util->getClientType() == Util::CLIENTTYPE_OFFICIAL) if(Util::getClientType() == Util::CLIENTTYPE_OFFICIAL)
{ {
result = util->execCMDWithOutput( result = util->execCMDWithOutput(
"hf mf nested " "hf mf nested "
+ QString::number(cardType.type) + QString::number(cardType.type)
+ " *", 10000); + " *",
Util::ReturnTrigger(15000, {"Can't found", "\\|000\\|"}));
} }
else if(util->getClientType() == Util::CLIENTTYPE_ICEMAN) else if(Util::getClientType() == Util::CLIENTTYPE_ICEMAN)
{ {
QString knownKeyInfo = ""; QString knownKeyInfo = "";
for(int i = 0; i < cardType.sector_size; i++) for(int i = 0; i < cardType.sector_size; i++)
{ {
if(data_isKeyValid(keyAList->at(i))) if(data_isKeyValid(keyAList->at(i)))
{ {
knownKeyInfo = " " + QString::number(i * 4) + " A " + keyAList->at(i); knownKeyInfo = " --blk " + QString::number(i * 4) + " -a -k " + keyAList->at(i);
break; break;
} }
} }
@ -202,7 +210,7 @@ void Mifare::nested()
{ {
if(data_isKeyValid(keyBList->at(i))) if(data_isKeyValid(keyBList->at(i)))
{ {
knownKeyInfo = " " + QString::number(i * 4) + " B " + keyBList->at(i); knownKeyInfo = " --blk " + QString::number(i * 4) + " -b -k " + keyBList->at(i);
break; break;
} }
} }
@ -210,9 +218,10 @@ void Mifare::nested()
if(knownKeyInfo != "") if(knownKeyInfo != "")
{ {
result = util->execCMDWithOutput( result = util->execCMDWithOutput(
"hf mf nested " "hf mf nested --"
+ QString::number(cardType.type) + cardType.typeText
+ knownKeyInfo, 10000); + knownKeyInfo,
Util::ReturnTrigger(15000, {"Can't authenticate", keyPattern_res->pattern()}));
} }
else else
{ {
@ -248,34 +257,57 @@ void Mifare::hardnested()
MF_Attack_hardnestedDialog dialog(cardType.block_size); MF_Attack_hardnestedDialog dialog(cardType.block_size);
connect(&dialog, &MF_Attack_hardnestedDialog::sendCMD, util, &Util::execCMD); connect(&dialog, &MF_Attack_hardnestedDialog::sendCMD, util, &Util::execCMD);
if(dialog.exec() == QDialog::Accepted) if(dialog.exec() == QDialog::Accepted)
ui->funcTab->setCurrentIndex(1); ui->funcTab->setCurrentIndex(Util::rawTabIndex);
}
void Mifare::darkside()
{
if(Util::getClientType() == Util::CLIENTTYPE_OFFICIAL)
util->execCMD("hf mf mifare");
else if(Util::getClientType() == Util::CLIENTTYPE_ICEMAN)
util->execCMD("hf mf darkside");
ui->funcTab->setCurrentIndex(Util::rawTabIndex);
} }
void Mifare::sniff() void Mifare::sniff()
{ {
if(Util::getClientType() == Util::CLIENTTYPE_OFFICIAL)
util->execCMD("hf mf sniff"); util->execCMD("hf mf sniff");
ui->funcTab->setCurrentIndex(1); else if(Util::getClientType() == Util::CLIENTTYPE_ICEMAN)
util->execCMD("hf sniff");
ui->funcTab->setCurrentIndex(Util::rawTabIndex);
} }
void Mifare::snoop() void Mifare::sniff14a()
{ {
if(Util::getClientType() == Util::CLIENTTYPE_OFFICIAL)
util->execCMD("hf 14a snoop"); util->execCMD("hf 14a snoop");
ui->funcTab->setCurrentIndex(1); else if(Util::getClientType() == Util::CLIENTTYPE_ICEMAN)
util->execCMD("hf 14a sniff");
ui->funcTab->setCurrentIndex(Util::rawTabIndex);
} }
void Mifare::list() void Mifare::list()
{ {
if(Util::getClientType() == Util::CLIENTTYPE_OFFICIAL)
util->execCMD("hf list mf"); util->execCMD("hf list mf");
ui->funcTab->setCurrentIndex(1); else if(Util::getClientType() == Util::CLIENTTYPE_ICEMAN)
util->execCMD("trace list -t mf");
ui->funcTab->setCurrentIndex(Util::rawTabIndex);
} }
QString Mifare::_readblk(int blockId, KeyType keyType, const QString& key, TargetType targetType, int waitTime) QString Mifare::_readblk(int blockId, KeyType keyType, const QString& key, TargetType targetType, int waitTime)
{ {
QString data; QString data;
QString result; QString result;
bool isKeyBlock = (blockId < 128 && ((blockId + 1) % 4 == 0)) || ((blockId + 1) % 16 == 0); QRegularExpressionMatch currMatch;
bool isTrailerBlock = (blockId < 128 && ((blockId + 1) % 4 == 0)) || ((blockId + 1) % 16 == 0);
if(util->getClientType() == Util::CLIENTTYPE_OFFICIAL || util->getClientType() == Util::CLIENTTYPE_ICEMAN) if(Util::getClientType() == Util::CLIENTTYPE_OFFICIAL || Util::getClientType() == Util::CLIENTTYPE_ICEMAN)
{ {
if(targetType == TARGET_MIFARE) if(targetType == TARGET_MIFARE)
{ {
@ -292,13 +324,14 @@ QString Mifare::_readblk(int blockId, KeyType keyType, const QString& key, Targe
+ " " + " "
+ key, + key,
waitTime); waitTime);
if(result.indexOf("isOk:01") != -1) currMatch = dataPattern->match(result);
if(currMatch.hasMatch())
{ {
data = dataPattern->match(result).captured().toUpper(); data = currMatch.captured().toUpper();
data.remove(" "); data.remove(" ");
// when the target block is a key block and the given key type is KeyA, try to check whether the KeyB is valid(by Access Bits) // when the target block is a key block and the given key type is KeyA, try to check whether the KeyB is valid(by Access Bits)
// if the given key type is KeyB, it will never get the KeyA from the key block // if the given key type is KeyB, it will never get the KeyA from the key block
if(isKeyBlock && keyType == KEY_A) // in this case, the Access Bits is always accessible if(isTrailerBlock && keyType == KEY_A) // in this case, the Access Bits is always accessible
{ {
data.replace(0, 12, key); data.replace(0, 12, key);
QList<quint8> ACBits = data_getACBits(data.mid(12, 8)); QList<quint8> ACBits = data_getACBits(data.mid(12, 8));
@ -307,7 +340,7 @@ QString Mifare::_readblk(int blockId, KeyType keyType, const QString& key, Targe
data.replace(20, 12, "????????????"); data.replace(20, 12, "????????????");
} }
} }
else if(isKeyBlock && keyType == KEY_B) else if(isTrailerBlock && keyType == KEY_B)
{ {
data.replace(20, 12, key);; data.replace(20, 12, key);;
data.replace(0, 12, "????????????"); // fill the keyA part with ? data.replace(0, 12, "????????????"); // fill the keyA part with ?
@ -322,15 +355,19 @@ QString Mifare::_readblk(int blockId, KeyType keyType, const QString& key, Targe
"hf mf cgetblk " "hf mf cgetblk "
+ QString::number(blockId), + QString::number(blockId),
waitTime); waitTime);
if(result.indexOf("Chinese magic") != -1) currMatch = dataPattern->match(result);
if(currMatch.hasMatch())
{ {
data = dataPattern->match(result).captured().toUpper(); data = currMatch.captured().toUpper();
data.remove(" "); data.remove(" ");
} }
else else
data = ""; data = "";
} }
else if(targetType == TARGET_EMULATOR) }
if(Util::getClientType() == Util::CLIENTTYPE_OFFICIAL)
{
if(targetType == TARGET_EMULATOR)
{ {
result = util->execCMDWithOutput( result = util->execCMDWithOutput(
"hf mf eget " "hf mf eget "
@ -340,6 +377,18 @@ QString Mifare::_readblk(int blockId, KeyType keyType, const QString& key, Targe
data.remove(" "); data.remove(" ");
} }
} }
else if(Util::getClientType() == Util::CLIENTTYPE_ICEMAN)
{
if(targetType == TARGET_EMULATOR)
{
result = util->execCMDWithOutput(
"hf mf egetblk "
+ QString::number(blockId),
150);
data = dataPattern->match(result).captured().toUpper();
data.remove(" ");
}
}
return data; return data;
} }
@ -348,14 +397,14 @@ QStringList Mifare::_readsec(int sectorId, KeyType keyType, const QString& key,
QStringList data; QStringList data;
QString result, tmp; QString result, tmp;
QRegularExpressionMatch reMatch; QRegularExpressionMatch reMatch;
int offset = -1; int offset = -1; // for targetType == TARGET_EMULATOR
for(int i = 0; i < cardType.blk[sectorId]; i++) for(int i = 0; i < cardType.blk[sectorId]; i++)
{ {
data.append(""); data.append("");
} }
if(util->getClientType() == Util::CLIENTTYPE_OFFICIAL || util->getClientType() == Util::CLIENTTYPE_ICEMAN) if(Util::getClientType() == Util::CLIENTTYPE_OFFICIAL || Util::getClientType() == Util::CLIENTTYPE_ICEMAN)
{ {
// try to read all blocks together // try to read all blocks together
if(targetType == TARGET_MIFARE) if(targetType == TARGET_MIFARE)
@ -372,7 +421,7 @@ QStringList Mifare::_readsec(int sectorId, KeyType keyType, const QString& key,
+ " " + " "
+ key, + key,
waitTime); waitTime);
offset = result.indexOf("isOk:01"); offset = result.indexOf("isOk:01"); // find successful flag
} }
else if(targetType == TARGET_UID) else if(targetType == TARGET_UID)
{ {
@ -380,7 +429,7 @@ QStringList Mifare::_readsec(int sectorId, KeyType keyType, const QString& key,
"hf mf cgetsc " "hf mf cgetsc "
+ QString::number(sectorId), + QString::number(sectorId),
waitTime); waitTime);
offset = result.indexOf("Chinese magic"); offset = result.indexOf("error") == -1 ? 0 : -1; // find failed flag
} }
if(offset != -1) if(offset != -1)
{ {
@ -399,7 +448,7 @@ QStringList Mifare::_readsec(int sectorId, KeyType keyType, const QString& key,
} }
// if failed, try to read them seperately. // if failed, try to read them seperately.
// (when one of the block cannot be read, the rdsc will return nothing, so you need to read the rest of blocks manually) // (when one of the block cannot be read, the rdsc will return nothing, so you need to read the rest of blocks manually)
else if(targetType != TARGET_UID) // if the targetType is Chinese Magic Card, then the result implies the backdoor command is invalid. else if(targetType == TARGET_UID || targetType == TARGET_EMULATOR) // if the targetType is Chinese Magic Card, then the result implies the backdoor command is invalid.
{ {
for(int i = 0; i < cardType.blk[sectorId]; i++) for(int i = 0; i < cardType.blk[sectorId]; i++)
data[i] = _readblk(cardType.blks[sectorId] + i, keyType, key, targetType, waitTime); data[i] = _readblk(cardType.blks[sectorId] + i, keyType, key, targetType, waitTime);
@ -536,12 +585,12 @@ bool Mifare::_writeblk(int blockId, KeyType keyType, const QString& key, const Q
{ {
QString result; QString result;
QString input = data.toUpper(); QString input = data.toUpper();
input.remove(" ");
input.remove(" ");
if(data_isDataValid(input) != DATA_NOSPACE) if(data_isDataValid(input) != DATA_NOSPACE)
return false; return false;
if(util->getClientType() == Util::CLIENTTYPE_OFFICIAL || util->getClientType() == Util::CLIENTTYPE_ICEMAN) if(Util::getClientType() == Util::CLIENTTYPE_OFFICIAL || Util::getClientType() == Util::CLIENTTYPE_ICEMAN)
{ {
if(targetType == TARGET_MIFARE) if(targetType == TARGET_MIFARE)
{ {
@ -567,7 +616,7 @@ bool Mifare::_writeblk(int blockId, KeyType keyType, const QString& key, const Q
+ " " + " "
+ input, + input,
waitTime); waitTime);
return (result.indexOf("Chinese magic") != -1); return (result.indexOf("error") == -1); // failed flag
} }
else if(targetType == TARGET_EMULATOR) else if(targetType == TARGET_EMULATOR)
{ {
@ -601,6 +650,8 @@ void Mifare::writeSelected(TargetType targetType)
{ {
QList<int> failedBlocks; QList<int> failedBlocks;
QList<int> selectedBlocks; QList<int> selectedBlocks;
bool yes2All = false, no2All = false;
for(int i = 0; i < cardType.block_size; i++) for(int i = 0; i < cardType.block_size; i++)
{ {
if(ui->MF_dataWidget->item(i, 1)->checkState() == Qt::Checked) if(ui->MF_dataWidget->item(i, 1)->checkState() == Qt::Checked)
@ -609,6 +660,29 @@ void Mifare::writeSelected(TargetType targetType)
for(int item : selectedBlocks) for(int item : selectedBlocks)
{ {
bool result = false; bool result = false;
bool isTrailerBlock = (item < 128 && ((item + 1) % 4 == 0)) || ((item + 1) % 16 == 0);
if(isTrailerBlock && !data_isACBitsValid(dataList->at(item).mid(12, 8))) // trailer block is invalid
{
if(!yes2All && !no2All)
{
QMessageBox::StandardButton choice = QMessageBox::information(parent, tr("Info"),
tr("The Access Bits is invalid!\nIt could make the whole sector blocked irreversibly!\nContinue to write?"),
QMessageBox::Yes | QMessageBox::YesToAll | QMessageBox::No | QMessageBox::NoToAll);
if(choice == QMessageBox::No)
continue;
else if(choice == QMessageBox::YesToAll)
yes2All = true;
else if(choice == QMessageBox::NoToAll)
{
no2All = true;
continue;
}
}
else if(no2All)
continue;
}
if(targetType == TARGET_MIFARE) if(targetType == TARGET_MIFARE)
{ {
result = _writeblk(item, KEY_A, keyAList->at(data_b2s(item)), dataList->at(item), TARGET_MIFARE); result = _writeblk(item, KEY_A, keyAList->at(data_b2s(item)), dataList->at(item), TARGET_MIFARE);
@ -667,23 +741,32 @@ void Mifare::writeSelected(TargetType targetType)
void Mifare::dump() void Mifare::dump()
{ {
if(Util::getClientType() == Util::CLIENTTYPE_OFFICIAL || Util::getClientType() == Util::CLIENTTYPE_ICEMAN)
util->execCMD("hf mf dump"); util->execCMD("hf mf dump");
ui->funcTab->setCurrentIndex(1); ui->funcTab->setCurrentIndex(Util::rawTabIndex);
} }
void Mifare::restore() void Mifare::restore()
{ {
if(Util::getClientType() == Util::CLIENTTYPE_OFFICIAL || Util::getClientType() == Util::CLIENTTYPE_ICEMAN)
util->execCMD("hf mf restore"); util->execCMD("hf mf restore");
ui->funcTab->setCurrentIndex(1); ui->funcTab->setCurrentIndex(Util::rawTabIndex);
} }
void Mifare::wipeC() void Mifare::wipeC()
{ {
if(Util::getClientType() == Util::CLIENTTYPE_OFFICIAL)
{
util->execCMD( util->execCMD(
"hf mf cwipe " "hf mf cwipe "
+ QString::number(cardType.type) + QString::number(cardType.type)
+ " f"); + " f");
ui->funcTab->setCurrentIndex(1); }
else if(Util::getClientType() == Util::CLIENTTYPE_ICEMAN)
{
util->execCMD("hf mf cwipe");
}
ui->funcTab->setCurrentIndex(Util::rawTabIndex);
} }
void Mifare::setParameterC() void Mifare::setParameterC()
@ -693,50 +776,78 @@ void Mifare::setParameterC()
QMessageBox::information(parent, tr("Info"), tr("Failed to read card.")); QMessageBox::information(parent, tr("Info"), tr("Failed to read card."));
else else
{ {
QStringList lis = result.split("\r\n"); result.replace("\r\n", "");
lis[0].replace(" ", ""); result.replace(QRegularExpression("\\[.\\]"), "");
lis[1].replace(" ", ""); result.replace("UID", "");
lis[2].replace(" ", ""); result.replace("ATQA", "");
MF_UID_parameterDialog dialog(lis[0].toUpper(), lis[1].toUpper(), lis[2].mid(0, 2).toUpper()); result.replace("SAK", "");
result.replace(" ", "");
QStringList lis = result.split(':');
qDebug() << lis;
MF_UID_parameterDialog dialog(lis[1].toUpper(), lis[2].toUpper(), lis[3].toUpper());
connect(&dialog, &MF_UID_parameterDialog::sendCMD, util, &Util::execCMD); connect(&dialog, &MF_UID_parameterDialog::sendCMD, util, &Util::execCMD);
if(dialog.exec() == QDialog::Accepted) if(dialog.exec() == QDialog::Accepted)
ui->funcTab->setCurrentIndex(1); ui->funcTab->setCurrentIndex(Util::rawTabIndex);
} }
} }
void Mifare::lockC() void Mifare::lockC()
{ {
if(Util::getClientType() == Util::CLIENTTYPE_OFFICIAL)
{
util->execCMD("hf 14a raw -pa -b7 40"); util->execCMD("hf 14a raw -pa -b7 40");
util->execCMD("hf 14a raw -pa 43"); util->execCMD("hf 14a raw -pa 43");
util->execCMD("hf 14a raw -pa E0 00 39 F7"); util->execCMD("hf 14a raw -pa E0 00 39 F7");
util->execCMD("hf 14a raw -pa E1 00 E1 EE"); util->execCMD("hf 14a raw -pa E1 00 E1 EE");
util->execCMD("hf 14a raw -pa 85 00 00 00 00 00 00 00 00 00 00 00 00 00 00 08 18 47"); util->execCMD("hf 14a raw -pa 85 00 00 00 00 00 00 00 00 00 00 00 00 00 00 08 18 47");
util->execCMD("hf 14a raw 52"); util->execCMD("hf 14a raw -a 52");
}
else if(Util::getClientType() == Util::CLIENTTYPE_ICEMAN)
{
util->execCMD("hf 14a raw -ak -b 7 40");
util->execCMD("hf 14a raw -ak 43");
util->execCMD("hf 14a raw -ak E0 00 39 F7");
util->execCMD("hf 14a raw -ak E1 00 E1 EE");
util->execCMD("hf 14a raw -ak 85 00 00 00 00 00 00 00 00 00 00 00 00 00 00 08 18 47");
util->execCMD("hf 14a raw -a 52");
}
} }
void Mifare::wipeE() void Mifare::wipeE()
{ {
if(Util::getClientType() == Util::CLIENTTYPE_OFFICIAL || Util::getClientType() == Util::CLIENTTYPE_ICEMAN)
util->execCMD("hf mf eclr"); util->execCMD("hf mf eclr");
} }
void Mifare::simulate() void Mifare::simulate()
{ {
MF_Sim_simDialog dialog(cardType.type); MF_Sim_simDialog dialog(cardType.type, cardType.typeText);
connect(&dialog, &MF_Sim_simDialog::sendCMD, util, &Util::execCMD); connect(&dialog, &MF_Sim_simDialog::sendCMD, util, &Util::execCMD);
if(dialog.exec() == QDialog::Accepted) if(dialog.exec() == QDialog::Accepted)
ui->funcTab->setCurrentIndex(1); ui->funcTab->setCurrentIndex(Util::rawTabIndex);
} }
void Mifare::loadSniff(const QString& file) void Mifare::loadSniff(const QString& file)
{ {
if(Util::getClientType() == Util::CLIENTTYPE_OFFICIAL)
util->execCMD("hf list mf -l " + file); util->execCMD("hf list mf -l " + file);
ui->funcTab->setCurrentIndex(1); else if(Util::getClientType() == Util::CLIENTTYPE_ICEMAN)
{
if(util->execCMDWithOutput("trace load -f " + file, Util::ReturnTrigger({"loaded"})) != "")
util->execCMD("trace list -t mf");
}
ui->funcTab->setCurrentIndex(Util::rawTabIndex);
} }
void Mifare::saveSniff(const QString& file) void Mifare::saveSniff(const QString& file)
{ {
if(Util::getClientType() == Util::CLIENTTYPE_OFFICIAL)
util->execCMD("hf list mf -s " + file); util->execCMD("hf list mf -s " + file);
ui->funcTab->setCurrentIndex(1); else if(Util::getClientType() == Util::CLIENTTYPE_ICEMAN)
util->execCMD("trace save -f " + file);
ui->funcTab->setCurrentIndex(Util::rawTabIndex);
} }
void Mifare::data_syncWithDataWidget(bool syncAll, int block) void Mifare::data_syncWithDataWidget(bool syncAll, int block)
@ -846,7 +957,7 @@ void Mifare::data_clearKey(bool clearAll)
} }
} }
bool Mifare::data_isKeyValid(const QString &key) bool Mifare::data_isKeyValid(const QString& key)
{ {
if(key.length() != 12) if(key.length() != 12)
return false; return false;
@ -912,7 +1023,7 @@ void Mifare::setCardType(int type)
} }
} }
bool Mifare::data_loadDataFile(const QString &filename) bool Mifare::data_loadDataFile(const QString& filename)
{ {
QFile file(filename, this); QFile file(filename, this);
if(file.open(QIODevice::ReadOnly)) if(file.open(QIODevice::ReadOnly))
@ -959,7 +1070,7 @@ bool Mifare::data_loadDataFile(const QString &filename)
} }
} }
bool Mifare::data_loadKeyFile(const QString &filename) bool Mifare::data_loadKeyFile(const QString& filename)
{ {
QFile file(filename, this); QFile file(filename, this);
if(file.open(QIODevice::ReadOnly)) if(file.open(QIODevice::ReadOnly))
@ -996,7 +1107,7 @@ bool Mifare::data_loadKeyFile(const QString &filename)
} }
} }
QString Mifare::bin2text(const QByteArray &buff, int i, int length) QString Mifare::bin2text(const QByteArray& buff, int i, int length)
{ {
QString ret = ""; QString ret = "";
char LByte, RByte; char LByte, RByte;
@ -1014,7 +1125,7 @@ QString Mifare::bin2text(const QByteArray &buff, int i, int length)
return ret; return ret;
} }
bool Mifare::data_saveDataFile(const QString &filename, bool isBin) bool Mifare::data_saveDataFile(const QString& filename, bool isBin)
{ {
QFile file(filename, this); QFile file(filename, this);
if(file.open(QIODevice::WriteOnly)) if(file.open(QIODevice::WriteOnly))
@ -1058,7 +1169,7 @@ bool Mifare::data_saveDataFile(const QString &filename, bool isBin)
} }
} }
bool Mifare::data_saveKeyFile(const QString &filename, bool isBin) bool Mifare::data_saveKeyFile(const QString& filename, bool isBin)
{ {
QFile file(filename, this); QFile file(filename, this);
if(file.open(QIODevice::WriteOnly)) if(file.open(QIODevice::WriteOnly))
@ -1153,12 +1264,12 @@ void Mifare::data_data2Key()
} }
} }
void Mifare::data_setData(int block, const QString &data) void Mifare::data_setData(int block, const QString& data)
{ {
dataList->replace(block, data); dataList->replace(block, data);
} }
void Mifare::data_setKey(int sector, KeyType keyType, const QString &key) void Mifare::data_setKey(int sector, KeyType keyType, const QString& key)
{ {
if(keyType == KEY_A) if(keyType == KEY_A)
keyAList->replace(sector, key); keyAList->replace(sector, key);
@ -1192,24 +1303,36 @@ int Mifare::data_b2s(int block)
return -1; return -1;
} }
QList<quint8> Mifare::data_getACBits(const QString& text) //return empty QList if the text is invalid bool Mifare::data_isACBitsValid(const QString& text, QList<quint8>* returnHalfBytes)
{ {
QString input = text; QString input = text;
QList<quint8> result;
input.remove(" "); input.remove(" ");
if(input.length() < 6) if(input.length() < 6)
{ {
return result; return false;
} }
input = input.left(6); input = input.left(6);
quint32 val = input.toUInt(nullptr, 16); quint32 val = input.toUInt(nullptr, 16);
quint8 halfBytes[6]; QList<quint8> halfBytes;
for(int i = 0; i < 6; i++) for(int i = 0; i < 6; i++)
{ {
halfBytes[i] = (val >> ((5 - i) * 4)) & 0xf; halfBytes.append((val >> ((5 - i) * 4)) & 0xf);
} }
qDebug() << val; qDebug() << val;
if((~halfBytes[0] & 0xf) == halfBytes[5] && (~halfBytes[1] & 0xf) == halfBytes[2] && (~halfBytes[3] & 0xf) == halfBytes[4]) if((~halfBytes[0] & 0xf) == halfBytes[5] && (~halfBytes[1] & 0xf) == halfBytes[2] && (~halfBytes[3] & 0xf) == halfBytes[4])
{
if(returnHalfBytes != nullptr)
*returnHalfBytes = halfBytes;
return true;
}
else
return false;
}
QList<quint8> Mifare::data_getACBits(const QString& text) //return empty QList if the text is invalid
{
QList<quint8> halfBytes, result;
if(data_isACBitsValid(text, &halfBytes))
{ {
for(int i = 0; i < 4; i++) for(int i = 0; i < 4; i++)
{ {

@ -37,6 +37,7 @@ public:
quint16 block_size; quint16 block_size;
quint8 blk[40]; quint8 blk[40];
quint8 blks[40]; quint8 blks[40];
QString typeText;
}; };
enum AccessType enum AccessType
@ -66,9 +67,10 @@ public:
QString info(bool isRequiringOutput = false); QString info(bool isRequiringOutput = false);
void chk(); void chk();
void nested(); void nested();
void darkside();
void hardnested(); void hardnested();
void sniff(); void sniff();
void snoop(); void sniff14a();
void list(); void list();
void readOne(TargetType targetType = TARGET_MIFARE); void readOne(TargetType targetType = TARGET_MIFARE);
void readSelected(TargetType targetType = TARGET_MIFARE); void readSelected(TargetType targetType = TARGET_MIFARE);
@ -106,8 +108,9 @@ public:
void saveSniff(const QString& file); void saveSniff(const QString& file);
void data_fillKeys(); void data_fillKeys();
static QList<quint8> data_getACBits(const QString &text); static QList<quint8> data_getACBits(const QString& text);
static int data_b2s(int block); static int data_b2s(int block);
static bool data_isACBitsValid(const QString& text, QList<quint8> *returnHalfBytes = nullptr);
public slots: public slots:
signals: signals:
@ -124,9 +127,9 @@ private:
QRegularExpression* keyPattern; QRegularExpression* keyPattern;
QString bin2text(const QByteArray& buff, int start, int length); 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); 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); 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); bool _writeblk(int blockId, KeyType keyType, const QString& key, const QString& data, TargetType targetType = TARGET_MIFARE, int waitTime = 300);
}; };
#endif // MIFARE_H #endif // MIFARE_H

@ -7,6 +7,7 @@ MainWindow::MainWindow(QWidget *parent):
{ {
ui->setupUi(this); ui->setupUi(this);
myInfo = new QAction("wh201906", this); myInfo = new QAction("wh201906", this);
currVersion = new QAction("Ver: " + QApplication::applicationVersion().section('.', 0, -2), this); // ignore the 4th version number
checkUpdate = new QAction(tr("Check Update"), this); checkUpdate = new QAction(tr("Check Update"), this);
connect(myInfo, &QAction::triggered, [ = ]() connect(myInfo, &QAction::triggered, [ = ]()
{ {
@ -17,9 +18,11 @@ MainWindow::MainWindow(QWidget *parent):
QDesktopServices::openUrl(QUrl("https://github.com/wh201906/Proxmark3GUI/releases")); QDesktopServices::openUrl(QUrl("https://github.com/wh201906/Proxmark3GUI/releases"));
}); });
this->addAction(myInfo); this->addAction(myInfo);
this->addAction(currVersion);
this->addAction(checkUpdate); this->addAction(checkUpdate);
settings = new QSettings("GUIsettings.ini", QSettings::IniFormat); settings = new QSettings("GUIsettings.ini", QSettings::IniFormat);
settings->setIniCodec("UTF-8");
pm3Thread = new QThread(this); pm3Thread = new QThread(this);
pm3 = new PM3Process(pm3Thread); pm3 = new PM3Process(pm3Thread);
@ -29,6 +32,18 @@ MainWindow::MainWindow(QWidget *parent):
util = new Util(this); util = new Util(this);
mifare = new Mifare(ui, util, this); mifare = new Mifare(ui, util, this);
keyEventFilter = new MyEventFilter(QEvent::KeyRelease);
resizeEventFilter = new MyEventFilter(QEvent::Resize);
// hide unused tabs
ui->funcTab->removeTab(1);
ui->funcTab->removeTab(1);
portSearchTimer = new QTimer(this);
portSearchTimer->setInterval(2000);
connect(portSearchTimer, &QTimer::timeout, this, &MainWindow::on_portSearchTimer_timeout);
portSearchTimer->start();
} }
MainWindow::~MainWindow() MainWindow::~MainWindow()
@ -51,52 +66,70 @@ void MainWindow::initUI() // will be called by main.app
// ******************** basic functions ******************** // ******************** basic functions ********************
void MainWindow::on_PM3_refreshPortButton_clicked() void MainWindow::on_portSearchTimer_timeout()
{ {
ui->PM3_portBox->clear(); QStringList newPortList;
QSerialPort serial;
QStringList serialList;
foreach(const QSerialPortInfo &info, QSerialPortInfo::availablePorts()) foreach(const QSerialPortInfo &info, QSerialPortInfo::availablePorts())
{ {
qDebug() << info.isBusy() << info.isNull() << info.portName(); // qDebug() << info.isBusy() << info.isNull() << info.portName() << info.description();
serial.setPort(info); if(!info.isNull())
newPortList << info.portName();
if(serial.open(QIODevice::ReadWrite))
{
serialList << info.portName();
serial.close();
}
} }
foreach(QString port, serialList) if(newPortList != portList) // update PM3_portBox when available ports changed
{ {
ui->PM3_portBox->addItem(port); portList = newPortList;
ui->PM3_portBox->clear();
ui->PM3_portBox->addItems(portList);
} }
} }
void MainWindow::on_PM3_connectButton_clicked() void MainWindow::on_PM3_connectButton_clicked()
{ {
qDebug() << "Main:" << QThread::currentThread(); qDebug() << "Main:" << QThread::currentThread();
QString port = ui->PM3_portBox->currentText(); QString port = ui->PM3_portBox->currentText();
if(port == "") if(port == "")
QMessageBox::information(NULL, tr("Info"), tr("Plz choose a port first"), QMessageBox::Ok); QMessageBox::information(NULL, tr("Info"), tr("Plz choose a port first"), QMessageBox::Ok);
else else
{ {
QStringList args = ui->Set_Client_startArgsEdit->text().replace("<port>", port).split(' ');
saveClientPath(ui->PM3_pathEdit->text()); saveClientPath(ui->PM3_pathEdit->text());
emit connectPM3(ui->PM3_pathEdit->text(), port); QProcess envSetProcess;
QFileInfo envScriptPath(ui->Set_Client_envScriptEdit->text());
if(envScriptPath.exists())
{
qDebug() << envScriptPath.absoluteFilePath();
#ifdef Q_OS_WIN
// cmd /c "<path>">>nul && set
envSetProcess.start("cmd /c \"" + envScriptPath.absoluteFilePath() + "\">>nul && set");
#else
// sh -c '. "<path>">>/dev/null && env'
envSetProcess.start("sh -c \' . \"" + envScriptPath.absoluteFilePath() + "\">>/dev/null && env");
#endif
envSetProcess.waitForReadyRead(10000);
clientEnv = QString(envSetProcess.readAll()).split(QRegExp("[\r\n]"), QString::SkipEmptyParts);
// qDebug() << "Get Env List" << clientEnv;
}
else
clientEnv.clear();
emit setProcEnv(&clientEnv);
emit connectPM3(ui->PM3_pathEdit->text(), port, args);
} }
} }
void MainWindow::onPM3StateChanged(bool st, QString info) void MainWindow::onPM3StateChanged(bool st, const QString& info)
{ {
pm3state = st; pm3state = st;
setState(st); setState(st);
if(st == true) if(st == true)
{ {
portSearchTimer->stop();
setStatusBar(PM3VersionBar, info); setStatusBar(PM3VersionBar, info);
setStatusBar(connectStatusBar, tr("Connected")); setStatusBar(connectStatusBar, tr("Connected"));
} }
else else
{ {
portSearchTimer->start();
setStatusBar(PM3VersionBar, ""); setStatusBar(PM3VersionBar, "");
setStatusBar(connectStatusBar, tr("Not Connected")); setStatusBar(connectStatusBar, tr("Not Connected"));
} }
@ -104,11 +137,8 @@ void MainWindow::onPM3StateChanged(bool st, QString info)
void MainWindow::on_PM3_disconnectButton_clicked() void MainWindow::on_PM3_disconnectButton_clicked()
{ {
pm3state = false;
setState(false);
emit killPM3(); emit killPM3();
emit setSerialListener("", false); emit setSerialListener("", false);
setStatusBar(connectStatusBar, tr("Not Connected"));
} }
void MainWindow::refreshOutput(const QString& output) void MainWindow::refreshOutput(const QString& output)
@ -118,17 +148,31 @@ void MainWindow::refreshOutput(const QString& output)
ui->Raw_outputEdit->moveCursor(QTextCursor::End); ui->Raw_outputEdit->moveCursor(QTextCursor::End);
} }
void MainWindow::refreshCMD(const QString& cmd) void MainWindow::on_stopButton_clicked()
{ {
ui->Raw_CMDEdit->setText(cmd); if(!pm3state)
if(cmd != "" && (ui->Raw_CMDHistoryWidget->count() == 0 || ui->Raw_CMDHistoryWidget->item(ui->Raw_CMDHistoryWidget->count() - 1)->text() != cmd)) on_PM3_disconnectButton_clicked();
ui->Raw_CMDHistoryWidget->addItem(cmd); else
{
on_PM3_disconnectButton_clicked();
for(int i = 0; i < 10; i++)
{
util->delay(200);
if(!pm3state)
break;
}
emit reconnectPM3();
}
} }
// ********************************************************* // *********************************************************
// ******************** raw command ******************** // ******************** raw command ********************
void MainWindow::on_Raw_CMDEdit_textChanged(const QString &arg1)
{
stashedCMDEditText = arg1;
}
void MainWindow::on_Raw_sendCMDButton_clicked() void MainWindow::on_Raw_sendCMDButton_clicked()
{ {
util->execCMD(ui->Raw_CMDEdit->text()); util->execCMD(ui->Raw_CMDEdit->text());
@ -173,17 +217,73 @@ void MainWindow::sendMSG() // send command when pressing Enter
on_Raw_sendCMDButton_clicked(); on_Raw_sendCMDButton_clicked();
} }
void MainWindow::refreshCMD(const QString& cmd)
{
ui->Raw_CMDEdit->blockSignals(true);
ui->Raw_CMDEdit->setText(cmd);
if(cmd != "" && (ui->Raw_CMDHistoryWidget->count() == 0 || ui->Raw_CMDHistoryWidget->item(ui->Raw_CMDHistoryWidget->count() - 1)->text() != cmd))
ui->Raw_CMDHistoryWidget->addItem(cmd);
stashedCMDEditText = cmd;
stashedIndex = -1;
ui->Raw_CMDEdit->blockSignals(false);
}
void MainWindow::on_Raw_CMDEdit_keyPressed(QObject* obj_addr, QEvent& event)
{
if(obj_addr == ui->Raw_CMDEdit && event.type() == QEvent::KeyRelease)
{
QKeyEvent& keyEvent = static_cast<QKeyEvent&>(event);
if(keyEvent.key() == Qt::Key_Up)
{
if(stashedIndex > 0)
stashedIndex--;
else if(stashedIndex == -1)
stashedIndex = ui->Raw_CMDHistoryWidget->count() - 1;
}
else if(keyEvent.key() == Qt::Key_Down)
{
if(stashedIndex < ui->Raw_CMDHistoryWidget->count() - 1 && stashedIndex != -1)
stashedIndex++;
else if(stashedIndex == ui->Raw_CMDHistoryWidget->count() - 1)
stashedIndex = -1;
}
if(keyEvent.key() == Qt::Key_Up || keyEvent.key() == Qt::Key_Down)
{
ui->Raw_CMDEdit->blockSignals(true);
if(stashedIndex == -1)
ui->Raw_CMDEdit->setText(stashedCMDEditText);
else
ui->Raw_CMDEdit->setText(ui->Raw_CMDHistoryWidget->item(stashedIndex)->text());
ui->Raw_CMDEdit->blockSignals(false);
}
}
}
// ***************************************************** // *****************************************************
// ******************** mifare ******************** // ******************** mifare ********************
void MainWindow::MF_onTypeChanged(int id, bool st) void MainWindow::on_MF_keyWidget_resized(QObject* obj_addr, QEvent& event)
{ {
typeBtnGroup->blockSignals(true); if(obj_addr == ui->MF_keyWidget && event.type() == QEvent::Resize)
qDebug() << id << typeBtnGroup->checkedId(); {
QTableWidget* widget = (QTableWidget*)obj_addr;
int keyItemWidth = widget->width();
keyItemWidth -= widget->verticalScrollBar()->width();
keyItemWidth -= 2 * widget->frameWidth();
keyItemWidth -= widget->horizontalHeader()->sectionSize(0);
widget->horizontalHeader()->resizeSection(1, keyItemWidth / 2);
widget->horizontalHeader()->resizeSection(2, keyItemWidth / 2);
}
}
void MainWindow::MF_onMFCardTypeChanged(int id, bool st)
{
MFCardTypeBtnGroup->blockSignals(true);
qDebug() << id << MFCardTypeBtnGroup->checkedId();
if(!st) if(!st)
{ {
int result; int result;
if(id > typeBtnGroup->checkedId()) // id is specified in uiInit() with a proper order, so I can compare the size by id. if(id > MFCardTypeBtnGroup->checkedId()) // id is specified in uiInit() with a proper order, so I can compare the size by id.
{ {
result = QMessageBox::question(this, tr("Info"), tr("Some of the data and key will be cleared.") + "\n" + tr("Continue?"), QMessageBox::Yes | QMessageBox::No); result = QMessageBox::question(this, tr("Info"), tr("Some of the data and key will be cleared.") + "\n" + tr("Continue?"), QMessageBox::Yes | QMessageBox::No);
} }
@ -194,7 +294,7 @@ void MainWindow::MF_onTypeChanged(int id, bool st)
if(result == QMessageBox::Yes) if(result == QMessageBox::Yes)
{ {
qDebug() << "Yes"; qDebug() << "Yes";
mifare->setCardType(typeBtnGroup->checkedId()); mifare->setCardType(MFCardTypeBtnGroup->checkedId());
MF_widgetReset(); MF_widgetReset();
mifare->data_syncWithDataWidget(); mifare->data_syncWithDataWidget();
mifare->data_syncWithKeyWidget(); mifare->data_syncWithKeyWidget();
@ -202,10 +302,10 @@ void MainWindow::MF_onTypeChanged(int id, bool st)
else else
{ {
qDebug() << "No"; qDebug() << "No";
typeBtnGroup->button(id)->setChecked(true); MFCardTypeBtnGroup->button(id)->setChecked(true);
} }
} }
typeBtnGroup->blockSignals(false); MFCardTypeBtnGroup->blockSignals(false);
} }
void MainWindow::on_MF_selectAllBox_stateChanged(int arg1) void MainWindow::on_MF_selectAllBox_stateChanged(int arg1)
@ -736,10 +836,10 @@ void MainWindow::on_MF_Sniff_sniffButton_clicked()
setState(true); setState(true);
} }
void MainWindow::on_MF_Sniff_snoopButton_clicked() void MainWindow::on_MF_14aSniff_snoopButton_clicked()
{ {
setState(false); setState(false);
mifare->snoop(); mifare->sniff14a();
setState(true); setState(true);
} }
@ -752,6 +852,7 @@ void MainWindow::MF_widgetReset()
{ {
int secs = mifare->cardType.sector_size; int secs = mifare->cardType.sector_size;
int blks = mifare->cardType.block_size; int blks = mifare->cardType.block_size;
QBrush trailerItemForeColor = QBrush(QColor(0, 160, 255));
ui->MF_RW_blockBox->clear(); ui->MF_RW_blockBox->clear();
ui->MF_keyWidget->setRowCount(secs); ui->MF_keyWidget->setRowCount(secs);
ui->MF_dataWidget->setRowCount(blks); ui->MF_dataWidget->setRowCount(blks);
@ -776,8 +877,10 @@ void MainWindow::MF_widgetReset()
setTableItem(ui->MF_keyWidget, i, 1, ""); setTableItem(ui->MF_keyWidget, i, 1, "");
setTableItem(ui->MF_keyWidget, i, 2, ""); setTableItem(ui->MF_keyWidget, i, 2, "");
setTableItem(ui->MF_dataWidget, mifare->cardType.blks[i], 0, QString::number(i)); setTableItem(ui->MF_dataWidget, mifare->cardType.blks[i], 0, QString::number(i));
ui->MF_dataWidget->item(mifare->cardType.blks[i] + mifare->cardType.blk[i] - 1, 2)->setForeground(trailerItemForeColor);
ui->MF_dataWidget->item(mifare->cardType.blks[i], 0)->setCheckState(Qt::Checked); ui->MF_dataWidget->item(mifare->cardType.blks[i], 0)->setCheckState(Qt::Checked);
} }
ui->MF_dataWidget->item(0, 2)->setForeground(QBrush(QColor(255, 160, 0)));
ui->MF_selectAllBox->setCheckState(Qt::Checked); ui->MF_selectAllBox->setCheckState(Qt::Checked);
ui->MF_selectTrailerBox->setCheckState(Qt::Checked); ui->MF_selectTrailerBox->setCheckState(Qt::Checked);
@ -794,42 +897,44 @@ void MainWindow::MF_widgetReset()
void MainWindow::uiInit() void MainWindow::uiInit()
{ {
connect(ui->Raw_CMDEdit, &QLineEdit::editingFinished, this, &MainWindow::sendMSG); connect(ui->Raw_CMDEdit, &QLineEdit::editingFinished, this, &MainWindow::sendMSG);
ui->Raw_CMDEdit->installEventFilter(keyEventFilter);
connect(keyEventFilter, &MyEventFilter::eventHappened, this, &MainWindow::on_Raw_CMDEdit_keyPressed);
ui->MF_keyWidget->installEventFilter(resizeEventFilter);
connect(resizeEventFilter, &MyEventFilter::eventHappened, this, &MainWindow::on_MF_keyWidget_resized);
connectStatusBar = new QLabel(this); connectStatusBar = new QLabel(this);
programStatusBar = new QLabel(this); programStatusBar = new QLabel(this);
PM3VersionBar = new QLabel(this); PM3VersionBar = new QLabel(this);
stopButton = new QPushButton(this);
setStatusBar(connectStatusBar, tr("Not Connected")); setStatusBar(connectStatusBar, tr("Not Connected"));
setStatusBar(programStatusBar, tr("Idle")); setStatusBar(programStatusBar, tr("Idle"));
setStatusBar(PM3VersionBar, ""); setStatusBar(PM3VersionBar, "");
stopButton->setText(tr("Stop"));
ui->statusbar->addPermanentWidget(PM3VersionBar, 1); ui->statusbar->addPermanentWidget(PM3VersionBar, 1);
ui->statusbar->addPermanentWidget(connectStatusBar, 1); ui->statusbar->addPermanentWidget(connectStatusBar, 1);
ui->statusbar->addPermanentWidget(programStatusBar, 1); ui->statusbar->addPermanentWidget(programStatusBar, 1);
ui->statusbar->addPermanentWidget(stopButton);
ui->MF_dataWidget->setColumnCount(3); ui->MF_dataWidget->setColumnCount(3);
ui->MF_dataWidget->setHorizontalHeaderItem(0, new QTableWidgetItem(tr("Sec"))); ui->MF_dataWidget->setHorizontalHeaderItem(0, new QTableWidgetItem(tr("Sec")));
ui->MF_dataWidget->setHorizontalHeaderItem(1, new QTableWidgetItem(tr("Blk"))); ui->MF_dataWidget->setHorizontalHeaderItem(1, new QTableWidgetItem(tr("Blk")));
ui->MF_dataWidget->setHorizontalHeaderItem(2, new QTableWidgetItem(tr("Data"))); ui->MF_dataWidget->setHorizontalHeaderItem(2, new QTableWidgetItem(tr("Data")));
ui->MF_dataWidget->verticalHeader()->setVisible(false);
ui->MF_dataWidget->setColumnWidth(0, 55); ui->MF_dataWidget->setColumnWidth(0, 55);
ui->MF_dataWidget->setColumnWidth(1, 55); ui->MF_dataWidget->setColumnWidth(1, 55);
ui->MF_dataWidget->setColumnWidth(2, 430);
ui->MF_keyWidget->setColumnCount(3); ui->MF_keyWidget->setColumnCount(3);
ui->MF_keyWidget->setHorizontalHeaderItem(0, new QTableWidgetItem(tr("Sec"))); ui->MF_keyWidget->setHorizontalHeaderItem(0, new QTableWidgetItem(tr("Sec")));
ui->MF_keyWidget->setHorizontalHeaderItem(1, new QTableWidgetItem(tr("KeyA"))); ui->MF_keyWidget->setHorizontalHeaderItem(1, new QTableWidgetItem(tr("KeyA")));
ui->MF_keyWidget->setHorizontalHeaderItem(2, new QTableWidgetItem(tr("KeyB"))); ui->MF_keyWidget->setHorizontalHeaderItem(2, new QTableWidgetItem(tr("KeyB")));
ui->MF_keyWidget->verticalHeader()->setVisible(false); ui->MF_keyWidget->setColumnWidth(0, 45);
ui->MF_keyWidget->setColumnWidth(0, 35);
ui->MF_keyWidget->setColumnWidth(1, 115);
ui->MF_keyWidget->setColumnWidth(2, 115);
MF_widgetReset(); MF_widgetReset();
typeBtnGroup = new QButtonGroup(this); MFCardTypeBtnGroup = new QButtonGroup(this);
typeBtnGroup->addButton(ui->MF_Type_miniButton, 0); MFCardTypeBtnGroup->addButton(ui->MF_Type_miniButton, 0);
typeBtnGroup->addButton(ui->MF_Type_1kButton, 1); MFCardTypeBtnGroup->addButton(ui->MF_Type_1kButton, 1);
typeBtnGroup->addButton(ui->MF_Type_2kButton, 2); MFCardTypeBtnGroup->addButton(ui->MF_Type_2kButton, 2);
typeBtnGroup->addButton(ui->MF_Type_4kButton, 4); MFCardTypeBtnGroup->addButton(ui->MF_Type_4kButton, 4);
connect(typeBtnGroup, QOverload<int, bool>::of(&QButtonGroup::buttonToggled), this, &MainWindow::MF_onTypeChanged); connect(MFCardTypeBtnGroup, QOverload<int, bool>::of(&QButtonGroup::buttonToggled), this, &MainWindow::MF_onMFCardTypeChanged);
ui->MF_keyWidget->installEventFilter(this); ui->MF_keyWidget->installEventFilter(this);
ui->MF_dataWidget->installEventFilter(this); ui->MF_dataWidget->installEventFilter(this);
@ -837,7 +942,7 @@ void MainWindow::uiInit()
settings->beginGroup("UI_grpbox_preference"); settings->beginGroup("UI_grpbox_preference");
QStringList boxNames = settings->allKeys(); QStringList boxNames = settings->allKeys();
QGroupBox* boxptr; QGroupBox * boxptr;
foreach(QString name, boxNames) foreach(QString name, boxNames)
{ {
boxptr = this->findChild<QGroupBox*>(name); boxptr = this->findChild<QGroupBox*>(name);
@ -860,11 +965,23 @@ void MainWindow::uiInit()
ui->PM3_pathEdit->setText(settings->value("path", "proxmark3").toString()); ui->PM3_pathEdit->setText(settings->value("path", "proxmark3").toString());
settings->endGroup(); settings->endGroup();
settings->beginGroup("Client_Args");
ui->Set_Client_startArgsEdit->setText(settings->value("args", "<port> -f").toString());
settings->endGroup();
settings->beginGroup("Client_forceButtonsEnabled");
keepButtonsEnabled = settings->value("state", false).toBool();
ui->Set_Client_forceEnabledBox->setChecked(keepButtonsEnabled);
settings->endGroup();
settings->beginGroup("Client_Env");
ui->Set_Client_envScriptEdit->setText(settings->value("scriptPath").toString());
settings->endGroup();
ui->MF_RW_keyTypeBox->addItem("A", Mifare::KEY_A); ui->MF_RW_keyTypeBox->addItem("A", Mifare::KEY_A);
ui->MF_RW_keyTypeBox->addItem("B", Mifare::KEY_B); ui->MF_RW_keyTypeBox->addItem("B", Mifare::KEY_B);
on_Raw_CMDHistoryBox_stateChanged(Qt::Unchecked); on_Raw_CMDHistoryBox_stateChanged(Qt::Unchecked);
on_PM3_refreshPortButton_clicked();
} }
void MainWindow::signalInit() void MainWindow::signalInit()
@ -874,8 +991,11 @@ void MainWindow::signalInit()
connect(util, &Util::refreshOutput, this, &MainWindow::refreshOutput); connect(util, &Util::refreshOutput, this, &MainWindow::refreshOutput);
connect(this, &MainWindow::connectPM3, pm3, &PM3Process::connectPM3); connect(this, &MainWindow::connectPM3, pm3, &PM3Process::connectPM3);
connect(this, &MainWindow::reconnectPM3, pm3, &PM3Process::reconnectPM3);
connect(pm3, &PM3Process::PM3StatedChanged, this, &MainWindow::onPM3StateChanged); connect(pm3, &PM3Process::PM3StatedChanged, this, &MainWindow::onPM3StateChanged);
connect(pm3, &PM3Process::PM3StatedChanged, util, &Util::setRunningState);
connect(this, &MainWindow::killPM3, pm3, &PM3Process::kill); connect(this, &MainWindow::killPM3, pm3, &PM3Process::kill);
connect(this, &MainWindow::setProcEnv, pm3, &PM3Process::setProcEnv);
connect(util, &Util::write, pm3, &PM3Process::write); connect(util, &Util::write, pm3, &PM3Process::write);
@ -886,9 +1006,11 @@ void MainWindow::signalInit()
connect(ui->MF_UIDGroupBox, &QGroupBox::clicked, this, &MainWindow::on_GroupBox_clicked); connect(ui->MF_UIDGroupBox, &QGroupBox::clicked, this, &MainWindow::on_GroupBox_clicked);
connect(ui->MF_simGroupBox, &QGroupBox::clicked, this, &MainWindow::on_GroupBox_clicked); connect(ui->MF_simGroupBox, &QGroupBox::clicked, this, &MainWindow::on_GroupBox_clicked);
connect(ui->MF_sniffGroupBox, &QGroupBox::clicked, this, &MainWindow::on_GroupBox_clicked); connect(ui->MF_sniffGroupBox, &QGroupBox::clicked, this, &MainWindow::on_GroupBox_clicked);
connect(stopButton, &QPushButton::clicked, this, &MainWindow::on_stopButton_clicked);
} }
void MainWindow::setStatusBar(QLabel * target, const QString & text) void MainWindow::setStatusBar(QLabel * target, const QString& text)
{ {
if(target == PM3VersionBar) if(target == PM3VersionBar)
target->setText(tr("HW Version:") + text); target->setText(tr("HW Version:") + text);
@ -898,7 +1020,7 @@ void MainWindow::setStatusBar(QLabel * target, const QString & text)
target->setText(tr("State:") + text); target->setText(tr("State:") + text);
} }
void MainWindow::setTableItem(QTableWidget * widget, int row, int column, const QString & text) void MainWindow::setTableItem(QTableWidget * widget, int row, int column, const QString& text)
{ {
if(widget->item(row, column) == nullptr) if(widget->item(row, column) == nullptr)
widget->setItem(row, column, new QTableWidgetItem()); widget->setItem(row, column, new QTableWidgetItem());
@ -956,6 +1078,11 @@ void MainWindow::setState(bool st)
{ {
setStatusBar(programStatusBar, tr("Idle")); setStatusBar(programStatusBar, tr("Idle"));
} }
setButtonsEnabled(st || keepButtonsEnabled);
}
void MainWindow::setButtonsEnabled(bool st)
{
ui->MF_attackGroupBox->setEnabled(st); ui->MF_attackGroupBox->setEnabled(st);
ui->MF_normalGroupBox->setEnabled(st); ui->MF_normalGroupBox->setEnabled(st);
ui->MF_UIDGroupBox->setEnabled(st); ui->MF_UIDGroupBox->setEnabled(st);
@ -983,10 +1110,53 @@ void MainWindow::on_GroupBox_clicked(bool checked)
settings->endGroup(); settings->endGroup();
} }
void MainWindow::saveClientPath(const QString & path) void MainWindow::saveClientPath(const QString& path)
{ {
settings->beginGroup("Client_Path"); settings->beginGroup("Client_Path");
settings->setValue("path", path); settings->setValue("path", path);
settings->endGroup(); settings->endGroup();
} }
// *********************************************** // ***********************************************
void MainWindow::on_MF_Attack_darksideButton_clicked()
{
setState(false);
mifare->darkside();
setState(true);
}
void MainWindow::on_Set_Client_startArgsEdit_editingFinished()
{
settings->beginGroup("Client_Args");
settings->setValue("args", ui->Set_Client_startArgsEdit->text());
settings->endGroup();
}
void MainWindow::on_Set_Client_forceEnabledBox_stateChanged(int arg1)
{
settings->beginGroup("Client_forceButtonsEnabled");
keepButtonsEnabled = (arg1 == Qt::Checked);
settings->setValue("state", keepButtonsEnabled);
settings->endGroup();
if(keepButtonsEnabled)
setButtonsEnabled(true);
}
void MainWindow::on_Set_GUI_setLanguageButton_clicked()
{
Util::chooseLanguage(settings, this);
}
void MainWindow::on_PM3_refreshPortButton_clicked()
{
on_portSearchTimer_timeout();
}
void MainWindow::on_Set_Client_envScriptEdit_editingFinished()
{
settings->beginGroup("Client_Env");
settings->setValue("scriptPath", ui->Set_Client_envScriptEdit->text());
settings->endGroup();
}

@ -19,7 +19,12 @@
#include <QGroupBox> #include <QGroupBox>
#include <QSizePolicy> #include <QSizePolicy>
#include <QSettings> #include <QSettings>
#include <QPushButton>
#include <QProcessEnvironment>
#include <QScrollBar>
#include <QTimer>
#include "common/myeventfilter.h"
#include "common/pm3process.h" #include "common/pm3process.h"
#include "module/mifare.h" #include "module/mifare.h"
#include "common/util.h" #include "common/util.h"
@ -43,11 +48,13 @@ public:
void initUI(); void initUI();
bool eventFilter(QObject *watched, QEvent *event); bool eventFilter(QObject *watched, QEvent *event);
public slots: public slots:
void refreshOutput(const QString &output); void refreshOutput(const QString& output);
void refreshCMD(const QString &cmd); void refreshCMD(const QString& cmd);
void setStatusBar(QLabel* target, const QString & text); void setStatusBar(QLabel* target, const QString& text);
void onPM3StateChanged(bool st, QString info); void onPM3StateChanged(bool st, const QString& info);
void MF_onTypeChanged(int id, bool st); void MF_onMFCardTypeChanged(int id, bool st);
void on_Raw_CMDEdit_keyPressed(QObject *obj_addr, QEvent &event);
void on_MF_keyWidget_resized(QObject *obj_addr, QEvent &event);
private slots: private slots:
void on_PM3_connectButton_clicked(); void on_PM3_connectButton_clicked();
@ -59,7 +66,8 @@ private slots:
void on_Raw_clearOutputButton_clicked(); void on_Raw_clearOutputButton_clicked();
void sendMSG(); void sendMSG();
void on_PM3_refreshPortButton_clicked();
void on_portSearchTimer_timeout();
void on_Raw_CMDHistoryBox_stateChanged(int arg1); void on_Raw_CMDHistoryBox_stateChanged(int arg1);
@ -87,7 +95,6 @@ private slots:
void on_MF_RW_writeSelectedButton_clicked(); void on_MF_RW_writeSelectedButton_clicked();
void on_MF_RW_dumpButton_clicked(); void on_MF_RW_dumpButton_clicked();
void on_MF_RW_restoreButton_clicked(); void on_MF_RW_restoreButton_clicked();
@ -142,27 +149,56 @@ private slots:
void on_MF_fillKeysButton_clicked(); void on_MF_fillKeysButton_clicked();
void on_MF_Sniff_snoopButton_clicked(); void on_MF_14aSniff_snoopButton_clicked();
void on_MF_trailerDecoderButton_clicked(); void on_MF_trailerDecoderButton_clicked();
void on_MF_selectTrailerBox_stateChanged(int arg1); 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();
private: private:
Ui::MainWindow* ui; Ui::MainWindow* ui;
QButtonGroup* typeBtnGroup; QButtonGroup* MFCardTypeBtnGroup;
QLabel* connectStatusBar; QLabel* connectStatusBar;
QLabel* programStatusBar; QLabel* programStatusBar;
QLabel* PM3VersionBar; QLabel* PM3VersionBar;
QPushButton* stopButton;
QAction* myInfo; QAction* myInfo;
QAction* currVersion;
QAction* checkUpdate; QAction* checkUpdate;
QSettings* settings; QSettings* settings;
MyEventFilter* keyEventFilter;
MyEventFilter* resizeEventFilter;
QString stashedCMDEditText;
int stashedIndex = -1;
void uiInit(); void uiInit();
PM3Process* pm3; PM3Process* pm3;
bool pm3state; bool pm3state;
bool keepButtonsEnabled;
QThread* pm3Thread; QThread* pm3Thread;
QTimer* portSearchTimer;
QStringList portList;
QStringList clientEnv;
Mifare* mifare; Mifare* mifare;
Util* util; Util* util;
@ -172,12 +208,14 @@ private:
void signalInit(); void signalInit();
void MF_widgetReset(); void MF_widgetReset();
void setTableItem(QTableWidget *widget, int row, int column, const QString &text); void setTableItem(QTableWidget *widget, int row, int column, const QString& text);
void setState(bool st); void setState(bool st);
void saveClientPath(const QString &path); void saveClientPath(const QString& path);
signals: signals:
void connectPM3(const QString path, const QString port); void connectPM3(const QString& path, const QString& port, const QStringList args);
void reconnectPM3();
void killPM3(); void killPM3();
void setSerialListener(const QString &name, bool state); void setSerialListener(const QString& name, bool state);
void setProcEnv(const QStringList *env);
}; };
#endif // MAINWINDOW_H #endif // MAINWINDOW_H

@ -6,14 +6,14 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>970</width> <width>1050</width>
<height>770</height> <height>700</height>
</rect> </rect>
</property> </property>
<property name="minimumSize"> <property name="minimumSize">
<size> <size>
<width>970</width> <width>800</width>
<height>770</height> <height>600</height>
</size> </size>
</property> </property>
<property name="contextMenuPolicy"> <property name="contextMenuPolicy">
@ -53,13 +53,20 @@
<item> <item>
<widget class="QLabel" name="label"> <widget class="QLabel" name="label">
<property name="text"> <property name="text">
<string>Path:</string> <string>Client Path:</string>
</property> </property>
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QLineEdit" name="PM3_pathEdit"/> <widget class="QLineEdit" name="PM3_pathEdit"/>
</item> </item>
<item>
<widget class="QLabel" name="label_18">
<property name="text">
<string>Port:</string>
</property>
</widget>
</item>
<item> <item>
<widget class="QComboBox" name="PM3_portBox"> <widget class="QComboBox" name="PM3_portBox">
<property name="minimumSize"> <property name="minimumSize">
@ -68,6 +75,9 @@
<height>0</height> <height>0</height>
</size> </size>
</property> </property>
<property name="editable">
<bool>true</bool>
</property>
</widget> </widget>
</item> </item>
<item> <item>
@ -79,7 +89,7 @@
</size> </size>
</property> </property>
<property name="text"> <property name="text">
<string>Refresh</string> <string>Refresh Ports</string>
</property> </property>
</widget> </widget>
</item> </item>
@ -170,6 +180,12 @@
<property name="selectionMode"> <property name="selectionMode">
<enum>QAbstractItemView::SingleSelection</enum> <enum>QAbstractItemView::SingleSelection</enum>
</property> </property>
<attribute name="horizontalHeaderStretchLastSection">
<bool>true</bool>
</attribute>
<attribute name="verticalHeaderVisible">
<bool>false</bool>
</attribute>
<attribute name="verticalHeaderMinimumSectionSize"> <attribute name="verticalHeaderMinimumSectionSize">
<number>20</number> <number>20</number>
</attribute> </attribute>
@ -329,6 +345,9 @@
<property name="selectionMode"> <property name="selectionMode">
<enum>QAbstractItemView::SingleSelection</enum> <enum>QAbstractItemView::SingleSelection</enum>
</property> </property>
<attribute name="verticalHeaderVisible">
<bool>false</bool>
</attribute>
<attribute name="verticalHeaderMinimumSectionSize"> <attribute name="verticalHeaderMinimumSectionSize">
<number>20</number> <number>20</number>
</attribute> </attribute>
@ -568,6 +587,19 @@
</property> </property>
</widget> </widget>
</item> </item>
<item>
<widget class="QPushButton" name="MF_Attack_darksideButton">
<property name="minimumSize">
<size>
<width>40</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>Darkside</string>
</property>
</widget>
</item>
<item> <item>
<spacer name="horizontalSpacer_2"> <spacer name="horizontalSpacer_2">
<property name="orientation"> <property name="orientation">
@ -1097,7 +1129,7 @@
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QPushButton" name="MF_Sniff_snoopButton"> <widget class="QPushButton" name="MF_14aSniff_snoopButton">
<property name="minimumSize"> <property name="minimumSize">
<size> <size>
<width>40</width> <width>40</width>
@ -1105,7 +1137,7 @@
</size> </size>
</property> </property>
<property name="text"> <property name="text">
<string>Snoop</string> <string>Sniff(14a)</string>
</property> </property>
</widget> </widget>
</item> </item>
@ -1168,6 +1200,222 @@
</item> </item>
</layout> </layout>
</widget> </widget>
<widget class="QWidget" name="lfTab">
<property name="enabled">
<bool>true</bool>
</property>
<attribute name="title">
<string>LF/Data</string>
</attribute>
<widget class="QGroupBox" name="LF_configGroupBox">
<property name="geometry">
<rect>
<x>10</x>
<y>10</y>
<width>121</width>
<height>211</height>
</rect>
</property>
<property name="title">
<string>LF Config</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_9">
<property name="spacing">
<number>2</number>
</property>
<property name="leftMargin">
<number>2</number>
</property>
<property name="topMargin">
<number>5</number>
</property>
<property name="rightMargin">
<number>2</number>
</property>
<property name="bottomMargin">
<number>2</number>
</property>
<item>
<widget class="QGroupBox" name="LF_Conf_freqGroupBox">
<property name="title">
<string>Frequency</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_13">
<property name="spacing">
<number>5</number>
</property>
<property name="leftMargin">
<number>2</number>
</property>
<property name="topMargin">
<number>5</number>
</property>
<property name="rightMargin">
<number>2</number>
</property>
<property name="bottomMargin">
<number>2</number>
</property>
<item>
<widget class="QRadioButton" name="LF_Conf_freq125kButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>125k</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="LF_Conf_freq134kButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>134k</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<layout class="QFormLayout" name="formLayout">
<item row="0" column="0">
<widget class="QLabel" name="label_6">
<property name="text">
<string>BitRate:</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_7">
<property name="text">
<string>Decimation:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QSpinBox" name="LF_Conf_decimationBox"/>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_8">
<property name="text">
<string>Averaging:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QCheckBox" name="LF_Conf_averagingBox">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_9">
<property name="text">
<string>Threshold:</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QSpinBox" name="LF_Conf_thresholdBox"/>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_10">
<property name="text">
<string>Skips:</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QSpinBox" name="LF_Conf_skipsBox"/>
</item>
<item row="0" column="1">
<widget class="QSpinBox" name="LF_Conf_bitRateBox"/>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_14">
<item>
<widget class="QPushButton" name="LF_Conf_getButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>20</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>Get</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_8">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="LF_Conf_setButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>20</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>Set</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</widget>
<widget class="QWidget" name="t55xxTab">
<attribute name="title">
<string>T55xx</string>
</attribute>
<widget class="QTableWidget" name="T55_dataWidget">
<property name="geometry">
<rect>
<x>20</x>
<y>10</y>
<width>256</width>
<height>192</height>
</rect>
</property>
</widget>
</widget>
<widget class="QWidget" name="rawTab"> <widget class="QWidget" name="rawTab">
<attribute name="title"> <attribute name="title">
<string>RawCommand</string> <string>RawCommand</string>
@ -1198,6 +1446,9 @@
<verstretch>0</verstretch> <verstretch>0</verstretch>
</sizepolicy> </sizepolicy>
</property> </property>
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="verticalScrollBarPolicy"> <property name="verticalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOn</enum> <enum>Qt::ScrollBarAlwaysOn</enum>
</property> </property>
@ -1283,6 +1534,212 @@
</item> </item>
</layout> </layout>
</widget> </widget>
<widget class="QWidget" name="settingsTab">
<attribute name="title">
<string>Settings</string>
</attribute>
<layout class="QHBoxLayout" name="horizontalLayout_15">
<item>
<layout class="QVBoxLayout" name="verticalLayout_12">
<item>
<widget class="QGroupBox" name="Set_clientGroupBox">
<property name="title">
<string>Client</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_10">
<item>
<widget class="QLabel" name="label_11">
<property name="text">
<string>Preload script path:</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="Set_Client_envScriptEdit">
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_13">
<property name="text">
<string>Note:
If the client requires some enviroment variables, you can make a script file(*.bat on Windows or *.sh on Linux) to configure them,
then put the path of the script there</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="Line" name="line">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_12">
<property name="text">
<string>Start arguments</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="Set_Client_startArgsEdit">
<property name="text">
<string>&lt;port&gt; -f</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_14">
<property name="text">
<string>Note:
-f is necessary because the GUI need to handle the output in time
In some cases the arguments should be set to &quot;-p /dev/&lt;port&gt; -f&quot;
or &quot;-p &lt;port&gt; -f&quot;</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="Line" name="line_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_16">
<item>
<widget class="QCheckBox" name="Set_Client_forceEnabledBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_15">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Keep buttons enabled even the client is running or disconnected</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="Line" name="line_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_2">
<property name="title">
<string>GUI</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_11">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_17">
<item>
<widget class="QLabel" name="label_16">
<property name="text">
<string>Language: </string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="Set_GUI_setLanguageButton">
<property name="text">
<string>Choose Language</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_17">
<property name="text">
<string>(Restart this app to use new language)</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_9">
<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>
</layout>
</widget>
</item>
<item>
<spacer name="verticalSpacer_5">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<spacer name="horizontalSpacer_10">
<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>
</widget>
</widget> </widget>
</item> </item>
</layout> </layout>

@ -21,6 +21,18 @@ MF_Attack_hardnestedDialog::~MF_Attack_hardnestedDialog()
void MF_Attack_hardnestedDialog::on_buttonBox_accepted() void MF_Attack_hardnestedDialog::on_buttonBox_accepted()
{ {
if(Util::getClientType() == Util::CLIENTTYPE_OFFICIAL)
emit sendCMD("hf mf hardnested "
+ ui->knownKeySectorBox->currentText()
+ " "
+ ui->knownKeyTypeBox->currentText()
+ " "
+ ui->knownKeyBox->text()
+ " "
+ ui->targetKeySectorBox->currentText()
+ " "
+ ui->targetKeyTypeBox->currentText());
else if(Util::getClientType() == Util::CLIENTTYPE_ICEMAN) // same format in v4.9237
emit sendCMD("hf mf hardnested " emit sendCMD("hf mf hardnested "
+ ui->knownKeySectorBox->currentText() + ui->knownKeySectorBox->currentText()
+ " " + " "

@ -2,8 +2,10 @@
#define MF_ATTACK_HARDNESTEDDIALOG_H #define MF_ATTACK_HARDNESTEDDIALOG_H
#include <QDialog> #include <QDialog>
#include "common/util.h"
namespace Ui { namespace Ui
{
class MF_Attack_hardnestedDialog; class MF_Attack_hardnestedDialog;
} }
@ -19,7 +21,7 @@ public:
private: private:
Ui::MF_Attack_hardnestedDialog *ui; Ui::MF_Attack_hardnestedDialog *ui;
signals: signals:
void sendCMD(QString cmd); void sendCMD(const QString& cmd);
private slots: private slots:
void on_buttonBox_accepted(); void on_buttonBox_accepted();
}; };

@ -1,12 +1,34 @@
#include "mf_sim_simdialog.h" #include "mf_sim_simdialog.h"
#include "ui_mf_sim_simdialog.h" #include "ui_mf_sim_simdialog.h"
MF_Sim_simDialog::MF_Sim_simDialog(int cardType, QWidget *parent) : MF_Sim_simDialog::MF_Sim_simDialog(int cardType, QString cardTypeText, QWidget *parent) :
QDialog(parent), QDialog(parent),
ui(new Ui::MF_Sim_simDialog) ui(new Ui::MF_Sim_simDialog)
{ {
ui->setupUi(this); 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->cardType = cardType;
this->cardTypeText = cardTypeText;
} }
MF_Sim_simDialog::~MF_Sim_simDialog() MF_Sim_simDialog::~MF_Sim_simDialog()
@ -55,6 +77,8 @@ void MF_Sim_simDialog::on_fBox_clicked(bool checked)
void MF_Sim_simDialog::on_buttonBox_accepted() void MF_Sim_simDialog::on_buttonBox_accepted()
{ {
QString paras; QString paras;
if(Util::getClientType() == Util::CLIENTTYPE_OFFICIAL)
{
paras += (ui->uBox->isChecked() ? "u " + ui->uEdit->text() + " " : ""); paras += (ui->uBox->isChecked() ? "u " + ui->uEdit->text() + " " : "");
paras += (ui->nBox->isChecked() ? "n " + ui->nEdit->text() + " " : ""); paras += (ui->nBox->isChecked() ? "n " + ui->nEdit->text() + " " : "");
paras += (ui->iBox->isChecked() ? "i " : ""); paras += (ui->iBox->isChecked() ? "i " : "");
@ -63,4 +87,17 @@ void MF_Sim_simDialog::on_buttonBox_accepted()
paras += (ui->fBox->isChecked() ? "f " + ui->fEdit->text() + " " : ""); paras += (ui->fBox->isChecked() ? "f " + ui->fEdit->text() + " " : "");
paras += (ui->rBox->isChecked() ? "r " : ""); paras += (ui->rBox->isChecked() ? "r " : "");
emit sendCMD(QString("hf mf sim ") + "*" + QString::number(cardType) + " " + paras.trimmed()); 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());
}
} }

@ -3,6 +3,7 @@
#include <QDialog> #include <QDialog>
#include <QDebug> #include <QDebug>
#include "common/util.h"
namespace Ui namespace Ui
{ {
@ -14,7 +15,7 @@ class MF_Sim_simDialog : public QDialog
Q_OBJECT Q_OBJECT
public: public:
explicit MF_Sim_simDialog(int cardType, QWidget *parent = nullptr); explicit MF_Sim_simDialog(int cardType, QString cardTypeText, QWidget *parent = nullptr);
~MF_Sim_simDialog(); ~MF_Sim_simDialog();
private slots: private slots:
@ -25,8 +26,9 @@ private slots:
private: private:
Ui::MF_Sim_simDialog *ui; Ui::MF_Sim_simDialog *ui;
int cardType; int cardType;
QString cardTypeText;
signals: signals:
void sendCMD(QString cmd); void sendCMD(const QString& cmd);
private slots: private slots:
void on_buttonBox_accepted(); void on_buttonBox_accepted();
}; };

@ -7,30 +7,31 @@
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>461</width> <width>461</width>
<height>456</height> <height>524</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
<string>Simulate</string> <string>Simulate</string>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout"> <layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QGroupBox" name="uGroupBox">
<layout class="QHBoxLayout" name="uLayout">
<property name="spacing"> <property name="spacing">
<number>5</number> <number>5</number>
</property> </property>
<property name="leftMargin"> <property name="leftMargin">
<number>5</number> <number>0</number>
</property> </property>
<property name="topMargin"> <property name="topMargin">
<number>5</number> <number>0</number>
</property> </property>
<property name="rightMargin"> <property name="rightMargin">
<number>5</number> <number>0</number>
</property> </property>
<property name="bottomMargin"> <property name="bottomMargin">
<number>5</number> <number>0</number>
</property> </property>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item> <item>
<widget class="QCheckBox" name="uBox"> <widget class="QCheckBox" name="uBox">
<property name="text"> <property name="text">
@ -71,16 +72,167 @@
</widget> </widget>
</item> </item>
</layout> </layout>
</widget>
</item> </item>
<item> <item>
<widget class="Line" name="line_6"> <widget class="Line" name="uLine">
<property name="orientation"> <property name="orientation">
<enum>Qt::Horizontal</enum> <enum>Qt::Horizontal</enum>
</property> </property>
</widget> </widget>
</item> </item>
<item> <item>
<layout class="QHBoxLayout" name="horizontalLayout_2"> <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> <item>
<widget class="QCheckBox" name="nBox"> <widget class="QCheckBox" name="nBox">
<property name="text"> <property name="text">
@ -121,16 +273,33 @@
</widget> </widget>
</item> </item>
</layout> </layout>
</widget>
</item> </item>
<item> <item>
<widget class="Line" name="line_5"> <widget class="Line" name="nLine">
<property name="orientation"> <property name="orientation">
<enum>Qt::Horizontal</enum> <enum>Qt::Horizontal</enum>
</property> </property>
</widget> </widget>
</item> </item>
<item> <item>
<layout class="QHBoxLayout" name="horizontalLayout_4"> <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> <item>
<widget class="QCheckBox" name="iBox"> <widget class="QCheckBox" name="iBox">
<property name="text"> <property name="text">
@ -155,16 +324,33 @@
</widget> </widget>
</item> </item>
</layout> </layout>
</widget>
</item> </item>
<item> <item>
<widget class="Line" name="line_4"> <widget class="Line" name="iLine">
<property name="orientation"> <property name="orientation">
<enum>Qt::Horizontal</enum> <enum>Qt::Horizontal</enum>
</property> </property>
</widget> </widget>
</item> </item>
<item> <item>
<layout class="QHBoxLayout" name="horizontalLayout_5"> <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> <item>
<widget class="QCheckBox" name="xBox"> <widget class="QCheckBox" name="xBox">
<property name="text"> <property name="text">
@ -189,16 +375,33 @@
</widget> </widget>
</item> </item>
</layout> </layout>
</widget>
</item> </item>
<item> <item>
<widget class="Line" name="line_3"> <widget class="Line" name="xLine">
<property name="orientation"> <property name="orientation">
<enum>Qt::Horizontal</enum> <enum>Qt::Horizontal</enum>
</property> </property>
</widget> </widget>
</item> </item>
<item> <item>
<layout class="QHBoxLayout" name="horizontalLayout_6"> <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> <item>
<widget class="QCheckBox" name="eBox"> <widget class="QCheckBox" name="eBox">
<property name="text"> <property name="text">
@ -215,7 +418,7 @@
</sizepolicy> </sizepolicy>
</property> </property>
<property name="text"> <property name="text">
<string>set keys found from 'reader attack' to emulator memory (implies x and i)</string> <string>set keys found from 'reader attack' to emulator memory (implies x(--crack) and i)</string>
</property> </property>
<property name="wordWrap"> <property name="wordWrap">
<bool>true</bool> <bool>true</bool>
@ -223,16 +426,33 @@
</widget> </widget>
</item> </item>
</layout> </layout>
</widget>
</item> </item>
<item> <item>
<widget class="Line" name="line_2"> <widget class="Line" name="eLine">
<property name="orientation"> <property name="orientation">
<enum>Qt::Horizontal</enum> <enum>Qt::Horizontal</enum>
</property> </property>
</widget> </widget>
</item> </item>
<item> <item>
<layout class="QHBoxLayout" name="horizontalLayout_3"> <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> <item>
<widget class="QCheckBox" name="fBox"> <widget class="QCheckBox" name="fBox">
<property name="text"> <property name="text">
@ -273,16 +493,33 @@
</widget> </widget>
</item> </item>
</layout> </layout>
</widget>
</item> </item>
<item> <item>
<widget class="Line" name="line"> <widget class="Line" name="fLine">
<property name="orientation"> <property name="orientation">
<enum>Qt::Horizontal</enum> <enum>Qt::Horizontal</enum>
</property> </property>
</widget> </widget>
</item> </item>
<item> <item>
<layout class="QHBoxLayout" name="horizontalLayout_7"> <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> <item>
<widget class="QCheckBox" name="rBox"> <widget class="QCheckBox" name="rBox">
<property name="text"> <property name="text">
@ -307,9 +544,61 @@
</widget> </widget>
</item> </item>
</layout> </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>
<item> <item>
<widget class="Line" name="line_7"> <widget class="Line" name="vLine">
<property name="orientation"> <property name="orientation">
<enum>Qt::Horizontal</enum> <enum>Qt::Horizontal</enum>
</property> </property>

@ -15,10 +15,10 @@ MF_trailerDecoderDialog::MF_trailerDecoderDialog(QWidget *parent) :
sizeGroup->addButton(ui->size4Button, 4); sizeGroup->addButton(ui->size4Button, 4);
sizeGroup->addButton(ui->size16Button, 16); sizeGroup->addButton(ui->size16Button, 16);
connect(sizeGroup, QOverload<int, bool>::of(&QButtonGroup::buttonToggled), this, &MF_trailerDecoderDialog::on_blockSizeChanged); connect(sizeGroup, QOverload<int, bool>::of(&QButtonGroup::buttonToggled), this, &MF_trailerDecoderDialog::on_blockSizeChanged);
connect(ui->C0Box, &QSpinBox::textChanged, this, &MF_trailerDecoderDialog::on_boxChanged); connect(ui->C0Box, QOverload<int>::of(&QSpinBox::valueChanged), this, &MF_trailerDecoderDialog::on_boxChanged);
connect(ui->C1Box, &QSpinBox::textChanged, this, &MF_trailerDecoderDialog::on_boxChanged); connect(ui->C1Box, QOverload<int>::of(&QSpinBox::valueChanged), this, &MF_trailerDecoderDialog::on_boxChanged);
connect(ui->C2Box, &QSpinBox::textChanged, this, &MF_trailerDecoderDialog::on_boxChanged); connect(ui->C2Box, QOverload<int>::of(&QSpinBox::valueChanged), this, &MF_trailerDecoderDialog::on_boxChanged);
connect(ui->C3Box, &QSpinBox::textChanged, this, &MF_trailerDecoderDialog::on_boxChanged); connect(ui->C3Box, QOverload<int>::of(&QSpinBox::valueChanged), this, &MF_trailerDecoderDialog::on_boxChanged);
ui->dataBlockWidget->setRowCount(3); ui->dataBlockWidget->setRowCount(3);
ui->dataBlockWidget->setColumnCount(4); ui->dataBlockWidget->setColumnCount(4);
@ -123,7 +123,7 @@ void MF_trailerDecoderDialog::setTableItem(QTableWidget* widget, int row, int co
widget->item(row, column)->setText(text); widget->item(row, column)->setText(text);
} }
void MF_trailerDecoderDialog::on_boxChanged(const QString &arg1) void MF_trailerDecoderDialog::on_boxChanged(int arg1)
{ {
quint8 ACBits[4]; quint8 ACBits[4];
ACBits[0] = ui->C0Box->value(); ACBits[0] = ui->C0Box->value();

@ -23,11 +23,11 @@ public:
private slots: private slots:
void on_accessBitsEdit_textChanged(const QString &arg1); void on_accessBitsEdit_textChanged(const QString& arg1);
void on_blockSizeChanged(int id, bool st); void on_blockSizeChanged(int id, bool st);
void on_boxChanged(const QString &arg1); void on_boxChanged(int arg1);
private: private:
Ui::MF_trailerDecoderDialog *ui; Ui::MF_trailerDecoderDialog *ui;
QRegularExpressionValidator* validator; QRegularExpressionValidator* validator;

@ -18,6 +18,14 @@ MF_UID_parameterDialog::~MF_UID_parameterDialog()
void MF_UID_parameterDialog::on_buttonBox_accepted() void MF_UID_parameterDialog::on_buttonBox_accepted()
{ {
if(Util::getClientType() == Util::CLIENTTYPE_OFFICIAL)
emit sendCMD("hf mf csetuid "
+ ui->UIDLineEdit->text()
+ " "
+ ui->ATQALineEdit->text()
+ " "
+ ui->SAKLineEdit->text());
else if(Util::getClientType() == Util::CLIENTTYPE_ICEMAN) // same format in v4.9237
emit sendCMD("hf mf csetuid " emit sendCMD("hf mf csetuid "
+ ui->UIDLineEdit->text() + ui->UIDLineEdit->text()
+ " " + " "

@ -2,8 +2,10 @@
#define MF_UID_PARAMETERDIALOG_H #define MF_UID_PARAMETERDIALOG_H
#include <QDialog> #include <QDialog>
#include "common/util.h"
namespace Ui { namespace Ui
{
class MF_UID_parameterDialog; class MF_UID_parameterDialog;
} }
@ -18,7 +20,7 @@ public:
private: private:
Ui::MF_UID_parameterDialog *ui; Ui::MF_UID_parameterDialog *ui;
signals: signals:
void sendCMD(QString cmd); void sendCMD(const QString& cmd);
private slots: private slots:
void on_buttonBox_accepted(); void on_buttonBox_accepted();
}; };

Loading…
Cancel
Save