网上冲浪 | 反毒杀毒 | 菜鸟进阶 | 网络安全 | 实用技术 | 网络安全 | 操作系统 |
工具软件 | 电脑医院 | 网上赚钱 | 网页制作 | 网络营销 | 经典教程 | IT趣 谈 |
当前位置:IT快活林网上冲浪工具软件

扭曲变换加密 防止软件破解最好方法

一,一般来讲,加密就是加壳 我们经常考虑,一个可执行文件,如何加密才能安全呢? 一般用的手段,是加壳.加壳工具的工作(Work)原理,就是把可执行文件的代码与数据(Data)都进行加密变换,作为数据(Data)存放.生成的目标文件入口代码是加壳软件(soft)准备好的防追踪代码.经过漫长的防追踪代码后,会把原始可执行文件的代码与数据(Data)段恢复,然后跳转到原来的入口处,继续运行.这样做的缺点是,不管您的加密多强,防追踪代码多牛,只要一运行,在计算机内存中就全部恢复了.只要把计算机内存映像dump下来,反汇编一下,就清清楚楚了.还超级有可能有工具可以直接或者间接把dump下来的计算机内存映像存为可执行文件.这样加密就彻底失败了. 简单加壳是不安全的,这大家都知道了.我们一般把上述简单的加壳方式叫“压缩壳”.所以现在的加壳软件(soft)都在上述“压缩壳”的基础上,多做了一些工作(Work),譬如: * 防止计算机内存被 dump .这实际上是不可能做到的.因为Windows操作操作操作系统就不是什么一个安全操作操作系统,您怎么可能做到计算机内存不被dump呢?曾有一个壳,我用了很多种的方法dump都不成功.但最后还是找到了一个方法成功dump了.我这才惊叹dump原来有这么很多种的方法,真是防不胜防. * 修改文件入口代码.因为一般软件(soft)绝大部分的都是用常用的几种编译器编译生成的.如果加壳软件(soft)知道您是用什么编译器编的(这很容易),把入口代码破坏掉,用另外一段功能类似的代码替换他.这样dump下来的代码就比较难找到正确的入口,直接或者间接被存为一个EXE的可能性就小多了.但还是会被反汇编的. * 还有一些加壳软件(soft),支持对一个或几个重点函数加密.还超级有可能使用了虚拟机.但他们都只能重点加密少数几个函数,不可能把所有函数都加密.而不能是且对这一个函数还有很多要求.这可以想像.如果用汇编写一个函数,不加ret他可能连函数结束地址都找不到,怎么可能加密呢? 尽管加壳软件(soft)可以使用以上很多种的技术防止被追踪,分析,还原,但我认为,他们仍然没没摆脱“壳”的这一个中心思想.以上的这些技术不过是在“壳”的大前提下所做的一些小的插曲.他仍然是不安全的 II.扭曲编译的思想 做个比喻.加壳保护就好比是您桌上有宝贝,为了保护他,您在屋外围了一圈铁丝网.只要有人突破了这道铁丝网,进入您的屋子,一眼就看到了桌上的宝贝.这当然不安全. 重点函数加密的思想,就好比是,我屋外围了一圈铁丝网,我还把宝贝放进了保险箱里.如果有人突破了铁丝网,进入屋子,一眼就看到了保险箱.虽然保险箱不怎么会被轻易打开,但他如果把保险箱搬走,慢慢分析呢?这也不够安全. 最安全的,就是进了屋子,却什么也找不着.没有目标,这才是最让人头疼的. 现在的编译器,绝大部分的都是追求生成高效率的运行代码.这些代码的模式基本一成不变.有经验的程序(Procedures)(Procedures)员看反汇编代码简单跟看源码一样,毫无秘密可言.如果我们有一个编译器,他的编译目标不是为了高效,而不能是是为了防止被读懂,那该多好!我有C++源码,我能看懂.一旦编译,谁也别想通过反汇编看懂我想做什么,或者很难.遗憾的是,这样的编译器还没有. 如果我们自己编一个这样的编译器呢?不现实.工作(Work)量很大了.即使是找一个开源的C++编译器来改工作(Work)量也不得了. 直接或者间接做一个会加密的编译器行不通.而不能是一旦编译连接生成EXE后,就只能加壳了.难道就没有办法了吗?我想出一个主意,就是加密编译的中间文件OBJ,输出ASM文件,用ML编译成OBJ,然后再link连接! 这一个方法有几个好处: * OBJ文件格式相对简单.不像处理C++源文件那么工作(Work)量大. * OBJ文件中保留了很多源文件的信息,譬如符号名,代码与数据(Data),标号等等.方便加密.这些信息很多在LINK的过程当中被丢掉了.所以LINK为EXE后再处理就极不方便了. * 这是一个全新的思想!对代码的加密已经不限于加壳,而不能是是加密每一个函数,每一条系统指令.再也没有一目了然的汇编了. * 可以很容易设定加密的强度(Strength).可以根据需要,对一部分代码轻量级加密,而不能是对另一部分代码重点加密. * 可以嵌套加密.重复使用几种加密变换,无限制地使代码膨胀. * 因为是加密OBJ文件,所以不管DLL还是EXE都可顺利加密,驱动程序(Procedures)(Procedures)也可以基于这一个思想,我们的加密软件(soft)就要出台了!我们暂时叫他扭曲变换器 I.0 III.扭曲变换器 有了思想,就开始动手编码.原以为OBJ文件格式是有文档的,工程进度应该很快.没想到当中还是有很多内容需要考虑.每每说这是最后一个问题,解决了就没事了,却总是后延.前前后后居然写了差不多半年时间. 主要碰到的技术问题: * 汇编器ML会把所有的代码放到一个段中,这是不可以的.CL则通常是一个函数一个段. * 汇编器ML不能生成 COMDAT 段.尽管文档中讲他支持COMMON,但加了这一个关键字无效果(Effect). * 汇编器ML不支持 WEAKEXTERN * 汇编器ML只支持 defaultlib 这一个 drectve 关键字,其他 export, include 等关键字不支持.总之,CL编译的OBJ当中有很多属性是ML根本没有办法生成的.微软的masm真的该升级了. 还有一些问题: * 分不清代码与数据(Data).数据(Data)段中肯定是数据(Data),但代码段中却有可能不是代码,是数据(Data).这时如果您试图反汇编他,就会出错. * ?????不管如何,这些问题都一一解决了(别问我怎么做的). 采用的代码扭曲方法: * 用 JMP 把代码打乱.这已经不是什么新鲜的招数了,但他依然有效. * 用 JMP 把多个函数缠绕在一起.这样可以让分析者找不到函数从什么地方开始,到什么地方结束. * 把 call 改掉.破解者对 call 是极敏感的,这举可以让他找不到一个 call. 譬如,我可以把 call sub1改为:
mov eax, offset sub1 + 3
push offset @1 sub eax, 3
jmp eax   
      @1:
* 把 ret 改掉.破解者对 ret 是极敏感的,这举可以让他找不到一个 ret.譬如,我可以把ret写作:
push ecx
mov ecx, [esp+4]
add esp,8
jmp ecx
* 改条件跳.条件跳也是极敏感的系统指令,譬如我们可以把:
  cmp reg1, reg2
  jge L_DST       
L_NEXT:写作:       
  push eax       
  mov eax, reg1       
  sub eax, reg2       
  shr eax, 1fh     
  neg eax       
  and eax, L2 - L1       
  add eax, L1       
  jmp eax    L1:       
  pop eax       
  jmp L_DST   
L2:     
  pop eax   
      L_NEXT:
再看这一个,您能看懂是什么样的意思吗:
push offset @@L - offset L_3 + 23h
jmp L_1
L_2:       
  jz L_3       
  ret 4
L_3:             
  add dword ptr [esp+4], offset L_3 - 23h       
  add esp,4       
  retL_1:
call L_2       
      ...
这里出现了call和ret,但又不是一般所期望的那种.这里面的call不代表您发现了一个函数调用.这里面的ret不代表是一个函数的结束. * 使用堆栈代替寄存器.譬如:
MOV    EAX, DWORD PTR [ECX+0AD8h]
PUSH    EAX
MOV    ECX, DWORD PTR [EAX]可以写作:
PUSH    EAX
PUSH    ECX
MOV    EAX, DWORD PTR [ESP]
ADD    EAX, 0AD8h
MOV    EAX, DWORD PTR [EAX]
MOV    DWORD PTR [ESP+04h], EAX
PUSH    DWORD PTR [ESP+04h]
MOV    EAX, DWORD PTR [ESP]
MOV    DWORD PTR [ESP+08h], EAX
MOV    EAX, DWORD PTR [ESP]
MOV    EAX, DWORD PTR [EAX]
MOV    DWORD PTR [ESP+04h], EAX
MOV    EAX, DWORD PTR [ESP]
MOV    ECX, DWORD PTR [ESP+04h]
      ADD    ESP, 08h
您能看懂吗?很明显,这一个变换是不可逆变换.因为他本来使用了哪个寄存器,已经没有办法知道了. * ……还可以想出很多扭曲变换的方法.化繁为简只有一种方法,化简为繁可以有无穷很多种的方法.还有一些功能: * 在C语言(Language)中,使用 #pragma code_seg(".code$curve_NoChange") 来指示后面的代码不做任何加密.因为有时候有些代码含有大量的循环,加密他会要紧影响效率. * 在C语言(Language)中,使用 #pragma code_seg(".code$curve_Max") 来指示后面的代码重点加密.譬如后面是与注册算法相关. 现在的扭曲变换器我叫他I.0版,已经非常稳定了.我用他把VC6的库文件LIB都处理了一遍,再用LIB.exe工具写回LIB文件中,我们就有了一套加密后的库.如果用这套库来LINK您的软件(soft),分析者就很难从汇编中找到哪个是printf哪个是strcpy,IDA也根本没有办法识别MFC静态链接的库函数了.能把VC6的库都加密一遍不出错,我相信他已经很强壮很稳定了. 用他来加密我们做的一个共享(Sharing)软件(soft),就再也没人写出注册机了.去读懂大量的经过以上变换的代码是不可想像的.但还是有人暴破了,真佩服他.我会不断丰富加密方法,让暴破者都放弃. 现在的扭曲变换器还只支持VC6使用的COFF格式的OBJ,下一步,要分析一下VS2005的OBJ格式,尽快支持他. 有几点: * 本软件(soft)暂时不对外发布,只自己使用.如果有朋友想对自己的代码加密,可以把OBJ文件发给我加密.防止所有的软件(soft)都用这一个加密,我们会IDA的就没饭吃了 :( * 现在只支持VC6的OBJ格式,就是 COFF. 下一步想支持VS2005的OBJ格式,碰到了问题.VS2005的debug编译OBJ还是 COFF, 但 release 编译的OBJ就不知道是什么格式了,找不到资料.有哪位朋友能帮助解决一下这一个问题?谢谢. 我们以用户名 12345678 错误的注册码 33333333 为例题,在40147E处下断.我们可以看到,程序(Procedures)(Procedures)把我们的注册码算成了16进制的 12 12 12 12 AF AF AF AF 然后后面继续,在40180A处把我们的注册码算成 15 16 17 18 B6 B7 B8 B9.然后在 405310 把我们的用户名展成 31 32 33 34 35 36 37 38. 到此处为止,在堆栈里,把我们的用户名,注册码展成堆栈地址 12FF18. 假注册码部分16进制:32 12 12 12 AF AF AF AF 15 16 17 18 B6 B7 B8 B9 1D 1E 1F 20 BE BF C0 C1 25 26 27 28 C6 C7 C8 00. 用户名部分:31 32 33 34 35 36 37 38 31 32 33 34 35 36 37 38 31 32 33 34 35 36 37. 展开后就是用户名与注册码混合运算了,在40226A 处可以看到运算的结果(这一个过程最为复杂,的确没时间仔细分析,所以没细看)在 4083DD 处我们可以看到 SUB EAX,3467ABDE 这就是爆破口,把他改成 MOV EAX,00爆破成功!!!!反正就是爆破 4083DD处,把他改为 B8 00 00 00 00, 运行就OK了!!!
-------
很早就看到过了.好好像是TRW2000作者的原创,这一个不错的主意,这一个加密方法要从软件(soft)编译时就加进去,也就是说,要所有的软件(soft)作者都明白这一个方法,这显然是不现实的.
[]作者:本站整理  来源:不祥