SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

DeveloperZine(デベロッパージン)- エンジニアの意思決定を支える技術情報メディア ProductZine

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

特集記事

SIDによるアカウントの列挙

SIDの構造とSID関数の使い方

IPアドレスの指定に対応する

 前ページで示したConvertNameToSidでリモートコンピュータのSIDを取得したいと考えた場合、その呼び出し方は次のようになるでしょう。

リモートコンピュータのSIDを取得する
// szComputerは、リモートコンピュータの名前が格納されているものとする。
ConvertNameToSid(szComputer, szComputer, pSidComputer);

 リモートコンピュータの名前が不正でなければ、恐らく関数は成功し、そのコンピュータのSIDを取得できます。しかし、ここで少し問題なのは、あらかじめリモートコンピュータの名前を知っておかなければならないという点です。これは当たり前のように思えるかもしれませんがそうとも限りません。例えば、コンピュータはIPアドレスでも表現できますし、現にLookupAccountNameLookupAccountSidの第1引数はIPアドレスの指定に対応しています。しかし、第1引数にIPアドレスを指定したとしても、第2引数のアカウント名はどうするのかという問題が浮上します。ここには、リモートコンピュータ上のアカウントを指定するわけですから、結局、リモートコンピュータ上のアカウントを把握していなければならないように思えます。

ビルトインアカウント

 「ビルトインアカウント」とはどのシステムにも存在するアカウントのことで、AdministratorやGuestアカウントなどが代表的です。これらのアカウントのSIDも一般のアカウントのようにコンピュータのSIDをベースにしており、RIDはそれぞれ、500、501と固定です。従って、ConvertNameToSidの第2引数にAdministratorを指定すれば、AdministratorのSIDを取得することができます。このSIDはコンピュータのSIDをベースにしているため、コンピュータのSIDを間接的に取得できたのと同じ意味を持つのです。

AdministratorのSIDを取得する
// szComputerは、IPアドレスで初期化されていても問題ない。
ConvertNameToSid(szComputer, TEXT("Administrator"), &pSid);

 関数が成功すると、pSidはコンピュータのSIDと500のRIDで構成されます。この500を他の値に置き換えてLookupAccountSidを呼び出していけば、コンピュータ上のアカウントを列挙することができます。

ビルトイングループ
 ビルトイングループとは、どのようなシステムにでも存在するグループのことで、AdministratorsやUsers、Guestsなどがあります。これらのグループのSIDは完全に固定であり、どのシステムでも同じ値となるため、既知のSIDと呼ばれることもあります。ビルトインアカウントのAdministratorなどはコンピュータのSIDをベースにしていますが、RIDが固定であるため、これも既知のSIDの一つです。既知のSIDを取得したいときは、CreateWellKnownSidを呼び出します。
 

RIDを置き換える

 次のコードは、サンプルプログラムのEnumAccountの内容と酷似しています。pSidのRIDを置き換えることにより、別のアカウントのSIDを完成させています。ConvertSidToNameという自作関数は、内部でLookupAccountSidを呼び出しています。

アカウントのSIDを完成させ、アカウント名を取得する
dwSubAuthorityCount = *GetSidSubAuthorityCount(pSid);

for (i = 500, j = 0; i < 1050; i++) {
    *GetSidSubAuthority(pSid, dwSubAuthorityCount - 1) = i;
    if (ConvertSidToName(szComputer, pSid, szAccount,
                         sizeof(szAccount), NULL))
        MessageBox(NULL, szAccount, TEXT("アカウント"), MB_OK);
}

 GetSidSubAuthorityCount関数は、SIDのサブ機関値の数を格納するメモリのアドレスを返します。GetSidSubAuthorityは、サブ機関値のアドレスを返します。サブ機関値は配列のように考えることができ、例えばdwSubAuthorityCountが3であれば、GetSidSubAuthorityの第2引数は0から2までの数字を指定できます。RIDは最後のサブ機関値なので、インデックスはdwSubAuthorityCount - 1となります。for文の開始が1000ではなく500となっているのは、ビルトインアカウントのAdministratorやGuestも列挙するためです。アカウントの数は予測できないため、とりあえず1050としています。これにより、51番目に作成されたアカウントまでは列挙できることになります。

サンプルプログラムについて
 サンプルの要となるのは、先に示したEnumAccountですが、その他の関数についても簡単に説明しておきます。DrawSidsという関数は、取得したSIDをテキスト形式で表示します。この関数が呼び出すConvertSidToStringSidは第1引数のSIDを基に、Sで始まるテキスト形式のSIDを第2引数に返します。ConvertSidToStringSidを使うには、_WIN32_WINNT 0x0500という定義と「sddl.h」のインクルードが必要になることに注意してください。また、GetComputerSidはアカウントのSIDからRIDを省いてコンピュータのSIDを完成させています。このSIDが最終的にLookupAccountSidに指定されることにより、コンピュータ名が取得されます。コンピュータをIPアドレスで識別しているのにも関わらず、コンピュータ名が表示されるのは、この関数の働きによるものです。なお、リモートコンピュータのアカウントを列挙する場合は、ネットワークの接続が必要となります。このとき、ファイアウォール系の機能が有効であると、アカウントの列挙に失敗することがあるので注意してください。
 

最後に

 最後に、システムがアカウントをアカウント名ではなくSIDで表す理由について考えてみます。これは、アカウントの実体がSIDで表されているからではないかと思われます。アカウントを作成するとき、そのアカウントのためにSIDが割り当てられますが、作成後にアカウント名を変更してもSIDは変化することはありません。例えば、Administratorという名前を変更したとしても、システムからはコンピュータの管理者を容易に特定できます。それは、システムが管理者をAdministratorという名前ではなく、RIDが500であるSIDとして解釈しているからです。アカウント名というのは、私達がSIDを識別しやすくするために付けたもので、システムから見ればどのような名前であるかは重要ではありません。

参考資料

  1. インサイドMicrosoft Windows 第4版(下)』 David A. Solomon・Mark E. Russinovich 原著、豊田孝 翻訳、日経BPソフトプレス、2005年10月
  2. EternalWindows 『セキュリティ / アクセスコントロール

この記事は参考になりましたか?

連載通知を行うには会員登録(無料)が必要です。
既に会員の方はを行ってください。
特集記事連載記事一覧

もっと読む

この記事の著者

NAO(ナオ)

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

CodeZine(コードジン)
https://codezine.jp/article/detail/434 2008/08/19 20:31

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー