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) IsVisibleInAB UnsignedByte 単一値
JET_COLUMNID(0x8) NCDNT_col 長い 単一値
JET_COLUMNID(0x3) Obj_col UnsignedByte 単一値
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を学習するために作成した小さなユーティリティ (誰かに合うかもしれません)。



All Articles