帮助CredEnumerate

时间:2008-10-31 21:12:34

标签: c# windows security winapi

作为this问题的后续问题,我希望有人可以帮助CredEnumerate API。

据我从文档中了解,PCREDENTIALS out参数是“指向凭证指针数组的指针”。我能够使用C#成功调用CredEnumerate API,但我不知道如何将PCREDENTIALS转换为有用的东西(如证书列表)。

编辑:这是我正在使用的代码:

        int count = 0;
        IntPtr pCredentials = IntPtr.Zero;
        bool ret = false;
        ret = CredEnumerate(null, 0, out count, out pCredentials);
        if (ret != false)
        {
            IntPtr[] credentials = new IntPtr[count];
            IntPtr p = pCredentials;
            for (int i = 0; i < count; i++)
            {
                p = new IntPtr(p.ToInt32() + i);
                credentials[i] = Marshal.ReadIntPtr(p);
            }
            List<Credential> creds = new List<Credential>(credentials.Length);
            foreach (IntPtr ptr in credentials)
            {
                creds.Add((Credential)Marshal.PtrToStructure(ptr, typeof(Credential)));
            }
        }

不幸的是,虽然这适用于数组中的第一个凭证 - 它会生成并正确地添加到列表中 - 后续数组项会在Marshal.PtrToStructure中炸弹,并出现以下错误:

尝试读取或写入受保护的内存。这通常表明其他内存已损坏。

有什么想法吗?任何人? Bueller?

2 个答案:

答案 0 :(得分:5)

您需要取消引用指向数组的指针才能获取数组,然后对于数组中的每个项目,您需要取消引用该项以获取PCREDENTIALS实例。

我找到this post with some example code来执行您要执行的操作:

[DllImport("advapi32", SetLastError = true, CharSet=CharSet.Unicode)]
static extern bool CredEnumerate(string filter, int flag, out int count, out IntPtr
pCredentials);

...

int count = 0;
IntPtr pCredentials = IntPtr.Zero;
IntPtr[] credentials = null;
bool ret = CredEnumerate(null, 0, out count, out pCredentials);
if (ret != false)
{
    credentials = new IntPtr[count];
    IntPtr p = pCredentials;
    for (int n = 0; n < count; n++)
    {
        credentials[n] = Marshal.ReadIntPtr(pCredentials,
           n * Marshal.SizeOf(typeof(IntPtr)));
    }
} 
else
// failed....

然后对于每个指针,您需要使用Marshal.PtrToStructure将指针解引用到PCREDENTIALS结构实例(抱歉,我无法在任何地方找到PCREDENTIALS的typedef,我会假设你有它 - 如果你确实没有忘记正确的MarshalAs属性和StructLayout属性你定义它:)

// assuming you have declared struct PCREDENTIALS
var creds = new List<PCREDENTIALS>(credentials.Length);
foreach (var ptr in credentials)
{
    creds.Add((PCREDENTIALS)Marshal.PtrToStructure(ptr, typeof(PCREDENTIALS)));
}

您显然希望将示例和PtrToStructure代码结合起来以获得最佳结果,但我希望保持示例的完整性。

答案 1 :(得分:1)

你还需要正确地计算'IntPtr p'上面的代码,并且它只会获取第一个结构。

以下代码将获取“IntPtr pCredentials”

中的所有结构
int count;
IntPtr pCredentials;

if (CredEnumerate(filter, 0, out count, out pCredentials) != 0)
{
    m_list = new List<PCREDENTIALS >(count);
    int sz = Marshal.SizeOf(pCredentials);

    for (int index = 0; index < count; index++)
    {
        IntPtr p = new IntPtr((sz == 4 ? pCredentials.ToInt32() : pCredentials.ToInt64()) + index * sz);
        m_list.Add((PCREDENTIALS)Marshal.PtrToStructure(p, typeof(PCREDENTIALS)));
    }
}