as3加密入門-1使用alchemy進行代碼混淆
from:http://bbs.9ria.com/viewthread.php?tid=47088
最近在考慮SWF安全方面的技術,看到一些關於這方面不錯的技術文章,記錄下來方便查閱.以下爲轉載內容:
聲明:這裏所討論的(以及後續相關的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-Int
- AS3_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/lib
source /cygdrive/f/alchemy/alchemy-setup
alc-on
gcc ALCSWF.c -O3 -Wall -swc -o ALCSWF.swc
生成ALCSWF.swc
AS3部分:打開ALCSWF.as3proj->build project