Hi @ll, on x64 editions of Windows, RegEdit.exe exists both as %windir%\regedit.exe and %windir%\SysWOW64\regedit.exe. <https://msdn.microsoft.com/en-us/library/aa384187.aspx> states | [...] whenever a 32-bit application attempts to access [...] | %windir%\regedit.exe is redirected to %windir%\SysWOW64\regedit.exe. But what is the "application directory" when a 32-bit application runs %windir%\regedit.exe? Is it %windir% or %windir%\SysWOW64, i.e. is it determined before or after the redirection? Remember that the "application directory" comes first in the standard/default DLL search order, as documented in <https://msdn.microsoft.com/en-us/library/ms682586.aspx> Since the 32-bit system DLLs are located in %windir%\SysWOW64, NOT in %windir%, this makes a difference... 1. compile the following source as 32-bit program: --- POC.C --- #pragma comment(lib, "KERNEL32.LIB") #pragma comment(linker, "/ENTRY:WinMainCRTStartup") #pragma comment(linker, "/SUBSYSTEM:Windows") #include <windows.h> void WinMainCRTStartup() { STARTUPINFO si = {sizeof(STARTUPINFO)}; PROCESS_INFORMATION pi = {0}; if (!CreateProcess("C:\\Windows\\regedit.exe", "* /M", NULL, NULL, FALSE, 0L, NULL, NULL, &si, &pi)) ExitProcess(GetLastError()); if (WaitForSingleObject(pi.hProcess, INFINITE) == WAIT_FAILED) ExitProcess(GetLastError()); if (!CloseHandle(pi.hThread)) ExitProcess(GetLastError()); if (!CloseHandle(pi.hProcess)) ExitProcess(GetLastError()); ExitProcess(ERROR_SUCCESS); } --- EOF --- 2. download <http://home.arcor.de/skanthak/temp/REGEDIT.CAB> and extract its contents to %windir%: WUSA.EXE /Extract:REGEDIT.CAB %windir% (yes, this needs administrative privileges, but that's NOT the point here). The 32-bit DLLs in REGEDIT.CAB are transparent proxies: they export all symbols and ordinals of their counterparts found in the "system directory" and forward them to these counterparts. --- FORWARD.C --- #pragma comment(linker, "/DLL") #pragma comment(linker, "/ENTRY:_DllMainCRTStartup") #pragma comment(linker, "/EXPORT:<symbol>=System32\\<filename>.<symbol>,@<ordinal>") ... #pragma comment(linker, "/EXPORT:<ordinal>=System32\\<filename>.#<ordinal>,@<ordinal>,NONAME") ... #pragma comment(linker, "/SUBSYSTEM:Windows") #include <windows.h> BOOL WINAPI _DllMainCRTStartup(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { MessageBox(...); return TRUE; } --- EOF --- See <http://home.arcor.de/skanthak/sentinel.html> for details. 3. run the program compiled in step 1: notice the message boxes displayed from the DLLs extracted to %windir% in step 2 and loaded by %windir%\SysWOW64\regedit.exe: the "application directory" of %windir%\SysWOW64\regedit.exe is %windir%\, NOT %windir%\SysWOW64\! Or use the 32-bit NTSD.EXE run %windir%\regedit.exe: you'll see the message boxes too plus the debugger output as shown in <http://home.arcor.de/skanthak/temp/REGEDIT.TXT> 4. finally use the 64-bit NTSD.EXE to run %windir%\regedit.exe: see <http://home.arcor.de/skanthak/temp/REGEDIT.LOG> for the debugger output. Notice that the 32-bit forwarder DLLs are loaded in the 64-bit process and that their exports/forwards are processed properly! Their DllMain() extry points are but NOT called (if they were you'd see some message boxes)! stay tuned Stefan Kanthak PS: the test whether 64-bit forwarder DLLs placed in %windir% are loaded in the 32-bit process %windir%\SysWOW64\regedit.exe is left as an exercise to the reader.