Легенда:
новое сообщение
закрытая нитка
новое сообщение
в закрытой нитке
старое сообщение
|
- Напоминаю, что масса вопросов по функционированию форума снимается после прочтения его описания.
- Новичкам также крайне полезно ознакомиться с данным документом.
| |
Спасибо, но не все так просто 26.01.05 21:23 Число просмотров: 1787
Автор: serge Статус: Незарегистрированный пользователь
|
В принципе, это оказалось решением проблемы (за что большое спасибо). Включение SeDebugPrivilege при помощи AdjustTokenPrivileges() помог таки раскольникову убить бабушку. Однако, вопрос остался неразрешенным: как процесс запущенный и летящий под Administrator'ом может уклоняться от топора пущенного под тем же Administrator'ом.
> если она > крутится под учётной записью, отличающейся от той, под > которой запущена "издеваемая" программа.
Дык обе они под админом крутятся!
|
<programming>
|
Winnt Security: Изменение DACL процесса. 25.01.05 21:56
Автор: serge Статус: Незарегистрированный пользователь
|
Некоторый процесс после запуска корректируют свою собственную security (это мое предположение) таким образом, что становится невозможно совершать над ним всякие манипуляции, как то: убить, поменять приоритет и т.д. И это при том, что он бегает под учетной записью Local Administrator. Но администратор может все. К примеру, достаточно к ACL папки 'System Volume Information' добавить себя родного и можно делать с её содержимым все чего душенька пожелает. Пытался по аналогии корректировать DACL процесса, однако потерпел полный крах: оказалось что Security descriptor этого 'нехорошего процесса' ничем не отличается от 'хорошего процесса' (юзал GetSecurityInfo(OpenProcess(READ_CONTROL...)...); ). Возможно вообще не в ту степь попер. У кого какие мысли?
|
|
Вот нарыл у себя... 28.01.05 09:04
Автор: Killer{R} <Dmitry> Статус: Elderman
|
ACL a;
if (InitializeAcl(&a,sizeof(ACL),ACL_REVISION)&& IsValidAcl(&a))SetSecurityInfo(GetCurrentProcess(),SE_KERNEL_OBJECT,DACL_SECURITY_INFORMATION,0,0,&a,0);
После такого процесс не убивается без привилегий отладки.
|
| |
Упс 28.01.05 21:43
Автор: serge Статус: Незарегистрированный пользователь
|
Sorry, не знаю куда глядел, когда писал в root'е, что Security Descriptor 'хорошего' процесса ничем не отличается от 'нехорошего'. Запустил тот же tool, что и раньше, и вот результат:
Так выглядит SD подопытного процесса:
O:LAG:S-1-5-21-1275210071-484763869-839522115-513D:(D;;SWRPWPWDWO;;;WD)(A;;;;;WD)
Видно, что у него нет access allowed rights, зато полно access denied связанных с directory servive(?).
Для сравнения привожу SD ни в чем не повинного Total Commander'а, всегда попадающего под горячую руку:
O:LAG:S-1-5-21-1275210071-484763869-839522115-513D:(A;;0x1f0fff;;;LA)(A;;0x1f0fff;;;SY)
|
| | |
Чего-то там странное у тебя с DACL... Вот, попробуй поюзать прогу (внутри)... 29.01.05 19:59
Автор: HandleX <Александр М.> Статус: The Elderman Отредактировано 29.01.05 20:36 Количество правок: 3
|
Дерзай, если не можешь скомпилить, можешь забрать её тут: ftp://ftp.nikol.biz/Prog/ShowProcessDACL.exe
program ShowProcessDacl;
{$APPTYPE CONSOLE}
uses SysUtils, Windows, ACLApi, AccCtrl;
Var pHndl: THandle;
Function toOEM(aStr: String): String;
Begin
Result := aStr;
UniqueString(Result);
ANSItoOEM(PChar(Result), PChar(Result));
End;
//Эти декларации взяты из winnt.h, в библиотеках Delphi этого нет
Const
ACCESS_ALLOWED_ACE_TYPE = 0;
ACCESS_DENIED_ACE_TYPE = 1;
Type
_ACE_HEADER = Packed Record
AceType, AceFlags: BYTE;
AceSize: WORD;
End;
ACE_HEADER = _ACE_HEADER;
PACE_HEADER = ^ACE_HEADER;
_ACCESS_ALLOWED_ACE = Record
Header: ACE_HEADER;
Mask: ACCESS_MASK;
SidStart: DWORD;
End;
PACCESS_ALLOWED_ACE = ^_ACCESS_ALLOWED_ACE;
_SID = Record
Revision: BYTE;
SubAuthorityCount: BYTE;
IdentifierAuthority: SID_IDENTIFIER_AUTHORITY;
SubAuthority: DWORD;
End;
TSID = _SID;
PSID = ^TSID;
Function SidToStr(aSID: PSID): String;
Var
AuthID: PSidIdentifierAuthority;
SubAuthCount: PUCHAR;
SubAuth: PDWORD;
J: Integer;
begin
Win32Check(IsValidSID(aSID));
Result := 'S-' + IntToStr(aSID.Revision) + '-';
AuthID := GetSidIdentifierAuthority(aSID);
Result := Result + IntToStr(AuthID.Value[High(AuthID.Value)]) + '-';
For J := High(AuthID.Value) - 1 DownTo Low(AuthID.Value) Do
If AuthID.Value[J] <> 0 Then
Result := Result + IntToStr(AuthID.Value[J]) + '-';
SubAuthCount := GetSIDSubAuthorityCount(aSID);
For J := 0 To SubAuthCount^ - 1 Do
Begin
SubAuth := GetSIDSubAuthority(ASID, J);
Result := Result + IntToStr(SubAuth^) + '-';
End;
J := Length(Result);
If J <> 0 Then
SetLength(Result, J - 1);
End;
Function GetAccountBySID(ServerName: String; aSID: PSID): String;
Var
nSize, dSize, pUse: DWORD;
aName, dName: PChar;
Begin
If Not IsValidSID(aSID) Then
Begin
Result := 'Erroneus SID!';
Exit;
End;
nSize := 0; dSize := 0;
If Not LookupAccountSid(PChar(ServerName), aSID, Nil, nSize, Nil, dSize, pUse) Then
If GetLastError <> ERROR_INSUFFICIENT_BUFFER Then
If GetLastError <> ERROR_NONE_MAPPED Then RaiseLastWin32Error
Else Begin
Result := SIDToStr(aSID);
Exit;
End;
aName := StrAlloc(nSize);
dName := StrAlloc(dSize);
Try
Win32Check(LookupAccountSid(PChar(ServerName), aSID, aName, nSize, dName, dSize, pUSE));
Result := aName + ' (' + dName + ')';
Finally
StrDispose(aName);
StrDispose(dName);
End;
End;
Var
TempStr: String;
SD: PPSECURITY_DESCRIPTOR; aDACL: PACL; anACE: PACCESS_ALLOWED_ACE;
anError, tempMask: DWORD;
J, I: Integer;
Const
AccessMaskStringMap: Array[0..31] Of String = (
'PROCESS_TERMINATE', 'PROCESS_CREATE_THREAD', 'PROCESS_SET_SESSIONID',
'PROCESS_VM_OPERATION', 'PROCESS_VM_READ', 'PROCESS_VM_WRITE',
'PROCESS_DUP_HANDLE', 'PROCESS_CREATE_PROCESS', 'PROCESS_SET_QUOTA',
'PROCESS_SET_INFORMATION', 'PROCESS_QUERY_INFORMATION', 'PROCESS_SUSPEND_RESUME',
'', '', '', '', 'DELETE', 'READ_DACL',
'WRITE_DACL', 'WRITE_OWNER', 'SYNCHRONIZE', '', '', '', 'Access System ACL',
'', '', '', '', '', '', ''
);
Procedure EnableDebugPrivilege;
Const
SE_DEBUG_NAME = 'SeDebugPrivilege';
Var
HToken: THandle;
tkp: TOKEN_PRIVILEGES;
Begin
Win32Check(OpenProcessToken(GetCurrentProcess, TOKEN_ADJUST_PRIVILEGES Or TOKEN_QUERY, hToken));
Win32Check(LookupPrivilegeValue(Nil, SE_DEBUG_NAME, tkp.Privileges[0].Luid));
tkp.PrivilegeCount := 1;
tkp.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED;
Win32Check(AdjustTokenPrivileges(HToken, False, tkp, 0, Nil, PDWORD(Nil)^));
End;
begin
Try
If ParamCount < 1 Then
Raise Exception.Create('Process ID must be first input parameter! Application terminated.');
pHndl := OpenProcess(READ_CONTROL, False, StrToInt(ParamStr(1)));
If pHndl = 0 Then
If GetLastError = ERROR_ACCESS_DENIED Then
Begin
Write(Format('Access to process ID %s denied, try to enable debug privilege? (Y/N):', [ParamStr(1)]));
ReadLn(TempStr);
If (Length(TempStr) = 1) and (TempStr[1] in ['y', 'Y'])
Then EnableDebugPrivilege Else Exit;
pHndl := OpenProcess(READ_CONTROL, False, StrToInt(ParamStr(1)));
End;
If pHndl = 0 Then RaiseLastWin32Error;
Try
anError := GetSecurityInfo(pHndl, SE_KERNEL_OBJECT, DACL_SECURITY_INFORMATION, Nil, Nil, @aDACL, Nil, SD);
If anError <> Error_Success Then
Begin
SetLastError(anError);
RaiseLastWin32Error;
End;
Try
//На этом этапе имеем Security Descriptor (в SD). Начинаем его "ковырять"...
WriteLn('DACL information for Process ID ', ParamStr(1));
WriteLn('ACEs count: ', aDACL.AceCount);
If aDACL.AceCount = 0 Then
Begin
WriteLn('Nothing to show!');
Exit;
End;
WriteLn('Start dumping...');
WriteLn;
//Вытаскиваем ACE's...
For J := 0 To aDACL.AceCount - 1 Do
Begin
If Not GetACE(aDACL^, J, Pointer(anACE)) Then RaiseLastWin32Error;
Case anACE.Header.AceType Of
ACCESS_ALLOWED_ACE_TYPE: TempStr := 'Allowed';
ACCESS_DENIED_ACE_TYPE: TempStr := 'Denied';
else TempStr := 'Unknown';
End;
//Выводим пользователя в этом ACE...
Writeln(
'Access ', TempStr, ' Ace (at index ', J, ') for user "',
toOEM(GetAccountBySID('', @anACE.SidStart)), '"'
);
WriteLn('Access mask:');
//Выводим AccessRights для ACE:
For I := 0 To 31 Do
Begin //Проверяем каждый бит в 32-битной маске доступа...
TempMask := 1 shl I;
If (anACE.Mask And TempMask) = TempMask Then
WriteLn(' ', AccessMaskStringMap[I]); //Выводим описание бита в маске доступа
End;
WriteLn;
End;
Writeln(aDACL.AceCount, ' ACE(s) printed successfully.');
Finally
LocalFree(DWORD(SD));
End;
Finally
CloseHandle(pHndl);
End;
Writeln('This program written by HandleX. Enjoy it!');
Write ('Press ENTER to continue...');
ReadLN;
Except
On E: Exception Do
If Not (E is EAbort) Then
Begin
WriteLn('Exception Class ' + E.ClassName + ' occured.');
WriteLn('Error: "' + toOEM(E.Message) + '"');
WriteLn('Program terminated.');
End;
End;
end.
---
|
| | | |
А с DACL то все в порядке 30.01.05 11:59
Автор: serge Статус: Незарегистрированный пользователь
|
DACL information for Process ID 1116
ACEs count: 2
Start dumping...
Access Allowed Ace (at index 0) for user "Administrator (HOME-LL5T6GVTC1)"
Access mask:
PROCESS_TERMINATE
PROCESS_CREATE_THREAD
PROCESS_SET_SESSIONID
PROCESS_VM_OPERATION
PROCESS_VM_READ
PROCESS_VM_WRITE
PROCESS_DUP_HANDLE
PROCESS_CREATE_PROCESS
PROCESS_SET_QUOTA
PROCESS_SET_INFORMATION
PROCESS_QUERY_INFORMATION
PROCESS_SUSPEND_RESUME
DELETE
READ_DACL
WRITE_DACL
WRITE_OWNER
SYNCHRONIZE
Access Allowed Ace (at index 1) for user "SYSTEM (NT AUTHORITY)"
Access mask:
PROCESS_TERMINATE
PROCESS_CREATE_THREAD
PROCESS_SET_SESSIONID
PROCESS_VM_OPERATION
PROCESS_VM_READ
PROCESS_VM_WRITE
PROCESS_DUP_HANDLE
PROCESS_CREATE_PROCESS
PROCESS_SET_QUOTA
PROCESS_SET_INFORMATION
PROCESS_QUERY_INFORMATION
PROCESS_SUSPEND_RESUME
DELETE
READ_DACL
WRITE_DACL
WRITE_OWNER
SYNCHRONIZE
2 ACE(s) printed successfully.
This program written by HandleX. Enjoy it!
Press ENTER to continue...
Так це ж одно и тоже, что и D:(A;;0x1f0fff;;;LA)(A;;0x1f0fff;;;SY),
просто места больше занимает, не только output, но и программный код(у меня - 4 строчки) :) . Конечно, ничуть не умаляю заслуги мистера HandleX, наколбасившего такую удобную прогу.
|
| | | | |
Зачит, с твоим процессом не всё в порядке... 31.01.05 13:14
Автор: HandleX <Александр М.> Статус: The Elderman Отредактировано 31.01.05 13:14 Количество правок: 1
|
> Так це ж одно и тоже, что и > D:(A;;0x1f0fff;;;LA)(A;;0x1f0fff;;;SY), > просто места больше занимает, не только output, но и > программный код(у меня - 4 строчки) :) . Это твой код? Значит вывод его тебе и понятен... Можно вообще весь DACL в Hex Dump выгнать, и разбирайтесь люди добрые, как хотите... ;-)
А теперь, возвращаясь к нашим баранам, то бишь к процессам, остаётся с прискорбием констатировать факт, что если Debug privilege при убийстве процесса не помогает, значет этот процесс вызвал функцию ядра, и не получил назад управление. Такое бывает в виндах. Се ля ви.
|
| | | | | |
ACL strings 01.02.05 12:35
Автор: serge Статус: Незарегистрированный пользователь
|
> Это твой код?
Нет, не мой. Он частенько используется при написании админовских скриптов (сисадмины подскажут). Описан он в MSDN (ACL strings, SD string format ...) , получить его можно легко вызовом ConvertSecurityDescriptorToStringSecurityDescriptor из sddl.h
|
| | | | | | |
Sorry, я на NT4 воспитан, там этого не было... ;-) 01.02.05 12:57
Автор: HandleX <Александр М.> Статус: The Elderman Отредактировано 01.02.05 13:58 Количество правок: 1
|
|
|
Программа, которая хочет поиздеваться над другим процессом,... 26.01.05 16:18
Автор: HandleX <Александр М.> Статус: The Elderman
|
> Возможно вообще не в ту степь попер. У кого какие мысли? Subj ... должна включать себе SE_DEBUG_PRIVILEGE, если она крутится под учётной записью, отличающейся от той, под которой запущена "издеваемая" программа.
К примеру, Far Manager, когда пытается прибить чужой процесс, честно предупреждает о включении для себя этой привилегии. Виндовозный диспетчер задач эту привелегию не включает. Я думаю, это именно твой случай. Выход: использовать Far или написать софтину, включающую SE_DEBUG_PRIVILEGE для диспетчера задач, а потом им можно делать твои эксперименты ;-)
|
| |
Спасибо, но не все так просто 26.01.05 21:23
Автор: serge Статус: Незарегистрированный пользователь
|
В принципе, это оказалось решением проблемы (за что большое спасибо). Включение SeDebugPrivilege при помощи AdjustTokenPrivileges() помог таки раскольникову убить бабушку. Однако, вопрос остался неразрешенным: как процесс запущенный и летящий под Administrator'ом может уклоняться от топора пущенного под тем же Administrator'ом.
> если она > крутится под учётной записью, отличающейся от той, под > которой запущена "издеваемая" программа.
Дык обе они под админом крутятся!
|
| | |
Попробуй pview из support tools 27.01.05 00:21
Автор: AlexD <Alexander> Статус: Member
|
покопайся ей в token'ах процесса всяких
|
| | | |
А где такой зверь водится? 28.01.05 08:02
Автор: serge Статус: Незарегистрированный пользователь
|
Вообще-то мне пришлось в процессе моих изысканий состряпать две тулсы для распечатки всяких там token'ов. Но за последние два дня у меня сложилось впечатление, что access token'ы отвечают за то что может делать процесс, а не за то что с ним можно делать. За это, вроде бы, отвечает DACL?
Кстати, нашел PViewer в стандартной поставке Support Tools WinXP и Win2kAS, но ни один из них, по крайней мере на первый взгляд, не обладает способностью к просмотру securit'ей. Какой pview имелся в виду?
|
| | | | |
За "первоначальный" ACL процесса отвечает CreateProcess() при его создании... 28.01.05 08:47
Автор: HandleX <Александр М.> Статус: The Elderman
|
> Вообще-то мне пришлось в процессе моих изысканий состряпать > две тулсы для распечатки всяких там token'ов. Но за > последние два дня у меня сложилось впечатление, что access > token'ы отвечают за то что может делать процесс, а не за то > что с ним можно делать. За это, вроде бы, отвечает DACL? Всё верно - токены содержат в себе инфу о том, что может делать процесс. А что другие могут делать с процессом -- всё зависит от того, что сунули при его создании в параметр lpProcessAttributes вызова CreateProcess(). Обычно туда пихают NULL, и винда по своим правилам шлёпает стандартные атрибуты.
Потом, когда процесс работает, эту инфу можно вытаскивать и устанавливать соотв. вызовами GetSecurityInfo() и SetSecurityInfo() c параметром ObjectType равным SE_KERNEL_OBJECT. Это в теории. Я сам не пробовал, но должно работать.
Удачи!
|
|
|