【Delphi】RDP文件中的密码Hash加解密单元

来源:互联网 发布:工程套价软件 编辑:程序博客网 时间:2024/06/11 18:04
RDP文件是微软远程桌面工具mstsc.exe用来记录登录信息的文件。有了RDP文件就可以方便的进行远程桌面连接
RDP文件中,密码需要加密后才可以使用。
这个单元实现了密码的加解密。注意要先安装JwAPI

JwAPI的SVN地址:https://jedi-apilib.svn.sourceforge.net/svnroot/jedi-apilib/jwapi/trunk

{******************************************************************}{ Author: Remko Weijnen (r dot weijnen at gmail dot com)           }{ Version: 0.1                                                     }{ Date: 21-03-2007                                                 }{                                                                  }{ The contents of this file are subject to                         }{ the Mozilla Public License Version 1.1 (the "License"); you may  }{ not use this file except in compliance with the License. You may }{ obtain a copy of the License at                                  }{ http://www.mozilla.org/MPL/MPL-1.1.html                          }{                                                                  }{ Software distributed under the License is distributed on an      }{ "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or   }{ implied. See the License for the specific language governing     }{ rights and limitations under the License.                        }{******************************************************************}unit RDPHash;interfaceuses  Windows, Sysutils, JwaWinCrypt;function CryptRDPPassword(sPassword: string): string;function DecryptRDPPassword(sPasswordHash: string): string;function BlobDataToHexStr(P: PByte; I: Integer): string;function PasswordHashToBlobData(sPasswordHash: string): DATA_BLOB;implementation{***********************************************************}{ HexToByte: Converts Hex value to Byte                     }{ Found this somewhere on the internet                      }{***********************************************************}function HexToByte(s : String): Byte;const  cs = '0123456789ABCDEF';begin  result := 0;  if (length(s) = 2) and     //(s[1] in ['0'..'9','A'..'F']) and     CharInSet(s[1], ['0'..'9','A'..'F']) and     //(s[2] in ['0'..'9','A'..'F']) then     CharInSet(s[2], ['0'..'9','A'..'F']) then    result := ((pos(s[1],cs)-1) *16) + (pos(s[2],cs)-1)  else raise EConvertError.CreateFmt('%s is not a Hexformatstring',[s]);end;{***********************************************************}{ PasswordHashToBlobData: Converts a RDP password Hash to   }{                         a DATA_BLOB structure             }{ sPasswordHash : RDP Password Hash (HEX String             }{***********************************************************}function PasswordHashToBlobData(sPasswordHash: string): DATA_BLOB;var Buf: array of Byte;  dwBufSize: Cardinal;  i: Cardinal;  j: Cardinal;  dwHashSize: Cardinal;begin  dwBufSize := Length(sPassWordHash) DIV 2;  dwHashSize := Length(sPasswordHash);  SetLength(Buf, dwBufSize);  i := 1;  j := 0;  while i < dwHashSize do begin    Buf[j] := HexToByte(sPassWordHash[i] + sPassWordHash[i+1]);    Inc(i, 2);    Inc(j);  end;  GetMem(Result.pbData, dwBufSize);  Result.cbData := dwBufSize;  Result.pbData := PByte(Buf);end;{***********************************************************}{ BlobDataToHexStr: Converts a PByte from a DATA_BLOB       }{                   to a Hex String so it can be saved in   }{                   an RDP file                             }{ P : PByte (pbData) from DATA_BLOB                         }{ I : Integer (cbData) from DATA_BLOB                       }{***********************************************************}function BlobDataToHexStr(P: PByte; I: Integer): string;var HexStr: string;begin  HexStr := '';  while (I > 0) do begin    Dec(I);    HexStr := HexStr + IntToHex(P^, 2);    Inc(P);  end;  Result := HexStr;end;{***********************************************************}{ CryptRDPPassword: Converts a plaintext password to        }{                   encrypted password hash                 }{                   an RDP file                             }{ sPassword: plaintext password                             }{***********************************************************}function CryptRDPPassword(sPassword: string): string;var  DataIn: DATA_BLOB;  DataOut: DATA_BLOB;  pwDescription: PWideChar;  PwdHash: string;begin  PwdHash := '';  DataOut.cbData := 0;  DataOut.pbData := nil;  // RDP uses UniCode  DataIn.pbData := Pointer(WideString(sPassword));  DataIn.cbData := Length(sPassword) * SizeOf(WChar);  // RDP always sets description to psw  pwDescription := WideString('psw');  if CryptProtectData(@DataIn,                      pwDescription,                      nil,                      nil,                      nil,                      CRYPTPROTECT_UI_FORBIDDEN, // Never show interface                      @DataOut) then  begin    PwdHash := BlobDataToHexStr(DataOut.pbData, DataOut.cbData);  end;  Result := PwdHash;  // Cleanup  LocalFree(Cardinal(DataOut.pbData));  LocalFree(Cardinal(DataIn.pbData));end;{***********************************************************}{ DecryptRDPPassword: Converts an RDP Password Hash back    }{                     to it's original password.            }{                     Note that this only works for the user}{                     who encrypted the password (or on the }{                     same computer in case it was encrypted}{                     with the computerkey                  }{ sPasswordHash: Password hash (string)                     }{***********************************************************}function DecryptRDPPassword(sPasswordHash: string): string;var  DataIn: DATA_BLOB;  DataOut: DATA_BLOB;  sPassword: string;  pwDecrypted: PWideChar;  pwDescription: PWideChar;begin  DataIn := PasswordHashToBlobData(sPasswordHash);  DataOut.cbData := 0;  DataOut.pbData := nil;  if CryptUnprotectData(@DataIn,                        @pwDescription,                        nil,                        nil,                        nil,                        CRYPTPROTECT_UI_FORBIDDEN, // Never show interface                        @DataOut) then  begin    Getmem(pwDecrypted, DataOut.cbData);    lstrcpynW(pwDecrypted, PWideChar(DataOut.pbData), (DataOut.cbData DIV 2) + 1);    sPassword := pwDecrypted;    FreeMem(pwDecrypted);  end  else    raise EConvertError.CreateFmt('Error decrypting: %s',[SysErrorMessage(GetLastError)]);  Result := sPassword;  // Cleanup  if DataOut.cbData > 0 then    LocalFree(Cardinal(DataOut.pbData));end;end.


原创粉丝点击