From 6e5f654cc578d745adb737c81eaeaa619ea65534 Mon Sep 17 00:00:00 2001 From: wh201906 Date: Mon, 15 Feb 2021 18:38:34 +0800 Subject: [PATCH] Support running a external script before client start, to configure the environment variables Optimize stop(reconnect) logic Search valid ports automatically Update translations --- common/pm3process.cpp | 25 ++- common/pm3process.h | 7 + lang/en_US.ts | 371 +++++++++++++++++++--------------------- lang/languages.ini | 6 +- lang/zh_CN.ts | 386 ++++++++++++++++++++---------------------- ui/mainwindow.cpp | 177 +++++++++---------- ui/mainwindow.h | 30 ++-- ui/mainwindow.ui | 200 +++++++++------------- 8 files changed, 567 insertions(+), 635 deletions(-) diff --git a/common/pm3process.cpp b/common/pm3process.cpp index 2313ddf..269a4f0 100644 --- a/common/pm3process.cpp +++ b/common/pm3process.cpp @@ -17,14 +17,19 @@ PM3Process::PM3Process(QThread* thread, QObject* parent): QProcess(parent) void PM3Process::connectPM3(const QString& path, const QString& port, const QStringList args) { QString result; - Util::ClientType clientType = Util::CLIENTTYPE_OFFICIAL; + Util::ClientType clientType; setRequiringOutput(true); + // stash for reconnect + currPath = path; + currPort = port; + currArgs = args; + // using "-f" option to make the client output flushed after every print. start(path, args, QProcess::Unbuffered | QProcess::ReadWrite); if(waitForStarted(10000)) { - waitForReadyRead(1000); + waitForReadyRead(10000); setRequiringOutput(false); result = *requiredOutput; if(result.indexOf("[=]") != -1) @@ -36,6 +41,10 @@ void PM3Process::connectPM3(const QString& path, const QString& port, const QStr result = *requiredOutput; setRequiringOutput(false); } + else + { + clientType = Util::CLIENTTYPE_OFFICIAL; + } if(result.indexOf("os: ") != -1) // make sure the PM3 is connected { emit changeClientType(clientType); @@ -50,6 +59,11 @@ void PM3Process::connectPM3(const QString& path, const QString& port, const QStr } } +void PM3Process::reconnectPM3() +{ + connectPM3(currPath, currPort, currArgs); +} + void PM3Process::setRequiringOutput(bool st) { isRequiringOutput = st; @@ -110,3 +124,10 @@ void PM3Process::onReadyRead() } } + +void PM3Process::setProcEnv(const QStringList* env) +{ +// qDebug() << "passed Env List" << *env; + this->setEnvironment(*env); +// qDebug() << "final Env List" << processEnvironment().toStringList(); +} diff --git a/common/pm3process.h b/common/pm3process.h index d6c55a0..b2a6631 100644 --- a/common/pm3process.h +++ b/common/pm3process.h @@ -8,6 +8,7 @@ #include #include #include +#include #include "util.h" @@ -24,6 +25,8 @@ public slots: void connectPM3(const QString& path, const QString& port, const QStringList args); void setSerialListener(const QString& name, bool state); qint64 write(QString data); + void reconnectPM3(); + void setProcEnv(const QStringList* env); private slots: void onTimeout(); void onReadyRead(); @@ -33,6 +36,10 @@ private: void setRequiringOutput(bool st);// It only works in this class now QTimer* serialListener; QSerialPortInfo* portInfo; + QString currPath; + QString currPort; + QStringList currArgs; + signals: void PM3StatedChanged(bool st, const QString& info = ""); void newOutput(const QString& output); diff --git a/lang/en_US.ts b/lang/en_US.ts index 2d3f93a..a9aff47 100644 --- a/lang/en_US.ts +++ b/lang/en_US.ts @@ -285,419 +285,402 @@ It could make the whole sector blocked irreversibly! - - Path: - - - - - Refresh - - - - + Connect - + Disconnect - + Mifare - + Select Trailer - + Card Type - + MINI 320 - + 1K 1024 - + 2K 2048 - + 4K 4096 - + File - - + + Load - - - + + Save - - + + Data - + Key - + Attack - + Card Info - + Check Default - + Nested - + Hardnested - + Darkside - + Read/Write - + Block: - + Key: - + Key Type: - + Snoop - + List Data - + Data: - + Normal(Require Password) - + Dump - + Restore - + Chinese Magic Card(Without Password) - + Lock UFUID Card - - + + About UID Card - + Set Parameter - + Wipe - - + + Simulate - - - + + Clear - + + Client Path: + + + + + Port: + + + + + Refresh Ports + + + + Select All - + KeyBlocks->Key - + KeyBlocks<-Key - + Fill Keys - + Trailer Decoder - + Set Fonts - - + + Read One - - + + Write One - - - + + + Read Selected - - - + + + Write Selected - - + + Sniff - + LF/Data - + LF Config - + Frequency - + 125k - + 134k - + BitRate: - + Decimation: - + Averaging: - + Threshold: - + Skips: - + Get - + Set - + T55xx - + RawCommand - - + + History: - + ClearHistory - + Send - + ClearOutput - + Settings - + Client - - Preload environment variables - - - - - Variable + + Preload script path: - Value - - - - - Add - - - - - Delete - - - - Note: -If the variable name already exists, this app will add the new value to the head of the existing one, so these new values have higher priority when calling Proxmark3 client. -The environment variables added here won't affect other apps. +If the client requires some enviroment variables, you can make a script file(*.bat on Windows or *.sh on Linux) to configure them, +then put the path of the script there - + Start arguments - + <port> -f - + Note: -f is necessary because the GUI need to handle the output in time In some cases the arguments should be set to "-p /dev/<port> -f" @@ -705,75 +688,75 @@ or "-p <port> -f" - + Keep buttons enabled even the client is running or disconnected - + GUI - + Language: - + Choose Language - + (Restart this app to use new language) - - - - - - - - - - - + + + + + + + + + + + Info - + Plz choose a port first - + Connected - - + + Not Connected - + Binary Data Files(*.bin *.dump);;Text Data Files(*.txt *.eml);;All Files(*.*) - - - + + + Failed to open - + Continue? @@ -783,222 +766,222 @@ or "-p <port> -f" - + Some of the data and key will be cleared. - + Plz select the font of data widget and key widget - + Data must consists of 32 Hex symbols(Whitespace is allowed) - - + + Key must consists of 12 Hex symbols(Whitespace is allowed) - + Plz select the data file: - + Plz select the key file: - + Binary Key Files(*.bin *.dump);;Binary Data Files(*.bin *.dump);;All Files(*.*) - + Plz select the location to save data file: - + Binary Data Files(*.bin *.dump);;Text Data Files(*.txt *.eml) - - - + + + Failed to save to - + Plz select the location to save key file: - + Binary Key Files(*.bin *.dump) - + 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. - + Chinese Magic Cards(aka UID Cards) are some special cards whose Block 0 are writeable. And you can change UID by writing to it. - + There are two versions of Chinese Magic Cards, the Gen1 and the Gen2. - + Gen1: - + 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. - + Gen2: - + doesn'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. - + There are some types of Chinese Magic Card Gen2. - + CUID Card: - + the Block 0 is writeable, you can write to this block repeatedly by normal wrbl command. - + (hf mf wrbl 0 A FFFFFFFFFFFF <the data you want to write>) - + FUID Card: - + you can only write to Block 0 once. After that, it seems like a typical Mifare card(Block 0 cannot be written to). - + (some readers might try changing the Block 0, which could detect the CUID Card. In that case, you should use FUID card.) - + UFUID Card: - + It behaves like a CUID card(or UID card? I'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). - + Seemingly, these Chinese Magic Cards are more easily to be compromised by Nested Attack(it takes little time to get an unknown key). - + Plz select the trace file: - + Trace Files(*.trc);;All Files(*.*) - + Plz select the location to save trace file: - + Trace Files(*.trc) - - + + Idle - + Stop - - + + Sec - + Blk - + KeyA - + KeyB - + HW Version: - + PM3: - + State: - + Running diff --git a/lang/languages.ini b/lang/languages.ini index 439ccd6..d9a11e4 100644 --- a/lang/languages.ini +++ b/lang/languages.ini @@ -1,3 +1,3 @@ -[Language] -English=en_US -简体中文=zh_CN \ No newline at end of file +[Languages] +en_US=English +zh_CN=简体中文 \ No newline at end of file diff --git a/lang/zh_CN.ts b/lang/zh_CN.ts index a2abf8a..957f603 100644 --- a/lang/zh_CN.ts +++ b/lang/zh_CN.ts @@ -289,421 +289,403 @@ It could make the whole sector blocked irreversibly! - - Path: - 路径: - - - - Refresh - 刷新端口 - - - + Connect 连接 - + Disconnect 断开 - + Mifare Mifare(IC)卡 - + Select Trailer 选中密码块 - + Card Type 卡片类型 - + MINI 320 - + 1K 1024 - + 2K 2048 - + 4K 4096 - + File 文件 - - + + Load 加载 - - - + + Save 保存 - - + + Data 数据 - + Key 密钥 - + Attack 破解 - + Card Info 读卡信息 - + Check Default 验证默认密码 - + Nested Nested攻击 - + Hardnested Hardested攻击 - + Darkside Darkside攻击 - + Read/Write 读/写 - + Block: 块: - + Key: 密钥: - + Key Type: 密钥类型: - + Snoop 嗅探(Snoop) - + List Data 列出嗅探数据 - + Data: 数据: - + Normal(Require Password) 普通卡(需要密码) - + Dump Dump命令 - + Restore Restore命令 - + Chinese Magic Card(Without Password) UID卡(不需要密码) - + Lock UFUID Card 锁定UFUID卡 - - + + About UID Card 关于UID卡 - + Set Parameter 设置卡参数 - + Wipe 擦除 - - + + Simulate 模拟 - - - + + Clear 清空 - + + Client Path: + 客户端路径: + + + + Port: + 端口: + + + + Refresh Ports + 刷新端口 + + + Select All 全选 - + KeyBlocks->Key 密码区->密码 - + KeyBlocks<-Key 密码区<-密码 - + Fill Keys 填充密码 - + Trailer Decoder Trailer解码 - + Set Fonts 设置字体 - - + + Read One 读取单个区 - - + + Write One 写入单个区 - - - + + + Read Selected 读取选中块 - - - + + + Write Selected 写入选中块 - - + + Sniff 嗅探 - + LF/Data - + LF Config - + Frequency - + 125k - + 134k - + BitRate: - + Decimation: - + Averaging: - + Threshold: - + Skips: - + Get - + Set - + T55xx - + RawCommand 原始命令 - - + + History: 命令历史: - + ClearHistory 清空历史 - + Send 发送 - + ClearOutput 清空输出 - + Settings 设置 - + Client 客户端 - - Preload environment variables - 预加载环境变量 - - - - Variable - 变量 + + Preload script path: + 预加载脚本路径: - Value - - - - - Add - 添加 - - - - Delete - 删除 - - - Note: -If the variable name already exists, this app will add the new value to the head of the existing one, so these new values have higher priority when calling Proxmark3 client. -The environment variables added here won't affect other apps. +If the client requires some enviroment variables, you can make a script file(*.bat on Windows or *.sh on Linux) to configure them, +then put the path of the script there 注意: -如果变量名已经存在,则会将新变量值添加至现有变量值之前,启动客户端时会优先使用此处添加的变量值。 -此处添加的环境变量不会影响其它程序。 +如果客户端需要配置环境变量才能正常运行,可以将配置环境变量所需的脚本文件(Windows系统内为*.bat,linux系统内为*.sh)路径填入此处 - + Start arguments 启动参数 - + <port> -f - + Note: -f is necessary because the GUI need to handle the output in time In some cases the arguments should be set to "-p /dev/<port> -f" @@ -714,83 +696,75 @@ or "-p <port> -f" 或"-p <port> -f" - + Language: 语言: - + Choose Language 选择语言 - + (Restart this app to use new language) - (重启以使用新语言) - - - Note: -f is necessary because the GUI need to handle the output in time - 注意:-f选项用于使客户端实时返回命令回显,必须添加 + (重启此程序以使用新语言) - + Keep buttons enabled even the client is running or disconnected 保持所有按钮可点击,即使未连接客户端或有任务正在运行 - + GUI 图形化界面 - Language - 语言 - - - - - - - - - - - - - + + + + + + + + + + + Info 信息 - + Plz choose a port first 请先选择端口 - + Connected 已连接 - - + + Not Connected 未连接 - + Binary Data Files(*.bin *.dump);;Text Data Files(*.txt *.eml);;All Files(*.*) 二进制数据文件(*.bin *.dump);;文本数据文件(*.txt *.eml);;所有文件(*.*) - - - + + + Failed to open 无法打开 - + Continue? 确定? @@ -800,222 +774,222 @@ or "-p <port> -f" 检查更新 - + Some of the data and key will be cleared. 部分数据和密码将被清除 - + Plz select the font of data widget and key widget 请选择数据窗口和密钥窗口的字体 - + Data must consists of 32 Hex symbols(Whitespace is allowed) 数据必须由32个十六进制字符组成(中间可含有空格) - - + + Key must consists of 12 Hex symbols(Whitespace is allowed) 密钥必须由12个十六进制字符组成(中间可含有空格) - + Plz select the data file: 请选择数据文件: - + Plz select the key file: 请选择密钥文件: - + Binary Key Files(*.bin *.dump);;Binary Data Files(*.bin *.dump);;All Files(*.*) 二进制密钥文件(*.bin *.dump)二进制密钥文件(*.bin *.dump);所有文件(*.*) - + Plz select the location to save data file: 请选择数据文件保存的位置: - + Binary Data Files(*.bin *.dump);;Text Data Files(*.txt *.eml) 二进制数据文件(*.bin *.dump);文本数据文件(*.txt *.eml) - - - + + + Failed to save to 无法保存至 - + Plz select the location to save key file: 请选择密钥文件保存的位置: - + Binary Key Files(*.bin *.dump) 二进制密码文件(*.bin *.dump) - + 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. 普通Mifare卡的块0无法写入,卡号也不能更改 - + Chinese Magic Cards(aka UID Cards) are some special cards whose Block 0 are writeable. And you can change UID by writing to it. UID卡(在国外叫Chinese Magic Card)的块0可写,卡号可变。 - + There are two versions of Chinese Magic Cards, the Gen1 and the Gen2. 国外把UID卡分为Chinese Magic Card Gen1和Gen2 - + Gen1: - + 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. 指通常所说的UID卡,可以通过后门指令直接读写块而无需密码,在PM3和此GUI中有特殊命令处理这类卡片 - + Gen2: - + doesn'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. 这个叫法在国内比较罕见,在国外指CUID/FUID/UFUID这类对后门指令不响应的卡(防火墙卡) - + There are some types of Chinese Magic Card Gen2. 以下是Gen2卡的详细介绍 - + CUID Card: CUID卡: - + the Block 0 is writeable, you can write to this block repeatedly by normal wrbl command. 可通过普通的写块命令来写块0,可重复擦写 - + (hf mf wrbl 0 A FFFFFFFFFFFF <the data you want to write>) (hf mf wrbl 0 A FFFFFFFFFFFF <待写入数据>) - + FUID Card: FUID卡: - + you can only write to Block 0 once. After that, it seems like a typical Mifare card(Block 0 cannot be written to). 块0只能写入一次 - + (some readers might try changing the Block 0, which could detect the CUID Card. In that case, you should use FUID card.) (更高级的穿防火墙卡,可以过一些能识别出CUID卡的读卡器) - + UFUID Card: UFUID卡: - + It behaves like a CUID card(or UID card? I'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). 锁卡前和普通UID/CUID卡一样可以反复读写块0,用特殊命令锁卡后就和FUID卡一样了 - + Seemingly, these Chinese Magic Cards are more easily to be compromised by Nested Attack(it takes little time to get an unknown key). 所有UID卡都似乎更容易被Nested攻击破解 - + Plz select the trace file: 请选择trace文件: - + Trace Files(*.trc);;All Files(*.*) Trace文件(*.trc);;所有文件(*.*) - + Plz select the location to save trace file: 请选择trace文件保存的位置: - + Trace Files(*.trc) Trace文件(*.trc) - - + + Idle 空闲 - + Stop 停止 - - + + Sec 扇区 - + Blk - + KeyA 密钥A - + KeyB 密钥B - + HW Version: 固件版本: - + PM3: 连接状态: - + State: 运行状态: - + Running 正在运行 diff --git a/ui/mainwindow.cpp b/ui/mainwindow.cpp index 8b50189..297520e 100644 --- a/ui/mainwindow.cpp +++ b/ui/mainwindow.cpp @@ -38,6 +38,12 @@ MainWindow::MainWindow(QWidget *parent): // hide unused tabs ui->funcTab->removeTab(1); ui->funcTab->removeTab(1); + + portSearchTimer = new QTimer(this); + portSearchTimer->setInterval(2000); + connect(portSearchTimer, &QTimer::timeout, this, &MainWindow::on_portSearchTimer_timeout); + portSearchTimer->start(); + } MainWindow::~MainWindow() @@ -60,31 +66,27 @@ void MainWindow::initUI() // will be called by main.app // ******************** basic functions ******************** -void MainWindow::on_PM3_refreshPortButton_clicked() +void MainWindow::on_portSearchTimer_timeout() { - ui->PM3_portBox->clear(); - QSerialPort serial; - QStringList serialList; + QStringList newPortList; foreach(const QSerialPortInfo &info, QSerialPortInfo::availablePorts()) { - qDebug() << info.isBusy() << info.isNull() << info.portName() << info.description(); - serial.setPort(info); - - if(serial.open(QIODevice::ReadWrite)) - { - serialList << info.portName(); - serial.close(); - } +// qDebug() << info.isBusy() << info.isNull() << info.portName() << info.description(); + if(!info.isNull()) + newPortList << info.portName(); } - foreach(QString port, serialList) + if(newPortList != portList) // update PM3_portBox when available ports changed { - ui->PM3_portBox->addItem(port); + portList = newPortList; + ui->PM3_portBox->clear(); + ui->PM3_portBox->addItems(portList); } } void MainWindow::on_PM3_connectButton_clicked() { qDebug() << "Main:" << QThread::currentThread(); + QString port = ui->PM3_portBox->currentText(); if(port == "") QMessageBox::information(NULL, tr("Info"), tr("Plz choose a port first"), QMessageBox::Ok); @@ -92,11 +94,27 @@ void MainWindow::on_PM3_connectButton_clicked() { QStringList args = ui->Set_Client_startArgsEdit->text().replace("", port).split(' '); saveClientPath(ui->PM3_pathEdit->text()); + QProcess envSetProcess; + QFileInfo envScriptPath(ui->Set_Client_envScriptEdit->text()); + if(envScriptPath.exists()) + { + qDebug() << envScriptPath.absoluteFilePath(); +#ifdef Q_OS_WIN + // cmd /c "">>nul && set + envSetProcess.start("cmd /c \"" + envScriptPath.absoluteFilePath() + "\">>nul && set"); +#else + // sh -c '. "">>/dev/null && env' + envSetProcess.start("sh -c \' . \"" + envScriptPath.absoluteFilePath() + "\">>/dev/null && env"); +#endif + envSetProcess.waitForReadyRead(10000); + clientEnv = QString(envSetProcess.readAll()).split(QRegExp("[\r\n]"), QString::SkipEmptyParts); +// qDebug() << "Get Env List" << clientEnv; + } + else + clientEnv.clear(); + emit setProcEnv(&clientEnv); emit connectPM3(ui->PM3_pathEdit->text(), port, args); } - QProcess proc; - QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); - //env.insert(); } void MainWindow::onPM3StateChanged(bool st, const QString& info) @@ -105,11 +123,13 @@ void MainWindow::onPM3StateChanged(bool st, const QString& info) setState(st); if(st == true) { + portSearchTimer->stop(); setStatusBar(PM3VersionBar, info); setStatusBar(connectStatusBar, tr("Connected")); } else { + portSearchTimer->start(); setStatusBar(PM3VersionBar, ""); setStatusBar(connectStatusBar, tr("Not Connected")); } @@ -141,7 +161,7 @@ void MainWindow::on_stopButton_clicked() if(!pm3state) break; } - on_PM3_connectButton_clicked(); + emit reconnectPM3(); } } // ********************************************************* @@ -256,14 +276,14 @@ void MainWindow::on_MF_keyWidget_resized(QObject* obj_addr, QEvent& event) } } -void MainWindow::MF_onTypeChanged(int id, bool st) +void MainWindow::MF_onMFCardTypeChanged(int id, bool st) { - typeBtnGroup->blockSignals(true); - qDebug() << id << typeBtnGroup->checkedId(); + MFCardTypeBtnGroup->blockSignals(true); + qDebug() << id << MFCardTypeBtnGroup->checkedId(); if(!st) { int result; - if(id > typeBtnGroup->checkedId()) // id is specified in uiInit() with a proper order, so I can compare the size by id. + if(id > MFCardTypeBtnGroup->checkedId()) // id is specified in uiInit() with a proper order, so I can compare the size by id. { result = QMessageBox::question(this, tr("Info"), tr("Some of the data and key will be cleared.") + "\n" + tr("Continue?"), QMessageBox::Yes | QMessageBox::No); } @@ -274,7 +294,7 @@ void MainWindow::MF_onTypeChanged(int id, bool st) if(result == QMessageBox::Yes) { qDebug() << "Yes"; - mifare->setCardType(typeBtnGroup->checkedId()); + mifare->setCardType(MFCardTypeBtnGroup->checkedId()); MF_widgetReset(); mifare->data_syncWithDataWidget(); mifare->data_syncWithKeyWidget(); @@ -282,10 +302,10 @@ void MainWindow::MF_onTypeChanged(int id, bool st) else { qDebug() << "No"; - typeBtnGroup->button(id)->setChecked(true); + MFCardTypeBtnGroup->button(id)->setChecked(true); } } - typeBtnGroup->blockSignals(false); + MFCardTypeBtnGroup->blockSignals(false); } void MainWindow::on_MF_selectAllBox_stateChanged(int arg1) @@ -898,23 +918,20 @@ void MainWindow::uiInit() ui->MF_dataWidget->setHorizontalHeaderItem(2, new QTableWidgetItem(tr("Data"))); ui->MF_dataWidget->setColumnWidth(0, 55); ui->MF_dataWidget->setColumnWidth(1, 55); - ui->MF_dataWidget->setColumnWidth(2, 450); ui->MF_keyWidget->setColumnCount(3); ui->MF_keyWidget->setHorizontalHeaderItem(0, new QTableWidgetItem(tr("Sec"))); ui->MF_keyWidget->setHorizontalHeaderItem(1, new QTableWidgetItem(tr("KeyA"))); ui->MF_keyWidget->setHorizontalHeaderItem(2, new QTableWidgetItem(tr("KeyB"))); - ui->MF_keyWidget->setColumnWidth(0, 35); - ui->MF_keyWidget->setColumnWidth(1, 125); - ui->MF_keyWidget->setColumnWidth(2, 125); + ui->MF_keyWidget->setColumnWidth(0, 45); MF_widgetReset(); - typeBtnGroup = new QButtonGroup(this); - typeBtnGroup->addButton(ui->MF_Type_miniButton, 0); - typeBtnGroup->addButton(ui->MF_Type_1kButton, 1); - typeBtnGroup->addButton(ui->MF_Type_2kButton, 2); - typeBtnGroup->addButton(ui->MF_Type_4kButton, 4); - connect(typeBtnGroup, QOverload::of(&QButtonGroup::buttonToggled), this, &MainWindow::MF_onTypeChanged); + MFCardTypeBtnGroup = new QButtonGroup(this); + MFCardTypeBtnGroup->addButton(ui->MF_Type_miniButton, 0); + MFCardTypeBtnGroup->addButton(ui->MF_Type_1kButton, 1); + MFCardTypeBtnGroup->addButton(ui->MF_Type_2kButton, 2); + MFCardTypeBtnGroup->addButton(ui->MF_Type_4kButton, 4); + connect(MFCardTypeBtnGroup, QOverload::of(&QButtonGroup::buttonToggled), this, &MainWindow::MF_onMFCardTypeChanged); ui->MF_keyWidget->installEventFilter(this); ui->MF_dataWidget->installEventFilter(this); @@ -954,13 +971,14 @@ void MainWindow::uiInit() ui->Set_Client_forceEnabledBox->setChecked(keepButtonsEnabled); settings->endGroup(); + settings->beginGroup("Client_Env"); + ui->Set_Client_envScriptEdit->setText(settings->value("scriptPath").toString()); + settings->endGroup(); + ui->MF_RW_keyTypeBox->addItem("A", Mifare::KEY_A); ui->MF_RW_keyTypeBox->addItem("B", Mifare::KEY_B); on_Raw_CMDHistoryBox_stateChanged(Qt::Unchecked); - on_PM3_refreshPortButton_clicked(); - - loadClientPreloadEnv(); } void MainWindow::signalInit() @@ -970,9 +988,11 @@ void MainWindow::signalInit() connect(util, &Util::refreshOutput, this, &MainWindow::refreshOutput); connect(this, &MainWindow::connectPM3, pm3, &PM3Process::connectPM3); + connect(this, &MainWindow::reconnectPM3, pm3, &PM3Process::reconnectPM3); connect(pm3, &PM3Process::PM3StatedChanged, this, &MainWindow::onPM3StateChanged); connect(pm3, &PM3Process::PM3StatedChanged, util, &Util::setRunningState); connect(this, &MainWindow::killPM3, pm3, &PM3Process::kill); + connect(this, &MainWindow::setProcEnv, pm3, &PM3Process::setProcEnv); connect(util, &Util::write, pm3, &PM3Process::write); @@ -1055,13 +1075,18 @@ void MainWindow::setState(bool st) { setStatusBar(programStatusBar, tr("Idle")); } - ui->MF_attackGroupBox->setEnabled(st || keepButtonsEnabled); - ui->MF_normalGroupBox->setEnabled(st || keepButtonsEnabled); - ui->MF_UIDGroupBox->setEnabled(st || keepButtonsEnabled); - ui->MF_simGroupBox->setEnabled(st || keepButtonsEnabled); - ui->MF_sniffGroupBox->setEnabled(st || keepButtonsEnabled); - ui->Raw_CMDEdit->setEnabled(st || keepButtonsEnabled); - ui->Raw_sendCMDButton->setEnabled(st || keepButtonsEnabled); + setButtonsEnabled(st || keepButtonsEnabled); +} + +void MainWindow::setButtonsEnabled(bool st) +{ + ui->MF_attackGroupBox->setEnabled(st); + ui->MF_normalGroupBox->setEnabled(st); + ui->MF_UIDGroupBox->setEnabled(st); + ui->MF_simGroupBox->setEnabled(st); + ui->MF_sniffGroupBox->setEnabled(st); + ui->Raw_CMDEdit->setEnabled(st); + ui->Raw_sendCMDButton->setEnabled(st); } void MainWindow::on_GroupBox_clicked(bool checked) @@ -1099,52 +1124,6 @@ void MainWindow::on_MF_Attack_darksideButton_clicked() setState(true); } -void MainWindow::on_Set_Client_envDeleteButton_clicked() -{ - ui->Set_Client_envTable->removeRow(ui->Set_Client_envTable->currentRow()); -} - -void MainWindow::on_Set_Client_envAddButton_clicked() -{ - ui->Set_Client_envTable->insertRow(ui->Set_Client_envTable->rowCount()); -} - -void MainWindow::on_Set_Client_envClearButton_clicked() -{ - ui->Set_Client_envTable->clearContents(); - ui->Set_Client_envTable->setRowCount(0); -} - -void MainWindow::on_Set_Client_envSaveButton_clicked() -{ - settings->beginGroup("Client_Env"); - for(int i = 0; i < ui->Set_Client_envTable->rowCount(); i++) - { - QTableWidgetItem* key = ui->Set_Client_envTable->item(i, 0); - QTableWidgetItem* val = ui->Set_Client_envTable->item(i, 1); - if(key == nullptr || val == nullptr || key->text().isEmpty() || val->text().isEmpty()) - continue; - settings->setValue(key->text(), val->text()); - qDebug() << "Env saved: " << i << key->text() << val->text(); - } - settings->endGroup(); -} - -void MainWindow::loadClientPreloadEnv() -{ - ui->Set_Client_envTable->clearContents(); - settings->beginGroup("Client_Env"); - QStringList keyList = settings->allKeys(); - ui->Set_Client_envTable->setRowCount(keyList.size()); - for(int i = 0; i < keyList.size(); i++) - { - ui->Set_Client_envTable->setItem(i, 0, new QTableWidgetItem(keyList[i])); - ui->Set_Client_envTable->setItem(i, 1, new QTableWidgetItem(settings->value(keyList[i]).toString())); - } - settings->endGroup(); -} - - void MainWindow::on_Set_Client_startArgsEdit_editingFinished() { settings->beginGroup("Client_Args"); @@ -1158,11 +1137,23 @@ void MainWindow::on_Set_Client_forceEnabledBox_stateChanged(int arg1) keepButtonsEnabled = (arg1 == Qt::Checked); settings->setValue("state", keepButtonsEnabled); settings->endGroup(); + if(keepButtonsEnabled) + setButtonsEnabled(true); } - - void MainWindow::on_Set_GUI_setLanguageButton_clicked() { Util::chooseLanguage(settings, this); } + +void MainWindow::on_PM3_refreshPortButton_clicked() +{ + on_portSearchTimer_timeout(); +} + +void MainWindow::on_Set_Client_envScriptEdit_editingFinished() +{ + settings->beginGroup("Client_Env"); + settings->setValue("scriptPath", ui->Set_Client_envScriptEdit->text()); + settings->endGroup(); +} diff --git a/ui/mainwindow.h b/ui/mainwindow.h index ebd4791..862adf2 100644 --- a/ui/mainwindow.h +++ b/ui/mainwindow.h @@ -22,6 +22,7 @@ #include #include #include +#include #include "common/myeventfilter.h" #include "common/pm3process.h" @@ -51,7 +52,7 @@ public slots: void refreshCMD(const QString& cmd); void setStatusBar(QLabel* target, const QString& text); void onPM3StateChanged(bool st, const QString& info); - void MF_onTypeChanged(int id, bool st); + void MF_onMFCardTypeChanged(int id, bool st); void on_Raw_CMDEdit_keyPressed(QObject *obj_addr, QEvent &event); void on_MF_keyWidget_resized(QObject *obj_addr, QEvent &event); private slots: @@ -65,7 +66,8 @@ private slots: void on_Raw_clearOutputButton_clicked(); void sendMSG(); - void on_PM3_refreshPortButton_clicked(); + + void on_portSearchTimer_timeout(); void on_Raw_CMDHistoryBox_stateChanged(int arg1); @@ -154,29 +156,26 @@ private slots: void on_MF_selectTrailerBox_stateChanged(int arg1); void on_stopButton_clicked(); + void on_Raw_CMDEdit_textChanged(const QString &arg1); void on_MF_Attack_darksideButton_clicked(); - void on_Set_Client_envDeleteButton_clicked(); - - void on_Set_Client_envAddButton_clicked(); - - void on_Set_Client_envSaveButton_clicked(); - - void loadClientPreloadEnv(); - void on_Set_Client_startArgsEdit_editingFinished(); void on_Set_Client_forceEnabledBox_stateChanged(int arg1); - void on_Set_Client_envClearButton_clicked(); - void on_Set_GUI_setLanguageButton_clicked(); + void setButtonsEnabled(bool st); + + void on_PM3_refreshPortButton_clicked(); + + void on_Set_Client_envScriptEdit_editingFinished(); + private: Ui::MainWindow* ui; - QButtonGroup* typeBtnGroup; + QButtonGroup* MFCardTypeBtnGroup; QLabel* connectStatusBar; QLabel* programStatusBar; QLabel* PM3VersionBar; @@ -197,6 +196,9 @@ private: bool pm3state; bool keepButtonsEnabled; QThread* pm3Thread; + QTimer* portSearchTimer; + QStringList portList; + QStringList clientEnv; Mifare* mifare; Util* util; @@ -211,7 +213,9 @@ private: void saveClientPath(const QString& path); signals: void connectPM3(const QString& path, const QString& port, const QStringList args); + void reconnectPM3(); void killPM3(); void setSerialListener(const QString& name, bool state); + void setProcEnv(const QStringList *env); }; #endif // MAINWINDOW_H diff --git a/ui/mainwindow.ui b/ui/mainwindow.ui index 642ae2d..d1fa6d4 100644 --- a/ui/mainwindow.ui +++ b/ui/mainwindow.ui @@ -6,14 +6,14 @@ 0 0 - 1029 - 770 + 1050 + 700 - 970 - 770 + 800 + 600 @@ -53,13 +53,20 @@ - Path: + Client Path: + + + + Port: + + + @@ -68,6 +75,9 @@ 0 + + true + @@ -79,7 +89,7 @@ - Refresh + Refresh Ports @@ -1528,7 +1538,7 @@ Settings - + @@ -1540,88 +1550,23 @@ - Preload environment variables + Preload script path: - - - - - QAbstractItemView::SelectRows - - - true - - - false - - - - Variable - - - - - Value - - - - - - - - - - Add - - - - - - - Delete - - - - - - - Clear - - - - - - - Save - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - + + + + + Note: -If the variable name already exists, this app will add the new value to the head of the existing one, so these new values have higher priority when calling Proxmark3 client. -The environment variables added here won't affect other apps. +If the client requires some enviroment variables, you can make a script file(*.bat on Windows or *.sh on Linux) to configure them, +then put the path of the script there true @@ -1709,55 +1654,62 @@ or "-p <port> -f" - - - GUI - - - - - - - - Language: - - - - - - - Choose Language - - - - - - - (Restart this app to use new language) - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - + + + Qt::Horizontal + + + + + GUI + + + + + + + + Language: + + + + + + + Choose Language + + + + + + + (Restart this app to use new language) + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + +