Last active
January 21, 2024 17:29
-
-
Save mrh1997/717b14f5783b49ca14310419fa7f03f6 to your computer and use it in GitHub Desktop.
Retrieve Windows Credential via Python
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!python3 | |
""" | |
Access windows credentials | |
""" | |
from typing import Tuple | |
import ctypes as CT | |
import ctypes.wintypes as WT | |
CRED_TYPE_GENERIC = 0x01 | |
LPBYTE = CT.POINTER(WT.BYTE) | |
LPWSTR = WT.LPWSTR | |
LPCWSTR = WT.LPWSTR | |
class CREDENTIAL_ATTRIBUTE(CT.Structure): | |
_fields_ = [ | |
('Keyword', LPWSTR), | |
('Flags', WT.DWORD), | |
('ValueSize', WT.DWORD), | |
('Value', LPBYTE)] | |
PCREDENTIAL_ATTRIBUTE = CT.POINTER(CREDENTIAL_ATTRIBUTE) | |
class CREDENTIAL(CT.Structure): | |
_fields_ = [ | |
('Flags', WT.DWORD), | |
('Type', WT.DWORD), | |
('TargetName', LPWSTR), | |
('Comment', LPWSTR), | |
('LastWritten', WT.FILETIME), | |
('CredentialBlobSize', WT.DWORD), | |
('CredentialBlob', LPBYTE), | |
('Persist', WT.DWORD), | |
('AttributeCount', WT.DWORD), | |
('Attributes', PCREDENTIAL_ATTRIBUTE), | |
('TargetAlias', LPWSTR), | |
('UserName', LPWSTR)] | |
PCREDENTIAL = CT.POINTER(CREDENTIAL) | |
advapi32 = CT.WinDLL('Advapi32.dll') | |
advapi32.CredReadA.restype = WT.BOOL | |
advapi32.CredReadA.argtypes = [LPCWSTR, WT.DWORD, WT.DWORD, CT.POINTER(PCREDENTIAL)] | |
def GetGenericCredential(name:str) -> Tuple[str, str]: | |
""" | |
Returns a Tuple of Name and Password of a Generic Windows Credential | |
Uses bytes in Py3 and str in Py2 for url, name and password. | |
""" | |
cred_ptr = PCREDENTIAL() | |
if advapi32.CredReadW(name, CRED_TYPE_GENERIC, 0, CT.byref(cred_ptr)): | |
username = cred_ptr.contents.UserName | |
cred_blob = cred_ptr.contents.CredentialBlob | |
cred_blob_size = cred_ptr.contents.CredentialBlobSize | |
cred_str = CT.string_at(cred_blob, cred_blob_size) | |
password = cred_str.decode('utf-16le', errors='ignore') | |
advapi32.CredFree(cred_ptr) | |
return username, password | |
else: | |
raise IOError("Failure reading credential") | |
def main(): | |
name, pwd = GetGenericCredential('git:https://github.com') | |
print("GITHUB NAME:", name) | |
print("GITHUB PASSWORD:", pwd) | |
if __name__ == '__main__': | |
main() |
I'm using this script in a node package. See: https://github.com/rolangom/wincred
I used a scarcely modified version of your code, posted here, to allow automating Box.com with Robin, the RPA language.
Works great, thank you!
A little improvement, I think...
import codecs
password = CT.string_at(cred_blob,cred_blob_size).decode('utf-16le', errors='ignore')
@apolkosnik: Thx for this tip. I incorporated it into my code...
Question : how can I get the Windows Session Password using Python ?
Do you mean the current windows users password? I am pretty sure that this is not possible (neither with python nor with C). It would be a big security flaw.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I aligned the code closer to PEP8 and made other things a bit more "pythonic" over at https://gist.github.com/exhuma/a310f927d878b3e5646dc67dfa509b42
In case you agree with the changes, you can merge them back if you like. Unfortunatly it's not possible to do PRs on gists yet.