as3加密入门-1使用alchemy进行代码混淆

    技术2026-08-22  20

    声明:这里所讨论的(以及后续相关的as3加密教程)所有方法都来自网络和我个人试验,如果有错误,还请大家赐教,所有其它内容均为个人观点,若有不同意见,也可提出讨论。所列举方法与代码引用了许多其它资料,在此可能不会一一列举出,相关作者如有需要注明来源,可以自行联系我(回帖或邮件都可)。另外,这几篇加密入门教程其实也可以看成普通教程,只不过披件“加密”外衣而已。比如,alchemy混淆可以看成简单的alchemy调用as3函数教程,跳转指令混淆可以看成as3c的hello world级入门教程。为什么要加密?1保护游戏数据,防止外挂作弊2客户要求3老板要求4保护个人权利之前对swf加解密没有研究,也不太感兴趣。一月份有位朋友同我探讨这一问题,才开始关注,也学到不少相关东西,空余也做了几个加壳、混淆试验。虽然商业的swf加密、破解软件已很成熟,网上关于这方面的资料却不多,这里总结了一下几个实际中常用as3代码混淆方法。如果说加壳是对swf化装,那么混淆就是整容,不,更确切的说是毁容,对破解者来说是才是整容。俗话说,毁容容易整容难,这就是混淆的优势。这里总结几个常见的方法,来把你的swf毁个面目全非。据我了解,实际中as3程序员对代码保护基本上都是手动混淆(修改变量名)。强制使用非法变量名完全可以保护住代码,尤其是源代码比较长,类文件比较多时。反编译出的东西基本没可用性。很少有人去用加密软件,即时用加密软件,基本上也就混淆一下代码,深度加密(加壳,随机跳转指令等)会降低flash运行效率,并很容易带来一些不可预知错误,甚至有时多次调试都发现不了,得不偿失。所以这里首先推荐强制使用非法变量名混淆方法。另外,我认为alchemy是flash10最有用、最有意义的东西(3D API目前就是个鸡肋,pixel bender实现的功能太弱,其他新功能也没见对flash有何惊人改变),alchemy的出现同时也给所有的swf反编译软件带来了一次“危机”。这里第一部分是一个简单的alchemy混淆代码教程(其实就是alchemy调用flash函数教程)。对alchemy不感兴趣的朋友可直接跳到第二部分-强制使用非法变量名。第一部分 使用alchemy混淆as3代码(选用)为什么要用alchemy?1.C语言是程序员的老本行,alchemy使用C/C++写代码,对多数程序员来说要比用as3更加得心应手。2.Alchemy代码效率高,使用一些优化指令,尤其对计算速度提升明显。Joa Ebert给过一个极端的例子:纯as3的fps3~5,使用Alchemy优化指令编译后fps飙到200多。当然一般来说速度不会这么大幅改进。我的Bengine引擎最初是纯as3写的,fps0~5,使用Alchemy后可达到8~40.3.Alchemy代码移植性好,尤其对纯bitmapdata操作的试验,可很方便地与allegro,sdl程序代码互相转换。目前没有反编译软件可导出使用Alchemy写的源C/C++代码。Alchemy使用C/C++直接生成AS3字节码,目前反编译软件只能针对as3代码反编译,而且编译生成swc就自动加入c标准库,直接导致源文件变大,导致破解难度加大。我估计以后也很难有反编译软件可以导出alchemy源C/C++代码,引用一段asv作者Burak关于反编译alchemy的评论"For Alchemy some new bytecode instructions were introduced to AVM2 (see Scott Petersen slides PDF). I'm not sure what this will mean for ASV. If we will be dealing with a full featured optimizing C/C++ compiler, decompiling back to C/C++ will be really hard work for us, that I can say..."(一些新的bytecode指令因alchemy而引入AVM2,我不敢肯定这对asv意味着什么。如果我们要面对的是一个全功能优化的C / C + +编译器,反编译回C/C++对我们来说将是非常困难的,我可以说…)使用alchemy混淆代码简单例子(源代码见附件):其实反编译器对HaXe生成的代码支持也不好。直接用HaXe写,代码反编译出,绝大多数不能编译,但一般代码结构还很清楚。如果项目比较大,使用HaXe写基本也用不着去加密。不喜欢使用HaXe原因:1.已有了Alchemy,2.HaXe资料少。基本思想,代码关键部分使用alchemy写(其实只有某一重要的小部分用alchemy也可以),as3部分只写一个class Main extends Sprite作容器。下面代码给了一个简单例子,其实as3部分还可以减少,转为alchemy部分。(项目文件以打包提供下载,见附件)代码(as3部分):

    package {import cmodule.Bengine.CLibInit;import flash.display.*;import flash.events.*;[SWF(width="300", height="300", backgroundColor="#123456")]public class Main extends Sprite {public var cLibInit : CLibInit;//alchemy库public var alcLookupLib:Object;public function Main(){ cLibInit = new CLibInit();alcLookupLib = cLibInit.init();//初始化alchemy库addChild(new Sprite())//添加一个空Sprite对象到舞台addEventListener(Event.ENTER_FRAME,enterFrame)// 添加帧循环}public function enterFrame(e):void{removeChildAt(0)addChild(alcLookupLib.initialize())//添加alchemy生成的Sprite对象到舞台}}} 复制代码

    代码(C部分):

    #include "AS3.h"int r=0;// AS3_Val initialize(void* self, AS3_Val args){AS3_Val spNS = AS3_String("flash.display");//取得命名空间AS3_Val spClass = AS3_NSGetS(spNS, "Sprite");//取得Sprite类AS3_Val emptyParams = AS3_Array("");//Sprite类参数AS3_Val sp = AS3_New(spClass, emptyParams);//声明一个Sprite对象AS3_Val gpc= AS3_GetS(sp, "graphics");//取得该Sprite对象graphics属性AS3_CallTS("beginFill", gpc, "IntType",0xffffff*rand());//使用随机颜色填充AS3_CallTS("drawRect", gpc, "IntType, IntType, IntType, IntType",-100,-100,200,200);//画一个方形r+=5;//旋转角度增加AS3_Val ro = AS3_Int(r);//转换C-Int为AS3-IntAS3_SetS(sp,"rotation",ro);//设置当前Sprite对象旋转角度AS3_Release(ro);AS3_Val xy = AS3_Int(150);AS3_SetS(sp,"x",xy); //设置当前Sprite对象x位置AS3_SetS(sp,"y",xy); //设置当前Sprite对象y位置AS3_Release(xy);//释放无用变量return sp;// 返回当前Sprite对象}int main(){AS3_Val initializeMethod = AS3_Function( NULL, initialize);AS3_Val result = AS3_Object("initialize: AS3ValType",initializeMethod);AS3_Release( initializeMethod );AS3_LibInit( result );return 0;}//end of int main 复制代码

    编译过程:C部分:打开cygwin->cd /cygdrive/f/alchemy/ALCSWF/libsource /cygdrive/f/alchemy/alchemy-setupalc-ongcc ALCSWF.c -O3 -Wall -swc -o ALCSWF.swc生成ALCSWF.swcAS3部分:打开ALCSWF.as3proj->build project编译结果见附件。大家可以尝试使用反编译软件看下源码。 alcswf.zip (161.04 KB)

    最新回复(0)