2011-12-06 83 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類派生。我將使用上述方法來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. 爲什麼不安全的手柄是危險的?

回答

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

只需使SafeHandleZeroOrMinusOneIsInvalid成爲SafeRegistryHandle的基類即可。或者如果你討厭輸入名字(誰沒有),那麼只是簡單的SafeHandle。 –

4

RegistryKey具有句柄屬性。所以,你可以當你使用它使用

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

這是潛在的危險,因爲你所得到的指針可能不再有效。引自MSDN

使用DangerousGetHandle方法可能會帶來安全風險,因爲,如果手柄已經打上SetHandleAsInvalid爲無效,DangerousGetHandle仍返回原來的,有可能失效的句柄值。返回的手柄也可以隨時回收。充其量,這意味着手柄可能突然停止工作。在最壞的情況下,如果句柄表示的句柄或資源暴露給不可信的代碼,這可能會導致對重用或返回句柄的再循環安全性攻擊。例如,不受信任的調用方可以查詢剛剛返回的句柄上的數據,並接收完全不相關的資源的信息。有關使用DangerousGetHandle方法的更多信息,請參閱DangerousAddRef和DangerousRelease方法。

+0

我忘了提及我的代碼的目的是模仿NETFX4的64位註冊表支持。我們只使用NETFX 3.5,因此RegistryKey類中沒有Handle成員。 – Ian