让密码更安全

---- 随着应用软件的日益丰富,需要使用密码的地方也越来越多,尤其是对于上网的人来说,密码几乎无处不在。然而在当前各种应用软件中普遍存在密码的安全问题,其原因在于各种开发工具中编辑框存在安全漏洞。密码输入显示是需要保密的,所以用来做输入和显示的编辑框可以设置passwordchar,这时候编辑框就会只显示‘*’之类的字符,而将真正的文本隐藏起来。这样似乎文本就无法看到了,然而事实上这样的保护是非常脆弱的,有很多办法可以突破这层保护,最简单的办法就是使用SendMessage向编辑框传送一个EM_SETPASSWRODCHAR消息,将Passwordchar设置为0,就可以让密码原形毕露,而且windows并没有对设置了passwordchar的编辑框文本读取进行保护,所以也可以编程直接读出密码文本。实际上现在已经有了不少这样的软件,还记得Revelation吗,一个15k的小程序却使得微软不得不出面解释,所以对于重要的密码还是再来加上一层保护吧。

---- 由于各种开发工具实际上都在使用Windows系统编辑框,所以从VC、VB到BC、Delphi等无一幸免,如何在自己的程序中避免这种情况呢,一个简单的办法就是子类化(subclassing),也就是使用自定义的编辑框WindowProc来进行消息处理,对于passwordchar的设置和文本读取消息(分别是WM_GETTEXT 和EM_SETPASSWORDCHAR))进行检查,把那些非法操作过滤掉。对于VC来说是非常简单的,可以从CEdit直接派生一个安全的新类CPwdEdit:首先用ClassWizard生成新类,然后加入共有变量BOOL m_bLock,并重载WndProc(),修改下面两个成员函数:


CPwdEdit::CPwdEdit()
{
  m_bLock=FALSE;
}
LRESULT CPwdEdit::WindowProc(UINT message,
WPARAM wParam, LPARAM lParam)
{
// TODO: Add your specialized code here
and/or call the base class
//在这里加入消息检查
  if( m_bLock && (message==WM_GETTEXT ||
message==EM_SETPASSWORDCHAR) )
    return 0;
---- //对于EM_SETPASSWORDCHAR,wParam是缓冲区大小,lParam是缓冲区地址,所以在这里可以向缓冲区拷贝一个设定的字符串来迷惑读取程序。 //其他消息调用缺省窗口函数

  return CEdit::WindowProc(message, wParam, lParam);
}

---- 使用时,只需要设置m_bLock=TRUE就可以阻止revelation的读取了。假定在对话框MyDlg中有一个编辑框IDC_EIDT1,用法如下:

CPwdEdit m_edit1;
BOOL CMyDlg::OnInitDialog()
{
。。。
// TODO: Add extra initialization here
m_edit1.SubclassDlgItem( IDC_EDIT1,this );
  m_edit1.SetPasswordChar( '*' );
  m_edit1.SetWindowText( "12345" );
  m_edit1.m_bLock=TRUE;
。。。
}

---- 直接使用SDK就稍微复杂一些,需要手工进行子类化,设定一个对话框应用,加入如下代码:


HWND hwndEdit;
BOOL bLock=FALSE;
#ifdef STRICT
 WNDPROC OldEditProc;
#else
 FARPROC OldEditProc;
#endif

//自定义窗口函数
LRESULT CALLBACK MyEidtProc
( HWND hwnd,UINT
uMsg,WPARAM wParam,LPARAM lParam )
{
  LRESULT lResult=0;
if( bLock && (uMsg==WM_GETTEXT ||
uMsg==EM_SETPASSWORDCHAR) )
return lResult;
//下面调用原窗口函数
  if( (DWORD)OldEditProc!=(DWORD)MyEidtProc )
lResult=CallWindowProc(OldEditProc,
hwnd,uMsg,wParam,lParam);
return lResult;
}
//在对话框中进行子类化
BOOL WINAPI DlgProc (HWND hwnd, UINT uMsg,
WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
//在初始化代码中进行子类化
    case WM_INITDIALOG:
//得到编辑框句柄
hwndEdit=GetDlgItem( hwnd,
IDC_ EDIT1 );
//得到原窗口函数地址
OldEditProc = GetWindowLong(
hwndEdit,GWL_WNDPROC );
//设置自定义窗口函数
SetWindowLong( hwndEdit,
     GWL_WNDPROC,
(DWORD)MyEidtProc );
bLock=TRUE;
break;
。。。
}
}
---- 经过测试,以上的方法可以成功地阻止Relevation1.1和其他软件窃取密码,不过由于这个漏洞实际上出自Windows系统本身,所以在编写软件时还是要注意这个问题,尽量避免密码的直接显示。

 

摘自:http://www.xici.net/main.asp?url=/u17083/d31454.htm

发布了26 篇原创文章 · 获赞 13 · 访问量 15万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章