[轉]as3的abc文件及as3代碼混淆的一點方法


首先先說說as的abc文件

從下面的am2框架圖可以看出abc文件所處的位置
 


abc文件

abc文件就是flash player可以直接解釋執行的的字節碼,該文件中的內容會直接嵌入到swf文件的doABC標簽下。源碼的asc包就是處理abc格式的。通常在編譯AS項目時,as3腳本文件都會被編譯成abc文件然后再生成doABC標簽。

手工編譯as3到abc文件

在flash sdk的lib目錄下,有個asc.jar,該文件就是用來生成abc文件的java程序,機器上要安裝java運行時。

    * 新建一個文件Hello.as,並寫上一行代碼     print("Hello");
    * 在控制台中輸入cd C:\Program Files\Adobe\Adobe Flash Builder 4\sdks\4.0.0\lib
    * 在控制台中輸入java -jar asc.jar Hello.as,
      編譯成功,輸出Hello.abc, 79 bytes written

察看Hello.as文件所在目錄會發現新生成一個Hello.abc文件。

繼續上面,把Hello.as文件改為一個class看看;

    * 把的代碼改成
      package {
       import flash.display.Sprite;
            public class Hello extends Sprite {
                  public function Hello() {
                       trace("Hello");
                  }
            }
      }
    * 編譯,出現[Compiler] Error #1017: The definition of base class Sprite was not found.提示,這是由於缺少Sprite類的定義
    * 導入as基本庫:在asc源碼包下有個abc文件,里面有builtin.abc,playerglobal.abc,toplevel.abc三個文件,他們就是flash的基本庫。asc的命令行參數可以直接用java -jar asc.jar來查看。
      重新輸入命令
      java -jar asc.jar -import E:\work\sdksrc\modules\asc\abc\builtin.abc -import E:\work\sdksrc\modules\asc\abc\playerglobal.abc Hello.as
      可以看到編譯成功。

ABC文件的格式

abcFile 
{
u16 minor_version
u16 major_version
cpool_info constant_pool
u30 method_count
method_info method[method_count]
u30 metadata_count
metadata_info metadata[metadata_count]
u30 class_count
instance_info instance[class_count]
class_info class[class_count]
u30 script_count
script_info script[script_count]
u30 method_body_count
method_body_info method_body[method_body_count]
}



常量池

cpool_info
{
u30 int_count
s32 integer[int_count]
u30 uint_count
u32 uinteger[uint_count]
u30 double_count
d64 double[double_count]
u30 string_count
string_info string[string_count]
u30 namespace_count
namespace_info namespace[namespace_count]
u30 ns_set_count
ns_set_info ns_set[ns_set_count]
u30 multiname_count
multiname_info multiname[multiname_count] 
}


在abc文件(參考“flash sdk開源相關的一些東西”)中,所有的字符串值都會保存到常量池的字符常量string_info string[string_count] 段中,因此要混淆代碼,只要把該段中的字符串值進行混淆就可以了。

但flash中的api中的類和方法以及代碼中使用的字符串常量,還有導出類(SymbolClass標簽中的)等是不能混淆的。實際上,需要混淆的只是自己定義的類和類的屬性、方法。用戶自己定義的類及屬性方法可以在

u30 class_count 
instance_info instance[class_count]

class_info class[class_count]

段中找到。class_count 是所有用戶定義的類的總數。段的定義結構如下:

 instance_info  

 u30 name 
 u30 super_name 
 u8  flags 
 u30 protectedNs  
 u30 intrf_count 
 u30 interface[intrf_count] 
 u30 iinit 
 u30 trait_count 
 traits_info trait[trait_count] 
}

class_info  

 u30 cinit 
 u30 trait_count 
 traits_info traits[trait_count] 
}

 

另一個問題,在abc文件中,所有相同的字符串都會保存為同一個字符串值常量,當類或方法名根代碼中的字符串相同時,則不能混淆。如下例子:

       class Test {

             public function Test() {

                   var str:String = "Test";   

                   trace(str);

             } 

       }

這時候,如果將Test類名混淆為a,那么str的值也會變為a,這樣會改變str的值,因此混淆時還需要排出跟代碼中字符串相同的類、方法或屬性。

想要找出代碼中使用的字符串,需要分析方法體內容,即

 u30 method_body_count 
 method_body_info method_body[method_body_count] 
段內容。方法體定義如下:

method_body_info 

 u30 method 
 u30 max_stack 
 u30 local_count 
 u30 init_scope_depth  
 u30 max_scope_depth 
 u30 code_length 
 u8  code[code_length] 
 u30 exception_count 
 exception_info exception[exception_count] 
 u30 trait_count 
 traits_info trait[trait_count] 
}

方法體的 

 u30 code_length 
 u8  code[code_length] 

段記錄了方法中的所有操作,只要找到其中的OP_pushstring(操作碼0x2C)即為字符串賦值操作,根據該操作碼后的字符串索引即可在字符串池中找到該字符串,將此字符串加入到排除列表即可。





免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM