Milyen címet jelent a Windows egy RDP-munkamenethez?
A WTS API jelentett ügyfélcímet ad vissza egy RDP-munkamenethez, a rendszerleíró adatbázis pedig nem. Kérdezze le a megfelelő munkamenet-azonosítót, és dekódolja helyesen az IPv4-et vagy az IPv6-ot.
Egy RDP-munkamenetnek ügyfélcím kell, és a kézenfekvő források nem értenek egyet. A CLIENTNAME számítógépnevet ad, a rendszerleíró adatbázis más munkamenetek értékeit tartalmazza, a socket túloldala pedig lehet átjáró- vagy NAT-cím az ügyfél helyett. A Windows valóban közzétesz munkamenetenként egy jelentett ügyfélcímet, de a megfelelő munkamenetet kell kérdeznie, és helyesen kell dekódolnia a választ.
Rögzítse a keresést egyetlen munkamenethez
A munkamenettel kezdje, ne a személlyel. Egy Windows RDP-gazdagép több munkamenetet is hordozhat egy fiókhoz, és az újracsatlakozás előtt látott cím már nem feltétlenül felel meg az élő kapcsolatnak. Jegyezze fel együtt a munkamenet-azonosítót, a felhasználót és az észlelés idejét. A munkamenet-azonosító az a kulcs, amelyet az API elvár, és ez az az érték, amely megakadályozza két munkamenet összekeverését.
A gazdagépen a telepített munkamenet-eszközök felsorolják, mi létezik; a felügyeleti nézetet csak akkor használja, ha jogosult rá. A kiválasztott azonosítót közvetlenül a lekérdezés előtt erősítse meg, mert az újrahasznosított azonosító más munkamenet adatait adja vissza.
qwinsta
Hívja meg a WTSQuerySessionInformationW-t ehhez az azonosítóhoz
A Terminal Services API a 14-es információosztállyal válaszol a kérdésre, WTSClientAddress. Windows alatt egy kis ctypes-burkoló elegendő, és elkerüli egy másik felhasználó hive-jának olvasását. Az alábbi kód explicit munkamenet-azonosítót vesz át, és a helyi gazdagépet kérdezi.
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)
Adja át az imént ellenőrzött egész munkamenet-azonosítót, és tartsa meg a null szerverfogantyút a helyi géphez. A sikertelen hívást hibaként kezelje, ne hiányzó címként, mert a kettő különböző következtetésekhez vezet. Egy másik felhasználó munkamenetének lekérdezése a megfelelő Query Information engedélyt igényli, ezért futtassa az eszközt olyan fiók alatt, amely megkapta, ne emeljen jogosultságot ad hoc módon. A visszaadott puffer az API-hoz tartozik, és akkor is fel kell szabadítani, ha a dekódolás meghiúsul.
Dekódolja a családot, majd szabadítsa fel a puffert
A struktúra nem IP-karakterlánc. A család mezője dönti el, hogyan kell olvasni a húsz címbytét: az IPv4 a kettes eltolásnál kezdődik, az IPv6 viszont a nulla eltolásnál. A nem meghatározott cím azt jelenti, hogy az ügyfél nem jelentett egyet sem, ami nem ugyanaz, mint az üres karakterlánc. A Remote Desktop Gateway kapcsolatok dokumentáltan olyan eset, amikor a cím nem érhető el, ezért az átjárón keresztüli munkamenet semmi hasznosat nem jelent az ügyfél valódi címéről. Ilyenkor a korrelációnak az átjáró saját nyilvántartásaira kell átkerülnie.
Hibakeresés közben nyomtassa ki a családot a cím mellett, mert a kettő közötti eltérés a szokásos oka egy hihető, de hibás értéknek. Szabadítsa fel a puffert a WTSFreeMemory hívással egy finally blokkban, hogy egy kivétel ne szivárogtathassa el.
Válassza el a jelentett címet a bizonyítéktól
A jelentett ügyfélcím az ügyfél által szolgáltatott állítás, nem megbízható megfigyelés. Nem a TCP túloldala, nem a VPN-átjáró bérleti táblázata, és nem az ügyfél nyilvános címe. Amikor a valódi kérdés az, melyik VPN-bérlet tartozik egy személyhez, akkor ugyanabban az időben korrelálja a VPN-kiszolgáló hitelesített munkamenet-rekordját. Amikor a kérdés az, melyik forrás érte el a figyelőt, olvassa a kapcsolati táblázatot vagy az engedélyezett kiszolgálóoldali naplókat.
Tartsa ezeket az értékeket külön címkézve minden támogatóeszközben. A hiányzó WTS-eredmény maradjon hiányzó, ahelyett hogy egy másik munkamenet tetszőleges rendszerleíró értékére esne vissza. Naplózza a munkamenet-azonosítót a cím mellett, mert ugyanaz a felhasználó újracsatlakozhat és új értéket kaphat. Sem az ügyfélnév, sem a jelentett cím nem elégséges bizonyíték a hozzáférés megadásához.