我只是想知道是否有一种有效的方法来保护TEdit字段,并使用可以用纯文本读回来的工具设置密码字符集。
我认为这些工具例如抓住TEdit的目标句柄并使用gettext或类似的东西。
我到目前为止所尝试的是创建一个密码的哈希值,将其存储在一个变量中并将其写回TEdit的焦点丢失但这对我来说没有意义,因为我需要存储另一个密码来计算可执行文件中的哈希。
也许有人能更好地了解如何保护TEdit文本免受这些工具的侵害。
答案 0 :(得分:1)
如果您真的只想通过从TEdit组件中读取文本来阻止其他程序提取密码,那么我建议您使用TMaskEdit(http://docwiki.embarcadero.com/Libraries/Berlin/en/Vcl.Mask.TMaskEdit)。
与TEdit不同,TMaskEdit将原始文本存储在局部变量中,同时它可以显示不同的格式化文本。这意味着这些程序总是会获得格式化文本而不是真正的密码文本。
但正如许多其他人所说,这不会给你很多保护,因为大多数恶意软件都依赖于Key-Logging方法,他们只是记录按下哪些键。
欺骗他们的最佳选择是使用完全自定义的组件,甚至使用标准的Windows文本处理API,因此他们甚至不知道密码何时被输入。
答案 1 :(得分:1)
使用ES_PASSWORD
样式编辑控件可防止将其文本复制到剪贴板。剩下的就是拒绝向其他应用程序显示其窗口文本并将密码字符重置为null。后代类可以处理这些。
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;
答案 2 :(得分:-3)
你可以这样做。使用普通的Edit with ReadOnly = true并隐藏自己的密码。只有编辑中的内容才是*。此示例适用于字母数字字符,但您可以轻松添加其他字符。此外,如果您想在编辑中使用选择,您也需要处理它。
代码:
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;