Chapter 2. NTドメインにおけるRPC

Luke Leighton

Duncan Stansfield

01 November 97(version 0.0.24)

Table of Contents

概要
ソース
クレジット
注意事項と構造
注意事項
列挙
構造体
名前付きパイプトランザクション上でのMSRPC
MSRPC パイプ
ヘッダー
Tail
RPC Bind / Bind Ack
NTLSA トランザクション名前付きパイプ
LSAオープンポリシー
LSA Query Info ポリシー
LSA がエミュレートする信頼するドメイン
LSA Open Secret
LSA Close
LSA Lookup SIDS
LSA ルックアップ名
NETLOGON rpc トランザクション名前付きパイプ
LSA Request Challenge
LSA Authenticate 2
LSA Server Password Set
LSA SAM Logon
LSA SAM Logoff
\\MAILSLOT\NET\NTLOGON
PDCのためのクエリ
SAM Logon
SRVSVC トランザクション名前付きパイプ
Net Share Enum
Net Server Get Info
NTドメイン認証における暗号化の側面
定義
プロトコル
コメント
SIDとRID
よく知られているSID
よく知られているRID

概要

この文書にはNTサーバーを使わないでNTワークステーションのログオンサービスを提供するための 情報が記述されている。これはLukeによって管理されている、 http://mailhost.cb1.com/~lkcl/cifsntdomain.txt のsgmlバージョンである。

(NTワークステーションのTCP/IP設定中で)ワークグループの代わりにドメインを選択することは 可能であり、必須である再起動後に、ユーザー名とパスワードを入力し、ドメインを選択すれば 正しくログオンできる。この文書に対する、上記作業の経験からの、何らかのフィードバック 、何らかのコメント、修正と追加事項は歓迎する。

ここで説明するパケットはNetmon.exeによって簡単に(そしておそらくそれを使うことでより よく理解でき)得られる。NETLOGON、lsarpcとsrvsvcトランザクションパイプを正しくデコード するために、使用しているシステムに一致するNetmonのバージョンを使う必要がある。 この文書は、NTサービスパック1の、それに適合したバージョンのNetmonから得られている。 これは、この文書よりもより有益であろう、注釈付きのパケットトレースが生成されることを 目的としている。

また、NTドメインログオンサービスを完全に実装するため、NTの認証の暗号化部分を 説明する文書も必要である。この文書は comp.protocols.smbから公開されている、 ntsecurity.net のからの要約とsamba digestからとその他のソースからのものを使っている。

コピーは以下にある:

http://ntbugtraq.rc.on.ca/SCRIPTS/WA.EXE?A2=ind9708;L=ntbugtraq;O=A;P=2935

http://mailhost.cb1.com/~lkcl/crypt.html

Linus Nordbergによる、 このプロトコルに関するC言語での実装は、以下にある:

http://samba.org/cgi-bin/mfs/01/digest/1997/97aug/0391.html

http://mailhost.cb1.com/~lkcl/crypt.txt

デバッグ情報の提供のためにはNT workstationのCheck Buildバージョンも必要であり、 NETLOGON中で完全なデバッグを有効にする。これは以下のようにして、REG_SZ レジストリーキーを 0x1ffffff に設定することで行える:

HKLM\SYSTEM\CurrentControlSet\Services\Netlogon\Parameters

不正にレジストリを編集すると、使用しているマシンを動作不能にさせる 事になる。このプロトコルの不正な実装になる。上記の"Liability:"を参照のこと。

ネットワーク上の各パケットはAPI呼び出しにおいて固有のオリジンを持っていることを 心にとめておくこと。そのため、その定義がほかの所で便利に文書化されている、 構造体や列挙型かもしれない。

この文書は、決して完全でも正式でもない。以下のようものだけではなく、 抜けているところがある:

  1. ユーザー名からRID(やその他(へのマッピング。

  2. ユーザーIDとグループIDが何であるかということ。

  3. 種々の、特定の定数または列挙型の正確な意味と定義。

  4. ワークステーションがドメインのメンバーになるときの、返されるエラーコードと エラーコードの使用法(後で説明)。失敗時に返されるエラーコードは、ワークステーション上で すでにドメインのメンバーになっているという表示を行わせる。

  5. ワークステーションにそのパスワードを変更させることが出来るようにする、 NetrServerPasswordSetコマンドの暗号化の側面。このパスワードは長期でのセッションキー を生成するのに使われる[このコマンドを拒否するのも可能で、その場合は既定値の ワークステーションパスワードを保持する]。

ソース

cket Traces from Netmonitor (Service Pack 1 and above)
ul Ashton and Luke Leighton's other "NT Domain" doc.
FS documentation - cifs6.txt
FS documentation - cifsrap2.txt

クレジット

Paul Ashton: loads of work with Net Monitor; understanding the NT authentication system; reference implementation of the NT domain support on which this document is originally based.
Duncan Stansfield: low-level analysis of MSRPC Pipes.
Linus Nordberg: producing c-code from Paul's crypto spec.
Windows Sourcer development team

注意事項と構造

注意事項

  1. SMBトランザクションパイプ中で、いくつかの"構造体"がここで説明されていて、 開始時に4バイト境界で整列されたSMBヘッダーがある。正確に"構造体"を整列させる 必要性は、正確には知られても、文書化されてもいない。

  2. UDP NETLOGON Mailslot中で、いくつかの"構造体"がここで説明されていて、開始時に、 mailslotの先頭に2バイト境界で整列されている。

  3. Domain SIDはS-revision-version-auth1-auth2...authNという形式である。たとえば、 Domain SID is of the format S-revision-version-auth1-auth2...authN. S-1-5-123-456-789-123-456である。ここで、5はサブバージョンでもありえる。

  4. 参照する文字バッファーが文字を含むなら、文書化されていないバッファーポインターは0以外で なければならない。それが正確に何であるかは不明である。0x0000 0002は、バッファーが 存在することを指示するためのトリックを行っているように見える。もしも、バッファー ポインターがNULLの場合、構造体が参照するものはSMBデータストリームへ(あるいは から) 置かれない。これは、経験的に得られたものであり、例えば、バッファーポインターがNULLの、 LSA SAMログオンレスポンスパケットのユーザー情報はデータストリーム中には挿入されない。 いろいろと推測することは出来るが、バッファーポインターの配列が正確になんなのかは 未知である。

  5. 構造体(コンテナー)の配列は、カウンターとポインターを持つように見える。もしもカウンターが ゼロならば、ポインターもゼロである。SMBデータストリームにさらなるデータは存在しない。 もしも、カウンターがゼロでない場合、ポインターもゼロではない。ポインターの直後には また、コンテナーのサブ構造体の配列が続くカウンターが来る。カウンターは最後のサブ構造体 の後に3回目のカウンターが来る。

列挙

MSRPCヘッダータイプ

msrpcパケットヘッダー中のコマンド番号

MSRPC_Request:

0x00

MSRPC_Response:

0x02

MSRPC_Bind:

0x0B

MSRPC_BindAck:

0x0C

MSRPC パケット情報

これらのフラグの意味は文書化されていない

FirstFrag:

0x01

LastFrag:

0x02

NotaFrag:

0x04

RecRespond:

0x08

NoMultiplex:

0x10

NotForIdemp:

0x20

NotforBcast:

0x40

NoUuid:

0x80

構造体

VOID *

sizeof VOID* は 32ビットである。

char

sizeof char は8 ビットである。

UTIME

UTIME は 32 ビットであり、1980年1月1日からの秒数を示す。cifs6.txtで説明がある (section 3.5 page, page 30)。

NTTIME

NTTIME は 64 ビットである。cifs6.txtで説明がある (section 3.5 page, page 30)。

DOM_SID (domain SID 構造体)

UINT32

num of sub-authorities in domain SID

UINT8

SID revision number

UINT8

num of sub-authorities in domain SID

UINT8[6]

6 bytes for domain SID - Identifier Authority.

UINT16[n_subauths]

domain SID sub-authorities

注意:ドメイン SID はどこかで文書化されている。

STR (文字列)

STR (文字列) は char[] である: これはnull文字で終端するASCII文字列である。

UNIHDR (UNICODE文字列ヘッダー)

UINT16

length of unicode string

UINT16

max length of unicode string

UINT32

4 - undocumented.

UNIHDR2 (UNICODE文字列ヘッダー+バッファーポインター)

UNIHDR

unicode string header

VOID*

undocumented buffer pointer

UNISTR (UNICODE文字列)

UINT16[]

null-terminated string of unicode characters.

NAME (長さが指定されているUNICODE文字列)

UINT32

length of unicode string

UINT16[]

null-terminated string of unicode characters.

UNISTR2 (境界に整合してあるUNICODE文字列)

UINT8[]

padding to get unicode string 4-byte aligned with the start of the SMB header.

UINT32

max length of unicode string

UINT32

0 - undocumented

UINT32

length of unicode string

UINT16[]

string of uncode characters

OBJ_ATTR (オブジェクト属性)

UINT32

0x18 - length (in bytes) including the length field.

VOID*

0 - root directory (pointer)

VOID*

0 - object name (pointer)

UINT32

0 - attributes (undocumented)

VOID*

0 - security descriptior (pointer)

UINT32

0 - security quality of service

POL_HND (LSAポリシーハンドル)

char[20]

policy handle

DOM_SID2 (ドメインSID構造体で、SIDSはUNICODEで格納される)

UINT32

5 - SID type

UINT32

0 - undocumented

UNIHDR2

domain SID unicode string header

UNISTR

domain SID unicode string

注意: 文字列の長さを指定示すために、どちらを使うかについて、 UNICODE文字列ヘッダーとUNICODE文字列自身との間で競合がある。これは解決されねばならないだろう。

注意: SIDタイプは、たとえば別名、既定のグループ等などを指示する。これは どこかで文書化されている。

DOM_RID (ドメイン RID 構造体)

UINT32

5 - well-known SID. 1 - user SID (see ShowACLs)

UINT32

5 - undocumented

UINT32

domain RID

UINT32

0 - domain index out of above reference domains

LOG_INFO (サーバー、アカウント、クライアント構造)

注意: ログオンサーバー名は、2つの'\'で始まり、大文字である。

注意: アカウント名は、LSAリクエストチャレンジからのログオンクライアント名で、最後に$があり、大文字である。

VOID*

undocumented buffer pointer

UNISTR2

logon server unicode string

UNISTR2

account name unicode string

UINT16

sec_chan - security channel type

UNISTR2

logon client machine unicode string

CLNT_SRV (サーバー、クライアント、名前構造体)

注意: ログオンサーバー名は2つの'\'で始まり、大文字である。

VOID*

undocumented buffer pointer

UNISTR2

logon server unicode string

VOID*

undocumented buffer pointer

UNISTR2

logon client machine unicode string

CREDS (credentials + time stamp)

char[8]

credentials

UTIME

time stamp

CLNT_INFO2 (サーバー、クライアント構造体、クライアント認証情報)

注意: 要求中にこの構造体が使われた時にはいつでも、引き続く認証検査で使われるため、 受け取ったクライアントで計算された認証情報のコピーを取る必要がある。仮定された意図は、認証された 要求/応答の痕跡を維持することである。

CLNT_SRV

client and server names

UINT8[]

???? padding, for 4-byte alignment with SMB header.

VOID*

pointer to client credentials.

CREDS

client-calculated credentials + client time

CLNT_INFO (サーバー、アカウント、クライアント構造体、クライアント認証情報)

注意: 要求中にこの構造体が使われた時にはいつでも、引き続く認証検査で使われるため、 受け取ったクライアントで計算された認証情報のコピーを取る必要がある。仮定された意図は、認証された 要求/応答の痕跡を維持することである。

LOG_INFO

logon account info

CREDS

client-calculated credentials + client time

ID_INFO_1 (id 情報構造体、認証レベル 1)

VOID*

ptr_id_info_1

UNIHDR

domain name unicode header

UINT32

param control

UINT64

logon ID

UNIHDR

user name unicode header

UNIHDR

workgroup name unicode header

char[16]

arc4 LM OWF Password

char[16]

arc4 NT OWF Password

UNISTR2

domain name unicode string

UNISTR2

user name unicode string

UNISTR2

workstation name unicode string

SAM_INFO (sam logon/logoff ID情報構造体)

注意: たぶん、戻される認証情報は、おそらく認証チェインが脆弱でない事を、サーバーが検査するためのものである。

CLNT_INFO2

client identification/authentication info

VOID*

pointer to return credentials.

CRED

return credentials - ignored.

UINT16

logon level

UINT16

switch value

        switch (switch_value)
        case 1:
        {
            ID_INFO_1     id_info_1;
        }

GID (グループID情報)

UINT32

group id

UINT32

user attributes (only used by NT 3.1 and 3.51)

DOM_REF (ドメインリファレンス情報)

VOID*

undocumented buffer pointer.

UINT32

num referenced domains?

VOID*

undocumented domain name buffer pointer.

UINT32

32 - max number of entries

UINT32

4 - num referenced domains?

UNIHDR2

domain name unicode string header

UNIHDR2[num_ref_doms-1]

referenced domain unicode string headers

UNISTR

domain name unicode string

DOM_SID[num_ref_doms]

referenced domain SIDs

DOM_INFO (ドメイン情報、レベル3と5は同じ))

UINT8[]

??? padding to get 4-byte alignment with start of SMB header

UINT16

domain name string length * 2

UINT16

domain name string length * 2

VOID*

undocumented domain name string buffer pointer

VOID*

undocumented domain SID string buffer pointer

UNISTR2

domain name (unicode string)

DOM_SID

domain SID

USER_INFO (ユーザーログオン情報)

注意: 16バイトのユーザーセッションキーが何のためかを知ることはすてきであろう。

NTTIME

logon time

NTTIME

logoff time

NTTIME

kickoff time

NTTIME

password last set time

NTTIME

password can change time

NTTIME

password must change time

UNIHDR

username unicode string header

UNIHDR

user's full name unicode string header

UNIHDR

logon script unicode string header

UNIHDR

profile path unicode string header

UNIHDR

home directory unicode string header

UNIHDR

home directory drive unicode string header

UINT16

logon count

UINT16

bad password count

UINT32

User ID

UINT32

Group ID

UINT32

num groups

VOID*

undocumented buffer pointer to groups.

UINT32

user flags

char[16]

user session key

UNIHDR

logon server unicode string header

UNIHDR

logon domain unicode string header

VOID*

undocumented logon domain id pointer

char[40]

40 undocumented padding bytes. future expansion?

UINT32

0 - num_other_sids?

VOID*

NULL - undocumented pointer to other domain SIDs.

UNISTR2

username unicode string

UNISTR2

user's full name unicode string

UNISTR2

logon script unicode string

UNISTR2

profile path unicode string

UNISTR2

home directory unicode string

UNISTR2

home directory drive unicode string

UINT32

num groups

GID[num_groups]

group info

UNISTR2

logon server unicode string

UNISTR2

logon domain unicode string

DOM_SID

domain SID

DOM_SID[num_sids]

other domain SIDs?

SH_INFO_1_PTR (レベル1共有情報文字列へのポインター)

注意: cifsrap2.txtの section5, page 10を参照。

0 for shi1_type indicates a Disk.
1 for shi1_type indicates a Print Queue.
2 for shi1_type indicates a Device.
3 for shi1_type indicates an IPC pipe.
0x8000 0000 (top bit set in shi1_type) indicates a hidden share.
VOID*

shi1_netname - pointer to net name

UINT32

shi1_type - type of share. 0 - undocumented.

VOID*

shi1_remark - pointer to comment.

SH_INFO_1_STR (level 1 共有情報文字列)

UNISTR2

shi1_netname - unicode string of net name

UNISTR2

shi1_remark - unicode string of comment.

SHARE_INFO_1_CTR

share container with 0 entries:

UINT32

0 - EntriesRead

UINT32

0 - Buffer

share container with > 0 entries:

UINT32

EntriesRead

UINT32

non-zero - Buffer

UINT32

EntriesRead

SH_INFO_1_PTR[EntriesRead]

share entry pointers

SH_INFO_1_STR[EntriesRead]

share entry strings

UINT8[]

padding to get unicode string 4-byte aligned with start of the SMB header.

UINT32

EntriesRead

UINT32

0 - padding

SERVER_INFO_101

注意: cifs6.txt section 6.4を参照 - その中で説明されているフィールドはここで補足する。 例えば、以下でリストされたタイプは6.4.1で説明されているfServerTypeと同じである。

SV_TYPE_WORKSTATION

0x00000001 All workstations

SV_TYPE_SERVER

0x00000002 All servers

SV_TYPE_SQLSERVER

0x00000004 Any server running with SQL server

SV_TYPE_DOMAIN_CTRL

0x00000008 Primary domain controller

SV_TYPE_DOMAIN_BAKCTRL

0x00000010 Backup domain controller

SV_TYPE_TIME_SOURCE

0x00000020 Server running the timesource service

SV_TYPE_AFP

0x00000040 Apple File Protocol servers

SV_TYPE_NOVELL

0x00000080 Novell servers

SV_TYPE_DOMAIN_MEMBER

0x00000100 Domain Member

SV_TYPE_PRINTQ_SERVER

0x00000200 Server sharing print queue

SV_TYPE_DIALIN_SERVER

0x00000400 Server running dialin service.

SV_TYPE_XENIX_SERVER

0x00000800 Xenix server

SV_TYPE_NT

0x00001000 NT server

SV_TYPE_WFW

0x00002000 Server running Windows for

SV_TYPE_SERVER_NT

0x00008000 Windows NT non DC server

SV_TYPE_POTENTIAL_BROWSER

0x00010000 Server that can run the browser service

SV_TYPE_BACKUP_BROWSER

0x00020000 Backup browser server

SV_TYPE_MASTER_BROWSER

0x00040000 Master browser server

SV_TYPE_DOMAIN_MASTER

0x00080000 Domain Master Browser server

SV_TYPE_LOCAL_LIST_ONLY

0x40000000 Enumerate only entries marked "local"

SV_TYPE_DOMAIN_ENUM

0x80000000 Enumerate Domains. The pszServer and pszDomain parameters must be NULL.

UINT32

500 - platform_id

VOID*

pointer to name

UINT32

5 - major version

UINT32

4 - minor version

UINT32

type (SV_TYPE_... bit field)

VOID*

pointer to comment

UNISTR2

sv101_name - unicode string of server name

UNISTR2

sv_101_comment - unicode string of server comment.

UINT8[]

padding to get unicode string 4-byte aligned with start of the SMB header.

名前付きパイプトランザクション上でのMSRPC

名前付きパイプ上のSMBトランザクションの詳細はcifs6.txtを参照。

MSRPC パイプ

MSRPCは\PIPE\という名前のSMBトランザクションパイプ上で行われる。 たとえば、パイプ名\PIPE\srvsvcでSMBopenXを送信することで、 まず初めに16ビットのファイルハンドルを得ておかねばならない。そうすると次に SMB Transを実行でき、処理が終了したら、ファイルハンドル上でSMBCloseを送る必要がある。

Trans Requestは(これについては知られていないが)1つのUINT16ではなく2つのUINT16 セットアップパラメーターと、MSRPCヘッダーを含むために十分なUINT8データパラメーターと MSRPCデータを送る必要がある。最初のUINT16セットアップパラメーターはRPCを指定するために 0x0026か、Set Named Pipe Handle Stateを指示するために、0x0001のどちらかでなければ ならない。2番目のUINT16パラメーターは、上記で得られた、パイプ用のファイルハンドルで なければならない。

Trans Request中の、0x0026 (RPC pipe)であるAPIコマンド用のデータセクションは、RPCデータが 後に来るRPCヘッダーである。0x0001のAPIコマンド(Set Named Pipe Handle state)のための データセクションは、2バイトである。その2バイトの中に現れるものは、0x00 0x43のみである。 The Data section for an API Command of 0x0026 (RPC pipe) in the Trans Request is the RPC Header, followed by the RPC Data. The Data section for an API Command of 0x0001 (Set Named Pipe Handle state) is two bytes. The only value seen for these two bytes is 0x00 0x43.

MSRPC ResponseはMSPRCヘッダー、MSRPCデータとMSRPCフッター(訳注:tail)がある、標準 SMB Transレスポンス内で、レスポンスデータとして送信される。

Trans Requestが少なくとも2バイト境界(おそらく4バイト)に配置される必要があるだろうと いうことは、推測される。これは、SMBに対して標準的な慣習である。また、MSRPCヘッダーと MSRPCデータの間での4バイト単位境界を含む、MSRPCヘッダーの4バイト単位境界とは独立している。 It is suspected that the Trans Requests will need to be at least 2-byte aligned (probably 4-byte). This is standard practice for SMBs. It is also independent of the observed 4-byte alignments with the start of the MSRPC header, including the 4-byte alignment between the MSRPC header and the MSRPC data.

最初に、IPC$共有に対してSMBtconX接続が行われる。コネクションは、平文ではなく、 暗号化したパスワードを使って行わなければならない。次に、SMBOpenXがパイプ上で行われる。 次に、Set Named Pipe Handle Stateが、APCコマンドを受け取れるようにパイプがなった後に 送られる必要がある。最後に、SMBcloseが送られる。

解決されること:

lkcl/01nov97において、RPCパイプのためのNULL文字で終端している\PIPE\名の後に2バイトが 存在するように見える。今のところ分かっている値は以下の通り:

        initial SMBopenX request:         RPC API command 0x26 params:
        "\\PIPE\\lsarpc"                  0x65 0x63; 0x72 0x70; 0x44 0x65;
        "\\PIPE\\srvsvc"                  0x73 0x76; 0x4E 0x00; 0x5C 0x43;

ヘッダー

[Duncan Stansfieldによる作業を受け取った後、この節は書き直される予定]

興味深い注意:もしも、パックされたデータを0x0100 0000と設定した場合、 すべての4バイトと2バイトワードの順番は逆転する!

NTLSAとNETLOGON名前付きパイプのおのおのの開始は、以下で始まる:

オフセット: 00
変数タイプ: UINT8
変数のデータ: 5 - RPC major version
オフセット: 01
変数タイプ: UINT8
変数のデータ: 0 - RPC minor version
オフセット: 02
変数タイプ: UINT8
変数のデータ: 2 - RPC response packet
オフセット: 03
変数タイプ: UINT8
変数のデータ: 3 - (FirstFrag bit-wise or with LastFrag)
オフセット: 04
変数タイプ: UINT32
変数のデータ: 0x1000 0000 - packed data representation
オフセット: 08
変数タイプ: UINT16
変数のデータ: fragment length - data size (bytes) inc header and tail.
オフセット: 0A
変数タイプ: UINT16
変数のデータ: 0 - authentication length
オフセット: 0C
変数タイプ: UINT32
変数のデータ: call identifier. matches 12th UINT32 of incoming RPC data.
オフセット: 10
変数タイプ: UINT32
変数のデータ: allocation hint - data size (bytes) minus header and tail.
オフセット: 14
変数タイプ: UINT16
変数のデータ: 0 - presentation context identifier
オフセット: 16
変数タイプ: UINT8
変数のデータ: 0 - cancel count
オフセット: 17
変数タイプ: UINT8
変数のデータ: in replies: 0 - reserved; in requests: opnum - see #defines.
オフセット: 18
変数タイプ: ......
変数のデータ: start of data (goes on for allocation_hint bytes)

要求、レスポンス、バインドとバインド承認に対するRPC_Packet

UINT8 versionmaj

reply same as request (0x05)

UINT8 versionmin

reply same as request (0x00)

UINT8 type

one of the MSRPC_Type enums

UINT8 flags

reply same as request (0x00 for Bind, 0x03 for Request)

UINT32 representation

reply same as request (0x00000010)

UINT16 fraglength

the length of the data section of the SMB trans packet

UINT16 authlength

UINT32 callid

call identifier. (e.g. 0x00149594)

* stub USE TvPacket

the remainder of the packet depending on the "type"

インタフェース識別

インタフェースには番号が付けられている。同じパイプ名srvsvc上で1つより多い インタフェースを使う場面にはまだ出会ったことがない。

abstract (0x4B324FC8, 0x01D31670, 0x475A7812, 0x88E16EBF, 0x00000003)
transfer (0x8A885D04, 0x11C91CEB, 0x0008E89F, 0x6048102B, 0x00000002)

RPC_Iface RW

UINT8 byte[16]

16 bytes of number

UINT32 version

the interface number

RPC_ReqBind RW

"タイプ"がレスポンスヘッダーのBINDであった場合、ヘッダーの後のパケットの残りの "タイプ"は、BindAckであるべきである。

UINT16 maxtsize

maximum transmission fragment size (0x1630)

UINT16 maxrsize

max receive fragment size (0x1630)

UINT32 assocgid

associated group id (0x0)

UINT32 numelements

the number of elements (0x1)

UINT16 contextid

presentation context identifier (0x0)

UINT8 numsyntaxes

the number of syntaxes (has always been 1?)(0x1)

UINT8[]

4-byte alignment padding, against SMB header

* abstractint USE RPC_Iface

num and vers. of interface client is using

* transferint USE RPC_Iface

num and vers. of interface to use for replies

RPC_Address RW

UINT16 length

length of the string including null terminator

* port USE string

the string above in single byte, null terminated form

RPC_ResBind RW

リプライパケット中でヘッダーの後に配置されるレスポンス

UINT16 maxtsize

same as request

UINT16 maxrsize

same as request

UINT32 assocgid

zero

* secondaddr USE RPC_Address

the address string, as described earlier

UINT8[]

4-byte alignment padding, against SMB header

UINT8 numresults

the number of results (0x01)

UINT8[]

4-byte alignment padding, against SMB header

UINT16 result

result (0x00 = accept)

UINT16 reason

reason (0x00 = no reason specified)

* transfersyntax USE RPC_Iface

the transfer syntax from the request

RPC_ReqNorm RW

すべての他のパケットのためのヘッダーの後のパケットの残り

UINT32 allochint

the size of the stub data in bytes

UINT16 prescontext

presentation context identifier (0x0)

UINT16 opnum

operation number (0x15)

* stub USE TvPacket

a packet dependent on the pipe name (probably the interface) and the op number)

RPC_ResNorm RW

UINT32 allochint

# size of the stub data in bytes

UINT16 prescontext

# presentation context identifier (same as request)

UINT8 cancelcount

# cancel count? (0x0)

UINT8 reserved

# 0 - one byte padding

* stub USE TvPacket

# the remainder of the reply

Tail

以下で終わる、各NTLSAとNETLOGON名前つきパイプの終了部分:

......

end of data

UINT32

return code

RPC Bind / Bind Ack

RPCバインドは、あるRPCパイプ(例えば\PIPE\lsarpc)と"transfer syntax"(RPC_Iface 構造体を参照)を関連づける手続きである。これを行う目的は不明である。

Note: The RPC_ResBind SMB Transact request is sent with two uint16 setup parameters. The first is 0x0026; the second is the file handle returned by the SMBopenX Transact response.

Note: The RPC_ResBind members maxtsize, maxrsize and assocgid are the same in the response as the same members in the RPC_ReqBind. The RPC_ResBind member transfersyntax is the same in the response as the

Note: The RPC_ResBind response member secondaddr contains the name of what is presumed to be the service behind the RPC pipe. The mapping identified so far is:

initial SMBopenX request:

RPC_ResBind response:

"\\PIPE\\srvsvc"

"\\PIPE\\ntsvcs"

"\\PIPE\\samr"

"\\PIPE\\lsass"

"\\PIPE\\lsarpc"

"\\PIPE\\lsass"

"\\PIPE\\wkssvc"

"\\PIPE\\wksvcs"

"\\PIPE\\NETLOGON"

"\\PIPE\\NETLOGON"

注意: バインド要求とバインド承認の両方におけるRPC_Packet fraglength メンバーは、RPC_Packet headerを含めて、RPCデータ全体の長さを含まなければならない。

Request:

RPC_Packet
RPC_ReqBind

Response:

RPC_Packet
RPC_ResBind

NTLSA トランザクション名前付きパイプ

このパイプ上で取られる動作の順番は以下の通り:

IPC$ share (SMBtconX)への接続を確立する。暗号化パスワードを使用。
"\\PIPE\\lsarpc"という名前でRPCパイプを開く。ファイルハンドルを格納する。
ファイルハンドルを使い、Named Pipe Handle stateを0x4300に設定する。
LSA Open Policy要求を送る。ポリシーハンドルを格納する。
ポリシーハンドルを使い、LSA Query Info Policy要求などを送る。
ポリシーハンドルを使い、LSA Closeを送る。
IPC$共有をクローズする。

このパイプの定義のための、問い合わせの識別子は以下の通り:

LSA Open Policy:

0x2c

LSA Query Info Policy:

0x07

LSA Enumerate Trusted Domains:

0x0d

LSA Open Secret:

0xff

LSA Lookup SIDs:

0xfe

LSA Lookup Names:

0xfd

LSA Close:

0x00

LSAオープンポリシー

注意: ポリシーハンドルはどんな好みのものでもあり得る。

Request

VOID*

buffer pointer

UNISTR2

server name - unicode string starting with two '\'s

OBJ_ATTR

object attributes

UINT32

1 - desired access

レスポンス

POL_HND

LSA policy handle

return

0 - indicates success

LSA Query Info ポリシー

注意: レスポンス中のinfo classはリクエスト中のものと同じである必要がある。

リクエスト

POL_HND

LSA policy handle

UINT16

info class (also a policy handle?)

レスポンス

VOID*

undocumented buffer pointer

UINT16

info class (same as info class in request).

switch (info class)
case 3:
case 5:
{
DOM_INFO domain info, levels 3 and 5 (are the same).
}

return    0 - indicates success

LSA がエミュレートする信頼するドメイン

リクエスト

no extra data

レスポンス

UINT32

0 - enumeration context

UINT32

0 - entries read

UINT32

0 - trust information

return

0x8000 001a - "no trusted domains" success code

LSA Open Secret

リクエスト

no extra data

レスポンス

UINT32

0 - undocumented

UINT32

0 - undocumented

UINT32

0 - undocumented

UINT32

0 - undocumented

UINT32

0 - undocumented

return 0x0C00 0034 - "no such secret" success code

LSA Close

リクエスト

POL_HND

policy handle to be closed

レスポンス

POL_HND

0s - closed policy handle (all zeros)

return 0 - indicates success

LSA Lookup SIDS

注意: レスポンス中のnum_entriesはリクエスト中のnum_entriesと同じでなければならない。

リクエスト

POL_HND

LSA policy handle

UINT32

num_entries

VOID*

undocumented domain SID buffer pointer

VOID*

undocumented domain name buffer pointer

VOID*[num_entries] undocumented domain SID pointers to be looked up.

DOM_SID[num_entries] domain SIDs to be looked up.

char[16]

completely undocumented 16 bytes.

レスポンス

DOM_REF

domain reference response

UINT32

num_entries (listed above)

VOID*

undocumented buffer pointer

UINT32

num_entries (listed above)

DOM_SID2[num_entries]

domain SIDs (from Request, listed above).

UINT32

num_entries (listed above)

return 0 - indicates success

LSA ルックアップ名

注意: レスポンス中のnum_entriesはリクエスト中のnum_entriesと同じでなければならない。

リクエスト

POL_HND

LSA policy handle

UINT32

num_entries

UINT32

num_entries

VOID*

undocumented domain SID buffer pointer

VOID*

undocumented domain name buffer pointer

NAME[num_entries]

names to be looked up.

char[]

undocumented bytes - falsely translated SID structure?

レスポンス

DOM_REF

domain reference response

UINT32

num_entries (listed above)

VOID*

undocumented buffer pointer

UINT32

num_entries (listed above)

DOM_RID[num_entries]

domain SIDs (from Request, listed above).

UINT32

num_entries (listed above)

return 0 - indicates success

NETLOGON rpc トランザクション名前付きパイプ

このパイプ上の動作の順番は以下の通り:

IPC$ 共有 (SMBtconX)に対して接続を確立する。暗号化パスワードを使用。
"\\PIPE\\NETLOGON"という名前でRPCパイプを開く。ファイルハンドルを格納する。
ファイルハンドルを使い、Named Pipe Handle stateを0x4300に設定する。
クライアント用のチャレンジデータを作成する。LSA Request Challengeを送信する。Server Challengeを格納する。
セッションキーを計算する。LSA Auth 2 Challengeを送信する。Auth2 Challengeを格納する。
Client Credsを計算して検証する。LSA Srv PW Setを送信する。Server Credsを計算、検証する。
Client Credsを計算して検証する。LSA Srv Logonを送信する。Server Credsを計算、検証する。
Client Credsを計算して検証する。LSA Srv Logoffを送信する。Server Credsを計算、検証する。
IPC$共有をクローズする。

このパイプの定義のための、問い合わせ識別子は以下の通り

LSA Request Challenge:

0x04

LSA Server Password Set:

0x06

LSA SAM Logon:

0x02

LSA SAM Logoff:

0x03

LSA Auth 2:

0x0f

LSA Logon Control:

0x0e

LSA Request Challenge

注意: ログオンサーバー名は2つの'\'で始まり、大文字である。

注意: ログオンクライアントはマシンであり、ユーザーではない。

注意: チャレンジが発行されたものに対する最初のLanManager パスワードハッシュは、(小文字の)マシン名それ自身である。あとで、これを変更するであろう 呼び出し(LSA Server Password Set)が発行されるであろう。これらの呼び出しを抑制すると、 常時同じパスワードで扱うことが出来るようになる(すなわち、小文字でのマシン名のLM#)。

リクエスト

VOID*

undocumented buffer pointer

UNISTR2

logon server unicode string

UNISTR2

logon client unicode string

char[8]

client challenge

レスポンス

char[8]

server challenge

return 0 - indicates success

LSA Authenticate 2

注意: リクエストとレスポンスの間で、クライアントの認証情報を計算し、 クライアントが計算した認証情報と比較する(この手続きは以前に受け取ったクライアントの 認証情報を使う)。

注意: レスポンス中のneg_flagsはリクエスト中のものと同じである。

注意: そのあとの認証パケット中で使われるという理由で、ここで受け取った クライアントが計算した認証情報のコピーを取る必要がある。

リクエスト

LOG_INFO

client identification info

char[8]

client-calculated credentials

UINT8[]

padding to 4-byte align with start of SMB header.

UINT32

neg_flags - negotiated flags (usual value is 0x0000 01ff)

レスポンス

char[8]

server credentials.

UINT32

neg_flags - same as neg_flags in request.

return 0 - indicates success. failure value unknown.

LSA Server Password Set

注意: 新しいパスワードはキーを生成するために古いパスワードを使って DES暗号化を使うことが推測される。

注意: リクエストとレスポンスの間で、クライアント認証情報を計算し、 クライアントが計算した認証情報と比較する(この手続きは以前に受け取ったクライアントの 認証情報を使う)。

注意: サーバーの認証情報はクライアントが計算した認証情報と、クライアント時間+1秒から構築される。

注意: そのあとの認証パケット中で使われるという理由で、ここで受け取った クライアントが計算した認証情報のコピーを取る必要がある。

リクエスト

CLNT_INFO

client identification/authentication info

char[]

new password - undocumented.

レスポンス

CREDS

server credentials. server time stamp appears to be ignored.

return 0 - indicates success; 0xC000 006a indicates failure

LSA SAM Logon

注意: valid_user は、もしもユーザー名とパスワードハッシュが、要求されたドメインに対して 有効ならば、Trueである。

リクエスト

SAM_INFO

sam_id structure

レスポンス

VOID*

undocumented buffer pointer

CREDS

server credentials. server time stamp appears to be ignored.

if (valid_user)
{
	UINT16      3 - switch value indicating USER_INFO structure.
    VOID*     non-zero - pointer to USER_INFO structure
    USER_INFO user logon information

    UINT32    1 - Authoritative response; 0 - Non-Auth?

    return    0 - indicates success
}
else
{
	UINT16    0 - switch value.  value to indicate no user presumed.
    VOID*     0x0000 0000 - indicates no USER_INFO structure.

    UINT32    1 - Authoritative response; 0 - Non-Auth?

    return    0xC000 0064 - NT_STATUS_NO_SUCH_USER.
}

LSA SAM Logoff

注意: おそらく、SAM_INFO構造体は検証され、Logoffが不正な場合、 (現在文書化されていない)エラーコードが返される。

リクエスト

SAM_INFO

sam_id structure

レスポンス

VOID*

undocumented buffer pointer

CREDS

server credentials. server time stamp appears to be ignored.

return 0 - indicates success. undocumented failure indication.

\\MAILSLOT\NET\NTLOGON

注意: mailslotsはレスポンスmailslotを含み、それは送信されるべきレスポンスである。 ターゲットのNetBIOS名はREQUEST_NAME<20>であり、ここで、REQUEST_NAME はリクエストを送信したマシンの名前である。

PDCのためのクエリ

注意: レスポンス中のNTversion, LMNTtoken, LM20tokenはリクエスト中で与えられたものと同じである。

リクエスト

UINT16

0x0007 - Query for PDC

STR

machine name

STR

response mailslot

UINT8[]

padding to 2-byte align with start of mailslot.

UNISTR

machine name

UINT32

NTversion

UINT16

LMNTtoken

UINT16

LM20token

レスポンス

UINT16

0x000A - Respose to Query for PDC

STR

machine name (in uppercase)

UINT8[]

padding to 2-byte align with start of mailslot.

UNISTR

machine name

UNISTR

domain name

UINT32

NTversion (same as received in request)

UINT16

LMNTtoken (same as received in request)

UINT16

LM20token (same as received in request)

SAM Logon

注意: レスポンス中のマシン名は先頭に2つの'\'が付く。

注意: レスポンス中のNTversion, LMNTtoken, LM20tokenはリクエスト中のものと同じである。

注意: レスポンス中のユーザー名はおそらくリクエスト中のものと同じである。

リクエスト

UINT16

0x0012 - SAM Logon

UINT16

request count

UNISTR

machine name

UNISTR

user name

STR

response mailslot

UINT32

alloweable account

UINT32

domain SID size

char[sid_size]

domain SID, of sid_size bytes.

UINT8[]

???? padding to 4? 2? -byte align with start of mailslot.

UINT32

NTversion

UINT16

LMNTtoken

UINT16

LM20token

レスポンス

UINT16

0x0013 - Response to SAM Logon

UNISTR

machine name

UNISTR

user name - workstation trust account

UNISTR

domain name

UINT32

NTversion

UINT16

LMNTtoken

UINT16

LM20token

SRVSVC トランザクション名前付きパイプ

このパイプのための定義で、クエリの識別は以下の通り:

Net Share Enum

0x0f

Net Server Get Info

0x15

Net Share Enum

注意: レスポンス中のスイッチの値と共有レベルはリクエスト中のものとおそらく同じである。

注意: cifsrap2.txt (section 5)はここで、限定的に手助けとなるかもしれない。

リクエスト

VOID*

pointer (to server name?)

UNISTR2

server name

UINT8[]

padding to get unicode string 4-byte aligned with the start of the SMB header.

UINT32

share level

UINT32

switch value

VOID*

pointer to SHARE_INFO_1_CTR

SHARE_INFO_1_CTR

share info with 0 entries

UINT32

preferred maximum length (0xffff ffff)

レスポンス

UINT32

share level

UINT32

switch value

VOID*

pointer to SHARE_INFO_1_CTR

SHARE_INFO_1_CTR

share info (only added if share info ptr is non-zero)

return 0 - indicates success

Net Server Get Info

注意: levelはリクエスト中のものと同じである。

リクエスト

UNISTR2

server name

UINT32

switch level

レスポンス

UINT32

switch level

VOID*

pointer to SERVER_INFO_101

SERVER_INFO_101

server info (only added if server info ptr is non-zero)

return 0 - indicates success

NTドメイン認証における暗号化の側面

定義

Add(A1,A2)

Intel byte ordered addition of corresponding 4 byte words in arrays A1 and A2

E(K,D)

DES ECB encryption of 8 byte data D using 7 byte key K

lmowf()

Lan man hash

ntowf()

NT hash

PW

md4(machine_password) == md4(lsadump $machine.acc) == pwdump(machine$) (initially) == md4(lmowf(unicode(machine)))

ARC4(K,Lk,D,Ld)

ARC4 encryption of data D of length Ld with key K of length Lk

v[m..n(,l)]

subset of v from bytes m to n, optionally padded with zeroes to length l

Cred(K,D)

E(K[7..7,7],E(K[0..6],D)) computes a credential

Time()

4 byte current time

Cc,Cs

8 byte client and server challenges Rc,Rs: 8 byte client and server credentials

プロトコル

C->S ReqChal,Cc
S->C Cs
C & S compute session key Ks = E(PW[9..15],E(PW[0..6],Add(Cc,Cs)))
C: Rc = Cred(Ks,Cc)
C->S Authenticate,Rc
S: Rs = Cred(Ks,Cs), assert(Rc == Cred(Ks,Cc))
S->C Rs
C: assert(Rs == Cred(Ks,Cs))

ドメインへの参加において、クライアントはオプションとしてそのパスワードを変更しようと し、ドメインコントローラーはレジストリの設定に依存して、その更新を抑制するかもしれない。 これは以降毎週毎に起きるであろう。

C: Tc = Time(), Rc' = Cred(Ks,Rc+Tc)
C->S ServerPasswordSet,Rc',Tc,arc4(Ks[0..7,16],lmowf(randompassword())
C: Rc = Cred(Ks,Rc+Tc+1)
S: assert(Rc' == Cred(Ks,Rc+Tc)), Ts = Time()
S: Rs' = Cred(Ks,Rs+Tc+1)
S->C Rs',Ts
C: assert(Rs' == Cred(Ks,Rs+Tc+1))
S: Rs = Rs'

ユーザー: パスワードがPのユーザーUはドメインにログオンしようとする(ワークステーションと ドメインのような付随的なデータは省略される)

C: Tc = Time(), Rc' = Cred(Ks,Rc+Tc)
C->S NetLogonSamLogon,Rc',Tc,U,arc4(Ks[0..7,16],16,ntowf(P),16), arc4(Ks[0..7,16],16,lmowf(P),16)
S: assert(Rc' == Cred(Ks,Rc+Tc)) assert(passwords match those in SAM)
S: Ts = Time()
S->C Cred(Ks,Cred(Ks,Rc+Tc+1)),userinfo(logon script,UID,SIDs,etc)
C: assert(Rs == Cred(Ks,Cred(Rc+Tc+1))
C: Rc = Cred(Ks,Rc+Tc+1)

コメント

最初のドメインへの参加において、マシンパスワードがよく知られた値であるように、 セッションキーは、ネットワーク上で盗聴している誰にでも、計算することが出来た。 マシンがリブートするまで、パスワードと同等の、NTとLMの一方向関数による暗号化 パスワードを、このセッションキーは使うであろう。このマシンが2回目にリブートする 前にログインする任意のユーザーは、パスワードと同等のものがばれてしまうであろう。 もちろん、新しいマシンのパスワードはとにかくこの時点でばれてしまう。

ログオンスクリプト、プロファイルパスと、SIDのような戻り情報は、TCPチェックサム以外の 何かによって保護されるように見えない。

サーバーのタイムスタンプは無視されるように見える。

クライアントは、それに対する使用法が分からない、SamLogonリクエスト中で ReturnAuthenticatorを送る。しかし、その時間はサーバーによって戻されるタイムスタンプ として使われる。

パスワードのOMFは解読できる暗号でネットワーク上に送信すべきでない。SAM中のowf値を 使う同じ機能でサーバーが計算するARC4(Ks,md4(owf))を使って送るべきである。

SIDとRID

SIDとRIDはどこかで詳細に説明がある。

SIDはNTセキュリティID(DOM_SID構造参照)である。これらは以下の形式を取る:

revision-NN-SubAuth1-SubAuth2-SubAuth3...
revision-0xNNNNNNNNNNNN-SubAuth1-SubAuth2-SubAuth3...

現在、SIDのリビジョンは1である。 Sub-Authoritiesは相対ID(RID)として知られている。

よく知られているSID

ユニバーサルによる知られているSID

Null SID

S-1-0-0

World

S-1-1-0

Local

S-1-2-0

Creator Owner ID

S-1-3-0

Creator Group ID

S-1-3-1

Creator Owner Server ID

S-1-3-2

Creator Group Server ID

S-1-3-3

(Non-unique IDs)

S-1-4

NTにおけるよく知られているSID

NT Authority

S-1-5

Dialup

S-1-5-1

Network

S-1-5-2

Batch

S-1-5-3

Interactive

S-1-5-4

Service

S-1-5-6

AnonymousLogon(aka null logon session)

S-1-5-7

Proxy

S-1-5-8

ServerLogon(aka domain controller account)

S-1-5-8

(Logon IDs)

S-1-5-5-X-Y

(NT non-unique IDs)

S-1-5-0x15-...

(Built-in domain)

s-1-5-0x20

よく知られているRID

RIDはsub-authorityであり、SIDの一部か、グループRIDの場合は、DOM_GID構造の一部であり、 USER_INFO_1構造ではLSA SAMログオンレスポンスの中である。 A RID is a sub-authority value, as part of either a SID, or in the case of Group RIDs, part of the DOM_GID structure, in the USER_INFO_1 structure, in the LSA SAM Logon response.

よく知られたRIDユーザー

Groupname: DOMAIN_USER_RID_ADMIN
????: 0x0000
RID: 01F4
Groupname: DOMAIN_USER_RID_GUEST
????: 0x0000
RID: 01F5

よく知られたRIDグループ

Groupname: DOMAIN_GROUP_RID_ADMINS
????: 0x0000
RID: 0200
Groupname: DOMAIN_GROUP_RID_USERS
????: 0x0000
RID: 0201
Groupname: DOMAIN_GROUP_RID_GUESTS
????: 0x0000
RID: 0202

よく知られたRID別名

Groupname: DOMAIN_ALIAS_RID_ADMINS
????: 0x0000
RID: 0220
Groupname: DOMAIN_ALIAS_RID_USERS
????: 0x0000
RID: 0221
Groupname: DOMAIN_ALIAS_RID_GUESTS
????: 0x0000
RID: 0222
Groupname: DOMAIN_ALIAS_RID_POWER_USERS
????: 0x0000
RID: 0223
Groupname: DOMAIN_ALIAS_RID_ACCOUNT_OPS
????: 0x0000
RID: 0224
Groupname: DOMAIN_ALIAS_RID_SYSTEM_OPS
????: 0x0000
RID: 0225
Groupname: DOMAIN_ALIAS_RID_PRINT_OPS
????: 0x0000
RID: 0226
Groupname: DOMAIN_ALIAS_RID_BACKUP_OPS
????: 0x0000
RID: 0227
Groupname: DOMAIN_ALIAS_RID_REPLICATOR
????: 0x0000
RID: 0228