Advertisement
Guest User

Untitled

a guest
May 27th, 2015
318
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 2.77 KB | None | 0 0
  1. template <class T> // T: PIMAGE_THUNK_DATA64 or PIMAGE_THUNK_DATA32
  2. vector<string> PE::getModuleAPIs(T pThunk, PIMAGE_SECTION_HEADER IT)
  3. {
  4. vector<string> APIs;
  5.  
  6. // check if IMAGE_THUNK_DATA is within the section of Import directory, otherwise, most likely the file is packed or manualy manipulated.
  7. if (((DWORD)pThunk < ((DWORD)LoadAddr + IT->PointerToRawData)) || ((DWORD)pThunk >((DWORD)LoadAddr + IT->PointerToRawData + IT->SizeOfRawData))) {
  8. Suspicious |= SUSPICIOUS_IMPORTS;
  9. }
  10.  
  11. // check if IMAGE_THUNK_DATA points out of file boundaries.
  12. if (((DWORD)pThunk < ((DWORD)LoadAddr)) || ( ((DWORD)pThunk + sizeof(*pThunk)) > ((DWORD)LoadAddr + FileSize)) ) {
  13. Suspicious |= CORRUPTED_IMPORTS;
  14. return APIs;
  15. }
  16.  
  17. ULONGLONG iIMAGE_ORDINAL_FLAG;
  18. if(isPE64())
  19. iIMAGE_ORDINAL_FLAG = IMAGE_ORDINAL_FLAG64;
  20. else
  21. iIMAGE_ORDINAL_FLAG = IMAGE_ORDINAL_FLAG32;
  22.  
  23. if(pThunk->u1.Ordinal & iIMAGE_ORDINAL_FLAG) fImportByOrdinal = true;
  24.  
  25. while(pThunk->u1.Ordinal)
  26. {
  27. string API;
  28.  
  29. // if import by name
  30. if(!(pThunk->u1.Ordinal & iIMAGE_ORDINAL_FLAG)) {
  31. // Yup, ApiNameOffset is DWORD, 32bit, for both 32bit and 64bit executables, assuming we've not yet seen an 64bit executable > 4GB.
  32. DWORD ApiNameOffset = getOffsetFromRva(pThunk->u1.AddressOfData) + FIELD_OFFSET(IMAGE_IMPORT_BY_NAME, Name);
  33.  
  34. // within file boundaries ?
  35. if (ApiNameOffset > FileSize) {
  36. Suspicious |= CORRUPTED_IMPORTS;
  37. }
  38. else {
  39. DWORD i = ApiNameOffset;
  40. while (i < FileSize && LoadAddr[i] != 0 && (i - ApiNameOffset < MAX_API_NAME)) i++; // There is no unallowed chars for API name.
  41. /*
  42. * There are three cases here:
  43. *
  44. * 1- If the size = MAX_API_NAME, Win loader's RtlInitString() will take the first MAX_API_NAME name regardless of the "real" size. That would be the API that will be looked for.
  45. * 2- If the Name was shorter that MAX_API_NAME but passes the file size, most likely the memory location at the offset "file size"
  46. * will be 0, so the loader will read the zero and terminates the string.
  47. * Unless in very rare condition that the file ends exactly at the boundary of a memory page and accessing next page will fire an exception.
  48. * For those two cases, we'll get the string up until the boundary, MAX_API_NAME or FileSize.
  49. * 3- The file we're scanning is a good file that respects itself and has a normal API name, which is a case we don't usually encounter when dealing with malware :)
  50. */
  51. if ((i >= FileSize) || (i - ApiNameOffset >= MAX_API_NAME))
  52. Suspicious |= SUSPICIOUS_IMPORTS;
  53.  
  54. API = string((char*) &LoadAddr[ApiNameOffset], i - ApiNameOffset);
  55. }
  56. }
  57. // else if import by ordinal
  58. else {
  59. int n = pThunk->u1.Ordinal & 0x00FF; // get ordinal number
  60. API = "Ord(" + numToStr(n) + ")";
  61. }
  62.  
  63. APIs.push_back(API);
  64. pThunk++;
  65. }
  66.  
  67. return APIs;
  68. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement