uses TlHelp32; type PTOKEN_USER = ^TOKEN_USER; _TOKEN_USER = record User:
TSidAndAttributes; end; TOKEN_USER = _TOKEN_USER; function GetUserAndDomainFromPID(ProcessId: DWORD;
var
User, Domain: string): Boolean; var hToken:
THandle; cbBuf:
Cardinal; ptiUser:
PTOKEN_USER; snu:
SID_NAME_USE; ProcessHandle: THandle; UserSize, DomainSize: DWORD; bSuccess: Boolean; begin Result
:= False; ProcessHandle := OpenProcess(PROCESS_QUERY_INFORMATION,
False, ProcessId); if
ProcessHandle <> 0
then begin //
EnableProcessPrivilege(ProcessHandle, 'SeSecurityPrivilege', True);
if
OpenProcessToken(ProcessHandle, TOKEN_QUERY, hToken) then
begin
bSuccess := GetTokenInformation(hToken, TokenUser, nil, 0,
cbBuf);
ptiUser := nil;
while (not
bSuccess) and
(GetLastError = ERROR_INSUFFICIENT_BUFFER) do
begin
ReallocMem(ptiUser, cbBuf);
bSuccess := GetTokenInformation(hToken, TokenUser, ptiUser, cbBuf,
cbBuf);
end;
CloseHandle(hToken);
if
not
bSuccess then
begin
Exit;
end;
UserSize := 0;
DomainSize := 0;
LookupAccountSid(nil,
ptiUser.User.Sid, nil,
UserSize, nil,
DomainSize, snu);
if
(UserSize <> 0)
and
(DomainSize <> 0)
then
begin
SetLength(User, UserSize);
SetLength(Domain, DomainSize);
if
LookupAccountSid(nil,
ptiUser.User.Sid, PChar(User), UserSize,
PChar(Domain), DomainSize, snu) then
begin
Result := True;
User := StrPas(PChar(User));
Domain := StrPas(PChar(Domain));
end;
end;
if
bSuccess then
begin
FreeMem(ptiUser);
end;
end;
CloseHandle(ProcessHandle); end; end; procedure TForm1.Button1Click(Sender: TObject); var hProcSnap: THandle; pe32:
TProcessEntry32; Domain,
User: string; s:
string; begin hProcSnap := CreateToolHelp32SnapShot(TH32CS_SNAPALL,
0); if
hProcSnap = INVALID_HANDLE_VALUE then Exit; pe32.dwSize := SizeOf(ProcessEntry32); if
Process32First(hProcSnap, pe32) = True then
while Process32Next(hProcSnap, pe32) = True do
begin
if
GetUserAndDomainFromPID(pe32.th32ProcessID, User, Domain) then
begin s
:= Format('%s User: %s ;
Domain: %s',[StrPas(pe32.szExeFile), User, Domain]);
Listbox1.Items.Add(s);
end
else
Listbox1.Items.Add(StrPas(pe32.szExeFile));
end; CloseHandle(hProcSnap); end;
Here is a translation of the content into Russian:
Код на Delphi, который получает информацию о пользователе и домене для каждого процесса, запущенного на системе, используя функции Windows API OpenProcessToken, GetTokenInformation и LookupAccountSid. Код использует unit TlHelp32 для взаимодействия с Windows API.
Вот разбивка кода:
Первая часть определяет тип записи PTOKEN_USER и переменную TOKEN_USER, которая используется для хранения информации о пользователе.
Функция GetUserAndDomainFromPID принимает идентификатор процесса, строку для имени пользователя и строку для имени домена в качестве параметров входа. Она возвращает булевое значение, указывающее, была ли операция успешной.
Внутри этой функции:
Открывается handle процесса с помощью OpenProcess.
Затем пытается открыть токен для процесса с помощью OpenProcessToken. Если это успешно, то получает информацию о пользователе из токена с помощью GetTokenInformation и выделяет память для нее с помощью ReallocMem.
Если буфер недостаточен, то продолжает реаллокировать память, пока не может хранить всю информацию о пользователе.
Затем закрывает handle и проверяет, была ли операция успешной. Если нет, то выходит из функции.
Если успешно, то получает имя домена из SID пользователя с помощью LookupAccountSid и хранит его в предоставленных строках.
Основная часть кода определяет процедуру Button1Click, которая вызывается при клике кнопки. Эта процедура:
Создает снимок процесса с помощью CreateToolHelp32SnapShot.
Итерирует по каждому процессу в снимке с помощью Process32First и Process32Next.
Для каждого процесса вызывает функцию GetUserAndDomainFromPID, чтобы получить информацию о пользователе и домене. Если успешно, то форматирует строку с этой информацией и добавляет ее в список.
Альтернативное решение, использующее более современный и безопасный подход:
Вместо использования OpenProcessToken и GetTokenInformation, можно использовать функцию QueryFullProcessImageName из unit Kernel32, чтобы получить имя пользователя и домена для каждого процесса. Это safer, потому что не требует handle токена.
Замечание: я определил две новые функции GetUserNameForProcess и GetDomainForProcess, которые не реализованы здесь. Вы можете реализовать их с помощью функций Windows API GetUserName и LookupAccountSid.
Из статьи можно узнать домен и имя пользователя владельца процесса с помощью функции GetUserAndDomainFromPID.
Комментарии и вопросы
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.