菜农电子淘宝:https://hotcomlock.taobao.com/ 准备出书:http://hotcomlock.com/hotcomlock.html
先举一个最低下和最容易犯的错误,它是软件被**的根源所在。
例如口令是“123”,键盘输入正确字符就运行,错误就退出。
那么就给逆向者留下了“特征码”字符串“123”,和分支判断是否正确。
拦截位置在键盘输入附近。
逆向者找到分支,并将有条件分支改为无条件分支(C语言的goto语句或汇编语言的jmp助记符)后,软件即可**运行。
故防止被**的两大手段就是源码信息的散列和杜绝分支判断语句的出现。
试问一个没有特征码和分支判断的软件,逆向者需要每一条语句都要分析,请问他还要继续吗???菜农肯定首先退出。
信息的长度和类型都不可能相同,但是在数学上“单向散列函数”即哈希函数就可以满足散列的需要。
单向散列函数的定义:
任意长度的信息数据都可以被散列函数动态地散列为固定长度的特定散列值。
由于信息长度必然大于固定长度的散列值,故必然发生“碰撞”,即不同的信息流具有相同的散列值。
由于碰撞的概率非常小,故可以认为一个散列值必定对应于一个自己需要的信息流(即使发生碰撞也无所谓,这就怪逆向者的运气太好)
再一个要点就是“无分支判断”。如果找到一个运算或散列结果恒为零,并用这个“零”到处“四则运算”时,基本不会影响原来的运算(当然不能做除数,但是可以做被除数)。
COM盾里就有几个(很难找)这样的“零”,例如反篡改中的“利用CRC初值碰撞保护版权信息不被篡改”,由于CRC的校验和必然恒为零,故就可以用这个crc=0。
方法大致有三种:
1.for(int i=0;i<len;i++)
改为for(int i=crc;i<len;i++)
如果反篡改通过测试,则这个crc恒为零,那么for()不受任何影响,如果程序被篡改,那么crc非零,则for()必然出错!!!
2.Array[…]
因为数组都是有大小的,访问范围超出必然发生异常或错误。
数组有读写两种,例如:
Array=x;改为Array[i + crc]=x;
或
x=Array;改为x=Array[i + crc];
当程序没有被篡改,数组不会溢出,否则必然溢出或访问错误(未溢出)。
如果不想数组溢出发生异常,可以改为
Array=crc+x;
Array=x-crc;
Array=x + 250*crc;
Array=x - crc/250;
Array=x^crc;
x=Array^crc;
…
建议采用异或运算。
所以无分支判断的关键就是如何得到这个恒为零的crc!!!
第三个就是用可逆CRC实现无分支判断。
例如需要传递三个数据或数组A,B,C,当需要比较判断内容是否正确时,必然需要分支判断语句。我们换一个思路,用ABC作为CRC的成员(权值,初值和出值),再增加一个数据或数组D,并且初始为零。
再用CRC的逆运算得到非零的验证数据,并且赋给D。
即数据或数组ABC,验证数据D(非零)。
然后对这个验证D进行CRC正运算(权值A,初值B,出值C),必然结果恒为零!!!!
COM盾里唯一的分支判断就是这个结果必须为零才能继续运行!!!
它的意思实际上数据ABC得到了验证,零则ABC全对!非零,则ABC必然发生错误,但天知道ABC谁出错了,错误在哪个位置!!!
当逆向者修改这个分支判断为goto也没有任何用处!!!
因为非零必然ABC有错误,程序如何正确运行???
而且此方法最大的好处是错误无法定位!!!
所以,菜农说COM盾理论上不可**是有理论依据的。
不要认为**软件只要找到分支即可,菜农的这个“D分支”你找到也没用!!!
因为D实际是个“诱饵”,“黄雀”实际上是“ABC”!!!(D公开了它们的对和错)
改这个“D分支”,你有本事改ABC吗???
无人能改!!!即使是数学家。菜农也无能为力!!!
菜农的知识几乎溢出了,头都大了,这几天高兴就多溢出一点,供大家学习!!!
也可以喷菜农技术陈旧,请你拿出更好的技术,63岁的菜农也想学学。
菜农HotPower@163.com 2022.9.29于西安雁塔菜地
|