分类目录归档:Flash

Amf数据分析

前段时间分析了一个网页游戏,美术风格类似梦幻西游,是外包的。分析代码得知,客户端资源做了一些特殊处理,是用通过netconnection发 过来的decode的swf来解资源,本地是无缓存,存在内存中,自己如果用模拟的客户端去连服务器, 接受的是只是一个zip压缩的png文件,wpe抓包如下:

看来做了域限制!用原客户端连服务器发的才是真实的decode的swf,一时找不到很好的内存读取工具,.只得用wpe抓包去分析amf3数据了,数据封包图如下:

现RTMP协议,amf0~3数据格式已开源,不难看出找个核心的数据包:

数据包协议头12字节
03表示12字节头,channelid=3,这个是Invoke通道,NetConnection.Call() 是用的找个通道,调用的方法在下面。
00 00 00表示时间戳 Timmer=0
00 31 D9表示数据大小 AMFSize=12761
14表示数据包类型 AMFType=Invoke 方法调用
00 00 00 00 表示StreamID = 0 音视频流的ID
AMF数据
02表示String
0008表示String长度8
6F 6E 42 57 44 6F 6E 65  是String的值onBWDone
00表示Double
40 00 00 00 00 00 00 00 表示double的
05表示 null
0a表示 ARRAY
00 00 05 87 数组长度1415
之后的就是数组里的数据,就是decode的swf数据文件.但这个只是amf序列化字节,还要转化,下面以如何得到arr[0]的值为例分析:
00 表示Double
40 5e 00 00 00 00 00 00 是表示在网络中的字节循序的(符号位在低存储)8字节的IEEE-754双精度浮点数,
那么读的时候就到过来,00 00 00 00 00 00 5e 40。java转换代码如下:
public static void main(String[] args) {
byte[] b = new byte[8];
b[0] = 0×00;
b[1] = 0×00;
b[2] = 0×00;
b[3] = 0×00;
b[4] = 0×00;
b[5] = 0×00;
b[6] = 0x5e;
b[7] = 0×40;
System.out.println(byteToDouble(b));
}
//bye转double
public static double byteToDouble(byte[] b){
long l;
l=b[0];
l&=0xff;
l|=((long)b[1]<<8);
l&=0xffff;
l|=((long)b[2]<<16);
l&=0xffffff;
l|=((long)b[3]<<24);
l&=0xffffffff;
l|=((long)b[4]<<32);
l&=0xffffffffffl;
l|=((long)b[5]<<40);
l&=0xffffffffffffl;
l|=((long)b[6]<<48);
l|=((long)b[7]<<56);
return Double.longBitsToDouble(l);
}

//当然用这个方法也可以验证一下数据
public static byte[] doubleToByte(double d){
byte[] b=new byte[8];
long l=Double.doubleToLongBits(d);
for(int i=0;i<b.length;i++){
b[i]=new Long(l).byteValue();
l=l>>8;
}
return b;
}

如此读1415个double数,得到一个byte[]转为bytearray,uncompress之,得到可以解文件的swf .
注意后续的字节,分了很多个包,用wpe封包后,凑一个完整的包,再读!

资料
Amf数据格式: http://download.macromedia.com/pub/labs/amf/amf3_spec_121207.pdf
RTMP协议: http://www.adobe.com/aboutadobe/pressroom/pressreleases/200901/012009RTMP.html