RDP sessiyasına müştəri ünvanı lazımdır və aşkar mənbələr razılaşmır. CLIENTNAME kompüter adı verir, qeydiyyat kitabçası başqa sessiyaların dəyərlərini saxlayır, soket qarşı tərəfi isə müştəri deyil, şlüz və ya NAT ünvanı ola bilər. Windows hər sessiya üçün bildirilmiş müştəri ünvanı təqdim edir, amma düzgün sessiyanı sorğulamalı və cavabı düzgün deşifrə etməlisiniz.

Axtarışı bir sessiyaya bağlayın

Şəxslə deyil, sessiya ilə başlayın. Windows RDP hostu bir hesab üçün bir neçə sessiya daşıya bilər və yenidən qoşulmadan əvvəl görünən ünvan artıq canlı əlaqəyə uyğun gəlməyə bilər. Sessiya ID-sini, istifadəçini və müşahidə vaxtını birlikdə qeyd edin. Sessiya ID-si API-nin gözlədiyi açardır və iki sessiyanın qarışdırılmasının qarşısını alan dəyər məhz budur.

Hostda quraşdırılmış sessiya alətləri mövcud olanları sadalayır; inzibati görünüşdən yalnız ona hüququnuz olduqda istifadə edin. Seçilmiş ID-ni sorğudan dərhal əvvəl təsdiqləyin, çünki təkrar istifadə olunan ID başqa sessiyanın məlumatını qaytarır.

qwinsta

Həmin ID üçün WTSQuerySessionInformationW çağırın

Terminal Xidmətləri API-si suala 14-cü məlumat sinfi ilə cavab verir: WTSClientAddress. Windows-da kiçik bir ctypes sarğı kifayətdir və bu, başqa istifadəçinin hive-ını oxumaqdan qaçır. Aşağıdakı kod açıq sessiya ID-si alır və yerli hosta müraciət edir.

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)

Yeni yoxladığınız tam ədəd sessiya ID-sini ötürün və yerli maşın üçün null server tutacağını saxlayın. Uğursuz çağırışı ünvanın olmaması kimi deyil, xəta kimi qəbul edin, çünki ikisi fərqli nəticələrə aparır. Başqa istifadəçinin sessiyasını sorğulamaq müvafiq Query Information icazəsi tələb edir, ona görə aləti ad hoc hüquq artırmaq əvəzinə bu icazənin verildiyi hesab altında işlədin. Qaytarılan bufer API-yə aiddir və deşifrə uğursuz olsa belə azad edilməlidir.

Ailəni deşifrə edin, sonra buferi azad edin

Struktur IP sətri deyil. Onun ailə sahəsi iyirmi ünvan baytının necə oxunacağını müəyyən edir: IPv4 iki ofsetindən başlayır, IPv6 isə sıfır ofsetindən. Təyin edilməmiş ünvan müştərinin ünvan bildirmədiyini ifadə edir və bu, boş sətirlə eyni şey deyil. Remote Desktop Gateway bağlantıları ünvanın mövcud olmadığı hal kimi sənədləşdirilib, buna görə şlüz vasitəsilə keçən sessiya müştərinin həqiqi ünvanı üçün faydalı heç nə bildirmir. Onda korrelyasiya şlüzün öz qeydlərinə keçməlidir.

Sazlama zamanı ailəni ünvanla birlikdə çap edin, çünki ikisi arasındakı uyğunsuzluq inandırıcı lakin səhv dəyərin adi səbəbidir. Buferi finally blokunda WTSFreeMemory ilə azad edin ki, istisna onu sızdırmasın.

Bildirilmiş ünvanı sübutdan ayırın

Bildirilmiş müştəri ünvanı müştərinin təqdim etdiyi bəyanatdır, etibarlı müşahidə deyil. O, TCP qarşı tərəfi deyil, VPN şlüzünün icarə cədvəli deyil və müştərinin ictimai ünvanı deyil. Əsl sual hansı VPN icarəsinin bir şəxsə aid olduğudursa, VPN serverinin autentifikasiya olunmuş sessiya qeydini eyni vaxtda korrelyasiya edin. Sual hansı mənbənin dinləyiciyə çatdığıdırsa, bağlantı cədvəlini və ya icazə verilmiş server tərəfli jurnalları oxuyun.

Bu dəyərləri istənilən dəstək alətində ayrıca işarələnmiş saxlayın. İtmiş WTS nəticəsi başqa sessiyadan götürülmüş ixtiyari qeydiyyat dəyərinə qayıtmaq əvəzinə itmiş olaraq qalmalıdır. Sessiya ID-sini ünvanın yanında jurnala yazın, çünki eyni istifadəçi yenidən qoşulub yeni dəyər ala bilər. Nə müştəri adı, nə də bildirilmiş ünvan giriş vermək üçün kifayət edən sübut deyil.

Əlaqəli məqalələr