近来,由于国人知识产权的意识较薄弱,很多高价
软件在网络上都能找到所谓的破解版,而且这破解版不仅仅被破解了,还可能被修改了一些公司、作者信息之类的,这就会给
软件的制作者或者制作公司带来极大的困扰,辛辛苦苦开发的产品被破解了,自己一分好处都得不到,反而别人还不知道是你开发的,这直接导致了国内的付费
软件发展不起来,都去使用一些所谓的“免费”的
软件。一些公司或作者为了利益可能会给这些所谓的“免费”的
软件 加上一些各种各样的后门来保护自己的利益,或使用广告等手段达到收益的目的。这样可 能就会给使用者带来困扰,导致用户群的减少,从而又影响了整体的利益,直接造成了一个恶性循环。
为了摆脱这种丑陋的循环,笔者正试图寻找一种能防止程序被破解的途径。众所周知, 反破解一般有两类方法,一是在程序代码上下功夫,像利用花代码啊、字符串加密等等;第二种方法是在程序编译完成后做的,比如像加壳之类的。
相信
大家对加壳这种方法也较了解了,但是只要程序可以在系统中运行,那么壳始终都是有脱下来的方法,而脱下来后我们可以轻松修改汇编代码。因此,我们必须在程序内部中做点手段才能防止程序被破解。
工具/原料
Ollydbg(OD)
步骤/方法
众所周知,很多破解是从字符串开始着手的,而我们一般在c++中使用字符串是直接写在函数参数中,而不是使用字符串指针,像这样:
MessageBoxW(NULL, 1"验证失败〃,1〃错误〃,MB_OK | MB_ICONERROR);
这样,如果我们在Ollydbg(OD)中打开,我们一下就可以找到对应的代码:
这样,我们可以通过修改汇编代码轻易的跳过这段代码,或者修改显示的内容等等。 假如我们现在使用另一种方法调用函数,通过字符串的函数指针,像这样(使用了一点 无意义的汇编是为了防止编译器优化代码,导致看不出效果):
LPCWSTR text, title;
—asm{
mov text. 0
mov title, 0 };
text = L〃验证失败〃; title =L"错误";
MessageBoxW(NULL, text, title, MB_OK | MB_ICONERROR);
这时,我们点开od看看:
原来可以直接看到的字符已经消失了。
但是,这种办法我们只用搜一下字符串对应的二进制数据就可以找到文本从而进行文本的篡改了。
这时,笔者想到了加密字符串的方法,常用的就是base64的算法了,但是base64就算加密后还是很容易被找到对应的ascii字符的密文和密匙从而进行修改破解。因此,我们需要一个可以便于加密和管理字符串的方法。由此,笔者再次想到了压缩数据。
不管用zlib或者lzma算法都可以很方便的压缩和解压缩字符串,我们只需要建立一张对应的字符串表就行了,同时我们要尽量保证字符串压缩解压缩算法不被轻易才出来就行了。
但是,问题又来了。我们很好地已经将字符串保护了起来,但是如果破解者在函数处下断点怎么办。这时我认为需要在函数前面包装一下,或者给函数下个钩子,在执行函数前先 检查有没有调试器的存在,如果有,那我们必须做一些伪装或者干脆不执行这个函数。但是请注意,检查是否有调试器存在最好不要直接调用IsDebugPresent,这是一及其愚蠢的做法,我们检查是否有调试器存在一般有几种方法:
1)检查FS寄存器,跳转到FS[0],再查看FS[30]单元,这个D
word是一个地址,转进 去,第三个字节就是指有没有附加调试器; 2)检查TIB(Thread Information Block)中的一些相关信息; 3)检查是否有调试器的进程或窗体,这种方法虽然不怎么准确,但是可以防患于未然。 由于FS寄存器那里的指向地址可以被修改,这种方法也不一定准确。但是如果用检查线程信息块的方法太繁琐了,很容易就被发现并修改了,检查进程和窗体虽然有点不靠谱但 是还算是一种通用的方法。看大家的取舍了。相信看到这里读者们一定有许多自己的创意吧!赶紧试试吧?