获取到预登陆flash的ActionScript源代码,在flash builder4.7中调试。

这里顺便说一下网上说的flash builder4.7破解总是出现奇怪的问题,要么是破解完了就提示许可证过期,要么就是一大堆错误。我现在是采用一个比较2的办法,把系统时间改到2008年,再按照网上的方法改Adobe文件夹里的version值。这样能使用,只是每次都会弹出试用提示。不理佢,我D继续。希望有路过的高手指点一二。

因为在分析这个网页游戏之前对ActionScript一无所知,在调试的时候一边看代码一边搜as教程。所以以下内容仅仅是我个人观点,如果有错漏之处,希望不吝赐教。

1 提示找不到ByteArrayAsset ,这个错误需要添加framework   解决办法

工程--属性--ActionScript构建路径--库路径--添加SWC

C:\Program Files\Adobe\Adobe Flash Builder 4.7\sdks\4.6.0\frameworks\libs\framework.swc

再修改一些其他的地方,源代码中就没有错误了,可以启动调试,但是可能会提示  未安装所需版本的Adobe flash player 这里需要设置用来调试的flash版本

2.设置flash调试版本。

首先在Adobe网站下载flash的调试版本。 在菜单--窗口--首选项--flash builder --调试--独立flash调试版本 里面设置下载到的调试版flash路径。

我这里是C:\Program Files\Adobe\Adobe Flash Builder 4.7\player\win\11.9\flashplayer_11_sa_debug.exe

这样就可以启动调试了。  Adobe flash builder和VS的调试方式有些类似。 以下是常用的键盘快捷键

F11启动调试

Ctrl+shift+B   打断点  相当于VS的 F9

F3  找到定义  相当于VS的F12

F5 调试单步步入  Vs的F11

F6调试单步步过   VS的F10

F8 运行到下一个断点  VS的 F5

Preload.swf从Preloader类的构造函数开始启动。Preloader继承自MovieClip类

设置显示对象的舞台  stage

if (stage) {stage.scaleMode = flash.display.StageScaleMode.NO_SCALE;stage.align = flash.display.StageAlign.TOP_LEFT;stage.stageFocusRect = false;}

以及一些其他的初始化

本地配置  全局变量里的舞台,根目录  ,资源目录,声音资源目录等。

添加事件侦听

addEventListener(flash.events.Event.ENTER_FRAME, this.Preloader_OnEnterFrame);   //进入主框架

loaderInfo.addEventListener(flash.events.ProgressEvent.PROGRESS, this.Preloader_OnProgress);//用于进度框

this._BgLoader.contentLoaderInfo.addEventListener(flash.events.Event.COMPLETE, this.Bg_OnComplete);//用于加载背景flash

在flash.events.Event.ENTER_FRAME 的事件侦听函数中执行了如下的操作,移除事件侦听,执行启动函数

internal function Preloader_OnEnterFrame(arg1:flash.events.Event):void{if (currentFrame == totalFrames) {removeEventListener(flash.events.Event.ENTER_FRAME, this.Preloader_OnEnterFrame);this.Startup();}return;}

在Startup函数主要是一些全局变量的初始化

uqee.core.global.GlobalVariables.Init();

这个函数有flash.external.ExternalInterface.call不能运行在本地,必须要在网页中运行。所以这里为了调试直接修改为函数调用得到的值。

public static function Init():void{/*获得 URL 的协议部分 var test = window.location.protocol;          alert(test); 程序返回 http:   *///Protocol = flash.external.ExternalInterface.call("function getURL(){return window.location.protocol + \'//\';}");Protocol = "http://";UrlParams = uqee.core.utils.HtmlUtils.GetParams();/*可以获得整个URL字符串(在浏览器中就是完整的地址栏)。                        var test = window.location.href;           alert(test);            *///var loc1:*=flash.external.ExternalInterface.call("function getURL(){return window.location.href;}");var loc1 = "http://www.lequ.com/server/wly/s/328/public/doLogin";loc1 = loc1.substr(0, loc1.lastIndexOf("/"));GameUrl = loc1;return;}

uqee.core.utils.HtmlUtils.GetParams() 函数

在htmlutils.as中的GetParams函数有一行

var loc3:*=uqee.core.utils.HtmlUtils.GetCookie("wly_key");     这个函数主要就是获取cookie项目wly_key的值

wly_key这个值可以在fiddle中看到

wly_key=eJw1jEtuxCAQRG%2fTyxEGbMOCK%2bQOpN3MIA%2fY6QZLmdMHL7Ip1UevOp6RYwkgR2ekUPv7DTXj%2fhUL%0aBdhKkCqp1wceBbI8O0kL8Mn1WShvQcHJx5U34mHbKCbjnVJqcQYSljAB08%2fQiDhG7Y1aFmXvWO9%2f%0aqTkl4s%2brQ5MWy%2fnPr9qCEF%2fEAzPajW%2fcqQW9GK88Tj6ZTTvrZmvWGL%2b1t7Oa1jSD8LXT7438AcrJ%0aRmg%3d

这个cookie值是加密了的。在GetParams()函数中会进行还原解密

(loc7 = Base64Decoder.decode(loc4)).uncompress();

解压出来的项如下

loc1 Object (@48f0c89)
accid "29306604"
accname "用户名"
dm "snsfun.com"
fcm "1"
isguest ""
nickname ""
provider "0"
req "1"
serverid "328"
source "null"
srvkey "328"
ticket "24a22f181e76201f9bba5b2bc313ed2a"
tid "1397570047"
tstamp "1397570548"
ucparam ""
wlydm "snsfun.com"
zingmeid "0"

回到Preloader.as里面的Startup()函数

添加事件侦听函数

uqee.core.loader.StreamLoader.Instance.addEventListener(uqee.core.events.LoaderEvent.ALL_COMPLETED, this.OnServerLoaded);

再添加一个流请求

req = uqee.core.loader.StreamLoader.Instance.AddRequest(uqee.core.global.GlobalConst.CONFIG_PATH, 
uqee.core.global.GlobalConst.SERVER_CONFIG + uqee.core.global.GlobalVariables.UrlParams.srvkey, 
uqee.core.utils.XmlUtils.GetText("preload.label.srvcfg"), 
"", true, "http://wlys328.snsfun.com/");

req.IsConfusion = false;

这个 IsConfusion 是一个布尔变量,标志要请求的流文件是否加密。FALSE则是不加密。

这个请求是下载一个地址为 http://wlys328.snsfun.com/config/Servers328.dat?t=1220447443987  的文件

这个文件下载完毕会产生uqee.core.events.LoaderEvent.ALL_COMPLETED事件,这个事件关联到了OnServerLoaded()函数,在这个函数中有两个操作

1.启动背景加载

this.Bg_Load();  这个函数判断全局变量uqee.core.global.GlobalVariables.UrlParams.bgoff  是否开启背景,如果开启就加载一个背景flash,这里为了调试我写死为

http://s2.res.uqee.com/resource/Image/zh_CN/i-15.1.swf文件

2添加一个流请求

uqee.core.loader.StreamLoader.Instance.AddRequest( uqee.core.global.GlobalConst.CONFIG_PATH, 
uqee.core.global.GlobalConst.MODULE_RESOURCE_CONFIG + "_" + uqee.core.global.GlobalVariables.Lang, 
uqee.core.utils.XmlUtils.GetText("preload.label.rescfg"), "", true, "http://wlys328.snsfun.com/");

这里没有设置 IsConfusion = false;所以这个文件是加密的。

这个流请求会下载一个地址为http://wlys328.snsfun.com/config/mns_zh_CN.dat?t=1220447444752  的文件

我们可以看到下载的 Servers328.dat 文件是明文的,内容如下

<?xml version="1.0" encoding="utf-8"?>
<ServerList adsrc="1" alias="" bgm="1" buycard="" create="3" defaultServer="dx" font="" fontsize="" guideSkip="" hidePirateBtn="" hideWarBtn="" hidecf="0" hideelite="0" ident="328" lang="zh_CN" loadReport="1" logo="" maxLv="" mix="0" multiByte="1" nameLen="8" nosword="" onlyen="" pay="" rarity="" regentGate="" resetTime="" reward="" ro="" se="1" showTime="" sys="" ujjcheck="" wf="1" wk="" wtpn=""><Server host="wlys328.snsfun.com" log="0" name="dx" platform="lequ" port="443,9118" preask="" report="/BattleReport" resHost="s2.res.uqee.com,s1.res.uqee.com"/><GameEvent url="http://wlys328.snsfun.com:9103/player/state"/><Pay url="http://www.lequ.com/pay/index/game/9/s/328"/><Main favname="乐趣网卧龙吟双线328区" favurl="" loginUrl="http://www.lequ.com/wly/" title="乐趣网卧龙吟双线328区" url="" welcome="欢迎来到乐趣网《卧龙吟》双线328区!"/><Indulge postUrl="http://www.lequ.com/api/fcm" url="http://www.lequ.com/user/idcard"/><Bug posturl="" url=""/><NewbieCard url=""/><BBS url=""/><GuestReg url="javascript:top.showReg();"/><QQ gmqq="" payqq=""/><Limit activities="" buildings="" campaignId="" navyTrain="" windows=""/><Bind force="" label="" url=""/><BgList>i-15.1.swf</BgList>
</ServerList>

这个文件定义了服务器的IP地址和端口列表  战斗报告地址  资源地址   背景flash名称等等非机密的数据

mns_zh_CN.dat则是一个加密的文件。文件长度为5163字节,是加密了的数据文件。在下一篇中解密这个文件

这里先看数据流请求和处理过程。

StreamLoader.as的AddRequest()函数根据传入的路径,服务器配置名,服务器Key,等参数生成请求的地址Url

loc1 uqee.core.entity.StreamRequestInfo (@4b97ee1)

Custom true
FileName "Servers328"
Folder "config/"
IsConfusion true
Label "preload.label.srvcfg"
LabelVersion "preload.label.srvcfg"
NoCache true
ResHost "http://wlys328.snsfun.com/"
_ResHost "http://wlys328.snsfun.com/"
Suffix "Servers328.dat"
Type null
UID null
Url "http://wlys328.snsfun.com/config/Servers328.dat"
_Url "http://wlys328.snsfun.com/config/Servers328.dat"
Version ""

在通过AddRequest函数发送流请求之后,StreamLoader.as 中的Process()函数来加载对应地址的流

protected function LoadStream(arg1:Boolean=false):void{if (!this._pStreamRequest) {return;}if (this._CloseFile[this._pCurrRequest.FileName]) {arg1 = true;delete this._CloseFile[this._pCurrRequest.FileName];}flash.utils.clearTimeout(this._ProcessTimeoutId);flash.utils.clearTimeout(this._LoadTimeoutId);//this._pStreamRequest.url = this._pCurrRequest.Url + (arg1 ? "?t=" + new Date().getTime() : "");//this._pStreamRequest.url = "http://wlys328.snsfun.com/config/Servers328.dat?t=" + (arg1 ? "?t=" + new Date().getTime() : "");//this._pStreamRequest.url = "http://wlys328.snsfun.com/config/"+ this._pCurrRequest.FileName + ".dat" + (arg1 ? "?t=" + new Date().getTime() : "");this._pStreamRequest.url = this._pCurrRequest.Url + (arg1 ? "?t=" + new Date().getTime() : "");this._pStream.load(this._pStreamRequest);trace("下载:"+this._pStreamRequest.url);return;}

因为StreamLoader.as类的构造函数中有如下的代码

public function StreamLoader(){this._pStreamRequestList = [];this._CloseFile = new flash.utils.Dictionary();super();this._pStreamRequest = new flash.net.URLRequest();this._pStream = new flash.net.URLStream();this._pStream.addEventListener(flash.events.Event.OPEN, this.Stream_OnOpen);this._pStream.addEventListener(flash.events.ProgressEvent.PROGRESS, this.Stream_OnProgress);this._pStream.addEventListener(flash.events.Event.COMPLETE, this.Stream_OnComplete);this._pStream.addEventListener(flash.events.IOErrorEvent.IO_ERROR, this.Stream_OnError);this._pStream.addEventListener(flash.events.SecurityErrorEvent.SECURITY_ERROR, this.Stream_OnError);this._pStream.addEventListener(flash.events.HTTPStatusEvent.HTTP_STATUS, this.Stream_OnHttpStatus);return;}

所以在流请求开始后会进入到  Stream_OnOpen()函数中

流请求过程中会进入 Stream_OnProgress()函数

流请求完成会进入 Stream_OnComplete()函数

 protected function Stream_OnComplete(arg1:flash.events.Event):void{flash.utils.clearTimeout(this._LoadTimeoutId);if (this._pCurrRequest) {Logger(this._pCurrRequest.LabelVersion + ":下载完成.平均速度:" + this.Speed, -1);}this.ProcessStreamData();return;}

这个ProcessStreamData()函数就是处理下载完毕的数据

try {err = this.Reader.ReadStream(this._pStream, this._pCurrRequest);}catch (e:Error){Logger("[Read Stream]" + _pCurrRequest.Url + ":" + e.message, -1);return;}

通过 AbstractXmlDataReader.as 类的ReadStreamd 的实例读入下载完毕的文件流通过判断请求的流的IsConfusion属性,确定流是否加密

if (!arg2.IsConfusion) {loc1 = new flash.utils.ByteArray();stream.readBytes(loc1, 0, loc2);loc1.position = 0;this.Store(arg2.FileName, new XML(loc1));return null;}

这里如果没有加密,就直接读取内容到局部变量 loc1 中

读取完毕就通过XmlDataRead.as类的 Store函数形成一个映射关系

_pXmlMap flash.utils.Dictionary (@2462749)
servers328 XML
<ServerList adsrc="1" alias="" bgm="1" buycard="" create="3" defaultServer="dx" font="" fontsize="" guideSkip="" hidePirateBtn="" hideWarBtn="" hidecf="0" hideelite="0" ident="328" lang="zh_CN" loadReport="1" logo="" maxLv="" mix="0" multiByte="1" nameLen="8" nosword="" onlyen="" pay="" rarity="" regentGate="" resetTime="" reward="" ro="" se="1" showTime="" sys="" ujjcheck="" wf="1" wk="" wtpn=""> ......

映射项名是  server328

键值就是下载到的流文件xml内容

在下一篇对加密过的xml文件 mns_zh_CN.dat  进行解密分析

/*******************witch_soya****************************************/

/********************2014-4-27***************************************/

对网页游戏《卧龙吟》的分析3-----预登陆flash的源代码分析相关推荐

  1. 基于HTML5的3D多人网页游戏实现方案

    摘  要: HTML5标准增强了网页在图形绘制.媒体播放.消息传送等方面的能力,为提高网页游戏性能创造了条件.基于该标准开发出一个3D多人网页游戏.介绍了其实现方案,测试了其相关性能,分析了该技术的可 ...

  2. Flash、HTML和Unity开发网页游戏的现实比较

    2011-11-21 这一天对于全球的flash开发者来说是一个黑暗的日子,因为Adobe宣布它将停止对移动浏览器上flash的支持.在此之前一天,Adobe刚刚宣布大规模裁员,这看起来似乎不是什么大 ...

  3. SDL2源代码分析1:初始化(SDL_Init())

    ===================================================== SDL源代码分析系列文章列表: SDL2源代码分析1:初始化(SDL_Init()) SDL ...

  4. BlogEngine.Net架构与源代码分析系列(转载)

    01.BlogEngine.Net架构与源代码分析系列part1:开篇介绍 02.BlogEngine.Net架构与源代码分析系列part2:业务对象--共同的父类BusinessBase 03.Bl ...

  5. SDL2源代码分析8:视频显示总结

    SDL源代码分析系列文章列表: SDL2源代码分析1:初始化(SDL_Init()) SDL2源代码分析2:窗口(SDL_Window) SDL2源代码分析3:渲染器(SDL_Renderer) SD ...

  6. RTMPdump(libRTMP) 源代码分析 7: 建立一个流媒体连接 (NetStream部分 2)

    ===================================================== RTMPdump(libRTMP) 源代码分析系列文章: RTMPdump 源代码分析 1: ...

  7. Android应用Activity、Dialog、PopWindow、Toast窗体加入机制及源代码分析

    [工匠若水 http://blog.csdn.net/yanbober 转载烦请注明出处.尊重劳动成果] 1 背景 之所以写这一篇博客的原因是由于之前有写过一篇<Android应用setCont ...

  8. SDL2源代码分析7:显示(SDL_RenderPresent())

    ===================================================== SDL源代码分析系列文章列表: SDL2源代码分析1:初始化(SDL_Init()) SDL ...

  9. SDL2源代码分析6:复制到渲染器(SDL_RenderCopy())

    ===================================================== SDL源代码分析系列文章列表: SDL2源代码分析1:初始化(SDL_Init()) SDL ...

最新文章

  1. JavaScript中的+运算
  2. linux宝塔如何开启gzip,宝塔nginx如何开启网站gzip
  3. Excel百万数据导入oracle,excel表数据导入oracle的方法!(超级有用)
  4. 选笔记本选择CPU风扇散热的重要性
  5. 机器学习系列3:能量函数分析
  6. BUUCTF web(一)
  7. NGINX前端代理TOMCAT取真实客户端IP
  8. 客户端压测server端计算qps以及不同延迟时间下响应数量所占百分比
  9. DPDK性能优化技术汇总
  10. Apple Silicon配置二进制环境(一)
  11. 如何在html中使用 es6语法让浏览器识别
  12. 【Android实战】----Android Studio2的安装使用
  13. 安装activesync同步时遇到的问题
  14. python 风玫瑰图_【求助】风玫瑰图
  15. s3c2410 2.6.22.1内核移植
  16. Linux 下的Chm 文件阅读器
  17. 即时通讯,1 天快速集成 支持单群聊、聊天室、系统通知等通信能力,安全可靠、 全球互通
  18. 基于联合独立成分分析(jICA)的EEG与fMRI耦合与解耦
  19. Bert算法:语言模型-BERT详细介绍
  20. matlab谐波电流测量,基于MATLAB的谐波电流检测方法的建模与仿真

热门文章

  1. creator 物理画线
  2. SML中的local
  3. 计算机网络专业函授,函授计算机专业都考什么课程
  4. JavaScript进阶(三)
  5. IT女白领突击怀孕避裁员
  6. IP地址、子网掩码、默认网关和DNS服务器之间的联系与区别
  7. java indexeddb_初探IndexedDB
  8. unity,时间控制插件vp_Timer简单介绍
  9. 灵遁者:写作没有固定的模型,也不会有固定的路
  10. 高可用集群下的负载均衡(8):pacemaker + corosync + haproxy 实现高可用