设为首页 收藏本站
查看: 1780|回复: 0

[经验分享] 谈网页游戏外挂之用python模拟游戏(热血三国2)登陆

[复制链接]

尚未签到

发表于 2015-4-19 05:44:58 | 显示全部楼层 |阅读模式
  看web看多了,想写写页游的外挂,其实原理是一样的,就是端口不一样协议字段你不知道,而这也提高了点技术门槛,看我们来一点一点突破这些门槛,这次我们来用python发包模拟flash的客户端登陆。
  以热血三国2为例,热血三国2是一款balabalaba自己查去吧的游戏。
  step1 : 在sg2.ledu.com注册个账户
   略过...
step2 : 登陆游戏,wireshark抓包分析
     以双线784服为例,游戏页面地址http://s784.sg2.ledu.com/,现在游戏一般都是联运的,就是我的域名下套着游戏给的iframe,当然请求iframe时会有之间的相互签名的。然后就变成这样了
DSC0000.png
真正的地址是
DSC0001.png
而这个地址带来的是我们最终想要的
DSC0002.png
一个flash地址跟它的参数s








  而第一个参数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
  捕获封包
DSC0003.png
其实就发了俩包,第二个是个持续的连接
第一个
DSC0004.png
第二个是认证登陆的
DSC0005.png

从我们能看懂的地方
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
此时大致的轮廓出来了,每个字符串前面有2个字节是表示字符串的字节数,比如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,其实我们没猜到的就是前面有个serverId
step3 : 用代码模拟封包发包过程



#!/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 os
import sys
import socket
import hashlib
import struct
import binascii
passport = "testfoliet"
version = "1.13.0.9"
hash = 'b7d6941a8e4fd04ac771f72fad167f10'
serverId  = 17614
serverIp = '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(".")

#print sock.recv(1024)
#sck.close

#登录socket

sock2 = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
server_address2 = (serverIp,serverPort)
sock2.connect(server_address2)
sock2.settimeout(3)
# 23

d1 = '0000000000000000000000000000000000000000000000'
# 114

d2 = ''
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 += buffer
except:
pass
print res
sock2.close
  
  
  打印出来的东西
DSC0006.png 一个socket连接hash只能被使用一次,所以每次测需要换hash当然你也可以结合我前面的 PYTHON 模拟web登录带着你的leducookie请求  游戏页面,动态解析 HTML获取HASH_TOKEN这样你就不用每次都换hash了。
  

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-58454-1-1.html 上篇帖子: 来一起写书?《Python快速教程》与《协议森林》 下篇帖子: Python深入05 装饰器
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表