информационная безопасность
без паники и всерьез
 подробно о проектеRambler's Top100
Портрет посетителяАтака на Internet
BugTraq.Ru
Русский BugTraq
 Анализ криптографических сетевых... 
 Модель надежности двухузлового... 
 Специальные марковские модели надежности... 
 Doom на газонокосилках 
 Умер Никлаус Вирт 
 С наступающим 
главная обзор RSN блог библиотека закон бред форум dnet о проекте
bugtraq.ru / форум / programming
Имя Пароль
ФОРУМ
если вы видите этот текст, отключите в настройках форума использование JavaScript
регистрация





Легенда:
  новое сообщение
  закрытая нитка
  новое сообщение
  в закрытой нитке
  старое сообщение
  • Напоминаю, что масса вопросов по функционированию форума снимается после прочтения его описания.
  • Новичкам также крайне полезно ознакомиться с данным документом.
Спасибо, но не все так просто 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. Это в теории. Я сам не пробовал, но должно работать.

Удачи!
1




Rambler's Top100
Рейтинг@Mail.ru


  Copyright © 2001-2024 Dmitry Leonov   Page build time: 0 s   Design: Vadim Derkach