Jump to content

Recommended Posts

Posted (edited)

Hi –

I’m currently working on a little project to write to/read from Window Credential Manager. I implemented successfully DllCalls 'CredWriteW', 'CredReadW', 'CredEnumerateW' and 'CredDeleteW' – (at least) with the help from this forum :)

The functions 'CredWriteW', 'CredReadW' have the ability to write/read attributes (up to 64) – the DLL structure for both is ( https://docs.microsoft.com/en-us/windows/desktop/api/wincred/ns-wincred-credentialw/ ):

typedef struct _CREDENTIALA {
  DWORD                  Flags;
  DWORD                  Type;
  LPSTR                  TargetName;
  LPSTR                  Comment;
  FILETIME               LastWritten;
  DWORD                  CredentialBlobSize;
  LPBYTE                 CredentialBlob;
  DWORD                  Persist;
  DWORD                  AttributeCount;
  PCREDENTIAL_ATTRIBUTEA Attributes;
  LPSTR                  TargetAlias;
  LPSTR                  UserName;
} CREDENTIALA, *PCREDENTIALA;

The structure (= PCREDENTIAL_ATTRIBUTEA) to write (read?) attributes is ( https://docs.microsoft.com/en-us/windows/desktop/api/wincred/ns-wincred-credential_attributea/ ):

typedef struct _CREDENTIAL_ATTRIBUTEA {
  LPSTR  Keyword;
  DWORD  Flags;
  DWORD  ValueSize;
  LPBYTE Value;
} CREDENTIAL_ATTRIBUTEA, *PCREDENTIAL_ATTRIBUTEA;

The structure constants I definied:

Global Const $tagCREDENTIAL_ATTRIBUTEA = _
        "PTR Keyword;" & _
        "DWORD Flags;" & _
        "DWORD ValueSize;" & _
        "PTR Value;"

Global Const $tagCREDENTIALA = _
        "DWORD Flags;" & _
        "DWORD Type;" & _
        "PTR TargetName;" & _
        "PTR Comment;" & _
        "DWORD LastWritten[2];" & _ ; Coordinated Universal Time (Greenwich Mean Time).
        "DWORD CredentialBlobSize;" & _
        "PTR CredentialBlob;" & _
        "DWORD Persist;" & _
        "DWORD AttributeCount;" & _
        "PTR Attributes;" & _
        "PTR TargetAlias;" & _
        "PTR UserName;"

My attempt to write attributes:

; Some code above...

Local $aTmp[3]

; Writing attribute count:
DllStructSetData($tCREDENTIALA, "AttributeCount", UBound($aTmp)

Local $sTmp = "Some text as test data."
Local $tTmp1 = 0
Local $tTmp2 = 0

For $i = 0 To UBound($aTmp) - 1
    
    $aTmp[$i] = DllStructCreate($tagCREDENTIAL_ATTRIBUTEA)
    
    ; Writing keyword:
    $tTmp1 = DllStructCreate("WCHAR[100];")
    DllStructSetData($tTmp1, 1, StringLeft("Keyword_" & $i, 256))
    DllStructSetData($aTmp[$i], "Keyword", DllStructGetPtr($tTmp1))
    $tTmp1 = 0

    ; Writing flags:
    DllStructSetData($aTmp[$i], "Flags", 0)

    ; Writing value size:
    DllStructSetData($aTmp[$i], "ValueSize", StringLen($sTmp) * 2)

    ; Writing value:
    $tTmp2 = DllStructCreate("WCHAR[100];")
    DllStructSetData($tTmp2, 1, $sTmp)
    DllStructSetData($aTmp[$i], "Value", DllStructGetPtr($tTmp2))
    $tTmp2 = 0
    
    ; Writing attributes:
    DllStructSetData($tCREDENTIALA, "Attributes", DllStructGetPtr($aTmp[$i]))

Next

; Some code below...

Here's something wrong - obvious :shifty: As far as I understand writing to/reading from attributes is accessing "a structure in a structure". Feeding the structure $tagCREDENTIAL_ATTRIBUTEA seems to work - but how to store it/them in $tagCREDENTIALA correctly (index by index)?

My attempt to read attributes:

; Some code above...

Local $tDummy = DllStructCreate("WCHAR[100];")
DllStructSetData($tDummy, 1, $sTargetName)
Local $aResult = DllCall($hADVAPI32_DLL, "BOOL", "CredReadW", "PTR", DllStructGetPtr($tDummy), "DWORD", 1, "DWORD", 0, "PTR*", 0) ; CRED_TYPE_GENERIC

; Some code between...

Local $tCREDENTIAL_ATTRIBUTEA = DllStructCreate($tagCREDENTIAL_ATTRIBUTEA, $aResult[4])
If (Not @error) Then

    ConsoleWrite(StringFormat("___%s\r\n___%s\r\n___%s\r\n___%s\r\n", _
            DllStructGetData($tCREDENTIAL_ATTRIBUTEA, 1), _
            DllStructGetData($tCREDENTIAL_ATTRIBUTEA, 2), _
            DllStructGetData($tCREDENTIAL_ATTRIBUTEA, 3), _
            DllStructGetData($tCREDENTIAL_ATTRIBUTEA, 4)))

    $tCREDENTIAL_ATTRIBUTEA = 0 ; !!!
EndIf

; Some code below...

If reading from structure $tagCREDENTIAL_ATTRIBUTEA "something" is returned - but not the data once written... I guess I have to address the indexes...!? How??

Anyone having a clue how to do it right?

 

Edited by supersonic
Posted
Global Const $tagCREDENTIAL_ATTRIBUTEA = _
        "PTR Keyword;" & _
        "DWORD Flags1;" & _
        "DWORD ValueSize;" & _
        "PTR Value;"

Global Const $tagCREDENTIALA = _
        "DWORD Flags2;" & _
        "DWORD Type;" & _
        "PTR TargetName;" & _
        "PTR Comment;" & _
        "DWORD LastWritten[2];" & _ ; Coordinated Universal Time (Greenwich Mean Time).
        "DWORD CredentialBlobSize;" & _
        "PTR CredentialBlob;" & _
        "DWORD Persist;" & _
        "DWORD AttributeCount;" & _
        $tagCREDENTIAL_ATTRIBUTEA & _
        "PTR TargetAlias;" & _
        "PTR UserName;"

Try this

Posted

Thank you - I already have. As far as I understand a pointer must be used?? Furthermore an "index" must also be addressed - somehow... The structure $tagCREDENTIAL_ATTRIBUTEA can store *one* attribute, but there can be up to 64...

Posted

It doesn't say it is a pointer.  The way I read the definition it is a sequence of structures inside the structure.  For 3 attribute count I would try :

Global Const $tagCREDENTIALA = _
        "DWORD Flags2;" & _
        "DWORD Type;" & _
        "PTR TargetName;" & _
        "PTR Comment;" & _
        "DWORD LastWritten[2];" & _ ; Coordinated Universal Time (Greenwich Mean Time).
        "DWORD CredentialBlobSize;" & _
        "PTR CredentialBlob;" & _
        "DWORD Persist;" & _
        "DWORD AttributeCount;" & _
        $tagCREDENTIAL_ATTRIBUTEA & _
        $tagCREDENTIAL_ATTRIBUTEA & _
        $tagCREDENTIAL_ATTRIBUTEA & _
        "PTR TargetAlias;" & _
        "PTR UserName;"

 

Posted

Ahh... I will give it a try!

Am I right in assuming that - for writing a credential - I have to "pre-build" $tagCREDENTIALA depending on how many attributes I like to store with a credential?

This also applies for reading a cred. containing 1+ attribute(s)?

Posted (edited)

I tried to build a "sequence of structures inside the structure" to write one attribute - it fails :(

Here's a reproducer:

#include <Array.au3>

Global Const $tagCREDENTIAL_ATTRIBUTEA = _
        "PTR KeywordA;" & _
        "DWORD FlagsA;" & _
        "DWORD ValueSizeA;" & _
        "PTR ValueA;"

Global Const $tagCREDENTIALA = _
        "DWORD Flags;" & _
        "DWORD Type;" & _
        "PTR TargetName;" & _
        "PTR Comment;" & _
        "DWORD LastWritten[2];" & _
        "DWORD CredentialBlobSize;" & _
        "PTR CredentialBlob;" & _
        "DWORD Persist;" & _
        "DWORD AttributeCount;" & _
        $tagCREDENTIAL_ATTRIBUTEA & _
        "PTR TargetAlias;" & _
        "PTR UserName;"

Local $aTDummy[] = [DllStructCreate("WCHAR[100];"), DllStructCreate("WCHAR[100];"), DllStructCreate("WCHAR[100];")]
Local $sUserName = "SomeUserName"
Local $sPassword = "SomePassword"
Local $sTargetName = "___" & @ComputerName
DllStructSetData($aTDummy[0], 1, $sUserName)
DllStructSetData($aTDummy[1], 1, $sPassword)
DllStructSetData($aTDummy[2], 1, $sTargetName)

Local $tCREDENTIALA = DllStructCreate($tagCREDENTIALA)
DllStructSetData($tCREDENTIALA, "Flags", 0)
DllStructSetData($tCREDENTIALA, "Type", 1) ; CRED_FLAGS_DEFAULT
DllStructSetData($tCREDENTIALA, "TargetName", DllStructGetPtr($aTDummy[2]))
DllStructSetData($tCREDENTIALA, "CredentialBlobSize", (StringLen($sPassword) * 2) + 2)
DllStructSetData($tCREDENTIALA, "CredentialBlob", DllStructGetPtr($aTDummy[1]))
DllStructSetData($tCREDENTIALA, "Persist", 1) ; CRED_PERSIST_SESSION

    ; Writing an attribute: ------------------------------------------------------------------------------
    DllStructSetData($tCREDENTIALA, "AttributeCount", 1)

    Local $sTmp = "Some text as test data."

    Local $tTmp1 = DllStructCreate("WCHAR[100];")
    DllStructSetData($tTmp1, 1, $sTmp)
    DllStructSetData($tCREDENTIALA, "KeywordA", DllStructGetPtr($tTmp1))

    DllStructSetData($tCREDENTIALA, "FlagsA", 0)
    DllStructSetData($tCREDENTIALA, "ValueSizeA", StringLen($sTmp) * 2)

    Local $tTmp2 = DllStructCreate("WCHAR[100];")
    DllStructSetData($tTmp2, 1, $sTmp)
    DllStructSetData($tCREDENTIALA, "ValueA", DllStructGetPtr($tTmp2))
    ; ----------------------------------------------------------------------------------------------------

DllStructSetData($tCREDENTIALA, "UserName", DllStructGetPtr($aTDummy[0]))

Local $aResult = DllCall("advapi32.dll", "BOOL", "CredWriteW", "PTR", DllStructGetPtr($tCREDENTIALA), "DWORD", 0)
_ArrayDisplay($aResult)

Already DllStructSetData($tCREDENTIALA, "AttributeCount", 1)  fails.

If I commented out the "Writing an attribute"-section it works.

Any help greatly appreciated...

Edited by supersonic
Posted (edited)

I am still investigating my issue (= writing/reading attributes) - still no luck finding a useful solution... :(

What I have found out so far -

TEST 1 --- Using this structures:

Global Const $tagCREDENTIAL_ATTRIBUTEA = _
        "PTR Keyword;" & _
        "DWORD Flags;" & _
        "DWORD ValueSize;" & _
        "PTR Value;"
Global Const $tagCREDENTIALA = _
        "DWORD Flags;" & _
        "DWORD Type;" & _
        "PTR TargetName;" & _
        "PTR Comment;" & _
        "DWORD LastWritten[2];" & _ ; Coordinated Universal Time (Greenwich Mean Time).
        "DWORD CredentialBlobSize;" & _
        "PTR CredentialBlob;" & _
        "DWORD Persist;" & _
        "DWORD AttributeCount;" & _
        "PTR Attributes;" & _ ; To be feeded by '$tagCREDENTIAL_ATTRIBUTEA'.
        "PTR TargetAlias;" & _
        "PTR UserName;"

... will return this output via _WinAPI_DisplayStruct:

image.png.fb7a6659119aae4f2209ca3f14e67a3e.png

... and a credential with one attribute is actually stored. Currently I am not able to store more than one attribute.

TEST 2 --- Using this structures (as suggested by forum member Nine):

Global Const $tagCREDENTIAL_ATTRIBUTEA = _
        "STRUCT;" & _
        "PTR Keyword;" & _
        "DWORD Flags;" & _
        "DWORD ValueSize;" & _
        "PTR Value;" & _
        "ENDSTRUCT;"

Global Const $tagCREDENTIALA = _
        "DWORD Flags;" & _
        "DWORD Type;" & _
        "PTR TargetName;" & _
        "PTR Comment;" & _
        "DWORD LastWritten[2];" & _
        "DWORD CredentialBlobSize;" & _
        "PTR CredentialBlob;" & _
        "DWORD Persist;" & _
        "DWORD AttributeCount;" & _
        $tagCREDENTIAL_ATTRIBUTEA & _ ; To be repeated for each attribute.
        "PTR TargetAlias;" & _
        "PTR UserName;"

... will return this output via _WinAPI_DisplayStruct:

image.png.c657d1633218192356211700cdc5e902.png

... and NO credential will be stored.

Still: Any help greatly appreciated...

Edited by supersonic
Posted

Thank you - I know about this thread, unfortunately there is nothing new (at least for me) regarding writing attributes. Or have I missed something?

I wish someone has a clue...

Posted

Hello. 

1.- You will use wide api call so use W in tag's structure declaration so it will be a good practices.

2.- Correct declaration for the structure would be this:

Global Const $tagCREDENTIAL_ATTRIBUTEW = _
        "PTR Keyword;" & _
        "DWORD Flags;" & _
        "DWORD ValueSize;" & _
        "PTR Value;"

Global Const $tagCREDENTIALW = _
        "DWORD Flags;" & _
        "DWORD Type;" & _
        "PTR TargetName;" & _
        "PTR Comment;" & _
        "DWORD LastWritten[2];" & _
        "DWORD CredentialBlobSize;" & _
        "PTR CredentialBlob;" & _
        "DWORD Persist;" & _
        "DWORD AttributeCount;" & _
        "PTR pCredentialAttribute;" & _
        "PTR TargetAlias;" & _
        "PTR UserName;"

3.-About usage I'll write an example when I got some free time.

 

Saludos

Posted

@Danyfirex -- I am totally confused and mixed up everything - i definitely need some help. :blink: So, if your time allows to show how to write/read attributes this would be great...

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...