2011-12-06 42 views
5

Đây là lần đầu tiên tôi sử dụng SafeHandle.Tại sao SafeHandle.DangerousGetHandle() "Nguy hiểm"?

Tôi cần gọi phương thức P/Invoke này cần có UIntPtr.

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

UIntPtr này sẽ được bắt nguồn từ lớp RegistryKey NET của. Tôi sẽ sử dụng phương pháp trên để chuyển đổi các lớp RegistryKey để một IntPtr vì vậy tôi có thể sử dụng P trên/Gọi:

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

Câu hỏi:

  1. Có cách nào tốt hơn để viết những dòng này mà không sử dụng xử lý "không an toàn"?
  2. Tại sao các tay cầm không an toàn lại nguy hiểm?

Trả lời

3

Điều bạn đang làm thực tế nguy hiểm. Đối tượng RegistryKey bạn sử dụng có thể lấy rác được thu thập và hoàn thành trong khi bạn đang sử dụng IntPtr. Mà làm cho giá trị xử lý không hợp lệ mà làm cho mã của bạn ngẫu nhiên thất bại. Vâng, được rồi, thất bại ngẫu nhiên không phải là chính xác nguy hiểm nhưng nó mở cửa cho một cuộc tấn công xử lý tái chế nếu bạn trong thực tế giữ một nắm giữ của xử lý trong một thời gian dài. Chế độ thất bại ngẫu nhiên phải đủ để truyền cảm hứng cho bạn làm điều gì đó về nó.

Khai pinvoke của bạn trông như thế này:

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

Vì vậy, bạn luôn có thể sử dụng lớp xử lý wrapper an toàn. Điều chỉnh mã phản chiếu tương ứng.

+0

Tôi quên đề cập rằng mục đích của mã của tôi là bắt chước hỗ trợ đăng ký 64-bit của NETFX4. Chúng tôi chỉ sử dụng NETFX 3.5 nên không có SafeRegistryHandle. – Ian

+0

Chỉ cần làm cho nó SafeHandleZeroOrMinusOneIsInvalid, lớp cơ sở của SafeRegistryHandle. Hoặc chỉ đơn giản là SafeHandle nếu bạn ghét gõ tên (người không). –

4

RegistryKey có thuộc tính xử lý. Vì vậy, bạn có thể sử dụng

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

Điều này có thể nguy hiểm, vì con trỏ bạn đang nhận có thể không hợp lệ nữa khi bạn đang sử dụng. Trích dẫn từ MSDN

Sử dụng phương pháp DangerousGetHandle có thể gây ra rủi ro bảo mật bởi vì, nếu xử lý đã được đánh dấu là không hợp lệ với SetHandleAsInvalid, DangerousGetHandle vẫn trả về ban đầu, có khả năng xử lý cũ giá trị. Tay cầm trả về cũng có thể được tái chế tại bất kỳ thời điểm nào. Tốt nhất, điều này có nghĩa là tay cầm có thể đột ngột ngừng hoạt động. Tệ nhất, nếu tay cầm hoặc tài nguyên mà tay cầm đại diện được tiếp xúc với mã không đáng tin cậy, điều này có thể dẫn đến một cuộc tấn công an ninh tái chế trên tay cầm được sử dụng lại hoặc được trả về. Ví dụ, một người gọi không tin cậy có thể truy vấn dữ liệu trên tay cầm vừa trả về và nhận thông tin cho một tài nguyên hoàn toàn không liên quan. Xem các phương thức DangerousAddRef và DangerousRelease để biết thêm thông tin về cách sử dụng các phương thức DangerousGetHandle.

+0

Tôi quên đề cập rằng mục đích của mã của tôi là bắt chước hỗ trợ đăng ký 64-bit của NETFX4. Chúng tôi chỉ sử dụng NETFX 3.5 vì vậy không có thành viên xử lý trong lớp RegistryKey. – Ian

Các vấn đề liên quan