早上上课的时候无聊搞了一下老师给的一个程序(程序已经上传附件),是一个没有按钮的程序进行逆向。讲真一开始我是比较蒙的,因为就算是字符串参考是没有用的,但是还有GetDigText之类的函数可以下断点,在不就是可以使用字符串参考来找到关键跳转。或者应对一般的程序,没有按钮的话,找到接收输入的序列号和用户名也是可以的,然后对字符串下硬件访问断点或者内存访问断点也是可以断的下来,但是这个程序竟然不行(可能是我太菜了)。
2. 在你输入的时候没有一点反应,也没有按钮来给你下消息断电之类的,但是输入字符串和它对应的序列号之后就会有对应的弹窗提示:
先讲一下我是在还没有破解的时候是怎么知道我名字对应的正确的序列号的,这里我是使用的搜索栈空间,在和输入的序列号相邻的位置肯定有一个序列号是正确的,所以可以搜索到483553,这里也可以使用加密和解密里面介绍的数据约束性方法,先加载程序起来,然后输入名字和序列号比如 jt 和12345,
这个时候不要进行其他操作,然后打开WinHex,
然后打开内存编辑窗口(热键ALT + F9) ,选择我们的程序点击第一项之后,
点击查找12345:
一直F3按键往下走,找到暴露出来的正确字符串了:
这个只是方便后面的进一步破解的,不能依赖这个方法找序列号:
3. 先把程序拖到PEidl里面看看有没有壳之类的:
发现就是一个简单的程序:
4. 然后放到od进行动态调试,因为没有对应的弹窗来提示输入的是正确还是错误,如果是简单的API函数的方式是断不下断点的,然后找到它保存自己输入的序列号的位置下内存访问和硬件访问也是不行的(我太菜了)。
我用的方式是万能断点bpx hmemcpy 一步步跟着,肯定可以找到处理的位置。
还有一种方式是OD载入后,CTRL+G,转到00401000处然后就CTRL+B,查找特征码740E8BD38B83????????FF93????????,直接定位到关键函数位置
我还不知道原理是什么,但是就这样的成了,这个函数位置每输入一个序列号都会中断一次,
往后走可以看到一个传入用户名的操作:
可以猜到下面的函数就是处理这个字符串,跟进去果然:
大概意思就是字符串和对应的数组下标(1开始)异或,然后进行累加,最后一个字符和对应位置异或结果循环左移12位,然后加上累加值,对应的十进制就是序列号:
keyGen:(控制端编程)
#include<iostream> #include<Windows.h> using namespace std; int main(int argc,char *argv[]) { int a=0x0; int k = 0x0; string name(argv[1]); //string name = "jt"; for (int i = 0; i < name.length(); i++) { int c = name[i]^i+1; a += c; if(i==name.length()-1) k = c; } k = (k >> (32 - 12)) | (k <<12); k = k + a; cout << dec << k; return 0; }