void DllLoader::PrintExportTable(ExportDirTable_t *ExportDirTable) { char *Name = (char*)RVA2Data(ExportDirTable->Name_RVA); unsigned long *ExportAddressTable = (unsigned long*)RVA2Data(ExportDirTable->ExportAddressTable_RVA); unsigned long *NamePointerTable = (unsigned long*)RVA2Data(ExportDirTable->NamePointerTable_RVA); unsigned short *OrdinalTable = (unsigned short*)RVA2Data(ExportDirTable->OrdinalTable_RVA); CLog::Log(LOGDEBUG, "Export Table for %s:\n", Name); CLog::Log(LOGDEBUG, "ExportFlags: %04lX\n", ExportDirTable->ExportFlags); CLog::Log(LOGDEBUG, "TimeStamp: %04lX\n", ExportDirTable->TimeStamp); CLog::Log(LOGDEBUG, "Major Ver: %02X\n", ExportDirTable->MajorVersion); CLog::Log(LOGDEBUG, "Minor Ver: %02X\n", ExportDirTable->MinorVersion); CLog::Log(LOGDEBUG, "Name RVA: %04lX\n", ExportDirTable->Name_RVA); CLog::Log(LOGDEBUG, "OrdinalBase %lu\n", ExportDirTable->OrdinalBase); CLog::Log(LOGDEBUG, "NumAddrTable %lu\n", ExportDirTable->NumAddrTable); CLog::Log(LOGDEBUG, "NumNamePtrs %lu\n", ExportDirTable->NumNamePtrs); CLog::Log(LOGDEBUG, "ExportAddressTable_RVA %04lX\n", ExportDirTable->ExportAddressTable_RVA); CLog::Log(LOGDEBUG, "NamePointerTable_RVA %04lX\n", ExportDirTable->NamePointerTable_RVA); CLog::Log(LOGDEBUG, "OrdinalTable_RVA %04lX\n\n", ExportDirTable->OrdinalTable_RVA); CLog::Log(LOGDEBUG, "Public Exports:\n"); CLog::Log(LOGDEBUG, " ordinal hint RVA name\n"); for (unsigned int i = 0; i < ExportDirTable->NumNamePtrs; i++) { char *Name = (char*)RVA2Data(NamePointerTable[i]); CLog::Log(LOGDEBUG, " %lu", OrdinalTable[i] + ExportDirTable->OrdinalBase); CLog::Log(LOGDEBUG, " %d", OrdinalTable[i]); CLog::Log(LOGDEBUG, " %08lX", ExportAddressTable[OrdinalTable[i]]); CLog::Log(LOGDEBUG, " %s\n", Name); } }
void CoffLoader::PerformFixups(void) { int FixupDataSize; char *FixupData; char *EndData; EntryAddress = (unsigned long)RVA2Data(EntryAddress); if( (PVOID)WindowsHeader->ImageBase == hModule ) return; if ( !Directory ) return ; if ( NumOfDirectories <= BASE_RELOCATION_TABLE ) return ; if ( !Directory[BASE_RELOCATION_TABLE].Size ) return ; FixupDataSize = Directory[BASE_RELOCATION_TABLE].Size; FixupData = (char*)RVA2Data(Directory[BASE_RELOCATION_TABLE].RVA); EndData = FixupData + FixupDataSize; while (FixupData < EndData) { // Starting a new Fixup Block unsigned long PageRVA = *((unsigned long*)FixupData); FixupData += 4; unsigned long BlockSize = *((unsigned long*)FixupData); FixupData += 4; BlockSize -= 8; for (unsigned int i = 0; i < BlockSize / 2; i++) { unsigned short Fixup = *((unsigned short*)FixupData); FixupData += 2; int Type = (Fixup >> 12) & 0x0f; Fixup &= 0xfff; if (Type == IMAGE_REL_BASED_HIGHLOW) { unsigned long *Off = (unsigned long*)RVA2Data(Fixup + PageRVA); *Off = (unsigned long)RVA2Data(*Off - WindowsHeader->ImageBase); } else if (Type == IMAGE_REL_BASED_ABSOLUTE) {} else { printf("Unsupported fixup type!!\n"); } } } }
void DllLoader::PrintImportTable(ImportDirTable_t *ImportDirTable) { ImportDirTable_t *Imp = ImportDirTable; int HavePrinted = 0; CLog::Log(LOGDEBUG, "The Coff Image contains the following imports:\n\n"); while ( Imp->ImportLookupTable_RVA != 0 || Imp->TimeStamp != 0 || Imp->ForwarderChain != 0 || Imp->Name_RVA != 0 || Imp->ImportAddressTable_RVA != 0) { char *Name; HavePrinted = 1; Name = (char*)RVA2Data(Imp->Name_RVA); CLog::Log(LOGDEBUG, " %s:\n", Name); CLog::Log(LOGDEBUG, " ImportAddressTable: %04lX\n", Imp->ImportAddressTable_RVA); CLog::Log(LOGDEBUG, " ImportLookupTable: %04lX\n", Imp->ImportLookupTable_RVA); CLog::Log(LOGDEBUG, " TimeStamp: %01lX\n", Imp->TimeStamp); CLog::Log(LOGDEBUG, " Forwarder Chain: %01lX\n", Imp->ForwarderChain); PrintImportLookupTable(Imp->ImportLookupTable_RVA); CLog::Log(LOGDEBUG, "\n"); Imp++; } if (!HavePrinted) CLog::Log(LOGDEBUG, "None."); }
int DllLoader::LoadExports() { if ( NumOfDirectories > EXPORT_TABLE && Directory[EXPORT_TABLE].Size > 0 ) { ExportDirTable = (ExportDirTable_t*)RVA2Data(Directory[EXPORT_TABLE].RVA); #ifdef DUMPING_DATA PrintExportTable(ExportDirTable); #endif // TODO - Validate all pointers are valid. Is a zero RVA valid or not? I'd guess not as it would // point to the coff file header, thus not right. unsigned long *ExportAddressTable = (unsigned long*)RVA2Data(ExportDirTable->ExportAddressTable_RVA); unsigned long *NamePointerTable = (unsigned long*)RVA2Data(ExportDirTable->NamePointerTable_RVA); unsigned short *OrdinalTable = (unsigned short*)RVA2Data(ExportDirTable->OrdinalTable_RVA); for (unsigned int i = 0; i < ExportDirTable->NumNamePtrs; i++) { char *Name = (char*)RVA2Data(NamePointerTable[i]); void* Addr = (void*)RVA2Data(ExportAddressTable[OrdinalTable[i]]); AddExport(Name, OrdinalTable[i]+ExportDirTable->OrdinalBase, Addr); } } return 0; }
void DllLoader::PrintImportLookupTable(unsigned long ImportLookupTable_RVA) { unsigned long *Table = (unsigned long*)RVA2Data(ImportLookupTable_RVA); while (*Table) { if (*Table & 0x80000000) { // Process Ordinal... CLog::Log(LOGDEBUG, " Ordinal: %01lX\n", *Table & 0x7fffffff); } else { CLog::Log(LOGDEBUG, " Don't process Hint/Name Table yet...\n"); } Table++; } }
int DllLoader::ResolveImports(void) { int bResult = 1; if ( NumOfDirectories >= 2 && Directory[IMPORT_TABLE].Size > 0 ) { ImportDirTable = (ImportDirTable_t*)RVA2Data(Directory[IMPORT_TABLE].RVA); #ifdef DUMPING_DATA PrintImportTable(ImportDirTable); #endif ImportDirTable_t *Imp = ImportDirTable; while ( Imp->ImportLookupTable_RVA != 0 || Imp->TimeStamp != 0 || Imp->ForwarderChain != 0 || Imp->Name_RVA != 0 || Imp->ImportAddressTable_RVA != 0) { const char *Name = (const char*)RVA2Data(Imp->Name_RVA); const char* FileName=ResolveReferencedDll(Name); // If possible use the dll name WITH path to resolve exports. We could have loaded // a dll with the same name as another dll but from a different directory if (FileName) Name=FileName; unsigned long *Table = (unsigned long*)RVA2Data(Imp->ImportLookupTable_RVA); unsigned long *Addr = (unsigned long*)RVA2Data(Imp->ImportAddressTable_RVA); while (*Table) { if (*Table & 0x80000000) { void *Fixup; if ( !ResolveOrdinal(Name, *Table&0x7ffffff, &Fixup) ) { bResult = 0; char szBuf[128]; CLog::Log(LOGDEBUG,"Unable to resolve ordinal %s %lu\n", Name, *Table&0x7ffffff); sprintf(szBuf, "%lu", *Table&0x7ffffff); *Addr = create_dummy_function(Name, szBuf); tracker_dll_data_track(this, *Addr); } else { *Addr = (unsigned long)Fixup; //woohoo!! } } else { // We don't handle Hint/Name tables yet!!! char *ImpName = (char*)RVA2Data(*Table + 2); void *Fixup; if ( !ResolveName(Name, ImpName, &Fixup) ) { *Addr=get_win_function_address(Name, ImpName); if(!*Addr) { CLog::Log(LOGDEBUG,"Unable to resolve %s %s\n", Name, ImpName); *Addr = create_dummy_function(Name, ImpName); tracker_dll_data_track(this, *Addr); bResult = 0; } } else { *Addr = (unsigned long)Fixup; } } Table++; Addr++; } Imp++; } } return bResult; }