I want to know how to find out if an imported function in a PE header is being imported by ordinal rather than by name because I came across an executable that does that. Here is the DLL that imports all functions by ordinal except for one (from WS2_32.dll
):
Screenshot from program called ExeinfoPE
This is what I'm doing to get to the imports:
- Read the PE header.
- Loop over data directories and find
IMAGE_DIRECTORY_ENTRY_IMPORT
. Once
IMAGE_DIRECTORY_ENTRY_IMPORT
is found, loop overIMAGE_IMPORT_DESCRIPTORS
.On each
IMAGE_IMPORT_DESCRIPTORS
, extract all the functions.
Here is how I extract the functions (only works for functions imported by name):
void extractFunctions(IMAGE_IMPORT_DESCRIPTOR dll, uintptr_t sectionStartAddrRaw) {
uintptr_t selectedFunctionImport = dll.Characteristics + sectionStartAddrRaw;
uintptr_t selectedFunctionImportIAT = dll.FirstThunk + sectionStartAddrRaw;
while (true) {
IMAGE_THUNK_DATA thunkPtrToImportByName = *(IMAGE_THUNK_DATA*)selectedFunctionImport;
selectedFunctionImport += sizeof(IMAGE_THUNK_DATA); //Next loop we'll loop over to the next IMAGE_THUNK_DATA.
if (thunkPtrToImportByName.u1.Function == NULL) { //Check if we need to exit the looping since there are no more functions to import.
break;
}
IMAGE_IMPORT_BY_NAME* functionImport = (IMAGE_IMPORT_BY_NAME*)(thunkPtrToImportByName.u1.Function + sectionStartAddrRaw);
Function function;
function.name = std::string(functionImport->Name); //Access violation here if the function needs to be imported by ordinal, instead of by name.
function.locationInIAT = selectedFunctionImportIAT;
function.locationInOriginalIAT = selectedFunctionImportIAT - sectionStartAddrRaw + header.OptionalHeader.ImageBase;
selectedFunctionImportIAT += sizeof(IMAGE_THUNK_DATA);
dlls.back().functions.push_back(function); //We assume that IMAGE_IMPORT_DESCRIPTOR dll is the last one in the dlls vector.]
}
}
I noticed that every function Hint/Ordinal inside ExeinfoPE
that is imported by name is 0
. However, in my code functionImport->Hint
is always set to something, regardless if the function is supposed to be imported by name or ordinal.
The IMAGE_IMPORT_DESCRIPTOR
cannot have information on whether the functions inside that IMAGE_IMPORT_DESCRIPTOR
are imported by ordinal or name, since one of the functions is imported by name and all of the others are imported by ordinal. So, I'm all out of ideas here.
Here are the data structures I'm using for your reference so no need to Google:
typedef struct _IMAGE_THUNK_DATA {
union {
uint32_t* Function; // address of imported function
uint32_t Ordinal; // ordinal value of function
PIMAGE_IMPORT_BY_NAME AddressOfData; // RVA of imported name
DWORD ForwarderStringl // RVA to forwarder string
} u1;
} IMAGE_THUNK_DATA, *PIMAGE_THUNK_DATA;
typedef struct _IMAGE_IMPORT_DESCRIPTOR {
union {
DWORD Characteristics; /* 0 for terminating null import descriptor */
DWORD OriginalFirstThunk; /* RVA to original unbound IAT */
} DUMMYUNIONNAME;
DWORD TimeDateStamp; /* 0 if not bound,
* -1 if bound, and real date\time stamp
* in IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT
* (new BIND)
* otherwise date/time stamp of DLL bound to
* (Old BIND)
*/
DWORD ForwarderChain; /* -1 if no forwarders */
DWORD Name;
/* RVA to IAT (if bound this IAT has actual addresses) */
DWORD FirstThunk;
} IMAGE_IMPORT_DESCRIPTOR,*PIMAGE_IMPORT_DESCRIPTOR;
typedef struct _IMAGE_IMPORT_BY_NAME {
WORD Hint;
BYTE Name[1];
} IMAGE_IMPORT_BY_NAME,*PIMAGE_IMPORT_BY_NAME;