// RDPWrap C++ port by Fusix (Nikita Parshin) // assisted by binarymaster (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.25 : // - added few comments about ARM platform for developers // 2014.07.22 : // - fixed bug in x64 signatures // 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) // - added x64 signatures for 6.3.9431.0 (Windows 8.1 Preview) // - just for check ^^) // 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) // - added x64 signatures for 6.3.9600.16384 (Windows 8.1) // - added x86 signatures for 6.3.9600.17095 (Windows 8.1 with KB2959626) // - added x64 signatures for 6.3.9600.17095 (Windows 8.1 with KB2959626) #include "stdafx.h" typedef struct { union { struct { WORD Minor; WORD Major; } wVersion; DWORD dwVersion; }; WORD Release; WORD Build; } FILE_VERSION; #ifdef _WIN64 typedef unsigned long long PLATFORM_DWORD; struct FARJMP { // x64 far jump | opcode | assembly BYTE MovOp; // 48 mov rax, ptr BYTE MovRegArg; // B8 DWORD64 MovArg; // PTR BYTE PushRaxOp; // 50 push rax BYTE RetOp; // C3 retn }; // x64 signatures char CDefPolicy_Query_eax_rcx_jmp[] = {0xB8, 0x00, 0x01, 0x00, 0x00, 0x89, 0x81, 0x38, 0x06, 0x00, 0x00, 0x90, 0xEB}; char CDefPolicy_Query_eax_rdi[] = {0xB8, 0x00, 0x01, 0x00, 0x00, 0x89, 0x87, 0x38, 0x06, 0x00, 0x00, 0x90}; char CDefPolicy_Query_eax_rcx[] = {0xB8, 0x00, 0x01, 0x00, 0x00, 0x89, 0x81, 0x38, 0x06, 0x00, 0x00, 0x90}; // termsrv.dll build 6.0.6000.16386 // Original // .text:000007FF7573C88F mov eax, [rcx+638h] // .text:000007FF7573C895 cmp [rcx+63Ch], eax // .text:000007FF7573C89B jnz short loc_7FF7573C8B3 //_______________ // // Changed // .text:000007FF7573C88F mov eax, 100h // .text:000007FF7573C894 mov [rcx+638h], eax // .text:000007FF7573C89A nop // .text:000007FF7573C89B jmp short loc_7FF7573C8B3 // char CDefPolicy_Query_eax_rcx_jmp[] // termsrv.dll build 6.0.6001.18000 // Original // .text:000007FF76285BD7 mov eax, [rcx+638h] // .text:000007FF76285BDD cmp [rcx+63Ch], eax // .text:000007FF76285BE3 jnz short loc_7FF76285BFB //_______________ // // Changed // .text:000007FF76285BD7 mov eax, 100h // .text:000007FF76285BDC mov [rcx+638h], eax // .text:000007FF76285BE2 nop // .text:000007FF76285BE3 jmp short loc_7FF76285BFB // char CDefPolicy_Query_eax_rcx_jmp[] // termsrv.dll build 6.0.6002.18005 // Original // .text:000007FF76725E83 mov eax, [rcx+638h] // .text:000007FF76725E89 cmp [rcx+63Ch], eax // .text:000007FF76725E8F jz short loc_7FF76725EA7 //_______________ // // Changed // .text:000007FF76725E83 mov eax, 100h // .text:000007FF76725E88 mov [rcx+638h], eax // .text:000007FF76725E8E nop // .text:000007FF76725E8F jmp short loc_7FF76725EA7 // char CDefPolicy_Query_eax_rcx_jmp[] // termsrv.dll build 6.1.7600.16385 // Original // .text:000007FF75A97AD2 cmp [rdi+63Ch], eax // .text:000007FF75A97AD8 jz loc_7FF75AA4978 //_______________ // // Changed // .text:000007FF75A97AD2 mov eax, 100h // .text:000007FF75A97AD7 mov [rdi+638h], eax // .text:000007FF75A97ADD nop // char CDefPolicy_Query_eax_rdi[] // termsrv.dll build 6.1.7601.17514 // Original // .text:000007FF75A97D8A cmp [rdi+63Ch], eax // .text:000007FF75A97D90 jz loc_7FF75AA40F4 //_______________ // // Changed // .text:000007FF75A97D8A mov eax, 100h // .text:000007FF75A97D8F mov [rdi+638h], eax // .text:000007FF75A97D95 nop // char CDefPolicy_Query_eax_rdi[] // termsrv.dll build 6.1.7601.18540 // Original // .text:000007FF75A97C82 cmp [rdi+63Ch], eax // .text:000007FF75A97C88 jz loc_7FF75AA3FBD //_______________ // // Changed // .text:000007FF75A97C82 mov eax, 100h // .text:000007FF75A97C87 mov [rdi+638h], eax // .text:000007FF75A97C8D nop // char CDefPolicy_Query_eax_rdi[] // termsrv.dll build 6.1.7601.22750 // Original // .text:000007FF75A97C92 cmp [rdi+63Ch], eax // .text:000007FF75A97C98 jz loc_7FF75AA40A2 //_______________ // // Changed // .text:000007FF75A97C92 mov eax, 100h // .text:000007FF75A97C97 mov [rdi+638h], eax // .text:000007FF75A97C9D nop // char CDefPolicy_Query_eax_rdi[] // termsrv.dll build 6.2.8102.0 // Original // .text:000000018000D3E6 cmp [rdi+63Ch], eax // .text:000000018000D3EC jz loc_180027792 //_______________ // // Changed // .text:000000018000D3E6 mov eax, 100h // .text:000000018000D3EB mov [rdi+638h], eax // .text:000000018000D3F1 nop // char CDefPolicy_Query_eax_rdi[] // termsrv.dll build 6.2.8250.0 // Original // .text:000000018001187A cmp [rdi+63Ch], eax // .text:0000000180011880 jz loc_1800273A2 //_______________ // // Changed // .text:000000018001187A mov eax, 100h // .text:000000018001187F mov [rdi+638h], eax // .text:0000000180011885 nop // char CDefPolicy_Query_eax_rdi[] // termsrv.dll build 6.2.8400.0 // Original // .text:000000018001F102 cmp [rdi+63Ch], eax // .text:000000018001F108 jz loc_18003A02E //_______________ // // Changed // .text:000000018001F102 mov eax, 100h // .text:000000018001F107 mov [rdi+638h], eax // .text:000000018001F10D nop // char CDefPolicy_Query_eax_rdi[] // termsrv.dll build 6.2.9200.16384 // Original // .text:000000018002A31A cmp [rdi+63Ch], eax // .text:000000018002A320 jz loc_18003A0F9 //_______________ // // Changed // .text:000000018002A31A mov eax, 100h // .text:000000018002A31F mov [rdi+638h], eax // .text:000000018002A325 nop // char CDefPolicy_Query_eax_rdi[] // termsrv.dll build 6.2.9200.17048 // Original // .text:000000018001F206 cmp [rdi+63Ch], eax // .text:000000018001F20C jz loc_18003A1B4 //_______________ // // Changed // .text:000000018001F206 mov eax, 100h // .text:000000018001F20B mov [rdi+638h], eax // .text:000000018001F211 nop // char CDefPolicy_Query_eax_rdi[] // termsrv.dll build 6.2.9200.21166 // Original // .text:000000018002A3B6 cmp [rdi+63Ch], eax // .text:000000018002A3BC jz loc_18003A174 //_______________ // // Changed // .text:000000018002A3B6 mov eax, 100h // .text:000000018002A3BB mov [rdi+638h], eax // .text:000000018002A3C1 nop // char CDefPolicy_Query_eax_rdi[] // termsrv.dll build 6.3.9431.0 // Original // .text:00000001800350FD cmp [rcx+63Ch], eax // .text:0000000180035103 jz loc_18004F6AE //_______________ // // Changed // .text:00000001800350FD mov eax, 100h // .text:0000000180035102 mov [rcx+638h], eax // .text:0000000180035108 nop // char CDefPolicy_Query_eax_rcx[] // termsrv.dll build 6.3.9600.16384 // Original // .text:0000000180057829 cmp [rcx+63Ch], eax // .text:000000018005782F jz loc_18005E850 //_______________ // // Changed // .text:0000000180057829 mov eax, 100h // .text:000000018005782E mov [rcx+638h], eax // .text:0000000180057834 nop // char CDefPolicy_Query_eax_rcx[] // termsrv.dll build 6.3.9600.17095 // Original // .text:000000018001F6A1 cmp [rcx+63Ch], eax // .text:000000018001F6A7 jz loc_18007284B //_______________ // // Changed // .text:000000018001F6A1 mov eax, 100h // .text:000000018001F6A6 mov [rcx+638h], eax // .text:000000018001F6AC nop // char CDefPolicy_Query_eax_rcx[] // termsrv.dll build 6.4.9841.0 // Original // .text:000000018000C125 cmp [rcx+63Ch], eax // .text:000000018000C12B jz sub_18003BABC //_______________ // // Changed // .text:000000018000C125 mov eax, 100h // .text:000000018000C12A mov [rcx+638h], eax // .text:000000018000C130 nop // char CDefPolicy_Query_eax_rcx[] #else typedef unsigned long PLATFORM_DWORD; struct FARJMP { // x86 far jump | opcode | assembly BYTE PushOp; // 68 push ptr DWORD PushArg; // PTR BYTE RetOp; // C3 retn }; // x86 signatures char CDefPolicy_Query_edx_ecx[] = {0xBA, 0x00, 0x01, 0x00, 0x00, 0x89, 0x91, 0x20, 0x03, 0x00, 0x00, 0x5E, 0x90}; char CDefPolicy_Query_eax_esi[] = {0xB8, 0x00, 0x01, 0x00, 0x00, 0x89, 0x86, 0x20, 0x03, 0x00, 0x00, 0x90}; char CDefPolicy_Query_eax_ecx[] = {0xB8, 0x00, 0x01, 0x00, 0x00, 0x89, 0x81, 0x20, 0x03, 0x00, 0x00, 0x90}; // termsrv.dll 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 // char CDefPolicy_Query_edx_ecx[] // termsrv.dll 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 // char CDefPolicy_Query_edx_ecx[] // termsrv.dll 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 // char CDefPolicy_Query_edx_ecx[] // termsrv.dll 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 // char CDefPolicy_Query_eax_esi[] // termsrv.dll 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 // char CDefPolicy_Query_eax_esi[] // termsrv.dll 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 // char CDefPolicy_Query_eax_esi[] // termsrv.dll 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 // char CDefPolicy_Query_eax_esi[] // termsrv.dll 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 // char CDefPolicy_Query_eax_esi[] // termsrv.dll 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 // char CDefPolicy_Query_eax_esi[] // termsrv.dll 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 // char CDefPolicy_Query_eax_esi[] // termsrv.dll 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 // char CDefPolicy_Query_eax_esi[] // termsrv.dll 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 // char CDefPolicy_Query_eax_esi[] // termsrv.dll 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 // char CDefPolicy_Query_eax_esi[] // termsrv.dll 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 // char CDefPolicy_Query_eax_ecx[] // termsrv.dll 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 // char CDefPolicy_Query_eax_ecx[] // termsrv.dll 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 // char CDefPolicy_Query_eax_ecx[] // termsrv.dll 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 // char CDefPolicy_Query_eax_ecx[] #endif FARJMP Old_SLGetWindowsInformationDWORD, Stub_SLGetWindowsInformationDWORD; SLGETWINDOWSINFORMATIONDWORD _SLGetWindowsInformationDWORD; HMODULE hTermSrv; HMODULE hSLC; PLATFORM_DWORD TermSrvBase; FILE_VERSION FV; SERVICEMAIN _ServiceMain; SVCHOSTPUSHSERVICEGLOBALS _SvchostPushServiceGlobals; bool AlreadyHooked = false; void WriteToLog(LPSTR Text) { DWORD dwBytesOfWritten; HANDLE hFile = CreateFile(L"\\rdpwrap.txt", GENERIC_WRITE, FILE_SHARE_WRITE|FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile == INVALID_HANDLE_VALUE) return; SetFilePointer(hFile, 0, 0, FILE_END); WriteFile(hFile, Text, strlen(Text), &dwBytesOfWritten, NULL); CloseHandle(hFile); } PLATFORM_DWORD SearchAddressBySignature(char *StartPosition, PLATFORM_DWORD Size, char *Signature, int SignatureSize) { PLATFORM_DWORD AddressReturn = -1; for (PLATFORM_DWORD i = 0; i < Size; i++) { for (int j = 0; StartPosition[i+j] == Signature[j] && j < SignatureSize; j++) { if (j == SignatureSize-1) AddressReturn = (PLATFORM_DWORD)&StartPosition[i]; } } return AddressReturn; } bool GetModuleCodeSectionInfo(HMODULE hModule, PLATFORM_DWORD *BaseAddr, PLATFORM_DWORD *BaseSize) { PIMAGE_DOS_HEADER pDosHeader; PIMAGE_FILE_HEADER pFileHeader; PIMAGE_OPTIONAL_HEADER pOptionalHeader; if (hModule == NULL) return false; pDosHeader = (PIMAGE_DOS_HEADER)hModule; pFileHeader = (PIMAGE_FILE_HEADER)(((PBYTE)hModule)+pDosHeader->e_lfanew+4); pOptionalHeader = (PIMAGE_OPTIONAL_HEADER)(pFileHeader+1); *BaseAddr = (PLATFORM_DWORD)hModule; *BaseSize = (PLATFORM_DWORD)pOptionalHeader->SizeOfCode; if (*BaseAddr <= 0 || *BaseSize <= 0) return false; return true; } void SetThreadsState(bool Resume) { HANDLE h, hThread; DWORD CurrTh, CurrPr; THREADENTRY32 Thread; CurrTh = GetCurrentThreadId(); CurrPr = GetCurrentProcessId(); h = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0); if (h != INVALID_HANDLE_VALUE) { Thread.dwSize = sizeof(THREADENTRY32); Thread32First(h, &Thread); do { if (Thread.th32ThreadID != CurrTh && Thread.th32OwnerProcessID == CurrPr) { hThread = OpenThread(THREAD_SUSPEND_RESUME, false, Thread.th32ThreadID); if (hThread != INVALID_HANDLE_VALUE) { if (Resume) ResumeThread(hThread); else SuspendThread(hThread); CloseHandle(hThread); } } } while (Thread32Next(h, &Thread)); CloseHandle(h); } } BOOL __stdcall GetModuleVersion(LPCWSTR lptstrModuleName, FILE_VERSION *FileVersion) { typedef struct { WORD wLength; WORD wValueLength; WORD wType; WCHAR szKey[16]; WORD Padding1; VS_FIXEDFILEINFO Value; WORD Padding2; WORD Children; } VS_VERSIONINFO; HMODULE hMod = GetModuleHandle(lptstrModuleName); if(!hMod) { return false; } HRSRC hResourceInfo = FindResourceW(hMod, (LPCWSTR)1, (LPCWSTR)0x10); if(!hResourceInfo) { return false; } VS_VERSIONINFO *VersionInfo = (VS_VERSIONINFO*)LoadResource(hMod, hResourceInfo); if(!VersionInfo) { return false; } FileVersion->dwVersion = VersionInfo->Value.dwFileVersionMS; FileVersion->Release = (WORD)(VersionInfo->Value.dwFileVersionLS >> 16); FileVersion->Build = (WORD)VersionInfo->Value.dwFileVersionLS; return true; } BOOL __stdcall GetFileVersion(LPCWSTR lptstrFilename, FILE_VERSION *FileVersion) { typedef struct { WORD wLength; WORD wValueLength; WORD wType; WCHAR szKey[16]; WORD Padding1; VS_FIXEDFILEINFO Value; WORD Padding2; WORD Children; } VS_VERSIONINFO; HMODULE hFile = LoadLibraryExW(lptstrFilename, NULL, LOAD_LIBRARY_AS_DATAFILE); if(!hFile) { return false; } HRSRC hResourceInfo = FindResourceW(hFile, (LPCWSTR)1, (LPCWSTR)0x10); if(!hResourceInfo) { return false; } VS_VERSIONINFO *VersionInfo = (VS_VERSIONINFO*)LoadResource(hFile, hResourceInfo); if(!VersionInfo) { return false; } FileVersion->dwVersion = VersionInfo->Value.dwFileVersionMS; FileVersion->Release = (WORD)(VersionInfo->Value.dwFileVersionLS >> 16); FileVersion->Build = (WORD)VersionInfo->Value.dwFileVersionLS; return true; } bool OverrideSL(LPWSTR ValueName, DWORD *Value) { // Allow Remote Connections if (wcscmp(ValueName, L"TerminalServices-RemoteConnectionManager-AllowRemoteConnections") == 0) { *Value = 1; return true; } // Allow Multiple Sessions if (wcscmp(ValueName, L"TerminalServices-RemoteConnectionManager-AllowMultipleSessions") == 0) { *Value = 1; return true; } // Allow Multiple Sessions (Application Server Mode) if (wcscmp(ValueName, L"TerminalServices-RemoteConnectionManager-AllowAppServerMode") == 0) { *Value = 1; return true; } // Allow Multiple Monitors if (wcscmp(ValueName, L"TerminalServices-RemoteConnectionManager-AllowMultimon") == 0) { *Value = 1; return true; } // Max User Sessions (0 = unlimited) if (wcscmp(ValueName, L"TerminalServices-RemoteConnectionManager-MaxUserSessions") == 0) { *Value = 0; return true; } // Max Debug Sessions (Win 8, 0 = unlimited) if (wcscmp(ValueName, L"TerminalServices-RemoteConnectionManager-ce0ad219-4670-4988-98fb-89b14c2f072b-MaxSessions") == 0) { *Value = 0; return true; } // Max Sessions // 0 - logon not possible even from console // 1 - only one active user (console or remote) // 2 - allow concurrent sessions if (wcscmp(ValueName, L"TerminalServices-RemoteConnectionManager-45344fe7-00e6-4ac6-9f01-d01fd4ffadfb-MaxSessions") == 0) { *Value = 2; return true; } // Allow Advanced Compression with RDP 7 Protocol if (wcscmp(ValueName, L"TerminalServices-RDP-7-Advanced-Compression-Allowed") == 0) { *Value = 1; return true; } // IsTerminalTypeLocalOnly = 0 if (wcscmp(ValueName, L"TerminalServices-RemoteConnectionManager-45344fe7-00e6-4ac6-9f01-d01fd4ffadfb-LocalOnly") == 0) { *Value = 0; return true; } // Max Sessions (hard limit) if (wcscmp(ValueName, L"TerminalServices-RemoteConnectionManager-8dc86f1d-9969-4379-91c1-06fe1dc60575-MaxSessions") == 0) { *Value = 1000; return true; } return false; } HRESULT WINAPI New_SLGetWindowsInformationDWORD(PWSTR pwszValueName, DWORD *pdwValue) { // wrapped SLGetWindowsInformationDWORD function // termsrv.dll will call this function instead of original SLC.dll // Override SL Policy extern FARJMP Old_SLGetWindowsInformationDWORD, Stub_SLGetWindowsInformationDWORD; extern SLGETWINDOWSINFORMATIONDWORD _SLGetWindowsInformationDWORD; char *Log; DWORD dw; SIZE_T bw; HRESULT Result; Log = new char[1024]; wsprintfA(Log, "Policy query: %S\r\n", pwszValueName); WriteToLog(Log); delete[] Log; if (OverrideSL(pwszValueName, &dw)) { *pdwValue = dw; Log = new char[1024]; wsprintfA(Log, "Rewrite: %i\r\n", dw); WriteToLog(Log); delete[] Log; return S_OK; } WriteProcessMemory(GetCurrentProcess(), _SLGetWindowsInformationDWORD, &Old_SLGetWindowsInformationDWORD, sizeof(FARJMP), &bw); Result = _SLGetWindowsInformationDWORD(pwszValueName, pdwValue); if (Result == S_OK) { Log = new char[1024]; wsprintfA(Log, "Result: %i\r\n", dw); WriteToLog(Log); delete[] Log; } else { WriteToLog("Failed\r\n"); } WriteProcessMemory(GetCurrentProcess(), _SLGetWindowsInformationDWORD, &Stub_SLGetWindowsInformationDWORD, sizeof(FARJMP), &bw); return Result; } HRESULT __fastcall New_Win8SL(PWSTR pwszValueName, DWORD *pdwValue) { // wrapped unexported function SLGetWindowsInformationDWORDWrapper in termsrv.dll // for Windows 8 support // Override SL Policy extern SLGETWINDOWSINFORMATIONDWORD _SLGetWindowsInformationDWORD; char *Log; DWORD dw; HRESULT Result; Log = new char[1024]; wsprintfA(Log, "Policy query: %S\r\n", pwszValueName); WriteToLog(Log); delete[] Log; if (OverrideSL(pwszValueName, &dw)) { *pdwValue = dw; Log = new char[1024]; wsprintfA(Log, "Rewrite: %i\r\n", dw); WriteToLog(Log); delete[] Log; return S_OK; } Result = _SLGetWindowsInformationDWORD(pwszValueName, pdwValue); if (Result == S_OK) { Log = new char[1024]; wsprintfA(Log, "Result: %i\r\n", dw); WriteToLog(Log); delete[] Log; } else { WriteToLog("Failed\r\n"); } return Result; } #ifndef _WIN64 HRESULT __fastcall New_Win8SL_CP(DWORD arg1, DWORD *pdwValue, PWSTR pwszValueName, DWORD arg4) { // wrapped unexported function SLGetWindowsInformationDWORDWrapper in termsrv.dll // for Windows 8 Consumer Preview support return New_Win8SL(pwszValueName, pdwValue); } #endif HRESULT WINAPI New_CSLQuery_Initialize() { extern PLATFORM_DWORD TermSrvBase; extern FILE_VERSION FV; char *Log; DWORD *bServerSku = NULL; DWORD *bRemoteConnAllowed = NULL; DWORD *bFUSEnabled = NULL; DWORD *bAppServerAllowed = NULL; DWORD *bMultimonAllowed = NULL; DWORD *lMaxUserSessions = NULL; DWORD *ulMaxDebugSessions = NULL; DWORD *bInitialized = NULL; WriteToLog("> CSLQuery::Initialize\r\n"); if (FV.Release == 9431 && FV.Build == 0) { #ifdef _WIN64 bFUSEnabled = (DWORD*)(TermSrvBase + 0xC4490); lMaxUserSessions = (DWORD*)(TermSrvBase + 0xC4494); bAppServerAllowed = (DWORD*)(TermSrvBase + 0xC4498); bInitialized = (DWORD*)(TermSrvBase + 0xC449C); bMultimonAllowed = (DWORD*)(TermSrvBase + 0xC44A0); bServerSku = (DWORD*)(TermSrvBase + 0xC44A4); ulMaxDebugSessions = (DWORD*)(TermSrvBase + 0xC44A8); bRemoteConnAllowed = (DWORD*)(TermSrvBase + 0xC44AC); #else bFUSEnabled = (DWORD*)(TermSrvBase + 0xA22A8); lMaxUserSessions = (DWORD*)(TermSrvBase + 0xA22AC); bAppServerAllowed = (DWORD*)(TermSrvBase + 0xA22B0); bInitialized = (DWORD*)(TermSrvBase + 0xA22B4); bMultimonAllowed = (DWORD*)(TermSrvBase + 0xA22B8); bServerSku = (DWORD*)(TermSrvBase + 0xA22BC); ulMaxDebugSessions = (DWORD*)(TermSrvBase + 0xA22C0); bRemoteConnAllowed = (DWORD*)(TermSrvBase + 0xA22C4); #endif } if (FV.Release == 9600 && FV.Build == 16384) { #ifdef _WIN64 bServerSku = (DWORD*)(TermSrvBase + 0xE6494); ulMaxDebugSessions = (DWORD*)(TermSrvBase + 0xE6498); bRemoteConnAllowed = (DWORD*)(TermSrvBase + 0xE649C); bFUSEnabled = (DWORD*)(TermSrvBase + 0xE64A0); lMaxUserSessions = (DWORD*)(TermSrvBase + 0xE64A4); bAppServerAllowed = (DWORD*)(TermSrvBase + 0xE64A8); bInitialized = (DWORD*)(TermSrvBase + 0xE64AC); bMultimonAllowed = (DWORD*)(TermSrvBase + 0xE64B0); #else bFUSEnabled = (DWORD*)(TermSrvBase + 0xC02A8); lMaxUserSessions = (DWORD*)(TermSrvBase + 0xC02AC); bAppServerAllowed = (DWORD*)(TermSrvBase + 0xC02B0); bInitialized = (DWORD*)(TermSrvBase + 0xC02B4); bMultimonAllowed = (DWORD*)(TermSrvBase + 0xC02B8); bServerSku = (DWORD*)(TermSrvBase + 0xC02BC); ulMaxDebugSessions = (DWORD*)(TermSrvBase + 0xC02C0); bRemoteConnAllowed = (DWORD*)(TermSrvBase + 0xC02C4); #endif /* __ARM_ARCH_7 bFUSEnabled = (DWORD*)(TermSrvBase + 0x?); lMaxUserSessions = (DWORD*)(TermSrvBase + 0x?); bAppServerAllowed = (DWORD*)(TermSrvBase + 0x?); bInitialized = (DWORD*)(TermSrvBase + 0x?); bMultimonAllowed = (DWORD*)(TermSrvBase + 0x?); bServerSku = (DWORD*)(TermSrvBase + 0x?); ulMaxDebugSessions = (DWORD*)(TermSrvBase + 0x?); bRemoteConnAllowed = (DWORD*)(TermSrvBase + 0x?); */ } if (FV.Release == 9600 && FV.Build == 17095) { #ifdef _WIN64 bServerSku = (DWORD*)(TermSrvBase + 0xE4494); ulMaxDebugSessions = (DWORD*)(TermSrvBase + 0xE4498); bRemoteConnAllowed = (DWORD*)(TermSrvBase + 0xE449C); bFUSEnabled = (DWORD*)(TermSrvBase + 0xE44A0); lMaxUserSessions = (DWORD*)(TermSrvBase + 0xE44A4); bAppServerAllowed = (DWORD*)(TermSrvBase + 0xE44A8); bInitialized = (DWORD*)(TermSrvBase + 0xE44AC); bMultimonAllowed = (DWORD*)(TermSrvBase + 0xE44B0); #else bFUSEnabled = (DWORD*)(TermSrvBase + 0xC12A8); lMaxUserSessions = (DWORD*)(TermSrvBase + 0xC12AC); bAppServerAllowed = (DWORD*)(TermSrvBase + 0xC12B0); bInitialized = (DWORD*)(TermSrvBase + 0xC12B4); bMultimonAllowed = (DWORD*)(TermSrvBase + 0xC12B8); bServerSku = (DWORD*)(TermSrvBase + 0xC12BC); ulMaxDebugSessions = (DWORD*)(TermSrvBase + 0xC12C0); bRemoteConnAllowed = (DWORD*)(TermSrvBase + 0xC12C4); #endif } if (FV.Release == 9841 && FV.Build == 0) { #ifdef _WIN64 bFUSEnabled = (DWORD*)(TermSrvBase + 0xECFF8); lMaxUserSessions = (DWORD*)(TermSrvBase + 0xECFFC); bAppServerAllowed = (DWORD*)(TermSrvBase + 0xED000); bInitialized = (DWORD*)(TermSrvBase + 0xED004); bMultimonAllowed = (DWORD*)(TermSrvBase + 0xED008); bServerSku = (DWORD*)(TermSrvBase + 0xED00C); ulMaxDebugSessions = (DWORD*)(TermSrvBase + 0xED010); bRemoteConnAllowed = (DWORD*)(TermSrvBase + 0xED014); #else bFUSEnabled = (DWORD*)(TermSrvBase + 0xBF9F0); lMaxUserSessions = (DWORD*)(TermSrvBase + 0xBF9F4); bAppServerAllowed = (DWORD*)(TermSrvBase + 0xBF9F8); bInitialized = (DWORD*)(TermSrvBase + 0xBF9FC); bMultimonAllowed = (DWORD*)(TermSrvBase + 0xBFA00); bServerSku = (DWORD*)(TermSrvBase + 0xBFA04); ulMaxDebugSessions = (DWORD*)(TermSrvBase + 0xBFA08); bRemoteConnAllowed = (DWORD*)(TermSrvBase + 0xBFA0C); #endif } if (bServerSku) { Log = new char[1024]; wsprintfA(Log, "[0x%p] bServerSku = 1\r\n", bServerSku); WriteToLog(Log); delete[] Log; *bServerSku = 1; } if (bRemoteConnAllowed) { Log = new char[1024]; wsprintfA(Log, "[0x%p] bRemoteConnAllowed = 1\r\n", bRemoteConnAllowed); WriteToLog(Log); delete[] Log; *bRemoteConnAllowed = 1; } if (bFUSEnabled) { Log = new char[1024]; wsprintfA(Log, "[0x%p] bFUSEnabled = 1\r\n", bFUSEnabled); WriteToLog(Log); delete[] Log; *bFUSEnabled = 1; } if (bAppServerAllowed) { Log = new char[1024]; wsprintfA(Log, "[0x%p] bAppServerAllowed = 1\r\n", bAppServerAllowed); WriteToLog(Log); delete[] Log; *bAppServerAllowed = 1; } if (bMultimonAllowed) { Log = new char[1024]; wsprintfA(Log, "[0x%p] bMultimonAllowed = 1\r\n", bMultimonAllowed); WriteToLog(Log); delete[] Log; *bMultimonAllowed = 1; } if (lMaxUserSessions) { Log = new char[1024]; wsprintfA(Log, "[0x%p] lMaxUserSessions = 0\r\n", lMaxUserSessions); WriteToLog(Log); delete[] Log; *lMaxUserSessions = 0; } if (ulMaxDebugSessions) { Log = new char[1024]; wsprintfA(Log, "[0x%p] ulMaxDebugSessions = 0\r\n", ulMaxDebugSessions); WriteToLog(Log); delete[] Log; *ulMaxDebugSessions = 0; } if (bInitialized) { Log = new char[1024]; wsprintfA(Log, "[0x%p] bInitialized = 1\r\n", bInitialized); WriteToLog(Log); delete[] Log; *bInitialized = 1; } return S_OK; } void Hook() { extern FARJMP Old_SLGetWindowsInformationDWORD, Stub_SLGetWindowsInformationDWORD; extern SLGETWINDOWSINFORMATIONDWORD _SLGetWindowsInformationDWORD; extern HMODULE hTermSrv; extern HMODULE hSLC; extern PLATFORM_DWORD TermSrvBase; extern FILE_VERSION FV; AlreadyHooked = true; bool Result; char *Log; SIZE_T bw; WORD Ver = 0; PLATFORM_DWORD TermSrvSize, SignPtr; FARJMP Jump; BYTE b; WriteToLog("init\r\n"); hTermSrv = LoadLibrary(L"termsrv.dll"); if (hTermSrv == 0) { WriteToLog("Error: Failed to load Terminal Services library\r\n"); return; } _ServiceMain = (SERVICEMAIN)GetProcAddress(hTermSrv, "ServiceMain"); _SvchostPushServiceGlobals = (SVCHOSTPUSHSERVICEGLOBALS)GetProcAddress(hTermSrv, "SvchostPushServiceGlobals"); Log = new char[1024]; wsprintfA(Log, "Base addr: 0x%p\r\n", hTermSrv); WriteToLog(Log); delete[] Log; Log = new char[1024]; wsprintfA(Log, "SvcMain: termsrv.dll+0x%p\r\n", (PLATFORM_DWORD)_ServiceMain - (PLATFORM_DWORD)hTermSrv); WriteToLog(Log); delete[] Log; Log = new char[1024]; wsprintfA(Log, "SvcGlobals: termsrv.dll+0x%p\r\n", (PLATFORM_DWORD)_SvchostPushServiceGlobals - (PLATFORM_DWORD)hTermSrv); WriteToLog(Log); delete[] Log; // check termsrv version if (GetModuleVersion(L"termsrv.dll", &FV)) { Ver = (BYTE)FV.wVersion.Minor | ((BYTE)FV.wVersion.Major << 8); } else { // check NT version // Ver = GetVersion(); // deprecated // Ver = ((Ver & 0xFF) << 8) | ((Ver & 0xFF00) >> 8); } if (Ver == 0) { WriteToLog("Error: Failed to detect Terminal Services version\r\n"); return; } Log = new char[1024]; wsprintfA(Log, "Version: %d.%d\r\n", FV.wVersion.Major, FV.wVersion.Minor); WriteToLog(Log); delete[] Log; Log = new char[1024]; wsprintfA(Log, "Release: %d\r\n", FV.Release); WriteToLog(Log); delete[] Log; Log = new char[1024]; wsprintfA(Log, "Build: %d\r\n", FV.Build); WriteToLog(Log); delete[] Log; // temporarily freeze threads WriteToLog("freeze\r\n"); SetThreadsState(false); if (Ver == 0x0600) { // Windows Vista // uses SL Policy API (slc.dll) // load slc.dll and hook function hSLC = LoadLibrary(L"slc.dll"); _SLGetWindowsInformationDWORD = (SLGETWINDOWSINFORMATIONDWORD)GetProcAddress(hSLC, "SLGetWindowsInformationDWORD"); if (_SLGetWindowsInformationDWORD != INVALID_HANDLE_VALUE) { // rewrite original function to call our function (make hook) WriteToLog("Hook SLGetWindowsInformationDWORD\r\n"); #ifdef _WIN64 Stub_SLGetWindowsInformationDWORD.MovOp = 0x48; Stub_SLGetWindowsInformationDWORD.MovRegArg = 0xB8; Stub_SLGetWindowsInformationDWORD.MovArg = (PLATFORM_DWORD)New_SLGetWindowsInformationDWORD; Stub_SLGetWindowsInformationDWORD.PushRaxOp = 0x50; Stub_SLGetWindowsInformationDWORD.RetOp = 0xC3; #else Stub_SLGetWindowsInformationDWORD.PushOp = 0x68; Stub_SLGetWindowsInformationDWORD.PushArg = (PLATFORM_DWORD)New_SLGetWindowsInformationDWORD; Stub_SLGetWindowsInformationDWORD.RetOp = 0xC3; #endif ReadProcessMemory(GetCurrentProcess(), _SLGetWindowsInformationDWORD, &Old_SLGetWindowsInformationDWORD, sizeof(FARJMP), &bw); WriteProcessMemory(GetCurrentProcess(), _SLGetWindowsInformationDWORD, &Stub_SLGetWindowsInformationDWORD, sizeof(FARJMP), &bw); } if (GetModuleCodeSectionInfo(hTermSrv, &TermSrvBase, &TermSrvSize)) { // Patch functions: // CSessionArbitrationHelper::IsSingleSessionPerUserEnabled // CDefPolicy::Query if (FV.Release == 6000 && FV.Build == 16386) { WriteToLog("Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled\r\n"); #ifdef _WIN64 // Imagebase: 7FF756E0000 // .text:000007FF75745E38 lea rcx, [rsp+198h+VersionInformation] ; lpVersionInformation // .text:000007FF75745E3D mov ebx, 1 <- 0 // .text:000007FF75745E42 mov [rsp+198h+VersionInformation.dwOSVersionInfoSize], 11Ch // .text:000007FF75745E4A mov [rdi], ebx // .text:000007FF75745E4C call cs:__imp_GetVersionExW SignPtr = (PLATFORM_DWORD)(TermSrvBase + 0x65E3E); b = 0; #else // 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 = (PLATFORM_DWORD)(TermSrvBase + 0x160BF); b = 0x90; #endif WriteProcessMemory(GetCurrentProcess(), (LPVOID)SignPtr, &b, sizeof(b), &bw); WriteToLog("Patch CDefPolicy::Query\r\n"); #ifdef _WIN64 SignPtr = (PLATFORM_DWORD)(TermSrvBase + 0x5C88F); WriteProcessMemory(GetCurrentProcess(), (LPVOID)SignPtr, &CDefPolicy_Query_eax_rcx_jmp, sizeof(CDefPolicy_Query_eax_rcx_jmp), &bw); #else SignPtr = (PLATFORM_DWORD)(TermSrvBase + 0x15CD8); WriteProcessMemory(GetCurrentProcess(), (LPVOID)SignPtr, &CDefPolicy_Query_edx_ecx, sizeof(CDefPolicy_Query_edx_ecx), &bw); #endif } if (FV.Release == 6001 && FV.Build == 18000) { WriteToLog("Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled\r\n"); #ifdef _WIN64 // Imagebase: 7FF76220000 // .text:000007FF76290DB4 lea rcx, [rsp+198h+VersionInformation] ; lpVersionInformation // .text:000007FF76290DB9 mov ebx, 1 <- 0 // .text:000007FF76290DBE mov [rsp+198h+VersionInformation.dwOSVersionInfoSize], 11Ch // .text:000007FF76290DC6 mov [rdi], ebx // .text:000007FF76290DC8 call cs:__imp_GetVersionExW SignPtr = (PLATFORM_DWORD)(TermSrvBase + 0x70DBA); b = 0; #else // 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 = (PLATFORM_DWORD)(TermSrvBase + 0x185E4); b = 0x90; #endif WriteProcessMemory(GetCurrentProcess(), (LPVOID)SignPtr, &b, sizeof(b), &bw); WriteToLog("Patch CDefPolicy::Query\r\n"); #ifdef _WIN64 SignPtr = (PLATFORM_DWORD)(TermSrvBase + 0x65BD7); WriteProcessMemory(GetCurrentProcess(), (LPVOID)SignPtr, &CDefPolicy_Query_eax_rcx_jmp, sizeof(CDefPolicy_Query_eax_rcx_jmp), &bw); #else SignPtr = (PLATFORM_DWORD)(TermSrvBase + 0x17FD8); WriteProcessMemory(GetCurrentProcess(), (LPVOID)SignPtr, &CDefPolicy_Query_edx_ecx, sizeof(CDefPolicy_Query_edx_ecx), &bw); #endif } if (FV.Release == 6002 && FV.Build == 18005) { WriteToLog("Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled\r\n"); #ifdef _WIN64 // Imagebase: 7FF766C0000 // .text:000007FF76730FF0 lea rcx, [rsp+198h+VersionInformation] ; lpVersionInformation // .text:000007FF76730FF5 mov ebx, 1 <- 0 // .text:000007FF76730FFA mov [rsp+198h+VersionInformation.dwOSVersionInfoSize], 11Ch // .text:000007FF76731002 mov [rdi], ebx // .text:000007FF76731004 call cs:__imp_GetVersionExW SignPtr = (PLATFORM_DWORD)(TermSrvBase + 0x70FF6); b = 0; #else // 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 = (PLATFORM_DWORD)(TermSrvBase + 0x17FA8); b = 0x90; #endif WriteProcessMemory(GetCurrentProcess(), (LPVOID)SignPtr, &b, sizeof(b), &bw); WriteToLog("Patch CDefPolicy::Query\r\n"); #ifdef _WIN64 SignPtr = (PLATFORM_DWORD)(TermSrvBase + 0x65E83); WriteProcessMemory(GetCurrentProcess(), (LPVOID)SignPtr, &CDefPolicy_Query_eax_rcx_jmp, sizeof(CDefPolicy_Query_eax_rcx_jmp), &bw); #else SignPtr = (PLATFORM_DWORD)(TermSrvBase + 0x179C0); WriteProcessMemory(GetCurrentProcess(), (LPVOID)SignPtr, &CDefPolicy_Query_edx_ecx, sizeof(CDefPolicy_Query_edx_ecx), &bw); #endif } } } if (Ver == 0x0601) { // Windows 7 // uses SL Policy API (slc.dll) // load slc.dll and hook function hSLC = LoadLibrary(L"slc.dll"); _SLGetWindowsInformationDWORD = (SLGETWINDOWSINFORMATIONDWORD)GetProcAddress(hSLC, "SLGetWindowsInformationDWORD"); if (_SLGetWindowsInformationDWORD != INVALID_HANDLE_VALUE) { // rewrite original function to call our function (make hook) WriteToLog("Hook SLGetWindowsInformationDWORD\r\n"); #ifdef _WIN64 Stub_SLGetWindowsInformationDWORD.MovOp = 0x48; Stub_SLGetWindowsInformationDWORD.MovRegArg = 0xB8; Stub_SLGetWindowsInformationDWORD.MovArg = (PLATFORM_DWORD)New_SLGetWindowsInformationDWORD; Stub_SLGetWindowsInformationDWORD.PushRaxOp = 0x50; Stub_SLGetWindowsInformationDWORD.RetOp = 0xC3; #else Stub_SLGetWindowsInformationDWORD.PushOp = 0x68; Stub_SLGetWindowsInformationDWORD.PushArg = (PLATFORM_DWORD)New_SLGetWindowsInformationDWORD; Stub_SLGetWindowsInformationDWORD.RetOp = 0xC3; #endif ReadProcessMemory(GetCurrentProcess(), _SLGetWindowsInformationDWORD, &Old_SLGetWindowsInformationDWORD, sizeof(FARJMP), &bw); WriteProcessMemory(GetCurrentProcess(), _SLGetWindowsInformationDWORD, &Stub_SLGetWindowsInformationDWORD, sizeof(FARJMP), &bw); } if (GetModuleCodeSectionInfo(hTermSrv, &TermSrvBase, &TermSrvSize)) { // Patch functions: // CSessionArbitrationHelper::IsSingleSessionPerUserEnabled // CDefPolicy::Query if (FV.Release == 7600 && FV.Build == 16385) { WriteToLog("Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled\r\n"); #ifdef _WIN64 // Imagebase: 7FF75A80000 // .text:000007FF75A97D90 lea rcx, [rsp+198h+VersionInformation] ; lpVersionInformation // .text:000007FF75A97D95 mov ebx, 1 <- 0 // .text:000007FF75A97D9A mov [rsp+198h+VersionInformation.dwOSVersionInfoSize], 11Ch // .text:000007FF75A97DA2 mov [rdi], ebx // .text:000007FF75A97DA4 call cs:__imp_GetVersionExW SignPtr = (PLATFORM_DWORD)(TermSrvBase + 0x17D96); b = 0; #else // 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 = (PLATFORM_DWORD)(TermSrvBase + 0x19E25); b = 0x90; #endif WriteProcessMemory(GetCurrentProcess(), (LPVOID)SignPtr, &b, sizeof(b), &bw); WriteToLog("Patch CDefPolicy::Query\r\n"); #ifdef _WIN64 SignPtr = (PLATFORM_DWORD)(TermSrvBase + 0x17AD2); WriteProcessMemory(GetCurrentProcess(), (LPVOID)SignPtr, &CDefPolicy_Query_eax_rdi, sizeof(CDefPolicy_Query_eax_rdi), &bw); #else SignPtr = (PLATFORM_DWORD)(TermSrvBase + 0x196F3); WriteProcessMemory(GetCurrentProcess(), (LPVOID)SignPtr, &CDefPolicy_Query_eax_esi, sizeof(CDefPolicy_Query_eax_esi), &bw); #endif } if (FV.Release == 7601 && FV.Build == 17514) { WriteToLog("Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled\r\n"); #ifdef _WIN64 // Imagebase: 7FF75A80000 // .text:000007FF75A980DC lea rcx, [rsp+198h+VersionInformation] ; lpVersionInformation // .text:000007FF75A980E1 mov ebx, 1 <- 0 // .text:000007FF75A980E6 mov [rsp+198h+VersionInformation.dwOSVersionInfoSize], 11Ch // .text:000007FF75A980EE mov [rdi], ebx // .text:000007FF75A980F0 call cs:__imp_GetVersionExW SignPtr = (PLATFORM_DWORD)(TermSrvBase + 0x180E2); b = 0; #else // 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 = (PLATFORM_DWORD)(TermSrvBase + 0x1A49D); b = 0x90; #endif WriteProcessMemory(GetCurrentProcess(), (LPVOID)SignPtr, &b, sizeof(b), &bw); WriteToLog("Patch CDefPolicy::Query\r\n"); #ifdef _WIN64 SignPtr = (PLATFORM_DWORD)(TermSrvBase + 0x17D8A); WriteProcessMemory(GetCurrentProcess(), (LPVOID)SignPtr, &CDefPolicy_Query_eax_rdi, sizeof(CDefPolicy_Query_eax_rdi), &bw); #else SignPtr = (PLATFORM_DWORD)(TermSrvBase + 0x19D53); WriteProcessMemory(GetCurrentProcess(), (LPVOID)SignPtr, &CDefPolicy_Query_eax_esi, sizeof(CDefPolicy_Query_eax_esi), &bw); #endif } if (FV.Release == 7601 && FV.Build == 18540) { WriteToLog("Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled\r\n"); #ifdef _WIN64 // Imagebase: 7FF75A80000 // .text:000007FF75A98000 lea rcx, [rsp+198h+VersionInformation] ; lpVersionInformation // .text:000007FF75A98005 mov ebx, 1 <- 0 // .text:000007FF75A9800A mov [rsp+198h+VersionInformation.dwOSVersionInfoSize], 11Ch // .text:000007FF75A98012 mov [rdi], ebx // .text:000007FF75A98014 call cs:__imp_GetVersionExW SignPtr = (PLATFORM_DWORD)(TermSrvBase + 0x18006); b = 0; #else // 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 = (PLATFORM_DWORD)(TermSrvBase + 0x1A4E5); b = 0x90; #endif WriteProcessMemory(GetCurrentProcess(), (LPVOID)SignPtr, &b, sizeof(b), &bw); WriteToLog("Patch CDefPolicy::Query\r\n"); #ifdef _WIN64 SignPtr = (PLATFORM_DWORD)(TermSrvBase + 0x17C82); WriteProcessMemory(GetCurrentProcess(), (LPVOID)SignPtr, &CDefPolicy_Query_eax_rdi, sizeof(CDefPolicy_Query_eax_rdi), &bw); #else SignPtr = (PLATFORM_DWORD)(TermSrvBase + 0x19D9F); WriteProcessMemory(GetCurrentProcess(), (LPVOID)SignPtr, &CDefPolicy_Query_eax_esi, sizeof(CDefPolicy_Query_eax_esi), &bw); #endif } if (FV.Release == 7601 && FV.Build == 22750) { WriteToLog("Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled\r\n"); #ifdef _WIN64 // Imagebase: 7FF75A80000 // .text:000007FF75A97E88 lea rcx, [rsp+198h+VersionInformation] ; lpVersionInformation // .text:000007FF75A97E8D mov ebx, 1 <- 0 // .text:000007FF75A97E92 mov [rsp+198h+VersionInformation.dwOSVersionInfoSize], 11Ch // .text:000007FF75A97E9A mov [rdi], ebx // .text:000007FF75A97E9C call cs:__imp_GetVersionExW SignPtr = (PLATFORM_DWORD)(TermSrvBase + 0x17E8E); b = 0; #else // 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 = (PLATFORM_DWORD)(TermSrvBase + 0x1A655); b = 0x90; #endif WriteProcessMemory(GetCurrentProcess(), (LPVOID)SignPtr, &b, sizeof(b), &bw); WriteToLog("Patch CDefPolicy::Query\r\n"); #ifdef _WIN64 SignPtr = (PLATFORM_DWORD)(TermSrvBase + 0x17C92); WriteProcessMemory(GetCurrentProcess(), (LPVOID)SignPtr, &CDefPolicy_Query_eax_rdi, sizeof(CDefPolicy_Query_eax_rdi), &bw); #else SignPtr = (PLATFORM_DWORD)(TermSrvBase + 0x19E21); WriteProcessMemory(GetCurrentProcess(), (LPVOID)SignPtr, &CDefPolicy_Query_eax_esi, sizeof(CDefPolicy_Query_eax_esi), &bw); #endif } } } if (Ver == 0x0602) { // Windows 8 // uses SL Policy internal unexported function // load slc.dll and get function // (will be used on intercepting undefined values) hSLC = LoadLibrary(L"slc.dll"); _SLGetWindowsInformationDWORD = (SLGETWINDOWSINFORMATIONDWORD)GetProcAddress(hSLC, "SLGetWindowsInformationDWORD"); if (GetModuleCodeSectionInfo(hTermSrv, &TermSrvBase, &TermSrvSize)) { // Patch functions: // CSessionArbitrationHelper::IsSingleSessionPerUserEnabled // CDefPolicy::Query // Hook function: // SLGetWindowsInformationDWORDWrapper if (FV.Release == 8102 && FV.Build == 0) { WriteToLog("Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled\r\n"); #ifdef _WIN64 // .text:000000018000D83A lea rcx, [rsp+180h+VersionInformation] ; lpVersionInformation // .text:000000018000D83F mov ebx, 1 <- 0 // .text:000000018000D844 mov [rsp+180h+VersionInformation.dwOSVersionInfoSize], 11Ch // .text:000000018000D84C mov [rdi], ebx // .text:000000018000D84E call cs:__imp_GetVersionExW SignPtr = (PLATFORM_DWORD)(TermSrvBase + 0xD840); b = 0; #else // .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 = (PLATFORM_DWORD)(TermSrvBase + 0xF7E9); b = 0x90; #endif WriteProcessMemory(GetCurrentProcess(), (LPVOID)SignPtr, &b, sizeof(b), &bw); WriteToLog("Patch CDefPolicy::Query\r\n"); #ifdef _WIN64 SignPtr = (PLATFORM_DWORD)(TermSrvBase + 0xD3E6); WriteProcessMemory(GetCurrentProcess(), (LPVOID)SignPtr, &CDefPolicy_Query_eax_rdi, sizeof(CDefPolicy_Query_eax_rdi), &bw); #else SignPtr = (PLATFORM_DWORD)(TermSrvBase + 0xE47C); WriteProcessMemory(GetCurrentProcess(), (LPVOID)SignPtr, &CDefPolicy_Query_eax_esi, sizeof(CDefPolicy_Query_eax_esi), &bw); #endif WriteToLog("Hook SLGetWindowsInformationDWORDWrapper\r\n"); #ifdef _WIN64 SignPtr = (PLATFORM_DWORD)(TermSrvBase + 0x1A484); Jump.MovOp = 0x48; Jump.MovRegArg = 0xB8; Jump.MovArg = (PLATFORM_DWORD)New_Win8SL; Jump.PushRaxOp = 0x50; Jump.RetOp = 0xC3; #else SignPtr = (PLATFORM_DWORD)(TermSrvBase + 0x1B909); Jump.PushOp = 0x68; Jump.PushArg = (PLATFORM_DWORD)New_Win8SL; Jump.RetOp = 0xC3; #endif WriteProcessMemory(GetCurrentProcess(), (LPVOID)SignPtr, &Jump, sizeof(FARJMP), &bw); } if (FV.Release == 8250 && FV.Build == 0) { WriteToLog("Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled\r\n"); #ifdef _WIN64 // .text:0000000180011E6E lea rcx, [rsp+180h+VersionInformation] ; lpVersionInformation // .text:0000000180011E73 mov ebx, 1 <- 0 // .text:0000000180011E78 mov [rsp+180h+VersionInformation.dwOSVersionInfoSize], 11Ch // .text:0000000180011E80 mov [rdi], ebx // .text:0000000180011E82 call cs:__imp_GetVersionExW SignPtr = (PLATFORM_DWORD)(TermSrvBase + 0x11E74); b = 0; #else // .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 = (PLATFORM_DWORD)(TermSrvBase + 0x159C9); b = 0x90; #endif WriteProcessMemory(GetCurrentProcess(), (LPVOID)SignPtr, &b, sizeof(b), &bw); WriteToLog("Patch CDefPolicy::Query\r\n"); #ifdef _WIN64 SignPtr = (PLATFORM_DWORD)(TermSrvBase + 0x1187A); WriteProcessMemory(GetCurrentProcess(), (LPVOID)SignPtr, &CDefPolicy_Query_eax_rdi, sizeof(CDefPolicy_Query_eax_rdi), &bw); #else SignPtr = (PLATFORM_DWORD)(TermSrvBase + 0x13520); WriteProcessMemory(GetCurrentProcess(), (LPVOID)SignPtr, &CDefPolicy_Query_eax_esi, sizeof(CDefPolicy_Query_eax_esi), &bw); #endif WriteToLog("Hook SLGetWindowsInformationDWORDWrapper\r\n"); #ifdef _WIN64 SignPtr = (PLATFORM_DWORD)(TermSrvBase + 0x18FAC); Jump.MovOp = 0x48; Jump.MovRegArg = 0xB8; Jump.MovArg = (PLATFORM_DWORD)New_Win8SL; Jump.PushRaxOp = 0x50; Jump.RetOp = 0xC3; #else SignPtr = (PLATFORM_DWORD)(TermSrvBase + 0x1A0A9); Jump.PushOp = 0x68; Jump.PushArg = (PLATFORM_DWORD)New_Win8SL_CP; Jump.RetOp = 0xC3; #endif WriteProcessMemory(GetCurrentProcess(), (LPVOID)SignPtr, &Jump, sizeof(FARJMP), &bw); } if (FV.Release == 8400 && FV.Build == 0) { WriteToLog("Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled\r\n"); #ifdef _WIN64 // .text:000000018002081E lea rcx, [rsp+180h+VersionInformation] ; lpVersionInformation // .text:0000000180020823 mov ebx, 1 <- 0 // .text:0000000180020828 mov [rsp+180h+VersionInformation.dwOSVersionInfoSize], 11Ch // .text:0000000180020830 mov [rdi], ebx // .text:0000000180020832 call cs:__imp_GetVersionExW SignPtr = (PLATFORM_DWORD)(TermSrvBase + 0x20824); b = 0; #else // .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 = (PLATFORM_DWORD)(TermSrvBase + 0x15482); b = 0x90; #endif WriteProcessMemory(GetCurrentProcess(), (LPVOID)SignPtr, &b, sizeof(b), &bw); WriteToLog("Patch CDefPolicy::Query\r\n"); #ifdef _WIN64 SignPtr = (PLATFORM_DWORD)(TermSrvBase + 0x1F102); WriteProcessMemory(GetCurrentProcess(), (LPVOID)SignPtr, &CDefPolicy_Query_eax_rdi, sizeof(CDefPolicy_Query_eax_rdi), &bw); #else SignPtr = (PLATFORM_DWORD)(TermSrvBase + 0x13E48); WriteProcessMemory(GetCurrentProcess(), (LPVOID)SignPtr, &CDefPolicy_Query_eax_esi, sizeof(CDefPolicy_Query_eax_esi), &bw); #endif WriteToLog("Hook SLGetWindowsInformationDWORDWrapper\r\n"); #ifdef _WIN64 SignPtr = (PLATFORM_DWORD)(TermSrvBase + 0x2492C); Jump.MovOp = 0x48; Jump.MovRegArg = 0xB8; Jump.MovArg = (PLATFORM_DWORD)New_Win8SL; Jump.PushRaxOp = 0x50; Jump.RetOp = 0xC3; #else SignPtr = (PLATFORM_DWORD)(TermSrvBase + 0x19629); Jump.PushOp = 0x68; Jump.PushArg = (PLATFORM_DWORD)New_Win8SL; Jump.RetOp = 0xC3; #endif WriteProcessMemory(GetCurrentProcess(), (LPVOID)SignPtr, &Jump, sizeof(FARJMP), &bw); } if (FV.Release == 9200 && FV.Build == 16384) { WriteToLog("Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled\r\n"); #ifdef _WIN64 // .text:000000018002BAA2 lea rcx, [rsp+180h+VersionInformation] ; lpVersionInformation // .text:000000018002BAA7 mov ebx, 1 <- 0 // .text:000000018002BAAC mov [rsp+180h+VersionInformation.dwOSVersionInfoSize], 11Ch // .text:000000018002BAB4 mov [rdi], ebx // .text:000000018002BAB6 call cs:__imp_GetVersionExW SignPtr = (PLATFORM_DWORD)(TermSrvBase + 0x2BAA8); b = 0; #else // .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 = (PLATFORM_DWORD)(TermSrvBase + 0x15552); b = 0x90; #endif /* __ARM_ARCH_7 SignPtr = (PLATFORM_DWORD)(TermSrvBase + 0x?); // unknown */ WriteProcessMemory(GetCurrentProcess(), (LPVOID)SignPtr, &b, sizeof(b), &bw); WriteToLog("Patch CDefPolicy::Query\r\n"); #ifdef _WIN64 SignPtr = (PLATFORM_DWORD)(TermSrvBase + 0x2A31A); WriteProcessMemory(GetCurrentProcess(), (LPVOID)SignPtr, &CDefPolicy_Query_eax_rdi, sizeof(CDefPolicy_Query_eax_rdi), &bw); #else SignPtr = (PLATFORM_DWORD)(TermSrvBase + 0x13F08); WriteProcessMemory(GetCurrentProcess(), (LPVOID)SignPtr, &CDefPolicy_Query_eax_esi, sizeof(CDefPolicy_Query_eax_esi), &bw); #endif /* __ARM_ARCH_7 SignPtr = (PLATFORM_DWORD)(TermSrvBase + 0x?); // unknown */ WriteToLog("Hook SLGetWindowsInformationDWORDWrapper\r\n"); #ifdef _WIN64 SignPtr = (PLATFORM_DWORD)(TermSrvBase + 0x21FA8); Jump.MovOp = 0x48; Jump.MovRegArg = 0xB8; Jump.MovArg = (PLATFORM_DWORD)New_Win8SL; Jump.PushRaxOp = 0x50; Jump.RetOp = 0xC3; #else SignPtr = (PLATFORM_DWORD)(TermSrvBase + 0x19559); Jump.PushOp = 0x68; Jump.PushArg = (PLATFORM_DWORD)New_Win8SL; Jump.RetOp = 0xC3; #endif /* __ARM_ARCH_7 SignPtr = (PLATFORM_DWORD)(TermSrvBase + 0x5F934); // hook opcodes? Don't know how to make far jump on ARM platform */ WriteProcessMemory(GetCurrentProcess(), (LPVOID)SignPtr, &Jump, sizeof(FARJMP), &bw); } if (FV.Release == 9200 && FV.Build == 17048) { WriteToLog("Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled\r\n"); #ifdef _WIN64 // .text:0000000180020942 lea rcx, [rsp+180h+VersionInformation] ; lpVersionInformation // .text:0000000180020947 mov ebx, 1 <- 0 // .text:000000018002094C mov [rsp+180h+VersionInformation.dwOSVersionInfoSize], 11Ch // .text:0000000180020954 mov [rdi], ebx // .text:0000000180020956 call cs:__imp_GetVersionExW SignPtr = (PLATFORM_DWORD)(TermSrvBase + 0x20948); b = 0; #else // .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 = (PLATFORM_DWORD)(TermSrvBase + 0x20592); b = 0x90; #endif WriteProcessMemory(GetCurrentProcess(), (LPVOID)SignPtr, &b, sizeof(b), &bw); WriteToLog("Patch CDefPolicy::Query\r\n"); #ifdef _WIN64 SignPtr = (PLATFORM_DWORD)(TermSrvBase + 0x1F206); WriteProcessMemory(GetCurrentProcess(), (LPVOID)SignPtr, &CDefPolicy_Query_eax_rdi, sizeof(CDefPolicy_Query_eax_rdi), &bw); #else SignPtr = (PLATFORM_DWORD)(TermSrvBase + 0x1F408); WriteProcessMemory(GetCurrentProcess(), (LPVOID)SignPtr, &CDefPolicy_Query_eax_esi, sizeof(CDefPolicy_Query_eax_esi), &bw); #endif WriteToLog("Hook SLGetWindowsInformationDWORDWrapper\r\n"); #ifdef _WIN64 SignPtr = (PLATFORM_DWORD)(TermSrvBase + 0x24570); Jump.MovOp = 0x48; Jump.MovRegArg = 0xB8; Jump.MovArg = (PLATFORM_DWORD)New_Win8SL; Jump.PushRaxOp = 0x50; Jump.RetOp = 0xC3; #else SignPtr = (PLATFORM_DWORD)(TermSrvBase + 0x17059); Jump.PushOp = 0x68; Jump.PushArg = (PLATFORM_DWORD)New_Win8SL; Jump.RetOp = 0xC3; #endif WriteProcessMemory(GetCurrentProcess(), (LPVOID)SignPtr, &Jump, sizeof(FARJMP), &bw); } if (FV.Release == 9200 && FV.Build == 21166) { WriteToLog("Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled\r\n"); #ifdef _WIN64 // .text:000000018002BAF2 lea rcx, [rsp+180h+VersionInformation] ; lpVersionInformation // .text:000000018002BAF7 mov ebx, 1 <- 0 // .text:000000018002BAFC mov [rsp+180h+VersionInformation.dwOSVersionInfoSize], 11Ch // .text:000000018002BB04 mov [rdi], ebx // .text:000000018002BB06 call cs:__imp_GetVersionExW SignPtr = (PLATFORM_DWORD)(TermSrvBase + 0x2BAF8); b = 0; #else // .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 = (PLATFORM_DWORD)(TermSrvBase + 0x1557A); b = 0x90; #endif WriteProcessMemory(GetCurrentProcess(), (LPVOID)SignPtr, &b, sizeof(b), &bw); WriteToLog("Patch CDefPolicy::Query\r\n"); #ifdef _WIN64 SignPtr = (PLATFORM_DWORD)(TermSrvBase + 0x2A3B6); WriteProcessMemory(GetCurrentProcess(), (LPVOID)SignPtr, &CDefPolicy_Query_eax_rdi, sizeof(CDefPolicy_Query_eax_rdi), &bw); #else SignPtr = (PLATFORM_DWORD)(TermSrvBase + 0x13F30); WriteProcessMemory(GetCurrentProcess(), (LPVOID)SignPtr, &CDefPolicy_Query_eax_esi, sizeof(CDefPolicy_Query_eax_esi), &bw); #endif WriteToLog("Hook SLGetWindowsInformationDWORDWrapper\r\n"); #ifdef _WIN64 SignPtr = (PLATFORM_DWORD)(TermSrvBase + 0x21FD0); Jump.MovOp = 0x48; Jump.MovRegArg = 0xB8; Jump.MovArg = (PLATFORM_DWORD)New_Win8SL; Jump.PushRaxOp = 0x50; Jump.RetOp = 0xC3; #else SignPtr = (PLATFORM_DWORD)(TermSrvBase + 0x19581); Jump.PushOp = 0x68; Jump.PushArg = (PLATFORM_DWORD)New_Win8SL; Jump.RetOp = 0xC3; #endif WriteProcessMemory(GetCurrentProcess(), (LPVOID)SignPtr, &Jump, sizeof(FARJMP), &bw); } } } if (Ver == 0x0603) { // Windows 8.1 // uses SL Policy internal inline code if (GetModuleCodeSectionInfo(hTermSrv, &TermSrvBase, &TermSrvSize)) { // Patch functions: // CEnforcementCore::GetInstanceOfTSLicense // CSessionArbitrationHelper::IsSingleSessionPerUserEnabled // CDefPolicy::Query // Hook function: // CSLQuery::Initialize if (FV.Release == 9431 && FV.Build == 0) { WriteToLog("Patch CEnforcementCore::GetInstanceOfTSLicense\r\n"); #ifdef _WIN64 // .text:000000018009F713 call ?IsLicenseTypeLocalOnly@CSLQuery@@SAJAEAU_GUID@@PEAH@Z ; CSLQuery::IsLicenseTypeLocalOnly(_GUID &,int *) // .text:000000018009F718 test eax, eax // .text:000000018009F71A js short loc_18009F73B // .text:000000018009F71C cmp [rsp+48h+arg_18], 0 // .text:000000018009F721 jz short loc_18009F73B <- jmp SignPtr = (PLATFORM_DWORD)(TermSrvBase + 0x9F721); #else // .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 = (PLATFORM_DWORD)(TermSrvBase + 0x8A611); #endif b = 0xEB; WriteProcessMemory(GetCurrentProcess(), (LPVOID)SignPtr, &b, sizeof(b), &bw); WriteToLog("Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled\r\n"); #ifdef _WIN64 // .text:00000001800367F3 lea rcx, [rsp+190h+VersionInformation] ; lpVersionInformation // .text:00000001800367F8 mov ebx, 1 <- 0 // .text:00000001800367FD mov [rsp+190h+VersionInformation.dwOSVersionInfoSize], 11Ch // .text:0000000180036805 mov [rdi], ebx // .text:0000000180036807 call cs:__imp_GetVersionExW SignPtr = (PLATFORM_DWORD)(TermSrvBase + 0x367F9); b = 0; #else // .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 = (PLATFORM_DWORD)(TermSrvBase + 0x306A8); b = 0x90; #endif WriteProcessMemory(GetCurrentProcess(), (LPVOID)SignPtr, &b, sizeof(b), &bw); WriteToLog("Patch CDefPolicy::Query\r\n"); #ifdef _WIN64 SignPtr = (PLATFORM_DWORD)(TermSrvBase + 0x350FD); WriteProcessMemory(GetCurrentProcess(), (LPVOID)SignPtr, &CDefPolicy_Query_eax_rcx, sizeof(CDefPolicy_Query_eax_rcx), &bw); #else SignPtr = (PLATFORM_DWORD)(TermSrvBase + 0x2EA25); WriteProcessMemory(GetCurrentProcess(), (LPVOID)SignPtr, &CDefPolicy_Query_eax_ecx, sizeof(CDefPolicy_Query_eax_ecx), &bw); #endif WriteToLog("Hook CSLQuery::Initialize\r\n"); #ifdef _WIN64 SignPtr = (PLATFORM_DWORD)(TermSrvBase + 0x2F9C0); Jump.MovOp = 0x48; Jump.MovRegArg = 0xB8; Jump.MovArg = (PLATFORM_DWORD)New_CSLQuery_Initialize; Jump.PushRaxOp = 0x50; Jump.RetOp = 0xC3; #else SignPtr = (PLATFORM_DWORD)(TermSrvBase + 0x196B0); Jump.PushOp = 0x68; Jump.PushArg = (PLATFORM_DWORD)New_CSLQuery_Initialize; Jump.RetOp = 0xC3; #endif WriteProcessMemory(GetCurrentProcess(), (LPVOID)SignPtr, &Jump, sizeof(FARJMP), &bw); } if (FV.Release == 9600 && FV.Build == 16384) { WriteToLog("Patch CEnforcementCore::GetInstanceOfTSLicense\r\n"); #ifdef _WIN64 // .text:000000018008181F cmp [rsp+48h+arg_18], 0 // .text:0000000180081824 jz loc_180031DEF <- nop + jmp SignPtr = (PLATFORM_DWORD)(TermSrvBase + 0x81824); b = 0x90; WriteProcessMemory(GetCurrentProcess(), (LPVOID)SignPtr, &b, sizeof(b), &bw); SignPtr = (PLATFORM_DWORD)(TermSrvBase + 0x81825); b = 0xE9; WriteProcessMemory(GetCurrentProcess(), (LPVOID)SignPtr, &b, sizeof(b), &bw); #else // .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 = (PLATFORM_DWORD)(TermSrvBase + 0xA2729); b = 0xEB; WriteProcessMemory(GetCurrentProcess(), (LPVOID)SignPtr, &b, sizeof(b), &bw); #endif WriteToLog("Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled\r\n"); #ifdef _WIN64 // .text:000000018002023B lea rcx, [rsp+190h+VersionInformation] ; lpVersionInformation // .text:0000000180020240 mov ebx, 1 <- 0 // .text:0000000180020245 mov [rsp+190h+VersionInformation.dwOSVersionInfoSize], 11Ch // .text:000000018002024D mov [rdi], ebx // .text:000000018002024F call cs:__imp_GetVersionExW SignPtr = (PLATFORM_DWORD)(TermSrvBase + 0x20241); b = 0; #else // .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 = (PLATFORM_DWORD)(TermSrvBase + 0x18028); b = 0x90; #endif WriteProcessMemory(GetCurrentProcess(), (LPVOID)SignPtr, &b, sizeof(b), &bw); WriteToLog("Patch CDefPolicy::Query\r\n"); #ifdef _WIN64 SignPtr = (PLATFORM_DWORD)(TermSrvBase + 0x57829); WriteProcessMemory(GetCurrentProcess(), (LPVOID)SignPtr, &CDefPolicy_Query_eax_rcx, sizeof(CDefPolicy_Query_eax_rcx), &bw); #else SignPtr = (PLATFORM_DWORD)(TermSrvBase + 0x16115); WriteProcessMemory(GetCurrentProcess(), (LPVOID)SignPtr, &CDefPolicy_Query_eax_ecx, sizeof(CDefPolicy_Query_eax_ecx), &bw); #endif WriteToLog("Hook CSLQuery::Initialize\r\n"); #ifdef _WIN64 SignPtr = (PLATFORM_DWORD)(TermSrvBase + 0x554C0); Jump.MovOp = 0x48; Jump.MovRegArg = 0xB8; Jump.MovArg = (PLATFORM_DWORD)New_CSLQuery_Initialize; Jump.PushRaxOp = 0x50; Jump.RetOp = 0xC3; #else SignPtr = (PLATFORM_DWORD)(TermSrvBase + 0x1CEB0); Jump.PushOp = 0x68; Jump.PushArg = (PLATFORM_DWORD)New_CSLQuery_Initialize; Jump.RetOp = 0xC3; #endif WriteProcessMemory(GetCurrentProcess(), (LPVOID)SignPtr, &Jump, sizeof(FARJMP), &bw); } if (FV.Release == 9600 && FV.Build == 17095) { WriteToLog("Patch CEnforcementCore::GetInstanceOfTSLicense\r\n"); #ifdef _WIN64 // .text:00000001800B914B call ?IsLicenseTypeLocalOnly@CSLQuery@@SAJAEAU_GUID@@PEAH@Z ; CSLQuery::IsLicenseTypeLocalOnly(_GUID &,int *) // .text:00000001800B9150 test eax, eax // .text:00000001800B9152 js short loc_1800B9173 // .text:00000001800B9154 cmp [rsp+48h+arg_18], 0 // .text:00000001800B9159 jz short loc_1800B9173 <- jmp SignPtr = (PLATFORM_DWORD)(TermSrvBase + 0xB9159); #else // .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 = (PLATFORM_DWORD)(TermSrvBase + 0xA36D1); #endif b = 0xEB; WriteProcessMemory(GetCurrentProcess(), (LPVOID)SignPtr, &b, sizeof(b), &bw); WriteToLog("Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled\r\n"); #ifdef _WIN64 // .text:0000000180021823 lea rcx, [rsp+190h+VersionInformation] ; lpVersionInformation // .text:0000000180021828 mov ebx, 1 <- 0 // .text:000000018002182D mov [rsp+190h+VersionInformation.dwOSVersionInfoSize], 11Ch // .text:0000000180021835 mov [rdi], ebx // .text:0000000180021837 call cs:__imp_GetVersionExW SignPtr = (PLATFORM_DWORD)(TermSrvBase + 0x21829); b = 0; #else // .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 = (PLATFORM_DWORD)(TermSrvBase + 0x36BA9); b = 0x90; #endif WriteProcessMemory(GetCurrentProcess(), (LPVOID)SignPtr, &b, sizeof(b), &bw); WriteToLog("Patch CDefPolicy::Query\r\n"); #ifdef _WIN64 SignPtr = (PLATFORM_DWORD)(TermSrvBase + 0x1F6A1); WriteProcessMemory(GetCurrentProcess(), (LPVOID)SignPtr, &CDefPolicy_Query_eax_rcx, sizeof(CDefPolicy_Query_eax_rcx), &bw); #else SignPtr = (PLATFORM_DWORD)(TermSrvBase + 0x16115); WriteProcessMemory(GetCurrentProcess(), (LPVOID)SignPtr, &CDefPolicy_Query_eax_ecx, sizeof(CDefPolicy_Query_eax_ecx), &bw); #endif WriteToLog("Hook CSLQuery::Initialize\r\n"); #ifdef _WIN64 SignPtr = (PLATFORM_DWORD)(TermSrvBase + 0x3B110); Jump.MovOp = 0x48; Jump.MovRegArg = 0xB8; Jump.MovArg = (PLATFORM_DWORD)New_CSLQuery_Initialize; Jump.PushRaxOp = 0x50; Jump.RetOp = 0xC3; #else SignPtr = (PLATFORM_DWORD)(TermSrvBase + 0x117F1); Jump.PushOp = 0x68; Jump.PushArg = (PLATFORM_DWORD)New_CSLQuery_Initialize; Jump.RetOp = 0xC3; #endif WriteProcessMemory(GetCurrentProcess(), (LPVOID)SignPtr, &Jump, sizeof(FARJMP), &bw); } } } if (Ver == 0x0604) { // Windows 10 // uses SL Policy internal inline code if (GetModuleCodeSectionInfo(hTermSrv, &TermSrvBase, &TermSrvSize)) { // Patch functions: // CEnforcementCore::GetInstanceOfTSLicense // CSessionArbitrationHelper::IsSingleSessionPerUserEnabled // CDefPolicy::Query // Hook function: // CSLQuery::Initialize if (FV.Release == 9841 && FV.Build == 0) { WriteToLog("Patch CEnforcementCore::GetInstanceOfTSLicense\r\n"); #ifdef _WIN64 // .text:0000000180081133 call sub_1800A9048 // .text:0000000180081138 test eax, eax // .text:000000018008113A js short loc_18008115B // .text:000000018008113C cmp [rsp+58h+arg_18], 0 // .text:0000000180081141 jz short loc_18008115B <- jmp SignPtr = (PLATFORM_DWORD)(TermSrvBase + 0x81141); #else // .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 = (PLATFORM_DWORD)(TermSrvBase + 0x956A8); #endif b = 0xEB; WriteProcessMemory(GetCurrentProcess(), (LPVOID)SignPtr, &b, sizeof(b), &bw); WriteToLog("Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled\r\n"); #ifdef _WIN64 // .text:0000000180012153 lea rcx, [rsp+190h+VersionInformation] ; lpVersionInformation // .text:0000000180012158 mov ebx, 1 <- 0 // .text:000000018001215D mov [rsp+190h+VersionInformation.dwOSVersionInfoSize], 11Ch // .text:0000000180012165 mov [rdi], ebx // .text:0000000180012167 call cs:GetVersionExW SignPtr = (PLATFORM_DWORD)(TermSrvBase + 0x12159); b = 0; #else // .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 = (PLATFORM_DWORD)(TermSrvBase + 0x30125); b = 0x90; #endif WriteProcessMemory(GetCurrentProcess(), (LPVOID)SignPtr, &b, sizeof(b), &bw); WriteToLog("Patch CDefPolicy::Query\r\n"); #ifdef _WIN64 SignPtr = (PLATFORM_DWORD)(TermSrvBase + 0xC125); WriteProcessMemory(GetCurrentProcess(), (LPVOID)SignPtr, &CDefPolicy_Query_eax_rcx, sizeof(CDefPolicy_Query_eax_rcx), &bw); #else SignPtr = (PLATFORM_DWORD)(TermSrvBase + 0x3B989); WriteProcessMemory(GetCurrentProcess(), (LPVOID)SignPtr, &CDefPolicy_Query_eax_ecx, sizeof(CDefPolicy_Query_eax_ecx), &bw); #endif WriteToLog("Hook CSLQuery::Initialize\r\n"); #ifdef _WIN64 SignPtr = (PLATFORM_DWORD)(TermSrvBase + 0x1EA50); Jump.MovOp = 0x48; Jump.MovRegArg = 0xB8; Jump.MovArg = (PLATFORM_DWORD)New_CSLQuery_Initialize; Jump.PushRaxOp = 0x50; Jump.RetOp = 0xC3; #else SignPtr = (PLATFORM_DWORD)(TermSrvBase + 0x46A68); Jump.PushOp = 0x68; Jump.PushArg = (PLATFORM_DWORD)New_CSLQuery_Initialize; Jump.RetOp = 0xC3; #endif WriteProcessMemory(GetCurrentProcess(), (LPVOID)SignPtr, &Jump, sizeof(FARJMP), &bw); } } } WriteToLog("resume\r\n"); SetThreadsState(true); return; } void WINAPI ServiceMain(DWORD dwArgc, LPTSTR *lpszArgv) { WriteToLog("> ServiceMain\r\n"); if (!AlreadyHooked) Hook(); if (_ServiceMain != NULL) _ServiceMain(dwArgc, lpszArgv); } void WINAPI SvchostPushServiceGlobals(void *lpGlobalData) { WriteToLog("> SvchostPushServiceGlobals\r\n"); if (!AlreadyHooked) Hook(); if (_SvchostPushServiceGlobals != NULL) _SvchostPushServiceGlobals(lpGlobalData); }