Присвоение прав администратора программе
От: igas Беларусь  
Дата: 12.02.13 09:26
Оценка:
Приветствую!
Есть необходимость присвоения в процессе выполнения программе прав администратора.
Как возможно это сделать?

12.02.13 13:42: Перенесено модератором из 'C/C++. Прикладные вопросы' — Кодт
c++ winapi
Re: Присвоение прав администратора программе
От: Abyx Россия  
Дата: 12.02.13 09:33
Оценка: -1
Здравствуйте, igas, Вы писали:

I>Приветствую!

I>Есть необходимость присвоения в процессе выполнения программе прав администратора.
I>Как возможно это сделать?

перезапустить ее.
все так делают, наверное на это есть какая-то причина
In Zen We Trust
Re[2]: Присвоение прав администратора программе
От: igas Беларусь  
Дата: 12.02.13 09:36
Оценка:
Здравствуйте, Abyx, Вы писали:

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


I>>Приветствую!

I>>Есть необходимость присвоения в процессе выполнения программе прав администратора.
I>>Как возможно это сделать?

A>перезапустить ее.

A>все так делают, наверное на это есть какая-то причина
Без перезапуска никак не обойтись?
Re[3]: Присвоение прав администратора программе
От: Mystic Украина http://mystic2000.newmail.ru
Дата: 12.02.13 09:46
Оценка:
Здравствуйте, igas, Вы писали:

A>>перезапустить ее.

A>>все так делают, наверное на это есть какая-то причина
I>Без перезапуска никак не обойтись?

Выполнение операций, для которых требуются административные привилегии, выполнять в отдельном процессе. Его запускать и с ним общаться.
Re[3]: Присвоение прав администратора программе
От: Кодт Россия  
Дата: 12.02.13 09:53
Оценка:
Здравствуйте, igas, Вы писали:

I>Без перезапуска никак не обойтись?


Разнести части программы — интерфейсную, обычно-деятельную и административно-деятельную в разные процессы.
Тогда делегирование прав админа не потребует перезапуска:
интерфейсная программа просто вызовет do_admin_job.exe или myself.exe /do_admin_job
А дальше как интерфейс наладит связь с серверной частью — однократно передав гору параметров, используя pipe на вводе-выводе, или какие-нибудь собственные средства взаимодействия и синхронизации — это уже частности.
Перекуём баги на фичи!
Re[4]: Присвоение прав администратора программе
От: igas Беларусь  
Дата: 12.02.13 10:04
Оценка:
Здравствуйте, Кодт, Вы писали:

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


I>>Без перезапуска никак не обойтись?


К>Разнести части программы — интерфейсную, обычно-деятельную и административно-деятельную в разные процессы.

К>Тогда делегирование прав админа не потребует перезапуска:
К>интерфейсная программа просто вызовет do_admin_job.exe или myself.exe /do_admin_job
К>А дальше как интерфейс наладит связь с серверной частью — однократно передав гору параметров, используя pipe на вводе-выводе, или какие-нибудь собственные средства взаимодействия и синхронизации — это уже частности.

Так этому же процессу нельзя присвоить привилегии администратора при выполнении?
Мне это нужно для смены владельца файла на Everyone.
Для небольшой задачи не хотелось бы заводить новый процесс.
Re[5]: Присвоение прав администратора программе
От: ononim  
Дата: 12.02.13 10:07
Оценка:
I>Так этому же процессу нельзя присвоить привилегии администратора при выполнении?
Нет. Иначе это было бы небезопасно.
Как много веселых ребят, и все делают велосипед...
Re[5]: Присвоение прав администратора программе
От: Jolly Roger  
Дата: 12.02.13 10:19
Оценка: +1
Здравствуйте, igas, Вы писали:

I>Так этому же процессу нельзя присвоить привилегии администратора при выполнении?


Нет, но такое требование можно в манифесте прописать или запустить через ShellExecute. Если юзер знает пароль, то введёт, а если нет, то ему и не положено.

I>Мне это нужно для смены владельца файла на Everyone.


Если ничего не поменялось со времён XP и если правильно помню, для этого надо быть не администратором, а оператором архивирования. Маловероятно, но возможно, что администратор таковым не окажется.
"Нормальные герои всегда идут в обход!"
Re[6]: Присвоение прав администратора программе
От: CaptainFlint Россия http://flint-inc.ru/
Дата: 12.02.13 11:21
Оценка: +1
Здравствуйте, ononim, Вы писали:

I>>Так этому же процессу нельзя присвоить привилегии администратора при выполнении?

O>Нет. Иначе это было бы небезопасно.

А чем конкретно? Почему не сделали, скажем, API-вызов ElevateCurrentProcess(), который выводил бы такой же UAC-запрос, как для запуска нового процесса, но вместо этого повышал привилегии существующего?

И ещё, как альтернативный подход: можно ли менять привилегии одного процесса из другого при условии, что этот другой процесс админский? Если да, то можно было бы не заморачиваться выносом функций и межпроцессными взаимодействиями, а просто запустить вспомогательную утилитку с повышенными привилегиями, которая повысит привилегии родителю, после чего тот сможет повторить требуемую операцию.
Почему же, ё-моё, ты нигде не пишешь «ё»?
Re[6]: Присвоение прав администратора программе
От: igas Беларусь  
Дата: 12.02.13 11:54
Оценка:
Здравствуйте, Jolly Roger, Вы писали:

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


I>>Так этому же процессу нельзя присвоить привилегии администратора при выполнении?


JR>Нет, но такое требование можно в манифесте прописать или запустить через ShellExecute. Если юзер знает пароль, то введёт, а если нет, то ему и не положено.


I>>Мне это нужно для смены владельца файла на Everyone.


JR>Если ничего не поменялось со времён XP и если правильно помню, для этого надо быть не администратором, а оператором архивирования. Маловероятно, но возможно, что администратор таковым не окажется.


Юзер является членом группs Backup Operators.
Re[6]: Присвоение прав администратора программе
От: igas Беларусь  
Дата: 12.02.13 12:07
Оценка:
Здравствуйте, 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 SACL

    if (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 SACL

    if (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;

}
Re[7]: Присвоение прав администратора программе
От: Jolly Roger  
Дата: 12.02.13 12:26
Оценка:
Здравствуйте, igas, Вы писали:

I>Заюзать MSDNовскую TakeOwnership() получится?


Ну я так понял, Вам только владельца поменять? Тогда здесь много лишнего. Вам нужно только включить привилегию, вызвать SetNamedSecurityInfo с OWNER_SECURITY_INFORMATION и опять восстановить состояние привилегии. Ну а так-то да, должна сработать.
"Нормальные герои всегда идут в обход!"
Re[7]: Присвоение прав администратора программе
От: Jolly Roger  
Дата: 12.02.13 12:35
Оценка:
Здравствуйте, CaptainFlint, Вы писали:

CF>А чем конкретно? Почему не сделали, скажем, API-вызов ElevateCurrentProcess(), который выводил бы такой же UAC-запрос, как для запуска нового процесса, но вместо этого повышал привилегии существующего?


В windows нельзя поменять маркер уровня процесса, это с самого начала так. А замена маркера потока даёт ограниченную функциональность. Например, не позволяет простым вызовом CreateProcess запустить новый процесс от имени имперсонировавшегося пользователя, а вызов CreateProcessAsUser требует наличие определённых привилегий. Связано всё это скорее всего с сетевой безопасностью.

CF>И ещё, как альтернативный подход: можно ли менять привилегии одного процесса из другого при условии, что этот другой процесс админский? Если да, то можно было бы не заморачиваться выносом функций и межпроцессными взаимодействиями, а просто запустить вспомогательную утилитку с повышенными привилегиями, которая повысит привилегии родителю, после чего тот сможет повторить требуемую операцию.


Так тоже нельзя.
"Нормальные герои всегда идут в обход!"
Re[8]: Присвоение прав администратора программе
От: igas Беларусь  
Дата: 12.02.13 14:05
Оценка:
Здравствуйте, 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 намутил
Re[9]: Присвоение прав администратора программе
От: Jolly Roger  
Дата: 12.02.13 15:00
Оценка:
Здравствуйте, 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 этой группы, какие именно элементы нужно использовать для его сборки. Помню, что группа администраторов владельцем может быть, а вот насчёт других групп —
"Нормальные герои всегда идут в обход!"
Re[7]: Присвоение прав администратора программе
От: ononim  
Дата: 12.02.13 20:05
Оценка: 6 (1)
I>>>Так этому же процессу нельзя присвоить привилегии администратора при выполнении?
O>>Нет. Иначе это было бы небезопасно.
CF>А чем конкретно? Почему не сделали, скажем, API-вызов ElevateCurrentProcess(), который выводил бы такой же UAC-запрос, как для запуска нового процесса, но вместо этого повышал привилегии существующего?
Потому что злонамеренный код может изменить память или еще каким либо из тысяч способов повлиять на процесс, работающий под тем же пользователем что и он сам, и таким образом получить повышение привилегий после того как тот вызовет гипотетическую ElevateCurrentProcess.
В случае же elevation'а через ShellExecute все что под силу сделать коду с текущими привилегиями — либо запустить злонамеренный процесс вместо хорошего, либо скормить хорошему команд лайн, заэксплоитив какую либо его дырку связанную с парсингом командлайна. Первый вариант — сразу будет виден пользователю в окошке UAC, второй — является фиксабельной секурити дырой которая лечится секурным парсингом командлайна в привилегированном процессе.

CF>И ещё, как альтернативный подход: можно ли менять привилегии одного процесса из другого при условии, что этот другой процесс админский?

CF>ИЕсли да, то можно было бы не заморачиваться выносом функций и межпроцессными взаимодействиями, а просто запустить вспомогательную утилитку с повышенными привилегиями, которая повысит привилегии родителю, после чего тот сможет повторить требуемую операцию.
С админскими правами делать можно что угодно, но то что вы хотите сделать — откроет брешь в системе безопасности винды ибо см выше.
Как много веселых ребят, и все делают велосипед...
Re[8]: Присвоение прав администратора программе
От: CaptainFlint Россия http://flint-inc.ru/
Дата: 12.02.13 20:54
Оценка:
Здравствуйте, ononim, Вы писали:

CF>>Почему не сделали, скажем, API-вызов ElevateCurrentProcess(), который выводил бы такой же UAC-запрос, как для запуска нового процесса, но вместо этого повышал привилегии существующего?

O>Потому что злонамеренный код может изменить память или еще каким либо из тысяч способов повлиять на процесс, работающий под тем же пользователем что и он сам, и таким образом получить повышение привилегий после того как тот вызовет гипотетическую ElevateCurrentProcess.

Понятно, про такой сценарий не сообразил. Спасибо.
Почему же, ё-моё, ты нигде не пишешь «ё»?
Re[9]: Присвоение прав администратора программе
От: ononim  
Дата: 13.02.13 14:10
Оценка:
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), а потом назначить овнером объекта когото другого, а вдруг он не хочет
Как много веселых ребят, и все делают велосипед...
Re[10]: Присвоение прав администратора программе
От: Jolly Roger  
Дата: 16.02.13 15:46
Оценка:
Здравствуйте, ononim, Вы писали:

O>

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.

На WinXP я проверял, так оно и есть.
"Нормальные герои всегда идут в обход!"
Re[11]: Присвоение прав администратора программе
От: Jolly Roger  
Дата: 16.02.13 15:59
Оценка:
Здравствуйте, Jolly Roger, Вы писали:

JR>На WinXP я проверял, так оно и есть.


здесь
Автор: Мизантроп
Дата: 13.10.09
"Нормальные герои всегда идут в обход!"
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.