デバイス オブジェクトのセキュリティ

久方ぶりです。まさかたです。
今回は、デバイスにアクセスする際のセキュリティに深く関係のある、デバイスオブジェクトのセキュリティについてお話ししたいと思います。
まず、アプリケーションが、デバイスに対して I/O のリクエストをする場合、入り口として CreateFile() でデバイスハンドルを取得し、このハンドルを通して ReadFile() や WriteFile(), DeviceIoControl() などでリクエストを行います。このようなデバイスハンドルの取得や、I/O のリクエストの実行は、セキュリティの観点から、どんなユーザーからでも実行できては困りますので、一定の制限を設ける必要があります。
以前、A 寿さんの記事の中で、I/O コントロールの発行に必要なデバイス ハンドルのアクセス権限についてのお話がありましたが、それもこのようなセキュリティを保つための仕組みの一つだと思います。
通常は、デバイスへのアクセスは管理者権限を必要とする場合が多いのですが、お客様によっては、管理者権限以外でもアクセスできるようにしたいなど、このセキュリティをコントロールする方法についてお問い合わせいただくことがあります。
そこで、これに関連するお話として、ユーザーによって、CreateFile() の実行可否や、設定可能なアクセス権限などをコントロールすることができる、デバイスオブジェクトのセキュリティについてお話をしたいと思います。


セキュリティのチェックを行うためには、どのユーザーが、どのデバイスオブジェクトに対して、どんなアクセス権限を持っているのかといったことを識別し、判断する必要がありますが、そのための情報として、アクセストークン、や Security Descriptorと呼ばれるものがあります。それぞれの詳細は、こちらのページを見ていただければと思いますが、大まかには以下のようになると思います。

  • Access Token - アクセスする側 (アプリケーション等) が持つ情報 プロセスが持つ Security Context を表すオブジェクト。Security Context は、プロセスを実行しているユーザー アカウントと、それに付与される権限 (Read/Write/Execute など) の組み合わせで、Access Token には、ユーザーアカウントを識別する SID と、システムから許可された権限のリストが記述されている。SID は、ユーザー、グループ、ログオンセッションを識別するためのセキュリティ上の ID。
  • Security Descriptor - アクセスされる側 (デバイス オブジェクト等) が持つ情報 オブジェクトが持つセキュリティに関する記述子。Security Descriptorは、オブジェクトの所有者・グループの SID、ACL (Access Control List) が記述されている。さらに、ACL は、ACE (Access Control Entry) の集まりで、ACE は、SID と、その SID に対して拒否又は許可されている権限の組み合わせを記述したもの。記述方法は、Security Descriptor定義言語 (SDDL; Security Descriptor Definition Language) が使用される。 デバイス オブジェクトの ACL は、INF または IoCreateDeviceSecure() 関数で設定が可能。

デバイスにアクセスしようとした時に、ユーザーの権限や、デバイスオブジェクトのアクセスに必要な権限を表すのは、これらの情報になります。そして、CreateFile() でデバイス オブジェクトのオープンを行おうとした場合、Windows では以下のような流れでリクエストの処理が行われており、その要所でセキュリティチェックが行われています。
※「Windows セキュリティ モデル : ドライバー作成者向け情報」から抜粋

図 2. CreateFile 要求の処理

図 2 は、ユーザー モードのアプリケーションが CreateFile 関数を呼び出すときのシステムの応答方法を示しています。下記の説明は、図中の丸で囲まれた数字に対応しています。

  1. ユーザー モード アプリケーションが、CreateFile 関数を呼び出して、Microsoft Win32 の有効なファイル名を渡します。
  2. ユーザー モードの Kernel32.dll は要求を Ntdll.dll に渡し、Ntdll.dll は Win32 名を Microsoft Windows NT のファイル名に変換します。
  3. Ntdll.dll は、Windows NT のファイル名を使用して NtCreateFile 関数を呼び出します。Ntoskrnl.exe 内で、I/O マネージャーは NtCreateFile を処理します。
  4. I/O マネージャーは、要求を再パッケージしてオブジェクト マネージャーを呼び出します。
  5. オブジェクト マネージャーは、シンボリック リンクを解決し、ファイルが作成されるパスに対するスキャン権限をユーザーが持っていることを確認します。詳細については、このペーパーの「オブジェクト マネージャーでのセキュリティ チェック」 参照してください。
  6. オブジェクト マネージャーは、要求に関連する基本的なオブジェクト タイプを保持しているシステム コンポーネントを呼び出します。ファイル作成要求では、このコンポーネントは I/O マネージャーであり、デバイス オブジェクトを保持しています。
  7. I/O マネージャーは、デバイス オブジェクトのSecurity Descriptorをユーザーのプロセスのアクセス トークンと比較してチェックし、ユーザーがデバイスに対して必要なアクセス権を持っていることを確認します。詳細については、このペーパーの「I/O マネージャーでのセキュリティ チェック」を参照してください。
  8. ユーザーのプロセスが必要なアクセス権を持っている場合、I/O マネージャーはハンドルを作成し、IRP_MJ_CREATE 要求をデバイスまたはファイル システムのドライバーに送信します。
  9. ドライバーは、必要に応じて追加のセキュリティ チェックを実行します。たとえば、要求がデバイスの名前空間内のオブジェクトを指定している場合、ドライバーは呼び出し元が必要なアクセス権を持っていることを確認する必要があります。詳細については、このペーパーの「ドライバーでのセキュリティ チェック」を参照してください。

この中で、特にドライバー自身がチェックを行うのは ⑨ になります。ただ、前述の Access Token や Security Descriptor に基づいたチェックは、⑦ の I/O マネージャーが行っています。
デバイス オブジェクトそのものに設定するという点では、前述の Security Descriptorの記述が、デバイス オブジェクトをセキュリティで保護するための直接的な方法です。これ以外にも、デバイスオブジェクトをセキュリティで保護するためにドライバー側でできることには、デバイスの名前空間の保護や、デバイスオープンの排他制御といったものがありますが、今回は、Security Descriptor の設定について、ご紹介したいと思います。

デバイスオブジェクトへのSecurity Descriptor の設定方法
デバイス オブジェクトに Security Descriptor を設定・変更する方法には、主に以下の 3 つを使った方法があります。

(1) INF
(2) IoCreateDeviceSecure 関数
(3) SetupDiSetDeviceRegistryProperty 関数

以下では、それぞれについて WDK の Toaster サンプルや DevCon サンプルを使った例を交えながら、紹介したいと思います。

(1) INF
INFに特定の記述を行うことで、デバイスオブジェクトに設定する Security Descriptor を制御できます。また、その方法は、(ア) デバイス セットアップ クラスの既定の設定を利用する方法と、(イ) SDDL で独自に指定する方法の 2 つがあります。(ア) は、既定ではセットアップクラスに属するデバイスすべてに適用されるものですが、(イ) の設定はクラスではなく個々のデバイスに対して適用されるもので、設定した場合には、(ア) の設定より優先されます。

(ア) デバイス セットアップ クラスの既定の設定を利用
INF の Version セクション内では、Class エントリや ClassGuid エントリでデバイスが属するデバイス セットアップ クラスを指定することができますが、既存のセットアップクラスは、既定の Security Descriptor を持っています。そのため、INF の中で既存のセットアップクラスに属するよう設定し、(イ) の設定を行わなければ、セットアップクラスの既定の Security Descriptor が適用されることになります。
なお、この既存のセットアップクラスの一部が持っている独自の Security Descriptor に関して、技術情報としてまとまったものは公開されていないようです。ただ、SetupDiGetClassProperty 関数を使用することで、セットアップクラス毎の Security Descriptor に関する情報を取得できます。具体的には、関数の引数に指定するプロパティのフラグとして、DEVPKEY_DeviceClass_SecurityDEVPKEY_DeviceClass_SecuritySDS を指定すれば、セットアップクラスの Security Descriptor の情報を取得できます。
例えば、WDK サンプルの devcon の classes オプションの処理 cmdClasses 関数に実装を追加して、SetupDiGetClassProperty 関数で、DEVPKEY_DeviceClass_SecuritySDS を指定し、各セットアップクラスの Security Descriptor の SDDL を取得できるようにしてみました。

// devcon サンプル cmds.cpp 112 行目付近 int cmdClasses(__in LPCTSTR BaseName, __in LPCTSTR Machine, __in DWORD Flags, __in int argc, __in_ecount(argc) TCHAR* argv[])     …(中略)…     for(index=0;index<numGuids;index++) { // 162 行目付近         …(中略)…         TCHAR propBuff[LINE_LEN];         DEVPROPTYPE devPropType;         if(!SetupDiGetClassProperty(&guids[index],                                     &DEVPKEY_DeviceClass_SecuritySDS,                                     &devPropType,                                     (PBYTE)propBuff,                                     LINE_LEN,                                     NULL,                                     DICLASSPROP_INSTALLER))         {             if (FAILED(StringCchCopy(propBuff,LINE_LEN,TEXT("Default")))) {                 goto final;         }     }     _tprintf(TEXT("%-20s: %s\n"),className,propBuff);

試しに、私の手元の Windows 7 SP1 の環境で実行してみた結果が以下です。事前に、サンプルの Toaster function driver をインストールしてあります。(SetupDiGetClassProperty 関数の戻り値が False の場合には、Default と出力しています。)

Listing 58 setup classes.

WCEUSBS : Default

USB : Default

Media Center Extender: Default

PnpPrinters : Default

Dot4 : Default

Dot4Print : Default

CDROM : Default

Computer : Default

DiskDrive : Default

Display : D:P(A;;GA;;;SY)

fdc : Default

hdc : D:P(A;;0x101f01ff;;;SY)(A;;0x101f01ff;;;BA)

Keyboard : Default

MEDIA : Default

Modem : Default

Monitor : Default

Mouse : Default

MTD : Default

MultiFunction : Default

Net : Default

NetClient : Default

NetService : Default

NetTrans : D:P(A;;GA;;;SY)(A;;GA;;;BA)(A;;GA;;;NS)(A;;GA;;;LS)(A;;GXGR;;;AU)

PCMCIA : Default

Ports : Default

Printer : Default

SCSIAdapter : D:P(A;;0x101f01ff;;;SY)(A;;0x101f01ff;;;BA)

System : Default

Unknown : Default

FloppyDisk : Default

Processor : Default

MultiPortSerial : Default

Memory : Default

SmartCardReader : Default

Sensor : Default

VolumeSnapshot : Default

BiometricDevice : Default

1394 : D:P(A;;GA;;;SY)(A;;GA;;;BA)

Infrared : Default

Image : Default

TapeDrive : D:P(A;;0x101f01ff;;;SY)(A;;0x101f01ff;;;BA)(A;;0x101f01ff;;;BO)

Volume : Default

Battery : Default

HIDClass : Default

61883 : Default

LegacyDriver : Default

SmartCard : Default

SideShow : Default

SDHost : Default

TOASTER : D:P(A;;GA;;;SY)(A;;GA;;;BA)

Transfer Cable : Default

AVC : Default

MediumChanger : D:P(A;;0x101f01ff;;;SY)(A;;0x101f01ff;;;BA)(A;;0x101f01ff;;;BO)

SBP2 : Default

XnaComposite : Default

SecurityDevices : Default

SmartCardFilter : Default

Bluetooth : Default

WPD : Default

Toaster クラスを含め、ところどころ、独自の Security Descriptor を設定しているクラスがありますが、多くは独自の設定はしていないことが分かります。その場合、多くのデバイスでは、Default の Security Descriptor として、Administrators に GENERIC_ALL、everyone に対して (GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE) を付与しています。

ちなみに、独自のセットアップクラスを作成する場合、クラスインストーラーの INF の ClassInstall32 セクション内の AddReg ディレクティブで、クラスの Security Descriptor を指定できます。
例として、WDK の Toaster サンプルでは、独自の Toaster クラスを作成していますが、INF の中で独自の Security Descriptor を設定しており、前述の Toaster クラスの SDDL と一致しているのが分かります。

// toaster.inf より抜粋 [Version] Signature="$WINDOWS NT$" Class=TOASTER ClassGuid={B85B7C50-6A01-11d2-B841-00C04FAD5171} … (中略) … ; ================= Class section ===================== [ClassInstall32] Addreg=ToasterClassReg CopyFiles=ToasterClassInstallerCopyFiles [ToasterClassReg] HKR,,,0,%ClassName% HKR,,Icon,,100 HKR,,Installer32,,"tostrcls.dll,ToasterClassInstaller" HKR,,DeviceCharacteristics,0x10001,0x100 ;Use same security checks on relative opens HKR,,Security,,"D:P(A;;GA;;;SY)(A;;GA;;;BA)" ;Allow generic all access to system and built-in Admin. ;This one overrides the security set by the driver

(イ) SDDL で明示的に指定
クラスごとの設定ではなく、個々のデバイスに独自の Security Descriptor を設定したい場合には、INF の DDInstall.HW セクション、AddReg ディレクティブ で、Security のレジストリに SDDL を記述します。前述の通り、ここで設定した値は、デバイスセットアップ クラス のSecurity Descriptorの既定値よりも優先されます。
例として、Toaster サンプルの bus ドライバーの INF が参考になると思います。Toaster Bus ドライバーでは、クラスは System になっていますが、Security Descriptor は独自に設定を行っています。

// bus.inf より抜粋 [Version] Signature="$WINDOWS NT$" Class=System ClassGuid={4D36E97D-E325-11CE-BFC1-08002BE10318} … (中略) … [ToasterBus_Device.NT.HW] AddReg=ToasterBus_Device.NT.AddReg [ToasterBus_Device.NT.AddReg] HKR,,DeviceCharacteristics,0x10001,0x0100 ; Use same security checks on relative opens HKR,,Security,,"D:P(A;;GA;;;BA)(A;;GA;;;SY)" ; Allow generic-all access to Built-in administrators and Local system

(2) IoCreateDeviceSecure 関数
デバイス オブジェクトを作成するための関数として、IoCreateDevice 関数が使われますが、本関数には、Security Descriptor を指定できるような引数がありません。これに対して、IoCreateDeviceSecure 関数では、引数の中で、SDDL を記述することができるようになっています。

NTSTATUS IoCreateDeviceSecure(     __in PDRIVER_OBJECT DriverObject,     __in ULONG DeviceExtensionSize,     __in_opt PUNICODE_STRING DeviceName,     __in DEVICE_TYPE DeviceType,     __in ULONG DeviceCharacteristics,     __in BOOLEAN Exclusive,     __in PCUNICODE_STRING DefaultSDDLString,     __in_opt LPCGUID DeviceClassGuid,     __out PDEVICE_OBJECT *DeviceObject );

ただし、IoCreateDeviceSecure 関数は、どんな種類のドライバーやデバイス オブジェクトの作成にも使えるわけではありませんのでご注意ください。
一般的に本関数の使用を想定しているのは、バスドライバーが作成する一部の PDO (Raw Mode で動作するデバイスの PDO や、クラスで既定のものではなく独自の SDDL を設定する必要のある PDO) や、レガシードライバーとなっており、通常の WDM Function Driver や Filter Driver でのデバイスオブジェクトの作成には、IoCreateDevice 関数を使い、独自の SDDL の記述は、INF で行うようにします。また、Bus Driver でも、クラスの既定の Security Descriptor を使用する場合には、IoCreateDevice 関数を使うことになります。これらの詳細については、以下が参考になると思います。

- Creating a Device Object
<https://msdn.microsoft.com/en-us/library/windows/hardware/ff542862(v=vs.85).aspx>

ただ、Function Driver や Filter Driver でも、コントロール デバイス オブジェクトを作成する場合は、 IoCreateDeviceSecure 関数でオブジェクトの SDDL を指定します。例えば、Toaster サンプルでは、IoCreateDeviceSecure 関数でコントロールデバイス オブジェクトを作成しているのが分かります。

// pnp.c 1108 行目付近 NTSTATUS Bus_PlugInDevice (     PBUSENUM_PLUGIN_HARDWARE PlugIn,     ULONG PlugInSize,     PFDO_DEVICE_DATA FdoData ) … (中略) …     //     // PDO must have a name. You should let the system auto generate a     // name by specifying FILE_AUTOGENERATED_DEVICE_NAME in the     // DeviceCharacteristics parameter. Let us create a secure deviceobject,     // in case the child gets installed as a raw device (RawDeviceOK), to prevent     // an unpriviledged user accessing our device. This function is avaliable     // in a static WDMSEC.LIB and can be used in Win2k, XP, and Server 2003     // Just make sure that the GUID specified here is not a setup class GUID.     // If you specify a setup class guid, you must make sure that class is     // installed before enumerating the PDO.     //     status = IoCreateDeviceSecure(FdoData->Self->DriverObject,                     sizeof (PDO_DEVICE_DATA),                     NULL,                     FILE_DEVICE_BUS_EXTENDER,                     FILE_AUTOGENERATED_DEVICE_NAME |FILE_DEVICE_SECURE_OPEN,                     FALSE,                     &SDDL_DEVOBJ_SYS_ALL_ADM_ALL, // read wdmsec.h for more info                     (LPCGUID)&GUID_SD_BUSENUM_PDO,                     &pdo);

 

補足 : デバイス オブジェクトのSDDL について デバイス オブジェクトの場合、INF で記述する場合には、一般的な SDDL と同じ記述が可能ですが、IoCreateDeviceSecure 関数で記述できる SDDL はそのサブセットとなっています。また、前述の Toaster の Bus Driver で指定していた、SDDL_DEVOBJ_SYS_ALL_ADM_ALL のような template を使用した SDDL の指定の仕方も可能です。詳細は以下をご参照いただければと思います。

- SDDL for Device Objects <https://msdn.microsoft.com/en-us/library/windows/hardware/ff563667(v=vs.85).aspx>

なお、一般的な SDDL の記述にご興味のある方は、こちらのページを見ていただければと思います。

- Security Descriptor String Format <https://msdn.microsoft.com/en-us/library/windows/desktop/aa379570(v=vs.85).aspx>

(3) SetupDiSetDeviceRegistryProperty 関数
(1) の INF の記述による Security Descriptor は、詰まる所、レジストリ上に値の設定を行っていますので、お馴染みの Setup API のひとつである、SetupDiSetDeviceRegistryProperty 関数を使うことで、ドライバーのインストール後でも設定の変更が可能です。
関数のプロパティを指定するためのフラグには、SPDRP_SECURITY もしくは SPDRP_SECURITY_SDS を使用することになると思います。ちなみに、値の取得は、SetupDiGetDeviceRegistryProperty 関数でできます。
例えば、DevCon サンプルを改造して、/findall オプション実行時に、SetupDiGetDeviceRegistryProperty 関数で、デバイスの Friendly Name を取得する代わりに、SDDL を取得するようにしてみます。

// devcon サンプル cmds.cpp 291 行目付近 #define DEFAULT_TEXT TEXT("Default") LPTSTR GetDeviceDescription(__in HDEVINFO Devs, __in PSP_DEVINFO_DATA DevInfo) {     LPTSTR desc; #if 0 // [masakata]    desc = GetDeviceStringProperty(Devs,DevInfo,SPDRP_FRIENDLYNAME); #else // [masakata]     desc = GetDeviceStringProperty(Devs,DevInfo,SPDRP_SECURITY_SDS); #endif // [masakata]     if(!desc) {         desc = new TCHAR[32];         lstrcpyn(desc,DEFAULT_TEXT,sizeof(DEFAULT_TEXT));     }     return desc; }

以下が、手元の Windows 7 SP1 環境 (Hyper-V 上) で試してみた結果です。デバイスによっては、複雑な SDDL を記述しているものがあるのが分かると思います。(レジストリが存在しない等、クラスで既定の設定を使っているものには、Default と表示するようにしています。)
ちなみに、赤字で示している ROOT\UNKNOWN000 は、事前にインストールしておいた Toaster の Bus Driver で、SDDL は前述の bus.inf で設定した通り、D:P(A;;GA;;;BA)(A;;GA;;;SY) となっているのが分かります。

ROOT\LEGACY_SRVNET000 : Default

ROOT\LEGACY_DISCACHE000 : Default

ROOT\MS_PPTPMINIPORT000 : Default

UMB\UMB\1&841921D&0&PRINTERBUSENUMERATOR : Default

ACPI\PNP0C02\1 : Default

ROOT\LEGACY_NDPROXY000 : Default

ROOT\LEGACY_STORFLT000 : Default

ROOT\LEGACY_FILEINFO000 : Default

ROOT\MS_SSTPMINIPORT000 : Default

ACPI\PNP0C02\2 : Default

VMBUS\{58F75A6D-D949-4320-99E1-A2A2576D581C}\5&296C0F0E&0&{58F75A6D-D949-4320-99E1-A2A2576D581C}: Default

ROOT\LEGACY_NETBIOS000 : Default

PCI\VEN_8086&DEV_7111&SUBSYS_00000000&REV_01\3&267A616A&0&39: Default

ACPI\PNP0C04\4&215D0F95&0 : Default

ROOT\LEGACY_TCPIP000 : Default

STORAGE\VOLUMESNAPSHOT\HARDDISKVOLUMESNAPSHOT3 : Default

VMBUS\{00000000-0000-8899-0000-000000000000}\5&296C0F0E&0&{00000000-0000-8899-0000-000000000000}: Default

ROOT\LEGACY_FLTMGR000 : Default

ROOT\RDPBUS000 : Default

ROOT\LEGACY_NETBT000 : Default

ROOT\RDP_KBD000 : Default

ROOT\LEGACY_TCPIPREG000 : Default

ACPI\PNP0F03\4&215D0F95&0 : Default

ROOT\LEGACY_FS_REC000 : Default

ROOT\RDP_MOU000 : Default

ROOT\LEGACY_NPFS000 : Default

ROOT\LEGACY_TDX000 : Default

ROOT\LEGACY_FVEVOL000 : Default

ACPI\VMBUS\4&215D0F95&0 : D:P(A;;GA;;;BA)(A;;GA;;;SY)

PCI\VEN_8086&DEV_7192&SUBSYS_00000000&REV_03\3&267A616A&0&00: Default

ROOT\SYSTEM000 : Default

ROOT\LEGACY_NSIPROXY000 : Default

ACPI\FIXEDBUTTON\2&DABA3FF&2 : Default

ROOT\LEGACY_UDFS000 : Default

ROOT\LEGACY_HTTP000 : Default

ACPI_HAL\PNP0C08 : Default

ROOT\UMBUS000 : Default

VMBUS\{6B6E7049-1CC7-4653-A142-9B7B5AC318FA}\5&296C0F0E&0&{6B6E7049-1CC7-4653-A142-9B7B5AC318FA}: Default

ROOT\LEGACY_NTFS000 : Default

VMBUS\{242FF919-07DB-4180-9C2E-B86CB68C8C55}\5&296C0F0E&0&{242FF919-07DB-4180-9C2E-B86CB68C8C55}: D:P(A;;GA;;;BA)(A;;GA;;;SY)(A;;GA;;;S-1-5-80-1877308096-3090306141-3032871208-3115266146-1400827410)

ROOT\LEGACY_VGASAVE000 : Default

FDC\GENERIC_FLOPPY_DRIVE\5&3AA3947E&0&0 : Default

ROOT\UNKNOWN000 : D:P(A;;GA;;;BA)(A;;GA;;;SY)

ROOT\LEGACY_HWPOLICY000 : Default

ACPI\GENUINEINTEL_-_X86_FAMILY_6_MODEL_15_-_INTEL(R)_CORE(TM)2_CPU__________6400__@_2.13GHZ\_1: Default

ROOT\LEGACY_NULL000 : Default

ROOT\VDRVROOT000 : Default

PCIIDE\IDECHANNEL\4&10BF2F88&0&0 : Default

ROOT\LEGACY_VOLMGRX000 : Default

ROOT\LEGACY_KSECDD000 : Default

HID\{58F75A6D-D949-4320-99E1-A2A2576D581C}\6&E4AA24C&0&0000 : Default

ROOT\VOLMGR000 : Default

ROOT\LEGACY_PCW000 : Default

ROOT\LEGACY_VOLSNAP000 : Default

ROOT\LEGACY_KSECPKG000 : Default

PCIIDE\IDECHANNEL\4&10BF2F88&0&1 : Default

STORAGE\VOLUME\{F841DCBE-4BB0-11E1-99F2-806E6F6E6963}#0000000000100000: Default

ROOT\LEGACY_PEAUTH000 : Default

ROOT\LEGACY_WANARPV6000 : Default

ROOT\LEGACY_LLTDIO000 : Default

VMBUS\{AA5601EE-5D88-48AD-8E1A-4250FB1256E7}\5&296C0F0E&0&{AA5601EE-5D88-48AD-8E1A-4250FB1256E7}: D:P(A;;GA;;;BA)(A;;GA;;;SY)(A;;GWGR;;;BU)

ROOT\LEGACY_PSCHED000 : Default

ROOT\*ISATAP000 : Default

VMBUS\{2450EE40-33BF-4FBD-892E-9FB06E9214CF}\5&296C0F0E&0&{2450EE40-33BF-4FBD-892E-9FB06E9214CF}: D:P(A;;GA;;;BA)(A;;GA;;;SY)(A;;GA;;;S-1-5-80-1752088424-1054500994-3489791022-3310831482-3926524968)

ACPI\PNP0000\4&215D0F95&0 : Default

HTREE\ROOT : Default

ROOT\LEGACY_LUAFV000 : Default

ROOT\LEGACY_WDF01000000 : Default

ROOT\ACPI_HAL000 : Default

ROOT\LEGACY_RDBSS000 : Default

IDE\CDROMMSFT_VIRTUAL_CD/ROM_____________________1.0_____\5&CFB56DE&0&1.0.0: Default

ACPI\PNP0100\4&215D0F95&0 : Default

ROOT\LEGACY_MOUNTMGR000 : Default

ROOT\BLBDRIVE000 : Default

STORAGE\VOLUME\{F841DCBE-4BB0-11E1-99F2-806E6F6E6963}#0000000006500000: Default

ROOT\LEGACY_WFPLWF000 : Default

ROOT\LEGACY_RDPCDD000 : Default

ROOT\COMPOSITEBUS000 : D:P(A;;GA;;;BA)(A;;GA;;;SY)

ACPI\PNP0200\4&215D0F95&0 : Default

ROOT\LEGACY_MPSDRV000 : Default

ROOT\MSSMBIOS000 : Default

ROOT\LEGACY_RDPENCDD000 : Default

ROOT\LEGACY_AFD000 : Default

ACPI\PNP0303\4&215D0F95&0 : Default

ROOT\MS_AGILEVPNMINIPORT000 : Default

VMBUS\{B6650FF7-33BC-4840-8048-E0676786F393}\5&296C0F0E&0&{B6650FF7-33BC-4840-8048-E0676786F393}: D:P(A;;GA;;;BA)(A;;GA;;;SY)(A;;GA;;;S-1-5-80-3110303136-3426481729-3186938678-1087894076-2178433439)

ROOT\LEGACY_MRXSMB000 : Default

IDE\DISKVIRTUAL_HD______________________________1.1.0___\5&35DC7040&0&0.0.0: Default

VMBUS\{2DD1CE17-079E-403C-B352-A1921EE207EE}\5&296C0F0E&0&{2DD1CE17-079E-403C-B352-A1921EE207EE}: D:P(A;;GA;;;BA)(A;;GA;;;SY)(A;;GA;;;S-1-5-80-3098585136-2538892366-1097114017-2832417424-2016953023)

ROOT\LEGACY_RDPREFMP000 : Default

ROOT\LEGACY_BEEP000 : Default

STORAGE\VOLUMESNAPSHOT\HARDDISKVOLUMESNAPSHOT1 : Default

ACPI\PNP0501\1 : Default

ROOT\LEGACY_MRXSMB10000 : Default

ROOT\MS_L2TPMINIPORT000 : Default

ROOT\LEGACY_RSPNDR000 : Default

ROOT\LEGACY_BOWSER000 : Default

ACPI\PNP0501\2 : Default

ROOT\LEGACY_MRXSMB20000 : Default

ROOT\MS_NDISWANBH000 : Default

ACPI\PNP0700\4&215D0F95&0 : Default

ROOT\LEGACY_SECDRV000 : Default

ROOT\LEGACY_CLFS000 : Default

STORAGE\VOLUMESNAPSHOT\HARDDISKVOLUMESNAPSHOT2 : Default

ROOT\LEGACY_MSFS000 : Default

ROOT\MS_NDISWANIP000 : Default

PCI\VEN_1414&DEV_5353&SUBSYS_00000000&REV_00\3&267A616A&0&40: Default

ACPI\PNP0800\4&215D0F95&0 : Default

ROOT\LEGACY_SPLDR000 : Default

ROOT\LEGACY_CNG000 : Default

VMBUS\{FD149E91-82E0-4A7D-AFA6-2A4166CBD7C0}\5&296C0F0E&0&{FD149E91-82E0-4A7D-AFA6-2A4166CBD7C0}: D:P(A;;GA;;;BA)(A;;GA;;;SY)(A;;GA;;;S-1-5-80-534935901-3437432317-481271085-1710633381-983106267)

ROOT\LEGACY_MSISADRV000 : Default

VMBUS\{5620E0C7-8062-4DCE-AEB7-520C7EF76171}\5&296C0F0E&0&{5620E0C7-8062-4DCE-AEB7-520C7EF76171}: Default

ROOT\MS_NDISWANIPV6000 : Default

ROOT\LEGACY_SRV000 : Default

ROOT\LEGACY_CSC000 : Default

ACPI\PNP0A03 : Default

SW\{EEAB7790-C514-11D1-B42B-00805FC1270E}\ASYNCMAC : Default

ROOT\LEGACY_MUP000 : Default

ACPI\PNP0B00\4&215D0F95&0 : Default

ROOT\MS_PPPOEMINIPORT000 : Default

ROOT\LEGACY_SRV2000 : Default

ROOT\LEGACY_DFSC000 : Default

PCI\VEN_8086&DEV_7110&SUBSYS_00001414&REV_01\3&267A616A&0&38: Default

ROOT\LEGACY_NDIS000 : Default

ACPI\PNP0C01\1 : Default

126 matching device(s) found.

さらに、SetupDiSetDeviceRegistryProperty 関数の方も試してみます。
実際にはこんなことをすべきではありませんが、以下では、全てのデバイスの SDDL で World (everyone) に対して、Generic_All のアクセス権を付与して、その後、SDDL を取得して表示します。

#define MY_SDDL_STRING TEXT("D:P(A;;GA;;;WD)") #define DEFAULT_TEXT TEXT("Default") LPTSTR GetDeviceDescription(__in HDEVINFO Devs, __in PSP_DEVINFO_DATA DevInfo) {     LPTSTR desc; #if 0 // [masakata]     desc = GetDeviceStringProperty(Devs,DevInfo,SPDRP_FRIENDLYNAME); #else // [masakata]     SetupDiSetDeviceRegistryProperty(Devs,DevInfo,SPDRP_SECURITY_SDS,(BYTE*)MY_SDDL_STRING,sizeof(MY_SDDL_STRING));     desc = GetDeviceStringProperty(Devs,DevInfo,SPDRP_SECURITY_SDS); #endif // [masakata]     if(!desc) {         desc = new TCHAR[64];         lstrcpyn(desc,DEFAULT_TEXT,sizeof(DEFAULT_TEXT));     }     return desc; }

すると、全ての SDDL が指定した通りに変更されました。しかし、これでは、セキュリティとしては穴だらけの状態ですので、このようなことはお勧めしません。
先ほどの Toaster Bus Driver も、元々の D:P(A;;GA;;;BA)(A;;GA;;;SY) から、D:P(A;;GA;;;WD) に変わってしまっています。

ROOT\LEGACY_SRVNET000 : D:P(A;;GA;;;WD) ROOT\LEGACY_DISCACHE000 : D:P(A;;GA;;;WD) ROOT\MS_PPTPMINIPORT000 : D:P(A;;GA;;;WD) UMB\UMB\1&841921D&0&PRINTERBUSENUMERATOR: D:P(A;;GA;;;WD) ACPI\PNP0C02\1 : D:P(A;;GA;;;WD) ROOT\LEGACY_NDPROXY000 : D:P(A;;GA;;;WD) ROOT\LEGACY_STORFLT000 : D:P(A;;GA;;;WD) ROOT\LEGACY_FILEINFO000 : D:P(A;;GA;;;WD) ROOT\MS_SSTPMINIPORT000 : D:P(A;;GA;;;WD) ACPI\PNP0C02\2 : D:P(A;;GA;;;WD) VMBUS\{58F75A6D-D949-4320-99E1-A2A2576D581C}\5&296C0F0E&0&{58F75A6D-D949-4320-99E1-A2A2576D581C} : D:P(A;;GA;;;WD) ROOT\LEGACY_NETBIOS000 : D:P(A;;GA;;;WD) PCI\VEN_8086&DEV_7111&SUBSYS_00000000&REV_01\3&267A616A&0&39 : D:P(A;;GA;;;WD) ACPI\PNP0C04\4&215D0F95&0 : D:P(A;;GA;;;WD) ROOT\LEGACY_TCPIP000 : D:P(A;;GA;;;WD) STORAGE\VOLUMESNAPSHOT\HARDDISKVOLUMESNAPSHOT3 : D:P(A;;GA;;;WD) VMBUS\{00000000-0000-8899-0000-000000000000}\5&296C0F0E&0&{00000000-0000-8899-0000-000000000000} : D:P(A;;GA;;;WD) ROOT\LEGACY_FLTMGR000 : D:P(A;;GA;;;WD) ROOT\RDPBUS000 : D:P(A;;GA;;;WD) ROOT\LEGACY_NETBT000 : D:P(A;;GA;;;WD) ROOT\RDP_KBD000 : D:P(A;;GA;;;WD) ROOT\LEGACY_TCPIPREG000 : D:P(A;;GA;;;WD) ACPI\PNP0F03\4&215D0F95&0 : D:P(A;;GA;;;WD) ROOT\LEGACY_FS_REC000 : D:P(A;;GA;;;WD) ROOT\RDP_MOU000 : D:P(A;;GA;;;WD) ROOT\LEGACY_NPFS000 : D:P(A;;GA;;;WD) ROOT\LEGACY_TDX000 : D:P(A;;GA;;;WD) ROOT\LEGACY_FVEVOL000 : D:P(A;;GA;;;WD) ACPI\VMBUS\4&215D0F95&0 : D:P(A;;GA;;;WD) PCI\VEN_8086&DEV_7192&SUBSYS_00000000&REV_03\3&267A616A&0&00 : D:P(A;;GA;;;WD) ROOT\SYSTEM000 : D:P(A;;GA;;;WD) ROOT\LEGACY_NSIPROXY000 : D:P(A;;GA;;;WD) ACPI\FIXEDBUTTON\2&DABA3FF&2 : D:P(A;;GA;;;WD) ROOT\LEGACY_UDFS000 : D:P(A;;GA;;;WD) ROOT\LEGACY_HTTP000 : D:P(A;;GA;;;WD) ACPI_HAL\PNP0C08 : D:P(A;;GA;;;WD) ROOT\UMBUS000 : D:P(A;;GA;;;WD) VMBUS\{6B6E7049-1CC7-4653-A142-9B7B5AC318FA}\5&296C0F0E&0&{6B6E7049-1CC7-4653-A142-9B7B5AC318FA} : D:P(A;;GA;;;WD) ROOT\LEGACY_NTFS000 : D:P(A;;GA;;;WD) VMBUS\{242FF919-07DB-4180-9C2E-B86CB68C8C55}\5&296C0F0E&0&{242FF919-07DB-4180-9C2E-B86CB68C8C55} : D:P(A;;GA;;;WD) ROOT\LEGACY_VGASAVE000 : D:P(A;;GA;;;WD) FDC\GENERIC_FLOPPY_DRIVE\5&3AA3947E&0&0 : D:P(A;;GA;;;WD) ROOT\UNKNOWN000 : D:P(A;;GA;;;WD) ROOT\LEGACY_HWPOLICY000 : D:P(A;;GA;;;WD) ACPI\GENUINEINTEL_-_X86_FAMILY_6_MODEL_15_-_INTEL(R)_CORE(TM)2_CPU__________6400__@_2.13GHZ\_1 : D:P(A;;GA;;;WD) ROOT\LEGACY_NULL000 : D:P(A;;GA;;;WD) ROOT\VDRVROOT000 : D:P(A;;GA;;;WD) PCIIDE\IDECHANNEL\4&10BF2F88&0&0 : D:P(A;;GA;;;WD) ROOT\LEGACY_VOLMGRX000 : D:P(A;;GA;;;WD) ROOT\LEGACY_KSECDD000 : D:P(A;;GA;;;WD) HID\{58F75A6D-D949-4320-99E1-A2A2576D581C}\6&E4AA24C&0&0000 : D:P(A;;GA;;;WD) ROOT\VOLMGR000 : D:P(A;;GA;;;WD) ROOT\LEGACY_PCW000 : D:P(A;;GA;;;WD) ROOT\LEGACY_VOLSNAP000 : D:P(A;;GA;;;WD) ROOT\LEGACY_KSECPKG000 : D:P(A;;GA;;;WD) PCIIDE\IDECHANNEL\4&10BF2F88&0&1 : D:P(A;;GA;;;WD) STORAGE\VOLUME\{F841DCBE-4BB0-11E1-99F2-806E6F6E6963}#0000000000100000: D:P(A;;GA;;;WD) ROOT\LEGACY_PEAUTH000 : D:P(A;;GA;;;WD) ROOT\LEGACY_WANARPV6000 : D:P(A;;GA;;;WD) ROOT\LEGACY_LLTDIO000 : D:P(A;;GA;;;WD) VMBUS\{AA5601EE-5D88-48AD-8E1A-4250FB1256E7}\5&296C0F0E&0&{AA5601EE-5D88-48AD-8E1A-4250FB1256E7}: D:P(A;;GA;;;WD) ROOT\LEGACY_PSCHED000 : D:P(A;;GA;;;WD) ROOT\*ISATAP000 : D:P(A;;GA;;;WD) VMBUS\{2450EE40-33BF-4FBD-892E-9FB06E9214CF}\5&296C0F0E&0&{2450EE40-33BF-4FBD-892E-9FB06E9214CF}: D:P(A;;GA;;;WD) ACPI\PNP0000\4&215D0F95&0 : D:P(A;;GA;;;WD) HTREE\ROOT : D:P(A;;GA;;;WD) ROOT\LEGACY_LUAFV000 : D:P(A;;GA;;;WD) ROOT\LEGACY_WDF01000000 : D:P(A;;GA;;;WD) ROOT\ACPI_HAL000 : D:P(A;;GA;;;WD) ROOT\LEGACY_RDBSS000 : D:P(A;;GA;;;WD) IDE\CDROMMSFT_VIRTUAL_CD/ROM_____________________1.0_____\5&CFB56DE&0&1.0.0: D:P(A;;GA;;;WD) ACPI\PNP0100\4&215D0F95&0 : D:P(A;;GA;;;WD) ROOT\LEGACY_MOUNTMGR000 : D:P(A;;GA;;;WD) ROOT\BLBDRIVE000 : D:P(A;;GA;;;WD) STORAGE\VOLUME\{F841DCBE-4BB0-11E1-99F2-806E6F6E6963}#0000000006500000: D:P(A;;GA;;;WD) ROOT\LEGACY_WFPLWF000 : D:P(A;;GA;;;WD) ROOT\LEGACY_RDPCDD000 : D:P(A;;GA;;;WD) ROOT\COMPOSITEBUS000 : D:P(A;;GA;;;WD) ACPI\PNP0200\4&215D0F95&0 : D:P(A;;GA;;;WD) ROOT\LEGACY_MPSDRV000 : D:P(A;;GA;;;WD) ROOT\MSSMBIOS000 : D:P(A;;GA;;;WD) ROOT\LEGACY_RDPENCDD000 : D:P(A;;GA;;;WD) ROOT\LEGACY_AFD000 : D:P(A;;GA;;;WD) ACPI\PNP0303\4&215D0F95&0 : D:P(A;;GA;;;WD) ROOT\MS_AGILEVPNMINIPORT000 : D:P(A;;GA;;;WD) VMBUS\{B6650FF7-33BC-4840-8048-E0676786F393}\5&296C0F0E&0&{B6650FF7-33BC-4840-8048-E0676786F393}: D:P(A;;GA;;;WD) ROOT\LEGACY_MRXSMB000 : D:P(A;;GA;;;WD) IDE\DISKVIRTUAL_HD______________________________1.1.0___\5&35DC7040&0&0.0.0: D:P(A;;GA;;;WD) VMBUS\{2DD1CE17-079E-403C-B352-A1921EE207EE}\5&296C0F0E&0&{2DD1CE17-079E-403C-B352-A1921EE207EE}: D:P(A;;GA;;;WD) ROOT\LEGACY_RDPREFMP000 : D:P(A;;GA;;;WD) ROOT\LEGACY_BEEP000 : D:P(A;;GA;;;WD) STORAGE\VOLUMESNAPSHOT\HARDDISKVOLUMESNAPSHOT1 : D:P(A;;GA;;;WD) ACPI\PNP0501\1 : D:P(A;;GA;;;WD) ROOT\LEGACY_MRXSMB10000 : D:P(A;;GA;;;WD) ROOT\MS_L2TPMINIPORT000 : D:P(A;;GA;;;WD) ROOT\LEGACY_RSPNDR000 : D:P(A;;GA;;;WD) ROOT\LEGACY_BOWSER000 : D:P(A;;GA;;;WD) ACPI\PNP0501\2 : D:P(A;;GA;;;WD) ROOT\LEGACY_MRXSMB20000 : D:P(A;;GA;;;WD) ROOT\MS_NDISWANBH000 : D:P(A;;GA;;;WD) ACPI\PNP0700\4&215D0F95&0 : D:P(A;;GA;;;WD) ROOT\LEGACY_SECDRV000 : D:P(A;;GA;;;WD) ROOT\LEGACY_CLFS000 : D:P(A;;GA;;;WD) STORAGE\VOLUMESNAPSHOT\HARDDISKVOLUMESNAPSHOT2 : D:P(A;;GA;;;WD) ROOT\LEGACY_MSFS000 : D:P(A;;GA;;;WD) ROOT\MS_NDISWANIP000 : D:P(A;;GA;;;WD) PCI\VEN_1414&DEV_5353&SUBSYS_00000000&REV_00\3&267A616A&0&40 : D:P(A;;GA;;;WD) ACPI\PNP0800\4&215D0F95&0 : D:P(A;;GA;;;WD) ROOT\LEGACY_SPLDR000 : D:P(A;;GA;;;WD) ROOT\LEGACY_CNG000 : D:P(A;;GA;;;WD) VMBUS\{FD149E91-82E0-4A7D-AFA6-2A4166CBD7C0}\5&296C0F0E&0&{FD149E91-82E0-4A7D-AFA6-2A4166CBD7C0} : D:P(A;;GA;;;WD) ROOT\LEGACY_MSISADRV000 : D:P(A;;GA;;;WD) VMBUS\{5620E0C7-8062-4DCE-AEB7-520C7EF76171}\5&296C0F0E&0&{5620E0C7-8062-4DCE-AEB7-520C7EF76171} : D:P(A;;GA;;;WD) ROOT\MS_NDISWANIPV6000 : D:P(A;;GA;;;WD) ROOT\LEGACY_SRV000 : D:P(A;;GA;;;WD) ROOT\LEGACY_CSC000 : D:P(A;;GA;;;WD) ACPI\PNP0A03 : D:P(A;;GA;;;WD) SW\{EEAB7790-C514-11D1-B42B-00805FC1270E}\ASYNCMAC : D:P(A;;GA;;;WD) ROOT\LEGACY_MUP000 : D:P(A;;GA;;;WD) ACPI\PNP0B00\4&215D0F95&0 : D:P(A;;GA;;;WD) ROOT\MS_PPPOEMINIPORT000 : D:P(A;;GA;;;WD) ROOT\LEGACY_SRV2000 : D:P(A;;GA;;;WD) ROOT\LEGACY_DFSC000 : D:P(A;;GA;;;WD) PCI\VEN_8086&DEV_7110&SUBSYS_00001414&REV_01\3&267A616A&0&38 : D:P(A;;GA;;;WD) ROOT\LEGACY_NDIS000 : D:P(A;;GA;;;WD) ACPI\PNP0C01\1 : D:P(A;;GA;;;WD) 126 matching device(s) found.

実際、この状態で、Bus Driver に対して、サンプルの Enum.exe を使用して、Toaster Device のインスタンスの追加を行おうとすると、管理者権限でなくても追加ができてしまいます。

Figure01
対して、サンプルの元々の Security Descriptor だと、管理者権限であればアクセスできますが、通常のユーザー権限だと以下のように Access Denied (Error Code : 0x5) となります。

Figure02
このように、デバイス オブジェクトの Security Descriptor は、ドライバー作成者の方々である程度コントロールすることができますし、Setup API を使用すれば、インストール後にも変更することが可能です。しかし、設定の際に、不用意に誰にでもアクセスできるようにしてしまうと、重大なセキュリティホールとなる可能性がありますので、十分ご注意ください。
それでは、また。

[参考]
- Controlling Device Access
<https://msdn.microsoft.com/en-us/library/windows/hardware/ff542063(v=vs.85).aspx>
- Applying Security Descriptors on the Device Object
<https://msdn.microsoft.com/en-us/library/windows/hardware/ff538907(v=vs.85).aspx>
- Creating Secure Device Installations
<https://msdn.microsoft.com/en-us/library/windows/hardware/ff540212(v=vs.85).aspx>
- Setting Device Object Properties in the Registry
<https://msdn.microsoft.com/en-us/library/windows/hardware/ff563750(v=vs.85).aspx>