Здравствуйте, igas, Вы писали:
I>Приветствую! I>Есть необходимость присвоения в процессе выполнения программе прав администратора. I>Как возможно это сделать?
перезапустить ее.
все так делают, наверное на это есть какая-то причина
Здравствуйте, Abyx, Вы писали:
A>Здравствуйте, igas, Вы писали:
I>>Приветствую! I>>Есть необходимость присвоения в процессе выполнения программе прав администратора. I>>Как возможно это сделать?
A>перезапустить ее. A>все так делают, наверное на это есть какая-то причина
Без перезапуска никак не обойтись?
Здравствуйте, igas, Вы писали:
I>Без перезапуска никак не обойтись?
Разнести части программы — интерфейсную, обычно-деятельную и административно-деятельную в разные процессы.
Тогда делегирование прав админа не потребует перезапуска:
интерфейсная программа просто вызовет do_admin_job.exe или myself.exe /do_admin_job
А дальше как интерфейс наладит связь с серверной частью — однократно передав гору параметров, используя pipe на вводе-выводе, или какие-нибудь собственные средства взаимодействия и синхронизации — это уже частности.
Здравствуйте, Кодт, Вы писали:
К>Здравствуйте, igas, Вы писали:
I>>Без перезапуска никак не обойтись?
К>Разнести части программы — интерфейсную, обычно-деятельную и административно-деятельную в разные процессы. К>Тогда делегирование прав админа не потребует перезапуска: К>интерфейсная программа просто вызовет do_admin_job.exe или myself.exe /do_admin_job К>А дальше как интерфейс наладит связь с серверной частью — однократно передав гору параметров, используя pipe на вводе-выводе, или какие-нибудь собственные средства взаимодействия и синхронизации — это уже частности.
Так этому же процессу нельзя присвоить привилегии администратора при выполнении?
Мне это нужно для смены владельца файла на Everyone.
Для небольшой задачи не хотелось бы заводить новый процесс.
Здравствуйте, igas, Вы писали:
I>Так этому же процессу нельзя присвоить привилегии администратора при выполнении?
Нет, но такое требование можно в манифесте прописать или запустить через ShellExecute. Если юзер знает пароль, то введёт, а если нет, то ему и не положено.
I>Мне это нужно для смены владельца файла на Everyone.
Если ничего не поменялось со времён XP и если правильно помню, для этого надо быть не администратором, а оператором архивирования. Маловероятно, но возможно, что администратор таковым не окажется.
Здравствуйте, ononim, Вы писали:
I>>Так этому же процессу нельзя присвоить привилегии администратора при выполнении? O>Нет. Иначе это было бы небезопасно.
А чем конкретно? Почему не сделали, скажем, API-вызов ElevateCurrentProcess(), который выводил бы такой же UAC-запрос, как для запуска нового процесса, но вместо этого повышал привилегии существующего?
И ещё, как альтернативный подход: можно ли менять привилегии одного процесса из другого при условии, что этот другой процесс админский? Если да, то можно было бы не заморачиваться выносом функций и межпроцессными взаимодействиями, а просто запустить вспомогательную утилитку с повышенными привилегиями, которая повысит привилегии родителю, после чего тот сможет повторить требуемую операцию.
Здравствуйте, Jolly Roger, Вы писали:
JR>Здравствуйте, igas, Вы писали:
I>>Так этому же процессу нельзя присвоить привилегии администратора при выполнении?
JR>Нет, но такое требование можно в манифесте прописать или запустить через ShellExecute. Если юзер знает пароль, то введёт, а если нет, то ему и не положено.
I>>Мне это нужно для смены владельца файла на Everyone.
JR>Если ничего не поменялось со времён XP и если правильно помню, для этого надо быть не администратором, а оператором архивирования. Маловероятно, но возможно, что администратор таковым не окажется.
Здравствуйте, Jolly Roger, Вы писали:
JR>Здравствуйте, igas, Вы писали:
I>>Так этому же процессу нельзя присвоить привилегии администратора при выполнении?
JR>Нет, но такое требование можно в манифесте прописать или запустить через ShellExecute. Если юзер знает пароль, то введёт, а если нет, то ему и не положено.
I>>Мне это нужно для смены владельца файла на Everyone.
JR>Если ничего не поменялось со времён XP и если правильно помню, для этого надо быть не администратором, а оператором архивирования. Маловероятно, но возможно, что администратор таковым не окажется.
Заюзать MSDNовскую TakeOwnership() получится?
BOOL TakeOwnership(LPTSTR lpszOwnFile)
{
BOOL bRetval = FALSE;
HANDLE hToken = NULL;
PSID pSIDAdmin = NULL;
PSID pSIDEveryone = NULL;
PACL pACL = NULL;
SID_IDENTIFIER_AUTHORITY SIDAuthWorld =
SECURITY_WORLD_SID_AUTHORITY;
SID_IDENTIFIER_AUTHORITY SIDAuthNT = SECURITY_NT_AUTHORITY;
const int NUM_ACES = 1;
EXPLICIT_ACCESS ea[NUM_ACES];
DWORD dwRes;
// Specify the DACL to use.
// Create a SID for the Everyone group.if (!AllocateAndInitializeSid(&SIDAuthWorld, 1,
SECURITY_WORLD_RID,
0,
0, 0, 0, 0, 0, 0,
&pSIDEveryone))
{
printf("AllocateAndInitializeSid (Everyone) error %u\n",
GetLastError());
goto Cleanup;
}
// Create a SID for the BUILTIN\Administrators group.if (!AllocateAndInitializeSid(&SIDAuthNT, 2,
SECURITY_BUILTIN_DOMAIN_RID,
DOMAIN_ALIAS_RID_ADMINS,
0, 0, 0, 0, 0, 0,
&pSIDAdmin))
{
printf("AllocateAndInitializeSid (Admin) error %u\n",
GetLastError());
goto Cleanup;
}
ZeroMemory(&ea, NUM_ACES * sizeof(EXPLICIT_ACCESS));
// Set full control for Everyone.
ea[0].grfAccessPermissions = GENERIC_ALL; //GENERIC_READ
ea[0].grfAccessMode = SET_ACCESS;
ea[0].grfInheritance = NO_INHERITANCE;
ea[0].Trustee.TrusteeForm = TRUSTEE_IS_SID;
ea[0].Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
ea[0].Trustee.ptstrName = (LPTSTR) pSIDEveryone;
if (ERROR_SUCCESS != SetEntriesInAcl(NUM_ACES,
ea,
NULL,
&pACL))
{
printf("Failed SetEntriesInAcl\n");
goto Cleanup;
}
// Try to modify the object's DACL.
dwRes = SetNamedSecurityInfo(
lpszOwnFile, // name of the object
SE_FILE_OBJECT, // type of object
DACL_SECURITY_INFORMATION, // change only the object's DACL
NULL, NULL, // do not change owner or group
pACL, // DACL specified
NULL); // do not change SACLif (ERROR_SUCCESS == dwRes)
{
printf("Successfully changed DACL\n");
bRetval = TRUE;
// No more processing needed.goto Cleanup;
}
if (dwRes != ERROR_ACCESS_DENIED)
{
printf("First SetNamedSecurityInfo call failed: %u\n",
dwRes);
goto Cleanup;
}
// If the preceding call failed because access was denied,
// enable the SE_TAKE_OWNERSHIP_NAME privilege, create a SID for
// the Administrators group, take ownership of the object, and
// disable the privilege. Then try again to set the object's DACL.
// Open a handle to the access token for the calling process.if (!OpenProcessToken(GetCurrentProcess(),
TOKEN_ADJUST_PRIVILEGES,
&hToken))
{
printf("OpenProcessToken failed: %u\n", GetLastError());
goto Cleanup;
}
// Enable the SE_TAKE_OWNERSHIP_NAME privilege.if (!SetPrivilege(hToken, SE_TAKE_OWNERSHIP_NAME, TRUE))
{
printf("You must be logged on as Administrator.\n");
goto Cleanup;
}
// Set the owner in the object's security descriptor.
dwRes = SetNamedSecurityInfo(
lpszOwnFile, // name of the object
SE_FILE_OBJECT, // type of object
OWNER_SECURITY_INFORMATION, // change only the object's owner
pSIDAdmin, // SID of Administrator group
NULL,
NULL,
NULL);
if (dwRes != ERROR_SUCCESS)
{
printf("Could not set owner. Error: %u\n", dwRes);
goto Cleanup;
}
// Disable the SE_TAKE_OWNERSHIP_NAME privilege.if (!SetPrivilege(hToken, SE_TAKE_OWNERSHIP_NAME, FALSE))
{
printf("Failed SetPrivilege call unexpectedly.\n");
goto Cleanup;
}
// Try again to modify the object's DACL,
// now that we are the owner.
dwRes = SetNamedSecurityInfo(
lpszOwnFile, // name of the object
SE_FILE_OBJECT, // type of object
DACL_SECURITY_INFORMATION, // change only the object's DACL
NULL, NULL, // do not change owner or group
pACL, // DACL specified
NULL); // do not change SACLif (dwRes == ERROR_SUCCESS)
{
printf("Successfully changed DACL\n");
bRetval = TRUE;
}
else
{
printf("Second SetNamedSecurityInfo call failed: %u\n",
dwRes);
}
Cleanup:
if (pSIDAdmin)
FreeSid(pSIDAdmin);
if (pSIDEveryone)
FreeSid(pSIDEveryone);
if (pACL)
LocalFree(pACL);
if (hToken)
CloseHandle(hToken);
return bRetval;
}
Здравствуйте, igas, Вы писали:
I>Заюзать MSDNовскую TakeOwnership() получится?
Ну я так понял, Вам только владельца поменять? Тогда здесь много лишнего. Вам нужно только включить привилегию, вызвать SetNamedSecurityInfo с OWNER_SECURITY_INFORMATION и опять восстановить состояние привилегии. Ну а так-то да, должна сработать.
Здравствуйте, CaptainFlint, Вы писали:
CF>А чем конкретно? Почему не сделали, скажем, API-вызов ElevateCurrentProcess(), который выводил бы такой же UAC-запрос, как для запуска нового процесса, но вместо этого повышал привилегии существующего?
В windows нельзя поменять маркер уровня процесса, это с самого начала так. А замена маркера потока даёт ограниченную функциональность. Например, не позволяет простым вызовом CreateProcess запустить новый процесс от имени имперсонировавшегося пользователя, а вызов CreateProcessAsUser требует наличие определённых привилегий. Связано всё это скорее всего с сетевой безопасностью.
CF>И ещё, как альтернативный подход: можно ли менять привилегии одного процесса из другого при условии, что этот другой процесс админский? Если да, то можно было бы не заморачиваться выносом функций и межпроцессными взаимодействиями, а просто запустить вспомогательную утилитку с повышенными привилегиями, которая повысит привилегии родителю, после чего тот сможет повторить требуемую операцию.
Здравствуйте, Jolly Roger, Вы писали:
JR>Здравствуйте, igas, Вы писали:
I>>Заюзать MSDNовскую TakeOwnership() получится?
JR>Ну я так понял, Вам только владельца поменять? Тогда здесь много лишнего. Вам нужно только включить привилегию, вызвать SetNamedSecurityInfo с OWNER_SECURITY_INFORMATION и опять восстановить состояние привилегии. Ну а так-то да, должна сработать.
Делаю так:
BOOL TakeOwnership(LPTSTR lpszOwnFile)
{
BOOL bRetval = FALSE;
HANDLE hToken = NULL;
PSID pSIDBackup = NULL;
SID_IDENTIFIER_AUTHORITY SIDBackup = SECURITY_NT_AUTHORITY;
DWORD dwRes;
if (!AllocateAndInitializeSid(&SIDBackup, 1,
SECURITY_BUILTIN_DOMAIN_RID,
DOMAIN_ALIAS_RID_BACKUP_OPS,
0, 0, 0, 0, 0, 0,
&pSIDBackup))
{
printf("AllocateAndInitializeSid (Backup) error %u\n",
GetLastError());
goto Cleanup;
}
if (!OpenProcessToken(GetCurrentProcess(),
TOKEN_ADJUST_PRIVILEGES,
&hToken))
{
printf("OpenProcessToken failed: %u\n", GetLastError());
goto Cleanup;
}
// Enable the SE_TAKE_OWNERSHIP_NAME privilege.if (!SetPrivilege(hToken, SE_TAKE_OWNERSHIP_NAME, TRUE))
{
printf("You must be logged on as Administrator.\n");
goto Cleanup;
}
// Set the owner in the object's security descriptor.
dwRes = SetNamedSecurityInfo(
lpszOwnFile, // name of the object
SE_FILE_OBJECT, // type of object
OWNER_SECURITY_INFORMATION, // change only the object's owner
pSIDBackup, // SID of Administrator group
NULL,
NULL,
NULL);
if (dwRes != ERROR_SUCCESS)
{
printf("Could not set owner. Error: %u\n", dwRes);
goto Cleanup;
}
// Disable the SE_TAKE_OWNERSHIP_NAME privilege.if (!SetPrivilege(hToken, SE_TAKE_OWNERSHIP_NAME, FALSE))
{
printf("Failed SetPrivilege call unexpectedly.\n");
goto Cleanup;
}
Cleanup:
if (pSIDBackup)
FreeSid(pSIDBackup);
if (hToken)
CloseHandle(hToken);
return bRetval;
}
Но на этом месте
// Set the owner in the object's security descriptor.
dwRes = SetNamedSecurityInfo(
lpszOwnFile, // name of the object
SE_FILE_OBJECT, // type of object
OWNER_SECURITY_INFORMATION, // change only the object's owner
pSIDBackup, // SID of Administrator group
NULL,
NULL,
NULL);
Вываливается с ошибкой ERROR_INVALID_OWNER 1307 (0x51B)
Я так понял что-то с SID намутил
Здравствуйте, igas, Вы писали:
I>Но на этом месте I>
I>// Set the owner in the object's security descriptor.
I> dwRes = SetNamedSecurityInfo(
I> lpszOwnFile, // name of the object
I> SE_FILE_OBJECT, // type of object
I> OWNER_SECURITY_INFORMATION, // change only the object's owner
I> pSIDBackup, // SID of Administrator group
I> NULL,
I> NULL,
I> NULL);
I>
I>Вываливается с ошибкой ERROR_INVALID_OWNER 1307 (0x51B) I>Я так понял что-то с SID намутил
Возможно, backup operators — неподходящий кандидат на высокое звание владельца. Я просто не помню, лучше Вам с MSDN свериться, в том числе и по составу SID этой группы, какие именно элементы нужно использовать для его сборки. Помню, что группа администраторов владельцем может быть, а вот насчёт других групп —
I>>>Так этому же процессу нельзя присвоить привилегии администратора при выполнении? O>>Нет. Иначе это было бы небезопасно. CF>А чем конкретно? Почему не сделали, скажем, API-вызов ElevateCurrentProcess(), который выводил бы такой же UAC-запрос, как для запуска нового процесса, но вместо этого повышал привилегии существующего?
Потому что злонамеренный код может изменить память или еще каким либо из тысяч способов повлиять на процесс, работающий под тем же пользователем что и он сам, и таким образом получить повышение привилегий после того как тот вызовет гипотетическую ElevateCurrentProcess.
В случае же elevation'а через ShellExecute все что под силу сделать коду с текущими привилегиями — либо запустить злонамеренный процесс вместо хорошего, либо скормить хорошему команд лайн, заэксплоитив какую либо его дырку связанную с парсингом командлайна. Первый вариант — сразу будет виден пользователю в окошке UAC, второй — является фиксабельной секурити дырой которая лечится секурным парсингом командлайна в привилегированном процессе.
CF>И ещё, как альтернативный подход: можно ли менять привилегии одного процесса из другого при условии, что этот другой процесс админский? CF>ИЕсли да, то можно было бы не заморачиваться выносом функций и межпроцессными взаимодействиями, а просто запустить вспомогательную утилитку с повышенными привилегиями, которая повысит привилегии родителю, после чего тот сможет повторить требуемую операцию.
С админскими правами делать можно что угодно, но то что вы хотите сделать — откроет брешь в системе безопасности винды ибо см выше.
Как много веселых ребят, и все делают велосипед...
Здравствуйте, ononim, Вы писали:
CF>>Почему не сделали, скажем, API-вызов ElevateCurrentProcess(), который выводил бы такой же UAC-запрос, как для запуска нового процесса, но вместо этого повышал привилегии существующего? O>Потому что злонамеренный код может изменить память или еще каким либо из тысяч способов повлиять на процесс, работающий под тем же пользователем что и он сам, и таким образом получить повышение привилегий после того как тот вызовет гипотетическую ElevateCurrentProcess.
Понятно, про такой сценарий не сообразил. Спасибо.
I>Вываливается с ошибкой ERROR_INVALID_OWNER 1307 (0x51B) I>Я так понял что-то с SID намутил
The write-owner standard access right allows a user to take ownership of a Windows NT securable object, but does not allow the user to change the ownership of a Windows NT securable object to a different account.
(c) http://support.microsoft.com/kb/245153
Чтож, это логично.. Иначе я могу создать объект и буду иметь все права на него (в т.ч. WRITE_OWNER), а потом назначить овнером объекта когото другого, а вдруг он не хочет
Как много веселых ребят, и все делают велосипед...
The write-owner standard access right allows a user to take ownership of a Windows NT securable object, but does not allow the user to change the ownership of a Windows NT securable object to a different account.
O>(c) http://support.microsoft.com/kb/245153 O>Чтож, это логично.. Иначе я могу создать объект и буду иметь все права на него (в т.ч. WRITE_OWNER), а потом назначить овнером объекта когото другого, а вдруг он не хочет
Там же:
If the calling user who is running the program is an Administrator or a Backup Operator, by default he or she has (SE_RESTORE_NAME) "Restore files and directories" User Right granted in the User Manager. The calling process can "enable" this SE_RESTORE_NAME privilege in the process token and can set any valid user or group SID as the owner of an object. This enables an Administrator or a Backup Operator to change the ownership of a Windows NT securable object.