7

を使用するのはこれが初めてSafeHandleです。

UIntPtr を必要とするこの P/Invoke メソッドを呼び出す必要があります。

    [DllImport("advapi32.dll", CharSet = CharSet.Auto)]
    public static extern int RegOpenKeyEx(
      UIntPtr hKey,
      string subKey,
      int ulOptions,
      int samDesired,
      out UIntPtr hkResult);

この UIntPtr は、.NET の RegistryKey クラスから派生します。上記のメソッドを使用して RegistryKey クラスを IntPtr に変換し、上記の P/Invoke を使用できるようにします。

        private static IntPtr GetRegistryKeyHandle(RegistryKey rKey)
        {
            //Get the type of the RegistryKey
            Type registryKeyType = typeof(RegistryKey);

            //Get the FieldInfo of the 'hkey' member of RegistryKey
            System.Reflection.FieldInfo fieldInfo =
                registryKeyType.GetField("hkey", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);

            //Get the handle held by hkey
            if (fieldInfo != null)
            {
                SafeHandle handle = (SafeHandle)fieldInfo.GetValue(rKey);

                //Get the unsafe handle
                IntPtr dangerousHandle = handle.DangerousGetHandle();                
                return dangerousHandle;
            }
}

質問:

  1. 「安全でない」ハンドルを使用せずにこれを記述するより良い方法はありますか?
  2. アンセーフ ハンドルが危険なのはなぜですか?
4

2 に答える 2

5

RegistryKey にはハンドル プロパティがあります。だからあなたが使うことができます

private static IntPtr GetRegistryKeyHandle(RegistryKey rKey)
{
    return rKey.Handle.DangerousGetHandle();
}

これは潜在的に危険です。取得しているポインタは、使用中に無効になる可能性があるためです。MSDNからの引用

DangerousGetHandle メソッドを使用すると、ハンドルが SetHandleAsInvalid で無効としてマークされている場合でも、DangerousGetHandle は元の古いハンドル値を返す可能性があるため、セキュリティ リスクが生じる可能性があります。返されたハンドルは、いつでもリサイクルできます。せいぜい、これはハンドルが突然機能しなくなる可能性があることを意味します。最悪の場合、ハンドルまたはハンドルが表すリソースが信頼されていないコードに公開されている場合、再利用または返されたハンドルに対するリサイクル セキュリティ攻撃が発生する可能性があります。たとえば、信頼されていない呼び出し元は、返されたばかりのハンドルでデータをクエリし、まったく関係のないリソースの情報を受け取ることができます。DangerousGetHandle メソッドを安全に使用する方法の詳細については、DangerousAddRef および DangerousRelease メソッドを参照してください。

于 2011-12-06T08:20:17.090 に答える
4

あなたがしていることは実際には危険です。使用する RegistryKey オブジェクトは、IntPtr の使用中にガベージ コレクションとファイナライズを取得できます。これにより、ハンドル値が無効になり、コードがランダムに失敗します。そうですね、偶発的な失敗は必ずしも危険ではありませんが、実際にハンドルを長時間保持し続けると、ハンドル リサイクル攻撃への扉が開かれます。ランダムな障害モードは、それについて何かをするように促すのに十分なはずです.

pinvoke 宣言を次のようにします。

[DllImport("advapi32.dll", CharSet=CharSet.Auto)]
internal static extern int RegOpenKeyEx(SafeRegistryHandle key, string subkey, 
    int options, int sam, out SafeRegistryHandle result);

そのため、安全なハンドル ラッパー クラスを一貫して使用できます。それに応じて反射コードを調整します。

于 2011-12-06T12:14:17.537 に答える