Wéi eng Adress mellt Windows fir eng RDP-Sessioun?
D’WTS-API gëtt eng gemellt Clientadress fir eng RDP-Sessioun zréck, an d’Registrierung net. Frot déi richteg Sessiouns-ID a decodéier IPv4 oder IPv6 richteg.
Eng RDP-Sessioun brauch eng Clientadress, an déi offensichtlech Quellen sinn net eens. CLIENTNAME gëtt e Computernumm, d’Registrierung hält Wäerter aus anere Sessiounen, an de Socket-Géigeniwwer kann eng Gateway- oder NAT-Adress sinn amplaz vum Client. Windows stellt wierklech eng gemellt Clientadress pro Sessioun zur Verfügung, awer Dir musst déi richteg Sessioun froen an d’Äntwert richteg decodéieren.
Verankert d’Sich an enger eenzeger Sessioun
Fänkt mat der Sessioun un, net mat der Persoun. En Windows-RDP-Host kann e puer Sessiounen fir ee Kont droen, an eng Adress, déi virun enger Neiverbindung gesi gouf, passt vläicht net méi zum aktive Link. Notéiert d’Sessiouns-ID, de Benotzer an den Observatiounszäitpunkt zesummen. D’Sessiouns-ID ass de Schlëssel, deen d’API erwaart, an et ass dee Wäert, deen zwee Sessiounen dovun ofhält, verwiesselt ze ginn.
Um Host lëschten déi installéiert Sessiounsinstrumenter op, wat et gëtt; benotzt d’administrativ Vue nëmme wann Dir berechtegt sidd. Bestätegt déi gewielten ID direkt virun der Ufro, well eng recycléiert ID d’Daten vun enger anerer Sessioun zréckgëtt.
qwinsta
Rufft WTSQuerySessionInformationW fir déi ID op
D’Terminal Services-API beäntwert d’Fro mat der Informatiounsklass 14, WTSClientAddress. En klengen ctypes-Wrapper ass op Windows genuch, an en ëmgeet d’Liese vun engem anere Benotzer senger Hive. De Code hei drënner hëlt eng explizit Sessiouns-ID a freet den lokalen Host.
import ctypes
import ipaddress
import socket
from ctypes import wintypes
class WTS_CLIENT_ADDRESS(ctypes.Structure):
_fields_ = [("AddressFamily", wintypes.DWORD),
("Address", ctypes.c_ubyte * 20)]
wts = ctypes.WinDLL("Wtsapi32", use_last_error=True)
query = wts.WTSQuerySessionInformationW
query.argtypes = [wintypes.HANDLE, wintypes.DWORD, ctypes.c_int,
ctypes.POINTER(ctypes.c_void_p), ctypes.POINTER(wintypes.DWORD)]
query.restype = wintypes.BOOL
free = wts.WTSFreeMemory
free.argtypes = [ctypes.c_void_p]
def client_address(session_id):
buf = ctypes.c_void_p()
size = wintypes.DWORD()
if not query(None, session_id, 14, ctypes.byref(buf), ctypes.byref(size)):
raise ctypes.WinError(ctypes.get_last_error())
try:
if size.value < ctypes.sizeof(WTS_CLIENT_ADDRESS):
raise RuntimeError("short WTS buffer")
value = ctypes.cast(buf, ctypes.POINTER(WTS_CLIENT_ADDRESS)).contents
raw = bytes(value.Address)
if value.AddressFamily == socket.AF_INET:
addr = ipaddress.ip_address(raw[2:6])
elif value.AddressFamily == socket.AF_INET6:
addr = ipaddress.ip_address(raw[:16])
else:
return None
return None if addr.is_unspecified else str(addr)
finally:
free(buf)
Gitt d’Sessiouns-ID als Ganzzuel weider, déi Dir just iwwerpréift hutt, a behält de Null-Serverhandle fir déi lokal Maschinn. Behandelt en heelen Opruff als Feeler an net als eng feelend Adress, well déi zwee zu verschiddene Schlussfolgerunge féieren. Fir d’Sessioun vun engem anere Benotzer ze froen, brauch een déi entspriechend Query Information-Berechtegung, also fuerdert den Instrument ënner engem Kont aus, deem se ginn ass, amplaz ad hoc ze eskaléieren. De zréckginnene Puffer gehéiert der API a muss fräiginn ginn och wann d’Decodéierung feelt.
Decodéiert d’Famill, da gitt de Puffer fräi
D’Struktur ass keng IP-Zeechenketten. Hire Familljefeld entscheet, wéi déi zwanzeg Adressbytes gelies ginn: IPv4 fänkt beim Offset zwee un, während IPv6 beim Offset null fänkt un. Déi onbestëmmten Adress bedeit, datt de Client keng gemellt huet, wat net datselwecht ass wéi eng eidel Zeechenketten. Verbindunge iwwer Remote Desktop Gateway sinn als Fall dokumentéiert, an deem d’Adress net disponibel ass, also mellt eng Sessioun iwwer en Gateway näischt Nëtzleches iwwer déi richteg Adress vum Client. D’Korrelatioun muss dann op d’eegen Opzeechnunge vum Gateway wiesselen.
Dréckt d’Famill nieft der Adress aus, während Dir debugg, well eng Ofwäichung tëschent deenen zwee déi üblech Ursaach vun engem plausiblen awer falsche Wäert ass. Gitt de Puffer mat WTSFreeMemory an engem finally-Block fräi, sou datt eng Ausnam en net leckt.
Trennt déi gemellt Adress vum Beweis
Eng gemellt Clientadress ass eng Ausso, déi de Client liwwert, keng verléisslech Observatioun. Et ass net de TCP-Géigeniwwer, net d’Lease-Tabell vum VPN-Gateway an net d’ëffentlech Adress vum Client. Wann déi richteg Fro ass, wéi eng VPN-Lease zu enger Persoun gehéiert, korreléiert gläichzäiteg den authentifizéierte Sessiounsopzeechnung vum VPN-Server. Wann d’Fro ass, wéi eng Quell den Nolauschterer erreecht huet, liest d’Verbindungstabell oder déi erlaabte Server-side Logs.
Halt dës Wäerter an all Supportinstrument getrennt etikettéiert. En feelende WTS-Resultat soll feelend bleiwen, amplaz op e wëllekësche Registrierungswäert aus enger anerer Sessioun zréckzefalen. Logt d’Sessiouns-ID nieft der Adress, well dee selwechte Benotzer sech nei verbinne kann a séier en neie Wäert kritt. Weder den Clientnumm nach déi gemellt Adress si genuch Beweis fir Zougang ze ginn.