密码控件安全技术浅析及攻击实例
Posted Tishion
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了密码控件安全技术浅析及攻击实例相关的知识,希望对你有一定的参考价值。
标 题: 密码控件安全技术浅析及攻击实例时 间: 2013-07-14,16:09:57
密码控件是一个很常见的控件,这篇文章主要介绍一下安全密码控件的一些实现思路和攻击思路。
1 物理密码键盘和密码控件的对比
先说一下程序中的密码控件和现实中的密码键盘的对比。几乎每个人都在银行或者ATM机器上输入过密码,那在输入密码的过程中你接触到的那个键盘就是一个金融密码键盘。一般柜台的密码键盘都像鼠标一样带一个数据线,这个数据线就是连接密码键盘和银行处处理终端的。结构图如下:
上图显而易见,如果一个坏人想要去窃取密码信息,由两个方式:
A. 在终端记录用户的输入按键
B. 从数据线中截获用户密码输入
对于第一种方法,就靠用户在输入密码时候的自我保护了,而第二种方法也不是轻易能实现的。不要小瞧了这个密码键盘,这个密码键盘的制造标准都是有国标规定的,国标规定的一点是:从键盘流出的数据一定要是用户输入加密后的数据,所以即使截获到键盘流出的数据想要破解出密码也需要先得到该密码键盘在加密过程中使用的密钥(这里使用的是对称加密算法)。
其实密码控件就是密码键盘的软件实现,在一个使用密码控件的软件系统中(多是网络校验系统),密码控件的整个软件实现就相当于整个物理的密码键盘,对于物理的数据线路和银行终端这样的角色,在密码控件系统中没有绝对的对应。因为密码控件可能只是简单的把用户输入的数据加密后发送到网络上,这时候网络就是物理的数据线路;而另一种情况是用密码控件产生的数据流向整个本地程序的另一个模块,这时候计算机内存就成为了物理的数据线路的角色。
无论如何,上述的物理密码键盘肯定要比各种密码控件安全,因为他们使用的场合有限,能够接触到密码键盘内部的人很少,所以就无法从密码键盘的内部来做一些恶意攻击行为。而软件实现的密码控件就现对显得捉襟见肘了,因为要部署到用户终端,而用户终端的环境十分的复杂,并且权限十分的宽松。
2 软键盘密码控件原理和攻击方法
Windows系统的内置的控件中没有专门的密码控件这一说,而只是对一个SingleLine的Edit控件设置一个属性password,这样就实现了这个Edit的输入内容只会显示成一种不可识别的字符。但是这种原生的密码控件从安全的角度来说就只有一点:从视觉上看不到用户输入的密码,但是整个密码控件仍然遵循Win32 消息派遣处理流程,也就是说,写一个标准的程序就可以达到先于密码空间获得用户输入从而记录密码的效果。
因此很多软件厂商出于安全的考虑就做出了各式各样的“安全密码控件”,常见的密码控件类型:
1. 低级键盘钩子,改变消息参数以及派遣路径
2. 软键盘,完全绕过键盘输入消息
3. 暂时还没想到……
下面简单介绍一下以上两种控件的原理
2.1 软键盘式密码控件
由于第2种方案使用的不是很多,所以简单介绍,这种方法使用不多的原因之一就是用户体验不如键盘输入。这种密码控件的方法就是把键盘输入转为鼠标按键输入,而鼠标按键消息中并没有携带原始的密码字符,而是按键的坐标,然后程序把坐标映射到相应的字符,而映射过程中遵循的F(x,y)是程序开发者自行设计并且可以实时动态更新(变序)。
先不考虑其他的保护措施,如果要攻击这种安全控件,从设计这种控件的程序员的角度来考虑,如果要获取用户输入密码,至少需要两个条件
A. 鼠标点击坐标(x,y)
B. 内存中映射算法F(x,y)
攻击者可以截获鼠标点击坐标(x,y)然后根据破解出来的F(x,y)来计算出用户输入,这种方法对于一个没有做到全方位保护的软键盘密码控件可能有效,但是还是太麻烦了,其实有个捷径,攻击者只要识别出用户的鼠标点击操作发生在软键盘上,然后在每次用户点击鼠标时就来一个屏幕截图,全屏or局部都可以,然后把截取的图片排序,就可以得到用户输入的密码数据了,完全绕过程序的映射算法。
所以从以上攻击方法可以看出,软件盘密码控件如果要做到更安全那就必须对两个事件进行处理,
A. 用户点击鼠标的消息不被其他程序截获
B. 发生截屏操作时对本程序的所有窗口DC做黑屏处理
关于软键盘密码控件就介绍这么多,只是原理性的介绍,并没有实践代码,但是原理和攻击方法已经十分清晰了,所以有兴趣的同学可以帮助一些采用软键盘密码控件的厂商做下安全测试。
2.2 低级键盘钩子式密码控件
这个就是现如今流行并且典型的密码控件实现方式了,这种方式下键盘还是那个键盘,输入框还是那个输入框,唯一的不同是这个输入框的消息派遣路径,贱了不少,各个厂商都想方设法的在Windows消息处理机制中寻找解决安全问题的途径。
正常的输入框,在接收用户的键盘输入时会相应WM_CHAR消息,这个消息是如何来的呢?当按下一个键,键盘驱动产生硬件中断IRQ,然后经过HAL映射中断请求级别(IRQL)如果这个级别比CPU的允许的级别高,那就发生中断,CPU取出键盘中断号,然后用该中断号作为索引取出IDT中的对应的描述符,然后执行该描述符所指向的一个键盘处理程序,键盘中断处理程序的作用就是处理原始的键盘扫描码生成数据结构,然后缓存数据。
然后就是键盘驱动的工作,键盘驱动的工作就是为了完成设备栈顶部的一个功能号为IRP_MJ_READ的IRP,这个IRP是win32子系统进程csrss.exe中的一个线程RIT(Raw input thread)产生的,当这个IRP被完成后,RIT负责用键盘事件产生的数据生成一个按键消息并且放入对应的GUI线程的输入队列中。
而后对应的GUI线程在消息循环中使用GetMessage获取消息,就会取出一个WM_KEYDOWN消息,然后如果该GUI线程中使用了TranslateMessage处理这个WM_KEYDOWN消息,则会生成一个WM_CHAR消息存入自身的POST消息队列,然后下次再去GetMessage的时候就会取出WM_CHAR消息,并且把该消息携带的char传入相应的Window Procedure,如果没有使用TranslateMessage处理这个消息就不会产生WM_CHAR消息。
完整的流程图如下:
从上面的描述以及流程图来看,如果作为一个攻击者想要获取用户输入的密码,很简单的做法就是截获WM_CHAR消息,的确是这样的,用Spy++就可以轻而易于的获得一个原生密码输入框的所有WM_CHAR消息,所以安全密码控件的目标就是让攻击者无法截获WM_CHAR消息,或者截获到WM_CHAR消息的时候这个VirtualKeyCode是假的,而真正的VirtualKeyCode已经被处理。因为在从用户按键到密码框多出一个显示字符的过程中只有WM_CHAR这个消息是明文记录了用户键入的数据。
对于保护WM_CHAR消息的做法,必然是要在得到WM_KEYDOWN这个消息的时候就进行,因为只要有了WM_KEYDWON这个消息就可以绕过系统后续的处理先于系统计算出用户按下的Virtual Key,然后保存这个案件对应的Char,然后再返回一个修改过的WM_KEYDOWN消息,后面的数据都不用再管了,WM_KEYDOWN被修改,Virtual Key被修改,导致后续调用TranselateMessage消息时产生的WM_CHAR也不正确,所以攻击者就算截获到WM_CHAR也是徒劳的。
产生假WM_CHAR的的方法各个厂商迥异,比如QQ的就是(此处过滤5000字)。再比如支x宝,如果一个用户的密码是mypasswordisaccess,那么按照这个键序列输入后,控件返回的char序列会是1234556789054qqw55,也就是说在支x宝安全控件每次初始化之后,当用户输入一个键,控件就会为这个键设置一个映射char,如果下次用户再输入这个键,那就不用设置直接返回上次设置的char,策略就是用户输入键之后控件负责生成映射关系,这个映射的值的产生方式很简单:
如上图的四行键位,从上到下从左到右排列。
上面说了原理,要实现的话,必然用到Windows的一种技术,那就是基于消息的Hook机制了(此Hook跟inline,IAT,SSDT等Hook完全不是一回事),因为要处理在系统生成WM_CHAR之前就处理WM_KEYDWON并且修改,就必须要使用低级键盘钩子,WH_KEYBOARD_LL。
2.3 支x宝安全密码控件原理分析实践
好了,不纸上谈兵了,找个靶子分析分析吧,为了避免律师函,还是选择支x宝吧宝,支x宝的密码控件用在了登陆和支付密码的输入过程中,两处使用的都是同一个密码控件,先来调试下吧。
按照前面的讲到的,该密码控件使用了windows hook机制,那就先从SetWindowsHookEx这个函数入手吧。
Code:
以上是关于密码控件安全技术浅析及攻击实例的主要内容,如果未能解决你的问题,请参考以下文章