Compare commits
46 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| bac6207634 | |||
| ccb07651cc | |||
| f706d59c48 | |||
| 9e31496131 | |||
| a232e4ec83 | |||
| 1bec73d1ad | |||
| a8b1a4a82e | |||
| 03bb57ee58 | |||
| 15538a9892 | |||
| 466cd0ecc1 | |||
| 019afed198 | |||
| 799e00d66e | |||
| ae9e4d1a4f | |||
| c3aafc3d31 | |||
| fb8e1a6e1b | |||
| 90e4fde882 | |||
| 705c8de54c | |||
| aa6b93984c | |||
| 7f96c061dc | |||
| b8c4e8e339 | |||
| 4f10e3d75c | |||
| 63f3424871 | |||
| 24a6e1869b | |||
| 6baa09221e | |||
| 6e5f654cc5 | |||
| 83445c7eef | |||
| 5330ed8d14 | |||
| a56a503b23 | |||
| 77d8049738 | |||
| bf9b3fb076 | |||
| 6d3dd5056c | |||
| e687cc39fd | |||
| 3c3944d150 | |||
| 091b4f63d1 | |||
| 0c4220c9a5 | |||
| 986e9aacfe | |||
| ce262db52c | |||
| 73533608e6 | |||
| 2f38d3c8c5 | |||
| f2d00ee088 | |||
| 862f0775f8 | |||
| a7985c5c89 | |||
| a3e6aa787b | |||
| 1c273a6527 | |||
| 3f899845b7 | |||
| 475580c342 |
@@ -14,7 +14,6 @@
|
|||||||
*.so.*
|
*.so.*
|
||||||
*_pch.h.cpp
|
*_pch.h.cpp
|
||||||
*_resource.rc
|
*_resource.rc
|
||||||
*.qm
|
|
||||||
.#*
|
.#*
|
||||||
*.*#
|
*.*#
|
||||||
core
|
core
|
||||||
|
|||||||
@@ -16,9 +16,11 @@ DEFINES += QT_DEPRECATED_WARNINGS
|
|||||||
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
|
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
|
||||||
|
|
||||||
SOURCES += \
|
SOURCES += \
|
||||||
|
common/myeventfilter.cpp \
|
||||||
main.cpp \
|
main.cpp \
|
||||||
common/pm3process.cpp \
|
common/pm3process.cpp \
|
||||||
common/util.cpp \
|
common/util.cpp \
|
||||||
|
module/lf.cpp \
|
||||||
module/mifare.cpp \
|
module/mifare.cpp \
|
||||||
ui/mf_trailerdecoderdialog.cpp \
|
ui/mf_trailerdecoderdialog.cpp \
|
||||||
ui/mf_sim_simdialog.cpp \
|
ui/mf_sim_simdialog.cpp \
|
||||||
@@ -27,8 +29,10 @@ SOURCES += \
|
|||||||
ui/mf_attack_hardnesteddialog.cpp \
|
ui/mf_attack_hardnesteddialog.cpp \
|
||||||
|
|
||||||
HEADERS += \
|
HEADERS += \
|
||||||
|
common/myeventfilter.h \
|
||||||
common/pm3process.h \
|
common/pm3process.h \
|
||||||
common/util.h \
|
common/util.h \
|
||||||
|
module/lf.h \
|
||||||
module/mifare.h \
|
module/mifare.h \
|
||||||
ui/mf_trailerdecoderdialog.h \
|
ui/mf_trailerdecoderdialog.h \
|
||||||
ui/mf_sim_simdialog.h \
|
ui/mf_sim_simdialog.h \
|
||||||
@@ -52,7 +56,7 @@ qnx: target.path = /tmp/$${TARGET}/bin
|
|||||||
else: unix:!android: target.path = /opt/$${TARGET}/bin
|
else: unix:!android: target.path = /opt/$${TARGET}/bin
|
||||||
!isEmpty(target.path): INSTALLS += target
|
!isEmpty(target.path): INSTALLS += target
|
||||||
|
|
||||||
VERSION = 0.1.3
|
VERSION = 0.2.1
|
||||||
QMAKE_TARGET_PRODUCT = "Proxmark3GUI"
|
QMAKE_TARGET_PRODUCT = "Proxmark3GUI"
|
||||||
QMAKE_TARGET_DESCRIPTION = "Proxmark3GUI"
|
QMAKE_TARGET_DESCRIPTION = "Proxmark3GUI"
|
||||||
QMAKE_TARGET_COMPANY = "wh201906"
|
QMAKE_TARGET_COMPANY = "wh201906"
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
# Proxmark3GUI
|
# Proxmark3GUI
|
||||||
A GUI for [Proxmark3](https://github.com/Proxmark/proxmark3) client
|

|
||||||
|
|
||||||
[中文](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
|
+ Support binary(.bin .dump) files and text(.eml) files
|
||||||
+ Analyze Access Bits
|
+ Analyze Access Bits
|
||||||
+ Support Chinese Magic Card
|
+ Support Chinese Magic Card
|
||||||
|
+ Have basic support for LF commands
|
||||||
+ Customize UI
|
+ Customize UI
|
||||||
+ ...
|
+ ...
|
||||||
|
|
||||||
@@ -25,37 +28,73 @@ A GUI for [Proxmark3](https://github.com/Proxmark/proxmark3) client
|
|||||||
## Preview
|
## Preview
|
||||||

|

|
||||||
|
|
||||||
more previews [here](README/doc/previews.md)
|
[more previews](README/doc/previews.md)
|
||||||
|
|
||||||
***
|
***
|
||||||
|
|
||||||
## About Iceman fork/repo
|
## About Iceman fork/repo
|
||||||
|
|
||||||
The [Iceman fork/repo](https://github.com/RfidResearchGroup/proxmark3) has more powerful functions like offline sniff. These guys even developed a new hardware called Proxmark3 RDV4 with smart card support. But the official repo and the Iceman repo is not fully compatible.
|
The [Iceman fork/repo](https://github.com/RfidResearchGroup/proxmark3) has more powerful functions like offline sniff. These guys even developed a new hardware called Proxmark3 RDV4 with smart card support. But the official repo and the Iceman repo is not fully compatible.
|
||||||
This GUI was designed for only official repo at first, but I'm trying to make it compatible with Iceman repo.
|
This GUI is compatible with Iceman/RRG repo(tested on v4.9237)
|
||||||
|
|
||||||
Supported functions when using Iceman client:
|
|
||||||
|
|
||||||
[supported functions](README/doc/supported_Iceman.md)
|
|
||||||
|
|
||||||
***
|
***
|
||||||
|
|
||||||
## About Compiled Windows clients
|
## About Compiled Windows clients
|
||||||
|
|
||||||
A cool guy [Gator96100](https://github.com/Gator96100) creates [ProxSpace](https://github.com/Gator96100/ProxSpace) and makes it possible to compile both the firmware and client on Windows.
|
A cool guy [Gator96100](https://github.com/Gator96100) creates [ProxSpace](https://github.com/Gator96100/ProxSpace) and makes it possible to compile both the firmware and the client on Windows.
|
||||||
Also, he makes the [pre-compiled Windows client](http://www.proxmark.org/forum/viewtopic.php?id=3975) so you can download it and run your PM3 client on Windows instantly.
|
Also, he makes the [pre-compiled Windows client](https://www.proxmarkbuilds.org/) so you can download it and run your PM3 client on Windows instantly.
|
||||||
I included his compiled client in my releases so you can use the GUI on the fly, and you can also use the GUI with your prefered client.
|
I included his compiled client in my releases so you can use the GUI on the fly, and you can also use the GUI with your prefered client.
|
||||||
Great thanks to him.
|
Great thanks to him.
|
||||||
|
|
||||||
***
|
***
|
||||||
|
|
||||||
|
## Build on Linux
|
||||||
|
|
||||||
|
cd ~
|
||||||
|
git clone https://github.com/wh201906/Proxmark3GUI.git
|
||||||
|
cd Proxmark3GUI
|
||||||
|
mkdir build
|
||||||
|
cd build
|
||||||
|
qmake ../
|
||||||
|
make
|
||||||
|
make clean
|
||||||
|
cp -r ../lang ./
|
||||||
|
./Proxmark3GUI
|
||||||
|
|
||||||
|
***
|
||||||
|
|
||||||
## Update Log:
|
## Update Log:
|
||||||
|
|
||||||
|
### V0.2.1
|
||||||
|
+ Optimize MIFARE Classic reading logic
|
||||||
|
+ Fix bug #16
|
||||||
|
+ Fix bug #15 partially (the path can contain spaces now)
|
||||||
|
|
||||||
|
### 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
|
### V0.1.2
|
||||||
+ Optimize read logic
|
+ Optimize read logic
|
||||||
+ Make UI Customizable
|
+ Make UI Customizable
|
||||||
+ Save client path automatically
|
+ 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 read/write selected blocks
|
||||||
+ Support a few Iceman functions
|
+ Support a few Iceman functions
|
||||||
+ Fix some bugs
|
+ Fix some bugs
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
# Proxmark3GUI
|
# Proxmark3GUI
|
||||||
一个自制的[Proxmark3](https://github.com/Proxmark/proxmark3) GUI
|

|
||||||
|
|
||||||
|
一个自制的[Proxmark3](https://github.com/Proxmark/proxmark3) GUI,可在Windows/Linux系统下运行
|
||||||
|
|
||||||
[English](../../README.md)
|
[English](../../README.md)
|
||||||
|
|
||||||
@@ -17,7 +19,8 @@
|
|||||||
+ 可以打开二进制/文本格式的扇区数据文件
|
+ 可以打开二进制/文本格式的扇区数据文件
|
||||||
+ 分析访问控制位(Access Bits)
|
+ 分析访问控制位(Access Bits)
|
||||||
+ 支持UID卡操作(UID快速读写,UFUID锁卡)
|
+ 支持UID卡操作(UID快速读写,UFUID锁卡)
|
||||||
+ 自定义UI界面
|
+ 支持部分低频命令
|
||||||
|
+ 自定义UI界面,各选项卡可拆分组合
|
||||||
+ ...
|
+ ...
|
||||||
|
|
||||||
***
|
***
|
||||||
@@ -30,28 +33,67 @@
|
|||||||
***
|
***
|
||||||
|
|
||||||
## 关于冰人版
|
## 关于冰人版
|
||||||
这个GUI一开始是针对官方版本做的,现在正在尽力让它兼容冰人版的功能
|
[冰人版](https://github.com/RfidResearchGroup/proxmark3)(Iceman/RRG)的客户端和固件更新更为激进,相比官方版具有更多的功能
|
||||||
(没钱买RDV4也没钱买两台PM3,测一次冰人就要烧一次固件 qwq)
|
此GUI所有功能均兼容冰人版(在v4.9237上测试通过)
|
||||||
|
|
||||||
[已支持功能](../doc/supported_Iceman.md)
|
|
||||||
***
|
***
|
||||||
|
|
||||||
## 关于预编译Windows客户端
|
## 关于预编译Windows客户端
|
||||||
|
|
||||||
一个国外大佬 [Gator96100](https://github.com/Gator96100) 做了个 [ProxSpace](https://github.com/Gator96100/ProxSpace) 以便在Windows平台上编译PM3固件和客户端,他还把自己编译好的客户端放到了[论坛](http://www.proxmark.org/forum/viewtopic.php?id=3975)里面
|
一位国外大佬 [Gator96100](https://github.com/Gator96100) 做了个 [ProxSpace](https://github.com/Gator96100/ProxSpace) 以便在Windows平台上编译PM3固件和客户端,他还把自己编译好的客户端放到了[网站](https://www.proxmarkbuilds.org/)上
|
||||||
文件都是放到Google Drive上面的,国内网络无法访问,所以我在release版本里面放了个带预编译客户端版本的GUI。这个GUI也可以搭配你自己的客户端使用
|
release页面中有含客户端的GUI。这个GUI也可以搭配你自己的客户端使用
|
||||||
(本来打算在CSDN下载里面放几个最新版客户端的,结果不能把下载币改为0)
|
(本来打算在CSDN下载里面放几个最新版客户端的,结果不能把下载币改为0)
|
||||||
感谢大佬
|
感谢大佬
|
||||||
|
|
||||||
***
|
***
|
||||||
|
|
||||||
|
## 在Linux系统下编译
|
||||||
|
|
||||||
|
cd ~
|
||||||
|
git clone https://github.com/wh201906/Proxmark3GUI.git
|
||||||
|
cd Proxmark3GUI
|
||||||
|
mkdir build
|
||||||
|
cd build
|
||||||
|
qmake ../
|
||||||
|
make
|
||||||
|
make clean
|
||||||
|
cp -r ../lang ./
|
||||||
|
./Proxmark3GUI
|
||||||
|
|
||||||
|
***
|
||||||
|
|
||||||
## 更新日志:
|
## 更新日志:
|
||||||
|
|
||||||
|
### V0.2.1
|
||||||
|
+ 优化MIFARE Classic读卡逻辑
|
||||||
|
+ 修复 #16 (配合新版RRG固件时无法读取扇区数据)
|
||||||
|
+ 修复 #15 (路径中支持空格)
|
||||||
|
|
||||||
|
### V0.2
|
||||||
|
+ 使用浮动窗口,界面配置更加灵活
|
||||||
|
+ 支持部分低频命令
|
||||||
|
+ 修复原始命令选项卡中的一个Bug
|
||||||
|
|
||||||
|
### V0.1.4
|
||||||
|
+ 优化性能
|
||||||
|
+ 优化用户界面
|
||||||
|
+ 自动搜索可用端口
|
||||||
|
+ 支持高分屏
|
||||||
|
+ 可通过外部脚本配置环境变量
|
||||||
|
(在客户端需要配置环境变量时很有用)
|
||||||
|
+ 全功能兼容冰人版(在v4.9237上测试通过)
|
||||||
|
+ 支持指定客户端工作路径
|
||||||
|
+ 修复部分bug
|
||||||
|
|
||||||
|
### V0.1.3
|
||||||
|
+ 修复访问控制位解码器
|
||||||
|
+ 写多个块时显示写入结果
|
||||||
|
|
||||||
### V0.1.2
|
### V0.1.2
|
||||||
+ 优化读卡逻辑
|
+ 优化读卡逻辑
|
||||||
+ UI自定义
|
+ UI自定义
|
||||||
+ 自动保存客户端路径
|
+ 自动保存客户端路径
|
||||||
+ 添加访问控制位解码器(也可用于自己构造访问控制位)
|
+ 添加访问控制位解码器(也可用于自己构造访问控制位)(有bug,请使用V0.1.3或更高版本)
|
||||||
+ 支持仅读写选中块
|
+ 支持仅读写选中块
|
||||||
+ 支持部分冰人功能
|
+ 支持部分冰人功能
|
||||||
+ 修复部分bug
|
+ 修复部分bug
|
||||||
|
|||||||
@@ -13,4 +13,8 @@ Mifare Edit File:
|
|||||||

|

|
||||||
|
|
||||||
Mifare Trailer Decoder:
|
Mifare Trailer Decoder:
|
||||||

|

|
||||||
|
|
||||||
|
Dock Widget:
|
||||||
|

|
||||||
|

|
||||||
@@ -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
|
|
||||||
|
After Width: | Height: | Size: 59 KiB |
|
After Width: | Height: | Size: 40 KiB |
|
Before Width: | Height: | Size: 407 KiB After Width: | Height: | Size: 468 KiB |
|
Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 44 KiB |
|
Before Width: | Height: | Size: 52 KiB After Width: | Height: | Size: 50 KiB |
@@ -0,0 +1,13 @@
|
|||||||
|
#include "myeventfilter.h"
|
||||||
|
|
||||||
|
MyEventFilter::MyEventFilter(QEvent::Type filter)
|
||||||
|
{
|
||||||
|
targetEventType = filter;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MyEventFilter::eventFilter(QObject *obj, QEvent *event)
|
||||||
|
{
|
||||||
|
if(event->type() == targetEventType)
|
||||||
|
emit eventHappened(obj, *event);
|
||||||
|
return QObject::eventFilter(obj, event);
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
#ifndef MYEVENTFILTER_H
|
||||||
|
#define MYEVENTFILTER_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QKeyEvent>
|
||||||
|
|
||||||
|
class MyEventFilter : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit MyEventFilter(QEvent::Type filter);
|
||||||
|
protected:
|
||||||
|
bool eventFilter(QObject *obj, QEvent *event) override;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void eventHappened(QObject* obj_addr, QEvent& event);
|
||||||
|
private:
|
||||||
|
QEvent::Type targetEventType;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // MYEVENTFILTER_H
|
||||||
@@ -12,19 +12,24 @@ PM3Process::PM3Process(QThread* thread, QObject* parent): QProcess(parent)
|
|||||||
serialListener->setTimerType(Qt::VeryCoarseTimer);
|
serialListener->setTimerType(Qt::VeryCoarseTimer);
|
||||||
connect(serialListener, &QTimer::timeout, this, &PM3Process::onTimeout);
|
connect(serialListener, &QTimer::timeout, this, &PM3Process::onTimeout);
|
||||||
connect(this, &PM3Process::readyRead, this, &PM3Process::onReadyRead);
|
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;
|
QString result;
|
||||||
Util::ClientType clientType = Util::CLIENTTYPE_OFFICIAL;
|
Util::ClientType clientType;
|
||||||
setRequiringOutput(true);
|
setRequiringOutput(true);
|
||||||
|
|
||||||
|
// stash for reconnect
|
||||||
|
currPath = path;
|
||||||
|
currArgs = args;
|
||||||
|
|
||||||
// using "-f" option to make the client output flushed after every print.
|
// using "-f" option to make the client output flushed after every print.
|
||||||
start(path, QStringList() << port << "-f", QProcess::Unbuffered | QProcess::ReadWrite);
|
start(path, args, QProcess::Unbuffered | QProcess::ReadWrite);
|
||||||
if(waitForStarted(10000))
|
if(waitForStarted(10000))
|
||||||
{
|
{
|
||||||
waitForReadyRead(1000);
|
waitForReadyRead(10000);
|
||||||
setRequiringOutput(false);
|
setRequiringOutput(false);
|
||||||
result = *requiredOutput;
|
result = *requiredOutput;
|
||||||
if(result.indexOf("[=]") != -1)
|
if(result.indexOf("[=]") != -1)
|
||||||
@@ -32,10 +37,17 @@ void PM3Process::connectPM3(const QString path, const QString port)
|
|||||||
clientType = Util::CLIENTTYPE_ICEMAN;
|
clientType = Util::CLIENTTYPE_ICEMAN;
|
||||||
setRequiringOutput(true);
|
setRequiringOutput(true);
|
||||||
write("hw version\r\n");
|
write("hw version\r\n");
|
||||||
waitForReadyRead(1000);
|
for(int i = 0; i < 10; i++)
|
||||||
result = *requiredOutput;
|
{
|
||||||
|
waitForReadyRead(200);
|
||||||
|
result += *requiredOutput;
|
||||||
|
}
|
||||||
setRequiringOutput(false);
|
setRequiringOutput(false);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
clientType = Util::CLIENTTYPE_OFFICIAL;
|
||||||
|
}
|
||||||
if(result.indexOf("os: ") != -1) // make sure the PM3 is connected
|
if(result.indexOf("os: ") != -1) // make sure the PM3 is connected
|
||||||
{
|
{
|
||||||
emit changeClientType(clientType);
|
emit changeClientType(clientType);
|
||||||
@@ -43,13 +55,17 @@ void PM3Process::connectPM3(const QString path, const QString port)
|
|||||||
result = result.left(result.indexOf("\r\n"));
|
result = result.left(result.indexOf("\r\n"));
|
||||||
result = result.mid(3, result.lastIndexOf(" ") - 3);
|
result = result.mid(3, result.lastIndexOf(" ") - 3);
|
||||||
emit PM3StatedChanged(true, result);
|
emit PM3StatedChanged(true, result);
|
||||||
setSerialListener(port, true);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
kill();
|
kill();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PM3Process::reconnectPM3()
|
||||||
|
{
|
||||||
|
connectPM3(currPath, currArgs);
|
||||||
|
}
|
||||||
|
|
||||||
void PM3Process::setRequiringOutput(bool st)
|
void PM3Process::setRequiringOutput(bool st)
|
||||||
{
|
{
|
||||||
isRequiringOutput = st;
|
isRequiringOutput = st;
|
||||||
@@ -66,6 +82,7 @@ void PM3Process::setSerialListener(const QString& name, bool state)
|
|||||||
{
|
{
|
||||||
if(state)
|
if(state)
|
||||||
{
|
{
|
||||||
|
currPort = name;
|
||||||
portInfo = new QSerialPortInfo(name);
|
portInfo = new QSerialPortInfo(name);
|
||||||
serialListener->start();
|
serialListener->start();
|
||||||
qDebug() << serialListener->thread();
|
qDebug() << serialListener->thread();
|
||||||
@@ -73,18 +90,25 @@ void PM3Process::setSerialListener(const QString& name, bool state)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
serialListener->stop();
|
serialListener->stop();
|
||||||
delete portInfo;
|
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);
|
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);
|
||||||
{
|
{
|
||||||
// qDebug()<<portInfo->isBusy();
|
// qDebug()<<portInfo->isBusy();
|
||||||
if(!portInfo->isBusy())
|
if(!portInfo->isBusy())
|
||||||
{
|
{
|
||||||
kill();
|
killPM3();
|
||||||
emit PM3StatedChanged(false);
|
|
||||||
setSerialListener("", false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -93,7 +117,6 @@ void PM3Process::testThread()
|
|||||||
qDebug() << "PM3:" << QThread::currentThread();
|
qDebug() << "PM3:" << QThread::currentThread();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
qint64 PM3Process::write(QString data)
|
qint64 PM3Process::write(QString data)
|
||||||
{
|
{
|
||||||
return QProcess::write(data.toLatin1());
|
return QProcess::write(data.toLatin1());
|
||||||
@@ -111,3 +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);
|
||||||
|
}
|
||||||
|
|||||||
@@ -8,6 +8,8 @@
|
|||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
#include <QtSerialPort/QSerialPortInfo>
|
#include <QtSerialPort/QSerialPortInfo>
|
||||||
#include <QtSerialPort/QSerialPort>
|
#include <QtSerialPort/QSerialPort>
|
||||||
|
#include <QProcessEnvironment>
|
||||||
|
#include <QDir>
|
||||||
|
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
@@ -21,9 +23,14 @@ public:
|
|||||||
void testThread();
|
void testThread();
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void connectPM3(const QString path, const QString port);
|
void connectPM3(const QString& path, const QStringList args);
|
||||||
void setSerialListener(const QString &name, bool state);
|
void setSerialListener(const QString& name, bool state);
|
||||||
|
void setSerialListener(bool state);
|
||||||
qint64 write(QString data);
|
qint64 write(QString data);
|
||||||
|
void reconnectPM3();
|
||||||
|
void setProcEnv(const QStringList* env);
|
||||||
|
void setWorkingDir(const QString& dir);
|
||||||
|
void killPM3();
|
||||||
private slots:
|
private slots:
|
||||||
void onTimeout();
|
void onTimeout();
|
||||||
void onReadyRead();
|
void onReadyRead();
|
||||||
@@ -33,9 +40,13 @@ private:
|
|||||||
void setRequiringOutput(bool st);// It only works in this class now
|
void setRequiringOutput(bool st);// It only works in this class now
|
||||||
QTimer* serialListener;
|
QTimer* serialListener;
|
||||||
QSerialPortInfo* portInfo;
|
QSerialPortInfo* portInfo;
|
||||||
|
QString currPath;
|
||||||
|
QString currPort = "";
|
||||||
|
QStringList currArgs;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void PM3StatedChanged(bool st, QString info = "");
|
void PM3StatedChanged(bool st, const QString& info = "");
|
||||||
void newOutput(QString output);
|
void newOutput(const QString& output);
|
||||||
void changeClientType(Util::ClientType);
|
void changeClientType(Util::ClientType);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,15 +1,22 @@
|
|||||||
#include "util.h"
|
#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)
|
Util::Util(QObject *parent) : QObject(parent)
|
||||||
{
|
{
|
||||||
isRequiringOutput = false;
|
isRequiringOutput = false;
|
||||||
requiredOutput = new QString();
|
requiredOutput = new QString();
|
||||||
timeStamp = QTime::currentTime();
|
timeStamp = QTime::currentTime();
|
||||||
this->clientType = CLIENTTYPE_OFFICIAL;
|
|
||||||
qRegisterMetaType<Util::ClientType>("Util::ClientType");
|
qRegisterMetaType<Util::ClientType>("Util::ClientType");
|
||||||
}
|
}
|
||||||
|
|
||||||
void Util::processOutput(QString output)
|
|
||||||
|
void Util::processOutput(const QString& output)
|
||||||
{
|
{
|
||||||
// qDebug() << "Util::processOutput:" << output;
|
// qDebug() << "Util::processOutput:" << output;
|
||||||
if(isRequiringOutput)
|
if(isRequiringOutput)
|
||||||
@@ -20,30 +27,58 @@ void Util::processOutput(QString output)
|
|||||||
emit refreshOutput(output);
|
emit refreshOutput(output);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Util::execCMD(QString cmd)
|
void Util::execCMD(const QString& cmd)
|
||||||
{
|
{
|
||||||
qDebug() << cmd;
|
qDebug() << "executing: " << cmd;
|
||||||
emit write(cmd + "\r\n");
|
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 currTime = QTime::currentTime();
|
||||||
QTime targetTime = QTime::currentTime().addMSecs(waitTime);
|
QTime targetTime = QTime::currentTime().addMSecs(trigger.waitTime);
|
||||||
isRequiringOutput = true;
|
isRequiringOutput = true;
|
||||||
requiredOutput->clear();
|
requiredOutput->clear();
|
||||||
execCMD(cmd);
|
execCMD(cmd);
|
||||||
while(QTime::currentTime() < targetTime)
|
while(QTime::currentTime() < targetTime)
|
||||||
{
|
{
|
||||||
|
if(!isRunning)
|
||||||
|
break;
|
||||||
QApplication::processEvents();
|
QApplication::processEvents();
|
||||||
if(timeStamp > currTime)
|
// qDebug() << "currOutput:" << *requiredOutput;
|
||||||
|
for(QString otpt : trigger.expectedOutputs)
|
||||||
|
{
|
||||||
|
re.setPattern(otpt);
|
||||||
|
isResultFound = re.match(*requiredOutput).hasMatch();
|
||||||
|
if(isResultFound)
|
||||||
|
{
|
||||||
|
qDebug() << "output Matched: " << *requiredOutput;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(isResultFound)
|
||||||
|
{
|
||||||
|
delay(200);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(timeStamp > currTime) //has new output
|
||||||
{
|
{
|
||||||
currTime = timeStamp;
|
currTime = timeStamp;
|
||||||
targetTime = timeStamp.addMSecs(waitTime);
|
targetTime = timeStamp.addMSecs(trigger.waitTime);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
isRequiringOutput = false;
|
isRequiringOutput = false;
|
||||||
return *requiredOutput;
|
return (isResultFound || trigger.expectedOutputs.isEmpty() ? *requiredOutput : "");
|
||||||
}
|
}
|
||||||
|
|
||||||
void Util::delay(unsigned int msec)
|
void Util::delay(unsigned int msec)
|
||||||
@@ -52,12 +87,61 @@ void Util::delay(unsigned int msec)
|
|||||||
while(QTime::currentTime() < timer)
|
while(QTime::currentTime() < timer)
|
||||||
QApplication::processEvents(QEventLoop::AllEvents, 100);
|
QApplication::processEvents(QEventLoop::AllEvents, 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
Util::ClientType Util::getClientType()
|
Util::ClientType Util::getClientType()
|
||||||
{
|
{
|
||||||
return this->clientType;
|
return Util::clientType;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Util::setClientType(Util::ClientType clientType)
|
void Util::setClientType(Util::ClientType clientType)
|
||||||
{
|
{
|
||||||
this->clientType = clientType;
|
Util::clientType = clientType;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Util::setRunningState(bool st)
|
||||||
|
{
|
||||||
|
this->isRunning = st;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Util::chooseLanguage(QSettings* guiSettings, QMainWindow* window)
|
||||||
|
{
|
||||||
|
// make sure the GUISettings is not in any group
|
||||||
|
QSettings* langSettings = new QSettings("lang/languages.ini", QSettings::IniFormat);
|
||||||
|
QMap<QString, QString> langMap;
|
||||||
|
langSettings->setIniCodec("UTF-8");
|
||||||
|
langSettings->beginGroup("Languages");
|
||||||
|
QStringList langList = langSettings->allKeys();
|
||||||
|
for(int i = 0; i < langList.size(); i++)
|
||||||
|
langMap.insert(langSettings->value(langList[i]).toString(), langList[i]);
|
||||||
|
langSettings->endGroup();
|
||||||
|
delete langSettings;
|
||||||
|
bool isOk = false;
|
||||||
|
QString selectedText = QInputDialog::getItem(window, "", "Choose a language:", langMap.keys(), 0, false, &isOk);
|
||||||
|
if(isOk)
|
||||||
|
{
|
||||||
|
guiSettings->beginGroup("lang");
|
||||||
|
guiSettings->setValue("language", langMap[selectedText]);
|
||||||
|
guiSettings->endGroup();
|
||||||
|
guiSettings->sync();
|
||||||
|
}
|
||||||
|
return isOk;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,13 @@
|
|||||||
#include <QTime>
|
#include <QTime>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
#include <QMetaType>
|
#include <QMetaType>
|
||||||
|
#include <QRegularExpression>
|
||||||
|
#include <QSettings>
|
||||||
|
#include <QMainWindow>
|
||||||
|
#include <QInputDialog>
|
||||||
|
#include <QDockWidget>
|
||||||
|
|
||||||
|
#include "ui_mainwindow.h"
|
||||||
|
|
||||||
class Util : public QObject
|
class Util : public QObject
|
||||||
{
|
{
|
||||||
@@ -20,26 +27,55 @@ public:
|
|||||||
CLIENTTYPE_ICEMAN,
|
CLIENTTYPE_ICEMAN,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ReturnTrigger
|
||||||
|
{
|
||||||
|
unsigned long waitTime;
|
||||||
|
QStringList expectedOutputs;
|
||||||
|
ReturnTrigger(unsigned long time)
|
||||||
|
{
|
||||||
|
waitTime = time;
|
||||||
|
expectedOutputs = QStringList();
|
||||||
|
}
|
||||||
|
ReturnTrigger(const QStringList& outputs)
|
||||||
|
{
|
||||||
|
waitTime = 10000;
|
||||||
|
expectedOutputs = outputs;
|
||||||
|
}
|
||||||
|
ReturnTrigger(unsigned long time, const QStringList& outputs)
|
||||||
|
{
|
||||||
|
waitTime = time;
|
||||||
|
expectedOutputs = outputs;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
Q_ENUM(Util::ClientType)
|
Q_ENUM(Util::ClientType)
|
||||||
|
|
||||||
explicit Util(QObject *parent = nullptr);
|
explicit Util(QObject *parent = nullptr);
|
||||||
|
|
||||||
void execCMD(QString cmd);
|
void execCMD(const QString& cmd);
|
||||||
QString execCMDWithOutput(QString cmd, unsigned long waitTime = 2000);
|
QString execCMDWithOutput(const QString& cmd, ReturnTrigger trigger = 10000);
|
||||||
void delay(unsigned int msec);
|
void delay(unsigned int msec);
|
||||||
ClientType getClientType();
|
static ClientType getClientType();
|
||||||
|
static int rawTabIndex;
|
||||||
|
static QDockWidget* rawDockPtr;
|
||||||
|
static bool chooseLanguage(QSettings *guiSettings, QMainWindow *window);
|
||||||
public slots:
|
public slots:
|
||||||
void processOutput(QString output);
|
void processOutput(const QString& output);
|
||||||
void setClientType(Util::ClientType clientType);
|
static void setClientType(Util::ClientType clientType);
|
||||||
|
void setRunningState(bool st);
|
||||||
|
static void gotoRawTab();
|
||||||
|
static void setUI(Ui::MainWindow *ui);
|
||||||
|
static void setRawTab(QDockWidget* dockPtr, int tabIndex);
|
||||||
private:
|
private:
|
||||||
bool isRequiringOutput;
|
bool isRequiringOutput;
|
||||||
|
bool isRunning;
|
||||||
QString* requiredOutput;
|
QString* requiredOutput;
|
||||||
QTime timeStamp;
|
QTime timeStamp;
|
||||||
ClientType clientType;
|
static ClientType clientType;
|
||||||
|
static Ui::MainWindow *ui;
|
||||||
signals:
|
signals:
|
||||||
void refreshOutput(const QString& output);
|
void refreshOutput(const QString& output);
|
||||||
void write(QString data);
|
void write(QString data); // connected to PM3Process::write(QString data);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // UTIL_H
|
#endif // UTIL_H
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
[Languages]
|
||||||
|
en_US=English
|
||||||
|
zh_CN=简体中文
|
||||||
@@ -4,56 +4,50 @@
|
|||||||
#include <QSettings>
|
#include <QSettings>
|
||||||
#include <QTranslator>
|
#include <QTranslator>
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
#include <QInputDialog>
|
#include <QTextCodec>
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
|
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
|
||||||
|
QTextCodec::setCodecForLocale(QTextCodec::codecForName("UTF-8"));
|
||||||
QApplication a(argc, argv);
|
QApplication a(argc, argv);
|
||||||
MainWindow w;
|
MainWindow w;
|
||||||
|
|
||||||
QSettings* settings = new QSettings("GUIsettings.ini", QSettings::IniFormat);
|
QSettings* settings = new QSettings("GUIsettings.ini", QSettings::IniFormat);
|
||||||
|
settings->setIniCodec("UTF-8");
|
||||||
settings->beginGroup("lang");
|
settings->beginGroup("lang");
|
||||||
QVariant lang = settings->value("language", "null");
|
QString currLang = settings->value("language", "").toString();
|
||||||
if(lang == "null")
|
settings->endGroup();
|
||||||
|
if(currLang == "")
|
||||||
{
|
{
|
||||||
#ifdef Q_OS_WIN
|
if(Util::chooseLanguage(settings, &w))
|
||||||
lang = "lang/en_US.qm";
|
|
||||||
#else
|
|
||||||
lang = "lang/en_US.ts";
|
|
||||||
#endif
|
|
||||||
QStringList langList;
|
|
||||||
langList.append("English");
|
|
||||||
langList.append("简体中文");
|
|
||||||
QString seletedText = QInputDialog::getItem(&w, "", "Choose a language:", langList, 0, false);
|
|
||||||
if(seletedText == "English")
|
|
||||||
{
|
{
|
||||||
#ifdef Q_OS_WIN
|
settings->beginGroup("lang");
|
||||||
lang = "lang/en_US.qm";
|
currLang = settings->value("language", "").toString();
|
||||||
#else
|
settings->endGroup();
|
||||||
lang = "lang/en_US.ts";
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
else if(seletedText == "简体中文")
|
|
||||||
{
|
|
||||||
#ifdef Q_OS_WIN
|
|
||||||
lang = "lang/zh_CN.qm";
|
|
||||||
#else
|
|
||||||
lang = "lang/zh_CN.ts";
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
currLang = "en_US";
|
||||||
}
|
}
|
||||||
|
currLang = "lang/" + currLang;
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
currLang += ".qm";
|
||||||
|
#else
|
||||||
|
currLang += ".ts";;
|
||||||
|
#endif
|
||||||
QTranslator* translator = new QTranslator(&w);
|
QTranslator* translator = new QTranslator(&w);
|
||||||
if(translator->load(lang.toString()))
|
if(translator->load(currLang))
|
||||||
{
|
{
|
||||||
a.installTranslator(translator);
|
a.installTranslator(translator);
|
||||||
settings->setValue("language", lang);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
QMessageBox::information(&w, "Error", "Can't load " + lang.toString() + " as translation file.");
|
QMessageBox::information(&w, "Error", "Can't load " + currLang + " as translation file.");
|
||||||
}
|
}
|
||||||
settings->endGroup();
|
|
||||||
delete settings;
|
delete settings;
|
||||||
w.initUI();
|
w.initUI();
|
||||||
w.show();
|
w.show();
|
||||||
return a.exec();
|
return a.exec();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
|
}
|
||||||
@@ -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
|
||||||
@@ -6,7 +6,8 @@ const Mifare::CardType Mifare::card_mini =
|
|||||||
5,
|
5,
|
||||||
20,
|
20,
|
||||||
{4, 4, 4, 4, 4},
|
{4, 4, 4, 4, 4},
|
||||||
{0, 4, 8, 12, 16}
|
{0, 4, 8, 12, 16},
|
||||||
|
"mini"
|
||||||
};
|
};
|
||||||
const Mifare::CardType Mifare::card_1k =
|
const Mifare::CardType Mifare::card_1k =
|
||||||
{
|
{
|
||||||
@@ -14,7 +15,8 @@ const Mifare::CardType Mifare::card_1k =
|
|||||||
16,
|
16,
|
||||||
64,
|
64,
|
||||||
{4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4},
|
{4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4},
|
||||||
{0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60}
|
{0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60},
|
||||||
|
"1k"
|
||||||
};
|
};
|
||||||
const Mifare::CardType Mifare::card_2k =
|
const Mifare::CardType Mifare::card_2k =
|
||||||
{
|
{
|
||||||
@@ -22,7 +24,8 @@ const Mifare::CardType Mifare::card_2k =
|
|||||||
32,
|
32,
|
||||||
128,
|
128,
|
||||||
{4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4},
|
{4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4},
|
||||||
{0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60, 64, 68, 72, 76, 80, 84, 88, 92, 96, 100, 104, 108, 112, 116, 120, 124}
|
{0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60, 64, 68, 72, 76, 80, 84, 88, 92, 96, 100, 104, 108, 112, 116, 120, 124},
|
||||||
|
"2k"
|
||||||
};
|
};
|
||||||
const Mifare::CardType Mifare::card_4k =
|
const Mifare::CardType Mifare::card_4k =
|
||||||
{
|
{
|
||||||
@@ -30,7 +33,8 @@ const Mifare::CardType Mifare::card_4k =
|
|||||||
40,
|
40,
|
||||||
256,
|
256,
|
||||||
{4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 16, 16, 16, 16, 16, 16, 16, 16},
|
{4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 16, 16, 16, 16, 16, 16, 16, 16},
|
||||||
{0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60, 64, 68, 72, 76, 80, 84, 88, 92, 96, 100, 104, 108, 112, 116, 120, 124, 128, 144, 160, 176, 192, 208, 224, 240}
|
{0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60, 64, 68, 72, 76, 80, 84, 88, 92, 96, 100, 104, 108, 112, 116, 120, 124, 128, 144, 160, 176, 192, 208, 224, 240},
|
||||||
|
"4k"
|
||||||
};
|
};
|
||||||
|
|
||||||
const Mifare::AccessType Mifare::dataCondition[8][4] =
|
const Mifare::AccessType Mifare::dataCondition[8][4] =
|
||||||
@@ -79,53 +83,49 @@ Mifare::Mifare(Ui::MainWindow *ui, Util *addr, QWidget *parent): QObject(parent)
|
|||||||
data_clearKey(); // fill with blank QString
|
data_clearKey(); // fill with blank QString
|
||||||
data_clearData(); // fill with blank QString
|
data_clearData(); // fill with blank QString
|
||||||
dataPattern = new QRegularExpression("([0-9a-fA-F]{2} ){15}[0-9a-fA-F]{2}");
|
dataPattern = new QRegularExpression("([0-9a-fA-F]{2} ){15}[0-9a-fA-F]{2}");
|
||||||
keyPattern_res = new QRegularExpression("\\|\\d{3}\\|.+?\\|.+?\\|.+?\\|.+?\\|");
|
keyPattern_res = new QRegularExpression("\\|\\s*\\d{3}\\s*\\|\\s*.+?\\s*\\|\\s*.+?\\s*\\|\\s*.+?\\s*\\|\\s*.+?\\s*\\|");
|
||||||
keyPattern = new QRegularExpression("\\|\\d{3}\\|.+?\\|.+?\\|");
|
keyPattern = new QRegularExpression("\\|\\s*\\d{3}\\s*\\|\\s*.+?\\s*\\|\\s*.+?\\s*\\|");
|
||||||
}
|
}
|
||||||
|
|
||||||
QString Mifare::info(bool isRequiringOutput)
|
QString Mifare::info(bool isRequiringOutput)
|
||||||
{
|
{
|
||||||
if(util->getClientType() == Util::CLIENTTYPE_OFFICIAL || util->getClientType() == Util::CLIENTTYPE_ICEMAN)
|
if(Util::getClientType() == Util::CLIENTTYPE_OFFICIAL || Util::getClientType() == Util::CLIENTTYPE_ICEMAN)
|
||||||
{
|
{
|
||||||
if(isRequiringOutput)
|
if(isRequiringOutput)
|
||||||
{
|
{
|
||||||
QString result = util->execCMDWithOutput("hf 14a info", 500);
|
QString result = util->execCMDWithOutput("hf 14a info", 500);
|
||||||
result.replace("UID :", "|||");
|
int begin, end;
|
||||||
result.replace("ATQA :", "|||");
|
begin = result.indexOf("UID");
|
||||||
result.replace("SAK :", "|||");
|
if(begin != -1)
|
||||||
result.replace("TYPE :", "|||");
|
|
||||||
QStringList lis = result.split("|||");
|
|
||||||
if(lis.length() > 4)
|
|
||||||
{
|
{
|
||||||
qDebug() << lis[1] + lis[2] + lis[3];
|
end = result.indexOf("SAK", begin);
|
||||||
return lis[1] + lis[2] + lis[3];
|
end = result.indexOf("\n", end);
|
||||||
|
return result.mid(begin, end - begin + 1);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
return "";
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
util->execCMD("hf 14a info");
|
util->execCMD("hf 14a info");
|
||||||
ui->funcTab->setCurrentIndex(1);
|
Util::gotoRawTab();
|
||||||
return "";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mifare::chk()
|
void Mifare::chk()
|
||||||
{
|
{
|
||||||
QRegularExpressionMatch reMatch;
|
QRegularExpressionMatch reMatch;
|
||||||
QString result = util->execCMDWithOutput(
|
QString result;
|
||||||
"hf mf chk *"
|
|
||||||
+ QString::number(cardType.type)
|
|
||||||
+ " ?",
|
|
||||||
1000 + cardType.type * 1000);
|
|
||||||
qDebug() << result;
|
|
||||||
|
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
QString data;
|
QString data;
|
||||||
if(util->getClientType() == Util::CLIENTTYPE_OFFICIAL)
|
if(Util::getClientType() == Util::CLIENTTYPE_OFFICIAL)
|
||||||
{
|
{
|
||||||
|
result = util->execCMDWithOutput(
|
||||||
|
"hf mf chk *"
|
||||||
|
+ QString::number(cardType.type)
|
||||||
|
+ " ?",
|
||||||
|
Util::ReturnTrigger(1000 + cardType.sector_size * 200, {"No valid", keyPattern->pattern()}));
|
||||||
|
qDebug() << result;
|
||||||
for(int i = 0; i < cardType.sector_size; i++)
|
for(int i = 0; i < cardType.sector_size; i++)
|
||||||
{
|
{
|
||||||
reMatch = keyPattern->match(result, offset);
|
reMatch = keyPattern->match(result, offset);
|
||||||
@@ -146,8 +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++)
|
for(int i = 0; i < cardType.sector_size; i++)
|
||||||
{
|
{
|
||||||
reMatch = keyPattern_res->match(result, offset);
|
reMatch = keyPattern_res->match(result, offset);
|
||||||
@@ -178,21 +183,22 @@ void Mifare::nested()
|
|||||||
QString result;
|
QString result;
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
QString data;
|
QString data;
|
||||||
if(util->getClientType() == Util::CLIENTTYPE_OFFICIAL)
|
if(Util::getClientType() == Util::CLIENTTYPE_OFFICIAL)
|
||||||
{
|
{
|
||||||
result = util->execCMDWithOutput(
|
result = util->execCMDWithOutput(
|
||||||
"hf mf nested "
|
"hf mf nested "
|
||||||
+ QString::number(cardType.type)
|
+ QString::number(cardType.type)
|
||||||
+ " *", 10000);
|
+ " *",
|
||||||
|
Util::ReturnTrigger(15000, {"Can't found", "\\|000\\|"}));
|
||||||
}
|
}
|
||||||
else if(util->getClientType() == Util::CLIENTTYPE_ICEMAN)
|
else if(Util::getClientType() == Util::CLIENTTYPE_ICEMAN)
|
||||||
{
|
{
|
||||||
QString knownKeyInfo = "";
|
QString knownKeyInfo = "";
|
||||||
for(int i = 0; i < cardType.sector_size; i++)
|
for(int i = 0; i < cardType.sector_size; i++)
|
||||||
{
|
{
|
||||||
if(data_isKeyValid(keyAList->at(i)))
|
if(data_isKeyValid(keyAList->at(i)))
|
||||||
{
|
{
|
||||||
knownKeyInfo = " " + QString::number(i * 4) + " A " + keyAList->at(i);
|
knownKeyInfo = " --blk " + QString::number(i * 4) + " -a -k " + keyAList->at(i);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -202,7 +208,7 @@ void Mifare::nested()
|
|||||||
{
|
{
|
||||||
if(data_isKeyValid(keyBList->at(i)))
|
if(data_isKeyValid(keyBList->at(i)))
|
||||||
{
|
{
|
||||||
knownKeyInfo = " " + QString::number(i * 4) + " B " + keyBList->at(i);
|
knownKeyInfo = " --blk " + QString::number(i * 4) + " -b -k " + keyBList->at(i);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -210,9 +216,10 @@ void Mifare::nested()
|
|||||||
if(knownKeyInfo != "")
|
if(knownKeyInfo != "")
|
||||||
{
|
{
|
||||||
result = util->execCMDWithOutput(
|
result = util->execCMDWithOutput(
|
||||||
"hf mf nested "
|
"hf mf nested --"
|
||||||
+ QString::number(cardType.type)
|
+ cardType.typeText
|
||||||
+ knownKeyInfo, 10000);
|
+ knownKeyInfo,
|
||||||
|
Util::ReturnTrigger(15000, {"Can't authenticate", keyPattern_res->pattern()}));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -248,34 +255,57 @@ void Mifare::hardnested()
|
|||||||
MF_Attack_hardnestedDialog dialog(cardType.block_size);
|
MF_Attack_hardnestedDialog dialog(cardType.block_size);
|
||||||
connect(&dialog, &MF_Attack_hardnestedDialog::sendCMD, util, &Util::execCMD);
|
connect(&dialog, &MF_Attack_hardnestedDialog::sendCMD, util, &Util::execCMD);
|
||||||
if(dialog.exec() == QDialog::Accepted)
|
if(dialog.exec() == QDialog::Accepted)
|
||||||
ui->funcTab->setCurrentIndex(1);
|
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()
|
void Mifare::sniff()
|
||||||
{
|
{
|
||||||
util->execCMD("hf mf sniff");
|
if(Util::getClientType() == Util::CLIENTTYPE_OFFICIAL)
|
||||||
ui->funcTab->setCurrentIndex(1);
|
util->execCMD("hf mf sniff");
|
||||||
|
else if(Util::getClientType() == Util::CLIENTTYPE_ICEMAN)
|
||||||
|
util->execCMD("hf sniff");
|
||||||
|
|
||||||
|
Util::gotoRawTab();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mifare::snoop()
|
void Mifare::sniff14a()
|
||||||
{
|
{
|
||||||
util->execCMD("hf 14a snoop");
|
if(Util::getClientType() == Util::CLIENTTYPE_OFFICIAL)
|
||||||
ui->funcTab->setCurrentIndex(1);
|
util->execCMD("hf 14a snoop");
|
||||||
|
else if(Util::getClientType() == Util::CLIENTTYPE_ICEMAN)
|
||||||
|
util->execCMD("hf 14a sniff");
|
||||||
|
|
||||||
|
Util::gotoRawTab();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mifare::list()
|
void Mifare::list()
|
||||||
{
|
{
|
||||||
util->execCMD("hf list mf");
|
if(Util::getClientType() == Util::CLIENTTYPE_OFFICIAL)
|
||||||
ui->funcTab->setCurrentIndex(1);
|
util->execCMD("hf list mf");
|
||||||
|
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 Mifare::_readblk(int blockId, KeyType keyType, const QString& key, TargetType targetType, int waitTime)
|
||||||
{
|
{
|
||||||
QString data;
|
QString data;
|
||||||
QString result;
|
QString result;
|
||||||
bool isKeyBlock = (blockId < 128 && ((blockId + 1) % 4 == 0)) || ((blockId + 1) % 16 == 0);
|
QRegularExpressionMatch currMatch;
|
||||||
|
bool isTrailerBlock = (blockId < 128 && ((blockId + 1) % 4 == 0)) || ((blockId + 1) % 16 == 0);
|
||||||
|
|
||||||
if(util->getClientType() == Util::CLIENTTYPE_OFFICIAL || util->getClientType() == Util::CLIENTTYPE_ICEMAN)
|
if(Util::getClientType() == Util::CLIENTTYPE_OFFICIAL || Util::getClientType() == Util::CLIENTTYPE_ICEMAN)
|
||||||
{
|
{
|
||||||
if(targetType == TARGET_MIFARE)
|
if(targetType == TARGET_MIFARE)
|
||||||
{
|
{
|
||||||
@@ -292,13 +322,14 @@ QString Mifare::_readblk(int blockId, KeyType keyType, const QString& key, Targe
|
|||||||
+ " "
|
+ " "
|
||||||
+ key,
|
+ key,
|
||||||
waitTime);
|
waitTime);
|
||||||
if(result.indexOf("isOk:01") != -1)
|
currMatch = dataPattern->match(result);
|
||||||
|
if(currMatch.hasMatch())
|
||||||
{
|
{
|
||||||
data = dataPattern->match(result).captured().toUpper();
|
data = currMatch.captured().toUpper();
|
||||||
data.remove(" ");
|
data.remove(" ");
|
||||||
// when the target block is a key block and the given key type is KeyA, try to check whether the KeyB is valid(by Access Bits)
|
// when the target block is a key block and the given key type is KeyA, try to check whether the KeyB is valid(by Access Bits)
|
||||||
// if the given key type is KeyB, it will never get the KeyA from the key block
|
// if the given key type is KeyB, it will never get the KeyA from the key block
|
||||||
if(isKeyBlock && keyType == KEY_A) // in this case, the Access Bits is always accessible
|
if(isTrailerBlock && keyType == KEY_A) // in this case, the Access Bits is always accessible
|
||||||
{
|
{
|
||||||
data.replace(0, 12, key);
|
data.replace(0, 12, key);
|
||||||
QList<quint8> ACBits = data_getACBits(data.mid(12, 8));
|
QList<quint8> ACBits = data_getACBits(data.mid(12, 8));
|
||||||
@@ -307,7 +338,7 @@ QString Mifare::_readblk(int blockId, KeyType keyType, const QString& key, Targe
|
|||||||
data.replace(20, 12, "????????????");
|
data.replace(20, 12, "????????????");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(isKeyBlock && keyType == KEY_B)
|
else if(isTrailerBlock && keyType == KEY_B)
|
||||||
{
|
{
|
||||||
data.replace(20, 12, key);;
|
data.replace(20, 12, key);;
|
||||||
data.replace(0, 12, "????????????"); // fill the keyA part with ?
|
data.replace(0, 12, "????????????"); // fill the keyA part with ?
|
||||||
@@ -322,15 +353,19 @@ QString Mifare::_readblk(int blockId, KeyType keyType, const QString& key, Targe
|
|||||||
"hf mf cgetblk "
|
"hf mf cgetblk "
|
||||||
+ QString::number(blockId),
|
+ QString::number(blockId),
|
||||||
waitTime);
|
waitTime);
|
||||||
if(result.indexOf("Chinese magic") != -1)
|
currMatch = dataPattern->match(result);
|
||||||
|
if(currMatch.hasMatch())
|
||||||
{
|
{
|
||||||
data = dataPattern->match(result).captured().toUpper();
|
data = currMatch.captured().toUpper();
|
||||||
data.remove(" ");
|
data.remove(" ");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
data = "";
|
data = "";
|
||||||
}
|
}
|
||||||
else if(targetType == TARGET_EMULATOR)
|
}
|
||||||
|
if(Util::getClientType() == Util::CLIENTTYPE_OFFICIAL)
|
||||||
|
{
|
||||||
|
if(targetType == TARGET_EMULATOR)
|
||||||
{
|
{
|
||||||
result = util->execCMDWithOutput(
|
result = util->execCMDWithOutput(
|
||||||
"hf mf eget "
|
"hf mf eget "
|
||||||
@@ -340,6 +375,18 @@ QString Mifare::_readblk(int blockId, KeyType keyType, const QString& key, Targe
|
|||||||
data.remove(" ");
|
data.remove(" ");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if(Util::getClientType() == Util::CLIENTTYPE_ICEMAN)
|
||||||
|
{
|
||||||
|
if(targetType == TARGET_EMULATOR)
|
||||||
|
{
|
||||||
|
result = util->execCMDWithOutput(
|
||||||
|
"hf mf egetblk "
|
||||||
|
+ QString::number(blockId),
|
||||||
|
150);
|
||||||
|
data = dataPattern->match(result).captured().toUpper();
|
||||||
|
data.remove(" ");
|
||||||
|
}
|
||||||
|
}
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -348,14 +395,14 @@ QStringList Mifare::_readsec(int sectorId, KeyType keyType, const QString& key,
|
|||||||
QStringList data;
|
QStringList data;
|
||||||
QString result, tmp;
|
QString result, tmp;
|
||||||
QRegularExpressionMatch reMatch;
|
QRegularExpressionMatch reMatch;
|
||||||
int offset = -1;
|
int offset = -1; // for targetType == TARGET_EMULATOR
|
||||||
|
|
||||||
for(int i = 0; i < cardType.blk[sectorId]; i++)
|
for(int i = 0; i < cardType.blk[sectorId]; i++)
|
||||||
{
|
{
|
||||||
data.append("");
|
data.append("");
|
||||||
}
|
}
|
||||||
|
|
||||||
if(util->getClientType() == Util::CLIENTTYPE_OFFICIAL || util->getClientType() == Util::CLIENTTYPE_ICEMAN)
|
if(Util::getClientType() == Util::CLIENTTYPE_OFFICIAL || Util::getClientType() == Util::CLIENTTYPE_ICEMAN)
|
||||||
{
|
{
|
||||||
// try to read all blocks together
|
// try to read all blocks together
|
||||||
if(targetType == TARGET_MIFARE)
|
if(targetType == TARGET_MIFARE)
|
||||||
@@ -372,7 +419,6 @@ QStringList Mifare::_readsec(int sectorId, KeyType keyType, const QString& key,
|
|||||||
+ " "
|
+ " "
|
||||||
+ key,
|
+ key,
|
||||||
waitTime);
|
waitTime);
|
||||||
offset = result.indexOf("isOk:01");
|
|
||||||
}
|
}
|
||||||
else if(targetType == TARGET_UID)
|
else if(targetType == TARGET_UID)
|
||||||
{
|
{
|
||||||
@@ -380,9 +426,18 @@ QStringList Mifare::_readsec(int sectorId, KeyType keyType, const QString& key,
|
|||||||
"hf mf cgetsc "
|
"hf mf cgetsc "
|
||||||
+ QString::number(sectorId),
|
+ QString::number(sectorId),
|
||||||
waitTime);
|
waitTime);
|
||||||
offset = result.indexOf("Chinese magic");
|
|
||||||
}
|
}
|
||||||
if(offset != -1)
|
else if(targetType == TARGET_EMULATOR)
|
||||||
|
{
|
||||||
|
for(int i = 0; i < cardType.blk[sectorId]; i++)
|
||||||
|
data[i] = _readblk(cardType.blks[sectorId] + i, keyType, key, targetType, waitTime);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
// for TARGET_MIFARE and TARGET_UID
|
||||||
|
reMatch = dataPattern->match(result);
|
||||||
|
offset = reMatch.capturedStart();
|
||||||
|
if(reMatch.hasMatch()) // read successful
|
||||||
{
|
{
|
||||||
for(int i = 0; i < cardType.blk[sectorId]; i++)
|
for(int i = 0; i < cardType.blk[sectorId]; i++)
|
||||||
{
|
{
|
||||||
@@ -397,13 +452,11 @@ 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
|
||||||
// (when one of the block cannot be read, the rdsc will return nothing, so you need to read the rest of blocks manually)
|
// the following rdbl operation is not handled there, for better speed(rdsc_A->rdsc_B->rdbl0~3)
|
||||||
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) // treat as MIFARE
|
||||||
{
|
data = _readsec(sectorId, keyType, key, TARGET_MIFARE, waitTime);
|
||||||
for(int i = 0; i < cardType.blk[sectorId]; i++)
|
|
||||||
data[i] = _readblk(cardType.blks[sectorId] + i, keyType, key, targetType, waitTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
//process trailer(like _readblk())
|
//process trailer(like _readblk())
|
||||||
QString trailer = data[cardType.blk[sectorId] - 1];
|
QString trailer = data[cardType.blk[sectorId] - 1];
|
||||||
@@ -446,7 +499,6 @@ void Mifare::readOne(TargetType targetType)
|
|||||||
|
|
||||||
void Mifare::readSelected(TargetType targetType)
|
void Mifare::readSelected(TargetType targetType)
|
||||||
{
|
{
|
||||||
QStringList data, dataA, dataB;
|
|
||||||
QString trailerA, trailerB;
|
QString trailerA, trailerB;
|
||||||
QList<bool> selectedSectors;
|
QList<bool> selectedSectors;
|
||||||
QList<int> selectedBlocks;
|
QList<int> selectedBlocks;
|
||||||
@@ -467,67 +519,81 @@ void Mifare::readSelected(TargetType targetType)
|
|||||||
|
|
||||||
for(int i = 0; i < cardType.sector_size; i++)
|
for(int i = 0; i < cardType.sector_size; i++)
|
||||||
{
|
{
|
||||||
|
if(!selectedSectors[i])
|
||||||
|
continue;
|
||||||
|
|
||||||
|
QStringList data, dataA, dataB;
|
||||||
|
for(int j = 0; j < cardType.blk[i]; j++)
|
||||||
{
|
{
|
||||||
if(!selectedSectors[i])
|
// dataA is always filled with "" because of the _readsec()
|
||||||
|
data.append("");
|
||||||
|
dataB.append("");
|
||||||
|
}
|
||||||
|
|
||||||
|
dataA = _readsec(i, Mifare::KEY_A, keyAList->at(i), targetType);
|
||||||
|
|
||||||
|
// in other situations, the key doesn't matters
|
||||||
|
// so the dataA is the final result
|
||||||
|
//
|
||||||
|
// if the targetType is TARGET_MIFARE and the dataA has unknown part, try to read by keyB
|
||||||
|
if(targetType == TARGET_MIFARE && (dataA.contains("") || dataA[cardType.blk[i] - 1].right(12) == "????????????"))
|
||||||
|
dataB = _readsec(i, Mifare::KEY_B, keyBList->at(i), targetType);
|
||||||
|
|
||||||
|
// process trailer block seperately
|
||||||
|
if(dataA[cardType.blk[i] - 1] == "" && selectedBlocks.contains(getTrailerBlockId(i)))
|
||||||
|
dataA[cardType.blk[i] - 1] = _readblk(getTrailerBlockId(i), Mifare::KEY_A, keyAList->at(i), targetType);
|
||||||
|
if(dataB[cardType.blk[i] - 1] == "" && dataA[cardType.blk[i] - 1].right(12) == "????????????" && selectedBlocks.contains(getTrailerBlockId(i)))
|
||||||
|
dataB[cardType.blk[i] - 1] = _readblk(getTrailerBlockId(i), Mifare::KEY_B, keyBList->at(i), targetType);
|
||||||
|
|
||||||
|
|
||||||
|
for(int j = 0; j < cardType.blk[i]; j++)
|
||||||
|
{
|
||||||
|
if(dataA[j] != "")
|
||||||
|
data[j] = dataA[j];
|
||||||
|
else
|
||||||
|
data[j] = dataB[j];
|
||||||
|
|
||||||
|
if(data[j] == "" && selectedBlocks.contains(cardType.blks[i] + j)) // try rdbl seperately
|
||||||
{
|
{
|
||||||
continue;
|
data[j] = _readblk(cardType.blks[i] + j, Mifare::KEY_A, keyAList->at(i), targetType);
|
||||||
|
if(data[j] == "")
|
||||||
|
data[j] = _readblk(cardType.blks[i] + j, Mifare::KEY_B, keyBList->at(i), targetType);
|
||||||
}
|
}
|
||||||
for(int j = 0; j < cardType.blk[i]; j++)
|
}
|
||||||
|
|
||||||
|
// process trailer block seperately
|
||||||
|
trailerA = dataA[cardType.blk[i] - 1];
|
||||||
|
trailerB = dataB[cardType.blk[i] - 1];
|
||||||
|
if(trailerA != "" && trailerB != "") // if KeyA and KeyB can both read the trailer, then concat them
|
||||||
|
{
|
||||||
|
QString ACbits = trailerA.mid(12, 8);
|
||||||
|
QString key_A = trailerA.left(12); // KeyA cannot be read by KeyB
|
||||||
|
QString key_B = trailerA.at(31) != '?' ? trailerA.right(12) : trailerB.right(12);
|
||||||
|
data[cardType.blk[i] - 1] = key_A + ACbits + key_B;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int j = 0; j < cardType.blk[i]; j++)
|
||||||
|
{
|
||||||
|
if(selectedBlocks.contains(cardType.blks[i] + j))
|
||||||
{
|
{
|
||||||
// dataA is always filled with "" because of the _readsec()
|
dataList->replace(cardType.blks[i] + j, data[j]);
|
||||||
data.append("");
|
data_syncWithDataWidget(false, cardType.blks[i] + j);
|
||||||
dataB.append("");
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
dataA = _readsec(i, Mifare::KEY_A, keyAList->at(i), targetType);
|
if(selectedBlocks.contains(getTrailerBlockId(i)))
|
||||||
|
{
|
||||||
// in other situations, the key doesn't matters
|
// data widget has been updated, so this is just a temporary varient.
|
||||||
if(targetType == TARGET_MIFARE && (dataA.contains("") || dataA[cardType.blk[i] - 1].right(12) == "????????????"))
|
if(data[cardType.blk[i] - 1] == "")
|
||||||
dataB = _readsec(i, Mifare::KEY_B, keyBList->at(i), targetType);
|
data[cardType.blk[i] - 1] = "????????????????????????????????";
|
||||||
|
|
||||||
for(int j = 0; j < cardType.blk[i]; j++)
|
|
||||||
{
|
|
||||||
if(dataA[j] != "")
|
|
||||||
data[j] = dataA[j];
|
|
||||||
else
|
|
||||||
data[j] = dataB[j];
|
|
||||||
}
|
|
||||||
|
|
||||||
// process trailer block seperately
|
|
||||||
trailerA = dataA[cardType.blk[i] - 1];
|
|
||||||
trailerB = dataB[cardType.blk[i] - 1];
|
|
||||||
if(trailerA != "" && trailerB != "")
|
|
||||||
{
|
|
||||||
QString ACbits = trailerA.mid(12, 8);
|
|
||||||
QString key_A = trailerA.left(12);
|
|
||||||
QString key_B = trailerA.at(31) != '?' ? trailerA.right(12) : trailerB.right(12);
|
|
||||||
data[cardType.blk[i] - 1] = key_A + ACbits + key_B;
|
|
||||||
}
|
|
||||||
|
|
||||||
for(int j = 0; j < cardType.blk[i]; j++)
|
|
||||||
{
|
|
||||||
if(selectedBlocks.contains(cardType.blks[i] + j))
|
|
||||||
{
|
|
||||||
dataList->replace(cardType.blks[i] + j, data[j]);
|
|
||||||
data_syncWithDataWidget(false, cardType.blks[i] + j);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(selectedBlocks.contains(cardType.blks[i] + cardType.blk[i] - 1))
|
|
||||||
{
|
|
||||||
// data widget has been updated, so this is just a temporary varient.
|
|
||||||
if(data[cardType.blk[i] - 1] == "")
|
|
||||||
data[cardType.blk[i] - 1] = "????????????????????????????????";
|
|
||||||
|
|
||||||
// doesn't replace the existing key.
|
|
||||||
if(!data_isKeyValid(keyAList->at(i)))
|
|
||||||
keyAList->replace(i, data[cardType.blk[i] - 1].left(12));
|
|
||||||
if(!data_isKeyValid(keyBList->at(i)))
|
|
||||||
keyBList->replace(i, data[cardType.blk[i] - 1].right(12));
|
|
||||||
data_syncWithKeyWidget(false, i, KEY_A);
|
|
||||||
data_syncWithKeyWidget(false, i, KEY_B);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// doesn't replace the existing key.
|
||||||
|
if(!data_isKeyValid(keyAList->at(i)))
|
||||||
|
keyAList->replace(i, data[cardType.blk[i] - 1].left(12));
|
||||||
|
if(!data_isKeyValid(keyBList->at(i)))
|
||||||
|
keyBList->replace(i, data[cardType.blk[i] - 1].right(12));
|
||||||
|
data_syncWithKeyWidget(false, i, KEY_A);
|
||||||
|
data_syncWithKeyWidget(false, i, KEY_B);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -536,12 +602,12 @@ bool Mifare::_writeblk(int blockId, KeyType keyType, const QString& key, const Q
|
|||||||
{
|
{
|
||||||
QString result;
|
QString result;
|
||||||
QString input = data.toUpper();
|
QString input = data.toUpper();
|
||||||
input.remove(" ");
|
|
||||||
|
|
||||||
|
input.remove(" ");
|
||||||
if(data_isDataValid(input) != DATA_NOSPACE)
|
if(data_isDataValid(input) != DATA_NOSPACE)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if(util->getClientType() == Util::CLIENTTYPE_OFFICIAL || util->getClientType() == Util::CLIENTTYPE_ICEMAN)
|
if(Util::getClientType() == Util::CLIENTTYPE_OFFICIAL || Util::getClientType() == Util::CLIENTTYPE_ICEMAN)
|
||||||
{
|
{
|
||||||
if(targetType == TARGET_MIFARE)
|
if(targetType == TARGET_MIFARE)
|
||||||
{
|
{
|
||||||
@@ -567,7 +633,7 @@ bool Mifare::_writeblk(int blockId, KeyType keyType, const QString& key, const Q
|
|||||||
+ " "
|
+ " "
|
||||||
+ input,
|
+ input,
|
||||||
waitTime);
|
waitTime);
|
||||||
return (result.indexOf("Chinese magic") != -1);
|
return (result.indexOf("error") == -1); // failed flag
|
||||||
}
|
}
|
||||||
else if(targetType == TARGET_EMULATOR)
|
else if(targetType == TARGET_EMULATOR)
|
||||||
{
|
{
|
||||||
@@ -580,6 +646,7 @@ bool Mifare::_writeblk(int blockId, KeyType keyType, const QString& key, const Q
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mifare::writeOne(TargetType targetType)
|
void Mifare::writeOne(TargetType targetType)
|
||||||
@@ -601,6 +668,8 @@ void Mifare::writeSelected(TargetType targetType)
|
|||||||
{
|
{
|
||||||
QList<int> failedBlocks;
|
QList<int> failedBlocks;
|
||||||
QList<int> selectedBlocks;
|
QList<int> selectedBlocks;
|
||||||
|
bool yes2All = false, no2All = false;
|
||||||
|
|
||||||
for(int i = 0; i < cardType.block_size; i++)
|
for(int i = 0; i < cardType.block_size; i++)
|
||||||
{
|
{
|
||||||
if(ui->MF_dataWidget->item(i, 1)->checkState() == Qt::Checked)
|
if(ui->MF_dataWidget->item(i, 1)->checkState() == Qt::Checked)
|
||||||
@@ -609,6 +678,29 @@ void Mifare::writeSelected(TargetType targetType)
|
|||||||
for(int item : selectedBlocks)
|
for(int item : selectedBlocks)
|
||||||
{
|
{
|
||||||
bool result = false;
|
bool result = false;
|
||||||
|
bool isTrailerBlock = (item < 128 && ((item + 1) % 4 == 0)) || ((item + 1) % 16 == 0);
|
||||||
|
|
||||||
|
if(isTrailerBlock && !data_isACBitsValid(dataList->at(item).mid(12, 8))) // trailer block is invalid
|
||||||
|
{
|
||||||
|
if(!yes2All && !no2All)
|
||||||
|
{
|
||||||
|
QMessageBox::StandardButton choice = QMessageBox::information(parent, tr("Info"),
|
||||||
|
tr("The Access Bits is invalid!\nIt could make the whole sector blocked irreversibly!\nContinue to write?"),
|
||||||
|
QMessageBox::Yes | QMessageBox::YesToAll | QMessageBox::No | QMessageBox::NoToAll);
|
||||||
|
if(choice == QMessageBox::No)
|
||||||
|
continue;
|
||||||
|
else if(choice == QMessageBox::YesToAll)
|
||||||
|
yes2All = true;
|
||||||
|
else if(choice == QMessageBox::NoToAll)
|
||||||
|
{
|
||||||
|
no2All = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(no2All)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if(targetType == TARGET_MIFARE)
|
if(targetType == TARGET_MIFARE)
|
||||||
{
|
{
|
||||||
result = _writeblk(item, KEY_A, keyAList->at(data_b2s(item)), dataList->at(item), TARGET_MIFARE);
|
result = _writeblk(item, KEY_A, keyAList->at(data_b2s(item)), dataList->at(item), TARGET_MIFARE);
|
||||||
@@ -667,23 +759,32 @@ void Mifare::writeSelected(TargetType targetType)
|
|||||||
|
|
||||||
void Mifare::dump()
|
void Mifare::dump()
|
||||||
{
|
{
|
||||||
util->execCMD("hf mf dump");
|
if(Util::getClientType() == Util::CLIENTTYPE_OFFICIAL || Util::getClientType() == Util::CLIENTTYPE_ICEMAN)
|
||||||
ui->funcTab->setCurrentIndex(1);
|
util->execCMD("hf mf dump");
|
||||||
|
Util::gotoRawTab();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mifare::restore()
|
void Mifare::restore()
|
||||||
{
|
{
|
||||||
util->execCMD("hf mf restore");
|
if(Util::getClientType() == Util::CLIENTTYPE_OFFICIAL || Util::getClientType() == Util::CLIENTTYPE_ICEMAN)
|
||||||
ui->funcTab->setCurrentIndex(1);
|
util->execCMD("hf mf restore");
|
||||||
|
Util::gotoRawTab();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mifare::wipeC()
|
void Mifare::wipeC()
|
||||||
{
|
{
|
||||||
util->execCMD(
|
if(Util::getClientType() == Util::CLIENTTYPE_OFFICIAL)
|
||||||
"hf mf cwipe "
|
{
|
||||||
+ QString::number(cardType.type)
|
util->execCMD(
|
||||||
+ " f");
|
"hf mf cwipe "
|
||||||
ui->funcTab->setCurrentIndex(1);
|
+ QString::number(cardType.type)
|
||||||
|
+ " f");
|
||||||
|
}
|
||||||
|
else if(Util::getClientType() == Util::CLIENTTYPE_ICEMAN)
|
||||||
|
{
|
||||||
|
util->execCMD("hf mf cwipe");
|
||||||
|
}
|
||||||
|
Util::gotoRawTab();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mifare::setParameterC()
|
void Mifare::setParameterC()
|
||||||
@@ -693,50 +794,78 @@ void Mifare::setParameterC()
|
|||||||
QMessageBox::information(parent, tr("Info"), tr("Failed to read card."));
|
QMessageBox::information(parent, tr("Info"), tr("Failed to read card."));
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
QStringList lis = result.split("\r\n");
|
result.replace("\r\n", "");
|
||||||
lis[0].replace(" ", "");
|
result.replace(QRegularExpression("\\[.\\]"), "");
|
||||||
lis[1].replace(" ", "");
|
result.replace("UID", "");
|
||||||
lis[2].replace(" ", "");
|
result.replace("ATQA", "");
|
||||||
MF_UID_parameterDialog dialog(lis[0].toUpper(), lis[1].toUpper(), lis[2].mid(0, 2).toUpper());
|
result.replace("SAK", "");
|
||||||
|
result.replace(" ", "");
|
||||||
|
QStringList lis = result.split(':');
|
||||||
|
qDebug() << lis;
|
||||||
|
MF_UID_parameterDialog dialog(lis[1].toUpper(), lis[2].toUpper(), lis[3].toUpper());
|
||||||
connect(&dialog, &MF_UID_parameterDialog::sendCMD, util, &Util::execCMD);
|
connect(&dialog, &MF_UID_parameterDialog::sendCMD, util, &Util::execCMD);
|
||||||
if(dialog.exec() == QDialog::Accepted)
|
if(dialog.exec() == QDialog::Accepted)
|
||||||
ui->funcTab->setCurrentIndex(1);
|
Util::gotoRawTab();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mifare::lockC()
|
void Mifare::lockC()
|
||||||
{
|
{
|
||||||
util->execCMD("hf 14a raw -pa -b7 40");
|
if(Util::getClientType() == Util::CLIENTTYPE_OFFICIAL)
|
||||||
util->execCMD("hf 14a raw -pa 43");
|
{
|
||||||
util->execCMD("hf 14a raw -pa E0 00 39 F7");
|
util->execCMD("hf 14a raw -pa -b7 40");
|
||||||
util->execCMD("hf 14a raw -pa E1 00 E1 EE");
|
util->execCMD("hf 14a raw -pa 43");
|
||||||
util->execCMD("hf 14a raw -pa 85 00 00 00 00 00 00 00 00 00 00 00 00 00 00 08 18 47");
|
util->execCMD("hf 14a raw -pa E0 00 39 F7");
|
||||||
util->execCMD("hf 14a raw 52");
|
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 -a 52");
|
||||||
|
}
|
||||||
|
else if(Util::getClientType() == Util::CLIENTTYPE_ICEMAN)
|
||||||
|
{
|
||||||
|
util->execCMD("hf 14a raw -ak -b 7 40");
|
||||||
|
util->execCMD("hf 14a raw -ak 43");
|
||||||
|
util->execCMD("hf 14a raw -ak E0 00 39 F7");
|
||||||
|
util->execCMD("hf 14a raw -ak E1 00 E1 EE");
|
||||||
|
util->execCMD("hf 14a raw -ak 85 00 00 00 00 00 00 00 00 00 00 00 00 00 00 08 18 47");
|
||||||
|
util->execCMD("hf 14a raw -a 52");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mifare::wipeE()
|
void Mifare::wipeE()
|
||||||
{
|
{
|
||||||
util->execCMD("hf mf eclr");
|
if(Util::getClientType() == Util::CLIENTTYPE_OFFICIAL || Util::getClientType() == Util::CLIENTTYPE_ICEMAN)
|
||||||
|
util->execCMD("hf mf eclr");
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mifare::simulate()
|
void Mifare::simulate()
|
||||||
{
|
{
|
||||||
MF_Sim_simDialog dialog(cardType.type);
|
MF_Sim_simDialog dialog(cardType.type, cardType.typeText);
|
||||||
connect(&dialog, &MF_Sim_simDialog::sendCMD, util, &Util::execCMD);
|
connect(&dialog, &MF_Sim_simDialog::sendCMD, util, &Util::execCMD);
|
||||||
if(dialog.exec() == QDialog::Accepted)
|
if(dialog.exec() == QDialog::Accepted)
|
||||||
ui->funcTab->setCurrentIndex(1);
|
Util::gotoRawTab();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mifare::loadSniff(const QString& file)
|
void Mifare::loadSniff(const QString& file)
|
||||||
{
|
{
|
||||||
util->execCMD("hf list mf -l " + file);
|
if(Util::getClientType() == Util::CLIENTTYPE_OFFICIAL)
|
||||||
ui->funcTab->setCurrentIndex(1);
|
util->execCMD("hf list mf -l " + file);
|
||||||
|
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)
|
void Mifare::saveSniff(const QString& file)
|
||||||
{
|
{
|
||||||
util->execCMD("hf list mf -s " + file);
|
if(Util::getClientType() == Util::CLIENTTYPE_OFFICIAL)
|
||||||
ui->funcTab->setCurrentIndex(1);
|
util->execCMD("hf list mf -s " + file);
|
||||||
|
else if(Util::getClientType() == Util::CLIENTTYPE_ICEMAN)
|
||||||
|
util->execCMD("trace save -f " + file);
|
||||||
|
|
||||||
|
Util::gotoRawTab();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mifare::data_syncWithDataWidget(bool syncAll, int block)
|
void Mifare::data_syncWithDataWidget(bool syncAll, int block)
|
||||||
@@ -846,7 +975,7 @@ void Mifare::data_clearKey(bool clearAll)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Mifare::data_isKeyValid(const QString &key)
|
bool Mifare::data_isKeyValid(const QString& key)
|
||||||
{
|
{
|
||||||
if(key.length() != 12)
|
if(key.length() != 12)
|
||||||
return false;
|
return false;
|
||||||
@@ -912,7 +1041,7 @@ void Mifare::setCardType(int type)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Mifare::data_loadDataFile(const QString &filename)
|
bool Mifare::data_loadDataFile(const QString& filename)
|
||||||
{
|
{
|
||||||
QFile file(filename, this);
|
QFile file(filename, this);
|
||||||
if(file.open(QIODevice::ReadOnly))
|
if(file.open(QIODevice::ReadOnly))
|
||||||
@@ -959,7 +1088,7 @@ bool Mifare::data_loadDataFile(const QString &filename)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Mifare::data_loadKeyFile(const QString &filename)
|
bool Mifare::data_loadKeyFile(const QString& filename)
|
||||||
{
|
{
|
||||||
QFile file(filename, this);
|
QFile file(filename, this);
|
||||||
if(file.open(QIODevice::ReadOnly))
|
if(file.open(QIODevice::ReadOnly))
|
||||||
@@ -980,7 +1109,7 @@ bool Mifare::data_loadKeyFile(const QString &filename)
|
|||||||
{
|
{
|
||||||
for(int i = 0; i < cardType.sector_size; i++)
|
for(int i = 0; i < cardType.sector_size; i++)
|
||||||
{
|
{
|
||||||
int blk = cardType.blks[i] + cardType.blk[i] - 1;
|
int blk = getTrailerBlockId(i);
|
||||||
QString tmp = bin2text(buff, blk, 16);
|
QString tmp = bin2text(buff, blk, 16);
|
||||||
keyAList->replace(i, tmp.left(12).toUpper());
|
keyAList->replace(i, tmp.left(12).toUpper());
|
||||||
keyBList->replace(i, tmp.right(12).toUpper());
|
keyBList->replace(i, tmp.right(12).toUpper());
|
||||||
@@ -996,7 +1125,7 @@ bool Mifare::data_loadKeyFile(const QString &filename)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QString Mifare::bin2text(const QByteArray &buff, int i, int length)
|
QString Mifare::bin2text(const QByteArray& buff, int i, int length)
|
||||||
{
|
{
|
||||||
QString ret = "";
|
QString ret = "";
|
||||||
char LByte, RByte;
|
char LByte, RByte;
|
||||||
@@ -1014,7 +1143,7 @@ QString Mifare::bin2text(const QByteArray &buff, int i, int length)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Mifare::data_saveDataFile(const QString &filename, bool isBin)
|
bool Mifare::data_saveDataFile(const QString& filename, bool isBin)
|
||||||
{
|
{
|
||||||
QFile file(filename, this);
|
QFile file(filename, this);
|
||||||
if(file.open(QIODevice::WriteOnly))
|
if(file.open(QIODevice::WriteOnly))
|
||||||
@@ -1058,7 +1187,7 @@ bool Mifare::data_saveDataFile(const QString &filename, bool isBin)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Mifare::data_saveKeyFile(const QString &filename, bool isBin)
|
bool Mifare::data_saveKeyFile(const QString& filename, bool isBin)
|
||||||
{
|
{
|
||||||
QFile file(filename, this);
|
QFile file(filename, this);
|
||||||
if(file.open(QIODevice::WriteOnly))
|
if(file.open(QIODevice::WriteOnly))
|
||||||
@@ -1120,17 +1249,17 @@ void Mifare::data_key2Data()
|
|||||||
else
|
else
|
||||||
tmp += "????????????";
|
tmp += "????????????";
|
||||||
|
|
||||||
if(dataList->at(cardType.blks[i] + cardType.blk[i] - 1) == "")
|
if(dataList->at(getTrailerBlockId(i)) == "")
|
||||||
tmp += "FF078069"; // default control bytes
|
tmp += "FF078069"; // default control bytes
|
||||||
else
|
else
|
||||||
tmp += dataList->at(cardType.blks[i] + cardType.blk[i] - 1).mid(12, 8);
|
tmp += dataList->at(getTrailerBlockId(i)).mid(12, 8);
|
||||||
|
|
||||||
if(data_isKeyValid(keyBList->at(i)))
|
if(data_isKeyValid(keyBList->at(i)))
|
||||||
tmp += keyBList->at(i);
|
tmp += keyBList->at(i);
|
||||||
else
|
else
|
||||||
tmp += "????????????";
|
tmp += "????????????";
|
||||||
|
|
||||||
dataList->replace(cardType.blks[i] + cardType.blk[i] - 1, tmp);
|
dataList->replace(getTrailerBlockId(i), tmp);
|
||||||
data_syncWithDataWidget();
|
data_syncWithDataWidget();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1139,26 +1268,26 @@ void Mifare::data_data2Key()
|
|||||||
{
|
{
|
||||||
for(int i = 0; i < cardType.sector_size; i++)
|
for(int i = 0; i < cardType.sector_size; i++)
|
||||||
{
|
{
|
||||||
if(dataList->at(cardType.blks[i] + cardType.blk[i] - 1) == "")
|
if(dataList->at(getTrailerBlockId(i)) == "")
|
||||||
{
|
{
|
||||||
keyAList->replace(i, "????????????");
|
keyAList->replace(i, "????????????");
|
||||||
keyBList->replace(i, "????????????");
|
keyBList->replace(i, "????????????");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
keyAList->replace(i, dataList->at(cardType.blks[i] + cardType.blk[i] - 1).left(12));
|
keyAList->replace(i, dataList->at(getTrailerBlockId(i)).left(12));
|
||||||
keyBList->replace(i, dataList->at(cardType.blks[i] + cardType.blk[i] - 1).right(12));
|
keyBList->replace(i, dataList->at(getTrailerBlockId(i)).right(12));
|
||||||
}
|
}
|
||||||
data_syncWithKeyWidget();
|
data_syncWithKeyWidget();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mifare::data_setData(int block, const QString &data)
|
void Mifare::data_setData(int block, const QString& data)
|
||||||
{
|
{
|
||||||
dataList->replace(block, data);
|
dataList->replace(block, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mifare::data_setKey(int sector, KeyType keyType, const QString &key)
|
void Mifare::data_setKey(int sector, KeyType keyType, const QString& key)
|
||||||
{
|
{
|
||||||
if(keyType == KEY_A)
|
if(keyType == KEY_A)
|
||||||
keyAList->replace(sector, key);
|
keyAList->replace(sector, key);
|
||||||
@@ -1192,24 +1321,36 @@ int Mifare::data_b2s(int block)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
QList<quint8> Mifare::data_getACBits(const QString& text) //return empty QList if the text is invalid
|
bool Mifare::data_isACBitsValid(const QString& text, QList<quint8>* returnHalfBytes)
|
||||||
{
|
{
|
||||||
QString input = text;
|
QString input = text;
|
||||||
QList<quint8> result;
|
|
||||||
input.remove(" ");
|
input.remove(" ");
|
||||||
if(input.length() < 6)
|
if(input.length() < 6)
|
||||||
{
|
{
|
||||||
return result;
|
return false;
|
||||||
}
|
}
|
||||||
input = input.left(6);
|
input = input.left(6);
|
||||||
quint32 val = input.toUInt(nullptr, 16);
|
quint32 val = input.toUInt(nullptr, 16);
|
||||||
quint8 halfBytes[6];
|
QList<quint8> halfBytes;
|
||||||
for(int i = 0; i < 6; i++)
|
for(int i = 0; i < 6; i++)
|
||||||
{
|
{
|
||||||
halfBytes[i] = (val >> ((5 - i) * 4)) & 0xf;
|
halfBytes.append((val >> ((5 - i) * 4)) & 0xf);
|
||||||
}
|
}
|
||||||
qDebug() << val;
|
qDebug() << val;
|
||||||
if((~halfBytes[0] & 0xf) == halfBytes[5] && (~halfBytes[1] & 0xf) == halfBytes[2] && (~halfBytes[3] & 0xf) == halfBytes[4])
|
if((~halfBytes[0] & 0xf) == halfBytes[5] && (~halfBytes[1] & 0xf) == halfBytes[2] && (~halfBytes[3] & 0xf) == halfBytes[4])
|
||||||
|
{
|
||||||
|
if(returnHalfBytes != nullptr)
|
||||||
|
*returnHalfBytes = halfBytes;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<quint8> Mifare::data_getACBits(const QString& text) //return empty QList if the text is invalid
|
||||||
|
{
|
||||||
|
QList<quint8> halfBytes, result;
|
||||||
|
if(data_isACBitsValid(text, &halfBytes))
|
||||||
{
|
{
|
||||||
for(int i = 0; i < 4; i++)
|
for(int i = 0; i < 4; i++)
|
||||||
{
|
{
|
||||||
@@ -1219,3 +1360,24 @@ QList<quint8> Mifare::data_getACBits(const QString& text) //return empty QList i
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString Mifare::data_getUID()
|
||||||
|
{
|
||||||
|
if(data_isDataValid(dataList->at(0)))
|
||||||
|
return dataList->at(0).left(8);
|
||||||
|
else
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
quint16 Mifare::getTrailerBlockId(quint8 sectorId, qint8 cardTypeId)
|
||||||
|
{
|
||||||
|
if(cardTypeId == 0)
|
||||||
|
return (card_mini.blks[sectorId] + card_mini.blk[sectorId] - 1);
|
||||||
|
else if(cardTypeId == 1)
|
||||||
|
return (card_1k.blks[sectorId] + card_1k.blk[sectorId] - 1);
|
||||||
|
else if(cardTypeId == 2)
|
||||||
|
return (card_2k.blks[sectorId] + card_2k.blk[sectorId] - 1);
|
||||||
|
else if(cardTypeId == 4)
|
||||||
|
return (card_4k.blks[sectorId] + card_4k.blk[sectorId] - 1);
|
||||||
|
else
|
||||||
|
// other cardTypeId: use current cardtype(include default -1)
|
||||||
|
return (cardType.blks[sectorId] + cardType.blk[sectorId] - 1);
|
||||||
|
}
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ public:
|
|||||||
quint16 block_size;
|
quint16 block_size;
|
||||||
quint8 blk[40];
|
quint8 blk[40];
|
||||||
quint8 blks[40];
|
quint8 blks[40];
|
||||||
|
QString typeText;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum AccessType
|
enum AccessType
|
||||||
@@ -66,9 +67,10 @@ public:
|
|||||||
QString info(bool isRequiringOutput = false);
|
QString info(bool isRequiringOutput = false);
|
||||||
void chk();
|
void chk();
|
||||||
void nested();
|
void nested();
|
||||||
|
void darkside();
|
||||||
void hardnested();
|
void hardnested();
|
||||||
void sniff();
|
void sniff();
|
||||||
void snoop();
|
void sniff14a();
|
||||||
void list();
|
void list();
|
||||||
void readOne(TargetType targetType = TARGET_MIFARE);
|
void readOne(TargetType targetType = TARGET_MIFARE);
|
||||||
void readSelected(TargetType targetType = TARGET_MIFARE);
|
void readSelected(TargetType targetType = TARGET_MIFARE);
|
||||||
@@ -106,8 +108,11 @@ public:
|
|||||||
void saveSniff(const QString& file);
|
void saveSniff(const QString& file);
|
||||||
void data_fillKeys();
|
void data_fillKeys();
|
||||||
|
|
||||||
static QList<quint8> data_getACBits(const QString &text);
|
static QList<quint8> data_getACBits(const QString& text);
|
||||||
static int data_b2s(int block);
|
static int data_b2s(int block);
|
||||||
|
static bool data_isACBitsValid(const QString& text, QList<quint8> *returnHalfBytes = nullptr);
|
||||||
|
QString data_getUID();
|
||||||
|
quint16 getTrailerBlockId(quint8 sectorId, qint8 cardTypeId = -1); // -1: use current cardtype
|
||||||
public slots:
|
public slots:
|
||||||
signals:
|
signals:
|
||||||
|
|
||||||
@@ -124,9 +129,9 @@ private:
|
|||||||
QRegularExpression* keyPattern;
|
QRegularExpression* keyPattern;
|
||||||
QString bin2text(const QByteArray& buff, int start, int length);
|
QString bin2text(const QByteArray& buff, int start, int length);
|
||||||
|
|
||||||
QString _readblk(int blockId, KeyType keyType, const QString &key, TargetType targetType = TARGET_MIFARE, int waitTime = 300);
|
QString _readblk(int blockId, KeyType keyType, const QString& key, TargetType targetType = TARGET_MIFARE, int waitTime = 300);
|
||||||
QStringList _readsec(int sectorId, KeyType keyType, const QString &key, TargetType targetType = TARGET_MIFARE, int waitTime = 300);
|
QStringList _readsec(int sectorId, KeyType keyType, const QString& key, TargetType targetType = TARGET_MIFARE, int waitTime = 300);
|
||||||
bool _writeblk(int blockId, KeyType keyType, const QString &key, const QString &data, TargetType targetType = TARGET_MIFARE, int waitTime = 300);
|
bool _writeblk(int blockId, KeyType keyType, const QString& key, const QString& data, TargetType targetType = TARGET_MIFARE, int waitTime = 300);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // MIFARE_H
|
#endif // MIFARE_H
|
||||||
|
|||||||
@@ -6,8 +6,15 @@ MainWindow::MainWindow(QWidget *parent):
|
|||||||
, ui(new Ui::MainWindow)
|
, ui(new Ui::MainWindow)
|
||||||
{
|
{
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
|
dockAllWindows = new QAction(tr("Dock all windows"), this);
|
||||||
myInfo = new QAction("wh201906", 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);
|
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, [ = ]()
|
connect(myInfo, &QAction::triggered, [ = ]()
|
||||||
{
|
{
|
||||||
QDesktopServices::openUrl(QUrl("https://github.com/wh201906"));
|
QDesktopServices::openUrl(QUrl("https://github.com/wh201906"));
|
||||||
@@ -16,18 +23,40 @@ MainWindow::MainWindow(QWidget *parent):
|
|||||||
{
|
{
|
||||||
QDesktopServices::openUrl(QUrl("https://github.com/wh201906/Proxmark3GUI/releases"));
|
QDesktopServices::openUrl(QUrl("https://github.com/wh201906/Proxmark3GUI/releases"));
|
||||||
});
|
});
|
||||||
this->addAction(myInfo);
|
|
||||||
this->addAction(checkUpdate);
|
|
||||||
|
|
||||||
settings = new QSettings("GUIsettings.ini", QSettings::IniFormat);
|
settings = new QSettings("GUIsettings.ini", QSettings::IniFormat);
|
||||||
|
settings->setIniCodec("UTF-8");
|
||||||
|
|
||||||
pm3Thread = new QThread(this);
|
pm3Thread = new QThread(this);
|
||||||
pm3 = new PM3Process(pm3Thread);
|
pm3 = new PM3Process(pm3Thread);
|
||||||
pm3Thread->start();
|
pm3Thread->start();
|
||||||
pm3state = false;
|
pm3state = false;
|
||||||
|
clientWorkingDir = new QDir;
|
||||||
|
|
||||||
util = new Util(this);
|
util = new Util(this);
|
||||||
|
Util::setUI(ui);
|
||||||
mifare = new Mifare(ui, util, this);
|
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,110 @@ void MainWindow::initUI() // will be called by main.app
|
|||||||
uiInit();
|
uiInit();
|
||||||
signalInit();
|
signalInit();
|
||||||
setState(false);
|
setState(false);
|
||||||
|
dockInit();
|
||||||
}
|
}
|
||||||
|
|
||||||
// ******************** basic functions ********************
|
// ******************** basic functions ********************
|
||||||
|
|
||||||
void MainWindow::on_PM3_refreshPortButton_clicked()
|
void MainWindow::on_portSearchTimer_timeout()
|
||||||
{
|
{
|
||||||
ui->PM3_portBox->clear();
|
QStringList newPortList;
|
||||||
QSerialPort serial;
|
|
||||||
QStringList serialList;
|
|
||||||
foreach(const QSerialPortInfo &info, QSerialPortInfo::availablePorts())
|
foreach(const QSerialPortInfo &info, QSerialPortInfo::availablePorts())
|
||||||
{
|
{
|
||||||
qDebug() << info.isBusy() << info.isNull() << info.portName();
|
// qDebug() << info.isBusy() << info.isNull() << info.portName() << info.description();
|
||||||
serial.setPort(info);
|
if(!info.isNull())
|
||||||
|
newPortList << info.portName();
|
||||||
if(serial.open(QIODevice::ReadWrite))
|
|
||||||
{
|
|
||||||
serialList << info.portName();
|
|
||||||
serial.close();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
foreach(QString port, serialList)
|
if(newPortList != portList) // update PM3_portBox when available ports changed
|
||||||
{
|
{
|
||||||
ui->PM3_portBox->addItem(port);
|
portList = newPortList;
|
||||||
|
ui->PM3_portBox->clear();
|
||||||
|
ui->PM3_portBox->addItems(portList);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::on_PM3_connectButton_clicked()
|
void MainWindow::on_PM3_connectButton_clicked()
|
||||||
{
|
{
|
||||||
qDebug() << "Main:" << QThread::currentThread();
|
qDebug() << "Main:" << QThread::currentThread();
|
||||||
|
|
||||||
QString port = ui->PM3_portBox->currentText();
|
QString port = ui->PM3_portBox->currentText();
|
||||||
if(port == "")
|
QString startArgs = ui->Set_Client_startArgsEdit->text();
|
||||||
QMessageBox::information(NULL, tr("Info"), tr("Plz choose a port first"), QMessageBox::Ok);
|
|
||||||
else
|
// 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());
|
QMessageBox::information(NULL, tr("Info"), tr("Plz choose a port first"), QMessageBox::Ok);
|
||||||
emit connectPM3(ui->PM3_pathEdit->text(), port);
|
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();
|
||||||
|
// use the shell session to keep the environment then read it
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
// cmd /c "<path>">>nul && set
|
||||||
|
envSetProcess.start("cmd");
|
||||||
|
envSetProcess.write(QString("\"" + envScriptPath.absoluteFilePath() + "\">>nul\r\n").toLatin1());
|
||||||
|
envSetProcess.waitForReadyRead(10000);
|
||||||
|
envSetProcess.readAll();
|
||||||
|
envSetProcess.write("set\r\n");
|
||||||
|
#else
|
||||||
|
// need implementation(or test if space works)
|
||||||
|
// sh -c '. "<path>">>/dev/null && env'
|
||||||
|
envSetProcess.start("sh -c \' . \"" + envScriptPath.absoluteFilePath() + "\">>/dev/null && env");
|
||||||
|
#endif
|
||||||
|
envSetProcess.waitForReadyRead(10000);
|
||||||
|
QString envSetResult = QString(envSetProcess.readAll());
|
||||||
|
clientEnv = envSetResult.split(QRegExp("[\r\n]{1,2}"), QString::SkipEmptyParts);
|
||||||
|
if(clientEnv.size() > 2) // the first element is "set" and the last element is the current path
|
||||||
|
{
|
||||||
|
clientEnv.removeFirst();
|
||||||
|
clientEnv.removeLast();
|
||||||
|
emit setProcEnv(&clientEnv);
|
||||||
|
}
|
||||||
|
// qDebug() << "Get Env List" << clientEnv;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
clientEnv.clear();
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
envSetProcess.kill();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::onPM3StateChanged(bool st, QString info)
|
void MainWindow::onPM3StateChanged(bool st, const QString& info)
|
||||||
{
|
{
|
||||||
pm3state = st;
|
pm3state = st;
|
||||||
setState(st);
|
setState(st);
|
||||||
if(st == true)
|
if(st == true)
|
||||||
{
|
{
|
||||||
|
portSearchTimer->stop();
|
||||||
setStatusBar(PM3VersionBar, info);
|
setStatusBar(PM3VersionBar, info);
|
||||||
setStatusBar(connectStatusBar, tr("Connected"));
|
setStatusBar(connectStatusBar, tr("Connected"));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
portSearchTimer->start();
|
||||||
setStatusBar(PM3VersionBar, "");
|
setStatusBar(PM3VersionBar, "");
|
||||||
setStatusBar(connectStatusBar, tr("Not Connected"));
|
setStatusBar(connectStatusBar, tr("Not Connected"));
|
||||||
}
|
}
|
||||||
@@ -104,31 +187,43 @@ void MainWindow::onPM3StateChanged(bool st, QString info)
|
|||||||
|
|
||||||
void MainWindow::on_PM3_disconnectButton_clicked()
|
void MainWindow::on_PM3_disconnectButton_clicked()
|
||||||
{
|
{
|
||||||
pm3state = false;
|
|
||||||
setState(false);
|
|
||||||
emit killPM3();
|
emit killPM3();
|
||||||
emit setSerialListener("", false);
|
emit setSerialListener(false);
|
||||||
setStatusBar(connectStatusBar, tr("Not Connected"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::refreshOutput(const QString& output)
|
void MainWindow::refreshOutput(const QString& output)
|
||||||
{
|
{
|
||||||
// qDebug() << "MainWindow::refresh:" << output;
|
// qDebug() << "MainWindow::refresh:" << output;
|
||||||
ui->Raw_outputEdit->insertPlainText(output);
|
ui->Raw_outputEdit->appendPlainText(output);
|
||||||
ui->Raw_outputEdit->moveCursor(QTextCursor::End);
|
ui->Raw_outputEdit->moveCursor(QTextCursor::End);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::refreshCMD(const QString& cmd)
|
void MainWindow::on_stopButton_clicked()
|
||||||
{
|
{
|
||||||
ui->Raw_CMDEdit->setText(cmd);
|
if(!pm3state)
|
||||||
if(cmd != "" && (ui->Raw_CMDHistoryWidget->count() == 0 || ui->Raw_CMDHistoryWidget->item(ui->Raw_CMDHistoryWidget->count() - 1)->text() != cmd))
|
on_PM3_disconnectButton_clicked();
|
||||||
ui->Raw_CMDHistoryWidget->addItem(cmd);
|
else
|
||||||
|
{
|
||||||
|
on_PM3_disconnectButton_clicked();
|
||||||
|
for(int i = 0; i < 10; i++)
|
||||||
|
{
|
||||||
|
util->delay(200);
|
||||||
|
if(!pm3state)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
emit reconnectPM3();
|
||||||
|
emit setSerialListener(!keepClientActive);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// *********************************************************
|
// *********************************************************
|
||||||
|
|
||||||
// ******************** raw command ********************
|
// ******************** raw command ********************
|
||||||
|
|
||||||
|
void MainWindow::on_Raw_CMDEdit_textChanged(const QString &arg1)
|
||||||
|
{
|
||||||
|
stashedCMDEditText = arg1;
|
||||||
|
}
|
||||||
|
|
||||||
void MainWindow::on_Raw_sendCMDButton_clicked()
|
void MainWindow::on_Raw_sendCMDButton_clicked()
|
||||||
{
|
{
|
||||||
util->execCMD(ui->Raw_CMDEdit->text());
|
util->execCMD(ui->Raw_CMDEdit->text());
|
||||||
@@ -173,17 +268,81 @@ void MainWindow::sendMSG() // send command when pressing Enter
|
|||||||
on_Raw_sendCMDButton_clicked();
|
on_Raw_sendCMDButton_clicked();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void MainWindow::refreshCMD(const QString& cmd)
|
||||||
|
{
|
||||||
|
ui->Raw_CMDEdit->blockSignals(true);
|
||||||
|
ui->Raw_CMDEdit->setText(cmd);
|
||||||
|
if(cmd != "" && (ui->Raw_CMDHistoryWidget->count() == 0 || ui->Raw_CMDHistoryWidget->item(ui->Raw_CMDHistoryWidget->count() - 1)->text() != cmd))
|
||||||
|
ui->Raw_CMDHistoryWidget->addItem(cmd);
|
||||||
|
stashedCMDEditText = cmd;
|
||||||
|
stashedIndex = -1;
|
||||||
|
ui->Raw_CMDEdit->blockSignals(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::on_Raw_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 ********************
|
// ******************** mifare ********************
|
||||||
void MainWindow::MF_onTypeChanged(int id, bool st)
|
void MainWindow::on_MF_keyWidget_resized(QObject* obj_addr, QEvent& event)
|
||||||
{
|
{
|
||||||
typeBtnGroup->blockSignals(true);
|
if(obj_addr == ui->MF_keyWidget && event.type() == QEvent::Resize)
|
||||||
qDebug() << id << typeBtnGroup->checkedId();
|
{
|
||||||
|
QTableWidget* widget = (QTableWidget*)obj_addr;
|
||||||
|
int keyItemWidth = widget->width();
|
||||||
|
keyItemWidth -= widget->verticalScrollBar()->width();
|
||||||
|
keyItemWidth -= 2 * widget->frameWidth();
|
||||||
|
keyItemWidth -= widget->horizontalHeader()->sectionSize(0);
|
||||||
|
widget->horizontalHeader()->resizeSection(1, keyItemWidth / 2);
|
||||||
|
widget->horizontalHeader()->resizeSection(2, keyItemWidth / 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::MF_onMFCardTypeChanged(int id, bool st)
|
||||||
|
{
|
||||||
|
MFCardTypeBtnGroup->blockSignals(true);
|
||||||
|
qDebug() << id << MFCardTypeBtnGroup->checkedId();
|
||||||
if(!st)
|
if(!st)
|
||||||
{
|
{
|
||||||
int result;
|
int result;
|
||||||
if(id > typeBtnGroup->checkedId()) // id is specified in uiInit() with a proper order, so I can compare the size by id.
|
if(id > MFCardTypeBtnGroup->checkedId()) // id is specified in uiInit() with a proper order, so I can compare the size by id.
|
||||||
{
|
{
|
||||||
result = QMessageBox::question(this, tr("Info"), tr("Some of the data and key will be cleared.") + "\n" + tr("Continue?"), QMessageBox::Yes | QMessageBox::No);
|
result = QMessageBox::question(this, tr("Info"), tr("Some of the data and key will be cleared.") + "\n" + tr("Continue?"), QMessageBox::Yes | QMessageBox::No);
|
||||||
}
|
}
|
||||||
@@ -194,7 +353,7 @@ void MainWindow::MF_onTypeChanged(int id, bool st)
|
|||||||
if(result == QMessageBox::Yes)
|
if(result == QMessageBox::Yes)
|
||||||
{
|
{
|
||||||
qDebug() << "Yes";
|
qDebug() << "Yes";
|
||||||
mifare->setCardType(typeBtnGroup->checkedId());
|
mifare->setCardType(MFCardTypeBtnGroup->checkedId());
|
||||||
MF_widgetReset();
|
MF_widgetReset();
|
||||||
mifare->data_syncWithDataWidget();
|
mifare->data_syncWithDataWidget();
|
||||||
mifare->data_syncWithKeyWidget();
|
mifare->data_syncWithKeyWidget();
|
||||||
@@ -202,10 +361,10 @@ void MainWindow::MF_onTypeChanged(int id, bool st)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
qDebug() << "No";
|
qDebug() << "No";
|
||||||
typeBtnGroup->button(id)->setChecked(true);
|
MFCardTypeBtnGroup->button(id)->setChecked(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
typeBtnGroup->blockSignals(false);
|
MFCardTypeBtnGroup->blockSignals(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::on_MF_selectAllBox_stateChanged(int arg1)
|
void MainWindow::on_MF_selectAllBox_stateChanged(int arg1)
|
||||||
@@ -489,11 +648,15 @@ void MainWindow::on_MF_File_saveButton_clicked()
|
|||||||
QString title = "";
|
QString title = "";
|
||||||
QString filename = "";
|
QString filename = "";
|
||||||
QString selectedType = "";
|
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())
|
if(ui->MF_File_dataBox->isChecked())
|
||||||
{
|
{
|
||||||
title = tr("Plz select the location to save data file:");
|
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;
|
qDebug() << filename;
|
||||||
if(filename != "")
|
if(filename != "")
|
||||||
{
|
{
|
||||||
@@ -506,7 +669,7 @@ void MainWindow::on_MF_File_saveButton_clicked()
|
|||||||
else if(ui->MF_File_keyBox->isChecked())
|
else if(ui->MF_File_keyBox->isChecked())
|
||||||
{
|
{
|
||||||
title = tr("Plz select the location to save key file:");
|
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;
|
qDebug() << filename;
|
||||||
if(filename != "")
|
if(filename != "")
|
||||||
{
|
{
|
||||||
@@ -736,10 +899,10 @@ void MainWindow::on_MF_Sniff_sniffButton_clicked()
|
|||||||
setState(true);
|
setState(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::on_MF_Sniff_snoopButton_clicked()
|
void MainWindow::on_MF_14aSniff_snoopButton_clicked()
|
||||||
{
|
{
|
||||||
setState(false);
|
setState(false);
|
||||||
mifare->snoop();
|
mifare->sniff14a();
|
||||||
setState(true);
|
setState(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -752,6 +915,7 @@ void MainWindow::MF_widgetReset()
|
|||||||
{
|
{
|
||||||
int secs = mifare->cardType.sector_size;
|
int secs = mifare->cardType.sector_size;
|
||||||
int blks = mifare->cardType.block_size;
|
int blks = mifare->cardType.block_size;
|
||||||
|
QBrush trailerItemForeColor = QBrush(QColor(0, 160, 255));
|
||||||
ui->MF_RW_blockBox->clear();
|
ui->MF_RW_blockBox->clear();
|
||||||
ui->MF_keyWidget->setRowCount(secs);
|
ui->MF_keyWidget->setRowCount(secs);
|
||||||
ui->MF_dataWidget->setRowCount(blks);
|
ui->MF_dataWidget->setRowCount(blks);
|
||||||
@@ -776,8 +940,10 @@ void MainWindow::MF_widgetReset()
|
|||||||
setTableItem(ui->MF_keyWidget, i, 1, "");
|
setTableItem(ui->MF_keyWidget, i, 1, "");
|
||||||
setTableItem(ui->MF_keyWidget, i, 2, "");
|
setTableItem(ui->MF_keyWidget, i, 2, "");
|
||||||
setTableItem(ui->MF_dataWidget, mifare->cardType.blks[i], 0, QString::number(i));
|
setTableItem(ui->MF_dataWidget, mifare->cardType.blks[i], 0, QString::number(i));
|
||||||
|
ui->MF_dataWidget->item(mifare->cardType.blks[i] + mifare->cardType.blk[i] - 1, 2)->setForeground(trailerItemForeColor);
|
||||||
ui->MF_dataWidget->item(mifare->cardType.blks[i], 0)->setCheckState(Qt::Checked);
|
ui->MF_dataWidget->item(mifare->cardType.blks[i], 0)->setCheckState(Qt::Checked);
|
||||||
}
|
}
|
||||||
|
ui->MF_dataWidget->item(0, 2)->setForeground(QBrush(QColor(255, 160, 0)));
|
||||||
ui->MF_selectAllBox->setCheckState(Qt::Checked);
|
ui->MF_selectAllBox->setCheckState(Qt::Checked);
|
||||||
ui->MF_selectTrailerBox->setCheckState(Qt::Checked);
|
ui->MF_selectTrailerBox->setCheckState(Qt::Checked);
|
||||||
|
|
||||||
@@ -793,43 +959,38 @@ void MainWindow::MF_widgetReset()
|
|||||||
|
|
||||||
void MainWindow::uiInit()
|
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);
|
connectStatusBar = new QLabel(this);
|
||||||
programStatusBar = new QLabel(this);
|
programStatusBar = new QLabel(this);
|
||||||
PM3VersionBar = new QLabel(this);
|
PM3VersionBar = new QLabel(this);
|
||||||
|
stopButton = new QPushButton(this);
|
||||||
setStatusBar(connectStatusBar, tr("Not Connected"));
|
setStatusBar(connectStatusBar, tr("Not Connected"));
|
||||||
setStatusBar(programStatusBar, tr("Idle"));
|
setStatusBar(programStatusBar, tr("Idle"));
|
||||||
setStatusBar(PM3VersionBar, "");
|
setStatusBar(PM3VersionBar, "");
|
||||||
|
stopButton->setText(tr("Stop"));
|
||||||
ui->statusbar->addPermanentWidget(PM3VersionBar, 1);
|
ui->statusbar->addPermanentWidget(PM3VersionBar, 1);
|
||||||
ui->statusbar->addPermanentWidget(connectStatusBar, 1);
|
ui->statusbar->addPermanentWidget(connectStatusBar, 1);
|
||||||
ui->statusbar->addPermanentWidget(programStatusBar, 1);
|
ui->statusbar->addPermanentWidget(programStatusBar, 1);
|
||||||
|
ui->statusbar->addPermanentWidget(stopButton);
|
||||||
|
|
||||||
ui->MF_dataWidget->setColumnCount(3);
|
|
||||||
ui->MF_dataWidget->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(0, 55);
|
||||||
ui->MF_dataWidget->setColumnWidth(1, 55);
|
ui->MF_dataWidget->setColumnWidth(1, 55);
|
||||||
ui->MF_dataWidget->setColumnWidth(2, 430);
|
|
||||||
|
|
||||||
ui->MF_keyWidget->setColumnCount(3);
|
ui->MF_keyWidget->setColumnWidth(0, 45);
|
||||||
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);
|
|
||||||
|
|
||||||
MF_widgetReset();
|
MF_widgetReset();
|
||||||
typeBtnGroup = new QButtonGroup(this);
|
MFCardTypeBtnGroup = new QButtonGroup(this);
|
||||||
typeBtnGroup->addButton(ui->MF_Type_miniButton, 0);
|
MFCardTypeBtnGroup->addButton(ui->MF_Type_miniButton, 0);
|
||||||
typeBtnGroup->addButton(ui->MF_Type_1kButton, 1);
|
MFCardTypeBtnGroup->addButton(ui->MF_Type_1kButton, 1);
|
||||||
typeBtnGroup->addButton(ui->MF_Type_2kButton, 2);
|
MFCardTypeBtnGroup->addButton(ui->MF_Type_2kButton, 2);
|
||||||
typeBtnGroup->addButton(ui->MF_Type_4kButton, 4);
|
MFCardTypeBtnGroup->addButton(ui->MF_Type_4kButton, 4);
|
||||||
connect(typeBtnGroup, QOverload<int, bool>::of(&QButtonGroup::buttonToggled), this, &MainWindow::MF_onTypeChanged);
|
connect(MFCardTypeBtnGroup, QOverload<int, bool>::of(&QButtonGroup::buttonToggled), this, &MainWindow::MF_onMFCardTypeChanged);
|
||||||
|
|
||||||
ui->MF_keyWidget->installEventFilter(this);
|
ui->MF_keyWidget->installEventFilter(this);
|
||||||
ui->MF_dataWidget->installEventFilter(this);
|
ui->MF_dataWidget->installEventFilter(this);
|
||||||
@@ -837,7 +998,7 @@ void MainWindow::uiInit()
|
|||||||
settings->beginGroup("UI_grpbox_preference");
|
settings->beginGroup("UI_grpbox_preference");
|
||||||
|
|
||||||
QStringList boxNames = settings->allKeys();
|
QStringList boxNames = settings->allKeys();
|
||||||
QGroupBox* boxptr;
|
QGroupBox * boxptr;
|
||||||
foreach(QString name, boxNames)
|
foreach(QString name, boxNames)
|
||||||
{
|
{
|
||||||
boxptr = this->findChild<QGroupBox*>(name);
|
boxptr = this->findChild<QGroupBox*>(name);
|
||||||
@@ -860,11 +1021,30 @@ void MainWindow::uiInit()
|
|||||||
ui->PM3_pathEdit->setText(settings->value("path", "proxmark3").toString());
|
ui->PM3_pathEdit->setText(settings->value("path", "proxmark3").toString());
|
||||||
settings->endGroup();
|
settings->endGroup();
|
||||||
|
|
||||||
|
settings->beginGroup("Client_Args");
|
||||||
|
ui->Set_Client_startArgsEdit->setText(settings->value("args", "<port> -f").toString());
|
||||||
|
settings->endGroup();
|
||||||
|
|
||||||
|
settings->beginGroup("Client_forceButtonsEnabled");
|
||||||
|
keepButtonsEnabled = settings->value("state", false).toBool();
|
||||||
|
ui->Set_Client_forceEnabledBox->setChecked(keepButtonsEnabled);
|
||||||
|
settings->endGroup();
|
||||||
|
|
||||||
|
settings->beginGroup("Client_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("A", Mifare::KEY_A);
|
||||||
ui->MF_RW_keyTypeBox->addItem("B", Mifare::KEY_B);
|
ui->MF_RW_keyTypeBox->addItem("B", Mifare::KEY_B);
|
||||||
|
|
||||||
on_Raw_CMDHistoryBox_stateChanged(Qt::Unchecked);
|
on_Raw_CMDHistoryBox_stateChanged(Qt::Unchecked);
|
||||||
on_PM3_refreshPortButton_clicked();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::signalInit()
|
void MainWindow::signalInit()
|
||||||
@@ -874,8 +1054,14 @@ void MainWindow::signalInit()
|
|||||||
connect(util, &Util::refreshOutput, this, &MainWindow::refreshOutput);
|
connect(util, &Util::refreshOutput, this, &MainWindow::refreshOutput);
|
||||||
|
|
||||||
connect(this, &MainWindow::connectPM3, pm3, &PM3Process::connectPM3);
|
connect(this, &MainWindow::connectPM3, pm3, &PM3Process::connectPM3);
|
||||||
|
connect(this, &MainWindow::reconnectPM3, pm3, &PM3Process::reconnectPM3);
|
||||||
connect(pm3, &PM3Process::PM3StatedChanged, this, &MainWindow::onPM3StateChanged);
|
connect(pm3, &PM3Process::PM3StatedChanged, this, &MainWindow::onPM3StateChanged);
|
||||||
connect(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);
|
connect(util, &Util::write, pm3, &PM3Process::write);
|
||||||
|
|
||||||
@@ -886,9 +1072,11 @@ void MainWindow::signalInit()
|
|||||||
connect(ui->MF_UIDGroupBox, &QGroupBox::clicked, this, &MainWindow::on_GroupBox_clicked);
|
connect(ui->MF_UIDGroupBox, &QGroupBox::clicked, this, &MainWindow::on_GroupBox_clicked);
|
||||||
connect(ui->MF_simGroupBox, &QGroupBox::clicked, this, &MainWindow::on_GroupBox_clicked);
|
connect(ui->MF_simGroupBox, &QGroupBox::clicked, this, &MainWindow::on_GroupBox_clicked);
|
||||||
connect(ui->MF_sniffGroupBox, &QGroupBox::clicked, this, &MainWindow::on_GroupBox_clicked);
|
connect(ui->MF_sniffGroupBox, &QGroupBox::clicked, this, &MainWindow::on_GroupBox_clicked);
|
||||||
|
|
||||||
|
connect(stopButton, &QPushButton::clicked, this, &MainWindow::on_stopButton_clicked);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::setStatusBar(QLabel * target, const QString & text)
|
void MainWindow::setStatusBar(QLabel * target, const QString& text)
|
||||||
{
|
{
|
||||||
if(target == PM3VersionBar)
|
if(target == PM3VersionBar)
|
||||||
target->setText(tr("HW Version:") + text);
|
target->setText(tr("HW Version:") + text);
|
||||||
@@ -898,7 +1086,7 @@ void MainWindow::setStatusBar(QLabel * target, const QString & text)
|
|||||||
target->setText(tr("State:") + text);
|
target->setText(tr("State:") + text);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::setTableItem(QTableWidget * widget, int row, int column, const QString & text)
|
void MainWindow::setTableItem(QTableWidget * widget, int row, int column, const QString& text)
|
||||||
{
|
{
|
||||||
if(widget->item(row, column) == nullptr)
|
if(widget->item(row, column) == nullptr)
|
||||||
widget->setItem(row, column, new QTableWidgetItem());
|
widget->setItem(row, column, new QTableWidgetItem());
|
||||||
@@ -956,6 +1144,11 @@ void MainWindow::setState(bool st)
|
|||||||
{
|
{
|
||||||
setStatusBar(programStatusBar, tr("Idle"));
|
setStatusBar(programStatusBar, tr("Idle"));
|
||||||
}
|
}
|
||||||
|
setButtonsEnabled(st || keepButtonsEnabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::setButtonsEnabled(bool st)
|
||||||
|
{
|
||||||
ui->MF_attackGroupBox->setEnabled(st);
|
ui->MF_attackGroupBox->setEnabled(st);
|
||||||
ui->MF_normalGroupBox->setEnabled(st);
|
ui->MF_normalGroupBox->setEnabled(st);
|
||||||
ui->MF_UIDGroupBox->setEnabled(st);
|
ui->MF_UIDGroupBox->setEnabled(st);
|
||||||
@@ -963,6 +1156,8 @@ void MainWindow::setState(bool st)
|
|||||||
ui->MF_sniffGroupBox->setEnabled(st);
|
ui->MF_sniffGroupBox->setEnabled(st);
|
||||||
ui->Raw_CMDEdit->setEnabled(st);
|
ui->Raw_CMDEdit->setEnabled(st);
|
||||||
ui->Raw_sendCMDButton->setEnabled(st);
|
ui->Raw_sendCMDButton->setEnabled(st);
|
||||||
|
ui->LF_configGroupBox->setEnabled(st);
|
||||||
|
ui->LF_operationGroupBox->setEnabled(st);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::on_GroupBox_clicked(bool checked)
|
void MainWindow::on_GroupBox_clicked(bool checked)
|
||||||
@@ -983,10 +1178,194 @@ void MainWindow::on_GroupBox_clicked(bool checked)
|
|||||||
settings->endGroup();
|
settings->endGroup();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::saveClientPath(const QString & path)
|
void MainWindow::saveClientPath(const QString& path)
|
||||||
{
|
{
|
||||||
settings->beginGroup("Client_Path");
|
settings->beginGroup("Client_Path");
|
||||||
settings->setValue("path", path);
|
settings->setValue("path", path);
|
||||||
settings->endGroup();
|
settings->endGroup();
|
||||||
}
|
}
|
||||||
// ***********************************************
|
// ***********************************************
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void MainWindow::on_MF_Attack_darksideButton_clicked()
|
||||||
|
{
|
||||||
|
setState(false);
|
||||||
|
mifare->darkside();
|
||||||
|
setState(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::on_Set_Client_startArgsEdit_editingFinished()
|
||||||
|
{
|
||||||
|
settings->beginGroup("Client_Args");
|
||||||
|
settings->setValue("args", ui->Set_Client_startArgsEdit->text());
|
||||||
|
settings->endGroup();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::on_Set_Client_forceEnabledBox_stateChanged(int arg1)
|
||||||
|
{
|
||||||
|
settings->beginGroup("Client_forceButtonsEnabled");
|
||||||
|
keepButtonsEnabled = (arg1 == Qt::Checked);
|
||||||
|
settings->setValue("state", keepButtonsEnabled);
|
||||||
|
settings->endGroup();
|
||||||
|
if(keepButtonsEnabled)
|
||||||
|
setButtonsEnabled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::on_Set_GUI_setLanguageButton_clicked()
|
||||||
|
{
|
||||||
|
Util::chooseLanguage(settings, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::on_PM3_refreshPortButton_clicked()
|
||||||
|
{
|
||||||
|
on_portSearchTimer_timeout();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::on_Set_Client_envScriptEdit_editingFinished()
|
||||||
|
{
|
||||||
|
settings->beginGroup("Client_Env");
|
||||||
|
settings->setValue("scriptPath", ui->Set_Client_envScriptEdit->text());
|
||||||
|
settings->endGroup();
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|||||||
@@ -19,9 +19,18 @@
|
|||||||
#include <QGroupBox>
|
#include <QGroupBox>
|
||||||
#include <QSizePolicy>
|
#include <QSizePolicy>
|
||||||
#include <QSettings>
|
#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 "common/pm3process.h"
|
||||||
#include "module/mifare.h"
|
#include "module/mifare.h"
|
||||||
|
#include "module/lf.h"
|
||||||
#include "common/util.h"
|
#include "common/util.h"
|
||||||
#include "ui/mf_trailerdecoderdialog.h"
|
#include "ui/mf_trailerdecoderdialog.h"
|
||||||
|
|
||||||
@@ -43,11 +52,13 @@ public:
|
|||||||
void initUI();
|
void initUI();
|
||||||
bool eventFilter(QObject *watched, QEvent *event);
|
bool eventFilter(QObject *watched, QEvent *event);
|
||||||
public slots:
|
public slots:
|
||||||
void refreshOutput(const QString &output);
|
void refreshOutput(const QString& output);
|
||||||
void refreshCMD(const QString &cmd);
|
void refreshCMD(const QString& cmd);
|
||||||
void setStatusBar(QLabel* target, const QString & text);
|
void setStatusBar(QLabel* target, const QString& text);
|
||||||
void onPM3StateChanged(bool st, QString info);
|
void onPM3StateChanged(bool st, const QString& info);
|
||||||
void MF_onTypeChanged(int id, bool st);
|
void MF_onMFCardTypeChanged(int id, bool st);
|
||||||
|
void on_Raw_keyPressed(QObject *obj_addr, QEvent &event);
|
||||||
|
void on_MF_keyWidget_resized(QObject *obj_addr, QEvent &event);
|
||||||
private slots:
|
private slots:
|
||||||
|
|
||||||
void on_PM3_connectButton_clicked();
|
void on_PM3_connectButton_clicked();
|
||||||
@@ -59,7 +70,8 @@ private slots:
|
|||||||
void on_Raw_clearOutputButton_clicked();
|
void on_Raw_clearOutputButton_clicked();
|
||||||
|
|
||||||
void sendMSG();
|
void sendMSG();
|
||||||
void on_PM3_refreshPortButton_clicked();
|
|
||||||
|
void on_portSearchTimer_timeout();
|
||||||
|
|
||||||
void on_Raw_CMDHistoryBox_stateChanged(int arg1);
|
void on_Raw_CMDHistoryBox_stateChanged(int arg1);
|
||||||
|
|
||||||
@@ -87,7 +99,6 @@ private slots:
|
|||||||
|
|
||||||
void on_MF_RW_writeSelectedButton_clicked();
|
void on_MF_RW_writeSelectedButton_clicked();
|
||||||
|
|
||||||
|
|
||||||
void on_MF_RW_dumpButton_clicked();
|
void on_MF_RW_dumpButton_clicked();
|
||||||
|
|
||||||
void on_MF_RW_restoreButton_clicked();
|
void on_MF_RW_restoreButton_clicked();
|
||||||
@@ -142,42 +153,111 @@ private slots:
|
|||||||
|
|
||||||
void on_MF_fillKeysButton_clicked();
|
void on_MF_fillKeysButton_clicked();
|
||||||
|
|
||||||
void on_MF_Sniff_snoopButton_clicked();
|
void on_MF_14aSniff_snoopButton_clicked();
|
||||||
|
|
||||||
void on_MF_trailerDecoderButton_clicked();
|
void on_MF_trailerDecoderButton_clicked();
|
||||||
|
|
||||||
void on_MF_selectTrailerBox_stateChanged(int arg1);
|
void on_MF_selectTrailerBox_stateChanged(int arg1);
|
||||||
|
|
||||||
|
void on_stopButton_clicked();
|
||||||
|
|
||||||
|
void on_Raw_CMDEdit_textChanged(const QString &arg1);
|
||||||
|
|
||||||
|
void on_MF_Attack_darksideButton_clicked();
|
||||||
|
|
||||||
|
void on_Set_Client_startArgsEdit_editingFinished();
|
||||||
|
|
||||||
|
void on_Set_Client_forceEnabledBox_stateChanged(int arg1);
|
||||||
|
|
||||||
|
void on_Set_GUI_setLanguageButton_clicked();
|
||||||
|
|
||||||
|
void setButtonsEnabled(bool st);
|
||||||
|
|
||||||
|
void on_PM3_refreshPortButton_clicked();
|
||||||
|
|
||||||
|
void on_Set_Client_envScriptEdit_editingFinished();
|
||||||
|
|
||||||
|
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:
|
private:
|
||||||
Ui::MainWindow* ui;
|
Ui::MainWindow* ui;
|
||||||
QButtonGroup* typeBtnGroup;
|
QButtonGroup* MFCardTypeBtnGroup;
|
||||||
QLabel* connectStatusBar;
|
QLabel* connectStatusBar;
|
||||||
QLabel* programStatusBar;
|
QLabel* programStatusBar;
|
||||||
QLabel* PM3VersionBar;
|
QLabel* PM3VersionBar;
|
||||||
|
QPushButton* stopButton;
|
||||||
|
QAction* dockAllWindows;
|
||||||
QAction* myInfo;
|
QAction* myInfo;
|
||||||
|
QAction* currVersion;
|
||||||
QAction* checkUpdate;
|
QAction* checkUpdate;
|
||||||
QSettings* settings;
|
QSettings* settings;
|
||||||
|
MyEventFilter* keyEventFilter;
|
||||||
|
MyEventFilter* resizeEventFilter;
|
||||||
|
|
||||||
|
QString stashedCMDEditText;
|
||||||
|
int stashedIndex = -1;
|
||||||
|
|
||||||
void uiInit();
|
void uiInit();
|
||||||
|
|
||||||
PM3Process* pm3;
|
PM3Process* pm3;
|
||||||
bool pm3state;
|
bool pm3state;
|
||||||
|
bool keepButtonsEnabled;
|
||||||
|
bool keepClientActive;
|
||||||
QThread* pm3Thread;
|
QThread* pm3Thread;
|
||||||
|
QTimer* portSearchTimer;
|
||||||
|
QStringList portList;
|
||||||
|
QStringList clientEnv;
|
||||||
|
QDir* clientWorkingDir;
|
||||||
|
|
||||||
Mifare* mifare;
|
Mifare* mifare;
|
||||||
|
LF* lf;
|
||||||
Util* util;
|
Util* util;
|
||||||
|
|
||||||
|
QList<QDockWidget*> dockList;
|
||||||
|
QMenu* contextMenu;
|
||||||
|
|
||||||
MF_trailerDecoderDialog* decDialog;
|
MF_trailerDecoderDialog* decDialog;
|
||||||
|
|
||||||
|
|
||||||
void signalInit();
|
void signalInit();
|
||||||
void MF_widgetReset();
|
void MF_widgetReset();
|
||||||
void setTableItem(QTableWidget *widget, int row, int column, const QString &text);
|
void setTableItem(QTableWidget *widget, int row, int column, const QString& text);
|
||||||
void setState(bool st);
|
void setState(bool st);
|
||||||
void saveClientPath(const QString &path);
|
void saveClientPath(const QString& path);
|
||||||
|
void onLFfreqConfChanged(int value, bool isCustomized);
|
||||||
|
void dockInit();
|
||||||
|
protected:
|
||||||
|
void contextMenuEvent(QContextMenuEvent *event) override;
|
||||||
signals:
|
signals:
|
||||||
void connectPM3(const QString path, const QString port);
|
void connectPM3(const QString& path, const QStringList args);
|
||||||
|
void reconnectPM3();
|
||||||
void killPM3();
|
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
|
#endif // MAINWINDOW_H
|
||||||
|
|||||||
@@ -21,14 +21,26 @@ MF_Attack_hardnestedDialog::~MF_Attack_hardnestedDialog()
|
|||||||
|
|
||||||
void MF_Attack_hardnestedDialog::on_buttonBox_accepted()
|
void MF_Attack_hardnestedDialog::on_buttonBox_accepted()
|
||||||
{
|
{
|
||||||
emit sendCMD("hf mf hardnested "
|
if(Util::getClientType() == Util::CLIENTTYPE_OFFICIAL)
|
||||||
+ ui->knownKeySectorBox->currentText()
|
emit sendCMD("hf mf hardnested "
|
||||||
+ " "
|
+ ui->knownKeySectorBox->currentText()
|
||||||
+ ui->knownKeyTypeBox->currentText()
|
+ " "
|
||||||
+ " "
|
+ ui->knownKeyTypeBox->currentText()
|
||||||
+ ui->knownKeyBox->text()
|
+ " "
|
||||||
+ " "
|
+ ui->knownKeyBox->text()
|
||||||
+ ui->targetKeySectorBox->currentText()
|
+ " "
|
||||||
+ " "
|
+ ui->targetKeySectorBox->currentText()
|
||||||
+ ui->targetKeyTypeBox->currentText());
|
+ " "
|
||||||
|
+ ui->targetKeyTypeBox->currentText());
|
||||||
|
else if(Util::getClientType() == Util::CLIENTTYPE_ICEMAN) // same format in v4.9237
|
||||||
|
emit sendCMD("hf mf hardnested "
|
||||||
|
+ ui->knownKeySectorBox->currentText()
|
||||||
|
+ " "
|
||||||
|
+ ui->knownKeyTypeBox->currentText()
|
||||||
|
+ " "
|
||||||
|
+ ui->knownKeyBox->text()
|
||||||
|
+ " "
|
||||||
|
+ ui->targetKeySectorBox->currentText()
|
||||||
|
+ " "
|
||||||
|
+ ui->targetKeyTypeBox->currentText());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,8 +2,10 @@
|
|||||||
#define MF_ATTACK_HARDNESTEDDIALOG_H
|
#define MF_ATTACK_HARDNESTEDDIALOG_H
|
||||||
|
|
||||||
#include <QDialog>
|
#include <QDialog>
|
||||||
|
#include "common/util.h"
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui
|
||||||
|
{
|
||||||
class MF_Attack_hardnestedDialog;
|
class MF_Attack_hardnestedDialog;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -19,7 +21,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
Ui::MF_Attack_hardnestedDialog *ui;
|
Ui::MF_Attack_hardnestedDialog *ui;
|
||||||
signals:
|
signals:
|
||||||
void sendCMD(QString cmd);
|
void sendCMD(const QString& cmd);
|
||||||
private slots:
|
private slots:
|
||||||
void on_buttonBox_accepted();
|
void on_buttonBox_accepted();
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,12 +1,34 @@
|
|||||||
#include "mf_sim_simdialog.h"
|
#include "mf_sim_simdialog.h"
|
||||||
#include "ui_mf_sim_simdialog.h"
|
#include "ui_mf_sim_simdialog.h"
|
||||||
|
|
||||||
MF_Sim_simDialog::MF_Sim_simDialog(int cardType, QWidget *parent) :
|
MF_Sim_simDialog::MF_Sim_simDialog(int cardType, QString cardTypeText, QWidget *parent) :
|
||||||
QDialog(parent),
|
QDialog(parent),
|
||||||
ui(new Ui::MF_Sim_simDialog)
|
ui(new Ui::MF_Sim_simDialog)
|
||||||
{
|
{
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
|
if(Util::getClientType() == Util::CLIENTTYPE_OFFICIAL)
|
||||||
|
{
|
||||||
|
ui->atqaGroupBox->setVisible(false);
|
||||||
|
ui->atqaLine->setVisible(false);
|
||||||
|
ui->sakGroupBox->setVisible(false);
|
||||||
|
ui->sakLine->setVisible(false);
|
||||||
|
ui->vGroupBox->setVisible(false);
|
||||||
|
ui->vLine->setVisible(false);
|
||||||
|
}
|
||||||
|
else if(Util::getClientType() == Util::CLIENTTYPE_ICEMAN)
|
||||||
|
{
|
||||||
|
ui->fGroupBox->setVisible(false);
|
||||||
|
ui->fLine->setVisible(false);
|
||||||
|
ui->rGroupBox->setVisible(false);
|
||||||
|
ui->rLine->setVisible(false);
|
||||||
|
ui->uBox->setText("-u");
|
||||||
|
ui->nBox->setText("-n");
|
||||||
|
ui->iBox->setText("-i");
|
||||||
|
ui->xBox->setText("--crack");
|
||||||
|
ui->eBox->setText("-e");
|
||||||
|
}
|
||||||
this->cardType = cardType;
|
this->cardType = cardType;
|
||||||
|
this->cardTypeText = cardTypeText;
|
||||||
}
|
}
|
||||||
|
|
||||||
MF_Sim_simDialog::~MF_Sim_simDialog()
|
MF_Sim_simDialog::~MF_Sim_simDialog()
|
||||||
@@ -55,12 +77,27 @@ void MF_Sim_simDialog::on_fBox_clicked(bool checked)
|
|||||||
void MF_Sim_simDialog::on_buttonBox_accepted()
|
void MF_Sim_simDialog::on_buttonBox_accepted()
|
||||||
{
|
{
|
||||||
QString paras;
|
QString paras;
|
||||||
paras += (ui->uBox->isChecked() ? "u " + ui->uEdit->text() + " " : "");
|
if(Util::getClientType() == Util::CLIENTTYPE_OFFICIAL)
|
||||||
paras += (ui->nBox->isChecked() ? "n " + ui->nEdit->text() + " " : "");
|
{
|
||||||
paras += (ui->iBox->isChecked() ? "i " : "");
|
paras += (ui->uBox->isChecked() ? "u " + ui->uEdit->text() + " " : "");
|
||||||
paras += (ui->xBox->isChecked() ? "x " : "");
|
paras += (ui->nBox->isChecked() ? "n " + ui->nEdit->text() + " " : "");
|
||||||
paras += (ui->eBox->isChecked() ? "e " : "");
|
paras += (ui->iBox->isChecked() ? "i " : "");
|
||||||
paras += (ui->fBox->isChecked() ? "f " + ui->fEdit->text() + " " : "");
|
paras += (ui->xBox->isChecked() ? "x " : "");
|
||||||
paras += (ui->rBox->isChecked() ? "r " : "");
|
paras += (ui->eBox->isChecked() ? "e " : "");
|
||||||
emit sendCMD(QString("hf mf sim ") + "*" + QString::number(cardType) + " " + paras.trimmed());
|
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());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#include <QDialog>
|
#include <QDialog>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
#include "common/util.h"
|
||||||
|
|
||||||
namespace Ui
|
namespace Ui
|
||||||
{
|
{
|
||||||
@@ -14,7 +15,7 @@ class MF_Sim_simDialog : public QDialog
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit MF_Sim_simDialog(int cardType, QWidget *parent = nullptr);
|
explicit MF_Sim_simDialog(int cardType, QString cardTypeText, QWidget *parent = nullptr);
|
||||||
~MF_Sim_simDialog();
|
~MF_Sim_simDialog();
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
@@ -25,8 +26,9 @@ private slots:
|
|||||||
private:
|
private:
|
||||||
Ui::MF_Sim_simDialog *ui;
|
Ui::MF_Sim_simDialog *ui;
|
||||||
int cardType;
|
int cardType;
|
||||||
|
QString cardTypeText;
|
||||||
signals:
|
signals:
|
||||||
void sendCMD(QString cmd);
|
void sendCMD(const QString& cmd);
|
||||||
private slots:
|
private slots:
|
||||||
void on_buttonBox_accepted();
|
void on_buttonBox_accepted();
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -7,309 +7,598 @@
|
|||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>461</width>
|
<width>461</width>
|
||||||
<height>456</height>
|
<height>524</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
<string>Simulate</string>
|
<string>Simulate</string>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout">
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
<property name="spacing">
|
|
||||||
<number>5</number>
|
|
||||||
</property>
|
|
||||||
<property name="leftMargin">
|
|
||||||
<number>5</number>
|
|
||||||
</property>
|
|
||||||
<property name="topMargin">
|
|
||||||
<number>5</number>
|
|
||||||
</property>
|
|
||||||
<property name="rightMargin">
|
|
||||||
<number>5</number>
|
|
||||||
</property>
|
|
||||||
<property name="bottomMargin">
|
|
||||||
<number>5</number>
|
|
||||||
</property>
|
|
||||||
<item>
|
<item>
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
<widget class="QGroupBox" name="uGroupBox">
|
||||||
<item>
|
<layout class="QHBoxLayout" name="uLayout">
|
||||||
<widget class="QCheckBox" name="uBox">
|
<property name="spacing">
|
||||||
<property name="text">
|
<number>5</number>
|
||||||
<string>u</string>
|
</property>
|
||||||
</property>
|
<property name="leftMargin">
|
||||||
</widget>
|
<number>0</number>
|
||||||
</item>
|
</property>
|
||||||
<item>
|
<property name="topMargin">
|
||||||
<widget class="QLineEdit" name="uEdit">
|
<number>0</number>
|
||||||
<property name="sizePolicy">
|
</property>
|
||||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
<property name="rightMargin">
|
||||||
<horstretch>0</horstretch>
|
<number>0</number>
|
||||||
<verstretch>0</verstretch>
|
</property>
|
||||||
</sizepolicy>
|
<property name="bottomMargin">
|
||||||
</property>
|
<number>0</number>
|
||||||
<property name="maximumSize">
|
</property>
|
||||||
<size>
|
<item>
|
||||||
<width>100</width>
|
<widget class="QCheckBox" name="uBox">
|
||||||
<height>16777215</height>
|
<property name="text">
|
||||||
</size>
|
<string>u</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QLabel" name="label">
|
<widget class="QLineEdit" name="uEdit">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
<verstretch>0</verstretch>
|
<verstretch>0</verstretch>
|
||||||
</sizepolicy>
|
</sizepolicy>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="maximumSize">
|
||||||
<string>UID 4 or 7 bytes. If not specified, the UID 4B from emulator memory will be used</string>
|
<size>
|
||||||
</property>
|
<width>100</width>
|
||||||
<property name="wordWrap">
|
<height>16777215</height>
|
||||||
<bool>true</bool>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
<item>
|
||||||
|
<widget class="QLabel" name="label">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>UID 4 or 7 bytes. If not specified, the UID 4B from emulator memory will be used</string>
|
||||||
|
</property>
|
||||||
|
<property name="wordWrap">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="Line" name="line_6">
|
<widget class="Line" name="uLine">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
<enum>Qt::Horizontal</enum>
|
<enum>Qt::Horizontal</enum>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
<widget class="QGroupBox" name="atqaGroupBox">
|
||||||
<item>
|
<layout class="QHBoxLayout" name="atqaLayout">
|
||||||
<widget class="QCheckBox" name="nBox">
|
<property name="spacing">
|
||||||
<property name="text">
|
<number>5</number>
|
||||||
<string>n</string>
|
</property>
|
||||||
</property>
|
<property name="leftMargin">
|
||||||
</widget>
|
<number>0</number>
|
||||||
</item>
|
</property>
|
||||||
<item>
|
<property name="topMargin">
|
||||||
<widget class="QLineEdit" name="nEdit">
|
<number>0</number>
|
||||||
<property name="sizePolicy">
|
</property>
|
||||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
<property name="rightMargin">
|
||||||
<horstretch>0</horstretch>
|
<number>0</number>
|
||||||
<verstretch>0</verstretch>
|
</property>
|
||||||
</sizepolicy>
|
<property name="bottomMargin">
|
||||||
</property>
|
<number>0</number>
|
||||||
<property name="maximumSize">
|
</property>
|
||||||
<size>
|
<item>
|
||||||
<width>100</width>
|
<widget class="QCheckBox" name="atqaBox">
|
||||||
<height>16777215</height>
|
<property name="text">
|
||||||
</size>
|
<string>--atqa</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QLabel" name="label_2">
|
<widget class="QLineEdit" name="atqaEdit">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
<verstretch>0</verstretch>
|
<verstretch>0</verstretch>
|
||||||
</sizepolicy>
|
</sizepolicy>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="maximumSize">
|
||||||
<string>Automatically exit simulation after <numreads> blocks have been read by reader. 0 = infinite</string>
|
<size>
|
||||||
</property>
|
<width>100</width>
|
||||||
<property name="wordWrap">
|
<height>16777215</height>
|
||||||
<bool>true</bool>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
<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>
|
||||||
<item>
|
<item>
|
||||||
<widget class="Line" name="line_5">
|
<widget class="Line" name="atqaLine">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
<enum>Qt::Horizontal</enum>
|
<enum>Qt::Horizontal</enum>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
<widget class="QGroupBox" name="sakGroupBox">
|
||||||
<item>
|
<layout class="QHBoxLayout" name="sakLayout">
|
||||||
<widget class="QCheckBox" name="iBox">
|
<property name="spacing">
|
||||||
<property name="text">
|
<number>5</number>
|
||||||
<string>i</string>
|
</property>
|
||||||
</property>
|
<property name="leftMargin">
|
||||||
</widget>
|
<number>0</number>
|
||||||
</item>
|
</property>
|
||||||
<item>
|
<property name="topMargin">
|
||||||
<widget class="QLabel" name="label_3">
|
<number>0</number>
|
||||||
<property name="sizePolicy">
|
</property>
|
||||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
<property name="rightMargin">
|
||||||
<horstretch>0</horstretch>
|
<number>0</number>
|
||||||
<verstretch>0</verstretch>
|
</property>
|
||||||
</sizepolicy>
|
<property name="bottomMargin">
|
||||||
</property>
|
<number>0</number>
|
||||||
<property name="text">
|
</property>
|
||||||
<string>Interactive, means that console will not be returned until simulation finishes or is aborted</string>
|
<item>
|
||||||
</property>
|
<widget class="QCheckBox" name="sakBox">
|
||||||
<property name="wordWrap">
|
<property name="text">
|
||||||
<bool>true</bool>
|
<string>--sak</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
<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>
|
||||||
<item>
|
<item>
|
||||||
<widget class="Line" name="line_4">
|
<widget class="Line" name="sakLine">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
<enum>Qt::Horizontal</enum>
|
<enum>Qt::Horizontal</enum>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_5">
|
<widget class="QGroupBox" name="nGroupBox">
|
||||||
<item>
|
<layout class="QHBoxLayout" name="nLayout">
|
||||||
<widget class="QCheckBox" name="xBox">
|
<property name="spacing">
|
||||||
<property name="text">
|
<number>5</number>
|
||||||
<string>x</string>
|
</property>
|
||||||
</property>
|
<property name="leftMargin">
|
||||||
</widget>
|
<number>0</number>
|
||||||
</item>
|
</property>
|
||||||
<item>
|
<property name="topMargin">
|
||||||
<widget class="QLabel" name="label_4">
|
<number>0</number>
|
||||||
<property name="sizePolicy">
|
</property>
|
||||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
<property name="rightMargin">
|
||||||
<horstretch>0</horstretch>
|
<number>0</number>
|
||||||
<verstretch>0</verstretch>
|
</property>
|
||||||
</sizepolicy>
|
<property name="bottomMargin">
|
||||||
</property>
|
<number>0</number>
|
||||||
<property name="text">
|
</property>
|
||||||
<string>Crack, performs the 'reader attack', nr/ar attack against a legitimate reader, fishes out the key(s)</string>
|
<item>
|
||||||
</property>
|
<widget class="QCheckBox" name="nBox">
|
||||||
<property name="wordWrap">
|
<property name="text">
|
||||||
<bool>true</bool>
|
<string>n</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
<item>
|
||||||
|
<widget class="QLineEdit" name="nEdit">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>100</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_2">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Automatically exit simulation after <numreads> blocks have been read by reader. 0 = infinite</string>
|
||||||
|
</property>
|
||||||
|
<property name="wordWrap">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="Line" name="line_3">
|
<widget class="Line" name="nLine">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
<enum>Qt::Horizontal</enum>
|
<enum>Qt::Horizontal</enum>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_6">
|
<widget class="QGroupBox" name="iGroupBox">
|
||||||
<item>
|
<layout class="QHBoxLayout" name="iLayout">
|
||||||
<widget class="QCheckBox" name="eBox">
|
<property name="spacing">
|
||||||
<property name="text">
|
<number>5</number>
|
||||||
<string>e</string>
|
</property>
|
||||||
</property>
|
<property name="leftMargin">
|
||||||
</widget>
|
<number>0</number>
|
||||||
</item>
|
</property>
|
||||||
<item>
|
<property name="topMargin">
|
||||||
<widget class="QLabel" name="label_5">
|
<number>0</number>
|
||||||
<property name="sizePolicy">
|
</property>
|
||||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
<property name="rightMargin">
|
||||||
<horstretch>0</horstretch>
|
<number>0</number>
|
||||||
<verstretch>0</verstretch>
|
</property>
|
||||||
</sizepolicy>
|
<property name="bottomMargin">
|
||||||
</property>
|
<number>0</number>
|
||||||
<property name="text">
|
</property>
|
||||||
<string>set keys found from 'reader attack' to emulator memory (implies x and i)</string>
|
<item>
|
||||||
</property>
|
<widget class="QCheckBox" name="iBox">
|
||||||
<property name="wordWrap">
|
<property name="text">
|
||||||
<bool>true</bool>
|
<string>i</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
<item>
|
||||||
|
<widget class="QLabel" name="label_3">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Interactive, means that console will not be returned until simulation finishes or is aborted</string>
|
||||||
|
</property>
|
||||||
|
<property name="wordWrap">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="Line" name="line_2">
|
<widget class="Line" name="iLine">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
<enum>Qt::Horizontal</enum>
|
<enum>Qt::Horizontal</enum>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
<widget class="QGroupBox" name="xGroupBox">
|
||||||
<item>
|
<layout class="QHBoxLayout" name="xLayout">
|
||||||
<widget class="QCheckBox" name="fBox">
|
<property name="spacing">
|
||||||
<property name="text">
|
<number>5</number>
|
||||||
<string>f</string>
|
</property>
|
||||||
</property>
|
<property name="leftMargin">
|
||||||
</widget>
|
<number>0</number>
|
||||||
</item>
|
</property>
|
||||||
<item>
|
<property name="topMargin">
|
||||||
<widget class="QLineEdit" name="fEdit">
|
<number>0</number>
|
||||||
<property name="sizePolicy">
|
</property>
|
||||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
<property name="rightMargin">
|
||||||
<horstretch>0</horstretch>
|
<number>0</number>
|
||||||
<verstretch>0</verstretch>
|
</property>
|
||||||
</sizepolicy>
|
<property name="bottomMargin">
|
||||||
</property>
|
<number>0</number>
|
||||||
<property name="maximumSize">
|
</property>
|
||||||
<size>
|
<item>
|
||||||
<width>100</width>
|
<widget class="QCheckBox" name="xBox">
|
||||||
<height>16777215</height>
|
<property name="text">
|
||||||
</size>
|
<string>x</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QLabel" name="label_6">
|
<widget class="QLabel" name="label_4">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
<verstretch>0</verstretch>
|
<verstretch>0</verstretch>
|
||||||
</sizepolicy>
|
</sizepolicy>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>get UIDs to use for 'reader attack' from file 'f <filename.txt>' (implies x and i)</string>
|
<string>Crack, performs the 'reader attack', nr/ar attack against a legitimate reader, fishes out the key(s)</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="wordWrap">
|
<property name="wordWrap">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="Line" name="line">
|
<widget class="Line" name="xLine">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
<enum>Qt::Horizontal</enum>
|
<enum>Qt::Horizontal</enum>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_7">
|
<widget class="QGroupBox" name="eGroupBox">
|
||||||
<item>
|
<layout class="QHBoxLayout" name="eLayout">
|
||||||
<widget class="QCheckBox" name="rBox">
|
<property name="spacing">
|
||||||
<property name="text">
|
<number>5</number>
|
||||||
<string>r</string>
|
</property>
|
||||||
</property>
|
<property name="leftMargin">
|
||||||
</widget>
|
<number>0</number>
|
||||||
</item>
|
</property>
|
||||||
<item>
|
<property name="topMargin">
|
||||||
<widget class="QLabel" name="label_7">
|
<number>0</number>
|
||||||
<property name="sizePolicy">
|
</property>
|
||||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
<property name="rightMargin">
|
||||||
<horstretch>0</horstretch>
|
<number>0</number>
|
||||||
<verstretch>0</verstretch>
|
</property>
|
||||||
</sizepolicy>
|
<property name="bottomMargin">
|
||||||
</property>
|
<number>0</number>
|
||||||
<property name="text">
|
</property>
|
||||||
<string>Generate random nonces instead of sequential nonces. Standard reader attack won't work with this option, only moebius attack works</string>
|
<item>
|
||||||
</property>
|
<widget class="QCheckBox" name="eBox">
|
||||||
<property name="wordWrap">
|
<property name="text">
|
||||||
<bool>true</bool>
|
<string>e</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
<item>
|
||||||
|
<widget class="QLabel" name="label_5">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>set keys found from 'reader attack' to emulator memory (implies x(--crack) and i)</string>
|
||||||
|
</property>
|
||||||
|
<property name="wordWrap">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="Line" name="line_7">
|
<widget class="Line" name="eLine">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QGroupBox" name="fGroupBox">
|
||||||
|
<layout class="QHBoxLayout" name="fLayout">
|
||||||
|
<property name="spacing">
|
||||||
|
<number>5</number>
|
||||||
|
</property>
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="QCheckBox" name="fBox">
|
||||||
|
<property name="text">
|
||||||
|
<string>f</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLineEdit" name="fEdit">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>100</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_6">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>get UIDs to use for 'reader attack' from file 'f <filename.txt>' (implies x and i)</string>
|
||||||
|
</property>
|
||||||
|
<property name="wordWrap">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="Line" name="fLine">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QGroupBox" name="rGroupBox">
|
||||||
|
<layout class="QHBoxLayout" name="rLayout">
|
||||||
|
<property name="spacing">
|
||||||
|
<number>5</number>
|
||||||
|
</property>
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="QCheckBox" name="rBox">
|
||||||
|
<property name="text">
|
||||||
|
<string>r</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_7">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Generate random nonces instead of sequential nonces. Standard reader attack won't work with this option, only moebius attack works</string>
|
||||||
|
</property>
|
||||||
|
<property name="wordWrap">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="Line" name="rLine">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QGroupBox" name="vGroupBox">
|
||||||
|
<layout class="QHBoxLayout" name="vLayout">
|
||||||
|
<property name="spacing">
|
||||||
|
<number>5</number>
|
||||||
|
</property>
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="QCheckBox" name="vBox">
|
||||||
|
<property name="text">
|
||||||
|
<string>-v</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_11">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>verbose output</string>
|
||||||
|
</property>
|
||||||
|
<property name="wordWrap">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="Line" name="vLine">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
<enum>Qt::Horizontal</enum>
|
<enum>Qt::Horizontal</enum>
|
||||||
</property>
|
</property>
|
||||||
|
|||||||
@@ -15,10 +15,10 @@ MF_trailerDecoderDialog::MF_trailerDecoderDialog(QWidget *parent) :
|
|||||||
sizeGroup->addButton(ui->size4Button, 4);
|
sizeGroup->addButton(ui->size4Button, 4);
|
||||||
sizeGroup->addButton(ui->size16Button, 16);
|
sizeGroup->addButton(ui->size16Button, 16);
|
||||||
connect(sizeGroup, QOverload<int, bool>::of(&QButtonGroup::buttonToggled), this, &MF_trailerDecoderDialog::on_blockSizeChanged);
|
connect(sizeGroup, QOverload<int, bool>::of(&QButtonGroup::buttonToggled), this, &MF_trailerDecoderDialog::on_blockSizeChanged);
|
||||||
connect(ui->C0Box, &QSpinBox::textChanged, this, &MF_trailerDecoderDialog::on_boxChanged);
|
connect(ui->C0Box, QOverload<int>::of(&QSpinBox::valueChanged), this, &MF_trailerDecoderDialog::on_boxChanged);
|
||||||
connect(ui->C1Box, &QSpinBox::textChanged, this, &MF_trailerDecoderDialog::on_boxChanged);
|
connect(ui->C1Box, QOverload<int>::of(&QSpinBox::valueChanged), this, &MF_trailerDecoderDialog::on_boxChanged);
|
||||||
connect(ui->C2Box, &QSpinBox::textChanged, this, &MF_trailerDecoderDialog::on_boxChanged);
|
connect(ui->C2Box, QOverload<int>::of(&QSpinBox::valueChanged), this, &MF_trailerDecoderDialog::on_boxChanged);
|
||||||
connect(ui->C3Box, &QSpinBox::textChanged, this, &MF_trailerDecoderDialog::on_boxChanged);
|
connect(ui->C3Box, QOverload<int>::of(&QSpinBox::valueChanged), this, &MF_trailerDecoderDialog::on_boxChanged);
|
||||||
|
|
||||||
ui->dataBlockWidget->setRowCount(3);
|
ui->dataBlockWidget->setRowCount(3);
|
||||||
ui->dataBlockWidget->setColumnCount(4);
|
ui->dataBlockWidget->setColumnCount(4);
|
||||||
@@ -123,7 +123,7 @@ void MF_trailerDecoderDialog::setTableItem(QTableWidget* widget, int row, int co
|
|||||||
widget->item(row, column)->setText(text);
|
widget->item(row, column)->setText(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MF_trailerDecoderDialog::on_boxChanged(const QString &arg1)
|
void MF_trailerDecoderDialog::on_boxChanged()
|
||||||
{
|
{
|
||||||
quint8 ACBits[4];
|
quint8 ACBits[4];
|
||||||
ACBits[0] = ui->C0Box->value();
|
ACBits[0] = ui->C0Box->value();
|
||||||
|
|||||||
@@ -23,11 +23,11 @@ public:
|
|||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
|
||||||
void on_accessBitsEdit_textChanged(const QString &arg1);
|
void on_accessBitsEdit_textChanged(const QString& arg1);
|
||||||
|
|
||||||
void on_blockSizeChanged(int id, bool st);
|
void on_blockSizeChanged(int id, bool st);
|
||||||
|
|
||||||
void on_boxChanged(const QString &arg1);
|
void on_boxChanged();
|
||||||
private:
|
private:
|
||||||
Ui::MF_trailerDecoderDialog *ui;
|
Ui::MF_trailerDecoderDialog *ui;
|
||||||
QRegularExpressionValidator* validator;
|
QRegularExpressionValidator* validator;
|
||||||
|
|||||||
@@ -18,10 +18,18 @@ MF_UID_parameterDialog::~MF_UID_parameterDialog()
|
|||||||
|
|
||||||
void MF_UID_parameterDialog::on_buttonBox_accepted()
|
void MF_UID_parameterDialog::on_buttonBox_accepted()
|
||||||
{
|
{
|
||||||
emit sendCMD("hf mf csetuid "
|
if(Util::getClientType() == Util::CLIENTTYPE_OFFICIAL)
|
||||||
+ ui->UIDLineEdit->text()
|
emit sendCMD("hf mf csetuid "
|
||||||
+ " "
|
+ ui->UIDLineEdit->text()
|
||||||
+ ui->ATQALineEdit->text()
|
+ " "
|
||||||
+ " "
|
+ ui->ATQALineEdit->text()
|
||||||
+ ui->SAKLineEdit->text());
|
+ " "
|
||||||
|
+ ui->SAKLineEdit->text());
|
||||||
|
else if(Util::getClientType() == Util::CLIENTTYPE_ICEMAN) // same format in v4.9237
|
||||||
|
emit sendCMD("hf mf csetuid "
|
||||||
|
+ ui->UIDLineEdit->text()
|
||||||
|
+ " "
|
||||||
|
+ ui->ATQALineEdit->text()
|
||||||
|
+ " "
|
||||||
|
+ ui->SAKLineEdit->text());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,8 +2,10 @@
|
|||||||
#define MF_UID_PARAMETERDIALOG_H
|
#define MF_UID_PARAMETERDIALOG_H
|
||||||
|
|
||||||
#include <QDialog>
|
#include <QDialog>
|
||||||
|
#include "common/util.h"
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui
|
||||||
|
{
|
||||||
class MF_UID_parameterDialog;
|
class MF_UID_parameterDialog;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -18,7 +20,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
Ui::MF_UID_parameterDialog *ui;
|
Ui::MF_UID_parameterDialog *ui;
|
||||||
signals:
|
signals:
|
||||||
void sendCMD(QString cmd);
|
void sendCMD(const QString& cmd);
|
||||||
private slots:
|
private slots:
|
||||||
void on_buttonBox_accepted();
|
void on_buttonBox_accepted();
|
||||||
};
|
};
|
||||||
|
|||||||