retdec
ImportDirectory.h
Go to the documentation of this file.
1 /*
2 * ImportDirectory.h - Part of the PeLib library.
3 *
4 * Copyright (c) 2004 - 2005 Sebastian Porst (webmaster@the-interweb.com)
5 * All rights reserved.
6 *
7 * This software is licensed under the zlib/libpng License.
8 * For more details see http://www.opensource.org/licenses/zlib-license.php
9 * or the license information file (license.htm) in the root directory
10 * of PeLib.
11 */
12 
13 #ifndef RETDEC_PELIB_IMPORTDIRECTORY_H
14 #define RETDEC_PELIB_IMPORTDIRECTORY_H
15 
16 #include <set>
17 #include <unordered_map>
18 
19 #include "retdec/pelib/PeLibAux.h"
21 
22 namespace PeLib
23 {
25  enum currdir {OLDDIR = 1, NEWDIR};
26 
27  class PeLibException;
28 
30 
42  {
43  typedef typename std::vector<PELIB_IMAGE_IMPORT_DIRECTORY>::iterator ImpDirFileIterator;
44  typedef typename std::vector<PELIB_IMAGE_IMPORT_DIRECTORY>::const_iterator ConstImpDirFileIterator;
45 
46  private:
48  std::vector<PELIB_IMAGE_IMPORT_DIRECTORY> m_vOldiid;
50  std::vector<PELIB_IMAGE_IMPORT_DIRECTORY> m_vNewiid;
52  std::vector<std::pair<unsigned int, unsigned int>> m_occupiedAddresses;
54  std::uint64_t m_ordinalMask;
58  std::size_t m_thunkSize;
59 
60  // I can't convince Borland C++ to compile the function outside of the class declaration.
61  // That's why the function definition is here.
63  template<typename T> bool hasFunction(std::string strFilename, T value, bool(PELIB_THUNK_DATA::* comp)(T) const) const
64  {
65  ConstImpDirFileIterator FileIter = m_vOldiid.begin();
66  ConstImpDirFileIterator EndIter = m_vOldiid.end();
67 
68  for (int i=0;i<=1;i++) // Loop once for m_vOldiid and once for m_vNewiid
69  {
70  do
71  {
72  FileIter = std::find_if(
73  FileIter,
74  EndIter,
75  [&](const auto& i) { return i == strFilename; }
76  );
77 
78  if (FileIter != EndIter)
79  {
80  auto Iter = std::find_if(
81  FileIter->originalfirstthunk.begin(),
82  FileIter->originalfirstthunk.end(),
83  std::bind(comp, std::placeholders::_1, value)
84  );
85  if (Iter != FileIter->originalfirstthunk.end())
86  {
87  return true;
88  }
89  ++FileIter;
90  }
91  }
92  while (FileIter != EndIter);
93 
94  FileIter = m_vNewiid.begin();
95  EndIter = m_vNewiid.end();
96  }
97 
98  return false;
99  }
100 
101  public:
102 
105  {
106  m_ordinalMask = 0x80000000;
107  m_thunkSize = 4;
108  }
109 
111  int addFunction(const std::string& strFilename, std::uint16_t wHint); // EXPORT _byHint
113  int addFunction(const std::string& strFilename, const std::string& strFuncname); // EXPORT _byName
114 
116  unsigned int getFileIndex(const std::string& strFilename, currdir cdDir) const; // EXPORT
118  unsigned int getFunctionIndex(const std::string& strFilename, const std::string& strFuncname, currdir cdDir) const; // EXPORT
119 
121  std::string getFileName(std::uint32_t dwFilenr, currdir cdDir) const; // EXPORT
122 
123  void setFileName(std::uint32_t filenr, currdir cdDir, const std::string& name); // EXPORT
124 
126  LoaderError loaderError() const;
127  void setLoaderError(LoaderError ldrError);
128 
130  std::uint16_t getFunctionHint(std::uint32_t dwFilenr, std::uint32_t dwFuncnr, currdir cdDir) const; // EXPORT
131  void setFunctionHint(std::uint32_t dwFilenr, std::uint32_t dwFuncnr, currdir cdDir, std::uint16_t value); // EXPORT
133  std::string getFunctionName(std::uint32_t dwFilenr, std::uint32_t dwFuncnr, currdir cdDir) const; // EXPORT
134  void setFunctionName(std::uint32_t dwFilenr, std::uint32_t dwFuncnr, currdir cdDir, const std::string& functionName); // EXPORT
136  std::uint32_t getNumberOfFiles(currdir cdDir) const; // EXPORT
138  std::uint32_t getNumberOfFunctions(std::uint32_t dwFilenr, currdir cdDir) const; // EXPORT
140  int read(ImageLoader & imageLoader); // EXPORT
142  void writePointer(OutputBuffer & obBuffer, std::uint64_t pointerValue);
144  void rebuild(std::vector<std::uint8_t>& vBuffer, std::uint32_t dwRva, bool fixEntries = true); // EXPORT
146  int removeFile(const std::string& strFilename); // EXPORT
148  int removeFunction(const std::string& strFilename, const std::string& strFuncname); // EXPORT _byName
150  int removeFunction(const std::string& strFilename, std::uint16_t wHint); // EXPORT _byHint
152  unsigned int calculateSize(std::uint32_t pointerSize) const; // EXPORT
154  int write(const std::string& strFilename, std::uint32_t uiOffset, std::uint32_t uiRva, std::uint32_t pointerSize); // EXPORT
156  void setPointerSize(std::uint32_t pointerSize);
157 
159  std::uint32_t getFirstThunk(std::uint32_t dwFilenr, std::uint32_t dwFuncnr, currdir cdDir) const; // EXPORT _byNumber
160  void setFirstThunk(std::uint32_t dwFilenr, std::uint32_t dwFuncnr, currdir cdDir, std::uint32_t value); // EXPORT _byNumber
162  std::uint32_t getOriginalFirstThunk(std::uint32_t dwFilenr, std::uint32_t dwFuncnr, currdir cdDir) const; // EXPORT _byNumber
163  void setOriginalFirstThunk(std::uint32_t dwFilenr, std::uint32_t dwFuncnr, currdir cdDir, std::uint32_t value); // EXPORT
164 
165 // std::uint64_t getFirstThunk(const std::string& strFilename, const std::string& strFuncname, currdir cdDir) const throw (PeLibException);
166 // std::uint64_t getOriginalFirstThunk(const std::string& strFilename, const std::string& strFuncname, currdir cdDir) const throw (PeLibException);
167 
169  std::uint32_t getFirstThunk(const std::string& strFilename, currdir cdDir) const; // EXPORT _byName
171  std::uint32_t getOriginalFirstThunk(const std::string& strFilename, currdir cdDir) const; // EXPORT _byName
173  std::uint32_t getForwarderChain(const std::string& strFilename, currdir cdDir) const; // EXPORT _byName
174  std::uint32_t getRvaOfName(const std::string& strFilename, currdir cdDir) const; // EXPORT _byName
176  std::uint32_t getTimeDateStamp(const std::string& strFilename, currdir cdDir) const; // EXPORT _byName
177 
179  std::uint32_t getFirstThunk(std::uint32_t dwFilenr, currdir cdDir) const; // EXPORT
180  void setFirstThunk(std::uint32_t dwFilenr, currdir cdDir, std::uint32_t value); // EXPORT _byNumber_function
182  std::uint32_t getOriginalFirstThunk(std::uint32_t dwFilenr, currdir cdDir) const; // EXPORT
183  void setOriginalFirstThunk(std::uint32_t dwFilenr, currdir cdDir, std::uint32_t value); // EXPORT _byNumber_function
185  std::uint32_t getForwarderChain(std::uint32_t dwFilenr, currdir cdDir) const; // EXPORT _byNumber
186  void setForwarderChain(std::uint32_t dwFilenr, currdir cdDir, std::uint32_t value); // EXPORT _byNumber_function
187  std::uint32_t getRvaOfName(std::uint32_t dwFilenr, currdir cdDir) const; // EXPORT _byNumber
188  void setRvaOfName(std::uint32_t dwFilenr, currdir cdDir, std::uint32_t value); // EXPORT
190  std::uint32_t getTimeDateStamp(std::uint32_t dwFilenr, currdir cdDir) const; // EXPORT
191  void setTimeDateStamp(std::uint32_t dwFilenr, currdir cdDir, std::uint32_t value); // EXPORT _byNumber
192 
193  const std::vector<std::pair<unsigned int, unsigned int>>& getOccupiedAddresses() const;
194 
195 // std::uint16_t getFunctionHint(const std::string& strFilename, const std::string& strFuncname, currdir cdDir) const throw (PeLibException);
196  };
197 
208  inline bool hasValidOriginalFirstThunk(const PELIB_IMAGE_IMPORT_DESCRIPTOR& impDesc, const ImageLoader & imageLoader)
209  {
210  return (imageLoader.getSizeOfHeaders() <= impDesc.OriginalFirstThunk && impDesc.OriginalFirstThunk < imageLoader.getSizeOfImage());
211  }
212 
220  inline
221  int ImportDirectory::addFunction(const std::string& strFilename, std::uint16_t wHint)
222  {
223  if (hasFunction(strFilename, wHint, &PELIB_THUNK_DATA::equalHint))
224  {
225  return ERROR_DUPLICATE_ENTRY;
226  }
227 
228  // Find the imported file.
229  ImpDirFileIterator FileIter = std::find_if(
230  m_vNewiid.begin(),
231  m_vNewiid.end(),
232  [&](const auto& i) { return i == strFilename; }
233  );
234 
236  PELIB_THUNK_DATA td;
237  td.hint = wHint;
238  td.itd.Ordinal = wHint /* | PELIB_IMAGE_ORDINAL_FLAGS::PELIB_IMAGE_ORDINAL_FLAG */;
239  iid.name = strFilename;
240  if (FileIter == m_vNewiid.end())
241  {
242  iid.originalfirstthunk.push_back(td);
243  iid.firstthunk.push_back(td);
244  m_vNewiid.push_back(iid);
245  }
246  else
247  {
248  FileIter->originalfirstthunk.push_back(td);
249  FileIter->firstthunk.push_back(td);
250  }
251 
252  return ERROR_NONE;
253  }
254 
260  inline
261  int ImportDirectory::addFunction(const std::string& strFilename, const std::string& strFuncname)
262  {
263  if (hasFunction(strFilename, strFuncname, &PELIB_THUNK_DATA::equalFunctionName))
264  {
265  return ERROR_DUPLICATE_ENTRY;
266  }
267 
268  // Find the imported file.
269  ImpDirFileIterator FileIter = std::find_if(
270  m_vNewiid.begin(),
271  m_vNewiid.end(),
272  [&](const auto& i) { return i == strFilename; }
273  );
274 
276  PELIB_THUNK_DATA td;
277  td.fname = strFuncname;
278  iid.name = strFilename;
279  if (FileIter == m_vNewiid.end())
280  {
281  iid.originalfirstthunk.push_back(td);
282  iid.firstthunk.push_back(td);
283  m_vNewiid.push_back(iid);
284  }
285  else
286  {
287  FileIter->originalfirstthunk.push_back(td);
288  FileIter->firstthunk.push_back(td);
289  }
290 
291  return ERROR_NONE;
292  }
293 
301  inline
302  unsigned int ImportDirectory::getFileIndex(const std::string& strFilename, currdir cdDir) const
303  {
304  const std::vector<PELIB_IMAGE_IMPORT_DIRECTORY>* currDir;
305 
306  if (cdDir == OLDDIR)
307  {
308  currDir = &m_vOldiid;
309  }
310  else
311  {
312  currDir = &m_vNewiid;
313  }
314 
315  ConstImpDirFileIterator FileIter = std::find_if(
316  currDir->begin(),
317  currDir->end(),
318  [&](const auto& i) { return i == strFilename; }
319  );
320 
321  if (FileIter != currDir->end())
322  {
323  return static_cast<unsigned int>(std::distance(currDir->begin(), FileIter));
324  }
325  else
326  {
327  return -1;
328  // throw Exceptions::InvalidName(ImportDirectoryId, __LINE__);
329  }
330 
331  return ERROR_NONE;
332  }
333 
341  inline
342  unsigned int ImportDirectory::getFunctionIndex(const std::string& strFilename, const std::string& strFuncname, currdir cdDir) const
343  {
344  unsigned int uiFile = getFileIndex(strFilename, cdDir);
345 
346  for (unsigned int i=0;i<getNumberOfFunctions(uiFile, cdDir);i++)
347  {
348  if (getFunctionName(uiFile, i, cdDir) == strFuncname) return i;
349  }
350 
351  return -1;
352  }
353 
360  inline
361  std::string ImportDirectory::getFileName(std::uint32_t dwFilenr, currdir cdDir) const
362  {
363  if (cdDir == OLDDIR) return m_vOldiid[dwFilenr].name;
364  else return m_vNewiid[dwFilenr].name;
365  }
366 
367  inline
368  void ImportDirectory::setFileName(std::uint32_t filenr, currdir cdDir, const std::string& name)
369  {
370  if (cdDir == OLDDIR) m_vOldiid[filenr].name = name;
371  else m_vNewiid[filenr].name = name;
372  }
373 
382  inline
383  std::string ImportDirectory::getFunctionName(std::uint32_t dwFilenr, std::uint32_t dwFuncnr, currdir cdDir) const
384  {
385  if (cdDir == OLDDIR)
386  {
387  // Unsafe
388  // mz: fix #1189
389  if (m_vOldiid[dwFilenr].impdesc.OriginalFirstThunk && dwFuncnr < m_vOldiid[dwFilenr].originalfirstthunk.size())
390  {
391  return m_vOldiid[dwFilenr].originalfirstthunk[dwFuncnr].fname;
392  }
393  else
394  {
395  return m_vOldiid[dwFilenr].firstthunk[dwFuncnr].fname;
396  }
397  }
398  else
399  {
400  if (m_vNewiid[dwFilenr].impdesc.OriginalFirstThunk)
401  {
402  return m_vNewiid[dwFilenr].originalfirstthunk[dwFuncnr].fname;
403  }
404  else
405  {
406  return m_vNewiid[dwFilenr].firstthunk[dwFuncnr].fname;
407  }
408  }
409  }
410 
411  inline
412  void ImportDirectory::setFunctionName(std::uint32_t dwFilenr, std::uint32_t dwFuncnr, currdir cdDir, const std::string& functionName)
413  {
414  if (cdDir == OLDDIR)
415  {
416  // Unsafe
417  if (m_vOldiid[dwFilenr].impdesc.OriginalFirstThunk)
418  {
419  m_vOldiid[dwFilenr].originalfirstthunk[dwFuncnr].fname = functionName;
420  }
421  else
422  {
423  m_vOldiid[dwFilenr].firstthunk[dwFuncnr].fname = functionName;
424  }
425  }
426  else
427  {
428  if (m_vNewiid[dwFilenr].impdesc.OriginalFirstThunk)
429  {
430  m_vNewiid[dwFilenr].originalfirstthunk[dwFuncnr].fname = functionName;
431  }
432  else
433  {
434  m_vNewiid[dwFilenr].firstthunk[dwFuncnr].fname = functionName;
435  }
436  }
437  }
438 
442  inline
444  {
445  return m_ldrError;
446  }
447 
448  inline
450  {
451  // Do not override an existing loader error
452  if (m_ldrError == LDR_ERROR_NONE)
453  {
454  m_ldrError = ldrError;
455  }
456  }
457 
465  inline
466  std::uint16_t ImportDirectory::getFunctionHint(std::uint32_t dwFilenr, std::uint32_t dwFuncnr, currdir cdDir) const
467  {
468  if (cdDir == OLDDIR)
469  {
470  // mz: fix #1189
471  if (m_vOldiid[dwFilenr].impdesc.OriginalFirstThunk && dwFuncnr < m_vOldiid[dwFilenr].originalfirstthunk.size())
472  {
473  return m_vOldiid[dwFilenr].originalfirstthunk[dwFuncnr].hint;
474  }
475  else
476  {
477  return m_vOldiid[dwFilenr].firstthunk[dwFuncnr].hint;
478  }
479  }
480  else return m_vNewiid[dwFilenr].originalfirstthunk[dwFuncnr].hint;
481  }
482 
483  inline
484  void ImportDirectory::setFunctionHint(std::uint32_t dwFilenr, std::uint32_t dwFuncnr, currdir cdDir, std::uint16_t value)
485  {
486  if (cdDir == OLDDIR)
487  {
488  if (m_vOldiid[dwFilenr].impdesc.OriginalFirstThunk)
489  {
490  m_vOldiid[dwFilenr].originalfirstthunk[dwFuncnr].hint = value;
491  }
492  else
493  {
494  m_vOldiid[dwFilenr].firstthunk[dwFuncnr].hint = value;
495  }
496  }
497  else m_vNewiid[dwFilenr].originalfirstthunk[dwFuncnr].hint = value;
498  }
499 
505  inline
506  std::uint32_t ImportDirectory::getNumberOfFiles(currdir cdDir) const
507  {
508  std::size_t numFiles = (cdDir == OLDDIR) ? m_vOldiid.size() : m_vNewiid.size();
509 
510  return static_cast<std::uint32_t>(numFiles);
511  }
512 
519  inline
520  std::uint32_t ImportDirectory::getNumberOfFunctions(std::uint32_t dwFilenr, currdir cdDir) const
521  {
522  if (cdDir == OLDDIR) return static_cast<unsigned int>(m_vOldiid[dwFilenr].firstthunk.size());
523  else return static_cast<unsigned int>(m_vNewiid[dwFilenr].firstthunk.size());
524  }
525 
526  inline bool isInvalidOrdinal(std::uint64_t ordinal, std::uint64_t ordinalMask, std::uint64_t sizeOfImage)
527  {
528  // Check for invalid name
529  if((ordinal & ordinalMask) == 0)
530  {
531  // Any name RVA that goes out of image is considered invalid
532  if(ordinal >= sizeOfImage)
533  {
534  return true;
535  }
536  }
537  else
538  {
539  // Mask out the ordinal bit. Then, any ordinal must not be larger than 0xFFFF
540  ordinal = ordinal & ~ordinalMask;
541  return (ordinal >> 0x10) != 0;
542  }
543 
544  return false;
545  }
546 
552  inline void ImportDirectory::setPointerSize(std::uint32_t pointerSize)
553  {
554  m_thunkSize = pointerSize;
555  m_ordinalMask = (uint64_t)1 << ((pointerSize * 8) - 1);
556  }
557 
558  inline bool isBadImportName(const std::string & importName)
559  {
560  // The name be of nonzero length
561  if(importName.size() == 0)
562  return true;
563 
564  // We don't accept space as the first character, but we accept space in the middle
565  // retdec-regression-tests\tools\fileinfo\bugs\issue-460-hash-from-empty-string\000b1f22029c979c27c7310712cae66b8ade37378023487277ad7c86d59a34f6
566  if(importName[0] <= 0x20)
567  return true;
568 
569  // All characters of the name must be a valid (printable) ASCII char
570  // Sample: retdec-regression-tests\tools\fileinfo\features\malformed-imports-exports\7CE5BB5CA99B3570514AF03782545D41213A77A0F93D4AAC8269823A8D3A58EF.dat
571  for(unsigned char singleChar : importName)
572  {
573  if(singleChar < 0x20 || singleChar >= 0x7f)
574  return true;
575  }
576 
577  // We didn't find any reason to consider this import invalid
578  return false;
579  }
580 
586  inline
588  {
589  std::uint64_t OrdinalMask = imageLoader.getOrdinalMask();
590  std::uint32_t SizeOfImage = imageLoader.getSizeOfImage();
591  std::uint32_t uiIndex;
592  std::uint32_t rvaBegin = imageLoader.getDataDirRva(PELIB_IMAGE_DIRECTORY_ENTRY_IMPORT);
593  std::uint32_t rva = rvaBegin;
594 
595  setPointerSize(imageLoader.getPointerSize());
597 
598  // Verify whether the import directory is within the image
599  if(rva > SizeOfImage)
600  {
602  return ERROR_INVALID_FILE;
603  }
604 
605  // For tracking unique imported DLLs
606  std::vector<PELIB_IMAGE_IMPORT_DIRECTORY> vOldIidCurr;
607  std::unordered_map<std::string, int> uniqueDllList;
608  std::uint32_t uiDescCounter = 0;
609 
610  // Read and store all descriptors
611  for (;;)
612  {
614 
615  // If the required range is within the file, then we read the data.
616  // If not, it's RVA may still be valid due mapping -> keep zeros.
617  // Example sample: de0dea00414015bacbcbfc1fa53af9f6731522687d82f5de2e9402410488d190
618  // (single entry in the import directory at file offset 0x3EC4 followed by end-of-file)
619  if ((rva + sizeof(PELIB_IMAGE_IMPORT_DESCRIPTOR)) >= SizeOfImage)
620  {
622  break;
623  }
624 
625  // The offset is within the file range -> read it from the image
626  imageLoader.readImage(&iidCurr.impdesc, rva, sizeof(PELIB_IMAGE_IMPORT_DESCRIPTOR));
627  rva += sizeof(PELIB_IMAGE_IMPORT_DESCRIPTOR);
628  uiDescCounter++;
629 
630  // If Name or FirstThunk are 0, this descriptor is considered as null-terminator.
631  if (iidCurr.impdesc.Name == 0 || iidCurr.impdesc.FirstThunk == 0)
632  break;
633 
634  // We ignore import names that go beyond the file
635  if (iidCurr.impdesc.Name > SizeOfImage)
636  {
638  break;
639  }
640 
641  if (iidCurr.impdesc.FirstThunk > SizeOfImage)
642  {
644  break;
645  }
646 
647  // Retrieve the library name from the image as ASCIIZ string
648  imageLoader.readString(iidCurr.name, iidCurr.impdesc.Name, IMPORT_LIBRARY_MAX_LENGTH);
649 
650  // Sample: 0BBA9D483A5E26932C1BA5904EA8FA2E063E0419C7B8A6342814266E96E1CEA2
651  // 4 imports all invalid names. We stop parsing the imports at an invalid entry,
652  // but we won't say that the file is invalid
653  if (isBadImportName(iidCurr.name))
654  {
656  break;
657  }
658 
659  // Ignore too large import directories
660  // Sample: CCE461B6EB23728BA3B8A97B9BE84C0FB9175DB31B9949E64144198AB3F702CE, # of impdesc 0x6253 (invalid)
661  // Sample: 395e64e7071d35cb85d8312095aede5166db731aac44920679eee5c7637cc58c, # of impdesc 0x0131 (valid)
662  if (uniqueDllList.find(iidCurr.name) == uniqueDllList.end())
663  {
664  // Remember that the DLL was imported before
665  uniqueDllList.emplace(iidCurr.name, 1);
666 
667  // Check the total number of imported DLLs
668  if(uniqueDllList.size() > PELIB_MAX_IMPORT_DLLS)
669  {
671  break;
672  }
673  }
674 
675  // Mark the range occupied by name
676  // +1 for null terminator
677  // If the end address is even, we need to align it by 2, so next name always starts at even address
678  m_occupiedAddresses.emplace_back(iidCurr.impdesc.Name, iidCurr.impdesc.Name + iidCurr.name.length() + 1);
679  if (!(m_occupiedAddresses.back().second & 1))
680  m_occupiedAddresses.back().second += 1;
681 
682  // Push the import descriptor into the vector
683  vOldIidCurr.push_back(std::move(iidCurr));
684  }
685 
686  // Space occupied by import descriptors
687  m_occupiedAddresses.emplace_back(rvaBegin, rva);
688 
689  // OriginalFirstThunk - ILT
690  for(std::size_t i = 0; i < vOldIidCurr.size(); i++)
691  {
692  // OriginalFirstThunk is only valid when pointing within the image, excluding headers
693  if(!hasValidOriginalFirstThunk(vOldIidCurr[i].impdesc, imageLoader))
694  continue;
695  std::uint32_t thunkRva = vOldIidCurr[i].impdesc.OriginalFirstThunk;
696 
697  PELIB_THUNK_DATA tdCurr;
698 
699  for(uiIndex = 0; ; uiIndex++)
700  {
701  // Read single value (32-bit or 64-bit) from the thunk chain
702  if(!imageLoader.readPointer(thunkRva, tdCurr.itd.Ordinal))
703  break;
704 
705  // Are we at the end of the list?
706  if (tdCurr.itd.Ordinal == 0)
707  break;
708 
709  // Did we exceed the count of imported functions?
710  if(uiIndex >= PELIB_MAX_IMPORTED_FUNCTIONS)
711  {
713  break;
714  }
715 
716  // Check samples that have import name out of the image
717  // Sample: CCE461B6EB23728BA3B8A97B9BE84C0FB9175DB31B9949E64144198AB3F702CE
718  // Import by ordinal must be lower-word only; any ordinal that is greater than 0xFFFF is invalid.
719  // Sample: 7CE5BB5CA99B3570514AF03782545D41213A77A0F93D4AAC8269823A8D3A58EF
720  if(isInvalidOrdinal(tdCurr.itd.Ordinal, OrdinalMask, SizeOfImage))
721  {
723  break;
724  }
725 
726  // Insert ordinal to the list
727  vOldIidCurr[i].originalfirstthunk.push_back(tdCurr);
728  thunkRva += m_thunkSize;
729  }
730 
731  // Space occupied by OriginalFirstThunks
732  // -1 because we need open interval
733  if (vOldIidCurr[i].impdesc.OriginalFirstThunk < thunkRva)
734  m_occupiedAddresses.emplace_back(vOldIidCurr[i].impdesc.OriginalFirstThunk, thunkRva - 1);
735  }
736 
737  // FirstThunk - IAT
738  std::set<std::uint32_t> seenOffsets;
739  for (std::size_t i = 0; i < vOldIidCurr.size(); i++)
740  {
741  std::uint32_t thunkRva = vOldIidCurr[i].impdesc.FirstThunk;
742  bool hasValidIlt = hasValidOriginalFirstThunk(vOldIidCurr[i].impdesc, imageLoader);
743 
744  if (thunkRva >= imageLoader.getSizeOfImage())
745  {
747  return ERROR_INVALID_FILE;
748  }
749  if (seenOffsets.count(thunkRva))
750  {
751  continue;
752  }
753  seenOffsets.insert(thunkRva);
754  PELIB_THUNK_DATA tdCurr;
755 
756  for(uiIndex = 0; ; uiIndex++)
757  {
758  if ((thunkRva + m_thunkSize) > SizeOfImage)
759  {
761  return ERROR_INVALID_FILE;
762  }
763 
764  // Read the import thunk. Make sure it's initialized in case the file read fails
765  tdCurr.itd.Ordinal = 0;
766  imageLoader.readPointer(thunkRva, tdCurr.itd.Ordinal);
767  thunkRva += m_thunkSize;
768 
769  // Are we at the end of the list?
770  if (tdCurr.itd.Ordinal == 0)
771  break;
772 
773  // Did the number of imported functions exceede maximum?
774  if(uiIndex >= PELIB_MAX_IMPORTED_FUNCTIONS)
775  {
777  return ERROR_INVALID_FILE;
778  }
779 
780  // Check samples that have import name out of the image
781  // Sample: CCE461B6EB23728BA3B8A97B9BE84C0FB9175DB31B9949E64144198AB3F702CE
782  //if(isInvalidOrdinal(tdCurr.itd.Ordinal, OrdinalMask, SizeOfImage))
783  // break;
784 
785  vOldIidCurr[i].firstthunk.push_back(tdCurr);
786 
787  // If this import descriptor has valid ILT, then size of IAT is determined from the size of ILT
788  if (hasValidIlt && vOldIidCurr[i].originalfirstthunk.size() == vOldIidCurr[i].firstthunk.size())
789  {
790  // We need to move this offset in this case because otherwise we would calculate the occupied addresses wrongly
791  thunkRva += m_thunkSize;
792  break;
793  }
794  }
795 
796  // Space occupied by FirstThunks
797  // -1 because we need open interval
798  if (vOldIidCurr[i].impdesc.FirstThunk < thunkRva)
799  m_occupiedAddresses.emplace_back(vOldIidCurr[i].impdesc.FirstThunk, thunkRva - 1);
800  }
801 
802  // Names
803  for (unsigned int i=0;i<vOldIidCurr.size();i++)
804  {
805  std::vector<PELIB_THUNK_DATA> & thunkVector = hasValidOriginalFirstThunk(vOldIidCurr[i].impdesc, imageLoader) ?
806  vOldIidCurr[i].originalfirstthunk :
807  vOldIidCurr[i].firstthunk;
808  for (auto & thunkData : thunkVector)
809  {
810  if (thunkData.itd.Ordinal & OrdinalMask)
811  {
812  thunkData.hint = 0;
813  continue;
814  }
815 
816  if(imageLoader.readImage(&thunkData.hint, thunkData.itd.Ordinal, sizeof(std::uint16_t)) != sizeof(std::uint16_t))
817  {
819  return ERROR_INVALID_FILE;
820  }
821 
822  imageLoader.readString(thunkData.fname, thunkData.itd.Ordinal + sizeof(std::uint16_t), IMPORT_SYMBOL_MAX_LENGTH);
823 
824  // Space occupied by names
825  // +1 for null terminator
826  // If the end address is even, we need to align it by 2, so next name always starts at even address
827  m_occupiedAddresses.emplace_back(
828  static_cast<unsigned int>(thunkData.itd.Ordinal),
829  static_cast<unsigned int>(thunkData.itd.Ordinal + sizeof(thunkData.hint) + thunkData.fname.length() + 1)
830  );
831  if (!(m_occupiedAddresses.back().second & 1))
832  m_occupiedAddresses.back().second += 1;
833  }
834  }
835 
836  std::swap(vOldIidCurr, m_vOldiid);
837  return ERROR_NONE;
838  }
839 
840  inline void ImportDirectory::writePointer(OutputBuffer & obBuffer, std::uint64_t pointerValue)
841  {
842  if(m_thunkSize == sizeof(std::uint32_t))
843  {
844  std::uint32_t pointerValue32 = (std::uint32_t)pointerValue;
845  obBuffer << pointerValue32;
846  }
847  else
848  {
849  obBuffer << pointerValue;
850  }
851  }
852 
860  inline
861  void ImportDirectory::rebuild(std::vector<std::uint8_t>& vBuffer, std::uint32_t dwRva, bool fixEntries)
862  {
863  unsigned int uiImprva = dwRva;
864  unsigned int uiSizeofdescriptors = (static_cast<unsigned int>(m_vNewiid.size() + m_vOldiid.size()) + 1) * PELIB_IMAGE_IMPORT_DESCRIPTOR::size();
865 
866  unsigned int uiSizeofdllnames = 0, uiSizeoffuncnames = 0;
867  unsigned int uiSizeofoft = 0;
868 
869  for (unsigned int i=0;i<m_vNewiid.size();i++)
870  {
871  uiSizeofdllnames += static_cast<unsigned int>(m_vNewiid[i].name.size()) + 1;
872  uiSizeofoft += (static_cast<unsigned int>(m_vNewiid[i].originalfirstthunk.size())+1) * m_thunkSize;
873 
874  for(unsigned int j=0;j<m_vNewiid[i].originalfirstthunk.size();j++)
875  {
876  // +3 for hint (std::uint16_t) and 00-std::uint8_t
877  uiSizeoffuncnames += (static_cast<unsigned int>(m_vNewiid[i].originalfirstthunk[j].fname.size()) + 3);
878  }
879  }
880 
881 // for (unsigned int i=0;i<m_vNewiid.size();i++)
882 // {
883 // uiSizeofoft += (static_cast<unsigned int>(m_vNewiid[i].originalfirstthunk.size())+1) * PELIB_IMAGE_THUNK_DATA::size();
884 // }
885 
886  OutputBuffer obBuffer(vBuffer);
887 
888  // Rebuild IMAGE_IMPORT_DESCRIPTORS
889  for (unsigned int i=0;i<m_vOldiid.size();i++)
890  {
891  obBuffer << m_vOldiid[i].impdesc.OriginalFirstThunk;
892  obBuffer << m_vOldiid[i].impdesc.TimeDateStamp;
893  obBuffer << m_vOldiid[i].impdesc.ForwarderChain;
894  obBuffer << m_vOldiid[i].impdesc.Name;
895  obBuffer << m_vOldiid[i].impdesc.FirstThunk;
896  }
897 
898  unsigned int dllsize = 0;
899 
900  for (unsigned int i=0;i<m_vNewiid.size();i++)
901  {
902  std::uint32_t dwPoft = uiSizeofdescriptors + uiImprva;
903 
904  for (unsigned int j=1;j<=i;j++)
905  {
906  dwPoft += (static_cast<unsigned int>(m_vNewiid[j-1].originalfirstthunk.size()) + 1) * m_thunkSize;
907  }
908 
909  obBuffer << (fixEntries ? dwPoft : m_vNewiid[i].impdesc.OriginalFirstThunk);
910  obBuffer << m_vNewiid[i].impdesc.TimeDateStamp;
911  obBuffer << m_vNewiid[i].impdesc.ForwarderChain;
912  std::uint32_t dwPdll = uiSizeofdescriptors + uiSizeofoft + uiImprva + dllsize;
913  obBuffer << (fixEntries ? dwPdll : m_vNewiid[i].impdesc.Name);
914  obBuffer << m_vNewiid[i].impdesc.FirstThunk;
915 
916  // store the recalculated values
917  if (fixEntries)
918  {
919  m_vNewiid[i].impdesc.OriginalFirstThunk = dwPoft;
920  m_vNewiid[i].impdesc.Name = dwPdll;
921  }
922 
923  dllsize += static_cast<unsigned int>(m_vNewiid[i].name.size()) + 1;
924  }
925 
926  obBuffer << static_cast<std::uint32_t>(0);
927  obBuffer << static_cast<std::uint32_t>(0);
928  obBuffer << static_cast<std::uint32_t>(0);
929  obBuffer << static_cast<std::uint32_t>(0);
930  obBuffer << static_cast<std::uint32_t>(0);
931 
932  std::uint64_t uiPfunc = uiSizeofdescriptors + uiSizeofoft + uiSizeofdllnames + uiImprva;
933 
934  // Rebuild original first thunk
935  for (std::size_t i = 0;i<m_vNewiid.size();i++)
936  {
937  for (std::size_t j = 0;j<m_vNewiid[i].originalfirstthunk.size();j++)
938  {
939  if((m_vNewiid[i].originalfirstthunk[j].itd.Ordinal & m_ordinalMask) || fixEntries == false)
940  {
941  writePointer(obBuffer, m_vNewiid[i].originalfirstthunk[j].itd.Ordinal);
942  //obBuffer << m_vNewiid[i].originalfirstthunk[j].itd.Ordinal;
943  }
944  else
945  {
946  writePointer(obBuffer, uiPfunc);
947  //obBuffer << uiPfunc;
948  // store the offset in Ordinal, they cannot overlay thanks to PELIB_IMAGE_ORDINAL_FLAG
949  m_vNewiid[i].originalfirstthunk[j].itd.Ordinal = uiPfunc;
950  }
951  uiPfunc += static_cast<std::uint64_t>(m_vNewiid[i].originalfirstthunk[j].fname.size()) + 3;
952  }
953  writePointer(obBuffer, 0);
954  //obBuffer << static_cast<std::uint64_t>(0);
955  }
956 
957  // Write dllnames into import directory
958  for (std::size_t i = 0; i < m_vNewiid.size(); i++)
959  {
960  obBuffer.add(m_vNewiid[i].name.c_str(), static_cast<unsigned int>(m_vNewiid[i].name.size())+1);
961  }
962 
963  // Write function names into directory
964  for (unsigned int i=0;i<m_vNewiid.size();i++)
965  {
966  for (unsigned int j=0;j<m_vNewiid[i].originalfirstthunk.size();j++)
967  {
968  obBuffer << m_vNewiid[i].originalfirstthunk[j].hint;
969  obBuffer.add(m_vNewiid[i].originalfirstthunk[j].fname.c_str(), static_cast<unsigned int>(m_vNewiid[i].originalfirstthunk[j].fname.size()) + 1);
970  }
971  }
972  }
973 
978  inline
979  int ImportDirectory::removeFile(const std::string& strFilename)
980  {
981  unsigned int oldSize = static_cast<unsigned int>(m_vNewiid.size());
982 
983  m_vNewiid.erase(
984  std::remove_if(
985  m_vNewiid.begin(),
986  m_vNewiid.end(),
987  [&](const auto& i) { return i == strFilename; }
988  ),
989  m_vNewiid.end()
990  );
991 
992  return oldSize == m_vNewiid.size() ? 1 : 0;
993  }
994 
1000  inline
1001  int ImportDirectory::removeFunction(const std::string& strFilename, const std::string& strFuncname)
1002  {
1003  ImpDirFileIterator viPos = m_vNewiid.begin();
1004 
1005  int notFound = 1;
1006 
1007  while (viPos != m_vNewiid.end())
1008  {
1009  if (isEqualNc(viPos->name, strFilename))
1010  {
1011  unsigned int oldSize = static_cast<unsigned int>(viPos->originalfirstthunk.size());
1012  viPos->originalfirstthunk.erase(
1013  std::remove_if(
1014  viPos->originalfirstthunk.begin(),
1015  viPos->originalfirstthunk.end(),
1016  [&](const auto& i) { return i.equalFunctionName(strFuncname); }
1017  ),
1018  viPos->originalfirstthunk.end()
1019  );
1020  if (viPos->originalfirstthunk.size() != oldSize) notFound = 0;
1021  }
1022  ++viPos;
1023  }
1024 
1025  return notFound;
1026  }
1027 
1033  inline
1034  int ImportDirectory::removeFunction(const std::string& strFilename, std::uint16_t wHint)
1035  {
1036  ImpDirFileIterator viPos = m_vNewiid.begin();
1037  int notFound = 1;
1038 
1039  while (viPos != m_vNewiid.end())
1040  {
1041  if (isEqualNc(viPos->name, strFilename))
1042  {
1043  unsigned int oldSize = static_cast<unsigned int>(viPos->originalfirstthunk.size());
1044  viPos->originalfirstthunk.erase(
1045  std::remove_if(
1046  viPos->originalfirstthunk.begin(),
1047  viPos->originalfirstthunk.end(),
1048  [&](const auto& i) { return i.equalHint(wHint); }
1049  ),
1050  viPos->originalfirstthunk.end()
1051  );
1052  if (viPos->originalfirstthunk.size() != oldSize) notFound = 0;
1053  }
1054  ++viPos;
1055  }
1056 
1057  return notFound;
1058  }
1059 
1067  inline
1068  int ImportDirectory::write(const std::string& strFilename, std::uint32_t uiOffset, std::uint32_t uiRva, std::uint32_t pointerSize)
1069  {
1070  std::fstream ofFile(strFilename.c_str(), std::ios_base::in);
1071 
1072  if (!ofFile)
1073  {
1074  ofFile.clear();
1075  ofFile.open(strFilename.c_str(), std::ios_base::out | std::ios_base::binary);
1076  }
1077  else
1078  {
1079  ofFile.close();
1080  ofFile.open(strFilename.c_str(), std::ios_base::in | std::ios_base::out | std::ios_base::binary);
1081  }
1082 
1083  if (!ofFile)
1084  {
1085  return ERROR_OPENING_FILE;
1086  }
1087 
1088  ofFile.seekp(uiOffset, std::ios_base::beg);
1089 
1090  std::vector<std::uint8_t> vBuffer;
1091 
1092  setPointerSize(pointerSize);
1093  rebuild(vBuffer, uiRva);
1094 
1095  ofFile.write(reinterpret_cast<const char*>(vBuffer.data()), vBuffer.size());
1096  ofFile.close();
1097 
1098  std::copy(m_vNewiid.begin(), m_vNewiid.end(), std::back_inserter(m_vOldiid));
1099  m_vNewiid.clear();
1100 
1101  return ERROR_NONE;
1102  }
1103 
1108  inline
1109  std::uint32_t ImportDirectory::calculateSize(std::uint32_t pointerSize) const
1110  {
1111  std::uint32_t totalSize = 0;
1112 
1113  // Only the descriptors of m_vOldiid must be rebuilt, not the data they point to.
1114  for(const auto & element : m_vNewiid)
1115  totalSize += element.calculateSize(pointerSize);
1116  return totalSize + (m_vOldiid.size() + 1) * PELIB_IMAGE_IMPORT_DESCRIPTOR::size();
1117  }
1118 
1124  inline
1125  std::uint32_t ImportDirectory::getFirstThunk(const std::string& strFilename, currdir cdDir) const
1126  {
1127  if (cdDir == OLDDIR)
1128  {
1129  return m_vOldiid[getFileIndex(strFilename, cdDir)].impdesc.FirstThunk;
1130  }
1131  else
1132  {
1133  return m_vNewiid[getFileIndex(strFilename, cdDir)].impdesc.FirstThunk;
1134  }
1135  }
1136 
1142  inline
1143  std::uint32_t ImportDirectory::getOriginalFirstThunk(const std::string& strFilename, currdir cdDir) const
1144  {
1145  if (cdDir == OLDDIR)
1146  {
1147  return m_vOldiid[getFileIndex(strFilename, cdDir)].impdesc.OriginalFirstThunk;
1148  }
1149  else
1150  {
1151  return m_vNewiid[getFileIndex(strFilename, cdDir)].impdesc.OriginalFirstThunk;
1152  }
1153  }
1154 
1160  inline
1161  std::uint32_t ImportDirectory::getForwarderChain(const std::string& strFilename, currdir cdDir) const
1162  {
1163  if (cdDir == OLDDIR)
1164  {
1165  return m_vOldiid[getFileIndex(strFilename, cdDir)].impdesc.ForwarderChain;
1166  }
1167  else
1168  {
1169  return m_vNewiid[getFileIndex(strFilename, cdDir)].impdesc.ForwarderChain;
1170  }
1171  }
1172 
1178  inline
1179  std::uint32_t ImportDirectory::getTimeDateStamp(const std::string& strFilename, currdir cdDir) const
1180  {
1181  if (cdDir == OLDDIR)
1182  {
1183  return m_vOldiid[getFileIndex(strFilename, cdDir)].impdesc.TimeDateStamp;
1184  }
1185  else
1186  {
1187  return m_vNewiid[getFileIndex(strFilename, cdDir)].impdesc.TimeDateStamp;
1188  }
1189  }
1190 
1191  inline
1192  std::uint32_t ImportDirectory::getRvaOfName(const std::string& strFilename, currdir cdDir) const
1193  {
1194  if (cdDir == OLDDIR)
1195  {
1196  return m_vOldiid[getFileIndex(strFilename, cdDir)].impdesc.Name;
1197  }
1198  else
1199  {
1200  return m_vNewiid[getFileIndex(strFilename, cdDir)].impdesc.Name;
1201  }
1202  }
1203 
1209  inline
1210  std::uint32_t ImportDirectory::getFirstThunk(std::uint32_t dwFilenr, currdir cdDir) const
1211  {
1212  if (cdDir == OLDDIR)
1213  {
1214  return m_vOldiid[dwFilenr].impdesc.FirstThunk;
1215  }
1216  else
1217  {
1218  return m_vNewiid[dwFilenr].impdesc.FirstThunk;
1219  }
1220  }
1221 
1222  inline
1223  void ImportDirectory::setFirstThunk(std::uint32_t dwFilenr, currdir cdDir, std::uint32_t value)
1224  {
1225  if (cdDir == OLDDIR)
1226  {
1227  m_vOldiid[dwFilenr].impdesc.FirstThunk = value;
1228  }
1229  else
1230  {
1231  m_vNewiid[dwFilenr].impdesc.FirstThunk = value;
1232  }
1233  }
1234 
1240  inline
1241  std::uint32_t ImportDirectory::getOriginalFirstThunk(std::uint32_t dwFilenr, currdir cdDir) const
1242  {
1243  if (cdDir == OLDDIR)
1244  {
1245  return m_vOldiid[dwFilenr].impdesc.OriginalFirstThunk;
1246  }
1247  else
1248  {
1249  return m_vNewiid[dwFilenr].impdesc.OriginalFirstThunk;
1250  }
1251  }
1252 
1253  inline
1254  void ImportDirectory::setOriginalFirstThunk(std::uint32_t dwFilenr, currdir cdDir, std::uint32_t value)
1255  {
1256  if (cdDir == OLDDIR)
1257  {
1258  m_vOldiid[dwFilenr].impdesc.OriginalFirstThunk = value;
1259  }
1260  else
1261  {
1262  m_vNewiid[dwFilenr].impdesc.OriginalFirstThunk = value;
1263  }
1264  }
1265 
1272  inline
1273  std::uint32_t ImportDirectory::getForwarderChain(std::uint32_t dwFilenr, currdir cdDir) const
1274  {
1275  if (cdDir == OLDDIR)
1276  {
1277  return m_vOldiid[dwFilenr].impdesc.ForwarderChain;
1278  }
1279  else
1280  {
1281  return m_vNewiid[dwFilenr].impdesc.ForwarderChain;
1282  }
1283  }
1284 
1285  inline
1286  void ImportDirectory::setForwarderChain(std::uint32_t dwFilenr, currdir cdDir, std::uint32_t value)
1287  {
1288  if (cdDir == OLDDIR)
1289  {
1290  m_vOldiid[dwFilenr].impdesc.ForwarderChain = value;
1291  }
1292  else
1293  {
1294  m_vNewiid[dwFilenr].impdesc.ForwarderChain = value;
1295  }
1296  }
1297 
1303  inline
1304  std::uint32_t ImportDirectory::getTimeDateStamp(std::uint32_t dwFilenr, currdir cdDir) const
1305  {
1306  if (cdDir == OLDDIR)
1307  {
1308  return m_vOldiid[dwFilenr].impdesc.TimeDateStamp;
1309  }
1310  else
1311  {
1312  return m_vNewiid[dwFilenr].impdesc.TimeDateStamp;
1313  }
1314  }
1315 
1316  inline
1317  void ImportDirectory::setTimeDateStamp(std::uint32_t dwFilenr, currdir cdDir, std::uint32_t value)
1318  {
1319  if (cdDir == OLDDIR)
1320  {
1321  m_vOldiid[dwFilenr].impdesc.TimeDateStamp = value;
1322  }
1323  else
1324  {
1325  m_vNewiid[dwFilenr].impdesc.TimeDateStamp = value;
1326  }
1327  }
1328 
1329  inline
1330  std::uint32_t ImportDirectory::getRvaOfName(std::uint32_t dwFilenr, currdir cdDir) const
1331  {
1332  if (cdDir == OLDDIR)
1333  {
1334  return m_vOldiid[dwFilenr].impdesc.Name;
1335  }
1336  else
1337  {
1338  return m_vNewiid[dwFilenr].impdesc.Name;
1339  }
1340  }
1341 
1342  inline
1343  void ImportDirectory::setRvaOfName(std::uint32_t dwFilenr, currdir cdDir, std::uint32_t value)
1344  {
1345  if (cdDir == OLDDIR)
1346  {
1347  m_vOldiid[dwFilenr].impdesc.Name = value;
1348  }
1349  else
1350  {
1351  m_vNewiid[dwFilenr].impdesc.Name = value;
1352  }
1353  }
1354 
1361  inline
1362  std::uint32_t ImportDirectory::getFirstThunk(std::uint32_t dwFilenr, std::uint32_t dwFuncnr, currdir cdDir) const
1363  {
1364  if (cdDir == OLDDIR) return m_vOldiid[dwFilenr].firstthunk[dwFuncnr].itd.Ordinal;
1365  else return m_vNewiid[dwFilenr].firstthunk[dwFuncnr].itd.Ordinal;
1366  }
1367 
1368  inline
1369  void ImportDirectory::setFirstThunk(std::uint32_t dwFilenr, std::uint32_t dwFuncnr, currdir cdDir, std::uint32_t value)
1370  {
1371  if (cdDir == OLDDIR) m_vOldiid[dwFilenr].firstthunk[dwFuncnr].itd.Ordinal = value;
1372  else m_vNewiid[dwFilenr].firstthunk[dwFuncnr].itd.Ordinal = value;
1373  }
1374 
1381  inline
1382  std::uint32_t ImportDirectory::getOriginalFirstThunk(std::uint32_t dwFilenr, std::uint32_t dwFuncnr, currdir cdDir) const
1383  {
1384  if (cdDir == OLDDIR)
1385  {
1386  if (dwFuncnr < m_vOldiid[dwFilenr].originalfirstthunk.size())
1387  {
1388  return m_vOldiid[dwFilenr].originalfirstthunk[dwFuncnr].itd.Ordinal;
1389  }
1390  else
1391  {
1392  return 0;
1393  }
1394  }
1395  else
1396  {
1397  return m_vNewiid[dwFilenr].originalfirstthunk[dwFuncnr].itd.Ordinal;
1398  }
1399  }
1400 
1401  inline
1402  void ImportDirectory::setOriginalFirstThunk(std::uint32_t dwFilenr, std::uint32_t dwFuncnr, currdir cdDir, std::uint32_t value)
1403  {
1404  if (cdDir == OLDDIR) m_vOldiid[dwFilenr].originalfirstthunk[dwFuncnr].itd.Ordinal = value;
1405  else m_vNewiid[dwFilenr].originalfirstthunk[dwFuncnr].itd.Ordinal = value;
1406  }
1407 
1408  inline
1409  const std::vector<std::pair<unsigned int, unsigned int>>& ImportDirectory::getOccupiedAddresses() const
1410  {
1411  return m_occupiedAddresses;
1412  }
1413 
1414 } // namespace PeLib
1415 
1416 #endif
Definition: ImageLoader.h:138
std::uint32_t readPointer(std::uint32_t rva, std::uint64_t &pointerValue)
Definition: ImageLoader.cpp:291
std::uint32_t getDataDirRva(std::size_t dataDirIndex) const
Definition: ImageLoader.h:315
std::uint32_t readString(std::string &str, std::uint32_t rva, std::uint32_t maxLength=65535)
Definition: ImageLoader.cpp:275
std::uint64_t getOrdinalMask() const
Definition: ImageLoader.h:210
std::uint32_t readImage(void *buffer, std::uint32_t rva, std::uint32_t bytesToRead)
Definition: ImageLoader.cpp:171
std::uint32_t getSizeOfHeaders() const
Definition: ImageLoader.h:275
std::uint32_t getSizeOfImage() const
Definition: ImageLoader.h:280
std::uint32_t getPointerSize() const
Definition: ImageLoader.cpp:322
Class that handles import directories.
Definition: ImportDirectory.h:42
void setRvaOfName(std::uint32_t dwFilenr, currdir cdDir, std::uint32_t value)
Definition: ImportDirectory.h:1343
void setForwarderChain(std::uint32_t dwFilenr, currdir cdDir, std::uint32_t value)
Definition: ImportDirectory.h:1286
void setPointerSize(std::uint32_t pointerSize)
Updates the pointer size for the import directory.
Definition: ImportDirectory.h:552
void rebuild(std::vector< std::uint8_t > &vBuffer, std::uint32_t dwRva, bool fixEntries=true)
Rebuild the import directory.
Definition: ImportDirectory.h:861
void setFunctionHint(std::uint32_t dwFilenr, std::uint32_t dwFuncnr, currdir cdDir, std::uint16_t value)
Definition: ImportDirectory.h:484
int removeFunction(const std::string &strFilename, const std::string &strFuncname)
Remove a function from the import directory.
Definition: ImportDirectory.h:1001
const std::vector< std::pair< unsigned int, unsigned int > > & getOccupiedAddresses() const
Definition: ImportDirectory.h:1409
std::uint32_t getNumberOfFiles(currdir cdDir) const
Get the number of files which are imported.
Definition: ImportDirectory.h:506
int read(ImageLoader &imageLoader)
Read a file's import directory.
Definition: ImportDirectory.h:587
std::uint64_t m_ordinalMask
Mask for file ordinal.
Definition: ImportDirectory.h:54
std::uint32_t getNumberOfFunctions(std::uint32_t dwFilenr, currdir cdDir) const
Get the number of fucntions which are imported by a specific file.
Definition: ImportDirectory.h:520
std::uint32_t getOriginalFirstThunk(std::uint32_t dwFilenr, std::uint32_t dwFuncnr, currdir cdDir) const
Returns the OriginalFirstThunk value of a function.
Definition: ImportDirectory.h:1382
void setFileName(std::uint32_t filenr, currdir cdDir, const std::string &name)
Definition: ImportDirectory.h:368
LoaderError m_ldrError
Error detected by the import table parser.
Definition: ImportDirectory.h:56
unsigned int calculateSize(std::uint32_t pointerSize) const
Returns the size of the current import directory.
Definition: ImportDirectory.h:1109
std::vector< std::pair< unsigned int, unsigned int > > m_occupiedAddresses
Stores RVAs which are occupied by this import directory.
Definition: ImportDirectory.h:52
std::string getFileName(std::uint32_t dwFilenr, currdir cdDir) const
Get the name of an imported file.
Definition: ImportDirectory.h:361
std::size_t m_thunkSize
size of single thunk item
Definition: ImportDirectory.h:58
void setFirstThunk(std::uint32_t dwFilenr, std::uint32_t dwFuncnr, currdir cdDir, std::uint32_t value)
Definition: ImportDirectory.h:1369
unsigned int getFunctionIndex(const std::string &strFilename, const std::string &strFuncname, currdir cdDir) const
Get the ID of a function through it's name.
Definition: ImportDirectory.h:342
std::uint16_t getFunctionHint(std::uint32_t dwFilenr, std::uint32_t dwFuncnr, currdir cdDir) const
Get the hint of an imported function.
Definition: ImportDirectory.h:466
int removeFile(const std::string &strFilename)
Remove a file from the import directory.
Definition: ImportDirectory.h:979
std::uint32_t getRvaOfName(const std::string &strFilename, currdir cdDir) const
Definition: ImportDirectory.h:1192
ImportDirectory()
Constructor.
Definition: ImportDirectory.h:104
void writePointer(OutputBuffer &obBuffer, std::uint64_t pointerValue)
Writes pointer to the buffer (32-bit or 64-bit)
Definition: ImportDirectory.h:840
void setFunctionName(std::uint32_t dwFilenr, std::uint32_t dwFuncnr, currdir cdDir, const std::string &functionName)
Definition: ImportDirectory.h:412
void setTimeDateStamp(std::uint32_t dwFilenr, currdir cdDir, std::uint32_t value)
Definition: ImportDirectory.h:1317
unsigned int getFileIndex(const std::string &strFilename, currdir cdDir) const
Get the ID of a file through it's name.
Definition: ImportDirectory.h:302
void setOriginalFirstThunk(std::uint32_t dwFilenr, std::uint32_t dwFuncnr, currdir cdDir, std::uint32_t value)
Definition: ImportDirectory.h:1402
int addFunction(const std::string &strFilename, std::uint16_t wHint)
Add a function to the import directory.
Definition: ImportDirectory.h:221
std::uint32_t getForwarderChain(const std::string &strFilename, currdir cdDir) const
Returns the ForwarderChain value of a file.
Definition: ImportDirectory.h:1161
int write(const std::string &strFilename, std::uint32_t uiOffset, std::uint32_t uiRva, std::uint32_t pointerSize)
Writes the import directory to a file.
Definition: ImportDirectory.h:1068
bool hasFunction(std::string strFilename, T value, bool(PELIB_THUNK_DATA::*comp)(T) const) const
Tests if a certain function is imported.
Definition: ImportDirectory.h:63
std::uint32_t getFirstThunk(std::uint32_t dwFilenr, std::uint32_t dwFuncnr, currdir cdDir) const
Returns the FirstThunk value of a function.
Definition: ImportDirectory.h:1362
std::uint32_t getTimeDateStamp(const std::string &strFilename, currdir cdDir) const
Returns the TimeDateStamp value of a file.
Definition: ImportDirectory.h:1179
LoaderError loaderError() const
Retrieve the loader error.
Definition: ImportDirectory.h:443
std::vector< PELIB_IMAGE_IMPORT_DIRECTORY > m_vNewiid
Stores information about imported DLLs which will be added.
Definition: ImportDirectory.h:50
std::vector< PELIB_IMAGE_IMPORT_DIRECTORY > m_vOldiid
Stores information about already imported DLLs.
Definition: ImportDirectory.h:48
void setLoaderError(LoaderError ldrError)
Definition: ImportDirectory.h:449
std::vector< PELIB_IMAGE_IMPORT_DIRECTORY >::const_iterator ConstImpDirFileIterator
Definition: ImportDirectory.h:44
std::string getFunctionName(std::uint32_t dwFilenr, std::uint32_t dwFuncnr, currdir cdDir) const
Get the name of an imported function.
Definition: ImportDirectory.h:383
std::vector< PELIB_IMAGE_IMPORT_DIRECTORY >::iterator ImpDirFileIterator
Definition: ImportDirectory.h:43
Definition: OutputBuffer.h:22
void add(const char *lpBuffer, unsigned long ulSize)
Definition: OutputBuffer.cpp:32
Definition: BoundImportDirectory.h:21
@ PELIB_IMAGE_DIRECTORY_ENTRY_IMPORT
Definition: PeLibAux.h:170
LoaderError
Definition: PeLibAux.h:47
@ LDR_ERROR_IMPDIR_OUT_OF_FILE
Definition: PeLibAux.h:85
@ LDR_ERROR_IMPDIR_COUNT_EXCEEDED
Definition: PeLibAux.h:87
@ LDR_ERROR_IMPDIR_IMPORT_COUNT_EXCEEDED
Definition: PeLibAux.h:90
@ LDR_ERROR_IMPDIR_CUT
Definition: PeLibAux.h:86
@ LDR_ERROR_IMPDIR_THUNK_RVA_INVALID
Definition: PeLibAux.h:89
@ LDR_ERROR_IMPDIR_NAME_RVA_INVALID
Definition: PeLibAux.h:88
@ LDR_ERROR_NONE
Definition: PeLibAux.h:48
bool isBadImportName(const std::string &importName)
Definition: ImportDirectory.h:558
const std::size_t IMPORT_LIBRARY_MAX_LENGTH
Definition: PeLibAux.h:1130
const std::uint32_t PELIB_MAX_IMPORT_DLLS
Definition: PeLibAux.h:152
bool isEqualNc(const std::string &s1, const std::string &s2)
Definition: PeLibAux.cpp:271
bool isInvalidOrdinal(std::uint64_t ordinal, std::uint64_t ordinalMask, std::uint64_t sizeOfImage)
Definition: ImportDirectory.h:526
const std::size_t IMPORT_SYMBOL_MAX_LENGTH
Definition: PeLibAux.h:1131
currdir
Parameter for functions that can operate on the OLDDIR or new import directory.
Definition: ImportDirectory.h:25
@ NEWDIR
Definition: ImportDirectory.h:25
@ OLDDIR
Definition: ImportDirectory.h:25
bool hasValidOriginalFirstThunk(const PELIB_IMAGE_IMPORT_DESCRIPTOR &impDesc, const ImageLoader &imageLoader)
Definition: ImportDirectory.h:208
const std::uint32_t PELIB_MAX_IMPORTED_FUNCTIONS
Definition: PeLibAux.h:153
@ ERROR_NONE
Definition: PeLibAux.h:33
@ ERROR_DUPLICATE_ENTRY
Definition: PeLibAux.h:41
@ ERROR_OPENING_FILE
Definition: PeLibAux.h:34
@ ERROR_INVALID_FILE
Definition: PeLibAux.h:35
Definition: PeLibAux.h:863
static std::size_t size()
Definition: PeLibAux.h:879
std::uint32_t Name
Definition: PeLibAux.h:867
std::uint32_t OriginalFirstThunk
Definition: PeLibAux.h:864
std::uint32_t FirstThunk
Definition: PeLibAux.h:868
Definition: PeLibAux.h:1105
std::vector< PELIB_THUNK_DATA > originalfirstthunk
All original first thunk values of an imported DLL.
Definition: PeLibAux.h:1111
std::vector< PELIB_THUNK_DATA > firstthunk
All first thunk value of an imported DLL.
Definition: PeLibAux.h:1113
std::string name
The name of an imported DLL.
Definition: PeLibAux.h:1109
PELIB_IMAGE_IMPORT_DESCRIPTOR impdesc
The IMAGE_IMPORT_DESCRIPTOR of an imported DLL.
Definition: PeLibAux.h:1107
std::uint64_t Ordinal
Definition: PeLibAux.h:854
Definition: PeLibAux.h:1060
bool equalFunctionName(std::string strFunctionName) const
Definition: PeLibAux.h:1079
std::uint16_t hint
The hint of an imported function.
Definition: PeLibAux.h:1064
PELIB_IMAGE_THUNK_DATA itd
The IMAGE_THUNK_DATA struct of an imported function.
Definition: PeLibAux.h:1062
bool equalHint(std::uint16_t wHint) const
Definition: PeLibAux.h:1073
std::string fname
The function name of an imported function.
Definition: PeLibAux.h:1066