mirror of
https://github.com/stascorp/rdpwrap.git
synced 2024-11-10 10:18:22 +00:00
1502 lines
55 KiB
ObjectPascal
1502 lines
55 KiB
ObjectPascal
|
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.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.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.4.9841.0 (Windows 10 Technical Preview) [init hook + extended patch]
|
||
|
|
||
|
// Known failures
|
||
|
// 6.0.6000.16386 (Windows Vista RTM x86, crashes on logon attempt)
|
||
|
|
||
|
// Internal changelog:
|
||
|
|
||
|
// 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.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.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
|
||
|
|
||
|
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 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;
|
||
|
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;
|
||
|
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;
|
||
|
|
||
|
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.
|