From 9661df2c722041fe4586c13315f5a6844b4e0a8a Mon Sep 17 00:00:00 2001 From: Pavel <68122101+red-prig@users.noreply.github.com> Date: Mon, 3 Feb 2025 17:01:52 +0300 Subject: [PATCH] ms shell hack This hack explicitly prevents third-party shell extensions from injecting into other threads. --- fpPS4.lpi | 4 ++ gui/game_edit.pas | 7 ++ gui/main.pas | 12 +++- gui/ms_shell_hack.pas | 159 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 180 insertions(+), 2 deletions(-) create mode 100644 gui/ms_shell_hack.pas diff --git a/fpPS4.lpi b/fpPS4.lpi index 36e9ae33..8d8e5630 100644 --- a/fpPS4.lpi +++ b/fpPS4.lpi @@ -1566,6 +1566,10 @@ + + + + diff --git a/gui/game_edit.pas b/gui/game_edit.pas index ef74c50e..f3c457c1 100644 --- a/gui/game_edit.pas +++ b/gui/game_edit.pas @@ -8,6 +8,8 @@ uses Classes, SysUtils, Forms, Controls, Graphics, Dialogs, ComCtrls, ExtCtrls, StdCtrls, Grids, + ms_shell_hack, + game_info, param_sfo_gui; @@ -96,7 +98,10 @@ type procedure TButtonPath.OpenDir(Sender:TObject); var d:TSelectDirectoryDialog; + Cookie:Pointer; begin + Cookie:=RegisterDllHack; + d:=nil; try @@ -120,6 +125,8 @@ begin end; FreeAndNil(d); + UnregisterDllHack(Cookie); + TfrmGameEditor(Self.Form).LoadParamSfo(True); Hide; diff --git a/gui/main.pas b/gui/main.pas index 6b2022e0..ee185585 100644 --- a/gui/main.pas +++ b/gui/main.pas @@ -22,6 +22,8 @@ uses Rtti, jsonscanner, + ms_shell_hack, + host_ipc, game_info, game_edit, @@ -1128,8 +1130,12 @@ procedure TfrmMain.MIAddFolderClick(Sender: TObject); var d:TSelectDirectoryDialog; form:TfrmGameEditor; + + Cookie:Pointer; begin - d:=TSelectDirectoryDialog.Create(nil); + Cookie:=RegisterDllHack; + + d:=TSelectDirectoryDialog.Create(Self); //d.InitialDir:= @@ -1151,7 +1157,9 @@ begin form.FormInit(True); end; - d.Free; + FreeAndNil(d); + + UnregisterDllHack(Cookie); end; procedure TfrmMain.MIEditClick(Sender: TObject); diff --git a/gui/ms_shell_hack.pas b/gui/ms_shell_hack.pas new file mode 100644 index 00000000..d625c2a2 --- /dev/null +++ b/gui/ms_shell_hack.pas @@ -0,0 +1,159 @@ +unit ms_shell_hack; + +{$mode ObjFPC}{$H+} + +interface + +function RegisterDllHack:Pointer; +Procedure UnregisterDllHack(Cookie:Pointer); + +implementation + +Uses + sysutils, + windows, + ntapi, + versionresource, + versiontypes, + CharStream; + +type + P_LDR_DLL_NOTIFICATION_DATA=^LDR_DLL_NOTIFICATION_DATA; + LDR_DLL_NOTIFICATION_DATA=record + Flags :ULONG; + FullDllName:PUNICODE_STRING; + BaseDllName:PUNICODE_STRING; + DllBase :Pointer; + SizeOfImage:ULONG; + end; + +type + TLdrDllNotification=procedure( + NotificationReason:ULONG; + NotificationData :P_LDR_DLL_NOTIFICATION_DATA; + Context :Pointer + ); MS_ABI_Default; + +function LdrRegisterDllNotification( + Flags :ULONG; + NotifFunction:TLdrDllNotification; + Context :Pointer; + Cookie :PPointer + ):DWORD; MS_ABI_Default; external 'ntdll'; + +function LdrUnregisterDllNotification( + Cookie:Pointer + ):DWORD; MS_ABI_Default; external 'ntdll'; + +function LdrResSearchResource( + DllBase :Pointer; + ResIds :PULONG_PTR; + ResIdCount :ULONG; + Flags :ULONG; + Resource :PPointer; + Size :PULONG_PTR; + FoundLanguage :PUSHORT; + FoundLanguageLength:PULONG + ):DWORD; MS_ABI_Default; external 'ntdll'; + +const + RT_VERSION=16; + CREATEPROCESS_MANIFEST_RESOURCE_ID=1; + + IdPath:array[0..2] of ULONG_PTR=( + RT_VERSION, + CREATEPROCESS_MANIFEST_RESOURCE_ID, + 0 + ); + +Function GetCompanyName(Data:Pointer;Size:ULONG_PTR):RawByteString; +label + _exit; +var + VR:TVersionResource; + SI:TVersionStringFileInfo; + ST:TVersionStringTable; + mem:TPCharStream; + + i,k:Integer; +begin + Result:=''; + + mem:=TPCharStream.Create(Data,Size); + + VR:=TVersionResource.Create; + VR.SetCustomRawDataStream(mem); + VR.UpdateRawData; + SI:=VR.StringFileInfo; + + if (SI.Count<>0) then + For i:=0 to SI.Count-1 do + begin + ST:=SI[i]; + // + if (ST.Count<>0) then + begin + For k:=0 to ST.Count-1 do + begin + if (ST.Keys[k]='CompanyName') then + begin + Result:=ST.ValuesByIndex[k]; + goto _exit; + end; + end; + end; + // + end; + + _exit: + + FreeAndNil(VR); + FreeAndNil(mem); +end; + +procedure LdrDllNotification( + NotificationReason:ULONG; + NotificationData :P_LDR_DLL_NOTIFICATION_DATA; + Context :Pointer + ); MS_ABI_Default; +var + Data:Pointer; + Size:ULONG_PTR; +begin + if (NotificationReason<>1) then Exit; + + Data:=nil; + Size:=0; + + LdrResSearchResource( + NotificationData^.DllBase, + @IdPath, + 3, + 0, + @Data, + @Size, + nil, + nil + ); + + if (Data=nil) then Exit; + + if (GetCompanyName(Data,Size)='Microsoft Corporation') then Exit; + + DisableThreadLibraryCalls(QWORD(NotificationData^.DllBase)); +end; + +function RegisterDllHack:Pointer; +begin + Result:=nil; + LdrRegisterDllNotification(0,@LdrDllNotification,nil,@Result); +end; + +Procedure UnregisterDllHack(Cookie:Pointer); +begin + LdrUnregisterDllNotification(Cookie); +end; + + +end. +