You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1722 lines
65 KiB
Plaintext

{
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;
// RDP Wrapper Library project by Stas'M
// Terminal Services supported versions
// 6.0.X.X (Windows Vista, any) [policy hook only]
// 6.0.6000.16386 (Windows Vista) [policy hook + extended patch]
// 6.0.6001.18000 (Windows Vista SP1) [policy hook + extended patch]
// 6.0.6001.22565 (Windows Vista SP1 with KB977541) [todo]
// 6.0.6001.22635 (Windows Vista SP1 with KB970911) [todo]
// 6.0.6001.22801 (Windows Vista SP1 with KB2381675) [todo]
// 6.0.6002.18005 (Windows Vista SP2) [policy hook + extended patch]
// 6.0.6002.22269 (Windows Vista SP2 with KB977541) [todo]
// 6.0.6002.22340 (Windows Vista SP2 with KB970911) [todo]
// 6.0.6002.22515 (Windows Vista SP2 with KB2381675) [todo]
// 6.0.6002.22641 (Windows Vista SP2 with KB2523307) [todo]
// 6.0.6002.19214 (Windows Vista SP2 with KB3003743 GDR) [policy hook + extended patch]
// 6.0.6002.23521 (Windows Vista SP2 with KB3003743 LDR) [policy hook + extended patch]
// 6.1.X.X (Windows 7, any) [policy hook only]
// 6.1.7600.16385 (Windows 7) [policy hook + extended patch]
// 6.1.7600.20890 (Windows 7 with KB2479710) [todo]
// 6.1.7600.21316 (Windows 7 with KB2750090) [todo]
// 6.1.7601.17514 (Windows 7 SP1) [policy hook + extended patch]
// 6.1.7601.21650 (Windows 7 SP1 with KB2479710) [todo]
// 6.1.7601.21866 (Windows 7 SP1 with KB2647409) [todo]
// 6.1.7601.22104 (Windows 7 SP1 with KB2750090) [todo]
// 6.1.7601.18540 (Windows 7 SP1 with KB2984972 GDR) [policy hook + extended patch]
// 6.1.7601.22750 (Windows 7 SP1 with KB2984972 LDR) [policy hook + extended patch]
// 6.1.7601.18637 (Windows 7 SP1 with KB3003743 GDR) [policy hook + extended patch]
// 6.1.7601.22843 (Windows 7 SP1 with KB3003743 LDR) [policy hook + extended patch]
// 6.2.8102.0 (Windows 8 Developer Preview) [policy hook + extended patch]
// 6.2.8250.0 (Windows 8 Consumer Preview) [policy hook + extended patch]
// 6.2.8400.0 (Windows 8 Release Preview) [policy hook + extended patch]
// 6.2.9200.16384 (Windows 8) [policy hook + extended patch]
// 6.2.9200.17048 (Windows 8 with KB2973501 GDR) [policy hook + extended patch]
// 6.2.9200.21166 (Windows 8 with KB2973501 LDR) [policy hook + extended patch]
// 6.3.9431.0 (Windows 8.1 Preview) [init hook + extended patch]
// 6.3.9600.16384 (Windows 8.1) [init hook + extended patch]
// 6.3.9600.17095 (Windows 8.1 with KB2959626) [init hook + extended patch]
// 6.3.9600.17415 (Windows 8.1 with KB3000850) [!todo]
// 6.4.9841.0 (Windows 10 Technical Preview) [init hook + extended patch]
// 6.4.9860.0 (Windows 10 Technical Preview Update 1) [init hook + extended patch]
// 6.4.9879.0 (Windows 10 Technical Preview Update 2) [!todo]
// Known failures
// 6.0.6000.16386 (Windows Vista RTM x86, crashes on logon attempt)
// Internal changelog:
// 2014.11.13 :
// - researching KB3003743
// - added support for version 6.0.6002.19214
// - added support for version 6.0.6002.23521
// - added support for version 6.1.7601.18637
// - added support for version 6.1.7601.22843
// 2014.11.02 :
// - researching termsrv.dll 6.4.9860.0
// - done
// 2014.10.19 :
// - added support for version 6.0.6000.16386 (x64)
// - added support for version 6.0.6001.18000 (x64)
// - added support for version 6.1.7600.16385
// 2014.10.18 :
// - corrected some typos in source
// - simplified signature constants
// - added support for version 6.0.6000.16386 (x86)
// - added support for version 6.0.6001.18000 (x86)
// - added support for version 6.0.6002.18005
// - added support for version 6.1.7601.17514
// - added support for version 6.1.7601.18540
// - added support for version 6.1.7601.22750
// - added support for version 6.2.9200.17048
// - added support for version 6.2.9200.21166
// 2014.10.17 :
// - collecting information about all versions of Terminal Services beginning from Vista
// - added [todo] to the versions list
// 2014.10.16 :
// - got new updates: KB2984972 for Win 7 (still works with 2 concurrent users) and KB2973501 for Win 8 (doesn't work)
// 2014.10.02 :
// - researching Windows 10 TP Remote Desktop
// - done! even without debugging symbols ^^)
// 2014.07.20 :
// - added support for Windows 8 Release Preview
// - added support for Windows 8 Consumer Preview
// - added support for Windows 8 Developer Preview
// 2014.07.19 :
// - improved patching of Windows 8
// - added policy patches
// - will patch CDefPolicy::Query
// - will patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled
// 2014.07.18 :
// - researched patched files from MDL forum
// - CSLQuery::GetMaxSessions requires no patching
// - it's better to change the default policy, so...
// - will patch CDefPolicy::Query
// - will patch CEnforcementCore::GetInstanceOfTSLicense
// - will patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled
// - the function CSLQuery::Initialize is hooked correctly
// 2014.07.17 :
// - will hook only CSLQuery::Initialize function
// - CSLQuery::GetMaxSessions will be patched
// - added x86 signatures for 6.3.9431.0 (Windows 8.1 Preview)
// 2014.07.16 :
// - changing asm opcodes is bad, will hook CSL functions
// 2014.07.15 :
// - added x86 signatures for 6.3.9600.16384 (Windows 8.1)
// 2014.07.15 :
// - added x86 signatures for 6.3.9600.17095 (Windows 8.1 with KB2959626)
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);
// ------------------- TermService build 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
// ------------------- TermService build 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
// ------------------- TermService build 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
// ------------------- TermService build 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
// ------------------- TermService build 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
// ------------------- TermService build 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
// ------------------- TermService build 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
// ------------------- TermService build 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
// ------------------- TermService build 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
// ------------------- TermService build 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
// ------------------- TermService build 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
// ------------------- TermService build 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
// ------------------- TermService build 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
// ------------------- TermService build 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
// ------------------- TermService build 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
// ------------------- TermService build 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
// ------------------- TermService build 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
// ------------------- TermService build 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
// ------------------- TermService build 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
// ------------------- TermService build 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
// ------------------- TermService build 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
// ------------------- TermService build 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.