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





Легенда:
  новое сообщение
  закрытая нитка
  новое сообщение
  в закрытой нитке
  старое сообщение
  • Напоминаю, что масса вопросов по функционированию форума снимается после прочтения его описания.
  • Новичкам также крайне полезно ознакомиться с данным документом.
Спасибо, но не все так просто 26.01.05 21:23  Число просмотров: 1667
Автор: 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-2022 Dmitry Leonov   Page build time: 0 s   Design: Vadim Derkach