UCRT64 ~/Desktop
$ cat delay_user32.d
cat: delay_user32.d: No such file or directory

UCRT64 ~/Desktop
$ cat delay_user32.def
LIBRARY "USER32.DLL"
EXPORTS
MessageBoxW

UCRT64 ~/Desktop
$ cat test.c
#include <stdio.h>
#include <windows.h>

extern void** __imp_MessageBoxW;

int
main(void)
  {
    fprintf(stderr, "main 1: __imp_MessageBoxW = %p\n", *__imp_MessageBoxW);
    MessageBoxW(NULL, L"test message", NULL, MB_ICONINFORMATION | MB_YESNO);
    fprintf(stderr, "main 2: __imp_MessageBoxW = %p\n", *__imp_MessageBoxW);
  }

UCRT64 ~/Desktop
$ dlltool -d delay_user32.def -y delay_user32.dll.a

UCRT64 ~/Desktop
$ gcc -Wall -Wextra test.c delay_user32.dll.a

UCRT64 ~/Desktop
$ ./a.exe
main 1: __imp_MessageBoxW = E900008F0B058D48
main 2: __imp_MessageBoxW = 44DB334538EC8348




--
Best regards,
LIU Hao

From e6fdf91f3d965ccd7491a02db929a1def4f5c0a8 Mon Sep 17 00:00:00 2001
From: LIU Hao <lh_mo...@126.com>
Date: Tue, 11 Feb 2025 10:34:14 +0800
Subject: [PATCH] crt/delayimp: Make IAT temporarily writeable before modifying
 it

Since Binutils 2.44, the import address table (abbr. IAT) is now read-only,
in alignment with Microsoft LINK and LLD. It is now required to make the IAT
writeable before modifying it.

Similar code exists in Microsoft delayhlp.cpp.

Reference: https://devblogs.microsoft.com/oldnewthing/20221006-07/?p=107257
Reference: 
https://sourceware.org/git/?p=binutils-gdb.git;a=commitdiff;h=db00f6c3aceabbf03acdb69e74b59b2d2b043cd7
Reference: https://bugs.winehq.org/show_bug.cgi?id=57819
Reference: https://sourceware.org/bugzilla/show_bug.cgi?id=32675
Signed-off-by: LIU Hao <lh_mo...@126.com>
---
 mingw-w64-crt/misc/delayimp.c | 13 ++++++++++++-
 1 file changed, 12 insertions(+), 1 deletion(-)

diff --git a/mingw-w64-crt/misc/delayimp.c b/mingw-w64-crt/misc/delayimp.c
index caa6166f0..6ced2d327 100644
--- a/mingw-w64-crt/misc/delayimp.c
+++ b/mingw-w64-crt/misc/delayimp.c
@@ -131,6 +131,9 @@ static int WINAPI 
FLoadedAtPreferredAddress(PIMAGE_NT_HEADERS pinh,HMODULE hmod)
 /*typedef unsigned long *PULONG_PTR;*/
 #endif
 
+/* Ideally this should be an SRWLOCK, but it would require Vista.  */
+static volatile LONG gDelayLoadLock = 0;
+
 FARPROC WINAPI __delayLoadHelper2(PCImgDelayDescr pidd,FARPROC *ppfnIATEntry);
 
 FARPROC WINAPI __delayLoadHelper2(PCImgDelayDescr pidd,FARPROC *ppfnIATEntry)
@@ -147,7 +150,9 @@ FARPROC WINAPI __delayLoadHelper2(PCImgDelayDescr 
pidd,FARPROC *ppfnIATEntry)
   unsigned iIAT, iINT;
   PCImgThunkData pitd;
   FARPROC pfnRet;
-  
+  DWORD dwOldProtect;
+  WINBOOL bUnprotected;
+
   if(!(idd.grAttrs & dlattrRva)) {
     PDelayLoadInfo rgpdli[1] = { &dli};
     
RaiseException(VcppException(ERROR_SEVERITY_ERROR,ERROR_INVALID_PARAMETER),0,1,(PULONG_PTR)(rgpdli));
@@ -217,7 +222,13 @@ FARPROC WINAPI __delayLoadHelper2(PCImgDelayDescr 
pidd,FARPROC *ppfnIATEntry)
     }
   }
 SetEntryHookBypass:
+  while(InterlockedExchange(&gDelayLoadLock, 1) != 0)
+    Sleep(100);
+  bUnprotected = VirtualProtect(ppfnIATEntry, sizeof(FARPROC), PAGE_READWRITE, 
&dwOldProtect);
   *ppfnIATEntry = pfnRet;
+  if(bUnprotected && dwOldProtect != PAGE_READWRITE)
+    VirtualProtect(ppfnIATEntry, sizeof(FARPROC), dwOldProtect, &dwOldProtect);
+  InterlockedExchange(&gDelayLoadLock, 0);
 HookBypass:
   if(__pfnDliNotifyHook2) {
     dli.dwLastError = 0;
-- 
2.48.1

Attachment: OpenPGP_signature.asc
Description: OpenPGP digital signature

_______________________________________________
Mingw-w64-public mailing list
Mingw-w64-public@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/mingw-w64-public

Reply via email to