您的位置:首页 > 其它

如何防止文本框中加密的字符被窃取??

2007-07-16 15:38 417 查看
使用了文本框后:防止 软件读取 文本框中 TEXT
在WINDOWS下的密码输入框一般都是以 “*” 来显示密码的,而有许多工具软件可以窃取密码,下面我就分析下如何防止“*” 密码泄露。

1. 取同一程序密码框中的内容
一般我们的密码框用 TEDIT 的PasswordChar 属性为 “*”,首先还是了解下EDIT1.TEXT 取文本框内容的原理。在DELPHI
中可以知道TEDIT继承自TCustomEdit,而TCustomEdit 继承自TControl. TControl中的Property Text是调用Gettext,而,GetText
调用了GetTextBuf,GetTextBuf 调用了Perform(SendMessage)最终实现了读取Edit中的内容。
关键代码可以在DELPHI的Controls.pas 和StdCtrls.pas文件中看到。

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;

通过看代码可以知道要获得Edit1的内容可以用下面的语句:
SendMessage(Edit1.handle,WM_GETTEXT,i,integer(buffer));
其中,buffer是PCHAR类型,用于存放Edit1中的内容,i 是buffer的空间大小。
示例代码如下:

procedure TForm1.Button1Click(Sender: TObject);
var
buffer:PChar;
L:integer;
begin
L:=GetWindowTextLength(Edit1.handle);
GetMem(buffer,L+1);
SendMessage(Edit1.handle,WM_GETTEXT,L,integer(buffer));
label1.Caption:=String(buffer);
FreeMem(buffer);
end;

实际使用 SendMessage(Edit1.handle,WM_GETTEXT,L,integer(Name));语句可以用
GetWindowText(Edit1.handle,buffer,L);代替,GetWindowText 是Windows API函数
这是在本地程序中取密码,如果在其他程序中取密码框中的内容时,必须先用各种方法取的密码框的句柄
再用SendMessage取的密码框的内容,为了保证通用性比较常用的办法是用鼠标钩子取鼠标当前位置的控件
句柄。具体的实现方法,在我的另外的读书笔记“钩子”中可以看到。

2.如何防范密码框密码泄露

现在软件的登陆密码时间上是一种很脆弱的安全防范方式,除了用上面说的方法窃取到,还可以用
更简单的办法可以得到,那就是用SendMessage向密码框发送一个EM_GETPASSWORDCHAR消息,将Passwordchar
设置为#0,就可以让密码显示出来,所以对重要的密码加上一曾保护是必要的。
因为现在的WINDOWS下的开发工具编写密码框时都是调用了WINDOWS系统编辑框,所以为了避免这种情况,一个
简单的饿办法就是子类化(Subclassing),也就是使用自己自定义的编辑框,并使字定义的WindowProc来进行消息
处理,对 Passwordchar的设置和文本读取消息(分别是EM_SETPASSWORDCHAR和WM_GETTEXT)进行检查,把那些
非法操作过滤掉,下面的子类化的TPasswordEdit完全过滤了以上两个消息,其基本原则是在密码框的消息处理
函数中使用一个变量(见下例中的FAllowPasswordRead或FAllowPasswordCharChange)来标志是否是自己的代码
如果是来历不明的代码试图设置passwordchar或读取文本,就不给它返回任何数值。

代码如下:
type
TPasswordEdit = class(TEdit) //建立新的控件
private
FFalsePassword: TCaption;
FAllowPasswordRead: Boolean;
FAllowPasswordCharChange: Boolean;
function GetPasswordChar: Char;
function GetText: TCaption;
procedure SetPasswordChar(const Value: Char);
procedure SetText(const Value: TCaption);
public
constructor Create(AOwner: TComponent); override;
procedure DefaultHandler(var Message); override;
published
property AllowPasswordCharChange: Boolean read FAllowPasswordCharChange write FAllowPasswordCharChange;
property AllowPasswordRead: Boolean read FAllowPasswordRead write FAllowPasswordRead;
property PasswordChar: Char read GetPasswordChar write SetPasswordChar default '*';
property FalsePassword: TCaption read FFalsePassword write FFalsePassword;
property Text: TCaption read GetText write SetText;
end;

TForm1 = class(TForm)
Edit1: TEdit;
Label1: TLabel;
Label2: TLabel;
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
PasswordEdit1: TPasswordEdit;
end;
var
Form1: TForm1;

implementation

{$R *.DFM}

constructor TPasswordEdit.Create(AOwner: TComponent);
begin
AllowPasswordCharChange := true;
AllowPasswordRead := true;
inherited Create(AOwner);
AllowPasswordCharChange := false;
AllowPasswordRead := false;
PasswordChar := '*'; {显示*}
end;

procedure TPasswordEdit.SetPasswordChar(const Value: Char);
var
OldAPCC, OldAPR: boolean;
begin
OldAPCC := FAllowPasswordCharChange;
OldAPR := FAllowPasswordRead;
FAllowPasswordCharChange := true;
FAllowPasswordRead := true;
if HandleAllocated then
inherited PasswordChar := Char(Sendmessage(Handle, EM_GETPASSWORDCHAR, 0, 0));
inherited PasswordChar := Value;
FAllowPasswordCharChange := OldAPCC;
FAllowPasswordRead := OldAPR;
end;

function TPasswordEdit.GetPasswordChar: Char;
begin
if HandleAllocated then
Result := Char(Sendmessage(Handle, EM_GETPASSWORDCHAR, 0, 0))
else
Result := inherited PasswordChar;
end;

procedure TPasswordEdit.SetText(const Value: TCaption);
begin
inherited Text := Value;
end;

function TPasswordEdit.GetText: TCaption;
var
OldAPCC, OldAPR: boolean;
begin
OldAPCC := FAllowPasswordCharChange;
OldAPR := FAllowPasswordRead;
FAllowPasswordCharChange := true;
FAllowPasswordRead := true;
Result := inherited Text;
FAllowPasswordCharChange := OldAPCC;
FAllowPasswordRead := OldAPR;
end;

procedure TPasswordEdit.DefaultHandler(var Message);
var
P: PChar;
begin
if (csDesigning in ComponentState) or (csCreating in ControlState) then
inherited //如果在程序设计和正在建立阶段不需要做任何变动
else
with TMessage(Message) do
case msg of
EM_SETPASSWORDCHAR: if FAllowPasswordCharChange then
inherited; //如果允许设置EM_SETPASSWORDCHAR才可以继续
WM_GETTEXT: if FAllowPasswordRead then inherited
else begin
P := PChar(FFalsePassword);
Result := StrLen(StrLCopy(PChar(LParam), P, WParam - 1));
end; //如果允许读文本才可以继续否则返回(FFalsePassword)的长度
WM_GETTEXTLENGTH: if FAllowPasswordRead then inherited
else
if PChar(FFalsePassword) = nil then Result := 0
else Result := StrLen(PChar(FFalsePassword)); //如果允许读文本 才可以继续否则返回0或位密码
else
inherited;
end
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
PasswordEdit1 := TPasswordEdit.Create(self);
PasswordEdit1.parent := form1;
PasswordEdit1.Width := 150;
PassWordEdit1.Height := 21;
PasswordEdit1.Top := 115;
PasswordEdit1.Left := 80;
PasswordEdit1.PasswordChar := '*';
PasswordEdit1.AllowPasswordRead := false;
PasswordEdit1.Visible := true;
PasswordEdit1.Text:='Hello';
PasswordEdit1.FalsePassword:= '想读我?没门!'
end;

end.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐