In part 1 I’ve showed how to get rid of some terminal server restrictions on Windows xp x64. But there are still some problems:

1) You cannot connect to the localhost (127.0.0.1) (but can to 127.a.b.c, where a,b,c in [0..255] (except 127.0.0.0 and 127.255.255.255)).

When you’re connecting to remote server, Remote Desktop Connection (mstsc.exe) checks through mtscax.dll that you’re connecting to your own address, connections are only allowed and you’re in the server mode. If this is not true, the connection is denied, usually with this message: ConsoleFailed. The logic of checking is the same: call gethostbyname for server name and check if it’s not equal to 127.0.0.1. So, we can use a very simple patch: find and replace 7F 00 00 01 (127.0.0.1) with, for example, some invalid network address, like FF FF FF FF (255.255.255.255).

It’s working for all known version of mstscax.dll (from 5.1 to Windows 7; version 5.0, which is shipped with Windows 2000 server, doesn’t have this restriction at all).

2) When FUS (Fast User Switching) is active, you’re getting some ‘strange’ results when connecting via RDP: when you press CAD (Ctrl+Alt+Del), Task Manager will popup; if you try to lock your workstation, for example, by calling LockWorkStation API, it will just disconnect your session. This is default behavior of Windows XP; let’s see what we can do.

Msgina.dll has an undocumented function, exported by number 3, named ShellIsFriendlyUIActive.

It’s a wrapper for function

which is used to determine if we’re displaying welcome screen or not. In turn, function calls

then

What if we’ll overwrite one of them to return true if we’re in RDP session and are active, and false overwise? Let’s write this function:

If we compile this function to x64 code, we’ll get the assembler code like below:

.text:0000000140001170
.text:0000000140001170
; =============== S U B R O U T I N E =======================================
.text:0000000140001170
.text:0000000140001170
.text:0000000140001170
; bool IsRpdSessionActive(void)
.text:0000000140001170 ?IsRpdSessionActive@@YA_NXZ proc near ; DATA XREF: main+131o
.text:0000000140001170 ; .pdata:000000014000400Co
.text:0000000140001170
.text:0000000140001170
var_18 = dword ptr -18h
.text:0000000140001170 var_10 = qword ptr -10h
.text:0000000140001170 arg_0 = dword ptr 8
.text:0000000140001170 arg_8 = byte ptr 10h
.text:0000000140001170
.text:0000000140001170
48 83 EC 38 sub rsp, 38h
.text:0000000140001174 B9 00 10 00 00 mov ecx, 1000h ; nIndex
.text:0000000140001179 FF 15 D1 0F 00 00 call cs:__imp_GetSystemMetrics
.text:000000014000117F 85 C0 test eax, eax
.text:0000000140001181 74 3A jz short loc_1400011BD
.text:0000000140001183 48 8D 44 24 48 lea rax, [rsp+38h+arg_8]
.text:0000000140001188 4C 8D 4C 24 40 lea r9, [rsp+38h+arg_0]
.text:000000014000118D 41 B8 25 00 00 00 mov r8d, 25h
.text:0000000140001193 48 89 44 24 28 mov [rsp+38h+var_10], rax
.text:0000000140001198 83 CA FF or edx, 0FFFFFFFFh
.text:000000014000119B 33 C9 xor ecx, ecx
.text:000000014000119D C7 44 24 20 04 00 00 00 mov [rsp+38h+var_18], 4
.text:00000001400011A5 FF 15 B5 0F 00 00 call cs:__imp_WinStationQueryInformationW
.text:00000001400011AB 84 C0 test al, al
.text:00000001400011AD 74 0E jz short loc_1400011BD
.text:00000001400011AF 83 7C 24 40 00 cmp [rsp+38h+arg_0], 0
.text:00000001400011B4 75 07 jnz short loc_1400011BD
.text:00000001400011B6 B0 01 mov al, 1
.text:00000001400011B8 48 83 C4 38 add rsp, 38h
.text:00000001400011BC C3 retn
.text:00000001400011BD ; —————————————————————————
.text:00000001400011BD
.text:00000001400011BD
loc_1400011BD: ; CODE XREF: IsRpdSessionActive(void)+11j
.text:00000001400011BD ; IsRpdSessionActive(void)+3Dj …
.text:00000001400011BD 32 C0 xor al, al
.text:00000001400011BF 48 83 C4 38 add rsp, 38h
.text:00000001400011C3 C3 retn
.text:00000001400011C3 ?IsRpdSessionActive@@YA_NXZ endp
.text:00000001400011C3 .text:00000001400011C3 ; —————————————————————————

So we can replace the function, for example CSystemSettings::IsNetwareActive with our one (if we’re not using Netware, which is a pretty rare case:-) ). Since our code is address independent (we can safely place it in any place), we only need to correct the call addresses of GetSystemMetrics and WinStationQueryInformationW, because they are located at other addresses in msgina.dll

Now, when we press CAD in RDP session, we’ll see the screen like this:
XPx64RdpLockScreen
while in console sessions FUS screen will be working and looking as usual.

Windows XP x64 SP2 Msgina FUS RDP Patch (2911 downloads )

Please note that this patch is for msgina.dll from Windows XP x64 SP2 build 5.2.3790.3959 EXACTLY. If you have other version of msgina.dll, you’ll have to repeat all of these steps and create the patch yourself!!!

Of course, to apply the patches you need to follow the same patching procedure which has described in part 1