能力值:
( LV5,RANK:60 )
|
-
-
2 楼
最简单的办法程序里面多处验证
|
能力值:
(RANK:260 )
|
-
-
3 楼
爆破,说白了就是你的判断逻辑太简单,比如if()...else...,或者类似的。
这样的逻辑,只要将你的 if 逻辑改成 if not逻辑,或者干脆改成if (true)就是通常所说的破解。
如果不使用这种简单的程序逻辑结构,比如用数据驱动代替条件判断。最简单的比如C++的运行时多态,或者退化到C的跳转表或函数指针表。
完全防爆破的方法是不存在的。但是,多一个if逻辑,就多一份爆破的可能。虽然即使不用if,也是可能爆破的,但“jmp [eax*4+0xXXXXXXXX]”的方式总比“cmp eax,1 \ je 0xXXXXXXXX”的代码隐蔽性更强一些的。
以上是从编程方面说的,再加上其它一些ANTI的方法或扰乱的方法,比如SEH,动态解码指令,或者加保护壳等,可以大大增加跟踪的难度,至少会让那些只会查找“字符串”,只会修改“关键跳”的新手望而却步了。
|
能力值:
( LV8,RANK:120 )
|
-
-
4 楼
你说得很好啊,看来以后还要多多学习。
还想问一个,你说到的“C的跳转表或函数指针表”,是什么意思啊。
在C语言中好像没听过这些词语,能指点下吗?
|
能力值:
( LV8,RANK:120 )
|
-
-
5 楼
哦,我在网上找到这方面的内容了。
谢谢你给我的启发。
|
能力值:
(RANK:260 )
|
-
-
6 楼
我说得也不准确,跳转表在汇编语言中程序员是可控制在,在C中跳转表通常是编译器优化的结果。
但函数指针表,则是C程序员可以控制的东西。实际上在C++中的运行时多态,就是基于函数表的原理,只不过是从另一个角度抽象了,被叫做vTable了。
举个例子:
void DoRealWork(void*p)
{
//这个函数是注册版本的
}
void DoTrialWork(void*p)
{
//这个函数演示版本的
}
void DoNothing(void*p)
{
//这个函数是什么都不做的,比如试用期过了等等。
}
typedef void (*function_ptr)(void*);
functin_ptr theFunctions[16]=
{
&DoRealWork,
&ExitProcess,
NULL,
&ExitProcess,
NULL,
&DoNothing,
&DoNothing,
...
};
这样,你设计一个算法,将日期、用名、注册码进行一定的处理,结果返回一个整数值。然后用这个值去索引函数表,并调用,类似这样:
void DoWork(void*p)
{
functin_ptr f = theFunctions[ CheckRegistInfo( name, code, date )];
f(p);
}
在这面这个函数里,并没有if结构,那么简单的爆破便不成立了,当然跟踪高手在弄明白了这其中的流程之后,要破解还是可能的,毕竟没有百分百不可破解的软件。
关键在于CheckRegistInfo函数,当正确时返回什么值,不正确时返回什么值等等,这个算法很重要,而且最好是只使用算术和逻辑运算,而不使用条件语句,如if等。
另外,还可以将函数表可以设计为更大,比如256个指针,而CheckRegistInfo函数返回unsigned char类型的值,这样你的算法设计便更加灵活,并且正确的函数散列于其中,其它部分填充一些无效的,或迷惑的值,而在外面用SEH将函数指针的调用包装起来。这样,试图单纯从数据上分析来逆向就会很难了,从而解密者不得不去分析CheckRegistInfo函数的计算过程。不过它即使分析清楚了,也很可能不知道究竟返回值是几才是正确的,所以还得去检查函数表中的指针的有效性。
此法具有一定效果,特别对于初级的解密者,可以说逆向的难度还是比较大的。如果再加上其它一些干扰手段,我个人认为可以达到中级以上的强度。
不过以上全部只是思路,算是抛砖引玉,编程功力高的人可以试试,也欢迎讨论。
|
能力值:
( LV6,RANK:90 )
|
-
-
7 楼
好高深、、
看高人讨论
|
能力值:
( LV8,RANK:120 )
|
-
-
8 楼
哇,真有意思啊。
你的介绍真是让我大开眼界啊,原来为了防止破解,在编程的时候还有这么多的手段。
我以前学编程,只是想着怎么去实现我要做的功能,从来都没往防破解这方面去考虑。
你说得太棒了,让我马上就想试试这个方法。
最后有一点没看明白,
“在外面用SEH将函数指针的调用包装起来”是何意?
PS:我对SEH只是停留在听说的阶段,还没有细细学过。
另外,我对算法的设计,也完全是毫无经验的。
你提到“最好是只使用算术和逻辑运算,而不使用条件语句”,
不知是为何这样?
再次感谢你的帮助,让我在学习中看到了曙光。
谢谢。
|
能力值:
( LV8,RANK:120 )
|
-
-
9 楼
哦,我知道了,CheckRegistInfo的算法“只使用算术和逻辑运算,而不使用条件语句”,
这样做还是为了防爆破的。
其他知识我会上网继续搜索的,谢谢。
|
能力值:
( LV8,RANK:120 )
|
-
-
10 楼
顶起,希望书呆彭再帮看看。
|
能力值:
(RANK:260 )
|
-
-
11 楼
在外层用SEH,拿我给出的例子来说,函数表中有用的函数在其中的分布是非常散的,它们之前的间隙,可以用一些占位函数(如DoNothing)填充,也可以用无效的值(比如NULL)来填充。
如果填充的值当中有无效的函数指针,那么在调用时肯定会引发异常。为此,加上SEH。
|
能力值:
( LV2,RANK:10 )
|
-
-
12 楼
高人都在这里高谈阔论啊,我却在这里坐井观天。
|
能力值:
( LV2,RANK:10 )
|
-
-
13 楼
很高深。。这是长期实践得来的。
|
|
|