diff --git a/module/mifare.cpp b/module/mifare.cpp index a9d9dcc..ad34915 100644 --- a/module/mifare.cpp +++ b/module/mifare.cpp @@ -269,7 +269,7 @@ void Mifare::list() ui->funcTab->setCurrentIndex(1); } -QString Mifare::_readblk(int blockId, KeyType keyType, const QString& key, TargetType targetType, int waitTime) +QString Mifare::_readblk(int blockId, KeyType keyType, const QString& key, TargetType targetType, int waitTime) { QString data; QString result; @@ -322,7 +322,7 @@ QString Mifare::_readblk(int blockId, KeyType keyType, const QString& key, Targ "hf mf cgetblk " + QString::number(blockId), waitTime); - if(result.indexOf("No chinese") == -1) + if(result.indexOf("Chinese magic") != -1) { data = dataPattern->match(result).captured().toUpper(); data.remove(" "); @@ -335,7 +335,7 @@ QString Mifare::_readblk(int blockId, KeyType keyType, const QString& key, Targ result = util->execCMDWithOutput( "hf mf eget " + QString::number(blockId), - waitTime); + 150); data = dataPattern->match(result).captured().toUpper(); data.remove(" "); } @@ -343,34 +343,45 @@ QString Mifare::_readblk(int blockId, KeyType keyType, const QString& key, Targ return data; } -QStringList Mifare::_readsec(int sectorId, KeyType keyType, const QString& key, int waitTime) +QStringList Mifare::_readsec(int sectorId, KeyType keyType, const QString& key, TargetType targetType, int waitTime) { QStringList data; QString result, tmp; QRegularExpressionMatch reMatch; - int offset = 0; + int offset = -1; for(int i = 0; i < cardType.blk[sectorId]; i++) { data.append(""); } - if(!data_isKeyValid(key)) - { - return data; - } if(util->getClientType() == Util::CLIENTTYPE_OFFICIAL || util->getClientType() == Util::CLIENTTYPE_ICEMAN) { // try to read all blocks together - result = util->execCMDWithOutput( - "hf mf rdsc " - + QString::number(sectorId) - + " " - + (char)keyType - + " " - + key, - waitTime); - offset = result.indexOf("isOk:01"); + if(targetType == TARGET_MIFARE) + { + if(!data_isKeyValid(key)) + { + return data; + } + result = util->execCMDWithOutput( + "hf mf rdsc " + + QString::number(sectorId) + + " " + + (char)keyType + + " " + + key, + waitTime); + offset = result.indexOf("isOk:01"); + } + else if(targetType == TARGET_UID) + { + result = util->execCMDWithOutput( + "hf mf cgetsc " + + QString::number(sectorId), + waitTime); + offset = result.indexOf("Chinese magic"); + } if(offset != -1) { for(int i = 0; i < cardType.blk[sectorId]; i++) @@ -388,17 +399,15 @@ QStringList Mifare::_readsec(int sectorId, KeyType keyType, const QString& key, } // if failed, try to read them seperately. // (when one of the block cannot be read, the rdsc will return nothing, so you need to read the rest of blocks manually) - else + else if(targetType != TARGET_UID) // if the targetType is Chinese Magic Card, then the result implies the backdoor command is invalid. { for(int i = 0; i < cardType.blk[sectorId]; i++) - { - data[i] = _readblk(cardType.blks[sectorId] + i, keyType, key, TARGET_MIFARE, waitTime); - } + data[i] = _readblk(cardType.blks[sectorId] + i, keyType, key, targetType, waitTime); } //process trailer(like _readblk()) QString trailer = data[cardType.blk[sectorId] - 1]; - if(trailer != "") + if(trailer != "" && targetType == TARGET_MIFARE) { if(keyType == KEY_A) // in this case, the Access Bits is always accessible { @@ -435,11 +444,17 @@ void Mifare::readOne(TargetType targetType) } } -void Mifare::readSelected(const QList& selectedBlocks) +void Mifare::readSelected(TargetType targetType) { QStringList data, dataA, dataB; QString trailerA, trailerB; QList selectedSectors; + QList selectedBlocks; + for(int i = 0; i < cardType.block_size; i++) + { + if(ui->MF_dataWidget->item(i, 1)->checkState() == Qt::Checked) + selectedBlocks.append(i); + } for(int i = 0; i < cardType.sector_size; i++) { @@ -452,64 +467,68 @@ void Mifare::readSelected(const QList& selectedBlocks) for(int i = 0; i < cardType.sector_size; i++) { - if(!selectedSectors[i]) - { - continue; - } - for(int j = 0; j < cardType.blk[i]; j++) { - // dataA is always filled with "" because of the _readsec() - data.append(""); - dataB.append(""); - } + if(!selectedSectors[i]) + { + continue; + } + for(int j = 0; j < cardType.blk[i]; j++) + { + // dataA is always filled with "" because of the _readsec() + data.append(""); + dataB.append(""); + } - dataA = _readsec(i, Mifare::KEY_A, keyAList->at(i)); - if(dataA.contains("") || dataA[cardType.blk[i] - 1].right(12) == "????????????") - dataB = _readsec(i, Mifare::KEY_B, keyBList->at(i)); + dataA = _readsec(i, Mifare::KEY_A, keyAList->at(i), targetType); - for(int j = 0; j < cardType.blk[i]; j++) - { - if(dataA[j] != "") - data[j] = dataA[j]; - else - data[j] = dataB[j]; - } + // in other situations, the key doesn't matters + if(targetType == TARGET_MIFARE && (dataA.contains("") || dataA[cardType.blk[i] - 1].right(12) == "????????????")) + dataB = _readsec(i, Mifare::KEY_B, keyBList->at(i), targetType); - // process trailer block seperately - trailerA = dataA[cardType.blk[i] - 1]; - trailerB = dataB[cardType.blk[i] - 1]; - if(trailerA != "" && trailerB != "") - { - QString ACbits = trailerA.mid(12, 8); - QString key_A = trailerA.left(12); - QString key_B = trailerA.at(31) != '?' ? trailerA.right(12) : trailerB.right(12); - data[cardType.blk[i] - 1] = key_A + ACbits + key_B; - } + for(int j = 0; j < cardType.blk[i]; j++) + { + if(dataA[j] != "") + data[j] = dataA[j]; + else + data[j] = dataB[j]; + } - for(int j = 0; j < cardType.blk[i]; j++) - { - if(selectedBlocks.contains(cardType.blks[i] + j)) + // process trailer block seperately + trailerA = dataA[cardType.blk[i] - 1]; + trailerB = dataB[cardType.blk[i] - 1]; + if(trailerA != "" && trailerB != "") { - dataList->replace(cardType.blks[i] + j, data[j]); - data_syncWithDataWidget(false, cardType.blks[i] + j); + QString ACbits = trailerA.mid(12, 8); + QString key_A = trailerA.left(12); + QString key_B = trailerA.at(31) != '?' ? trailerA.right(12) : trailerB.right(12); + data[cardType.blk[i] - 1] = key_A + ACbits + key_B; } - } - if(selectedBlocks.contains(cardType.blks[i] + cardType.blk[i] - 1)) - { - // data widget has been updated, so this is just a temporary varient. - if(data[cardType.blk[i] - 1] == "") - data[cardType.blk[i] - 1] = "????????????????????????????????"; - - // doesn't replace the existing key. - if(!data_isKeyValid(keyAList->at(i))) - keyAList->replace(i, data[cardType.blk[i] - 1].left(12)); - if(!data_isKeyValid(keyBList->at(i))) - keyBList->replace(i, data[cardType.blk[i] - 1].right(12)); - data_syncWithKeyWidget(false, i, KEY_A); - data_syncWithKeyWidget(false, i, KEY_B); - } + for(int j = 0; j < cardType.blk[i]; j++) + { + if(selectedBlocks.contains(cardType.blks[i] + j)) + { + dataList->replace(cardType.blks[i] + j, data[j]); + data_syncWithDataWidget(false, cardType.blks[i] + j); + } + } + + if(selectedBlocks.contains(cardType.blks[i] + cardType.blk[i] - 1)) + { + // data widget has been updated, so this is just a temporary varient. + if(data[cardType.blk[i] - 1] == "") + data[cardType.blk[i] - 1] = "????????????????????????????????"; + + // doesn't replace the existing key. + if(!data_isKeyValid(keyAList->at(i))) + keyAList->replace(i, data[cardType.blk[i] - 1].left(12)); + if(!data_isKeyValid(keyBList->at(i))) + keyBList->replace(i, data[cardType.blk[i] - 1].right(12)); + data_syncWithKeyWidget(false, i, KEY_A); + data_syncWithKeyWidget(false, i, KEY_B); + } + } } } @@ -548,16 +567,16 @@ bool Mifare::_writeblk(int blockId, KeyType keyType, const QString& key, const Q + " " + input, waitTime); - return (result.indexOf("No chinese") == -1); + return (result.indexOf("Chinese magic") != -1); } else if(targetType == TARGET_EMULATOR) { - result = util->execCMDWithOutput( - "hf mf eset " - + QString::number(blockId) - + " " - + input, - waitTime); + util->execCMD( + "hf mf eset " + + QString::number(blockId) + + " " + + input); + util->delay(5); return true; } } @@ -578,78 +597,40 @@ void Mifare::writeOne(TargetType targetType) } } -void Mifare::writeSelected(const QList& selectedBlocks) +QList Mifare::writeSelected(TargetType targetType) { - for(int item : selectedBlocks) + QList failedBlocks; + QList selectedBlocks; + for(int i = 0; i < cardType.block_size; i++) { - bool result = false; - result = _writeblk(item, KEY_A, keyAList->at(data_b2s(item)), dataList->at(item)); - if(!result) - { - result = _writeblk(item, KEY_B, keyBList->at(data_b2s(item)), dataList->at(item)); - } - if(!result) - { - result = _writeblk(item, KEY_A, "FFFFFFFFFFFF", dataList->at(item)); - } + if(ui->MF_dataWidget->item(i, 1)->checkState() == Qt::Checked) + selectedBlocks.append(i); } -} - -void Mifare::readAllC() -{ - QString result; - const int waitTime = 150; - - QString tmp; - int offset = 0; - for(int i = 0; i < cardType.sector_size; i++) + for(int item : selectedBlocks) { - result = util->execCMDWithOutput( - "hf mf cgetsc " - + QString::number(i), - waitTime); - qDebug() << result; - if(result.indexOf("No chinese") == -1) + bool result = false; + if(targetType == TARGET_MIFARE) { - offset = 0; - for(int j = 0; j < cardType.blk[i]; j++) + result = _writeblk(item, KEY_A, keyAList->at(data_b2s(item)), dataList->at(item), TARGET_MIFARE); + if(!result) { -// offset = dataPattern->indexIn(result, offset); -// offset = result.indexOf(*dataPattern, offset); - tmp = result.mid(offset, 47).toUpper(); - offset += 47; - qDebug() << tmp; - tmp.replace(" ", ""); - dataList->replace(cardType.blks[i] + j, tmp); - data_syncWithDataWidget(false, cardType.blks[i] + j); + result = _writeblk(item, KEY_B, keyBList->at(data_b2s(item)), dataList->at(item), TARGET_MIFARE); + } + if(!result) + { + result = _writeblk(item, KEY_A, "FFFFFFFFFFFF", dataList->at(item), TARGET_MIFARE); } - keyAList->replace(i, dataList->at(cardType.blks[i] + cardType.blk[i] - 1).left(12)); - keyBList->replace(i, dataList->at(cardType.blks[i] + cardType.blk[i] - 1).right(12)); - data_syncWithKeyWidget(false, i, KEY_A); - data_syncWithKeyWidget(false, i, KEY_B); } - } -} - -void Mifare::writeAllC() -{ - const int waitTime = 150; - QString result; - for(int i = 0; i < cardType.sector_size; i++) - { - for(int j = 0; j < cardType.blk[i]; j++) + else // key doesn't matter when writing to Chinese Magic Card and Emulator Memory { - result = ""; - if(data_isDataValid(dataList->at(cardType.blks[i] + j)) != DATA_NOSPACE || dataList->at(cardType.blks[i] + j).contains('?')) - continue; - result = util->execCMDWithOutput( - "hf mf csetblk " - + QString::number(cardType.blks[i] + j) - + " " - + dataList->at(cardType.blks[i] + j), - waitTime); + result = _writeblk(item, KEY_A, "FFFFFFFFFFFF", dataList->at(item), targetType); + } + if(!result) + { + failedBlocks.append(item); } } + return failedBlocks; } void Mifare::dump() @@ -701,69 +682,6 @@ void Mifare::lockC() util->execCMD("hf 14a raw 52"); } -void Mifare::writeAllE() -{ - const int waitTime = 200; - QString result; - for(int i = 0; i < cardType.sector_size; i++) - { - for(int j = 0; j < cardType.blk[i]; j++) - { - result = ""; - if(data_isDataValid(dataList->at(cardType.blks[i] + j)) != DATA_NOSPACE || dataList->at(cardType.blks[i] + j).contains('?')) - continue; - result = util->execCMDWithOutput( - "hf mf eset " - + QString::number(cardType.blks[i] + j) - + " " - + dataList->at(cardType.blks[i] + j), - waitTime); - } - } - util->execCMDWithOutput("hf mf eget", waitTime); // to refresh output buffer; -} - -void Mifare::readAllE() -{ - QString result; - const int waitTime = 200; - - QString tmp; - int offset = 0; - for(int i = 0; i < cardType.sector_size; i++) - { - offset = 0; - for(int j = 0; j < cardType.blk[i]; j++) - { - - qDebug() << "**********" ; - result = util->execCMDWithOutput( - "hf mf eget " - + QString::number(cardType.blks[i] + j), - waitTime); - qDebug() << result ; - -// offset = dataPattern->indexIn(result); -// offset = result.indexOf(*dataPattern, offset); // When I find the data position in this way, the Regex might fail to match. - - tmp = result.mid(offset, 47).toUpper(); - qDebug() << tmp << offset; - qDebug() << "**********" ; - - if(offset == -1) - continue; - tmp.replace(" ", ""); - dataList->replace(cardType.blks[i] + j, tmp); - data_syncWithDataWidget(false, cardType.blks[i] + j); - } - keyAList->replace(i, dataList->at(cardType.blks[i] + cardType.blk[i] - 1).left(12)); - keyBList->replace(i, dataList->at(cardType.blks[i] + cardType.blk[i] - 1).right(12)); - data_syncWithKeyWidget(false, i, KEY_A); - data_syncWithKeyWidget(false, i, KEY_B); - - } -} - void Mifare::wipeE() { util->execCMD("hf mf eclr"); diff --git a/module/mifare.h b/module/mifare.h index 5a86d4b..3223f67 100644 --- a/module/mifare.h +++ b/module/mifare.h @@ -71,9 +71,9 @@ public: void snoop(); void list(); void readOne(TargetType targetType = TARGET_MIFARE); - void readSelected(const QList& selectedBlocks); + void readSelected(TargetType targetType = TARGET_MIFARE); void writeOne(TargetType targetType = TARGET_MIFARE); - void writeSelected(const QList& selectedBlocks); + QList writeSelected(TargetType targetType = TARGET_MIFARE); void dump(); void restore(); @@ -87,8 +87,6 @@ public: CardType cardType; Mifare::CardType getCardType(); void setCardType(int type); - void writeAllC(); - void readAllC(); void wipeC(); void setParameterC(); @@ -102,8 +100,6 @@ public: 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); @@ -129,7 +125,7 @@ private: 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, 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); }; diff --git a/ui/mainwindow.cpp b/ui/mainwindow.cpp index 4c801d1..6b33e30 100644 --- a/ui/mainwindow.cpp +++ b/ui/mainwindow.cpp @@ -17,8 +17,6 @@ MainWindow::MainWindow(QWidget *parent): pm3Thread = new QThread(this); pm3 = new PM3Process(pm3Thread); -// pm3->moveToThread(pm3Thread); -// pm3->init(); pm3Thread->start(); pm3state = false; @@ -491,13 +489,7 @@ void MainWindow::on_MF_Attack_hardnestedButton_clicked() void MainWindow::on_MF_RW_readSelectedButton_clicked() { setState(false); - QList selectedBlocks; - for(int i = 0; i < mifare->cardType.block_size; i++) - { - if(ui->MF_dataWidget->item(i, 1)->checkState() == Qt::Checked) - selectedBlocks.append(i); - } - mifare->readSelected(selectedBlocks); + mifare->readSelected(Mifare::TARGET_MIFARE); setState(true); } @@ -517,14 +509,9 @@ void MainWindow::on_MF_RW_writeBlockButton_clicked() void MainWindow::on_MF_RW_writeSelectedButton_clicked() { + QList failedBlocks; setState(false); - QList selectedBlocks; - for(int i = 0; i < mifare->cardType.block_size; i++) - { - if(ui->MF_dataWidget->item(i, 1)->checkState() == Qt::Checked) - selectedBlocks.append(i); - } - mifare->writeSelected(selectedBlocks); + failedBlocks = mifare->writeSelected(Mifare::TARGET_MIFARE); setState(true); } @@ -538,10 +525,10 @@ 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); } @@ -552,10 +539,11 @@ void MainWindow::on_MF_UID_readBlockButton_clicked() setState(true); } -void MainWindow::on_MF_UID_writeAllButton_clicked() +void MainWindow::on_MF_UID_writeSelectedButton_clicked() { + QList failedBlocks; setState(false); - mifare->writeAllC(); + failedBlocks = mifare->writeSelected(Mifare::TARGET_UID); setState(true); } @@ -604,17 +592,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 failedBlocks; setState(false); - mifare->readAllE(); + failedBlocks = mifare->writeSelected(Mifare::TARGET_EMULATOR); setState(true); } diff --git a/ui/mainwindow.h b/ui/mainwindow.h index d5622bd..9f19b29 100644 --- a/ui/mainwindow.h +++ b/ui/mainwindow.h @@ -92,11 +92,11 @@ private slots: 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(); @@ -124,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(); diff --git a/ui/mainwindow.ui b/ui/mainwindow.ui index e0ca29f..42e918e 100644 --- a/ui/mainwindow.ui +++ b/ui/mainwindow.ui @@ -72,6 +72,12 @@ + + + 40 + 0 + + Refresh @@ -79,6 +85,12 @@ + + + 40 + 0 + + Connect @@ -86,6 +98,12 @@ + + + 40 + 0 + + Disconnect @@ -188,8 +206,27 @@ + + + + + 40 + 0 + + + + Select Trailer + + + + + + 40 + 0 + + KeyBlocks->Key @@ -197,6 +234,12 @@ + + + 40 + 0 + + KeyBlocks<-Key @@ -204,6 +247,12 @@ + + + 40 + 0 + + Fill Keys @@ -211,6 +260,12 @@ + + + 40 + 0 + + Trailer Decoder @@ -218,6 +273,12 @@ + + + 40 + 0 + + Set Fonts @@ -290,6 +351,12 @@ + + + 0 + 0 + + MINI @@ -297,6 +364,12 @@ + + + 0 + 0 + + 1K @@ -307,6 +380,12 @@ + + + 0 + 0 + + 2K @@ -314,6 +393,12 @@ + + + 0 + 0 + + 4K @@ -426,6 +511,12 @@ + + + 40 + 0 + + Card Info @@ -439,6 +530,12 @@ 0 + + + 40 + 0 + + Check Default @@ -448,7 +545,7 @@ - 0 + 40 0 @@ -459,6 +556,12 @@ + + + 40 + 0 + + Hardnested @@ -611,6 +714,12 @@ + + + 40 + 0 + + Read One @@ -618,6 +727,12 @@ + + + 40 + 0 + + Write One @@ -625,6 +740,12 @@ + + + 0 + 0 + + Read Selected @@ -632,6 +753,12 @@ + + + 0 + 0 + + Write Selected @@ -664,6 +791,12 @@ 0 + + + 40 + 0 + + Restore @@ -689,6 +822,12 @@ + + + 0 + 0 + + Lock UFUID Card @@ -696,6 +835,12 @@ + + + 0 + 0 + + About UID Card @@ -703,6 +848,12 @@ + + + 40 + 0 + + Read One @@ -710,20 +861,38 @@ + + + 40 + 0 + + Write One - + + + + 0 + 0 + + Read Selected - + + + + 0 + 0 + + Write Selected @@ -737,6 +906,12 @@ 0 + + + 0 + 0 + + Set Parameter @@ -812,22 +987,28 @@ - + + + + 0 + 0 + + - Load from data above + Write Selected - + - 40 + 0 0 - Read All + Read Selected