Flash网页游戏辅助工具制作简析

《热血三国》好像是比较热,玩的人也挺多的,年前一个朋友希望能让我写一个这个游戏的外挂,也出于无聊,所以去玩了一下,谁知道一玩就有点喜欢这个游戏了,当然玩归玩,东西还是要做地,当然还不能算得上是外挂,最多算是一个辅助工具。

三国,是一个全FLASH制作的网页游戏,使用Flex做架构,使用AMF协议做数据通讯。

首先针对一款FLASH网页游戏大家需要了解他的AMF协议调用模式,就三国而言,服务器返回的消息全为AMF0格式,客户端向服务器提交的是AMF3的格式。

刚开始分析这款游戏的时候想着自己建一个AMF协议解析器,但由于做出来的功能局限性比较大时间仓促,因此从网上找到了FluorineFx开源组件,要做好一款功能强大的网页游戏工具我自己觉得应该做到功能脱机,要能在工具中独立完成各种功能调用,做全点就相当于为游戏的客户端。

但做之前最头痛的问题就是分析协议调用参数及返回参数结构,在做这个工具前我对Flash Flex是一无所知,对AS的编写还只是停留在Flash 5的程度上并且已是近十年未用了。。。

为了方便使用了以下几种工具

SWFDecompiler的SWF文件反编译工具

Notepad++文本编辑工具,主要用来整个目录查找指定文本(用WINDOWS的查找功能太让人失望了)

科来网络分析系统,用来获取网络通讯数据

SocketSniff,相对科来系统更轻量级的网络监听工具,对于了解基本通讯流程更为方便

以上几种是通过网络能找到的实用工具,再加一自己做的一个AMF协议半自动分析器,主要功能是解析HEX DATA的AMF协议,及跟踪游戏AMF协议通讯过程,并简单解析体现,为更进一步分析调用过程提供参考。

一个AMF通讯过程的分析:

1.打开网页游戏,并在你需要获取命令的功能前停止操作

2.打开网络嗅探器,并执行嗅探,在此过程中最好能按IP、端口进行过滤

3.执行所需要的命令,并等待命令执行返回

4.停止网络嗅探

5.去除无关网络通讯数据,AMF协议下必定会有一个业务处理的gateway,像三国的地址为:/server/amfphp/gateway.php,并且HTTP头部的内容格式为application/x-amf,因此只需要过滤相关gateway的通讯对话就可以

6.获得通讯的HTTP数据体,并交分析工具进行协议解析

7.查看协议参数结构,并偿试重构协议复本

8.偿试将协议复本发送至服务器(请求协议)

9.调试服务器反馈数据,调试完成后即为游戏的实际AMF协议函数

在三国中,使用三种Flex消息:CommandMessage、RemotingMessage、AcknowledgeMessage

CommandMessage在游戏登录前向服务器发送请求,并返回session等安全信息

RemotingMessage为客户端向服务器提交的消息格式

AcknowledgeMessage服务器向客户端反馈的消息格式

目前工具的游戏界面

登录后主界面(可分脱机跟非脱机登录,下面为非脱机登录,其实只不过显示了一个游戏界面而已,里面的处理都是按脱机模式处理)

游戏辅助信息

地图查询工具

posted @ 2009-02-18 01:12 Pvistely 阅读(10692) 评论(147) 编辑 收藏

评论共2页: 上一页 1 2 
 回复 引用   
#51楼2009-03-26 10:33 | tantais[未注册用户]
这段amf能帮我分析一下吗,我到0A 00 00 00 01 11 0A 出卡了
"00 03 00 00 00 01 00 04 6E 75 6C 6C 00 02 "
+ "2F 34 00 00 01 33 0A 00 00 00 01 11 0A 81 13 "
+ "4F 66 6C 65 78 2E 6D 65 73 73 61 67 69 6E 67 "
+ "2E 6D 65 73 73 61 67 65 73 2E 52 65 6D 6F 74 "
+ "69 6E 67 4D 65 73 73 61 67 65 13 6F 70 65 72 "
+ "61 74 69 6F 6E 0D 73 6F 75 72 63 65 09 62 6F "
+ "64 79 13 6D 65 73 73 61 67 65 49 64 0F 68 65 "
+ "61 64 65 72 73 11 63 6C 69 65 6E 74 49 64 15 "
+ "74 69 6D 65 54 6F 4C 69 76 65 13 74 69 6D 65 "
+ "73 74 61 6D 70 17 64 65 73 74 69 6E 61 74 69 "
+ "6F 6E 06 0F 64 6F 4C 6F 67 69 6E 06 0B 4C 6F "
+ "67 69 6E 09 03 01 09 0B 01 04 88 56 04 00 06 "
+ "0F 6A 69 75 74 69 61 6E 06 0D 68 68 68 6F 6E "
+ "67 06 0D 37 36 30 35 31 31 06 49 46 31 45 30 "
+ "34 38 38 30 2D 30 33 45 45 2D 39 39 33 39 2D "
+ "33 33 34 46 2D 33 37 39 31 43 39 43 36 45 32 "
+ "46 41 0A 0B 01 09 44 53 49 64 06 07 6E 69 6C "
+ "15 44 53 45 6E 64 70 6F 69 6E 74 06 13 6D 79 "
+ "2D 61 6D 66 70 68 70 01 06 49 30 37 38 44 33 "
+ "33 30 33 2D 41 38 36 36 2D 30 38 38 38 2D 39 "
+ "42 36 39 2D 30 30 30 30 36 41 35 36 33 41 37 "
+ "31 04 00 04 00 06 0D 61 6D 66 70 68 70 00";

 回复 引用 查看   
#52楼[楼主]2009-03-26 16:02 | Pvistely      
@tantais
解析出来是doLogin的命令

 回复 引用   
#53楼2009-03-26 17:13 | tantais[未注册用户]
谢谢了楼主Pvistely,
0A 00 00 00 01 11
按理是个Ojbect但如何解析

 回复 引用   
#54楼2009-03-26 17:20 | tantais[未注册用户]
请教楼主:
如何把这个二进制数据解析成AMFMessage对象

 回复 引用   
#55楼2009-03-27 08:54 | tantais[未注册用户]
谢谢楼主,我解析成功了
 回复 引用   
#56楼2009-03-27 09:08 | nabar[未注册用户]
@tantais
自己重构一下FluorineFx里面的方法,加上
request.ServicePoint.Expect100Continue = false;
这句就ok了

 回复 引用 查看   
#57楼2009-03-27 16:27 | Tzot      
看了博主的这篇文章后,也试了下 不过一直出现如下错误! 似乎是Class没有找到。。 怎么定位这个类所在的路径?????

correlationId (String): 35a60094-8935-4ea8-91eb-ea39fed06dea
faultCode (String): AMFPHP_FILE_NOT_FOUND
faultDetail (String): /bloodwar/server/amfphp/core/shared/app/BasicActions.php on line 33
faultString (String): The class {amfphp} could not be found under the class path {/bloodwar/server/game/amfphp.php}

 回复 引用   
#58楼2009-03-27 17:20 | tantais[未注册用户]
楼主,重构一下FluorineFx里面的哪个方法啊,请指教
request.ServicePoint.Expect100Continue = false;
我设了,可是第一次可以,后面如何处理?

 回复 引用   
#59楼2009-03-27 23:44 | tantais[未注册用户]
楼主能简要介绍一下socket如何发AMFMessage及接受数据吗,我不熟悉这个,这几天把我搞得晕晕的
 回复 引用   
#60楼2009-03-27 23:46 | tantais[未注册用户]
就是socket的参数如何设置
 回复 引用   
#61楼2009-03-28 02:49 | Pvistely
@tantais
用AMFSerializer进行重构,SOCKET发HTTP请求,具体怎么操作你可以网上找相关代码,SOCKET操作很多

@Tzot
服务器路径不用理会,我不知道你是怎么调用的,我是通过FluorineFx做AMF消息重构

 回复 引用   
#62楼2009-03-28 08:15 | tantais[未注册用户]
我再试试
 回复 引用   
#63楼2009-03-28 12:39 | bgwace[未注册用户]
那里可以下载。。。。
 回复 引用   
#64楼2009-03-28 13:36 | tantais[未注册用户]
socket.Send(bytesSendStr, bytesSendStr.Length, SocketFlags.None);
string sendStr = "GET / HTTP/1.1\r\nHost: " + hostName +
"\r\nConnection: Close\r\n\r\n";
这个sendStr的格式有没有资料
谢谢楼主

 回复 引用   
#65楼2009-03-28 13:38 | tantais[未注册用户]
是不是直接把AMFMessage序列化了作为bytesSendStr传出去就行了
 回复 引用 查看   
#66楼2009-03-28 15:34 | Tzot      
@tantais
你怎么解析那个十六进制数据为 AMFMessage的!!???


 回复 引用 查看   
#67楼[楼主]2009-03-28 16:41 | Pvistely      
@tantais
sendStr你或许可以去查下HTTP协议的说明,你可以用AMFSerializer.ToArray()方法获取字节序列。AMF编码都是UTF8格式的,这个在AMF解析器里已经帮你处理了。

@Tzot
可以用AMFSerializer做序列,因为AMFSerializer是派生于MemoryStream

 回复 引用   
#68楼2009-03-29 02:19 | tantais[未注册用户]
谢谢楼主,刚刚看看HTTP协议的说明,基本懂了
明天试试,呵呵 睡觉去了

 回复 引用 查看   
#69楼[楼主]2009-03-30 03:34 | Pvistely      
这楼好高啊。难得难得,哈哈
 回复 引用   
#70楼2009-03-30 11:08 | tantais[未注册用户]
楼主帮忙
“您的主机中的软件放弃了一个已建立的连接。”
这个错误是什么意思啊

 回复 引用   
#71楼2009-03-31 10:31 | tantais[未注册用户]
是否要按照游戏中登入时的顺序发Send呢
我卡在这了,还没到发消息的那一步啊
楼主抽空指教指教 吧

 回复 引用   
#72楼2009-03-31 10:56 | tantais[未注册用户]
是不是还要设Cookie
如何设置Cookie?

 回复 引用 查看   
#73楼[楼主]2009-03-31 22:09 | Pvistely      
@tantais
中气游戏顺序发送数据包,COOKIE需要设置,直接写在HTTP头部就行

 回复 引用   
#74楼2009-04-01 09:34 | tantais[未注册用户]
是否必须要把SWF文件反编译来研究啊,我没做这个
 回复 引用 查看   
#75楼[楼主]2009-04-01 15:03 | Pvistely      
@tantais
我第一个工具就是,你去找下就行了

 回复 引用 查看   
#76楼2009-04-02 14:15 | 無尽海      
00 03 00 00 00 01 00 04 6E 75 6C 6C 00 03 2F 39 38 00 00 01 53 0A 00 00 00 01 11 0A 81 13 4F 66 6C 65 78 2E 6D 65 73 73 61 67 69 6E 67 2E 6D 65 73 73 61 67 65 73 2E 52 65 6D 6F 74 69 6E 67 4D 65 73 73 61 67 65 13 6F 70 65 72 61 74 69 6F 6E 0D 73 6F 75 72 63 65 13 6D 65 73 73 61 67 65 49 64 0F 68 65 61 64 65 72 73 11 63 6C 69 65 6E 74 49 64 09 62 6F 64 79 13 74 69 6D 65 73 74 61 6D 70 15 74 69 6D 65 54 6F 4C 69 76 65 17 64 65 73 74 69 6E 61 74 69 6F 6E 06 17 73 65 6E 64 43 6F 6D 6D 61 6E 64 06 0F 43 6F 6D 6D 61 6E 64 06 49 41 35 39 41 41 30 43 45 2D 30 36 41 31 2D 32 38 32 32 2D 34 41 39 36 2D 36 35 31 35 35 33 32 39 46 43 35 41 0A 0B 01 09 44 53 49 64 06 07 6E 69 6C 15 44 53 45 6E 64 70 6F 69 6E 74 06 13 6D 79 2D 61 6D 66 70 68 70 21 44 53 52 65 71 75 65 73 74 54 69 6D 65 6F 75 74 04 0F 01 06 49 32 46 36 43 46 32 39 36 2D 39 41 36 38 2D 39 36 43 38 2D 30 41 33 34 2D 30 30 30 30 33 32 30 36 45 34 32 34 09 03 01 09 0F 01 04 8A 0D 05 41 C8 69 72 63 00 00 00 04 02 06 09 63 69 74 79 06 13 63 68 61 6E 67 65 54 61 78 04 9B 97 5C 04 09 04 00 04 00 06 0D 61 6D 66 70 68 70

请教下楼主是如何把这类16进制串,反序列化成AMFMessage对象,通过FluorineFx这个组件吗?

 回复 引用 查看   
#77楼2009-04-02 15:51 | 無尽海      
我装了fluorinefx反序列化搞定了谢谢
 回复 引用 查看   
#78楼2009-04-02 19:13 | 無尽海      
.....观察了几个AMFMessage对象参数真是多啊,想不明白amf格式传输会快

楼主能不能给点提示主要观察那几个参数,突然不习惯用C#,要有个php var_dump之类的方法就好了

 回复 引用 查看   
#79楼[楼主]2009-04-03 01:36 | Pvistely      
@無尽海
主点管他BODY中有哪些东西就行了,重构一下BODY,这是数据域

 回复 引用   
#80楼2009-04-07 10:26 | sos[未注册用户]
我只想问下。要做出你写的东西。需要什么知识都。比如我现在是0基础
 回复 引用   
#81楼2009-04-07 21:28 | sos[未注册用户]
我用WPE截取封包也可以吧
 回复 引用   
#82楼2009-04-09 11:55 | 無尽海
请教下作者,你实现的界面是用了WebBrowser这个控件?
那么你的脱机方式辅助功能怎么处理,
我辅助界面登陆,浏览器页面就掉线,
这游戏帐号不能同时登陆,唯一想到的方法就是在winfrom里面截获webbrowser或者浏览器登陆时候返回的包,
你是这样实现的吗?

 回复 引用   
#83楼2009-04-10 14:47 | tantais[未注册用户]
用AMFSerializer做序列出来的数据为何和原始数据不一致啊
 回复 引用   
#84楼2009-04-10 16:54 | tantais[未注册用户]
终于发送成功了,但是收到的数据解析后是
俩个值
0
invalid_user_auth
怎么回事

 回复 引用 查看   
#85楼[楼主]2009-04-10 18:10 | Pvistely      
@tantais
不能一个用户多次登录的,呵呵
这个提示是说明掉线了

 回复 引用 查看   
#86楼[楼主]2009-04-10 18:16 | Pvistely      
@無尽海
获取不到WEBBROWSER的具体数据,

 回复 引用   
#87楼2009-04-10 18:34 | 無尽海
。。。那楼主怎么实现的,
我的想法是在WEBBROWSER登陆的时候,通过SharpPcap这类的类库抓取登陆返回的数据包这样应该可以实现自己在浏览器登陆,同时辅助工具进行。

SharpPcap抓包还真不太懂,继续请教^_^

 回复 引用   
#88楼2009-04-10 20:39 | yyjgame
欲请楼主帮做一款网页FLASH扑克游戏的辅助工具。不知有意否。价格如何收取。请加QQ:100999991.
有这方面能力的高手也可以加。

 回复 引用 查看   
#89楼[楼主]2009-04-12 23:19 | Pvistely      
@無尽海
嗯,我就是直接通过PCAP实现的

 回复 引用   
#90楼2009-04-14 10:17 | tantais[未注册用户]
唉,还是没法登入
给我回了个ErrorMessage
FaultCode:AMFPHP_FILE_NOT_FOUND
FaultDetail:/bloodwar/server/amfphp/core/shared/app/BasicActions.php on line 33
FaultString:The class {Amf3Broker} could not be found under the class path {/bloodwar/server/game/amfphp/Amf3Broker.php}
楼主,我的思路有问题吧
给个登陆的发送顺序吧
谢谢楼主了

 回复 引用   
#91楼2009-04-14 10:18 | tantais[未注册用户]
我是用WebBrowser打开网页,没登陆
然后用他的Cookie发个CommandMessage过去

 回复 引用   
#92楼2009-04-15 15:26 | tantais[未注册用户]
请教楼主CommandMessage的messageId如何设置啊
 回复 引用   
#93楼2009-04-15 17:00 | tantais[未注册用户]
楼主,救救我吧
 回复 引用 查看   
#94楼[楼主]2009-04-15 17:10 | Pvistely      
messageId是随机的,
你向服务器发送一个空的DOLOGIN指令,
他会返回相应COOKIE值
然后再向服务器发送一个完整的DOLOGIN指令就行了

 回复 引用   
#95楼2009-04-15 17:15 | tantais[未注册用户]
byte[] ParaseLoginMessage()
{
FluorineFx.Messaging.Messages.CommandMessage cm = new FluorineFx.Messaging.Messages.CommandMessage();
//cm.messageId = "36835A87-58C1-08BA-79F8-A1E50A8C3A55";
cm.timestamp = 0;
cm.clientId = null;
cm.destination = "";
cm.timeToLive=0;
cm.headers.Add("DSMessagingVersion", 1);
cm.headers.Add("DSId", "nil");
FluorineFx.IO.AMFMessage amfM = new FluorineFx.IO.AMFMessage(3);
FluorineFx.IO.AMFBody body = new FluorineFx.IO.AMFBody();
body.Response = @"/30";
body.Content = new object[] { cm };
byte[] data = new byte[2048];
amfM.AddBody(body);
MemoryStream ms = new MemoryStream(data);
FluorineFx.IO.AMFSerializer amfS = new FluorineFx.IO.AMFSerializer(ms);
amfS.WriteMessage(amfM);
string byteString = Bytes2String(data, System.Convert.ToInt32(ms.Position));
ms.Close();
return String2Bytes(byteString);
}

 回复 引用   
#96楼2009-04-15 17:16 | tantais[未注册用户]
byte[] contentBytes = ParaseLoginMessage();
sendStr = "POST /server/amfphp/gateway.php HTTP/1.0\r\n";
sendStr += "Accept: */*\r\n";
sendStr += "Accept-Language: zh-CN\r\n";
sendStr += "Referer: http://sg4.haowan173.com/BloodWar.swf\r\n";
sendStr += "X-Flash-Version: 10,0,22,87\r\n";
sendStr += "Content-Type: application/x-amf\r\n";
sendStr += "Content-Length: " + contentBytes.Length.ToString() + "\r\n";
sendStr += "User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; CIBA; InfoPath.2)\r\n";
sendStr += "Host: " + hostName + "\r\n";
sendStr += "Cookie: " + cookieString + "\r\n";
sendStr += "\r\n";

bytesSendBytes = new byte[1024];
bytesSendBytes = Encoding.ASCII.GetBytes(sendStr);
bytesSendBytes = BytesConnect(bytesSendBytes, contentBytes);
if (!SocketSend(bytesSendBytes))
return;

 回复 引用   
#97楼2009-04-15 17:16 | tantais[未注册用户]
楼主帮看看哪里出问题了
 回复 引用   
#98楼2009-04-15 17:17 | tantais[未注册用户]
哦,谢谢楼主,我试试
 回复 引用   
#99楼2009-04-15 17:47 | tantais[未注册用户]
楼主太伟大了,谢谢了
 回复 引用   
#100楼2009-04-18 23:15 | syskey
--引用--------------------------------------------------
Pvistely: @tantais<br />
解析出来是doLogin的命令<br />
<img height="263" alt="" src="/images/cnblogs_com/pvistely/6125/o_untitled.PNG" width="678" border="0" />

--------------------------------------------------------
请问楼主,这个是用哪个软件分析的?谢谢!

 回复 引用 查看   
#101楼2009-04-19 01:38 | 無尽海      
请求getCityInfo方法获得的数据包使用AMFSerializer序列化提示
解析异常:
{"索引超出了数组界限。"}

获得别的数据都解析正常,这个让我很纳闷,不知道楼主碰到过没

 回复 引用   
#102楼2009-04-20 12:59 | zhys9[未注册用户]
抢占100楼。。。
 回复 引用   
#103楼2009-04-20 13:00 | zhys9[未注册用户]
come on.. yeah!!
 回复 引用 查看   
#104楼[楼主]2009-04-20 22:59 | Pvistely      
@syskey
VS2008

 回复 引用 查看   
#105楼[楼主]2009-04-20 23:00 | Pvistely      
@無尽海
没遇到过呀。。。。嘿嘿,有些时候消息没有的

 回复 引用   
#106楼2009-04-22 16:44 | tantais[未注册用户]
多亏楼主指导,我现在势如破竹啊,呵呵
楼主在指导一下,getBuildingInfo前面的0是何含义
在StartTroop前是6
还有就是
第三个参数有时是1有时是2,是何含义
谢谢了

妈呀~~~
怎么比天书还难懂哦~~?
牛比人呦~~

 回复 引用   
#108楼2009-04-24 16:20 | 殤灬歼丨珷灬瑝丨
很想学,可是一看就头晕 哪些个英语一个不懂,汗...没办法,支持楼主了.
 回复 引用   
#109楼2009-04-25 01:21 | libra_r[未注册用户]
对FluorineFx不是很熟悉,尤其是AMF消息重构方面,帮助文件里也找不到。只好打开Source来看,但还是不太了了。希望能向楼主多请教。
看了一下tantais的代码,似乎没有把传递的参数写入到body中去,是用writebody写入么?其中的objectEncoding参数什么含义,该怎么定义?

 回复 引用   
#110楼2009-04-27 10:51 | nabar[未注册用户]
今天偶然又转到这个地方了,发现好多人还是没有搞定,我现在都已经自己用外挂自动升级了。
 回复 引用   
#111楼2009-04-27 14:56 | syskey
--引用--------------------------------------------------
Pvistely: @syskey
VS2008
--------------------------------------------------------
不好意思,再请教楼主,是用vs2008解析flash文件吗?个人理解应该不是,呵呵,麻烦楼主能不能详细说下具体分析的流程?

 回复 引用 查看   
#112楼[楼主]2009-04-27 17:24 | Pvistely      
@syskey
用FluorineFx解析AMF协议,然后在VS中查看对象内容

你如果需要了解游戏AMF传递内容结构推荐使用ServiceCapture

 回复 引用   
#113楼2009-04-27 20:01 | syskey
--引用--------------------------------------------------
Pvistely: @syskey
用FluorineFx解析AMF协议,然后在VS中查看对象内容

你如果需要了解游戏AMF传递内容结构推荐使用ServiceCapture
--------------------------------------------------------
谢谢您的回复,可是为什么ServiceCapture不管如何设置就是捕获不到数据呢?望解答,谢谢!

 回复 引用 查看   
#114楼[楼主]2009-04-28 02:36 | Pvistely      
@syskey
不知道你是怎么设置的,没遇到过SC取不到数据的情况

 回复 引用   
#115楼2009-04-28 13:17 | mos[未注册用户]
楼主很负责。
以前我做过纯Web的辅助程序,但这是第一次解除Flash格式的,有很多问题想请假下楼主:

6.获得通讯的HTTP数据体,并交分析工具进行协议解析
// 我理解是用FluorineFx解析AMF协议或者ServiceCapture来做?
不知道对不对,由于我以前没有什么经验,还要麻烦你多多指教。
我能不能去取得服务器,然后用代码解析出来里面的数据,然后再加上自己的参数重构发回服务器?

 回复 引用   
#116楼2009-04-28 14:48 | syskey
--引用--------------------------------------------------
Pvistely: @syskey
不知道你是怎么设置的,没遇到过SC取不到数据的情况
--------------------------------------------------------
呵呵,也许我设置的不对,ServiceCapture应该如何设置呢?楼主能讲下吗?
谢谢,另能否告知您的联系QQ呢?本人的QQ在是本人的邮箱号!以便更好的向您请教!

 回复 引用   
#117楼2009-04-28 21:51 | kurt7[未注册用户]
不错不错,我刚刚上路,已经搞定的兄弟们能否把发送AMF请求的代码发出来,我困扰在这个地方好几天了,按照前面的做法发送数据,总是返回417不成功。
 回复 引用   
#118楼2009-04-29 10:23 | mos[未注册用户]
看了下,有的WebGame還是用的Socket
 回复 引用   
#119楼2009-04-29 12:02 | kurt7[未注册用户]
@tzot
我遇到跟你一样的问题,
correlationId (String):
faultCode (String): AMFPHP_FILE_NOT_FOUND
faultDetail (String): /bloodwar/server/amfphp/core/shared/app/BasicActions.php on line 33
faultString (String): The class {amfphp} could not be found under the class path {/bloodwar/server/game/amfphp.php}
不知道你找到问题所在了吗?
望指教,谢


 回复 引用 查看   
#120楼[楼主]2009-04-29 12:47 | Pvistely      

你是不是没有把Message中的关联ID填写正确,在AMF中消息是对称的
下面是测试消息对称性的函数
AcknowledgeMessage
TestReslutCmdMsg(SocketData pTagSocket, object pRltMsg)

{

AcknowledgeMessage tmpAckMsg = null;

AMFMessage tmpRvMsg = (AMFMessage)pRltMsg;

if (tmpRvMsg != null &&

    tmpRvMsg.Bodies.Count > 0 &&

    tmpRvMsg.Bodies[0].Content != null &&

    tmpRvMsg.Bodies[0].Content.GetType() == typeof(AcknowledgeMessage))

{

    tmpAckMsg = (AcknowledgeMessage)tmpRvMsg.Bodies[0].Content;

    if (pTagSocket.RequestMessage != null &&

        pTagSocket.RequestMessage.Bodies.Count > 0 &&

        pTagSocket.RequestMessage.Bodies[0].Content is Array &&

        ((object[])(pTagSocket.RequestMessage.Bodies[0].Content as Array))[0].GetType() == typeof(RemotingMessage))

    {

        RemotingMessage tmpCmdMsg = (RemotingMessage)((object[])(pTagSocket.RequestMessage.Bodies[0].Content as Array))[0];

        if (tmpAckMsg.correlationId != tmpCmdMsg.messageId)

            throw new Exception("AMF反馈消息与请求不匹配!!");
    }

}

return tmpAckMsg;

}


 回复 引用 查看   
#121楼[楼主]2009-04-29 12:48 | Pvistely      

有不少还是用SOCKET进行交互,我这里只是一个AMF协议应用的游戏而已


 回复 引用   
#122楼2009-04-29 13:25 | kurt7[未注册用户]
楼主,
我用servicecapture抓包,发现里面的发送的数据跟flash发送的都一样,可是不知道为什么返回的数据却不对,而且cookie我也已经设置了,还有可能是什么地方的问题呢?

 回复 引用   
#123楼2009-05-03 07:58 | lkllllllllllllll[未注册用户]
好,好,,好,好,好,好,好,好好,好,好好,,好,好好,好好
 回复 引用   
#124楼2009-05-07 09:55 | tantais[未注册用户]
楼主,请教一下
AMFBody的Response属性是何含义,如何设置
谢谢

 回复 引用   
#125楼2009-05-07 09:55 | tantais[未注册用户]
楼主,请教一下
AMFBody的Response属性是何含义,如何设置
谢谢

 回复 引用   
#126楼2009-05-21 09:45 | ghoul
楼主你好。。很高兴看到你的帖子。我也是一个新手。用wpe抓到登录的数据包。然后模拟向服务器发送这个数据包。结果服务器返回ErrorMessage
FaultCode:AMFPHP_FILE_NOT_FOUND
FaultDetail:/bloodwar/server/amfphp/core/shared/app/BasicActions.php on line 33
FaultString:The class {Amf3Broker} could not be found under the class path {/bloodwar/server/game/amfphp/Amf3Broker.php}
请问楼主我的问题是在哪里喃??我不知道我问的问题是否合理。不过还请楼主指点一下我这个新手、谢谢。。

 回复 引用   
#127楼2009-05-24 14:03 | 一旧饭
楼主如何把16进制的数据转换为AMFMessage对像
我看这么多人问同一个问题楼主可否写编文章介绍一下

 回复 引用   
#128楼2009-05-25 01:32 | yanghoul[未注册用户]
楼主你好:
我想请教两个个问题。在发送loadGlobalData这个数据包到服务器之后,我用wpe抓到的包全是乱码。。跟前面几个数据包的内容完全不一样。。不知这个包怎样解析??
在这个包之后的通信都使用与loadGlobalData包之前不同的clientid。请问后面的clientid是在哪里传回来的?是loadGlobalData返回的这个乱码包还是客服端生成的?应为接收到的这个包是乱码包。所以在代码中无法定位处理函数。因此始终无法确定后面的那个clientid。。还请楼主在闲暇之余多多指教我们新手。。谢谢

 回复 引用   
#129楼2009-05-25 23:32 | yanghoul[未注册用户]
怎么没人回答哦。。。。。。还请楼主多多指点下的啊。。谢谢了
 回复 引用   
#130楼2009-05-27 14:23 | ghoul
楼主你好:
我想请教两个个问题。在发送loadGlobalData这个数据包到服务器之后,我用wpe抓到的包全是乱码。。跟前面几个数据包的内容完全不一样。。不知这个包怎样解析??
在这个包之后的通信都使用与loadGlobalData包之前不同的clientid。请问后面的clientid是在哪里传回来的?是loadGlobalData返回的这个乱码包还是客服端生成的?应为接收到的这个包是乱码包。所以在代码中无法定位处理函数。因此始终无法确定后面的那个clientid。。还请楼主在闲暇之余多多指教我们新手。。谢谢

 回复 引用 查看   
#131楼[楼主]2009-05-28 17:22 | Pvistely      
@ghoul
首先你确定他返回的是不是GZIP格式的内容,如果是GZIP需要解压,
LOADGLOBALDTA是获取全局数据用的,里面只有一个时间项目是不同,基本内容应该一至
CLIENTID你可以用GUID来自己生成,并不是需要服务器返回,只要保存在同一会话里CLIENTID保持一至就行

 回复 引用   
#132楼2009-05-31 08:33 | 一旧饭
楼主怎么不解答一下我的问题呢。。。
我用了FluorineFx组件怎么反序列化也不能还原为一个amfmessage呀
00 03 00 00 00 01 00 04 6E 75 6C 6C 00 03 2F 39 38 00 00 01 53 0A 00 00 00 01 11 0A 81 13 4F 66 6C 65 78 2E 6D 65 73 73 61 67 69 6E 67 2E 6D 65 73 73 61 67 65 73 2E 52 65 6D 6F 74 69 6E 67 4D 65 73 73 61 67 65 13 6F 70 65 72 61 74 69 6F 6E 0D 73 6F 75 72 63 65 13 6D 65 73 73 61 67 65 49 64 0F 68 65 61 64 65 72 73 11 63 6C 69 65 6E 74 49 64 09 62 6F 64 79 13 74 69 6D 65 73 74 61 6D 70 15 74 69 6D 65 54 6F 4C 69 76 65 17 64 65 73 74 69 6E 61 74 69 6F 6E 06 17 73 65 6E 64 43 6F 6D 6D 61 6E 64 06 0F 43 6F 6D 6D 61 6E 64 06 49 41 35 39 41 41 30 43 45 2D 30 36 41 31 2D 32 38 32 32 2D 34 41 39 36 2D 36 35 31 35 35 33 32 39 46 43 35 41 0A 0B 01 09 44 53 49 64 06 07 6E 69 6C 15 44 53 45 6E 64 70 6F 69 6E 74 06 13 6D 79 2D 61 6D 66 70 68 70 21 44 53 52 65 71 75 65 73 74 54 69 6D 65 6F 75 74 04 0F 01 06 49 32 46 36 43 46 32 39 36 2D 39 41 36 38 2D 39 36 43 38 2D 30 41 33 34 2D 30 30 30 30 33 32 30 36 45 34 32 34 09 03 01 09 0F 01 04 8A 0D 05 41 C8 69 72 63 00 00 00 04 02 06 09 63 69 74 79 06 13 63 68 61 6E 67 65 54 61 78 04 9B 97 5C 04 09 04 00 04 00 06 0D 61 6D 66 70 68 70



代码:
FluorineFx.IO.AMFMessage ob = new FluorineFx.IO.AMFMessage(3);

string aa = "00 03 00 00 00 01 00 04 6E 75 6C 6C 00 02 "
+ "2F 34 00 00 01 33 0A 00 00 00 01 11 0A 81 13 "
+ "4F 66 6C 65 78 2E 6D 65 73 73 61 67 69 6E 67 "
+ "2E 6D 65 73 73 61 67 65 73 2E 52 65 6D 6F 74 "
+ "69 6E 67 4D 65 73 73 61 67 65 13 6F 70 65 72 "
+ "61 74 69 6F 6E 0D 73 6F 75 72 63 65 09 62 6F "
+ "64 79 13 6D 65 73 73 61 67 65 49 64 0F 68 65 "
+ "61 64 65 72 73 11 63 6C 69 65 6E 74 49 64 15 "
+ "74 69 6D 65 54 6F 4C 69 76 65 13 74 69 6D 65 "
+ "73 74 61 6D 70 17 64 65 73 74 69 6E 61 74 69 "
+ "6F 6E 06 0F 64 6F 4C 6F 67 69 6E 06 0B 4C 6F "
+ "67 69 6E 09 03 01 09 0B 01 04 88 56 04 00 06 "
+ "0F 6A 69 75 74 69 61 6E 06 0D 68 68 68 6F 6E "
+ "67 06 0D 37 36 30 35 31 31 06 49 46 31 45 30 "
+ "34 38 38 30 2D 30 33 45 45 2D 39 39 33 39 2D "
+ "33 33 34 46 2D 33 37 39 31 43 39 43 36 45 32 "
+ "46 41 0A 0B 01 09 44 53 49 64 06 07 6E 69 6C "
+ "15 44 53 45 6E 64 70 6F 69 6E 74 06 13 6D 79 "
+ "2D 61 6D 66 70 68 70 01 06 49 30 37 38 44 33 "
+ "33 30 33 2D 41 38 36 36 2D 30 38 38 38 2D 39 "
+ "42 36 39 2D 30 30 30 30 36 41 35 36 33 41 37 "
+ "31 04 00 04 00 06 0D 61 6D 66 70 68 70 00";


byte[] bb = Encoding.UTF8.GetBytes(aa);

MemoryStream ms = new MemoryStream(bb);

FluorineFx.IO.AMFDeserializer ad = new FluorineFx.IO.AMFDeserializer(ms);
ob = ad.ReadAMFMessage();
求助

 回复 引用   
#133楼2009-06-02 13:14 | DDTT[未注册用户]
好难看懂啊!头都看大了 来回看了 不下10遍 就是没看懂 楼主 帮帮 忙
过程 发下 简单点的!

 回复 引用 查看   
#134楼2009-06-02 23:44 | Record drip      
请教楼主
我用的是delphi7,不会安装使用FluorineFx。我想请教下大体思路,所谓的重构是不是类似下面的形式(StrSend是字符串类型)的字符串,然后用scoket发送出去
StrSend:= 'POST /server/amfphp/gateway.php HTTP/1.1'+ #13#10#13#10;
StrSend:= StrSend+'Accept: */*'+ #13#10;
StrSend:= StrSend+'Accept-Language: zh-CN'+ #13#10;
StrSend:= StrSend+'Referer: http://s66.91wan.com/BloodWar.swf'+ #13#10;
StrSend:= StrSend+'x-flash-version: 10,0,22,87'+ #13#10;
StrSend:= StrSend+'Content-Type: application/x-amf'+ #13#10;
StrSend:= StrSend+'Content-Length: 341'+ #13#10;
StrSend:= StrSend+'UA-CPU: x86'+ #13#10;
StrSend:= StrSend+'Accept-Encoding: gzip, deflate'+ #13#10;
StrSend:= StrSend+'User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; .NET CLR 3.5.30729; .NET CLR 3.0.30618)'+ #13#10;
StrSend:= StrSend+'Host: s66.91wan.com'+ #13#10;
StrSend:= StrSend+'Pragma: no-cache'+ #13#10;
StrSend:= StrSend+'Cookie: game_tr=%27219.128.48.129%27; login_timee=2009-05-28+18%3A29%3A59; 3Z0_sid=Xe9ESc; 3Z0_visitedfid=3D5D21D2D4; smile=2D1; game=%E7%83%AD%E8%A1%80%E4%B8%89%E5%9B%BD; PHPSESSID=hgetldaaugt7huflv1paveqqt6'+ #13#10;
StrSend:= StrSend+ Memo2.Lines.Text; //Memo中是Hex内容
StrSend:= StrSend+#13#13;
上面的代码是我根据用Charles软件截取“地图移动到1,1”动作时的请求信息的head部分和Hex部分写的,不知道这是不是叫重构……,抱歉,初学协议通讯,完全新手。

 回复 引用   
#135楼2009-06-04 12:15 | 老白1[未注册用户]
能和您联系下么
 回复 引用   
#136楼2009-06-08 16:00 | cgl[未注册用户]
我太菜了,看不懂,请教个问题,7374617465060DE9A9BBE5869B13 这是我用wpe截取的,我知道里面包含“驻军”这两个字,但是为什么却找不到驻军的utf8编码?

我的意思是,如何把这些代码转到中文?

 回复 引用   
#137楼2009-06-10 01:40 | 网游大全[未注册用户]
虽然不太明白,支持楼主的精神。
 回复 引用   
#138楼2009-06-11 17:21 | novas[未注册用户]
同上,开源下,要份源码
novas@163.com

 回复 引用   
#139楼2009-06-14 15:12 | cgl[未注册用户]
无法在流的结尾之外进行读取

这是什么原因呢,
我用129楼的例子

 回复 引用   
#140楼2009-06-16 17:28 | zxd1201
FLASH网游外挂研究QQ群29814021


 回复 引用   
#141楼2009-06-16 17:29 | zxd1201
这个帖子研究了一段时间了,还是存在很多问题,有兴趣的朋友加群 交流下
 回复 引用   
#142楼2009-06-17 23:17 | libra_r[未注册用户]
终于发送并返回成功了,原来一直返回AMFPHP_FILE_NOT_FOUND的错误不再出现。
再次感谢楼主!
建议各位先用网络嗅探器获取游戏发送出去的数据,用FluorineFx反序列化后可获得commandmessage或remotingmessage的各项参数值,设置好这些参数后再进行AMF序列化发送。

 回复 引用   
#143楼2009-06-28 01:54 | 飞腾辅助[未注册用户]
长期寻找实力作者合作,只要你能开发游戏外挂,有实力的,或者你有现成的外挂,可以联系我,只要你挂好,销售量不是问题,联系QQ89434948
 回复 引用   
#144楼2009-07-03 14:20 | Dracula[未注册用户]
楼主发个源码给我学习下行么? 非常感谢..
ezwjl@163.com

 回复 引用   
#145楼2009-07-05 05:02 | airblue[未注册用户]
好文章啊。

有个问题。

我用了楼主的方法对一个游戏“星际帝国”进行了分析。
它应该是基于 amf3 的。

我用java模拟了amf的发包。
游戏服务器对我的amf字段有回应,但是对我的具体建造指令没有正确回应(只回应了些类似用户数据之类的信息)。

想请教下楼主,能不能帮我看下我的思路是否可行,还是这个游戏做了额外的加密。
最好能email联系。
谢谢

 回复 引用 查看   
#146楼2011-07-31 14:15 | 石高飞      
博主您好想请问一下,我使用SharpPcap3.6.1版本
网络连接 为网桥
为何 抓不到任何的 TCP/IP 的数据包呢?

        public Device()
        {
            //.Devices(System.Net.IPAddress.Any, 0, new Win.RemoteAuthentication(Win.AuthenticationTypes.Null, "", ""));
          

        }


        public void Run(SharpPcap.PacketArrivalEventHandler packetArrival,string filter)
        {
            
            OriDevice = OriDevices[0];
            if (filter == string.Empty)
            {
                filter = "ip and tcp";
            }
            OriDevice.OnPacketArrival += new PacketArrivalEventHandler(packetArrival);//设置异步捕获事件
            OriDevice.Open(OpenFlags.MaxResponsiveness, 1000);//打开设备
            OriDevice.Filter = filter;//设置拦截过滤器
            OriDevice.Mode = CaptureMode.Packets;
            OriDevice.StartCapture();//开始拦截
        
        }
        public WinPcapDeviceList OriDevices { get { return WinPcapDeviceList.Instance; } }

        public void Close()
        {
            if (OriDevice != null)
            {
                OriDevice.StopCapture();
                OriDevice.Close();
            }
        }

        public WinPcapDevice OriDevice { get; set; }

        #region IDisposable 成员

        public void Dispose()
        {
            Close();
            OriDevice = null;
        }

如果不设置 Filter 就会有 拦截到数据,但一旦设置Filter就拦截不到 任何东西了。。。

 回复 引用 查看   
#147楼2011-08-20 19:34 | ssddff      
楼主,看不懂啊。能不能做个百度仙侠记的网页辅助器发发发发发给我啊??
 回复 引用 查看   
#148楼2011-09-28 16:07 | helloGo      
楼主,请教下传奇国度,客户端与服务器是用什么原理交互的呢?
我用firefox和ie都抓过包,但抓下来的swf里都没有价值的代码,看不到任何数据定义和处理,还抓到过一些xml,但xml打开是乱码的,可能是加密过的,我看不到游戏的任何数据定义,所以也构不了包,请问能指点下思路吗?

 回复 引用 查看   
#149楼2012-01-16 23:22 | jingyu      
给个源码吧,大哥
aiqingshenming@163.com

 回复 引用 查看   
#150楼2012-01-30 23:31 | 星星不说话      
大大,求例子程序
endysaiwang@163.com
对AMF的编程那块太生疏了。。。

评论共2页: 上一页 1 2