2010-01-21 13 views
5

Đó là một con trỏ tới một mảng các cấu trúc LSA_UNICODE_STRING. Tôi đã tìm thấy một số mã mà ngược lại, tức là, tạo ra một LSA_UNICODE_STRING từ một chuỗi C#. Bạn có thể thấy điều đó trong phần mã trợ giúp bên dưới.Tôi đã gọi thành công LapiEnumerateAccountRights() của advapi32 từ C#. Bây giờ làm thế nào để tôi unmarshal mảng LSA_UNICODE_STRING nó trả về?

Những gì tôi có và bao gồm cuộc gọi đến LsaEnumerateAccountRights() dường như hoạt động tốt. Các giá trị nhạy cảm được trả về cho con trỏ mảng và cho số đếm.

Tôi không biết làm cách nào để nhận được tại các chuỗi bị vỡ đó. Giúp đỡ xin vui lòng? Khá vui lòng?

CẬP NHẬT: chức năng trợ giúp của nobugz trong câu trả lời dưới đây là ALMOST đúng, bạn chỉ phải chia độ dài cho UnicodeEncoding.CharSize. Nhờ anh ta, bây giờ tôi có thể thấy chuỗi FIRST trong mảng. Xem các cập nhật ở cuối cả hai phần mã bên dưới.

Bây giờ, làm thế nào để làm netherworld con số học?

CẬP NHẬT 2.5: Xem câu trả lời cho mã hoạt động. Tôi đã mất mã cũ, "sai".

+0

liên quan: https://stefsewell.com/2010/10/10/accessing-the-lsa- from-managed-code/Và: http://www.tech-archive.net/Archive/DotNet/microsoft.public.dotnet.framework.interop/2004-11/0394.html –

Trả lời

9

Tìm thấy nó! Trong this blog post. Bây giờ mã sửa đổi dưới đây hoạt động đầy đủ. Nó thậm chí còn an toàn 64-bit!

Mã chính:

IntPtr sid = IntPtr.Zero; 
int sidSize = 0; 
StringBuilder domainName = new StringBuilder(); 
int nameSize = 0; 
int accountType = 0; 

LookupAccountName("\\\\" + tbHost.Text, tbUsername.Text, sid, ref sidSize, 
    domainName, ref nameSize, ref accountType); 
domainName = new StringBuilder(nameSize); 
sid = Marshal.AllocHGlobal(sidSize); 

bool result = LookupAccountName("\\\\" + tbHost.Text, tbUsername.Text, sid, ref sidSize, 
    domainName, ref nameSize, ref accountType); 

myResults.Text += String.Format("LookupAccountName(): Result {0}, SID {1}\n", result, sid); 

LSA_UNICODE_STRING systemName = string2LSAUS("\\\\" + tbHost.Text); 
IntPtr policyHandle = IntPtr.Zero; 
LSA_OBJECT_ATTRIBUTES objAttrs = new LSA_OBJECT_ATTRIBUTES(); 
uint retVal = LsaOpenPolicy(ref systemName, ref objAttrs, 
        POLICY_LOOKUP_NAMES | POLICY_VIEW_LOCAL_INFORMATION, out policyHandle); 

myResults.Text += String.Format("LsaOpenPolicy(): Result {0}, Policy Handle {1}\n", retVal, policyHandle); 

IntPtr rightsArray = IntPtr.Zero; 
ulong rightsCount = 0; 
long lretVal = LsaEnumerateAccountRights(policyHandle, sid, out rightsArray, out rightsCount); 
retVal = LsaNtStatusToWinError(lretVal); 

if (retVal != 0) 
    throw new System.ComponentModel.Win32Exception((int)retVal); 

myResults.Text += String.Format("LsaEnumerateAccountRights(): Result {0}, RightsArray {1}, Count {2}\n", 
    retVal, rightsArray, rightsCount); 

LSA_UNICODE_STRING myLsaus = new LSA_UNICODE_STRING(); 
for (ulong i = 0; i < rightsCount; i++) 
{ 
    IntPtr itemAddr = new IntPtr(rightsArray.ToInt64() + (long)(i * (ulong) Marshal.SizeOf(myLsaus))); 
    myLsaus = (WinNetUtils.LSA_UNICODE_STRING)Marshal.PtrToStructure(itemAddr, myLsaus.GetType()); 
    string thisRight = WinNetUtils.LSAUS2string(myLsaus); 
    NonBlockingPrint(wmiResults, "Right #{0}: {1}\n", i+1, thisRight); 
} 
LsaClose(policyHandle); 

Các chức năng helper, nhập khẩu vv:

public const int POLICY_VIEW_LOCAL_INFORMATION = 0x1; 
public const int POLICY_LOOKUP_NAMES = 0x00000800; 

[DllImport("advapi32.dll", CharSet = CharSet.Unicode, PreserveSig = true)] 
public static extern UInt32 LsaNtStatusToWinError(
    long Status); 

[DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true, PreserveSig = true)] 
public static extern bool ConvertStringSidToSid(
    string StringSid, out IntPtr pSid); 

[DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true, PreserveSig = true)] 
public static extern bool LookupAccountName( 
    string lpSystemName, string lpAccountName, 
    IntPtr psid, ref int cbsid, 
    StringBuilder domainName, ref int cbdomainLength, 
    ref int use); 

[DllImport("advapi32.dll", CharSet = CharSet.Unicode, PreserveSig = true)] 
public static extern UInt32 LsaOpenPolicy(
    ref LSA_UNICODE_STRING SystemName, 
    ref LSA_OBJECT_ATTRIBUTES ObjectAttributes, 
    Int32 DesiredAccess, 
    out IntPtr PolicyHandle); 

[DllImport("advapi32.dll", SetLastError = true, PreserveSig = true)] 
public static extern long LsaEnumerateAccountRights(
    IntPtr PolicyHandle, IntPtr AccountSid, 
    out /* LSA_UNICODE_STRING[] */ IntPtr UserRights, 
    out ulong CountOfRights); 

[DllImport("advapi32.dll", SetLastError = true, PreserveSig = true)] 
public static extern long LsaClose(
      IntPtr PolicyHandle); 

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] 
public struct LSA_UNICODE_STRING 
{ 
    public UInt16 Length; 
    public UInt16 MaximumLength; 
    public IntPtr Buffer; 
} 

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] 
public struct LSA_OBJECT_ATTRIBUTES 
{ 
    public IntPtr RootDirectory; 
    public IntPtr SecurityDescriptor; 
    public IntPtr SecurityQualityOfService; 
    public LSA_UNICODE_STRING ObjectName; 
    public UInt32 Attributes; 
    public UInt32 Length; 
} 

public static LSA_UNICODE_STRING string2LSAUS(string myString) 
{ 
    LSA_UNICODE_STRING retStr = new LSA_UNICODE_STRING(); 
    retStr.Buffer = Marshal.StringToHGlobalUni(myString); 
    retStr.Length = (UInt16)(myString.Length * UnicodeEncoding.CharSize); 
    retStr.MaximumLength = (UInt16)((myString.Length + 1) * UnicodeEncoding.CharSize); 
    return retStr; 
} 

public static string LSAUS2string(LSA_UNICODE_STRING lsaus) 
{ 
    char[] cvt = new char[lsaus.Length/UnicodeEncoding.CharSize]; 
    Marshal.Copy(lsaus.Buffer, cvt, 0, lsaus.Length/UnicodeEncoding.CharSize); 
    return new string(cvt); 
} 
+0

Bạn nên rút câu trả lời của bạn ra khỏi câu hỏi và đặt nó ở đây. –

+0

Ngoài ra, bạn cần phải chắc chắn rằng bạn đang gọi LsaClose() để đóng xử lý. –

+0

Xong và xong. Thật không may, tôi đã mất mã không có chức năng ban đầu, vì vậy câu hỏi có vẻ không hoàn chỉnh. – JCCyC

2

này nên làm việc cho bạn:

private static string LSAUS2String(LSA_UNICODE_STRING lsa) { 
     char[] cvt = new char[lsa.Length]; 
     Marshal.Copy(lsa.Buffer, cvt, 0, lsa.Length); 
     return new string(cvt); 
    } 
+0

Có vẻ như tôi sẽ phải sử dụng Marshal.PtrToStructure() trên mỗi thành viên của mảng, nhưng làm thế nào để tôi đi qua mảng? Số học con trỏ ??? – JCCyC

+0

PtrToStructure? Không, nó là một mảng của Char. Marshal.Copy sao chép nó từ IntPtr đến char []. Sau đó, nó rất dễ dàng. –

+0

Xin lỗi, tôi đã nói về mảng cấp cao hơn, mảng của LSA_UNICODE_STRING. Tôi nhận nó hoạt động ngay bây giờ (xem ở trên). Cảm ơn đã giúp đỡ! – JCCyC

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