1
0
Fork 0

DBG: add export and import parsing routines in module.cpp

#580
This commit is contained in:
Duncan Ogilvie 2018-02-12 03:07:05 +01:00
parent bee62fbbf0
commit 476bc093bc
No known key found for this signature in database
GPG Key ID: FC89E0AAA0C1AAD8
2 changed files with 196 additions and 25 deletions

View File

@ -14,9 +14,152 @@
std::map<Range, MODINFO, RangeCompare> modinfo;
std::unordered_map<duint, std::string> hashNameMap;
bool MODRELOCATIONINFO::Contains(duint Address) const
static void ReadExportDirectory(MODINFO & Info, ULONG_PTR FileMapVA)
{
return Address >= rva && Address < rva + size;
// TODO: proper bounds checking
duint exportDirRva = GetPE32DataFromMappedFile(FileMapVA, 0, UE_EXPORTTABLEADDRESS);
duint exportDirSize = GetPE32DataFromMappedFile(FileMapVA, 0, UE_EXPORTTABLESIZE);
if(!exportDirRva || !exportDirSize)
return;
auto rva2offset = [&Info, FileMapVA](duint rva)
{
return ConvertVAtoFileOffsetEx(FileMapVA, Info.loadedSize, 0, rva, true, false);
};
auto exportDirOffset = rva2offset(exportDirRva);
if(!exportDirOffset)
return;
auto exportDir = PIMAGE_EXPORT_DIRECTORY(exportDirOffset + FileMapVA);
if(!exportDir->NumberOfFunctions)
return;
auto addressOfFunctionsOffset = rva2offset(exportDir->AddressOfFunctions);
if(!addressOfFunctionsOffset)
return;
auto addressOfFunctions = PDWORD(addressOfFunctionsOffset + FileMapVA);
auto addressOfNamesOffset = rva2offset(exportDir->AddressOfNames);
auto addressOfNames = PDWORD(addressOfNamesOffset ? addressOfNamesOffset + FileMapVA : 0);
auto addressOfNameOrdinalsOffset = rva2offset(exportDir->AddressOfNameOrdinals);
auto addressOfNameOrdinals = PWORD(addressOfNameOrdinalsOffset ? addressOfNameOrdinalsOffset + FileMapVA : 0);
Info.exports.reserve(exportDir->NumberOfFunctions);
Info.exportOrdinalBase = exportDir->Base;
for(DWORD i = 0; i < exportDir->NumberOfFunctions; i++)
{
MODEXPORT entry;
entry.ordinal = i + exportDir->Base;
entry.rva = addressOfFunctions[i];
if(entry.forwarded = entry.rva >= exportDirRva && entry.rva < exportDirRva + exportDirSize)
{
auto forwardNameOffset = rva2offset(entry.rva);
if(forwardNameOffset) // TODO: what does the Windows loader do if this fails?
entry.forwardName = String((const char*)(forwardNameOffset + FileMapVA));
}
Info.exports.push_back(entry);
}
for(DWORD i = 0; i < exportDir->NumberOfNames; i++)
{
auto index = addressOfNameOrdinals[i];
if(index >= 0 && index < Info.exports.size()) // TODO: what does the Windows loader do if this fails?
{
auto nameOffset = rva2offset(addressOfNames[i]);
if(nameOffset) // TODO: what does the Windows loader do if this fails?
Info.exports[index].name = String((const char*)(nameOffset + FileMapVA));
}
}
// prepare sorted vectors
Info.exportsByName.resize(Info.exports.size());
Info.exportsByRva.resize(Info.exports.size());
for(size_t i = 0; i < Info.exports.size(); i++)
{
Info.exportsByName[i] = i;
Info.exportsByRva[i] = i;
}
std::sort(Info.exportsByName.begin(), Info.exportsByName.end(), [&Info](size_t a, size_t b)
{
return Info.exports.at(a).name < Info.exports.at(b).name;
});
std::sort(Info.exportsByRva.begin(), Info.exportsByRva.end(), [&Info](size_t a, size_t b)
{
return Info.exports.at(a).rva < Info.exports.at(b).rva;
});
}
static void ReadImportDirectory(MODINFO & Info, ULONG_PTR FileMapVA)
{
// TODO: proper bounds checking
duint importDirRva = GetPE32DataFromMappedFile(FileMapVA, 0, UE_IMPORTTABLEADDRESS);
duint importDirSize = GetPE32DataFromMappedFile(FileMapVA, 0, UE_IMPORTTABLESIZE);
if(!importDirRva || !importDirSize)
return;
auto rva2offset = [&Info, FileMapVA](duint rva)
{
return ConvertVAtoFileOffsetEx(FileMapVA, Info.loadedSize, 0, rva, true, false);
};
auto importDirOffset = rva2offset(importDirRva);
if(!importDirOffset)
return;
auto importDescriptor = PIMAGE_IMPORT_DESCRIPTOR(importDirOffset + FileMapVA);
for(size_t moduleIndex = 0; importDescriptor->FirstThunk; importDescriptor++, moduleIndex++)
{
auto moduleNameOffset = rva2offset(importDescriptor->Name);
if(!moduleNameOffset) // TODO: what does the Windows loader do if this fails?
continue;
auto moduleName = String((const char*)(moduleNameOffset + FileMapVA));
Info.importModules.push_back(moduleName);
auto firstThunkOffset = rva2offset(importDescriptor->FirstThunk);
if(!firstThunkOffset) // TODO: what does the Windows loader do if this fails?
continue;
auto thunkData = PIMAGE_THUNK_DATA(firstThunkOffset + FileMapVA);
for(auto iatRva = importDescriptor->FirstThunk; thunkData->u1.AddressOfData; thunkData++, iatRva += sizeof(duint))
{
MODIMPORT entry;
entry.iatRva = iatRva;
entry.moduleIndex = moduleIndex;
if((thunkData->u1.Ordinal & IMAGE_ORDINAL_FLAG) == IMAGE_ORDINAL_FLAG)
{
entry.ordinal = thunkData->u1.Ordinal & ~IMAGE_ORDINAL_FLAG;
}
else
{
auto importByNameOffset = rva2offset(thunkData->u1.AddressOfData);
if(!importByNameOffset) // TODO: what does the Windows loader do if this fails?
continue;
auto importByName = PIMAGE_IMPORT_BY_NAME(importByNameOffset + FileMapVA);
entry.name = String((const char*)importByName->Name);
entry.ordinal = -1;
}
Info.imports.push_back(entry);
}
}
// prepare sorted vectors
Info.importsByRva.resize(Info.imports.size());
for(size_t i = 0; i < Info.imports.size(); i++)
Info.importsByRva[i] = i;
std::sort(Info.importsByRva.begin(), Info.importsByRva.end(), [&Info](size_t a, size_t b)
{
return Info.imports[a].iatRva < Info.imports[b].iatRva;
});
}
static void ReadTlsCallbacks(MODINFO & Info, ULONG_PTR FileMapVA)
@ -32,15 +175,19 @@ static void ReadTlsCallbacks(MODINFO & Info, ULONG_PTR FileMapVA)
if(tlsDirRva == 0 || tlsDirSize == 0)
return;
auto tlsDir = PIMAGE_TLS_DIRECTORY(ConvertVAtoFileOffsetEx(FileMapVA, Info.loadedSize, 0, tlsDirRva, true, false) + FileMapVA);
if(!tlsDir || !tlsDir->AddressOfCallBacks)
auto tlsDirOffset = ConvertVAtoFileOffsetEx(FileMapVA, Info.loadedSize, 0, tlsDirRva, true, false);
if(!tlsDirOffset)
return;
auto tlsDir = PIMAGE_TLS_DIRECTORY(tlsDirOffset + FileMapVA);
if(!tlsDir->AddressOfCallBacks)
return;
auto imageBase = GetPE32DataFromMappedFile(FileMapVA, 0, UE_IMAGEBASE);
auto tlsArray = PULONG_PTR(ConvertVAtoFileOffsetEx(FileMapVA, Info.loadedSize, 0, tlsDir->AddressOfCallBacks - imageBase, true, false) + FileMapVA);
if(!tlsArray)
auto tlsArrayOffset = ConvertVAtoFileOffsetEx(FileMapVA, Info.loadedSize, 0, tlsDir->AddressOfCallBacks - imageBase, true, false);
if(!tlsArrayOffset)
return;
auto tlsArray = PULONG_PTR(tlsArrayOffset + FileMapVA);
while(*tlsArray)
Info.tlsCallbacks.push_back(*tlsArray++ - imageBase + Info.base);
}
@ -327,6 +474,8 @@ void GetModuleInfo(MODINFO & Info, ULONG_PTR FileMapVA)
Info.sections.push_back(curSection);
}
ReadExportDirectory(Info, FileMapVA);
ReadImportDirectory(Info, FileMapVA);
ReadTlsCallbacks(Info, FileMapVA);
ReadBaseRelocationTable(Info, FileMapVA);
ReadDebugDirectory(Info, FileMapVA);

View File

@ -8,25 +8,21 @@
struct MODSECTIONINFO
{
duint addr; // Virtual address
duint size; // Virtual size
char name[MAX_SECTION_SIZE * 5]; // Escaped section name
};
struct MODIMPORTINFO
{
duint addr; // Virtual address
char name[MAX_IMPORT_SIZE];
char moduleName[MAX_MODULE_SIZE];
duint addr; // Virtual address
duint size; // Virtual size
char name[MAX_SECTION_SIZE * 5]; // Escaped section name
};
struct MODRELOCATIONINFO
{
DWORD rva; // Virtual address
BYTE type; // Relocation type (IMAGE_REL_BASED_*)
DWORD rva; // Virtual address
BYTE type; // Relocation type (IMAGE_REL_BASED_*)
WORD size;
bool Contains(duint Address) const;
bool Contains(duint Address) const
{
return Address >= rva && Address < rva + size;
}
};
struct PdbValidationData
@ -41,21 +37,47 @@ struct PdbValidationData
}
};
struct MODEXPORT
{
DWORD ordinal = 0;
DWORD rva = 0;
bool forwarded = false;
String forwardName;
String name;
};
struct MODIMPORT
{
size_t moduleIndex; //index in MODINFO.importModules
DWORD iatRva;
duint ordinal; //equal to -1 if imported by name
String name;
};
struct MODINFO
{
duint base = 0; // Module base
duint size = 0; // Module size
duint hash = 0; // Full module name hash
duint base = 0; // Module base
duint size = 0; // Module size
duint hash = 0; // Full module name hash
duint entry = 0; // Entry point
char name[MAX_MODULE_SIZE]; // Module name (without extension)
char extension[MAX_MODULE_SIZE]; // File extension
char path[MAX_PATH]; // File path (in UTF8)
char name[MAX_MODULE_SIZE]; // Module name (without extension)
char extension[MAX_MODULE_SIZE]; // File extension (including the dot)
char path[MAX_PATH]; // File path (in UTF8)
std::vector<MODSECTIONINFO> sections;
std::vector<MODRELOCATIONINFO> relocations;
std::vector<duint> tlsCallbacks;
std::vector<MODEXPORT> exports;
DWORD exportOrdinalBase = 0; //ordinal - 'exportOrdinalBase' = index in 'exports'
std::vector<size_t> exportsByName; //index in 'exports', sorted by export name
std::vector<size_t> exportsByRva; //index in 'exports', sorted by rva
std::vector<String> importModules;
std::vector<MODIMPORT> imports;
std::vector<size_t> importsByRva; //index in 'imports', sorted by rva
SymbolSourceBase* symbols = nullptr;
String pdbSignature;
String pdbFile;