简体   繁体   English

保护编辑组件的密码

[英]protect password of tedit components

I just wonder if there is an efficient way of protecting an TEdit field with password char set from tools which can read it back in plain text. 我只是想知道是否存在一种有效的方法来保护带有密码字符集的TEdit字段,而该工具的设置只能以纯文本形式将其读回。

I think those tools for example grab the target handle of the TEdit and use gettext or something similar. 我认为这些工具例如可以抓住TEdit的目标句柄并使用gettext或类似的东西。

What I have tried so far is creating a hash for the password stored it in a variable and write it back on focus lost of the TEdit but that doesn't make sense to me since I would need to store another password for calculating the hash inside of the executable. 到目前为止,我尝试过的工作是为密码创建一个哈希,将其存储在变量中,然后将其写回到丢失的TEdit上,但这对我来说没有意义,因为我需要存储另一个密码来计算内部哈希可执行文件。

Maybe someone has a better idea of how the TEdit text could be protected against those tools. 也许有人对如何使用这些工具保护TEdit文本有更好的主意。

If you are realy only interested in preventing other programs from extracting the pasword by reading text from TEdit component then I suggest you use TMaskEdit instead ( http://docwiki.embarcadero.com/Libraries/Berlin/en/Vcl.Mask.TMaskEdit ). 如果您真的只想通过读取TEdit组件中的文本来阻止其他程序提取密码,那么我建议您改用TMaskEdit( http://docwiki.embarcadero.com/Libraries/Berlin/en/Vcl.Mask.TMaskEdit ) 。

Unlike TEdit TMaskEdit stores the orginal text inside local variable while it can display different formated text. 与TEdit不同,TMaskEdit将原始文本存储在局部变量中,同时可以显示不同格式的文本。 This means that those programs would always get that formated text instead of real password text. 这意味着这些程序将始终获取该格式化的文本,而不是真实的密码文本。

But as many others said this won't give you much protection as most malicious software instead rely on Key-Logging approach where they are simply loging which keys were pressed. 但是,正如许多其他人所说,这不会给您太多保护,因为大多数恶意软件都依赖于Key-Logging方法,在该方法中,他们只是记录按下了哪些键。

Best option in fooling them would be to use compleetely custom component which doesen't even use standard Windows text handling API, so they don't know when the pasword is even being entered. 欺骗他们的最佳选择是使用完全自定义的组件,该组件甚至不使用标准的Windows文本处理API,因此他们甚至不知道何时输入密码。

Edit controls with ES_PASSWORD style prevent their text to be copied to the clipboard. 具有ES_PASSWORD样式的编辑控件可防止将其文本复制到剪贴板。 What remains is to deny revealing its window text to other applications and resetting the password character to null. 剩下的就是拒绝向其他应用程序显示其窗口文本并将密码字符重置为null。 A descendant class can handle these. 后代类可以处理这些。

type
  TPasswordEdit = class(TEdit)
  protected
    procedure EmGetPasswordChar(var Message: TMessage); message EM_GETPASSWORDCHAR;
    procedure EmSetPasswordChar(var Message: TMessage); message EM_SETPASSWORDCHAR;
    procedure WMGetText(var Message: TMessage); message WM_GETTEXT;
  end;

procedure TPasswordEdit.EmGetPasswordChar(var Message: TMessage);
begin
  // for nirsoft's BulletsPassView, probably only prevents further inspection, 
  // injecting a thread perhaps - I have no idea what it's doing..
  if (PasswordChar = #0) or not InSendMessage then
    inherited;
end;

procedure TPasswordEdit.EmSetPasswordChar(var Message: TMessage);
begin
  if (PasswordChar <> #0) and (Message.WParam <> 0) then
    inherited;
end;

procedure TPasswordEdit.WMGetText(var Message: TMessage);
begin
  if (PasswordChar = #0) or not InSendMessage then // allow owning thread
    inherited;
end;

You can do something like this. 你可以做这样的事情。 Use a normal Edit with ReadOnly=true and make your own password hiding. 使用ReadOnly = true的普通Edit并隐藏自己的密码。 Only content which would be in the Edit are the *. *仅包含在“编辑”中的内容。 This example works with alphanumeric characters but you can easily add the others. 此示例适用于字母数字字符,但您可以轻松添加其他字符。 Also if you want to use selection in the Edit, you need to handle that too. 另外,如果要在“编辑”中使用选择,则也需要处理。

Code: 码:

uses
  StrUtils;

var
  password: String;

...

procedure TForm1.FormCreate(Sender: TObject);
begin
  password:='';
end;

...

procedure TForm1.Edit1KeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
var sel: Integer;
begin
  sel:=Edit1.SelStart;
  if((Key>=48) and (Key<=90))then
  begin
    if(ssShift in Shift)then
      password:=LeftStr(password, sel)+Char(Key)+RightStr(password, Length(Edit1.Text)-sel)
    else
      password:=LeftStr(password, sel)+LowerCase(Char(Key))+RightStr(password, Length(Edit1.Text)-sel);

    Edit1.Text:=Edit1.Text+'*';
    Edit1.SelStart:=sel+1;
  end
  else if((Key>=VK_NUMPAD0) and (Key<=VK_NUMPAD9))then
  begin
    password:=LeftStr(password, sel)+Char(Key-48)+RightStr(password, Length(Edit1.Text)-sel);
    Edit1.Text:=Edit1.Text+'*';
    Edit1.SelStart:=sel+1;
  end
  else if((Key=VK_BACK) and (sel>0))then
  begin
    Delete(password, sel, 1);
    Edit1.Text:=Copy(Edit1.Text, 1, Length(Edit1.Text)-1);
    Edit1.SelStart:=sel-1;
  end
  else if((Key=VK_DELETE) and (sel<Length(Edit1.Text)))then
  begin
    Delete(password, sel+1, 1);
    Edit1.Text:=Copy(Edit1.Text, 1, Length(Edit1.Text)-1);
    Edit1.SelStart:=sel;
  end
  else if(Key=VK_RETURN)then
  begin
    //handle the password check here (make hash etc)
    ShowMessage(password);
    password:='';
    Edit1.Text:='';
  end;

  //just for the testing, this should be removed of course
  Form1.Caption:=password;
end;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM