George的博客

您所在的位置:网站首页 git的概念 George的博客

George的博客

#George的博客| 来源: 网络整理| 查看: 265

¶网页游戏的核心

网页网游的游戏界面绝大多数是通过canvas实现的

网页网游的通信绝大多数是通过websocket实现的

¶如何找到赛尔号的通信函数

首先打开一个空白页,再打开浏览器的调试工具,快捷键f12

这时输入网址s.61.com,因为我们提前打开了调试工具,就能截获到从页面html开始之后的所有的HTTP请求

如图,281次请求,这些请求主要是加载页面素材的,真正的游戏通信在画红线的websocket里

点开ws,再点开左侧的某一个protocol,这时就能看到和服务器的通信了

这时的消息主要是登录时的请求,并没有什么重要性,所以我们进游戏后再看protocol里的变化

登录进去后发现另一个protocal里出现了很多消息,那么这个protocal就是我们和服务器建立的ws连接

我们随意在游戏里进行一些操作,然后选中最近的一个收到的消息(红色),点击上方发起程序,

然后我们在调用堆栈里选择这个e.connect,点击右侧进入源代码位置

然后点击左下角的美化,这时自动定位到了发起程序的源码位置

点击左侧空栏,下断点,如图,我下在第1045行

这时回到游戏进行操作,发现仍能操作,这说明这一行代码现在并没有在运行

往下发现一个sendMessage函数,在这里下断点后,游戏瞬间暂停

在右方监视输入t._cmd和t._body,就可以实时分别地看到通信的协议号和包体

此时的协议279代表从服务器获取当前时间,包体为空

此时的协议4353代表角色移动,包体x,y代表移动的坐标

¶找到通信函数后如何制作脚本呢?

归根到底有几种办法:

每次打开进入游戏后,在控制台写入脚本 直接写入html源代码中,这样每次打开不用手动输入脚本 制作浏览器扩展插件 ¶1.控制台脚本 ¶hook 负责发包的js对象

既然我们已经找到了发包的函数,直接将尝试将其打包

首先注意prototype关键词,prototype是原型的意思,也就是说我们现在是在复杂的函数e内的一个叫sendMessage的原型函数中,要想能够完整还原函数e的全部功能,我们需要整个e,而不仅仅是它的sendMessage函数,这时使用this关键字就能在一个原型函数内获得其外部的整体

封装的发包函数=this就是一行代码这么简单!!我们新建了一个全局变量封装的发包函数并将其指向了this实例

然后再封装我们想要模拟发送的包,也就是函数的参数上图括号里的t

这么简单,三个字符的代码包=t

然后只需要每次发包时对包进行我们需要的更改(下图的4353是玩家移动的指令,包._body.x是移动的横坐标),然后使用封装的发包函数.sendMessage(包)就可以模拟真人操作了

视频演示

虽然本地没看到用户移动,但是服务器确实收到了包,因为其他账号可以看到

接下来的时间我会制作一些其他发包的脚本,欢迎加入赛尔号启航战队混元~太极门,学习交流

¶2.本地替代

chrome浏览器有一个强大功能——本地替代。本地替代可以使你随心所欲的修改任意一个网页,其原理是在请求远程网站时会先查看是否存在本地替代的改写文件。

本地替代只有打开F12时才会生效。所以在打开目标网页之前需要先打开任意网页并打开F12然后再跳转到目标网页。查看s.61.com的网页源代码后,会发现整个游戏的代码都在BootStrapV2.min.js?(后跟时间戳)里,而经过我的测试,发现不论什么时间,返回的包都是一样的,虽然文件名带有不断变化的时间戳,但完全给它一个固定的文件名并进行本地改写。以下代码,先定义了一个网络请求的函数sendasgetRequest,然后使用这个函数来加载名为bootStart.js的文件,这个文件其实就是BootStrapV2.min.js的替代。

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748async function sendasgetRequest(url) { const Http = new XMLHttpRequest(); Http.open("GET", url); Http.send(); if (Http.readyState === XMLHttpRequest.DONE) { return Http; } let res; const p = new Promise((r) => res = r); Http.onreadystatechange = () => { if (Http.readyState === XMLHttpRequest.DONE) { res(Http); } } return p;} document.body.ontouchstart = function (e) { e.preventDefault && e.preventDefault(); }; setTimeout(async function () { var oHead = document.getElementsByTagName('HEAD').item(0);// var script = document.createElement("script");// script.type = "text/javascript";// script.src = 'BootStrapV2.min.js?' + ~~(Date.now() / 1000);// oHead.appendChild(script);// var response=await sendasgetRequest( 'BootStrapV2.min.js?' + ~~(Date.now() / 1000) ); var response=await sendasgetRequest( 'bootStart.js' ); var script =// ' debugger; ' + response.response+'\n'// + '//# sourceURL=s.61.com/bootStart.js'// ; var el = document.createElement('script'); el.type = 'text/javascript'; el.text = script ; oHead.appendChild(el);

接下来分析网页的主要代码bootStart.js,可以发现游戏加载了如图所示的几个重要的js文件,在原本的index.html中你会发现一个奇怪的单词egret,经过研究,赛尔号启航使用的就是这个叫egret的游戏引擎制作的。在控制台输入egret,你会发现的确它是一个已经存在的全局变量。而图上的几个js文件就是赛尔号个性化修改后的egret的引擎文件。

接下来再通过修改这几个重要的引擎文件,就能实现游戏脚本的制作。那么接下来首先要找到这些引擎文件的请求是在哪里发起的。在网络选项=》发起程序中找到其请求是由bootStart.js中如下代码发起的

12345o.$value=e(n.$value)}catch(e){t=!0,o.$error=e}n.$error=null,n.$value=null,n.$next=null,o.$next?o.$next():t&&setTimeout(function(t){console.error(t)},0,o.$error)},o},t}();t.SimplePromise=e,egret.registerClass(e,"bootStrap.SimplePromise");var r=e,n=function(){function t(){}return __define,t.prototype,t.get=function(t,e,n,o){return void 0===e&&(e="text"),void 0===n&&(n="GET"),void 0===o&&(o=6e4),new r(function(r,i){var a,u,c=/^([\w-]+:)\/\//.test(t)?RegExp.$1:w.location.protocol;if(w.XMLHttpRequest)a=new w.XMLHttpRequest;else try{a=new ActiveXObject("MSXML2.XMLHTTP")}catch(t){a=new ActiveXObject("Microsoft.XMLHTTP")}a.onreadystatechange=function(){if(4==a.readyState)if(u&&clearTimeout(u),a.onreadystatechange=null,a.status>=200&&a.status{return List.some((ur)=>{if (ur==e){ return true }})} if(judgr()){await fetch("http://localhost:3009/"+encodeURI(e).replaceAll('%','%25').replaceAll('?','%253f'), {mode: "cors", method: "GET", headers: { "Accept": "application/javascript; " }}).then(response => response.text()).then((response) => {// alert(response) f.text=responsedocument.head.appendChild(f).parentNode.removeChild(f) })

这里我为什么不继续使用chrome的本地替代功能,而要大费周章从自建服务器获取文件呢?

因为有BUG,chrome的本地替代有bug,修改index.html和bootStart还好,因为它们都在s.61.com的域名下,而这里的/bootStrap/不知为何变成了未知域名网址,网页就不会自动加载这些本地文件,仍然从远端获取。

¶egret引擎的介绍

egret是一个2D的游戏引擎,也就是说游戏里所有的2D图像本质上都是egret里的“显示物体”和“显示容器”,而所有这些物体和容器都存在于“舞台”之内,在控制台输入MFC.stage你就能得到这个”舞台“指向的 Object。

有了这个舞台 Object,你会发现它有一个children属性,这个属性就是它所有的子对象,有些子对象还会有自己的子对象,如此递进,就能得到”舞台“中任意的对象,也就是egret里的“显示物体”和“显示容器”。

1


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3