mirror of
https://github.com/hasherezade/bearparser
synced 2026-06-08 14:32:38 +00:00
326 lines
8.9 KiB
C++
326 lines
8.9 KiB
C++
#include "pe/DebugDirWrapper.h"
|
|
#include <QtGlobal>
|
|
|
|
using namespace pe;
|
|
/*
|
|
typedef struct _IMAGE_DEBUG_DIRECTORY {
|
|
DWORD Characteristics;
|
|
DWORD TimeDateStamp;
|
|
WORD MajorVersion;
|
|
WORD MinorVersion;
|
|
DWORD Type;
|
|
DWORD SizeOfData;
|
|
DWORD AddressOfRawData;
|
|
DWORD PointerToRawData;
|
|
} IMAGE_DEBUG_DIRECTORY, *PIMAGE_DEBUG_DIRECTORY;
|
|
|
|
*/
|
|
|
|
bool DebugDirWrapper::loadNextEntry(size_t cntr)
|
|
{
|
|
const size_t dirSize = this->getSize();
|
|
const size_t entriesCount = dirSize / sizeof(IMAGE_DEBUG_DIRECTORY);
|
|
if (cntr >= entriesCount) {
|
|
return false;
|
|
}
|
|
|
|
DebugDirEntryWrapper* dbgEntry = new DebugDirEntryWrapper(m_PE, this, cntr);
|
|
if (!dbgEntry || !dbgEntry->getPtr()) {
|
|
delete dbgEntry;
|
|
return false;
|
|
}
|
|
entries.push_back(dbgEntry);
|
|
return true;
|
|
}
|
|
|
|
bool DebugDirWrapper::isRepro()
|
|
{
|
|
for (auto itr = entries.begin(); itr != entries.end(); ++itr) {
|
|
DebugDirEntryWrapper* dbgEntry = dynamic_cast<DebugDirEntryWrapper*>(*itr);
|
|
if (!dbgEntry) continue;
|
|
|
|
bool isOk = false;
|
|
uint64_t typeVal = dbgEntry->getNumValue(DebugDirEntryWrapper::TYPE, &isOk);
|
|
if (isOk && typeVal == pe::DT_REPRO) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
//---
|
|
|
|
bool DebugDirEntryWrapper::wrap()
|
|
{
|
|
if (this->getDebugStruct()) {
|
|
DebugDirCVEntryWrapper *cvWrapper = new DebugDirCVEntryWrapper(m_Exe, this);
|
|
this->entries.push_back(cvWrapper);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void* DebugDirEntryWrapper::getPtr()
|
|
{
|
|
return debugDir();
|
|
}
|
|
|
|
bufsize_t DebugDirEntryWrapper::getSize()
|
|
{
|
|
if (!getPtr()) return 0;
|
|
return sizeof(IMAGE_DEBUG_DIRECTORY);
|
|
}
|
|
|
|
void* DebugDirEntryWrapper::getFieldPtr(size_t fId, size_t subField)
|
|
{
|
|
IMAGE_DEBUG_DIRECTORY* d = debugDir();
|
|
if (d == NULL) return NULL;
|
|
|
|
switch (fId) {
|
|
case CHARACTERISTIC: return &d->Characteristics;
|
|
case TIMESTAMP: return &d->TimeDateStamp;
|
|
case MAJOR_VER: return &d->MajorVersion;
|
|
case MINOR_VER: return &d->MinorVersion;
|
|
case TYPE: return &d->Type;
|
|
case DATA_SIZE: return &d->SizeOfData;
|
|
case RAW_DATA_ADDR: return &d->AddressOfRawData;
|
|
case RAW_DATA_PTR: return &d->PointerToRawData;
|
|
}
|
|
return this->getPtr();
|
|
}
|
|
|
|
QString DebugDirEntryWrapper::getFieldName(size_t fieldId)
|
|
{
|
|
switch (fieldId) {
|
|
case CHARACTERISTIC: return "Characteristics";
|
|
case TIMESTAMP: return (dbgRootDir && dbgRootDir->isRepro()) ? "ReproChecksum" :"TimeDateStamp";
|
|
case MAJOR_VER: return "MajorVersion";
|
|
case MINOR_VER: return "MinorVersion";
|
|
case TYPE: return "Type";
|
|
case DATA_SIZE: return "SizeOfData";
|
|
case RAW_DATA_ADDR: return "AddressOfRawData";
|
|
case RAW_DATA_PTR: return "PointerToRawData";
|
|
}
|
|
return getName();
|
|
}
|
|
|
|
Executable::addr_type DebugDirEntryWrapper::containsAddrType(size_t fieldId, size_t subField)
|
|
{
|
|
switch (fieldId) {
|
|
case RAW_DATA_ADDR: return Executable::RVA;
|
|
case RAW_DATA_PTR: return Executable::RAW;
|
|
}
|
|
return Executable::NOT_ADDR;
|
|
}
|
|
|
|
QString DebugDirEntryWrapper::translateType(int type)
|
|
{
|
|
switch (type) {
|
|
case pe::DT_UNKNOWN : return "unknown";
|
|
case pe::DT_COFF : return "COFF";
|
|
case pe::DT_CODEVIEW : return "Visual C++ (CodeView)";
|
|
case pe::DT_FPO : return "Frame pointer omission";
|
|
case pe::DT_MISC : return "DBG file";
|
|
case pe::DT_EXCEPTION : return "A copy of .pdata section";
|
|
case pe::DT_FIXUP : return "Reserved";
|
|
case pe::DT_OMAP_TO_SRC : return "mapping from an RVA in image to an RVA in source image";
|
|
case pe::DT_OMAP_FROM_SRC : return "mapping from an RVA in source image to an RVA in image";
|
|
case pe::DT_BORLAND : return "Borland";
|
|
case pe::DT_RESERVED10 : return "Reserved";
|
|
case pe::DT_CLSID : return "CLSID";
|
|
case pe::DT_VC_FEATURE : return "VC Feature";
|
|
case pe::DT_POGO : return "POGO";
|
|
case pe::DT_ILTCG : return "ILTCG";
|
|
case pe::DT_MPX : return "MPX";
|
|
case pe::DT_REPRO : return "REPRO";
|
|
}
|
|
return "<Unknown>";
|
|
}
|
|
|
|
QString DebugDirEntryWrapper::translateFieldContent(size_t fieldId)
|
|
{
|
|
if (fieldId != TYPE) return "";
|
|
|
|
IMAGE_DEBUG_DIRECTORY* d = debugDir();
|
|
if (d == NULL) return NULL;
|
|
|
|
return translateType(d->Type);
|
|
}
|
|
|
|
BYTE* DebugDirEntryWrapper::getDebugStruct()
|
|
{
|
|
IMAGE_DEBUG_DIRECTORY* d = this->debugDir();
|
|
if (d == NULL) return NULL;
|
|
if (d->Type != DT_CODEVIEW) {
|
|
return NULL;
|
|
}
|
|
offset_t rva = d->PointerToRawData;
|
|
size_t dirSize = d->SizeOfData;
|
|
return m_Exe->getContentAt(rva, Executable::RAW, dirSize);
|
|
}
|
|
|
|
DEBUG_RSDSI* DebugDirEntryWrapper::getRDSI()
|
|
{
|
|
BYTE* debugStr = getDebugStruct();
|
|
IMAGE_DEBUG_DIRECTORY* d = debugDir();
|
|
if (!debugStr || !d) return NULL;
|
|
if (d->SizeOfData < sizeof(DEBUG_RSDSI)) {
|
|
return NULL;
|
|
}
|
|
DEBUG_RSDSI* rdsi = (DEBUG_RSDSI*)debugStr;
|
|
if (rdsi->dwSig == CV_SIGNATURE_RSDS) {
|
|
return rdsi;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
pe::DEBUG_NB10* DebugDirEntryWrapper::getNB10()
|
|
{
|
|
BYTE* debugStr = getDebugStruct();
|
|
IMAGE_DEBUG_DIRECTORY* d = debugDir();
|
|
if (!debugStr || !d) return NULL;
|
|
if (d->SizeOfData < sizeof(DEBUG_NB10)) {
|
|
return NULL;
|
|
}
|
|
DEBUG_NB10* nb = (DEBUG_NB10*)debugStr;
|
|
if (nb->cvHdr.CvSignature == CV_SIGNATURE_NB10) {
|
|
return nb;
|
|
}
|
|
return NULL;
|
|
}
|
|
//-------------------------
|
|
|
|
void* DebugDirCVEntryWrapper::getPtr()
|
|
{
|
|
DEBUG_RSDSI* rdsi = parentDir->getRDSI();
|
|
if (rdsi) {
|
|
return rdsi;
|
|
}
|
|
return parentDir->getNB10();
|
|
}
|
|
|
|
bufsize_t DebugDirCVEntryWrapper::getSize()
|
|
{
|
|
IMAGE_DEBUG_DIRECTORY* d = parentDir->debugDir();
|
|
if (d == NULL) return 0;
|
|
return d->SizeOfData;
|
|
}
|
|
|
|
void* DebugDirCVEntryWrapper::getFieldPtr(size_t fId, size_t subField)
|
|
{
|
|
DEBUG_RSDSI* rdsi = parentDir->getRDSI();
|
|
if (rdsi) {
|
|
switch (fId) {
|
|
case F_CVDBG_SIGN: return &rdsi->dwSig;
|
|
case F_CVDBG_GUID: return &rdsi->guidSig;
|
|
case F_CVDBG_AGE: return &rdsi->age;
|
|
case F_CVDBG_PDB: return &rdsi->szPdb;
|
|
}
|
|
return rdsi;
|
|
}
|
|
DEBUG_NB10* dbg = parentDir->getNB10();
|
|
if (dbg) {
|
|
switch (fId) {
|
|
case F_CVDBG_SIGN: return &dbg->cvHdr.CvSignature;
|
|
case F_CVDBG_GUID: return &dbg->Signature;
|
|
case F_CVDBG_AGE: return &dbg->Age;
|
|
case F_CVDBG_PDB: return &dbg->PdbFileName;
|
|
}
|
|
return dbg;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
QString DebugDirCVEntryWrapper::getGuidString()
|
|
{
|
|
DEBUG_RSDSI* rdsi = parentDir->getRDSI();
|
|
if (rdsi) {
|
|
QString chunk4 = "";
|
|
for (size_t i = 0; i < sizeof(rdsi->guidSig.Data4); i++) {
|
|
QString out;
|
|
#if QT_VERSION >= 0x050000
|
|
out = QString().asprintf("%02X", rdsi->guidSig.Data4[i]);
|
|
#else
|
|
out = QString().sprintf("%02X", rdsi->guidSig.Data4[i]);
|
|
#endif
|
|
chunk4 += out;
|
|
}
|
|
QString chunk5 = "";
|
|
for (size_t i = 0; i < sizeof(rdsi->guidSig.Data5); i++) {
|
|
QString out;
|
|
#if QT_VERSION >= 0x050000
|
|
out = QString().asprintf("%02X", rdsi->guidSig.Data5[i]);
|
|
#else
|
|
out = QString().sprintf("%02X", rdsi->guidSig.Data5[i]);
|
|
#endif
|
|
chunk5 += out;
|
|
}
|
|
QString out;
|
|
#if QT_VERSION >= 0x050000
|
|
out = QString().asprintf("%08X-%04X-%04X-",
|
|
rdsi->guidSig.Data1,
|
|
rdsi->guidSig.Data2,
|
|
rdsi->guidSig.Data3);
|
|
#else
|
|
out = QString().sprintf("%08X-%04X-%04X-",
|
|
rdsi->guidSig.Data1,
|
|
rdsi->guidSig.Data2,
|
|
rdsi->guidSig.Data3);
|
|
#endif
|
|
return "{" + out + chunk4 + "-" + chunk5 + "}";
|
|
}
|
|
|
|
DEBUG_NB10* dbg = parentDir->getNB10();
|
|
if (dbg) {
|
|
QString out;
|
|
#if QT_VERSION >= 0x050000
|
|
out = QString().asprintf("%04X", dbg->Signature);
|
|
#else
|
|
out = QString().sprintf("%04X", dbg->Signature);
|
|
#endif
|
|
return out;
|
|
}
|
|
return "";
|
|
}
|
|
|
|
QString DebugDirCVEntryWrapper::getSignature()
|
|
{
|
|
DEBUG_RSDSI* rdsi = (DEBUG_RSDSI*)this->getPtr();
|
|
if (!rdsi) return "";
|
|
|
|
QString out;
|
|
#if QT_VERSION >= 0x050000
|
|
out = QString().asprintf("%.4s", (char*)&rdsi->dwSig);
|
|
#else
|
|
out = QString().sprintf("%.4s", (char*)&rdsi->dwSig);
|
|
#endif
|
|
return out;
|
|
}
|
|
|
|
QString DebugDirCVEntryWrapper::getFieldName(size_t fId)
|
|
{
|
|
switch (fId) {
|
|
case F_CVDBG_SIGN: return "CvSig";
|
|
case F_CVDBG_GUID: return "Signature";
|
|
case F_CVDBG_AGE: return "Age";
|
|
case F_CVDBG_PDB: return "PDB";
|
|
}
|
|
return "";
|
|
}
|
|
|
|
QString DebugDirCVEntryWrapper::translateFieldContent(size_t fId)
|
|
{
|
|
DEBUG_RSDSI* rdsi = parentDir->getRDSI();
|
|
DEBUG_NB10* dbg = parentDir->getNB10();
|
|
if (!rdsi && !dbg) return "";
|
|
|
|
char *pdb = NULL;
|
|
if (rdsi) pdb = (char*)rdsi->szPdb;
|
|
if (dbg) pdb = (char*)dbg->PdbFileName;
|
|
|
|
switch (fId) {
|
|
case F_CVDBG_SIGN: return getSignature();
|
|
case F_CVDBG_GUID: return getGuidString();
|
|
case F_CVDBG_PDB: return pdb ? pdb : "";
|
|
}
|
|
return "";
|
|
}
|