Головне завдання дослідження: отримати паролі, що зберігаються в Active Directory, зашифровані оборотним чином. Дана стаття є продовженням «Дослідження Active Directory. Під час проведеного дослідження сховища Active Directory (Extensible Storage Engine) була продемонстрована можливість отримання даних зі сховища в обхід перевірок дозволів агентом NTDSA (NT Directory Services Agent). Розроблена програма essential виконує експорт даних із закритого сховища ESE у відкритий формат XML. Тобто з’явилася можливість працювати з даними AD не через високорівневі інтерфейси, такі як ADSI, а безпосередньо отримуючи їх з сховища. Отримувати дані в тому вигляді, в якому з ними працює операційна система. У цій статті описано процес вирішення проблеми.

Шифрування паролів Windows 2000

Дослідження
У попередньому дослідженні ми дізналися, що база Active Directory зберігається в одній таблиці (datatable), тепер спробуємо зрозуміти як зберігаються в ній атрибути, зокрема нас цікавлять паролі.
Атрибут Active Directory (далі просто атрибут) користувача, в якому зберігається пароль в формі NT OWF (стандартної в середовищі Windows 2000) називається unicode-Pwd. У datatable знаходимо рядок, де присутні наступні поля:
ATTm131298=«Unicode-Pwd» ATTm131266=«Unicode-Pwd» ATTc131102=«589914» ATTc131104=«524298» ATTm3=«Unicode-Pwd» ATTj131073=«4» ATTi131105=«1» ATTm131532=«unicodePwd».
Схоже на те, що поле таблиці datatable (далі просто поле) ATTc131102 унікальне для кожного запису, що описує атрибут. Припустимо, що це поле код атрибута. Знайдемо в таблиці, в якій записи зустрічається 131102 в поле ATTc131102. Знаходимо запис з наступними полями: ATTm131298=«Attribute-ID» ATTm131266=«Attribute-ID» ATTc131102=«131102» ATTc131104=«524290» ATTm3=«Attribute-ID». Припущення виявилося вірним — дійсно в атрибуті ATTc13102 зберігається код атрибута. Цікаво, що базовий атрибут (Attribute-ID) визначено сам через себе.
Повертаючись до атрибуту unicode-Pwd, отримуємо код атрибута 589914. Назву поля в таблиці datatable виходить додаванням ATT і якийсь букви (зустрічаються c,m,j,k,..). В даний момент нас не цікавить, як отримати цю невідому букву — поле з кодом 589914 всього одне — ATTk589914. Подивимося, як виглядає цей атрибут для якогось користувача:
ATTk589914=«X1100000000000000B1C9DEEFD22A0A80C64E61F3D1FCEB374B6D 2E76C3059ABEAAC907129B453582»
Звичайно, нічого схожого на пароль тут не видно, незважаючи на те, що для користувача встановлена ознака «Зберігати пароль, використовуючи оборотне шифрування».
Можна припустити, що оборотно зашифрований пароль зберігається в атрибуті DBCS-Pwd. Визначаємо код атрибута — ATTc131102=«589879», потім назва поля: ATTk589879. Для деяких користувачів він визначений, і виглядає приблизно так:
ATTk589879=«X110000000000000014517683BA70D3E85693399B30EAC1F72D8F D12716C18C856DAE6DCD88836D4A»,
у деяких відсутня. Однаковими у цих атрибутів виглядає заголовок — перший кілька байт. Схоже на те, що вони зашифровані одним способом. Визначимо всі атрибути користувача, що виглядає схожим чином:
ATTk589914=«X11000000000000005075DB20450590922ABD56742443CA71724B 724B68CD80A2000CA8383A16DDC3»,
ATTk589918=«X11000000000000008BB5C5D5046E939877C9D89EAACAE1DE19A 447DAADA34CAE64D2522ECFD8FF2B»,
ATTk589949=«X1100000000000000355D6B72D113B7C81D497BD::::»,
ATTk589984=«X1100000000000000F2B9FCDCA74C93550DB88362E147B922B002 7F05C3E025580C9DAEDD944BAB04».
Знайдемо визначення цих атрибутів (записи, де поле ATTc131102 одно кодом атрибута), підведемо підсумки: 589879 DBCS-Pwd
589914 Unicode-Pwd
589918 Nt-Pwd-History
589949 Supplemental-Credentials
589984 Lm-Pwd-History
Схоже, що всі ці атрибути, пов’язані з паролями, шифруються. Алгоритм шифрування, також як і механізм зберігання не документований. При зміні пароля, вміст цих атрибутів змінюється, незмінним залишається лише заголовок. Подальше вивчення таблиці datatable схоже втрачає сенс. Спроба отримати паролі зі сховища виявилася невдалою. Невдачі лише загартовують і тому продовжимо.

Спробуємо зайти з іншого боку, через парадні двері. Спробуємо розібратися, коли і як Windows 2000 все ж використовує цей зашифрований оборотним чином пароль.
Як вже було сказано в попередній статті, такий пароль використовується при віддаленому підключенні користувачів до RAS (Remote Access Server — сервер віддаленого доступу) з використанням протоколу автентифікації CHAP(Challenge Handshake Authentication Protocol). Умовно можна вважати, що згідно з протоколом CHAP користувач передає пароль, причому не у відкритому вигляді, а в зашифрованому — застосовується алгоритм MD5.
Змоделювати віддалене підключення зовсім нескладно, для цього досить включити службу маршрутизації для прийому вхідних підключень, налаштувати протокол автентифікації CHAP, в політиці віддаленої також визначити можливість використовувати цей протокол. Потім створити VPN підключення до нього самого. У властивостях підключення також треба встановити протокол — CHAP. Після цього встановлюється з’єднання дійсно тільки тоді, коли для користувача включено оборотне шифрування. Тобто в даній моделі користувач передає пароль, зашифрований за допомогою незворотного шифрування MD5.
Сервер в такому вигляді пароля не має, і змушений отримати «чистий» пароль з Active Directory, також зашифрувати його з допомогою MD5 і порівняти з тим, що передав користувач.
Залишилося тільки знайти в папці %windir%/System32 DLL або EXE-модуль, який виконує цю дію(отримує пароль у «чистому» вигляді).

Приступаємо до аналізу системи. Допомогти нам можуть налагоджувальні символи (Symbols), (http://www.microsoft.com/whdc/ddk/debugging/default.mspx) і відладчик Налагоджувач (http://www.microsoft.com/whdc/ddk/debugging/installx86.mspx) відкриті для усіх допитливих.
Пройшов день і цей модуль був знайдений. RASSFM.DLL.
У коді модуля виявляємо цікаву функцію: _MD5ChapSubAuthentication, в тілі якої зустрічаємо те, що потрібно: _RetrieveCleartextPassword з якимись трьома параметрами. Викликати її зі своєї програми, на жаль, ми не зможемо, так як вона не є експортується.
Доведеться забиратися далі. Наступна: _SamIRetrievePrimaryCredentials — функція, що експортується з SAMSRV.DLL. Вже краще, таку функцію ми можемо викликати своєї програми, просто підключивши SAMSRV.DLL. Спроба зробити це виявляється невдалою. Виявляється, що ця функція не працює, коли ми завантажимо цю бібліотеку самостійно (використовуючи динамічний або статичний зв’язування).
Виникає питання, а хто і як тоді використовує її в системі. Скориставшись вже знайомим нам за попереднім дослідженням ProcDump, отримуємо — LSASS.EXE. Він завантажує бібліотеку SAMSRV.DLL, ініціалізує її. Цей же процес завантажує RASSFM.DLL при спробі підключення користувача. Ситуація нагадує ту, що була з NTDSA (NT Directory Services Агента ом).
На цьому не зупиняємося і опускаємося глибше. Скориставшись Windbg, встановимо точку зупину у відомій нам RASSFM.DLL і будемо забиратися в код отримання пароля в «чистому» вигляді. По дорозі нам зустрічається багато цікавого, я буду зупинятися на найцікавіших моментах:
SampQueryUserSupplementalCredentials (SupplementalCredentials — щось знайоме — так, був такий зашифрований атрибут, повідомляється на сайті Microsoft:
(Stored credentials for use in authenticating. The encrypted version of the user’s password. This attribute is neither readable nor writable.)
(Параметри облікового запису, використовувані при автентифікації користувача. Зашифрована версія пароля користувача. Атрибут недоступний ні для читання, ні для запису.) (Для кого-то може і не доступний).
Напевно, ми на вірному шляху. Ще глибше: _SampDsRead, а ось і читання з Active Directory. Продовжуємо занурення: _DirRead, отримуємо виклик функції, що експортується з NTDSA.DLL __imp__DirRead.
Ось і старий знайомий NTDSA — минулого разу нам вдалося його вирішити, звернувшись до сховища знизу, відразу до ESENT.DLL. Цікаво, що ж таке робить NTDSA.DLL? На вході (зі сховища ESE — ESENT.DLL він отримує атрибут Supplemental-Credentials в зашифрованому вигляді, а на вихід (в SAMSRV.DLL) передає його у відкритому вигляді. Тобто цікаве знаходиться у функції DirRead. Судячи за розміром NTDSA.DLL нам там повинно сподобатися.
Через якийсь час знаходимо цікаву таблицю адрес функцій(наводиться фрагмент):
_ExtIntBool, _EvalBool, _ExtIntUnd, _ExtIntUnd, _EvalInt, _IntExtOctet, _ExtIntOctet, _EvalOctet, _ExtIntUnd, _ExtIntUnd, _EvalTime, _ExtIntUnd, _ExtIntUnicode.
Виявляється, NTDSA віддає дані «нагору» не в тому вигляді, в якому вони знаходяться в сховищі, а вміє їх перетворювати. В залежності від типу атрибута використовується та чи інша функція перетворення. І функція нашого (мабуть самого непростого) перетворення знайдено: _IntExtOctet (Int, що зберігається всередині Active Directory, Ext — те, що видно зовні). Викликати цю функцію зі своєї програми ми не зможемо, тому що ніхто не може звертатися до NTDSA, крім LSASS.EXE. Мабуть доведеться розбиратися, як вона працює і писати аналогічну. Здаватися рано, продовжуємо.
Відразу в функції попадається _PEKDecrypt, ага — знаючі люди нас попереджали, що паролі шифруються за допомогою PEK (Password Encryption Key) (ключ для шифрування пароля). Подивимося, як це робиться.
Перевіряється заголовок _IsValidPEKHeader, потім _PekDecryptData, ще глибше: _PEKInPlaceEncryptDecryptDataWithkey з якимось параметром _g_PekList. Ще глибше: MD5Init, MD5Update,…, rc4_key, rc4.
Ось тут і розшифровується наш атрибут. Як це не сумно, але доведеться переписувати це все, повторити цей алгоритм. Потім, використовуючи його з зашифрованими атрибутами (що знаходяться в XML(згадаємо про essential)), ми зможемо отримати пароль. Так, як це робить функція DirRead. Деяким полегшенням є те, що Microsoft використовувала стандартні алгоритми MD5, RC4. Принаймні, їх реалізацію не треба переписувати. До честі програмістів Microsoft, хочеться сказати, що їх реалізація, зокрема rc4_key є досить ефективною:
char *buf;
int tmp=0x03020100L;
for(int i = 0; i < 0x40; i++, tmp+=0x04040404L) ((int *)(buf))[i] = tmp;
замість стандартного:
for(int i=0;i<0x100;i++) buf[i] =i;
Витрачено час, функція _IntExtOctet переписана. Вона працює! Вона розшифровує атрибут. Залишилася тільки одна маленька проблема, той параметр _g_PekList функції _PEKInPlaceEncryptDecryptDataWithkey. І тепер ця проблема починає рости прямо на очах.
PEKList (Список ключів шифрування пароля) — мабуть в цій структурі може зберігатися не один ключ шифрування атрибута, а кілька, і в зашифрованому атрибуті вказується номер ключа. (Мені не зустрічалися PEKList’и з декількома ключами). При перевірці функції я використовував PekList, який перебував у пам’яті процесу LSASS.EXE. Так дійсно, в моєму домені я можу розшифровувати атрибути.
Але що робити в загальному випадку? Звідки береться цей список?
Спробуємо пошукати поле з таким значення в таблиці datatable. Його там немає! Тобто PekList в тому вигляді, в якому його використовує функція _PekDecryptData, в Active Directory не зберігається. Дивно — невже і він зашифрований? А якщо це так, то як вона розшифровується? Це напевно вже не функція _IntExtOctet (для її роботи як раз і потрібен PekList). А якщо спробувати знайти цей атрибут по імені? Так, дійсно — ось він: PEK-List.
Знаходимо його Attribute-id (590689), потім запис з таким атрибутом: ATTm590715=”[LDAP://CN={31B2F340-016D-11D2-945F-00C04FB984F9},CN=Policies,CN=System,DC=domain,DC=ru;0]”якийсь системний об’єкт. У чому ж відмінність між PEK-List’ом який знаходиться в Active Directory і тим, що знаходиться в пам’яті процесу LSASS.EXE?
Початок однакове, відмінності починаються зі зміщення 0x18, а функція _PEKDecryptData використовує по 16 байт для кожного ключа, починаючи з 60-го. Ці дані якраз відрізняються і мабуть, в Active Directory зашифровані. Після того, що вже було зроблено, здаватися не хочеться, і тому продовжуємо.
В NTDSA.DLL трапляється функція _PEKIntiliaze, в якій _DBGetAttVal_AC (одержання значення атрибута з Active Directory), це ми вже вміємо, потім _PEKGetClearPekList — а це ще немає. Без стуку проходимо всередину: _PEKUpgradeEncryptedPekListToCurrentversion, мабуть використовується при оновленні Windows 2000, Windows NT. Перші чотири байти в PEKList’e визначають номер версії — Windows 2000, версія дорівнює 2. А потім в коді кількома способами виходять якісь дані.
Розглянемо докладніше один. Виконується функція _LsaIHealthCheck c якимись параметрами, у разі її успішного завершення _PEKDecryptPekList, всередині якої вже відома нам _PEKInPlaceEncryptDecryptDataWithkey. Вона вже реалізована і працює. Залишилося знайти, що ж робить _LsaIHealthCheck? Ця функція імпортується з LSASRV.DLL. Бажання завантажити LSASRV у своїй програмі і викликати функцію більше не з’являється. Переходимо до вивчення LSASRV.DLL. Скільки ще DLL залишилося в каталозі System32?
Дивимося, що ж відбувається в функції _LsaIHealthCheck. З тими параметрами, що її викликає _PEKDecryptPekList, вона повертає _LsapDbSysKey!!!
SysKey — адже нас ще на березі попереджали, що зустріч з ним неминуча. Так, і говорили, що він не зберігається в Active Directory. І алгоритм складний і туманний його отримання:
(Use a computer-generated random key as the system key and store it on the local system by using a complex obfuscation algorithm that scatters the system key throughout the registry. This option allows you to restart the computer without having to enter the system key. This is the default configuration for the system key.)
Спробуємо дізнатися про нього. Він зберігається в реєстрі. Microsoft соромиться сказати де і як. Невже кінець?
Але є програми, які паролі підбирають. Наприклад, l0pht crack. Як поводяться вони?
А вони, використовуючи привілей налагоджувати процеси(seDebug), «чіпляються» до процесу LSASS.EXE і читають його пам’ять. Але якщо тепер отримувати Syskey з пам’яті таким способом, чи не простіше просто викликати функцію _SamIRetrievePrimaryCredentials, яку ми зустріли в самому початку? І коштувало тоді з-за цього робити експорт Active Directory? Тобто шлях спочатку був обраний невірно?
Не хочеться зупинятися і визнавати це. Може, є ще якісь програми, які читають, змінюють паролі? Так є, наприклад Offline NT password and registry editor, програма, написана на мові С, її вихідний код доступний. Програма застосовується для скидання пароля.
Маючи доступ до комп’ютера з базою SAM (скидання пароля в домені не виконується), можна завантажитися з linux-диска, при цьому буде змонтований диск NTFS, потім програма CHNTPW підключається до файлів реєстру (SAM, Security,..) і скидає паролі користувачів. Якщо вона може отримати доступ до реєстру, чому не можемо ми? Тому що файли реєстру використовуються і блокуються?
Ми можемо зробити їх резервні копії і використовуючи алгоритми CHNTPW, отримати з реєстру SysKey, так як це робить вона. Велика проблема тільки в тому, що вона не отримує SysKey. Є сенс прочитати, що пишуть розробники про syskey(поки залишено без перекладу):

My utility doesn’t try to crack passwords, it puts new hashes into the SAM, thus changing a users password. And it does this offline. Syskey was a showstopper for this.
As far as I can see, there’s 2 ways to solve this:

1) Find the registry key in, get user to enter it, or get hold of floppy then use the syskey on the new password too. However, it’s not documented and I haven’t found any reverse engineering of it anyplace.

2) Try to turn it off. This has one drawback, and one good side: Bad: all passwords must be reset, since the old hashes will be invalid.
VeryBAD: SWITHCHING OFF IN WINDOWS 2000 AND XP NOT PERFECT, WILL CAUSE TROUBLE, but you can access the computer afterwards. Domain relationships & syskey may be impossible to change after this, requiring a перевстановити (or possibly only an upgrade)
Good: there’s no need for the key (which may be lost).

3) (NEW 2000-04-01, no, not a joke) Insert old styles password-hashes into the SAM, will be converted to syskey-hashes on next boot. This is how syskey is enabled on NT4, the hashes won’t be touched until the first reboot after turning on syskey.

I’ve found out how to do #2 і #3.
What happens when syskey is turned on, and how to turn it off again:

— 1 –
Serveral new keys are added to HKLMSystemCurrentControlSetControllsa, it seems that most of the keys/values is used for the obfuscation of the key they change when syskey is updated.
However the value named ‘SecureBoot’ holds the mode of syskey: 1 — Key in registry
2 — Enter passphrase
3 — Key on floppy
But removing this key (or setting it to 0) isn’t enough to disable syskey. There’s more…

— 2 –
HKLMSAMDomainsAccountF is a binary structure usually containing the computer SID and some other stuff related to that. When syskey is installed it’s expanded (about twice the size), with something I guess is the key heavily encrypted + some flags and other values. One of these other flag/values also contains the same mode as SecureBoot above.
So… resetting this mode flag and SecureBoot to 0 is all that’s needed to switch off syskey in NT4 (up to SP6 at time of writing). Changing only one of them results in a warning about inconsistencies between the SAM and system settings on completed boot, and syskey is re-invoked.

— 3 –
On Windows 2000 there’s yet another place info about syskey is stored:
HKLMsecurityPolicyPolSecretEncryptionkey which is also a binary structure, but also there the mode is stored. Reset to this 0, and syskey is gone on win2k. (if there’s a mismatch between the three, it silently resets them to the most likely value on boot)

— 4 –
Then there’s the password hashes. The usual (old) hashlength is 16 bytes, but all hashes are expanded to 20 bytes with syskey, the first 4 bytes looks like some kind of counter. (maybe history-counter?).
Strangely, they’re not updated at once when syskey is turned on, update of the hashes happens during next reboot after syskey has been turned on. And when the key is later updated, the hashes are also updated? NO!!! Strangely it SEEMS like the password hashes REMAINS THE SAME! (however, the binaries in the 3 keys noted above changes..) i’ll try to dig more into this. Help wanted 🙂
When syskey has been switched off, all passwords must be reset. My utility will write and adjust hash-lengths of the users (usually administrator) that you reset the password for.
NT itself will fix the rest of the hashes when you set new passwords from NT.
And yes, it’s possible to re-enable syskey after turning it off. (not on win2k, yet!)
So, anybody reverse engineered the whole syskeystuff? (yes, I know something’s on it’s way..)

Все дуже сумно. Навіть якщо зробити копію реєстру, отримати SysKey з допомогою відомих програм неможливо. Пора зупинитися і сказати що паролі, зашифровані оборотним чином, не можна розшифрувати? Тому що невідомий складний і заплутаний алгоритм формування SysKey? А якщо все-таки продовжити?

Отже, ми зупинилися на _LsaIHealthCheck і структурі _LsapDbSysKey. Звідки вона береться у LSASS.DLL? Зустрічаємо: _LsapDbGetSyskeyFromWinlogon. І тут підключення до порту SecurityWxApiPort, потім читання з нього даних. А чому ми не можемо це повторити? Підключитися до порту і прочитати SysKey? Може нашій програмі не вистачить прав? Ні, ми не зможемо підключитися, тому що в момент роботи системи цей порт закритий. Мабуть, він використовується лише на етапі завантаження системи. Що залишається?
Знайти хто його відкриває і хто віддає дані. Як можна здогадатися це справа рук WINLOGON.EXE (викреслюємо ще один файл з білого списку). І тут дійсно трапляється NtCreatePort («SecurityWxApiPort»). Трохи походивши навколо, знаходимо процедуру _SbGetKeyData з одним параметром, в якій він аналізується, у випадку 2 — створюється діалог для введення пароля у випадку 3 — теж діалог, потім читається з диска файл a:startkey.key.
Так, у цій процедурі система і отримує SysKey. Нас цікавить варіант читання з реєстру. Параметр дорівнює 1. І ось починається «складний і заплутаний» алгоритм. RegOpenKey — відкривається ключ: SystemCurrentControlSetControlLsa, і потім викликається функція, назва якої приховано (налагоджувальних символах відсутня), наведу її приблизний текст, вже на мові C:
int mix[0x10]={8,0x0A,3,7,2,1,9,0 xF,0,5,0 xD,4,0 xB,6,0 xC,0xE};
RegOpenKey( hKey0, «SYSTEMCurrentControlSetControlLsa», &lsaKey);
buffer[0]=HexToInt(GetClass((«JD», lsaKey)));
buffer[1]=HexToInt(GetClass((«Skew1», lsaKey)));
buffer[2]=HexToInt(GetClass((«Gbg», lsaKey)));
buffer[3]=HexToInt(GetClass((«Data», lsaKey)));
for (int i=0;i<0x10;i++) SysKey[mix[i]]=((BYTE *)buffer)[i];
От і все. Автори chntpw не знайшли Syskey в реєстрі, тому що він зберігається не в значенні якогось ключа, а в назві класу. Причому складається з чотирьох частин. Цей незвичайний хід дозволяв Microsoft тривалий час приховувати його. Цікаво, що право читати його частини має група «Пройшли перевірку». Напевно права не змінені на більш жорсткі, щоб не привертати увагу.
Примітка. У Windows 2003 такі ключі також присутні, але права вже більш суворі.

Залишилося підвести підсумки і отримати остаточний результат. Попередня програма essential може виявитися марною, якщо вам буде необхідно читати зашифрованнные дані, або відновити з XML знову ntds.dit. Не вистачало ключ для розшифрування атрибутів datatable.xml.
Її необхідно доопрацювати і додати процедуру вилучення SYSKEY з того ж комп’ютера, з якого робиться Backup Active Directory. Чому саме з того? В результаті дослідження стало ясно, що для отримання ВСІХ даних зі сховища необхідний ключ, який знаходиться в реєстрі, але реєстру у різних контролерів домену різний.
І Syskey теж. А як же тоді PEKList який зберігається в Active Directory? Адже після реплікації стане однаковим на всіх контролерах, при тому що SysKey різний. Треба думати, що реплікація атрибута SysKey не виконується. Таким чином, контролер домену в своїй копії Active Directory зберігає PEKList(Список ключів шифрування паролів), зашифрований своїм Syskey(ключем). І ClearPEKList («Чистий» список ключів) в домені один, а ось зашифровані відрізняються. Ще один висновок — у загальному випадку неможливо відновити з резервної копії Active Directory (ntds.dit), не відновлюючи реєстру (System).
І ще одне питання — наскільки це універсально? Можливо ці ключі JD, Skew, Gbg, Data — змінюються при установці Service Pack’а, або залежать від мови операційної системи? Відповідь можна знайти знову ж таки в процедурі відновлення системи. Якщо резервна копія стану системи, зроблена в Windows 2000 SP3 відновлюється Windows 2000 без пакетів виправлень, тобто атрибути коректно розшифровуються, значить і syskey знаходиться правильно і алгоритм його використання. Те ж саме можна сказати про локалізовані системи. У Windows 2000 можливо зробити резервну копію стану системи на версією російської і відновити на англійській. Тобто розроблені програми (essential і showmust)працюють в середовищі Windows 2000, на момент написання незалежно від Service Pack’а й системи мови. А як у Windows 2003? Я думаю, що докорінних змін не сталося(можливо там змінено complex obfuscation (складний «туманний» алгоритм), треба просто перевірити…

Можливий був більш простий шлях отримання результату? Так, можливий. Як уже згадувалося, можна було скористатися привілеєм SeDebugPrivilege. За замовчуванням ця привілей дана адміністратору. Але якщо оператор архіву може отримати будь-які дані з системи, чому не можна використовувати його можливості? Хоча б тому в такому довгому дослідженні є сенс.
Які нові можливості відкриваються? Перше що приходить в голову, адміністратор може встановити для користувача атрибут оборотне шифрування пароля, змусити змінити його, і потім, знаючи пароль, отримувати доступ до зашифрованих файлів(EFS) користувача. Цікаво, що в атрибуті SupplementalCredentials знаходиться також параметр Primary:Kerberos. Мабуть це не кінець, і можливо подальший розвиток подій.
Але на даний момент отримуємо програму(essential), яка виконує експорт ntds.dit (Сховища даних Active Directory) в файл XML, з того ж контролера домену отримує SysKey. Друга програма showmust — розшифровує атрибути, розкладає по каталогах і, якщо знаходить паролі, зашифровані оборотним чином, показує їх. Що і слід було написати.

Зауваження.
1. Запустити програму Essential в середовищі Windows XP на жаль не виходить, так як esent.dll змінена. Тому для запуску в Windows XP додайте в каталозі з essential.exe бібліотеки esenet.dll з постачання Windows 2000.
2.У середовищі Windows 2003, програма не була перевірена, на жаль, не вистачає часу, є ще багато цікавого в житті. (Треба ще знайти просте доказ теореми Ферма, а життя таке коротке).