Delphi的TEdit作为密码框使用时存在安全性问题(5分)

  • 主题发起人 主题发起人 redforks
  • 开始时间 开始时间
R

redforks

Unregistered / Unconfirmed
GUEST, unregistred user!
把TEdit的PasswordChar设成'*'作为密码框使用,存在较大的安全性问题。
运行一个用TEdit作为密码框的程序,用Spy++或WinSight32中的"Find Window"功能
找到这个密码框,然后检查这个窗口的属性,可以发现可以密码框中的内容作为Caption
属性显示出来了,也就是说,可以很容易的使用Spy++读出Delphi密码框中的密码。

大家可以试试FoxMail,如果把密码保存在密码框中,使用Spy++...

问题就处在Delphi没有当TEdit是密码框是正确地截获WM_GETTEXT消息。
 
没有啊?用Spy++看到的总是TEdit的Name属性呀!(D5)
 
你不会处理一下啊?
 
自己处理
 
这个是微软的问题
不关DELPHI的事
你可以自己处理一下的
你用过Notes吗?
它的密码框就可以保密的!!!
 
那些能保密的.
都是假的密码.
都是出来后,在象征的写些*在筐里.
 
自己对keydown0懈怠吗
 
呵呵,redforks快成联邦调查局的了
 
TEdit是标准的Window控件Edit Control,它的密码功能是系统的问题,想避免此问题,就
得Do It Youself。在OnKeyPress这样的键盘事件中截获用户所键入的每一个密码字符,保
存它们,然后把Key参数改为'*'的ASCII码,这样TEdit中显示的就是'*'号,而你却已经得
到了密码,其他人即使用什么工具也没法看到密码,他们只能得到一串'*'号。
 
To Zephyr:
您的办法看上去确实可行,但有没有考虑过:
1. 数据输入时,需要保证用户输入和密码缓冲区的数据一致:
1.1 需要处理"BackSpace"、"Home"、"End"、移动Cursor的左右箭头键等编辑键,
1.2 需要处理"Shift+"、鼠标拖动的块选择功能,以及"Cut"、"Paste"编辑消息
1.3 需要处理Windows IME,关闭任何软件输入法,防止用户输入了汉字密码。
2. 如果系统中有多个密码框,则需要为每个密码框编写OnKeyPress事件,如果编写成通用的
OnKeyPress方法,则要解决保存密码的字符串变量的内存管理问题。
软件如此DIY,还叫什么RAD?

我的解决办法:
根据WINAPI,获得一个窗口的Text属性是使用GetWindowText()函数,而GetWindowText()函数又是通过
向目标窗口句柄发送WM_GETTEXT消息而获得Text属性的(原文:
If the target window is owned by the current process, GetWindowText causes a WM_GETTEXT message
to be sent to the specified window or control. )。所以我们只需要从TCustomEdit或TEdit派生,在派生
类中重载WM_GETTEXT消息:
...
TSafeEdit = class(TEdit)
protected
procedure WMGETTEXT(var message: TWMGetText)
message WM_GETTEXT;
end;

implementation

procedure TSafeEdit.WMGETTEXT(var message: TWMGetText);
begin
message.Text := '';
message.TextMax := 1;
message.Result := 0;
end;
...
这样GetWindowText只能返回空字符串了。可是这样作右碰到了新的问题:
如果这是读TSafeEdit.Text属性,返回的也是空串,因为Text属性是在TControl中实现的,而TControl:
property Text: TCaption read GetText write SetText;

function TControl.GetText: TCaption;
var
Len: Integer;
begin
Len := GetTextLen;
SetString(Result, PChar(nil), Len);
if Len <> 0 then GetTextBuf(Pointer(Result), Len + 1);
end;

function TControl.GetTextBuf(Buffer: PChar
BufSize: Integer): Integer;
begin
Result := Perform(WM_GETTEXT, BufSize, Longint(Buffer));
end;
这样可以看出:Text属性也是用WM_GETTEXT消息实现的,所以...

最终的解决办法:
重载GetText方法是不可能的,因为他是TControl的虚函数,只有重新定义Text属性

TSafeEdit = class(TEdit)
private
FRealText: string;
procedure SetText(const value: string);
published
property Text: string read FRealText write SetText;
end;

implementation

procedure TSafeEdit.WMGETTEXT(var message: TWMGetText);
begin
inherited;
FRealText := message.Text;

message.Text := '';
message.TextMax := 1;
message.Result := 0;
end;

procedure TSafeEdit.SetText(const value: string);
begin
if FRealText <> Value then SetTextBuf(PChar(Value));
end;
这样读写都没有问题了。
 
接受答案了.
 
后退
顶部