• 标 题:另类注册机(一MFC程序的改造心得) (3千字)
  • 作 者:herofire
  • 时 间:2001-9-10 22:46:13
  • 链 接:http://bbs.pediy.com

另类注册机
    本文主要说明注册机编写的另一种方式,实现将一个MFC程序授权程序改造成一个标准的注册机,这样我们就可以绕过不必分析繁杂的加密过程了。
    参考资料:《看雪学院精华三》中关于MFC程序分析文章;
    目标简介:一个MFC做的授权程序,注册码保护,界面有一个序列号窗口(只读属性),一注册码输入窗口,一个注册按钮。
    经过反编译分析得到程序大致流程:
1) 程序启动时读取网卡信息后运算后显示于只读窗口中;
2) 取得用户输入的注册码;
3) 判断输入的注册码是否合要求;
4) 读取本机网卡信息并进行运算,返回运算后的结果;
5) 将运算后的网卡信息与输入的注册码一起进行运算比较,产生正确注册码,判断后返回判断结果;
6) 正确则将注册码写入注册表中,错误则提示;
7) 程序中各种功能都是独立的过程调用。
根据以上的分析我们就有了大致改造思路以达到我们的目的,具体思路如下:
1. )使程序能接受我们的输入;
2. )替换步骤4)中得到的网卡信息运算后的返回结果换成我们的输入;
3. )将步骤5)后得到的注册码通过一个对话框显示出来。
根据我们思路经过具体分析总结出下面几个待解决问题:
1:如何使程序能接受我们的输入?
我的如法为用eXeScope将只读窗口的属性修改为可写,用于我们输入信息;
2:如何得到我们的信息替代运算后的信息?
一般的做法就是在程序中加入自己的代码,在步骤4)中返回运算后的信息时转到我们代码中,在我们的代码中实现输入信息的获取,并替换原来的运算结果,最终实现返回我们输入的信息到步骤5)。
这里需要解决两个问题:如何加入我们的代码、如何获得输入的信息。
问题一用SMC方法就可以很好解决,具体做法参见《看雪的精华三》中SMC部分。
在解决问题二时我遇到一些问题:原来我打算用GETWINDOWTEXT函数获取我们输入信息的窗口的字符串,但似乎用MFC写成的程序在创建窗口时是动态分配窗口句柄,即每次运行时输入窗口的句柄是不固定的,这就造成没法使用GETWINDOWTEXT来取得我们想要的信息,可能是我对MFC程序的不了解,有那位高人知道就指点一二。
现在似乎山穷水尽了,再用IDA分析一下程序,发现程序中在在步骤5)有一个地方是调用了UpdateData(BOOL)函数,如下所示:
004024FF  push    esi
00402500  push    1
00402502  call    j_?UpdateData@CWnd@@QAEHH@Z ; CWnd::UpdateData(int)
00402507  mov    edx, [esi+64h]
这个有什么用呢?用MFC写过程序的人都知道,MFC封装了窗口中的消息传递,在增加一个窗口后可以增加一个成员对应窗口的文字,而UpdateData(BOOL)就是用来完成将窗口的信息更新到成员的功能,它的参数就是更新的方向,为1时就是将窗口中的信息,也就是我们输入的注册码更新到它自定义的成员中,那00402507的语句应该就是将得到的注册码写入成员变量中,那我们输入的信息应该也是从这里可得到。
根据上面的猜测我们做一下试验:修改了只读窗口的属性,使它可写。用ICEL载入程序,将中断下于00402502处,等待程序出现主窗口后修改原只读窗口中的信息以及按正确格式输入错误的注册码,点击注册按钮,程序中断在我们00402502,再用F10执行一步,到达00402507 ,我们查看ESI+64 处的内存,果然看到了我们输入的注册码以及我们在原只读窗口中修改后的信息,那么我们就找到办法解决问题2)了。如此我们要插入的代码基本流程就可以形成了,如下:
1).保存步骤4)返回前的状态;
    2).调用UpdateData功能,取得我们需要的信息
    3).将得到的信息换步骤4)中运算后的结果
    4).正常返回步骤4)
3 如何显示正确的注册码?
我采用的方法是将步骤5)中运算后的正确注册码的内存地址替换步骤6)中出错提示时的字符串调用的地址。这样程序就可以自己显示正确的注册码了。
经过上面3 步后我们就已经能实现的我们的目标了。
最后整理一下,我们改动后的程序流程:
1) 屏蔽程序启动时读取网卡信息后运算后显示于只读窗口中的过程,因为它要用到步骤4)的调用;
2) 取得我们输入的信息和符合要求的错误注册码;
3) 判断输入的注册码是否合要求;
4) 读取本机网卡信息并进行运算,返回前转到我们插入的代码中,将取得的窗口信息替换经过运算后的返回值后返回原来4)中下一条指令处;
5) 将我们的信息与输入的注册码一起进行运算比较,产生正确注册码,判断后返回判断结果;
6) 将5)中得到的正确注册码地址替换原错误提示的字符串地址,弹出正确注册码。
经过如上改造我们就可以将一个原来程序改造成一个注册机,但在实际测试中发现在同一种操作系统中程序才能正确运行。