diff --git a/include/retdec/fileformat/file_format/pe/pe_format_parser.h b/include/retdec/fileformat/file_format/pe/pe_format_parser.h index 6b7a29e39..94591ffcd 100644 --- a/include/retdec/fileformat/file_format/pe/pe_format_parser.h +++ b/include/retdec/fileformat/file_format/pe/pe_format_parser.h @@ -185,7 +185,7 @@ class PeFormatParser std::uint32_t getNumberOfImportedLibraries() const { - return peFile->impDir().getNumberOfFiles(PeLib::OLDDIR); + return peFile->impDir().getNumberOfFiles(false); } std::uint32_t getNumberOfDelayImportedLibraries() const @@ -309,10 +309,10 @@ class PeFormatParser { const auto & imports = peFile->impDir(); - if(index >= imports.getNumberOfFiles(PeLib::OLDDIR)) + if(index >= imports.getNumberOfFiles(false)) return false; - fileName = imports.getFileName(index, PeLib::OLDDIR); + fileName = imports.getFileName(index, false); return true; } @@ -327,51 +327,37 @@ class PeFormatParser return true; } - std::unique_ptr getImport(unsigned long long fileIndex, unsigned long long importIndex) const + std::unique_ptr getImport(std::size_t fileIndex, std::size_t importIndex) const { const PeLib::ImportDirectory & peImports = peFile->impDir(); - const auto ordinalMask = peFile->imageLoader().getOrdinalMask(); + const auto imageBase = peFile->imageLoader().getImageBase(); const auto bits = peFile->imageLoader().getImageBitability(); + std::string importName; + std::uint32_t ordinalNumber = 0; + std::uint32_t patchRva = 0; + std::uint16_t importHint = 0; + bool isImportByOrdinal = false; - if(fileIndex >= peImports.getNumberOfFiles(PeLib::OLDDIR) || - importIndex >= peImports.getNumberOfFunctions(fileIndex, PeLib::OLDDIR)) + if(peImports.getImportedFunction(fileIndex, importIndex, importName, importHint, ordinalNumber, patchRva, isImportByOrdinal, false)) { - return nullptr; - } + auto import = std::make_unique(PeImportFlag::None); - auto isOrdinalNumberValid = true; - unsigned long long ordinalNumber = peImports.getFunctionHint(fileIndex, importIndex, PeLib::OLDDIR); - if(!ordinalNumber) - { - const auto firstThunk = peImports.getFirstThunk(fileIndex, importIndex, PeLib::OLDDIR); - const auto originalFirstThunk = peImports.getOriginalFirstThunk(fileIndex, importIndex, PeLib::OLDDIR); - if(firstThunk & ordinalMask) - { - ordinalNumber = firstThunk - ordinalMask; - } - else if(originalFirstThunk & ordinalMask) - { - ordinalNumber = originalFirstThunk - ordinalMask; - } - else + if(isImportByOrdinal) { - isOrdinalNumberValid = false; + import->setOrdinalNumber(ordinalNumber); } - } - auto import = std::make_unique(PeImportFlag::None); - if(isOrdinalNumberValid) - { - import->setOrdinalNumber(ordinalNumber); - } - else - { - import->invalidateOrdinalNumber(); + // Note: Even when the function is imported by ordinal, there can be name + // Example: WS2_32.dll!@115 -> WSAStartup + import->setName(importName); + + import->setLibraryIndex(fileIndex); + import->setAddress(imageBase + patchRva); + return import; } - import->setName(peImports.getFunctionName(fileIndex, importIndex, PeLib::OLDDIR)); - import->setAddress(peFile->imageLoader().getImageBase() + peImports.getFirstThunk(fileIndex, PeLib::OLDDIR) + importIndex * (bits / 8)); - import->setLibraryIndex(fileIndex); - return import; + + // Out of range + return nullptr; } std::unique_ptr getDelayImport(unsigned long long fileIndex, unsigned long long importIndex) const diff --git a/include/retdec/pelib/ImportDirectory.h b/include/retdec/pelib/ImportDirectory.h index d6f85dbd0..f8a0a3c7f 100644 --- a/include/retdec/pelib/ImportDirectory.h +++ b/include/retdec/pelib/ImportDirectory.h @@ -18,19 +18,19 @@ #include "retdec/pelib/PeLibAux.h" #include "retdec/pelib/ImageLoader.h" +#include "retdec/pelib/ImageLoader.h" +#include "retdec/utils/ord_lookup.h" +#include "retdec/utils/string.h" namespace PeLib { - /// Parameter for functions that can operate on the OLDDIR or new import directory. - enum currdir {OLDDIR = 1, NEWDIR}; - class PeLibException; /// Class that handles import directories. /** * This class can read import directories from existing PE files or start completely from scratch. * Modifying import directories and writing them to files is also possible. - * It's worthy to note that many functions require an extra parameter of type currdir + * It's worthy to note that many functions require an extra parameter of type newDir * because the structure of import directories make it necessary that the OLDDIR import directory * must be preserved. That's why some functions (like adding and removing) imported functions * only exist for the new import directory, not for the one which is already written to the file. @@ -78,11 +78,11 @@ namespace PeLib if (FileIter != EndIter) { auto Iter = std::find_if( - FileIter->originalfirstthunk.begin(), - FileIter->originalfirstthunk.end(), + FileIter->thunk_data.begin(), + FileIter->thunk_data.end(), std::bind(comp, std::placeholders::_1, value) ); - if (Iter != FileIter->originalfirstthunk.end()) + if (Iter != FileIter->thunk_data.end()) { return true; } @@ -113,29 +113,32 @@ namespace PeLib int addFunction(const std::string& strFilename, const std::string& strFuncname); // EXPORT _byName /// Get the ID of a file through it's name. - unsigned int getFileIndex(const std::string& strFilename, currdir cdDir) const; // EXPORT + unsigned int getFileIndex(const std::string& strFilename, bool newDir) const; // EXPORT /// Get the ID of a function through it's name. - unsigned int getFunctionIndex(const std::string& strFilename, const std::string& strFuncname, currdir cdDir) const; // EXPORT + unsigned int getFunctionIndex(const std::string& strFilename, const std::string& strFuncname, bool newDir) const; // EXPORT /// Get the name of an imported file. - std::string getFileName(std::uint32_t dwFilenr, currdir cdDir) const; // EXPORT + std::string getFileName(std::uint32_t dwFilenr, bool newDir) const; // EXPORT - void setFileName(std::uint32_t filenr, currdir cdDir, const std::string& name); // EXPORT + void setFileName(std::uint32_t filenr, bool newDir, const std::string& name); // EXPORT /// Retrieve the loader error LoaderError loaderError() const; void setLoaderError(LoaderError ldrError); + /// Get the number of files which are imported. + std::uint32_t getNumberOfFiles(bool newDir) const; // EXPORT + /// Get the number of functions which are imported by a specific file. + std::uint32_t getNumberOfFunctions(std::size_t dwFilenr, bool newDir) const; // EXPORT + /// Get information about n-th imported function + bool getImportedFunction(std::size_t dwFilenr, std::size_t dwFuncnr, std::string & importName, std::uint16_t & importHint, std::uint32_t & importOrdinal, std::uint32_t & patchRva, bool & isImportByOrdinal, bool newDir) const; + /// Get the hint of an imported function. - std::uint16_t getFunctionHint(std::uint32_t dwFilenr, std::uint32_t dwFuncnr, currdir cdDir) const; // EXPORT - void setFunctionHint(std::uint32_t dwFilenr, std::uint32_t dwFuncnr, currdir cdDir, std::uint16_t value); // EXPORT + std::uint16_t getFunctionHint(std::uint32_t dwFilenr, std::uint32_t dwFuncnr, bool newDir) const; // EXPORT + void setFunctionHint(std::uint32_t dwFilenr, std::uint32_t dwFuncnr, bool newDir, std::uint16_t value); // EXPORT /// Get the name of an imported function. - std::string getFunctionName(std::uint32_t dwFilenr, std::uint32_t dwFuncnr, currdir cdDir) const; // EXPORT - void setFunctionName(std::uint32_t dwFilenr, std::uint32_t dwFuncnr, currdir cdDir, const std::string& functionName); // EXPORT - /// Get the number of files which are imported. - std::uint32_t getNumberOfFiles(currdir cdDir) const; // EXPORT - /// Get the number of fucntions which are imported by a specific file. - std::uint32_t getNumberOfFunctions(std::uint32_t dwFilenr, currdir cdDir) const; // EXPORT + std::string getFunctionName(std::uint32_t dwFilenr, std::uint32_t dwFuncnr, bool newDir) const; // EXPORT + void setFunctionName(std::uint32_t dwFilenr, std::uint32_t dwFuncnr, bool newDir, const std::string& functionName); // EXPORT /// Read a file's import directory. int read(ImageLoader & imageLoader); // EXPORT /// Writes pointer to the buffer (32-bit or 64-bit) @@ -156,43 +159,48 @@ namespace PeLib void setPointerSize(std::uint32_t pointerSize); /// Returns the FirstThunk value of a function. - std::uint32_t getFirstThunk(std::uint32_t dwFilenr, std::uint32_t dwFuncnr, currdir cdDir) const; // EXPORT _byNumber - void setFirstThunk(std::uint32_t dwFilenr, std::uint32_t dwFuncnr, currdir cdDir, std::uint32_t value); // EXPORT _byNumber + std::uint32_t getFirstThunk(std::uint32_t dwFilenr, std::uint32_t dwFuncnr, bool newDir) const; // EXPORT _byNumber + void setFirstThunk(std::uint32_t dwFilenr, std::uint32_t dwFuncnr, bool newDir, std::uint32_t value); // EXPORT _byNumber /// Returns the OriginalFirstThunk value of a function. - std::uint32_t getOriginalFirstThunk(std::uint32_t dwFilenr, std::uint32_t dwFuncnr, currdir cdDir) const; // EXPORT _byNumber - void setOriginalFirstThunk(std::uint32_t dwFilenr, std::uint32_t dwFuncnr, currdir cdDir, std::uint32_t value); // EXPORT + std::uint32_t getOriginalFirstThunk(std::uint32_t dwFilenr, std::uint32_t dwFuncnr, bool newDir) const; // EXPORT _byNumber + void setOriginalFirstThunk(std::uint32_t dwFilenr, std::uint32_t dwFuncnr, bool newDir, std::uint32_t value); // EXPORT -// std::uint64_t getFirstThunk(const std::string& strFilename, const std::string& strFuncname, currdir cdDir) const throw (PeLibException); -// std::uint64_t getOriginalFirstThunk(const std::string& strFilename, const std::string& strFuncname, currdir cdDir) const throw (PeLibException); +// std::uint64_t getFirstThunk(const std::string& strFilename, const std::string& strFuncname, bool newDir) const throw (PeLibException); +// std::uint64_t getOriginalFirstThunk(const std::string& strFilename, const std::string& strFuncname, bool newDir) const throw (PeLibException); /// Returns the FirstThunk value of a file. - std::uint32_t getFirstThunk(const std::string& strFilename, currdir cdDir) const; // EXPORT _byName + std::uint32_t getFirstThunk(const std::string& strFilename, bool newDir) const; // EXPORT _byName /// Returns the OriginalFirstThunk value of a file. - std::uint32_t getOriginalFirstThunk(const std::string& strFilename, currdir cdDir) const; // EXPORT _byName + std::uint32_t getOriginalFirstThunk(const std::string& strFilename, bool newDir) const; // EXPORT _byName /// Returns the ForwarderChain value of a file. - std::uint32_t getForwarderChain(const std::string& strFilename, currdir cdDir) const; // EXPORT _byName - std::uint32_t getRvaOfName(const std::string& strFilename, currdir cdDir) const; // EXPORT _byName + std::uint32_t getForwarderChain(const std::string& strFilename, bool newDir) const; // EXPORT _byName + std::uint32_t getRvaOfName(const std::string& strFilename, bool newDir) const; // EXPORT _byName /// Returns the TimeDateStamp value of a file. - std::uint32_t getTimeDateStamp(const std::string& strFilename, currdir cdDir) const; // EXPORT _byName + std::uint32_t getTimeDateStamp(const std::string& strFilename, bool newDir) const; // EXPORT _byName /// Returns the FirstThunk value of a file. - std::uint32_t getFirstThunk(std::uint32_t dwFilenr, currdir cdDir) const; // EXPORT - void setFirstThunk(std::uint32_t dwFilenr, currdir cdDir, std::uint32_t value); // EXPORT _byNumber_function + std::uint32_t getFirstThunk(std::uint32_t dwFilenr, bool newDir) const; // EXPORT + void setFirstThunk(std::uint32_t dwFilenr, bool newDir, std::uint32_t value); // EXPORT _byNumber_function /// Returns the OriginalFirstThunk value of a file. - std::uint32_t getOriginalFirstThunk(std::uint32_t dwFilenr, currdir cdDir) const; // EXPORT - void setOriginalFirstThunk(std::uint32_t dwFilenr, currdir cdDir, std::uint32_t value); // EXPORT _byNumber_function + std::uint32_t getOriginalFirstThunk(std::uint32_t dwFilenr, bool newDir) const; // EXPORT + void setOriginalFirstThunk(std::uint32_t dwFilenr, bool newDir, std::uint32_t value); // EXPORT _byNumber_function /// Returns the ForwarderChain value of a file. - std::uint32_t getForwarderChain(std::uint32_t dwFilenr, currdir cdDir) const; // EXPORT _byNumber - void setForwarderChain(std::uint32_t dwFilenr, currdir cdDir, std::uint32_t value); // EXPORT _byNumber_function - std::uint32_t getRvaOfName(std::uint32_t dwFilenr, currdir cdDir) const; // EXPORT _byNumber - void setRvaOfName(std::uint32_t dwFilenr, currdir cdDir, std::uint32_t value); // EXPORT + std::uint32_t getForwarderChain(std::uint32_t dwFilenr, bool newDir) const; // EXPORT _byNumber + void setForwarderChain(std::uint32_t dwFilenr, bool newDir, std::uint32_t value); // EXPORT _byNumber_function + std::uint32_t getRvaOfName(std::uint32_t dwFilenr, bool newDir) const; // EXPORT _byNumber + void setRvaOfName(std::uint32_t dwFilenr, bool newDir, std::uint32_t value); // EXPORT /// Returns the TimeDateStamp value of a file. - std::uint32_t getTimeDateStamp(std::uint32_t dwFilenr, currdir cdDir) const; // EXPORT - void setTimeDateStamp(std::uint32_t dwFilenr, currdir cdDir, std::uint32_t value); // EXPORT _byNumber + std::uint32_t getTimeDateStamp(std::uint32_t dwFilenr, bool newDir) const; // EXPORT + void setTimeDateStamp(std::uint32_t dwFilenr, bool newDir, std::uint32_t value); // EXPORT _byNumber const std::vector>& getOccupiedAddresses() const; -// std::uint16_t getFunctionHint(const std::string& strFilename, const std::string& strFuncname, currdir cdDir) const throw (PeLibException); +// std::uint16_t getFunctionHint(const std::string& strFilename, const std::string& strFuncname, bool newDir) const throw (PeLibException); + + protected: + + const std::vector& getImportList(bool newDir) const; + std::vector& getImportList(bool newDir); }; /** @@ -235,18 +243,16 @@ namespace PeLib PELIB_IMAGE_IMPORT_DIRECTORY iid; PELIB_THUNK_DATA td; td.hint = wHint; - td.itd.Ordinal = wHint /* | PELIB_IMAGE_ORDINAL_FLAGS::PELIB_IMAGE_ORDINAL_FLAG */; + td.itd.Ordinal = wHint | m_ordinalMask; iid.name = strFilename; if (FileIter == m_vNewiid.end()) { - iid.originalfirstthunk.push_back(td); - iid.firstthunk.push_back(td); + iid.thunk_data.push_back(td); m_vNewiid.push_back(iid); } else { - FileIter->originalfirstthunk.push_back(td); - FileIter->firstthunk.push_back(td); + FileIter->thunk_data.push_back(td); } return ERROR_NONE; @@ -278,14 +284,12 @@ namespace PeLib iid.name = strFilename; if (FileIter == m_vNewiid.end()) { - iid.originalfirstthunk.push_back(td); - iid.firstthunk.push_back(td); + iid.thunk_data.push_back(td); m_vNewiid.push_back(iid); } else { - FileIter->originalfirstthunk.push_back(td); - FileIter->firstthunk.push_back(td); + FileIter->thunk_data.push_back(td); } return ERROR_NONE; @@ -295,32 +299,23 @@ namespace PeLib * Searches through the import directory and returns the number of the import * directory entry which belongs to the given filename. * @param strFilename Name of the imported file. - * @param cdDir Flag to decide if the OLDDIR or new import directory is used. + * @param newDir Flag to decide if the OLDDIR or new import directory is used. * @return The ID of an imported file. **/ inline - unsigned int ImportDirectory::getFileIndex(const std::string& strFilename, currdir cdDir) const + unsigned int ImportDirectory::getFileIndex(const std::string& strFilename, bool newDir) const { - const std::vector* currDir; - - if (cdDir == OLDDIR) - { - currDir = &m_vOldiid; - } - else - { - currDir = &m_vNewiid; - } + auto * il = &getImportList(newDir); ConstImpDirFileIterator FileIter = std::find_if( - currDir->begin(), - currDir->end(), + il->begin(), + il->end(), [&](const auto& i) { return i == strFilename; } ); - if (FileIter != currDir->end()) + if (FileIter != il->end()) { - return static_cast(std::distance(currDir->begin(), FileIter)); + return static_cast(std::distance(il->begin(), FileIter)); } else { @@ -335,17 +330,17 @@ namespace PeLib * Searches through an imported file for a specific function. * @param strFilename Name of the imported file. * @param strFuncname Name of the imported function. - * @param cdDir Flag to decide if the OLDDIR or new import directory is used. + * @param newDir Flag to decide if the OLDDIR or new import directory is used. * @return ID of the imported function. **/ inline - unsigned int ImportDirectory::getFunctionIndex(const std::string& strFilename, const std::string& strFuncname, currdir cdDir) const + unsigned int ImportDirectory::getFunctionIndex(const std::string& strFilename, const std::string& strFuncname, bool newDir) const { - unsigned int uiFile = getFileIndex(strFilename, cdDir); + unsigned int uiFile = getFileIndex(strFilename, newDir); - for (unsigned int i=0;i(getImportList(newDir).size()); } + /** + * Get the number of functions which are currently being imported from a specific file. + * @param dwFilenr Identifies which file should be checked. + * @param newDir Flag to decide if the OLDDIR or new import directory is used. + * @return Number of functions which are currently being imported from a specific file. + **/ inline - void ImportDirectory::setFunctionHint(std::uint32_t dwFilenr, std::uint32_t dwFuncnr, currdir cdDir, std::uint16_t value) + std::uint32_t ImportDirectory::getNumberOfFunctions(std::size_t dwFilenr, bool newDir) const { - if (cdDir == OLDDIR) - { - if (m_vOldiid[dwFilenr].impdesc.OriginalFirstThunk) - { - m_vOldiid[dwFilenr].originalfirstthunk[dwFuncnr].hint = value; - } - else - { - m_vOldiid[dwFilenr].firstthunk[dwFuncnr].hint = value; - } - } - else m_vNewiid[dwFilenr].originalfirstthunk[dwFuncnr].hint = value; + auto& il = getImportList(newDir); + std::uint32_t numFuncs = 0; + + if(dwFilenr < il.size()) + numFuncs = static_cast(il[dwFilenr].thunk_data.size()); + return numFuncs; } /** - * Get the number of files which are currently being imported. - * @param cdDir Flag to decide if the OLDDIR or new import directory is used. - * @return Number of files which are currently being imported. + * Retrieves the n-th import function from the m-th import directory + * @param dwFilenr Zero-based index of the imported module + * @param dwFuncnr Zero-based index of the imported function in the module above + * @param importName If this is import by name, this string is filled by the import name + * @param importHint If this is import by name, this 16-bit integer will be filled by the import hint + * @param importOrdinal If this is import by orginal, this 32-bit integer will be filled by the ordinal of the function + * @param patchRva RVA of the patched address + * @param isImportByOrdinal Set to true if this is import by ordinal + * @param newDir Flag to decide if the OLDDIR or new import directory is used. + * @return true = the indexes are in range, so an import was returned **/ inline - std::uint32_t ImportDirectory::getNumberOfFiles(currdir cdDir) const + bool ImportDirectory::getImportedFunction( + std::size_t dwFilenr, + std::size_t dwFuncnr, + std::string& importName, + std::uint16_t& importHint, + std::uint32_t& importOrdinal, + std::uint32_t& patchRva, + bool& isImportByOrdinal, + bool newDir) const { - std::size_t numFiles = (cdDir == OLDDIR) ? m_vOldiid.size() : m_vNewiid.size(); + auto& il = getImportList(newDir); + + // Range check for the number of modules + if(dwFilenr < il.size()) + { + // Range check for the number of functions + if(dwFuncnr < il[dwFilenr].thunk_data.size()) + { + if(il[dwFilenr].thunk_data[dwFuncnr].itd.Ordinal & m_ordinalMask) + { + importOrdinal = il[dwFilenr].thunk_data[dwFuncnr].itd.Ordinal & ~m_ordinalMask; + isImportByOrdinal = true; + importHint = 0; + } + else + { + importHint = il[dwFilenr].thunk_data[dwFuncnr].hint; + isImportByOrdinal = false; + importOrdinal = 0; + } + + // Function name may be present even if import by ordinal + // (auto-retrieved on well-known ordinals, e.g. ws2_32.dll) + importName = il[dwFilenr].thunk_data[dwFuncnr].fname; + patchRva = il[dwFilenr].thunk_data[dwFuncnr].patchRva; + return true; + } + } - return static_cast(numFiles); + // Out of range + return false; } /** - * Get the number of functions which are currently being imported from a specific file. + * Get the hint of an imported function. * @param dwFilenr Identifies which file should be checked. - * @param cdDir Flag to decide if the OLDDIR or new import directory is used. - * @return Number of functions which are currently being imported from a specific file. + * @param dwFuncnr Identifies which function should be checked. + * @param newDir Flag to decide if the OLDDIR or new import directory is used. + * @return Hint of an imported function. **/ inline - std::uint32_t ImportDirectory::getNumberOfFunctions(std::uint32_t dwFilenr, currdir cdDir) const + std::uint16_t ImportDirectory::getFunctionHint(std::uint32_t dwFilenr, std::uint32_t dwFuncnr, bool newDir) const { - if (cdDir == OLDDIR) return static_cast(m_vOldiid[dwFilenr].firstthunk.size()); - else return static_cast(m_vNewiid[dwFilenr].firstthunk.size()); - } + auto& il = getImportList(newDir); + std::uint16_t hint = 0; - inline bool isInvalidOrdinal(std::uint64_t ordinal, std::uint64_t ordinalMask, std::uint64_t sizeOfImage) - { - // Check for invalid name - if((ordinal & ordinalMask) == 0) + if(dwFilenr < il.size() && dwFuncnr < il[dwFilenr].thunk_data.size()) { - // Any name RVA that goes out of image is considered invalid - if(ordinal >= sizeOfImage) - { - return true; - } + hint = il[dwFilenr].thunk_data[dwFuncnr].hint; } - else + + return hint; + } + + inline + void ImportDirectory::setFunctionHint(std::uint32_t dwFilenr, std::uint32_t dwFuncnr, bool newDir, std::uint16_t value) + { + auto& il = getImportList(newDir); + + if(dwFilenr < il.size() && dwFuncnr < il[dwFilenr].thunk_data.size()) { - // Mask out the ordinal bit. Then, any ordinal must not be larger than 0xFFFF - ordinal = ordinal & ~ordinalMask; - return (ordinal >> 0x10) != 0; + il[dwFilenr].thunk_data[dwFuncnr].hint = value; } - - return false; } /** @@ -588,9 +573,9 @@ namespace PeLib { std::uint64_t OrdinalMask = imageLoader.getOrdinalMask(); std::uint32_t SizeOfImage = imageLoader.getSizeOfImage(); - std::uint32_t uiIndex; std::uint32_t rvaBegin = imageLoader.getDataDirRva(PELIB_IMAGE_DIRECTORY_ENTRY_IMPORT); std::uint32_t rva = rvaBegin; + std::uint32_t uiIndex; setPointerSize(imageLoader.getPointerSize()); m_ldrError = LDR_ERROR_NONE; @@ -605,9 +590,10 @@ namespace PeLib // For tracking unique imported DLLs std::vector vOldIidCurr; std::unordered_map uniqueDllList; + std::set seenOffsets; std::uint32_t uiDescCounter = 0; - // Read and store all descriptors + // Read and store all descriptors. Each descriptor corresponds to one imported DLL name. for (;;) { PELIB_IMAGE_IMPORT_DIRECTORY iidCurr; @@ -686,24 +672,34 @@ namespace PeLib // Space occupied by import descriptors m_occupiedAddresses.emplace_back(rvaBegin, rva); - // OriginalFirstThunk - ILT + // Read the import entries (functions) for each import descriptor. Read both thunks at once for(std::size_t i = 0; i < vOldIidCurr.size(); i++) { - // OriginalFirstThunk is only valid when pointing within the image, excluding headers - if(!hasValidOriginalFirstThunk(vOldIidCurr[i].impdesc, imageLoader)) + // This reflects the check in the Windows loader (LdrpSnapIAT) + // "If the OriginalFirstThunk field does not point inside the image, then ignore + // it. This is will detect bogus Borland Linker 2.25 images that did not fill + // this field in." + std::uint32_t originalThunk = hasValidOriginalFirstThunk(vOldIidCurr[i].impdesc, imageLoader) ? + vOldIidCurr[i].impdesc.OriginalFirstThunk : + vOldIidCurr[i].impdesc.FirstThunk; + std::uint32_t firstThunk = vOldIidCurr[i].impdesc.FirstThunk; + + // Don't allow multiple import descriptors to take data from the same RVA + if(seenOffsets.count(firstThunk)) continue; - std::uint32_t thunkRva = vOldIidCurr[i].impdesc.OriginalFirstThunk; - - PELIB_THUNK_DATA tdCurr; + seenOffsets.insert(firstThunk); - for(uiIndex = 0; ; uiIndex++) + // Parse individual imports + for(uiIndex = 0;; uiIndex++) { + PELIB_THUNK_DATA thunkData; + // Read single value (32-bit or 64-bit) from the thunk chain - if(!imageLoader.readPointer(thunkRva, tdCurr.itd.Ordinal)) + if(!imageLoader.readPointer(originalThunk, thunkData.itd.Ordinal)) break; // Are we at the end of the list? - if (tdCurr.itd.Ordinal == 0) + if(thunkData.itd.Ordinal == 0) break; // Did we exceed the count of imported functions? @@ -713,123 +709,66 @@ namespace PeLib break; } - // Check samples that have import name out of the image - // Sample: CCE461B6EB23728BA3B8A97B9BE84C0FB9175DB31B9949E64144198AB3F702CE - // Import by ordinal must be lower-word only; any ordinal that is greater than 0xFFFF is invalid. - // Sample: 7CE5BB5CA99B3570514AF03782545D41213A77A0F93D4AAC8269823A8D3A58EF - if(isInvalidOrdinal(tdCurr.itd.Ordinal, OrdinalMask, SizeOfImage)) - { - setLoaderError(LDR_ERROR_IMPDIR_NAME_RVA_INVALID); - break; - } - - // Insert ordinal to the list - vOldIidCurr[i].originalfirstthunk.push_back(tdCurr); - thunkRva += m_thunkSize; - } - - // Space occupied by OriginalFirstThunks - // -1 because we need open interval - if (vOldIidCurr[i].impdesc.OriginalFirstThunk < thunkRva) - m_occupiedAddresses.emplace_back(vOldIidCurr[i].impdesc.OriginalFirstThunk, thunkRva - 1); - } + // Set the patch RVA + thunkData.patchRva = firstThunk; - // FirstThunk - IAT - std::set seenOffsets; - for (std::size_t i = 0; i < vOldIidCurr.size(); i++) - { - std::uint32_t thunkRva = vOldIidCurr[i].impdesc.FirstThunk; - bool hasValidIlt = hasValidOriginalFirstThunk(vOldIidCurr[i].impdesc, imageLoader); - - if (thunkRva >= imageLoader.getSizeOfImage()) - { - setLoaderError(LDR_ERROR_IMPDIR_THUNK_RVA_INVALID); - return ERROR_INVALID_FILE; - } - if (seenOffsets.count(thunkRva)) - { - continue; - } - seenOffsets.insert(thunkRva); - PELIB_THUNK_DATA tdCurr; - - for(uiIndex = 0; ; uiIndex++) - { - if ((thunkRva + m_thunkSize) > SizeOfImage) + // Is it an import by name? + if((thunkData.itd.Ordinal & OrdinalMask) == 0) { - setLoaderError(LDR_ERROR_IMPDIR_THUNK_RVA_INVALID); - return ERROR_INVALID_FILE; - } - - // Read the import thunk. Make sure it's initialized in case the file read fails - tdCurr.itd.Ordinal = 0; - imageLoader.readPointer(thunkRva, tdCurr.itd.Ordinal); - thunkRva += m_thunkSize; - - // Are we at the end of the list? - if (tdCurr.itd.Ordinal == 0) - break; - - // Did the number of imported functions exceede maximum? - if(uiIndex >= PELIB_MAX_IMPORTED_FUNCTIONS) - { - setLoaderError(LDR_ERROR_IMPDIR_IMPORT_COUNT_EXCEEDED); - return ERROR_INVALID_FILE; - } + // Check samples that have import name out of the image + // Sample: CCE461B6EB23728BA3B8A97B9BE84C0FB9175DB31B9949E64144198AB3F702CE + if(thunkData.itd.Ordinal < imageLoader.getSizeOfImage()) + { + // Read the import hint + if(imageLoader.readImage(&thunkData.hint, thunkData.itd.Ordinal, sizeof(std::uint16_t)) != sizeof(std::uint16_t)) + { + setLoaderError(LDR_ERROR_IMPDIR_THUNK_RVA_INVALID); + thunkData.hint = 0; + } - // Check samples that have import name out of the image - // Sample: CCE461B6EB23728BA3B8A97B9BE84C0FB9175DB31B9949E64144198AB3F702CE - //if(isInvalidOrdinal(tdCurr.itd.Ordinal, OrdinalMask, SizeOfImage)) - // break; + // Read the import name + imageLoader.readString(thunkData.fname, thunkData.itd.Ordinal + sizeof(std::uint16_t), IMPORT_SYMBOL_MAX_LENGTH); - vOldIidCurr[i].firstthunk.push_back(tdCurr); + // Space occupied by names + // +1 for null terminator + // If the end address is even, we need to align it by 2, so next name always starts at even address + m_occupiedAddresses.emplace_back( + static_cast(thunkData.itd.Ordinal), + static_cast(thunkData.itd.Ordinal + sizeof(thunkData.hint) + thunkData.fname.length() + 1) + ); - // If this import descriptor has valid ILT, then size of IAT is determined from the size of ILT - if (hasValidIlt && vOldIidCurr[i].originalfirstthunk.size() == vOldIidCurr[i].firstthunk.size()) - { - // We need to move this offset in this case because otherwise we would calculate the occupied addresses wrongly - thunkRva += m_thunkSize; - break; + // Align the end by 2 + m_occupiedAddresses.back().second = (m_occupiedAddresses.back().second + 1) & 0xFFFFFFFFE; + } + else + { + setLoaderError(LDR_ERROR_IMPDIR_THUNK_RVA_INVALID); + } } - } - - // Space occupied by FirstThunks - // -1 because we need open interval - if (vOldIidCurr[i].impdesc.FirstThunk < thunkRva) - m_occupiedAddresses.emplace_back(vOldIidCurr[i].impdesc.FirstThunk, thunkRva - 1); - } - - // Names - for (unsigned int i=0;i & thunkVector = hasValidOriginalFirstThunk(vOldIidCurr[i].impdesc, imageLoader) ? - vOldIidCurr[i].originalfirstthunk : - vOldIidCurr[i].firstthunk; - for (auto & thunkData : thunkVector) - { - if (thunkData.itd.Ordinal & OrdinalMask) + else { - thunkData.hint = 0; - continue; - } + // Mask out the ordinal bit. Then, any ordinal must not be larger than 0xFFFF + std::uint32_t ordinal = thunkData.itd.Ordinal & ~OrdinalMask; - if(imageLoader.readImage(&thunkData.hint, thunkData.itd.Ordinal, sizeof(std::uint16_t)) != sizeof(std::uint16_t)) - { - setLoaderError(LDR_ERROR_IMPDIR_THUNK_RVA_INVALID); - return ERROR_INVALID_FILE; + // Import by ordinal must be lower-word only; any ordinal that is greater than 0xFFFF is invalid. + // Sample: 7CE5BB5CA99B3570514AF03782545D41213A77A0F93D4AAC8269823A8D3A58EF + if((ordinal >> 0x10) == 0) + { + thunkData.fname = retdec::utils::ordLookUp(vOldIidCurr[i].name, ordinal, false); + thunkData.hint = 0; + } + else + { + setLoaderError(LDR_ERROR_IMPDIR_THUNK_RVA_INVALID); + } } - imageLoader.readString(thunkData.fname, thunkData.itd.Ordinal + sizeof(std::uint16_t), IMPORT_SYMBOL_MAX_LENGTH); + // Insert the thunk into the import descriptor + vOldIidCurr[i].thunk_data.push_back(thunkData); - // Space occupied by names - // +1 for null terminator - // If the end address is even, we need to align it by 2, so next name always starts at even address - m_occupiedAddresses.emplace_back( - static_cast(thunkData.itd.Ordinal), - static_cast(thunkData.itd.Ordinal + sizeof(thunkData.hint) + thunkData.fname.length() + 1) - ); - if (!(m_occupiedAddresses.back().second & 1)) - m_occupiedAddresses.back().second += 1; + // Increment both pointers + originalThunk += imageLoader.getPointerSize(); + firstThunk += imageLoader.getPointerSize(); } } @@ -869,18 +808,18 @@ namespace PeLib for (unsigned int i=0;i(m_vNewiid[i].name.size()) + 1; - uiSizeofoft += (static_cast(m_vNewiid[i].originalfirstthunk.size())+1) * m_thunkSize; + uiSizeofoft += (static_cast(m_vNewiid[i].thunk_data.size())+1) * m_thunkSize; - for(unsigned int j=0;j(m_vNewiid[i].originalfirstthunk[j].fname.size()) + 3); + uiSizeoffuncnames += (static_cast(m_vNewiid[i].thunk_data[j].fname.size()) + 3); } } // for (unsigned int i=0;i(m_vNewiid[i].originalfirstthunk.size())+1) * PELIB_IMAGE_THUNK_DATA::size(); +// uiSizeofoft += (static_cast(m_vNewiid[i].thunk_data.size())+1) * PELIB_IMAGE_THUNK_DATA::size(); // } OutputBuffer obBuffer(vBuffer); @@ -903,7 +842,7 @@ namespace PeLib for (unsigned int j=1;j<=i;j++) { - dwPoft += (static_cast(m_vNewiid[j-1].originalfirstthunk.size()) + 1) * m_thunkSize; + dwPoft += (static_cast(m_vNewiid[j-1].thunk_data.size()) + 1) * m_thunkSize; } obBuffer << (fixEntries ? dwPoft : m_vNewiid[i].impdesc.OriginalFirstThunk); @@ -934,21 +873,21 @@ namespace PeLib // Rebuild original first thunk for (std::size_t i = 0;i(m_vNewiid[i].originalfirstthunk[j].fname.size()) + 3; + uiPfunc += static_cast(m_vNewiid[i].thunk_data[j].fname.size()) + 3; } writePointer(obBuffer, 0); //obBuffer << static_cast(0); @@ -963,10 +902,10 @@ namespace PeLib // Write function names into directory for (unsigned int i=0;i(m_vNewiid[i].originalfirstthunk[j].fname.size()) + 1); + obBuffer << m_vNewiid[i].thunk_data[j].hint; + obBuffer.add(m_vNewiid[i].thunk_data[j].fname.c_str(), static_cast(m_vNewiid[i].thunk_data[j].fname.size()) + 1); } } } @@ -1008,16 +947,16 @@ namespace PeLib { if (isEqualNc(viPos->name, strFilename)) { - unsigned int oldSize = static_cast(viPos->originalfirstthunk.size()); - viPos->originalfirstthunk.erase( + unsigned int oldSize = static_cast(viPos->thunk_data.size()); + viPos->thunk_data.erase( std::remove_if( - viPos->originalfirstthunk.begin(), - viPos->originalfirstthunk.end(), + viPos->thunk_data.begin(), + viPos->thunk_data.end(), [&](const auto& i) { return i.equalFunctionName(strFuncname); } ), - viPos->originalfirstthunk.end() + viPos->thunk_data.end() ); - if (viPos->originalfirstthunk.size() != oldSize) notFound = 0; + if (viPos->thunk_data.size() != oldSize) notFound = 0; } ++viPos; } @@ -1040,16 +979,16 @@ namespace PeLib { if (isEqualNc(viPos->name, strFilename)) { - unsigned int oldSize = static_cast(viPos->originalfirstthunk.size()); - viPos->originalfirstthunk.erase( + unsigned int oldSize = static_cast(viPos->thunk_data.size()); + viPos->thunk_data.erase( std::remove_if( - viPos->originalfirstthunk.begin(), - viPos->originalfirstthunk.end(), + viPos->thunk_data.begin(), + viPos->thunk_data.end(), [&](const auto& i) { return i.equalHint(wHint); } ), - viPos->originalfirstthunk.end() + viPos->thunk_data.end() ); - if (viPos->originalfirstthunk.size() != oldSize) notFound = 0; + if (viPos->thunk_data.size() != oldSize) notFound = 0; } ++viPos; } @@ -1118,274 +1057,167 @@ namespace PeLib /** * @param strFilename Name of the imported file. - * @param cdDir Flag to decide if the OLDDIR or new import directory is used. + * @param newDir Flag to decide if the OLDDIR or new import directory is used. * @return FirstThunk value of an imported file. **/ inline - std::uint32_t ImportDirectory::getFirstThunk(const std::string& strFilename, currdir cdDir) const + std::uint32_t ImportDirectory::getFirstThunk(const std::string& strFilename, bool newDir) const { - if (cdDir == OLDDIR) - { - return m_vOldiid[getFileIndex(strFilename, cdDir)].impdesc.FirstThunk; - } - else - { - return m_vNewiid[getFileIndex(strFilename, cdDir)].impdesc.FirstThunk; - } + return getImportList(newDir)[getFileIndex(strFilename, newDir)].impdesc.FirstThunk; } /** * @param strFilename Name of the imported file. - * @param cdDir Flag to decide if the OLDDIR or new import directory is used. + * @param newDir Flag to decide if the OLDDIR or new import directory is used. * @return OriginalFirstThunk value of an imported file. **/ inline - std::uint32_t ImportDirectory::getOriginalFirstThunk(const std::string& strFilename, currdir cdDir) const + std::uint32_t ImportDirectory::getOriginalFirstThunk(const std::string& strFilename, bool newDir) const { - if (cdDir == OLDDIR) - { - return m_vOldiid[getFileIndex(strFilename, cdDir)].impdesc.OriginalFirstThunk; - } - else - { - return m_vNewiid[getFileIndex(strFilename, cdDir)].impdesc.OriginalFirstThunk; - } + return getImportList(newDir)[getFileIndex(strFilename, newDir)].impdesc.OriginalFirstThunk; } /** * @param strFilename Name of the imported file. - * @param cdDir Flag to decide if the OLDDIR or new import directory is used. + * @param newDir Flag to decide if the OLDDIR or new import directory is used. * @return ForwarderChain value of an imported file. **/ inline - std::uint32_t ImportDirectory::getForwarderChain(const std::string& strFilename, currdir cdDir) const + std::uint32_t ImportDirectory::getForwarderChain(const std::string& strFilename, bool newDir) const { - if (cdDir == OLDDIR) - { - return m_vOldiid[getFileIndex(strFilename, cdDir)].impdesc.ForwarderChain; - } - else - { - return m_vNewiid[getFileIndex(strFilename, cdDir)].impdesc.ForwarderChain; - } + return getImportList(newDir)[getFileIndex(strFilename, newDir)].impdesc.ForwarderChain; } /** * @param strFilename Name of the imported file. - * @param cdDir Flag to decide if the OLDDIR or new import directory is used. + * @param newDir Flag to decide if the OLDDIR or new import directory is used. * @return TimeDateStamp value of an imported file. **/ inline - std::uint32_t ImportDirectory::getTimeDateStamp(const std::string& strFilename, currdir cdDir) const + std::uint32_t ImportDirectory::getTimeDateStamp(const std::string& strFilename, bool newDir) const { - if (cdDir == OLDDIR) - { - return m_vOldiid[getFileIndex(strFilename, cdDir)].impdesc.TimeDateStamp; - } - else - { - return m_vNewiid[getFileIndex(strFilename, cdDir)].impdesc.TimeDateStamp; - } + return getImportList(newDir)[getFileIndex(strFilename, newDir)].impdesc.TimeDateStamp; } inline - std::uint32_t ImportDirectory::getRvaOfName(const std::string& strFilename, currdir cdDir) const + std::uint32_t ImportDirectory::getRvaOfName(const std::string& strFilename, bool newDir) const { - if (cdDir == OLDDIR) - { - return m_vOldiid[getFileIndex(strFilename, cdDir)].impdesc.Name; - } - else - { - return m_vNewiid[getFileIndex(strFilename, cdDir)].impdesc.Name; - } + return getImportList(newDir)[getFileIndex(strFilename, newDir)].impdesc.Name; } /** * @param dwFilenr Name of the imported file. - * @param cdDir Flag to decide if the OLDDIR or new import directory is used. + * @param newDir Flag to decide if the OLDDIR or new import directory is used. * @return FirstThunk value of an imported file. **/ inline - std::uint32_t ImportDirectory::getFirstThunk(std::uint32_t dwFilenr, currdir cdDir) const + std::uint32_t ImportDirectory::getFirstThunk(std::uint32_t dwFilenr, bool newDir) const { - if (cdDir == OLDDIR) - { - return m_vOldiid[dwFilenr].impdesc.FirstThunk; - } - else - { - return m_vNewiid[dwFilenr].impdesc.FirstThunk; - } + return getImportList(newDir)[dwFilenr].impdesc.FirstThunk; } inline - void ImportDirectory::setFirstThunk(std::uint32_t dwFilenr, currdir cdDir, std::uint32_t value) + void ImportDirectory::setFirstThunk(std::uint32_t dwFilenr, bool newDir, std::uint32_t value) { - if (cdDir == OLDDIR) - { - m_vOldiid[dwFilenr].impdesc.FirstThunk = value; - } - else - { - m_vNewiid[dwFilenr].impdesc.FirstThunk = value; - } + getImportList(newDir)[dwFilenr].impdesc.FirstThunk = value; } /** * @param dwFilenr Name of the imported file. - * @param cdDir Flag to decide if the OLDDIR or new import directory is used. + * @param newDir Flag to decide if the OLDDIR or new import directory is used. * @return OriginalFirstThunk value of an imported file. **/ inline - std::uint32_t ImportDirectory::getOriginalFirstThunk(std::uint32_t dwFilenr, currdir cdDir) const + std::uint32_t ImportDirectory::getOriginalFirstThunk(std::uint32_t dwFilenr, bool newDir) const { - if (cdDir == OLDDIR) - { - return m_vOldiid[dwFilenr].impdesc.OriginalFirstThunk; - } - else - { - return m_vNewiid[dwFilenr].impdesc.OriginalFirstThunk; - } + return getImportList(newDir)[dwFilenr].impdesc.OriginalFirstThunk; } inline - void ImportDirectory::setOriginalFirstThunk(std::uint32_t dwFilenr, currdir cdDir, std::uint32_t value) + void ImportDirectory::setOriginalFirstThunk(std::uint32_t dwFilenr, bool newDir, std::uint32_t value) { - if (cdDir == OLDDIR) - { - m_vOldiid[dwFilenr].impdesc.OriginalFirstThunk = value; - } - else - { - m_vNewiid[dwFilenr].impdesc.OriginalFirstThunk = value; - } + getImportList(newDir)[dwFilenr].impdesc.OriginalFirstThunk = value; } /** * @param dwFilenr Name of the imported file. - * @param cdDir Flag to decide if the OLDDIR or new import directory is used. + * @param newDir Flag to decide if the OLDDIR or new import directory is used. * @return ForwarderChain value of an imported file. **/ inline - std::uint32_t ImportDirectory::getForwarderChain(std::uint32_t dwFilenr, currdir cdDir) const + std::uint32_t ImportDirectory::getForwarderChain(std::uint32_t dwFilenr, bool newDir) const { - if (cdDir == OLDDIR) - { - return m_vOldiid[dwFilenr].impdesc.ForwarderChain; - } - else - { - return m_vNewiid[dwFilenr].impdesc.ForwarderChain; - } + return getImportList(newDir)[dwFilenr].impdesc.ForwarderChain; } inline - void ImportDirectory::setForwarderChain(std::uint32_t dwFilenr, currdir cdDir, std::uint32_t value) + void ImportDirectory::setForwarderChain(std::uint32_t dwFilenr, bool newDir, std::uint32_t value) { - if (cdDir == OLDDIR) - { - m_vOldiid[dwFilenr].impdesc.ForwarderChain = value; - } - else - { - m_vNewiid[dwFilenr].impdesc.ForwarderChain = value; - } + getImportList(newDir)[dwFilenr].impdesc.ForwarderChain = value; } /** * @param dwFilenr Name of the imported file. - * @param cdDir Flag to decide if the OLDDIR or new import directory is used. + * @param newDir Flag to decide if the OLDDIR or new import directory is used. * @return TimeDateStamp value of an imported file. **/ inline - std::uint32_t ImportDirectory::getTimeDateStamp(std::uint32_t dwFilenr, currdir cdDir) const + std::uint32_t ImportDirectory::getTimeDateStamp(std::uint32_t dwFilenr, bool newDir) const { - if (cdDir == OLDDIR) - { - return m_vOldiid[dwFilenr].impdesc.TimeDateStamp; - } - else - { - return m_vNewiid[dwFilenr].impdesc.TimeDateStamp; - } + return getImportList(newDir)[dwFilenr].impdesc.TimeDateStamp; } inline - void ImportDirectory::setTimeDateStamp(std::uint32_t dwFilenr, currdir cdDir, std::uint32_t value) + void ImportDirectory::setTimeDateStamp(std::uint32_t dwFilenr, bool newDir, std::uint32_t value) { - if (cdDir == OLDDIR) - { - m_vOldiid[dwFilenr].impdesc.TimeDateStamp = value; - } - else - { - m_vNewiid[dwFilenr].impdesc.TimeDateStamp = value; - } + getImportList(newDir)[dwFilenr].impdesc.TimeDateStamp = value; } inline - std::uint32_t ImportDirectory::getRvaOfName(std::uint32_t dwFilenr, currdir cdDir) const + std::uint32_t ImportDirectory::getRvaOfName(std::uint32_t dwFilenr, bool newDir) const { - if (cdDir == OLDDIR) - { - return m_vOldiid[dwFilenr].impdesc.Name; - } - else - { - return m_vNewiid[dwFilenr].impdesc.Name; - } + return getImportList(newDir)[dwFilenr].impdesc.Name; } inline - void ImportDirectory::setRvaOfName(std::uint32_t dwFilenr, currdir cdDir, std::uint32_t value) + void ImportDirectory::setRvaOfName(std::uint32_t dwFilenr, bool newDir, std::uint32_t value) { - if (cdDir == OLDDIR) - { - m_vOldiid[dwFilenr].impdesc.Name = value; - } - else - { - m_vNewiid[dwFilenr].impdesc.Name = value; - } + getImportList(newDir)[dwFilenr].impdesc.Name = value; } /** * @param dwFilenr ID of the imported file. * @param dwFuncnr ID of the imported function. - * @param cdDir Flag to decide if the OLDDIR or new import directory is used. + * @param newDir Flag to decide if the OLDDIR or new import directory is used. * @return FirstThunk value of an imported function. **/ inline - std::uint32_t ImportDirectory::getFirstThunk(std::uint32_t dwFilenr, std::uint32_t dwFuncnr, currdir cdDir) const + std::uint32_t ImportDirectory::getFirstThunk(std::uint32_t dwFilenr, std::uint32_t dwFuncnr, bool newDir) const { - if (cdDir == OLDDIR) return m_vOldiid[dwFilenr].firstthunk[dwFuncnr].itd.Ordinal; - else return m_vNewiid[dwFilenr].firstthunk[dwFuncnr].itd.Ordinal; + return getImportList(newDir)[dwFilenr].thunk_data[dwFuncnr].itd.Ordinal; } inline - void ImportDirectory::setFirstThunk(std::uint32_t dwFilenr, std::uint32_t dwFuncnr, currdir cdDir, std::uint32_t value) + void ImportDirectory::setFirstThunk(std::uint32_t dwFilenr, std::uint32_t dwFuncnr, bool newDir, std::uint32_t value) { - if (cdDir == OLDDIR) m_vOldiid[dwFilenr].firstthunk[dwFuncnr].itd.Ordinal = value; - else m_vNewiid[dwFilenr].firstthunk[dwFuncnr].itd.Ordinal = value; + getImportList(newDir)[dwFilenr].thunk_data[dwFuncnr].itd.Ordinal = value; } /** * @param dwFilenr ID of the imported file. * @param dwFuncnr ID of the imported function. - * @param cdDir Flag to decide if the OLDDIR or new import directory is used. + * @param newDir Flag to decide if the OLDDIR or new import directory is used. * @return OriginalFirstThunk value of an imported function. **/ inline - std::uint32_t ImportDirectory::getOriginalFirstThunk(std::uint32_t dwFilenr, std::uint32_t dwFuncnr, currdir cdDir) const + std::uint32_t ImportDirectory::getOriginalFirstThunk(std::uint32_t dwFilenr, std::uint32_t dwFuncnr, bool newDir) const { - if (cdDir == OLDDIR) + if (newDir == false) { - if (dwFuncnr < m_vOldiid[dwFilenr].originalfirstthunk.size()) + if (dwFuncnr < m_vOldiid[dwFilenr].thunk_data.size()) { - return m_vOldiid[dwFilenr].originalfirstthunk[dwFuncnr].itd.Ordinal; + return m_vOldiid[dwFilenr].thunk_data[dwFuncnr].itd.Ordinal; } else { @@ -1394,15 +1226,14 @@ namespace PeLib } else { - return m_vNewiid[dwFilenr].originalfirstthunk[dwFuncnr].itd.Ordinal; + return m_vNewiid[dwFilenr].thunk_data[dwFuncnr].itd.Ordinal; } } inline - void ImportDirectory::setOriginalFirstThunk(std::uint32_t dwFilenr, std::uint32_t dwFuncnr, currdir cdDir, std::uint32_t value) + void ImportDirectory::setOriginalFirstThunk(std::uint32_t dwFilenr, std::uint32_t dwFuncnr, bool newDir, std::uint32_t value) { - if (cdDir == OLDDIR) m_vOldiid[dwFilenr].originalfirstthunk[dwFuncnr].itd.Ordinal = value; - else m_vNewiid[dwFilenr].originalfirstthunk[dwFuncnr].itd.Ordinal = value; + getImportList(newDir)[dwFilenr].thunk_data[dwFuncnr].itd.Ordinal = value; } inline @@ -1411,6 +1242,17 @@ namespace PeLib return m_occupiedAddresses; } + inline const std::vector& ImportDirectory::getImportList(bool newDir) const + { + return (newDir == false) ? m_vOldiid : m_vNewiid; + } + + inline std::vector& ImportDirectory::getImportList(bool newDir) + { + return (newDir == false) ? m_vOldiid : m_vNewiid; + } + + } // namespace PeLib #endif diff --git a/include/retdec/pelib/PeLibAux.h b/include/retdec/pelib/PeLibAux.h index 395d8dbe7..880f8e0f0 100644 --- a/include/retdec/pelib/PeLibAux.h +++ b/include/retdec/pelib/PeLibAux.h @@ -1063,13 +1063,16 @@ namespace PeLib { /// The IMAGE_THUNK_DATA struct of an imported function. PELIB_IMAGE_THUNK_DATA itd; - /// The hint of an imported function. - std::uint16_t hint; /// The function name of an imported function. std::string fname; + /// The RVA of the patched address (from the FirstThunk) + std::uint32_t patchRva; + /// The hint of an imported function (only if imported by name) + std::uint16_t hint; PELIB_THUNK_DATA() { + patchRva = 0; hint = 0; } @@ -1110,16 +1113,16 @@ namespace PeLib PELIB_IMAGE_IMPORT_DESCRIPTOR impdesc; /// The name of an imported DLL. std::string name; - /// All original first thunk values of an imported DLL. - std::vector originalfirstthunk; - /// All first thunk value of an imported DLL. - std::vector firstthunk; + /// The list of functions imported from the DLL + //std::vector originalfirstthunk; + //std::vector firstthunk; + std::vector thunk_data; inline std::uint32_t calculateSize(std::uint32_t pointerSize) const { std::uint32_t totalSize = sizeof(PELIB_IMAGE_IMPORT_DESCRIPTOR) + name.size() + 1; // descriptor + dllname - for(const auto & element : originalfirstthunk) + for(const auto & element : thunk_data) totalSize += element.calculateSize(pointerSize); return totalSize + pointerSize; // Add zero-termination } diff --git a/include/retdec/utils/ord_lookup.h b/include/retdec/utils/ord_lookup.h new file mode 100644 index 000000000..c43bcf705 --- /dev/null +++ b/include/retdec/utils/ord_lookup.h @@ -0,0 +1,18 @@ +/** + * @file include/retdec/utils/ord_lookup.h + * @brief Converts well-known ordinals to function names + * @copyright (c) 2017 Avast Software, licensed under the MIT license + */ + +#ifndef RETDEC_UTILS_ORD_LOOKUP_H +#define RETDEC_UTILS_ORD_LOOKUP_H + +namespace retdec { +namespace utils { + +std::string ordLookUp(const std::string& libName, const std::size_t& ordNum, bool forceNameFromOrdinal); + +} // namespace utils +} // namespace retdec + +#endif diff --git a/src/fileformat/types/import_table/import_table.cpp b/src/fileformat/types/import_table/import_table.cpp index 6fd31ed10..f97098888 100644 --- a/src/fileformat/types/import_table/import_table.cpp +++ b/src/fileformat/types/import_table/import_table.cpp @@ -7,6 +7,7 @@ #include "retdec/utils/container.h" #include "retdec/utils/conversion.h" #include "retdec/utils/string.h" +#include "retdec/utils/ord_lookup.h" #include "retdec/fileformat/utils/crypto.h" #include "retdec/pelib/PeLibAux.h" #include "retdec/fileformat/types/import_table/import_table.h" @@ -14,558 +15,6 @@ using namespace retdec::utils; -namespace { - -// Ordinal-name LUT for YARA compatible import hash computation. -// This must stay compatible with YARA's ord_lookup function - -std::map winsock32Map = -{ - {1, "accept"}, - {2, "bind"}, - {3, "closesocket"}, - {4, "connect"}, - {5, "getpeername"}, - {6, "getsockname"}, - {7, "getsockopt"}, - {8, "htonl"}, - {9, "htons"}, - {10, "ioctlsocket"}, - {11, "inet_addr"}, - {12, "inet_ntoa"}, - {13, "listen"}, - {14, "ntohl"}, - {15, "ntohs"}, - {16, "recv"}, - {17, "recvfrom"}, - {18, "select"}, - {19, "send"}, - {20, "sendto"}, - {21, "setsockopt"}, - {22, "shutdown"}, - {23, "socket"}, - {24, "GetAddrInfoW"}, - {25, "GetNameInfoW"}, - {26, "WSApSetPostRoutine"}, - {27, "FreeAddrInfoW"}, - {28, "WPUCompleteOverlappedRequest"}, - {29, "WSAAccept"}, - {30, "WSAAddressToStringA"}, - {31, "WSAAddressToStringW"}, - {32, "WSACloseEvent"}, - {33, "WSAConnect"}, - {34, "WSACreateEvent"}, - {35, "WSADuplicateSocketA"}, - {36, "WSADuplicateSocketW"}, - {37, "WSAEnumNameSpaceProvidersA"}, - {38, "WSAEnumNameSpaceProvidersW"}, - {39, "WSAEnumNetworkEvents"}, - {40, "WSAEnumProtocolsA"}, - {41, "WSAEnumProtocolsW"}, - {42, "WSAEventSelect"}, - {43, "WSAGetOverlappedResult"}, - {44, "WSAGetQOSByName"}, - {45, "WSAGetServiceClassInfoA"}, - {46, "WSAGetServiceClassInfoW"}, - {47, "WSAGetServiceClassNameByClassIdA"}, - {48, "WSAGetServiceClassNameByClassIdW"}, - {49, "WSAHtonl"}, - {50, "WSAHtons"}, - {51, "gethostbyaddr"}, - {52, "gethostbyname"}, - {53, "getprotobyname"}, - {54, "getprotobynumber"}, - {55, "getservbyname"}, - {56, "getservbyport"}, - {57, "gethostname"}, - {58, "WSAInstallServiceClassA"}, - {59, "WSAInstallServiceClassW"}, - {60, "WSAIoctl"}, - {61, "WSAJoinLeaf"}, - {62, "WSALookupServiceBeginA"}, - {63, "WSALookupServiceBeginW"}, - {64, "WSALookupServiceEnd"}, - {65, "WSALookupServiceNextA"}, - {66, "WSALookupServiceNextW"}, - {67, "WSANSPIoctl"}, - {68, "WSANtohl"}, - {69, "WSANtohs"}, - {70, "WSAProviderConfigChange"}, - {71, "WSARecv"}, - {72, "WSARecvDisconnect"}, - {73, "WSARecvFrom"}, - {74, "WSARemoveServiceClass"}, - {75, "WSAResetEvent"}, - {76, "WSASend"}, - {77, "WSASendDisconnect"}, - {78, "WSASendTo"}, - {79, "WSASetEvent"}, - {80, "WSASetServiceA"}, - {81, "WSASetServiceW"}, - {82, "WSASocketA"}, - {83, "WSASocketW"}, - {84, "WSAStringToAddressA"}, - {85, "WSAStringToAddressW"}, - {86, "WSAWaitForMultipleEvents"}, - {87, "WSCDeinstallProvider"}, - {88, "WSCEnableNSProvider"}, - {89, "WSCEnumProtocols"}, - {90, "WSCGetProviderPath"}, - {91, "WSCInstallNameSpace"}, - {92, "WSCInstallProvider"}, - {93, "WSCUnInstallNameSpace"}, - {94, "WSCUpdateProvider"}, - {95, "WSCWriteNameSpaceOrder"}, - {96, "WSCWriteProviderOrder"}, - {97, "freeaddrinfo"}, - {98, "getaddrinfo"}, - {99, "getnameinfo"}, - {101, "WSAAsyncSelect"}, - {102, "WSAAsyncGetHostByAddr"}, - {103, "WSAAsyncGetHostByName"}, - {104, "WSAAsyncGetProtoByNumber"}, - {105, "WSAAsyncGetProtoByName"}, - {106, "WSAAsyncGetServByPort"}, - {107, "WSAAsyncGetServByName"}, - {108, "WSACancelAsyncRequest"}, - {109, "WSASetBlockingHook"}, - {110, "WSAUnhookBlockingHook"}, - {111, "WSAGetLastError"}, - {112, "WSASetLastError"}, - {113, "WSACancelBlockingCall"}, - {114, "WSAIsBlocking"}, - {115, "WSAStartup"}, - {116, "WSACleanup"}, - {151, "__WSAFDIsSet"}, - {500, "WEP"} -}; - -std::map oleaut32Map = -{ - {2, "SysAllocString"}, - {3, "SysReAllocString"}, - {4, "SysAllocStringLen"}, - {5, "SysReAllocStringLen"}, - {6, "SysFreeString"}, - {7, "SysStringLen"}, - {8, "VariantInit"}, - {9, "VariantClear"}, - {10, "VariantCopy"}, - {11, "VariantCopyInd"}, - {12, "VariantChangeType"}, - {13, "VariantTimeToDosDateTime"}, - {14, "DosDateTimeToVariantTime"}, - {15, "SafeArrayCreate"}, - {16, "SafeArrayDestroy"}, - {17, "SafeArrayGetDim"}, - {18, "SafeArrayGetElemsize"}, - {19, "SafeArrayGetUBound"}, - {20, "SafeArrayGetLBound"}, - {21, "SafeArrayLock"}, - {22, "SafeArrayUnlock"}, - {23, "SafeArrayAccessData"}, - {24, "SafeArrayUnaccessData"}, - {25, "SafeArrayGetElement"}, - {26, "SafeArrayPutElement"}, - {27, "SafeArrayCopy"}, - {28, "DispGetParam"}, - {29, "DispGetIDsOfNames"}, - {30, "DispInvoke"}, - {31, "CreateDispTypeInfo"}, - {32, "CreateStdDispatch"}, - {33, "RegisterActiveObject"}, - {34, "RevokeActiveObject"}, - {35, "GetActiveObject"}, - {36, "SafeArrayAllocDescriptor"}, - {37, "SafeArrayAllocData"}, - {38, "SafeArrayDestroyDescriptor"}, - {39, "SafeArrayDestroyData"}, - {40, "SafeArrayRedim"}, - {41, "SafeArrayAllocDescriptorEx"}, - {42, "SafeArrayCreateEx"}, - {43, "SafeArrayCreateVectorEx"}, - {44, "SafeArraySetRecordInfo"}, - {45, "SafeArrayGetRecordInfo"}, - {46, "VarParseNumFromStr"}, - {47, "VarNumFromParseNum"}, - {48, "VarI2FromUI1"}, - {49, "VarI2FromI4"}, - {50, "VarI2FromR4"}, - {51, "VarI2FromR8"}, - {52, "VarI2FromCy"}, - {53, "VarI2FromDate"}, - {54, "VarI2FromStr"}, - {55, "VarI2FromDisp"}, - {56, "VarI2FromBool"}, - {57, "SafeArraySetIID"}, - {58, "VarI4FromUI1"}, - {59, "VarI4FromI2"}, - {60, "VarI4FromR4"}, - {61, "VarI4FromR8"}, - {62, "VarI4FromCy"}, - {63, "VarI4FromDate"}, - {64, "VarI4FromStr"}, - {65, "VarI4FromDisp"}, - {66, "VarI4FromBool"}, - {67, "SafeArrayGetIID"}, - {68, "VarR4FromUI1"}, - {69, "VarR4FromI2"}, - {70, "VarR4FromI4"}, - {71, "VarR4FromR8"}, - {72, "VarR4FromCy"}, - {73, "VarR4FromDate"}, - {74, "VarR4FromStr"}, - {75, "VarR4FromDisp"}, - {76, "VarR4FromBool"}, - {77, "SafeArrayGetVartype"}, - {78, "VarR8FromUI1"}, - {79, "VarR8FromI2"}, - {80, "VarR8FromI4"}, - {81, "VarR8FromR4"}, - {82, "VarR8FromCy"}, - {83, "VarR8FromDate"}, - {84, "VarR8FromStr"}, - {85, "VarR8FromDisp"}, - {86, "VarR8FromBool"}, - {87, "VarFormat"}, - {88, "VarDateFromUI1"}, - {89, "VarDateFromI2"}, - {90, "VarDateFromI4"}, - {91, "VarDateFromR4"}, - {92, "VarDateFromR8"}, - {93, "VarDateFromCy"}, - {94, "VarDateFromStr"}, - {95, "VarDateFromDisp"}, - {96, "VarDateFromBool"}, - {97, "VarFormatDateTime"}, - {98, "VarCyFromUI1"}, - {99, "VarCyFromI2"}, - {100, "VarCyFromI4"}, - {101, "VarCyFromR4"}, - {102, "VarCyFromR8"}, - {103, "VarCyFromDate"}, - {104, "VarCyFromStr"}, - {105, "VarCyFromDisp"}, - {106, "VarCyFromBool"}, - {107, "VarFormatNumber"}, - {108, "VarBstrFromUI1"}, - {109, "VarBstrFromI2"}, - {110, "VarBstrFromI4"}, - {111, "VarBstrFromR4"}, - {112, "VarBstrFromR8"}, - {113, "VarBstrFromCy"}, - {114, "VarBstrFromDate"}, - {115, "VarBstrFromDisp"}, - {116, "VarBstrFromBool"}, - {117, "VarFormatPercent"}, - {118, "VarBoolFromUI1"}, - {119, "VarBoolFromI2"}, - {120, "VarBoolFromI4"}, - {121, "VarBoolFromR4"}, - {122, "VarBoolFromR8"}, - {123, "VarBoolFromDate"}, - {124, "VarBoolFromCy"}, - {125, "VarBoolFromStr"}, - {126, "VarBoolFromDisp"}, - {127, "VarFormatCurrency"}, - {128, "VarWeekdayName"}, - {129, "VarMonthName"}, - {130, "VarUI1FromI2"}, - {131, "VarUI1FromI4"}, - {132, "VarUI1FromR4"}, - {133, "VarUI1FromR8"}, - {134, "VarUI1FromCy"}, - {135, "VarUI1FromDate"}, - {136, "VarUI1FromStr"}, - {137, "VarUI1FromDisp"}, - {138, "VarUI1FromBool"}, - {139, "VarFormatFromTokens"}, - {140, "VarTokenizeFormatString"}, - {141, "VarAdd"}, - {142, "VarAnd"}, - {143, "VarDiv"}, - {144, "DllCanUnloadNow"}, - {145, "DllGetClassObject"}, - {146, "DispCallFunc"}, - {147, "VariantChangeTypeEx"}, - {148, "SafeArrayPtrOfIndex"}, - {149, "SysStringByteLen"}, - {150, "SysAllocStringByteLen"}, - {151, "DllRegisterServer"}, - {152, "VarEqv"}, - {153, "VarIdiv"}, - {154, "VarImp"}, - {155, "VarMod"}, - {156, "VarMul"}, - {157, "VarOr"}, - {158, "VarPow"}, - {159, "VarSub"}, - {160, "CreateTypeLib"}, - {161, "LoadTypeLib"}, - {162, "LoadRegTypeLib"}, - {163, "RegisterTypeLib"}, - {164, "QueryPathOfRegTypeLib"}, - {165, "LHashValOfNameSys"}, - {166, "LHashValOfNameSysA"}, - {167, "VarXor"}, - {168, "VarAbs"}, - {169, "VarFix"}, - {170, "OaBuildVersion"}, - {171, "ClearCustData"}, - {172, "VarInt"}, - {173, "VarNeg"}, - {174, "VarNot"}, - {175, "VarRound"}, - {176, "VarCmp"}, - {177, "VarDecAdd"}, - {178, "VarDecDiv"}, - {179, "VarDecMul"}, - {180, "CreateTypeLib2"}, - {181, "VarDecSub"}, - {182, "VarDecAbs"}, - {183, "LoadTypeLibEx"}, - {184, "SystemTimeToVariantTime"}, - {185, "VariantTimeToSystemTime"}, - {186, "UnRegisterTypeLib"}, - {187, "VarDecFix"}, - {188, "VarDecInt"}, - {189, "VarDecNeg"}, - {190, "VarDecFromUI1"}, - {191, "VarDecFromI2"}, - {192, "VarDecFromI4"}, - {193, "VarDecFromR4"}, - {194, "VarDecFromR8"}, - {195, "VarDecFromDate"}, - {196, "VarDecFromCy"}, - {197, "VarDecFromStr"}, - {198, "VarDecFromDisp"}, - {199, "VarDecFromBool"}, - {200, "GetErrorInfo"}, - {201, "SetErrorInfo"}, - {202, "CreateErrorInfo"}, - {203, "VarDecRound"}, - {204, "VarDecCmp"}, - {205, "VarI2FromI1"}, - {206, "VarI2FromUI2"}, - {207, "VarI2FromUI4"}, - {208, "VarI2FromDec"}, - {209, "VarI4FromI1"}, - {210, "VarI4FromUI2"}, - {211, "VarI4FromUI4"}, - {212, "VarI4FromDec"}, - {213, "VarR4FromI1"}, - {214, "VarR4FromUI2"}, - {215, "VarR4FromUI4"}, - {216, "VarR4FromDec"}, - {217, "VarR8FromI1"}, - {218, "VarR8FromUI2"}, - {219, "VarR8FromUI4"}, - {220, "VarR8FromDec"}, - {221, "VarDateFromI1"}, - {222, "VarDateFromUI2"}, - {223, "VarDateFromUI4"}, - {224, "VarDateFromDec"}, - {225, "VarCyFromI1"}, - {226, "VarCyFromUI2"}, - {227, "VarCyFromUI4"}, - {228, "VarCyFromDec"}, - {229, "VarBstrFromI1"}, - {230, "VarBstrFromUI2"}, - {231, "VarBstrFromUI4"}, - {232, "VarBstrFromDec"}, - {233, "VarBoolFromI1"}, - {234, "VarBoolFromUI2"}, - {235, "VarBoolFromUI4"}, - {236, "VarBoolFromDec"}, - {237, "VarUI1FromI1"}, - {238, "VarUI1FromUI2"}, - {239, "VarUI1FromUI4"}, - {240, "VarUI1FromDec"}, - {241, "VarDecFromI1"}, - {242, "VarDecFromUI2"}, - {243, "VarDecFromUI4"}, - {244, "VarI1FromUI1"}, - {245, "VarI1FromI2"}, - {246, "VarI1FromI4"}, - {247, "VarI1FromR4"}, - {248, "VarI1FromR8"}, - {249, "VarI1FromDate"}, - {250, "VarI1FromCy"}, - {251, "VarI1FromStr"}, - {252, "VarI1FromDisp"}, - {253, "VarI1FromBool"}, - {254, "VarI1FromUI2"}, - {255, "VarI1FromUI4"}, - {256, "VarI1FromDec"}, - {257, "VarUI2FromUI1"}, - {258, "VarUI2FromI2"}, - {259, "VarUI2FromI4"}, - {260, "VarUI2FromR4"}, - {261, "VarUI2FromR8"}, - {262, "VarUI2FromDate"}, - {263, "VarUI2FromCy"}, - {264, "VarUI2FromStr"}, - {265, "VarUI2FromDisp"}, - {266, "VarUI2FromBool"}, - {267, "VarUI2FromI1"}, - {268, "VarUI2FromUI4"}, - {269, "VarUI2FromDec"}, - {270, "VarUI4FromUI1"}, - {271, "VarUI4FromI2"}, - {272, "VarUI4FromI4"}, - {273, "VarUI4FromR4"}, - {274, "VarUI4FromR8"}, - {275, "VarUI4FromDate"}, - {276, "VarUI4FromCy"}, - {277, "VarUI4FromStr"}, - {278, "VarUI4FromDisp"}, - {279, "VarUI4FromBool"}, - {280, "VarUI4FromI1"}, - {281, "VarUI4FromUI2"}, - {282, "VarUI4FromDec"}, - {283, "BSTR_UserSize"}, - {284, "BSTR_UserMarshal"}, - {285, "BSTR_UserUnmarshal"}, - {286, "BSTR_UserFree"}, - {287, "VARIANT_UserSize"}, - {288, "VARIANT_UserMarshal"}, - {289, "VARIANT_UserUnmarshal"}, - {290, "VARIANT_UserFree"}, - {291, "LPSAFEARRAY_UserSize"}, - {292, "LPSAFEARRAY_UserMarshal"}, - {293, "LPSAFEARRAY_UserUnmarshal"}, - {294, "LPSAFEARRAY_UserFree"}, - {295, "LPSAFEARRAY_Size"}, - {296, "LPSAFEARRAY_Marshal"}, - {297, "LPSAFEARRAY_Unmarshal"}, - {298, "VarDecCmpR8"}, - {299, "VarCyAdd"}, - {300, "DllUnregisterServer"}, - {301, "OACreateTypeLib2"}, - {303, "VarCyMul"}, - {304, "VarCyMulI4"}, - {305, "VarCySub"}, - {306, "VarCyAbs"}, - {307, "VarCyFix"}, - {308, "VarCyInt"}, - {309, "VarCyNeg"}, - {310, "VarCyRound"}, - {311, "VarCyCmp"}, - {312, "VarCyCmpR8"}, - {313, "VarBstrCat"}, - {314, "VarBstrCmp"}, - {315, "VarR8Pow"}, - {316, "VarR4CmpR8"}, - {317, "VarR8Round"}, - {318, "VarCat"}, - {319, "VarDateFromUdateEx"}, - {322, "GetRecordInfoFromGuids"}, - {323, "GetRecordInfoFromTypeInfo"}, - {325, "SetVarConversionLocaleSetting"}, - {326, "GetVarConversionLocaleSetting"}, - {327, "SetOaNoCache"}, - {329, "VarCyMulI8"}, - {330, "VarDateFromUdate"}, - {331, "VarUdateFromDate"}, - {332, "GetAltMonthNames"}, - {333, "VarI8FromUI1"}, - {334, "VarI8FromI2"}, - {335, "VarI8FromR4"}, - {336, "VarI8FromR8"}, - {337, "VarI8FromCy"}, - {338, "VarI8FromDate"}, - {339, "VarI8FromStr"}, - {340, "VarI8FromDisp"}, - {341, "VarI8FromBool"}, - {342, "VarI8FromI1"}, - {343, "VarI8FromUI2"}, - {344, "VarI8FromUI4"}, - {345, "VarI8FromDec"}, - {346, "VarI2FromI8"}, - {347, "VarI2FromUI8"}, - {348, "VarI4FromI8"}, - {349, "VarI4FromUI8"}, - {360, "VarR4FromI8"}, - {361, "VarR4FromUI8"}, - {362, "VarR8FromI8"}, - {363, "VarR8FromUI8"}, - {364, "VarDateFromI8"}, - {365, "VarDateFromUI8"}, - {366, "VarCyFromI8"}, - {367, "VarCyFromUI8"}, - {368, "VarBstrFromI8"}, - {369, "VarBstrFromUI8"}, - {370, "VarBoolFromI8"}, - {371, "VarBoolFromUI8"}, - {372, "VarUI1FromI8"}, - {373, "VarUI1FromUI8"}, - {374, "VarDecFromI8"}, - {375, "VarDecFromUI8"}, - {376, "VarI1FromI8"}, - {377, "VarI1FromUI8"}, - {378, "VarUI2FromI8"}, - {379, "VarUI2FromUI8"}, - {401, "OleLoadPictureEx"}, - {402, "OleLoadPictureFileEx"}, - {411, "SafeArrayCreateVector"}, - {412, "SafeArrayCopyData"}, - {413, "VectorFromBstr"}, - {414, "BstrFromVector"}, - {415, "OleIconToCursor"}, - {416, "OleCreatePropertyFrameIndirect"}, - {417, "OleCreatePropertyFrame"}, - {418, "OleLoadPicture"}, - {419, "OleCreatePictureIndirect"}, - {420, "OleCreateFontIndirect"}, - {421, "OleTranslateColor"}, - {422, "OleLoadPictureFile"}, - {423, "OleSavePictureFile"}, - {424, "OleLoadPicturePath"}, - {425, "VarUI4FromI8"}, - {426, "VarUI4FromUI8"}, - {427, "VarI8FromUI8"}, - {428, "VarUI8FromI8"}, - {429, "VarUI8FromUI1"}, - {430, "VarUI8FromI2"}, - {431, "VarUI8FromR4"}, - {432, "VarUI8FromR8"}, - {433, "VarUI8FromCy"}, - {434, "VarUI8FromDate"}, - {435, "VarUI8FromStr"}, - {436, "VarUI8FromDisp"}, - {437, "VarUI8FromBool"}, - {438, "VarUI8FromI1"}, - {439, "VarUI8FromUI2"}, - {440, "VarUI8FromUI4"}, - {441, "VarUI8FromDec"}, - {442, "RegisterTypeLibForUser"}, - {443, "UnRegisterTypeLibForUser"} -}; - -/** - * Lookup import name for given library name and ordinal number - * @param libName library name - * @param ordNum ordinal number - * @return new string name - */ -std::string ordLookUp(const std::string& libName, const std::size_t& ordNum) -{ - std::string res; - - if(libName == "ws2_32.dll" || libName == "wsock32.dll") - { - res = mapGetValueOrDefault(winsock32Map, ordNum); - } - else if (libName == "oleaut32.dll") - { - res = mapGetValueOrDefault(oleaut32Map, ordNum); - } - - return res.empty() ? "ord" + std::to_string(ordNum) : res; -} - -} // anonymous namespace - namespace retdec { namespace fileformat { @@ -792,7 +241,7 @@ void ImportTable::computeHashes() unsigned long long ord; if(import->getOrdinalNumber(ord)) { - funcName = toLower(ordLookUp(libName, ord)); + funcName = toLower(retdec::utils::ordLookUp(libName, ord, true)); } } @@ -804,9 +253,11 @@ void ImportTable::computeHashes() libName.erase(libName.length() - 4, 4); } + // Issue 460: Do not generate import name hash if there is an imported name that is either empty or invalid + // https://github.com/avast/retdec/issues/460 if(libName.empty() || funcName.empty()) { - continue; + break; } // Yara adds comma if there are multiple imports diff --git a/src/unpackertool/plugins/mpress/mpress.cpp b/src/unpackertool/plugins/mpress/mpress.cpp index a0651965e..c54ed038c 100644 --- a/src/unpackertool/plugins/mpress/mpress.cpp +++ b/src/unpackertool/plugins/mpress/mpress.cpp @@ -319,11 +319,11 @@ void MpressPlugin::fixImportsAndEp(DynamicBuffer& buffer) readPos++; // skip null terminator // Set FirstThunk to point into IAT - int fileIndex = _peFile->impDir().getFileIndex(moduleName, PeLib::NEWDIR); + int fileIndex = _peFile->impDir().getFileIndex(moduleName, true); if (fileIndex == -1) throw InvalidImportHintsException(); - _peFile->impDir().setFirstThunk(fileIndex, PeLib::NEWDIR, destOffset); + _peFile->impDir().setFirstThunk(fileIndex, true, destOffset); lowestDestOffset = std::min(destOffset, lowestDestOffset); highestDestOffset = std::max(destOffset, highestDestOffset); destOffset += destOffsetDiff; @@ -677,15 +677,15 @@ void MpressPlugin::saveFile(const std::string& fileName, DynamicBuffer& content) // After this all we need to update the IAT with the contents of ILT // since Import Directory in PeLib is built after the write to the file - for (size_t fileIndex = 0; fileIndex < _peFile->impDir().getNumberOfFiles(PeLib::OLDDIR); ++fileIndex) + for (size_t fileIndex = 0; fileIndex < _peFile->impDir().getNumberOfFiles(false); ++fileIndex) { auto tmp = static_cast(fileIndex); auto w = static_cast(_packedContentSect->getSecSeg()->getIndex()); - size_t destOffset = _peFile->impDir().getFirstThunk(tmp, PeLib::OLDDIR) - imageLoader.getSectionHeader(w)->VirtualAddress; - for (size_t funcIndex = 0; funcIndex < _peFile->impDir().getNumberOfFunctions(tmp, PeLib::OLDDIR); ++funcIndex, destOffset += 4) + size_t destOffset = _peFile->impDir().getFirstThunk(tmp, false) - imageLoader.getSectionHeader(w)->VirtualAddress; + for (size_t funcIndex = 0; funcIndex < _peFile->impDir().getNumberOfFunctions(tmp, false); ++funcIndex, destOffset += 4) { content.write( - _peFile->impDir().getOriginalFirstThunk(tmp, static_cast(funcIndex), PeLib::OLDDIR), + _peFile->impDir().getOriginalFirstThunk(tmp, static_cast(funcIndex), false), static_cast(destOffset)); } } diff --git a/src/unpackertool/plugins/upx/pe/pe_upx_stub.cpp b/src/unpackertool/plugins/upx/pe/pe_upx_stub.cpp index 35ca50542..c13ec1cec 100644 --- a/src/unpackertool/plugins/upx/pe/pe_upx_stub.cpp +++ b/src/unpackertool/plugins/upx/pe/pe_upx_stub.cpp @@ -706,9 +706,9 @@ template void PeUpxStub::fixImports(const DynamicBuffer& unpack } // Sets the proper FirstThunk for new record in import directory - std::uint32_t fileIndex = _newPeFile->impDir().getFileIndex(libraryName, PeLib::NEWDIR); + std::uint32_t fileIndex = _newPeFile->impDir().getFileIndex(libraryName, true); if (fileIndex != static_cast(-1)) - _newPeFile->impDir().setFirstThunk(fileIndex, PeLib::NEWDIR, firstThunk); + _newPeFile->impDir().setFirstThunk(fileIndex, true, firstThunk); iltOffset = importHints.read(readPos); readPos += 4; @@ -1218,13 +1218,13 @@ template void PeUpxStub::saveFile(const std::string& outputFile // OrignalFirstThunk-s are known only after the impDir is written into the file // We then need to read it function by function and set the contents of IAT to be same as ILT // If it isn't, the windows loader refuses to load the executable file - for(std::uint32_t fileIndex = 0; fileIndex < _newPeFile->impDir().getNumberOfFiles(PeLib::OLDDIR); ++fileIndex) + for(std::uint32_t fileIndex = 0; fileIndex < _newPeFile->impDir().getNumberOfFiles(false); ++fileIndex) { - std::uint32_t destOffset = _newPeFile->impDir().getFirstThunk(fileIndex, PeLib::OLDDIR) - VirtualAddress; + std::uint32_t destOffset = _newPeFile->impDir().getFirstThunk(fileIndex, false) - VirtualAddress; - for(std::uint32_t funcIndex = 0; funcIndex < _newPeFile->impDir().getNumberOfFunctions(fileIndex, PeLib::OLDDIR); ++funcIndex, destOffset += 4) + for(std::uint32_t funcIndex = 0; funcIndex < _newPeFile->impDir().getNumberOfFunctions(fileIndex, false); ++funcIndex, destOffset += 4) { - unpackedData.write(_newPeFile->impDir().getOriginalFirstThunk(fileIndex, funcIndex, PeLib::OLDDIR), destOffset); + unpackedData.write(_newPeFile->impDir().getOriginalFirstThunk(fileIndex, funcIndex, false), destOffset); } } } diff --git a/src/utils/CMakeLists.txt b/src/utils/CMakeLists.txt index f77f235e3..9e372ca83 100644 --- a/src/utils/CMakeLists.txt +++ b/src/utils/CMakeLists.txt @@ -11,6 +11,7 @@ add_library(utils STATIC file_io.cpp math.cpp memory.cpp + ord_lookup.cpp string.cpp system.cpp time.cpp diff --git a/src/utils/ord_lookup.cpp b/src/utils/ord_lookup.cpp new file mode 100644 index 000000000..7307bcfdc --- /dev/null +++ b/src/utils/ord_lookup.cpp @@ -0,0 +1,567 @@ +/** + * @file src/fileformat/types/import_table/import_table.cpp + * @brief Class for import table. + * @copyright (c) 2017 Avast Software, licensed under the MIT license + */ + +#include "retdec/utils/container.h" +#include "retdec/utils/conversion.h" +#include "retdec/utils/string.h" +#include "retdec/utils/ord_lookup.h" + +namespace retdec { +namespace utils { + +// Ordinal-name LUT for YARA compatible import hash computation. +// This must stay compatible with YARA's ord_lookup function + +std::map winsock32Map = +{ + {1, "accept"}, + {2, "bind"}, + {3, "closesocket"}, + {4, "connect"}, + {5, "getpeername"}, + {6, "getsockname"}, + {7, "getsockopt"}, + {8, "htonl"}, + {9, "htons"}, + {10, "ioctlsocket"}, + {11, "inet_addr"}, + {12, "inet_ntoa"}, + {13, "listen"}, + {14, "ntohl"}, + {15, "ntohs"}, + {16, "recv"}, + {17, "recvfrom"}, + {18, "select"}, + {19, "send"}, + {20, "sendto"}, + {21, "setsockopt"}, + {22, "shutdown"}, + {23, "socket"}, + {24, "GetAddrInfoW"}, + {25, "GetNameInfoW"}, + {26, "WSApSetPostRoutine"}, + {27, "FreeAddrInfoW"}, + {28, "WPUCompleteOverlappedRequest"}, + {29, "WSAAccept"}, + {30, "WSAAddressToStringA"}, + {31, "WSAAddressToStringW"}, + {32, "WSACloseEvent"}, + {33, "WSAConnect"}, + {34, "WSACreateEvent"}, + {35, "WSADuplicateSocketA"}, + {36, "WSADuplicateSocketW"}, + {37, "WSAEnumNameSpaceProvidersA"}, + {38, "WSAEnumNameSpaceProvidersW"}, + {39, "WSAEnumNetworkEvents"}, + {40, "WSAEnumProtocolsA"}, + {41, "WSAEnumProtocolsW"}, + {42, "WSAEventSelect"}, + {43, "WSAGetOverlappedResult"}, + {44, "WSAGetQOSByName"}, + {45, "WSAGetServiceClassInfoA"}, + {46, "WSAGetServiceClassInfoW"}, + {47, "WSAGetServiceClassNameByClassIdA"}, + {48, "WSAGetServiceClassNameByClassIdW"}, + {49, "WSAHtonl"}, + {50, "WSAHtons"}, + {51, "gethostbyaddr"}, + {52, "gethostbyname"}, + {53, "getprotobyname"}, + {54, "getprotobynumber"}, + {55, "getservbyname"}, + {56, "getservbyport"}, + {57, "gethostname"}, + {58, "WSAInstallServiceClassA"}, + {59, "WSAInstallServiceClassW"}, + {60, "WSAIoctl"}, + {61, "WSAJoinLeaf"}, + {62, "WSALookupServiceBeginA"}, + {63, "WSALookupServiceBeginW"}, + {64, "WSALookupServiceEnd"}, + {65, "WSALookupServiceNextA"}, + {66, "WSALookupServiceNextW"}, + {67, "WSANSPIoctl"}, + {68, "WSANtohl"}, + {69, "WSANtohs"}, + {70, "WSAProviderConfigChange"}, + {71, "WSARecv"}, + {72, "WSARecvDisconnect"}, + {73, "WSARecvFrom"}, + {74, "WSARemoveServiceClass"}, + {75, "WSAResetEvent"}, + {76, "WSASend"}, + {77, "WSASendDisconnect"}, + {78, "WSASendTo"}, + {79, "WSASetEvent"}, + {80, "WSASetServiceA"}, + {81, "WSASetServiceW"}, + {82, "WSASocketA"}, + {83, "WSASocketW"}, + {84, "WSAStringToAddressA"}, + {85, "WSAStringToAddressW"}, + {86, "WSAWaitForMultipleEvents"}, + {87, "WSCDeinstallProvider"}, + {88, "WSCEnableNSProvider"}, + {89, "WSCEnumProtocols"}, + {90, "WSCGetProviderPath"}, + {91, "WSCInstallNameSpace"}, + {92, "WSCInstallProvider"}, + {93, "WSCUnInstallNameSpace"}, + {94, "WSCUpdateProvider"}, + {95, "WSCWriteNameSpaceOrder"}, + {96, "WSCWriteProviderOrder"}, + {97, "freeaddrinfo"}, + {98, "getaddrinfo"}, + {99, "getnameinfo"}, + {101, "WSAAsyncSelect"}, + {102, "WSAAsyncGetHostByAddr"}, + {103, "WSAAsyncGetHostByName"}, + {104, "WSAAsyncGetProtoByNumber"}, + {105, "WSAAsyncGetProtoByName"}, + {106, "WSAAsyncGetServByPort"}, + {107, "WSAAsyncGetServByName"}, + {108, "WSACancelAsyncRequest"}, + {109, "WSASetBlockingHook"}, + {110, "WSAUnhookBlockingHook"}, + {111, "WSAGetLastError"}, + {112, "WSASetLastError"}, + {113, "WSACancelBlockingCall"}, + {114, "WSAIsBlocking"}, + {115, "WSAStartup"}, + {116, "WSACleanup"}, + {151, "__WSAFDIsSet"}, + {500, "WEP"} +}; + +std::map oleaut32Map = +{ + {2, "SysAllocString"}, + {3, "SysReAllocString"}, + {4, "SysAllocStringLen"}, + {5, "SysReAllocStringLen"}, + {6, "SysFreeString"}, + {7, "SysStringLen"}, + {8, "VariantInit"}, + {9, "VariantClear"}, + {10, "VariantCopy"}, + {11, "VariantCopyInd"}, + {12, "VariantChangeType"}, + {13, "VariantTimeToDosDateTime"}, + {14, "DosDateTimeToVariantTime"}, + {15, "SafeArrayCreate"}, + {16, "SafeArrayDestroy"}, + {17, "SafeArrayGetDim"}, + {18, "SafeArrayGetElemsize"}, + {19, "SafeArrayGetUBound"}, + {20, "SafeArrayGetLBound"}, + {21, "SafeArrayLock"}, + {22, "SafeArrayUnlock"}, + {23, "SafeArrayAccessData"}, + {24, "SafeArrayUnaccessData"}, + {25, "SafeArrayGetElement"}, + {26, "SafeArrayPutElement"}, + {27, "SafeArrayCopy"}, + {28, "DispGetParam"}, + {29, "DispGetIDsOfNames"}, + {30, "DispInvoke"}, + {31, "CreateDispTypeInfo"}, + {32, "CreateStdDispatch"}, + {33, "RegisterActiveObject"}, + {34, "RevokeActiveObject"}, + {35, "GetActiveObject"}, + {36, "SafeArrayAllocDescriptor"}, + {37, "SafeArrayAllocData"}, + {38, "SafeArrayDestroyDescriptor"}, + {39, "SafeArrayDestroyData"}, + {40, "SafeArrayRedim"}, + {41, "SafeArrayAllocDescriptorEx"}, + {42, "SafeArrayCreateEx"}, + {43, "SafeArrayCreateVectorEx"}, + {44, "SafeArraySetRecordInfo"}, + {45, "SafeArrayGetRecordInfo"}, + {46, "VarParseNumFromStr"}, + {47, "VarNumFromParseNum"}, + {48, "VarI2FromUI1"}, + {49, "VarI2FromI4"}, + {50, "VarI2FromR4"}, + {51, "VarI2FromR8"}, + {52, "VarI2FromCy"}, + {53, "VarI2FromDate"}, + {54, "VarI2FromStr"}, + {55, "VarI2FromDisp"}, + {56, "VarI2FromBool"}, + {57, "SafeArraySetIID"}, + {58, "VarI4FromUI1"}, + {59, "VarI4FromI2"}, + {60, "VarI4FromR4"}, + {61, "VarI4FromR8"}, + {62, "VarI4FromCy"}, + {63, "VarI4FromDate"}, + {64, "VarI4FromStr"}, + {65, "VarI4FromDisp"}, + {66, "VarI4FromBool"}, + {67, "SafeArrayGetIID"}, + {68, "VarR4FromUI1"}, + {69, "VarR4FromI2"}, + {70, "VarR4FromI4"}, + {71, "VarR4FromR8"}, + {72, "VarR4FromCy"}, + {73, "VarR4FromDate"}, + {74, "VarR4FromStr"}, + {75, "VarR4FromDisp"}, + {76, "VarR4FromBool"}, + {77, "SafeArrayGetVartype"}, + {78, "VarR8FromUI1"}, + {79, "VarR8FromI2"}, + {80, "VarR8FromI4"}, + {81, "VarR8FromR4"}, + {82, "VarR8FromCy"}, + {83, "VarR8FromDate"}, + {84, "VarR8FromStr"}, + {85, "VarR8FromDisp"}, + {86, "VarR8FromBool"}, + {87, "VarFormat"}, + {88, "VarDateFromUI1"}, + {89, "VarDateFromI2"}, + {90, "VarDateFromI4"}, + {91, "VarDateFromR4"}, + {92, "VarDateFromR8"}, + {93, "VarDateFromCy"}, + {94, "VarDateFromStr"}, + {95, "VarDateFromDisp"}, + {96, "VarDateFromBool"}, + {97, "VarFormatDateTime"}, + {98, "VarCyFromUI1"}, + {99, "VarCyFromI2"}, + {100, "VarCyFromI4"}, + {101, "VarCyFromR4"}, + {102, "VarCyFromR8"}, + {103, "VarCyFromDate"}, + {104, "VarCyFromStr"}, + {105, "VarCyFromDisp"}, + {106, "VarCyFromBool"}, + {107, "VarFormatNumber"}, + {108, "VarBstrFromUI1"}, + {109, "VarBstrFromI2"}, + {110, "VarBstrFromI4"}, + {111, "VarBstrFromR4"}, + {112, "VarBstrFromR8"}, + {113, "VarBstrFromCy"}, + {114, "VarBstrFromDate"}, + {115, "VarBstrFromDisp"}, + {116, "VarBstrFromBool"}, + {117, "VarFormatPercent"}, + {118, "VarBoolFromUI1"}, + {119, "VarBoolFromI2"}, + {120, "VarBoolFromI4"}, + {121, "VarBoolFromR4"}, + {122, "VarBoolFromR8"}, + {123, "VarBoolFromDate"}, + {124, "VarBoolFromCy"}, + {125, "VarBoolFromStr"}, + {126, "VarBoolFromDisp"}, + {127, "VarFormatCurrency"}, + {128, "VarWeekdayName"}, + {129, "VarMonthName"}, + {130, "VarUI1FromI2"}, + {131, "VarUI1FromI4"}, + {132, "VarUI1FromR4"}, + {133, "VarUI1FromR8"}, + {134, "VarUI1FromCy"}, + {135, "VarUI1FromDate"}, + {136, "VarUI1FromStr"}, + {137, "VarUI1FromDisp"}, + {138, "VarUI1FromBool"}, + {139, "VarFormatFromTokens"}, + {140, "VarTokenizeFormatString"}, + {141, "VarAdd"}, + {142, "VarAnd"}, + {143, "VarDiv"}, + {144, "DllCanUnloadNow"}, + {145, "DllGetClassObject"}, + {146, "DispCallFunc"}, + {147, "VariantChangeTypeEx"}, + {148, "SafeArrayPtrOfIndex"}, + {149, "SysStringByteLen"}, + {150, "SysAllocStringByteLen"}, + {151, "DllRegisterServer"}, + {152, "VarEqv"}, + {153, "VarIdiv"}, + {154, "VarImp"}, + {155, "VarMod"}, + {156, "VarMul"}, + {157, "VarOr"}, + {158, "VarPow"}, + {159, "VarSub"}, + {160, "CreateTypeLib"}, + {161, "LoadTypeLib"}, + {162, "LoadRegTypeLib"}, + {163, "RegisterTypeLib"}, + {164, "QueryPathOfRegTypeLib"}, + {165, "LHashValOfNameSys"}, + {166, "LHashValOfNameSysA"}, + {167, "VarXor"}, + {168, "VarAbs"}, + {169, "VarFix"}, + {170, "OaBuildVersion"}, + {171, "ClearCustData"}, + {172, "VarInt"}, + {173, "VarNeg"}, + {174, "VarNot"}, + {175, "VarRound"}, + {176, "VarCmp"}, + {177, "VarDecAdd"}, + {178, "VarDecDiv"}, + {179, "VarDecMul"}, + {180, "CreateTypeLib2"}, + {181, "VarDecSub"}, + {182, "VarDecAbs"}, + {183, "LoadTypeLibEx"}, + {184, "SystemTimeToVariantTime"}, + {185, "VariantTimeToSystemTime"}, + {186, "UnRegisterTypeLib"}, + {187, "VarDecFix"}, + {188, "VarDecInt"}, + {189, "VarDecNeg"}, + {190, "VarDecFromUI1"}, + {191, "VarDecFromI2"}, + {192, "VarDecFromI4"}, + {193, "VarDecFromR4"}, + {194, "VarDecFromR8"}, + {195, "VarDecFromDate"}, + {196, "VarDecFromCy"}, + {197, "VarDecFromStr"}, + {198, "VarDecFromDisp"}, + {199, "VarDecFromBool"}, + {200, "GetErrorInfo"}, + {201, "SetErrorInfo"}, + {202, "CreateErrorInfo"}, + {203, "VarDecRound"}, + {204, "VarDecCmp"}, + {205, "VarI2FromI1"}, + {206, "VarI2FromUI2"}, + {207, "VarI2FromUI4"}, + {208, "VarI2FromDec"}, + {209, "VarI4FromI1"}, + {210, "VarI4FromUI2"}, + {211, "VarI4FromUI4"}, + {212, "VarI4FromDec"}, + {213, "VarR4FromI1"}, + {214, "VarR4FromUI2"}, + {215, "VarR4FromUI4"}, + {216, "VarR4FromDec"}, + {217, "VarR8FromI1"}, + {218, "VarR8FromUI2"}, + {219, "VarR8FromUI4"}, + {220, "VarR8FromDec"}, + {221, "VarDateFromI1"}, + {222, "VarDateFromUI2"}, + {223, "VarDateFromUI4"}, + {224, "VarDateFromDec"}, + {225, "VarCyFromI1"}, + {226, "VarCyFromUI2"}, + {227, "VarCyFromUI4"}, + {228, "VarCyFromDec"}, + {229, "VarBstrFromI1"}, + {230, "VarBstrFromUI2"}, + {231, "VarBstrFromUI4"}, + {232, "VarBstrFromDec"}, + {233, "VarBoolFromI1"}, + {234, "VarBoolFromUI2"}, + {235, "VarBoolFromUI4"}, + {236, "VarBoolFromDec"}, + {237, "VarUI1FromI1"}, + {238, "VarUI1FromUI2"}, + {239, "VarUI1FromUI4"}, + {240, "VarUI1FromDec"}, + {241, "VarDecFromI1"}, + {242, "VarDecFromUI2"}, + {243, "VarDecFromUI4"}, + {244, "VarI1FromUI1"}, + {245, "VarI1FromI2"}, + {246, "VarI1FromI4"}, + {247, "VarI1FromR4"}, + {248, "VarI1FromR8"}, + {249, "VarI1FromDate"}, + {250, "VarI1FromCy"}, + {251, "VarI1FromStr"}, + {252, "VarI1FromDisp"}, + {253, "VarI1FromBool"}, + {254, "VarI1FromUI2"}, + {255, "VarI1FromUI4"}, + {256, "VarI1FromDec"}, + {257, "VarUI2FromUI1"}, + {258, "VarUI2FromI2"}, + {259, "VarUI2FromI4"}, + {260, "VarUI2FromR4"}, + {261, "VarUI2FromR8"}, + {262, "VarUI2FromDate"}, + {263, "VarUI2FromCy"}, + {264, "VarUI2FromStr"}, + {265, "VarUI2FromDisp"}, + {266, "VarUI2FromBool"}, + {267, "VarUI2FromI1"}, + {268, "VarUI2FromUI4"}, + {269, "VarUI2FromDec"}, + {270, "VarUI4FromUI1"}, + {271, "VarUI4FromI2"}, + {272, "VarUI4FromI4"}, + {273, "VarUI4FromR4"}, + {274, "VarUI4FromR8"}, + {275, "VarUI4FromDate"}, + {276, "VarUI4FromCy"}, + {277, "VarUI4FromStr"}, + {278, "VarUI4FromDisp"}, + {279, "VarUI4FromBool"}, + {280, "VarUI4FromI1"}, + {281, "VarUI4FromUI2"}, + {282, "VarUI4FromDec"}, + {283, "BSTR_UserSize"}, + {284, "BSTR_UserMarshal"}, + {285, "BSTR_UserUnmarshal"}, + {286, "BSTR_UserFree"}, + {287, "VARIANT_UserSize"}, + {288, "VARIANT_UserMarshal"}, + {289, "VARIANT_UserUnmarshal"}, + {290, "VARIANT_UserFree"}, + {291, "LPSAFEARRAY_UserSize"}, + {292, "LPSAFEARRAY_UserMarshal"}, + {293, "LPSAFEARRAY_UserUnmarshal"}, + {294, "LPSAFEARRAY_UserFree"}, + {295, "LPSAFEARRAY_Size"}, + {296, "LPSAFEARRAY_Marshal"}, + {297, "LPSAFEARRAY_Unmarshal"}, + {298, "VarDecCmpR8"}, + {299, "VarCyAdd"}, + {300, "DllUnregisterServer"}, + {301, "OACreateTypeLib2"}, + {303, "VarCyMul"}, + {304, "VarCyMulI4"}, + {305, "VarCySub"}, + {306, "VarCyAbs"}, + {307, "VarCyFix"}, + {308, "VarCyInt"}, + {309, "VarCyNeg"}, + {310, "VarCyRound"}, + {311, "VarCyCmp"}, + {312, "VarCyCmpR8"}, + {313, "VarBstrCat"}, + {314, "VarBstrCmp"}, + {315, "VarR8Pow"}, + {316, "VarR4CmpR8"}, + {317, "VarR8Round"}, + {318, "VarCat"}, + {319, "VarDateFromUdateEx"}, + {322, "GetRecordInfoFromGuids"}, + {323, "GetRecordInfoFromTypeInfo"}, + {325, "SetVarConversionLocaleSetting"}, + {326, "GetVarConversionLocaleSetting"}, + {327, "SetOaNoCache"}, + {329, "VarCyMulI8"}, + {330, "VarDateFromUdate"}, + {331, "VarUdateFromDate"}, + {332, "GetAltMonthNames"}, + {333, "VarI8FromUI1"}, + {334, "VarI8FromI2"}, + {335, "VarI8FromR4"}, + {336, "VarI8FromR8"}, + {337, "VarI8FromCy"}, + {338, "VarI8FromDate"}, + {339, "VarI8FromStr"}, + {340, "VarI8FromDisp"}, + {341, "VarI8FromBool"}, + {342, "VarI8FromI1"}, + {343, "VarI8FromUI2"}, + {344, "VarI8FromUI4"}, + {345, "VarI8FromDec"}, + {346, "VarI2FromI8"}, + {347, "VarI2FromUI8"}, + {348, "VarI4FromI8"}, + {349, "VarI4FromUI8"}, + {360, "VarR4FromI8"}, + {361, "VarR4FromUI8"}, + {362, "VarR8FromI8"}, + {363, "VarR8FromUI8"}, + {364, "VarDateFromI8"}, + {365, "VarDateFromUI8"}, + {366, "VarCyFromI8"}, + {367, "VarCyFromUI8"}, + {368, "VarBstrFromI8"}, + {369, "VarBstrFromUI8"}, + {370, "VarBoolFromI8"}, + {371, "VarBoolFromUI8"}, + {372, "VarUI1FromI8"}, + {373, "VarUI1FromUI8"}, + {374, "VarDecFromI8"}, + {375, "VarDecFromUI8"}, + {376, "VarI1FromI8"}, + {377, "VarI1FromUI8"}, + {378, "VarUI2FromI8"}, + {379, "VarUI2FromUI8"}, + {401, "OleLoadPictureEx"}, + {402, "OleLoadPictureFileEx"}, + {411, "SafeArrayCreateVector"}, + {412, "SafeArrayCopyData"}, + {413, "VectorFromBstr"}, + {414, "BstrFromVector"}, + {415, "OleIconToCursor"}, + {416, "OleCreatePropertyFrameIndirect"}, + {417, "OleCreatePropertyFrame"}, + {418, "OleLoadPicture"}, + {419, "OleCreatePictureIndirect"}, + {420, "OleCreateFontIndirect"}, + {421, "OleTranslateColor"}, + {422, "OleLoadPictureFile"}, + {423, "OleSavePictureFile"}, + {424, "OleLoadPicturePath"}, + {425, "VarUI4FromI8"}, + {426, "VarUI4FromUI8"}, + {427, "VarI8FromUI8"}, + {428, "VarUI8FromI8"}, + {429, "VarUI8FromUI1"}, + {430, "VarUI8FromI2"}, + {431, "VarUI8FromR4"}, + {432, "VarUI8FromR8"}, + {433, "VarUI8FromCy"}, + {434, "VarUI8FromDate"}, + {435, "VarUI8FromStr"}, + {436, "VarUI8FromDisp"}, + {437, "VarUI8FromBool"}, + {438, "VarUI8FromI1"}, + {439, "VarUI8FromUI2"}, + {440, "VarUI8FromUI4"}, + {441, "VarUI8FromDec"}, + {442, "RegisterTypeLibForUser"}, + {443, "UnRegisterTypeLibForUser"} +}; + +/** + * Lookup import name for given library name and ordinal number + * @param libName library name + * @param ordNum ordinal number + * @param forceNameFromOrdinal + * @return new string name + */ +std::string ordLookUp(const std::string& libName, const std::size_t& ordNum, bool forceNameFromOrdinal) +{ + std::string res; + + if(areEqualCaseInsensitive(libName, "ws2_32.dll") || areEqualCaseInsensitive(libName, "wsock32.dll")) + { + res = mapGetValueOrDefault(winsock32Map, ordNum); + } + else if (areEqualCaseInsensitive(libName, "oleaut32.dll")) + { + res = mapGetValueOrDefault(oleaut32Map, ordNum); + } + + if(res.empty() && forceNameFromOrdinal) + res = "ord" + std::to_string(ordNum); + return res; +} + +} // namespace utils +} // namespace retdec