[原创]python获取swf的宽和高
2011-02-22 12:06
316 查看
swf格式其实是公开的,据说在adobe的官网上有,不过我没找到,感兴趣的同学去找原文阅读,因为项目只需要提取出swf的宽和高,所以只作相关分析。
00000000: 4357 5308 483a 0500 789c 7cbb 6554 5c4d
00000010: d335 7c70 770d eeee 1adc dd1d 0602 c1dd
首先载入我们的swf. 切换到十六进制方式。我们需要的宽和高信息就在上面的字节序列里,其中
头3个字节内容为43 57 53 或 46 57 53。 其中43 57 53 代表的是cws,也就是这个Swf是压缩过的。而46 57 53代表的是fws,也就是这个swf是未压缩过的。本次实验中使用的flash基本上是cws的。如果新建一个空白fla,再导出swf的话。那么头部就是fws的。同学们可以自己实验下。这3个字节对于我们来说的作用是cws的swf我们需要对其内容进行解压缩。而这种压缩方式就是标准的zlib格式。而fws的我们直接就可以分析了。
接下来的5个字节08 48 3a 05 00我们忽略不计,里面包含了flash的版本号和其它信息,感兴趣的同学自己看看。
最关键的是78 9c 7c bb 65 54 5c 4d d3这里9个字节,里面包含的是宽和高的信息。这里是要运算得到的。注意我们不能直接拿来运算,先由头3个字节来确定,flash是否是压缩过的,如果是压缩过的,那么这9个字节是不能直接运算的,要先解压缩为fws格式,才能运算。
新格式为: 46 57 53 + 原头部08 48 3a 05 00这5个字节 + 从这里9个字节开始至文件尾的数据以zlib格式解压缩。 这样就是新文件格式了,不懂的同学看最后面的py源码。
这里只需要知道如果是cws的,那么要先解压缩就可以了。附上解压后的头部:
00000000: 4657 5308 483a 0500 8000 0272 e000 00a4 FWS.H:…..r….
00000010: 6000 2d08 0044 1100 0000 0043 0200 0000 `.-..D…..C….
下面就可以开始分析了。
包含宽高信息的9个字节:80 00 02 72 e0 00 00 a4 60
把每个字节的十六进制值转为二进制码,不足8位的头部补0:
0×80 = 10000000
0×00 = 00000000
0×02 = 00000010
0×72 = 01110010
0xe0 = 11100000
0×00 = 00000000
0×00 = 00000000
0xa4 = 10100100
0×60 = 01100000
把2进制码连成新字串得到:
100000000000000000000010011100101110000000000000000000001010010001100000
去掉头部5位,形成新字串:
0000000000000000010011100101110000000000000000000001010010001100000
每15位分隔字串,得到5组,丢弃最后一组。
000000000000000
001001110010111
000000000000000
000000101001000
1100000
留下的4组其中第2和第4组就是宽和高,但并不是最终的
(001001110010111)2 = (5015)10
(000000101001000)2 = (328)10
最终的宽和高要依据9个字节的第一个字节来确定是哪种类型的,比如
80 00 02 72 e0 00 00 a4 60这里首字节是80,那么最终宽高应该是
w = 5015 / 5 = 1003
h = 328 / 1.24 = 264 (取整,和dw相比有一点偏差)
如果首字节是78,那么就要各除以20,才是最终的宽和高。
如果首字节是70,那么上面所有的算法不成立,这个还没有分析出来,因为项目使用的flash没有这种情况。
如果表述的不详细的地方,请结合参考资料和源代码理解。如果有任何意义请留言提出。谢谢。
附上python源代码:
本文首发于http://www.hkcat.org/407.html,转载请带上链接,谢谢
4000
00000000: 4357 5308 483a 0500 789c 7cbb 6554 5c4d
00000010: d335 7c70 770d eeee 1adc dd1d 0602 c1dd
首先载入我们的swf. 切换到十六进制方式。我们需要的宽和高信息就在上面的字节序列里,其中
头3个字节内容为43 57 53 或 46 57 53。 其中43 57 53 代表的是cws,也就是这个Swf是压缩过的。而46 57 53代表的是fws,也就是这个swf是未压缩过的。本次实验中使用的flash基本上是cws的。如果新建一个空白fla,再导出swf的话。那么头部就是fws的。同学们可以自己实验下。这3个字节对于我们来说的作用是cws的swf我们需要对其内容进行解压缩。而这种压缩方式就是标准的zlib格式。而fws的我们直接就可以分析了。
接下来的5个字节08 48 3a 05 00我们忽略不计,里面包含了flash的版本号和其它信息,感兴趣的同学自己看看。
最关键的是78 9c 7c bb 65 54 5c 4d d3这里9个字节,里面包含的是宽和高的信息。这里是要运算得到的。注意我们不能直接拿来运算,先由头3个字节来确定,flash是否是压缩过的,如果是压缩过的,那么这9个字节是不能直接运算的,要先解压缩为fws格式,才能运算。
新格式为: 46 57 53 + 原头部08 48 3a 05 00这5个字节 + 从这里9个字节开始至文件尾的数据以zlib格式解压缩。 这样就是新文件格式了,不懂的同学看最后面的py源码。
这里只需要知道如果是cws的,那么要先解压缩就可以了。附上解压后的头部:
00000000: 4657 5308 483a 0500 8000 0272 e000 00a4 FWS.H:…..r….
00000010: 6000 2d08 0044 1100 0000 0043 0200 0000 `.-..D…..C….
下面就可以开始分析了。
包含宽高信息的9个字节:80 00 02 72 e0 00 00 a4 60
把每个字节的十六进制值转为二进制码,不足8位的头部补0:
0×80 = 10000000
0×00 = 00000000
0×02 = 00000010
0×72 = 01110010
0xe0 = 11100000
0×00 = 00000000
0×00 = 00000000
0xa4 = 10100100
0×60 = 01100000
把2进制码连成新字串得到:
100000000000000000000010011100101110000000000000000000001010010001100000
去掉头部5位,形成新字串:
0000000000000000010011100101110000000000000000000001010010001100000
每15位分隔字串,得到5组,丢弃最后一组。
000000000000000
001001110010111
000000000000000
000000101001000
1100000
留下的4组其中第2和第4组就是宽和高,但并不是最终的
(001001110010111)2 = (5015)10
(000000101001000)2 = (328)10
最终的宽和高要依据9个字节的第一个字节来确定是哪种类型的,比如
80 00 02 72 e0 00 00 a4 60这里首字节是80,那么最终宽高应该是
w = 5015 / 5 = 1003
h = 328 / 1.24 = 264 (取整,和dw相比有一点偏差)
如果首字节是78,那么就要各除以20,才是最终的宽和高。
如果首字节是70,那么上面所有的算法不成立,这个还没有分析出来,因为项目使用的flash没有这种情况。
如果表述的不详细的地方,请结合参考资料和源代码理解。如果有任何意义请留言提出。谢谢。
附上python源代码:
#-*- coding:utf-8 #write by script@HKCAT.ORG import zlib import binascii from StringIO import StringIO #计算宽高 class swfWHMath: width=0; height=0; hexvalue = hex(0); def getWidth(self): return self.width; def getHeight(self): return self.height; def getHex(self,f): fdHex = file(f.name,"rb"); fdHex.seek(8,0); self.hexvalue = fdHex.read(9); fdHex.close(); return self.hexvalue; def addzero(self,s): a = len(s); n=s; for i in range(0,8-a): n = '0' + n; return n; def returnWH(self): dff = self.hexvalue; s= binascii.b2a_hex(dff); j = 2; i = 0; s_bin = ""; for n in range(0,9): s_bin = s_bin + self.addzero(hex2bin(s[i:j])); i = i +2; j = i + 2; s3 = s_bin[20:35]; #22: 37 s5 = s_bin[50:65]; #50:65 r1 = bin2dec(s3); r2 = bin2dec(s5); if s[0:2] == '80': self.width = int(r1) / 5; self.height = int(int(r2) / 1.24); elif s[0:2] == '78': print "78"; self.width = int(r1) / 20; self.height = int(r2) / 20; else: #70的未分析 print "未知swf类型:%s" % s[0:2]; print "W字串值:%d" % int(r1); print "H字串值:%d" % int(r2); #swf解压缩类 class swfDecompress: path=""; magic_cws = "CWS"; magic_fws = "FWS"; def check(self,f): f.seek(0,0); magic = f.read(3); if magic == self.magic_cws: return True; elif magic == self.magic_fws: return False; else: return None; def unzip(self,f): data = "FWS"+f.read(5)+zlib.decompress(f.read()); tmpf = file("tmp.swf","wb"); tmpf.write(data); tmpf.close(); return tmpf; # base = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F] base = [str(x) for x in range(10)] + [ chr(x) for x in range(ord('A'),ord('A')+6)] # bin2dec # 二进制 to 十进制: int(str,n=10) def bin2dec(string_num): return str(int(string_num, 2)) # hex2dec # 十六进制 to 十进制 def hex2dec(string_num): return str(int(string_num.upper(), 16)) # dec2bin # 十进制 to 二进制: bin() def dec2bin(string_num): num = int(string_num) mid = [] while True: if num == 0: break num,rem = divmod(num, 2) mid.append(base[rem]) return ''.join([str(x) for x in mid[::-1]]) # dec2hex # 十进制 to 八进制: oct() # 十进制 to 十六进制: hex() def dec2hex(string_num): num = int(string_num) mid = [] while True: if num == 0: break num,rem = divmod(num, 16) mid.append(base[rem]) return ''.join([str(x) for x in mid[::-1]]) # hex2tobin # 十六进制 to 二进制: bin(int(str,16)) def hex2bin(string_num): return dec2bin(hex2dec(string_num.upper())) # bin2hex # 二进制 to 十六进制: hex(int(str,2)) def bin2hex(string_num): return dec2hex(bin2dec(string_num)) if __name__ == "__main__": path = "main.swf"; f = file(path,"rb"); sd = swfDecompress(); isZip = sd.check(f); sm1 = swfWHMath(); if isZip == None: print "Error swf file format"; exit(0); if isZip : tmpf = sd.unzip(f); print "CWS:"; hexw = sm1.getHex(tmpf); else: print "FWS:"; hexw = sm1.getHex(f); #print hexw; sm1.returnWH(); print sm1.getWidth(); print sm1.getHeight(); f.close();
本文首发于http://www.hkcat.org/407.html,转载请带上链接,谢谢
4000
相关文章推荐
- 【原创分享】python获取乌云最新提交的漏洞,邮件发送
- [原创] Python 仅获取响应头, 不获取实体
- 【原创】python爬虫获取网站数据并存入本地数据库
- 【原创-未完】python获取指定目录…
- 【原创】Python 获取本机内网…
- [原创]Python 运行 shell 获取输出结果
- python 获取指定文件列表
- python获取当前脚本下的所有方法
- Python3 HTMLParser 获取 Python Events
- [原创]C#获取可用端口及已经使用的端口
- 使用python获取传入目录下apk文件的所有图标
- 【翻译】Python如何使用urllib2获取网络资源
- Python通过PIL获取图片主要颜色并和颜色库进行对比的方法
- python3用BeautifulSoup用limit来获取指定数量的a标签
- python中获取异常描述与else用法
- python通过urllib2获取带有中文参数url内容的方法
- Python爬虫获取迅雷会员帐号
- Python数据获取-文件、word、Excel、数据库
- Python脚本获取Windows窗口标题,输出到命令行
- python时间工具:获取当前日期前后N天或N月的日期