1
0
Fork 0

search for GUID (#1156)

This commit is contained in:
Torusrxxx 2016-10-09 16:30:37 +00:00 committed by Duncan Ogilvie
parent 408f2f4a71
commit 294a806a31
10 changed files with 303 additions and 2 deletions

View File

@ -538,7 +538,7 @@ static bool cbModCallFind(Capstone* disasm, BASIC_INSTRUCTION_INFO* basicinfo, R
if(found)
{
char addrText[20] = "";
char moduleTargetText[256] = "";
char moduleTargetText[MAX_MODULE_SIZE] = "";
sprintf_s(addrText, "%p", disasm->Address());
sprintf(moduleTargetText, "%s.%s", module, label);
GuiReferenceSetRowCount(refinfo->refcount + 1);
@ -581,6 +581,248 @@ CMDRESULT cbInstrModCallFind(int argc, char* argv[])
return STATUS_CONTINUE;
}
struct GUIDHashObject
{
inline size_t operator()(const GUID & ref)
{
size_t* p = (size_t*)&ref;
#ifdef _WIN64
static_assert(sizeof(size_t) == 8, "The system is not 64-bit!");
return p[0] + p[1];
#else //x86
static_assert(sizeof(size_t) == 4, "The system is not 32-bit!");
return p[0] + p[1] + p[2] + p[3];
#endif //_WIN64
};
};
struct GUIDEqualObject
{
inline bool operator()(const GUID & a, const GUID & b)
{
return memcmp(&a, &b, sizeof(GUID)) == 0;
};
};
class GUIDInfo
{
public:
String ProgId;
String Description;
String Path;
GUIDInfo(const GUID & ref, HKEY CLSID)
{
wchar_t subkey[40];
HKEY hKey;
StringFromGUID2(ref, subkey, 40);
if(RegOpenKeyExW(CLSID, subkey, 0, KEY_READ, &hKey) == ERROR_SUCCESS)
{
Description = ReadValue(nullptr, hKey);
HKEY hProgIdKey;
if(RegOpenKeyExW(hKey, L"ProgId", 0, KEY_READ, &hProgIdKey) == ERROR_SUCCESS)
{
ProgId = ReadValue(nullptr, hProgIdKey);
RegCloseKey(hProgIdKey);
}
else
{
ProgId = "";
}
HKEY hPathKey;
if(RegOpenKeyExW(hKey, L"InprocServer32", 0, KEY_READ, &hPathKey) == ERROR_SUCCESS)
{
Path = ReadValue(nullptr, hPathKey);
RegCloseKey(hPathKey);
}
else
{
Path = "";
}
RegCloseKey(hKey);
}
}
private:
String ReadValue(const wchar_t* name, HKEY hKey)
{
DWORD regType = 0;
DWORD cbData = 0;
if(RegQueryValueExW(hKey, name, nullptr, &regType, nullptr, &cbData))
return "";
if(regType != REG_SZ)
return "";
Memory<wchar_t*> buffer(cbData + 2, "GUIDInfo::ReadValue");
buffer()[cbData / 2] = 0; //ensure the buffer is null-terminated
if(RegQueryValueExW(hKey, name, nullptr, nullptr, reinterpret_cast<LPBYTE>(buffer()), &cbData))
return "";
return StringUtils::Utf16ToUtf8(buffer());
}
};
struct GUIDRefInfo
{
std::unordered_map<GUID, size_t, GUIDHashObject, GUIDEqualObject>* allRegisteredGUIDs;
std::vector<GUIDInfo>* allQueriedGUIDs;
HKEY CLSID;
};
static bool cbGUIDFind(Capstone* disasm, BASIC_INSTRUCTION_INFO* basicinfo, REFINFO* refinfo)
{
if(!disasm || !basicinfo) //initialize
{
GuiReferenceInitialize(refinfo->name);
GuiReferenceAddColumn(2 * sizeof(duint), GuiTranslateText(QT_TRANSLATE_NOOP("DBG", "Address")));
GuiReferenceAddColumn(20, GuiTranslateText(QT_TRANSLATE_NOOP("DBG", "Disassembly")));
GuiReferenceAddColumn(40, GuiTranslateText(QT_TRANSLATE_NOOP("DBG", "GUID")));
GuiReferenceAddColumn(20, GuiTranslateText(QT_TRANSLATE_NOOP("DBG", "ProgId")));
GuiReferenceAddColumn(40, GuiTranslateText(QT_TRANSLATE_NOOP("DBG", "Path")));
GuiReferenceAddColumn(40, GuiTranslateText(QT_TRANSLATE_NOOP("DBG", "Description")));
GuiReferenceSetRowCount(0);
GuiReferenceReloadData();
return true;
}
duint value = 0;
if(basicinfo->branch) //cannot branch to a GUID
return false;
GUIDRefInfo* refInfo = reinterpret_cast<GUIDRefInfo*>(refinfo->userinfo);
if((basicinfo->type & TYPE_VALUE) == TYPE_VALUE)
value = basicinfo->value.value;
if((basicinfo->type & TYPE_MEMORY) == TYPE_MEMORY)
value = basicinfo->memory.value;
if((basicinfo->type & TYPE_ADDR) == TYPE_ADDR)
value = basicinfo->addr;
GUID guid;
unsigned char membuffer[38 * 2];
bool found = false;
memset(&membuffer, 0, sizeof(membuffer));
if(MemRead(value, &membuffer, sizeof(membuffer), nullptr, true))
{
std::unordered_map<GUID, size_t, GUIDHashObject, GUIDEqualObject>::iterator iterator;
if(membuffer[0] == '{' && membuffer[37] == '}' && membuffer[24] == '-' && membuffer[9] == '-' && membuffer[14] == '-' && membuffer[19] == '-')
{
//very likely a ASCII string representation of GUID
wchar_t wideguid[39];
for(size_t i = 0; i < 38; i++)
wideguid[i] = membuffer[i];
wideguid[38] = 0;
if(CLSIDFromString(wideguid, &guid) == S_OK)
{
iterator = refInfo->allRegisteredGUIDs->find(guid);
if(iterator != refInfo->allRegisteredGUIDs->end())
found = true;
}
}
if(!found)
{
wchar_t* wideguid = reinterpret_cast<wchar_t*>(membuffer);
if(wideguid[0] == L'{' && wideguid[37] == L'}' && wideguid[24] == L'-' && wideguid[9] == L'-' && wideguid[14] == L'-' && wideguid[19] == L'-')
{
//very likely a Unicode string representation of GUID
if(CLSIDFromString(wideguid, &guid) == S_OK)
{
iterator = refInfo->allRegisteredGUIDs->find(guid);
if(iterator != refInfo->allRegisteredGUIDs->end())
found = true;
}
}
}
if(!found)
{
memcpy(&guid, membuffer, sizeof(guid));
iterator = refInfo->allRegisteredGUIDs->find(guid);
if(iterator != refInfo->allRegisteredGUIDs->end())
found = true;
}
if(found)
{
char addrText[20] = "";
sprintf_s(addrText, "%p", disasm->Address());
GuiReferenceSetRowCount(refinfo->refcount + 1);
GuiReferenceSetCellContent(refinfo->refcount, 0, addrText);
char disassembly[4096] = "";
if(GuiGetDisassembly((duint)disasm->Address(), disassembly))
GuiReferenceSetCellContent(refinfo->refcount, 1, disassembly);
else
GuiReferenceSetCellContent(refinfo->refcount, 1, disasm->InstructionText().c_str());
wchar_t guidText[40];
StringFromGUID2(guid, guidText, 40);
GuiReferenceSetCellContent(refinfo->refcount, 2, StringUtils::Utf16ToUtf8(guidText).c_str());
size_t infoIndex = iterator->second;
if(infoIndex == 0)
{
refInfo->allQueriedGUIDs->push_back(GUIDInfo(guid, refInfo->CLSID));
infoIndex = refInfo->allQueriedGUIDs->size();
refInfo->allRegisteredGUIDs->at(guid) = infoIndex;
}
infoIndex--;
GuiReferenceSetCellContent(refinfo->refcount, 3, refInfo->allQueriedGUIDs->at(infoIndex).ProgId.c_str());
GuiReferenceSetCellContent(refinfo->refcount, 4, refInfo->allQueriedGUIDs->at(infoIndex).Path.c_str());
GuiReferenceSetCellContent(refinfo->refcount, 5, refInfo->allQueriedGUIDs->at(infoIndex).Description.c_str());
}
}
return found;
}
CMDRESULT cbInstrGUIDFind(int argc, char* argv[])
{
duint ticks = GetTickCount();
duint addr;
duint size = 0;
String TranslatedString;
std::unordered_map<GUID, size_t, GUIDHashObject, GUIDEqualObject> allRegisteredGUIDs;
std::vector<GUIDInfo> allQueriedGUIDs;
GUIDRefInfo refInfo;
// If not specified, assume CURRENT_REGION by default
if(argc < 2 || !valfromstring(argv[1], &addr, true))
addr = GetContextDataEx(hActiveThread, UE_CIP);
if(argc >= 3)
if(!valfromstring(argv[2], &size, true))
size = 0;
duint refFindType = CURRENT_REGION;
if(argc >= 4 && valfromstring(argv[3], &refFindType, true))
if(refFindType != CURRENT_REGION && refFindType != CURRENT_MODULE && refFindType != ALL_MODULES)
refFindType = CURRENT_REGION;
HKEY CLSID;
if(RegOpenKeyExW(HKEY_CLASSES_ROOT, L"CLSID", 0, KEY_READ, &CLSID))
{
dputs(QT_TRANSLATE_NOOP("DBG", "RegOpenKeyExW() failed. Cannot enumerate GUIDs."));
return STATUS_ERROR;
}
wchar_t subkeyName[40];
subkeyName[39] = 0;
DWORD i = 0;
DWORD subkeyNameLen = 40;
LONG result;
while(result = RegEnumKeyExW(CLSID, i++, subkeyName, &subkeyNameLen, nullptr, nullptr, nullptr, nullptr), result == ERROR_SUCCESS || result == ERROR_MORE_DATA)
{
if(subkeyNameLen == 38 && result != ERROR_MORE_DATA)
{
if(subkeyName[0] == '{' && subkeyName[37] == '}' && subkeyName[24] == '-' && subkeyName[9] == '-' && subkeyName[14] == '-' && subkeyName[19] == '-')
{
//very likely a GUID
GUID temp;
if(CLSIDFromString(subkeyName, &temp) == S_OK)
allRegisteredGUIDs.insert(std::make_pair(temp, 0));
}
}
subkeyNameLen = 40;
subkeyName[39] = 0;
}
refInfo.allQueriedGUIDs = &allQueriedGUIDs;
refInfo.allRegisteredGUIDs = &allRegisteredGUIDs;
refInfo.CLSID = CLSID;
TranslatedString = GuiTranslateText(QT_TRANSLATE_NOOP("DBG", "GUID"));
int found = RefFind(addr, size, cbGUIDFind, &refInfo, false, TranslatedString.c_str(), (REFFINDTYPE)refFindType, false);
dprintf(QT_TRANSLATE_NOOP("DBG", "%u GUID(s) in %ums\n"), DWORD(found), GetTickCount() - DWORD(ticks));
varset("$result", found, false);
RegCloseKey(CLSID);
return STATUS_CONTINUE;
}
static void yaraCompilerCallback(int error_level, const char* file_name, int line_number, const char* message, void* user_data)
{
switch(error_level)

View File

@ -10,6 +10,7 @@ CMDRESULT cbInstrRefFind(int argc, char* argv[]);
CMDRESULT cbInstrRefFindRange(int argc, char* argv[]);
CMDRESULT cbInstrRefStr(int argc, char* argv[]);
CMDRESULT cbInstrModCallFind(int argc, char* argv[]);
CMDRESULT cbInstrGUIDFind(int argc, char* argv[]);
CMDRESULT cbInstrYara(int argc, char* argv[]);
CMDRESULT cbInstrYaramod(int argc, char* argv[]);
CMDRESULT cbInstrSetMaxFindResult(int argc, char* argv[]);

View File

@ -10,6 +10,17 @@
#include "module.h"
#include "threading.h"
/**
@brief RefFind Find reference to the buffer by a given criterion.
@param Address The base address of the buffer
@param Size The size of the buffer
@param Callback The callback that is invoked to identify whether an instruction satisfies the criterion. prototype: bool callback(Capstone* disasm, BASIC_INSTRUCTION_INFO* basicinfo, REFINFO* refinfo)
@param UserData The data that will be passed to Callback
@param Silent If true, no log will be outputed.
@param Name The name of the reference criterion. Not null.
@param type The type of the memory buffer. Possible values:CURRENT_REGION,CURRENT_MODULE,ALL_MODULES
@param disasmText If false, disassembled text will not be available.
*/
int RefFind(duint Address, duint Size, CBREF Callback, void* UserData, bool Silent, const char* Name, REFFINDTYPE type, bool disasmText)
{
char fullName[deflen];

View File

@ -419,6 +419,7 @@ static void registercommands()
dbgcmdnew("meminfo", cbInstrMeminfo, true); //command to debug memory map bugs
dbgcmdnew("briefcheck", cbInstrBriefcheck, true); //check if mnemonic briefs are missing
dbgcmdnew("traceexecute", cbInstrTraceexecute, true); //execute trace record on address
dbgcmdnew("guidfind\1findguid", cbInstrGUIDFind, true); //find GUID references
};
static bool cbCommandProvider(char* cmd, int maxlen)

View File

@ -565,11 +565,13 @@ void CPUDisassembly::setupRightClickContextMenu()
mFindStringsRegion = makeAction(DIcon("search_for_string.png"), tr("&String references"), SLOT(findStringsSlot()));
mFindCallsRegion = makeAction(DIcon("call.png"), tr("&Intermodular calls"), SLOT(findCallsSlot()));
mFindPatternRegion = makeShortcutAction(DIcon("search_for_pattern.png"), tr("&Pattern"), SLOT(findPatternSlot()), "ActionFindPattern");
mFindGUIDRegion = makeAction(tr("&GUID"), SLOT(findGUIDSlot()));
mSearchRegionMenu->addAction(mFindCommandRegion);
mSearchRegionMenu->addAction(mFindConstantRegion);
mSearchRegionMenu->addAction(mFindStringsRegion);
mSearchRegionMenu->addAction(mFindCallsRegion);
mSearchRegionMenu->addAction(mFindPatternRegion);
mSearchRegionMenu->addAction(mFindGUIDRegion);
// Search in Current Module menu
mFindCommandModule = makeAction(DIcon("search_for_command.png"), tr("C&ommand"), SLOT(findCommandSlot()));
@ -577,21 +579,25 @@ void CPUDisassembly::setupRightClickContextMenu()
mFindStringsModule = makeAction(DIcon("search_for_string.png"), tr("&String references"), SLOT(findStringsSlot()));
mFindCallsModule = makeAction(DIcon("call.png"), tr("&Intermodular calls"), SLOT(findCallsSlot()));
mFindPatternModule = makeAction(DIcon("search_for_pattern.png"), tr("&Pattern"), SLOT(findPatternSlot()));
mFindGUIDModule = makeAction(tr("&GUID"), SLOT(findGUIDSlot()));
mSearchModuleMenu->addAction(mFindCommandModule);
mSearchModuleMenu->addAction(mFindConstantModule);
mSearchModuleMenu->addAction(mFindStringsModule);
mSearchModuleMenu->addAction(mFindCallsModule);
mSearchModuleMenu->addAction(mFindPatternModule);
mSearchModuleMenu->addAction(mFindGUIDModule);
// Search in All Modules menu
mFindCommandAll = makeAction(DIcon("search_for_command.png"), tr("C&ommand"), SLOT(findCommandSlot()));
mFindConstantAll = makeAction(DIcon("search_for_constant.png"), tr("&Constant"), SLOT(findConstantSlot()));
mFindStringsAll = makeAction(DIcon("search_for_string.png"), tr("&String references"), SLOT(findStringsSlot()));
mFindCallsAll = makeAction(DIcon("call.png"), tr("&Intermodular calls"), SLOT(findCallsSlot()));
mFindGUIDAll = makeAction(tr("&GUID"), SLOT(findGUIDSlot()));
mSearchAllMenu->addAction(mFindCommandAll);
mSearchAllMenu->addAction(mFindConstantAll);
mSearchAllMenu->addAction(mFindStringsAll);
mSearchAllMenu->addAction(mFindCallsAll);
mSearchAllMenu->addAction(mFindGUIDAll);
searchMenu->addMenu(makeMenu(DIcon("search_current_region.png"), tr("Current Region")), mSearchRegionMenu);
searchMenu->addMenu(makeMenu(DIcon("search_current_module.png"), tr("Current Module")), mSearchModuleMenu);
@ -1204,6 +1210,21 @@ void CPUDisassembly::findPatternSlot()
emit displayReferencesWidget();
}
void CPUDisassembly::findGUIDSlot()
{
int refFindType = 0;
if(sender() == mFindGUIDRegion)
refFindType = 0;
else if(sender() == mFindGUIDModule)
refFindType = 1;
else if(sender() == mFindGUIDAll)
refFindType = 2;
auto addrText = ToHexString(rvaToVa(getInitialSelection()));
DbgCmdExec(QString("findguid %1, 0, %2").arg(addrText).arg(refFindType).toUtf8().constData());
emit displayReferencesWidget();
}
void CPUDisassembly::selectionGetSlot(SELECTIONDATA* selection)
{
selection->start = rvaToVa(getSelectionStart());
@ -1753,6 +1774,7 @@ void CPUDisassembly::togglePreviewSlot()
void CPUDisassembly::analyzeModuleSlot()
{
DbgCmdExec("cfanal");
DbgCmdExec("analx");
}
void CPUDisassembly::createThreadSlot()

View File

@ -67,6 +67,7 @@ public slots:
void findStringsSlot();
void findCallsSlot();
void findPatternSlot();
void findGUIDSlot();
void selectionGetSlot(SELECTIONDATA* selection);
void selectionSetSlot(const SELECTIONDATA* selection);
void enableHighlightingModeSlot();
@ -129,17 +130,20 @@ private:
QAction* mFindStringsRegion;
QAction* mFindCallsRegion;
QAction* mFindPatternRegion;
QAction* mFindGUIDRegion;
QAction* mFindCommandModule;
QAction* mFindConstantModule;
QAction* mFindStringsModule;
QAction* mFindCallsModule;
QAction* mFindPatternModule;
QAction* mFindGUIDModule;
QAction* mFindCommandAll;
QAction* mFindConstantAll;
QAction* mFindStringsAll;
QAction* mFindCallsAll;
QAction* mFindGUIDAll;
// Goto dialog specific
GotoDialog* mGoto;

View File

@ -43,6 +43,7 @@ CustomizeMenuDialog::CustomizeMenuDialog(QWidget* parent) :
ui->treeWidget->addTopLevelItem(parentItem);
}
connect(ui->btnOk, SIGNAL(clicked()), this, SLOT(onOk()));
connect(ui->btnDisselectAll, SIGNAL(clicked()), this, SLOT(onDisselectAll()));
}
void CustomizeMenuDialog::onOk()
@ -59,6 +60,18 @@ void CustomizeMenuDialog::onOk()
emit accept();
}
void CustomizeMenuDialog::onDisselectAll()
{
for(int i = ui->treeWidget->topLevelItemCount(); i != 0; i--)
{
const QTreeWidgetItem* parentItem = ui->treeWidget->topLevelItem(i - 1);
for(int j = parentItem->childCount(); j != 0; j--)
{
parentItem->child(j - 1)->setCheckState(0, Qt::Unchecked);
}
}
}
CustomizeMenuDialog::~CustomizeMenuDialog()
{
delete ui;

View File

@ -18,6 +18,7 @@ public:
public slots:
void onOk();
void onDisselectAll();
private:
Ui::CustomizeMenuDialog* ui;

View File

@ -51,6 +51,13 @@
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="btnDisselectAll">
<property name="text">
<string>Disselect All</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btnOk">
<property name="text">

View File

@ -5,7 +5,6 @@
/**
* @brief MenuBuilder::loadFromConfig Set the menu builder to be customizable
* @param id The id of menu builder. It should be the same on every same menu.
* See CustomizeMenuDialog for a list of defined identifiers.
*/
void MenuBuilder::loadFromConfig()
{