mirror of
https://github.com/hasherezade/pe-bear
synced 2026-06-08 14:34:04 +00:00
182 lines
5.0 KiB
C++
182 lines
5.0 KiB
C++
#include "PatternSearchWindow.h"
|
|
|
|
PatternSearchWindow::PatternSearchWindow(QWidget *parent, PeHandler* peHndl)
|
|
: QDialog(parent, Qt::Dialog),
|
|
m_peHndl(peHndl), threadMngr(nullptr)
|
|
{
|
|
setModal(true);
|
|
setWindowTitle(tr("Define search"));
|
|
offsetLabel.setText(tr("Starting from the offset:" ));
|
|
secPropertyLayout2.addWidget(&offsetLabel);
|
|
secPropertyLayout2.addWidget(&startOffsetBox);
|
|
|
|
startOffsetBox.setRange(0, 0);
|
|
startOffsetBox.setPrefix("0x");
|
|
startOffsetBox.setValue(0);
|
|
|
|
// Pattern search:
|
|
QRegularExpressionValidator *validator = new QRegularExpressionValidator(QRegularExpression("([0-9A-Fa-f\\?]{0,2} {0,1})*"), this);
|
|
patternEdit.setValidator(validator);
|
|
|
|
const QString signInfo = tr("Hexadecimal with wild characters, i.e.") + "\"55 8B ?? 8B 45 0C\"";
|
|
patternEdit.setToolTip(signInfo);
|
|
patternLabel.setText(tr("Signature to search:"));
|
|
patternEdit.setPlaceholderText(signInfo);
|
|
patternLabel.setBuddy(&patternEdit);
|
|
|
|
signatureTabLayout.addWidget(&patternLabel);
|
|
signatureTabLayout.addWidget(&patternEdit);
|
|
signatureTab.setLayout(&signatureTabLayout);
|
|
|
|
// String search
|
|
searchedStrLabel.setText(tr("String to search:"));
|
|
searchedStrLabel.setBuddy(&searchedStrEdit);
|
|
|
|
encodingCombo.addItem(tr("ANSI"));
|
|
encodingCombo.addItem(tr("UTF-16"));
|
|
|
|
stringTabLayout.addWidget(&searchedStrLabel);
|
|
stringTabLayout.addWidget(&searchedStrEdit);
|
|
stringTabLayout.addWidget(&encodingCombo);
|
|
|
|
stringTab.setLayout(&stringTabLayout);
|
|
//---
|
|
tabWidget.addTab(&stringTab, tr("Strings"));
|
|
tabWidget.addTab(&signatureTab, tr("Signatures"));
|
|
|
|
secPropertyLayout4.addWidget(&progressBar);
|
|
|
|
topLayout.addLayout(&secPropertyLayout2);
|
|
topLayout.addWidget(&tabWidget);
|
|
topLayout.addLayout(&secPropertyLayout4);
|
|
topLayout.addLayout(&buttonLayout);
|
|
|
|
progressBar.setRange(0, 1000);
|
|
progressBar.setVisible(false);
|
|
topLayout.addStretch();
|
|
setLayout(&topLayout);
|
|
|
|
searchButton.setText(tr("Search"));
|
|
buttonLayout.addWidget(&searchButton);
|
|
connect(&searchButton, SIGNAL(clicked()), this, SLOT(onSearchClicked()));
|
|
patternEdit.setFocus();
|
|
}
|
|
|
|
QString PatternSearchWindow::stringToSignature(const QString& text)
|
|
{
|
|
QByteArray bytes;
|
|
|
|
switch (encodingCombo.currentIndex())
|
|
{
|
|
case 0: // ANSI
|
|
bytes = text.toLocal8Bit();
|
|
break;
|
|
|
|
case 1: // UTF-16
|
|
bytes = QByteArray(
|
|
reinterpret_cast<const char*>(text.utf16()),
|
|
text.size() * sizeof(ushort)
|
|
);
|
|
break;
|
|
|
|
default:
|
|
return QString();
|
|
}
|
|
|
|
return bytes.toHex().toUpper();
|
|
}
|
|
|
|
void PatternSearchWindow::onSearchClicked()
|
|
{
|
|
if (!this->m_peHndl) return;
|
|
MappedExe* exe = m_peHndl->getPe();
|
|
if (!exe) return;
|
|
|
|
offset_t offset = startOffsetBox.value();
|
|
if (this->progressBar.value() == this->progressBar.maximum()) {
|
|
startOffsetBox.setValue(0);
|
|
offset = 0;
|
|
}
|
|
|
|
const size_t fullSize = exe->getContentSize();
|
|
if (offset >= fullSize) return;
|
|
|
|
QString text;
|
|
if (tabWidget.currentWidget() == &signatureTab) {
|
|
text = patternEdit.text();
|
|
}
|
|
else if (tabWidget.currentWidget() == &stringTab) {
|
|
text = searchedStrEdit.text();
|
|
if (text.length()) {
|
|
text = stringToSignature(text);
|
|
}
|
|
}
|
|
if (text.isEmpty()) {
|
|
return;
|
|
}
|
|
|
|
if (!this->threadMngr) {
|
|
threadMngr = new SignFinderThreadManager(exe);
|
|
}
|
|
|
|
if (!threadMngr->loadSignature("Searched", text)) {
|
|
progressBar.setValue(0);
|
|
QMessageBox::information(this, tr("Info"), tr("Could not parse the signature!"), QMessageBox::Ok);
|
|
return;
|
|
}
|
|
|
|
connect(threadMngr, SIGNAL(gotMatches(MatchesCollection* )),
|
|
this, SLOT(matchesFound(MatchesCollection *)), Qt::UniqueConnection);
|
|
connect(threadMngr, SIGNAL(progressUpdated(int )),
|
|
this, SLOT(onProgressUpdated(int )), Qt::UniqueConnection);
|
|
connect(threadMngr, SIGNAL(searchStarted(bool )),
|
|
this, SLOT(onSearchStarted(bool )), Qt::UniqueConnection);
|
|
|
|
progressBar.setVisible(true);
|
|
progressBar.setValue(0);
|
|
threadMngr->setStartOffset(offset);
|
|
threadMngr->recreateThread();
|
|
}
|
|
|
|
void PatternSearchWindow::onProgressUpdated(int progress)
|
|
{
|
|
progressBar.setValue(progress);
|
|
}
|
|
|
|
void PatternSearchWindow::onSearchStarted(bool isStarted)
|
|
{
|
|
searchButton.setEnabled(!isStarted);
|
|
}
|
|
|
|
void PatternSearchWindow::matchesFound(MatchesCollection *matches)
|
|
{
|
|
if (!threadMngr) return; //should never happen
|
|
|
|
if (!matches || !matches->packerAtOffset.size()) {
|
|
QMessageBox::information(this, tr("Info"), tr("Not found!"), QMessageBox::Ok);
|
|
threadMngr->stopThread();
|
|
return;
|
|
}
|
|
const QList<MatchedSign> &signAtOffset = matches->packerAtOffset;
|
|
if (!signAtOffset.size()) {
|
|
QMessageBox::information(this, tr("Info"), tr("Not found!"), QMessageBox::Ok);
|
|
threadMngr->stopThread();
|
|
return;
|
|
}
|
|
MatchedSign match = *(signAtOffset.begin());
|
|
const size_t offset = match.offset;
|
|
const size_t signLen = match.len;
|
|
m_peHndl->setDisplayed(false, offset, signLen);
|
|
m_peHndl->setHilighted(offset, signLen);
|
|
startOffsetBox.setValue(offset);
|
|
if (QMessageBox::question(this, tr("Info"), tr("Found at:") + " 0x" + QString::number(offset, 16) + "\n"+
|
|
tr("Search next?"), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
|
|
{
|
|
threadMngr->stopThread();
|
|
return;
|
|
}
|
|
|
|
threadMngr->setStartOffset(offset + 1);
|
|
threadMngr->recreateThread();
|
|
}
|