swf文件格式解析(一)
最近一直在研究加密,一層一層加進去,終于對swf結構算有了一個清晰的認識,本回合重點說文件頭的解析
為了引起大家的性趣,先引用前輩的一個例子吧
上邊是一個swf導出類查看器,拿到類名 導出素材不難,如何通過解析tag 導出類名是個學問...
下邊開始正文
SWF文件格式規范
適合屏幕顯示——需要適合屏幕顯示同時支持抗鋸齒。能夠快速渲染各種顏色格式的位圖、
動畫和交互按鈕。(ps:比如ARGB、RGBA 等)
易于擴展——使用標簽格式,讓他能夠很容易保證與Flash Player 之前的版本兼容同時又能
夠隨意擴展新的特性。
方便網絡傳輸——要能夠在有限或者不確定的帶寬下傳輸。文件使用壓縮來減少尺寸同時支
持流式渲染。采用的是二進制格式的標簽而不是像HTML 一樣的可讀性標簽,同時使用了bitpack(ps:相當于內置一些編譯好的二進制)和標記位結構(structures with optional
fields)的技巧來讓文件跟小。(ps: 標記位結構表示用一個字節中的某幾個位來作為標記,比如:某字節的二進制位:10001010,最高位的為1 表示某個標記位true,如果為0 表示某個標記位false)
簡單——這種格式需要盡量簡單以使他的播放器小一點容易實現。同時他還必須盡量少依賴
操作系統的特性,方便跨平臺。
文件獨立——這種文件的現實不要依賴像字體這樣外部的資源
可伸縮性——在有限硬件條件下能夠運行,同時在硬件條件好的情況下能夠充分發揮硬件優
勢。這一點很重要因為計算機有不同的顯示分辨率和處理能力。
迅速——高速、高質量的渲染。
腳本實現——這種格式包含各種標簽,標簽提供堆棧機解釋需要的字節碼。字節碼支持
ActionScript 語言。Flash Player 提供運行時的ActionScript 對象模型允許Flash Player 的圖
元、服務交互。
OK 理論與實踐相結合,下面我們用一個二進制查看器(我用的是HWorkS32,大家google之,很容易下載)查看一個最簡單的swf
圖一
好了,上圖就是一個普通的swf用HWorkS32打開的效果,下面開始穿插理論
SWF文件頭
所有的SWF
文件都由文件頭開始。
(類型中U
表示無符號,I
表示整型。下面的UI8
表示占8
位二進制的無符號整型,其實就是16進制的兩個字節)
圖二
文件頭都是由三個字節開始的0x46,0x57,0x53(“FWS”);或者0x43,0x57,0x53
(“CWS”)。FWS
表示文件沒有壓縮,CWS
表示第8
個字節后面是經過ZLIB
開放標準壓
縮的(文件長度字段后面)。SWF6
之后的版本才開始使用壓縮。
版本號占一個字節緊跟在標志之后。版本數字不是一個ASCII
字符而是一個8
位的數
字。例如SWF4,版本號字節為0x04,而不是ASCII
字符“4”(0x35)。
文件長度字段記錄SWF
文件的總長度,包括文件頭。對于未壓縮的swf
文件(標志位
FWS),文件長度字段的數值跟該文件長度一致。而對于壓縮的swf
文件(標志為CWS),
文件長度字段的長度表示第8
個字節之后的數據解壓縮之后的長度。(ZLIB
標準)
顯示尺寸字段定義了屏幕顯示的寬度和高度。這個字段使用一個RECT
結構來存儲(一
種可變長度的存儲結構,詳細信息看swf_file_format_spec_v10中基本數據結構中對于RECT
的介紹),這表示它的占位長度會根據bits
的描述來隨時改變。顯示尺寸字段的RECT
結構的Xmin
和Ymin
通常為0;Xmax
和Ymax
定義寬度和高度。
幀速字段定義了每秒的播放速率。這個速率無法絕對保證,比如CPU
忙的時候或者慢
的時候。
幀總數定義了SWF
文件的總幀數。(ps:注意到沒有?只有16
位,那么幀總數的極限只
能是65535
幀了)
大家看圖一中我紅線圈出來的東東,很顯然,這是一個壓縮過的swf(CWS),SWF的壓縮方式使用的是標準的ZLIB壓縮的,(FP11出測試版了,改用LAMA了,據說壓縮率提高40%)
Adobe默認會對生成的swf進行壓縮的
,壓縮過的是CWS,未壓縮的是FWS,上圖中(圖二)有說明,這里
有一點補充
壓縮過的swf =
(CWS+文件版本+文件版本)
+
壓縮的內容
這個我們后邊用bytearray解壓會用到
在理論不太充足的情況下我們還是用工具解壓,OK,SWF Compressor,這個工具google之也很多,專門用于flash壓縮解壓,很容易用明白,這里不贅述
解壓后的文件我們繼續用HexWorkstop打開,如下圖
好吧
,文件頭的說明我在上邊做了標注,下邊是開始逐個解析
首先:前面8字節
|
數據 |
含義 |
|
43 |
“F”,表示未壓縮的 |
|
57 |
“W” |
|
53 |
“S” |
|
0a |
SWF文件版本為10 |
|
44 |
文件大小為0×00000344=836字節(注意44跟33調換位置) |
接著分析70 00 09 60 00 00
4B 00 00:
第一個字節70
= 01110000
取前5位01110
= 14表示定義位數
我們在重新算一下需要的數組數,5(定義位數)+(xmin,xmax,ymin,ymax)×14(定義位數的值)=61,61/8=
7.625
也就是要取8個字節(這里兩位十六進制算一個字節,區別與常規的字節)
接著要取8位
讀取70 00 09 60 00 00 4B
00
換成2進制:0111
0000 0000 0000 0000 1001 0110 0000 0000 0000 0000 0000 0100 1011
0000 0000
接著按位排列下:01110+
00000000000000(xmin)+
01001011000000(xmax)
+00000000000000
(ymin)+00100101100000(ymax)+
000
代表的意義:(定義位數5)+(xmin=0)(xmax=4800)(ymin=0)
(ymax=2400)+(多余的)
得到的值width
= (xmax-xmin)/20 ; height =
(ymax-ymin)/20;
說明:SWF文件格式中所有的x-y
坐標信息都被存為整數,計量單位稱作緹(twips)。在SWF
中,1緹是1/20個邏輯像素
最后得到的SWF文件的尺寸大?。?40×120;
接著是幀頻:00
18,表示幀頻為24
然后是幀數:01
00,這個也要倒序來算所以是00
01,是1幀
下邊是我用AS3寫的一個解釋文件頭的代碼,大家參考之,需要對ByteArray有一定的了解
public
function
ByteArrayTest()
{
vartempByteArray:ByteArray
=
new
TestSwf();
//是否
壓縮
var
compressed:String = tempByteArray.readUTFBytes(3);
//swf
版本
_version = tempByteArray.readByte();
//文件長度
var
length:uint = tempByteArray.readUnsignedInt();
tempByteArray.readBytes(_swfByteArray);
//判斷文件格式
是否解壓
if(compressed
== COMPRESSED)
{
_swfByteArray.uncompress();
}
//這個很重要,通過這個設置可以反順序讀取雙字節字符串,例如
44 11 讀完之后是11 44 詳細內容百度之
_swfByteArray.endian = Endian.LITTLE_ENDIAN;
//
解析swf 寬度 高度 數據 rect 數據
_swfSize =
_swfByteArray.readUnsignedByte()>>3;
_swfByteArray.position =
Math.ceil(5+(_swfSize*4)/8);//
計算 rect 結束位置
_frameRate = _swfByteArray.readShort()/256;//讀取幀頻
因為低8位是小數,所以需要除以2的8次方
_frameTotal = _swfByteArray.readShort();//讀取
總幀數
trace("compressed:",compressed,"swf_version:",_version,"frameRate:",
_frameRate,"frameTota:",_frameTotal);
}
通過這個方法能夠輸出swf文件頭的大部分信息
OK
,本回合到此結束,關于Tag的解析,且聽下回講解
參考資料
http://rcant.com/wordpress/archives/260
http://www.swfdiy.com/?p=675
swf_file_format_spec_v10.pdf
avm2overview.pdf
原文地址:http://blog.sina.com.cn/s/blog_6859df370100wsv2.html
人生沒有失敗,只有自我放棄;只要不放棄,夢想總有一天會變成現實。
總結
以上是生活随笔為你收集整理的swf文件格式解析(一)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 腾达路由器如何开启WPS腾达路由器如何打
- 下一篇: 安装Beanstalk