diff --git a/common/util.cpp b/common/util.cpp index 1da8256..e9bf045 100644 --- a/common/util.cpp +++ b/common/util.cpp @@ -22,13 +22,16 @@ void Util::processOutput(const QString& output) void Util::execCMD(const QString& cmd) { - qDebug() << cmd; + qDebug() << "executing: " << cmd; if(isRunning) emit write(cmd + "\r\n"); } QString Util::execCMDWithOutput(const QString& cmd, ReturnTrigger trigger) { + // if the trigger is empty, this function will wait trigger.waitTime then return all outputs during the wait time. + // otherwise, this function will return empty string if no trigger is detected, or return outputs if any trigger is detected. + // the waitTime will be refreshed if the client have new outputs bool isResultFound = false; QRegularExpression re; re.setPatternOptions(QRegularExpression::DotMatchesEverythingOption); @@ -42,27 +45,32 @@ QString Util::execCMDWithOutput(const QString& cmd, ReturnTrigger trigger) execCMD(cmd); while(QTime::currentTime() < targetTime) { + if(!isRunning) + break; QApplication::processEvents(); for(QString otpt : trigger.expectedOutputs) { re.setPattern(otpt); isResultFound = re.match(*requiredOutput).hasMatch(); - if(requiredOutput->contains(otpt)) + if(isResultFound) + { + qDebug() << "output Matched: " << *requiredOutput; break; + } } if(isResultFound) { delay(200); break; } - if(timeStamp > currTime) + if(timeStamp > currTime) //has new output { currTime = timeStamp; targetTime = timeStamp.addMSecs(trigger.waitTime); } } isRequiringOutput = false; - return *requiredOutput; + return (isResultFound || trigger.expectedOutputs.isEmpty() ? *requiredOutput : ""); } void Util::delay(unsigned int msec) diff --git a/common/util.h b/common/util.h index 04a4ec0..05d0467 100644 --- a/common/util.h +++ b/common/util.h @@ -50,6 +50,7 @@ public: QString execCMDWithOutput(const QString& cmd, ReturnTrigger trigger = 10000); void delay(unsigned int msec); ClientType getClientType(); + static const int rawTabIndex = 1; public slots: void processOutput(const QString& output); void setClientType(Util::ClientType clientType); diff --git a/lang/en_US.ts b/lang/en_US.ts index b881d0e..5a58b0b 100644 --- a/lang/en_US.ts +++ b/lang/en_US.ts @@ -310,534 +310,681 @@ It could make the whole sector blocked irreversibly! - + 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 - + 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 + + + + + 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. + + + + + 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" +or "-p <port> -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(*.*) - - - + + + Failed to open - + Continue? - + Check Update - + 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 @@ -845,31 +992,56 @@ It could make the whole sector blocked irreversibly! Mifare - + Success! - - - - + + + + + + + Info - + Plz provide at least one known key - - + + Failed! - + + The Access Bits is invalid! +It could make the whole sector blocked irreversibly! +Continue to write? + + + + + Successful! + + + + + Failed to write to these blocks: + + + + + Select them? + + + + Failed to read card. diff --git a/lang/languages.ini b/lang/languages.ini new file mode 100644 index 0000000..e69de29 diff --git a/lang/zh_CN.ts b/lang/zh_CN.ts index 0990cac..ac86f92 100644 --- a/lang/zh_CN.ts +++ b/lang/zh_CN.ts @@ -314,534 +314,690 @@ It could make the whole sector blocked irreversibly! 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 清空 - + 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 + 预加载环境变量 + + + + 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. + 注意: +如果变量名已经存在,则会将新变量值添加至现有变量值之前,启动客户端时会优先使用此处添加的变量值。 +此处添加的环境变量不会影响其它程序。 + + + + 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" +or "-p <port> -f" + 注意: +-f选项用于使客户端实时返回命令回显,必须添加 +部分情况下启动参数需设置为"-p /dev/<port> -f" +或"-p <port> -f" + + + 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? 确定? - + Check Update 检查更新 - + 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 正在运行 @@ -849,31 +1005,58 @@ It could make the whole sector blocked irreversibly! Mifare - + Success! 成功! - - - - + + + + + + + Info 信息 - + Plz provide at least one known key 请至少提供一个已知密码 - - + + Failed! 失败! - + + The Access Bits is invalid! +It could make the whole sector blocked irreversibly! +Continue to write? + 控制位无效! +使用该控制位可能导致目标扇区损坏且无法恢复! +确定要写入吗? + + + + Successful! + 成功! + + + + Failed to write to these blocks: + 写入以下块失败: + + + + Select them? + 选中这些块? + + + Failed to read card. 读卡失败。 diff --git a/module/mifare.cpp b/module/mifare.cpp index 4ac028b..bc6b10e 100644 --- a/module/mifare.cpp +++ b/module/mifare.cpp @@ -106,7 +106,7 @@ QString Mifare::info(bool isRequiringOutput) else { util->execCMD("hf 14a info"); - ui->funcTab->setCurrentIndex(1); + ui->funcTab->setCurrentIndex(Util::rawTabIndex); return ""; } } @@ -115,17 +115,16 @@ QString Mifare::info(bool isRequiringOutput) void Mifare::chk() { QRegularExpressionMatch reMatch; - QString result = util->execCMDWithOutput( - "hf mf chk *" - + QString::number(cardType.type) - + " ?", - Util::ReturnTrigger(1000 + cardType.sector_size * 200, {"No valid", "\\|---\\|----------------\\|----------------\\|"})); - qDebug() << result; - + QString result; int offset = 0; QString data; if(util->getClientType() == Util::CLIENTTYPE_OFFICIAL) { + result = util->execCMDWithOutput( + "hf mf chk *" + + QString::number(cardType.type) + + " ?", + Util::ReturnTrigger(1000 + cardType.sector_size * 200, {"No valid", "\\|---\\|----------------\\|----------------\\|"})); for(int i = 0; i < cardType.sector_size; i++) { reMatch = keyPattern->match(result, offset); @@ -148,6 +147,11 @@ void Mifare::chk() } else if(util->getClientType() == Util::CLIENTTYPE_ICEMAN) { + result = util->execCMDWithOutput( + "hf mf chk *" + + QString::number(cardType.type) + + " ?", + Util::ReturnTrigger(1000 + cardType.sector_size * 200, {"No valid", "\\|---\\|----------------\\|---\\|----------------\\|"})); for(int i = 0; i < cardType.sector_size; i++) { reMatch = keyPattern_res->match(result, offset); @@ -213,7 +217,8 @@ void Mifare::nested() result = util->execCMDWithOutput( "hf mf nested " + QString::number(cardType.type) - + knownKeyInfo, 10000); + + knownKeyInfo, + Util::ReturnTrigger(10000, {"key is wrong", "\\|000\\|"})); } else { @@ -249,7 +254,7 @@ void Mifare::hardnested() MF_Attack_hardnestedDialog dialog(cardType.block_size); connect(&dialog, &MF_Attack_hardnestedDialog::sendCMD, util, &Util::execCMD); if(dialog.exec() == QDialog::Accepted) - ui->funcTab->setCurrentIndex(1); + ui->funcTab->setCurrentIndex(Util::rawTabIndex); } void Mifare::darkside() @@ -257,12 +262,12 @@ void Mifare::darkside() if(util->getClientType() == Util::CLIENTTYPE_OFFICIAL) { util->execCMD("hf mf mifare"); - ui->funcTab->setCurrentIndex(1); + ui->funcTab->setCurrentIndex(Util::rawTabIndex); } else if(util->getClientType() == Util::CLIENTTYPE_ICEMAN) { util->execCMD("hf mf darkside"); - ui->funcTab->setCurrentIndex(1); + ui->funcTab->setCurrentIndex(Util::rawTabIndex); } } @@ -270,19 +275,19 @@ void Mifare::darkside() void Mifare::sniff() { util->execCMD("hf mf sniff"); - ui->funcTab->setCurrentIndex(1); + ui->funcTab->setCurrentIndex(Util::rawTabIndex); } void Mifare::snoop() { util->execCMD("hf 14a snoop"); - ui->funcTab->setCurrentIndex(1); + ui->funcTab->setCurrentIndex(Util::rawTabIndex); } void Mifare::list() { util->execCMD("hf list mf"); - ui->funcTab->setCurrentIndex(1); + ui->funcTab->setCurrentIndex(Util::rawTabIndex); } QString Mifare::_readblk(int blockId, KeyType keyType, const QString& key, TargetType targetType, int waitTime) @@ -709,13 +714,13 @@ void Mifare::writeSelected(TargetType targetType) void Mifare::dump() { util->execCMD("hf mf dump"); - ui->funcTab->setCurrentIndex(1); + ui->funcTab->setCurrentIndex(Util::rawTabIndex); } void Mifare::restore() { util->execCMD("hf mf restore"); - ui->funcTab->setCurrentIndex(1); + ui->funcTab->setCurrentIndex(Util::rawTabIndex); } void Mifare::wipeC() @@ -724,7 +729,7 @@ void Mifare::wipeC() "hf mf cwipe " + QString::number(cardType.type) + " f"); - ui->funcTab->setCurrentIndex(1); + ui->funcTab->setCurrentIndex(Util::rawTabIndex); } void Mifare::setParameterC() @@ -741,7 +746,7 @@ void Mifare::setParameterC() MF_UID_parameterDialog dialog(lis[0].toUpper(), lis[1].toUpper(), lis[2].mid(0, 2).toUpper()); connect(&dialog, &MF_UID_parameterDialog::sendCMD, util, &Util::execCMD); if(dialog.exec() == QDialog::Accepted) - ui->funcTab->setCurrentIndex(1); + ui->funcTab->setCurrentIndex(Util::rawTabIndex); } } @@ -765,19 +770,19 @@ void Mifare::simulate() MF_Sim_simDialog dialog(cardType.type); connect(&dialog, &MF_Sim_simDialog::sendCMD, util, &Util::execCMD); if(dialog.exec() == QDialog::Accepted) - ui->funcTab->setCurrentIndex(1); + ui->funcTab->setCurrentIndex(Util::rawTabIndex); } void Mifare::loadSniff(const QString& file) { util->execCMD("hf list mf -l " + file); - ui->funcTab->setCurrentIndex(1); + ui->funcTab->setCurrentIndex(Util::rawTabIndex); } void Mifare::saveSniff(const QString& file) { util->execCMD("hf list mf -s " + file); - ui->funcTab->setCurrentIndex(1); + ui->funcTab->setCurrentIndex(Util::rawTabIndex); } void Mifare::data_syncWithDataWidget(bool syncAll, int block) diff --git a/ui/mainwindow.cpp b/ui/mainwindow.cpp index ed0f0ca..c4d0f7e 100644 --- a/ui/mainwindow.cpp +++ b/ui/mainwindow.cpp @@ -92,6 +92,9 @@ void MainWindow::on_PM3_connectButton_clicked() saveClientPath(ui->PM3_pathEdit->text()); emit connectPM3(ui->PM3_pathEdit->text(), port); } + QProcess proc; + QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); + //env.insert(); } void MainWindow::onPM3StateChanged(bool st, const QString& info) @@ -112,11 +115,8 @@ void MainWindow::onPM3StateChanged(bool st, const QString& info) void MainWindow::on_PM3_disconnectButton_clicked() { - pm3state = false; - setState(false); emit killPM3(); emit setSerialListener("", false); - setStatusBar(connectStatusBar, tr("Not Connected")); } void MainWindow::refreshOutput(const QString& output) @@ -128,7 +128,19 @@ void MainWindow::refreshOutput(const QString& output) void MainWindow::on_stopButton_clicked() { - + if(!pm3state) + on_PM3_disconnectButton_clicked(); + else + { + on_PM3_disconnectButton_clicked(); + for(int i = 0; i < 10; i++) + { + util->delay(200); + if(!pm3state) + break; + } + on_PM3_connectButton_clicked(); + } } // ********************************************************* @@ -866,7 +878,6 @@ void MainWindow::uiInit() ui->MF_dataWidget->setHorizontalHeaderItem(0, new QTableWidgetItem(tr("Sec"))); ui->MF_dataWidget->setHorizontalHeaderItem(1, new QTableWidgetItem(tr("Blk"))); ui->MF_dataWidget->setHorizontalHeaderItem(2, new QTableWidgetItem(tr("Data"))); - ui->MF_dataWidget->verticalHeader()->setVisible(false); ui->MF_dataWidget->setColumnWidth(0, 55); ui->MF_dataWidget->setColumnWidth(1, 55); ui->MF_dataWidget->setColumnWidth(2, 450); @@ -875,7 +886,6 @@ void MainWindow::uiInit() ui->MF_keyWidget->setHorizontalHeaderItem(0, new QTableWidgetItem(tr("Sec"))); ui->MF_keyWidget->setHorizontalHeaderItem(1, new QTableWidgetItem(tr("KeyA"))); ui->MF_keyWidget->setHorizontalHeaderItem(2, new QTableWidgetItem(tr("KeyB"))); - ui->MF_keyWidget->verticalHeader()->setVisible(false); ui->MF_keyWidget->setColumnWidth(0, 35); ui->MF_keyWidget->setColumnWidth(1, 125); ui->MF_keyWidget->setColumnWidth(2, 125); @@ -917,11 +927,21 @@ void MainWindow::uiInit() ui->PM3_pathEdit->setText(settings->value("path", "proxmark3").toString()); settings->endGroup(); + settings->beginGroup("Client_Args"); + ui->Set_Client_startArgsEdit->setText(settings->value("args", " -f").toString()); + settings->endGroup(); + + settings->beginGroup("Client_forceButtonsEnabled"); + ui->Set_Client_forceEnabledBox->setChecked(settings->value("state", false).toBool()); + 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() @@ -1059,3 +1079,65 @@ void MainWindow::on_MF_Attack_darksideButton_clicked() mifare->darkside(); 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"); + settings->setValue("args", ui->Set_Client_startArgsEdit->text()); + settings->endGroup(); +} + +void MainWindow::on_Set_Client_forceEnabledBox_stateChanged(int arg1) +{ + settings->beginGroup("Client_forceButtonsEnabled"); + settings->setValue("state", arg1 == Qt::Checked); + settings->endGroup(); +} + + diff --git a/ui/mainwindow.h b/ui/mainwindow.h index 948e991..e0f9e9d 100644 --- a/ui/mainwindow.h +++ b/ui/mainwindow.h @@ -20,6 +20,7 @@ #include #include #include +#include #include "common/myeventfilter.h" #include "common/pm3process.h" @@ -90,7 +91,6 @@ private slots: void on_MF_RW_writeSelectedButton_clicked(); - void on_MF_RW_dumpButton_clicked(); void on_MF_RW_restoreButton_clicked(); @@ -156,6 +156,20 @@ private slots: 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(); + private: Ui::MainWindow* ui; QButtonGroup* typeBtnGroup; diff --git a/ui/mainwindow.ui b/ui/mainwindow.ui index 6801816..813c8c3 100644 --- a/ui/mainwindow.ui +++ b/ui/mainwindow.ui @@ -6,7 +6,7 @@ 0 0 - 970 + 1029 770 @@ -120,7 +120,7 @@ - 0 + 4 @@ -170,6 +170,12 @@ QAbstractItemView::SingleSelection + + true + + + false + 20 @@ -329,6 +335,9 @@ QAbstractItemView::SingleSelection + + false + 20 @@ -1515,6 +1524,259 @@ + + + Settings + + + + + + + + Client + + + + + + Preload environment variables + + + + + + + + + QAbstractItemView::SelectRows + + + true + + + false + + + + Key + + + + + 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. + + + true + + + + + + + Qt::Horizontal + + + + + + + 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" +or "-p <port> -f" + + + true + + + + + + + Qt::Horizontal + + + + + + + + + + 0 + 0 + + + + + 0 + 0 + + + + + + + + + + + + 0 + 0 + + + + Keep buttons enabled even the client is running or disconnected + + + true + + + + + + + + + GUI + + + + + + Language + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + +