|
[求助]程序容易被爆破的原因是什么?
我说得也不准确,跳转表在汇编语言中程序员是可控制在,在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函数的计算过程。不过它即使分析清楚了,也很可能不知道究竟返回值是几才是正确的,所以还得去检查函数表中的指针的有效性。 此法具有一定效果,特别对于初级的解密者,可以说逆向的难度还是比较大的。如果再加上其它一些干扰手段,我个人认为可以达到中级以上的强度。 不过以上全部只是思路,算是抛砖引玉,编程功力高的人可以试试,也欢迎讨论。 |
|
|
|
|
|
[求助]关于keymake的问题
哇,刚看了下keymake的说明书,惭愧啊,原来如此强大。 以前复制汇编代码都是用MASM或VC的程序框架来写注册机的。今天才发现刘健英的keymake的强大功能。真好用。 |
|
|
|
[求助]无法下断点?
断不下来就换个方法。没有什么断点是保证有效的。程序是千差万别的,没有百分之百的通用的方法。 消息断点,实际上是用条件断点实现的。只有条件被满足时才会中断。无法保证程序一定会处理你说的什么“buttonup"消息(不是你写错了就是我孤陋了,没听说过有这么个消息)。 再退一步,只有程序自已创建的窗口,消息断点才可能有效果。如果是mfc或wol的框架,消息断点要么不起作用,要么会不停地中断,根本无法到达关键代码的。 |
|
|
|
[求助]程序容易被爆破的原因是什么?
爆破,说白了就是你的判断逻辑太简单,比如if()...else...,或者类似的。 这样的逻辑,只要将你的 if 逻辑改成 if not逻辑,或者干脆改成if (true)就是通常所说的破解。 如果不使用这种简单的程序逻辑结构,比如用数据驱动代替条件判断。最简单的比如C++的运行时多态,或者退化到C的跳转表或函数指针表。 完全防爆破的方法是不存在的。但是,多一个if逻辑,就多一份爆破的可能。虽然即使不用if,也是可能爆破的,但“jmp [eax*4+0xXXXXXXXX]”的方式总比“cmp eax,1 \ je 0xXXXXXXXX”的代码隐蔽性更强一些的。 以上是从编程方面说的,再加上其它一些ANTI的方法或扰乱的方法,比如SEH,动态解码指令,或者加保护壳等,可以大大增加跟踪的难度,至少会让那些只会查找“字符串”,只会修改“关键跳”的新手望而却步了。 |
|
[求助]求助大牛帮我看看这个是个什么算法啊?
如果你已经去花了,来看一下它的算法。 猜测[EBP-0xDC]处是输入的用户名吧。 00401A8E 7E 2A JLE SHORT 00401ABA 这一段用伪C描述为: extern unsigned long table_48B834[0x100]; { unsigned long t = 0xFFFFFFFF; // 寄存器变量esi for (int i = 0; i < strlen(name); ++i ) { unsigned char c = name[i] ^ (t & 0xFF); t = (t >> 8) ^ table_48B834[c]; } } 其中table_48B834是一个查询表,它是怎么来的呢,看这一段代码: 00401900 /$ 56 PUSH ESI 用伪C描述是: for ( int i = 0; i < 0x100; ++i ) { int t = i; for ( int j = 0; j < 8; ++j ) { if( t是奇数 ) { t ^= 0xBA511FE1; } t >>= 1; } table_0048B834[i] = t; } 可以看到这个表是一个常数表,与输入信息无关。 至于下面这个循环,从你贴出的代码来看似乎没有什么作用,因为它影响到的变量[ebp-4],[ebp-8],[ebp-0x0c]在后面都没有被使用。所以姑且认为它是作者扰乱视听的作用吧。 MOVSX ECX, BYTE PTR SS:[EBP+ESI-DC] ;取用户名第一个字符 |
|
|
|
[求助]Visual c++ 6.0中怎样添加WM_MOUSELEAVE消息
使用TrackMouseEvent()函数,才可以让系统发送WM_MOUSE消息。请参考MSDN关于API的说明和以下这个帖子。 http://bbs.pediy.com/showthread.php?t=76795 |
|
[求助][求助]Billy Belceb 病毒教程(win32)编译出错
要copy也只能是从纯文本的文件当中,前提是你确信copy的代码是经过良好测试的。 我要睡了,这不算什么大问题,你自行解决就行了。 PS 如果实在不愿意手输入代码,用正则表达式,将所有非打印字符全部用空格替换(一般不宜直接去掉)或许能解决问题。否则,还是老老实实地敲代码吧。 |
|
[求助][求助]Billy Belceb 病毒教程(win32)编译出错
有非法字符,由于是不显示的,所以人看起来没问题,但汇编器扫描文件的时候就不认识了。 这是常识,不要copy/paste代码,否则造成的错误是不易察觉的。如果编译器能够指出全部错误,那还算幸运,如果编译器恰好把某些错误给漏掉了,那将来程序出了错误你得费老了劲去寻找错误! |
|
[求助]汇编程序的不解
只要调用的参数的点落在子窗口的范围(一个矩形区域)之内,它就能返回该子窗口的句柄。 |
操作理由
RANk
{{ user_info.golds == '' ? 0 : user_info.golds }}
雪币
{{ experience }}
课程经验
{{ score }}
学习收益
{{study_duration_fmt}}
学习时长
基本信息
荣誉称号:
{{ honorary_title }}
能力排名:
No.{{ rank_num }}
等 级:
LV{{ rank_lv-100 }}
活跃值:
在线值:
浏览人数:{{ visits }}
最近活跃:{{ last_active_time }}
注册时间:{{ user_info.create_date_jsonfmt }}
勋章
兑换勋章
证书
证书查询 >
能力值