国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學(xué)院 > 開發(fā)設(shè)計(jì) > 正文

談網(wǎng)頁游戲外掛之用python模擬游戲(熱血三國2)登陸

2019-11-14 17:37:51
字體:
供稿:網(wǎng)友

  看web看多了,想寫寫頁游的外掛,其實(shí)原理是一樣的,就是端口不一樣協(xié)議字段你不知道,而這也提高了點(diǎn)技術(shù)門檻,看我們來一點(diǎn)一點(diǎn)突破這些門檻,這次我們來用python發(fā)包模擬Flash的客戶端登陸。
  以熱血三國2為例,熱血三國2是一款balabalaba自己查去吧的游戲

step1 : 在sg2.ledu.com注冊個賬戶
    略過...
step2 : 登陸游戲,wireshark抓包分析
     以雙線784服為例,游戲頁面地址http://s784.sg2.ledu.com/,現(xiàn)在游戲一般都是聯(lián)運(yùn)的,就是我的域名下套著游戲給的iframe,當(dāng)然請求iframe時(shí)會有之間的相互簽名的。然后就變成這樣了

真正的地址是

而這個地址帶來的是我們最終想要的

一個flash地址跟它的參數(shù)s

<object type="application/x-shockwave-flash" data="http://cdn.ledu.com/rxsg2/1.13.0.9/swf/Rxsg2Runner.swf?r=1916775188" width="100%" height="100%" id="web_game" style="visibility: visible;">
<param name="flashvars" value="g_version=1.13.0.9&amp;g_swf_path=http%3A%2F%2Fcdn.ledu.com%2Frxsg2%2F1.13.0.9&amp;g_res_path=http%3A%2F%2Fcdn.ledu.com%2Frxsg2%2F1.13.0&amp;g_pass_type=ledu&amp;g_pass_port=testfoliet&amp;g_pass_token=2dfdca253759b6986807421362e05e55&amp;g_host=183.60.46.109&amp;g_port=27614&amp;g_pay_url=http%3A%2F%2Fepay.ledu.com%2Findex%2Findex%2Fgid%2F22%2Fsid%2F17614&amp;g_act_url=UNIQUE&amp;g_fcm_url=http%3A%2F%2Fkf.ledu.com%2Ffcm%2F%3Fgameid%3D0%26pid%3Duuyx&amp;g_server_id=17614&amp;">
<param name="allowscriptaccess" value="always">
<param name="wmode" value="Opaque">
<param name="menu" value="false">
<param name="bgcolor" value="#000000">
</object>

而第一個參數(shù)flashvars包含了通信的變量,我們把它urldecode一下得到,

#g_version 1.13.0.9#g_swf_path#g_res_path#g_pass_type ledu#g_pass_port testfoliet#g_pass_token  string(md5)   2DFDCA253759B6986807421362E05E55#g_host 183.60.46.109#g_port 27614#g_pat_url #g_act_url#g_fcm_url#g_server_id  17614

捕獲封包

其實(shí)就發(fā)了倆包,第二個是個持續(xù)的連接
第一個

第二個是認(rèn)證登陸的




從我們能看懂的地方
6c 65 64 75  -> ledu ,
中間是個0a00
下面是74 65 73 74 66 6f 6c 69 65 74 -> testfoliet
2000
38 37 37 35 38 63 33 31 62 65 62 63 35 65  33 65 35 61 38 33 63 6237 35 63 39 36 35 34 66  32 64
這個是我們的32個字符的hash ,
0800 
31 2e 31 33 2e 30 2e 39這個是我們的版本1.13.0.9,
2000
61 63 65 32 30 39 63 65  64 66 30 36 35 34 39 33 34 61 63 62 38 62 35 6338 62 32 35 36 32

這個事32位的hash
此時(shí)大致的輪廓出來了,每個字符串前面有2個字節(jié)是表示字符串的字節(jié)數(shù),比如ledu前面是0400,testfoliet (10位)前面是0a00,hash前面是2000.

然后我們再讀下解密后的swf文件as代碼(http://www.showmycode.com/)在線反編譯swf文件

package Rxsg2.Common {    import Nireus.Base.Service.Socket.*;     public class Login {         PRivate static var _login_func:Function = null;        private static var _code_transfer_loaded:Boolean = false;        private static var _mask:String = "";         public static function login(_arg1:Function):void{            var succ_func:* = _arg1;            _login_func = succ_func;            SocketService.getInstance().registerNotify(ProcDef.USER_NOTIFY_LOGIN, onUserLogin);            SocketService.getInstance().callProcRaw(ProcDef.SYSTEM_PROC_LOGIN, function (_arg1:NetData):void{                _arg1.writeInt(GlobalData.server_id);                _arg1.writeString(GlobalData.pass_type);                _arg1.writeString(GlobalData.pass_port);                _arg1.writeString(GlobalData.pass_token);                _arg1.writeString(GlobalData.version);                _arg1.writeString(Crypto.hash((((GlobalData.pass_port + GlobalData.version) + "8Ij18Hisl1na0Ous2f") + ProcDef.PROC_SIGN)));            });        }        public static function onUserLogin(_arg1:NetData):void{            var _local2:int = _arg1.readByte();            var _local3 = !((_arg1.readByte() == 0));            var _local4:String = _arg1.readString();            ((_login_func) && (_login_func((_local2 > 0), _local3)));            if (_local2 >= 0){                loadProcTransfer(_local4);            };        }        public static function loadProcTransfer(_arg1:String):void{            onLoadProcTransfer();        }        private static function onLoadProcTransfer():void{            _code_transfer_loaded = true;            tryEnterGame();        }        public static function tryEnterGame():void{            if (((((GlobalData.allow_enter) && (GlobalData.main_loaded))) && (_code_transfer_loaded))){                SocketService.getInstance().callProc(ProcDef.USER_PROC_ENTER_GAME);                sendMask();            };        }        public static function setMask(_arg1:String):void{            _mask = _arg1;            sendMask();        }        private static function sendMask():void{            if (GlobalData.login_mask.length > 0){                SocketService.getInstance().sendProc(ProcDef.USER_PROC_SEND_LOGIN_MASK, function (_arg1:NetData):void{                    _arg1.writeString(GlobalData.login_mask);                });            };        }     }}//package Rxsg2.Common 

 

 ProcDef.PROC_SIGN 是個常量PROC_SIGN_DEFAULT,其實(shí)我們沒猜到的就是前面有個serverId

step3 : 用代碼模擬封包發(fā)包過程 

#!/usr/bin/env python#-*- encoding: utf-8 -*-'''Created on Wed Aug 27 10:13:18 CST 2014@author lietdai@Gmail.com'''#flashvar#g_version 1.13.0.9#g_swf_path#g_res_path#g_pass_type ledu#g_pass_port testfoliet#g_pass_token  string(md5) a7e13597be485ec3cd2741335bb81b10#g_host 183.60.46.109#g_port 27617#g_pat_url #g_act_url#g_fcm_url#g_server_id  16431  import osimport sysimport socketimport hashlibimport structimport binasciipassport = "testfoliet"version = "1.13.0.9"hash = 'b7d6941a8e4fd04ac771f72fad167f10'serverId  = 17614serverIp = '183.60.46.109'serverPort = 27614 #token 加密串的獲取def getToken(passport,version):    key = "8Ij18Hisl1na0Ous2f"    sign = "PROC_SIGN_DEFAULT"    return hashlib.md5(passport+version+key+sign).hexdigest() #第一次socket#sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)#server_address = ('183.60.46.107',843)#sock.connect(server_address)#sock.send("<policy-file-request/>.") #print sock.recv(1024)#sck.close #登錄socketsock2 = socket.socket(socket.AF_INET,socket.SOCK_STREAM)server_address2 = (serverIp,serverPort)sock2.connect(server_address2)sock2.settimeout(3)# 23d1 = '0000000000000000000000000000000000000000000000'# 114d2 = ''d2 += '0100c800'd2 += '00000100'd2 += '00000000'd2 += '00006000'd2 += '0000'+str(hex(serverId)[4:]+hex(serverId)[2:4])d2 += '00000400'd2 +=  binascii.hexlify("ledu")d2 +=  "0"+str(hex(len(passport)))[2:]+"00"d2 +=  binascii.hexlify(passport)d2 += '2000'd2 +=  binascii.hexlify(hash)d2 += '0800'd2 +=  binascii.hexlify(version)d2 += '2000'd2 +=  binascii.hexlify(getToken(passport,version)) sock2.send(binascii.unhexlify(d1))sock2.send(binascii.unhexlify(d2))res = ""try:    while True:        buffer =  sock2.recv(1460)            if not buffer:            break        res += bufferexcept:    passprint ressock2.close

 

 

打印出來的東西
 一個socket連接hash只能被使用一次,所以每次測需要換hash當(dāng)然你也可以結(jié)合我前面的 PYTHON 模擬web登錄帶著你的leducookie請求  游戲頁面,動態(tài)解析 HTML獲取HASH_TOKEN這樣你就不用每次都換hash了。

 


發(fā)表評論 共有條評論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 泽普县| 黔西| 浮梁县| 栾川县| 班玛县| 武功县| 景洪市| 武穴市| 湘潭市| 绥芬河市| 上杭县| 肇东市| 滦南县| 吴旗县| 远安县| 合作市| 应城市| 永胜县| 保山市| 昌黎县| 马边| 涞源县| 宁化县| 崇州市| 宾川县| 汉中市| 招远市| 宿迁市| 娱乐| 民勤县| 陆川县| 平潭县| 松桃| 南皮县| 千阳县| 北安市| 东丽区| 普洱| 澄迈县| 阳西县| 义马市|