г============================¬
                                             ¦     Version: 1.0           ¦
                                             ¦     Release: 12-Nov-1998y  ¦
                                             ¦  Created by: Hard Wisdom   ¦
                                             L============================-

-[12-Nov-1998y]-[v1.0]——————————————————— Первоначально созданный файл

   Описание механизма функционирования парольных кэшей Windows v4.xx
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

[] Содержание

 [0] О теме разговора
 [1] Обзор реализации парольных кэшей Windows v4.0 (a.k.a. 95)
 [2] Обзор реализации парольных кэшей Windows v4.0.1111 (a.k.a. 95 OSR2)
 [3] Дополнения и изменения в операционной системе Windows v4.1 (a.k.a. 98)
 [4] Детали реализации алгоритмов
 [5] Подведение итогов
 [6] Greetings!


[0] О теме разговора

Сейчас мы с вами поговорим о парольных кэшах Windows v4.xx. Под парольным кэшем понимается механизм сохранения и повторного использования паролей в системе. От обычной базы логинов данный механизм отличается именно хранением дополнительных парольных ресурсов и возможностью их использования по специальному запросу без участия пользователя. Для чего появился данный механизм? Отчасти для облегчения работы пользователей ;-) Интересно, все для них… А во вторых… Можно расценивать это как дополнительный защитный механизм. Достоинством является затруднение “подглядывания” за клавиатурой, уменьшение количества ошибок при вводе паролей и возможность использользования паролей большей длинны (нет нужды их запоминать или записывать на бумажке). Недостатками - возможность получения существенного объема “секретной” информации злоумышленником при взломе парольного кэша, крайне несерьезная реализация данного механизма в имеющихся версиях операционной системы Windows. Появился данный механизм работы с парольными ресурсами относительно давно. Определенные предпосылки реализации были заложены еще в Windows v3.11 Ничего не могу сказать про эту систему, т.к. сам прыгнул из MS-DOS’a сразу в Windows v4.0 С нее и начнем. А пока позвольте рассказать о том как все выглядит снаружи. Способность кэшировать парольные ресурсы появляется в Windows при установке “сетевого окружения” или “множественных параметров рабочего стола” (блин, ну и названия). Политика функционирования подсистемы кэширования определяется редактором системных правил PolicyEditor (его можно взять из пакета Resources Kit от Micro$oft), по умолчанию кэширование включено (это означает, что его можно выключить). Обычно на такие мелочи никто внимания не обращает. Кэширование паролей - общесистемный сервис, это значит, что любое приложение может получить к нему доступ. Очевидно предполагалось, что компьютер физически надежно защищен (ибо персональный ;-), разумеется, в реальной жизни это не так. Как же предполагалось легальным способом использовать данный сервис? Приложение (например Explorer a.k.a. “проводник”, гильдии Ивана Сусанина ;-) пытается подключиться к сетевому (и не только) ресурсу, функция WNetAddConnection возвращает код результата ERROR_INVALID_PASSWORD или ERROR_ACCESS_DENIED, в таком случае выводится стандартный диалог запроса пароля (для любителей, можете написать перехватчик данного диалога, в частности, это будет WNetConnectionDialog), затем производится повтор попытки подключения, в случае успеха пароль заносится в кэш паролей и в дальнейшем делается попытка его использования именно оттуда (при возникновении проблем происходит переключение на “ручное управление”). Как использовать данный сервис нестандартно? а вот как:

     IMPORTS
        WNetEnumCachedPasswords = MPR.WNetEnumCachedPasswords

Затем: Push 0 Push Offset AcceptCache Push 0FFh Push 0 Push 0 Call WNetEnumCachedPasswords

Где процедура AcceptCache является точкой обратного вызова и принимает два параметра, первый из которых - адрес элемента парольного кэша, про структуру кэша мы поговорим дальше. В вашей программе можно писать так:

     Mov EAx,[ESp+4]
     ...............
     Ret 8h

На самом деле ничего писать не надо, все уже и так реализовано в моей программе PWLHACK v4.02, которую можно взять по адресу указанному в конце этой статьи. Как вы уже успели понять, на залогиненной машине возможно элементарно получить весь список парольных ресурсов со всей сопутствующей критической (с точки зрения безопасности) информацией. Виват, Micro$oft! Кстати, во всей литературе, которую я читал про защиту информации, слова MS-DOS и Windows не упоминаются вообще (разве что во введении, причем единожды ;-). В принципе, описанный выше механизм работы с парольным кэшем суть существенный просчет (даже на фоне прочей дырявости) в системе безопасности Windows. Раз уж я заговорил о дырках… скажу еще пару слов (все это делает PWLHACK v4.02), ресурсы предоставляемые машиной в сеть для публичного использования хранятся в регистри (причем вместе с паролями). Вот как это происходит:

    Software\Microsoft\Windows\CurrentVersion\Network\LanMan

Начиная отсюда подключами располагаются сетевые каталоги плюс вспомогательная информация (флаги, пароли и проч.) Хотите знать механизм шифрования паролей? Вот он: Seed=6Ah; ForEach Password (Ror Seed,1; Character Xor Seed) Все желающие могут чуть-ли не батником добавлять шаровые ресурсы в машину (при условии физического доступа к ней). Управлением локальными ресурсами машины, предоставляемыми в сеть, занимается VSERVER.vxd, а обменом информацией с удаленными серверами VREDIR.vxd Безусловно, в связке работают так же MSNET32.dll, MSNP32.dll и проч. Физически парольный кэш располагается в каталоге %WINDIR% и имеет расширение .PWL, причем список файлов, составляющих парольный кэш, находится в SYSTEM.ini в разделе [Passwords Lists]. Интересен такой момент, имя файла есть имя пользователя обрезанное до 8 букв (8.3 стандарт на имена файлов). Если имена 2-х пользователей совпадают в первых 8-ми буквах, и различны, то работать сможет только второй из них, первый потеряет все настройки, т.к. парольный файл второго затрет аналогичный файл существовавший до него. Никаких проверок не производится, уф! Физически всю работу производит модуль MSPWL32.dll Кстати, еще один факт слабой проработки кодирования защитных модулей, заменой 3-х байтов полностью отключается весь механизм шифрования файлов, составляющих парольный кэш, затем due to технические причины автоматически является легальным любой вводимый пароль, вот иллюстрация:

-[MSPWL32.crk]—————————————————————– Windows 95-98 passwords. (C) by HW

[W95 & OSR/2] All passwords are legal and *.PWL’s are not encrypted. MSPWL32.DLL 00000511: 30 90 00000512: 0C 90 00000513: 28 90

[W98 4.10.1691] All passwords are legal and *.PWL’s are not encrypted. MSPWL32.DLL 00001241: 30 90 00001242: 0C 90 00001243: 28 90

-[MSPWL32.crk]—————————————————————–

Заменяемые байты есть команда наложения гаммы на файл (XOR кого-то с кем-то), об этом мы поговорим подробнее чуть ниже. При обработке файлов используются алгоритмы RC4 (RFC-…. ну нет у меня интернета) и MD5 (RFC-1321). На настоящий момент уже появился алгоритм RC5 (можно ожидать его применения в дальнейшем). Алгоритм RC4 является алгоритмом потокового шифрования и считается вполне устойчивым, MD5 - алгоритм создания дайджестов (сверток) сообщений, достаточно быстр в реализации, разработчик R.Rivest. Про MD5 мы поговорим особо в дальнейшем. Итак, подошло время технической информации.

[1] Обзор реализации парольных кэшей Windows v4.0 (a.k.a. 95)

   Для начала я приведу  Си-подобную  структуру  расписывающую  отдельные  поля
этого файла, затем будут комментарии.

#define W95_PwlSign 0x4E464DB0        // Некоторые называют это "MFN"
#define W95_PwlBase 0x23C

typedef struct {             /* version depended W95 PWL partition */
 byte UserName[20];                         /* Padded owner name   */
 word ResOffsets[0xF];                      /* Resources offsets.  */
} W95_pwl_data;

typedef struct {                         /* PWL file header itself */
 dword Sign;                                /* .PWL file signature */
 dword UnknownC;                            /* ?? Strange counter  */
 byte ResLink[0x100];                       /* Resource link index */
 byte ResKey[0x100];                        /* Resource key entry  */
 union {
  W95_pwl_data W95_Data;                    /* W95 format PWL data */
  OSR_pwl_data OSR_Data;                    /* OSR format PWL data */
 } HdrV;
} pwl_hdr;

Итак, файл содержит в  самом  начале  сигнатуру  W95_PwlSign,  заголовок  имеет
размер  W95_PwlBase,  собственно,  с  этого  смещения  располагаются   (обычно)
зашифрованные ресурсы. Поле  UnknownC  увеличивается  с  течением  времени  при
модификации файла и является скорее всего версией парольного  кэша  (вернее  не
столько версией, сколько возрастом).
   Теперь ключевой момент,  доступ  к  ресурсам.  Он  осуществляется  по  16-ти
точкам входа (соответствующая индексация осуществляется по телу  ресурса),  это
позволяет  значительно  ускорить   доступ   к   ресурсной   информации   и   не
расшифровывать лишний раз "критические" данные (впрочем, их все равно  потом  в
памяти _не_ затирают). Лирическое отступление: я часто замечал  вольную  работу
со стеком и регистрами библиотечных функций Windows (здесь и  далее  версия  не
ниже 4.0). Имеется ненулевая вероятность получения интересной информации  после
отработки многих системных вызовов. (Скажем, многие функции осуществляют  поиск
файла по системному маршруту: текущий каталог, затем  %WINDIR%,  затем  PATH  и
т.п. Достаточно часто после выхода из такой функции в EDx содержится  указатель
на  полный  путь  найденного  файла,  это  лишь  пример...  Только  пример  для
думающего человека...) Собственно, файл кэша может  содержать  максимально  255
ресурсов. Поля массива ResLink[]  содержат  номера  ресурсов  (в  случае,  если
необходим итеративный, а не ассоциативный доступ), эти  поля  индексируют  поля
ResKey[], содержащие номера точек  входа  (другими  словами  -  номера  каналов
ресурсов)  в  ресурсном  файле.  Почему  именно  такая  двухуровневая  система?
Возможно по соображениям простоты вставки-удаления элементов (ну лень  им  было
возиться со списками и проч., файлы, кстати, вычитываются по кусочкам, т.е.  по
2-4-...-256 байта, как раз полями).
   Открытие парольного кэша  осуществляется  следующим  образом:  сворачивается
пароль в 4-х байтовый хеш, затем по хешу строится таблица RC4 и  осуществляется
расшифровка полей UserName и ResOffsets, поле  UserName  должно  содержать  имя
пользователя. Ресурсы в каждом канале зашифрованы независимо друг от друга,  но
одним и тем же ключевым значением. Вспомним о том, что RC4 потоковый  алгоритм.
Практически всегда зная имя  пользователя  (которое  выровнено  0-ми  на  20-ти
байтовую границу) мы получаем  начало  гаммы,  затем  предполагая  определенные
значения смещений ресурсов (на основе полей ResKey и ResLink, а так  же  знания
константы W95_PwlBase) мы можем получить еще несколько (до 15*2) байтов  гаммы,
итого max 50 байтов гаммы, это позволит  нам  расшифровать  max  по  50  байтов
каждого  ресурсного  входа,  абсолютно  без  всякого  предположения  о   пароле
пользователя. Данную задачу решала программа Glide в свое время. Этот  нюанс  в
применении  стойких  криптоалгоритмов   даже   явился   источником   нескольких
журнальных статей в околокомпьютерной журналистике. В настоящее время  это  уже
история,  так  как  только  у  нас  еще  используют  чистую  Windows  v4.0  без
обновлений. Второй путь: ключ для RC4 шифрования короток, 2^32, полный  перебор
может быть осуществлен за сутки (даже менее). А это значит, что парольные  кэши
Windows v4.0 гарантированно _не_ защищают хранящуюся в них информацию.
   Рассмотрим поближе формат канала ресурсов, именно в  таком  формате  ресурсы
получает точка обратного вызова для WNetEnumCachedPasswords (по одному  ресурсу
на вызов).
-----------T------T-----------------------------------------------------------¬
¦ Смещение ¦Размер¦Значение                                                   ¦
¦==========+======+===========================================================¦
¦    0     ¦ Word ¦ Общий размер ресурса                                      ¦
¦    2     ¦ Word ¦ Размер описателя ресурса (имя соединения, сетевого        ¦
¦          ¦      ¦ диска, игрового сервера, и проч.)                         ¦
¦    4     ¦ Word ¦ Размер секретной информации ресурса (пароль на            ¦
¦          ¦      ¦ соединение и проч.)                                       ¦
¦    6     ¦ Byte ¦ Номер ресурса (абсолютный)                                ¦
¦    7     ¦ Byte ¦ Дескриптор ресурса (6 - DialUp, 6 - NetLink и проч.)      ¦
L----------+------+------------------------------------------------------------
Стоит добавить, что ресурсы далеко не всегда текстовые строки.  MAPI  хранит  в
парольных кэшах свои бинарные данные, а  Novell  Network  Provider  хранит  имя
пользователя и логин на сервер как 2  строки  закрытые  0  в  "секретном"  поле
ресурса. Все желающие поисследовать файлы  .PWL  могут  воспользоваться  ключем
/LIST:E программы PWLHACK v4.02 Еще один момент: это процедура  свертки  пароля
в  Windows  v4.0  Очевидно,  что  такая  свертка  достаточно  просто   обратима
(возможна генерация некоторого множества паролей для отдельно взятого хеша).

              ; EDx - hash, EBx - Pointer to password.
              W95_Hash_Pwd    Proc
                              Xor     EDx,EDx
              W95_Hash_Next:  MovZx   EAx,Byte Ptr [EBx]
                              Add     EDx,EAx
                              Rol     EDx,7
                              Inc     EBx
                              Or      Al,Al
                              Jnz     Short W95_Hash_Next
                              Ret
              W95_Hash_Pwd    EndP

   Наверное, мне больше  нечего  добавить  в  этом  разделе,  думаю,  что  пора
переходить к следующему. Micro$oft иногда прислушивается к мнению  "прогрессив-
ной общественности",  особенно  в  вышеописанном  случае,  иначе она не была бы
Micro$oft.


[2] Обзор реализации парольных кэшей Windows v4.0.1111 (a.k.a. 95 OSR2)

Начнем как обычно, с Си-подобного заголовка .PWL файлов этой версии Windows, продолжим пояснениями.

#define OSR_PwlSign 0x968582E3 // Некоторые называют это “УВЕЦ” #define OSR_PwlBase 0x290 #define OSR_PwlHdrOfs 0x252

typedef struct { /* OSR PWL checking sign / byte CryptoSign[0x10]; / Crypto sign / byte CheckoSign[0x10]; / Checko sign / word ResOffsets[0xF]; / Resources offsets. */ } check_pack;

typedef struct { /* version depended OSR PWL partition / dword HdrOfs; / Offset to CryptoHdr / dword CryptoSeed[0x11]; / Resource CryptoSeed / word UnkAlign; / ?? Just alignment / check_pack Check; / Checking crypt-sign */ } OSR_pwl_data;

typedef struct { /* PWL file header itself / dword Sign; / .PWL file signature / dword UnknownC; / ?? Strange counter / byte ResLink[0x100]; / Resource link index / byte ResKey[0x100]; / Resource key entry / union { W95_pwl_data W95_Data; / W95 format PWL data / OSR_pwl_data OSR_Data; / OSR format PWL data */ } HdrV; } pwl_hdr;

Общая структура файла осталась без изменений, те же ресурсные входы, механизм доступа по каналам (точкам входа) и проч. Но что-то ведь изменилось? Как минимум, изменилась сигнатура файла, теперь это OSR_PwlSign, соответственно изменилось и положение ресурсной информации, она теперь обычно располагается по смещению OSR_PwlBase Появилось дополнительное поле HdrOfs имеющее как правило значение OSR_PwlHdrOfs, по данному смещению располагаются описатели ресурсных точек входа (смещения внутри файла, соответственно размер ресурсного канала есть ResOffsets[i+1]-ResOffsets[i]), ну, если более точно, то структура check_pack. Поскольку работа с ресурсами была описана выше, то перейдем к новому моменту: открытию парольного кеша. И вот теперь начинаются проблемы. Первоначально пароль вместе с константой 0xFFFFFFFF, а так же CryptoSeed[0x10], именем пользователя и паролем сворачивается в MD5 хеш, длинной 4 DWord’a (за 2 прохода, вначале имя, затем пароль). После этого расшифровывается участок файла check_pack (алгоритмом RC4), затем выполняется еще одна MD5 свертка, в ней участвуют имя пользователя и поле CryptoSign[] в результате должна получиться сигнатура CheckoSign[], тогда и только тогда пароль расценивается допустимым. Как видим, исправлены все недостатки предыдущего формата ресурсного файла. В частности, реализация переборщика показала, что скорость снизилась в 2 раза, по сравнению с вариантом из Windows v4.0 (38 тыс. pps против 55 тыс. pps) Исправлены также недостатки малой длинны свертки пароля и тривиальная зависимость свертки от пароля. Хочется отметить такой факт, что поля ввода в диалогах позволяют ввести пароль максимально до 14 символов и преобразуют его к верхнему регистру (справедливо для версий Windows v4.0-4.0.1111). Это существенно сокращает пространство для перебора. А как с одиноковой гаммой для каждого ресурсного ка- нала? Теперь, при создании ключа для шифрования, используют поля CryptoSeed[i], причем пропускание этой информации сквозь MD5 не позволяет говорить о прямой реконструкции гаммы даже при знании некоторых ресурсов.

[3] Дополнения и изменения в операционной системе Windows v4.1 (a.k.a. 98)

   Их очень немного, прежде всего, сняли ограничения с полей ввода в диалоговых
окнах (теперь можно  ввести  свыше  сотни  символов  в  имя  пользователя  и  в
пароль). Так  же,  при  логине  имя  пользователя  выбирается  из  списка,  что
позволяет достаточно  просто  использовать  длинные  имена  пользователей  (что
очень замедляет перебор). Жаль, но  пароль из списка выбирать нельзя ;-) Вот  и
все, форматы файлов изменений  не  претерпели.  Была  дополнительно  переписана
MSPWL32.dll, конечно же она стала в 2 раза больше объемом (такое ощущение,  что
мировые производители винчестеров - одно  из  подразделений  фирмы  Micro$oft).
Больше назвать нечего.


[4] Детали реализации алгоритмов
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   Здесь я бы хотел рассмотреть особенности использованных  алгоритмов:  RC4  и
MD5, а так же кое что из Windows v4.x Начнем с RC4.

typedef struct {                               /* main cryptotable */
 byte body[0x100];                            /* data table itself */
 byte c1,c2;                    /* crypto pointers into data table */
 dword keylen;                                       /* len of key */
 void* key;                              /* key for table building */
} RC4_table;


void init_RC4_table(RC4_table* x) {    /* initializing cryptotable */
 int i,p,t,tt; x->c1=0,x->c2=0;
 for (i=0;i<=255;x->body[i]=i,i++);
 t=0; for (i=0,p=0;i<=255;i++,p=i & 0x0F) {
  t+=x->key[p]+x->body[i]; t&=0xFF;
  tt=x->body[i]; x->body[i]=x->body[t]; x->body[t]=tt;
 }
}

void use_RC4_table(xor_table* x, void* data, word datalen) {
 byte p1,p2,t;           /* en/decrypting the data via cryptotable */
 p1=x->c1; p2=x->c2;
 while (datalen--) { p2+=x->body[++p1];
  t=x->body[p1]; x->body[p1]=x->body[p2]; x->body[p2]=t;
  t+=x->body[p1]; *((byte*)data)++^=x->body[t];
 }; x->c1=p1; x->c2=p2;
}

RC4_table  инкапсулирует  в  себя  все  данные   необходимые   для   выполнения
шифрования  (все  поля  и  процедуры  получены  в   результате   анализа   кода
MSPWL32.dll, стандарт я  в  руках  не  держал).  init_RC4_table()  осуществляет
первичную настройку таблицы по ключу key, а use_RC4_table  выполняет  наложение
получающейся гаммы на поток данных  data  длинной  datalen.  Надеюсь,  что  все
вышеприведенное прозрачно, поэтому перейдем  к  MD5.  Выполнение  одного  этапа
свертки выполняется следующей функцией:

                 MD5_FF  1,2,3,4,  0, 0D76AA478h,  7 ; Round 1
                 MD5_FF  4,1,2,3,  1, 0E8C7B756h, 12
                 MD5_FF  3,4,1,2,  2, 0242070DBh, 17
                 MD5_FF  2,3,4,1,  3, 0C1BDCEEEh, 22
                 MD5_FF  1,2,3,4,  4, 0F57C0FAFh,  7
                 MD5_FF  4,1,2,3,  5, 04787C62Ah, 12
                 MD5_FF  3,4,1,2,  6, 0A8304613h, 17
                 MD5_FF  2,3,4,1,  7, 0FD469501h, 22
                 MD5_FF  1,2,3,4,  8, 0698098D8h,  7
                 MD5_FF  4,1,2,3,  9, 08B44F7AFh, 12
                 MD5_FF  3,4,1,2, 10, 0FFFF5BB1h, 17
                 MD5_FF  2,3,4,1, 11, 0895CD7BEh, 22
                 MD5_FF  1,2,3,4, 12, 06B901122h,  7
                 MD5_FF  4,1,2,3, 13, 0FD987193h, 12
                 MD5_FF  3,4,1,2, 14, 0A679438Eh, 17
                 MD5_FF  2,3,4,1, 15, 049B40821h, 22

                 MD5_GG  1,2,3,4,  1, 0F61E2562h,  5 ; Round 2
                 MD5_GG  4,1,2,3,  6, 0C040B340h,  9
                 MD5_GG  3,4,1,2, 11, 0265E5A51h, 14
                 MD5_GG  2,3,4,1,  0, 0E9B6C7AAh, 20
                 MD5_GG  1,2,3,4,  5, 0D62F105Dh,  5
                 MD5_GG  4,1,2,3, 10, 002441453h,  9
                 MD5_GG  3,4,1,2, 15, 0D8A1E681h, 14
                 MD5_GG  2,3,4,1,  4, 0E7D3FBC8h, 20
                 MD5_GG  1,2,3,4,  9, 021E1CDE6h,  5
                 MD5_GG  4,1,2,3, 14, 0C33707D6h,  9
                 MD5_GG  3,4,1,2,  3, 0F4D50D87h, 14
                 MD5_GG  2,3,4,1,  8, 0455A14EDh, 20
                 MD5_GG  1,2,3,4, 13, 0A9E3E905h,  5
                 MD5_GG  4,1,2,3,  2, 0FCEFA3F8h,  9
                 MD5_GG  3,4,1,2,  7, 0676F02D9h, 14
                 MD5_GG  2,3,4,1, 12, 08D2A4C8Ah, 20

                 MD5_HH  1,2,3,4,  5, 0FFFA3942h,  4 ; Round 3
                 MD5_HH  4,1,2,3,  8, 08771F681h, 11
                 MD5_HH  3,4,1,2, 11, 06D9D6122h, 16
                 MD5_HH  2,3,4,1, 14, 0FDE5380Ch, 23
                 MD5_HH  1,2,3,4,  1, 0A4BEEA44h,  4
                 MD5_HH  4,1,2,3,  4, 04BDECFA9h, 11
                 MD5_HH  3,4,1,2,  7, 0F6BB4B60h, 16
                 MD5_HH  2,3,4,1, 10, 0BEBFBC70h, 23
                 MD5_HH  1,2,3,4, 13, 0289B7EC6h,  4
                 MD5_HH  4,1,2,3,  0, 0EAA127FAh, 11
                 MD5_HH  3,4,1,2,  3, 0D4EF3085h, 16
                 MD5_HH  2,3,4,1,  6, 004881D05h, 23
                 MD5_HH  1,2,3,4,  9, 0D9D4D039h,  4
                 MD5_HH  4,1,2,3, 12, 0E6DB99E5h, 11
                 MD5_HH  3,4,1,2, 15, 01FA27CF8h, 16
                 MD5_HH  2,3,4,1,  2, 0C4AC5665h, 23

                 MD5_II  1,2,3,4,  0, 0F4292244h,  6 ; Round 4
                 MD5_II  4,1,2,3,  7, 0432AFF97h, 10
                 MD5_II  3,4,1,2, 14, 0AB9423A7h, 15
                 MD5_II  2,3,4,1,  5, 0FC93A039h, 21
                 MD5_II  1,2,3,4, 12, 0655B59C3h,  6
                 MD5_II  4,1,2,3,  3, 08F0CCC92h, 10
                 MD5_II  3,4,1,2, 10, 0FFEFF47Dh, 15
                 MD5_II  2,3,4,1,  1, 085845DD1h, 21
                 MD5_II  1,2,3,4,  8, 06FA87E4Fh,  6
                 MD5_II  4,1,2,3, 15, 0FE2CE6E0h, 10
                 MD5_II  3,4,1,2,  6, 0A3014314h, 15
                 MD5_II  2,3,4,1, 13, 04E0811A1h, 21
                 MD5_II  1,2,3,4,  4, 0F7537E82h,  6
                 MD5_II  4,1,2,3, 11, 0BD3AF235h, 10
                 MD5_II  3,4,1,2,  2, 02AD7D2BBh, 15
                 MD5_II  2,3,4,1,  9, 0EB86D391h, 21

Вышеописанный безумный столбец функций осуществляет  сворачивание  64-х  байтов
данных в  16.  В  свертке  участвует  счетчик  битов  данных  (располагается  в
последнем  DWord'е  сворачиваемого  блока),   фрагменты   данных   не   кратные
64-байтовой границе выравниваются добавлением  байта  80h,  а  затем  0-лей  до
требуемой   границы.   Сейчас   я   приведу   тела   функций,    осуществляющих
преобразования, они несколько отличаются от стандарта, они  оптимизированы!  За
что  огромная  благодарность  Shadow  Dragon'у.  Изменения  коснулись   функции
MD5_HH, это позволило значительно ускорить PWLHACK v4.02

   ; p1 = ( ( p1 += ( ( p3 ^ p4 ) & p2 ^ p4 ) + K[] + X ) Roll R ) + p2
   MD5_FF          Macro   P1,P2,P3,P4,K,X,R

   ; p1 = ( ( p1 += ( ( p2 ^ p3 ) & p4 ^ p3 ) + K[] + X ) Roll R ) + p2
   MD5_GG          Macro   P1,P2,P3,P4,K,X,R

   ; p1 = ( ( p1 += ( ( p2 ^ p3 ^ p4 ) + K[] + X ) Roll R ) + p2
   MD5_HH          Macro   P1,P2,P3,P4,K,X,R

   ; p1 = ( ( p1 += ( ( p2 | ~p4 ) ^ p3) + K[] + X ) Roll R ) + p2
   MD5_II          Macro   P1,P2,P3,P4,K,X,R

Всю детальную информацию можно взять в RFC-1321 (в  том  числе  и  оригинальные
формы функций FF..II). То, что я привел  выше,  является  адаптацией  стандарта
под Intel платформу. Параметры P1..P4 это соответствующие DWord дайджеста, K  -
сворачиваемое сообщение (индекс DWord'ов от 0 до 16),  X  -  хитро-замороченные
константы, получены преобразованием таблички синусов.


[5] Подведение итогов
~~~~~~~~~~~~~~~~~~~~~
   Вот и подошло к концу наше маленькое путешествие,  проблема  рассмотрена  со
всех  сторон  и  разобрана  по  кусочкам,  надо  выбирать  новые  цели,   новые
горизонты... Пускай каждый сделает  для  себя  выводы  о  принципах  построения
систем хранения "критической" (с точки зрения безопасности) информации,  увидит
ошибки в существующем программном обеспечении и не повторит их.


[6] Greetings!
~~~~~~~~~~~~~~

  Shadow Dragon  - помощь в оптимизации кода и алгоритмов PWLHACK, идеи
       ERL       - идеи, разговоры, комментарии, информация и глюки
       SJ        - поддержка домашней странички, откуда все вышеописанное
                   барахло можно скачать, разговоры, информация
    PolyGris     - эксперименты с новой штучкой - Windows 98, где бы я еще
                   мог посмотреть новейший софт, как не здесь?
 WorkPC'n'HomePC - да, именно на этих 2х компьютерах все и было сделано,
                   а их ТТХ и начинка - уже неважно
    .........    - очень много людей, писавших мне, их список будет больше
                   в размерах, чем весь текст данного описания



           Home Page: www.geocities.com/SiliconValley/Hills/7827
              E-Mail:         hardwisdom@geocities.com


                     FidoNet: 2:461/133.69 * Hard Wisdom
                 -------------------------------------------
                              Seek And Destroy!
                              

::: Первый вариант сайта ::: Все для DataLife Engine ::: Генератор паролей :::

Основные разделы сайта
:: Android :: DLE :: Linux :: MARKDOWN :: PWM Шим генераторы :: Shell :: Windows :: Безопасность :: Веб Сервер :: Дизаин :: Еда :: Тесла :: HTML :: Посты :: Регулярные Выражения :: Софт :: Электроника :: Уфология ::

Карта сайта