rdpwrap/src-x86-binarymaster/rdpwrap-old.dpr
2014-11-21 16:42:39 +03:00

1648 lines
58 KiB
ObjectPascal

{
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;
{$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
bw: DWORD;
IsHooked: Boolean = False;
FCount: Cardinal = 0;
// 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;
const
CDefPolicy_Query_edx_ecx: Array[0..12] of Byte =
($BA,$00,$01,$00,$00,$89,$91,$20,$03,$00,$00,$5E,$90);
CDefPolicy_Query_eax_esi: Array[0..11] of Byte =
($B8,$00,$01,$00,$00,$89,$86,$20,$03,$00,$00,$90);
CDefPolicy_Query_eax_ecx: Array[0..11] of Byte =
($B8,$00,$01,$00,$00,$89,$81,$20,$03,$00,$00,$90);
{
termsrv.dll 6.0.6000.16386
Original
.text:6F335CD8 cmp edx, [ecx+320h]
.text:6F335CDE pop esi
.text:6F335CDF jz loc_6F3426F1
_______________
Changed
.text:6F335CD8 mov edx, 100h
.text:6F335CDD mov [ecx+320h], edx
.text:6F335CE3 pop esi
.text:6F335CE4 nop
CDefPolicy_Query_edx_ecx
termsrv.dll 6.0.6001.18000
Original
.text:6E817FD8 cmp edx, [ecx+320h]
.text:6E817FDE pop esi
.text:6E817FDF jz loc_6E826F16
_______________
Changed
.text:6E817FD8 mov edx, 100h
.text:6E817FDD mov [ecx+320h], edx
.text:6E817FE3 pop esi
.text:6E817FE4 nop
CDefPolicy_Query_edx_ecx
termsrv.dll 6.0.6002.18005
Original
.text:6F5979C0 cmp edx, [ecx+320h]
.text:6F5979C6 pop esi
.text:6F5979C7 jz loc_6F5A6F26
_______________
Changed
.text:6F5979C0 mov edx, 100h
.text:6F5979C5 mov [ecx+320h], edx
.text:6F5979CB pop esi
.text:6F5979CC nop
CDefPolicy_Query_edx_ecx
termsrv.dll 6.0.6002.19214
Original
.text:6F5979B8 cmp edx, [ecx+320h]
.text:6F5979BE pop esi
.text:6F5979BF jz loc_6F5A6F3E
_______________
Changed
.text:6F5979B8 mov edx, 100h
.text:6F5979BD mov [ecx+320h], edx
.text:6F5979C3 pop esi
.text:6F5979C4 nop
CDefPolicy_Query_edx_ecx
termsrv.dll 6.0.6002.23521
Original
.text:6F5979CC cmp edx, [ecx+320h]
.text:6F5979D2 pop esi
.text:6F5979D3 jz loc_6F5A6F2E
_______________
Changed
.text:6F5979CC mov edx, 100h
.text:6F5979D1 mov [ecx+320h], edx
.text:6F5979D7 pop esi
.text:6F5979D8 nop
CDefPolicy_Query_edx_ecx
termsrv.dll 6.1.7600.16385
Original
.text:6F2F96F3 cmp eax, [esi+320h]
.text:6F2F96F9 jz loc_6F30E256
_______________
Changed
.text:6F2F96F3 mov eax, 100h
.text:6F2F96F8 mov [esi+320h], eax
.text:6F2F96FE nop
CDefPolicy_Query_eax_esi
termsrv.dll 6.1.7601.17514
Original
.text:6F2F9D53 cmp eax, [esi+320h]
.text:6F2F9D59 jz loc_6F30B25E
_______________
Changed
.text:6F2F9D53 mov eax, 100h
.text:6F2F9D58 mov [esi+320h], eax
.text:6F2F9D5E nop
CDefPolicy_Query_eax_esi
termsrv.dll 6.1.7601.18540
Original
.text:6F2F9D9F cmp eax, [esi+320h]
.text:6F2F9DA5 jz loc_6F30B2AE
_______________
Changed
.text:6F2F9D9F mov eax, 100h
.text:6F2F9DA4 mov [esi+320h], eax
.text:6F2F9DAA nop
CDefPolicy_Query_eax_esi
termsrv.dll 6.1.7601.22750
Original
.text:6F2F9E21 cmp eax, [esi+320h]
.text:6F2F9E27 jz loc_6F30B6CE
_______________
Changed
.text:6F2F9E21 mov eax, 100h
.text:6F2F9E26 mov [esi+320h], eax
.text:6F2F9E2C nop
CDefPolicy_Query_eax_esi
termsrv.dll 6.1.7601.18637
Original
.text:6F2F9DBB cmp eax, [esi+320h]
.text:6F2F9DC1 jz loc_6F30B2A6
_______________
Changed
.text:6F2F9DBB mov eax, 100h
.text:6F2F9DC0 mov [esi+320h], eax
.text:6F2F9DC6 nop
CDefPolicy_Query_eax_esi
termsrv.dll 6.1.7601.22843
Original
.text:6F2F9E25 cmp eax, [esi+320h]
.text:6F2F9E2B jz loc_6F30B6D6
_______________
Changed
.text:6F2F9E25 mov eax, 100h
.text:6F2F9E2A mov [esi+320h], eax
.text:6F2F9E30 nop
CDefPolicy_Query_eax_esi
termsrv.dll 6.2.8102.0
Original
.text:1000E47C cmp eax, [esi+320h]
.text:1000E482 jz loc_1002D775
_______________
Changed
.text:1000E47C mov eax, 100h
.text:1000E481 mov [esi+320h], eax
.text:1000E487 nop
CDefPolicy_Query_eax_esi
termsrv.dll 6.2.8250.0
Original
.text:10013520 cmp eax, [esi+320h]
.text:10013526 jz loc_1002DB85
_______________
Changed
.text:10013520 mov eax, 100h
.text:10013525 mov [esi+320h], eax
.text:1001352B nop
CDefPolicy_Query_eax_esi
termsrv.dll 6.2.8400.0
Original
.text:10013E48 cmp eax, [esi+320h]
.text:10013E4E jz loc_1002E079
_______________
Changed
.text:10013E48 mov eax, 100h
.text:10013E4D mov [esi+320h], eax
.text:10013E53 nop
CDefPolicy_Query_eax_esi
termsrv.dll 6.2.9200.16384
Original
.text:10013F08 cmp eax, [esi+320h]
.text:10013F0E jz loc_1002E161
_______________
Changed
.text:10013F08 mov eax, 100h
.text:10013F0D mov [esi+320h], eax
.text:10013F13 nop
CDefPolicy_Query_eax_esi
termsrv.dll 6.2.9200.17048
Original
.text:1001F408 cmp eax, [esi+320h]
.text:1001F40E jz loc_1002E201
_______________
Changed
.text:1001F408 mov eax, 100h
.text:1001F40D mov [esi+320h], eax
.text:1001F413 nop
CDefPolicy_Query_eax_esi
termsrv.dll 6.2.9200.21166
Original
.text:10013F30 cmp eax, [esi+320h]
.text:10013F36 jz loc_1002E189
_______________
Changed
.text:10013F30 mov eax, 100h
.text:10013F35 mov [esi+320h], eax
.text:10013F3B nop
CDefPolicy_Query_eax_esi
termsrv.dll 6.3.9431.0
Original
.text:1002EA25 cmp eax, [ecx+320h]
.text:1002EA2B jz loc_100348C1
_______________
Changed
.text:1002EA25 mov eax, 100h
.text:1002EA2A mov [ecx+320h], eax
.text:1002EA30 nop
CDefPolicy_Query_eax_ecx
termsrv.dll 6.3.9600.16384
Original
.text:10016115 cmp eax, [ecx+320h]
.text:1001611B jz loc_10034DE1
_______________
Changed
.text:10016115 mov eax, 100h
.text:1001611A mov [ecx+320h], eax
.text:10016120 nop
CDefPolicy_Query_eax_ecx
termsrv.dll 6.3.9600.17095
Original
.text:10037529 cmp eax, [ecx+320h]
.text:1003752F jz loc_10043662
_______________
Changed
.text:10037529 mov eax, 100h
.text:1003752E mov [ecx+320h], eax
.text:10037534 nop
CDefPolicy_Query_eax_ecx
termsrv.dll 6.4.9841.0
Original
.text:1003B989 cmp eax, [ecx+320h]
.text:1003B98F jz loc_1005E809
_______________
Changed
.text:1003B989 mov eax, 100h
.text:1003B98E mov [ecx+320h], eax
.text:1003B994 nop
CDefPolicy_Query_eax_ecx
termsrv.dll 6.4.9860.0
Original
.text:1003BEC9 cmp eax, [ecx+320h]
.text:1003BECF jz loc_1005EE1A
_______________
Changed
.text:1003BEC9 mov eax, 100h
.text:1003BECE mov [ecx+320h], eax
.text:1003BED4 nop
CDefPolicy_Query_eax_ecx
}
var
Stub_SLGetWindowsInformationDWORD: far_jmp;
Old_SLGetWindowsInformationDWORD: OldCode;
// Main code
procedure WriteLog(S: AnsiString);
const
LogFile = '\rdpwrap.txt';
var
F: TextFile;
begin
if not FileExists(LogFile) then
Exit;
AssignFile(F, LogFile);
Append(F);
Write(F, S+#13#10);
CloseFile(F);
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: TFileName; 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: TFileName; 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;
// Allow Remote Connections
if ValueName = 'TerminalServices-RemoteConnectionManager-AllowRemoteConnections' then begin
Value := 1;
Exit;
end;
// Allow Multiple Sessions
if ValueName = 'TerminalServices-RemoteConnectionManager-AllowMultipleSessions' then begin
Value := 1;
Exit;
end;
// Allow Multiple Sessions (Application Server Mode)
if ValueName = 'TerminalServices-RemoteConnectionManager-AllowAppServerMode' then begin
Value := 1;
Exit;
end;
// Allow Multiple Monitors
if ValueName = 'TerminalServices-RemoteConnectionManager-AllowMultimon' then begin
Value := 1;
Exit;
end;
// Max User Sessions (0 = unlimited)
if ValueName = 'TerminalServices-RemoteConnectionManager-MaxUserSessions' then begin
Value := 0;
Exit;
end;
// Max Debug Sessions (Win 8, 0 = unlimited)
if ValueName = 'TerminalServices-RemoteConnectionManager-ce0ad219-4670-4988-98fb-89b14c2f072b-MaxSessions' then begin
Value := 0;
Exit;
end;
// Max Sessions
// 0 - logon not possible even from console
// 1 - only one active user (console or remote)
// 2 - allow concurrent sessions
if ValueName = 'TerminalServices-RemoteConnectionManager-45344fe7-00e6-4ac6-9f01-d01fd4ffadfb-MaxSessions' then begin
Value := 2;
Exit;
end;
// Allow Advanced Compression with RDP 7 Protocol
if ValueName = 'TerminalServices-RDP-7-Advanced-Compression-Allowed' then begin
Value := 1;
Exit;
end;
// IsTerminalTypeLocalOnly = 0
if ValueName = 'TerminalServices-RemoteConnectionManager-45344fe7-00e6-4ac6-9f01-d01fd4ffadfb-LocalOnly' then begin
Value := 0;
Exit;
end;
// Max Sessions (hard limit)
if ValueName = 'TerminalServices-RemoteConnectionManager-8dc86f1d-9969-4379-91c1-06fe1dc60575-MaxSessions' then begin
Value := 1000;
Exit;
end;
// Allow Easy Print
if ValueName = 'TerminalServices-DeviceRedirection-Licenses-TSEasyPrintAllowed' then begin
Value := 1;
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('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('Result: ' + IntToStr(pdwValue^))
else
WriteLog('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('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('Result: ' + IntToStr(pdwValue^))
else
WriteLog('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
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');
if (FV.Release = 9431) and (FV.Build = 0) then begin
bFUSEnabled := Pointer(Cardinal(TermSrvBase) + $A22A8);
lMaxUserSessions := Pointer(Cardinal(TermSrvBase) + $A22AC);
bAppServerAllowed := Pointer(Cardinal(TermSrvBase) + $A22B0);
bInitialized := Pointer(Cardinal(TermSrvBase) + $A22B4);
bMultimonAllowed := Pointer(Cardinal(TermSrvBase) + $A22B8);
bServerSku := Pointer(Cardinal(TermSrvBase) + $A22BC);
ulMaxDebugSessions := Pointer(Cardinal(TermSrvBase) + $A22C0);
bRemoteConnAllowed := Pointer(Cardinal(TermSrvBase) + $A22C4);
end;
if (FV.Release = 9600) and (FV.Build = 16384) then begin
bFUSEnabled := Pointer(Cardinal(TermSrvBase) + $C02A8);
lMaxUserSessions := Pointer(Cardinal(TermSrvBase) + $C02AC);
bAppServerAllowed := Pointer(Cardinal(TermSrvBase) + $C02B0);
bInitialized := Pointer(Cardinal(TermSrvBase) + $C02B4);
bMultimonAllowed := Pointer(Cardinal(TermSrvBase) + $C02B8);
bServerSku := Pointer(Cardinal(TermSrvBase) + $C02BC);
ulMaxDebugSessions := Pointer(Cardinal(TermSrvBase) + $C02C0);
bRemoteConnAllowed := Pointer(Cardinal(TermSrvBase) + $C02C4);
end;
if (FV.Release = 9600) and (FV.Build = 17095) then begin
bFUSEnabled := Pointer(Cardinal(TermSrvBase) + $C12A8);
lMaxUserSessions := Pointer(Cardinal(TermSrvBase) + $C12AC);
bAppServerAllowed := Pointer(Cardinal(TermSrvBase) + $C12B0);
bInitialized := Pointer(Cardinal(TermSrvBase) + $C12B4);
bMultimonAllowed := Pointer(Cardinal(TermSrvBase) + $C12B8);
bServerSku := Pointer(Cardinal(TermSrvBase) + $C12BC);
ulMaxDebugSessions := Pointer(Cardinal(TermSrvBase) + $C12C0);
bRemoteConnAllowed := Pointer(Cardinal(TermSrvBase) + $C12C4);
end;
if (FV.Release = 9841) and (FV.Build = 0) then begin
bFUSEnabled := Pointer(Cardinal(TermSrvBase) + $BF9F0);
lMaxUserSessions := Pointer(Cardinal(TermSrvBase) + $BF9F4);
bAppServerAllowed := Pointer(Cardinal(TermSrvBase) + $BF9F8);
bInitialized := Pointer(Cardinal(TermSrvBase) + $BF9FC);
bMultimonAllowed := Pointer(Cardinal(TermSrvBase) + $BFA00);
bServerSku := Pointer(Cardinal(TermSrvBase) + $BFA04);
ulMaxDebugSessions := Pointer(Cardinal(TermSrvBase) + $BFA08);
bRemoteConnAllowed := Pointer(Cardinal(TermSrvBase) + $BFA0C);
end;
if (FV.Release = 9860) and (FV.Build = 0) then begin
bFUSEnabled := Pointer(Cardinal(TermSrvBase) + $BF7E0);
lMaxUserSessions := Pointer(Cardinal(TermSrvBase) + $BF7E4);
bAppServerAllowed := Pointer(Cardinal(TermSrvBase) + $BF7E8);
bInitialized := Pointer(Cardinal(TermSrvBase) + $BF7EC);
bMultimonAllowed := Pointer(Cardinal(TermSrvBase) + $BF7F0);
bServerSku := Pointer(Cardinal(TermSrvBase) + $BF7F4);
ulMaxDebugSessions := Pointer(Cardinal(TermSrvBase) + $BF7F8);
bRemoteConnAllowed := Pointer(Cardinal(TermSrvBase) + $BF7FC);
end;
if bServerSku <> nil then begin
WriteLog('[0x'+IntToHex(DWORD(bServerSku), 1)+'] bServerSku = 1');
bServerSku^ := 1;
end;
if bRemoteConnAllowed <> nil then begin
WriteLog('[0x'+IntToHex(DWORD(bRemoteConnAllowed), 1)+'] bRemoteConnAllowed = 1');
bRemoteConnAllowed^ := 1;
end;
if bFUSEnabled <> nil then begin
WriteLog('[0x'+IntToHex(DWORD(bFUSEnabled), 1)+'] bFUSEnabled = 1');
bFUSEnabled^ := 1;
end;
if bAppServerAllowed <> nil then begin
WriteLog('[0x'+IntToHex(DWORD(bAppServerAllowed), 1)+'] bAppServerAllowed = 1');
bAppServerAllowed^ := 1;
end;
if bMultimonAllowed <> nil then begin
WriteLog('[0x'+IntToHex(DWORD(bMultimonAllowed), 1)+'] bMultimonAllowed = 1');
bMultimonAllowed^ := 1;
end;
if lMaxUserSessions <> nil then begin
WriteLog('[0x'+IntToHex(DWORD(lMaxUserSessions), 1)+'] lMaxUserSessions = 0');
lMaxUserSessions^ := 0;
end;
if ulMaxDebugSessions <> nil then begin
WriteLog('[0x'+IntToHex(DWORD(ulMaxDebugSessions), 1)+'] ulMaxDebugSessions = 0');
ulMaxDebugSessions^ := 0;
end;
if bInitialized <> nil then begin
WriteLog('[0x'+IntToHex(DWORD(bInitialized), 1)+'] bInitialized = 1');
bInitialized^ := 1;
end;
Result := S_OK;
end;
procedure HookFunctions;
var
V: DWORD;
TS_Handle, SLC_Handle: THandle;
TermSrvSize: DWORD;
SignPtr: Pointer;
Results: IntArray;
Jump: far_jmp;
MovJump: mov_far_jmp;
nop: DWORD;
b: Byte;
begin
{ hook function ^^
(called once) }
IsHooked := True;
nop := $90909090;
TSMain := nil;
TSGlobals := nil;
SLGetWindowsInformationDWORD := nil;
WriteLog('init');
// 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;
WriteLog('Base addr: 0x'+IntToHex(TS_Handle, 8));
TSMain := GetProcAddress(TS_Handle, 'ServiceMain');
WriteLog('SvcMain: termsrv.dll+0x'+IntToHex(Cardinal(@TSMain) - TS_Handle, 1));
TSGlobals := GetProcAddress(TS_Handle, 'SvchostPushServiceGlobals');
WriteLog('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));
WriteLog('Release: '+IntToStr(FV.Release));
WriteLog('Build: '+IntToStr(FV.Build));
// temporarily freeze threads
WriteLog('freeze');
StopThreads();
if (V = $0600) 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;
if GetModuleAddress('termsrv.dll', GetCurrentProcessId, TermSrvBase, TermSrvSize) then begin
// Patch functions:
// CSessionArbitrationHelper::IsSingleSessionPerUserEnabled
// CDefPolicy::Query
if (FV.Release = 6000) and (FV.Build = 16386) then begin
WriteLog('Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled');
{ Imagebase: 6F320000
.text:6F3360B9 lea eax, [ebp+VersionInformation]
.text:6F3360BF inc ebx <- nop
.text:6F3360C0 push eax ; lpVersionInformation
.text:6F3360C1 mov [ebp+VersionInformation.dwOSVersionInfoSize], 11Ch
.text:6F3360CB mov [esi], ebx
.text:6F3360CD call ds:__imp__GetVersionExW@4 ; GetVersionExW(x)
}
SignPtr := Pointer(Cardinal(TermSrvBase) + $160BF);
WriteProcessMemory(GetCurrentProcess, SignPtr, @nop, 1, bw);
WriteLog('Patch CDefPolicy::Query');
SignPtr := Pointer(Cardinal(TermSrvBase) + $15CD8);
WriteProcessMemory(GetCurrentProcess, SignPtr,
@CDefPolicy_Query_edx_ecx[0],
SizeOf(CDefPolicy_Query_edx_ecx), bw);
end;
if (FV.Release = 6001) and (FV.Build = 18000) then begin
WriteLog('Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled');
{ Imagebase: 6E800000
.text:6E8185DE lea eax, [ebp+VersionInformation]
.text:6E8185E4 inc ebx <- nop
.text:6E8185E5 push eax ; lpVersionInformation
.text:6E8185E6 mov [ebp+VersionInformation.dwOSVersionInfoSize], 11Ch
.text:6E8185F0 mov [esi], ebx
.text:6E8185F2 call ds:__imp__GetVersionExW@4 ; GetVersionExW(x)
}
SignPtr := Pointer(Cardinal(TermSrvBase) + $185E4);
WriteProcessMemory(GetCurrentProcess, SignPtr, @nop, 1, bw);
WriteLog('Patch CDefPolicy::Query');
SignPtr := Pointer(Cardinal(TermSrvBase) + $17FD8);
WriteProcessMemory(GetCurrentProcess, SignPtr,
@CDefPolicy_Query_edx_ecx[0],
SizeOf(CDefPolicy_Query_edx_ecx), bw);
end;
if (FV.Release = 6002) and (FV.Build = 18005) then begin
WriteLog('Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled');
{ Imagebase: 6F580000
.text:6F597FA2 lea eax, [ebp+VersionInformation]
.text:6F597FA8 inc ebx <- nop
.text:6F597FA9 push eax ; lpVersionInformation
.text:6F597FAA mov [ebp+VersionInformation.dwOSVersionInfoSize], 11Ch
.text:6F597FB4 mov [esi], ebx
.text:6F597FB6 call ds:__imp__GetVersionExW@4 ; GetVersionExW(x)
}
SignPtr := Pointer(Cardinal(TermSrvBase) + $17FA8);
WriteProcessMemory(GetCurrentProcess, SignPtr, @nop, 1, bw);
WriteLog('Patch CDefPolicy::Query');
SignPtr := Pointer(Cardinal(TermSrvBase) + $179C0);
WriteProcessMemory(GetCurrentProcess, SignPtr,
@CDefPolicy_Query_edx_ecx[0],
SizeOf(CDefPolicy_Query_edx_ecx), bw);
end;
if (FV.Release = 6002) and (FV.Build = 19214) then begin
WriteLog('Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled');
{ Imagebase: 6F580000
.text:6F597FBE lea eax, [ebp+VersionInformation]
.text:6F597FC4 inc ebx <- nop
.text:6F597FC5 push eax ; lpVersionInformation
.text:6F597FC6 mov [ebp+VersionInformation.dwOSVersionInfoSize], 11Ch
.text:6F597FD0 mov [esi], ebx
.text:6F597FD2 call ds:__imp__GetVersionExW@4 ; GetVersionExW(x)
}
SignPtr := Pointer(Cardinal(TermSrvBase) + $17FC4);
WriteProcessMemory(GetCurrentProcess, SignPtr, @nop, 1, bw);
WriteLog('Patch CDefPolicy::Query');
SignPtr := Pointer(Cardinal(TermSrvBase) + $179B8);
WriteProcessMemory(GetCurrentProcess, SignPtr,
@CDefPolicy_Query_edx_ecx[0],
SizeOf(CDefPolicy_Query_edx_ecx), bw);
end;
if (FV.Release = 6002) and (FV.Build = 23521) then begin
WriteLog('Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled');
{ Imagebase: 6F580000
.text:6F597FAE lea eax, [ebp+VersionInformation]
.text:6F597FB4 inc ebx <- nop
.text:6F597FB5 push eax ; lpVersionInformation
.text:6F597FB6 mov [ebp+VersionInformation.dwOSVersionInfoSize], 11Ch
.text:6F597FC0 mov [esi], ebx
.text:6F597FC2 call ds:__imp__GetVersionExW@4 ; GetVersionExW(x)
}
SignPtr := Pointer(Cardinal(TermSrvBase) + $17FB4);
WriteProcessMemory(GetCurrentProcess, SignPtr, @nop, 1, bw);
WriteLog('Patch CDefPolicy::Query');
SignPtr := Pointer(Cardinal(TermSrvBase) + $179CC);
WriteProcessMemory(GetCurrentProcess, SignPtr,
@CDefPolicy_Query_edx_ecx[0],
SizeOf(CDefPolicy_Query_edx_ecx), bw);
end;
end;
end;
if (V = $0601) 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;
if GetModuleAddress('termsrv.dll', GetCurrentProcessId, TermSrvBase, TermSrvSize) then begin
// Patch functions:
// CSessionArbitrationHelper::IsSingleSessionPerUserEnabled
// CDefPolicy::Query
if (FV.Release = 7600) and (FV.Build = 16385) then begin
WriteLog('Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled');
{ Imagebase: 6F2E0000
.text:6F2F9E1F lea eax, [ebp+VersionInformation]
.text:6F2F9E25 inc ebx <- nop
.text:6F2F9E26 push eax ; lpVersionInformation
.text:6F2F9E27 mov [ebp+VersionInformation.dwOSVersionInfoSize], 11Ch
.text:6F2F9E31 mov [esi], ebx
.text:6F2F9E33 call ds:__imp__GetVersionExW@4 ; GetVersionExW(x)
}
SignPtr := Pointer(Cardinal(TermSrvBase) + $19E25);
WriteProcessMemory(GetCurrentProcess, SignPtr, @nop, 1, bw);
WriteLog('Patch CDefPolicy::Query');
SignPtr := Pointer(Cardinal(TermSrvBase) + $196F3);
WriteProcessMemory(GetCurrentProcess, SignPtr,
@CDefPolicy_Query_eax_esi[0],
SizeOf(CDefPolicy_Query_eax_esi), bw);
end;
if (FV.Release = 7601) and (FV.Build = 17514) then begin
WriteLog('Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled');
{ Imagebase: 6F2E0000
.text:6F2FA497 lea eax, [ebp+VersionInformation]
.text:6F2FA49D inc ebx <- nop
.text:6F2FA49E push eax ; lpVersionInformation
.text:6F2FA49F mov [ebp+VersionInformation.dwOSVersionInfoSize], 11Ch
.text:6F2FA4A9 mov [esi], ebx
.text:6F2FA4AB call ds:__imp__GetVersionExW@4 ; GetVersionExW(x)
}
SignPtr := Pointer(Cardinal(TermSrvBase) + $1A49D);
WriteProcessMemory(GetCurrentProcess, SignPtr, @nop, 1, bw);
WriteLog('Patch CDefPolicy::Query');
SignPtr := Pointer(Cardinal(TermSrvBase) + $19D53);
WriteProcessMemory(GetCurrentProcess, SignPtr,
@CDefPolicy_Query_eax_esi[0],
SizeOf(CDefPolicy_Query_eax_esi), bw);
end;
if (FV.Release = 7601) and (FV.Build = 18540) then begin
WriteLog('Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled');
{ Imagebase: 6F2E0000
.text:6F2FA4DF lea eax, [ebp+VersionInformation]
.text:6F2FA4E5 inc ebx <- nop
.text:6F2FA4E6 push eax ; lpVersionInformation
.text:6F2FA4E7 mov [ebp+VersionInformation.dwOSVersionInfoSize], 11Ch
.text:6F2FA4F1 mov [esi], ebx
.text:6F2FA4F3 call ds:__imp__GetVersionExW@4 ; GetVersionExW(x)
}
SignPtr := Pointer(Cardinal(TermSrvBase) + $1A4E5);
WriteProcessMemory(GetCurrentProcess, SignPtr, @nop, 1, bw);
WriteLog('Patch CDefPolicy::Query');
SignPtr := Pointer(Cardinal(TermSrvBase) + $19D9F);
WriteProcessMemory(GetCurrentProcess, SignPtr,
@CDefPolicy_Query_eax_esi[0],
SizeOf(CDefPolicy_Query_eax_esi), bw);
end;
if (FV.Release = 7601) and (FV.Build = 22750) then begin
WriteLog('Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled');
{ Imagebase: 6F2E0000
.text:6F2FA64F lea eax, [ebp+VersionInformation]
.text:6F2FA655 inc ebx <- nop
.text:6F2FA656 push eax ; lpVersionInformation
.text:6F2FA657 mov [ebp+VersionInformation.dwOSVersionInfoSize], 11Ch
.text:6F2FA661 mov [esi], ebx
.text:6F2FA663 call ds:__imp__GetVersionExW@4 ; GetVersionExW(x)
}
SignPtr := Pointer(Cardinal(TermSrvBase) + $1A655);
WriteProcessMemory(GetCurrentProcess, SignPtr, @nop, 1, bw);
WriteLog('Patch CDefPolicy::Query');
SignPtr := Pointer(Cardinal(TermSrvBase) + $19E21);
WriteProcessMemory(GetCurrentProcess, SignPtr,
@CDefPolicy_Query_eax_esi[0],
SizeOf(CDefPolicy_Query_eax_esi), bw);
end;
if (FV.Release = 7601) and (FV.Build = 18637) then begin
WriteLog('Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled');
{ Imagebase: 6F2E0000
.text:6F2FA4D7 lea eax, [ebp+VersionInformation]
.text:6F2FA4DD inc ebx <- nop
.text:6F2FA4DE push eax ; lpVersionInformation
.text:6F2FA4DF mov [ebp+VersionInformation.dwOSVersionInfoSize], 11Ch
.text:6F2FA4E9 mov [esi], ebx
.text:6F2FA4EB call ds:__imp__GetVersionExW@4 ; GetVersionExW(x)
}
SignPtr := Pointer(Cardinal(TermSrvBase) + $1A4DD);
WriteProcessMemory(GetCurrentProcess, SignPtr, @nop, 1, bw);
WriteLog('Patch CDefPolicy::Query');
SignPtr := Pointer(Cardinal(TermSrvBase) + $19DBB);
WriteProcessMemory(GetCurrentProcess, SignPtr,
@CDefPolicy_Query_eax_esi[0],
SizeOf(CDefPolicy_Query_eax_esi), bw);
end;
if (FV.Release = 7601) and (FV.Build = 22843) then begin
WriteLog('Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled');
{ Imagebase: 6F2E0000
.text:6F2FA64F lea eax, [ebp+VersionInformation]
.text:6F2FA655 inc ebx <- nop
.text:6F2FA656 push eax ; lpVersionInformation
.text:6F2FA657 mov [ebp+VersionInformation.dwOSVersionInfoSize], 11Ch
.text:6F2FA661 mov [esi], ebx
.text:6F2FA663 call ds:__imp__GetVersionExW@4 ; GetVersionExW(x)
}
SignPtr := Pointer(Cardinal(TermSrvBase) + $1A655);
WriteProcessMemory(GetCurrentProcess, SignPtr, @nop, 1, bw);
WriteLog('Patch CDefPolicy::Query');
SignPtr := Pointer(Cardinal(TermSrvBase) + $19E25);
WriteProcessMemory(GetCurrentProcess, SignPtr,
@CDefPolicy_Query_eax_esi[0],
SizeOf(CDefPolicy_Query_eax_esi), bw);
end;
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');
if GetModuleAddress('termsrv.dll', GetCurrentProcessId, TermSrvBase, TermSrvSize) then begin
// Patch functions:
// CSessionArbitrationHelper::IsSingleSessionPerUserEnabled
// CDefPolicy::Query
// Hook function:
// SLGetWindowsInformationDWORDWrapper
if (FV.Release = 8102) and (FV.Build = 0) then begin
WriteLog('Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled');
{
.text:1000F7E5 lea eax, [esp+150h+VersionInformation]
.text:1000F7E9 inc esi <- nop
.text:1000F7EA push eax ; lpVersionInformation
.text:1000F7EB mov [esp+154h+VersionInformation.dwOSVersionInfoSize], 11Ch
.text:1000F7F3 mov [edi], esi
.text:1000F7F5 call ds:__imp__GetVersionExW@4 ; GetVersionExW(x)
}
SignPtr := Pointer(Cardinal(TermSrvBase) + $F7E9);
WriteProcessMemory(GetCurrentProcess, SignPtr, @nop, 1, bw);
WriteLog('Patch CDefPolicy::Query');
SignPtr := Pointer(Cardinal(TermSrvBase) + $E47C);
WriteProcessMemory(GetCurrentProcess, SignPtr,
@CDefPolicy_Query_eax_esi[0],
SizeOf(CDefPolicy_Query_eax_esi), bw);
WriteLog('Hook SLGetWindowsInformationDWORDWrapper');
SignPtr := Pointer(Cardinal(TermSrvBase) + $1B909);
MovJump.MovOp := $89; // mov eax, ecx
MovJump.MovArg := $C8; // __msfastcall compatibility
MovJump.PushOp := $68;
MovJump.PushArg := @New_Win8SL;
MovJump.RetOp := $C3;
WriteProcessMemory(GetCurrentProcess, SignPtr,
@MovJump, SizeOf(mov_far_jmp), bw);
end;
if (FV.Release = 8250) and (FV.Build = 0) then begin
WriteLog('Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled');
{
.text:100159C5 lea eax, [esp+150h+VersionInformation]
.text:100159C9 inc esi <- nop
.text:100159CA push eax ; lpVersionInformation
.text:100159CB mov [esp+154h+VersionInformation.dwOSVersionInfoSize], 11Ch
.text:100159D3 mov [edi], esi
.text:100159D5 call ds:__imp__GetVersionExW@4 ; GetVersionExW(x)
}
SignPtr := Pointer(Cardinal(TermSrvBase) + $159C9);
WriteProcessMemory(GetCurrentProcess, SignPtr, @nop, 1, bw);
WriteLog('Patch CDefPolicy::Query');
SignPtr := Pointer(Cardinal(TermSrvBase) + $13520);
WriteProcessMemory(GetCurrentProcess, SignPtr,
@CDefPolicy_Query_eax_esi[0],
SizeOf(CDefPolicy_Query_eax_esi), bw);
WriteLog('Hook SLGetWindowsInformationDWORDWrapper');
SignPtr := Pointer(Cardinal(TermSrvBase) + $1A0A9);
MovJump.MovOp := $89; // mov eax, ecx
MovJump.MovArg := $C8; // __msfastcall compatibility
MovJump.PushOp := $68;
MovJump.PushArg := @New_Win8SL_CP;
MovJump.RetOp := $C3;
WriteProcessMemory(GetCurrentProcess, SignPtr,
@MovJump, SizeOf(mov_far_jmp), bw);
end;
if (FV.Release = 8400) and (FV.Build = 0) then begin
WriteLog('Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled');
{
.text:1001547E lea eax, [esp+150h+VersionInformation]
.text:10015482 inc esi <- nop
.text:10015483 push eax ; lpVersionInformation
.text:10015484 mov [esp+154h+VersionInformation.dwOSVersionInfoSize], 11Ch
.text:1001548C mov [edi], esi
.text:1001548E call ds:__imp__GetVersionExW@4 ; GetVersionExW(x)
}
SignPtr := Pointer(Cardinal(TermSrvBase) + $15482);
WriteProcessMemory(GetCurrentProcess, SignPtr, @nop, 1, bw);
WriteLog('Patch CDefPolicy::Query');
SignPtr := Pointer(Cardinal(TermSrvBase) + $13E48);
WriteProcessMemory(GetCurrentProcess, SignPtr,
@CDefPolicy_Query_eax_esi[0],
SizeOf(CDefPolicy_Query_eax_esi), bw);
WriteLog('Hook SLGetWindowsInformationDWORDWrapper');
SignPtr := Pointer(Cardinal(TermSrvBase) + $19629);
MovJump.MovOp := $89; // mov eax, ecx
MovJump.MovArg := $C8; // __msfastcall compatibility
MovJump.PushOp := $68;
MovJump.PushArg := @New_Win8SL;
MovJump.RetOp := $C3;
WriteProcessMemory(GetCurrentProcess, SignPtr,
@MovJump, SizeOf(mov_far_jmp), bw);
end;
if (FV.Release = 9200) and (FV.Build = 16384) then begin
WriteLog('Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled');
{
.text:1001554E lea eax, [esp+150h+VersionInformation]
.text:10015552 inc esi <- nop
.text:10015553 push eax ; lpVersionInformation
.text:10015554 mov [esp+154h+VersionInformation.dwOSVersionInfoSize], 11Ch
.text:1001555C mov [edi], esi
.text:1001555E call ds:__imp__GetVersionExW@4 ; GetVersionExW(x)
}
SignPtr := Pointer(Cardinal(TermSrvBase) + $15552);
WriteProcessMemory(GetCurrentProcess, SignPtr, @nop, 1, bw);
WriteLog('Patch CDefPolicy::Query');
SignPtr := Pointer(Cardinal(TermSrvBase) + $13F08);
WriteProcessMemory(GetCurrentProcess, SignPtr,
@CDefPolicy_Query_eax_esi[0],
SizeOf(CDefPolicy_Query_eax_esi), bw);
WriteLog('Hook SLGetWindowsInformationDWORDWrapper');
SignPtr := Pointer(Cardinal(TermSrvBase) + $19559);
MovJump.MovOp := $89; // mov eax, ecx
MovJump.MovArg := $C8; // __msfastcall compatibility
MovJump.PushOp := $68;
MovJump.PushArg := @New_Win8SL;
MovJump.RetOp := $C3;
WriteProcessMemory(GetCurrentProcess, SignPtr,
@MovJump, SizeOf(mov_far_jmp), bw);
end;
if (FV.Release = 9200) and (FV.Build = 17048) then begin
WriteLog('Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled');
{
.text:1002058E lea eax, [esp+150h+VersionInformation]
.text:10020592 inc esi <- nop
.text:10020593 push eax ; lpVersionInformation
.text:10020594 mov [esp+154h+VersionInformation.dwOSVersionInfoSize], 11Ch
.text:1002059C mov [edi], esi
.text:1002059E call ds:__imp__GetVersionExW@4 ; GetVersionExW(x)
}
SignPtr := Pointer(Cardinal(TermSrvBase) + $20592);
WriteProcessMemory(GetCurrentProcess, SignPtr, @nop, 1, bw);
WriteLog('Patch CDefPolicy::Query');
SignPtr := Pointer(Cardinal(TermSrvBase) + $1F408);
WriteProcessMemory(GetCurrentProcess, SignPtr,
@CDefPolicy_Query_eax_esi[0],
SizeOf(CDefPolicy_Query_eax_esi), bw);
WriteLog('Hook SLGetWindowsInformationDWORDWrapper');
SignPtr := Pointer(Cardinal(TermSrvBase) + $17059);
MovJump.MovOp := $89; // mov eax, ecx
MovJump.MovArg := $C8; // __msfastcall compatibility
MovJump.PushOp := $68;
MovJump.PushArg := @New_Win8SL;
MovJump.RetOp := $C3;
WriteProcessMemory(GetCurrentProcess, SignPtr,
@MovJump, SizeOf(mov_far_jmp), bw);
end;
if (FV.Release = 9200) and (FV.Build = 21166) then begin
WriteLog('Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled');
{
.text:10015576 lea eax, [esp+150h+VersionInformation]
.text:1001557A inc esi <- nop
.text:1001557B push eax ; lpVersionInformation
.text:1001557C mov [esp+154h+VersionInformation.dwOSVersionInfoSize], 11Ch
.text:10015584 mov [edi], esi
.text:10015586 call ds:__imp__GetVersionExW@4 ; GetVersionExW(x)
}
SignPtr := Pointer(Cardinal(TermSrvBase) + $1557A);
WriteProcessMemory(GetCurrentProcess, SignPtr, @nop, 1, bw);
WriteLog('Patch CDefPolicy::Query');
SignPtr := Pointer(Cardinal(TermSrvBase) + $13F30);
WriteProcessMemory(GetCurrentProcess, SignPtr,
@CDefPolicy_Query_eax_esi[0],
SizeOf(CDefPolicy_Query_eax_esi), bw);
WriteLog('Hook SLGetWindowsInformationDWORDWrapper');
SignPtr := Pointer(Cardinal(TermSrvBase) + $19581);
MovJump.MovOp := $89; // mov eax, ecx
MovJump.MovArg := $C8; // __msfastcall compatibility
MovJump.PushOp := $68;
MovJump.PushArg := @New_Win8SL;
MovJump.RetOp := $C3;
WriteProcessMemory(GetCurrentProcess, SignPtr,
@MovJump, SizeOf(mov_far_jmp), bw);
end;
end;
end;
if V = $0603 then begin
// Windows 8.1
// uses SL Policy internal inline code
if GetModuleAddress('termsrv.dll', GetCurrentProcessId, TermSrvBase, TermSrvSize) then begin
// Patch functions:
// CEnforcementCore::GetInstanceOfTSLicense
// CSessionArbitrationHelper::IsSingleSessionPerUserEnabled
// CDefPolicy::Query
// Hook function:
// CSLQuery::Initialize
if (FV.Release = 9431) and (FV.Build = 0) then begin
WriteLog('Patch CEnforcementCore::GetInstanceOfTSLicense');
{
.text:1008A604 call ?IsLicenseTypeLocalOnly@CSLQuery@@SGJAAU_GUID@@PAH@Z ; CSLQuery::IsLicenseTypeLocalOnly(_GUID &,int *)
.text:1008A609 test eax, eax
.text:1008A60B js short loc_1008A628
.text:1008A60D cmp [ebp+var_8], 0
.text:1008A611 jz short loc_1008A628 <- jmp
}
SignPtr := Pointer(Cardinal(TermSrvBase) + $8A611);
b := $EB;
WriteProcessMemory(GetCurrentProcess, SignPtr, @b, 1, bw);
WriteLog('Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled');
{
.text:100306A4 lea eax, [esp+150h+VersionInformation]
.text:100306A8 inc ebx <- nop
.text:100306A9 mov [edi], ebx
.text:100306AB push eax ; lpVersionInformation
.text:100306AC call ds:__imp__GetVersionExW@4 ; GetVersionExW(x)
}
SignPtr := Pointer(Cardinal(TermSrvBase) + $306A8);
WriteProcessMemory(GetCurrentProcess, SignPtr, @nop, 1, bw);
WriteLog('Patch CDefPolicy::Query');
SignPtr := Pointer(Cardinal(TermSrvBase) + $2EA25);
WriteProcessMemory(GetCurrentProcess, SignPtr,
@CDefPolicy_Query_eax_ecx[0],
SizeOf(CDefPolicy_Query_eax_ecx), bw);
WriteLog('Hook CSLQuery::Initialize');
SignPtr := Pointer(Cardinal(TermSrvBase) + $196B0);
Jump.PushOp := $68;
Jump.PushArg := @New_CSLQuery_Initialize;
Jump.RetOp := $C3;
WriteProcessMemory(GetCurrentProcess, SignPtr,
@Jump, SizeOf(far_jmp), bw);
end;
if (FV.Release = 9600) and (FV.Build = 16384) then begin
WriteLog('Patch CEnforcementCore::GetInstanceOfTSLicense');
{
.text:100A271C call ?IsLicenseTypeLocalOnly@CSLQuery@@SGJAAU_GUID@@PAH@Z ; CSLQuery::IsLicenseTypeLocalOnly(_GUID &,int *)
.text:100A2721 test eax, eax
.text:100A2723 js short loc_100A2740
.text:100A2725 cmp [ebp+var_8], 0
.text:100A2729 jz short loc_100A2740 <- jmp
}
SignPtr := Pointer(Cardinal(TermSrvBase) + $A2729);
b := $EB;
WriteProcessMemory(GetCurrentProcess, SignPtr, @b, 1, bw);
WriteLog('Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled');
{
.text:10018024 lea eax, [esp+150h+VersionInformation]
.text:10018028 inc ebx <- nop
.text:10018029 mov [edi], ebx
.text:1001802B push eax ; lpVersionInformation
.text:1001802C call ds:__imp__GetVersionExW@4 ; GetVersionExW(x)
}
SignPtr := Pointer(Cardinal(TermSrvBase) + $18028);
WriteProcessMemory(GetCurrentProcess, SignPtr, @nop, 1, bw);
WriteLog('Patch CDefPolicy::Query');
SignPtr := Pointer(Cardinal(TermSrvBase) + $16115);
WriteProcessMemory(GetCurrentProcess, SignPtr,
@CDefPolicy_Query_eax_ecx[0],
SizeOf(CDefPolicy_Query_eax_ecx), bw);
WriteLog('Hook CSLQuery::Initialize');
SignPtr := Pointer(Cardinal(TermSrvBase) + $1CEB0);
Jump.PushOp := $68;
Jump.PushArg := @New_CSLQuery_Initialize;
Jump.RetOp := $C3;
WriteProcessMemory(GetCurrentProcess, SignPtr,
@Jump, SizeOf(far_jmp), bw);
end;
if (FV.Release = 9600) and (FV.Build = 17095) then begin
WriteLog('Patch CEnforcementCore::GetInstanceOfTSLicense');
{
.text:100A36C4 call ?IsLicenseTypeLocalOnly@CSLQuery@@SGJAAU_GUID@@PAH@Z ; CSLQuery::IsLicenseTypeLocalOnly(_GUID &,int *)
.text:100A36C9 test eax, eax
.text:100A36CB js short loc_100A36E8
.text:100A36CD cmp [ebp+var_8], 0
.text:100A36D1 jz short loc_100A36E8 <- jmp
}
SignPtr := Pointer(Cardinal(TermSrvBase) + $A36D1);
b := $EB;
WriteProcessMemory(GetCurrentProcess, SignPtr, @b, 1, bw);
WriteLog('Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled');
{
.text:10036BA5 lea eax, [esp+150h+VersionInformation]
.text:10036BA9 inc ebx <- nop
.text:10036BAA mov [edi], ebx
.text:10036BAC push eax ; lpVersionInformation
.text:10036BAD call ds:__imp__GetVersionExW@4 ; GetVersionExW(x)
}
SignPtr := Pointer(Cardinal(TermSrvBase) + $36BA9);
WriteProcessMemory(GetCurrentProcess, SignPtr, @nop, 1, bw);
WriteLog('Patch CDefPolicy::Query');
SignPtr := Pointer(Cardinal(TermSrvBase) + $37529);
WriteProcessMemory(GetCurrentProcess, SignPtr,
@CDefPolicy_Query_eax_ecx[0],
SizeOf(CDefPolicy_Query_eax_ecx), bw);
WriteLog('Hook CSLQuery::Initialize');
SignPtr := Pointer(Cardinal(TermSrvBase) + $117F1);
Jump.PushOp := $68;
Jump.PushArg := @New_CSLQuery_Initialize;
Jump.RetOp := $C3;
WriteProcessMemory(GetCurrentProcess, SignPtr,
@Jump, SizeOf(far_jmp), bw);
end;
end;
end;
if V = $0604 then begin
// Windows 10
// uses SL Policy internal inline code
if GetModuleAddress('termsrv.dll', GetCurrentProcessId, TermSrvBase, TermSrvSize) then begin
// Patch functions:
// CEnforcementCore::GetInstanceOfTSLicense
// CSessionArbitrationHelper::IsSingleSessionPerUserEnabled
// CDefPolicy::Query
// Hook function:
// CSLQuery::Initialize
if (FV.Release = 9841) and (FV.Build = 0) then begin
WriteLog('Patch CEnforcementCore::GetInstanceOfTSLicense');
{
.text:1009569B call sub_100B7EE5
.text:100956A0 test eax, eax
.text:100956A2 js short loc_100956BF
.text:100956A4 cmp [ebp+var_C], 0
.text:100956A8 jz short loc_100956BF <- jmp
}
SignPtr := Pointer(Cardinal(TermSrvBase) + $956A8);
b := $EB;
WriteProcessMemory(GetCurrentProcess, SignPtr, @b, 1, bw);
WriteLog('Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled');
{
.text:10030121 lea eax, [esp+150h+VersionInformation]
.text:10030125 inc ebx <- nop
.text:10030126 mov [edi], ebx
.text:10030128 push eax ; lpVersionInformation
.text:10030129 call ds:GetVersionExW
}
SignPtr := Pointer(Cardinal(TermSrvBase) + $30125);
WriteProcessMemory(GetCurrentProcess, SignPtr, @nop, 1, bw);
WriteLog('Patch CDefPolicy::Query');
SignPtr := Pointer(Cardinal(TermSrvBase) + $3B989);
WriteProcessMemory(GetCurrentProcess, SignPtr,
@CDefPolicy_Query_eax_ecx[0],
SizeOf(CDefPolicy_Query_eax_ecx), bw);
WriteLog('Hook CSLQuery::Initialize');
SignPtr := Pointer(Cardinal(TermSrvBase) + $46A68);
Jump.PushOp := $68;
Jump.PushArg := @New_CSLQuery_Initialize;
Jump.RetOp := $C3;
WriteProcessMemory(GetCurrentProcess, SignPtr,
@Jump, SizeOf(far_jmp), bw);
end;
if (FV.Release = 9860) and (FV.Build = 0) then begin
WriteLog('Patch CEnforcementCore::GetInstanceOfTSLicense');
{
.text:100962BB call ?IsLicenseTypeLocalOnly@CSLQuery@@SGJAAU_GUID@@PAH@Z ; CSLQuery::IsLicenseTypeLocalOnly(_GUID &,int *)
.text:100962C0 test eax, eax
.text:100962C2 js short loc_100962DF
.text:100962C4 cmp [ebp+var_C], 0
.text:100962C8 jz short loc_100962DF <- jmp
}
SignPtr := Pointer(Cardinal(TermSrvBase) + $962C8);
b := $EB;
WriteProcessMemory(GetCurrentProcess, SignPtr, @b, 1, bw);
WriteLog('Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled');
{
.text:10030841 lea eax, [esp+150h+VersionInformation]
.text:10030845 inc ebx <- nop
.text:10030846 mov [edi], ebx
.text:10030848 push eax ; lpVersionInformation
.text:10030849 call ds:__imp__GetVersionExW@4 ; GetVersionExW(x)
}
SignPtr := Pointer(Cardinal(TermSrvBase) + $30845);
WriteProcessMemory(GetCurrentProcess, SignPtr, @nop, 1, bw);
WriteLog('Patch CDefPolicy::Query');
SignPtr := Pointer(Cardinal(TermSrvBase) + $3BEC9);
WriteProcessMemory(GetCurrentProcess, SignPtr,
@CDefPolicy_Query_eax_ecx[0],
SizeOf(CDefPolicy_Query_eax_ecx), bw);
WriteLog('Hook CSLQuery::Initialize');
SignPtr := Pointer(Cardinal(TermSrvBase) + $46F18);
Jump.PushOp := $68;
Jump.PushArg := @New_CSLQuery_Initialize;
Jump.RetOp := $C3;
WriteProcessMemory(GetCurrentProcess, SignPtr,
@Jump, SizeOf(far_jmp), bw);
end;
end;
end;
// unfreeze threads
WriteLog('resume');
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);
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);
end;
// export section
exports
TermServiceMain index 1 name 'ServiceMain';
exports
TermServiceGlobals index 2 name 'SvchostPushServiceGlobals';
begin
// DllMain procedure is not used
end.