Hokker adres rapportearret Windows foar in RDP-sesje?
De WTS-API jout in rapportearre kliïntadres foar ien RDP-sesje, en it register net. Freegje it krekte sesje-ID op en dekodearje IPv4 of IPv6 goed.
In RDP-sesje hat in kliïntadres nedich, en de fanselssprekkende boarnen binne it net iens. CLIENTNAME jout in kompjûternamme, it register hâldt wearden fan oare sesjes, en de socket-tsjinpart kin in gateway- of NAT-adres wêze ynstee fan de kliïnt. Windows biedt wol in rapportearre kliïntadres per sesje, mar jo moatte de krekte sesje freegje en it antwurd goed dekodearje.
Fêstigje it sykjen oan ien sesje
Begjin mei de sesje, net mei de persoan. In Windows RDP-host kin ferskate sesjes foar ien akkount drage, en in adres dat foar in werferbining sjoen is, kin net mear by de libbene keppeling passe. Notearje it sesje-ID, de brûker en de observaasjetiid byinoar. It sesje-ID is de kaai dy’t de API ferwachtet, en it is de wearde dy’t foarkomt dat twa sesjes trochinoar helle wurde.
Op de host listet de ynstalleare sesje-ark op wat der bestiet; brûk de administratyve werjefte allinnich as jo der rjocht op hawwe. Befêstigje it keazen ID fuort foar de oanfraach, want in werbrûkt ID jout de gegevens fan in oare sesje.
qwinsta
Rop WTSQuerySessionInformationW oan foar dat ID
De Terminal Services-API beantwurdet de fraach mei ynformaasjeklasse 14, WTSClientAddress. In lyts ctypes-omhulsel is genôch op Windows, en it foarkomt it lêzen fan in oare brûker syn hive. De koade hjirûnder nimt in eksplisyt sesje-ID en freget de lokale 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)
Jou it hielgetal-sesje-ID troch dat jo krekt befêstige hawwe, en hâld de nul-serverhandgreep foar de lokale masine. Behannelje in mislearre oprop as in flater ynstee fan as in ôfwêzich adres, want de beide liede ta ferskate konklúzjes. It opfreegjen fan in oare brûker syn sesje freget de passende Query Information-tastimming, dus rin it ark ûnder in akkount dat dy krigen hat ynstee fan ad hoc te eskalearjen. De weromjûne buffer heart by de API en moat frijjûn wurde sels as it dekodearjen mislearret.
Dekodearje de famylje en jou dan de buffer frij
De struktuer is gjin IP-string. Syn famyljefjild beslút hoe’t de tweintich adresbytes lêzen wurde: IPv4 begjint by offset twa, wylst IPv6 by offset nul begjint. It net-opjûne adres betsjut dat de kliïnt der gjin ien rapportearre hat, wat net itselde is as in lege string. Remote Desktop Gateway-ferbiningen binne dokumintearre as in gefal wêryn’t it adres net beskikber is, dus in sesje fia in gateway rapportearret neat nuttichs oer it echte adres fan de kliïnt. Korrelaasje moat dan nei de eigen records fan de gateway ferhúzje.
Print de famylje njonken it adres wylst jo debugge, want in misferhâlding tusken de beide is de gewoane oarsaak fan in leauwensweardige mar ferkearde wearde. Jouw de buffer frij mei WTSFreeMemory yn in finally-blok, sadat in útsûndering him net lekje lit.
Skaai it rapportearre adres fan bewiis
In rapportearre kliïntadres is in ferklearring fan de kliïnt, gjin betroubere observaasje. It is net de TCP-tsjinpart, net de lease-tabel fan de VPN-gateway, en net it iepenbiere adres fan de kliïnt. As de echte fraach is hokker VPN-lease by in persoan heart, korrelearje dan tagelyk it autentisearre sesjerekord fan de VPN-server. As de fraach is hokker boarne de listener berikt hat, lês dan de ferbiningstabel of de tastiene server-side logs.
Hâld dizze wearden apart labelle yn elk supportark. In ûntbrekkend WTS-resultaat moat ûntbrekkend bliuwe ynstee fan werom te fallen op in willekeurige registerwearde út in oare sesje. Log it sesje-ID njonken it adres, want deselde brûker kin opnij ferbine en in nije wearde krije. Noch de kliïntnamme noch it rapportearre adres is genôch bewiis om tagong te jaan.