4.10 打造一个密码显示器

关于系统提供的调试API函数我们已经学习了不少了,而且基本上常用到的函数我们也都学习过了。下面用调试API编写一个能够显示密码的程序。大家别以为我们写的程序什么密码都能显示,这是不可能的。下面针对前面的那个CrackMe来编写一个显示密码的程序。

在编写关于CrackMe的密码显示程序以前需要准备两项工作,第一个工作是知道要在什么地方合理地下断点,第二个工作是从哪里能读取到密码。带着这两个问题重新来进行思考一下。在我们的程序中,要对两个字符串进行比较,而比较的函数是strcmp(),该函数有两个参数,分别是输入的密码和真正的密码。也就是说在调用strcmp()这个函数的位置下断点通过查看它的参数是可以获取到正确的密码的。就在调用strcmp()这个函数的位置设置INT3断点,也就是将0×CC机器码写入这个地址。用OD看一下调用strcmp()函数的地址,如图 4-75所示。

4.10 打造一个密码显示器 - 图1

图4-75 调用strcmp()函数的地址

从图4-75中可以看出,调用strcmp()函数的地址为004024CE。有了这个地址只要找到该函数的两个参数,就可以找到输入的错误的密码及正确的密码。从图4-75中看出,正确的密码的起始地址保存在EDX中,错误的密码的起始地址保存在ECX中,只要在004024CE这个地址下断,并通过线程环境读取EDX和ECX寄存器值就可以得到两个密码的起始地址。

要进行准备的工作已经做好了,下面来写一个控制台的程序。先定义两个常量,一个是用来设置断点的地址,另一个是INT3指令的机器码。定义如下:

4.10 打造一个密码显示器 - 图2

把CrackMe的文件路径及文件名当参数传递给显示密码的程序。显示的程序首先要以调试的方式创建CrackMe,代码如下:

4.10 打造一个密码显示器 - 图3

然后就进入调试循环,调试循环中要处理两个调试事件,一个是 CREATE_PROCESS_DEBUG_EVENT,另一个调试事件是 EXCEPTION_DEBUG_EVENT下的EXCEPTION_BREAKPOINT。这两个事件在调试循环中进行处理,对于处理 CREATE_PROCESS_DEBUG_EVENT的代码如下:

4.10 打造一个密码显示器 - 图4

4.10 打造一个密码显示器 - 图5

在CREATE_PROCESS_DEBUG_EVENT中对调用strcmp()函数的地址处设置INT3断点,在将0×CC写入这里时要把原来的机器码读取出来。读取原机器码使用 ReadProcessMemory(),写入 INT3的机器码使用 WriteProcessMemory()。再来看一下 EXCEPTION_DEBUG_EVENT下的 EXCEPTION_BREAKPOINT是如何进行处理的。

4.10 打造一个密码显示器 - 图6

对于调试事件的处理,应该放到调试循环中,上面的代码给的是对调试事件的处理,再来看一下调试循环的大体代码:

4.10 打造一个密码显示器 - 图7

4.10 打造一个密码显示器 - 图8

只要把调试事件的处理方法放入到调试循环中,程序就完整了。接下来编译连接一下,然后把CrackMe直接拖放到这个密码显示程序上。程序会启动CrackMe进程,并等待我们的输入,当输入账号及密码后单击“确定”按钮,程序会显示出正确的密码和我们输入的密码,如图4-76所示。

4.10 打造一个密码显示器 - 图9

图4-76 显示正确密码

根据图4-76显示的结果进行验证,可见我们的获取是成功的。至此程序到此结束了。大家可以把该程序修改一下,把它改成通过附加调试进程来显示密码,以巩固我们的知识。