2011-12-06 26 views
5

初めてSafeHandleを使用します。SafeHandle.DangerousGetHandle()はなぜ危険なのですか?

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クラスから派生されます。使用せずにこれを書くためのより良い方法はあり

  1.  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; 
          } 
    } 
    

    質問:私は、私は上記のP /呼び出しを使用することができるのIntPtrへのRegistryKeyクラスを変換するために、上記の方法を使用することになります「安全でない」ハンドル?

  2. なぜ安全でないハンドルは危険ですか?

答えて

3

あなたがやっていることは実際には危険です。使用している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); 

ですから、一貫安全なハンドルラッパークラスを使用することができます。それに応じてリフレクションコードを調整します。

+0

私のコードの目的は、NETFX4の64ビットレジストリサポートを模倣することであることを忘れてしまいました。私たちはNETFX 3.5しか使用していないので、SafeRegistryHandleは利用できません。 – Ian

+0

SafeRandryHandleの基本クラスSafeHandleZeroOrMinusOneIsInvalidにします。あなたが名前を入力することを嫌うならば、SafeHandleを単なる普通のもの(誰もいない)。 –

4

レジストリキーにはハンドルプロパティがあります。あなたがそれを使用しているときに取得しているポインタは、もはや有効ではないかもしれないので、だから、

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

を使用することができますこれは、潜在的に危険です。ハンドルはSetHandleAsInvalidで無効としてマークされている場合は、DangerousGetHandleはまだ元の、潜在的に古いハンドル値を返すため、セキュリティ上のリスクをもたらす可能性がDangerousGetHandleメソッドを使用してMSDN

からの引用。返されたハンドルは、いつでもリサイクルすることができます。せいぜい、これはハンドルが突然動作を停止する可能性があることを意味します。最悪の場合、ハンドルまたはハンドルが表すリソースが信頼できないコードにさらされている場合、これは再利用または返されたハンドルのリサイクルセキュリティ攻撃につながります。たとえば、信頼されていない呼び出し元は、返されたばかりのハンドルのデータを照会して、まったく関係のないリソースに関する情報を受け取ることができます。 DangerousGetHandleメソッドの詳細については、DangerousAddRefメソッドとDangerousReleaseメソッドを参照してください。

+0

私のコードの目的は、NETFX4の64ビットレジストリサポートを模倣することです。 NETFX 3.5のみを使用しているため、RegistryKeyクラスにHandleメンバーはありません。 – Ian

関連する問題