ntds.ditはどのように構造化されていますか?


すべてのActive Directoryデータは、データベースのntds.ditファイルに保存されます。 大部分のアプリケーションは、ntdsa.dllに実装されているDSAレイヤーを介してディレクトリと対話します。 同様に、ntdsa.dllの関数はntds.ditで直接動作せず、その機能はディレクトリサービスのニーズによって制限され、Active Directoryデータベースの内部構造を把握することはできません。 ただし、ntds.ditはJET Blueデータベースにすぎません。 Windowsの各バージョン(Windows 2000以降)には、このデータベースを操作するために必要なものがすべて揃っています。

以下の記事では、次の問題を強調します。




ntds.ditを見るには何が必要ですか?

少なくとも: esent.dll
ESENT APIを介してさまざまなプログラミング言語を「快適に」使用するために、さまざまな「ラッパー」があります。 Meneged EsentをC#とともに使用しました 。 プロジェクトのサイトには多くの例がありますので、後でntds.ditのコンテンツに焦点を当てようとします。

また、JET BlueデータベースにはPageSizeなどのパラメーターがあることに注意してください。 デフォルトでは、4096です(私が遭遇したesent.dllのバージョンの場合)。 したがって、ntds.ditでは、ページサイズは8192であり、このパラメーターはデータベースを開く前に正しく設定する必要があります。
ESENT APIにはいくつかのバージョンがあります。 これらのバージョンには互換性がありません! そのため、Windows Server 2008 R2のntds.ditはWindows XPでは開かず、Windoes 7でのみ開きます(後方互換性はチェックしませんでした)。

質問1:データベースの構造は何ですか?

GetTableNames関数は、データベース内のテーブルのリストを返します。
datatable-すべてのカタログデータを含むメインテーブル
隠れた
link_table - technet記事によると、関連する属性(MemberOfなど)に関する情報を含むテーブル
quota_rebuild_progress_table
quota_table
sdpropcounttable
sd_table - technet記事によると、テーブルには各ディレクトリオブジェクトの継承されたアクセスルールに関する情報が含まれています。

データテーブルの表を見てみましょう。 列のリストは次のようになります(スクリーンショットの最初の数行)。

行き止まり? いや!
ほとんどの列名は、ATT形式<1文字のラテン文字> <数値コード>です。 したがって、このデジタルコードは、Active Directory属性の一意の識別子です。 テーブルには、列のデジタルコードの値がその値と一致する行が1つあります。 この行からテキストタイプのすべての値を推測すると、これが属性「attributeID」の定義であることがわかります。

現在、テーブルのすべての列をActive Directoryの属性と一致させることを妨げるものはありません(テーブルは例です-短縮されています。そうでない場合、投稿に収まりませんでした)。
JET_COLUMNID列名ジェットコラムタイプAD属性名
JET_COLUMNID(0x6)ab_cnt_col長い単一値
JET_COLUMNID(0x100)祖先_colロングバイナリ単一値
JET_COLUMNID(0x536)ATTb131079長いsubRefs多値
JET_COLUMNID(0x121)ATTb131088長いnCName多値
JET_COLUMNID(0x2dd)ATTb131108長いdMDLocation多値
JET_COLUMNID(0x42c)ATTb1376270長いdocumentAuthor多値
JET_COLUMNID(0x169)ATTb1376277長い秘書多値
JET_COLUMNID(0x2b8)ATTb1376294長いrelatedName多値
JET_COLUMNID(0x470)ATTb33長いroleOccupant多値
JET_COLUMNID(0x203)ATTb34長いまた見よ多値
JET_COLUMNID(0x2d2)ATTb49長い識別名多値
JET_COLUMNID(0x4cc)ATTb50長いuniqueMember多値
JET_COLUMNID(0x206)ATTb589856長いdomainPolicyObject多値
JET_COLUMNID(0x250)ATTb589864長いfromServer多値
JET_COLUMNID(0x205)ATTb589881長いdefaultLocalPolicyObject多値
JET_COLUMNID(0x1cc)ATTb589921長いpreferredOU多値
JET_COLUMNID(0x5a6)ATTb590037長いdefaultClassStore多値
JET_COLUMNID(0x270)ATTb590038長いnextLevelStore多値
JET_COLUMNID(0x183)ATTb590127長いnotificationList多値
JET_COLUMNID(0x238)ATTb590192長いrIDManagerReference多値
JET_COLUMNID(0x57c)ATTb590193長いfSMORoleOwner多値
JET_COLUMNID(0x3c8)ATTb590246長いdomainPolicyReference多値
JET_COLUMNID(0x566)ATTb590281長いlocalPolicyReference多値
JET_COLUMNID(0x3c1)ATTb590295長いtrustParent多値
JET_COLUMNID(0x4c1)ATTb590296長いdomainCrossRef多値
JET_COLUMNID(0x5bc)ATTb590304長いdefaultGroup多値
JET_COLUMNID(0x57f)ATTb590318長いsiteServer多値
JET_COLUMNID(0x532)ATTb590338長いphysicalLocationObject多値
JET_COLUMNID(0x563)ATTb590341長いipsecPolicyReference多値
JET_COLUMNID(0x24f)ATTb590361長いdynamicLDAPServer多値
JET_COLUMNID(0x1a4)ATTb590381長いparentCA多値
JET_COLUMNID(0x233)ATTb590448長いipsecOwnersReference多値
JET_COLUMNID(0x345)ATTq590722通貨aCSNonReservedTxSize多値
JET_COLUMNID(0x398)ATTq591137通貨aCSMaxTokenBucketPerFlow多値
JET_COLUMNID(0x19b)ATTq591138通貨aCSMaximumSDUSize多値
JET_COLUMNID(0x4d3)ATTq591139通貨aCSMinimumPolicedSize多値
JET_COLUMNID(0x244)ATTq591140通貨aCSMinimumLatency多値
JET_COLUMNID(0x12f)ATTq591141通貨aCSMinimumDelayVariation多値
JET_COLUMNID(0x16e)ATTq591142通貨aCSNonReservedPeakRate多値
JET_COLUMNID(0x344)ATTq591143通貨aCSNonReservedTokenSize多値
JET_COLUMNID(0x4d4)ATTq591144通貨aCSNonReservedMaxSDUSize多値
JET_COLUMNID(0x343)ATTq591145通貨aCSNonReservedMinPolicedSize多値
JET_COLUMNID(0x5ac)ATTq591191通貨mS-SQL-Memory多値
JET_COLUMNID(0x213)ATTq591204通貨mS-SQL-Status多値
JET_COLUMNID(0x4d5)ATTq591220通貨mS-SQL-サイズ多値
JET_COLUMNID(0x2c5)ATTq591266通貨msDS-Cached-Membership-Time-Stamp多値
JET_COLUMNID(0x548)ATTq591456通貨msWMI-Int8Default多値
JET_COLUMNID(0x52a)ATTq591457通貨msWMI-Int8Max多値
JET_COLUMNID(0x53f)ATTq591458通貨msWMI-Int8Min多値
JET_COLUMNID(0x214)ATTq591459通貨msWMI-Int8ValidValues多値
JET_COLUMNID(0x2c1)ATTq591520通貨lastLogonTimestamp多値
JET_COLUMNID(0x2cc)ATTq591794通貨msDS-LastSuccessfulInteractiveLogonTime多値
JET_COLUMNID(0x462)ATTq591795通貨msDS-LastFailedInteractiveLogonTime多値
JET_COLUMNID(0x440)ATTq591835通貨msDS-MaximumPasswordAge多値
JET_COLUMNID(0x2a5)ATTq591836通貨msDS-MinimumPasswordAge多値
JET_COLUMNID(0x200)ATTq591841通貨msDS-LockoutObservationWindow多値
JET_COLUMNID(0x2e7)ATTq591842通貨msDS-LockoutDuration多値
JET_COLUMNID(0x3d0)ATTq591879通貨msDS-USNLastSyncSuccess多値
JET_COLUMNID(0x49a)ATTq591922通貨msDS-ClaimValueType多値
JET_COLUMNID(0x476)ATTq592002通貨msKds-UseStartTime多値
JET_COLUMNID(0x477)ATTq592003通貨msKds-CreateTime多値
JET_COLUMNID(0x3a0)ATTq592007通貨msDS-GeoCoordinatesAltitude多値
JET_COLUMNID(0x3a1)ATTq592008通貨msDS-GeoCoordinatesLatitude多値
JET_COLUMNID(0x3a2)ATTq592009通貨msDS-GeoCoordinatesLongitude多値
JET_COLUMNID(0x43b)ATTr589945ロングバイナリsecurityIdentifier多値
JET_COLUMNID(0x1c9)ATTr589970ロングバイナリobjectSid多値
JET_COLUMNID(0x276)ATTr590433ロングバイナリsIDHistory多値
JET_COLUMNID(0x443)ATTr590491ロングバイナリsyncWithSID多値
JET_COLUMNID(0x5e4)ATTr591234ロングバイナリmS-DS-CreatorSID多値
JET_COLUMNID(0x50a)ATTr591668ロングバイナリmsDS-QuotaTrustee多値
JET_COLUMNID(0x1c2)ATTr591978ロングバイナリmsAuthz-CentralAccessPolicyID多値
JET_COLUMNID(0x5)cnt_col長い単一値
JET_COLUMNID(0x1)DNT_col長い単一値
JET_COLUMNID(0x5f1)extendedprocesslinks_colロングバイナリ単一値
JET_COLUMNID(0x9)IsVisibleInABUnsignedByte単一値
JET_COLUMNID(0x8)NCDNT_col長い単一値
JET_COLUMNID(0x3)Obj_colUnsignedByte単一値
JET_COLUMNID(0x2)PDNT_col長い単一値
JET_COLUMNID(0x4)RDNtyp_col長い単一値
JET_COLUMNID(0xa)recycle_time_col通貨単一値
JET_COLUMNID(0x7)time_col通貨単一値



「暗号化されていない」ATTc0属性が1つ残っています。これは「objectClass」への参照です。
Active Directoryの属性を格納するすべての列は、スキームに関係なく複数値として設定されることに注意してください。

質問2:ntds.ditのデータはどのように「ツリー」ですか?

列名「DNT_col」は、それが何らかの形でオブジェクトのdistinguishedNameに関連していることを示唆するように誘発します(後で判明したように、それらは等しい)
DNT_col列の値は1で始まり、DNT_col = 1の行は、属性値name = "$ NOT_AN_OBJECT1 $"を持つ興味深いオブジェクトに対応します。
DNT_col = 2の行には、「$ ROOT_OBJECT $」という名前のオブジェクトの属性が含まれています(RootDSEと混同しないでください)
DNT_col = 6で、objectClass定義が始まります
別の行き止まり? もういや!
他の方法で行きましょう。
タイプ「Administrator」の値のATTm589825(名前)列での検索は、DNT_col = 3841およびPDNT_col = 1951のレコードを返しました。
ATTm589825(名前)列でテキスト「ユーザー」タイプの値(標準管理者アカウントが配置されているコンテナ)を検索すると、DNT_col = 1951およびPDNT_col = 1944のエントリが返されました
これが接続です! PDNT_col列には、親オブジェクトのDNT_col識別子が含まれています。
DNT_col = 1944(PDNT_col = 1943)の行-第2レベルドメインオブジェクトがありました(ntds.ditは第2レベルドメインコントローラーから取得されました)
DNT_col = 1943(PDNT_col = 2)の行-第1レベルドメインのオブジェクト。


「cn =構成のオブジェクト、dc = contoso、dc = contoso、dc = comに接続したときにdc = comが表示されないのはなぜですか?」ネーミングコンテキストオブジェクト。 (さらに、第1レベルのドメインオブジェクトには名前付けコンテキストがありません。表示されないようにすることはできますか?)。 命名コンテキスト「dc = contoso、dc = com」および「cn =構成、dc = contoso、dc = com」のオブジェクトの場合、この列の値は異なります。

これらの数値からオブジェクトの完全なdistinguishedNameがどのように取得されるかは、それほど興味深いことではありません。 オブジェクトのどの属性が相対固有名(RDN)であり、完全識別名を作成するために使用されます。
RDNtyp_col列には、RDNを含む属性識別子(attributeID)が含まれます。
CNT_col列には、現在に関連付けられているオブジェクトの数が含まれています。 この列は、 Link Cleanerによって使用されます。
OBJ_col列のビットが1に設定されている場合、この行はディレクトリオブジェクトを示します。 それ以外の場合は、ファントムオブジェクトです。

SubTree検索はどのように実装されますか?
このような構造では、OneLavelを検索するには、PDNT_colが検索ベースのDNに等しいレコードを検索するだけで十分ですが、SubTreeで検索するにはどうすればよいでしょうか? すべての支店を回る? いいえ、複雑すぎます。
Ancestors_colという名前の列の値を見てみましょう。 階層内のオブジェクトが深いほど、この列の値が長くなることは印象的です。 ネストレベルごとに、長さが4バイト追加されます。 これは、親オブジェクトの優先順位のリストに過ぎません。
さらに、リストはdn = 2で始まります。 「$ ROOT_OBJECT $」
Ancestors_colを最新の状態に保つのは誰ですか? 文書によると、オブジェクトを新しい場所に移動すると、そのPDNT_colのみが変更され、Ancestors_colの値は、オブジェクトにアクセスするための新しいルールが再カウントされると同時にSDPropメカニズムによって更新されます。

質問3:グループメンバーシップはどのように実装されますか?

2003年以降、サーバーにはグループに無制限の数のユーザーを含める機会があり、文字列または数値の複数値属性に最大1200を超える値を書き込むことができないのはなぜですか?
はい。「member」と「memberOf」はリンクとして定義されているためです。 これらの属性に一致するデータテーブルの列はありません。 これらの属性の値は、別個のlink_tableのマッピングとして実装されます。
おそらくこれが、(RecucleBinを使用せずに)グループを削除すると、そのメンバーに関する情報を失うためです- 削除されたオブジェクトをコンテナーに移動すると、リモートグループのオブジェクトはDNT_colで新しい識別子を受け取ります (グループとそのメンバーの接続はこの識別子を使用して構築されます)
link_tableの列を見てみましょう
JET_COLUMNID(0x2)backlink_DNT長い単一値
JET_COLUMNID(0x3)link_base長い単一値
JET_COLUMNID(0x100)link_dataロングバイナリ単一値
JET_COLUMNID(0x4)link_deactivetime通貨単一値
JET_COLUMNID(0x5)link_deltime通貨単一値
JET_COLUMNID(0x1)link_DNT長い単一値
JET_COLUMNID(0x80)link_metadataバイナリ単一値
JET_COLUMNID(0x7)link_ncdnt長い単一値
JET_COLUMNID(0x101)link_ndesc長い単一値
JET_COLUMNID(0x6)link_usnchanged通貨単一値



列の名前とタイプがヒントになり、列に含まれるデータの分析により次のことが確認されます。
link_DNT-通信が記述されているオブジェクト(グループオブジェクトなど)の識別子dn(データテーブルのDNT_colに対応)を含む
backlink_DNT-関連するオブジェクト(ユーザーオブジェクトなど)のdn識別子が含まれます
link_ncdnt-通信参加者が存在するネーミングコンテキストのdn識別子が含まれます。
link_usnchanged-最後の最後のUSN変更が含まれています
link_data-このフィールドは、NTDS設定オブジェクトの関連付けについてのみ入力されているのを見ました。 はい! NTDS設定オブジェクトには、ディレクトリパーティションオブジェクトとのリンクがありますが、これらのリンクを通じて、さまざまなディレクトリセクションのレプリケーションパラメータが設定されているようです。
link_deltime-リンクが削除された時刻が含まれます
link_metadata-行われた変更を複製するために必要なメタデータが含まれています。 Windows 2012では、この列の入力値のみを見ました。ChristofferAndersson列にDS_REPL_VALUE_META_DATA構造が含まれ いる書いていますがここでは強く反対します。 DS_REPL_VALUE_META_DATA構造はより高いレベルで使用されます-ntdsa.dllの呼び出しはそれを返します。 この列に含まれるデータは、DS_REPL_VALUE_META_DATA構造の下で必要なデータよりも小さくなっています。 このコラムは私には謎のままです。 原則として、リンク属性のレプリケーションメタデータは、構築されたmsDS-ReplValueMetaData属性から取得できますが、このデータを処理および保存するための内部メカニズムは明らかにされていません。

4番目の質問:replPropertyMetaData属性の形式は何ですか?また、タイムスタンプはレプリケーションメタデータにどの程度正確に保存されますか?


この属性は、バイナリ複製メタデータを保存します

この構造の最初の8バイトに何が格納されているかはまだわかりません。
値を持つ複製された属性のみがreplPropertyMetaData構造にリストされるという事実に注意する必要があります。 したがって、たとえば、replPropertyMetaDataにlogonTimestamp属性識別子は表示されません。
興味深い点があります。ActiveDirectoryセキュリティオブジェクト(ユーザー、グループ、およびコンピューター)のreplPropertyMetaData構造には、objectSid属性が存在します。
ところで、この属性の値を解読するために-このように負担をかける必要はありません-構築された属性msDS-ReplAttributeMetaDataがあります-それはreplPropertyMetaDataの解析された値以外を表しません。

Active Directoryのタイムスタンプは、1601年1月1日00:00から経過した秒数を示す64ビットの符号なし整数です。 これには興味深いニュアンスがあります。2つのドメインコントローラー上の同じオブジェクトの1つの属性を1秒間編集すると(たとえば、多数のユーザーをバッチ処理する場合)、予期しない結果が得られます。
technetの記事によると、 GUIDが低いコントローラーの属性のバージョンが優先されます。

使用される情報:

technet.microsoft.com/en-us/library/cc772829%28v=ws.10%29.aspx
blogs.chrisse.se/2012/02/11/how-the-active-directory-data-store-really-works-inside-ntds-dit-part-1
blogs.chrisse.se/2012/02/15/how-the-active-directory-data-store-really-works-inside-ntds-dit-part-2
blogs.chrisse.se/2012/02/20/how-the-active-directory-data-store-really-works-inside-ntds-dit-part-3
blogs.chrisse.se/2012/02/28/how-the-active-directory-data-store-really-works-inside-ntds-dit-part-4
gexeg.blogspot.ru/2009/12/active-directory.html
www.ntdsxtract.com

すべての実験は、Windows Server 2012 Engのntds.ditで実行されました

UPD まず、ntds.ditを学習するために作成した小さなユーティリティ (誰かに合うかもしれません)。

Source: https://habr.com/ru/post/J172865/


All Articles