HOME FORUMS MEMBERS RECENT POSTS LOG IN  
× Авторизация
Имя пользователя:
Пароль:
Нет аккаунта? Регистрация
Баннер 1   Баннер 2
НОВЫЕ ТОРГОВАЯ НОВОСТИ ЧАТ
loading...
Скрыть
Вернуться   ANTICHAT > БЕЗОПАСНОСТЬ И УЯЗВИМОСТИ > Безопасность и Анонимность > Защита ОС: вирусы, антивирусы, файрволы.
   
 
 
Опции темы Поиск в этой теме Опции просмотра

  #1  
Старый 13.06.2021, 17:12
Marylin
Постоянный
Регистрация: 01.09.2019
Сообщений: 378
С нами: 3526561

Репутация: 0
По умолчанию

Все, кто хоть немного дорожит своей информацией, направляют фокус на её защиту. Учитывая эти обстоятельства, начиная ещё с Win-2k инженеры Microsoft ввели в состав своей ОС специальный интерфейс и назвали его "Data-Protection Programming Interface", или коротко DPAPI. В результате, не прибегая к услугам внешних библиотек, у нас появилась возможность защищать свои данные вполне крипткостойким механизмом, причём эти данные могут находиться как на жёстком диске, так и непосредственно в памяти. В состав этого интерфейса входят всего 4 функции, однако практическая его реализация довольно сложна и корнями уходит в нёдра операционной системы, иначе DPAPI не получил-бы столь высокий кредит доверия в высшем обществе. В данной статье рассматриваются технические детали этого интерфейса, и некоторые советы к области его применения.

Содержание:


1. Data Protect – основная идея;
2. Функции DPAPI из библиотеки crypt32.dll;
3. Практика – реверс интерфейса DPAPI;
4. Алгоритм поиска Master-Key;
5. Постскриптум.
-------------------------------------------------------

1. DataProtect– основная идея

В программистcких кругах бытует мнение, что для защиты критически важных данных лучше применять не стандартные методы (которые предлагает нам система), а выстраивать крепость вручную, щедро разбавляя программный код обратимыми математическими формулами от-фонаря. Аргументируются доводы тем, что мол все системные алгоритмы шифрования уже давно изучены, и с их взломом не сталкивался только ленивый. Если учесть вычислительные возможности современных процессоров, то доля правды в этом есть – элементарный брутфорс с применением радужных таблиц рано или поздно всё-же даст результат, не говоря уже о более продуманном подходе.

Но проблема в том, что какую-бы высшую математику мы не применили, сам алгоритм остаётся всегда на поверхности и при интерактивной отладке сразу-же всплывёт на поверхность. На вопрос "как спрятать его от посторонних глаз?" можно смело ответить – никак! Это напоминает эффект-плацебо, когда мы тупо верим в пользу некоторого действия, в реале нейтрального, прямой эффект которого не наблюдается.

Однако любую критику выдерживает герой этой статьи – механизм шифрования данных DPAPI. Только столкнувшись с его реверсом понимаешь, что разрабатывался он с уклоном на то, чтобы закрыть данные не только от различного рода кодокопателей, но при некоторых обстоятельствах и от самой системы. Достичь такого уровня позволяет передача данных по закрытым каналам ALPC/RPC, что подразумевает локальный (Advanced Local) и удалённый вызов системных процедур из пользовательского режима (Remote Procedure Call). Другими словами, при вызове функций DPAPI происходит переключение контекста из юзера в кернел, где и осуществляется вся магия непосредственного шифрования.

Такой расклад привлёк внимание сразу нескольких независимых групп, которые занялись анализом интерфейса DPAPI. Первыми, результатов добилась команда из фирмы "Passcape Software" ещё в 2003 году, которым удалось полностью обратить никак недокументированный на тот момент алгоритм защиты Microsoft. По их докладу стало известно, что в процессе шифрования, DPAPI использует три составляющие – это т.н. "мастер-ключ", идентификатор безопасности пользователя SID (Security Identifiers), и хеш от пароля юзера на вход в систему. Гремучая смесь этих составляющих даёт на выходе невероятно прочную стену, пробить которую юзермодным отладчикам становится не под силу.

Как мы узнаем позже, под своей учётной записью, системный мастер-ключ и SID юзера добыть не проблема, а вот с паролем могут возникнуть трудности, т.к. его хеш зарыт в недоступной никому области памяти системного процесса lsass.exe. Именно для доступа к паролю, код интерфейса DPAPI использует закрытые каналы Lsass и SRM, по которым гоняет служебные запросы и данные. Пройдя этап переработки и метаболизма, шифруемые данные из ядра через эти-же каналы возвращаются опять в приложение юзера. Конечно можно сдампить память процесса lsass в свой бокс, но выташить потом из этого дампа пароль находясь в офлайне – задача не простая. В грубой форме это выглядит примерно так:




Ядерный монитор безопасности SRM и пользовательский процесс Lsass обмениваются данными при помощи механизма ALPC (см.рис.выше). В ходе инициализации системы, SRM и Lsass создают свои порты (SeRmCmdPort и SeLsaCmdPort соответственно), после чего присовокупляются друг к другу. Это приводит к созданию закрытого коммуникационного канала связи. Один раз создав соединение при загрузке системы, как SRM так и Lsass больше не разрывают его, поэтому "любопытные" процессы юзера не имеют возможности подключиться к ним – запросы на коннект будут в мёртвом цикле крутится в кольцевом буфере АLPC, или попросту отвергаться.

Система безопасности Win разделяет права своих пользователей при помощи трёх составляющих – это учётные записи юзеров, их пароли, и защита принадлежащих этим юзерам личных файлов. Рассмотрим, каким образом каждый из перечисленных аспектов архитектуры влияет на выполнение жёстких требований безопасности. В неё входят следующие компоненты и привязанные к ним базы-данных:


• SRM – Security Reference Monitor, или глобальный монитор безопасности. Находится в исполняющей подсистеме ядра Ntoskrnl.exe, и отвечает за: (1) оформление "маркеров доступа" (токенов) для предоставления контекста безопасности, (2) выполнение проверок доступа к объектам, (3) работу с привилегиями (правами) пользователей.

• LSASS – Local Security Authority Sub-System. Это процесс пользовательского режима Lsass.exe, который отвечает за политику безопасности системы и аутентификацию всех пользователей. Функционал реализован в библиотеке Lsasrv.dll. Более того, в Lsass хранится зашифрованный двоичный объект хеша SHA-512 от пароля юзверя, на который опирается весь интерфейс DPAPI. Кстати такие процессы называют ещё "транслеты" – изолированные процессы ядра в пользовательском режиме.

• Lsa-база, где хранятся настройки политики безопасности системы. Она прописана в ACL-закрытой ветке реестра HKLM\SECURITY (Access Control List, список управления доступом). По информации из этой базы система определяет, у кого есть права на доступ к нёдрам системы, кому из них и какие конкретно привилегии назначены.

• SAM – Security Accounts Manager, или администратор учётных записей. Сервис samsrv.dll загружается в процесс Lsass и отвечает за управление базой с именами пользователей, и поддержки групп на локальной машине. Привязанная к нему база содержит данные локальных юзеров и групп, наряду с их паролями и другими атрибутами безопасности. База хранится в защищённой ветке реестра HKLM\SAM.

Системный транслет Lsass.exe довольно творческая единица, и загружает в своё пространство множество библиотек для решения различного круга задач. В контексте данной статьи нас будут интересовать: lsasrv, samsrv, authz и crypt32.dll (где и сосредоточены собственно функции DPAPI). Консольная утилита tasklist.exe с одноимённым фильтром(/fi) и аргументом(/m) возвращает список всех загруженных в процесс библиотек, что продемонстрированно на скрине ниже. Обратите внимание, сколько имеется модулей, где фигурирует слово "crypt" (я насчитал их 7):



Что касается баз LSA и SAM, то они не доступны в реестре смертным пользователям,
однако просмотреть их содержимое можно утилитой "PsExec" из комплекта "SysInternals" Марка Руссиновича:



2. Функции DPAPIиз библиотеки crypt32.dll

Выше упоминалось, что в интерфейс "Data-Protect-API" входят всего 4 функции – это CryptProtectData() для шифрования данных, и CryptUnprotectData() для их-же расшифровки. Есть ещё пара аналогичных функций, только для шифрования данных прямо в памяти CryptProtectMemory(), но они применяются довольно редко, поэтому останавливаться на них не будем. У всех этих функций прототипы одинаковы и выглядят так:


C-подобный:


Код:
BOOL
CryptProtectData
(
;
//
;
//-- Запрос на ввод пароля и узнаём его длину
cinvoke  printf
,

cinvoke  scanf
,

,
buff
          invoke  lstrlen
,
buff
;
//-- Оформляем входную структуру DATA_BLOB и шифруем пароль!
mov
[
inBlob
.
dataSize
]
,
eax
          mov
[
inBlob
.
pData
]
,
buff
          invoke  CryptProtectData
,
inBlob
,
0
,
0
,
0
,
0
,
0
,
outBlob
;
//-- Получили выходную структуру DATA_BLOB – покажем инфу из неё
mov     ecx
,
[
outBlob
.
dataSize
]
mov     esi
,
[
outBlob
.
pData
]
push    esi ecx
         cinvoke  printf
,

,
ecx
,
esi
          pop     ecx esi
          call    PrintHexDump
;
//************************************************************
;
//-- Проецируем структуру DPAPI_DATABLOB на полученные данные,
;
//-- и выводим их на консоль.
cinvoke  printf
,

mov     esi
,
[
outBlob
.
pData
]
mov     eax
,
[
esi
+
DPAPI_DATABLOB
.
dwVersion
]
cinvoke  printf
,

,
eax

          mov     esi
,
[
outBlob
.
pData
]
push    esi esi
          add     esi
,
DPAPI_DATABLOB
.
ProvGuid
          invoke  StringFromGUID2
,
esi
,
buff
,
dwRet
         cinvoke  printf
,

,
buff

          pop     esi
          add     esi
,
DPAPI_DATABLOB
.
MasterKeyGuid
          invoke  StringFromGUID2
,
esi
,
buff
,
dwRet
         cinvoke  printf
,

,
buff

          pop     esi
          mov     eax
,
[
esi
+
DPAPI_DATABLOB
.
dwFlags
]
cinvoke  printf
,

,
eax

          mov     esi
,
[
outBlob
.
pData
]
mov     eax
,
[
esi
+
DPAPI_DATABLOB
.
dwDataDescLen
]
push    esi eax
         cinvoke  printf
,

,
eax
          pop     ecx esi
          add     esi
,
DPAPI_DATABLOB
.
szDataDesc
          push    esi ecx
          call    PrintHexString

          pop     ecx esi
          add     esi
,
ecx
;
//
,
ebx
,
edx

          pop     esi
          add     esi
,
4
lodsd
          push    eax esi eax esi
         cinvoke  printf
,

,
eax
          pop     esi ecx
          or      ecx
,
ecx
          je      @f
;
//
,
eax
          pop     esi ecx
          or      ecx
,
ecx
          je      @f
          call    PrintHexString

@@
:
pop     esi eax
          add     esi
,
eax
          lodsd
          push    esi
          mov     ebx
,
eax
          mov     esi
,
HashTable
          mov     ecx
,
13
call    GetAlgorithm
         cinvoke  printf
,

,
ebx
,
edx

          pop     esi
          add     esi
,
4
lodsd
          push    eax esi eax esi
         cinvoke  printf
,

,
eax
          pop     esi ecx
          or      ecx
,
ecx
          je      @f
          call    PrintHexString

@@
:
pop     esi eax
          add     esi
,
eax
          lodsd
          push    eax esi eax esi
         cinvoke  printf
,

,
eax
          pop     esi ecx
          or      ecx
,
ecx
          je      @f
          call    PrintHexString

@@
:
pop     esi eax
          add     esi
,
eax
          lodsd
          push    eax esi
         cinvoke  printf
,

,
eax
          pop     esi ecx
          or      ecx
,
ecx
          je      @exit
          call    PrintHexString

@exit
:
cinvoke  _getch
;
//
pop     ecx
          mov     ebp
,
32
@miss0
:
xor     eax
,
eax
          lodsb
          push    ecx esi
         cinvoke  printf
,

,
eax
;
//
pop     ecx
          mov     ebp
,
16
@miss1
:
xor     eax
,
eax
          lodsb
          push    ecx esi ebp
         cinvoke  printf
,

,
eax
;
//
;
//-- Формируем путь до файла "Master-Key"
invoke  SHGetFolderPathA
,
0
,
CSIDL_APPDATA
,
0
,
0
,
userPath
          invoke  lstrcat
,
userPath
,
keyPath
;
//-- Вычисляем имя папки SID, с ключами пользователя
invoke  FindFirstFile
,
userPath
,
fd
          mov
[
hndl
]
,
eax
@find0
:
cmp     dword
[
fd
.
cFileName
]
,
'S-1-'
je      @found0
          invoke  FindNextFile
,
[
hndl
]
,
fd
          or      eax
,
eax
          jnz     @find0
         cinvoke  printf
,

jmp     @exit
;
//-- Каталог нашли – покажем SID юзера (имя папки)
@found0
:
invoke  FindClose
,
[
hndl
]
cinvoke  printf
,

,
fd
.
cFileName
;
//-- Добавляем к пути имя папки, чтобы открыть её
mov     edi
,
userPath
          xor     ecx
,
ecx
          dec     ecx
          mov     al
,
'*'
repne   scasb
          dec     edi
          mov     byte
[
edi
]
,
0
invoke  lstrcat
,
userPath
,
fd
.
cFileName
          invoke  lstrcat
,
userPath
,
preferred
;
//-- Прочитать из папки SID файл "Preferred"
invoke  _lopen
,
userPath
,
0
or      eax
,
eax
;
// ошибка?
jns     @next
         cinvoke  printf
,

jmp     @exit
@next
:
push    eax
          invoke  _lread
,
eax
,
buff
,
24
;
// читаем файл в буфер
pop     eax
          invoke  _lclose
,
eax
;
//-- Покажем время действия мастер-ключа, из последних 8-байт файла "Preferred"
mov     eax
,
buff
          add     eax
,
24
-
8
invoke  FileTimeToSystemTime
,
eax
,
sysTime
          movzx   ecx
,
word
[
sysTime
.
wYear
]
movzx   ebx
,
word
[
sysTime
.
wMonth
]
movzx   eax
,
word
[
sysTime
.
wDay
]
movzx   edx
,
word
[
sysTime
.
wHour
]
movzx   esi
,
word
[
sysTime
.
wMinute
]
cinvoke  printf
,

,
\
                          eax
,
ebx
,
ecx
,
edx
,
esi
;
//-- Вытащим из файла "Preferred" GUID активного ключа,
;
//-- и переведём его из Unicode в ANSI
invoke  StringFromGUID2
,
buff
,
fName
,
dwRet
          mov     esi
,
fName
          mov     edi
,
esi
          mov     byte
[
esi
]
,
'\'
@@
:
lodsw
          cmp     al
,
'}'
je      @f
          stosb
          jmp     @b
@@
:
mov     byte
[
edi
]
,
0
;
//-- Наконец добавим к пути Guid в виде имени файла-ключа
invoke  lstrlen
,
userPath
          mov     esi
,
userPath
          add     esi
,
eax
          sub     esi
,
10
mov     byte
[
esi
]
,
0
invoke  lstrcat
,
userPath
,
fName
;
//-- Читаем файл мастер-ключа в свой буфер
invoke  _lopen
,
userPath
,
0
or      eax
,
eax
;
// ошибка?
jns     @open
         cinvoke  printf
,

jmp     @exit
@open
:
push    eax
          invoke  _lread
,
eax
,
buff
,
468
pop     eax
          invoke  _lclose
,
eax
;
//*******************************************************
;
//-- Проецируем структуру MASTERKEY_HEADER на данные файла-ключа,
;
//-- и выводим всю инфу на консоль.
cinvoke  printf
,

mov     esi
,
buff
          push    esi
          mov     eax
,
[
esi
+
MASTERKEY_HEADER
.
dwVersion
]
cinvoke  printf
,

,
eax
,
eax

          pop     esi
          add     esi
,
MASTERKEY_HEADER
.
szGuid
         cinvoke  printf
,

,
esi

          mov     esi
,
buff
          mov     eax
,
[
esi
+
MASTERKEY_HEADER
.
dwPolicy
]
mov     ebx
,
[
esi
+
MASTERKEY_HEADER
.
dwUserKeySize
]
mov     ecx
,
[
esi
+
MASTERKEY_HEADER
.
dwLocalEncKeySize
]
mov     edx
,
[
esi
+
MASTERKEY_HEADER
.
dwLocalKeySize
]
mov     edi
,
[
esi
+
MASTERKEY_HEADER
.
dwDomainKeySize
]
cinvoke  printf
,

,
\
                          eax
,
eax
,
ebx
,
ebx
,
ecx
,
ecx
,
edx
,
edx
,
edi
,
edi

         cinvoke  printf
,

mov     esi
,
buff
          push    esi
          mov     eax
,
[
esi
+
MASTERKEY_HEADER
.
Version
]
cinvoke  printf
,

,
eax
,
eax
          pop     esi
          add     esi
,
MASTERKEY_HEADER
.
pSalt
          mov     ecx
,
16
call    PrintHexString

          mov     esi
,
buff
          mov     eax
,
[
esi
+
MASTERKEY_HEADER
.
dwRounds
]
cinvoke  printf
,

,
eax
,
eax

          mov     esi
,
buff
          mov     ebx
,
[
esi
+
MASTERKEY_HEADER
.
HMACAlgId
]
mov     ecx
,
13
mov     esi
,
HashTable
          call    GetAlgorithm
         cinvoke  printf
,

,
ebx
,
edx

          mov     esi
,
buff
          mov     ebx
,
[
esi
+
MASTERKEY_HEADER
.
CryptAlgId
]
mov     ecx
,
4
mov     esi
,
CryptTable
          call    GetAlgorithm
         cinvoke  printf
,

,
,
ebx
,
edx
          mov     esi
,
buff
          mov     ecx
,
[
esi
+
MASTERKEY_HEADER
.
dwUserKeySize
]
add     esi
,
MASTERKEY_HEADER
.
pKey
          call    PrintHexString

@exit
:
cinvoke  _getch
         cinvoke  exit
,
0
;
//------------
;
//----- Процедура вывода дампа на консоль --------------
;
//----- на входе: ESI = указатель на данные, ECX = длина
proc PrintHexString
          mov     ebp
,
16
@@
:
or      ebp
,
ebp
          jnz     @miss
          push    ecx
         cinvoke  printf
,

pop     ecx
          mov     ebp
,
16
@miss
:
xor     eax
,
eax
          lodsb
          push    ecx esi ebp
         cinvoke  printf
,

,
eax
          pop     ebp esi ecx
          dec     ebp
          loop    @b
          ret
endp
;
//----- Процедура поиска алгоритмов --------------
;
//----- на входе:  EBX = код алгоритма, ESI = указатель на таблицу, ECX = длина таблицы
;
//----- на выходе: EDX = указатель на строку с именем (см.инклуд DPAPI.INC)
proc  GetAlgorithm
          mov     edx
,
unk
@findAlgo
:
lodsd
          cmp     ebx
,
eax
          jne     @f
          mov     edx
,
[
esi
]
jmp     @foundAlgo
@@
:
add     esi
,
4
loop    @findAlgo
@foundAlgo
:
ret
endp
;
//------------
section
'.idata'
import data readable
library  kernel32
,
'kernel32.dll'
,
shell32
,
'shell32.dll'
,
\
         ole32
,
'ole32.dll'
,
msvcrt
,
'msvcrt.dll'
import   ole32
,
StringFromGUID2
,
'StringFromGUID2'
include
'api\kernel32.inc'
include
'api\shell32.inc'
include
'api\msvcrt.inc'


Обратите внимание на Guid мастер-ключа. В предыдущей программе мы шифровали данные при помощи CryptProtectData(), с последующим выводом результирующего BLOB'а на консоль. Если всё было сделано правильно, то Guid из блоба-данных должен совпадать с Guid'ом из блоба мастер-ключа, т.к. именно им и происходит шифрование. Как видим ошибок нет и ключ мы получили валидный:



5. Постскриптум

Система использует интерфейс DPAPI при защите большого зоопарка персональных данных. Это пароли и данные автозаполнения форм в браузерах IE, кукисов и паролей Chrome, учётных записей в Outlook, Win-Mail, FTP, для доступа к расшаренным папкам и ключам учёток Wi-Fi, для удаленного доступа к рабочему столу и многое другое. DPAPI активно юзают и сторонние разработчики типа Skype, GoogleTalk и др. К сожалению ограниченные объёмы статьи не позволяют охватить всего материала на эту тему (хотя и так получилось слишком много букаф), а потому за бортом осталось много интересного. В скрепку кладу два представленных здесь исполняемых файла, а так-же инклуд с описанием основных структур DPAPI. Всем удачи, пока!
 
Ответить с цитированием
 



Предыдущая тема Следующая тема

Здесь присутствуют: 1 (пользователей: 0 , гостей: 1)
 


Быстрый переход




ANTICHAT ™ © 2001- Antichat Kft.