解密Windows凭据文件

时间:2015-07-13 13:17:39

标签: c# c++ delphi winapi

我正在进入一个需要管理(写/读)缓存凭据的项目。就我而言,特别是(TERMSRV)或流行的远程桌面。

在我的Windows 7上,我发现文件存储在“AppData \ Local \ Microsoft \ Credentials”中。当我打开mstsc(远程桌面客户端)并保存凭证时,会在此目录上创建一个新文件(隐藏并受系统保护)。我试着在记事本上打开文件,它是加密数据。就我所看到的,看起来像Windows使用Data Protection API(DPAPI),特别是CryptProtectData / CryptUnprotectData函数来保存/检索缓存的凭据。

我的第一次尝试是在CredRead函数上,但我发现域密码(CRED_TYPE_DOMAIN_PASSWORD - 完全是终端服务的类型)只能由身份验证包读取。在发现之后,我开始搜索一些工具,我发现有些人正在将一个DLL注入LSASS进程,以完成这项工作。但是我看到Nirsoft NetPass成功解密了我保存的密码,并且通过Process Explorer,我没有在LSASS上看到任何新的DLL注入。看起来他使用CryptUnprotectData直接在凭证文件上工作。

问题是:无论如何从这个文件中检索缓存的密码,而不需要注入dll并执行此类操作?如果是,那么CryptUnprotectData的方式是什么?最后,如果是,那么函数接收的DATA_BLOB是什么?文件的内容?我只是无法理解如何使用该功能,从哪里获取blob?

修改::

我仅在Windows / WinAPI标签上发布此问题,但几乎没有视图,也没有答案。我相信主要的问题,是语言无关,但我在Delphi中做项目,所以这里是CredRead的Delphi代码,它只获取用户名,但无法列出密码,因为该帐户是域类型(CRED_TYPE_DOMAIN_PASSWORD)

type
 PCREDENTIAL_ATTRIBUTEW = ^_CREDENTIAL_ATTRIBUTEW;
  _CREDENTIAL_ATTRIBUTEW = record
    Keyword: LPWSTR;
    Flags: DWORD;
    ValueSize: DWORD;
    Value: LPBYTE;
  end;


  PCREDENTIALW = ^_CREDENTIALW;
  _CREDENTIALW = record
    Flags: DWORD;
    Type_: DWORD;
    TargetName: LPWSTR;
    Comment: LPWSTR;
    LastWritten: FILETIME;
    CredentialBlobSize: DWORD;
    CredentialBlob: LPBYTE;
    Persist: DWORD;
    AttributeCount: DWORD;
    Attributes: PCREDENTIAL_ATTRIBUTEW;
    TargetAlias: LPWSTR;
    UserName: LPWSTR;
  end;

PCredentialArray = array of PCREDENTIALW;

const
  CRED_TYPE_GENERIC                 = 1;
  CRED_TYPE_DOMAIN_PASSWORD         = 2;
  CRED_TYPE_DOMAIN_CERTIFICATE      = 3;
  CRED_TYPE_DOMAIN_VISIBLE_PASSWORD = 4;
  CRED_TYPE_MAXIMUM                 = 5;  // Maximum supported cred type
  CRED_TYPE_MAXIMUM_EX              = CRED_TYPE_MAXIMUM + 1000;  // Allow new applications to run on old OSes

var
  Form1: TForm1;

function CredReadW(TargetName: LPCWSTR; Type_: DWORD; Flags: DWORD; var Credential: PCREDENTIALW): BOOL; stdcall; external 'advapi32.dll';
function CredEnumerateW(Filter: LPCWSTR; Flags: DWORD; out Count: DWORD; out Credential: PCredentialArray): BOOL; stdcall; external 'advapi32.dll';

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
var
  Credentials: PCredentialArray;
  Credential: PCREDENTIALW;
  UserName: WideString;
  i: integer;
  dwCount: DWORD;
begin
    if CredEnumerateW(PChar('TERM*'), 0, dwCount, Credentials) then
    begin
      for i:= 0 to dwCount - 1  do
        begin
            if CredReadW(Credentials[i].TargetName, Credentials[i].Type_, 0, Credential) then
            begin
              UserName:= Credential.UserName;
              Memo1.Lines.Add(Credentials[i].TargetName + ' :: ' + UserName + ' >> ' + IntToStr(Credentials[i].Type_));
              Memo1.Lines.Add(IntToStr(Credential.CredentialBlobSize));
            end;
        end;
    end;
end;

0 个答案:

没有答案