Краткий ответ:
Решение в диспетчере задач жестко запрограммировано на основе следующего списка (взятого из версии для Windows 10):
%windir%\explorer.exe
%windir%\system32\ntoskrnl.exe
%windir%\system32\WerFault.exe
%windir%\system32\backgroundTaskHost.exe
%windir%\system32\backgroundTransferHost.exe
%windir%\system32\winlogon.exe
%windir%\system32\wininit.exe
%windir%\system32\csrss.exe
%windir%\system32\lsass.exe
%windir%\system32\smss.exe
%windir%\system32\services.exe
%windir%\system32\taskeng.exe
%windir%\system32\taskhost.exe
%windir%\system32\dwm.exe
%windir%\system32\conhost.exe
%windir%\system32\svchost.exe
%windir%\system32\sihost.exe
Длинный ответ:
Потребовалось некоторое время, чтобы добраться до этого списка - ниже находится путь к просветлению ;-)
Оригинальный ответ:
Чтобы ответить на ваш вопрос Узнать, является ли процесс системным процессом не так просто, как кажется.Чтобы получить эту информацию, вы должны получить владельца процесса, который в системах Windows обычно выполняется для идентификаторов безопасности .
идентификатора безопасности(SID) - это уникальное значение переменной длины, используемое для идентификации доверенного лица.Каждая учетная запись имеет уникальный SID, выданный органом, таким как контроллер домена Windows, и сохраненным в базе данных безопасности.Каждый раз, когда пользователь входит в систему, система извлекает SID для этого пользователя из базы данных и помещает его в маркер доступа для этого пользователя.Система использует SID в маркере доступа для идентификации пользователя во всех последующих взаимодействиях с безопасностью Windows.Когда SID использовался в качестве уникального идентификатора для пользователя или группы, он никогда не сможет снова использоваться для идентификации другого пользователя или группы.
Вы наверняка видели один из них, эточто-то вроде S-1-5-18 или S-1-5-21-2557247 ...-... ... ... ... 1001 .
Существует полный список WellKnown SID , который также включает в себя набор SID, которые вы, вероятно, все рассматривали бы как Системный процесс -связанный.
Если я не ошибаюсь, вы хотите получить все процессы, которые работают под локальной системной учетной записью , что будет S-1-5-18 .
Хватит говорить, давайте код:
Прежде всего мы (это вы, я уже проверял это ;-)) должны импортировать GetSecurityInfo из advapi32.dll вот так:
[DllImport("advapi32.dll", SetLastError = true)]
private static extern uint GetSecurityInfo(IntPtr handle,
SE_OBJECT_TYPE objectType,
SECURITY_INFORMATION securityInfo,
out IntPtr sidOwner,
out IntPtr sidGroup,
out IntPtr dacl,
out IntPtr sacl,
out IntPtr securityDescriptor);
... который требует двух перечислений для SE_OBJECT_TYPE и SECURITY_INFORMATION , которые должны быть определены следующим образом:
private enum SE_OBJECT_TYPE
{
SE_UNKNOWN_OBJECT_TYPE,
SE_FILE_OBJECT,
SE_SERVICE,
SE_PRINTER,
SE_REGISTRY_KEY,
SE_LMSHARE,
SE_KERNEL_OBJECT,
SE_WINDOW_OBJECT,
SE_DS_OBJECT,
SE_DS_OBJECT_ALL,
SE_PROVIDER_DEFINED_OBJECT,
SE_WMIGUID_OBJECT,
SE_REGISTRY_WOW64_32KEY
}
private enum SECURITY_INFORMATION
{
OWNER_SECURITY_INFORMATION = 1,
GROUP_SECURITY_INFORMATION = 2,
DACL_SECURITY_INFORMATION = 4,
SACL_SECURITY_INFORMATION = 8,
}
Теперь мы почти у цели.Если вы вызываете GetSecurityInfo
следующим образом ...
uint returnValue = GetSecurityInfo(process.Handle,
SE_OBJECT_TYPE.SE_KERNEL_OBJECT,
SECURITY_INFORMATION.OWNER_SECURITY_INFORMATION,
out IntPtr ownerSid,
out IntPtr groupSid,
out IntPtr dacl,
out IntPtr sacl,
out IntPtr securityDescriptor);
... и в результате получаете ERROR_SUCESS (то есть 0
), вы можете использовать экземпляркласса SecurityIdentifier , чтобы проверить, является ли полученный SID локальной системной учетной записью или нет, например:
SecurityIdentifier securityIdentifier = new SecurityIdentifier(ownerSid);
if (securityIdentifier.IsWellKnown(WellKnownSidType.LocalSystemSid))
{
// The process is running unter the local system account.
}
Вот и все.Для достижения окончательного результата вам необходимо проверить наличие нескольких идентификаторов безопасности, таких как Система , Локальная служба , Сетевая служба и т. Д. *
Вот небольшой пример, который делает это для всех процессов на локальной машине.Конечно, вам нужно будет запустить его с правами доступа, в противном случае вы получите ошибки об отказе в доступе.
private static void Main(string[] args)
{
const uint ERROR_SUCCESS = 0;
Process[] processes = Process.GetProcesses();
foreach (Process process in processes)
{
try
{
uint returnValue = GetSecurityInfo(process.Handle,
SE_OBJECT_TYPE.SE_KERNEL_OBJECT,
SECURITY_INFORMATION.OWNER_SECURITY_INFORMATION,
out IntPtr ownerSid,
out IntPtr groupSid,
out IntPtr dacl,
out IntPtr sacl,
out IntPtr securityDescriptor);
if (returnValue != ERROR_SUCCESS)
{
// If the function succeeds, the return value is ERROR_SUCCESS.
// If the function fails, the return value is a nonzero error code defined in WinError.h.
continue;
}
SecurityIdentifier securityIdentifier = new SecurityIdentifier(ownerSid);
Console.WriteLine("Owner of process {0} is {1}", process.ProcessName, securityIdentifier);
if (securityIdentifier.IsWellKnown(WellKnownSidType.LocalSystemSid))
{
Console.WriteLine("Running under System Account");
}
}
catch (Exception e)
{
Console.WriteLine("Unable to retrieve owner for process {0}: {1}", process.ProcessName, e.Message);
}
}
Обновление:
Если вы сравните результат (с исходным ответом) со списком процессов в диспетчере задач, все равно будет расхождение.В ходе дальнейшего изучения этой проблемы я натолкнулся на статью , в которой говорится, что процессы, помеченные как критические , будут отображаться в процессах Windows . * 1107.*
Если у процесса есть видимое окно, диспетчер задач называет его «приложением».
Если процесс помечен как критический, диспетчер задач называет его «Windows».Процесс ".
В противном случае диспетчер задач называет его" фоновым процессом ".
Это можно оценить, просто вызвав IsProcessCritical .Следовательно, DllImport
необходим ...
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool IsProcessCritical(IntPtr hProcess, ref bool Critical);
... впоследствии его можно назвать так:
bool criticalProcess = false;
if (!IsProcessCritical(process.Handle, ref criticalProcess))
{
// Could not retrieve process information
}
if (criticalProcess)
{
// This is a critical process, it should be listed
// in the "Windows processes" section.
}
Хотя это звучит многообещающе, это не так- это все еще приводит к неправильным результатам.
Итак, после установки API Monitor (кстати, невероятного программного обеспечения), фильтрации и поиска по более чем 5 миллионам (уже предварительно отфильтрованных) вызовов API, я заметил, что Taskmgr.exe вызывает ExpandEnvironmentString несколько раз с аргументами, которые, по-видимому, не извлекаются до вызова.
После дальнейшего исследования (и логического вывода) я заметил, что в Taskmgr.exe есть жестко закодированный список. Его можно просто найти с помощью Process Explorer :
- Запуск обозревателя процессов
- Щелкните правой кнопкой мыши Taskmgr.exe
- Переход к строкам вкладка
- Прокрутка вниз
- Быть разочарованным
Есть следующие записи:
%windir%\explorer.exe
%windir%\system32\ntoskrnl.exe
%windir%\system32\WerFault.exe
%windir%\system32\backgroundTaskHost.exe
%windir%\system32\backgroundTransferHost.exe
%windir%\system32\winlogon.exe
%windir%\system32\wininit.exe
%windir%\system32\csrss.exe
%windir%\system32\lsass.exe
%windir%\system32\smss.exe
%windir%\system32\services.exe
%windir%\system32\taskeng.exe
%windir%\system32\taskhost.exe
%windir%\system32\dwm.exe
%windir%\system32\conhost.exe
%windir%\system32\svchost.exe
%windir%\system32\sihost.exe
Итак, мой вывод:
Решение в диспетчере задач жестко запрограммировано на основе приведенного выше списка (взято из версии для Windows 10).