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





Легенда:
  новое сообщение
  закрытая нитка
  новое сообщение
  в закрытой нитке
  старое сообщение
  • Напоминаю, что масса вопросов по функционированию форума снимается после прочтения его описания.
  • Новичкам также крайне полезно ознакомиться с данным документом.
Согласен, но... 12.01.03 14:25  Число просмотров: 1109
Автор: amirul <Serge> Статус: The Elderman
<"чистая" ссылка>
Я там выше дал прототипы ZwOpenProcessToken и ZwOpenThreadToken - юзай лучше их вместо ReferencePrimaryToken->OpenObjectByPointer
<programming>
[Win32] W2K Kernel security? Писал в internals, в ответ - тишина, может, здесь кто знает? 08.01.03 04:48  
Автор: Zef <Alloo Zef> Статус: Elderman
<"чистая" ссылка>
Как в ядре (R0) получить имя пользователя?
В идеале: не просто - текущего, а того, от чьего имени работает конкретное приложение.
вот валялся исходник в примерах... может поможет 09.01.03 05:53  
Автор: Killer{R} <Dmitry> Статус: Elderman
<"чистая" ссылка>

Q> Как SID привести к текстовому виду(например для загрузки HKEY_USERS)?
A> См.исходник:

// nearly straight from the SDK
BOOL Sid2Text( PSID ps, char *buf, int bufSize )
{
PSID_IDENTIFIER_AUTHORITY psia;
DWORD dwSubAuthorities;
DWORD dwSidRev = SID_REVISION;
DWORD i;
int n, size;
char *p;

// Validate the binary SID.

if ( ! IsValidSid( ps ) )
return FALSE;

// Get the identifier authority value from the SID.

psia = GetSidIdentifierAuthority( ps );

// Get the number of subauthorities in the SID.

dwSubAuthorities = *GetSidSubAuthorityCount( ps );

// Compute the buffer length.
// S-SID_REVISION- + IdentifierAuthority- + subauthorities- + NULL

size = 15 + 12 + ( 12 * dwSubAuthorities ) + 1;

// Check input buffer length.
// If too small, indicate the proper size and set last error.

if ( bufSize < size )
{
SetLastError( ERROR_INSUFFICIENT_BUFFER );
return FALSE;
}

// Add 'S' prefix and revision number to the string.

size = wsprintf( buf, "S-%lu-", dwSidRev );
p = buf + size;

// Add SID identifier authority to the string.

if ( psia->Value[0] != 0|psia->Value[1] != 0 )
{
n = wsprintf( p, "0x%02hx%02hx%02hx%02hx%02hx%02hx",
(USHORT) psia->Value[0], (USHORT) psia->Value[1],
(USHORT) psia->Value[2], (USHORT) psia->Value[3],
(USHORT) psia->Value[4], (USHORT) psia->Value[5] );
size += n;
p += n;
}
else
{
n = wsprintf( p, "%lu", ( (ULONG) psia->Value[5] ) +
( (ULONG) psia->Value[4] << 8 ) + ( (ULONG) psia->Value[3] << 16 ) +
( (ULONG) psia->Value[2] << 24 ) );
size += n;
p += n;
}

// Add SID subauthorities to the string.

for ( i = 0; i < dwSubAuthorities; ++ i )
{
n = wsprintf( p, "-%lu", *GetSidSubAuthority( ps, i ) );
size += n;
p += n;
}

return TRUE;
}
ntdll экспортирует функцию такую RtlConvertSidToUnicodeString 09.01.03 15:10  
Автор: amirul <Serge> Статус: The Elderman
<"чистая" ссылка>
NTSTATUS STDCALL
RtlConvertSidToUnicodeString(PUNICODE_STRING String,
PSID Sid,
BOOLEAN AllocateString);

Думаю понятно. Она тоже конвертит sid в S-1-...
Лучше не привязываться к имени, а по возможности использовать SID 08.01.03 10:14  
Автор: leo <Леонид Юрьев> Статус: Elderman
<"чистая" ссылка>
Лучше не привязываться к имени, а по возможности использовать SID.
По-хорошему "имя пользователя" должно фигурировать только в "user mode" при взаимодействии с пользователем.
А SID, он уникален, или у одного юзера он может быть разным? 08.01.03 12:02  
Автор: Zef <Alloo Zef> Статус: Elderman
<"чистая" ссылка>
Вот блин, а я тебе такую статейку в интерналсах отгрохал 08.01.03 13:59  
Автор: amirul <Serge> Статус: The Elderman
<"чистая" ссылка>
Только сейчас заметил что ее там нету.
Наверное нет глюканул или штрафанули меня втихую :-)), хотя в скрапе вроде нету.

Ладно попробую восстановить по памяти. (Повторно детально копаться и описывать все структуры в лом - если чего не хватит - пиши)
Есть функции
ZwOpenProcessToken opens the token of a process.
NTSYSAPI NTSTATUS NTAPI ZwOpenProcessToken( IN HANDLE ProcessHandle, IN ACCESS_MASK DesiredAccess, OUT PHANDLE TokenHandle ); Parameters ProcessHandle A handle to a process object. The handle must grant PROCESS_QUERY_INFORMATION access. DesiredAccess Specifies the type of access that the caller requires to the token object. This parameter can be zero, or any combination of the following flags: TOKEN_ASSIGN_PRIMARY Can be assigned as primary token TOKEN_DUPLICATE Can be duplicated TOKEN_IMPERSONATE Can be assigned as impersonation token TOKEN_QUERY Can be queried TOKEN_QUERY_SOURCE Can be queried for source TOKEN_ADJUST_PRIVILEGES Token privileges can be adjusted TOKEN_ADJUST_GROUPS Token groups can be adjusted TOKEN_ADJUST_DEFAULT Token default ACL and owner can be adjusted TOKEN_ADJUST_SESSIONID Token session id can be adjusted TOKEN_ALL_ACCESS All of the preceding + STANDARD_RIGHTS_REQUIRED TokenHandle Points to a variable that will receive the token object handle if the call is successful. Return Value Returns STATUS_SUCCESS or an error status, such as STATUS_ACCESS_DENIED or STATUS_INVALID_HANDLE.
И ZwOpenThreadToken opens the token of a thread.
NTSYSAPI NTSTATUS NTAPI ZwOpenThreadToken( IN HANDLE ThreadHandle, IN ACCESS_MASK DesiredAccess, IN BOOLEAN OpenAsSelf, OUT PHANDLE TokenHandle ); Parameters ThreadHandle A handle to a thread. The handle must grant THREAD_QUERY_INFORMATION access. DesiredAccess Specifies the type of access that the caller requires to the token object. This parameter can be zero, or any combination of the following flags: TOKEN_ASSIGN_PRIMARY Can be assigned as primary token TOKEN_DUPLICATE Can be duplicated TOKEN_IMPERSONATE Can be assigned as impersonation token TOKEN_QUERY Can be queried TOKEN_QUERY_SOURCE Can be queried for source TOKEN_ADJUST_PRIVILEGES Token privileges can be adjusted TOKEN_ADJUST_GROUPS Token groups can be adjusted TOKEN_ADJUST_DEFAULT Token default ACL and owner can be adjusted TOKEN_ADJUST_SESSIONID Token session id can be adjusted TOKEN_ALL_ACCESS All of the preceding + STANDARD_RIGHTS_REQUIRED OpenAsSelf A boolean specifying whether the security context of the process should be used to check the access to the token object. If OpenAsSelf is false, the security context of the thread is used, which may be an impersonation context. TokenHandle Points to a variable that will receive the token object handle if the call is successful. Return Value Returns STATUS_SUCCESS or an error status, such as STATUS_ACCESS_DENIED, STATUS_INVALID_HANDLE, or STATUS_NO_TOKEN. Related Win32 Functions OpenThreadToken. Remarks OpenThreadToken exposes the full functionality of ZwOpenThreadToken. TOKEN_ADJUST_SESSIONID is only valid in Windows 2000.
Хотя я бы советовал открывать именно ZwThreadToken, так как он может открыть и глобальный для процесса токен и имперсонированный токен для отдельно взятого потока. В качестве хендлов можешь передавать NtOpenProcess() и NtOpenThread() (есть в DDK).
С открытым токеном можно сделать следующее:
1) Закрыть ZwClose() или NtClose() :-))))
2) ZwQweryInformationToken()
ZwQueryInformationToken retrieves information about a token object.
NTSYSAPI NTSTATUS NTAPI ZwQueryInformationToken( IN HANDLE TokenHandle, IN TOKEN_INFORMATION_CLASS TokenInformationClass, OUT PVOID TokenInformation, IN ULONG TokenInformationLength, OUT PULONG ReturnLength ); Parameters TokenHandle A handle to a token object. The handle must grant TOKEN_QUERY access for most information classes. To query the token source TOKEN_QUERY_SOURCE access must be granted. TokenInformationClass Specifies the type of token information to be queried. The permitted values are drawn from the enumeration TOKEN_INFORMATION_CLASS, described in the following section. TokenInformation Points to a caller-allocated buffer or variable that receives the requested token information. TokenInformationLength Specifies the size in bytes of TokenInformation, which the caller should set according to the given TokenInformationClass. ReturnLength Points to a variable that receives the number of bytes actually returned to TokenInformation; if TokenInformationLength is too small to contain the available data, ReturnLength points to the number of bytes required for the available data. Return Value Returns STATUS_SUCCESS or an error status, such as STATUS_ACCESS_DENIED, STATUS_INVALID_HANDLE, STATUS_INVALID_INFO_CLASS, or STATUS_BUFFER_TOO_SMALL. Related Win32 Functions GetTokenInformation. Windows NT/2000 Native API 168 Remarks GetTokenInformation exposes the full functionality of ZwQueryInformationToken. typedef enum _TOKEN_INFORMATION_CLASS { TokenUser = 1, // 1 Y N TokenGroups, // 2 Y N TokenPrivileges, // 3 Y N TokenOwner, // 4 Y Y TokenPrimaryGroup, // 5 Y Y TokenDefaultDacl, // 6 Y Y Windows NT/2000 Native API 169 TokenSource, // 7 Y N TokenType, // 8 Y N TokenImpersonationLevel, // 9 Y N TokenStatistics, // 10 Y N TokenRestrictedSids, // 11 Y N TokenSessionld // 12 Y Y } TOKEN_INFORMATION_CLASS;

Все классы описывать не буду - опять таки в лом, здесь нужон TokenUser - инфа возвращается в следующей структуре
typedef struct _TOKEN_USER { // Information Class 1 SID_AND_ATTRIBUTES User; } TOKEN_USER, *PTOKEN_USER;
SID_AND_ATTRIBUTES - описан в winnt.h, тебе оттуда нужен SID.
Для kernel-mode имя юзера тебе не надо - не встречал ни одной фунции, работающей с ним - всем нужен только ACCESS_TOKEN. Хотя как-нить можно использовать имя только из user-mode (вывести где-нить на экран), а уж после того, как из дривера передан sid - его можно преобразовать в имя: LookupAccountSid() - описан в MSDN-е, находится в advapi32.dll

Бест регардс - если чего - пиши
Не все так просто 08.01.03 13:57  
Автор: leo <Леонид Юрьев> Статус: Elderman
<"чистая" ссылка>
Прежде всего SID - это "more general". SID не меняется при смене имени пользователя.

В пределах одного компьютера он всегда уникален для локальных юзеров и для всех объектов внутри домена. С другой стороны, например SID для локального администратора одинаков на всех инталляциях NT.

Но не все так просто, особенно при рассмотрении объектов ActiveDirectory. Для простоты можно пологать, что юзер получивший доступ к ресурсу имеет некий уникальный SID на этом ресурсе.

Более подробная информация в Platform SDK и других разделах MSDN.
Удачи!
Могу только добавить 08.01.03 14:03  
Автор: amirul <Serge> Статус: The Elderman
<"чистая" ссылка>
В состав SID входит RID (по мойму Reduced ID) - это как раз аналог uid-а для unix-а, вся остальная инфа в SID-е связана с членством в группах, правами и т.д. В общем он не просто уникален, он даже чересчур специфицирует - но одназначно преобразовать к юзеру можно
Тогда я тоже добавлю :) 08.01.03 14:23  
Автор: leo <Леонид Юрьев> Статус: Elderman
<"чистая" ссылка>
RID это relative identifier, и его смысл действительно очень близок к uid из Unix в случае одного компьютера (точнее одного local authority).
В сети (когда несколько authority) все сложнее, а в при развитой структуре Active Directory еще сложнее. Но все сводится к правильному пониманию и использованию API.

В SIDе, кроме RID, есть SID_IDENTIFIER_AUTHORITY которое может быть:
SECURITY_NULL_SID_AUTHORITY
SECURITY_WORLD_SID_AUTHORITY
SECURITY_LOCAL_SID_AUTHORITY
SECURITY_CREATOR_SID_AUTHORITY
SECURITY_NT_AUTHORITY
SECURITY_NON_UNIQUE_AUTHORITY

Поэтому доку изучать нужно обязательно! Иначе без серьезных проблем не обойдется.

Удачи.
Как обычно гоню с расшифровкой аббревиатур :-)) 08.01.03 15:45  
Автор: amirul <Serge> Статус: The Elderman
<"чистая" ссылка>
> RID это relative identifier

И это не первый случай у меня на багтраке %-))))
Ну да ладно, все остальное вроде близко к истине - и то хорошо. Надо себе в инфу добавить, что мол - перепроверяйте все, что я говорю ибо говорю, не заглядывая в доки - по памяти. А до достаточно глубокого копания с Security подсистемой (чтоб я все помнил) руки все никак не доходят (уже пару лет не доходят :-)) ). Чует мое сердце и не дойдут пока действительно не припечет.

Спасибо хоть матюкать не начинают :-))) Пока не начинают. А ведь рассеянность - один из признаков гениальности :-)))
Ух-х-х! Сенкс всем! Прямо, песнь о SIDe! 8) 08.01.03 14:44  
Автор: Zef <Alloo Zef> Статус: Elderman
Отредактировано 08.01.03 14:55  Количество правок: 1
<"чистая" ссылка>
Смотря что тебе надо 08.01.03 15:49  
Автор: amirul <Serge> Статус: The Elderman
<"чистая" ссылка>
Если выдрать именно имя юзера - то SID выковыривать надо, а если работать с security-функциями ядра, то им почти всегда (а может и не почти - не смотрел) нужен ACCESS_TOKEN и долбаться с ZwQueryInformationToken не придется
Мне нужен аналог UID (чтобы от сессии-к-сессии не менялся) 09.01.03 04:40  
Автор: Zef <Alloo Zef> Статус: Elderman
<"чистая" ссылка>
Я модернизировал Filemon, теперь он пишет лог не в память, а в файл, или в синхронном режиме отправляет в сеть (драйвер сидит в ядре, GUI к нему не нужно, все настройки при запуске из командной строки). Кроме того, он отслеживает теперь запуск и завершение процессов. Осталось сделать, чтобы он писал в лог юзера, от имени к-рого все это выполняется.
SID не меняется от сессии к сессии. Сможешь заюзать LookupAccountSID из ядра? Если нет, то пиши в лог сам SID, и сделай тулзу для анализа лога. 09.01.03 10:23  
Автор: HandleX <Александр М.> Статус: The Elderman
<"чистая" ссылка>
Еще вариант 09.01.03 15:31  
Автор: amirul <Serge> Статус: The Elderman
<"чистая" ссылка>
Вообще-то я тоже за то, чтоб писать SID, но как вариант можешь рассмотреть создание Worker thread-а (сама NT-я создает таких до фига). С синхронизацией несколько вариантов. Первое что пришло в голову: 1) Event и кусок шарового mapped файла, через который они будут инфой обмениваться 2) Поток всегда держит в дривере IRP с IOCTL-ом, а когда дриверу нужно преобразовать SID - дривер завершает этот пакет. Возвращать преобразованный SID можно или в следующем таком же IOCTL-е или (предпочтительнее) в IOCTL-е с другим кодом.

Ну есть еще варианты, но это уже не так важно. А вот процесс с этим потоком запросто может ликоваться к advapi32 и делать всю нужную работу.

ЗЫ: Кстати это очень распространенная техника. Не только user-space приложения держат драйвера, чтоб выполнять что-нить в 0-м кольце, но и сервисы держат поток в 3-м кольце, чтоб он для них что-нить делал. Стоит только поглянуть сколько процессов в системе запущено от имени SYSTEM и сколько потоков у процесса System
Есть pid, есть eprocess как получить hprocess??!!! блин, песня не кончается... 8) 09.01.03 11:22  
Автор: Zef <Alloo Zef> Статус: Elderman
<"чистая" ссылка>
Есть pid, есть eprocess как получить hprocess??!!! блин, песня не кончается... 8) 09.01.03 11:34  
Автор: cb <cb> Статус: Member
<"чистая" ссылка>
можно попробовать так:

ULONG 
KQueryPrimarySidByProcess (
   IN void* pSid, 
   IN ULONG dwSidLength,
   IN PEPROCESS pEProcess
   )
{
  if (
      pEProcess == NULL|      KeGetCurrentIrql() != PASSIVE_LEVEL
     )
    return 0;

  ULONG    dwSidLengthReal = 0;
  HANDLE   hToken = NULL;
  NTSTATUS NtStatus;// = ZwOpenProcessToken(pEProcess, TOKEN_READ, &hToken);

  void* pToken = PsReferencePrimaryToken(pEProcess);
  if (pToken != NULL)
  {
    NtStatus = ObOpenObjectByPointer(pToken, 0, 0, TOKEN_QUERY, 0, KernelMode, &hToken);
    if (NT_SUCCESS(NtStatus)) 
    {
      ULONG dwSizeOfToken = 0;
      NtStatus = ZwQueryInformationToken(hToken, TokenUser, NULL, 0, &dwSizeOfToken);
      if (NtStatus == STATUS_BUFFER_TOO_SMALL)
      {
        PTOKEN_USER pTokenUser = (PTOKEN_USER) new char[dwSizeOfToken];
        if (pTokenUser != NULL)
        {
          NtStatus = ZwQueryInformationToken(hToken, TokenUser, pTokenUser, dwSizeOfToken, &dwSizeOfToken);
          if (NT_SUCCESS(NtStatus)) 
          {
            if (RtlValidSid(pTokenUser->User.Sid) == TRUE)
            {
              dwSidLengthReal = RtlLengthSid(pTokenUser->User.Sid);
              if (dwSidLengthReal != 0 && dwSidLengthReal <= dwSidLength && pSid != NULL)
              {
                RtlCopySid(dwSidLengthReal+1, pSid, pTokenUser->User.Sid);
              }
            }
          }
          delete[] (char*) pTokenUser;
        }
      }
      ZwClose(hToken);
    }

    ObDereferenceObject(pToken);
  }
    
  return dwSidLengthReal;
}

ULONG 
KQueryImpersonationSidByThread (
   IN void* pSid, 
   IN ULONG dwSidLength,
   IN PETHREAD pEThread
   )
{
  if (
      pEThread == NULL|      KeGetCurrentIrql() != PASSIVE_LEVEL
     )
    return 0;

  ULONG    dwSidLengthReal = 0;
  HANDLE   hToken = NULL;
  NTSTATUS NtStatus;
  BOOLEAN  bCopyOnUse, bEffectiveOnly;
  SECURITY_IMPERSONATION_LEVEL Level;

  void* pToken = PsReferenceImpersonationToken(pEThread, &bCopyOnUse, &bEffectiveOnly, &Level);
  if (pToken != NULL)
  {
    NtStatus = ObOpenObjectByPointer(pToken, 0, 0, TOKEN_QUERY, 0, KernelMode, &hToken);
    if (NT_SUCCESS(NtStatus)) 
    {
      ULONG dwSizeOfToken = 0;
      NtStatus = ZwQueryInformationToken(hToken, TokenUser, NULL, 0, &dwSizeOfToken);
      if (NtStatus == STATUS_BUFFER_TOO_SMALL)
      {
        PTOKEN_USER pTokenUser = (PTOKEN_USER) new char[dwSizeOfToken];
        if (pTokenUser != NULL)
        {
          NtStatus = ZwQueryInformationToken(hToken, TokenUser, pTokenUser, dwSizeOfToken, &dwSizeOfToken);
          if (NT_SUCCESS(NtStatus)) 
          {
            if (RtlValidSid(pTokenUser->User.Sid) == TRUE)
            {
              dwSidLengthReal = RtlLengthSid(pTokenUser->User.Sid);
              if (dwSidLengthReal != 0 && dwSidLengthReal <= dwSidLength && pSid != NULL)
              {
                RtlCopySid(dwSidLengthReal, pSid, pTokenUser->User.Sid);
              }
            }
          }
          delete[] (char*) pTokenUser;
        }
      }
      ZwClose(hToken);
    }

    ObDereferenceObject(pToken);
  }
    
  return dwSidLengthReal;
}


---
Это ты где надыбал?! 10.01.03 05:16  
Автор: Zef <Alloo Zef> Статус: Elderman
<"чистая" ссылка>
я по совету amirul'а ReactOS заюзал - исключительно рульная вещь! Но там этого нет.
Дык вроде есть 10.01.03 19:07  
Автор: amirul <Serge> Статус: The Elderman
<"чистая" ссылка>
> я по совету amirul'а ReactOS заюзал - исключительно рульная
> вещь! Но там этого нет.
Не умаляя заслуг cb, но как говорили классики: "Платон мне друг..."
Для чистоты эксперимента я начал искать с нуля, как я бы искал, если б даже не знал как какие функции называются.
Запустил в FAR-е поиск по поддиректориям ntoskrnl-а (почему-то я не сомневался, что искать надо именно там :-))) ) файлов со строкой "ACCESS_TOKEN" внутри. Нашлось не так много файлов и вообщем-то я проверил все обнаруженные. Наибольший интерес представляют файлы create.c и process.c из каталога ntoskrnl\ps\

PsReferenceEffectiveToken - очень хорошая демонстрация того как из executive объектов (ethread и eprocess) вытаскивать токены (глобальный и имперсонированный)

NtOpenProcessToken (NtOpenThreadToken) - видно, что хоть в функцию и передается хэндл, из него сразу вытаскивается executive объект, на который он ссылается (ObReferenceObjectByHandle). Так что если объект уже есть - попытка сделать на него хендл - лишняя работа. Далее по ходу исполнения смотрим какие функции юзаются.

Ну а ZwQueryInformationToken там тоже есть, но о ней я узнал задолго до реактоса, так что искать не пришлось.

Можно сделать кучу других выводов, но в нашем случае из всех этих функций осталось только найти, какие экпортируются из кернела - и все. Можно конечно и напрямую со структурами работать, но это может привести к проблемам при смене сервис пака и т.д. Хотя скорее всего не приведет, так как все изменения в эти самые структуры вносятся в конец, а уже готовая часть остается без изменений.

Не сочтите за наезд :-)))) Это действительно не наезд (а всего лишь мерянье пузами :-))) )

ЗЫ: Реактос действительно недоделан во многих местах - сам все никак не дождусь человеческой реализации lsass - интересна структура SAM (а самому реверсить - ума нема :-)) ), но даже по uniplemented функциям можно многое сказать по типам и названиям аргументов.
А почему не так: Process->Token->UserAndGroups->Sid?! Только ради совместимости 11.01.03 09:17  
Автор: Zef <Alloo Zef> Статус: Elderman
<"чистая" ссылка>
с будущими версиями? Даже для Мелкософта крайне мало вероятно, что структура изменится. В крайнем случае добавят в хвост новые поля, но существующие не сдвинут и не уберут.
1  |  2 >>  »  




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


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