首先来看下TraceMe这个序列号验证程序流程图:
程序运行截图:
程序流程:用户输入用户名和序列号,程序通过GetDlgItemTextA函数获取到用户输入的内容,然后调用比较序列号的函数判断序列号是否正确,函数会有返回值来表示正确与否。根据返回值来选择弹出正确还是错误的对话框。
使用OllyDebug载入程序:
在反汇编窗口中Ctrl+G,查找GetDlgItemTextA函数,如下图所示:
然后在该地址处设置断点,重新F9运行到该断点处,程序提示输入用户名和注册号“lzx123,123456”,输入完成之后,一直F8,找到程序将刚才输入的lzx123入栈的地方:
edx存放用户名,eax存放注册号。
注意,程序将我们输入的用户名和注册号入栈之后,下一步一般就是判断注册号是否合法了,注意下面一个CALL函数,根据上面的汇编代码,大致能够反推出验证函数大致如下:12345int a(注册号,用户名,用户名长度){ ... return;}
本次破解不考虑函数内部,我们只管函数的返回值,程序继续执行,运行到下面的一个跳转语句,如下图所示:
由于我们输入的注册码是任意输入的,那个这个跳转按照正常流程,一定是调到错误处理,所以,破解的办法就是不让程序跳转,使用nop指令替换该跳转语句。
选中该跳转语句,右键->二进制->用nop填充:
然后使用之前的方法,将修改保存到可执行文件就ok了。
破解之后,运行效果如下:
(注意,跳转语句之前有一条语句:
test eax,eax;任何函数执行之后的返回值,都会放在这个寄存器里面,如果返回的内容大于4个字节,那么寄存器会存储返回数据的地址。)
关键代码注释: