使用 SecureSWF 做包含外部模組的專案時,遇到混淆過頭
導致外部 SWF 模組無法正常執行的問題
當然基本的共用類別需要必須先排除在外
可是還是無法正常執行
測試簡化問題之後,發生條件如下

主程式 SWF 包含一共享父類別定義
該類別宣告了 protected getter/setter member
且型別是一個 interface
外部子 SWF 模組繼承此共享父類別

當兩個 SWF 混淆過之後 (排除共享父類別)
外部子 SWF 模組載入後,嘗試存取 super protected member
會得到 ReferenceError: Error #1065: 變數 default::foo 未定義。
以下是測試原始碼:

Main.as

package {
 import com.ticore.obfu.SupClass;
 
 import flash.display.Loader;
 import flash.display.Sprite;
 import flash.events.Event;
 import flash.net.URLRequest;
 import flash.system.ApplicationDomain;
 import flash.system.LoaderContext;
 
 /**
  * Main 主程式 SWF
  * 持有共用的 SupClass 類別定義
  * 依據自身 application domain 產生 child domain
  * 用來載入繼承 SupClass 的外部 SWF 模組
  */
 [SWF(width="300", height="200")]
 public class Main extends Sprite {
 
  public var currAppDom:ApplicationDomain = ApplicationDomain.currentDomain;
  public var childAppDom:ApplicationDomain = new ApplicationDomain(currAppDom);
 
  public var ldr:Loader = new Loader();
 
  public var req:URLRequest = new URLRequest("Mod.swf");
  public var ldrCxt:LoaderContext = new LoaderContext(false, childAppDom);
 
  public function Main() {
   // 明確引用父類別定義,編入 parent application domain
   SupClass;
 
   ldr.contentLoaderInfo.addEventListener(Event.COMPLETE, onLoadCompleteHandler);
   ldr.load(req, ldrCxt);
   addChild(ldr);
  }
 
  public function onLoadCompleteHandler(e:Event):void{
   trace("onLoadCompleteHandler();");
  }
 }
}

com/ticore/obfu/SupClass.as

package com.ticore.obfu {
 import flash.display.Bitmap;
 import flash.display.IBitmapDrawable;
 import flash.display.Sprite;
 
 /**
  * 共用的 SupClass 類別定義
  * 帶有 protected getter/setter 且型別為 interface
  */
 public class SupClass extends Sprite {
 
  protected var _foo_:IBitmapDrawable = new Bitmap();
 
  protected function get foo():IBitmapDrawable {
   return _foo_;
  }
 
  protected function set foo(value:IBitmapDrawable):void{
   _foo_ = value;
  }
 }
}

Mod.as

package  {
 import com.ticore.obfu.SupClass;
 
 import flash.display.Sprite;
 import flash.text.TextField;
 
 /**
  * 外部 SWF 模組
  * 繼承共用的 SupClass 類別定義
  * 嘗試用不同方式存取 SupClass protected getter member
  */
 [SWF(width="300", height="200")]
 public class Mod extends SupClass {
 
  public var txt:TextField = new TextField();
 
  public function Mod() {
   init();
   doTrace(new Date());
 
   // 直接呼叫 super protected getter member 會得到 error
   try {
    doTrace("foo:", foo);
   } catch (e:Error) {
    doTrace(e);
   }
 
   // 用 with block
   with (0) {
    doTrace("foo:", foo);
   }
 
   // 用關聯陣列存取算子
   doTrace("foo:", this["foo"]);
  }
 
 
  public function init():void{
   txt.wordWrap = true;
   txt.width = 250;
   txt.height = 150;
   txt.x = txt.y = 25;
   txt.border = true;
   addChild(txt);
  }
 
  public function doTrace(...args):void{
   trace.apply(null, args);
   txt.appendText(args.join(" ") + "\n");
  }
 }
}

用來混淆的 Ant Task

<?xml version="1.0" encoding="utf-8"?>
<project name="SecureSWF Test" default="protect main" basedir=".">
 
 <property environment="env" />
 
 <!-- secureSWF Pro v3.61.5987 -->
 <taskdef name="protect"
   classpath="${env.SECURE_SWF_HOME}\secureSWF.jar"
   classname="secureSWF.ant.ProtectTask" />

 <target name="protect main">
  <protect outputPath="secure">
   <fileset dir="bin-release" includes="**.swf"/>
   <rule filter="com.ticore.obfu.*" rename="false" />
  </protect>
 </target>

</project>

非常神奇的是,用 ASV 觀察混淆過的 SWF
明明沒有任何混淆的跡象,可是卻會造成執行失敗
而用 with block 與關聯陣列運算子,卻又能避開問題

解決方式除了上面兩種方式
SecureSWF 還有定義一個參數是 renameProtectedNamespaces
設為 false or off 就可以了

測試用的 Flash Builder Project 原始檔案下載