Столкнулся со странной ошибкой, причем сугубо на ХР. Есть код, примерно такой, копирует токен с Winlogon.exe или smss.exe Код (C): int main() { DWORD dAccess,dwProcessId = GetSysPid(); HANDLE hProcess,TokenHandle,phNewToken; BOOL bRet; SECURITY_ATTRIBUTES TokenAttributes = { .lpSecurityDescriptor = NULL, .bInheritHandle = FALSE, .nLength = sizeof(SECURITY_ATTRIBUTES) }; EnableWindowsPrivilege(L"SeDebugPrivilege"); hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, dwProcessId); bRet = OpenProcessToken(hProcess, MAXIMUM_ALLOWED, &TokenHandle); bRet = DuplicateTokenEx(TokenHandle,MAXIMUM_ALLOWED,&TokenAttributes,SecurityImpersonation,TokenPrimary,&phNewToken); if (bRet == FALSE) { wprintf(L"Error , can't duplicate token %d\n",GetLastError()); return FALSE; } else { wprintf(L"token duplicated..\n"); } return 0; } Код прекрасно работает на последней десятке, но возвращает access_denied на WinXP ! Причем на функции DuplicateTokenEx . На всех остальных ОС (виста и выше ) все работает. Почему такое может быть, что было в ХР ? Indy_
На виста+ работает так. Считается, что плохая практика передавать _ALL_ACCESS , + в более новых ОС никто таких прав банально не даст.
Indy_, ок. Как в ХР запустить процесс с правами системы? Имея админский аккаунт, но не через службу. В ОС выше ХР решается вот кодом выше - открываем Winlogon/smss , копируем оттуда токен, создаем новый процесс. В ХР такой фокус не проходит, дает ошибку ACCESS_DENIED на том или ином этапе.
M0rg0t, Отладчиком пройди и посмотри статусный код. Этот winerr это группа из пол сотни статусов поэтому это не ошибка а вообще ничего. За пол часа это можно было сделать сотню раз.
M0rg0t, Всё даст, так как на XP есть сурки и всё можно посмотреть не отлаживая ядро: Код (Text): // Check the handle's access to the existing token and get // a pointer to that token. Pick up the default desired // access mask from the handle while we're at it. // Status = ObReferenceObjectByHandle( ExistingTokenHandle, // Handle TOKEN_DUPLICATE, // DesiredAccess SeTokenObjectType, // ObjectType PreviousMode, // AccessMode (PVOID *)&Token, // Object &HandleInformation // GrantedAccess ); Дальше смотри по цепочке. Реф можно проверить остановкой потока. PROCESS_QUERY_INFORMATION -> TOKEN_DUPLICATE ?
Indy_, но на ОС выше работает без DUPLICATE, более того - на десятке даже PROCESS_QUERY_INFORMATION не проходит. Впрочем, не суть. Может , на ХР и ниже вообще нельзя создать процесс от имени системы? Попробовать Process Hacker, тоже какую-то ошибку показал.
Максимум эллауд устанавливает всего один бит, который, можно предположить не обрабатывается на xp, но обрабатывается на виста+. В документации мсдн к дупликейт хендл и оупен процесс токен такого флага в принципе нет. --- Сообщение объединено, 18 мар 2020 --- Так а что твой максимум эллауд это меньше прав, чем олл эксес или что? Передавай конкретный набор прав, который тебе нужен тогда.
Rel, в любом случае, оно не работает. Пишу OpenProcess(PROCESS_ALL_ACCESS... ) - тут гуд. А OpenProcessToken(hProcess, TOKEN_ALL_ACCESS.. - возвращает все тот же ACCESS_DENIED. Процесс системный. т.е. винлогон. Мб нельзя такое там сделать, вот сторонние тулзы тоже не запускают от системы.
M0rg0t, вам OpenProcessToken возвращает хэндл без TOKEN_DUPLICATE и вы этого не замечаете, т.к. используете MAXIMUM_ALLOWED, вместо того чтобы задавать конкретные права. Дело в том, что в DACL токена в ACE для администраторов нет данного разрешения, однако владельцем являются администраторы. А раз мы и есть владелец, то мы можем открыть токен с правом WRITE_DAC и отредактировать DACL как нам нужно.
Andrey333, так с какими правами нужно открыть системный процесс? Какие флаги передать ? Сначала WRITE_DAC , а потом что ? Не пойму до конца мысль. Rel, ну какие права-то? Проблема такая, что нельзя просто так взять и написать OpenProcessToken с TOKEN_ADJUST_DEFAULT | TOKEN_ADJUST_SESSIONID | TOKEN_QUERY | TOKEN_DUPLICATE | TOKEN_ASSIGN_PRIMARY; Для системного процесса в ХР / 2к не хватает привилегий, какие не указывай - все равно, один фиг не откроется. Для обычного процесса все будет гуд. А вот lsass/ winlogon так не открыть. Если же указывать тут другие флаги, тогда падает DuplicateToken.
На 10 можно сделать следующим образом, может и на хрюше сработает: 1. Получить SeDebugPrivilege привилегии 2. Получить хэндл системного процесса 3. Передать полученный хэндл в NtCreateProcess/NtCreateUserProccess
Эмм, ну токен_дупликейт и какие там еще права нужны на запуск процесса? Если я правильно понимаю, что ты пытаешься сделать. --- Сообщение объединено, 20 мар 2020 --- В мсдн написано, что нужно TOKEN_QUERY, TOKEN_DUPLICATE и TOKEN_ASSIGN_PRIMARY.
Мне проще кодом ответить. Код (C++): #include <sddl.h> #include <stdio.h> const wchar_t ACCESS_FOR_ADMINS_SECURITY_DESCRIPTOR[] = SDDL_OWNER SDDL_DELIMINATOR SDDL_BUILTIN_ADMINISTRATORS SDDL_GROUP SDDL_DELIMINATOR SDDL_BUILTIN_ADMINISTRATORS SDDL_DACL SDDL_DELIMINATOR SDDL_PROTECTED SDDL_ACE_BEGIN SDDL_ACCESS_ALLOWED SDDL_SEPERATOR SDDL_CONTAINER_INHERIT SDDL_OBJECT_INHERIT SDDL_SEPERATOR SDDL_GENERIC_ALL SDDL_SEPERATOR SDDL_SEPERATOR SDDL_SEPERATOR SDDL_BUILTIN_ADMINISTRATORS SDDL_ACE_END; int main() { HANDLE hProcess = NULL; HANDLE hToken = NULL; HANDLE hNewToken = NULL; PSECURITY_DESCRIPTOR pSD = NULL; EnablePrivilege(L"SeDebugPrivilege"); hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, 368 /* smss.exe PID */); if (NULL == hProcess) { printf("OpenProcess failed, error code: 0x%0.8lX", GetLastError()); goto Cleanup; } if (!OpenProcessToken(hProcess, WRITE_DAC, &hToken)) { printf("OpenProcessToken failed, error code: 0x%0.8lX", GetLastError()); goto Cleanup; } if (!ConvertStringSecurityDescriptorToSecurityDescriptor( ACCESS_FOR_ADMINS_SECURITY_DESCRIPTOR, SDDL_REVISION_1, &pSD, NULL)) { printf("ConvertStringSecurityDescriptorToSecurityDescriptor failed, " "error code: 0x%0.8lX", GetLastError()); goto Cleanup; } if (!SetKernelObjectSecurity(hToken, DACL_SECURITY_INFORMATION, pSD)) { printf("SetKernelObjectSecurity failed, error code: 0x%0.8lX", GetLastError()); goto Cleanup; } CloseHandle(hToken); hToken = NULL; if (!OpenProcessToken(hProcess, TOKEN_DUPLICATE, &hToken)) { printf("OpenProcessToken failed, error code: 0x%0.8lX", GetLastError()); goto Cleanup; } if (!DuplicateTokenEx(hToken, TOKEN_QUERY | TOKEN_DUPLICATE | TOKEN_ASSIGN_PRIMARY, NULL, SecurityImpersonation, TokenPrimary, &hNewToken)) { printf("DuplicateTokenEx failed, error code: 0x%0.8lX", GetLastError()); goto Cleanup; } printf("TOKEN DUPLICATED!"); Cleanup: if (NULL != pSD) LocalFree((HLOCAL)pSD); if (NULL != hNewToken) CloseHandle(hToken); if (NULL != hToken) CloseHandle(hNewToken); if (NULL != hProcess) CloseHandle(hProcess); return 0; } А чем плох запуск через службу?
Andrey333, да, это то что надо. Спасибо! В нем ничего плохого нет, да и в целом, мне поддержка ХР давно уже не нужна. Кто ее юзает? Ну вот кроме Клерка и того товарища, что ходит по форумам с глюками АМД. Практической ценности мало. Просто, однажды тестил код запуска от системы, который корректно работает на виста-10, но не сработал на ХР. Вот стало интересно. А через службу , конечно же, я знал как запустить, но задался целью разобраться с токенами - почему в ОС выше оно работает, а тут нет. Как то так. Спасибо еще раз за помощь!