Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- template <class T> // T: PIMAGE_THUNK_DATA64 or PIMAGE_THUNK_DATA32
- vector<string> PE::getModuleAPIs(T pThunk, PIMAGE_SECTION_HEADER IT)
- {
- vector<string> APIs;
- // check if IMAGE_THUNK_DATA is within the section of Import directory, otherwise, most likely the file is packed or manualy manipulated.
- if (((DWORD)pThunk < ((DWORD)LoadAddr + IT->PointerToRawData)) || ((DWORD)pThunk >((DWORD)LoadAddr + IT->PointerToRawData + IT->SizeOfRawData))) {
- Suspicious |= SUSPICIOUS_IMPORTS;
- }
- // check if IMAGE_THUNK_DATA points out of file boundaries.
- if (((DWORD)pThunk < ((DWORD)LoadAddr)) || ( ((DWORD)pThunk + sizeof(*pThunk)) > ((DWORD)LoadAddr + FileSize)) ) {
- Suspicious |= CORRUPTED_IMPORTS;
- return APIs;
- }
- ULONGLONG iIMAGE_ORDINAL_FLAG;
- if(isPE64())
- iIMAGE_ORDINAL_FLAG = IMAGE_ORDINAL_FLAG64;
- else
- iIMAGE_ORDINAL_FLAG = IMAGE_ORDINAL_FLAG32;
- if(pThunk->u1.Ordinal & iIMAGE_ORDINAL_FLAG) fImportByOrdinal = true;
- while(pThunk->u1.Ordinal)
- {
- string API;
- // if import by name
- if(!(pThunk->u1.Ordinal & iIMAGE_ORDINAL_FLAG)) {
- // Yup, ApiNameOffset is DWORD, 32bit, for both 32bit and 64bit executables, assuming we've not yet seen an 64bit executable > 4GB.
- DWORD ApiNameOffset = getOffsetFromRva(pThunk->u1.AddressOfData) + FIELD_OFFSET(IMAGE_IMPORT_BY_NAME, Name);
- // within file boundaries ?
- if (ApiNameOffset > FileSize) {
- Suspicious |= CORRUPTED_IMPORTS;
- }
- else {
- DWORD i = ApiNameOffset;
- while (i < FileSize && LoadAddr[i] != 0 && (i - ApiNameOffset < MAX_API_NAME)) i++; // There is no unallowed chars for API name.
- /*
- * There are three cases here:
- *
- * 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.
- * 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"
- * will be 0, so the loader will read the zero and terminates the string.
- * 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.
- * For those two cases, we'll get the string up until the boundary, MAX_API_NAME or FileSize.
- * 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 :)
- */
- if ((i >= FileSize) || (i - ApiNameOffset >= MAX_API_NAME))
- Suspicious |= SUSPICIOUS_IMPORTS;
- API = string((char*) &LoadAddr[ApiNameOffset], i - ApiNameOffset);
- }
- }
- // else if import by ordinal
- else {
- int n = pThunk->u1.Ordinal & 0x00FF; // get ordinal number
- API = "Ord(" + numToStr(n) + ")";
- }
- APIs.push_back(API);
- pThunk++;
- }
- return APIs;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement