スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

--.--.-- | スポンサー広告

Windowsのセキュリティ周りの勉強中……

某スレッドで Windows2000 と Windows XP 違いってなに? という質問があった。

ん~一般の人が関係ありそうで意外に知られていないこととなると

・Windows XP はブロードバンドに最適化されている
 →Windows 2000 は最適化されていないため光回線になっても
  性能を 100% 発揮することはできない

・Windows XP は DirectX にも最適化されている
 →Windows 2000 と比べて約 30% ほど実は速くなる

くらいかな~

これだけ見てもそれなりにメリットはありそうです^^;




現在セキュリティの勉強中(;´-`)y-~~

こんな図を書いてたりしてます。
※間違ってたらスマソ(笑)
Kerberos


で、いろいろ分かったのですが
アプリケーションサーバーとして登録すれば
特にドメインアドミニストレータとして起動しなくても
WMI for C++ にてリモートの情報を取得できるっぽいです。

VB などで特に設定しなくてもリモートの情報を取得できるのは
おそらく何かしらのアプリケーションサーバが仲介しているんじゃないかと考えています。

# ……ってよくみると"WSHRemote"(wscript.exe)というのが
 登録されてますね……

いずれにせよまだまだ勉強が必要そうです(;´-`)y-~~



テーマ:プログラミング - ジャンル:コンピュータ

2005.12.29 | Comments(0) | Trackback(0) | プログラム

WMIプログラムC++編-4

ん~ CSS の white-space で pre を指定しても
IE だとうまく表示されない(スペースが無視される)ことがありますね……

日別で表示させて更新させればうまく表示されることがあるので
それでかんべんしてorz

あと前回のサンプルプログラムですがフォトショップ形式(PSD)
存在するフォルダを指定すると落ちます(ノ∀`*)

原因はそのうち調査するかもしれません……




WMIプログラムC++編-4

VB で EXE を作成するとドメインアドミニストレータ権限で実行しなくても
リモート上の PC の情報を見ることができるので C++ でもできそうだけどなあ~……

とぼやきつつ、今回はレジストリの操作をやってみたいと思います。
やっぱり WMI を使うからにはレジストリの情報を見れなければ
魅力が半減すると思います(ぇ

プログラム自体はWMIプログラムC++編-3とたいして変わりません。

違うところといえばメソッド実行後に値の取得を行うところでしょうか。

ただ注意点が一つだけあります。
今まで扱ってきたクラスは //root/cimv2 というネームスペースに属していましたが
レジストリは //root/default ネームスペースに属しています。
ConnectServer 時のパラメータに気をつけましょう(´・ω・`)b

以下はソースとなります。

enum ENUM_REGISTRY_PARAMETER{
REG_BINARY_VALUE = 0x00,
REG_DWORD_VALUE = 0x01,
REG_EXPANDED_STRING_VALUE = 0x02,
REG_MULTI_STRING_VALUE = 0x03,
REG_STRING_VALUE = 0x04,
};

_variant_t
CWMI::GetRegistry(HKEY Root, BSTR SubKey, BSTR Value,
ENUM_REGISTRY_PARAMETER Type)
{
VARIANT property;
::VariantInit(&property);

// レジストリクラスオブジェクトを取得
IWbemClassObject* registry = NULL;
if(m_WbemServices->GetObject(_bstr_t(L"StdRegProv"),
0,
NULL,
&registry,
NULL) != WBEM_S_NO_ERROR)
{
return property;
}

// メソッドの取得
// 何故か海外のサンプルは OUT メソッドでインスタンスを作成してた……
IWbemClassObject* in_method = NULL;
IWbemClassObject* out_method = NULL;
BSTR parameter[] = {L"GetBinaryValue",
L"GetDWORDValue",
L"GetExpandedStringValue",
L"GetMultiStringValue",
L"GetStringValue"};

if(registry->GetMethod(_bstr_t(parameter[Type]),
0,
&in_method,
&out_method) != WBEM_S_NO_ERROR)
{
registry->Release();
return property;
}

// インスタンスの作成
IWbemClassObject* instance = NULL;
if(in_method->SpawnInstance(0, &instance) != WBEM_S_NO_ERROR)
{
in_method->Release();
out_method->Release();
registry->Release();
return property;
}

// 取得するレジストリ項目のセット
// ルート、サブキーネーム、バリューネーム
VARIANT root;
::VariantInit(&root);
root.vt = VT_I4;
root.lVal = reinterpret_cast<unsigned long>(Root);
instance->Put(_bstr_t(L"hDefKey"), 0, &root, 0);
::VariantClear(&root);

VARIANT sub_key;
::VariantInit(&sub_key);
sub_key.vt = VT_BSTR;
sub_key.bstrVal = _bstr_t(SubKey);
instance->Put(_bstr_t(L"sSubKeyName"), 0, &sub_key, 0);
::VariantClear(&sub_key);

VARIANT value_name;
::VariantInit(&value_name);
value_name.vt = VT_BSTR;
value_name.bstrVal = _bstr_t(Value);
instance->Put(_bstr_t(L"sValueName"), 0, &value_name, 0);
::VariantClear(&value_name);

// メソッドの実行
IWbemClassObject* param = NULL;
if(m_WbemServices->ExecMethod(_bstr_t(L"StdRegProv"),
_bstr_t(parameter[Type]),
0,
NULL,
instance,
&param,
NULL) != WBEM_S_NO_ERROR)
{
instance->Release();
out_method->Release();
in_method->Release();
registry->Release();
return property;
}

// 値の取得
_bstr_t value;
switch(Type)
{
case REG_BINARY_VALUE:
case REG_DWORD_VALUE:
value = L"uValue";
break;

case REG_EXPANDED_STRING_VALUE:
case REG_MULTI_STRING_VALUE:
case REG_STRING_VALUE:
value = L"sValue";
break;

default:
return property;
}
param->Get(value, 0, &property, 0, 0);

param->Release();
instance->Release();
out_method->Release();
in_method->Release();
registry->Release();

return property;
}


いやはや Release が鬱陶しいですね(笑)
例外処理で throw してしまえば綺麗になるんですが
分かりやすくするためこんな感じにしてます。
(過去ログ見てると Release してないところが結構ある(汗))

セキュリティの設定やら WMI の初期化やらは省略しました。
このサンプルを改良すればレジストリへの書き込みもできますが
私は WMI はクライアント情報の管理機構だとおもってるのでお奨めはしません。

社内クライアント全体のレジストリの変更などは
グループポリシーテンプレートなどにお任せしたほうがいいでしょう。

テーマ:プログラミング - ジャンル:コンピュータ

2005.12.19 | Comments(0) | Trackback(0) | プログラム

IShellFolder

随分長いこと更新を忘れていましたorz

プログラムのソースコードを載せようとすると
どうしても検証が必要で、それが億劫で更新を忘れてしまう……

なんか別のネタを考えなくては(;´-`)y-~~
(かといってセキュリティ関係とかはやっている方が多いからなあ~)



IShellFolderを使ったイメージの表示

XML をやる予定だったんですが
やる気がまったく起きなかっ(ry ので
ここからしばらく Shell Extension を扱っていこうと思います。

今回は「IShellFolder」が題材です。

こいつはファイルやフォルダを操作するインターフェイスで
比較的よく使われていると思います。
(……本当か?)

エクスプローラ周りのインターフェイスは込み入っていて
"ファイル名"ではなく"一意のID"(item identifier)よって管理されているため
ややこしく感じる人も多いとは思いますが
現在の Windows OS がほぼ COM で作られていることを考えると
慣れておいたほうが良いでしょう。

// エクスプローラ風のウインドウの作成。
// チョット改良して Shell Extension に関連付けられている
// イメージファイルをアイコンとして表示しています。
bool MainDialog::CreateThumbnailFolder(TCHAR* Path)
{
IMalloc* malloc;
IShellFolder* folder;
IShellFolder* item;
IEnumIDList* enumID;
ITEMIDLIST* object = NULL;
ITEMIDLIST* item_list = NULL;
DWORD fetch = 0;
DWORD eaten = 0;

// リストビュー内のアイテムの消去
...

// シェル用メモリ割り当て&開放
::SHGetMalloc(&malloc);
// デフォルトフォルダの取得
::SHGetDesktopFolder(&folder);
// 表示するフォルダのアイテム(item identifier)の取得
folder->ParseDisplayName(NULL, 0, Path, &eaten, &object, 0);
// IShellFolder にバインド
folder->BindToObject(object, 0, IID_IShellFolder,
reinterpret_cast<void**>(&item));
// IEnumIDList の取得
item->EnumObjects(NULL,
SHCONTF_FOLDERS | SHCONTF_NONFOLDERS,
&enumID);

SIZE size = {32, 32};
// フォルダ内のアイテム(item identifier)の列挙
while(enumID->Next(1, &item_list, &fetch) == NOERROR)
{
/* Shell Extension に関連付けられたファイルのイメージを取得 */

// フルパス名の取得
TCHAR full_path[MAX_PATH + 1] = L"";
::SHGetPathFromIDList(item_list, full_path);

// IExtractImage の取得
IExtractImage* image;
HRESULT hr = item->GetUIObjectOf(NULL, 1,
const_cast<const ITEMIDLIST**>(&item_list),
IID_IExtractImage, 0,
reinterpret_cast<void**>(&image));

TCHAR path[MAX_PATH + 1] = L"";
DWORD flag = IEIFLAG_ASPECT | IEIFLAG_SCREEN;
HBITMAP hBmp = NULL;

if(hr == S_OK)
{
// ロケーションの設定
image->GetLocation(path, MAX_PATH, 0, &size, 32, &flag);

// イメージの取得
image->Extract(&hBmp);
}

if(hBmp != NULL)
{
// イメージリスト&リストビューにファイル名を追加~
...
}
else
{
/* イメージの取得が出来なかった場合、アイコンを表示 */

// IExtractIcon の取得
IExtractIcon* icon;
item->GetUIObjectOf(NULL, 1,
const_cast<const ITEMIDLIST**>(&item_list),
IID_IExtractIcon, 0,
reinterpret_cast<void**>(&icon));

// ロケーションの設定&インディックスの取得
UINT flag = 0;
int index = 0;
hr = icon->GetIconLocation(GIL_FORSHELL, path,
MAX_PATH, &index, &flag);

if(hr != S_OK) continue;

// アイコンイメージの取得(スモールアイコン使ってないけど……)
HICON icon_small = NULL, icon_large = NULL;
icon->Extract(path, index, &icon_large,
&icon_small, MAKELONG(32, 16));

if(icon_large != NULL)
{
// イメージリスト&リストビューにファイル名を追加~
...
}
// アイコンイメージの削除
::DestroyIcon(icon_small);
::DestroyIcon(icon_large);
}
// アイテム(item identifier)の開放
malloc->Free(item_list);
item_list = NULL;
}

// 後始末
malloc->Free(object);
malloc->Release();

return true;
}

さあ、例によってソースコードが長くなりました(笑)

今回はコメントを多めにしたので特に説明することもないでしょう。

せっかくなので実行可能なファイルを置きました。
http://www6.plala.or.jp/metatoron/files/ThumbnailFolder.zip
……ちなみにイメージリストの上限を255に設定しているので
それ以上のファイルが存在するフォルダを指定すると落ちます(爆)

次回は再び WMI In レジストリ編をお送りします(ぁ

テーマ:プログラミング - ジャンル:コンピュータ

2005.12.17 | Comments(0) | Trackback(0) | プログラム

WMIの補足……

SONY BMG の rootkit 騒ぎは加熱する一方ですね(;´Д`)

XCP「rootkit」組み込みマシン、日本は最多の21万台?――専門家が指摘
http://www.itmedia.co.jp/news/articles/0511/16/news026.html




WMIの補足(というか修正……)
「WMIプログラムC++編-2」のソースコードにて

if(NULL != property_array)
SafeArrayDestroy(property_array);

という個所がありますが、これはまずかったようです(;´Д`)
特にMSDNに記載があるわけではないですが
IWbemClassObject インターフェイスの Get メソッドにて獲得した値を
勝手に開放すると内部でも開放が行われているらしく
2重開放によってメモリーリークが発生します。
(会社で物の見事なくらい、はまりましたorz)

というわけで上の2行は削除してください。


もうひとつ。
これは補足になりますが
同じく「WMIプログラムC++編-2」のソースコードにて

wbem_enumerator->Next(WBEM_INFINITE, 1, &wbem_object, &returned);

という個所がありますが、
この個所のエラー処理をする際、

if(FAILED(wbem_enumerator->Next(WBEM_INFINITE, 1,
&wbem_object, &returned)))
return FALSE;
else
return TRUE;

これは特に問題ありません……が

if(FAILED(wbem_enumerator->Next(WBEM_INFINITE, 10,
&wbem_object, &returned)))
return FALSE;
else
return TRUE;

これはダメです。

Next メソッドが戻してくる辺値に"WBEM_S_FALSE"というものがあります。
残念ながらこいつはFAILEDマクロやSECESSEDマクロでは正確に補足できません。
では何故上のものが大丈夫なのかというと、
MSDN の解説にこう明記されています。

The number of objects returned was less than the number requested.
WBEM_S_FALSE is also returned when this method is
called with a value of 0 for the uCount parameter.

ようするに値の取得には成功したが
指定(第2パラメータ)された数のオブジェクトの取得に失敗した時に
"WBEM_S_FALSE"が返されます……というわけです。
(第2パラメータに"0"を指定した場合にも同様に"WBEM_S_FALSE"が返されます。
 "0"を指定すると存在するObjectの数を第4パラメータに出力します)

上の例では1つだけ取得するように指定しているため
"WBEM_S_FALSE"が発生する条件を絶対に満たすことがないわけです(´・ω・`)b

とはいえ"WBEM_S_FALSE"をうまくはじく処理を
どちらにも入れたほうがいいとはおもいますけどね……


テーマ:プログラミング - ジャンル:コンピュータ

2005.11.17 | Comments(0) | Trackback(0) | プログラム

WMIプログラムC++編-3

英語の MSDN を色々斜め読みしたが
Windows2000 のアプリケーションの実行権限を変更する方法が見つからなかった_| ̄|○

う~ん、「別のユーザーとして実行」ダイアログを表示する方法はないのだろうか?




WMIプログラムC++編-3
斜め読みしていて分かったのだが
Windows2000 のみ CoInitializeSecurity の設定が違うのは
サーバーによって NTLMDomain 認証と Kerberos 認証を使うからのようだ。

う~ん、もう少しセキュリティの勉強しないとダメだなあ~と思った(;´-`)y-~~

とりあえず前回の予告どおり、WMIにてアプリケーションを実行する方法を紹介。
しかしただ実行するだけではつまらない!
……ということでチョット改良してみました。

<Win32_Process 周りの説明>
IWbemServices の GetObject を使用してクラスオブジェクトを取得。
取得したオブジェクト の GetMethod を使用して "Create"メソッドを取得。
その後 SpawnInstance を使用してインスタンスを取得し Put で
値を設定します。
Win32_ProcessStartup も同じような感じです。
最後に ExecMethod で実行です。
VB などと比べると面倒ですね^^;

#define _WIN32_DCOM
#include <iostream>
#include <comdef.h>
#include <Wbemidl.h>
using namespace std;

#pragma comment(lib, "wbemuuid.lib")

int main(int argc, char **argv)
{
IWbemLocator *wbem_locator = NULL;
IWbemServices *wbem_services = NULL;
IEnumWbemClassObject *wbem_enumerator = NULL;

// 各種初期化
::CoInitializeEx(0, COINIT_MULTITHREADED);

::CoInitializeSecurity(NULL, -1, NULL, NULL,
RPC_C_AUTHN_LEVEL_DEFAULT,
RPC_C_IMP_LEVEL_IMPERSONATE,
NULL, EOAC_NONE, NULL);

::CoCreateInstance(CLSID_WbemLocator, 0,
CLSCTX_INPROC_SERVER,
IID_IWbemLocator,
reinterpret_cast(&wbem_locator));

// 接続開始
wbem_locator->ConnectServer(_bstr_t(L"\\\\.\\ROOT\\CIMV2"),
NULL, NULL, 0, NULL,
0, 0, &wbem_services);

::CoSetProxyBlanket(wbem_services,
RPC_C_AUTHN_WINNT,
RPC_C_AUTHZ_NONE, NULL,
RPC_C_AUTHN_LEVEL_CALL,
RPC_C_IMP_LEVEL_IMPERSONATE,
NULL, EOAC_NONE);

// Win32_ProcessStartup の設定
IWbemClassObject* wmi_startup = NULL;
wbem_services->GetObject(_bstr_t(L"Win32_ProcessStartup"),
0, NULL, &wmi_startup, NULL);

IWbemClassObject* startup_instance = NULL;
wmi_startup->SpawnInstance(0, &startup_instance);

// ウインドウ最大化
VARIANT show;
VariantInit(&show);
show.vt = VT_I2;
show.intVal = SW_SHOWMAXIMIZED;
startup_instance->Put(_bstr_t(L"ShowWindow"), 0, &show, 0);
VariantClear(&show);

// Win32_Process の設定
IWbemClassObject* wmi_process = NULL;
wbem_services->GetObject(_bstr_t(L"Win32_Process"), 0,
NULL, &wmi_process, NULL);

IWbemClassObject* params_definition = NULL;
IWbemClassObject* out_method = NULL;
wmi_process->GetMethod(_bstr_t(L"Create"), 0,
¶ms_definition, &out_method);

IWbemClassObject* process_instance = NULL;
params_definition->SpawnInstance(0, &process_instance);

// EXE ファイルの指定
VARIANT file_name;
VariantInit(&file_name);
file_name.vt = VT_BSTR;
// OS によって適宜ファイルパスを替えてください^^;
file_name.bstrVal = _bstr_t("C:\\WINNT\\system32\\notepad.exe");
process_instance->Put(_bstr_t(L"CommandLine"), 0, &file_name, 0);
VariantClear(&file_name);

// Win32_ProcessStartup の指定
VARIANT startup;
VariantInit(&startup);
startup.vt = VT_DISPATCH;
startup.byref = startup_instance;
process_instance->Put(_bstr_t(L"ProcessStartupInformation"),
0, &startup, 0);
VariantClear(&startup);

wbem_services->ExecMethod(_bstr_t(L"Win32_Process"),
_bstr_t(L"Create"), 0, NULL,
process_instance, NULL, NULL);

// 後始末
startup_instance->Release();
wmi_startup->Release();
process_instance->Release();
out_method->Release();
params_definition->Release();
wmi_process->Release();
wbem_services->Release();
wbem_locator->Release();

::CoUninitialize();
return 0;
}

Win32_ProcessStartup の ShowWindow に SW_SHOWMAXIMIZED を
指定することによってノートパッドが最大化の状態で起動します。

最初 ProcessStartupInformation に指定する Variant Type は
なにかな? と思い、とりあえず VT_BYREF を指定したらものの見事に
はずれorz
一番怪しそうな VT_DISPATCH を指定したらとりあえず起動^^;
とはいえこの辺かなりプログラムが怪しいです……
といっても資料がないしなあ~

本当はWMIを使用したイベントシンクやサービスなんかもしたかったのですが
今回はこれにて終了(・∀・)
次回はXMLでも載せようかな~と思ってます。




テーマ:プログラミング - ジャンル:コンピュータ

2005.11.01 | Comments(1) | Trackback(0) | プログラム

«  | HOME |  »

FC2Ad

ブロとも申請フォーム

この人とブロともになる

カウンター


上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。