轉載:as3加密入門-1使用alchemy進行代碼混淆

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部分):

  1. package {
  2. import cmodule.Bengine.CLibInit;
  3. import flash.display.*;
  4. import flash.events.*;
  5. [SWF(width="300", height="300", backgroundColor="#123456")]
  6. public class Main extends Sprite {
  7. public var cLibInit : CLibInit;//alchemy庫
  8. public var alcLookupLib:Object;
  9. public function Main()
  10. {
  11. cLibInit = new CLibInit();
  12. alcLookupLib = cLibInit.init();//初始化alchemy庫
  13. addChild(new Sprite())//添加一個空Sprite對象到舞臺
  14. addEventListener(Event.ENTER_FRAME,enterFrame)// 添加幀循環
  15. }
  16. public function enterFrame(e):void
  17. {
  18. removeChildAt(0)
  19. addChild(alcLookupLib.initialize())//添加alchemy生成的Sprite對象到舞臺
  20. }
  21. }
  22. }
複製代碼

代碼(C部分):

  1. #include "AS3.h"
  2. int r=0;//
  3. AS3_Val initialize(void* self, AS3_Val args)
  4. {
  5. AS3_Val spNS = AS3_String("flash.display");//取得命名空間
  6. AS3_Val spClass = AS3_NSGetS(spNS, "Sprite");//取得Sprite類
  7. AS3_Val emptyParams = AS3_Array("");//Sprite類參數
  8. AS3_Val sp = AS3_New(spClass, emptyParams);//聲明一個Sprite對象
  9. AS3_Val gpc= AS3_GetS(sp, "graphics");//取得該Sprite對象graphics屬性
  10. AS3_CallTS("beginFill", gpc, "IntType",0xffffff*rand());//使用隨機顏色填充
  11. AS3_CallTS("drawRect", gpc, "IntType, IntType, IntType, IntType",-100,-100,200,200);
  12. //畫一個方形
  13. r+=5;//旋轉角度增加
  14. AS3_Val ro = AS3_Int(r);//轉換C-Int爲AS3-Int
  15. AS3_SetS(sp,"rotation",ro);//設置當前Sprite對象旋轉角度
  16. AS3_Release(ro);
  17. AS3_Val xy = AS3_Int(150);
  18. AS3_SetS(sp,"x",xy); //設置當前Sprite對象x位置
  19. AS3_SetS(sp,"y",xy); //設置當前Sprite對象y位置
  20. AS3_Release(xy);//釋放無用變量
  21. return sp;// 返回當前Sprite對象
  22. }
  23. int main()
  24. {
  25. AS3_Val initializeMethod = AS3_Function( NULL, initialize);
  26. AS3_Val result = AS3_Object("initialize: AS3ValType",initializeMethod);
  27. AS3_Release( initializeMethod );
  28. AS3_LibInit( result );
  29. return 0;
  30. }//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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章