#include "pe/ClrDirWrapper.h" /* typedef struct IMAGE_COR20_HEADER { // Header versioning DWORD cb; WORD MajorRuntimeVersion; WORD MinorRuntimeVersion; // Symbol table and startup information IMAGE_DATA_DIRECTORY MetaData; DWORD Flags; // The main program if it is an EXE (not used if a DLL?) // If COMIMAGE_FLAGS_NATIVE_ENTRYPOINT is not set, EntryPointToken represents a managed entrypoint. // If COMIMAGE_FLAGS_NATIVE_ENTRYPOINT is set, EntryPointRVA represents an RVA to a native entrypoint // (depricated for DLLs, use modules constructors intead). union { DWORD EntryPointToken; DWORD EntryPointRVA; }; // This is the blob of managed resources. Fetched using code:AssemblyNative.GetResource and // code:PEFile.GetResource and accessible from managed code from // System.Assembly.GetManifestResourceStream. The meta data has a table that maps names to offsets into // this blob, so logically the blob is a set of resources. IMAGE_DATA_DIRECTORY Resources; // IL assemblies can be signed with a public-private key to validate who created it. The signature goes // here if this feature is used. IMAGE_DATA_DIRECTORY StrongNameSignature; IMAGE_DATA_DIRECTORY CodeManagerTable; // Depricated, not used // Used for manged codee that has unmaanaged code inside it (or exports methods as unmanaged entry points) IMAGE_DATA_DIRECTORY VTableFixups; IMAGE_DATA_DIRECTORY ExportAddressTableJumps; // null for ordinary IL images. NGEN images it points at a code:CORCOMPILE_HEADER structure IMAGE_DATA_DIRECTORY ManagedNativeHeader; } IMAGE_COR20_HEADER, *PIMAGE_COR20_HEADER; */ pe::IMAGE_COR20_HEADER* ClrDirWrapper::clrDir() { offset_t rva = getDirEntryAddress(); BYTE *ptr = m_Exe->getContentAt(rva, Executable::RVA, sizeof(pe::IMAGE_COR20_HEADER)); if (ptr == NULL) return NULL; return (pe::IMAGE_COR20_HEADER*) ptr; } bool ClrDirWrapper::wrap() { return true; } void* ClrDirWrapper::getPtr() { return clrDir(); } bufsize_t ClrDirWrapper::getSize() { if (!getPtr()) return 0; return sizeof(pe::IMAGE_COR20_HEADER); } size_t ClrDirWrapper::getFieldsCount() { if (!getPtr()) return 0; return FIELD_COUNTER; } QString ClrDirWrapper::getName() { return "CLR Directory"; } void* ClrDirWrapper::getFieldPtr(size_t fId, size_t subField) { pe::IMAGE_COR20_HEADER* d = clrDir(); if (!d) return NULL; switch (fId) { case CB: return &d->cb; case MAJOR_RUNTIME_VER: return &d->MajorRuntimeVersion; case MINOR_RUNTIME_VER: return &d->MinorRuntimeVersion; case META_DATA_VA: return &d->MetaData.VirtualAddress; case META_DATA_SIZE: return &d->MetaData.Size; case FLAGS: return &d->Flags; case ENTRY_POINT: { return &d->EntryPointRVA; } case RESOURCES_VA: return &d->Resources.VirtualAddress; case RESOURCES_SIZE: return &d->Resources.Size; case STRONG_NAME_SIGNATURE_VA: return &d->StrongNameSignature.VirtualAddress; case STRONG_NAME_SIGNATURE_SIZE: return &d->StrongNameSignature.Size; case CODE_MANAGER_TABLE_VA: return &d->CodeManagerTable.VirtualAddress; case CODE_MANAGER_TABLE_SIZE: return &d->CodeManagerTable.Size; case VTABLE_FIXUPS_VA: return &d->VTableFixups.VirtualAddress; case VTABLE_FIXUPS_SIZE: return &d->VTableFixups.Size; case EXPORT_ADDR_TABLE_JMPS_VA: return &d->ExportAddressTableJumps.VirtualAddress; case EXPORT_ADDR_TABLE_JMPS_SIZE: return &d->ExportAddressTableJumps.Size; case MANAGED_NATIVE_HDR_VA: return &d->ManagedNativeHeader.VirtualAddress; case MANAGED_NATIVE_HDR_SIZE: return &d->ManagedNativeHeader.Size; } return this->getPtr(); } QString ClrDirWrapper::getFieldName(size_t fieldId) { switch (fieldId) { case CB: return "Cb"; case MAJOR_RUNTIME_VER: return "MajorRuntimeVersion"; case MINOR_RUNTIME_VER: return "MinorRuntimeVersion"; case META_DATA_VA: return "MetaData.VA"; case META_DATA_SIZE: return "MetaData.Size"; case FLAGS: return "Flags"; case ENTRY_POINT: { const pe::IMAGE_COR20_HEADER* d = clrDir(); if (!d) return "EntryPoint"; if (d->Flags & pe::COMIMAGE_FLAGS_NATIVE_ENTRYPOINT) { return "EntryPointRVA"; } else { return "EntryPointToken"; } } case RESOURCES_VA: return "Resources.VA"; case RESOURCES_SIZE: return "Resources.Size"; case STRONG_NAME_SIGNATURE_VA: return "StrongNameSignature.VA"; case STRONG_NAME_SIGNATURE_SIZE: return "StrongNameSignature.Size"; case CODE_MANAGER_TABLE_VA: return "CodeManagerTable.VA"; case CODE_MANAGER_TABLE_SIZE: return "CodeManagerTable.Size"; case VTABLE_FIXUPS_VA: return "VTableFixups.VA"; case VTABLE_FIXUPS_SIZE: return "VTableFixups.Size"; case EXPORT_ADDR_TABLE_JMPS_VA: return "ExportAddressTableJumps.VA"; case EXPORT_ADDR_TABLE_JMPS_SIZE: return "ExportAddressTableJumps.Size"; case MANAGED_NATIVE_HDR_VA: return "ManagedNativeHeader.VA"; case MANAGED_NATIVE_HDR_SIZE: return "ManagedNativeHeader.Size"; } return getName(); } Executable::addr_type ClrDirWrapper::containsAddrType(size_t fieldId, size_t subField) { switch (fieldId) { case ENTRY_POINT: { const pe::IMAGE_COR20_HEADER* d = clrDir(); if (!d) return Executable::NOT_ADDR; if (d->Flags & pe::COMIMAGE_FLAGS_NATIVE_ENTRYPOINT) { return Executable::RVA; } else { return Executable::NOT_ADDR; } } case RESOURCES_VA: case META_DATA_VA: case STRONG_NAME_SIGNATURE_VA: case CODE_MANAGER_TABLE_VA: case VTABLE_FIXUPS_VA: case EXPORT_ADDR_TABLE_JMPS_VA: case MANAGED_NATIVE_HDR_VA: return Executable::RVA; } return Executable::NOT_ADDR; } std::set ClrDirWrapper::getFlagsSet(DWORD flags) { const size_t clrFlagsCount = 6; const DWORD clrFlags[clrFlagsCount] = { pe::COMIMAGE_FLAGS_ILONLY, pe::COMIMAGE_FLAGS_32BITREQUIRED, pe::COMIMAGE_FLAGS_IL_LIBRARY, pe::COMIMAGE_FLAGS_STRONGNAMESIGNED, pe::COMIMAGE_FLAGS_NATIVE_ENTRYPOINT, pe::COMIMAGE_FLAGS_TRACKDEBUGDATA }; std::set allFlags; for (size_t i = 0; i < clrFlagsCount; ++i) { const DWORD nextFlag = clrFlags[i]; if (flags & nextFlag) { allFlags.insert(nextFlag); } } return allFlags; } QString ClrDirWrapper::translateFlag(DWORD flags) { if (flags & pe::COMIMAGE_FLAGS_ILONLY) { return ("IL Only"); } if (flags & pe::COMIMAGE_FLAGS_32BITREQUIRED) { return("32-bit required"); } if (flags & pe::COMIMAGE_FLAGS_IL_LIBRARY) { return ("IL Library"); } if (flags & pe::COMIMAGE_FLAGS_STRONGNAMESIGNED) { return("Strong Name Signed"); } if (flags & pe::COMIMAGE_FLAGS_NATIVE_ENTRYPOINT) { return("Native EntryPoint"); } if (flags & pe::COMIMAGE_FLAGS_TRACKDEBUGDATA) { return("Track Debug Data"); } return ""; } QString ClrDirWrapper::translateFieldContent(size_t fieldId) { const pe::IMAGE_COR20_HEADER* d = clrDir(); if (!d) return ""; if (fieldId != FLAGS) return ""; std::set flagsSet = ClrDirWrapper::getFlagsSet(d->Flags); std::set::iterator itr; QStringList list; for (itr = flagsSet.begin() ; itr != flagsSet.end(); ++itr) { const DWORD nextFlag = *itr; const QString flagInfo = ClrDirWrapper::translateFlag(nextFlag); if (flagInfo.length() == 0) continue; list.append(flagInfo); } return list.join(";"); }