Skip to content

Commit

Permalink
Merge pull request #32 from itsmattkc/msil-patch-on-the-fly
Browse files Browse the repository at this point in the history
Patch MSIL files at build time
  • Loading branch information
itsmattkc authored Apr 20, 2024
2 parents 86d0cae + 61e8ac5 commit f7ba96a
Show file tree
Hide file tree
Showing 21 changed files with 132 additions and 4 deletions.
5 changes: 5 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,11 @@ jobs:
cd build
cmake .. -G "NMake Makefiles" -DCMAKE_BUILD_TYPE=Release
cmake --build .
- name: Generate patched MSIL
shell: cmd
run: |
msil\patch.bat
- name: Build installer
shell: cmd
Expand Down
Binary file added bin/ildasm/1033/IlDasmrc.dll
Binary file not shown.
Binary file added bin/ildasm/1033/TrackerUI.dll
Binary file not shown.
Binary file added bin/ildasm/1033/flogvwrc.dll
Binary file not shown.
Binary file added bin/ildasm/1033/gacutlrc.dll
Binary file not shown.
Binary file added bin/ildasm/1033/pevrfyrc.dll
Binary file not shown.
Binary file added bin/ildasm/1033/snrc.dll
Binary file not shown.
Binary file added bin/ildasm/ildasm.exe
Binary file not shown.
6 changes: 6 additions & 0 deletions bin/ildasm/ildasm.exe.config
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?xml version ="1.0"?>
<configuration>
<startup useLegacyV2RuntimeActivationPolicy="true">
<requiredRuntime safemode="true" imageVersion="v4.0.30319" version="v4.0.30319"/>
</startup>
</configuration>
Binary file added bin/patch/patch.exe
Binary file not shown.
2 changes: 1 addition & 1 deletion msil/README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Patched MSIL/managed code DLLs

This folder contains managed code DLLs that have been manually patched to redirect or remove references to Win32 APIs that do not exist on Windows 95. They have been edited with [https://github.com/dnSpy/dnSpy](dnSpy).
This folder contains patches for managed code DLLs to redirect or remove references to Win32 APIs that do not exist on Windows 95. They are applied to the MSIL that can be generated using `ildisasm` (in the `bin` folder) and reassembled with `ilasm` (in `bin/dotnetfx20/URTInstallPath`). For ease of use, a `patch.bat` script is provided which should automate this process.

.NET appears to use a hashing/signing system that will prevent these DLLs from getting installed into the Global Assembly Cache (GAC) by any normal means. Instead, the installer installs the original DLLs into the GAC and then clobbers them with these patched DLLs at the end. The hash/signing check is never done again so this ends up working, even though it is a hacky solution. There may be a better one I'm not aware of.
Binary file removed msil/System.Windows.Forms.dll
Binary file not shown.
20 changes: 20 additions & 0 deletions msil/System.Windows.Forms.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
--- System.Windows.Forms.asm.original 2024-04-19 12:15:06.880649435 -0700
+++ System.Windows.Forms.asm 2024-04-19 12:16:01.487091612 -0700
@@ -58528,7 +58528,7 @@
IL_000f: ret
} // end of method UnsafeNativeMethods::CreateMenu

- .method public hidebysig static pinvokeimpl("comdlg32.dll" autochar lasterr winapi)
+ .method public hidebysig static pinvokeimpl("corkel32.dll" autochar lasterr winapi)
bool GetOpenFileName([in][out] class System.Windows.Forms.NativeMethods/OPENFILENAME_I ofn) cil managed preservesig
{
}
@@ -59879,7 +59879,7 @@
[in][out] object& marshal( interface ) pAcc) cil managed preservesig
{
}
- .method public hidebysig static pinvokeimpl("user32.dll" nomangle autochar winapi)
+ .method public hidebysig static pinvokeimpl("corusr.dll" nomangle autochar winapi)
void NotifyWinEvent(int32 winEvent,
valuetype [mscorlib]System.Runtime.InteropServices.HandleRef hwnd,
int32 objType,
Binary file removed msil/System.configuration.dll
Binary file not shown.
19 changes: 19 additions & 0 deletions msil/System.configuration.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
--- System.configuration.asm.original 2024-04-19 13:20:09.458249700 -0700
+++ System.configuration.asm 2024-04-19 13:22:09.844507556 -0700
@@ -8,6 +8,7 @@
.module extern kernel32.dll
.module extern crypt32.dll
.module extern advapi32.dll
+.module extern corkel32.dll
.assembly extern mscorlib
{
.publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4..
@@ -71914,7 +71915,7 @@

.field static assembly literal int32 GetFileExInfoStandard = int32(0x00000000)
.field static assembly literal int32 MOVEFILE_REPLACE_EXISTING = int32(0x00000001)
- .method assembly hidebysig static pinvokeimpl("kernel32.dll" autochar lasterr winapi bestfit:off)
+ .method assembly hidebysig static pinvokeimpl("corkel32.dll" autochar lasterr winapi bestfit:off)
bool GetFileAttributesEx(string name,
int32 fileInfoLevel,
[out] valuetype Microsoft.Win32.UnsafeNativeMethods/WIN32_FILE_ATTRIBUTE_DATA& data) cil managed preservesig
Binary file removed msil/mscorlib.dll
Binary file not shown.
42 changes: 42 additions & 0 deletions msil/mscorlib.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
--- mscorlib.asm.original 2024-04-19 12:55:04.782157988 -0700
+++ mscorlib.asm 2024-04-19 12:57:54.287832486 -0700
@@ -11,6 +11,7 @@
.module extern kernel32.dll
.module extern mscorwks.dll
.module extern oleaut32.dll
+.module extern corkel32.dll
.module extern advapi32.dll
.module extern ole32.dll
.module extern user32.dll
@@ -367275,19 +367276,19 @@
native int mustBeZero) cil managed preservesig
{
}
- .method assembly hidebysig static pinvokeimpl("kernel32.dll" autochar lasterr winapi bestfit:off)
+ .method assembly hidebysig static pinvokeimpl("corkel32.dll" autochar lasterr winapi bestfit:off)
int32 GetLongPathName(string path,
class System.Text.StringBuilder longPathBuffer,
int32 bufferLength) cil managed preservesig
{
}
- .method assembly hidebysig static pinvokeimpl("kernel32.dll" autochar lasterr winapi bestfit:off)
+ .method assembly hidebysig static pinvokeimpl("corkel32.dll" autochar lasterr winapi bestfit:off)
int32 GetLongPathName([in] char[] path,
[out] char[] longPathBuffer,
int32 bufferLength) cil managed preservesig
{
}
- .method assembly hidebysig static pinvokeimpl("kernel32.dll" autochar lasterr winapi bestfit:off)
+ .method assembly hidebysig static pinvokeimpl("corkel32.dll" autochar lasterr winapi bestfit:off)
int32 GetLongPathName(char* path,
char* longPathBuffer,
int32 bufferLength) cil managed preservesig
@@ -367675,7 +367676,7 @@
class System.Text.StringBuilder lpBuffer) cil managed preservesig
{
}
- .method assembly hidebysig static pinvokeimpl("kernel32.dll" autochar lasterr winapi bestfit:off)
+ .method assembly hidebysig static pinvokeimpl("corkel32.dll" autochar lasterr winapi bestfit:off)
bool GetFileAttributesEx(string name,
int32 fileInfoLevel,
valuetype Microsoft.Win32.Win32Native/WIN32_FILE_ATTRIBUTE_DATA& lpFileInformation) cil managed preservesig
20 changes: 20 additions & 0 deletions msil/patch.bat
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
@echo off
setlocal
cd /d %~dp0
mkdir build
mkdir temp
cd temp

goto patchFiles

:doPatch
..\..\bin\ildasm\ildasm.exe /out=%~1.asm ../../bin/dotnetfx20/URTInstallPath/%~1.dll
..\..\bin\patch\patch %~1.asm ..\%~1.patch
..\..\bin\dotnetfx20\URTInstallPath\ilasm.exe /dll %~1.asm
copy %~1.dll ..\build
goto :eof

:patchFiles
call:doPatch System.Windows.Forms
call:doPatch mscorlib
call:doPatch System.configuration
6 changes: 3 additions & 3 deletions setup/dotnet9x.nsi
Original file line number Diff line number Diff line change
Expand Up @@ -5583,11 +5583,11 @@ File /r "..\wrappers\build\*.dll"
!insertmacro Check95 0 SkipNET20MSILPatches

SetOutPath $WINDIR\assembly\GAC_MSIL\System.Windows.Forms\2.0.0.0__b77a5c561934e089
File "..\msil\System.Windows.Forms.dll"
File "..\msil\build\System.Windows.Forms.dll"
SetOutPath $WINDIR\assembly\GAC_32\mscorlib\2.0.0.0__b77a5c561934e089
File "..\msil\mscorlib.dll"
File "..\msil\build\mscorlib.dll"
SetOutPath $WINDIR\assembly\GAC_MSIL\System.Configuration\2.0.0.0__b03f5f7f11d50a3a
File "..\msil\System.configuration.dll"
File "..\msil\build\System.configuration.dll"

SkipNET20MSILPatches:

Expand Down
1 change: 1 addition & 0 deletions wrappers/corusr.def
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ EXPORTS
MsgWaitForMultipleObjects=CORUSR_MsgWaitForMultipleObjects
MsgWaitForMultipleObjectsEx=CORUSR_MsgWaitForMultipleObjectsEx
wsprintfW=CORUSR_wsprintfW
NotifyWinEvent=CORUSR_NotifyWinEvent

GetUserObjectInformationW=USER32.GetUserObjectInformationW
PostMessageW=USER32.PostMessageW
Expand Down
15 changes: 15 additions & 0 deletions wrappers/user32.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,18 @@ INT WINAPIV CORUSR_wsprintfW(LPWSTR param_0, LPCWSTR param_1, ...)

return r;
}

void WINAPI CORUSR_NotifyWinEvent(DWORD event, HWND hwnd, LONG idObject, LONG idChild)
{
// Only Windows 95 lacks this function so if we have it, we passthrough.
// Otherwise, just do nothing.

typedef void (WINAPI *NotifyWinEvent_t)(DWORD, HWND, LONG, LONG);
NotifyWinEvent_t notifyWinEvent = (NotifyWinEvent_t) GetProcAddress(GetModuleHandleA("USER32.DLL"), "NotifyWinEvent");

Trace(TRACE_IMPLEMENTED, "NotifyWinEvent");

if (notifyWinEvent) {
notifyWinEvent(event, hwnd, idObject, idChild);
}
}

0 comments on commit f7ba96a

Please sign in to comment.