/* * ImportDirectory.h - Part of the PeLib library. * * Copyright (c) 2004 - 2005 Sebastian Porst (webmaster@the-interweb.com) * All rights reserved. * * This software is licensed under the zlib/libpng License. * For more details see http://www.opensource.org/licenses/zlib-license.php * or the license information file (license.htm) in the root directory * of PeLib. */ #ifndef IMPORTDIRECTORY_H #define IMPORTDIRECTORY_H #include "PeLibAux.h" #include "PeHeader.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 * 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. * \todo Adding functions by ordinal doesn't work yet (rebuild needs to be changed). * \todo Somehow store the rvas of the chunks in the file. **/ template class ImportDirectory { typedef typename std::vector >::iterator ImpDirFileIterator; typedef typename std::vector >::const_iterator ConstImpDirFileIterator; private: /// Stores information about already imported DLLs. std::vector > m_vOldiid; /// Stores information about imported DLLs which will be added. std::vector > m_vNewiid; // I can't convince Borland C++ to compile the function outside of the class declaration. // That's why the function definition is here. /// Tests if a certain function is imported. template bool hasFunction(std::string strFilename, T value, bool(PELIB_THUNK_DATA::* comp)(T) const) const { ConstImpDirFileIterator FileIter = m_vOldiid.begin(); ConstImpDirFileIterator EndIter = m_vOldiid.end(); for (int i=0;i<=1;i++) // Loop once for m_vOldiid and once for m_vNewiid { do { FileIter = std::find_if(FileIter, EndIter, std::bind2nd(std::mem_fun_ref(&PELIB_IMAGE_IMPORT_DIRECTORY::operator==), strFilename)); if (FileIter != EndIter) { typename std::vector >::const_iterator Iter = std::find_if(FileIter->originalfirstthunk.begin(), FileIter->originalfirstthunk.end(), std::bind2nd(std::mem_fun_ref(comp), value)); if (Iter != FileIter->originalfirstthunk.end()) { return true; } ++FileIter; } } while (FileIter != EndIter); FileIter = m_vNewiid.begin(); EndIter = m_vNewiid.end(); } return false; } public: /// Add a function to the import directory. int addFunction(const std::string& strFilename, word wHint); // EXPORT _byHint /// Add a function to the import directory. 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 /// 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 /// Get the name of an imported file. std::string getFileName(dword dwFilenr, currdir cdDir) const; // EXPORT void setFileName(dword filenr, currdir dir, const std::string& name); // EXPORT /// Get the hint of an imported function. word getFunctionHint(dword dwFilenr, dword dwFuncnr, currdir cdDir) const; // EXPORT void setFunctionHint(dword dwFilenr, dword dwFuncnr, currdir cdDir, word value); // EXPORT /// Get the name of an imported function. std::string getFunctionName(dword dwFilenr, dword dwFuncnr, currdir cdDir) const; // EXPORT void setFunctionName(dword dwFilenr, dword dwFuncnr, currdir cdDir, const std::string& functionName); // EXPORT /// Get the number of files which are imported. dword getNumberOfFiles(currdir cdDir) const; // EXPORT /// Get the number of fucntions which are imported by a specific file. dword getNumberOfFunctions(dword dwFilenr, currdir cdDir) const; // EXPORT /// Read a file's import directory. int read(const std::string& strFilename, unsigned int uiOffset, unsigned int uiSize, const PeHeaderT& pehHeader); // EXPORT /// Rebuild the import directory. void rebuild(std::vector& vBuffer, dword dwRva, bool fixEntries = true) const; // EXPORT /// Remove a file from the import directory. int removeFile(const std::string& strFilename); // EXPORT /// Remove a function from the import directory. int removeFunction(const std::string& strFilename, const std::string& strFuncname); // EXPORT _byName /// Remove a function from the import directory. int removeFunction(const std::string& strFilename, word wHint); // EXPORT _byHint /// Returns the size of the current import directory. unsigned int size() const; // EXPORT /// Writes the import directory to a file. int write(const std::string& strFilename, unsigned int uiOffset, unsigned int uiRva); // EXPORT /// Returns the FirstThunk value of a function. dword getFirstThunk(dword dwFilenr, dword dwFuncnr, currdir cdDir) const; // EXPORT _byNumber void setFirstThunk(dword dwFilenr, dword dwFuncnr, currdir cdDir, dword value); // EXPORT _byNumber /// Returns the OriginalFirstThunk value of a function. dword getOriginalFirstThunk(dword dwFilenr, dword dwFuncnr, currdir cdDir) const; // EXPORT _byNumber void setOriginalFirstThunk(dword dwFilenr, dword dwFuncnr, currdir cdDir, dword value); // EXPORT // dword getFirstThunk(const std::string& strFilename, const std::string& strFuncname, currdir cdDir) const throw (PeLibException); // dword getOriginalFirstThunk(const std::string& strFilename, const std::string& strFuncname, currdir cdDir) const throw (PeLibException); /// Returns the FirstThunk value of a file. dword getFirstThunk(const std::string& strFilename, currdir cdDir) const; // EXPORT _byName /// Returns the OriginalFirstThunk value of a file. dword getOriginalFirstThunk(const std::string& strFilename, currdir cdDir) const; // EXPORT _byName /// Returns the ForwarderChain value of a file. dword getForwarderChain(const std::string& strFilename, currdir cdDir) const; // EXPORT _byName dword getRvaOfName(const std::string& strFilename, currdir cdDir) const; // EXPORT _byName /// Returns the TimeDateStamp value of a file. dword getTimeDateStamp(const std::string& strFilename, currdir cdDir) const; // EXPORT _byName /// Returns the FirstThunk value of a file. dword getFirstThunk(dword dwFilenr, currdir cdDir) const; // EXPORT void setFirstThunk(dword dwFilenr, currdir cdDir, dword value); // EXPORT _byNumber_function /// Returns the OriginalFirstThunk value of a file. dword getOriginalFirstThunk(dword dwFilenr, currdir cdDir) const; // EXPORT void setOriginalFirstThunk(dword dwFilenr, currdir cdDir, dword value); // EXPORT _byNumber_function /// Returns the ForwarderChain value of a file. dword getForwarderChain(dword dwFilenr, currdir cdDir) const; // EXPORT _byNumber void setForwarderChain(dword dwFilenr, currdir cdDir, dword value); // EXPORT _byNumber_function dword getRvaOfName(dword dwFilenr, currdir cdDir) const; // EXPORT _byNumber void setRvaOfName(dword dwFilenr, currdir cdDir, dword value); // EXPORT /// Returns the TimeDateStamp value of a file. dword getTimeDateStamp(dword dwFilenr, currdir cdDir) const; // EXPORT void setTimeDateStamp(dword dwFilenr, currdir cdDir, dword value); // EXPORT _byNumber // word getFunctionHint(const std::string& strFilename, const std::string& strFuncname, currdir cdDir) const throw (PeLibException); }; /** * Add another import (by Ordinal) to the current file. Note that the import table is not automatically updated. * The new imported functions will be added when you recalculate the import table as it's necessary * to specify the address the import table will have in the file. * @param strFilename The name of a DLL. * @param wHint The ordinal of the function in the DLL. **/ template int ImportDirectory::addFunction(const std::string& strFilename, word wHint) { if (hasFunction(strFilename, wHint, &PELIB_THUNK_DATA::equalHint)) { return ERROR_DUPLICATE_ENTRY; } // Find the imported file. ImpDirFileIterator FileIter = std::find_if(m_vNewiid.begin(), m_vNewiid.end(), std::bind2nd(std::mem_fun_ref(&PELIB_IMAGE_IMPORT_DIRECTORY::operator==), strFilename)); PELIB_IMAGE_IMPORT_DIRECTORY iid; PELIB_THUNK_DATA td; td.hint = wHint; td.itd.Ordinal = wHint | PELIB_IMAGE_ORDINAL_FLAGS::IMAGE_ORDINAL_FLAG; iid.name = strFilename; if (FileIter == m_vNewiid.end()) { iid.originalfirstthunk.push_back(td); iid.firstthunk.push_back(td); m_vNewiid.push_back(iid); } else { FileIter->originalfirstthunk.push_back(td); FileIter->firstthunk.push_back(td); } return NO_ERROR; } /** * Add a function to the Import Directory. * @param strFilename Name of the file which will be imported * @param strFuncname Name of the function which will be imported. **/ template int ImportDirectory::addFunction(const std::string& strFilename, const std::string& strFuncname) { if (hasFunction(strFilename, strFuncname, &PELIB_THUNK_DATA::equalFunctionName)) { return ERROR_DUPLICATE_ENTRY; } // Find the imported file. ImpDirFileIterator FileIter = std::find_if(m_vNewiid.begin(), m_vNewiid.end(), std::bind2nd(std::mem_fun_ref(&PELIB_IMAGE_IMPORT_DIRECTORY::operator==), strFilename)); PELIB_IMAGE_IMPORT_DIRECTORY iid; PELIB_THUNK_DATA td; td.fname = strFuncname; iid.name = strFilename; if (FileIter == m_vNewiid.end()) { iid.originalfirstthunk.push_back(td); iid.firstthunk.push_back(td); m_vNewiid.push_back(iid); } else { FileIter->originalfirstthunk.push_back(td); FileIter->firstthunk.push_back(td); } return NO_ERROR; } /** * 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. * @return The ID of an imported file. **/ template unsigned int ImportDirectory::getFileIndex(const std::string& strFilename, currdir cdDir) const { const std::vector >* currDir; if (cdDir == OLDDIR) { currDir = &m_vOldiid; } else { currDir = &m_vNewiid; } ConstImpDirFileIterator FileIter = std::find_if(currDir->begin(), currDir->end(), std::bind2nd(std::mem_fun_ref(&PELIB_IMAGE_IMPORT_DIRECTORY::operator==), strFilename)); if (FileIter != currDir->end()) { return static_cast(std::distance(currDir->begin(), FileIter)); } else { return -1; // throw Exceptions::InvalidName(ImportDirectoryId, __LINE__); } return NO_ERROR; } /** * 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. * @return ID of the imported function. **/ template unsigned int ImportDirectory::getFunctionIndex(const std::string& strFilename, const std::string& strFuncname, currdir cdDir) const { unsigned int uiFile = getFileIndex(strFilename, cdDir); for (unsigned int i=0;i std::string ImportDirectory::getFileName(dword dwFilenr, currdir cdDir) const { if (cdDir == OLDDIR) return m_vOldiid[dwFilenr].name; else return m_vNewiid[dwFilenr].name; } template void ImportDirectory::setFileName(dword filenr, currdir dir, const std::string& name) { if (dir == OLDDIR) m_vOldiid[filenr].name = name; else m_vNewiid[filenr].name = name; } /** * Get the name of an imported function. * @param dwFilenr Identifies which file should be checked. * @param dwFuncnr Identifies which function should be checked. * @param cdDir Flag to decide if the OLDDIR or new import directory is used. * @return Name of an imported function. * \todo Marked line is unsafe (function should be rewritten). **/ template std::string ImportDirectory::getFunctionName(dword dwFilenr, dword dwFuncnr, currdir cdDir) const { if (cdDir == OLDDIR) { // Unsafe if (m_vOldiid[dwFilenr].impdesc.OriginalFirstThunk) { return m_vOldiid[dwFilenr].originalfirstthunk[dwFuncnr].fname; } else { return m_vOldiid[dwFilenr].firstthunk[dwFuncnr].fname; } } else { if (m_vNewiid[dwFilenr].impdesc.OriginalFirstThunk) { return m_vNewiid[dwFilenr].originalfirstthunk[dwFuncnr].fname; } else { return m_vNewiid[dwFilenr].firstthunk[dwFuncnr].fname; } } } template void ImportDirectory::setFunctionName(dword dwFilenr, dword dwFuncnr, currdir cdDir, const std::string& functionName) { if (cdDir == OLDDIR) { // Unsafe if (m_vOldiid[dwFilenr].impdesc.OriginalFirstThunk) { m_vOldiid[dwFilenr].originalfirstthunk[dwFuncnr].fname = functionName; } else { m_vOldiid[dwFilenr].firstthunk[dwFuncnr].fname = functionName; } } else { if (m_vNewiid[dwFilenr].impdesc.OriginalFirstThunk) { m_vNewiid[dwFilenr].originalfirstthunk[dwFuncnr].fname = functionName; } else { m_vNewiid[dwFilenr].firstthunk[dwFuncnr].fname = functionName; } } } /** * Get the hint of an imported function. * @param dwFilenr Identifies which file should be checked. * @param dwFuncnr Identifies which function should be checked. * @param cdDir Flag to decide if the OLDDIR or new import directory is used. * @return Hint of an imported function. **/ template word ImportDirectory::getFunctionHint(dword dwFilenr, dword dwFuncnr, currdir cdDir) const { if (cdDir == OLDDIR) { if (m_vOldiid[dwFilenr].impdesc.OriginalFirstThunk) { return m_vOldiid[dwFilenr].originalfirstthunk[dwFuncnr].hint; } else { return m_vOldiid[dwFilenr].firstthunk[dwFuncnr].hint; } } else return m_vNewiid[dwFilenr].originalfirstthunk[dwFuncnr].hint; } template void ImportDirectory::setFunctionHint(dword dwFilenr, dword dwFuncnr, currdir cdDir, word value) { 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; } /** * 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. **/ template dword ImportDirectory::getNumberOfFiles(currdir cdDir) const { if (cdDir == OLDDIR) return static_cast(m_vOldiid.size()); else return static_cast(m_vNewiid.size()); } /** * Get the number of functions which are currently being imported from a specific file. * @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. **/ template dword ImportDirectory::getNumberOfFunctions(dword dwFilenr, currdir cdDir) const { if (cdDir == OLDDIR) return static_cast(m_vOldiid[dwFilenr].firstthunk.size()); else return static_cast(m_vNewiid[dwFilenr].firstthunk.size()); } /** * Read an import directory from a file. * \todo Check if streams failed. * @param strFilename Name of the file which will be read. * @param uiOffset Offset of the import directory (see #PeLib::PeHeader::getIDImportRVA). * @param uiSize Size of the import directory (see #PeLib::PeHeader::getIDImportSize). * @param pehHeader A valid PE header. **/ template int ImportDirectory::read(const std::string& strFilename, unsigned int uiOffset, unsigned int uiSize, const PeHeaderT& pehHeader) { std::ifstream ifFile(strFilename.c_str(), std::ios_base::binary); if (!ifFile) { return ERROR_OPENING_FILE; } unsigned int uiFileSize = fileSize(ifFile); if (uiFileSize < uiOffset + uiSize) { return ERROR_INVALID_FILE; } ifFile.seekg(uiOffset, std::ios_base::beg); std::vector vImportdirectory(uiSize); ifFile.read(reinterpret_cast(&vImportdirectory[0]), uiSize); PELIB_IMAGE_IMPORT_DIRECTORY iidCurr; unsigned int uiDesccounter = 0; InputBuffer inpBuffer(vImportdirectory); std::vector > vOldIidCurr; do // Read and store all descriptors { inpBuffer >> iidCurr.impdesc.OriginalFirstThunk; inpBuffer >> iidCurr.impdesc.TimeDateStamp; inpBuffer >> iidCurr.impdesc.ForwarderChain; inpBuffer >> iidCurr.impdesc.Name; inpBuffer >> iidCurr.impdesc.FirstThunk; if (iidCurr.impdesc.OriginalFirstThunk != 0 || iidCurr.impdesc.TimeDateStamp != 0 || iidCurr.impdesc.ForwarderChain != 0 || iidCurr.impdesc.Name != 0 || iidCurr.impdesc.FirstThunk != 0) { vOldIidCurr.push_back(iidCurr); } uiDesccounter++; if (uiSize < (uiDesccounter + 1) * PELIB_IMAGE_IMPORT_DESCRIPTOR::size()) break; } while (iidCurr.impdesc.OriginalFirstThunk != 0 || iidCurr.impdesc.TimeDateStamp != 0 || iidCurr.impdesc.ForwarderChain != 0 || iidCurr.impdesc.Name != 0 || iidCurr.impdesc.FirstThunk != 0); char namebuffer[2] = {0}; // Name for (unsigned int i=0;i(pehHeader.rvaToOffset(vOldIidCurr[i].impdesc.Name)), std::ios_base::beg); std::string dllname = ""; do { ifFile.read(namebuffer, 1); if (!ifFile || !namebuffer[0]) break; // reached end of file or 0-byte dllname += namebuffer; } while (true); vOldIidCurr[i].name = dllname; } // OriginalFirstThunk for (unsigned int i=0;i tdCurr; dword uiVaoft = vOldIidCurr[i].impdesc.OriginalFirstThunk; if (!uiVaoft) { continue; } ifFile.seekg(static_cast(pehHeader.rvaToOffset(uiVaoft)), std::ios_base::beg); do { if (uiFileSize < pehHeader.rvaToOffset(uiVaoft) + sizeof(tdCurr.itd.Ordinal)) { return ERROR_INVALID_FILE; } uiVaoft += sizeof(tdCurr.itd.Ordinal); ifFile.read(reinterpret_cast(&tdCurr.itd.Ordinal), sizeof(tdCurr.itd.Ordinal)); if (tdCurr.itd.Ordinal) vOldIidCurr[i].originalfirstthunk.push_back(tdCurr); } while (tdCurr.itd.Ordinal); } // FirstThunk for (unsigned int i=0;i tdCurr; ifFile.seekg(static_cast(pehHeader.rvaToOffset(uiVaoft)), std::ios_base::beg); do { if (uiFileSize < pehHeader.rvaToOffset(uiVaoft) + sizeof(tdCurr.itd.Ordinal)) { return ERROR_INVALID_FILE; } uiVaoft += sizeof(tdCurr.itd.Ordinal); ifFile.read(reinterpret_cast(&tdCurr.itd.Ordinal), sizeof(tdCurr.itd.Ordinal)); if (tdCurr.itd.Ordinal) vOldIidCurr[i].firstthunk.push_back(tdCurr); } while (tdCurr.itd.Ordinal); } // Names for (unsigned int i=0;i::IMAGE_ORDINAL_FLAG) { vOldIidCurr[i].originalfirstthunk[j].hint = 0; continue; } ifFile.seekg(static_cast(pehHeader.rvaToOffset(vOldIidCurr[i].originalfirstthunk[j].itd.Ordinal)), std::ios_base::beg); ifFile.read(reinterpret_cast(&vOldIidCurr[i].originalfirstthunk[j].hint), sizeof(vOldIidCurr[i].originalfirstthunk[j].hint)); if (!ifFile) return ERROR_INVALID_FILE; std::string funcname = ""; do { ifFile.read(namebuffer, 1); if (!ifFile || !namebuffer[0]) break; // reached end of file or 0-byte funcname += namebuffer; } while (true); vOldIidCurr[i].originalfirstthunk[j].fname = funcname; } } else { for (unsigned int j=0;j::IMAGE_ORDINAL_FLAG) { continue; } ifFile.seekg(static_cast(pehHeader.rvaToOffset(vOldIidCurr[i].firstthunk[j].itd.Ordinal)), std::ios_base::beg); ifFile.read(reinterpret_cast(&vOldIidCurr[i].firstthunk[j].hint), sizeof(vOldIidCurr[i].firstthunk[j].hint)); if (!ifFile) return ERROR_INVALID_FILE; std::string funcname = ""; do { ifFile.read(namebuffer, 1); if (!ifFile || !namebuffer[0]) break; // reached end of file or 0-byte funcname += namebuffer; } while (true); vOldIidCurr[i].firstthunk[j].fname = funcname; } } } std::swap(vOldIidCurr, m_vOldiid); return NO_ERROR; } /** * Rebuilds the import directory. * @param vBuffer Buffer the rebuilt import directory will be written to. * @param dwRva The RVA of the ImportDirectory in the file. * \todo uiSizeoffuncnames is not used. **/ template void ImportDirectory::rebuild(std::vector& vBuffer, dword dwRva, bool fixEntries) const { unsigned int uiImprva = dwRva; unsigned int uiSizeofdescriptors = (static_cast(m_vNewiid.size() + m_vOldiid.size()) + 1) * PELIB_IMAGE_IMPORT_DESCRIPTOR::size(); unsigned int uiSizeofdllnames = 0, uiSizeoffuncnames = 0; unsigned int uiSizeofoft = 0; for (unsigned int i=0;i(m_vNewiid[i].name.size()) + 1; uiSizeofoft += (static_cast(m_vNewiid[i].originalfirstthunk.size())+1) * PELIB_IMAGE_THUNK_DATA::size(); for(unsigned int j=0;j(m_vNewiid[i].originalfirstthunk[j].fname.size()) + 3); } } // for (unsigned int i=0;i(m_vNewiid[i].originalfirstthunk.size())+1) * PELIB_IMAGE_THUNK_DATA::size(); // } OutputBuffer obBuffer(vBuffer); // Rebuild IMAGE_IMPORT_DESCRIPTORS for (unsigned int i=0;i(m_vNewiid[j-1].originalfirstthunk.size()) + 1) * PELIB_IMAGE_THUNK_DATA::size(); } obBuffer << (fixEntries ? dwPoft : m_vNewiid[i].impdesc.OriginalFirstThunk); obBuffer << m_vNewiid[i].impdesc.TimeDateStamp; obBuffer << m_vNewiid[i].impdesc.ForwarderChain; dword dwPdll = uiSizeofdescriptors + uiSizeofoft + uiImprva + dllsize; obBuffer << (fixEntries ? dwPdll : m_vNewiid[i].impdesc.Name); obBuffer << (fixEntries ? dwPoft : m_vNewiid[i].impdesc.FirstThunk); dllsize += static_cast(m_vNewiid[i].name.size()) + 1; } obBuffer << (dword)0; obBuffer << (dword)0; obBuffer << (dword)0; obBuffer << (dword)0; obBuffer << (dword)0; unsigned int uiPfunc = uiSizeofdescriptors + uiSizeofoft + uiSizeofdllnames + uiImprva; // Rebuild original first thunk for (unsigned int i=0;i::IMAGE_ORDINAL_FLAG || fixEntries == false) { obBuffer << m_vNewiid[i].originalfirstthunk[j].itd.Ordinal; } else { obBuffer << uiPfunc; } uiPfunc += static_cast(m_vNewiid[i].originalfirstthunk[j].fname.size()) + 3; } obBuffer << (dword)0; } // Write dllnames into import directory for (unsigned int i=0;i(m_vNewiid[i].name.size())+1); } // Write function names into directory for (unsigned int i=0;i(m_vNewiid[i].originalfirstthunk[j].fname.size()) + 1); } } } /** * Removes a specific file and all functions of it from the import directory. * @param strFilename Name of the file which will be removed. **/ template int ImportDirectory::removeFile(const std::string& strFilename) { unsigned int oldSize = static_cast(m_vNewiid.size()); m_vNewiid.erase(std::remove_if(m_vNewiid.begin(), m_vNewiid.end(), std::bind2nd(std::mem_fun_ref(&PELIB_IMAGE_IMPORT_DIRECTORY::operator==), strFilename)), m_vNewiid.end()); return oldSize == m_vNewiid.size() ? 1 : 0; } /** * Removes a specific function from the import directory. * @param strFilename Name of the file which exports the function. * @param strFuncname Name of the imported function. **/ template int ImportDirectory::removeFunction(const std::string& strFilename, const std::string& strFuncname) { ImpDirFileIterator viPos = m_vNewiid.begin(); int notFound = 1; while (viPos != m_vNewiid.end()) { if (isEqualNc(viPos->name, strFilename)) { unsigned int oldSize = static_cast(viPos->originalfirstthunk.size()); viPos->originalfirstthunk.erase(std::remove_if(viPos->originalfirstthunk.begin(), viPos->originalfirstthunk.end(), std::bind2nd(std::mem_fun_ref(&PELIB_THUNK_DATA::equalFunctionName), strFuncname)), viPos->originalfirstthunk.end()); //viPos->originalfirstthunk.erase(std::remove_if(viPos->originalfirstthunk.begin(), viPos->originalfirstthunk.end(), std::bind2nd(CompPolicy(), strFuncname))); if (viPos->originalfirstthunk.size() != oldSize) notFound = 0; } ++viPos; } return notFound; } /** * Removes a specific function from the import directory. * @param strFilename Name of the file which exports the function. * @param wHint The hint of the function. **/ template int ImportDirectory::removeFunction(const std::string& strFilename, word wHint) { ImpDirFileIterator viPos = m_vNewiid.begin(); int notFound = 1; while (viPos != m_vNewiid.end()) { if (isEqualNc(viPos->name, strFilename)) { unsigned int oldSize = static_cast(viPos->originalfirstthunk.size()); viPos->originalfirstthunk.erase(std::remove_if(viPos->originalfirstthunk.begin(), viPos->originalfirstthunk.end(), std::bind2nd(std::mem_fun_ref(&PELIB_THUNK_DATA::equalHint), wHint)), viPos->originalfirstthunk.end()); unsigned int newPos = static_cast(viPos->originalfirstthunk.size()); if (viPos->originalfirstthunk.size() != oldSize) notFound = 0; } ++viPos; } return notFound; } /** * Writes the current import directory to a file. * @param strFilename Name of the file. * @param uiOffset File Offset of the new import directory. * @param uiRva RVA which belongs to that file offset. **/ template int ImportDirectory::write(const std::string& strFilename, unsigned int uiOffset, unsigned int uiRva) { std::fstream ofFile(strFilename.c_str(), std::ios_base::in); if (!ofFile) { ofFile.clear(); ofFile.open(strFilename.c_str(), std::ios_base::out | std::ios_base::binary); } else { ofFile.close(); ofFile.open(strFilename.c_str(), std::ios_base::in | std::ios_base::out | std::ios_base::binary); } if (!ofFile) { return ERROR_OPENING_FILE; } ofFile.seekp(uiOffset, std::ios_base::beg); std::vector vBuffer; rebuild(vBuffer, uiRva); ofFile.write(reinterpret_cast(&vBuffer[0]), vBuffer.size()); ofFile.close(); std::copy(m_vNewiid.begin(), m_vNewiid.end(), std::back_inserter(m_vOldiid)); m_vNewiid.clear(); return NO_ERROR; } /** * Returns the size of the import directory. * @return Size of the import directory. **/ template unsigned int ImportDirectory::size() const { // Only the descriptors of m_vOldiid must be rebuilt, not the data they point to. return std::accumulate(m_vNewiid.begin(), m_vNewiid.end(), 0, accumulate >) + (m_vOldiid.size() + 1) * PELIB_IMAGE_IMPORT_DESCRIPTOR::size(); } /** * @param strFilename Name of the imported file. * @param cdDir Flag to decide if the OLDDIR or new import directory is used. * @return FirstThunk value of an imported file. **/ template dword ImportDirectory::getFirstThunk(const std::string& strFilename, currdir cdDir) const { if (cdDir == OLDDIR) { return m_vOldiid[getFileIndex(strFilename, cdDir)].impdesc.FirstThunk; } else { return m_vNewiid[getFileIndex(strFilename, cdDir)].impdesc.FirstThunk; } } /** * @param strFilename Name of the imported file. * @param cdDir Flag to decide if the OLDDIR or new import directory is used. * @return OriginalFirstThunk value of an imported file. **/ template dword ImportDirectory::getOriginalFirstThunk(const std::string& strFilename, currdir cdDir) const { if (cdDir == OLDDIR) { return m_vOldiid[getFileIndex(strFilename, cdDir)].impdesc.OriginalFirstThunk; } else { return m_vNewiid[getFileIndex(strFilename, cdDir)].impdesc.OriginalFirstThunk; } } /** * @param strFilename Name of the imported file. * @param cdDir Flag to decide if the OLDDIR or new import directory is used. * @return ForwarderChain value of an imported file. **/ template dword ImportDirectory::getForwarderChain(const std::string& strFilename, currdir cdDir) const { if (cdDir == OLDDIR) { return m_vOldiid[getFileIndex(strFilename, cdDir)].impdesc.ForwarderChain; } else { return m_vNewiid[getFileIndex(strFilename, cdDir)].impdesc.ForwarderChain; } } /** * @param strFilename Name of the imported file. * @param cdDir Flag to decide if the OLDDIR or new import directory is used. * @return TimeDateStamp value of an imported file. **/ template dword ImportDirectory::getTimeDateStamp(const std::string& strFilename, currdir cdDir) const { if (cdDir == OLDDIR) { return m_vOldiid[getFileIndex(strFilename, cdDir)].impdesc.TimeDateStamp; } else { return m_vNewiid[getFileIndex(strFilename, cdDir)].impdesc.TimeDateStamp; } } template dword ImportDirectory::getRvaOfName(const std::string& strFilename, currdir cdDir) const { if (cdDir == OLDDIR) { return m_vOldiid[getFileIndex(strFilename, cdDir)].impdesc.Name; } else { return m_vNewiid[getFileIndex(strFilename, cdDir)].impdesc.Name; } } /** * @param strFilename Name of the imported file. * @param cdDir Flag to decide if the OLDDIR or new import directory is used. * @return FirstThunk value of an imported file. **/ template dword ImportDirectory::getFirstThunk(dword dwFilenr, currdir cdDir) const { if (cdDir == OLDDIR) { return m_vOldiid[dwFilenr].impdesc.FirstThunk; } else { return m_vNewiid[dwFilenr].impdesc.FirstThunk; } } template void ImportDirectory::setFirstThunk(dword dwFilenr, currdir cdDir, dword value) { if (cdDir == OLDDIR) { m_vOldiid[dwFilenr].impdesc.FirstThunk = value; } else { m_vNewiid[dwFilenr].impdesc.FirstThunk = value; } } /** * @param strFilename Name of the imported file. * @param cdDir Flag to decide if the OLDDIR or new import directory is used. * @return OriginalFirstThunk value of an imported file. **/ template dword ImportDirectory::getOriginalFirstThunk(dword dwFilenr, currdir cdDir) const { if (cdDir == OLDDIR) { return m_vOldiid[dwFilenr].impdesc.OriginalFirstThunk; } else { return m_vNewiid[dwFilenr].impdesc.OriginalFirstThunk; } } template void ImportDirectory::setOriginalFirstThunk(dword dwFilenr, currdir cdDir, dword value) { if (cdDir == OLDDIR) { m_vOldiid[dwFilenr].impdesc.OriginalFirstThunk = value; } else { m_vNewiid[dwFilenr].impdesc.OriginalFirstThunk = value; } } /** * @param strFilename Name of the imported file. * @param cdDir Flag to decide if the OLDDIR or new import directory is used. * @return ForwarderChain value of an imported file. **/ template dword ImportDirectory::getForwarderChain(dword dwFilenr, currdir cdDir) const { if (cdDir == OLDDIR) { return m_vOldiid[dwFilenr].impdesc.ForwarderChain; } else { return m_vNewiid[dwFilenr].impdesc.ForwarderChain; } } template void ImportDirectory::setForwarderChain(dword dwFilenr, currdir cdDir, dword value) { if (cdDir == OLDDIR) { m_vOldiid[dwFilenr].impdesc.ForwarderChain = value; } else { m_vNewiid[dwFilenr].impdesc.ForwarderChain = value; } } /** * @param strFilename Name of the imported file. * @param cdDir Flag to decide if the OLDDIR or new import directory is used. * @return TimeDateStamp value of an imported file. **/ template dword ImportDirectory::getTimeDateStamp(dword dwFilenr, currdir cdDir) const { if (cdDir == OLDDIR) { return m_vOldiid[dwFilenr].impdesc.TimeDateStamp; } else { return m_vNewiid[dwFilenr].impdesc.TimeDateStamp; } } template void ImportDirectory::setTimeDateStamp(dword dwFilenr, currdir cdDir, dword value) { if (cdDir == OLDDIR) { m_vOldiid[dwFilenr].impdesc.TimeDateStamp = value; } else { m_vNewiid[dwFilenr].impdesc.TimeDateStamp = value; } } template dword ImportDirectory::getRvaOfName(dword dwFilenr, currdir cdDir) const { if (cdDir == OLDDIR) { return m_vOldiid[dwFilenr].impdesc.Name; } else { return m_vNewiid[dwFilenr].impdesc.Name; } } template void ImportDirectory::setRvaOfName(dword dwFilenr, currdir cdDir, dword value) { if (cdDir == OLDDIR) { m_vOldiid[dwFilenr].impdesc.Name = value; } else { m_vNewiid[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. * @return FirstThunk value of an imported function. **/ template dword ImportDirectory::getFirstThunk(dword dwFilenr, dword dwFuncnr, currdir cdDir) const { if (cdDir == OLDDIR) return m_vOldiid[dwFilenr].firstthunk[dwFuncnr].itd.Ordinal; else return m_vNewiid[dwFilenr].firstthunk[dwFuncnr].itd.Ordinal; } template void ImportDirectory::setFirstThunk(dword dwFilenr, dword dwFuncnr, currdir cdDir, dword value) { if (cdDir == OLDDIR) m_vOldiid[dwFilenr].firstthunk[dwFuncnr].itd.Ordinal = value; else m_vNewiid[dwFilenr].firstthunk[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. * @return OriginalFirstThunk value of an imported function. **/ template dword ImportDirectory::getOriginalFirstThunk(dword dwFilenr, dword dwFuncnr, currdir cdDir) const { if (cdDir == OLDDIR) return m_vOldiid[dwFilenr].originalfirstthunk[dwFuncnr].itd.Ordinal; else return m_vNewiid[dwFilenr].originalfirstthunk[dwFuncnr].itd.Ordinal; } template void ImportDirectory::setOriginalFirstThunk(dword dwFilenr, dword dwFuncnr, currdir cdDir, dword value) { if (cdDir == OLDDIR) m_vOldiid[dwFilenr].originalfirstthunk[dwFuncnr].itd.Ordinal = value; else m_vNewiid[dwFilenr].originalfirstthunk[dwFuncnr].itd.Ordinal = value; } typedef ImportDirectory<32> ImportDirectory32; typedef ImportDirectory<64> ImportDirectory64; } #endif