Merge pull request #4 from wh201906/dev

V0.1.2
This commit is contained in:
wh201906 2020-08-08 22:02:32 +08:00 committed by GitHub
commit d6beafe175
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
32 changed files with 2906 additions and 1217 deletions

View file

@ -20,6 +20,7 @@ SOURCES += \
common/pm3process.cpp \
common/util.cpp \
module/mifare.cpp \
ui/mf_trailerdecoderdialog.cpp \
ui/mf_sim_simdialog.cpp \
ui/mf_uid_parameterdialog.cpp \
ui/mainwindow.cpp \
@ -29,12 +30,14 @@ HEADERS += \
common/pm3process.h \
common/util.h \
module/mifare.h \
ui/mf_trailerdecoderdialog.h \
ui/mf_sim_simdialog.h \
ui/mf_uid_parameterdialog.h \
ui/mainwindow.h \
ui/mf_attack_hardnesteddialog.h \
FORMS += \
ui/mf_trailerdecoderdialog.ui \
ui/mf_sim_simdialog.ui \
ui/mf_uid_parameterdialog.ui \
ui/mainwindow.ui \
@ -49,7 +52,7 @@ qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
VERSION = 0.1.1
VERSION = 0.1.2
QMAKE_TARGET_PRODUCT = "Proxmark3GUI"
QMAKE_TARGET_DESCRIPTION = "Proxmark3GUI"
QMAKE_TARGET_COMPANY = "wh201906"

View file

@ -1,33 +1,65 @@
# Proxmark3GUI
A GUI for [Proxmark3](https://github.com/Proxmark/proxmark3) client
[中文](README/README.zh_CN.md)
[中文](README/doc/README_zh_CN.md)
***
## Features
+ Support raw commands of Proxmark3 client
+ Easy to find available Serial Port
+ Support raw commands of Proxmark3 client(Official/Iceman)
+ Have a friendly UI to test Mifare cards
+ Easy to edit Mifare data files
+ Support binary(.bin .dump) files and text(.eml) files
+ Support different card size(MINI, 1K, 2K, 4K)
+ Easy to edit Mifare block data
+ Easy to read all/selected blocks with well-designed read logic
+ Easy to write all/selected blocks
+ Support binary(.bin .dump) files and text(.eml) files
+ Analyze Access Bits
+ Support Chinese Magic Card
+ Customize UI
+ ...
***
## Previews
![nested_attack](README/mf_nested_attack.gif)
## Preview
![preview](README/img/preview.png)
![mf_load_file](README/mf_load_file.gif)
more previews [here](README/doc/previews.md)
![mf_edit_file](README/mf_edit_file.gif)
***
![raw_command](README/raw_command.gif)
## About Iceman fork/repo
The [Iceman fork/repo](https://github.com/RfidResearchGroup/proxmark3) has more powerful functions like offline sniff. These guys even developed a new hardware called Proxmark3 RDV4 with smart card support. But the official repo and the Iceman repo is not fully compatible.
This GUI was designed for only official repo at first, but I'm trying to make it compatible with Iceman repo.
Supported functions when using Iceman client:
[supported functions](README/doc/supported_Iceman.md)
***
## About Compiled Windows clients
A cool guy [Gator96100](https://github.com/Gator96100) creates [ProxSpace](https://github.com/Gator96100/ProxSpace) and makes it possible to compile both the firmware and client on Windows.
Also, he makes the [pre-compiled Windows client](http://www.proxmark.org/forum/viewtopic.php?id=3975) so you can download it and run your PM3 client on Windows instantly.
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.
***
## Update Log:
### V0.1.2
+ Optimize read logic
+ Make UI Customizable
+ Save client path automatically
+ Add Trailer Decoder
+ Support read/write selected blocks
+ Support a few Iceman functions
+ Fix some bugs
### V0.1.1
+ Complete Mifare module(support simulate and sniff)

View file

@ -1,38 +0,0 @@
# Proxmark3GUI
一个自制的[Proxmark3](https://github.com/Proxmark/proxmark3) GUI
[English](../README.md)
***
## 特色功能
+ 支持直接输入PM3命令
+ 有针对于Mifare卡IC卡的图形界面
+ 支持编辑Mifare扇区数据文件
+ 可以打开二进制/文本格式的扇区数据文件
+ ...
***
## 预览图
![nested_attack](mf_nested_attack.gif)
![mf_load_file](mf_load_file.gif)
![mf_edit_file](mf_edit_file.gif)
![raw_command](raw_command.gif)
***
## 更新日志:
### V0.1.1
+ 完成整个Mifare模块支持模拟卡和嗅探功能
### V0.1
+ 支持处理Mifare卡片及相关数据文件
### V0.0.1
+ 一个带串口选择框的实验版本

View file

@ -0,0 +1,66 @@
# Proxmark3GUI
一个自制的[Proxmark3](https://github.com/Proxmark/proxmark3) GUI
[English](../../README.md)
***
## 功能
+ 快速查找可用端口并连接
+ 支持直接输入PM3命令(官方版/冰人版)
+ 有针对于Mifare卡IC卡的图形界面
+ 支持不同大小的卡片(MINI, 1K, 2K, 4K)
+ 支持编辑Mifare扇区数据
+ 支持读取全卡/选中扇区,读卡逻辑更加智能
+ 支持写入全卡/选中扇区
+ 可以打开二进制/文本格式的扇区数据文件
+ 分析访问控制位Access Bits
+ 支持UID卡操作UID快速读写UFUID锁卡
+ 自定义UI界面
+ ...
***
## 预览图
![preview](../img/preview_zh_CN.png)
[更多预览](../doc/previews.md)
***
## 关于冰人版
这个GUI一开始是针对官方版本做的现在正在尽力让它兼容冰人版的功能
没钱买RDV4也没钱买两台PM3测一次冰人就要烧一次固件 qwq
[已支持功能](../doc/supported_Iceman.md)
***
## 关于预编译Windows客户端
一个国外大佬 [Gator96100](https://github.com/Gator96100) 做了个 [ProxSpace](https://github.com/Gator96100/ProxSpace) 以便在Windows平台上编译PM3固件和客户端他还把自己编译好的客户端放到了[论坛](http://www.proxmark.org/forum/viewtopic.php?id=3975)里面
文件都是放到Google Drive上面的国内网络无法访问所以我在release版本里面放了个带预编译客户端版本的GUI。这个GUI也可以搭配你自己的客户端使用
(本来打算在CSDN下载里面放几个最新版客户端的结果不能把下载币改为0)
感谢大佬
***
## 更新日志:
### V0.1.2
+ 优化读卡逻辑
+ UI自定义
+ 自动保存客户端路径
+ 添加访问控制位解码器(也可用于自己构造访问控制位)
+ 支持仅读写选中块
+ 支持部分冰人功能
+ 修复部分bug
### V0.1.1
+ 完成整个Mifare模块支持模拟卡和嗅探功能
### V0.1
+ 支持处理Mifare卡片及相关数据文件
### V0.0.1
+ 一个带串口选择框的实验版本

16
README/doc/previews.md Normal file
View file

@ -0,0 +1,16 @@
## Previews
Raw Command:
![raw_command](../img/raw_command.gif)
Mifare Nested Attack:
![nested_attack](../img/mf_nested_attack.gif)
Mifare Load File:
![mf_loadfile](../img/mf_loadfile.gif)
Mifare Edit File:
![mf_editfile](../img/mf_editfile.gif)
Mifare Trailer Decoder:
![mf_trailer](../img/mf_trailer.gif)

View file

@ -0,0 +1,9 @@
## 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

BIN
README/img/mf_editfile.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

BIN
README/img/mf_loadfile.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 797 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 438 KiB

BIN
README/img/mf_trailer.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 407 KiB

BIN
README/img/preview.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

BIN
README/img/raw_command.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 345 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 650 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 637 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 857 KiB

View file

@ -16,18 +16,29 @@ PM3Process::PM3Process(QThread* thread, QObject* parent): QProcess(parent)
void PM3Process::connectPM3(const QString path, const QString port)
{
QString result;
Util::ClientType clientType = Util::CLIENTTYPE_OFFICIAL;
setRequiringOutput(true);
// using "-f" option to make the client output flushed after every print.
start(path, QStringList() << port << "-f", QProcess::Unbuffered | QProcess::ReadWrite);
if(waitForStarted(10000))
{
while(waitForReadyRead(1000))
;
waitForReadyRead(1000);
setRequiringOutput(false);
QString result = *requiredOutput;
result = *requiredOutput;
if(result.indexOf("[=]") != -1)
{
clientType = Util::CLIENTTYPE_ICEMAN;
setRequiringOutput(true);
write("hw version\r\n");
waitForReadyRead(1000);
result = *requiredOutput;
setRequiringOutput(false);
}
if(result.indexOf("os: ") != -1) // make sure the PM3 is connected
{
emit changeClientType(clientType);
result = result.mid(result.indexOf("os: "));
result = result.left(result.indexOf("\r\n"));
result = result.mid(3, result.lastIndexOf(" ") - 3);

View file

@ -9,6 +9,8 @@
#include <QtSerialPort/QSerialPortInfo>
#include <QtSerialPort/QSerialPort>
#include "util.h"
class PM3Process : public QProcess
{
Q_OBJECT
@ -34,6 +36,7 @@ private:
signals:
void PM3StatedChanged(bool st, QString info = "");
void newOutput(QString output);
void changeClientType(Util::ClientType);
};
#endif // PM3PROCESS_H

View file

@ -5,6 +5,8 @@ Util::Util(QObject *parent) : QObject(parent)
isRequiringOutput = false;
requiredOutput = new QString();
timeStamp = QTime::currentTime();
this->clientType = CLIENTTYPE_OFFICIAL;
qRegisterMetaType<Util::ClientType>("Util::ClientType");
}
void Util::processOutput(QString output)
@ -24,20 +26,20 @@ void Util::execCMD(QString cmd)
emit write(cmd + "\r\n");
}
QString Util::execCMDWithOutput(QString cmd, unsigned long timeout)
QString Util::execCMDWithOutput(QString cmd, unsigned long waitTime)
{
QTime currTime = QTime::currentTime();
QTime targetTime = QTime::currentTime().addMSecs(timeout);
QTime targetTime = QTime::currentTime().addMSecs(waitTime);
isRequiringOutput = true;
requiredOutput->clear();
execCMD(cmd);
while( QTime::currentTime() < targetTime)
while(QTime::currentTime() < targetTime)
{
QApplication::processEvents();
if(timeStamp > currTime)
{
currTime = timeStamp;
targetTime = timeStamp.addMSecs(timeout);
targetTime = timeStamp.addMSecs(waitTime);
}
}
isRequiringOutput = false;
@ -47,6 +49,15 @@ QString Util::execCMDWithOutput(QString cmd, unsigned long timeout)
void Util::delay(unsigned int msec)
{
QTime timer = QTime::currentTime().addMSecs(msec);
while( QTime::currentTime() < timer )
while(QTime::currentTime() < timer)
QApplication::processEvents(QEventLoop::AllEvents, 100);
}
Util::ClientType Util::getClientType()
{
return this->clientType;
}
void Util::setClientType(Util::ClientType clientType)
{
this->clientType = clientType;
}

View file

@ -8,23 +8,35 @@
#include <QApplication>
#include <QTime>
#include <QTimer>
#include <QMetaType>
class Util : public QObject
{
Q_OBJECT
public:
enum ClientType
{
CLIENTTYPE_OFFICIAL,
CLIENTTYPE_ICEMAN,
};
Q_ENUM(Util::ClientType)
explicit Util(QObject *parent = nullptr);
void execCMD(QString cmd);
QString execCMDWithOutput(QString cmd, unsigned long timeout = 2000);
QString execCMDWithOutput(QString cmd, unsigned long waitTime = 2000);
void delay(unsigned int msec);
ClientType getClientType();
public slots:
void processOutput(QString output);
void setClientType(Util::ClientType clientType);
private:
bool isRequiringOutput;
QString* requiredOutput;
QTime timeStamp;
ClientType clientType;
signals:
void refreshOutput(const QString& output);
void write(QString data);

File diff suppressed because it is too large Load diff

View file

@ -8,10 +8,6 @@
<source>Hardnested Attack</source>
<translation>Hardnested攻击</translation>
</message>
<message>
<source>Known Key:</source>
<translation type="obsolete">Key</translation>
</message>
<message>
<location filename="../ui/mf_attack_hardnesteddialog.ui" line="20"/>
<source>Known Block:</source>
@ -40,17 +36,9 @@
<source>Target Block:</source>
<translation></translation>
</message>
<message>
<source>Target Block: </source>
<translation type="vanished"></translation>
</message>
</context>
<context>
<name>MF_Sim_simDialog</name>
<message>
<source>Dialog</source>
<translation type="obsolete"></translation>
</message>
<message>
<location filename="../ui/mf_sim_simdialog.ui" line="14"/>
<source>Simulate</source>
@ -126,17 +114,9 @@
<source>Generate random nonces instead of sequential nonces. Standard reader attack won&apos;t work with this option, only moebius attack works</source>
<translation>nonce而不是顺序的noncePM3将不对读卡器进行标准攻击moebius攻击</translation>
</message>
<message>
<source> Generate random nonces instead of sequential nonces. Standard reader attack won&apos;t work with this option, only moebius attack works.</source>
<translation type="vanished">nonce而不是顺序的noncePM3将不对读卡器进行标准攻击moebius攻击</translation>
</message>
</context>
<context>
<name>MF_UID_parameterDialog</name>
<message>
<source>Dialog</source>
<translation type="vanished"></translation>
</message>
<message>
<location filename="../ui/mf_uid_parameterdialog.ui" line="14"/>
<source>Set Parameter</source>
@ -157,9 +137,148 @@
<source>SAK:</source>
<translation></translation>
</message>
</context>
<context>
<name>MF_trailerDecoderDialog</name>
<message>
<source>The parameter will not change if you leave it empty.</source>
<translation type="vanished"></translation>
<location filename="../ui/mf_trailerdecoderdialog.ui" line="14"/>
<source>Trailer Decoder</source>
<translation>Trailer解码</translation>
</message>
<message>
<location filename="../ui/mf_trailerdecoderdialog.ui" line="22"/>
<source>Blocks</source>
<translation></translation>
</message>
<message>
<location filename="../ui/mf_trailerdecoderdialog.ui" line="28"/>
<source>4</source>
<translation></translation>
</message>
<message>
<location filename="../ui/mf_trailerdecoderdialog.ui" line="38"/>
<source>16</source>
<translation></translation>
</message>
<message>
<location filename="../ui/mf_trailerdecoderdialog.ui" line="67"/>
<source>Trailer Data:
(like &quot;FF0780&quot; or &quot;FF 07 80&quot;)</source>
<translation>Access Bits
FF0780FF 07 80</translation>
</message>
<message>
<location filename="../ui/mf_trailerdecoderdialog.ui" line="120"/>
<source>Or set bits manually</source>
<translation>访</translation>
</message>
<message>
<location filename="../ui/mf_trailerdecoderdialog.ui" line="134"/>
<source>Cx0</source>
<translation></translation>
</message>
<message>
<location filename="../ui/mf_trailerdecoderdialog.ui" line="155"/>
<source>Cx1</source>
<translation></translation>
</message>
<message>
<location filename="../ui/mf_trailerdecoderdialog.ui" line="176"/>
<source>Cx2</source>
<translation></translation>
</message>
<message>
<location filename="../ui/mf_trailerdecoderdialog.ui" line="197"/>
<source>Cx3</source>
<translation></translation>
</message>
<message>
<location filename="../ui/mf_trailerdecoderdialog.ui" line="235"/>
<source>Data Block Permission:</source>
<translation>Block访问权限</translation>
</message>
<message>
<location filename="../ui/mf_trailerdecoderdialog.ui" line="252"/>
<source>Block0</source>
<translation></translation>
</message>
<message>
<location filename="../ui/mf_trailerdecoderdialog.ui" line="257"/>
<source>Block1</source>
<translation></translation>
</message>
<message>
<location filename="../ui/mf_trailerdecoderdialog.ui" line="262"/>
<source>Block2</source>
<translation></translation>
</message>
<message>
<location filename="../ui/mf_trailerdecoderdialog.ui" line="267"/>
<location filename="../ui/mf_trailerdecoderdialog.ui" line="307"/>
<source>Read</source>
<translation></translation>
</message>
<message>
<location filename="../ui/mf_trailerdecoderdialog.ui" line="272"/>
<location filename="../ui/mf_trailerdecoderdialog.ui" line="312"/>
<source>Write</source>
<translation></translation>
</message>
<message>
<location filename="../ui/mf_trailerdecoderdialog.ui" line="277"/>
<source>Increase</source>
<translation></translation>
</message>
<message>
<location filename="../ui/mf_trailerdecoderdialog.ui" line="282"/>
<source>Decrease/Transfer/Restore</source>
<translation>//</translation>
</message>
<message>
<location filename="../ui/mf_trailerdecoderdialog.ui" line="290"/>
<source>Trailer Block Permission:</source>
<translation>Trailer访问权限</translation>
</message>
<message>
<location filename="../ui/mf_trailerdecoderdialog.ui" line="317"/>
<source>KeyA</source>
<translation></translation>
</message>
<message>
<location filename="../ui/mf_trailerdecoderdialog.ui" line="322"/>
<source>Access Bits</source>
<translation>Access Bits</translation>
</message>
<message>
<location filename="../ui/mf_trailerdecoderdialog.ui" line="327"/>
<source>KeyB</source>
<translation></translation>
</message>
<message>
<location filename="../ui/mf_trailerdecoderdialog.ui" line="337"/>
<source>Reference:
MF1S70YYX_V1 Product data sheet
Rev. 3.2 23 November 2017</source>
<translation>
MF1S70YYX_V1 Product data sheet
Rev. 3.2 23 November 2017</translation>
</message>
<message>
<location filename="../ui/mf_trailerdecoderdialog.ui" line="358"/>
<source>Note:the Access Bits usually contains 4 bytes(8 hex symbols), but only the first 3 bytes matters. You can set the 4th byte randomly.</source>
<translation>Access Bits一般包含4个字节8163访</translation>
</message>
<message>
<location filename="../ui/mf_trailerdecoderdialog.cpp" line="43"/>
<source>Invalid!
It could make the whole sector blocked irreversibly!</source>
<translation>
</translation>
</message>
<message>
<location filename="../ui/mf_trailerdecoderdialog.cpp" line="52"/>
<source>Valid</source>
<translation></translation>
</message>
</context>
<context>
@ -175,555 +294,554 @@
<translation></translation>
</message>
<message>
<location filename="../ui/mainwindow.ui" line="80"/>
<location filename="../ui/mainwindow.ui" line="82"/>
<source>Refresh</source>
<translation></translation>
</message>
<message>
<location filename="../ui/mainwindow.ui" line="87"/>
<location filename="../ui/mainwindow.ui" line="95"/>
<source>Connect</source>
<translation></translation>
</message>
<message>
<location filename="../ui/mainwindow.ui" line="94"/>
<location filename="../ui/mainwindow.ui" line="108"/>
<source>Disconnect</source>
<translation></translation>
</message>
<message>
<location filename="../ui/mainwindow.ui" line="110"/>
<location filename="../ui/mainwindow.ui" line="127"/>
<source>Mifare</source>
<translation>Mifare(IC)</translation>
</message>
<message>
<location filename="../ui/mainwindow.ui" line="203"/>
<source>&gt;&gt;</source>
<translation></translation>
<location filename="../ui/mainwindow.ui" line="209"/>
<source>Select Trailer</source>
<translation></translation>
</message>
<message>
<location filename="../ui/mainwindow.ui" line="228"/>
<source>&lt;&lt;</source>
<translation></translation>
</message>
<message>
<location filename="../ui/mainwindow.ui" line="260"/>
<source>F</source>
<translation></translation>
</message>
<message>
<location filename="../ui/mainwindow.ui" line="317"/>
<location filename="../ui/mainwindow.ui" line="347"/>
<source>Card Type</source>
<translation></translation>
</message>
<message>
<location filename="../ui/mainwindow.ui" line="332"/>
<location filename="../ui/mainwindow.ui" line="368"/>
<source>MINI</source>
<extracomment>320</extracomment>
<translation></translation>
</message>
<message>
<location filename="../ui/mainwindow.ui" line="339"/>
<location filename="../ui/mainwindow.ui" line="381"/>
<source>1K</source>
<extracomment>1024</extracomment>
<translation></translation>
</message>
<message>
<location filename="../ui/mainwindow.ui" line="349"/>
<location filename="../ui/mainwindow.ui" line="397"/>
<source>2K</source>
<extracomment>2048</extracomment>
<translation></translation>
</message>
<message>
<location filename="../ui/mainwindow.ui" line="356"/>
<location filename="../ui/mainwindow.ui" line="410"/>
<source>4K</source>
<extracomment>4096</extracomment>
<translation></translation>
</message>
<message>
<location filename="../ui/mainwindow.ui" line="366"/>
<location filename="../ui/mainwindow.ui" line="420"/>
<source>File</source>
<translation></translation>
</message>
<message>
<location filename="../ui/mainwindow.ui" line="384"/>
<location filename="../ui/mainwindow.ui" line="948"/>
<location filename="../ui/mainwindow.ui" line="441"/>
<location filename="../ui/mainwindow.ui" line="1134"/>
<source>Load</source>
<translation></translation>
</message>
<message>
<location filename="../ui/mainwindow.ui" line="397"/>
<location filename="../ui/mainwindow.ui" line="961"/>
<location filename="../ui/mainwindow.ui" line="454"/>
<location filename="../ui/mainwindow.ui" line="1147"/>
<source>Save</source>
<translation></translation>
</message>
<message>
<location filename="../ui/mainwindow.ui" line="417"/>
<location filename="../ui/mainwindow.cpp" line="602"/>
<location filename="../ui/mainwindow.ui" line="474"/>
<location filename="../ui/mainwindow.cpp" line="814"/>
<source>Data</source>
<translation></translation>
</message>
<message>
<location filename="../ui/mainwindow.ui" line="427"/>
<location filename="../ui/mainwindow.ui" line="484"/>
<source>Key</source>
<translation></translation>
</message>
<message>
<location filename="../ui/mainwindow.ui" line="437"/>
<location filename="../ui/mainwindow.ui" line="494"/>
<source>Attack</source>
<translation></translation>
</message>
<message>
<location filename="../ui/mainwindow.ui" line="462"/>
<location filename="../ui/mainwindow.ui" line="528"/>
<source>Card Info</source>
<translation></translation>
</message>
<message>
<location filename="../ui/mainwindow.ui" line="475"/>
<location filename="../ui/mainwindow.ui" line="541"/>
<source>Check Default</source>
<translation></translation>
</message>
<message>
<location filename="../ui/mainwindow.ui" line="488"/>
<location filename="../ui/mainwindow.ui" line="554"/>
<source>Nested</source>
<translation>Nested攻击</translation>
</message>
<message>
<location filename="../ui/mainwindow.ui" line="495"/>
<location filename="../ui/mainwindow.ui" line="567"/>
<source>Hardnested</source>
<translation>Hardested攻击</translation>
</message>
<message>
<location filename="../ui/mainwindow.ui" line="520"/>
<location filename="../ui/mainwindow.ui" line="592"/>
<source>Read/Write</source>
<translation>/</translation>
</message>
<message>
<location filename="../ui/mainwindow.ui" line="530"/>
<location filename="../ui/mainwindow.ui" line="605"/>
<source>Block:</source>
<translation></translation>
</message>
<message>
<location filename="../ui/mainwindow.ui" line="562"/>
<location filename="../ui/mainwindow.ui" line="637"/>
<source>Key:</source>
<translation></translation>
</message>
<message>
<location filename="../ui/mainwindow.ui" line="581"/>
<location filename="../ui/mainwindow.ui" line="656"/>
<source>Key Type:</source>
<translation>Key类型</translation>
</message>
<message>
<location filename="../ui/mainwindow.ui" line="601"/>
<source>A</source>
<translation></translation>
<location filename="../ui/mainwindow.ui" line="1108"/>
<source>Snoop</source>
<translation>(Snoop)</translation>
</message>
<message>
<location filename="../ui/mainwindow.ui" line="606"/>
<source>B</source>
<translation></translation>
<location filename="../ui/mainwindow.ui" line="1121"/>
<source>List Data</source>
<translation></translation>
</message>
<message>
<location filename="../ui/mainwindow.ui" line="614"/>
<location filename="../ui/mainwindow.ui" line="679"/>
<source>Data:</source>
<translation></translation>
</message>
<message>
<location filename="../ui/mainwindow.ui" line="636"/>
<location filename="../ui/mainwindow.ui" line="701"/>
<source>Normal(Require Password)</source>
<translation></translation>
</message>
<message>
<location filename="../ui/mainwindow.ui" line="651"/>
<location filename="../ui/mainwindow.ui" line="740"/>
<source>Read Block</source>
<translation></translation>
</message>
<message>
<location filename="../ui/mainwindow.ui" line="658"/>
<location filename="../ui/mainwindow.ui" line="747"/>
<source>Write Block</source>
<translation></translation>
</message>
<message>
<location filename="../ui/mainwindow.ui" line="665"/>
<location filename="../ui/mainwindow.ui" line="754"/>
<location filename="../ui/mainwindow.ui" line="854"/>
<source>Read All</source>
<translation></translation>
</message>
<message>
<location filename="../ui/mainwindow.ui" line="672"/>
<location filename="../ui/mainwindow.ui" line="761"/>
<source>Write All</source>
<translation></translation>
</message>
<message>
<location filename="../ui/mainwindow.ui" line="691"/>
<location filename="../ui/mainwindow.ui" line="783"/>
<source>Dump</source>
<translation>Dump命令</translation>
</message>
<message>
<location filename="../ui/mainwindow.ui" line="704"/>
<location filename="../ui/mainwindow.ui" line="802"/>
<source>Restore</source>
<translation>Restore命令</translation>
</message>
<message>
<location filename="../ui/mainwindow.ui" line="714"/>
<location filename="../ui/mainwindow.ui" line="812"/>
<source>Chinese Magic Card(Without Password)</source>
<translation>UID卡</translation>
</message>
<message>
<location filename="../ui/mainwindow.ui" line="726"/>
<location filename="../ui/mainwindow.ui" line="833"/>
<source>Lock UFUID Card</source>
<translation>UFUID卡</translation>
</message>
<message>
<location filename="../ui/mainwindow.ui" line="733"/>
<location filename="../ui/mainwindow.cpp" line="461"/>
<location filename="../ui/mainwindow.ui" line="846"/>
<location filename="../ui/mainwindow.cpp" line="651"/>
<source>About UID Card</source>
<translation>UID卡</translation>
</message>
<message>
<location filename="../ui/mainwindow.ui" line="774"/>
<location filename="../ui/mainwindow.ui" line="917"/>
<source>Set Parameter</source>
<translation></translation>
</message>
<message>
<location filename="../ui/mainwindow.ui" line="793"/>
<location filename="../ui/mainwindow.ui" line="936"/>
<source>Wipe</source>
<translation></translation>
</message>
<message>
<location filename="../ui/mainwindow.ui" line="819"/>
<location filename="../ui/mainwindow.ui" line="874"/>
<location filename="../ui/mainwindow.ui" line="962"/>
<location filename="../ui/mainwindow.ui" line="1038"/>
<source>Simulate</source>
<translation></translation>
</message>
<message>
<location filename="../ui/mainwindow.ui" line="847"/>
<source>Load from data above</source>
<translation></translation>
</message>
<message>
<location filename="../ui/mainwindow.ui" line="410"/>
<location filename="../ui/mainwindow.ui" line="867"/>
<location filename="../ui/mainwindow.ui" line="467"/>
<location filename="../ui/mainwindow.ui" line="1025"/>
<source>Clear</source>
<translation></translation>
</message>
<message>
<location filename="../ui/mainwindow.ui" line="897"/>
<location filename="../ui/mainwindow.ui" line="928"/>
<location filename="../ui/mainwindow.ui" line="202"/>
<source>Select All</source>
<translation></translation>
</message>
<message>
<location filename="../ui/mainwindow.ui" line="238"/>
<source>KeyBlocks-&gt;Key</source>
<translation>-&gt;</translation>
</message>
<message>
<location filename="../ui/mainwindow.ui" line="251"/>
<source>KeyBlocks&lt;-Key</source>
<translation>&lt;-</translation>
</message>
<message>
<location filename="../ui/mainwindow.ui" line="264"/>
<source>Fill Keys</source>
<translation></translation>
</message>
<message>
<location filename="../ui/mainwindow.ui" line="277"/>
<source>Trailer Decoder</source>
<translation>Trailer解码</translation>
</message>
<message>
<location filename="../ui/mainwindow.ui" line="290"/>
<source>Set Fonts</source>
<translation></translation>
</message>
<message>
<location filename="../ui/mainwindow.ui" line="725"/>
<location filename="../ui/mainwindow.ui" line="859"/>
<source>Read One</source>
<translation></translation>
</message>
<message>
<location filename="../ui/mainwindow.ui" line="738"/>
<location filename="../ui/mainwindow.ui" line="872"/>
<source>Write One</source>
<translation></translation>
</message>
<message>
<location filename="../ui/mainwindow.ui" line="751"/>
<location filename="../ui/mainwindow.ui" line="885"/>
<location filename="../ui/mainwindow.ui" line="1012"/>
<source>Read Selected</source>
<translation></translation>
</message>
<message>
<location filename="../ui/mainwindow.ui" line="764"/>
<location filename="../ui/mainwindow.ui" line="898"/>
<location filename="../ui/mainwindow.ui" line="999"/>
<source>Write Selected</source>
<translation></translation>
</message>
<message>
<location filename="../ui/mainwindow.ui" line="1061"/>
<location filename="../ui/mainwindow.ui" line="1095"/>
<source>Sniff</source>
<translation></translation>
</message>
<message>
<location filename="../ui/mainwindow.ui" line="935"/>
<source>List Sniff Data</source>
<translation></translation>
</message>
<message>
<location filename="../ui/mainwindow.ui" line="987"/>
<location filename="../ui/mainwindow.ui" line="1173"/>
<source>RawCommand</source>
<translation></translation>
</message>
<message>
<location filename="../ui/mainwindow.ui" line="1034"/>
<location filename="../ui/mainwindow.cpp" line="143"/>
<location filename="../ui/mainwindow.ui" line="1220"/>
<location filename="../ui/mainwindow.cpp" line="149"/>
<source>History:</source>
<translation></translation>
</message>
<message>
<location filename="../ui/mainwindow.ui" line="1066"/>
<location filename="../ui/mainwindow.ui" line="1252"/>
<source>ClearHistory</source>
<translation></translation>
</message>
<message>
<location filename="../ui/mainwindow.ui" line="1085"/>
<location filename="../ui/mainwindow.ui" line="1271"/>
<source>Send</source>
<translation></translation>
</message>
<message>
<location filename="../ui/mainwindow.ui" line="1092"/>
<location filename="../ui/mainwindow.ui" line="1278"/>
<source>ClearOutput</source>
<translation></translation>
</message>
<message>
<location filename="../ui/mainwindow.cpp" line="77"/>
<location filename="../ui/mainwindow.cpp" line="179"/>
<location filename="../ui/mainwindow.cpp" line="229"/>
<location filename="../ui/mainwindow.cpp" line="246"/>
<location filename="../ui/mainwindow.cpp" line="259"/>
<location filename="../ui/mainwindow.cpp" line="278"/>
<location filename="../ui/mainwindow.cpp" line="291"/>
<location filename="../ui/mainwindow.cpp" line="314"/>
<location filename="../ui/mainwindow.cpp" line="327"/>
<location filename="../ui/mainwindow.cpp" line="518"/>
<location filename="../ui/mainwindow.cpp" line="537"/>
<location filename="../ui/mainwindow.cpp" line="81"/>
<location filename="../ui/mainwindow.cpp" line="188"/>
<location filename="../ui/mainwindow.cpp" line="414"/>
<location filename="../ui/mainwindow.cpp" line="434"/>
<location filename="../ui/mainwindow.cpp" line="447"/>
<location filename="../ui/mainwindow.cpp" line="466"/>
<location filename="../ui/mainwindow.cpp" line="479"/>
<location filename="../ui/mainwindow.cpp" line="502"/>
<location filename="../ui/mainwindow.cpp" line="515"/>
<location filename="../ui/mainwindow.cpp" line="709"/>
<location filename="../ui/mainwindow.cpp" line="728"/>
<source>Info</source>
<translation></translation>
</message>
<message>
<location filename="../ui/mainwindow.cpp" line="77"/>
<location filename="../ui/mainwindow.cpp" line="81"/>
<source>Plz choose a port first</source>
<translation></translation>
</message>
<message>
<location filename="../ui/mainwindow.cpp" line="91"/>
<location filename="../ui/mainwindow.cpp" line="96"/>
<source>Connected</source>
<translation></translation>
</message>
<message>
<location filename="../ui/mainwindow.cpp" line="95"/>
<location filename="../ui/mainwindow.cpp" line="105"/>
<location filename="../ui/mainwindow.cpp" line="592"/>
<location filename="../ui/mainwindow.cpp" line="101"/>
<location filename="../ui/mainwindow.cpp" line="111"/>
<location filename="../ui/mainwindow.cpp" line="804"/>
<source>Not Connected</source>
<translation></translation>
</message>
<message>
<source>When Changeing card type, the data and keys in this app will be cleard.
Continue?</source>
<translation type="vanished">data和key会被清空\n要继续吗</translation>
</message>
<message>
<source>Plz choose the data file:</source>
<translation type="vanished">data文件</translation>
</message>
<message>
<location filename="../ui/mainwindow.cpp" line="272"/>
<location filename="../ui/mainwindow.cpp" line="460"/>
<source>Binary Data Files(*.bin *.dump);;Text Data Files(*.txt *.eml);;All Files(*.*)</source>
<translation>Data文件(*.bin *.dump);;Data文件(*.txt *.eml);;(*.*)</translation>
</message>
<message>
<location filename="../ui/mainwindow.cpp" line="278"/>
<location filename="../ui/mainwindow.cpp" line="291"/>
<location filename="../ui/mainwindow.cpp" line="518"/>
<location filename="../ui/mainwindow.cpp" line="466"/>
<location filename="../ui/mainwindow.cpp" line="479"/>
<location filename="../ui/mainwindow.cpp" line="709"/>
<source>Failed to open</source>
<translation></translation>
</message>
<message>
<source>Plz choose the key file:</source>
<translation type="vanished">key文件</translation>
</message>
<message>
<source>Binary Key Files(*.bin *.dump);;All Files(*.*)</source>
<translation type="vanished">Key文件(*.bin *.dump);;(*.*)</translation>
</message>
<message>
<source>Save data to</source>
<translation type="vanished"></translation>
</message>
<message>
<location filename="../ui/mainwindow.cpp" line="179"/>
<source>When Changeing card type, the data and keys in this app will be cleard.</source>
<translation>Data和Key会被清空</translation>
</message>
<message>
<location filename="../ui/mainwindow.cpp" line="179"/>
<location filename="../ui/mainwindow.cpp" line="188"/>
<source>Continue?</source>
<translation></translation>
</message>
<message>
<location filename="../ui/mainwindow.cpp" line="208"/>
<location filename="../ui/mainwindow.cpp" line="10"/>
<source>Check Update</source>
<translation></translation>
</message>
<message>
<location filename="../ui/mainwindow.cpp" line="188"/>
<source>Some of the data and key will be cleared.</source>
<translation></translation>
</message>
<message>
<location filename="../ui/mainwindow.cpp" line="301"/>
<source>Plz select the font of data widget and key widget</source>
<translation>Data窗口和Key窗口的字体</translation>
</message>
<message>
<location filename="../ui/mainwindow.cpp" line="229"/>
<location filename="../ui/mainwindow.cpp" line="414"/>
<source>Data must consists of 32 Hex symbols(Whitespace is allowed)</source>
<translation>Data必须由32个十六进制字符组成</translation>
</message>
<message>
<location filename="../ui/mainwindow.cpp" line="246"/>
<location filename="../ui/mainwindow.cpp" line="259"/>
<location filename="../ui/mainwindow.cpp" line="434"/>
<location filename="../ui/mainwindow.cpp" line="447"/>
<source>Key must consists of 12 Hex symbols(Whitespace is allowed)</source>
<translation>Key必须由12个十六进制字符组成</translation>
</message>
<message>
<location filename="../ui/mainwindow.cpp" line="271"/>
<location filename="../ui/mainwindow.cpp" line="459"/>
<source>Plz select the data file:</source>
<translation>data文件</translation>
</message>
<message>
<location filename="../ui/mainwindow.cpp" line="284"/>
<location filename="../ui/mainwindow.cpp" line="472"/>
<source>Plz select the key file:</source>
<translation>key文件</translation>
</message>
<message>
<location filename="../ui/mainwindow.cpp" line="285"/>
<location filename="../ui/mainwindow.cpp" line="473"/>
<source>Binary Key Files(*.bin *.dump);;Binary Data Files(*.bin *.dump);;All Files(*.*)</source>
<translation>Key文件(*.bin *.dump)Data文件(*.bin *.dump);;(*.*)</translation>
</message>
<message>
<location filename="../ui/mainwindow.cpp" line="307"/>
<location filename="../ui/mainwindow.cpp" line="495"/>
<source>Plz select the location to save data file:</source>
<translation></translation>
</message>
<message>
<location filename="../ui/mainwindow.cpp" line="308"/>
<location filename="../ui/mainwindow.cpp" line="496"/>
<source>Binary Data Files(*.bin *.dump);;Text Data Files(*.txt *.eml)</source>
<translation>Data文件(*.bin *.dump);;Data文件(*.txt *.eml)</translation>
</message>
<message>
<location filename="../ui/mainwindow.cpp" line="314"/>
<location filename="../ui/mainwindow.cpp" line="327"/>
<location filename="../ui/mainwindow.cpp" line="537"/>
<location filename="../ui/mainwindow.cpp" line="502"/>
<location filename="../ui/mainwindow.cpp" line="515"/>
<location filename="../ui/mainwindow.cpp" line="728"/>
<source>Failed to save to</source>
<translation></translation>
</message>
<message>
<location filename="../ui/mainwindow.cpp" line="320"/>
<location filename="../ui/mainwindow.cpp" line="508"/>
<source>Plz select the location to save key file:</source>
<translation>key文件保存的位置</translation>
</message>
<message>
<location filename="../ui/mainwindow.cpp" line="321"/>
<location filename="../ui/mainwindow.cpp" line="509"/>
<source>Binary Key Files(*.bin *.dump)</source>
<translation>Key文件(*.bin *.dump)</translation>
</message>
<message>
<location filename="../ui/mainwindow.cpp" line="446"/>
<location filename="../ui/mainwindow.cpp" line="636"/>
<source> Normally, the Block 0 of a typical Mifare card, which contains the UID, is locked during the manufacture. Users cannot write anything to Block 0 or set a new UID to a normal Mifare card.</source>
<translation> Mifare卡的Block0无法写入UID也不能更改</translation>
</message>
<message>
<location filename="../ui/mainwindow.cpp" line="447"/>
<location filename="../ui/mainwindow.cpp" line="637"/>
<source> Chinese Magic Cards(aka UID Cards) are some special cards whose Block 0 are writeable. And you can change UID by writing to it.</source>
<translation> UID卡Chinese Magic CardBlock0可写UID可变</translation>
</message>
<message>
<location filename="../ui/mainwindow.cpp" line="449"/>
<location filename="../ui/mainwindow.cpp" line="639"/>
<source>There are two versions of Chinese Magic Cards, the Gen1 and the Gen2.</source>
<translation>UID卡分为Chinese Magic Card Gen1和Gen2</translation>
</message>
<message>
<location filename="../ui/mainwindow.cpp" line="450"/>
<location filename="../ui/mainwindow.cpp" line="640"/>
<source> Gen1:</source>
<translation></translation>
</message>
<message>
<location filename="../ui/mainwindow.cpp" line="450"/>
<location filename="../ui/mainwindow.cpp" line="640"/>
<source> also called UID card in China. It responses to some backdoor commands so you can access any blocks without password. The Proxmark3 has a bunch of related commands(csetblk, cgetblk, ...) to deal with this type of card, and my GUI also support these commands.</source>
<translation> UID卡PM3和此GUI中有特殊命令处理这类卡片</translation>
</message>
<message>
<location filename="../ui/mainwindow.cpp" line="451"/>
<location filename="../ui/mainwindow.cpp" line="641"/>
<source> Gen2:</source>
<translation></translation>
</message>
<message>
<location filename="../ui/mainwindow.cpp" line="451"/>
<location filename="../ui/mainwindow.cpp" line="641"/>
<source> doesn&apos;t response to the backdoor commands, which means that a reader cannot detect whether it is a Chinese Magic Card or not by sending backdoor commands.</source>
<translation> CUID/FUID/UFUID这类对后门指令不响应的卡</translation>
</message>
<message>
<location filename="../ui/mainwindow.cpp" line="453"/>
<location filename="../ui/mainwindow.cpp" line="643"/>
<source>There are some types of Chinese Magic Card Gen2.</source>
<translation>Gen2卡的详细介绍</translation>
</message>
<message>
<location filename="../ui/mainwindow.cpp" line="454"/>
<location filename="../ui/mainwindow.cpp" line="644"/>
<source> CUID Card:</source>
<translation> CUID卡</translation>
</message>
<message>
<location filename="../ui/mainwindow.cpp" line="454"/>
<location filename="../ui/mainwindow.cpp" line="644"/>
<source> the Block 0 is writeable, you can write to this block repeatedly by normal wrbl command.</source>
<translation> Block0</translation>
</message>
<message>
<location filename="../ui/mainwindow.cpp" line="455"/>
<location filename="../ui/mainwindow.cpp" line="645"/>
<source> (hf mf wrbl 0 A FFFFFFFFFFFF &lt;the data you want to write&gt;)</source>
<translation> (hf mf wrbl 0 A FFFFFFFFFFFF &lt;&gt;)</translation>
</message>
<message>
<location filename="../ui/mainwindow.cpp" line="456"/>
<location filename="../ui/mainwindow.cpp" line="646"/>
<source> FUID Card:</source>
<translation> FUID卡</translation>
</message>
<message>
<location filename="../ui/mainwindow.cpp" line="456"/>
<location filename="../ui/mainwindow.cpp" line="646"/>
<source> you can only write to Block 0 once. After that, it seems like a typical Mifare card(Block 0 cannot be written to).</source>
<translation> Block0只能写入一次</translation>
</message>
<message>
<location filename="../ui/mainwindow.cpp" line="457"/>
<location filename="../ui/mainwindow.cpp" line="647"/>
<source> (some readers might try changing the Block 0, which could detect the CUID Card. In that case, you should use FUID card.)</source>
<translation> (穿CUID卡的读卡器)</translation>
</message>
<message>
<location filename="../ui/mainwindow.cpp" line="458"/>
<location filename="../ui/mainwindow.cpp" line="648"/>
<source> UFUID Card:</source>
<translation> UFUID卡</translation>
</message>
<message>
<location filename="../ui/mainwindow.cpp" line="458"/>
<location filename="../ui/mainwindow.cpp" line="648"/>
<source> It behaves like a CUID card(or UID card? I&apos;m not sure) before you send some special command to lock it. Once it is locked, you cannot change its Block 0(just like a typical Mifare card).</source>
<translation> UID/CUID卡一样可以反复读写Block0FUID卡一样了</translation>
</message>
<message>
<location filename="../ui/mainwindow.cpp" line="460"/>
<location filename="../ui/mainwindow.cpp" line="650"/>
<source> Seemingly, these Chinese Magic Cards are more easily to be compromised by Nested Attack(it takes little time to get an unknown key).</source>
<translation> UID卡都似乎更容易被Nested攻击破解</translation>
</message>
<message>
<location filename="../ui/mainwindow.cpp" line="505"/>
<location filename="../ui/mainwindow.cpp" line="696"/>
<source>Plz select the trace file:</source>
<translation>trace文件</translation>
</message>
<message>
<location filename="../ui/mainwindow.cpp" line="506"/>
<location filename="../ui/mainwindow.cpp" line="697"/>
<source>Trace Files(*.trc);;All Files(*.*)</source>
<translation>Trace文件(*.trc);;(*.*)</translation>
</message>
<message>
<location filename="../ui/mainwindow.cpp" line="528"/>
<location filename="../ui/mainwindow.cpp" line="719"/>
<source>Plz select the location to save trace file:</source>
<translation>trace文件保存的位置</translation>
</message>
<message>
<location filename="../ui/mainwindow.cpp" line="529"/>
<location filename="../ui/mainwindow.cpp" line="720"/>
<source>Trace Files(*.trc)</source>
<translation>Trace文件(*.trc)</translation>
</message>
<message>
<location filename="../ui/mainwindow.cpp" line="593"/>
<location filename="../ui/mainwindow.cpp" line="710"/>
<location filename="../ui/mainwindow.cpp" line="805"/>
<location filename="../ui/mainwindow.cpp" line="960"/>
<source>Idle</source>
<translation></translation>
</message>
<message>
<location filename="../ui/mainwindow.cpp" line="600"/>
<location filename="../ui/mainwindow.cpp" line="609"/>
<location filename="../ui/mainwindow.cpp" line="812"/>
<location filename="../ui/mainwindow.cpp" line="821"/>
<source>Sec</source>
<translation></translation>
</message>
<message>
<location filename="../ui/mainwindow.cpp" line="601"/>
<location filename="../ui/mainwindow.cpp" line="813"/>
<source>Blk</source>
<translation></translation>
</message>
<message>
<location filename="../ui/mainwindow.cpp" line="610"/>
<location filename="../ui/mainwindow.cpp" line="822"/>
<source>KeyA</source>
<translation></translation>
</message>
<message>
<location filename="../ui/mainwindow.cpp" line="611"/>
<location filename="../ui/mainwindow.cpp" line="823"/>
<source>KeyB</source>
<translation></translation>
</message>
<message>
<location filename="../ui/mainwindow.cpp" line="647"/>
<location filename="../ui/mainwindow.cpp" line="897"/>
<source>HW Version:</source>
<translation></translation>
</message>
<message>
<location filename="../ui/mainwindow.cpp" line="649"/>
<location filename="../ui/mainwindow.cpp" line="899"/>
<source>PM3:</source>
<translation></translation>
</message>
<message>
<location filename="../ui/mainwindow.cpp" line="651"/>
<location filename="../ui/mainwindow.cpp" line="901"/>
<source>State:</source>
<translation></translation>
</message>
<message>
<location filename="../ui/mainwindow.cpp" line="706"/>
<location filename="../ui/mainwindow.cpp" line="956"/>
<source>Running</source>
<translation></translation>
</message>
@ -731,32 +849,31 @@ Continue?</source>
<context>
<name>Mifare</name>
<message>
<source>info</source>
<translation type="vanished"></translation>
</message>
<message>
<location filename="../module/mifare.cpp" line="310"/>
<location filename="../module/mifare.cpp" line="419"/>
<location filename="../module/mifare.cpp" line="592"/>
<source>Success!</source>
<translation></translation>
</message>
<message>
<location filename="../module/mifare.cpp" line="310"/>
<location filename="../module/mifare.cpp" line="314"/>
<location filename="../module/mifare.cpp" line="419"/>
<location filename="../module/mifare.cpp" line="423"/>
<location filename="../module/mifare.cpp" line="473"/>
<location filename="../module/mifare.cpp" line="219"/>
<location filename="../module/mifare.cpp" line="592"/>
<location filename="../module/mifare.cpp" line="596"/>
<location filename="../module/mifare.cpp" line="661"/>
<source>Info</source>
<translation></translation>
</message>
<message>
<location filename="../module/mifare.cpp" line="314"/>
<location filename="../module/mifare.cpp" line="423"/>
<location filename="../module/mifare.cpp" line="219"/>
<source>Plz provide at least one known key</source>
<translation></translation>
</message>
<message>
<location filename="../module/mifare.cpp" line="443"/>
<location filename="../module/mifare.cpp" line="596"/>
<source>Failed!</source>
<translation></translation>
</message>
<message>
<location filename="../module/mifare.cpp" line="473"/>
<location filename="../module/mifare.cpp" line="661"/>
<source>Failed to read card.</source>
<translation></translation>
</message>

View file

@ -11,7 +11,8 @@ int main(int argc, char *argv[])
QApplication a(argc, argv);
MainWindow w;
QSettings* settings = new QSettings("GUIsettings.ini", QSettings::IniFormat);
QVariant lang = settings->value("lang", "null");
settings->beginGroup("lang");
QVariant lang = settings->value("language", "null");
if(lang == "null")
{
#ifdef Q_OS_WIN
@ -44,12 +45,13 @@ int main(int argc, char *argv[])
if(translator->load(lang.toString()))
{
a.installTranslator(translator);
settings->setValue("lang", lang);
settings->setValue("language", lang);
}
else
{
QMessageBox::information(&w, "Error", "Can't load " + lang.toString() + " as translation file.");
}
settings->endGroup();
delete settings;
w.initUI();
w.show();

File diff suppressed because it is too large Load diff

View file

@ -9,7 +9,7 @@
#include <QObject>
#include <QString>
#include <QStringList>
#include <QRegExp>
#include <QRegularExpression>
#include <QMessageBox>
class Mifare : public QObject
{
@ -17,18 +17,11 @@ class Mifare : public QObject
public:
explicit Mifare(Ui::MainWindow *ui, Util *addr, QWidget *parent = nullptr);
QString info(bool isRequiringOutput = false);
void chk();
void nested();
void hardnested();
void sniff();
void list();
void read();
void readAll();
void write();
void writeAll();
void dump();
void restore();
enum KeyType
{
KEY_A = 'A',
KEY_B = 'B',
};
enum DataType
{
@ -39,79 +32,82 @@ public:
struct CardType
{
int type;
int sectors;
int blocks;
int blk[40];
int blks[40];
quint8 type;
quint8 sector_size;
quint16 block_size;
quint8 blk[40];
quint8 blks[40];
};
const CardType card_mini =
enum AccessType
{
0,
5,
20,
{4, 4, 4, 4, 4},
{0, 4, 8, 12, 16}
};
const CardType card_1k =
{
1,
16,
64,
{4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4},
{0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60}
};
const CardType card_2k =
{
2,
32,
128,
{4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4},
{0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60, 64, 68, 72, 76, 80, 84, 88, 92, 96, 100, 104, 108, 112, 116, 120, 124}
};
const CardType card_4k =
{
4,
40,
256,
{4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 16, 16, 16, 16, 16, 16, 16, 16},
{0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60, 64, 68, 72, 76, 80, 84, 88, 92, 96, 100, 104, 108, 112, 116, 120, 124, 128, 144, 160, 176, 192, 208, 224, 240}
ACC_NEVER = 0,
ACC_KEY_A = 1,
ACC_KEY_B = 2,
ACC_KEY_AB = 3,
};
void data_clearData();
void data_clearKey();
bool data_isKeyValid(const QString &key);
Mifare::DataType data_isDataValid(QString data);
enum TargetType
{
TARGET_MIFARE,
TARGET_UID,
TARGET_EMULATOR,
};
static const CardType card_mini;
static const CardType card_1k;
static const CardType card_2k;
static const CardType card_4k;
static const AccessType dataCondition[8][4];
static const AccessType trailerReadCondition[8][3];
static const AccessType trailerWriteCondition[8][3];
QString info(bool isRequiringOutput = false);
void chk();
void nested();
void hardnested();
void sniff();
void snoop();
void list();
void readOne(TargetType targetType = TARGET_MIFARE);
void readSelected(TargetType targetType = TARGET_MIFARE);
void writeOne(TargetType targetType = TARGET_MIFARE);
QList<int> writeSelected(TargetType targetType = TARGET_MIFARE);
void dump();
void restore();
void data_clearData(bool clearAll = true);
void data_clearKey(bool clearAll = true);
static bool data_isKeyValid(const QString& key);
static Mifare::DataType data_isDataValid(const QString& data);
void data_syncWithDataWidget(bool syncAll = true, int block = 0);
void data_syncWithKeyWidget(bool syncAll = true, int sector = 0, bool isKeyA = true);
void data_syncWithKeyWidget(bool syncAll = true, int sector = 0, KeyType keyType = KEY_A);
CardType cardType;
Mifare::CardType getCardType();
void setCardType(int type);
void writeAllC();
void writeC();
void readAllC();
void readC();
void wipeC();
void setParameterC();
bool data_loadDataFile(const QString &filename);
bool data_loadKeyFile(const QString &filename);
bool data_loadDataFile(const QString& filename);
bool data_loadKeyFile(const QString& filename);
bool data_saveDataFile(const QString& filename, bool isBin);
bool data_saveKeyFile(const QString &filename, bool isBin);
bool data_saveKeyFile(const QString& filename, bool isBin);
void data_key2Data();
void data_data2Key();
void data_setData(int block, const QString &data);
void data_setKey(int sector, bool isKeyA, const QString &key);
void data_setData(int block, const QString& data);
void data_setKey(int sector, KeyType keyType, const QString& key);
void lockC();
void writeAllE();
void readAllE();
void wipeE();
void simulate();
void loadSniff(const QString& file);
void saveSniff(const QString& file);
void data_fillKeys();
static QList<quint8> data_getACBits(const QString &text);
static int data_b2s(int block);
public slots:
signals:
@ -123,11 +119,14 @@ private:
QStringList* keyAList;
QStringList* keyBList;
QStringList* dataList;
QRegExp* dataPattern;
QRegExp* chkKeyPattern;
QRegExp* nestedKeyPattern;
QRegExp* UIDPattern;
QString bin2text(const QByteArray &buff, int start, int length);
QRegularExpression* dataPattern;
QRegularExpression* keyPattern_res;
QRegularExpression* keyPattern;
QString bin2text(const QByteArray& buff, int start, int length);
QString _readblk(int blockId, KeyType keyType, const QString &key, TargetType targetType = TARGET_MIFARE, int waitTime = 300);
QStringList _readsec(int sectorId, KeyType keyType, const QString &key, TargetType targetType = TARGET_MIFARE, int waitTime = 300);
bool _writeblk(int blockId, KeyType keyType, const QString &key, const QString &data, TargetType targetType = TARGET_MIFARE, int waitTime = 300);
};
#endif // MIFARE_H

View file

@ -6,19 +6,23 @@ MainWindow::MainWindow(QWidget *parent):
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
// ui->MF_simGroupBox->setVisible(false); // developing...
// ui->MF_sniffGroupBox->setVisible(false); // developing...
myInfo = new QAction("wh201906", this);
checkUpdate = new QAction(tr("Check Update"), this);
connect(myInfo, &QAction::triggered, [ = ]()
{
QDesktopServices::openUrl(QUrl("https://github.com/wh201906"));
});
connect(checkUpdate, &QAction::triggered, [ = ]()
{
QDesktopServices::openUrl(QUrl("https://github.com/wh201906/Proxmark3GUI/releases"));
});
this->addAction(myInfo);
this->addAction(checkUpdate);
settings = new QSettings("GUIsettings.ini", QSettings::IniFormat);
pm3Thread = new QThread(this);
pm3 = new PM3Process(pm3Thread);
// pm3->moveToThread(pm3Thread);
// pm3->init();
pm3Thread->start();
pm3state = false;
@ -77,6 +81,7 @@ void MainWindow::on_PM3_connectButton_clicked()
QMessageBox::information(NULL, tr("Info"), tr("Plz choose a port first"), QMessageBox::Ok);
else
{
saveClientPath(ui->PM3_pathEdit->text());
emit connectPM3(ui->PM3_pathEdit->text(), port);
}
}
@ -92,6 +97,7 @@ void MainWindow::onPM3StateChanged(bool st, QString info)
}
else
{
setStatusBar(PM3VersionBar, "");
setStatusBar(connectStatusBar, tr("Not Connected"));
}
}
@ -176,12 +182,22 @@ void MainWindow::MF_onTypeChanged(int id, bool st)
qDebug() << id << typeBtnGroup->checkedId();
if(!st)
{
int result = QMessageBox::question(this, tr("Info"), tr("When Changeing card type, the data and keys in this app will be cleard.") + "\n" + tr("Continue?"), QMessageBox::Yes | QMessageBox::No);
int result;
if(id > typeBtnGroup->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);
}
else
{
result = QMessageBox::Yes;
}
if(result == QMessageBox::Yes)
{
qDebug() << "Yes";
mifare->setCardType(typeBtnGroup->checkedId());
MF_widgetReset();
mifare->data_syncWithDataWidget();
mifare->data_syncWithKeyWidget();
}
else
{
@ -192,16 +208,93 @@ void MainWindow::MF_onTypeChanged(int id, bool st)
typeBtnGroup->blockSignals(false);
}
void MainWindow::on_MF_data2KeyBotton_clicked()
void MainWindow::on_MF_selectAllBox_stateChanged(int arg1)
{
ui->MF_dataWidget->blockSignals(true);
ui->MF_selectAllBox->blockSignals(true);
ui->MF_selectTrailerBox->blockSignals(true);
if(arg1 == Qt::PartiallyChecked)
{
ui->MF_selectAllBox->setTristate(false);
ui->MF_selectAllBox->setCheckState(Qt::Checked);
}
for(int i = 0; i < mifare->cardType.block_size; i++)
{
ui->MF_dataWidget->item(i, 1)->setCheckState(ui->MF_selectAllBox->checkState());
}
for(int i = 0; i < mifare->cardType.sector_size; i++)
{
ui->MF_dataWidget->item(mifare->cardType.blks[i], 0)->setCheckState(ui->MF_selectAllBox->checkState());
}
ui->MF_selectTrailerBox->setCheckState(ui->MF_selectAllBox->checkState());
ui->MF_dataWidget->blockSignals(false);
ui->MF_selectAllBox->blockSignals(false);
ui->MF_selectTrailerBox->blockSignals(false);
}
void MainWindow::on_MF_selectTrailerBox_stateChanged(int arg1)
{
int selectedSubBlocks = 0;
ui->MF_dataWidget->blockSignals(true);
ui->MF_selectAllBox->blockSignals(true);
ui->MF_selectTrailerBox->blockSignals(true);
if(arg1 == Qt::PartiallyChecked)
{
ui->MF_selectTrailerBox->setTristate(false);
ui->MF_selectTrailerBox->setCheckState(Qt::Checked);
}
for(int i = 0; i < mifare->cardType.sector_size; i++)
{
ui->MF_dataWidget->item(mifare->cardType.blks[i] + mifare->cardType.blk[i] - 1, 1)->setCheckState(ui->MF_selectTrailerBox->checkState());
selectedSubBlocks = 0;
for(int j = 0; j < mifare->cardType.blk[i]; j++)
{
if(ui->MF_dataWidget->item(j + mifare->cardType.blks[i], 1)->checkState() == Qt::Checked)
selectedSubBlocks++;
}
if(selectedSubBlocks == 0)
{
ui->MF_dataWidget->item(mifare->cardType.blks[i], 0)->setCheckState(Qt::Unchecked);
}
else if(selectedSubBlocks == mifare->cardType.blk[i])
{
ui->MF_dataWidget->item(mifare->cardType.blks[i], 0)->setCheckState(Qt::Checked);
}
else
{
ui->MF_dataWidget->item(mifare->cardType.blks[i], 0)->setCheckState(Qt::PartiallyChecked);
}
}
ui->MF_dataWidget->blockSignals(false);
ui->MF_selectAllBox->blockSignals(false);
ui->MF_selectTrailerBox->blockSignals(false);
}
void MainWindow::on_MF_data2KeyButton_clicked()
{
mifare->data_data2Key();
}
void MainWindow::on_MF_key2DataBotton_clicked()
void MainWindow::on_MF_key2DataButton_clicked()
{
mifare->data_key2Data();
}
void MainWindow::on_MF_fillKeysButton_clicked()
{
mifare->data_fillKeys();
}
void MainWindow::on_MF_trailerDecoderButton_clicked()
{
decDialog = new MF_trailerDecoderDialog(this);
decDialog->show();
}
void MainWindow::on_MF_fontButton_clicked()
{
bool isOK = false;
@ -216,8 +309,100 @@ void MainWindow::on_MF_fontButton_clicked()
void MainWindow::on_MF_dataWidget_itemChanged(QTableWidgetItem *item)
{
ui->MF_dataWidget->blockSignals(true);
ui->MF_selectAllBox->blockSignals(true);
ui->MF_selectTrailerBox->blockSignals(true);
if(item->column() == 0)
{
int selectedSectors = 0;
for(int i = 0; i < mifare->cardType.blk[Mifare::data_b2s(item->row())]; i++)
{
ui->MF_dataWidget->item(i + item->row(), 1)->setCheckState(item->checkState());
qDebug() << i << mifare->cardType.blk[item->row()] << i + item->row() << ui->MF_dataWidget->item(i + item->row(), 1)->text();
}
for(int i = 0; i < mifare->cardType.sector_size; i++)
{
if(ui->MF_dataWidget->item(mifare->cardType.blks[i], 0)->checkState() == Qt::Checked)
{
selectedSectors++;
}
}
if(selectedSectors == 0)
{
ui->MF_selectAllBox->setCheckState(Qt::Unchecked);
ui->MF_selectTrailerBox->setCheckState(Qt::Unchecked);
}
else if(selectedSectors == mifare->cardType.sector_size)
{
ui->MF_selectAllBox->setCheckState(Qt::Checked);
ui->MF_selectTrailerBox->setCheckState(Qt::Checked);
}
else
{
ui->MF_selectAllBox->setCheckState(Qt::PartiallyChecked);
ui->MF_selectTrailerBox->setCheckState(Qt::PartiallyChecked);
}
}
else if(item->column() == 1)
{
int selectedSubBlocks = 0;
int selectedBlocks = 0;
int selectedTrailers = 0;
if(item->column() == 2)
for(int i = 0; i < mifare->cardType.block_size; i++)
{
if(ui->MF_dataWidget->item(i, 1)->checkState() == Qt::Checked)
selectedBlocks++;
}
for(int i = 0; i < mifare->cardType.blk[Mifare::data_b2s(item->row())]; i++)
{
if(ui->MF_dataWidget->item(i + mifare->cardType.blks[Mifare::data_b2s(item->row())], 1)->checkState() == Qt::Checked)
selectedSubBlocks++;
}
for(int i = 0; i < mifare->cardType.sector_size; i++)
{
int targetBlock = mifare->cardType.blks[i] + mifare->cardType.blk[i] - 1;
if(ui->MF_dataWidget->item(targetBlock, 1)->checkState() == Qt::Checked)
selectedTrailers++;
}
if(selectedBlocks == 0)
{
ui->MF_selectAllBox->setCheckState(Qt::Unchecked);
}
else if(selectedBlocks == mifare->cardType.block_size)
{
ui->MF_selectAllBox->setCheckState(Qt::Checked);
}
else
{
ui->MF_selectAllBox->setCheckState(Qt::PartiallyChecked);
}
if(selectedSubBlocks == 0)
{
ui->MF_dataWidget->item(mifare->cardType.blks[Mifare::data_b2s(item->row())], 0)->setCheckState(Qt::Unchecked);
}
else if(selectedSubBlocks == mifare->cardType.blk[Mifare::data_b2s(item->row())])
{
ui->MF_dataWidget->item(mifare->cardType.blks[Mifare::data_b2s(item->row())], 0)->setCheckState(Qt::Checked);
}
else
{
ui->MF_dataWidget->item(mifare->cardType.blks[Mifare::data_b2s(item->row())], 0)->setCheckState(Qt::PartiallyChecked);
}
if(selectedTrailers == 0)
{
ui->MF_selectTrailerBox->setCheckState(Qt::Unchecked);
}
else if(selectedTrailers == mifare->cardType.sector_size)
{
ui->MF_selectTrailerBox->setCheckState(Qt::Checked);
}
else
{
ui->MF_selectTrailerBox->setCheckState(Qt::PartiallyChecked);
}
}
else if(item->column() == 2)
{
QString data = item->text().replace(" ", "").toUpper();
if(data == "" || mifare->data_isDataValid(data) == Mifare::DATA_NOSPACE)
@ -230,6 +415,9 @@ void MainWindow::on_MF_dataWidget_itemChanged(QTableWidgetItem *item)
}
mifare->data_syncWithDataWidget(false, item->row());
}
ui->MF_dataWidget->blockSignals(false);
ui->MF_selectAllBox->blockSignals(false);
ui->MF_selectTrailerBox->blockSignals(false);
}
void MainWindow::on_MF_keyWidget_itemChanged(QTableWidgetItem *item)
@ -239,26 +427,26 @@ void MainWindow::on_MF_keyWidget_itemChanged(QTableWidgetItem *item)
QString key = item->text().replace(" ", "").toUpper();
if(key == "" || mifare->data_isKeyValid(key))
{
mifare->data_setKey(item->row(), true, key);
mifare->data_setKey(item->row(), Mifare::KEY_A, key);
}
else
{
QMessageBox::information(this, tr("Info"), tr("Key must consists of 12 Hex symbols(Whitespace is allowed)"));
}
mifare->data_syncWithKeyWidget(false, item->row(), true);
mifare->data_syncWithKeyWidget(false, item->row(), Mifare::KEY_A);
}
else if(item->column() == 2)
{
QString key = item->text().replace(" ", "");
QString key = item->text().replace(" ", "").toUpper();
if(key == "" || mifare->data_isKeyValid(key))
{
mifare->data_setKey(item->row(), false, key);
mifare->data_setKey(item->row(), Mifare::KEY_B, key);
}
else
{
QMessageBox::information(this, tr("Info"), tr("Key must consists of 12 Hex symbols(Whitespace is allowed)"));
}
mifare->data_syncWithKeyWidget(false, item->row(), false);
mifare->data_syncWithKeyWidget(false, item->row(), Mifare::KEY_B);
}
}
@ -369,31 +557,32 @@ void MainWindow::on_MF_Attack_hardnestedButton_clicked()
mifare->hardnested();
}
void MainWindow::on_MF_RW_readAllButton_clicked()
void MainWindow::on_MF_RW_readSelectedButton_clicked()
{
setState(false);
mifare->readAll();
mifare->readSelected(Mifare::TARGET_MIFARE);
setState(true);
}
void MainWindow::on_MF_RW_readBlockButton_clicked()
{
setState(false);
mifare->read();
mifare->readOne(Mifare::TARGET_MIFARE);
setState(true);
}
void MainWindow::on_MF_RW_writeBlockButton_clicked()
{
setState(false);
mifare->write();
mifare->writeOne();
setState(true);
}
void MainWindow::on_MF_RW_writeAllButton_clicked()
void MainWindow::on_MF_RW_writeSelectedButton_clicked()
{
QList<int> failedBlocks;
setState(false);
mifare->writeAll();
failedBlocks = mifare->writeSelected(Mifare::TARGET_MIFARE);
setState(true);
}
@ -407,31 +596,32 @@ void MainWindow::on_MF_RW_restoreButton_clicked()
mifare->restore();
}
void MainWindow::on_MF_UID_readAllButton_clicked()
void MainWindow::on_MF_UID_readSelectedButton_clicked()
{
setState(false);
mifare->readAllC();
mifare->readSelected(Mifare::TARGET_UID);
setState(true);
}
void MainWindow::on_MF_UID_readBlockButton_clicked()
{
setState(false);
mifare->readC();
mifare->readOne(Mifare::TARGET_UID);
setState(true);
}
void MainWindow::on_MF_UID_writeAllButton_clicked()
void MainWindow::on_MF_UID_writeSelectedButton_clicked()
{
QList<int> failedBlocks;
setState(false);
mifare->writeAllC();
failedBlocks = mifare->writeSelected(Mifare::TARGET_UID);
setState(true);
}
void MainWindow::on_MF_UID_writeBlockButton_clicked()
{
setState(false);
mifare->writeC();
mifare->writeOne(Mifare::TARGET_UID);
setState(true);
}
@ -473,17 +663,18 @@ void MainWindow::on_MF_UID_lockButton_clicked()
mifare->lockC();
}
void MainWindow::on_MF_Sim_loadDataButton_clicked()
void MainWindow::on_MF_Sim_readSelectedButton_clicked()
{
setState(false);
mifare->writeAllE();
mifare->readSelected(Mifare::TARGET_EMULATOR);
setState(true);
}
void MainWindow::on_MF_Sim_writeAllButton_clicked()
void MainWindow::on_MF_Sim_writeSelectedButton_clicked()
{
QList<int> failedBlocks;
setState(false);
mifare->readAllE();
failedBlocks = mifare->writeSelected(Mifare::TARGET_EMULATOR);
setState(true);
}
@ -548,6 +739,13 @@ void MainWindow::on_MF_Sniff_sniffButton_clicked()
setState(true);
}
void MainWindow::on_MF_Sniff_snoopButton_clicked()
{
setState(false);
mifare->snoop();
setState(true);
}
void MainWindow::on_MF_Sniff_listButton_clicked()
{
mifare->list();
@ -555,16 +753,22 @@ void MainWindow::on_MF_Sniff_listButton_clicked()
void MainWindow::MF_widgetReset()
{
int secs = mifare->cardType.sectors;
int blks = mifare->cardType.blocks;
int secs = mifare->cardType.sector_size;
int blks = mifare->cardType.block_size;
ui->MF_RW_blockBox->clear();
ui->MF_keyWidget->setRowCount(secs);
ui->MF_dataWidget->setRowCount(blks);
ui->MF_dataWidget->blockSignals(true);
ui->MF_keyWidget->blockSignals(true);
ui->MF_selectAllBox->blockSignals(true);
ui->MF_selectTrailerBox->blockSignals(true);
for(int i = 0; i < blks; i++)
{
setTableItem(ui->MF_dataWidget, i, 0, "");
setTableItem(ui->MF_dataWidget, i, 1, QString::number(i));
ui->MF_dataWidget->item(i, 1)->setCheckState(Qt::Checked);
setTableItem(ui->MF_dataWidget, i, 2, "");
ui->MF_RW_blockBox->addItem(QString::number(i));
}
@ -575,7 +779,15 @@ void MainWindow::MF_widgetReset()
setTableItem(ui->MF_keyWidget, i, 1, "");
setTableItem(ui->MF_keyWidget, i, 2, "");
setTableItem(ui->MF_dataWidget, mifare->cardType.blks[i], 0, QString::number(i));
ui->MF_dataWidget->item(mifare->cardType.blks[i], 0)->setCheckState(Qt::Checked);
}
ui->MF_selectAllBox->setCheckState(Qt::Checked);
ui->MF_selectTrailerBox->setCheckState(Qt::Checked);
ui->MF_dataWidget->blockSignals(false);
ui->MF_keyWidget->blockSignals(false);
ui->MF_selectAllBox->blockSignals(false);
ui->MF_selectTrailerBox->blockSignals(false);
}
// ************************************************
@ -601,8 +813,8 @@ void MainWindow::uiInit()
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, 35);
ui->MF_dataWidget->setColumnWidth(1, 35);
ui->MF_dataWidget->setColumnWidth(0, 55);
ui->MF_dataWidget->setColumnWidth(1, 55);
ui->MF_dataWidget->setColumnWidth(2, 430);
ui->MF_keyWidget->setColumnCount(3);
@ -625,6 +837,35 @@ void MainWindow::uiInit()
ui->MF_keyWidget->installEventFilter(this);
ui->MF_dataWidget->installEventFilter(this);
settings->beginGroup("UI_grpbox_preference");
QStringList boxNames = settings->allKeys();
QGroupBox* boxptr;
foreach(QString name, boxNames)
{
boxptr = this->findChild<QGroupBox*>(name);
if(boxptr == nullptr)
continue;
if(settings->value(name, true).toBool())
{
boxptr->setMaximumHeight(16777215);
boxptr->setChecked(true);
}
else
{
boxptr->setMaximumHeight(20);
boxptr->setChecked(false);
}
}
settings->endGroup();
settings->beginGroup("Client_Path");
ui->PM3_pathEdit->setText(settings->value("path", "proxmark3").toString());
settings->endGroup();
ui->MF_RW_keyTypeBox->addItem("A", Mifare::KEY_A);
ui->MF_RW_keyTypeBox->addItem("B", Mifare::KEY_B);
on_Raw_CMDHistoryBox_stateChanged(Qt::Unchecked);
on_PM3_refreshPortButton_clicked();
}
@ -632,6 +873,7 @@ void MainWindow::uiInit()
void MainWindow::signalInit()
{
connect(pm3, &PM3Process::newOutput, util, &Util::processOutput);
connect(pm3, &PM3Process::changeClientType, util, &Util::setClientType);
connect(util, &Util::refreshOutput, this, &MainWindow::refreshOutput);
connect(this, &MainWindow::connectPM3, pm3, &PM3Process::connectPM3);
@ -639,6 +881,14 @@ void MainWindow::signalInit()
connect(this, &MainWindow::killPM3, pm3, &PM3Process::kill);
connect(util, &Util::write, pm3, &PM3Process::write);
connect(ui->MF_typeGroupBox, &QGroupBox::clicked, this, &MainWindow::on_GroupBox_clicked);
connect(ui->MF_fileGroupBox, &QGroupBox::clicked, this, &MainWindow::on_GroupBox_clicked);
connect(ui->MF_RWGroupBox, &QGroupBox::clicked, this, &MainWindow::on_GroupBox_clicked);
connect(ui->MF_normalGroupBox, &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_sniffGroupBox, &QGroupBox::clicked, this, &MainWindow::on_GroupBox_clicked);
}
void MainWindow::setStatusBar(QLabel* target, const QString & text)
@ -718,8 +968,28 @@ void MainWindow::setState(bool st)
ui->Raw_sendCMDButton->setEnabled(st);
}
void MainWindow::on_GroupBox_clicked(bool checked)
{
QGroupBox* box = dynamic_cast<QGroupBox*>(sender());
settings->beginGroup("UI_grpbox_preference");
if(checked)
{
box->setMaximumHeight(16777215);
settings->setValue(box->objectName(), true);
}
else
{
box->setMaximumHeight(20);
settings->setValue(box->objectName(), false);
}
settings->endGroup();
}
void MainWindow::saveClientPath(const QString& path)
{
settings->beginGroup("Client_Path");
settings->setValue("path", path);
settings->endGroup();
}
// ***********************************************

View file

@ -16,10 +16,14 @@
#include <QMimeData>
#include <QAction>
#include <QDesktopServices>
#include <QGroupBox>
#include <QSizePolicy>
#include <QSettings>
#include "common/pm3process.h"
#include "module/mifare.h"
#include "common/util.h"
#include "ui/mf_trailerdecoderdialog.h"
QT_BEGIN_NAMESPACE
namespace Ui
@ -73,7 +77,7 @@ private slots:
void on_MF_Sniff_listButton_clicked();
void on_MF_RW_readAllButton_clicked();
void on_MF_RW_readSelectedButton_clicked();
void on_MF_RW_readBlockButton_clicked();
@ -81,18 +85,18 @@ private slots:
void on_MF_Attack_infoButton_clicked();
void on_MF_RW_writeAllButton_clicked();
void on_MF_RW_writeSelectedButton_clicked();
void on_MF_RW_dumpButton_clicked();
void on_MF_RW_restoreButton_clicked();
void on_MF_UID_readAllButton_clicked();
void on_MF_UID_readSelectedButton_clicked();
void on_MF_UID_readBlockButton_clicked();
void on_MF_UID_writeAllButton_clicked();
void on_MF_UID_writeSelectedButton_clicked();
void on_MF_UID_writeBlockButton_clicked();
@ -100,9 +104,9 @@ private slots:
void on_MF_File_saveButton_clicked();
void on_MF_data2KeyBotton_clicked();
void on_MF_data2KeyButton_clicked();
void on_MF_key2DataBotton_clicked();
void on_MF_key2DataButton_clicked();
void on_MF_dataWidget_itemChanged(QTableWidgetItem *item);
@ -120,9 +124,9 @@ private slots:
void on_MF_UID_lockButton_clicked();
void on_MF_Sim_loadDataButton_clicked();
void on_MF_Sim_readSelectedButton_clicked();
void on_MF_Sim_writeAllButton_clicked();
void on_MF_Sim_writeSelectedButton_clicked();
void on_MF_Sim_clearButton_clicked();
@ -132,6 +136,18 @@ private slots:
void on_MF_Sniff_saveButton_clicked();
void on_GroupBox_clicked(bool checked);
void on_MF_selectAllBox_stateChanged(int arg1);
void on_MF_fillKeysButton_clicked();
void on_MF_Sniff_snoopButton_clicked();
void on_MF_trailerDecoderButton_clicked();
void on_MF_selectTrailerBox_stateChanged(int arg1);
private:
Ui::MainWindow* ui;
QButtonGroup* typeBtnGroup;
@ -139,6 +155,8 @@ private:
QLabel* programStatusBar;
QLabel* PM3VersionBar;
QAction* myInfo;
QAction* checkUpdate;
QSettings* settings;
void uiInit();
@ -149,11 +167,14 @@ private:
Mifare* mifare;
Util* util;
MF_trailerDecoderDialog* decDialog;
void signalInit();
void MF_widgetReset();
void setTableItem(QTableWidget *widget, int row, int column, const QString &text);
void setState(bool st);
void saveClientPath(const QString &path);
signals:
void connectPM3(const QString path, const QString port);
void killPM3();

View file

@ -6,13 +6,13 @@
<rect>
<x>0</x>
<y>0</y>
<width>870</width>
<width>970</width>
<height>770</height>
</rect>
</property>
<property name="minimumSize">
<size>
<width>870</width>
<width>970</width>
<height>770</height>
</size>
</property>
@ -58,11 +58,7 @@
</widget>
</item>
<item>
<widget class="QLineEdit" name="PM3_pathEdit">
<property name="text">
<string notr="true">../pm3/win64/proxmark3</string>
</property>
</widget>
<widget class="QLineEdit" name="PM3_pathEdit"/>
</item>
<item>
<widget class="QComboBox" name="PM3_portBox">
@ -76,6 +72,12 @@
</item>
<item>
<widget class="QPushButton" name="PM3_refreshPortButton">
<property name="minimumSize">
<size>
<width>40</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>Refresh</string>
</property>
@ -83,6 +85,12 @@
</item>
<item>
<widget class="QPushButton" name="PM3_connectButton">
<property name="minimumSize">
<size>
<width>40</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>Connect</string>
</property>
@ -90,6 +98,12 @@
</item>
<item>
<widget class="QPushButton" name="PM3_disconnectButton">
<property name="minimumSize">
<size>
<width>40</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>Disconnect</string>
</property>
@ -105,6 +119,9 @@
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="mifareTab">
<attribute name="title">
<string>Mifare</string>
@ -180,84 +197,97 @@
</spacer>
</item>
<item>
<widget class="QPushButton" name="MF_data2KeyBotton">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
<widget class="QCheckBox" name="MF_selectAllBox">
<property name="text">
<string>&gt;&gt;</string>
<string>Select All</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="MF_key2DataBotton">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
<widget class="QCheckBox" name="MF_selectTrailerBox">
<property name="text">
<string>Select Trailer</string>
</property>
<property name="minimumSize">
</widget>
</item>
<item>
<spacer name="verticalSpacer_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
<property name="maximumSize">
</spacer>
</item>
<item>
<widget class="QPushButton" name="MF_data2KeyButton">
<property name="minimumSize">
<size>
<width>20</width>
<height>20</height>
<width>40</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>&lt;&lt;</string>
<string>KeyBlocks-&gt;Key</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="MF_key2DataButton">
<property name="minimumSize">
<size>
<width>40</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>KeyBlocks&lt;-Key</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="MF_fillKeysButton">
<property name="minimumSize">
<size>
<width>40</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>Fill Keys</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="MF_trailerDecoderButton">
<property name="minimumSize">
<size>
<width>40</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>Trailer Decoder</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="MF_fontButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>20</horstretch>
<verstretch>20</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>20</width>
<height>20</height>
<width>40</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
<property name="font">
<font>
<family>Courier</family>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>F</string>
<string>Set Fonts</string>
</property>
</widget>
</item>
@ -317,7 +347,7 @@
<string>Card Type</string>
</property>
<property name="checkable">
<bool>false</bool>
<bool>true</bool>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_10">
<property name="topMargin">
@ -328,15 +358,27 @@
</property>
<item>
<widget class="QRadioButton" name="MF_Type_miniButton">
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>MINI</string>
<string extracomment="320">MINI</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="MF_Type_1kButton">
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>1K</string>
<string extracomment="1024">1K</string>
</property>
<property name="checked">
<bool>true</bool>
@ -345,15 +387,27 @@
</item>
<item>
<widget class="QRadioButton" name="MF_Type_2kButton">
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>2K</string>
<string extracomment="2048">2K</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="MF_Type_4kButton">
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>4K</string>
<string extracomment="4096">4K</string>
</property>
</widget>
</item>
@ -365,6 +419,9 @@
<property name="title">
<string>File</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_8">
<property name="topMargin">
<number>5</number>
@ -436,6 +493,9 @@
<property name="title">
<string>Attack</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_5">
<property name="topMargin">
<number>5</number>
@ -458,6 +518,12 @@
</item>
<item>
<widget class="QPushButton" name="MF_Attack_infoButton">
<property name="minimumSize">
<size>
<width>40</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>Card Info</string>
</property>
@ -480,7 +546,7 @@
<widget class="QPushButton" name="MF_Attack_nestedButton">
<property name="minimumSize">
<size>
<width>0</width>
<width>40</width>
<height>0</height>
</size>
</property>
@ -491,6 +557,12 @@
</item>
<item>
<widget class="QPushButton" name="MF_Attack_hardnestedButton">
<property name="minimumSize">
<size>
<width>40</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>Hardnested</string>
</property>
@ -519,6 +591,9 @@
<property name="title">
<string>Read/Write</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_12">
@ -586,7 +661,7 @@
<widget class="QComboBox" name="MF_RW_keyTypeBox">
<property name="minimumSize">
<size>
<width>35</width>
<width>45</width>
<height>0</height>
</size>
</property>
@ -596,16 +671,6 @@
<height>16777215</height>
</size>
</property>
<item>
<property name="text">
<string>A</string>
</property>
</item>
<item>
<property name="text">
<string>B</string>
</property>
</item>
</widget>
</item>
<item>
@ -635,6 +700,9 @@
<property name="title">
<string>Normal(Require Password)</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<property name="topMargin">
<number>5</number>
@ -647,29 +715,53 @@
</property>
<item row="2" column="0">
<widget class="QPushButton" name="MF_RW_readBlockButton">
<property name="minimumSize">
<size>
<width>40</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>Read Block</string>
<string>Read One</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QPushButton" name="MF_RW_writeBlockButton">
<property name="minimumSize">
<size>
<width>40</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>Write Block</string>
<string>Write One</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QPushButton" name="MF_RW_readAllButton">
<widget class="QPushButton" name="MF_RW_readSelectedButton">
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>Read All</string>
<string>Read Selected</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QPushButton" name="MF_RW_writeAllButton">
<widget class="QPushButton" name="MF_RW_writeSelectedButton">
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>Write All</string>
<string>Write Selected</string>
</property>
</widget>
</item>
@ -700,6 +792,12 @@
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>40</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>Restore</string>
</property>
@ -713,6 +811,9 @@
<property name="title">
<string>Chinese Magic Card(Without Password)</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<layout class="QGridLayout" name="gridLayout">
<property name="topMargin">
<number>5</number>
@ -722,6 +823,12 @@
</property>
<item row="0" column="2">
<widget class="QPushButton" name="MF_UID_lockButton">
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>Lock UFUID Card</string>
</property>
@ -729,6 +836,12 @@
</item>
<item row="1" column="2">
<widget class="QPushButton" name="MF_UID_aboutUIDButton">
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>About UID Card</string>
</property>
@ -736,29 +849,53 @@
</item>
<item row="2" column="0">
<widget class="QPushButton" name="MF_UID_readBlockButton">
<property name="minimumSize">
<size>
<width>40</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>Read Block</string>
<string>Read One</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QPushButton" name="MF_UID_writeBlockButton">
<property name="minimumSize">
<size>
<width>40</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>Write Block</string>
<string>Write One</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QPushButton" name="MF_UID_readAllButton">
<widget class="QPushButton" name="MF_UID_readSelectedButton">
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>Read All</string>
<string>Read Selected</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QPushButton" name="MF_UID_writeAllButton">
<widget class="QPushButton" name="MF_UID_writeSelectedButton">
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>Write All</string>
<string>Write Selected</string>
</property>
</widget>
</item>
@ -770,6 +907,12 @@
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>Set Parameter</string>
</property>
@ -818,6 +961,9 @@
<property name="title">
<string>Simulate</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_11">
<property name="topMargin">
<number>5</number>
@ -842,16 +988,28 @@
</spacer>
</item>
<item>
<widget class="QPushButton" name="MF_Sim_loadDataButton">
<widget class="QPushButton" name="MF_Sim_writeSelectedButton">
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>Load from data above</string>
<string>Write Selected</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="MF_Sim_writeAllButton">
<widget class="QPushButton" name="MF_Sim_readSelectedButton">
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>Read All</string>
<string>Read Selected</string>
</property>
</widget>
</item>
@ -870,6 +1028,12 @@
</item>
<item>
<widget class="QPushButton" name="MF_Sim_simButton">
<property name="minimumSize">
<size>
<width>40</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>Simulate</string>
</property>
@ -896,6 +1060,9 @@
<property name="title">
<string>Sniff</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<property name="topMargin">
<number>5</number>
@ -930,9 +1097,28 @@
</widget>
</item>
<item>
<widget class="QPushButton" name="MF_Sniff_listButton">
<widget class="QPushButton" name="MF_Sniff_snoopButton">
<property name="minimumSize">
<size>
<width>40</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>List Sniff Data</string>
<string>Snoop</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="MF_Sniff_listButton">
<property name="minimumSize">
<size>
<width>40</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>List Data</string>
</property>
</widget>
</item>

View file

@ -0,0 +1,154 @@
#include "mf_trailerdecoderdialog.h"
#include "ui_mf_trailerdecoderdialog.h"
MF_trailerDecoderDialog::MF_trailerDecoderDialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::MF_trailerDecoderDialog)
{
ui->setupUi(this);
QRegularExpression re("(([0-9a-fA-F]{2} ){0,4})|([0-9a-fA-F]{0,8})");
validator = new QRegularExpressionValidator(this);
validator->setRegularExpression(re);
ui->accessBitsEdit->setValidator(validator);
sizeGroup = new QButtonGroup(this);
sizeGroup->addButton(ui->size4Button, 4);
sizeGroup->addButton(ui->size16Button, 16);
connect(sizeGroup, QOverload<int, bool>::of(&QButtonGroup::buttonToggled), this, &MF_trailerDecoderDialog::on_blockSizeChanged);
connect(ui->C0Box, &QSpinBox::textChanged, this, &MF_trailerDecoderDialog::on_boxChanged);
connect(ui->C1Box, &QSpinBox::textChanged, this, &MF_trailerDecoderDialog::on_boxChanged);
connect(ui->C2Box, &QSpinBox::textChanged, this, &MF_trailerDecoderDialog::on_boxChanged);
connect(ui->C3Box, &QSpinBox::textChanged, this, &MF_trailerDecoderDialog::on_boxChanged);
ui->dataBlockWidget->setRowCount(3);
ui->dataBlockWidget->setColumnCount(4);
ui->trailerBlockWidget->setRowCount(2);
ui->trailerBlockWidget->setColumnCount(3);
}
MF_trailerDecoderDialog::~MF_trailerDecoderDialog()
{
delete ui;
}
void MF_trailerDecoderDialog::on_accessBitsEdit_textChanged(const QString &arg1)
{
ui->C0Box->blockSignals(true);
ui->C1Box->blockSignals(true);
ui->C2Box->blockSignals(true);
ui->C3Box->blockSignals(true);
QList<quint8> ACBits = Mifare::data_getACBits(arg1);
if(ACBits.size() == 0)
{
ui->isAccessBitsValidLabel->setStyleSheet("color:rgb(200, 0, 0)");
ui->isAccessBitsValidLabel->setText(tr("Invalid!\nIt could make the whole sector blocked irreversibly!"));
}
else
{
ui->C0Box->setValue(ACBits[0]);
ui->C1Box->setValue(ACBits[1]);
ui->C2Box->setValue(ACBits[2]);
ui->C3Box->setValue(ACBits[3]);
ui->isAccessBitsValidLabel->setStyleSheet("color:rgb(0, 200, 0)");
ui->isAccessBitsValidLabel->setText(tr("Valid"));
bool isKeyBReadable = ACBits[3] == 0 || ACBits[3] == 1 || ACBits[3] == 4;
for(int j = 0; j < 3; j++)
{
setTableItem(ui->trailerBlockWidget, 0, j, Mifare::trailerReadCondition[ACBits[3]][j]);
setTableItem(ui->trailerBlockWidget, 1, j, Mifare::trailerWriteCondition[ACBits[3]][j]);
}
for(int i = 0; i < 3; i++)
{
for(int j = 0; j < 4; j++)
{
Mifare::AccessType type = Mifare::dataCondition[ACBits[i]][j];
if(type == Mifare::ACC_KEY_B && isKeyBReadable)
{
type = Mifare::ACC_NEVER;
}
else if(type == Mifare::ACC_KEY_AB && isKeyBReadable)
{
type = Mifare::ACC_KEY_A;
}
setTableItem(ui->dataBlockWidget, i, j, type);
}
}
}
ui->C0Box->blockSignals(false);
ui->C1Box->blockSignals(false);
ui->C2Box->blockSignals(false);
ui->C3Box->blockSignals(false);
}
void MF_trailerDecoderDialog::on_blockSizeChanged(int id, bool st)
{
if(st)
{
if(id == 4)
{
ui->dataBlockWidget->verticalHeaderItem(0)->setText("Block0");
ui->dataBlockWidget->verticalHeaderItem(1)->setText("Block1");
ui->dataBlockWidget->verticalHeaderItem(2)->setText("Block2");
}
else if(id == 16)
{
ui->dataBlockWidget->verticalHeaderItem(0)->setText("Block0~4");
ui->dataBlockWidget->verticalHeaderItem(1)->setText("Block5~9");
ui->dataBlockWidget->verticalHeaderItem(2)->setText("Block10~14");
}
}
}
void MF_trailerDecoderDialog::setTableItem(QTableWidget* widget, int row, int column, Mifare::AccessType accessType)
{
if(widget->item(row, column) == nullptr)
widget->setItem(row, column, new QTableWidgetItem());
QString text;
if(accessType == Mifare::ACC_NEVER)
{
text = "X";
}
else if(accessType == Mifare::ACC_KEY_A)
{
text = "KeyA";
}
else if(accessType == Mifare::ACC_KEY_B)
{
text = "KeyB";
}
else if(accessType == Mifare::ACC_KEY_AB)
{
text = "KeyA+B";
}
widget->item(row, column)->setText(text);
}
void MF_trailerDecoderDialog::on_boxChanged(const QString &arg1)
{
quint8 ACBits[4];
ACBits[0] = ui->C0Box->value();
ACBits[1] = ui->C1Box->value();
ACBits[2] = ui->C2Box->value();
ACBits[3] = ui->C3Box->value();
quint8 halfBytes[6] = {0, 0, 0, 0, 0, 0};
for(int i = 0; i < 4; i++)
{
halfBytes[2] |= (((ACBits[i] >> 0) & 1) << i);
halfBytes[5] |= (((ACBits[i] >> 1) & 1) << i);
halfBytes[4] |= (((ACBits[i] >> 2) & 1) << i);
}
halfBytes[0] = (~halfBytes[5]) & 0xf;
halfBytes[1] = (~halfBytes[2]) & 0xf;
halfBytes[3] = (~halfBytes[4]) & 0xf;
QString result;
for(int i = 0; i < 3; i++)
{
result += QString::number(halfBytes[i * 2], 16);
result += QString::number(halfBytes[i * 2 + 1], 16);
result += " ";
}
result = result.toUpper();
ui->accessBitsEdit->setText(result);
}

View file

@ -0,0 +1,39 @@
#ifndef MF_TRAILERDECODERDIALOG_H
#define MF_TRAILERDECODERDIALOG_H
#include <QDialog>
#include <QValidator>
#include <QDebug>
#include <QButtonGroup>
#include <QTableWidget>
#include "../module/mifare.h"
namespace Ui
{
class MF_trailerDecoderDialog;
}
class MF_trailerDecoderDialog : public QDialog
{
Q_OBJECT
public:
explicit MF_trailerDecoderDialog(QWidget *parent = nullptr);
~MF_trailerDecoderDialog();
private slots:
void on_accessBitsEdit_textChanged(const QString &arg1);
void on_blockSizeChanged(int id, bool st);
void on_boxChanged(const QString &arg1);
private:
Ui::MF_trailerDecoderDialog *ui;
QRegularExpressionValidator* validator;
QButtonGroup* sizeGroup;
void setTableItem(QTableWidget *widget, int row, int column, Mifare::AccessType accessType);
};
#endif // MF_TRAILERDECODERDIALOG_H

View file

@ -0,0 +1,402 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MF_trailerDecoderDialog</class>
<widget class="QDialog" name="MF_trailerDecoderDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>534</width>
<height>507</height>
</rect>
</property>
<property name="windowTitle">
<string>Trailer Decoder</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_7">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QGroupBox" name="sizeGroupBox">
<property name="title">
<string>Blocks</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QRadioButton" name="size4Button">
<property name="text">
<string>4</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="size16Button">
<property name="text">
<string>16</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_5">
<item>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Trailer Data:
(like &quot;FF0780&quot; or &quot;FF 07 80&quot;)</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="accessBitsEdit"/>
</item>
<item>
<widget class="QLabel" name="isAccessBitsValidLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>40</height>
</size>
</property>
<property name="text">
<string/>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::MinimumExpanding</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_6">
<item>
<widget class="QLabel" name="label_4">
<property name="text">
<string>Or set bits manually</string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<layout class="QVBoxLayout" name="verticalLayout_2">
<property name="spacing">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="label_6">
<property name="text">
<string>Cx0</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="C0Box">
<property name="maximum">
<number>7</number>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_3">
<property name="spacing">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="label_7">
<property name="text">
<string>Cx1</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="C1Box">
<property name="maximum">
<number>7</number>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_4">
<property name="spacing">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="label_8">
<property name="text">
<string>Cx2</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="C2Box">
<property name="maximum">
<number>7</number>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_5">
<property name="spacing">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="label_9">
<property name="text">
<string>Cx3</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="C3Box">
<property name="maximum">
<number>7</number>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::MinimumExpanding</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</item>
<item>
<widget class="QLabel" name="label_3">
<property name="text">
<string>Data Block Permission:</string>
</property>
</widget>
</item>
<item>
<widget class="QTableWidget" name="dataBlockWidget">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>4</verstretch>
</sizepolicy>
</property>
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
<row>
<property name="text">
<string>Block0</string>
</property>
</row>
<row>
<property name="text">
<string>Block1</string>
</property>
</row>
<row>
<property name="text">
<string>Block2</string>
</property>
</row>
<column>
<property name="text">
<string>Read</string>
</property>
</column>
<column>
<property name="text">
<string>Write</string>
</property>
</column>
<column>
<property name="text">
<string>Increase</string>
</property>
</column>
<column>
<property name="text">
<string>Decrease/Transfer/Restore</string>
</property>
</column>
</widget>
</item>
<item>
<widget class="QLabel" name="label_5">
<property name="text">
<string>Trailer Block Permission:</string>
</property>
</widget>
</item>
<item>
<widget class="QTableWidget" name="trailerBlockWidget">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>3</verstretch>
</sizepolicy>
</property>
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
<row>
<property name="text">
<string>Read</string>
</property>
</row>
<row>
<property name="text">
<string>Write</string>
</property>
</row>
<column>
<property name="text">
<string>KeyA</string>
</property>
</column>
<column>
<property name="text">
<string>Access Bits</string>
</property>
</column>
<column>
<property name="text">
<string>KeyB</string>
</property>
</column>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<widget class="QLabel" name="label_2">
<property name="text">
<string>Reference:
MF1S70YYX_V1 Product data sheet
Rev. 3.2 — 23 November 2017</string>
</property>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QLabel" name="label_10">
<property name="text">
<string>Note:the Access Bits usually contains 4 bytes(8 hex symbols), but only the first 3 bytes matters. You can set the 4th byte randomly.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>MF_trailerDecoderDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>MF_trailerDecoderDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>