Ei RDP-økt treng ei klientadresse, og dei openberre kjeldene er ikkje samde. CLIENTNAME gir eit datamaskinnamn, registeret held verdiar frå andre økter, og socket-motparten kan vere ei gateway- eller NAT-adresse i staden for klienten. Windows tilbyr faktisk ei rapportert klientadresse per økt, men du må spørje etter rett økt og dekode svaret rett.

Forankre oppslaget i éi økt

Byrj med økta, ikkje personen. Ein Windows RDP-vert kan bere fleire økter for éin konto, og ei adresse som vart sett før ei attkopling, passar kanskje ikkje lenger til den aktive sambindinga. Noter økt-ID, brukar og observasjonstidspunkt saman. Økt-ID-en er nøkkelen API-et ventar, og det er verdien som hindrar to økter i å bli forveksla.

På verten listar dei installerte øktverktya opp kva som finst; bruk den administrative visninga berre når du har rett til henne. Stadfest den valde ID-en rett før spørjinga, fordi ein gjenbrukt ID returnerer data frå ei anna økt.

qwinsta

Kall WTSQuerySessionInformationW for den ID-en

Terminal Services-API-et svarar på spørsmålet med informasjonsklasse 14, WTSClientAddress. Ei lita ctypes-innpakking er nok på Windows, og ho unngår å lese hive-en til ein annan brukar. Koden nedanfor tek ein eksplisitt økt-ID og spør den lokale verten.

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)

Send heiltals-økt-ID-en du nettopp stadfesta, og hald null-serverhandtaket for den lokale maskina. Handsame eit mislukka kall som ein feil i staden for som ei manglande adresse, fordi dei to fører til ulike konklusjonar. Spørjing om økta til ein annan brukar krev den relevante Query Information-løyva, så køyr verktyet under ein konto som har fått henne, i staden for å eskalere ad hoc. Den returnerte bufferen høyrer til API-et og må frigjerast sjølv når dekodinga mislukkast.

Dekod familien, og frigjer deretter bufferen

Strukturen er ikkje ein IP-streng. Familie-feltet avgjer korleis dei tjue adressebyta blir lesne: IPv4 byrjar ved forskyving to, medan IPv6 byrjar ved forskyving null. Den uspesifiserte adressa tyder at klienten ikkje rapporterte noka, noko som ikkje er det same som ein tom streng. Remote Desktop Gateway-sambindingar er dokumenterte som eit tilfelle der adressa ikkje er tilgjengeleg, så ei gateway-formidla økt rapporterer ingenting nyttig om den verkelege adressa til klienten. Korrelasjonen må då flyttast til gatewayen sine eigne registreringar.

Skriv ut familien ved sida av adressa medan du feilsøkjer, fordi usemje mellom dei to er den vanlege årsaka til ein truverdig men feil verdi. Frigjer bufferen med WTSFreeMemory i ein finally-blokk, slik at eit unntak ikkje lekker han.

Skil den rapporterte adressa frå bevis

Ei rapportert klientadresse er ei fråsegn klienten leverer, ikkje ein påliteleg observasjon. Ho er ikkje TCP-motparten, ikkje leasetabellen til VPN-gatewayen og ikkje den offentlege adressa til klienten. Når det eigentlege spørsmålet er kva VPN-lease som høyrer til ein person, korreler du den autentiserte øktregistreringa til VPN-tenaren samstundes. Når spørsmålet er kva kjelde som nådde lyttaren, les sambindingstabellen eller dei tillatne tenarside-loggene.

Hald desse verdiane skilt merkte i eitkvart støtteverkty. Eit manglande WTS-resultat bør bli verande manglande i staden for å falle tilbake på ein vilkårleg registerverdi frå ei anna økt. Logg økt-ID-en ved sida av adressa, fordi same brukar kan kople til på nytt og få ein ny verdi. Korkje klientnamnet eller den rapporterte adressa er tilstrekkeleg bevis for å gi tilgang.

Relaterte artiklar