Информация об изменениях

Сообщение Re[7]: Загрузка профиля пользователя от 05.05.2017 20:57

Изменено 05.05.2017 21:02 ononim

Re[7]: Загрузка профиля пользователя
S>NetUserGetInfo показывает, что нет у пользователя roaming profile (пустое поле usri4_profile).
S>Прицепился Windbg к psexecsvc: в структуре PROFILEINFO заполняются только dwSize и lpUserName.
S>Да и вообще, windbg показывает в psexecsvc вроде бы всё то же, что и в моем сервисе, но вот путь в результате получается другой
Еще момент есть с токенами и процессами тонкий, не знаю правда может ли вызвать такие проблемы и не уверен подвержена ли ему ета LogonUserExExW. Момент состоит в том, что токен и процесс — сам по себе объект ядра, защищенный DACL'ом. И когда они создаются — они получают себе овнером — того кто их создает, и дефолтовый SD/DACL разрешает доступ только этому овнеру. И ежели токен был создан system'ом, то в результате доступ к нему имеет только SYSTEM. А тот юзер который этот токен представляет — фиг. На практике ето вылазит в виде забавного access denied'а от OpenProcessToken(GetCurrentProcess() вызванного из процесса, который был стартован с таким токеном. Аналогичный эффект имеет место с процессами. Вызывая CreateProcessAsUserW с нулевыми lpProcessAttributes/lpThreadAttributes — создаются объекты процесса и потока, владельцами которых является не юзер, под которым их запустили, а юзер, который их запустил, то есть — систем. Это в свою очередь выражается в том что OpenProcess(GetCurrentProcessId() и OpenThread(GetCurrentThreadId) такого процесса говорит access denied

Лечиться все созданием security descriptor'a, который разрешает доступ к объекту данному юзеру и созданием токена и процесса/потока с испольованием этого SD в аргументах SECURITY_ATTRIBUTES:
DuplicateTokenEx(token, MAXIMUM_ALLOWED, lpTokenAttributes, SecurityIdentification, TokenPrimary, &new_token);
CreateProcessAsUserW(new_token, .. lpProcessAttribute, lpThreadAttributes.. )


Можно попробовать проще — проимперсонейтив нужного юзера:
ImpersonateLoggedOnUser(token)
DuplicateTokenEx(token, MAXIMUM_ALLOWED, NULL, SecurityIdentification, TokenPrimary, &new_token);
CreateProcessAsUserW(new_token, .. NULL, NULL.. )
RevertToSelf()

логика такая, что объекты получают SD согласно _эффективному_ токену. Так что если проимперсонировать юзера и вызвать DuplicateTokenEx — то новый токен будет создан с SD, разрешающему доступ этому юзеру. Но боюсь что CreateProcessAsUserW обломается обнаружив отсутствие SE_ASSIGN_PRIMARY_TOKEN у вызывающего потока. А может додумается проверить привилегию у процесса и не обломается. Ваш код — вам и ковыряться..
Re[7]: Загрузка профиля пользователя
S>NetUserGetInfo показывает, что нет у пользователя roaming profile (пустое поле usri4_profile).
S>Прицепился Windbg к psexecsvc: в структуре PROFILEINFO заполняются только dwSize и lpUserName.
S>Да и вообще, windbg показывает в psexecsvc вроде бы всё то же, что и в моем сервисе, но вот путь в результате получается другой
Еще момент есть с токенами и процессами тонкий, не знаю правда может ли вызвать такие проблемы и не уверен подвержена ли ему ета LogonUserExExW. Момент состоит в том, что токен и процесс — сам по себе объект ядра, защищенный DACL'ом. И когда они создаются — они получают себе овнером — того кто их создает, и дефолтовый SD/DACL разрешает доступ только этому овнеру. И ежели токен был создан system'ом, то в результате доступ к нему имеет только SYSTEM. А тот юзер который этот токен представляет — фиг. На практике ето вылазит в виде забавного access denied'а от OpenProcessToken(GetCurrentProcess() вызванного из процесса, который был стартован с таким токеном. Аналогичный эффект имеет место с процессами. Вызывая CreateProcessAsUserW с нулевыми lpProcessAttributes/lpThreadAttributes — создаются объекты процесса и потока, владельцами которых является не юзер, под которым их запустили, а юзер, который их запустил, то есть — систем. Это в свою очередь выражается в том что OpenProcess(GetCurrentProcessId() и OpenThread(GetCurrentThreadId) такого процесса говорит access denied

Лечиться все созданием security descriptor'a, который разрешает доступ к объекту данному юзеру и созданием токена и процесса/потока с испольованием этого SD в аргументах SECURITY_ATTRIBUTES:
DuplicateTokenEx(token, MAXIMUM_ALLOWED, lpTokenAttributes, SecurityIdentification, TokenPrimary, &new_token);
LoadUserProfile(..new_token..)
CreateProcessAsUserW(new_token, .. lpProcessAttribute, lpThreadAttributes.. )


Можно попробовать проще — проимперсонейтив нужного юзера:
ImpersonateLoggedOnUser(token)
DuplicateTokenEx(token, MAXIMUM_ALLOWED, NULL, SecurityIdentification, TokenPrimary, &new_token);
LoadUserProfile(..new_token..)
CreateProcessAsUserW(new_token, .. NULL, NULL.. )
RevertToSelf()

логика такая, что объекты получают SD согласно _эффективному_ токену. Так что если проимперсонировать юзера и вызвать DuplicateTokenEx — то новый токен будет создан с SD, разрешающему доступ этому юзеру. Но боюсь что CreateProcessAsUserW обломается обнаружив отсутствие SE_ASSIGN_PRIMARY_TOKEN у вызывающего потока. А может додумается проверить привилегию у процесса и не обломается. Ваш код — вам и ковыряться..