管理者権限への権限上昇が必要なのはどのようなときか - その2
その1はレジストリの説明をしました。
その2ではファイルアクセスの例を示します。
XP/2003までは、Administratorsグループに所属しているアカウントはProgram Filesにファイルを作成・書き込む・削除することができました。
Windows Vistaでは、Administratorsグループに所属しているアカウントでも「Program Files」のファイルを直接操作することはできませんが、プログラム上では成功しているように見えます。
以下は、Vistaでは、管理者権限へ権限上昇しなくても書き込みは成功しますが、権限上昇しないと、実はユーザーフォルダのVirtualStoreの中に保存されるという例です。
■■■ write_prgf プロジェクト
■ main.cpp
//----------------------------------------------------------------------------------------------------
// Program Filesへのファイル書き込み
// XP/2003まででも、Administratorsグループに所属していないアカウントは動作しない
// Vistaでは、管理者権限へ権限上昇しなくても書き込みは成功するが、
// 実はユーザーフォルダのVirtualStoreの中に保存される。
//
// 権限上昇しない場合
// "C:\\Program Files\\sample.txt"を作成した場合、アクセスは成功するが、
// 実際には、下記に保存される
// "C:\\Users\\[ユーザ名]\\AppData\\Local\\VirtualStore\\Program Files\\sample.txt"
//----------------------------------------------------------------------------------------------------
#include <windows.h>
#include <tchar.h>
#include <string>
#include <shlobj.h>
#include <io.h>
#include <fcntl.h>
#include <sys/stat.h>
// CSIDL へのパスを取得
std::basic_string < _TCHAR > GetCSIDLPath ( int nCSIDL )
{
enum
{
MY_MAX_PATH = MAX_PATH + 1
};
std::basic_string < _TCHAR > strResult;
ITEMIDLIST *pItemIDList;
_TCHAR szPath[ MY_MAX_PATH ];
if ( SUCCEEDED ( SHGetSpecialFolderLocation ( NULL,
nCSIDL,
&pItemIDList ) ) )
{
if ( SHGetPathFromIDList ( pItemIDList, szPath ) )
{
strResult = szPath;
}
CoTaskMemFree ( pItemIDList );
}
return strResult;
}
// エントリポイント
int WINAPI _tWinMain ( HINSTANCE,
HINSTANCE,
_TCHAR *,
int )
{
// Program Filesへのパスを取得
std::basic_string < _TCHAR > strProgramFilesPath;
strProgramFilesPath = GetCSIDLPath ( CSIDL_PROGRAM_FILES );
// ファイルパス作成
const _TCHAR cszSample[] = _TEXT ( "\\sample.txt" );
std::basic_string < _TCHAR > strPath;
strPath = strProgramFilesPath + cszSample;
// ファイル書き込み作成
int nHandle;
// ファイルを開く
nHandle = _topen ( strPath.c_str (), _O_BINARY | _O_CREAT | _O_WRONLY, _S_IWRITE );
if ( -1 == nHandle )
{
MessageBox ( NULL,
_TEXT ( "ファイルを開くことができません" ),
_TEXT ( "エラー" ),
MB_OK | MB_ICONSTOP );
return 0;
}
const char csz[] = "sample";
// ファイルを書き込み
if ( -1 == _write ( nHandle, csz, ( sizeof ( csz ) - 1 ) * sizeof ( char ) ) )
{
MessageBox ( NULL,
_TEXT ( "ファイルを書き込むことができません" ),
_TEXT ( "エラー" ),
MB_OK | MB_ICONSTOP );
// ファイルを閉じる
_close ( nHandle );
}
// 管理者権限へ権限上昇していないと、実際にはstrPathには書き込まれませんが
// 処理は成功したことになります。
MessageBox ( NULL,
strPath.c_str (),
_TEXT ( "下記に作成しました" ),
MB_OK );
_close ( nHandle );
return 0;
} |
上記を管理者権限へ権限上昇せずに実行し、実行したWindowsアカウントのフォルダを開いてみましょう。
アクセスしたパスではなく、C:\Users\[ユーザ名]\AppData\Local\VirtualStore\Program Files\sample.txt に書き込まれたことがわかります。
管理者権限へ権限上昇しなくてもProgram Filesの中身を読み込むことはできますが、権限上昇せずに書き込もうとすると権限がないため、パスがVirtualStoreにエミュレートされて書き込まれてしまうのです。
今度は、管理者権限へ権限上昇するようにrequireAdministratorにしてみましょう。
■■■ write_prgf2 プロジェクト
■ main.cpp
write_prgf2のmain.cppと同じソース |
■resrc.rc
1 24 "write_prgf2.exe.manifest" |
■write_prgf2.exe.manifest
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity version="1.0.0.0"
processorArchitecture="X86"
name="write_prgf2.exe"
type="win32"/>
<description>Privilege's elevation for writeprgf2</description>
<!-- Identify the application security requirements. -->
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
<security>
<requestedPrivileges>
<requestedExecutionLevel
level="requireAdministrator"
uiAccess="false"/>
</requestedPrivileges>
</security>
</trustInfo>
<dependency>
<dependentAssembly>
<assemblyIdentity
type="win32"
name="Microsoft.Windows.Common-Controls"
version="6.0.0.0"
processorArchitecture="X86"
publicKeyToken="6595b64144ccf1df"
language="*"
/>
</dependentAssembly>
</dependency>
</assembly>
|
今度はProgram Filesに実際書き込むことができました。
以上からわかるように、
Administratorsグループに所属していても、XPまでのように最高権限としては動作しません。
システムの内容の「読み込み」権限はありますが、「変更」「作成」「書き込み」権限がありません。場合によってはエミュレートされます。
これはレジストリ・ファイルに限った話ではありません。
|