123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737 |
- {
- Copyright 2014 Stas'M Corp.
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
- http://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- }
- library rdpwrap;
- uses
- SysUtils,
- Windows,
- TlHelp32,
- LiteINI;
- {$R rdpwrap.res}
- // Hook core definitions
- type
- OldCode = packed record
- One: DWORD;
- two: Word;
- end;
- far_jmp = packed record
- PushOp: Byte;
- PushArg: Pointer;
- RetOp: Byte;
- end;
- mov_far_jmp = packed record
- MovOp: Byte;
- MovArg: Byte;
- PushOp: Byte;
- PushArg: Pointer;
- RetOp: Byte;
- end;
- TTHREADENTRY32 = packed record
- dwSize: DWORD;
- cntUsage: DWORD;
- th32ThreadID: DWORD;
- th32OwnerProcessID: DWORD;
- tpBasePri: LongInt;
- tpDeltaPri: LongInt;
- dwFlags: DWORD;
- end;
- //IntArray = Array of Integer;
- FILE_VERSION = record
- Version: record case Boolean of
- True: (dw: DWORD);
- False: (w: record
- Minor, Major: Word;
- end;)
- end;
- Release, Build: Word;
- bDebug, bPrerelease, bPrivate, bSpecial: Boolean;
- end;
- const
- THREAD_SUSPEND_RESUME = 2;
- TH32CS_SNAPTHREAD = 4;
- var
- INI: INIFile;
- LogFile: String = '\rdpwrap.txt';
- bw: {$if CompilerVersion>=16} NativeUInt {$else} DWORD {$endif};
- IsHooked: Boolean = False;
- // Unhooked import
- function OpenThread(dwDesiredAccess: DWORD; bInheritHandle: BOOL;
- dwThreadId: DWORD): DWORD; stdcall; external kernel32;
- function CreateToolhelp32Snapshot(dwFlags, th32ProcessID: DWORD): DWORD;
- stdcall; external kernel32;
- function Thread32First(hSnapshot: THandle; var lpte: TTHREADENTRY32): bool;
- stdcall; external kernel32;
- function Thread32Next(hSnapshot: THandle; var lpte: TTHREADENTRY32): bool;
- stdcall; external kernel32;
- // Wrapped import
- var
- TSMain: function(dwArgc: DWORD; lpszArgv: PWideChar): DWORD; stdcall;
- TSGlobals: function(lpGlobalData: Pointer): DWORD; stdcall;
- // Hooked import and vars
- var
- SLGetWindowsInformationDWORD: function(pwszValueName: PWideChar;
- pdwValue: PDWORD): HRESULT; stdcall;
- TermSrvBase: Pointer;
- FV: FILE_VERSION;
- var
- Stub_SLGetWindowsInformationDWORD: far_jmp;
- Old_SLGetWindowsInformationDWORD: OldCode;
- // Main code
- procedure WriteLog(S: AnsiString);
- var
- F: TextFile;
- begin
- if not FileExists(LogFile) then
- Exit;
- AssignFile(F, LogFile);
- Append(F);
- Write(F, S+#13#10);
- CloseFile(F);
- end;
- function GetModuleHandleEx(dwFlags: DWORD; lpModuleName: PWideChar;
- var phModule: HMODULE): BOOL; stdcall; external kernel32 name 'GetModuleHandleExW';
- function GetCurrentModule: HMODULE;
- const
- GET_MODULE_HANDLE_EX_FLAG_PIN = 1;
- GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT = 2;
- GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS = 4;
- begin
- Result := 0;
- GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, @GetCurrentModule, Result);
- end;
- function GetBinaryPath: String;
- var
- Buf: Array[0..511] of Byte;
- begin
- ZeroMemory(@Buf[0], Length(Buf));
- GetModuleFileName(GetCurrentModule, PWideChar(@Buf[0]), Length(Buf));
- Result := PWideChar(@Buf[0]);
- end;
- procedure StopThreads;
- var
- h, CurrTh, ThrHandle, CurrPr: DWORD;
- Thread: TTHREADENTRY32;
- begin
- CurrTh := GetCurrentThreadId;
- CurrPr := GetCurrentProcessId;
- h := CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
- if h <> INVALID_HANDLE_VALUE then
- begin
- Thread.dwSize := SizeOf(TTHREADENTRY32);
- if Thread32First(h, Thread) then
- repeat
- if (Thread.th32ThreadID <> CurrTh) and
- (Thread.th32OwnerProcessID = CurrPr) then
- begin
- ThrHandle := OpenThread(THREAD_SUSPEND_RESUME, false,
- Thread.th32ThreadID);
- if ThrHandle > 0 then
- begin
- SuspendThread(ThrHandle);
- CloseHandle(ThrHandle);
- end;
- end;
- until not Thread32Next(h, Thread);
- CloseHandle(h);
- end;
- end;
- procedure RunThreads;
- var
- h, CurrTh, ThrHandle, CurrPr: DWORD;
- Thread: TTHREADENTRY32;
- begin
- CurrTh := GetCurrentThreadId;
- CurrPr := GetCurrentProcessId;
- h := CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
- if h <> INVALID_HANDLE_VALUE then
- begin
- Thread.dwSize := SizeOf(TTHREADENTRY32);
- if Thread32First(h, Thread) then
- repeat
- if (Thread.th32ThreadID <> CurrTh) and
- (Thread.th32OwnerProcessID = CurrPr) then
- begin
- ThrHandle := OpenThread(THREAD_SUSPEND_RESUME, false,
- Thread.th32ThreadID);
- if ThrHandle > 0 then
- begin
- ResumeThread(ThrHandle);
- CloseHandle(ThrHandle);
- end;
- end;
- until not Thread32Next(h, Thread);
- CloseHandle(h);
- end;
- end;
- function GetModuleAddress(ModuleName: String; ProcessId: DWORD; var BaseAddr: Pointer; var BaseSize: DWORD): Boolean;
- var
- hSnap: THandle;
- md: MODULEENTRY32;
- begin
- Result := False;
- hSnap := CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, ProcessId);
- if hSnap = INVALID_HANDLE_VALUE Then
- Exit;
- md.dwSize := SizeOf(MODULEENTRY32);
- if Module32First(hSnap, md) then
- begin
- if LowerCase(ExtractFileName(md.szExePath)) = LowerCase(ModuleName) then
- begin
- Result := True;
- BaseAddr := Pointer(md.modBaseAddr);
- BaseSize := md.modBaseSize;
- CloseHandle(hSnap);
- Exit;
- end;
- while Module32Next(hSnap, md) Do
- begin
- if LowerCase(ExtractFileName(md.szExePath)) = LowerCase(ModuleName) then
- begin
- Result := True;
- BaseAddr := Pointer(md.modBaseAddr);
- BaseSize := md.modBaseSize;
- Break;
- end;
- end;
- end;
- CloseHandle(hSnap);
- end;
- {procedure FindMem(Mem: Pointer; MemSz: DWORD; Buf: Pointer; BufSz: DWORD;
- From: DWORD; var A: IntArray);
- var
- I: Integer;
- begin
- SetLength(A, 0);
- I:=From;
- if From>0 then
- Inc(PByte(Mem), From);
- while I < MemSz - BufSz + 1 do
- begin
- if (not IsBadReadPtr(Mem, BufSz)) and (CompareMem(Mem, Buf, BufSz)) then
- begin
- SetLength(A, Length(A)+1);
- A[Length(A)-1] := I;
- end;
- Inc(I);
- Inc(PByte(Mem));
- end;
- end;}
- function GetModuleVersion(const ModuleName: String; var FileVersion: FILE_VERSION): Boolean;
- type
- VS_VERSIONINFO = record
- wLength, wValueLength, wType: Word;
- szKey: Array[1..16] of WideChar;
- Padding1: Word;
- Value: VS_FIXEDFILEINFO;
- Padding2, Children: Word;
- end;
- PVS_VERSIONINFO = ^VS_VERSIONINFO;
- const
- VFF_DEBUG = 1;
- VFF_PRERELEASE = 2;
- VFF_PRIVATE = 8;
- VFF_SPECIAL = 32;
- var
- hMod: HMODULE;
- hResourceInfo: HRSRC;
- VersionInfo: PVS_VERSIONINFO;
- begin
- Result := False;
- if ModuleName = '' then
- hMod := GetModuleHandle(nil)
- else
- hMod := GetModuleHandle(PWideChar(ModuleName));
- if hMod = 0 then
- Exit;
- hResourceInfo := FindResource(hMod, PWideChar(1), PWideChar($10));
- if hResourceInfo = 0 then
- Exit;
- VersionInfo := Pointer(LoadResource(hMod, hResourceInfo));
- if VersionInfo = nil then
- Exit;
- FileVersion.Version.dw := VersionInfo.Value.dwFileVersionMS;
- FileVersion.Release := Word(VersionInfo.Value.dwFileVersionLS shr 16);
- FileVersion.Build := Word(VersionInfo.Value.dwFileVersionLS);
- FileVersion.bDebug := (VersionInfo.Value.dwFileFlags and VFF_DEBUG) = VFF_DEBUG;
- FileVersion.bPrerelease := (VersionInfo.Value.dwFileFlags and VFF_PRERELEASE) = VFF_PRERELEASE;
- FileVersion.bPrivate := (VersionInfo.Value.dwFileFlags and VFF_PRIVATE) = VFF_PRIVATE;
- FileVersion.bSpecial := (VersionInfo.Value.dwFileFlags and VFF_SPECIAL) = VFF_SPECIAL;
- Result := True;
- end;
- function GetFileVersion(const FileName: String; var FileVersion: FILE_VERSION): Boolean;
- type
- VS_VERSIONINFO = record
- wLength, wValueLength, wType: Word;
- szKey: Array[1..16] of WideChar;
- Padding1: Word;
- Value: VS_FIXEDFILEINFO;
- Padding2, Children: Word;
- end;
- PVS_VERSIONINFO = ^VS_VERSIONINFO;
- const
- VFF_DEBUG = 1;
- VFF_PRERELEASE = 2;
- VFF_PRIVATE = 8;
- VFF_SPECIAL = 32;
- var
- hFile: HMODULE;
- hResourceInfo: HRSRC;
- VersionInfo: PVS_VERSIONINFO;
- begin
- Result := False;
- hFile := LoadLibraryEx(PWideChar(FileName), 0, LOAD_LIBRARY_AS_DATAFILE);
- if hFile = 0 then
- Exit;
- hResourceInfo := FindResource(hFile, PWideChar(1), PWideChar($10));
- if hResourceInfo = 0 then
- Exit;
- VersionInfo := Pointer(LoadResource(hFile, hResourceInfo));
- if VersionInfo = nil then
- Exit;
- FileVersion.Version.dw := VersionInfo.Value.dwFileVersionMS;
- FileVersion.Release := Word(VersionInfo.Value.dwFileVersionLS shr 16);
- FileVersion.Build := Word(VersionInfo.Value.dwFileVersionLS);
- FileVersion.bDebug := (VersionInfo.Value.dwFileFlags and VFF_DEBUG) = VFF_DEBUG;
- FileVersion.bPrerelease := (VersionInfo.Value.dwFileFlags and VFF_PRERELEASE) = VFF_PRERELEASE;
- FileVersion.bPrivate := (VersionInfo.Value.dwFileFlags and VFF_PRIVATE) = VFF_PRIVATE;
- FileVersion.bSpecial := (VersionInfo.Value.dwFileFlags and VFF_SPECIAL) = VFF_SPECIAL;
- Result := True;
- end;
- function OverrideSL(ValueName: String; var Value: DWORD): Boolean;
- begin
- Result := True;
- if INIValueExists(INI, 'SLPolicy', ValueName) then begin
- Value := INIReadDWord(INI, 'SLPolicy', ValueName, 0);
- Exit;
- end;
- Result := False;
- end;
- function New_SLGetWindowsInformationDWORD(pwszValueName: PWideChar;
- pdwValue: PDWORD): HRESULT; stdcall;
- var
- dw: DWORD;
- begin
- // wrapped SLGetWindowsInformationDWORD function
- // termsrv.dll will call this function instead of original SLC.dll
- // Override SL Policy
- WriteLog('Policy query: ' + pwszValueName);
- if OverrideSL(pwszValueName, dw) then begin
- pdwValue^ := dw;
- Result := S_OK;
- WriteLog('Policy rewrite: ' + IntToStr(pdwValue^));
- Exit;
- end;
- // If the requested value name is not defined above
- // revert to original SL Policy function
- WriteProcessMemory(GetCurrentProcess, @SLGetWindowsInformationDWORD,
- @Old_SLGetWindowsInformationDWORD, SizeOf(OldCode), bw);
- // get result
- Result := SLGetWindowsInformationDWORD(pwszValueName, pdwValue);
- if Result = S_OK then
- WriteLog('Policy result: ' + IntToStr(pdwValue^))
- else
- WriteLog('Policy request failed');
- // wrap it back
- WriteProcessMemory(GetCurrentProcess, @SLGetWindowsInformationDWORD,
- @Stub_SLGetWindowsInformationDWORD, SizeOf(far_jmp), bw);
- end;
- function New_Win8SL(pwszValueName: PWideChar; pdwValue: PDWORD): HRESULT; register;
- var
- dw: DWORD;
- begin
- // wrapped unexported function SLGetWindowsInformationDWORDWrapper in termsrv.dll
- // for Windows 8 support
- // Override SL Policy
- WriteLog('Policy query: ' + pwszValueName);
- if OverrideSL(pwszValueName, dw) then begin
- pdwValue^ := dw;
- Result := S_OK;
- WriteLog('Policy rewrite: ' + IntToStr(pdwValue^));
- Exit;
- end;
- // If the requested value name is not defined above
- // use function from SLC.dll
- Result := SLGetWindowsInformationDWORD(pwszValueName, pdwValue);
- if Result = S_OK then
- WriteLog('Policy result: ' + IntToStr(pdwValue^))
- else
- WriteLog('Policy request failed');
- end;
- function New_Win8SL_CP(eax: DWORD; pdwValue: PDWORD; ecx: DWORD; pwszValueName: PWideChar): HRESULT; register;
- begin
- // wrapped unexported function SLGetWindowsInformationDWORDWrapper in termsrv.dll
- // for Windows 8 Consumer Preview support
- Result := New_Win8SL(pwszValueName, pdwValue);
- end;
- function New_CSLQuery_Initialize: HRESULT; stdcall;
- var
- Sect: String;
- bServerSku,
- bRemoteConnAllowed,
- bFUSEnabled,
- bAppServerAllowed,
- bMultimonAllowed,
- lMaxUserSessions,
- ulMaxDebugSessions,
- bInitialized: PDWORD;
- begin
- bServerSku := nil;
- bRemoteConnAllowed := nil;
- bFUSEnabled := nil;
- bAppServerAllowed := nil;
- bMultimonAllowed := nil;
- lMaxUserSessions := nil;
- ulMaxDebugSessions := nil;
- bInitialized := nil;
- WriteLog('>>> CSLQuery::Initialize');
- Sect := IntToStr(FV.Version.w.Major)+'.'+IntToStr(FV.Version.w.Minor)+'.'+
- IntToStr(FV.Release)+'.'+IntToStr(FV.Build)+'-SLInit';
- if INISectionExists(INI, Sect) then begin
- bServerSku := Pointer(Cardinal(TermSrvBase) + INIReadDWordHex(INI, Sect, 'bServerSku.x86', 0));
- bRemoteConnAllowed := Pointer(Cardinal(TermSrvBase) + INIReadDWordHex(INI, Sect, 'bRemoteConnAllowed.x86', 0));
- bFUSEnabled := Pointer(Cardinal(TermSrvBase) + INIReadDWordHex(INI, Sect, 'bFUSEnabled.x86', 0));
- bAppServerAllowed := Pointer(Cardinal(TermSrvBase) + INIReadDWordHex(INI, Sect, 'bAppServerAllowed.x86', 0));
- bMultimonAllowed := Pointer(Cardinal(TermSrvBase) + INIReadDWordHex(INI, Sect, 'bMultimonAllowed.x86', 0));
- lMaxUserSessions := Pointer(Cardinal(TermSrvBase) + INIReadDWordHex(INI, Sect, 'lMaxUserSessions.x86', 0));
- ulMaxDebugSessions := Pointer(Cardinal(TermSrvBase) + INIReadDWordHex(INI, Sect, 'ulMaxDebugSessions.x86', 0));
- bInitialized := Pointer(Cardinal(TermSrvBase) + INIReadDWordHex(INI, Sect, 'bInitialized.x86', 0));
- end;
- if bServerSku <> nil then begin
- bServerSku^ := INIReadDWord(INI, 'SLInit', 'bServerSku', 1);
- WriteLog('SLInit [0x'+IntToHex(DWORD(bServerSku), 1)+'] bServerSku = ' + IntToStr(bServerSku^));
- end;
- if bRemoteConnAllowed <> nil then begin
- bRemoteConnAllowed^ := INIReadDWord(INI, 'SLInit', 'bRemoteConnAllowed', 1);
- WriteLog('SLInit [0x'+IntToHex(DWORD(bRemoteConnAllowed), 1)+'] bRemoteConnAllowed = ' + IntToStr(bRemoteConnAllowed^));
- end;
- if bFUSEnabled <> nil then begin
- bFUSEnabled^ := INIReadDWord(INI, 'SLInit', 'bFUSEnabled', 1);
- WriteLog('SLInit [0x'+IntToHex(DWORD(bFUSEnabled), 1)+'] bFUSEnabled = ' + IntToStr(bFUSEnabled^));
- end;
- if bAppServerAllowed <> nil then begin
- bAppServerAllowed^ := INIReadDWord(INI, 'SLInit', 'bAppServerAllowed', 1);
- WriteLog('SLInit [0x'+IntToHex(DWORD(bAppServerAllowed), 1)+'] bAppServerAllowed = ' + IntToStr(bAppServerAllowed^));
- end;
- if bMultimonAllowed <> nil then begin
- bMultimonAllowed^ := INIReadDWord(INI, 'SLInit', 'bMultimonAllowed', 1);
- WriteLog('SLInit [0x'+IntToHex(DWORD(bMultimonAllowed), 1)+'] bMultimonAllowed = ' + IntToStr(bMultimonAllowed^));
- end;
- if lMaxUserSessions <> nil then begin
- lMaxUserSessions^ := INIReadDWord(INI, 'SLInit', 'lMaxUserSessions', 0);
- WriteLog('SLInit [0x'+IntToHex(DWORD(lMaxUserSessions), 1)+'] lMaxUserSessions = ' + IntToStr(lMaxUserSessions^));
- end;
- if ulMaxDebugSessions <> nil then begin
- ulMaxDebugSessions^ := INIReadDWord(INI, 'SLInit', 'ulMaxDebugSessions', 0);
- WriteLog('SLInit [0x'+IntToHex(DWORD(ulMaxDebugSessions), 1)+'] ulMaxDebugSessions = ' + IntToStr(ulMaxDebugSessions^));
- end;
- if bInitialized <> nil then begin
- bInitialized^ := INIReadDWord(INI, 'SLInit', 'bInitialized', 1);
- WriteLog('SLInit [0x'+IntToHex(DWORD(bInitialized), 1)+'] bInitialized = ' + IntToStr(bInitialized^));
- end;
- Result := S_OK;
- WriteLog('<<< CSLQuery::Initialize');
- end;
- procedure HookFunctions;
- var
- ConfigFile, Sect, FuncName: String;
- V: DWORD;
- TS_Handle, SLC_Handle: THandle;
- TermSrvSize: DWORD;
- SignPtr: Pointer;
- I: Integer;
- PatchList: SList;
- Patch: Array of TBytes;
- Jump: far_jmp;
- MovJump: mov_far_jmp;
- begin
- { hook function ^^
- (called once) }
- IsHooked := True;
- TSMain := nil;
- TSGlobals := nil;
- SLGetWindowsInformationDWORD := nil;
- WriteLog('Loading configuration...');
- ConfigFile := ExtractFilePath(GetBinaryPath) + 'rdpwrap.ini';
- WriteLog('Configuration file: ' + ConfigFile);
- INILoad(INI, ConfigFile);
- if Length(INI) = 0 then begin
- WriteLog('Error: Failed to load configuration');
- Exit;
- end;
- LogFile := INIReadString(INI, 'Main', 'LogFile', ExtractFilePath(GetBinaryPath) + 'rdpwrap.txt');
- WriteLog('Initializing RDP Wrapper...');
- // load termsrv.dll and get functions
- TS_Handle := LoadLibrary('termsrv.dll');
- if TS_Handle = 0 then begin
- WriteLog('Error: Failed to load Terminal Services library');
- Exit;
- end;
- TSMain := GetProcAddress(TS_Handle, 'ServiceMain');
- TSGlobals := GetProcAddress(TS_Handle, 'SvchostPushServiceGlobals');
- WriteLog(
- 'Base addr: 0x' + IntToHex(TS_Handle, 8) + #13#10 +
- 'SvcMain: termsrv.dll+0x' + IntToHex(Cardinal(@TSMain) - TS_Handle, 1) + #13#10 +
- 'SvcGlobals: termsrv.dll+0x' + IntToHex(Cardinal(@TSGlobals) - TS_Handle, 1)
- );
- V := 0;
- // check termsrv version
- if GetModuleVersion('termsrv.dll', FV) then
- V := Byte(FV.Version.w.Minor) or (Byte(FV.Version.w.Major) shl 8)
- else begin
- // check NT version
- // V := GetVersion; // deprecated
- // V := ((V and $FF) shl 8) or ((V and $FF00) shr 8);
- end;
- if V = 0 then begin
- WriteLog('Error: Failed to detect Terminal Services version');
- Exit;
- end;
- WriteLog('Version: '+
- IntToStr(FV.Version.w.Major)+'.'+
- IntToStr(FV.Version.w.Minor)+'.'+
- IntToStr(FV.Release)+'.'+
- IntToStr(FV.Build));
- // temporarily freeze threads
- WriteLog('Freezing threads...');
- StopThreads();
- WriteLog('Caching patch codes...');
- PatchList := INIReadSection(INI, 'PatchCodes');
- SetLength(Patch, Length(PatchList));
- for I := 0 to Length(Patch) - 1 do begin
- Patch[I] := INIReadBytes(INI, 'PatchCodes', PatchList[I]);
- if Length(Patch[I]) > 16 then // for security reasons
- SetLength(Patch[I], 16); // not more than 16 bytes
- end;
- if (V = $0600) and (INIReadBool(INI, 'Main', 'SLPolicyHookNT60', True)) then begin
- // Windows Vista
- // uses SL Policy API (slc.dll)
- // load slc.dll and hook function
- SLC_Handle := LoadLibrary('slc.dll');
- SLGetWindowsInformationDWORD := GetProcAddress(SLC_Handle, 'SLGetWindowsInformationDWORD');
- if @SLGetWindowsInformationDWORD <> nil then
- begin
- // rewrite original function to call our function (make hook)
- WriteLog('Hook SLGetWindowsInformationDWORD');
- Stub_SLGetWindowsInformationDWORD.PushOp := $68;
- Stub_SLGetWindowsInformationDWORD.PushArg := @New_SLGetWindowsInformationDWORD;
- Stub_SLGetWindowsInformationDWORD.RetOp := $C3;
- ReadProcessMemory(GetCurrentProcess, @SLGetWindowsInformationDWORD,
- @Old_SLGetWindowsInformationDWORD, SizeOf(OldCode), bw);
- WriteProcessMemory(GetCurrentProcess, @SLGetWindowsInformationDWORD,
- @Stub_SLGetWindowsInformationDWORD, SizeOf(far_jmp), bw);
- end;
- end;
- if (V = $0601) and (INIReadBool(INI, 'Main', 'SLPolicyHookNT61', True)) then begin
- // Windows 7
- // uses SL Policy API (slc.dll)
- // load slc.dll and hook function
- SLC_Handle := LoadLibrary('slc.dll');
- SLGetWindowsInformationDWORD := GetProcAddress(SLC_Handle, 'SLGetWindowsInformationDWORD');
- if @SLGetWindowsInformationDWORD <> nil then
- begin
- // rewrite original function to call our function (make hook)
- WriteLog('Hook SLGetWindowsInformationDWORD');
- Stub_SLGetWindowsInformationDWORD.PushOp := $68;
- Stub_SLGetWindowsInformationDWORD.PushArg := @New_SLGetWindowsInformationDWORD;
- Stub_SLGetWindowsInformationDWORD.RetOp := $C3;
- ReadProcessMemory(GetCurrentProcess, @SLGetWindowsInformationDWORD,
- @Old_SLGetWindowsInformationDWORD, SizeOf(OldCode), bw);
- WriteProcessMemory(GetCurrentProcess, @SLGetWindowsInformationDWORD,
- @Stub_SLGetWindowsInformationDWORD, SizeOf(far_jmp), bw);
- end;
- end;
- if V = $0602 then begin
- // Windows 8
- // uses SL Policy internal unexported function
- // load slc.dll and get function
- // (will be used on intercepting undefined values)
- SLC_Handle := LoadLibrary('slc.dll');
- SLGetWindowsInformationDWORD := GetProcAddress(SLC_Handle, 'SLGetWindowsInformationDWORD');
- end;
- if V = $0603 then begin
- // Windows 8.1
- // uses SL Policy internal inline code
- end;
- if V = $0604 then begin
- // Windows 10
- // uses SL Policy internal inline code
- end;
- Sect := IntToStr(FV.Version.w.Major)+'.'+IntToStr(FV.Version.w.Minor)+'.'+
- IntToStr(FV.Release)+'.'+IntToStr(FV.Build);
- if INISectionExists(INI, Sect) then
- if GetModuleAddress('termsrv.dll', GetCurrentProcessId, TermSrvBase, TermSrvSize) then begin
- if INIReadBool(INI, Sect, 'LocalOnlyPatch.x86', False) then begin
- WriteLog('Patch CEnforcementCore::GetInstanceOfTSLicense');
- SignPtr := Pointer(Cardinal(TermSrvBase) + INIReadDWordHex(INI, Sect, 'LocalOnlyOffset.x86', 0));
- I := SListFind(PatchList, INIReadString(INI, Sect, 'LocalOnlyCode.x86', ''));
- if I >= 0 then
- WriteProcessMemory(GetCurrentProcess, SignPtr, @Patch[I][0], Length(Patch[I]), bw);
- end;
- if INIReadBool(INI, Sect, 'SingleUserPatch.x86', False) then begin
- WriteLog('Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled');
- SignPtr := Pointer(Cardinal(TermSrvBase) + INIReadDWordHex(INI, Sect, 'SingleUserOffset.x86', 0));
- I := SListFind(PatchList, INIReadString(INI, Sect, 'SingleUserCode.x86', ''));
- if I >= 0 then
- WriteProcessMemory(GetCurrentProcess, SignPtr, @Patch[I][0], Length(Patch[I]), bw);
- end;
- if INIReadBool(INI, Sect, 'DefPolicyPatch.x86', False) then begin
- WriteLog('Patch CDefPolicy::Query');
- SignPtr := Pointer(Cardinal(TermSrvBase) + INIReadDWordHex(INI, Sect, 'DefPolicyOffset.x86', 0));
- I := SListFind(PatchList, INIReadString(INI, Sect, 'DefPolicyCode.x86', ''));
- if I >= 0 then
- WriteProcessMemory(GetCurrentProcess, SignPtr, @Patch[I][0], Length(Patch[I]), bw);
- end;
- if INIReadBool(INI, Sect, 'SLPolicyInternal.x86', False) then begin
- WriteLog('Hook SLGetWindowsInformationDWORDWrapper');
- SignPtr := Pointer(Cardinal(TermSrvBase) + INIReadDWordHex(INI, Sect, 'SLPolicyOffset.x86', 0));
- MovJump.MovOp := $89; // mov eax, ecx
- MovJump.MovArg := $C8; // __msfastcall compatibility
- MovJump.PushOp := $68;
- MovJump.PushArg := @New_Win8SL;
- MovJump.RetOp := $C3;
- FuncName := INIReadString(INI, Sect, 'SLPolicyFunc.x86', 'New_Win8SL');
- if FuncName = 'New_Win8SL' then
- MovJump.PushArg := @New_Win8SL;
- if FuncName = 'New_Win8SL_CP' then
- MovJump.PushArg := @New_Win8SL_CP;
- WriteProcessMemory(GetCurrentProcess, SignPtr,
- @MovJump, SizeOf(mov_far_jmp), bw);
- end;
- if INIReadBool(INI, Sect, 'SLInitHook.x86', False) then begin
- WriteLog('Hook CSLQuery::Initialize');
- SignPtr := Pointer(Cardinal(TermSrvBase) + INIReadDWordHex(INI, Sect, 'SLInitOffset.x86', 0));
- Jump.PushOp := $68;
- Jump.PushArg := @New_CSLQuery_Initialize;
- Jump.RetOp := $C3;
- FuncName := INIReadString(INI, Sect, 'SLInitFunc.x86', 'New_CSLQuery_Initialize');
- if FuncName = 'New_CSLQuery_Initialize' then
- Jump.PushArg := @New_CSLQuery_Initialize;
- WriteProcessMemory(GetCurrentProcess, SignPtr,
- @Jump, SizeOf(far_jmp), bw);
- end;
- end;
- // unfreeze threads
- WriteLog('Resumimg threads...');
- RunThreads();
- end;
- function TermServiceMain(dwArgc: DWORD; lpszArgv: PWideChar): DWORD; stdcall;
- begin
- // wrap ServiceMain function
- WriteLog('>>> ServiceMain');
- if not IsHooked then
- HookFunctions;
- Result := 0;
- if @TSMain <> nil then
- Result := TSMain(dwArgc, lpszArgv);
- WriteLog('<<< ServiceMain');
- end;
- function TermServiceGlobals(lpGlobalData: Pointer): DWORD; stdcall;
- begin
- // wrap SvchostPushServiceGlobals function
- WriteLog('>>> SvchostPushServiceGlobals');
- if not IsHooked then
- HookFunctions;
- Result := 0;
- if @TSGlobals <> nil then
- Result := TSGlobals(lpGlobalData);
- WriteLog('<<< SvchostPushServiceGlobals');
- end;
- // export section
- exports
- TermServiceMain index 1 name 'ServiceMain',
- TermServiceGlobals index 2 name 'SvchostPushServiceGlobals';
- begin
- // DllMain procedure is not used
- end.
|