防 止 密 码 被 非 法 获 取
郝 峰
----Windows 虽 然 是 一 个 功 能 强 大 的 操 作 系 统, 但 其 存 在 的 一 些 先 天 性 不 足 给 黑 客
留 下 了 许 多 可 乘 之 机, 著 名 的BO 程 序 就 是 利 用Windows 的 这 些 漏 洞 来 危 害 计 算 机 的
安 全。 笔 者 最 近 发 现 了 一 个 很 流 行 的 专 门 获 取Edit 框Password 的 工 具, 甚 至 其 源 代
码 已 在 某 报 纸 上 发 表 了, 这 无 疑 是 对Edit 的Password 功 能 的 完 全 否 定。 本 文 将 首 先
分 析 非 法 获 取Password 的 原 理, 然 后 给 出 用Visual C + + 来 实 现 保 护Edit 框 中 的
Password 不 被 非 法 获 取 的 对 策。
一、 非 法 获 取Password 的 原 理
----Edit 是Windows 的 一 个 标 准 控 件, 当 把 其 Password 属 性 设 为True 时, 就 会 将 输 入 的
内 容 屏 蔽 为 星 号( *), 从 而 达 到 保 护 的 目 的。 而Edit 框 中 的 内 容 可 通 过 发
WM_GETTEXT,EM_GETLINE 消 息 来 获 取。 黑 客 程 序 就 是 利 用Edit 的 这 个 特 性, 首 先 枚 举 当
前 程 序 的 所 有 子 窗 口, 当 发 现 枚 举 的 窗 口 是EDIT 并 且 具 有ES_PASSWORD 属 性 时, 则 通
过SendMessage 向 此 窗 口 发 送WM_GETTEXT 或EM_GETLINE 消 息, 这 样Edit 框 中 的 内 容 就 一 目 了
然 了。
二、 对Password 进 行 保 护
----由 上 述 分 析 可 看 出,Edit 的 漏 洞 在 于 没 有 检 查 发 送WM_GETTEXT 或EM_GETLINE 消 息 者
的 身 份, 只 要 找 到Edit 窗 口 句 柄, 任 何 进 程 都 可 获 取 其 内 容。 这 里 给 出 一 种 简 单
的 方 法 来 验 证 发 送 消 息 者 的 身 份 是 否 合 法。
----1. 创 建 新CEdit 类
----从CEdit 继 承 一 个 子 类CPasswordEdit, 申 明 全 局 变 量g_bAuthorIdentity 表 明 消 息 发 送 者
的 身 份:
BOOL g_bAuthorIdentity;
----然 后 响 应CWnd 的 虚 函 数DefWindowProc, 在 这 个 回 调 函 数 中 进 行 身 份 验 证:
LRESULT CPasswordEdit::DefWindowProc
(UINT message, WPARAM wParam, LPARAM lParam)
{
// 对Edit 的 内 容 获 取 必 须 通 过
以 下 两 个 消 息 之 一
if(( message == WM_GETTEXT)
|| ( message == EM_GETLINE))
{
// 检 查 是 否 为 合 法
if( !g_bAuthorIdentity)
{
// 非 法 获 取, 显 示 信 息
AfxMessageBox(_T
(“ 我 的 密 码, 可 不 能 让 你 看!"));
//
return 0;
}
// 合 法 获 取
g_bAuthorIdentity = FALSE;
}
return CEdit::DefWindowProc
(message, wParam, lParam);
}
----2. 在 数 据 输 入 对 话 框 中 做 处 理
----在 对 话 框 中 申 明 一 个 类 成 员m_edtPassword:
CPasswordEdit m_edtPassword;
----然 后 在 对 话 框 的OnInitDialog() 中 加 入 下 列 代 码:
m_edtPassword.SubclassDlgItem(IDC_EDIT_ PASSWORD, this);
----其 目 的 是 将 控 制 与 新 类 做 关 联。
----之 后 在 对 话 框 的 数 据 交 换 中 将 身 份 设 为 合 法:
void CDlgInput::DoDataExchange
(CDataExchange * pDX)
{
// 如 果 获 取 数 据
// 注 意: 对 于CPropertyPage 类 这 里 不 需 要if
( pDX ->m_bSaveAndValidate) 条 件
if( pDX ->m_bSaveAndValidate)
{
g_bAuthorIdentity = TRUE;
}
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CDlgInput)
DDX_Text
(pDX, IDC_EDIT_PASSWORD, m_sPassword);
//}}AFX_DATA_MAP
}
----这 样,Password 输 入 框 就 会 受 到 保 护。
三、 需 要 注 意 的 问 题
----以 上 的 方 法 仅 针 对VC 程 序, 对 于VB 程 序, 需 要 借 助VC 做 一 个Password 的ActiveX 控
件, 实 现 方 法 与 上 类 似。 以 上 程 序 在Visual C + +6.0 上 通 过, 并 且 用 黑 客 程 序
PWBTool 测 试 通 过。 完 整 演 示 代 码 请 到http://myhelper.yeah.net 的“ 编 程 技 巧” 下 载。