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