ImpersonateLoggedOnUser даёт ошибку 6 (ERROR_INVALID_HANDLE)
От: ruslanv США  
Дата: 30.12.09 04:05
Оценка:
Ребята, подскажите как можно передать security token из одного процесса в другой ? По идее же это объект ядра и работать должно.

У меня два приложения UI и Windows Service, пишу на C#, но в принципе я думаю код будет понятен всем. В UI приложении получаю token так:

        private static bool GetImpersonationToken(out IntPtr token)
        {
            token = IntPtr.Zero;
            IntPtr tempToken;
            if (OpenProcessToken(GetCurrentProcess(), TokenImpersonate | TokenQuery | TokenDuplicate, out tempToken))
            {
                var sa = new SecurityAttributes { bInheritHandle = false };
                sa.Length = Marshal.SizeOf(sa);
                sa.lpSecurityDescriptor = (IntPtr)0;

                // duplicate the token (this is necessary to convert the impersonated token to a primary token)
                return DuplicateTokenEx(
                    tempToken,
                    0x000f01ff /* all access */,
                    ref sa,
                    /* ImpersonationLevel = SecurityImpersonation */2,
                    /* TokenType = TokenImpersonation */ 2,
                    ref token);
            }

            return false;
        }


полученный token перекидываю по named pipe в мой Windows сервис который крутится под пользователем Local System и пытаюсь вызвать на него ImpersonateLoggedOnUser. Получаю ошибку 6, что мой HANDLE корявый. Я пробовал вызвать ImpersonateLoggedOnUser на полученный токен сразу же в том же UI приложении, оно работает.

Заранее спасибо!
Re: ImpersonateLoggedOnUser даёт ошибку 6 (ERROR_INVALID_HAN
От: x64 Россия  
Дата: 30.12.09 18:52
Оценка:
Сначала DuplicateHandle(), потом остальное.
Re[2]: ImpersonateLoggedOnUser даёт ошибку 6 (ERROR_INVALID_
От: ruslanv США  
Дата: 30.12.09 22:33
Оценка:
Здравствуйте, x64, Вы писали:

x64>Сначала DuplicateHandle(), потом остальное.


"Сначала" это где ? На какой HANDLE ?
Re[3]: ImpersonateLoggedOnUser даёт ошибку 6 (ERROR_INVALID_
От: x64 Россия  
Дата: 30.12.09 22:43
Оценка: 3 (1) +2
R>"Сначала" это где ? На какой HANDLE ?

Хендлы уникальны в пределах процесса, а не системы. Ты передаёшь значение хендла из одного процесса в другой, но этого недостаточно, необходимо скопировать сам хендл из таблицы хендлов исходного процесса (в твоём случае, UI-приложение) в таблицу хендлов целевого процесса (в твоём случае, служба). Для этого следует воспользоваться DuplicateHandle(), а для этого, в свою очередь, у тебя должен быть хендл исходного процесса с соответствующими правами. Ну и наконец, полученный в результате копирования хендл уже можно будет использовать в контексте твоего целевого процесса (служба). Что ещё?
Re[4]: ImpersonateLoggedOnUser даёт ошибку 6 (ERROR_INVALID_
От: ruslanv США  
Дата: 31.12.09 00:03
Оценка:
Здравствуйте, x64, Вы писали:

R>>"Сначала" это где ? На какой HANDLE ?


x64>Хендлы уникальны в пределах процесса, а не системы. Ты передаёшь значение хендла из одного процесса в другой, но этого недостаточно, необходимо скопировать сам хендл из таблицы хендлов исходного процесса (в твоём случае, UI-приложение) в таблицу хендлов целевого процесса (в твоём случае, служба). Для этого следует воспользоваться DuplicateHandle(), а для этого, в свою очередь, у тебя должен быть хендл исходного процесса с соответствующими правами. Ну и наконец, полученный в результате копирования хендл уже можно будет использовать в контексте твоего целевого процесса (служба). Что ещё?


Не знал. Спасибо за наводку. Я почему-то полагал что HANDLE уникальны во всей системе.


Я попробовал использовать DuplicateHandle, работает, но эффект не тот который я ожидал. Я сделал так:

1) Из UI приложения передаю в Windows Service handle процесса UI приложения
2) В Windows Service делаю такое

IntPtr tempToken;
IntPtr finalToken = IntPtr.Zero;
if (OpenProcessToken(uiProcessHandle, TOKEN_IMPERSONATE | TOKEN_QUERY | TOKEN_DUPLICATE, out tempToken))
    DuplicateHandle(uiProcessHandle, tempToken, GetCurrentProcess(), out finalToken, 0, false, DuplicateHandleOptions.DuplicateSameAccess);

bool res = ImpersonateLoggedOnUser(finalToken);
if (res)
{
    InstallationManager.Instance.WindowsUsername = Environment.UserName;
    InstallationManager.Instance.WindowsDomain = Environment.UserDomainName;
    RevertToSelf();
}


Т.е. ImpersonateLoggedOnUser то конечно отработало, но имперсонировалось оно в конктесте аккаунта SYSTEM, того в котором крутится Windows Service, а не UI приложение
Re[5]: ImpersonateLoggedOnUser даёт ошибку 6 (ERROR_INVALID_
От: ruslanv США  
Дата: 31.12.09 00:11
Оценка:
Беру свои слова обратно, я в сервис передал значение GetCurrentProcess() = -1 Щас ещё поиграюсь.
Re[4]: ImpersonateLoggedOnUser даёт ошибку 6 (ERROR_INVALID_
От: ruslanv США  
Дата: 31.12.09 01:13
Оценка:
Здравствуйте, x64, Вы писали:

R>>"Сначала" это где ? На какой HANDLE ?


x64>Хендлы уникальны в пределах процесса, а не системы. Ты передаёшь значение хендла из одного процесса в другой, но этого недостаточно, необходимо скопировать сам хендл из таблицы хендлов исходного процесса (в твоём случае, UI-приложение) в таблицу хендлов целевого процесса (в твоём случае, служба). Для этого следует воспользоваться DuplicateHandle(), а для этого, в свою очередь, у тебя должен быть хендл исходного процесса с соответствующими правами. Ну и наконец, полученный в результате копирования хендл уже можно будет использовать в контексте твоего целевого процесса (служба). Что ещё?


Кароче говоря проблему решил. Правда без использования DuplicateHandle т.к. мне пришлось бы гонять между сервисом и приложением несколько значений типа HANDLE процесса сервиса. Порядок действий был таков:

1) из UI приложения в сервис кидаю process id зовя GetProcessId(GetCurrentProcess())
2) в сервисе по этому id делаю

OpenProcess(processAllAccess, false, (uint) uiProcessId)
OpenProcessToken(uiProcess, (uint) TokenAccessLevels.MaximumAllowed, out tempToken)


Видимо т.к. процесс пользовательского приложения я открывал уже в контексте сервиса handles все рабочие и я смог использовать tempToken в ImpersonateLoggedOnUser.

Спасибо за наводку. Позор конечно что я прочитав когда-то Рихтера не знал что HANDLEs уникальны только в рамках процесса.

Спасибо.
Re[5]: ImpersonateLoggedOnUser даёт ошибку 6 (ERROR_INVALID_
От: x64 Россия  
Дата: 31.12.09 01:16
Оценка:
R>1) из UI приложения в сервис кидаю process id зовя GetProcessId(GetCurrentProcess())
R>Позор конечно что я прочитав когда-то Рихтера не знал...

Позор №2: открой для себя GetCurrentProcessId().
Re[6]: ImpersonateLoggedOnUser даёт ошибку 6 (ERROR_INVALID_
От: ruslanv США  
Дата: 31.12.09 01:25
Оценка:
Здравствуйте, x64, Вы писали:

R>>1) из UI приложения в сервис кидаю process id зовя GetProcessId(GetCurrentProcess())

R>>Позор конечно что я прочитав когда-то Рихтера не знал...

x64>Позор №2: открой для себя GetCurrentProcessId().


Сэкономил 12 букв, спасибо
Re: ImpersonateLoggedOnUser даёт ошибку 6 (ERROR_INVALID_HAN
От: Jolly Roger  
Дата: 31.12.09 12:08
Оценка: +1
Здравствуйте, ruslanv, Вы писали:

R>полученный token перекидываю по named pipe в мой Windows сервис который крутится под пользователем Local System и пытаюсь вызвать на него ImpersonateLoggedOnUser.


Хм, стесняюсь спросить, а чем не устроил ImpersonateNamedPipeClient ?
"Нормальные герои всегда идут в обход!"
Re: ImpersonateLoggedOnUser даёт ошибку 6 (ERROR_INVALID_HAN
От: okman Беларусь https://searchinform.ru/
Дата: 31.12.09 20:19
Оценка: -1
Сервисы Windows работают в специальной сессии, это как другая плоскость.
Попробуйте инсталлировать ваш сервис с флагом SERVICE_INTERACTIVE_PROCESS.
Re[5]: ImpersonateLoggedOnUser даёт ошибку 6 (ERROR_INVALID_
От: ononim  
Дата: 02.01.10 19:00
Оценка: +1 -1
R>1) из UI приложения в сервис кидаю process id зовя GetProcessId(GetCurrentProcess())
R>2) в сервисе по этому id делаю
R>
R>OpenProcess(processAllAccess, false, (uint) uiProcessId)
R>OpenProcessToken(uiProcess, (uint) TokenAccessLevels.MaximumAllowed, out tempToken)
R>


Ну и смысл? Если данное действие происходит ради секурити, то вот вам дыра — malicious IPC клиент передает вам не не свой process id, а какого нить системного процесса. И ваш сервис его успешно проимперсонирует.
Для имперсонации клиентов IPC нужно использовать предоставляемые этим самым IPC средства. Для пайпов к примеру вам тут уже правильно говорили это ImpersonateNamedPipeClient .
Как много веселых ребят, и все делают велосипед...
Re[6]: ImpersonateLoggedOnUser даёт ошибку 6 (ERROR_INVALID_
От: ruslanv США  
Дата: 04.01.10 20:57
Оценка: -1
Здравствуйте, ononim, Вы писали:

R>>1) из UI приложения в сервис кидаю process id зовя GetProcessId(GetCurrentProcess())

R>>2) в сервисе по этому id делаю
R>>
R>>OpenProcess(processAllAccess, false, (uint) uiProcessId)
R>>OpenProcessToken(uiProcess, (uint) TokenAccessLevels.MaximumAllowed, out tempToken)
R>>


O>Ну и смысл? Если данное действие происходит ради секурити, то вот вам дыра — malicious IPC клиент передает вам не не свой process id, а какого нить системного процесса. И ваш сервис его успешно проимперсонирует.

O>Для имперсонации клиентов IPC нужно использовать предоставляемые этим самым IPC средства. Для пайпов к примеру вам тут уже правильно говорили это ImpersonateNamedPipeClient .

По поводу ImpersonateNamedPipeClient мне тут не говорили (кстати до named pipe handle будет сложно добраться, я использую WCF). Я думаю Вы путаете меня с другим участником форума.

Имперсонацию делаю с целью доступа к HKCU.
Re[7]: ImpersonateLoggedOnUser даёт ошибку 6 (ERROR_INVALID_
От: ononim  
Дата: 04.01.10 22:04
Оценка:
O>>Ну и смысл? Если данное действие происходит ради секурити, то вот вам дыра — malicious IPC клиент передает вам не не свой process id, а какого нить системного процесса. И ваш сервис его успешно проимперсонирует.
O>>Для имперсонации клиентов IPC нужно использовать предоставляемые этим самым IPC средства. Для пайпов к примеру вам тут уже правильно говорили это ImpersonateNamedPipeClient .
R>По поводу ImpersonateNamedPipeClient мне тут не говорили (кстати до named pipe handle будет сложно добраться, я использую WCF). Я думаю Вы путаете меня с другим участником форума.
говорили: http://rsdn.ru/forum/winapi/3658072.1.aspx
Автор: Jolly Roger
Дата: 31.12.09

что до WCF — чтото мне подсказывает что в WFC есть средства для этого, просто вы про них немного не в курсе. Я как человек далекий от мира .нет могу только предложить начать копать отсюда: http://msdn.microsoft.com/en-us/library/ms788971.aspx

R>Имперсонацию делаю с целью доступа к HKCU.

мм.. ну ежели вы оттуда только читаете — может быть и не страшно... но ежели и пишете туда — уже хуже.
Как много веселых ребят, и все делают велосипед...
Re[2]: ImpersonateLoggedOnUser даёт ошибку 6 (ERROR_INVALID_
От: ruslanv США  
Дата: 04.01.10 22:39
Оценка:
Здравствуйте, Jolly Roger, Вы писали:

JR>Здравствуйте, ruslanv, Вы писали:


R>>полученный token перекидываю по named pipe в мой Windows сервис который крутится под пользователем Local System и пытаюсь вызвать на него ImpersonateLoggedOnUser.


JR>Хм, стесняюсь спросить, а чем не устроил ImpersonateNamedPipeClient ?


У меня .Net приложение, общение сервисов идёт через WCF. Выковыривать из него handle от named pipe не хотелось бы.
Re[3]: ImpersonateLoggedOnUser даёт ошибку 6 (ERROR_INVALID_
От: Jolly Roger  
Дата: 05.01.10 07:18
Оценка:
Здравствуйте, ruslanv, Вы писали:

R>У меня .Net приложение, общение сервисов идёт через WCF. Выковыривать из него handle от named pipe не хотелось бы.


Это?
"Нормальные герои всегда идут в обход!"
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.