#ifndef UNICODE
#define UNICODE
#endif
#include <windows.h>
#include <stdio.h>
#include <lm.h>
int main()
{
HANDLE hProcess;
ACL *lpDacl; // указатель на список доступа
DWORD dwDaclLength; // длина списка доступа
wchar_t wchUserName[UNLEN]; // имя пользователя
DWORD dwLengthOfDomainName = 0; // длина имени домена
DWORD dwLengthOfSid = 0; // длина SID
SID *lpSid = NULL; // указатель на SID
LPTSTR lpDomainName = NULL; // указатель на имя домена
SID_NAME_USE typeOfSid; // тип учетной записи
SECURITY_DESCRIPTOR sd; // дескриптор безопасности
SECURITY_ATTRIBUTES sa; // атрибуты защиты
DWORD dwRetCode; // код возврата
// вводим имя пользователя, которому разрешим\запретип доступ
printf("Input a user name: ");
_getws(wchUserName);
// определяем длину SID пользователя
if (!LookupAccountName(
NULL, // ищем имя на локальном компьютере
wchUserName, // имя пользователя
NULL, // определяем длину SID
&dwLengthOfSid, // длина SID
NULL, // определяем имя домена
&dwLengthOfDomainName, // длина имени домена
&typeOfSid)) // тип учетной записи
{
dwRetCode = GetLastError();
if (dwRetCode == ERROR_INSUFFICIENT_BUFFER)
{
// распределяем память для SID и имени домена
lpSid = (SID*) new char[dwLengthOfSid];
lpDomainName = (LPTSTR) new wchar_t[dwLengthOfDomainName];
}
else
{
// выходим из программы
printf("Lookup account name failed.\n");
printf("Error code: %d\n", dwRetCode);
getchar();
return dwRetCode;
}
}
// определяем SID и имя домена пользователя
if(!LookupAccountName(
NULL, // ищем имя на локальном компьютере
wchUserName, // имя пользователя
lpSid, // указатель на SID
&dwLengthOfSid, // длина SID
lpDomainName, // указатель на имя домена
&dwLengthOfDomainName, // длина имени домена
&typeOfSid)) // тип учетной записи
{
dwRetCode = GetLastError();
printf("Lookup account name failed.\n");
printf("Error code: %d\n", dwRetCode);
getchar();
return dwRetCode;
}
// проверяем тип SID
if (typeOfSid != SidTypeUser)
{
printf("This is not a user name.\n");
getchar();
return 1;
}
// определем длину списка DACL
dwDaclLength = sizeof(ACL)
+ sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + dwLengthOfSid
+ sizeof(ACCESS_DENIED_ACE) - sizeof(DWORD) + dwLengthOfSid;
// распределяем память под DACL
lpDacl = (ACL*)new char[dwDaclLength];
// инициализируем список DACL
if (!InitializeAcl(
lpDacl, // адрес DACL
dwDaclLength, // длина DACL
ACL_REVISION)) // версия DACL
{
dwRetCode = GetLastError();
printf("Lookup account name failed.\n");
printf("Error code: %d\n", dwRetCode);
getchar();
return dwRetCode;
}
// добавляем запрещающий элемент в список DACL
if (!AddAccessDeniedAce(
lpDacl, // адрес DACL
ACL_REVISION, // версия DACL
PROCESS_TERMINATE, // запрещаем грохать объект
lpSid)) // адрес SID
{
dwRetCode = GetLastError();
perror("Add access denied ace failed.\n");
printf("The last error code: %u\n", dwRetCode);
getchar();
return dwRetCode;
}
// добавляем разрешающий элемент в список DACL
if (!AddAccessAllowedAce(
lpDacl, // адрес DACL
ACL_REVISION, // версия DACL
WRITE_DAC, // разрешаем менять dacl
lpSid)) // адрес SID
{
dwRetCode = GetLastError();
perror("Add access allowed ace failed.\n");
printf("The last error code: %u\n", dwRetCode);
getchar();
return dwRetCode;
}
// инициализируем версию дескриптора безопасности
if (!InitializeSecurityDescriptor(
&sd,
SECURITY_DESCRIPTOR_REVISION))
{
dwRetCode = GetLastError();
printf("Initialize security descroptor failed.\n");
printf("Error code: %d\n", dwRetCode);
getchar();
return dwRetCode;
}
// устанавливаем SID владельца объекта
if (!SetSecurityDescriptorOwner(
&sd, // адрес дескриптора безопасности
NULL, // не задаем владельца
SE_OWNER_DEFAULTED)) // определить владельца по умолчанию
{
dwRetCode = GetLastError();
perror("Set security descriptor owner failed.\n");
printf("The last error code: %u\n", dwRetCode);
getchar();
return dwRetCode;
}
// устанавливаем SID первичной группы владельца
if (!SetSecurityDescriptorGroup(
&sd, // адрес дескриптора безопасности
NULL, // не задаем первичную группу
SE_GROUP_DEFAULTED)) // определить первичную группу по умолчанию
{
dwRetCode = GetLastError();
perror("Set security descriptor group failed.\n");
printf("The last error code: %u\n", dwRetCode);
getchar();
return dwRetCode;
}
// устанавливаем DACL в дескриптор безопасности
if (!SetSecurityDescriptorDacl(
&sd, // адрес дескриптора безопасности
TRUE, // DACL присутствует
lpDacl, // указатель на DACL
FALSE)) // DACL не задан по умолчанию
{
dwRetCode = GetLastError();
perror("Set security descriptor group failed.\n");
printf("The last error code: %u\n", dwRetCode);
getchar();
return dwRetCode;
}
// проверяем структуру дескриптора безопасности
if (!IsValidSecurityDescriptor(&sd))
{
dwRetCode = GetLastError();
perror("Security descriptor is invalid.\n");
printf("The last error code: %u\n", dwRetCode);
getchar();
return dwRetCode;
}
// инициализируем атрибуты безопасности
sa.nLength = sizeof(sa); // устанавливаем длину атрибутов защиты
sa.lpSecurityDescriptor = &sd; // устанавливаем адрес SD
sa.bInheritHandle = FALSE; // дескриптор не наследуемый
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory( &si, sizeof(si));
si.cb = sizeof(si);
ZeroMemory( &pi, sizeof(pi));
CreateProcess(L"C:\\Windows\\System32\\calc.exe",NULL,&sa,NULL,FALSE,0,NULL,NULL,&si,&pi);
if (pi.hProcess == NULL)
{
dwRetCode = GetLastError();
perror("Create process failed.\n");
printf("The last error code: %u\n", dwRetCode);
getchar();
return dwRetCode;
}
printf("The process is created.\n");
getchar();
// освобождаем память
delete[] lpSid;
delete[] lpDomainName;
delete[] lpDacl;
CloseHandle(pi.hProcess);
return 0;
}
DALC и процесс
То есть хочу отобрать некоторые права у самого себя. Ниже привожу код, пытаюсь запустить калькулятор, без прав на его завершения.
Код работает без ошибок, но процесс все равно грохается без проблем. Подскажите в чем может быть проблема?
Код:
экспериментально определил, что если у пользователя есть права отлаживать приложения (см. аттач), то он имеет полный доступ к процессам (еще надо запросить SeDebugPrivilege) даже к csrss.exe, например (правда будет BSOD) и может завершить его.