|
[求助]程序被跟踪出注册码的原因是什么?
多步验证就是分多个步骤啊! 我曾经在一个CrackMe中看到过一种方法,很值得参考。具体是谁写的CrackMe记不住了。 大致是这么个过程(只是示例,具体应用请自己发挥): // 先定义一个函数指针 typedef bool (*function_t)(std::string const&); function_t next_step = &null_stub; ... // 取得用户输入,开始验证,我还添加了个利用C++异常处理的“小伎俩” std::string sn = GetUserInput(); next_step = &step_one; try { while( next_step( sn ) ) ; // 空循环,实际工作在next_step的调用中,如果上一步成功,则调用下一步。 } catch( function_t last_step ) { if ( last_step(sn) ) throw; } ... // 实际的验证步骤由以下的函数序列完成,可以自由发挥。 bool null_stub(std::string const & ) { return false; } bool step_one(std::string const & sn) { // 对sn作第一步的验证,另外为干扰跟踪,可以添加垃圾代码等。 // 我就以第一步验证字串长度为例 if ( sn.length() < 8 ) return false; if ( sn.length() > 17 ) { next_step = &null_stub; return true; } if ( isdigit( sn[0] ) ) return false; next_step = &step_two; return true; } // 以下是第2步,等等,自由发挥吧 bool step_two(std::string const& sn) { if ( ... ) throw &good_sn; else next_step = &bad_sn; return true; } // step_three,step_four,... // good_sn,bad_sn,trial_sn,... |
|
[求助]谁能帮我看看这段是不是加了花花.
“stc/jb”是典型的花指令,是无意义指令,完全是为了干扰反汇编器。 在OD中,将光标移到stc这一行,按键盘的4(意为用4个字节的nop填充),即可去掉这个花指令。 注意:对于不同的花指令,其字节数是不一样的,在本例中是可用4个字节的nop来替换,具体情况需要具体操作,千万别误会我的意思是按4就可以去花指令! |
|
[求助]程序被跟踪出注册码的原因是什么?
你这还是没理解为什么要先进行转换。 既然我们比较的是转换之后的值,那么正确的注册码的原文是不需要的,所以程序里只需要存储temp2的值,这个值根本就是一个const,而根本不用在运行时再计算temp2=f(正确注册码),所以程序里也不用存储正确的注册码的明文了。 如果这个值是一个简单数据类型,比如32位整数,那么我们甚至根本没必要定义一个const some_value_type temp2,只需要使用一个立即数即可。 而所谓“明文”,是指“正确注册码”,而不是temp2。 所以 if ( temp2 == f( 用户输入的字符串 ) ) then success这样的代码中,并不会出现明文。 最简单的,f可以是一个单向散列函数,那么别人是无论如何也不可能通过简单的跟踪就知道正确注册码是什么,所以只能爆破。 但如果不是与固定的序列号比较,而是需要与注册的用户名相关联,f必须是一个可逆的函数,此时temp2不再是const,但我们设计算法,可以从username计算得到temp2,而不从正确的注册码得到temp2。 再说一次,这里说的是防止明文出现的方法,而不是防止简单爆破的方法。防爆需要其它的技术。 |
|
[求助]程序被跟踪出注册码的原因是什么?
上面说的是防止在内存中出现注册码的明文,所以要将字符串转换后再比较。 现在新的问题已经不是明文的问题,而防爆破的问题。 防爆破是个很复杂的问题,简单来说,如果你的验证过程只在一处进行比较,不管比较的是明文还是某种转换结果,那即使你的转换过程再复杂,因为只有一处比较,那么就可以在比较点轻松爆破。 举个例子,假设 some_value_type Encrypt(std::string sn)是一个对注册码进行处理的函数,不管这个函数有多么复杂,甚至采用高强度的加密算法,如果你的程序只是使用类似这样的判断逻辑: if ( Encrypt( GetInputSn() ) == valid_value ) { // 验证通过 } else { // 验证失败 } 这样的判断逻辑,编译后必然有一个条件分支。那么只要找到这个位置,别人不用去管正确的值或者注册码应该是什么就可以轻松爆破。 一种最简单的改进是多步验证,但实质是将一个爆破点变成多个爆破点,别人只要把整个判断逻辑搞清楚,还是可以轻松爆破的。 还有一点,就是将验证代码分散开来,而且不立即验证,而是当受保护的功能被使用之前进行验证,对于防止简单爆破也有一定效果。 关于防爆,常用的方法还有利用异常处理来改变程序流程。这方面我不是专家,不多说了。 防爆是个很有意义的话题,也是软件保护当中最基本的问题之一了。 你试试在论坛搜索“防爆”,看能不能得到什么信息。 |
|
|
|
[求助]VB-PCODE的问题
VB P-CODE当然是数据是,是由虚拟机解释执行的。 如果要用OD调试,应该下内存断点,当虚拟机读取这里的伪指令时发生中断。 不过推荐用P-CODE的专门调试器WKT VB Debugger。 |
|
[求助]32位汇编用什么书
你要会用16位汇编写程序,32位也是不在话下,反而更简单,因为32位基本都用flat内存模式,不用再考虑什么“段”的限制了(当然,Windows的FS段是个特例) 我看好像一般人都推荐罗云彬的书,我是没看过,不过既然大家都推荐,应该是不错的。主页上有书的介绍。 罗云彬的主页/ |
|
[求助]程序被跟踪出注册码的原因是什么?
sessiondiy是说,如果是进行字符串比较,那必然会出现字符串的明文。 如果将字符串转换成某种值类型,再进行值比较,就不会出现明文的字符串格式的注册码了。 PS.如果你是VB程序员,可能不好理解,需要先学一下C语言,特别是C语言中的基本数据类型,一定要搞清楚。因为VB是弱类型语言。 |
|
[求助]程序入口在程序外面是怎么回事?(od反汇编的结果)
出现这种提示,一般是由于加了壳导致的。 当然也不排除其它可能性,比如手动指令连接器参数而生成的程序等。 出现这条警告,一般来说都要先脱壳。 当然如果不是保护壳,也可以直接忽略它,带壳调试,只是无法保存UDD数据了。 |
|
[求助]谁帮我看看这个是不是oep
很像是不行的,如果是VC的,必须是完全一样的。 比如VC6,很明显的标志就是 004038ED |> \50 PUSH EAX ; /Arg4 004038EE |. FF75 9C PUSH [LOCAL.25] ; |Arg3 004038F1 |. 56 PUSH ESI ; |Arg2 004038F2 |. 56 PUSH ESI ; |/pModule 004038F3 |. FF15 3C604000 CALL DWORD PTR DS:[<&kernel32.GetModul>; |\GetModuleHandleA 004038F9 |. 50 PUSH EAX ; |Arg1 004038FA |. E8 3BD8FFFF CALL i注册机.0040113A ; \i注册机.0040113A 而其它VC的版本,也都跟你这个不一样。 其实在你给出的这个例子中,代码的地址范围根本不在模块代码段范围之内。这是临时解压的代码。甭说这不是OEP,就算是OEP,这也是被壳处理过的,是无法DUMP的。 |
|
[求助]如何反编译.Net Reactor加密过的C#程序,谢谢
请勿一贴多发。 |
|
[求助]谁帮我看看这个是不是oep
1.可以确定,这不是oep。 2.如果程序能运行但OD无法加载,说明文件头进行了变形处理,可以从论坛上搜索下载大牛修改过的OD版本。如果程序本来就不能运行,那就是脱壳后没有成功修复,它的格式本来就不正确,OD当然也就无法加载了。 3.试试先选中修改过的代码,然后再点右键看看,应该会有一个“复制到可执行文件” 4.无法定位到文件,一般来说是你修改的地方是程序运行过程中动态分配的内存空间,也就是说内存区域不是EXE文件的map。 |
|
|
|
|
操作理由
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 }}
勋章
兑换勋章
证书
证书查询 >
能力值