43 Commits

Author SHA1 Message Date
wh201906 a8b1a4a82e V0.2 2021-02-23 20:40:55 +08:00
wh201906 03bb57ee58 Update translations 2021-02-23 19:47:36 +08:00
wh201906 15538a9892 LF: Support write LF config
When setting LF freq, the "lf config" and "hw setlfdivisor" will both be called.
Change some UI
2021-02-23 18:14:59 +08:00
wh201906 466cd0ecc1 LF: support read LF config 2021-02-23 16:35:58 +08:00
wh201906 019afed198 Add QAction: Dock all windows 2021-02-22 22:20:49 +08:00
wh201906 799e00d66e Replace QTabWidget with QDockWidget
dock it(√)
doki(?)
2021-02-22 15:57:32 +08:00
wh201906 ae9e4d1a4f LF: support read(), sniff(), search() and tune() 2021-02-22 13:55:45 +08:00
wh201906 c3aafc3d31 Fix a bug in disconnect() 2021-02-22 12:47:55 +08:00
wh201906 fb8e1a6e1b New experimental feature
Keep client active even the PM3 hardware is disconnected
2021-02-21 23:00:07 +08:00
wh201906 90e4fde882 Fix a bug in RawCommand Tab
Not all of the keys should be redirected.
2021-02-21 21:30:22 +08:00
wh201906 705c8de54c Fix a bug in RawCommand Tab
If a widget is set to NoFocus, then it will not respond to the key Event
2021-02-20 20:51:26 +08:00
wh201906 aa6b93984c A small patch
Support specifying client working directory
Clean all compile warnings
2021-02-17 01:26:14 +08:00
wh201906 7f96c061dc Merge pull request #14 from wh201906/dev
V0.1.4
2021-02-16 14:28:50 +08:00
wh201906 b8c4e8e339 V0.1.4 2021-02-16 14:25:20 +08:00
wh201906 4f10e3d75c All functions are compatible to Iceman/RRG fork
Use different foreground color for Trailer block and Block 0
2021-02-16 13:52:04 +08:00
wh201906 63f3424871 Support wipe(), lockUFUID(), setUIDParameter(),
in latest Iceman repo
Fix a error in keyPattern
Test all R/W functions in Iceman client and Official client
2021-02-16 01:17:50 +08:00
wh201906 24a6e1869b Support hardnested(), darkside(), readblk(),
readsec() in latest Iceman repo
2021-02-15 23:46:05 +08:00
wh201906 6baa09221e Support chk(), nested() in latest Iceman repo 2021-02-15 23:00:02 +08:00
wh201906 6e5f654cc5 Support running a external script before client start,
to configure the environment variables

Optimize stop(reconnect) logic
Search valid ports automatically
Update translations
2021-02-15 18:38:34 +08:00
wh201906 83445c7eef Add new features
Support change language in Settings
Support customized start arguments
Strech data section in MF_dataWidget and key section in MF_keyWidget
2021-02-14 22:47:56 +08:00
wh201906 5330ed8d14 Some changes
Refactor execCMDWithOutput
Add UI for advanced settings
Add stop button(reconnect)
Update translations
2021-02-13 23:58:11 +08:00
wh201906 a56a503b23 Some slight changes
Add HighDPI support(not tested)
Support Mifare darkside attack
Hide unfinished function tabs
2021-02-12 23:48:25 +08:00
wh201906 77d8049738 Merge pull request #13 from wh201906/master
Replace textChanged() with valueChanged(). This fixes #9
2020-11-04 15:12:39 +08:00
wh201906 bf9b3fb076 Merge branch 'dev' into master 2020-11-04 15:12:18 +08:00
wh201906 6d3dd5056c Replace textChanged() with valueChanged(). This fixes #9 2020-11-04 15:09:28 +08:00
wh201906 e687cc39fd Merge pull request #12 from wh201906/master
Update translation
2020-11-01 22:46:33 +08:00
wh201906 3c3944d150 Slight change 2020-11-01 22:43:46 +08:00
wh201906 091b4f63d1 Merge pull request #11 from ruling/master
Update zh_CN.ts
2020-11-01 18:17:56 +08:00
wh201906 0c4220c9a5 Change some translation 2020-10-31 18:19:06 +08:00
Ruling 986e9aacfe Correct some Chinese Translation
Correct some Chinese Translation
2020-10-30 12:58:11 +08:00
Ruling ce262db52c Update zh_CN.ts 2020-10-27 11:31:33 +08:00
wh201906 73533608e6 Add some useless UI 2020-08-14 00:46:07 +08:00
wh201906 2f38d3c8c5 Support choose history command by Key_Up and Key_Down 2020-08-13 16:39:04 +08:00
wh201906 f2d00ee088 Replace QString with const QString& 2020-08-13 09:30:47 +08:00
wh201906 862f0775f8 Shorten the waitTime for execCMDWithOutput() 2020-08-12 12:30:15 +08:00
wh201906 a7985c5c89 Stop the running command after disconnected 2020-08-11 11:51:27 +08:00
wh201906 a3e6aa787b Check Access Bits when writing to selected blocks 2020-08-11 11:30:33 +08:00
wh201906 1c273a6527 Update preview for Trailer Decoder 2020-08-10 10:37:09 +08:00
wh201906 3f899845b7 Update README 2020-08-09 11:16:45 +08:00
wh201906 475580c342 Merge pull request #5 from wh201906/dev
V0.1.3
2020-08-09 10:34:54 +08:00
wh201906 3a577bdd32 V0.1.3 2020-08-09 10:33:15 +08:00
wh201906 f8d2bbb206 Fix Trailer Decoder and add write feedback 2020-08-09 10:32:48 +08:00
wh201906 d6beafe175 Merge pull request #4 from wh201906/dev
V0.1.2
2020-08-08 22:02:32 +08:00
39 changed files with 4086 additions and 1003 deletions
-1
View File
@@ -14,7 +14,6 @@
*.so.*
*_pch.h.cpp
*_resource.rc
*.qm
.#*
*.*#
core
+5 -1
View File
@@ -16,9 +16,11 @@ DEFINES += QT_DEPRECATED_WARNINGS
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES += \
common/myeventfilter.cpp \
main.cpp \
common/pm3process.cpp \
common/util.cpp \
module/lf.cpp \
module/mifare.cpp \
ui/mf_trailerdecoderdialog.cpp \
ui/mf_sim_simdialog.cpp \
@@ -27,8 +29,10 @@ SOURCES += \
ui/mf_attack_hardnesteddialog.cpp \
HEADERS += \
common/myeventfilter.h \
common/pm3process.h \
common/util.h \
module/lf.h \
module/mifare.h \
ui/mf_trailerdecoderdialog.h \
ui/mf_sim_simdialog.h \
@@ -52,7 +56,7 @@ qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
VERSION = 0.1.2
VERSION = 0.2.0
QMAKE_TARGET_PRODUCT = "Proxmark3GUI"
QMAKE_TARGET_DESCRIPTION = "Proxmark3GUI"
QMAKE_TARGET_COMPANY = "wh201906"
+45 -11
View File
@@ -1,7 +1,9 @@
# Proxmark3GUI
A GUI for [Proxmark3](https://github.com/Proxmark/proxmark3) client
![downloads](https://img.shields.io/github/downloads/wh201906/Proxmark3GUI/total)
[中文](README/doc/README_zh_CN.md)
A cross-platform GUI for [Proxmark3](https://github.com/Proxmark/proxmark3) client
[中文介绍](README/doc/README_zh_CN.md)
***
@@ -17,6 +19,7 @@ A GUI for [Proxmark3](https://github.com/Proxmark/proxmark3) client
+ Support binary(.bin .dump) files and text(.eml) files
+ Analyze Access Bits
+ Support Chinese Magic Card
+ Have basic support for LF commands
+ Customize UI
+ ...
@@ -25,37 +28,68 @@ A GUI for [Proxmark3](https://github.com/Proxmark/proxmark3) client
## Preview
![preview](README/img/preview.png)
more previews [here](README/doc/previews.md)
[more previews](README/doc/previews.md)
***
## 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:
[supported functions](README/doc/supported_Iceman.md)
This GUI is compatible with Iceman/RRG repo(tested on v4.9237)
***
## 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.
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.
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 the client on Windows.
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.
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:
### V0.2
+ Use Dock widget for more flexible layout
+ Support basic LF commands
+ Fix a bug in RawCommand tab
### 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)
+ Support specifying client working directory
+ Fix some bugs
### V0.1.3
+ Fix Trailer Decoder
+ Add feedback when writing selected blocks
### V0.1.2
+ Optimize read logic
+ Make UI Customizable
+ Save client path automatically
+ Add Trailer Decoder
+ Add Trailer Decoder(Deprecated, plz use V0.1.3 or higher version)
+ Support read/write selected blocks
+ Support a few Iceman functions
+ Fix some bugs
+45 -8
View File
@@ -1,5 +1,7 @@
# 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)
@@ -17,7 +19,8 @@
+ 可以打开二进制/文本格式的扇区数据文件
+ 分析访问控制位(Access Bits
+ 支持UID卡操作(UID快速读写,UFUID锁卡)
+ 自定义UI界面
+ 支持部分低频命令
+ 自定义UI界面,各选项卡可拆分组合
+ ...
***
@@ -30,28 +33,62 @@
***
## 关于冰人版
这个GUI一开始是针对官方版本做的,现在正在尽力让它兼容冰人版的功能
(没钱买RDV4也没钱买两台PM3,测一次冰人就要烧一次固件 qwq)
[冰人版](https://github.com/RfidResearchGroup/proxmark3)(Iceman/RRG)的客户端和固件更新更为激进,相比官方版具有更多的功能
此GUI所有功能均兼容冰人版(在v4.9237上测试通过)
[已支持功能](../doc/supported_Iceman.md)
***
## 关于预编译Windows客户端
国外大佬 [Gator96100](https://github.com/Gator96100) 做了个 [ProxSpace](https://github.com/Gator96100/ProxSpace) 以便在Windows平台上编译PM3固件和客户端,他还把自己编译好的客户端放到了[论坛](http://www.proxmark.org/forum/viewtopic.php?id=3975)里面
文件都是放到Google Drive上面的,国内网络无法访问,所以我在release版本里面放了个带预编译客户端版本的GUI。这个GUI也可以搭配你自己的客户端使用
国外大佬 [Gator96100](https://github.com/Gator96100) 做了个 [ProxSpace](https://github.com/Gator96100/ProxSpace) 以便在Windows平台上编译PM3固件和客户端,他还把自己编译好的客户端放到了[网站](https://www.proxmarkbuilds.org/)上
release页面中有含客户端的GUI。这个GUI也可以搭配你自己的客户端使用
(本来打算在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.2
+ 使用浮动窗口,界面配置更加灵活
+ 支持部分低频命令
+ 修复原始命令选项卡中的一个Bug
### V0.1.4
+ 优化性能
+ 优化用户界面
+ 自动搜索可用端口
+ 支持高分屏
+ 可通过外部脚本配置环境变量
(在客户端需要配置环境变量时很有用)
+ 全功能兼容冰人版(在v4.9237上测试通过)
+ 支持指定客户端工作路径
+ 修复部分bug
### V0.1.3
+ 修复访问控制位解码器
+ 写多个块时显示写入结果
### V0.1.2
+ 优化读卡逻辑
+ UI自定义
+ 自动保存客户端路径
+ 添加访问控制位解码器(也可用于自己构造访问控制位)
+ 添加访问控制位解码器(也可用于自己构造访问控制位)(有bug,请使用V0.1.3或更高版本)
+ 支持仅读写选中块
+ 支持部分冰人功能
+ 修复部分bug
+4
View File
@@ -14,3 +14,7 @@ Mifare Edit File:
Mifare Trailer Decoder:
![mf_trailer](../img/mf_trailer.gif)
Dock Widget:
![dock1](../img/dock1.png)
![dock2](../img/dock2.png)
-9
View File
@@ -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.

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 407 KiB

After

Width:  |  Height:  |  Size: 468 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 52 KiB

After

Width:  |  Height:  |  Size: 50 KiB

+13
View File
@@ -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);
}
+22
View File
@@ -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
+54 -11
View File
@@ -12,19 +12,24 @@ PM3Process::PM3Process(QThread* thread, QObject* parent): QProcess(parent)
serialListener->setTimerType(Qt::VeryCoarseTimer);
connect(serialListener, &QTimer::timeout, this, &PM3Process::onTimeout);
connect(this, &PM3Process::readyRead, this, &PM3Process::onReadyRead);
portInfo = nullptr;
}
void PM3Process::connectPM3(const QString path, const QString port)
void PM3Process::connectPM3(const QString& path, const QStringList args)
{
QString result;
Util::ClientType clientType = Util::CLIENTTYPE_OFFICIAL;
Util::ClientType clientType;
setRequiringOutput(true);
// stash for reconnect
currPath = path;
currArgs = args;
// using "-f" option to make the client output flushed after every print.
start(path, QStringList() << port << "-f", QProcess::Unbuffered | QProcess::ReadWrite);
start(path, args, QProcess::Unbuffered | QProcess::ReadWrite);
if(waitForStarted(10000))
{
waitForReadyRead(1000);
waitForReadyRead(10000);
setRequiringOutput(false);
result = *requiredOutput;
if(result.indexOf("[=]") != -1)
@@ -32,10 +37,17 @@ void PM3Process::connectPM3(const QString path, const QString port)
clientType = Util::CLIENTTYPE_ICEMAN;
setRequiringOutput(true);
write("hw version\r\n");
waitForReadyRead(1000);
result = *requiredOutput;
for(int i = 0; i < 10; i++)
{
waitForReadyRead(200);
result += *requiredOutput;
}
setRequiringOutput(false);
}
else
{
clientType = Util::CLIENTTYPE_OFFICIAL;
}
if(result.indexOf("os: ") != -1) // make sure the PM3 is connected
{
emit changeClientType(clientType);
@@ -43,13 +55,17 @@ void PM3Process::connectPM3(const QString path, const QString port)
result = result.left(result.indexOf("\r\n"));
result = result.mid(3, result.lastIndexOf(" ") - 3);
emit PM3StatedChanged(true, result);
setSerialListener(port, true);
}
else
kill();
}
}
void PM3Process::reconnectPM3()
{
connectPM3(currPath, currArgs);
}
void PM3Process::setRequiringOutput(bool st)
{
isRequiringOutput = st;
@@ -66,6 +82,7 @@ void PM3Process::setSerialListener(const QString& name, bool state)
{
if(state)
{
currPort = name;
portInfo = new QSerialPortInfo(name);
serialListener->start();
qDebug() << serialListener->thread();
@@ -73,8 +90,17 @@ void PM3Process::setSerialListener(const QString& name, bool state)
else
{
serialListener->stop();
if(portInfo != nullptr)
{
delete portInfo;
portInfo = nullptr;
}
}
}
void PM3Process::setSerialListener(bool state)
{
setSerialListener(currPort, state);
}
void PM3Process::onTimeout() //when the proxmark3 client is unexpectedly terminated or the PM3 hardware is removed, the isBusy() will return false(only tested on Windows);
@@ -82,9 +108,7 @@ void PM3Process::onTimeout() //when the proxmark3 client is unexpectedly termina
// qDebug()<<portInfo->isBusy();
if(!portInfo->isBusy())
{
kill();
emit PM3StatedChanged(false);
setSerialListener("", false);
killPM3();
}
}
@@ -93,7 +117,6 @@ void PM3Process::testThread()
qDebug() << "PM3:" << QThread::currentThread();
}
qint64 PM3Process::write(QString data)
{
return QProcess::write(data.toLatin1());
@@ -111,3 +134,23 @@ void PM3Process::onReadyRead()
}
}
void PM3Process::setProcEnv(const QStringList* env)
{
// qDebug() << "passed Env List" << *env;
this->setEnvironment(*env);
// qDebug() << "final Env List" << processEnvironment().toStringList();
}
void PM3Process::setWorkingDir(const QString& dir)
{
// the working directory cannot be the default, or the client will failed to load the dll
this->setWorkingDirectory(dir);
}
void PM3Process::killPM3()
{
kill();
emit PM3StatedChanged(false);
setSerialListener(false);
}
+15 -4
View File
@@ -8,6 +8,8 @@
#include <QTimer>
#include <QtSerialPort/QSerialPortInfo>
#include <QtSerialPort/QSerialPort>
#include <QProcessEnvironment>
#include <QDir>
#include "util.h"
@@ -21,9 +23,14 @@ public:
void testThread();
public slots:
void connectPM3(const QString path, const QString port);
void setSerialListener(const QString &name, bool state);
void connectPM3(const QString& path, const QStringList args);
void setSerialListener(const QString& name, bool state);
void setSerialListener(bool state);
qint64 write(QString data);
void reconnectPM3();
void setProcEnv(const QStringList* env);
void setWorkingDir(const QString& dir);
void killPM3();
private slots:
void onTimeout();
void onReadyRead();
@@ -33,9 +40,13 @@ private:
void setRequiringOutput(bool st);// It only works in this class now
QTimer* serialListener;
QSerialPortInfo* portInfo;
QString currPath;
QString currPort = "";
QStringList currArgs;
signals:
void PM3StatedChanged(bool st, QString info = "");
void newOutput(QString output);
void PM3StatedChanged(bool st, const QString& info = "");
void newOutput(const QString& output);
void changeClientType(Util::ClientType);
};
+95 -11
View File
@@ -1,15 +1,22 @@
#include "util.h"
Util::ClientType Util::clientType = CLIENTTYPE_OFFICIAL;
int Util::rawTabIndex = 0;
QDockWidget* Util::rawDockPtr = nullptr;
Ui::MainWindow* Util::ui = nullptr;
Util::Util(QObject *parent) : QObject(parent)
{
isRequiringOutput = false;
requiredOutput = new QString();
timeStamp = QTime::currentTime();
this->clientType = CLIENTTYPE_OFFICIAL;
qRegisterMetaType<Util::ClientType>("Util::ClientType");
}
void Util::processOutput(QString output)
void Util::processOutput(const QString& output)
{
// qDebug() << "Util::processOutput:" << output;
if(isRequiringOutput)
@@ -20,30 +27,58 @@ void Util::processOutput(QString 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");
}
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 targetTime = QTime::currentTime().addMSecs(waitTime);
QTime targetTime = QTime::currentTime().addMSecs(trigger.waitTime);
isRequiringOutput = true;
requiredOutput->clear();
execCMD(cmd);
while(QTime::currentTime() < targetTime)
{
if(!isRunning)
break;
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;
targetTime = timeStamp.addMSecs(waitTime);
targetTime = timeStamp.addMSecs(trigger.waitTime);
}
}
isRequiringOutput = false;
return *requiredOutput;
return (isResultFound || trigger.expectedOutputs.isEmpty() ? *requiredOutput : "");
}
void Util::delay(unsigned int msec)
@@ -52,12 +87,61 @@ void Util::delay(unsigned int msec)
while(QTime::currentTime() < timer)
QApplication::processEvents(QEventLoop::AllEvents, 100);
}
Util::ClientType Util::getClientType()
{
return this->clientType;
return Util::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;
}
void Util::gotoRawTab()
{
Util::ui->funcTab->setCurrentIndex(Util::rawTabIndex);
Util::rawDockPtr->setVisible(true);
Util::rawDockPtr->raise();
}
void Util::setUI(Ui::MainWindow *ui)
{
Util::ui = ui;
}
void Util::setRawTab(QDockWidget *dockPtr, int tabIndex)
{
Util::rawDockPtr = dockPtr;
Util::rawTabIndex = tabIndex;
}
+44 -8
View File
@@ -9,6 +9,13 @@
#include <QTime>
#include <QTimer>
#include <QMetaType>
#include <QRegularExpression>
#include <QSettings>
#include <QMainWindow>
#include <QInputDialog>
#include <QDockWidget>
#include "ui_mainwindow.h"
class Util : public QObject
{
@@ -20,26 +27,55 @@ public:
CLIENTTYPE_ICEMAN,
};
struct ReturnTrigger
{
unsigned long waitTime;
QStringList expectedOutputs;
ReturnTrigger(unsigned long time)
{
waitTime = time;
expectedOutputs = QStringList();
}
ReturnTrigger(const QStringList& outputs)
{
waitTime = 10000;
expectedOutputs = outputs;
}
ReturnTrigger(unsigned long time, const QStringList& outputs)
{
waitTime = time;
expectedOutputs = outputs;
}
};
Q_ENUM(Util::ClientType)
explicit Util(QObject *parent = nullptr);
void execCMD(QString cmd);
QString execCMDWithOutput(QString cmd, unsigned long waitTime = 2000);
void execCMD(const QString& cmd);
QString execCMDWithOutput(const QString& cmd, ReturnTrigger trigger = 10000);
void delay(unsigned int msec);
ClientType getClientType();
static ClientType getClientType();
static int rawTabIndex;
static QDockWidget* rawDockPtr;
static bool chooseLanguage(QSettings *guiSettings, QMainWindow *window);
public slots:
void processOutput(QString output);
void setClientType(Util::ClientType clientType);
void processOutput(const QString& output);
static void setClientType(Util::ClientType clientType);
void setRunningState(bool st);
static void gotoRawTab();
static void setUI(Ui::MainWindow *ui);
static void setRawTab(QDockWidget* dockPtr, int tabIndex);
private:
bool isRequiringOutput;
bool isRunning;
QString* requiredOutput;
QTime timeStamp;
ClientType clientType;
static ClientType clientType;
static Ui::MainWindow *ui;
signals:
void refreshOutput(const QString& output);
void write(QString data);
void write(QString data); // connected to PM3Process::write(QString data);
};
#endif // UTIL_H
BIN
View File
Binary file not shown.
+504 -195
View File
File diff suppressed because it is too large Load Diff
+3
View File
@@ -0,0 +1,3 @@
[Languages]
en_US=English
zh_CN=简体中文
BIN
View File
Binary file not shown.
+538 -215
View File
File diff suppressed because it is too large Load Diff
+23 -29
View File
@@ -4,56 +4,50 @@
#include <QSettings>
#include <QTranslator>
#include <QMessageBox>
#include <QInputDialog>
#include <QTextCodec>
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QTextCodec::setCodecForLocale(QTextCodec::codecForName("UTF-8"));
QApplication a(argc, argv);
MainWindow w;
QSettings* settings = new QSettings("GUIsettings.ini", QSettings::IniFormat);
settings->setIniCodec("UTF-8");
settings->beginGroup("lang");
QVariant lang = settings->value("language", "null");
if(lang == "null")
QString currLang = settings->value("language", "").toString();
settings->endGroup();
if(currLang == "")
{
#ifdef Q_OS_WIN
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")
if(Util::chooseLanguage(settings, &w))
{
settings->beginGroup("lang");
currLang = settings->value("language", "").toString();
settings->endGroup();
}
else
currLang = "en_US";
}
currLang = "lang/" + currLang;
#ifdef Q_OS_WIN
lang = "lang/en_US.qm";
currLang += ".qm";
#else
lang = "lang/en_US.ts";
currLang += ".ts";;
#endif
}
else if(seletedText == "简体中文")
{
#ifdef Q_OS_WIN
lang = "lang/zh_CN.qm";
#else
lang = "lang/zh_CN.ts";
#endif
}
}
QTranslator* translator = new QTranslator(&w);
if(translator->load(lang.toString()))
if(translator->load(currLang))
{
a.installTranslator(translator);
settings->setValue("language", lang);
}
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;
w.initUI();
w.show();
return a.exec();
}
+167
View File
@@ -0,0 +1,167 @@
#include "lf.h"
const LF::Config LF::defaultConfig;
LF::LF(Ui::MainWindow *ui, Util *addr, QWidget *parent): QObject(parent)
{
this->parent = parent;
util = addr;
this->ui = ui;
configPattern = new QRegularExpression("(\\d+)|Yes|No");
currConfig = defaultConfig;
}
void LF::read()
{
if(Util::getClientType() == Util::CLIENTTYPE_OFFICIAL)
util->execCMD("lf read");
else if(Util::getClientType() == Util::CLIENTTYPE_ICEMAN)
util->execCMD("lf read -v");
Util::gotoRawTab();
util->execCMD("data plot");
}
void LF::sniff()
{
if(Util::getClientType() == Util::CLIENTTYPE_OFFICIAL)
util->execCMD("lf snoop");
else if(Util::getClientType() == Util::CLIENTTYPE_ICEMAN)
util->execCMD("lf sniff -v");
Util::gotoRawTab();
util->execCMD("data plot");
}
void LF::search()
{
if(Util::getClientType() == Util::CLIENTTYPE_OFFICIAL)
util->execCMD("lf search u");
else if(Util::getClientType() == Util::CLIENTTYPE_ICEMAN)
util->execCMD("lf search -u");
Util::gotoRawTab();
}
void LF::tune()
{
if(Util::getClientType() == Util::CLIENTTYPE_OFFICIAL)
util->execCMD("hw tune l");
else if(Util::getClientType() == Util::CLIENTTYPE_ICEMAN)
util->execCMD("lf tune --divisor " + QString::number(currConfig.divisor));
Util::gotoRawTab();
}
void LF::getConfig()
{
QRegularExpressionMatch reMatch;
QString result;
QStringList resultList;
QStringList symbolList =
{
"divisor",
"bps",
"bits per sample",
"decimation",
"averaging",
"trigger threshold",
"samples to skip"
};
int offset;
QStringList configList = {"", "", "", "", "", "", ""};
result = util->execCMDWithOutput("hw status", 400); // not all output from "hw status will be processed".
result = result.right(result.length() - result.indexOf("LF Sampling config"));
offset = result.indexOf("samples to skip");
offset = result.indexOf("\r\n", offset);
result = result.mid(0, offset + 2);
qDebug() << "LF CONFIG GET\n" << result;
resultList = result.split("\r\n");
for(int i = 0; i < resultList.length(); i++)
{
for(int j = 0; j < symbolList.length(); j++)
{
if(!configList[j].isEmpty())
continue;
offset = resultList[i].indexOf(symbolList[j]);
if(offset != -1)
{
reMatch = configPattern->match(resultList[i]);
qDebug() << "finded: " << resultList[i];
if(!reMatch.hasMatch())
continue;
qDebug() << "captured: " << reMatch.captured();
configList[j] = reMatch.captured();
break;
}
}
}
qDebug() << "configList: " << configList;
currConfig.divisor = configList[0].toUInt();
currConfig.decimation = configList[3].toUInt();
currConfig.triggerThreshold = configList[5].toUInt();
currConfig.samplesToSkip = configList[6].toUInt();
if(Util::getClientType() == Util::CLIENTTYPE_OFFICIAL)
{
currConfig.bitPerSample = configList[1].toUInt();
currConfig.averaging = (configList[4] == "1");
}
else if(Util::getClientType() == Util::CLIENTTYPE_ICEMAN)
{
currConfig.bitPerSample = configList[2].toUInt();
currConfig.averaging = (configList[4] == "Yes");
}
syncWithUI();
}
void LF::setConfig(LF::Config config)
{
currConfig = config;
if(Util::getClientType() == Util::CLIENTTYPE_OFFICIAL)
{
util->execCMDWithOutput(QString("lf config")
+ " q " + QString::number(currConfig.divisor)
+ " b " + QString::number(currConfig.bitPerSample)
+ " d " + QString::number(currConfig.decimation)
+ " a " + QString(currConfig.averaging ? "1" : "0")
+ " t " + QString::number(currConfig.triggerThreshold)
+ " s " + QString::number(currConfig.samplesToSkip),
500);
util->execCMDWithOutput("hw setlfdivisor " + QString::number(currConfig.divisor), 500);
}
else if(Util::getClientType() == Util::CLIENTTYPE_ICEMAN)
{
util->execCMDWithOutput(QString("lf config")
+ " -a " + QString(currConfig.averaging ? "1" : "0")
+ " -b " + QString::number(currConfig.bitPerSample)
+ " --dec " + QString::number(currConfig.decimation)
+ " --divisor " + QString::number(currConfig.divisor)
+ " -s " + QString::number(currConfig.samplesToSkip)
+ " -t " + QString::number(currConfig.triggerThreshold),
500);
util->execCMDWithOutput("hw setlfdivisor -d " + QString::number(currConfig.divisor), 500);
}
}
void LF::resetConfig()
{
setConfig(defaultConfig);
getConfig();
}
float LF::divisor2Freq(uint8_t divisor)
{
return (12000.0 / (divisor + 1.0));
}
uint8_t LF::freq2Divisor(float freq)
{
return ((uint16_t)(12000.0 / freq + 0.5) - 1); // uint16_t for (divisor + 1) = 256
}
void LF::syncWithUI()
{
ui->LF_Conf_freqDivisorBox->setValue(currConfig.divisor); // will trigger valueChanged()
ui->LF_Conf_bitPerSampleBox->setValue(currConfig.bitPerSample);
ui->LF_Conf_decimationBox->setValue(currConfig.decimation);
ui->LF_Conf_averagingBox->setChecked(currConfig.averaging);
ui->LF_Conf_thresholdBox->setValue(currConfig.triggerThreshold);
ui->LF_Conf_skipsBox->setValue(currConfig.samplesToSkip);
}
+56
View File
@@ -0,0 +1,56 @@
#ifndef LF_H
#define LF_H
#include <QObject>
#include "common/util.h"
#include "ui_mainwindow.h"
class LF : public QObject
{
Q_OBJECT
public:
explicit LF(Ui::MainWindow *ui, Util *addr, QWidget *parent = nullptr);
struct Config
{
uint8_t divisor;
uint8_t bitPerSample;
uint8_t decimation;
bool averaging;
uint8_t triggerThreshold;
uint16_t samplesToSkip;
};
static constexpr Config defaultConfig =
{
95,
8,
1,
true,
0,
0
};
void read();
void sniff();
void search();
void tune();
void getConfig();
void setConfig(LF::Config config);
void resetConfig();
static float divisor2Freq(uint8_t divisor);
static uint8_t freq2Divisor(float freq);
private:
QWidget* parent;
Ui::MainWindow *ui;
Util* util;
Config currConfig;
QRegularExpression* configPattern;
void syncWithUI();
signals:
};
#endif // LF_H
+253 -92
View File
@@ -6,7 +6,8 @@ const Mifare::CardType Mifare::card_mini =
5,
20,
{4, 4, 4, 4, 4},
{0, 4, 8, 12, 16}
{0, 4, 8, 12, 16},
"mini"
};
const Mifare::CardType Mifare::card_1k =
{
@@ -14,7 +15,8 @@ const Mifare::CardType Mifare::card_1k =
16,
64,
{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 =
{
@@ -22,7 +24,8 @@ const Mifare::CardType Mifare::card_2k =
32,
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},
{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 =
{
@@ -30,25 +33,26 @@ const Mifare::CardType Mifare::card_4k =
40,
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},
{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] =
{
{ACC_KEY_AB, ACC_KEY_AB, ACC_KEY_AB, ACC_KEY_AB},
{ACC_KEY_AB, ACC_NEVER, ACC_NEVER, ACC_NEVER},
{ACC_KEY_AB, ACC_KEY_B, ACC_NEVER, ACC_NEVER},
{ACC_KEY_AB, ACC_NEVER, ACC_NEVER, ACC_NEVER},
{ACC_KEY_AB, ACC_KEY_B, ACC_KEY_B, ACC_KEY_AB},
{ACC_KEY_AB, ACC_NEVER, ACC_NEVER, ACC_KEY_AB},
{ACC_KEY_B, ACC_KEY_B, ACC_NEVER, ACC_NEVER},
{ACC_KEY_B, ACC_NEVER, ACC_NEVER, ACC_NEVER},
{ACC_KEY_B, ACC_KEY_B, ACC_NEVER, ACC_NEVER},
{ACC_NEVER, ACC_NEVER, ACC_NEVER, ACC_NEVER},
};
const Mifare::AccessType Mifare::trailerReadCondition[8][3] =
{
{ACC_NEVER, ACC_KEY_A, ACC_KEY_A},
{ACC_NEVER, ACC_KEY_A, ACC_KEY_A},
{ACC_NEVER, ACC_KEY_AB, ACC_NEVER},
{ACC_NEVER, ACC_KEY_A, ACC_KEY_A},
{ACC_NEVER, ACC_KEY_AB, ACC_NEVER},
{ACC_NEVER, ACC_KEY_A, ACC_KEY_A},
{ACC_NEVER, ACC_KEY_AB, ACC_NEVER},
@@ -58,12 +62,12 @@ const Mifare::AccessType Mifare::trailerReadCondition[8][3] =
const Mifare::AccessType Mifare::trailerWriteCondition[8][3] =
{
{ACC_KEY_A, ACC_NEVER, ACC_KEY_A},
{ACC_NEVER, ACC_NEVER, ACC_NEVER},
{ACC_KEY_B, ACC_NEVER, ACC_KEY_B},
{ACC_NEVER, ACC_NEVER, ACC_NEVER},
{ACC_NEVER, ACC_NEVER, ACC_NEVER},
{ACC_KEY_A, ACC_KEY_A, ACC_KEY_A},
{ACC_KEY_B, ACC_KEY_B, ACC_KEY_B},
{ACC_NEVER, ACC_KEY_B, ACC_NEVER},
{ACC_KEY_B, ACC_KEY_B, ACC_KEY_B},
{ACC_NEVER, ACC_NEVER, ACC_NEVER},
};
@@ -79,53 +83,49 @@ Mifare::Mifare(Ui::MainWindow *ui, Util *addr, QWidget *parent): QObject(parent)
data_clearKey(); // fill with blank QString
data_clearData(); // fill with blank QString
dataPattern = new QRegularExpression("([0-9a-fA-F]{2} ){15}[0-9a-fA-F]{2}");
keyPattern_res = new QRegularExpression("\\|\\d{3}\\|.+?\\|.+?\\|.+?\\|.+?\\|");
keyPattern = new QRegularExpression("\\|\\d{3}\\|.+?\\|.+?\\|");
keyPattern_res = new QRegularExpression("\\|\\s*\\d{3}\\s*\\|\\s*.+?\\s*\\|\\s*.+?\\s*\\|\\s*.+?\\s*\\|\\s*.+?\\s*\\|");
keyPattern = new QRegularExpression("\\|\\s*\\d{3}\\s*\\|\\s*.+?\\s*\\|\\s*.+?\\s*\\|");
}
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)
{
QString result = util->execCMDWithOutput("hf 14a info", 500);
result.replace("UID :", "|||");
result.replace("ATQA :", "|||");
result.replace("SAK :", "|||");
result.replace("TYPE :", "|||");
QStringList lis = result.split("|||");
if(lis.length() > 4)
int begin, end;
begin = result.indexOf("UID");
if(begin != -1)
{
qDebug() << lis[1] + lis[2] + lis[3];
return lis[1] + lis[2] + lis[3];
end = result.indexOf("SAK", begin);
end = result.indexOf("\n", end);
return result.mid(begin, end - begin + 1);
}
else
return "";
}
else
{
util->execCMD("hf 14a info");
ui->funcTab->setCurrentIndex(1);
Util::gotoRawTab();
}
}
return "";
}
}
}
void Mifare::chk()
{
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 *"
+ QString::number(cardType.type)
+ " ?",
1000 + cardType.type * 1000);
Util::ReturnTrigger(1000 + cardType.sector_size * 200, {"No valid", keyPattern->pattern()}));
qDebug() << result;
int offset = 0;
QString data;
if(util->getClientType() == Util::CLIENTTYPE_OFFICIAL)
{
for(int i = 0; i < cardType.sector_size; i++)
{
reMatch = keyPattern->match(result, offset);
@@ -146,8 +146,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++)
{
reMatch = keyPattern_res->match(result, offset);
@@ -178,21 +183,22 @@ void Mifare::nested()
QString result;
int offset = 0;
QString data;
if(util->getClientType() == Util::CLIENTTYPE_OFFICIAL)
if(Util::getClientType() == Util::CLIENTTYPE_OFFICIAL)
{
result = util->execCMDWithOutput(
"hf mf nested "
+ 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 = "";
for(int i = 0; i < cardType.sector_size; 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;
}
}
@@ -202,7 +208,7 @@ void Mifare::nested()
{
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;
}
}
@@ -210,9 +216,10 @@ void Mifare::nested()
if(knownKeyInfo != "")
{
result = util->execCMDWithOutput(
"hf mf nested "
+ QString::number(cardType.type)
+ knownKeyInfo, 10000);
"hf mf nested --"
+ cardType.typeText
+ knownKeyInfo,
Util::ReturnTrigger(15000, {"Can't authenticate", keyPattern_res->pattern()}));
}
else
{
@@ -248,34 +255,57 @@ void Mifare::hardnested()
MF_Attack_hardnestedDialog dialog(cardType.block_size);
connect(&dialog, &MF_Attack_hardnestedDialog::sendCMD, util, &Util::execCMD);
if(dialog.exec() == QDialog::Accepted)
ui->funcTab->setCurrentIndex(1);
Util::gotoRawTab();
}
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");
Util::gotoRawTab();
}
void Mifare::sniff()
{
if(Util::getClientType() == Util::CLIENTTYPE_OFFICIAL)
util->execCMD("hf mf sniff");
ui->funcTab->setCurrentIndex(1);
else if(Util::getClientType() == Util::CLIENTTYPE_ICEMAN)
util->execCMD("hf sniff");
Util::gotoRawTab();
}
void Mifare::snoop()
void Mifare::sniff14a()
{
if(Util::getClientType() == Util::CLIENTTYPE_OFFICIAL)
util->execCMD("hf 14a snoop");
ui->funcTab->setCurrentIndex(1);
else if(Util::getClientType() == Util::CLIENTTYPE_ICEMAN)
util->execCMD("hf 14a sniff");
Util::gotoRawTab();
}
void Mifare::list()
{
if(Util::getClientType() == Util::CLIENTTYPE_OFFICIAL)
util->execCMD("hf list mf");
ui->funcTab->setCurrentIndex(1);
else if(Util::getClientType() == Util::CLIENTTYPE_ICEMAN)
util->execCMD("trace list -t mf");
Util::gotoRawTab();
}
QString Mifare::_readblk(int blockId, KeyType keyType, const QString& key, TargetType targetType, int waitTime)
{
QString data;
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)
{
@@ -292,13 +322,14 @@ QString Mifare::_readblk(int blockId, KeyType keyType, const QString& key, Targe
+ " "
+ key,
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(" ");
// 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(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);
QList<quint8> ACBits = data_getACBits(data.mid(12, 8));
@@ -307,7 +338,7 @@ QString Mifare::_readblk(int blockId, KeyType keyType, const QString& key, Targe
data.replace(20, 12, "????????????");
}
}
else if(isKeyBlock && keyType == KEY_B)
else if(isTrailerBlock && keyType == KEY_B)
{
data.replace(20, 12, key);;
data.replace(0, 12, "????????????"); // fill the keyA part with ?
@@ -322,15 +353,19 @@ QString Mifare::_readblk(int blockId, KeyType keyType, const QString& key, Targe
"hf mf cgetblk "
+ QString::number(blockId),
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(" ");
}
else
data = "";
}
else if(targetType == TARGET_EMULATOR)
}
if(Util::getClientType() == Util::CLIENTTYPE_OFFICIAL)
{
if(targetType == TARGET_EMULATOR)
{
result = util->execCMDWithOutput(
"hf mf eget "
@@ -340,6 +375,18 @@ QString Mifare::_readblk(int blockId, KeyType keyType, const QString& key, Targe
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;
}
@@ -348,14 +395,14 @@ QStringList Mifare::_readsec(int sectorId, KeyType keyType, const QString& key,
QStringList data;
QString result, tmp;
QRegularExpressionMatch reMatch;
int offset = -1;
int offset = -1; // for targetType == TARGET_EMULATOR
for(int i = 0; i < cardType.blk[sectorId]; i++)
{
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
if(targetType == TARGET_MIFARE)
@@ -372,7 +419,7 @@ QStringList Mifare::_readsec(int sectorId, KeyType keyType, const QString& key,
+ " "
+ key,
waitTime);
offset = result.indexOf("isOk:01");
offset = result.indexOf("isOk:01"); // find successful flag
}
else if(targetType == TARGET_UID)
{
@@ -380,7 +427,7 @@ QStringList Mifare::_readsec(int sectorId, KeyType keyType, const QString& key,
"hf mf cgetsc "
+ QString::number(sectorId),
waitTime);
offset = result.indexOf("Chinese magic");
offset = result.indexOf("error") == -1 ? 0 : -1; // find failed flag
}
if(offset != -1)
{
@@ -399,7 +446,7 @@ QStringList Mifare::_readsec(int sectorId, KeyType keyType, const QString& key,
}
// 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)
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++)
data[i] = _readblk(cardType.blks[sectorId] + i, keyType, key, targetType, waitTime);
@@ -536,12 +583,12 @@ bool Mifare::_writeblk(int blockId, KeyType keyType, const QString& key, const Q
{
QString result;
QString input = data.toUpper();
input.remove(" ");
input.remove(" ");
if(data_isDataValid(input) != DATA_NOSPACE)
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)
{
@@ -567,7 +614,7 @@ bool Mifare::_writeblk(int blockId, KeyType keyType, const QString& key, const Q
+ " "
+ input,
waitTime);
return (result.indexOf("Chinese magic") != -1);
return (result.indexOf("error") == -1); // failed flag
}
else if(targetType == TARGET_EMULATOR)
{
@@ -580,6 +627,7 @@ bool Mifare::_writeblk(int blockId, KeyType keyType, const QString& key, const Q
return true;
}
}
return false;
}
void Mifare::writeOne(TargetType targetType)
@@ -597,10 +645,12 @@ void Mifare::writeOne(TargetType targetType)
}
}
QList<int> Mifare::writeSelected(TargetType targetType)
void Mifare::writeSelected(TargetType targetType)
{
QList<int> failedBlocks;
QList<int> selectedBlocks;
bool yes2All = false, no2All = false;
for(int i = 0; i < cardType.block_size; i++)
{
if(ui->MF_dataWidget->item(i, 1)->checkState() == Qt::Checked)
@@ -609,6 +659,29 @@ QList<int> Mifare::writeSelected(TargetType targetType)
for(int item : selectedBlocks)
{
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)
{
result = _writeblk(item, KEY_A, keyAList->at(data_b2s(item)), dataList->at(item), TARGET_MIFARE);
@@ -630,28 +703,69 @@ QList<int> Mifare::writeSelected(TargetType targetType)
failedBlocks.append(item);
}
}
return failedBlocks;
if(failedBlocks.size() == 0)
QMessageBox::information(parent, tr("Info"), tr("Successful!"));
else
{
QString suffix = "";
int counter = 0;
for(int failedBlk : failedBlocks)
{
suffix += QString::number(failedBlk) + " ";
counter++;
counter %= 20;
if(counter == 0)
suffix += "\n";
}
QMessageBox::StandardButton res = QMessageBox::information(parent, tr("Info"), tr("Failed to write to these blocks:")
+ "\n"
+ suffix
+ "\n"
+ tr("Select them?"),
QMessageBox::Yes | QMessageBox::No);
if(res == QMessageBox::Yes)
{
for(int item : selectedBlocks)
{
ui->MF_dataWidget->item(item, 1)->setCheckState(Qt::Unchecked);
}
for(int failedBlk : failedBlocks)
{
ui->MF_dataWidget->item(failedBlk, 1)->setCheckState(Qt::Checked);
}
}
}
}
void Mifare::dump()
{
if(Util::getClientType() == Util::CLIENTTYPE_OFFICIAL || Util::getClientType() == Util::CLIENTTYPE_ICEMAN)
util->execCMD("hf mf dump");
ui->funcTab->setCurrentIndex(1);
Util::gotoRawTab();
}
void Mifare::restore()
{
if(Util::getClientType() == Util::CLIENTTYPE_OFFICIAL || Util::getClientType() == Util::CLIENTTYPE_ICEMAN)
util->execCMD("hf mf restore");
ui->funcTab->setCurrentIndex(1);
Util::gotoRawTab();
}
void Mifare::wipeC()
{
if(Util::getClientType() == Util::CLIENTTYPE_OFFICIAL)
{
util->execCMD(
"hf mf cwipe "
+ QString::number(cardType.type)
+ " f");
ui->funcTab->setCurrentIndex(1);
}
else if(Util::getClientType() == Util::CLIENTTYPE_ICEMAN)
{
util->execCMD("hf mf cwipe");
}
Util::gotoRawTab();
}
void Mifare::setParameterC()
@@ -661,50 +775,78 @@ void Mifare::setParameterC()
QMessageBox::information(parent, tr("Info"), tr("Failed to read card."));
else
{
QStringList lis = result.split("\r\n");
lis[0].replace(" ", "");
lis[1].replace(" ", "");
lis[2].replace(" ", "");
MF_UID_parameterDialog dialog(lis[0].toUpper(), lis[1].toUpper(), lis[2].mid(0, 2).toUpper());
result.replace("\r\n", "");
result.replace(QRegularExpression("\\[.\\]"), "");
result.replace("UID", "");
result.replace("ATQA", "");
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);
if(dialog.exec() == QDialog::Accepted)
ui->funcTab->setCurrentIndex(1);
Util::gotoRawTab();
}
}
void Mifare::lockC()
{
if(Util::getClientType() == Util::CLIENTTYPE_OFFICIAL)
{
util->execCMD("hf 14a raw -pa -b7 40");
util->execCMD("hf 14a raw -pa 43");
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 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()
{
if(Util::getClientType() == Util::CLIENTTYPE_OFFICIAL || Util::getClientType() == Util::CLIENTTYPE_ICEMAN)
util->execCMD("hf mf eclr");
}
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);
if(dialog.exec() == QDialog::Accepted)
ui->funcTab->setCurrentIndex(1);
Util::gotoRawTab();
}
void Mifare::loadSniff(const QString& file)
{
if(Util::getClientType() == Util::CLIENTTYPE_OFFICIAL)
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");
}
Util::gotoRawTab();
}
void Mifare::saveSniff(const QString& file)
{
if(Util::getClientType() == Util::CLIENTTYPE_OFFICIAL)
util->execCMD("hf list mf -s " + file);
ui->funcTab->setCurrentIndex(1);
else if(Util::getClientType() == Util::CLIENTTYPE_ICEMAN)
util->execCMD("trace save -f " + file);
Util::gotoRawTab();
}
void Mifare::data_syncWithDataWidget(bool syncAll, int block)
@@ -814,7 +956,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)
return false;
@@ -880,7 +1022,7 @@ void Mifare::setCardType(int type)
}
}
bool Mifare::data_loadDataFile(const QString &filename)
bool Mifare::data_loadDataFile(const QString& filename)
{
QFile file(filename, this);
if(file.open(QIODevice::ReadOnly))
@@ -927,7 +1069,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);
if(file.open(QIODevice::ReadOnly))
@@ -964,7 +1106,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 = "";
char LByte, RByte;
@@ -982,7 +1124,7 @@ QString Mifare::bin2text(const QByteArray &buff, int i, int length)
return ret;
}
bool Mifare::data_saveDataFile(const QString &filename, bool isBin)
bool Mifare::data_saveDataFile(const QString& filename, bool isBin)
{
QFile file(filename, this);
if(file.open(QIODevice::WriteOnly))
@@ -1026,7 +1168,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);
if(file.open(QIODevice::WriteOnly))
@@ -1121,12 +1263,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);
}
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)
keyAList->replace(sector, key);
@@ -1160,24 +1302,36 @@ int Mifare::data_b2s(int block)
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;
QList<quint8> result;
input.remove(" ");
if(input.length() < 6)
{
return result;
return false;
}
input = input.left(6);
quint32 val = input.toUInt(nullptr, 16);
quint8 halfBytes[6];
QList<quint8> halfBytes;
for(int i = 0; i < 6; i++)
{
halfBytes[i] = (val >> ((5 - i) * 4)) & 0xf;
halfBytes.append((val >> ((5 - i) * 4)) & 0xf);
}
qDebug() << val;
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++)
{
@@ -1187,3 +1341,10 @@ QList<quint8> Mifare::data_getACBits(const QString& text) //return empty QList i
return result;
}
QString Mifare::data_getUID()
{
if(data_isDataValid(dataList->at(0)))
return dataList->at(0).left(8);
else
return "";
}
+10 -6
View File
@@ -37,6 +37,7 @@ public:
quint16 block_size;
quint8 blk[40];
quint8 blks[40];
QString typeText;
};
enum AccessType
@@ -66,14 +67,15 @@ public:
QString info(bool isRequiringOutput = false);
void chk();
void nested();
void darkside();
void hardnested();
void sniff();
void snoop();
void sniff14a();
void list();
void readOne(TargetType targetType = TARGET_MIFARE);
void readSelected(TargetType targetType = TARGET_MIFARE);
void writeOne(TargetType targetType = TARGET_MIFARE);
QList<int> writeSelected(TargetType targetType = TARGET_MIFARE);
void writeSelected(TargetType targetType = TARGET_MIFARE);
void dump();
void restore();
@@ -106,8 +108,10 @@ public:
void saveSniff(const QString& file);
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 bool data_isACBitsValid(const QString& text, QList<quint8> *returnHalfBytes = nullptr);
QString data_getUID();
public slots:
signals:
@@ -124,9 +128,9 @@ private:
QRegularExpression* keyPattern;
QString bin2text(const QByteArray& buff, int start, int length);
QString _readblk(int blockId, KeyType keyType, const QString &key, TargetType targetType = TARGET_MIFARE, int waitTime = 300);
QStringList _readsec(int sectorId, KeyType keyType, const QString &key, TargetType targetType = TARGET_MIFARE, int waitTime = 300);
bool _writeblk(int blockId, KeyType keyType, const QString &key, const QString &data, TargetType targetType = TARGET_MIFARE, int waitTime = 300);
QString _readblk(int blockId, KeyType keyType, const QString& key, TargetType targetType = TARGET_MIFARE, int waitTime = 300);
QStringList _readsec(int sectorId, KeyType keyType, const QString& key, TargetType targetType = TARGET_MIFARE, int waitTime = 300);
bool _writeblk(int blockId, KeyType keyType, const QString& key, const QString& data, TargetType targetType = TARGET_MIFARE, int waitTime = 300);
};
#endif // MIFARE_H
+440 -68
View File
@@ -6,8 +6,15 @@ MainWindow::MainWindow(QWidget *parent):
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
dockAllWindows = new QAction(tr("Dock all windows"), this);
myInfo = new QAction("wh201906", this);
currVersion = new QAction(tr("Ver: ") + QApplication::applicationVersion().section('.', 0, -2), this); // ignore the 4th version number
checkUpdate = new QAction(tr("Check Update"), this);
connect(dockAllWindows, &QAction::triggered, [ = ]()
{
for(int i = 0; i < dockList.size(); i++)
dockList[i]->setFloating(false);
});
connect(myInfo, &QAction::triggered, [ = ]()
{
QDesktopServices::openUrl(QUrl("https://github.com/wh201906"));
@@ -16,18 +23,40 @@ MainWindow::MainWindow(QWidget *parent):
{
QDesktopServices::openUrl(QUrl("https://github.com/wh201906/Proxmark3GUI/releases"));
});
this->addAction(myInfo);
this->addAction(checkUpdate);
settings = new QSettings("GUIsettings.ini", QSettings::IniFormat);
settings->setIniCodec("UTF-8");
pm3Thread = new QThread(this);
pm3 = new PM3Process(pm3Thread);
pm3Thread->start();
pm3state = false;
clientWorkingDir = new QDir;
util = new Util(this);
Util::setUI(ui);
mifare = new Mifare(ui, util, this);
lf = new LF(ui, util, this);
keyEventFilter = new MyEventFilter(QEvent::KeyPress);
resizeEventFilter = new MyEventFilter(QEvent::Resize);
// hide unused tabs
// ui->funcTab->removeTab(1);
ui->funcTab->removeTab(2);
portSearchTimer = new QTimer(this);
portSearchTimer->setInterval(2000);
connect(portSearchTimer, &QTimer::timeout, this, &MainWindow::on_portSearchTimer_timeout);
portSearchTimer->start();
contextMenu = new QMenu();
contextMenu->addAction(dockAllWindows);
contextMenu->addSeparator();
contextMenu->addAction(myInfo);
currVersion->setEnabled(false);
contextMenu->addAction(currVersion);
contextMenu->addAction(checkUpdate);
}
@@ -47,56 +76,98 @@ void MainWindow::initUI() // will be called by main.app
uiInit();
signalInit();
setState(false);
dockInit();
}
// ******************** basic functions ********************
void MainWindow::on_PM3_refreshPortButton_clicked()
void MainWindow::on_portSearchTimer_timeout()
{
ui->PM3_portBox->clear();
QSerialPort serial;
QStringList serialList;
QStringList newPortList;
foreach(const QSerialPortInfo &info, QSerialPortInfo::availablePorts())
{
qDebug() << info.isBusy() << info.isNull() << info.portName();
serial.setPort(info);
if(serial.open(QIODevice::ReadWrite))
{
serialList << info.portName();
serial.close();
// qDebug() << info.isBusy() << info.isNull() << info.portName() << info.description();
if(!info.isNull())
newPortList << info.portName();
}
}
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()
{
qDebug() << "Main:" << QThread::currentThread();
QString port = ui->PM3_portBox->currentText();
if(port == "")
QMessageBox::information(NULL, tr("Info"), tr("Plz choose a port first"), QMessageBox::Ok);
else
QString startArgs = ui->Set_Client_startArgsEdit->text();
// on RRG repo, if no port is specified, the client will search the available port
if(port == "" && startArgs.contains("<port>")) // has <port>, no port
{
saveClientPath(ui->PM3_pathEdit->text());
emit connectPM3(ui->PM3_pathEdit->text(), port);
QMessageBox::information(NULL, tr("Info"), tr("Plz choose a port first"), QMessageBox::Ok);
return;
}
if(!startArgs.contains("<port>")) // no <port>
port = ""; // a symbol
QStringList args = startArgs.replace("<port>", port).split(' ');
saveClientPath(ui->PM3_pathEdit->text());
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);
clientWorkingDir->setPath(QApplication::applicationDirPath());
qDebug() << clientWorkingDir->absolutePath();
clientWorkingDir->mkpath(ui->Set_Client_workingDirEdit->text());
qDebug() << clientWorkingDir->absolutePath();
clientWorkingDir->cd(ui->Set_Client_workingDirEdit->text());
qDebug() << clientWorkingDir->absolutePath();
emit setWorkingDir(clientWorkingDir->absolutePath());
emit connectPM3(ui->PM3_pathEdit->text(), args);
if(port != "" && !keepClientActive)
emit setSerialListener(port, true);
else if(!keepClientActive)
emit setSerialListener(false);
}
void MainWindow::onPM3StateChanged(bool st, QString info)
void MainWindow::onPM3StateChanged(bool st, const QString& info)
{
pm3state = st;
setState(st);
if(st == true)
{
portSearchTimer->stop();
setStatusBar(PM3VersionBar, info);
setStatusBar(connectStatusBar, tr("Connected"));
}
else
{
portSearchTimer->start();
setStatusBar(PM3VersionBar, "");
setStatusBar(connectStatusBar, tr("Not Connected"));
}
@@ -104,31 +175,43 @@ void MainWindow::onPM3StateChanged(bool st, QString info)
void MainWindow::on_PM3_disconnectButton_clicked()
{
pm3state = false;
setState(false);
emit killPM3();
emit setSerialListener("", false);
setStatusBar(connectStatusBar, tr("Not Connected"));
emit setSerialListener(false);
}
void MainWindow::refreshOutput(const QString& output)
{
// qDebug() << "MainWindow::refresh:" << output;
ui->Raw_outputEdit->insertPlainText(output);
ui->Raw_outputEdit->appendPlainText(output);
ui->Raw_outputEdit->moveCursor(QTextCursor::End);
}
void MainWindow::refreshCMD(const QString& cmd)
void MainWindow::on_stopButton_clicked()
{
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);
if(!pm3state)
on_PM3_disconnectButton_clicked();
else
{
on_PM3_disconnectButton_clicked();
for(int i = 0; i < 10; i++)
{
util->delay(200);
if(!pm3state)
break;
}
emit reconnectPM3();
emit setSerialListener(!keepClientActive);
}
}
// *********************************************************
// ******************** raw command ********************
void MainWindow::on_Raw_CMDEdit_textChanged(const QString &arg1)
{
stashedCMDEditText = arg1;
}
void MainWindow::on_Raw_sendCMDButton_clicked()
{
util->execCMD(ui->Raw_CMDEdit->text());
@@ -173,17 +256,81 @@ void MainWindow::sendMSG() // send command when pressing Enter
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_keyPressed(QObject* obj_addr, QEvent& event)
{
if(event.type() == QEvent::KeyPress)
{
QKeyEvent& keyEvent = static_cast<QKeyEvent&>(event);
if(obj_addr == ui->Raw_CMDEdit)
{
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);
}
}
else if(obj_addr == ui->Raw_outputEdit)
{
if(keyEvent.key() == Qt::Key_Up || keyEvent.key() == Qt::Key_Down)
ui->Raw_CMDEdit->setFocus();
}
}
}
// *****************************************************
// ******************** mifare ********************
void MainWindow::MF_onTypeChanged(int id, bool st)
void MainWindow::on_MF_keyWidget_resized(QObject* obj_addr, QEvent& event)
{
typeBtnGroup->blockSignals(true);
qDebug() << id << typeBtnGroup->checkedId();
if(obj_addr == ui->MF_keyWidget && event.type() == QEvent::Resize)
{
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)
{
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);
}
@@ -194,7 +341,7 @@ void MainWindow::MF_onTypeChanged(int id, bool st)
if(result == QMessageBox::Yes)
{
qDebug() << "Yes";
mifare->setCardType(typeBtnGroup->checkedId());
mifare->setCardType(MFCardTypeBtnGroup->checkedId());
MF_widgetReset();
mifare->data_syncWithDataWidget();
mifare->data_syncWithKeyWidget();
@@ -202,10 +349,10 @@ void MainWindow::MF_onTypeChanged(int id, bool st)
else
{
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)
@@ -489,11 +636,15 @@ void MainWindow::on_MF_File_saveButton_clicked()
QString title = "";
QString filename = "";
QString selectedType = "";
QString defaultName = mifare->data_getUID();
if(defaultName != "")
defaultName += "_";
defaultName += QDateTime::currentDateTime().toString("yyyy-MM-dd-hh-mm-ss");
if(ui->MF_File_dataBox->isChecked())
{
title = tr("Plz select the location to save data file:");
filename = QFileDialog::getSaveFileName(this, title, "./", tr("Binary Data Files(*.bin *.dump);;Text Data Files(*.txt *.eml)"), &selectedType);
filename = QFileDialog::getSaveFileName(this, title, "./data_" + defaultName, tr("Binary Data Files(*.bin *.dump);;Text Data Files(*.txt *.eml)"), &selectedType);
qDebug() << filename;
if(filename != "")
{
@@ -506,7 +657,7 @@ void MainWindow::on_MF_File_saveButton_clicked()
else if(ui->MF_File_keyBox->isChecked())
{
title = tr("Plz select the location to save key file:");
filename = QFileDialog::getSaveFileName(this, title, "./", tr("Binary Key Files(*.bin *.dump)"), &selectedType);
filename = QFileDialog::getSaveFileName(this, title, "./key_" + defaultName, tr("Binary Key Files(*.bin *.dump)"), &selectedType);
qDebug() << filename;
if(filename != "")
{
@@ -580,9 +731,8 @@ void MainWindow::on_MF_RW_writeBlockButton_clicked()
void MainWindow::on_MF_RW_writeSelectedButton_clicked()
{
QList<int> failedBlocks;
setState(false);
failedBlocks = mifare->writeSelected(Mifare::TARGET_MIFARE);
mifare->writeSelected(Mifare::TARGET_MIFARE);
setState(true);
}
@@ -612,9 +762,8 @@ void MainWindow::on_MF_UID_readBlockButton_clicked()
void MainWindow::on_MF_UID_writeSelectedButton_clicked()
{
QList<int> failedBlocks;
setState(false);
failedBlocks = mifare->writeSelected(Mifare::TARGET_UID);
mifare->writeSelected(Mifare::TARGET_UID);
setState(true);
}
@@ -672,9 +821,8 @@ void MainWindow::on_MF_Sim_readSelectedButton_clicked()
void MainWindow::on_MF_Sim_writeSelectedButton_clicked()
{
QList<int> failedBlocks;
setState(false);
failedBlocks = mifare->writeSelected(Mifare::TARGET_EMULATOR);
mifare->writeSelected(Mifare::TARGET_EMULATOR);
setState(true);
}
@@ -739,10 +887,10 @@ void MainWindow::on_MF_Sniff_sniffButton_clicked()
setState(true);
}
void MainWindow::on_MF_Sniff_snoopButton_clicked()
void MainWindow::on_MF_14aSniff_snoopButton_clicked()
{
setState(false);
mifare->snoop();
mifare->sniff14a();
setState(true);
}
@@ -755,6 +903,7 @@ void MainWindow::MF_widgetReset()
{
int secs = mifare->cardType.sector_size;
int blks = mifare->cardType.block_size;
QBrush trailerItemForeColor = QBrush(QColor(0, 160, 255));
ui->MF_RW_blockBox->clear();
ui->MF_keyWidget->setRowCount(secs);
ui->MF_dataWidget->setRowCount(blks);
@@ -779,8 +928,10 @@ void MainWindow::MF_widgetReset()
setTableItem(ui->MF_keyWidget, i, 1, "");
setTableItem(ui->MF_keyWidget, i, 2, "");
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(0, 2)->setForeground(QBrush(QColor(255, 160, 0)));
ui->MF_selectAllBox->setCheckState(Qt::Checked);
ui->MF_selectTrailerBox->setCheckState(Qt::Checked);
@@ -796,43 +947,46 @@ void MainWindow::MF_widgetReset()
void MainWindow::uiInit()
{
connect(ui->Raw_CMDEdit, &QLineEdit::editingFinished, this, &MainWindow::sendMSG);
connect(ui->Raw_CMDEdit, &QLineEdit::returnPressed, this, &MainWindow::sendMSG);
ui->Raw_CMDEdit->installEventFilter(keyEventFilter);
connect(keyEventFilter, &MyEventFilter::eventHappened, this, &MainWindow::on_Raw_keyPressed);
ui->MF_keyWidget->installEventFilter(resizeEventFilter);
connect(resizeEventFilter, &MyEventFilter::eventHappened, this, &MainWindow::on_MF_keyWidget_resized);
ui->Raw_outputEdit->installEventFilter(keyEventFilter);
connectStatusBar = new QLabel(this);
programStatusBar = new QLabel(this);
PM3VersionBar = new QLabel(this);
stopButton = new QPushButton(this);
setStatusBar(connectStatusBar, tr("Not Connected"));
setStatusBar(programStatusBar, tr("Idle"));
setStatusBar(PM3VersionBar, "");
stopButton->setText(tr("Stop"));
ui->statusbar->addPermanentWidget(PM3VersionBar, 1);
ui->statusbar->addPermanentWidget(connectStatusBar, 1);
ui->statusbar->addPermanentWidget(programStatusBar, 1);
ui->statusbar->addPermanentWidget(stopButton);
ui->MF_dataWidget->setColumnCount(3);
ui->MF_dataWidget->setHorizontalHeaderItem(0, new QTableWidgetItem(tr("Sec")));
ui->MF_dataWidget->setHorizontalHeaderItem(1, new QTableWidgetItem(tr("Blk")));
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(1, 55);
ui->MF_dataWidget->setColumnWidth(2, 430);
ui->MF_keyWidget->setColumnCount(3);
ui->MF_keyWidget->setHorizontalHeaderItem(0, new QTableWidgetItem(tr("Sec")));
ui->MF_keyWidget->setHorizontalHeaderItem(1, new QTableWidgetItem(tr("KeyA")));
ui->MF_keyWidget->setHorizontalHeaderItem(2, new QTableWidgetItem(tr("KeyB")));
ui->MF_keyWidget->verticalHeader()->setVisible(false);
ui->MF_keyWidget->setColumnWidth(0, 35);
ui->MF_keyWidget->setColumnWidth(1, 115);
ui->MF_keyWidget->setColumnWidth(2, 115);
ui->MF_keyWidget->setColumnWidth(0, 45);
MF_widgetReset();
typeBtnGroup = new QButtonGroup(this);
typeBtnGroup->addButton(ui->MF_Type_miniButton, 0);
typeBtnGroup->addButton(ui->MF_Type_1kButton, 1);
typeBtnGroup->addButton(ui->MF_Type_2kButton, 2);
typeBtnGroup->addButton(ui->MF_Type_4kButton, 4);
connect(typeBtnGroup, QOverload<int, bool>::of(&QButtonGroup::buttonToggled), this, &MainWindow::MF_onTypeChanged);
MFCardTypeBtnGroup = new QButtonGroup(this);
MFCardTypeBtnGroup->addButton(ui->MF_Type_miniButton, 0);
MFCardTypeBtnGroup->addButton(ui->MF_Type_1kButton, 1);
MFCardTypeBtnGroup->addButton(ui->MF_Type_2kButton, 2);
MFCardTypeBtnGroup->addButton(ui->MF_Type_4kButton, 4);
connect(MFCardTypeBtnGroup, QOverload<int, bool>::of(&QButtonGroup::buttonToggled), this, &MainWindow::MF_onMFCardTypeChanged);
ui->MF_keyWidget->installEventFilter(this);
ui->MF_dataWidget->installEventFilter(this);
@@ -840,7 +994,7 @@ void MainWindow::uiInit()
settings->beginGroup("UI_grpbox_preference");
QStringList boxNames = settings->allKeys();
QGroupBox* boxptr;
QGroupBox * boxptr;
foreach(QString name, boxNames)
{
boxptr = this->findChild<QGroupBox*>(name);
@@ -863,11 +1017,30 @@ void MainWindow::uiInit()
ui->PM3_pathEdit->setText(settings->value("path", "proxmark3").toString());
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_keepClientActive");
keepClientActive = settings->value("state", false).toBool();
ui->Set_Client_keepClientActiveBox->setChecked(keepClientActive);
settings->endGroup();
settings->beginGroup("Client_Env");
ui->Set_Client_envScriptEdit->setText(settings->value("scriptPath").toString());
ui->Set_Client_workingDirEdit->setText(settings->value("workingDir", "../data").toString());
settings->endGroup();
ui->MF_RW_keyTypeBox->addItem("A", Mifare::KEY_A);
ui->MF_RW_keyTypeBox->addItem("B", Mifare::KEY_B);
on_Raw_CMDHistoryBox_stateChanged(Qt::Unchecked);
on_PM3_refreshPortButton_clicked();
}
void MainWindow::signalInit()
@@ -877,8 +1050,14 @@ void MainWindow::signalInit()
connect(util, &Util::refreshOutput, this, &MainWindow::refreshOutput);
connect(this, &MainWindow::connectPM3, pm3, &PM3Process::connectPM3);
connect(this, &MainWindow::reconnectPM3, pm3, &PM3Process::reconnectPM3);
connect(pm3, &PM3Process::PM3StatedChanged, this, &MainWindow::onPM3StateChanged);
connect(this, &MainWindow::killPM3, pm3, &PM3Process::kill);
connect(pm3, &PM3Process::PM3StatedChanged, util, &Util::setRunningState);
connect(this, &MainWindow::killPM3, pm3, &PM3Process::killPM3);
connect(this, &MainWindow::setProcEnv, pm3, &PM3Process::setProcEnv);
connect(this, &MainWindow::setWorkingDir, pm3, &PM3Process::setWorkingDir);
connect(this, QOverload<bool>::of(&MainWindow::setSerialListener), pm3, QOverload<bool>::of(&PM3Process::setSerialListener));
connect(this, QOverload<const QString&, bool>::of(&MainWindow::setSerialListener), pm3, QOverload<const QString&, bool>::of(&PM3Process::setSerialListener));
connect(util, &Util::write, pm3, &PM3Process::write);
@@ -889,9 +1068,11 @@ void MainWindow::signalInit()
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_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)
target->setText(tr("HW Version:") + text);
@@ -901,14 +1082,14 @@ void MainWindow::setStatusBar(QLabel* target, const QString & 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)
widget->setItem(row, column, new QTableWidgetItem());
widget->item(row, column)->setText(text);
}
bool MainWindow::eventFilter(QObject *watched, QEvent *event) // drag support
bool MainWindow::eventFilter(QObject * watched, QEvent * event) // drag support
{
if(event->type() == QEvent::DragEnter)
{
@@ -959,6 +1140,11 @@ void MainWindow::setState(bool st)
{
setStatusBar(programStatusBar, tr("Idle"));
}
setButtonsEnabled(st || keepButtonsEnabled);
}
void MainWindow::setButtonsEnabled(bool st)
{
ui->MF_attackGroupBox->setEnabled(st);
ui->MF_normalGroupBox->setEnabled(st);
ui->MF_UIDGroupBox->setEnabled(st);
@@ -966,6 +1152,8 @@ void MainWindow::setState(bool st)
ui->MF_sniffGroupBox->setEnabled(st);
ui->Raw_CMDEdit->setEnabled(st);
ui->Raw_sendCMDButton->setEnabled(st);
ui->LF_configGroupBox->setEnabled(st);
ui->LF_operationGroupBox->setEnabled(st);
}
void MainWindow::on_GroupBox_clicked(bool checked)
@@ -993,3 +1181,187 @@ void MainWindow::saveClientPath(const QString& path)
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();
}
void MainWindow::on_Set_Client_saveWorkingDirButton_clicked()
{
settings->beginGroup("Client_Env");
settings->setValue("workingDir", ui->Set_Client_workingDirEdit->text());
settings->endGroup();
}
void MainWindow::on_Set_Client_keepClientActiveBox_stateChanged(int arg1)
{
settings->beginGroup("Client_keepClientActive");
keepClientActive = (arg1 == Qt::Checked);
settings->setValue("state", keepClientActive);
settings->endGroup();
emit setSerialListener(!keepClientActive);
}
void MainWindow::on_LF_Conf_freqSlider_valueChanged(int value)
{
onLFfreqConfChanged(value, true);
}
void MainWindow::onLFfreqConfChanged(int value, bool isCustomized)
{
ui->LF_Conf_freqDivisorBox->blockSignals(true);
ui->LF_Conf_freqSlider->blockSignals(true);
if(isCustomized)
ui->LF_Conf_freqOtherButton->setChecked(true);
ui->LF_Conf_freqLabel->setText(tr("Actural Freq: ") + QString("%1kHz").arg(LF::divisor2Freq(value), 0, 'f', 3));
ui->LF_Conf_freqDivisorBox->setValue(value);
ui->LF_Conf_freqSlider->setValue(value);
ui->LF_Conf_freqDivisorBox->blockSignals(false);
ui->LF_Conf_freqSlider->blockSignals(false);
}
void MainWindow::on_LF_Conf_freqDivisorBox_valueChanged(int arg1)
{
onLFfreqConfChanged(arg1, true);
}
void MainWindow::on_LF_Conf_freq125kButton_clicked()
{
onLFfreqConfChanged(95, false);
}
void MainWindow::on_LF_Conf_freq134kButton_clicked()
{
onLFfreqConfChanged(88, false);
}
void MainWindow::on_LF_Op_searchButton_clicked()
{
setState(false);
lf->search();
setState(true);
}
void MainWindow::on_LF_Op_readButton_clicked()
{
setState(false);
lf->read();
setState(true);
}
void MainWindow::on_LF_Op_tuneButton_clicked()
{
setState(false);
lf->tune();
setState(true);
}
void MainWindow::on_LF_Op_sniffButton_clicked()
{
setState(false);
lf->sniff();
setState(true);
}
void MainWindow::dockInit()
{
setDockNestingEnabled(true);
QDockWidget* dock;
QWidget* widget;
int count = ui->funcTab->count();
qDebug() << "dock count" << count;
for(int i = 0; i < count; i++)
{
dock = new QDockWidget(ui->funcTab->tabText(0), this);
qDebug() << "dock name" << ui->funcTab->tabText(0);
dock->setFeatures(QDockWidget::DockWidgetFloatable | QDockWidget::DockWidgetMovable);// movable is necessary, otherwise the dock cannot be dragged
dock->setAllowedAreas(Qt::BottomDockWidgetArea);
dock->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
widget = ui->funcTab->widget(0);
dock->setWidget(widget);
if(widget->objectName() == "rawTab")
Util::setRawTab(dock, i);
addDockWidget(Qt::BottomDockWidgetArea, dock);
if(!dockList.isEmpty())
tabifyDockWidget(dockList[0], dock);
dockList.append(dock);
}
ui->funcTab->setVisible(false);
dockList[0]->setVisible(true);
dockList[0]->raise();
}
void MainWindow::contextMenuEvent(QContextMenuEvent *event)
{
contextMenu->exec(event->globalPos());
}
void MainWindow::on_LF_Conf_getButton_clicked()
{
setState(false);
lf->getConfig();
setState(true);
}
void MainWindow::on_LF_Conf_setButton_clicked()
{
LF::Config config;
setState(false);
config.divisor = ui->LF_Conf_freqDivisorBox->value();
config.bitPerSample = ui->LF_Conf_bitPerSampleBox->value();
config.decimation = ui->LF_Conf_decimationBox->value();
config.averaging = ui->LF_Conf_averagingBox->isChecked();
config.triggerThreshold = ui->LF_Conf_thresholdBox->value();
config.samplesToSkip = ui->LF_Conf_skipsBox->value();
lf->setConfig(config);
Util::gotoRawTab();
setState(true);
}
void MainWindow::on_LF_Conf_resetButton_clicked()
{
setState(false);
lf->resetConfig();
setState(true);
}
+94 -14
View File
@@ -19,9 +19,18 @@
#include <QGroupBox>
#include <QSizePolicy>
#include <QSettings>
#include <QPushButton>
#include <QProcessEnvironment>
#include <QScrollBar>
#include <QTimer>
#include <QDateTime>
#include <QDockWidget>
#include <QMenu>
#include "common/myeventfilter.h"
#include "common/pm3process.h"
#include "module/mifare.h"
#include "module/lf.h"
#include "common/util.h"
#include "ui/mf_trailerdecoderdialog.h"
@@ -43,11 +52,13 @@ public:
void initUI();
bool eventFilter(QObject *watched, QEvent *event);
public slots:
void refreshOutput(const QString &output);
void refreshCMD(const QString &cmd);
void setStatusBar(QLabel* target, const QString & text);
void onPM3StateChanged(bool st, QString info);
void MF_onTypeChanged(int id, bool st);
void refreshOutput(const QString& output);
void refreshCMD(const QString& cmd);
void setStatusBar(QLabel* target, const QString& text);
void onPM3StateChanged(bool st, const QString& info);
void MF_onMFCardTypeChanged(int id, bool st);
void on_Raw_keyPressed(QObject *obj_addr, QEvent &event);
void on_MF_keyWidget_resized(QObject *obj_addr, QEvent &event);
private slots:
void on_PM3_connectButton_clicked();
@@ -59,7 +70,8 @@ private slots:
void on_Raw_clearOutputButton_clicked();
void sendMSG();
void on_PM3_refreshPortButton_clicked();
void on_portSearchTimer_timeout();
void on_Raw_CMDHistoryBox_stateChanged(int arg1);
@@ -87,7 +99,6 @@ private slots:
void on_MF_RW_writeSelectedButton_clicked();
void on_MF_RW_dumpButton_clicked();
void on_MF_RW_restoreButton_clicked();
@@ -142,42 +153,111 @@ private slots:
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_selectTrailerBox_stateChanged(int arg1);
void on_stopButton_clicked();
void on_Raw_CMDEdit_textChanged(const QString &arg1);
void on_MF_Attack_darksideButton_clicked();
void on_Set_Client_startArgsEdit_editingFinished();
void on_Set_Client_forceEnabledBox_stateChanged(int arg1);
void on_Set_GUI_setLanguageButton_clicked();
void setButtonsEnabled(bool st);
void on_PM3_refreshPortButton_clicked();
void on_Set_Client_envScriptEdit_editingFinished();
void on_Set_Client_saveWorkingDirButton_clicked();
void on_Set_Client_keepClientActiveBox_stateChanged(int arg1);
void on_LF_Conf_freqSlider_valueChanged(int value);
void on_LF_Conf_freqDivisorBox_valueChanged(int arg1);
void on_LF_Conf_freq125kButton_clicked();
void on_LF_Conf_freq134kButton_clicked();
void on_LF_Op_searchButton_clicked();
void on_LF_Op_readButton_clicked();
void on_LF_Op_tuneButton_clicked();
void on_LF_Op_sniffButton_clicked();
void on_LF_Conf_getButton_clicked();
void on_LF_Conf_setButton_clicked();
void on_LF_Conf_resetButton_clicked();
private:
Ui::MainWindow* ui;
QButtonGroup* typeBtnGroup;
QButtonGroup* MFCardTypeBtnGroup;
QLabel* connectStatusBar;
QLabel* programStatusBar;
QLabel* PM3VersionBar;
QPushButton* stopButton;
QAction* dockAllWindows;
QAction* myInfo;
QAction* currVersion;
QAction* checkUpdate;
QSettings* settings;
MyEventFilter* keyEventFilter;
MyEventFilter* resizeEventFilter;
QString stashedCMDEditText;
int stashedIndex = -1;
void uiInit();
PM3Process* pm3;
bool pm3state;
bool keepButtonsEnabled;
bool keepClientActive;
QThread* pm3Thread;
QTimer* portSearchTimer;
QStringList portList;
QStringList clientEnv;
QDir* clientWorkingDir;
Mifare* mifare;
LF* lf;
Util* util;
QList<QDockWidget*> dockList;
QMenu* contextMenu;
MF_trailerDecoderDialog* decDialog;
void signalInit();
void MF_widgetReset();
void setTableItem(QTableWidget *widget, int row, int column, const QString &text);
void setTableItem(QTableWidget *widget, int row, int column, const QString& text);
void setState(bool st);
void saveClientPath(const QString &path);
void saveClientPath(const QString& path);
void onLFfreqConfChanged(int value, bool isCustomized);
void dockInit();
protected:
void contextMenuEvent(QContextMenuEvent *event) override;
signals:
void connectPM3(const QString path, const QString port);
void connectPM3(const QString& path, const QStringList args);
void reconnectPM3();
void killPM3();
void setSerialListener(const QString &name, bool state);
void setSerialListener(bool state);
void setSerialListener(const QString& name, bool state);
void setProcEnv(const QStringList *env);
void setWorkingDir(const QString& dir);
};
#endif // MAINWINDOW_H
+999 -15
View File
File diff suppressed because it is too large Load Diff
+12
View File
@@ -21,6 +21,18 @@ MF_Attack_hardnestedDialog::~MF_Attack_hardnestedDialog()
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 "
+ ui->knownKeySectorBox->currentText()
+ " "
+4 -2
View File
@@ -2,8 +2,10 @@
#define MF_ATTACK_HARDNESTEDDIALOG_H
#include <QDialog>
#include "common/util.h"
namespace Ui {
namespace Ui
{
class MF_Attack_hardnestedDialog;
}
@@ -19,7 +21,7 @@ public:
private:
Ui::MF_Attack_hardnestedDialog *ui;
signals:
void sendCMD(QString cmd);
void sendCMD(const QString& cmd);
private slots:
void on_buttonBox_accepted();
};
+38 -1
View File
@@ -1,12 +1,34 @@
#include "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),
ui(new Ui::MF_Sim_simDialog)
{
ui->setupUi(this);
if(Util::getClientType() == Util::CLIENTTYPE_OFFICIAL)
{
ui->atqaGroupBox->setVisible(false);
ui->atqaLine->setVisible(false);
ui->sakGroupBox->setVisible(false);
ui->sakLine->setVisible(false);
ui->vGroupBox->setVisible(false);
ui->vLine->setVisible(false);
}
else if(Util::getClientType() == Util::CLIENTTYPE_ICEMAN)
{
ui->fGroupBox->setVisible(false);
ui->fLine->setVisible(false);
ui->rGroupBox->setVisible(false);
ui->rLine->setVisible(false);
ui->uBox->setText("-u");
ui->nBox->setText("-n");
ui->iBox->setText("-i");
ui->xBox->setText("--crack");
ui->eBox->setText("-e");
}
this->cardType = cardType;
this->cardTypeText = cardTypeText;
}
MF_Sim_simDialog::~MF_Sim_simDialog()
@@ -55,6 +77,8 @@ void MF_Sim_simDialog::on_fBox_clicked(bool checked)
void MF_Sim_simDialog::on_buttonBox_accepted()
{
QString paras;
if(Util::getClientType() == Util::CLIENTTYPE_OFFICIAL)
{
paras += (ui->uBox->isChecked() ? "u " + ui->uEdit->text() + " " : "");
paras += (ui->nBox->isChecked() ? "n " + ui->nEdit->text() + " " : "");
paras += (ui->iBox->isChecked() ? "i " : "");
@@ -63,4 +87,17 @@ void MF_Sim_simDialog::on_buttonBox_accepted()
paras += (ui->fBox->isChecked() ? "f " + ui->fEdit->text() + " " : "");
paras += (ui->rBox->isChecked() ? "r " : "");
emit sendCMD(QString("hf mf sim ") + "*" + QString::number(cardType) + " " + paras.trimmed());
}
else if(Util::getClientType() == Util::CLIENTTYPE_ICEMAN)
{
paras += (ui->uBox->isChecked() ? "-u " + ui->uEdit->text() + " " : "");
paras += (ui->atqaBox->isChecked() ? "--atqa " + ui->atqaEdit->text() + " " : "");
paras += (ui->sakBox->isChecked() ? "--sak " + ui->sakEdit->text() + " " : "");
paras += (ui->nBox->isChecked() ? "-n " + ui->nEdit->text() + " " : "");
paras += (ui->iBox->isChecked() ? "-i " : "");
paras += (ui->xBox->isChecked() ? "--crack " : "");
paras += (ui->eBox->isChecked() ? "-e " : "");
paras += (ui->vBox->isChecked() ? "-v " : "");
emit sendCMD(QString("hf mf sim --") + cardTypeText + " " + paras.trimmed());
}
}
+4 -2
View File
@@ -3,6 +3,7 @@
#include <QDialog>
#include <QDebug>
#include "common/util.h"
namespace Ui
{
@@ -14,7 +15,7 @@ class MF_Sim_simDialog : public QDialog
Q_OBJECT
public:
explicit MF_Sim_simDialog(int cardType, QWidget *parent = nullptr);
explicit MF_Sim_simDialog(int cardType, QString cardTypeText, QWidget *parent = nullptr);
~MF_Sim_simDialog();
private slots:
@@ -25,8 +26,9 @@ private slots:
private:
Ui::MF_Sim_simDialog *ui;
int cardType;
QString cardTypeText;
signals:
void sendCMD(QString cmd);
void sendCMD(const QString& cmd);
private slots:
void on_buttonBox_accepted();
};
+310 -21
View File
@@ -7,30 +7,31 @@
<x>0</x>
<y>0</y>
<width>461</width>
<height>456</height>
<height>524</height>
</rect>
</property>
<property name="windowTitle">
<string>Simulate</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QGroupBox" name="uGroupBox">
<layout class="QHBoxLayout" name="uLayout">
<property name="spacing">
<number>5</number>
</property>
<property name="leftMargin">
<number>5</number>
<number>0</number>
</property>
<property name="topMargin">
<number>5</number>
<number>0</number>
</property>
<property name="rightMargin">
<number>5</number>
<number>0</number>
</property>
<property name="bottomMargin">
<number>5</number>
<number>0</number>
</property>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QCheckBox" name="uBox">
<property name="text">
@@ -71,16 +72,167 @@
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="Line" name="line_6">
<widget class="Line" name="uLine">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</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>
<widget class="QCheckBox" name="nBox">
<property name="text">
@@ -121,16 +273,33 @@
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="Line" name="line_5">
<widget class="Line" name="nLine">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</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>
<widget class="QCheckBox" name="iBox">
<property name="text">
@@ -155,16 +324,33 @@
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="Line" name="line_4">
<widget class="Line" name="iLine">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</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>
<widget class="QCheckBox" name="xBox">
<property name="text">
@@ -189,16 +375,33 @@
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="Line" name="line_3">
<widget class="Line" name="xLine">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</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>
<widget class="QCheckBox" name="eBox">
<property name="text">
@@ -215,7 +418,7 @@
</sizepolicy>
</property>
<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 name="wordWrap">
<bool>true</bool>
@@ -223,16 +426,33 @@
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="Line" name="line_2">
<widget class="Line" name="eLine">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</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>
<widget class="QCheckBox" name="fBox">
<property name="text">
@@ -273,16 +493,33 @@
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="Line" name="line">
<widget class="Line" name="fLine">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</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>
<widget class="QCheckBox" name="rBox">
<property name="text">
@@ -307,9 +544,61 @@
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="Line" name="line_7">
<widget class="Line" name="rLine">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<widget class="QGroupBox" name="vGroupBox">
<layout class="QHBoxLayout" name="vLayout">
<property name="spacing">
<number>5</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QCheckBox" name="vBox">
<property name="text">
<string>-v</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_11">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>verbose output</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="Line" name="vLine">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
+5 -5
View File
@@ -15,10 +15,10 @@ MF_trailerDecoderDialog::MF_trailerDecoderDialog(QWidget *parent) :
sizeGroup->addButton(ui->size4Button, 4);
sizeGroup->addButton(ui->size16Button, 16);
connect(sizeGroup, QOverload<int, bool>::of(&QButtonGroup::buttonToggled), this, &MF_trailerDecoderDialog::on_blockSizeChanged);
connect(ui->C0Box, &QSpinBox::textChanged, this, &MF_trailerDecoderDialog::on_boxChanged);
connect(ui->C1Box, &QSpinBox::textChanged, this, &MF_trailerDecoderDialog::on_boxChanged);
connect(ui->C2Box, &QSpinBox::textChanged, this, &MF_trailerDecoderDialog::on_boxChanged);
connect(ui->C3Box, &QSpinBox::textChanged, this, &MF_trailerDecoderDialog::on_boxChanged);
connect(ui->C0Box, QOverload<int>::of(&QSpinBox::valueChanged), this, &MF_trailerDecoderDialog::on_boxChanged);
connect(ui->C1Box, QOverload<int>::of(&QSpinBox::valueChanged), this, &MF_trailerDecoderDialog::on_boxChanged);
connect(ui->C2Box, QOverload<int>::of(&QSpinBox::valueChanged), this, &MF_trailerDecoderDialog::on_boxChanged);
connect(ui->C3Box, QOverload<int>::of(&QSpinBox::valueChanged), this, &MF_trailerDecoderDialog::on_boxChanged);
ui->dataBlockWidget->setRowCount(3);
ui->dataBlockWidget->setColumnCount(4);
@@ -123,7 +123,7 @@ void MF_trailerDecoderDialog::setTableItem(QTableWidget* widget, int row, int co
widget->item(row, column)->setText(text);
}
void MF_trailerDecoderDialog::on_boxChanged(const QString &arg1)
void MF_trailerDecoderDialog::on_boxChanged()
{
quint8 ACBits[4];
ACBits[0] = ui->C0Box->value();
+2 -2
View File
@@ -23,11 +23,11 @@ public:
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_boxChanged(const QString &arg1);
void on_boxChanged();
private:
Ui::MF_trailerDecoderDialog *ui;
QRegularExpressionValidator* validator;
+8
View File
@@ -18,6 +18,14 @@ MF_UID_parameterDialog::~MF_UID_parameterDialog()
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 "
+ ui->UIDLineEdit->text()
+ " "
+4 -2
View File
@@ -2,8 +2,10 @@
#define MF_UID_PARAMETERDIALOG_H
#include <QDialog>
#include "common/util.h"
namespace Ui {
namespace Ui
{
class MF_UID_parameterDialog;
}
@@ -18,7 +20,7 @@ public:
private:
Ui::MF_UID_parameterDialog *ui;
signals:
void sendCMD(QString cmd);
void sendCMD(const QString& cmd);
private slots:
void on_buttonBox_accepted();
};