Short answer: No, you don't have to guess it's a string. There's a 'trick'.
But first, some background: export forwarding is a legitimate and useful functionality piece. There are a handful of documentation describing how imports are loaded by the PE loader unfortunately export forwarding documentation is a little harder to come by and most of articles only mention export forwarding.
The key to identifying if you're processing an export forward is, a described here:
Forwarding is achieved by making an RVA in the AddressOfFunctions array point into the section which contains the export directory, something that normal exports should not do. At that location, there should be a zero terminated ASCII string of format "LibraryName.ExportName" for the appropriate place to forward this export to.
If the RVA in the AddressOfFunctions array points to the exports section, that function is forwarded and can't be located in the DLL being loaded. Instead, the value pointed should be interpreted as a null-terminated string, another module should be loaded and the loading process should be repeated.
In case the dot is followed by the hash sign, the forward entry points to an export by ordinal, not name, and the digits following the hash sign are the ordinal number of target function.
Please note an API may be forwarded multiple times before being reached.
Additionally, if you're handling bound imports you should make sure to treat ForwarderChain
properly, see the following from the same article:
Binding can of course be a problem if the bound library / module forwards its exports to another module. In these cases, the non-forwarded imports can be bound, but the values which get forwarded must be identified so the loader can resolve them. This is done through the ForwarderChain member of the import descriptor. The value of "ForwarderChain" is an index into the FirstThunk and OriginalFirstThunk arrays. The OriginalFirstThunk for that index identifies the IMAGE_IMPORT_BY_NAME structure for a import that needs to be resolved, and the FirstThunk for that index is the index of another entry that needs to be resolved. This continues until the FirstThunk value is -1, indicating no more forwarded values to import.
For additional reading about the PE format and imports in particular, I recommend this resource.