Как получить SID текущего сеанса?
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 29.12.19 17:20
Оценка:
Во всех найденных примерах, начиная с родного от MS, предлагается применять GetTokenInformation к маркеру, полученному от OpenProcessToken. Таким образом можно получить пользователя, от имени которого создан процесс, но не пользователя, которому принадлежит текущий сеанс. То есть, в простейшем случае, для процессов, созданных "as administrator", это не работает.

Попробовал применить GetUserObjectInformation к результатам GetProcessWindowStation и OpenInputDesktop — в обоих случаях возвращается какой-то бред, отдаленно похожий на well-known SID:

S-1-5-5-0-607555

Какие еще есть способы? Желательно, чтоб работало под XP, но можно и начиная с Win7.
Re: Как получить SID текущего сеанса?
От: kov_serg Россия  
Дата: 29.12.19 20:04
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>Во всех найденных примерах, начиная с родного от MS, предлагается применять GetTokenInformation к маркеру, полученному от OpenProcessToken. Таким образом можно получить пользователя, от имени которого создан процесс, но не пользователя, которому принадлежит текущий сеанс. То есть, в простейшем случае, для процессов, созданных "as administrator", это не работает.


ЕМ>Попробовал применить GetUserObjectInformation к результатам GetProcessWindowStation и OpenInputDesktop — в обоих случаях возвращается какой-то бред, отдаленно похожий на well-known SID:


ЕМ>S-1-5-5-0-607555


ЕМ>Какие еще есть способы? Желательно, чтоб работало под XP, но можно и начиная с Win7.


А если так попробовать?
using System;
using System.Security.Principal;
using System.Management;

class App {
    static string GetSID() {
        var mos = new ManagementObjectSearcher(
            new ManagementScope("\\\\localhost\\root\\cimv2"),
            new ObjectQuery("SELECT username FROM Win32_ComputerSystem")
        );
        foreach (var mo in mos.Get()) {
            var username = mo["username"].ToString();
            var nta = new NTAccount(username);
            var sid = (SecurityIdentifier)nta.Translate(typeof(SecurityIdentifier));
            return sid.ToString();
        }
        throw new Exception("panic");
    }
    [STAThread]
    static void Main(string[] args) {
        Console.WriteLine(GetSID());
    }
}
Re[2]: Как получить SID текущего сеанса?
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 29.12.19 20:22
Оценка:
Здравствуйте, kov_serg, Вы писали:

_>А если так попробовать?


На "чистом" WinAPI, без залезания в классы WMI — никак?
Re: Как получить SID текущего сеанса?
От: Conr Россия  
Дата: 29.12.19 22:48
Оценка: 10 (1)
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>Во всех найденных примерах, начиная с родного от MS, предлагается применять GetTokenInformation к маркеру, полученному от OpenProcessToken. Таким образом можно получить пользователя, от имени которого создан процесс, но не пользователя, которому принадлежит текущий сеанс. То есть, в простейшем случае, для процессов, созданных "as administrator", это не работает.


ЕМ>Попробовал применить GetUserObjectInformation к результатам GetProcessWindowStation и OpenInputDesktop — в обоих случаях возвращается какой-то бред, отдаленно похожий на well-known SID:


ЕМ>S-1-5-5-0-607555


ЕМ>Какие еще есть способы? Желательно, чтоб работало под XP, но можно и начиная с Win7.

На коленке, без обработки ошибок:
#include <iostream>
#include <Windows.h>
#include <sddl.h> // ConvertSidToStringSidW
#include <wtsapi32.h> // WTSQuerySessionInformation
#pragma comment(lib,"Wtsapi32")

int main()
{
    LPWSTR username;
    DWORD len;
    WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, WTS_CURRENT_SESSION, WTSUserName, &username, &len);

    LPWSTR domain;
    WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, WTS_CURRENT_SESSION, WTSDomainName, &domain, &len);

    SID_NAME_USE sid_type;
    char sid_buffer[1024] = { 0 };
    DWORD sid_len = sizeof(sid_buffer);
    LookupAccountNameW(NULL, username, sid_buffer, &sid_len, domain, &len, &sid_type);

    LPWSTR str = nullptr;
    ConvertSidToStringSidW((PSID)sid_buffer, &str);

    std::wcout << L"SID: " << str << std::endl;

    WTSFreeMemory(username);
    WTSFreeMemory(domain);
    LocalFree(str);
}
Re[3]: Как получить SID текущего сеанса?
От: kov_serg Россия  
Дата: 29.12.19 22:49
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>Здравствуйте, kov_serg, Вы писали:


_>>А если так попробовать?


ЕМ>На "чистом" WinAPI, без залезания в классы WMI — никак?

Не ну можно конечно и грязно сделать:
#include <windows.h>
#include <sddl.h>
#include <stdio.h>

static void GetWindowSID(HWND wnd,char *dst,int dst_size) {
    enum { buf_size=256 }; char buf[buf_size];
    HANDLE pr=0,token=0; DWORD pid=0; BOOL res; char *sid=0;

    *dst=0;
    GetWindowThreadProcessId(wnd,&pid);                            if (!pid) goto leave;
    pr=OpenProcess(PROCESS_QUERY_INFORMATION,0,pid);               if (!pr)  goto leave;
    res=OpenProcessToken(pr,TOKEN_QUERY,&token);                   if (!res) goto leave;
    res=GetTokenInformation(token,TokenUser,buf,buf_size,0);       if (!res) goto leave;
    res=ConvertSidToStringSidA(((PTOKEN_USER)buf)->User.Sid,&sid); if (!res) goto leave;
leave:
    if (sid) {
        strncpy(dst,sid,dst_size); 
        LocalFree(sid);
    }
    if (token) CloseHandle(token);
    if (pr) CloseHandle(pr);
}
static BOOL CALLBACK enum_window(HWND wnd, LPARAM prm) {
    *(HWND*)prm=wnd;
    return FALSE;
}
static char* GetSID(char* dst,int dst_size) {
    HWND wnd=0; 
    EnumWindows(enum_window,(LPARAM)&wnd);
    GetWindowSID(wnd,dst,dst_size);
    return dst;
}
int main(int argc,char** argv) {
    enum { buf_size=64 }; char buf[buf_size];
    printf("%s\n",GetSID(buf,buf_size));
    return 0;
}

Но есть нюансы
Re[2]: Как получить SID текущего сеанса?
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 30.12.19 09:26
Оценка:
Здравствуйте, Conr, Вы писали:

C>На коленке, без обработки ошибок:


Спасибо, работает. Хотя я уже сообразил сделать через GetShellWindow/GetWindowThreadProcessId. Насколько вероятна ситуация, в которой работают оконные приложения, но GetShellWindow возвращает нуль?
Re[4]: Как получить SID текущего сеанса?
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 30.12.19 09:27
Оценка:
Здравствуйте, kov_serg, Вы писали:

_>Не ну можно конечно и грязно сделать:


И определять методом голосования? Тогда уж проще через GetShellWindow/GetWindowThreadProcessId.
Re[3]: Как получить SID текущего сеанса?
От: Conr Россия  
Дата: 30.12.19 09:42
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>Спасибо, работает. Хотя я уже сообразил сделать через GetShellWindow/GetWindowThreadProcessId. Насколько вероятна ситуация, в которой работают оконные приложения, но GetShellWindow возвращает нуль?

Достаточно "уронить" explorer.exe. Или если установлен нестандартный shell, который не полностью реализует DDE запросы.

В Chromium когда-то давно из-за использования GetShellWindow были проблемы с отрисовкой: https://bugs.chromium.org/p/chromium/issues/detail?id=169652.
Re[4]: Как получить SID текущего сеанса?
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 30.12.19 11:23
Оценка:
Здравствуйте, Conr, Вы писали:

C>Достаточно "уронить" explorer.exe.


В этом случае он автоматически перезапускается.

C>Или если установлен нестандартный shell, который не полностью реализует DDE запросы.


Это уже маловероятно. Да и у меня на это ничего важного не завязано, для 99% сгодится, а в остальных никто и не заметит.
Re[4]: Как получить SID текущего сеанса?
От: ononim  
Дата: 30.12.19 14:24
Оценка:
ЕМ>>Спасибо, работает. Хотя я уже сообразил сделать через GetShellWindow/GetWindowThreadProcessId. Насколько вероятна ситуация, в которой работают оконные приложения, но GetShellWindow возвращает нуль?
C>Достаточно "уронить" explorer.exe. Или если установлен нестандартный shell, который не полностью реализует DDE запросы.
Windows terminal services тоже можно отключить.
Как много веселых ребят, и все делают велосипед...
Re[5]: Как получить SID текущего сеанса?
От: ononim  
Дата: 30.12.19 14:33
Оценка:
C>>Или если установлен нестандартный shell, который не полностью реализует DDE запросы.
ЕМ>Это уже маловероятно. Да и у меня на это ничего важного не завязано, для 99% сгодится, а в остальных никто и не заметит.
OpenDesktop("default",...) / GetUserObjectSecurity (owner)
Как много веселых ребят, и все делают велосипед...
Re[5]: Как получить SID текущего сеанса?
От: Lonely Dog Россия  
Дата: 06.01.20 07:15
Оценка:
Здравствуйте, ononim, Вы писали:

ЕМ>>>Спасибо, работает. Хотя я уже сообразил сделать через GetShellWindow/GetWindowThreadProcessId. Насколько вероятна ситуация, в которой работают оконные приложения, но GetShellWindow возвращает нуль?

C>>Достаточно "уронить" explorer.exe. Или если установлен нестандартный shell, который не полностью реализует DDE запросы.
O>Windows terminal services тоже можно отключить.
Можно, но АПИ останется рабочим. Ведь начиная с висты сервисы работают в отдельной терм. сессии.
Re[2]: Как получить SID текущего сеанса?
От: Lonely Dog Россия  
Дата: 06.01.20 07:17
Оценка:
Здравствуйте, Conr, Вы писали:

C>На коленке, без обработки ошибок:

А еще короче должно быть через WTSQueryUserToken (если права есть)
Re[6]: Как получить SID текущего сеанса?
От: ononim  
Дата: 06.01.20 10:02
Оценка:
O>>Windows terminal services тоже можно отключить.
LD>Можно, но АПИ останется рабочим.
Но не на ХР
Как много веселых ребят, и все делают велосипед...
Re[6]: Как получить SID текущего сеанса?
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 06.01.20 22:24
Оценка:
Здравствуйте, ononim, Вы писали:

O>OpenDesktop("default",...) / GetUserObjectSecurity (owner)


Там еще не лучше. И для OpenDesktop("default",...), и для OpenInputDesktop, и для GetProcessWindowStation выдаются одинаковые "SID":

GetUserObjectInformation: S-1-5-5-0-599500
GetUserObjectSecurity: S-1-0x8014000000

Это что вообще за идентификаторы такие?
Re[7]: Как получить SID текущего сеанса?
От: Lonely Dog Россия  
Дата: 07.01.20 09:55
Оценка:
Здравствуйте, ononim, Вы писали:

O>>>Windows terminal services тоже можно отключить.

LD>>Можно, но АПИ останется рабочим.
O>Но не на ХР
Разве? Мне казалось, там это всегда работает в отличии от windows 2000.
Re[8]: Как получить SID текущего сеанса?
От: ononim  
Дата: 07.01.20 20:52
Оценка:
O>>>>Windows terminal services тоже можно отключить.
LD>>>Можно, но АПИ останется рабочим.
O>>Но не на ХР
LD>Разве? Мне казалось, там это всегда работает в отличии от windows 2000.
Не уверен, но вроде именно на ХР оно не работало, в те времена когда я ето апи щупал впервые 2000я уже была не актуальна (для меня). И у меня оно не работало, так как я отрубал терминал сервисы нафиг
Как много веселых ребят, и все делают велосипед...
Re[7]: Как получить SID текущего сеанса?
От: ononim  
Дата: 07.01.20 20:54
Оценка: 12 (1) :)
O>>OpenDesktop("default",...) / GetUserObjectSecurity (owner)
ЕМ>Там еще не лучше. И для OpenDesktop("default",...), и для OpenInputDesktop, и для GetProcessWindowStation выдаются одинаковые "SID":
ЕМ>GetUserObjectInformation: S-1-5-5-0-599500
ЕМ>GetUserObjectSecurity: S-1-0x8014000000
А ну сори, написал, не проверив на винде.

ЕМ>Это что вообще за идентификаторы такие?

SID: S-1-5-5-X-Y
Название: Сеанс входа в систему
Описание: Сеанс входа в систему. Значения X и Y для этих идентификаторов SID меняются в каждом сеансе.

(c) https://support.microsoft.com/ru-ru/help/243330/well-known-security-identifiers-in-windows-operating-systems
Получается что это и есть, самый что ни на есть "SID текущего сеанса", как тебе хотелось. Бойся своих желаний
Как много веселых ребят, и все делают велосипед...
Отредактировано 07.01.2020 20:57 ononim . Предыдущая версия .
Re[8]: Как получить SID текущего сеанса?
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 07.01.20 21:56
Оценка:
Здравствуйте, ononim, Вы писали:

O>SID: S-1-5-5-X-Y

O>Название: Сеанс входа в систему

Блин, а я искал по S-1-5-5-0 (у мены там везде нуль). Спасибо!

O>Получается что это и есть, самый что ни на есть "SID текущего сеанса", как тебе хотелось. Бойся своих желаний


Да уж.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.