Active references seem ignored by ld, for MinGW delay-loaded import libraries
Pete Batard
pete@akeo.ie
Tue Jul 16 16:42:32 GMT 2024
Hi,
# Description
This whole issue is better illustrated (and replicated) with the MinGW
sample code provided at [1] and, since it pertains to delay loading of
Windows DLL with MinGW, we first reported it to the MinGW mailing list
[2], before people there suggested that it ultimately looks like a
binutils bug, and would be better submitted to this list.
The gist of the issue is that, because of the longstanding issue of
sideloading vulnerabilities with Windows DLLs, Windows applications
compiled with MinGW may want to delay-load vulnerable DLLs by using
dlltool with the '--output-delaylib' option, in order to create an
import library, that takes care of the delay-loading, and can be linked
with the final executable, per the method described at [3].
This appears works fine with some DLLs, but for quite a few others, such
as wininet.dll, this results in an application crash whenever a
delay-loaded function call is invoked, on account that the thunk, that
is meant to perform the actual loading, contains a NULL dereference.
Currently, we are assuming that this is due to ld.bfd erroneously
thinking that the code is not referenced at all, and not including it.
This seems further evidenced by the fact that, in our test sample, if we
force an explicit reference to __imp__InternetCrackUrlA@16 (which is one
of the internal calls that is exposed by the import library) then the
problem goes away.
So it does seem to us like, in some circumstances, ld is dismissing what
should be an active reference, as an unused one.
# Steps to replicate
Note that the issue only manifests itself when using the 32-bit version
of MinGW and not the 64-bit version (which we assume has to do with the
fact that the calling convention/decorations appears to play a role, as
another workaround we found was to switch the delay-loaded API calls
from '__declspec(dllimport)' to '__attribute__((visibility("hidden")))')
1. Clone https://github.com/pbatard/delayload.git
2. From a MinGW32 (32-bit) prompt issue 'make'
3. Run ./delayload.exe and observe the crash.
4. To test the "hidden" visibility or explicit reference workarounds,
you can issue 'make clean' and then 'make WORKAROUND1' or 'make
WORKAROUND2' respectively.
Because none of the "workarounds" we have found are satisfactory for our
usage, we would really appreciate if this issue could be investigated
and, if it does turn out to be a binutils bug, remediated.
Regards,
/Pete
[1] https://github.com/pbatard/delayload
[2]
https://sourceforge.net/p/mingw-w64/mailman/mingw-w64-public/thread/ea87573f-65ea-44a2-b4bb-ca96c0a136ab%40akeo.ie/#msg58793876
[3] https://stackoverflow.com/a/70416894/1069307
More information about the Binutils
mailing list