首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >JNA中的Windows CredEnumerate

JNA中的Windows CredEnumerate
EN

Stack Overflow用户
提问于 2015-11-17 18:12:38
回答 1查看 918关注 0票数 2

我正在尝试使用JNA读取存储在Windows凭据管理器(控制面板>凭据管理器)中的凭据。找到了它的c函数(CredEnumerateW似乎运行正常,因为它返回"true“,并且我能够在我的代码中获得凭证管理器(pCount.getValue() )中存储的凭证数量)。

问题是我不知道如何读取凭证数据。保存凭据的结构(_CREDENTIAL内部包含另外两个结构(FILETIME和CREDENTIAL_ATTRIBUTE)。我试图搜索类似的示例,但找不到与我的场景匹配的示例。请看我下面的代码。

有人能帮我解决这个问题吗?

代码语言:javascript
复制
public class CredEnumerate {

        /*
        typedef struct _CREDENTIAL {
              DWORD                 Flags;
              DWORD                 Type;
              LPTSTR                TargetName;
              LPTSTR                Comment;
              FILETIME              LastWritten;
              DWORD                 CredentialBlobSize;
              LPBYTE                CredentialBlob;
              DWORD                 Persist;
              DWORD                 AttributeCount;
              PCREDENTIAL_ATTRIBUTE Attributes;
              LPTSTR                TargetAlias;
              LPTSTR                UserName;
            } CREDENTIAL, *PCREDENTIAL; */
        public static class _CREDENTIAL extends Structure {
            public int                      Flags;
            public int                      Type;
            public String                   TargetName;
            public String                   Comment;
            public _FILETIME                LastWritten = new _FILETIME();
            public int                      CredentialBlobSize;
            public byte                     CredentialBlob;
            public  int                     Persist;
            public int                      AttributeCount;
            public _CREDENTIAL_ATTRIBUTE    Attributes = new _CREDENTIAL_ATTRIBUTE();
            public String                   TargetAlias;
            public String                   UserName;
        }

        /*
        typedef struct _CREDENTIAL_ATTRIBUTE {
              LPTSTR Keyword;
              DWORD  Flags;
              DWORD  ValueSize;
              LPBYTE Value;
                } CREDENTIAL_ATTRIBUTE, *PCREDENTIAL_ATTRIBUTE; */
        public static class _CREDENTIAL_ATTRIBUTE extends Structure {
            public String Keyword;
            public int  Flags;
            public int  ValueSize;
            public byte Value;
        }

        /*
        typedef struct _FILETIME {
              DWORD dwLowDateTime;
              DWORD dwHighDateTime;
            } FILETIME, *PFILETIME; */
        public static class _FILETIME extends Structure {
            public int dwLowDateTime;
            public int dwHighDateTime;
        }

        /*
        BOOL CredEnumerate( 
            _In_  LPCTSTR     Filter,
            _In_  DWORD       Flags,
            _Out_ DWORD       *Count,
            _Out_ PCREDENTIAL **Credentials) */ 
        public interface Advapi32 extends StdCallLibrary {
            Advapi32 INSTANCE = (Advapi32) Native.loadLibrary("advapi32", Advapi32.class);      
            boolean CredEnumerateW(String filter, int flags, IntByReference count, PointerByReference pref);
        }

        public static void main(String[] args) {

            IntByReference pCount = new IntByReference();
            PointerByReference pCredentials = new PointerByReference();     
            boolean result = Advapi32.INSTANCE.CredEnumerateW(null, 0, pCount, pCredentials);

            System.out.println("result: " + result);
            System.out.println("number of credentials: " +  pCount.getValue()); 

            //how to read the _CREDENTIAL structure data from pCredentials?

        }

    }
EN

回答 1

Stack Overflow用户

发布于 2020-08-15 22:51:05

对我来说,指针数组,也就是指向指针的指针,是使用CredEnumerate时唯一棘手的事情。这个问题已经用p.getPointerArray解决了。

使用Win32函数CredEnumerateW的声明

代码语言:javascript
复制
boolean CredEnumerateW(WString Filter, int Flags, IntByReference Count, // int ref
            PointerByReference pptr);

我的解决方案如下所示:

代码语言:javascript
复制
try {
    IntByReference count = new IntByReference();
    PointerByReference pptr = new PointerByReference();
    boolean ok = WinCrypt.INSTANCE.CredEnumerateW(null, WinCrypt.Enumerate.CRED_ENUMERATE_ALL_CREDENTIALS,
    count, pptr);
    System.out.println("count: " + count.getValue());

    CREDENTIAL[] credentials = new CREDENTIAL[count.getValue()];

    Pointer p = pptr.getValue();
    Pointer[] credPointers = p.getPointerArray(0, count.getValue());

    for (int i = 0; i < count.getValue(); i++) {
        CREDENTIAL cred = new CREDENTIAL(credPointers[i]);
        credentials[i] = cred;

        String tnameEncoded = cred.targetName.toString();
        String namespace = tnameEncoded.substring(0, tnameEncoded.indexOf(":"));
        String attributeAndTargetName = tnameEncoded.substring(tnameEncoded.indexOf(":") + 1);
        String targetName = attributeAndTargetName.substring(attributeAndTargetName.indexOf("=") + 1);

        System.out.println(namespace + " / " + targetName);

        if (namespace.indexOf("MicrosoftAccount") < 0 && namespace.indexOf("WindowsLive") < 0) {
    CREDENTIAL fullcred = readCredentials(targetName, getType(namespace), 0);
    System.out.println("  " + cred.userName);
    System.out.println("  " + fullcred.getPassword());
        }
    }

} catch (LastErrorException error) {
    int rc = error.getErrorCode();
    String errMsg = error.getMessage();
    System.out.println(rc + ": " + errMsg);
    System.exit(1);

}

并且从指针地址读取凭证被实现为

代码语言:javascript
复制
private static CREDENTIAL readCredentials(String targetName, int type, int flags)
throws UnsupportedEncodingException {
    try {
        PointerByReference pptr = new PointerByReference();
        boolean ok = WinCrypt.INSTANCE.CredReadW(new WString(targetName), type, flags, pptr);
        CREDENTIAL cred = new CREDENTIAL(pptr.getValue());

        return (cred);
    } catch (LastErrorException error) {
        int rc = error.getErrorCode();
        String errMsg = error.getMessage();
        System.out.println(rc + ": " + errMsg);
        throw new IllegalAccessError("cannot access windows vault for " + targetName);
    }
}

有关使用Win32 credentials API读取/写入凭据的基本信息,请参阅How to map Windows API CredWrite/CredRead in JNA?

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/33754249

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档