SWF 文件分析

SWF 文件头分析 (一)

swf文件头包含的信息量巨大。告诉了人们SWF文件工作的方式方法等基本信息呵

Macromedia Flash文件格式是Macromedia Flash播放器在互联网上进行矢量图形和动画发布的文件格式。

SWF文件格式不是为图像编辑器之间共享图像而是为高效的解释格式设计的,它的设计是为了满足以下条件:

A:在屏幕上即时显示:此格式的最主要目标是在屏幕上即时显示和支持实例,彩色图像的快速播放,动画和交互式按钮。

B:可扩展性:此格式为标签式格式,因此其播放器能够通过增加新的特性来进行升级而兼容其播放器的早期版本。

C:网络发布:此格式能够在有限的网络资源和不可预测的网络状况下进行传输,文件被压缩到很小并且支持流式播放。SWF文件是一种二进制格式的文件,它不能像HTML文件一样可以直接阅读和理解。SWF文件使用了诸如位压缩、可选字段式结构等方法来减小文件的尺寸。

D:简易性:此格式简单的结构使Flash播放器变得很小且便于携带。另外,Flash播放器仅仅依赖操作系统特性中有限的集合。

E:文件独立性:文件的显示不依赖任何诸如字体之类的扩展资源。

F:可变性:文件能够在有限的硬件环境下很好的工作,而且能够尽可能的利用更好的硬件,这一点很重要,因为用户的计算机有着不同的显示器设置和色彩深度。

G:速度:文件能够以很快的速度和很高的质量播放。

H:支持脚本:此格式包含了约定格式的标签,标签规定了堆栈式机器解释字节码的顺序。字节码支持一种叫做ActionScript(动作脚本)的语言。Flash播放器规定了运行时的ActionScript(动作脚本)模式,此模式允许原始的绘制、服务和Flash播放器特性之间相互作用。

SWF文件的扩展名为.swf,它是一种MIME(多用途的网际邮件扩充协议)类型的应用程序(X-Shockwave-Flash)。

SWF格式经历了若干个版本。在第5个版本中,SWF的标签设置经过了一次较大规模的充实和完善。从第6个版本之后,文件格式变化较小,例如仅在ActionScript中越来越多的Flash新特性部分或者完全的被实现。因此,如果打算增加SWF文件中使用较新特性的内容,那么就应该熟悉Flash播放器提供的ActionScript对象模型,对于这些最好的参考是OReilly的《ActionScript: the Definitive Guide》,由科林·莫克出版社出版。

SWF文件头:所有的SWF文件均以以下头部开始:

我们先看下关于SWF文件头的官方说明

区域数据类型数据类型

标识

 

UI8(8位二进制无符号整数)

“F”表示该文件是未压缩的

“C”表示压缩文件(SWF6及后续版本支持)

标识UI8总是”W”
标识UI8总是”S”
版本UI8SWF文件版本
文件大小UI32文件字节大小
画面尺寸RECTtwips为单位(单位帧的尺寸)
帧速UI168.8形式的定点小数
总帧数UI16总帧数

文件头部是由一个三字节的标识符开始,为0×460×570×53(“FWS”)或者0×430×570×53(“CWS”)其中之一。“FWS”标识符说明该文件是未压缩的SWF文件,“CWS”标识符则说明该文件前8个字节之后(即文件长度字段之后)的全部数据为开源的标准ZLIB方式压缩。

ZLIB库所使用的数据格式在19501952年的请求注解, Internet标准文档(RFCS)中被详细说明。CWF文件压缩形式仅适用于版本6或者更高。

标识符之后是一个字节的版本号,这个版本号并不是一个ASCII码,而是一个8位的数字,比如,版本40×04标识,而不是ASCII码“4”(0×35)。

文件长度字段是整个包含文件头在内的文件字节长度,如果是未压缩的SWF文件(标识符FWS),那么长度字段应该是和文件大小恰好匹配,如果是一个经过压缩的SWF文件(标识符CWS),那么文件长度字段是指文件经过解压缩之后的总长度,因此它一般不会和文件大小匹配,使用未压缩的文件尺寸能够让解压过程获得更高的效率。

帧尺寸字段定义了影片的宽度和高度,它使用了RECT结构进行存储,这就意味着它的尺寸能够根据坐标编码所需的位数变化。帧尺寸的RECT结构使用的XY轴的最小值总为0。而XY轴最大值分别表示了宽度和高度(参阅位值的使用)

帧率是以帧每秒为单位的帧回放比率,此比率在SWF文件包含流式声音数据或者Flash播放器运行在低速CPU下时并不会得到保证。

帧数是整个SWF影片帧的总数量。

SWF文件结构

文件头之后是一系列连续的标签数据块,所有的标签都共享一种通用格式,因此任何解析SWF文件的程序都能跳过它不能识别的数据块。块内数据能够指向当前一个块内的偏移量,但不能指向其它数据块内的偏移量。这就使得标签能够被处理SWF文件的工具进行移除、插入或修改操作。

编写一个简单的SWF文件:

1
2
3
4
5
6
7
8
9
10
11
12
package
{
    import flash.display.Sprite ;
    [SWF (width = "240",height = "120" ) ]
    public class AS3Test extends Sprite
    {
        public function AS3Test ( )
        {
           
        }
    }
}

通过Release生成一个 SWF 文件:

Download

通过Hex Workshop 打开文件可以显示以下数据

一个简单的SWF的二进制数据:

OK了,对应着它我们来分析下刚才生成的文件

数据含义
43“C”,表示压缩的
57“W”
53“S”
0aSWF文件版本为10
44 03 00 00文件大小为 0×00000344836字节

可以看到 这是压缩过的,SWF的压缩方式使用的是标准的ZLIB压缩的,所以可以使用7-ZIP打开刚才下载下来的压缩文件:

我们取出 分解出来的 SWF文件
Download SWFTest_1.swf

右击其属性可以看到 他的文件大小是 836 字节的

通过Hex Workshop 打开文件可以显示以下数据
SWF的二进制数据:

分析:
首先: 前面 8 字节

数据含义
43“F”,表示未压缩的
57“W”
53“S”
0aSWF文件版本为10
44 03 00 00文件大小为 0×00000344836字节

接着分析 70 00 09 60 00 00 4B 00 00
第一个 字节 70 = 01110000
5位(原因不明) 01110 = 14表示定义位数
我们在重新算一下需要的数组数,4xmin,xmax,ymin,ymax)×14(定义位数的值)+5(定义位数)6161/8= 7.625
接着 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 01001011000000 00000000000000 00100101100000 000
代表的意义: (定义位数)(xmin=0xmax=4800 (ymin=0) (ymax=2400)(多余的)
得到的值 width = (xmax-xmin)/20 ; height = (ymax-ymin)/20; 为什么 要除以 20,我也不是很懂哦。
最后得到的 SWF 文件的尺寸大小:240×120;

接着是帧频:00 18 ,表示帧频为 24
然后是帧数:01 00 ,这个也要倒序来算 所以是 00 01 ,是1

这就是所有的SWF文件头的内容,接下来的内容就是SWF的真正内容了



先来说明下SWF文件结构:

SWF文件结构
文件头之后是一系列连续的标签数据块,所有的标签都共享一种通用格式,因此任何解析SWF文件的程序都能跳过它不能识别的数据块。块内数据能够指向当前一个块内的偏移量,但不能指向其它数据块内的偏移量。这就使得标签能够被处理SWF文件的工具进行移除、插入或修改操作。
SWF文件格式
*************************************

标签格式
每个标签都是由一个类型和一个长度值开始的,存在两种标签头部格式:短格式和长格式。短标签头部用于62字节或者更小的标签数据,长标签头部能够用于任何大小不超过4GB的标签数据,从长远来看这将会是非常实用的。

记录头部(短格式)

字段类型说明
标签编码和长度UI1610位标签类型 6位标签长度

注意:标签编码和长度字段并不是一个10位的位字段后面跟着6位的位字段,而是一个双字节的字,SWF文件不间断的字节排序使得这两者具有不同的布局。
该字段中的长度并不包含标签开始处的记录头部(即该字段所占有的长度)。
如果标签的长度大于或者等于63字节,那么它会被存储在长标签头部。长标签头部由一个标识长度为63字节(0x3f)的短标签头部和一个32位的长度组成。

记录头部(长格式)

字段类型说明
标签编码和长度UI1610位标签类型 6位一定是111111
长度UI32标签长度

描述标签和控制标签
SWF中的标签分描述标签控制标签两种:

描述标签这种标签描述了SWF影片的内容—形状、文本、图像、声音等等。每个定义标签都为其描述的内容指定了一个被称为“角色ID”的唯一IDFlash播放器把这些角色存放在一种叫“字典”的库里。描述标签本身不能驱动某个事件的产生。

控制标签这种标签可以创建和驱动字典中角色的实例,控制影片的播放。

SWF文件标签分类
通常,SWF文件中的标签可以任意出现。但尽管如此,也必须遵循少数几个规则:
1、一个标签只能依赖前面定义过的标签。任何一个标签都不能依赖在才后面定义的标签。
2、描述标签必须在使用它的任何控制标签之前定义。
3、流式声音标签必须以顺序方式存储。不规范的流式声音标签将会导致声音播放不正常。
4、结束标签一般是SWF文件的最后一个标签。

字典
字典是存放已经定义好的角色的库,它可以被控制标签所应用。字典的建立和使用应遵循以下规则:
1、描述标签定义了诸如形状、字体、位图或者声音。
2、每一个描述标签都被指定一个唯一的角色ID
3、字典中的内容被存储在角色ID之后。
4、控制标签能够通过角色ID在字典中找到所需内容并对其执行某种操作,例如显示形状或者播放声音。

每个角色ID必须指定一个唯一的ID,不允许重复ID。例如,第一个角色ID1,第二个是2。角色0被指定为表示空角色的专用ID
并不是只有控制标签才能引用字典。描述标签同样也可以使用字典中的数据进行更复杂的角色定义。例如,按钮和剪辑标签都使用到了定义它们内容的角色。文本标签也包含了字体角色以便于为文本选择不同的字体。
以下图表说明了描述标签、控制标签和字典之间的一种典型交互关系:

好吧,接下来我们就来看看上次的那个SWF的解析内容:

上次解析到头文件结束 00 18 01 00 位置:

第一个标签:
记录头部 44 11 11 44 0001000101 000100
因为 000100!= 111111 所以是短格式, 而且这个标签的长度为 4 ,标签的类型为 69

这里先给出从别人那里得到的一张标签和具体内容对应的一张表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
Tag -value     Tag -name
0            End
1         ShowFrame
2         DefineShape
4         PlaceObject
5         RemoveObject
6         DefineBits
7         DefineButton
8         JPEGTables
9         SetBackgroundColor
10     DefineFont
11     DefineText
12     DoAction
13     DefineFontInfo
14     DefineSound
15     StartSound
17     DefineButtonSound
18     SoundStreamHead
19     SoundStreamBlock
20     DefineBitsLossless
21     DefineBitsJPEG2
22     DefineShape2
23     DefineButtonCxform
24     Protect
26     PlaceObject2
28     RemoveObject2
32     DefineShape3
33     DefineText2
34     DefineButton2
35     DefineBitsJPEG3
36     DefineBitsLossless2
37     DefineEditText
39     DefineSprite
43     FrameLabel
45     SoundStreamHead2
46     DefineMorphShape
48     DefineFont2
56     ExportAssets
57     ImportAssets
58     EnableDebugger
59     DoInitAction
60     DefineVideoStream
61     VideoFrame
62     DefineFontInfo2
64     EnableDebugger2
65     ScriptLimits
66     SetTabIndex
69     FileAttributes
70     PlaceObject3
71     ImportAssets2
73     DefineFontAlignZones
74     CSMTextSettings
75     DefineFont3
76     SymbolClass
77     Metadata
78     DefineScalingGrid
82     DoABC
83     DefineShape4
84     DefineMorphShape2
86     DefineSceneAndFrameLabelData
87     DefineBinaryData
88     DefineFontName
89     StartSound2

所有,第一个tag对应的是FileAttributes(文件属性)
44 11 19 00 00 00 。恩恩,很好很好

第二个标签
记录头部 7f 13 13 7f 0001001101 111111
因为 111111 所以是长格式, 取后四位作为这个标签的长度 0x000001CB = 459 ,标签的类型为 77
属性是 Metadata,内容是

1
2
3
4
5
6
7
8
9
10
11
<rdf :RDF xmlns :rdf = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#' >
<rdf :Description rdf :about = '' xmlns :dc = 'http://purl.org/dc/elements/1.1' >
<dc :format >application /x -shockwave -flash </dc :format >
<dc :title >Adobe Flex 4 Application </dc :title >
<dc :description >http : //www.adobe.com/products/flex</dc:description>
<dc :publisher >unknown </dc :publisher >
<dc :creator >unknown </dc :creator >
<dc :language >EN </dc :language >
<dc :date >Dec 21, 2010 </dc :date >
</rdf :Description >
</rdf :RDF >.

第三个标签:
记录头部 44 10 = 10 44 = 0001000001 000100
短标签: 标签长度为 4 标签65
标签属性:ScriptLimits
标签头 内容为 44 10 E8 03 3C 00

第四个标签:
记录头部:43 02 = 02 43 = 0000001001 000011
短标签:标签长度为3,标签类型为9
标签属性:SetBackgroundColor
标签头 内容为 43 02 FF FF FF

第五个标签:
记录头部:5A 0A = 0A 5A = 0000101001 011010
短标签:标签长度为26,标签类型为41
标签属性:未知
标签头 内容为 5A 0A 03 00 00 00 06 00 00 00 04 00 4F 37 00 00 00 00 00 00 77 C1 FD 06 2D 01 00 00

第六个标签:
记录头部:C8 0A = 0A C8 = 0000101011 001000
短标签:标签长度为8,标签类型为43
标签属性:FrameLabel
标签头 内容为 C8 0A 41 53 33 54 65 73 74 00

第七个标签:
记录头部:BF 14 = 14 BF = 0001010010 111111
长标签:标签长度为 00000110 = 272 ,标签类型为82
标签属性:DoABC
标签头 内容为

1
2
3
4
5
6
7
BF14 1001 0000 0100 0000 6672 616D 6531 0010 002E 0000 0000 0B00 0741 5333 5465 7374 0D66 6C61 7368 2E64 6973
706C 6179 0653 7072 6974 6506 4F62 6A65 6374 0C66 6C61 7368 2E65 7665 6E74 730F 4576 656E 7444 6973 7061 7463
6865 720D 4469 7370 6C61 794F 626A 6563 7411 496E 7465 7261 6374 6976 654F 626A 6563 7416 4469 7370 6C61 794F
626A 6563 7443 6F6E 7461 696E 6572 0516 0116 0318 0216 0600 0807 0102 0702 0407 0105 0704 0707 0208 0702 0907
 020A 0300 0000 0000 0000 0000 0000 0000 0101 0209 0300 0100 0000 0102 0101 0401 0003 0001 0108 0903 D030 4700
0001 0101 090A 06D0 30D0 4900 4700 0002 0201 0108 23D0 3065 0060 0330 6004 3060 0530 6006 3060 0730 6002 3060
0258 001D 1D1D 1D1D 1D68 0147 0000

对于这部分内容可以有时间探讨,一般进行反编译 或者加密都是对这部分进行的

第八个标签:
记录头部:0C 13 = 13 0C = 0001001100 001100
短标签:标签长度为12,标签类型为76
标签属性:SymbolClass
标签头 内容为 0C 13 0100 0000 4153 3354 6573 7400

第九个标签:
记录头部:40 00 = 00 40 = 0000000001 000000
短标签:标签长度为0,标签类型为1
标签属性:ShowFrame
标签头 内容为 40 00

第十个标签:
记录头部:00 00 = 00 00 = 0000000000 000000
短标签:标签长度为0,标签类型为0
标签属性:End
标签头 内容为 00 00

原文地址:http://rcant.com/wordpress/archives/260

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值