На языке C я создаю программу, использующую WinAPI. Для этой программы я пишу функцию, которая будет включать указанные привилегии. Вот что у меня есть:
void EnablePrivileges(LPCWSTR awszPrivileges[], DWORD dwCount){
HANDLE hToken;
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken)) {
printf("Failed to open process token. Error: %lu\n", GetLastError());
return;
}
TOKEN_PRIVILEGES tp;
tp.PrivilegeCount = dwCount;
for (DWORD i = 0; i < dwCount; ++i) {
wprintf(TEXT("Privilege constant: %ls | Iterator value: %i\n"), awszPrivileges[i], i);
if (!LookupPrivilegeValueW(NULL, awszPrivileges[i], &tp.Privileges[i].Luid)) {
printf("Failed to lookup privilege value. Error: %lu\n", GetLastError());
CloseHandle(hToken);
return;
}
tp.Privileges[i].Attributes = SE_PRIVILEGE_ENABLED;
}
if (!AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL)) {
printf("Failed to adjust token privileges. Error: %lu\n", GetLastError());
} else {
printf("Token privileges adjusted successfully.\n");
}
CloseHandle(hToken);
}
int main() {
LPCWSTR awszPrivileges[] = {SE_TAKE_OWNERSHIP_NAME, SE_AUDIT_NAME, SE_RESTORE_NAME};
EnablePrivileges(awszPrivileges, 3);
system("pause");
return 0;
}
Он компилируется без ошибок.
Однако, когда я затем запускаю его с правами администратора, он выдает следующее:
Privilege constant: SeTakeOwnershipPrivilege | Iterator value: 0
Privilege constant: SeAuditPrivilege | Iterator value: 1
Privilege constant: SeAuditPrivilege | Iterator value: 1
Privilege constant: SeAuditPrivilege | Iterator value: 1
Privilege constant: SeAuditPrivilege | Iterator value: 1
Privilege constant: SeAuditPrivilege | Iterator value: 1
... и так далее.
Это также произошло, когда пытались включить только две привилегии. Однако успешно работает только с одним.
Что заставляет цикл for вести себя подобным образом? Как исправить эту ошибку?
@Chris Это C, но я уверен, что с C++ возникнут некоторые проблемы.
Мысль о том, что в коде могут быть те же проблемы, не оправдывает злоупотребление тегами. Пожалуйста, удалите тег, который не имеет прямого отношения к коду, который вы разместили здесь в этом вопросе.
@KenWhite Я пишу на C, я ясно дал это понять. Причина, по которой я также отметил «C++», заключается в том, что я уверен, что ошибка сохранится и в этом языке. Я также попробовал скомпилировать компилятором C++, но ошибка осталась.
Вы объявили переменную стека TOKEN_PRIVILEGES tp;
— вы не можете получить доступ к элементам в массиве «любого размера», как вы сейчас делаете с tp.Privileges[i]
, потому что это адресация к концу структуры данных. Эта структура предназначена для выделения размера, который отражает фактический объем памяти, необходимый для массива, чтобы вы могли обращаться к концу поля Privileges
. См. Learn.microsoft.com/en-us/windows/win32/api/winnt/…
Ваше оправдание неправильного использования тега не имеет значения. Теги здесь имеют значение и актуальность, и вам следует использовать только те теги, которые действительно применимы к содержанию вашего сообщения. Если ваш код написан на C, то добавление тега C++ является неправильным использованием системы тегов. Не отмечайте спам.
Вы обращаетесь к концу tp.Privileges
. Размер этого массива равен 1. Как указано в документации :
Важно. Константа
ANYSIZE_ARRAY
определена как 1 в общедоступном заголовке Winnt.h. Чтобы создать этот массив с более чем одним элементом, необходимо выделить достаточно памяти для того, чтобы структура учитывала дополнительные элементы.
Вы должны выделить (правильно выровненный) блок памяти размером не менее sizeof(TOKEN_PRIVILEGES) + (dwCount - 1) * sizeof(LUID_AND_ATTRIBUTES)
и инициализировать там свой TOKEN_PRIVILEGES
объект.
Более традиционный способ определить размер — заставить компилятор выполнить математические действия, т. е. offsetof(TOKEN_PRIVILEGES, Privileges[dwCount])
(используйте FIELD_OFFSET() , если ваш компилятор не поддерживает offsetof() ). Обоснование конечного массива размера 1: Почему некоторые структуры заканчиваются массивом размера 1?,
Пожалуйста, не отмечайте спам. C, C# и C++ — это не один и тот же язык, поскольку они начинаются с буквы C, так же как автомобиль, кошка и морковка не связаны друг с другом. Пожалуйста, используйте только тот тег, который действительно соответствует языку, который вы используете. Если вы не уверены, используете ли вы C или C++, прекратите писать код, пока не разберетесь в нем, потому что вы ничего не добьетесь.