1.使用Fiddler进行抓包
使用Fiddle对夜神模拟器进行抓包的设置,详情参考(https://blog.csdn.net/agree_qy/article/details/82490940)
设置完成后打开模拟器上的手游和Fiddler进行抓包,此次我们用登录功能作为例子:
注册好游戏账号点击“立即登录”
这时切换到fiddler,如图所示:
图中蓝色部分即为所抓到的登录包
2.用python发送登录请求
代码如下:
# -*- coding:utf-8 -*- import requests import time import tools import json pid = '1' dev = '0d001e11875d004903dbabd464d31417' sversion = '3.5.6' scut = '1' gid = '1006609' mdev ='' version = '0.3.5' refer = '1_1006609_10913_1022' gwversion = '1.0.0' android_id = '2f8d4d3f6c8a4914' appkey = 'slDMjCNm0na18Jdxq79HgocQTf:GvF/W' def login(uname, upwd): url = 'http://s-api.37.com.cn/sdk/login/' headers = { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8', 'User-Agent': 'Dalvik/2.1.0 (Linux; U; Android 5.1.1; OPPO R11 Plus Build/NMF26X)', 'Host': 's-api.37.com.cn', 'Connection': 'Keep-Alive', 'Accept-Encoding': 'gzip' # 'Content - Length': '255' } t = time.time() sign_str = pid + gid + refer + dev + version + str(t) + appkey + uname + upwd sign = tools.md5(sign_str.encode('utf-8')) param = 'sign=' + sign \ +'&pid=' + pid \ +'&time=' + str(t) \ +'&dev=' + dev \ +'&sversion=' + sversion \ +'&scut=' + scut \ +'&gid=' + gid \ +'&mdev=' + mdev \ +'&upwd=' + upwd \ +'&version=' + version \ +'&refer=' + refer \ +'&gwversion=' + gwversion \ +'&uname=' + uname \ +'&android_id=' + android_id response = requests.post(url=url, headers=headers, data=param) # print(param) print(response.text) ret_json = json.loads(response.text) if response.status_code == 200: if ret_json['msg'] == '成功': return True return False #否定所有if def get_token(uname, upwd): url = 'http://s-api.37.com.cn/sdk/login/' headers = { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8', 'User-Agent': 'Dalvik/2.1.0 (Linux; U; Android 5.1.1; OPPO R11 Plus Build/NMF26X)', 'Host': 's-api.37.com.cn', 'Connection': 'Keep-Alive', 'Accept-Encoding': 'gzip' # 'Content - Length': '255' } t = time.time() sign_str = pid + gid + refer + dev + version + str(t) + appkey + uname + upwd sign = tools.md5(sign_str.encode('utf-8')) param = 'sign=' + sign \ + '&pid=' + pid \ + '&time=' + str(t) \ + '&dev=' + dev \ + '&sversion=' + sversion \ + '&scut=' + scut \ + '&gid=' + gid \ + '&mdev=' + mdev \ + '&upwd=' + upwd \ + '&version=' + version \ + '&refer=' + refer \ + '&gwversion=' + gwversion \ + '&uname=' + uname \ + '&android_id=' + android_id response = requests.post(url=url, headers=headers, data=param) # print(param) # print(response.text) ret_json = json.loads(response.text) return (ret_json['data']) if __name__ == '__main__': if login('jbzd3c757311','1262fa18') == True: print('login success') '''''' else: print('login error') exit(-1) token_1 = get_token('jbzd3c757311','1262fa18') 工具类: import hashlib def md5(str): m = hashlib.md5() m.update(str) # 传入需要加密的字符串进行MD5加密 return m.hexdigest() # 获取到经过MD5加密的字符串并返回
3.逆向分析
1.点击fiddler中的Raw分析内容:
图中sign的整行内容如下:
sign=a4f4eea04b7dcd619af26a5edf58af74&pid=1&time=1597315103&dev=0d001e11875d004903dbabd464d31417&sversion=3.5.6&scut=1&gid=1006609&mdev=&upwd=1262fa18&version=0.3.5&refer=1_1006609_10913_1022&gwversion=1.0.0&uname=jbzd3c757311&android_id=2f8d4d3f6c8a4914&
2.为方便查看,可以点击WebForms查看各对应值:
3.这个时候需要对游戏代码进行反编译,这里我们使用jadx工具进行反编译
说明:
反编译出来代码可以用于代码分析,一般都是没法直接编译通过的。
经过加密的APP,反编译出来的代码肯定是混淆的。
(如何使用jadx详情参考:https://blog.csdn.net/weixin_38193813/article/details/87904209 / https://www.jianshu.com/p/34295008ee1f )
打开文件后:
因为我们抓到的包是login包,所以可以直接点击放大镜通过URL地址来搜索代码位置:
跳转后界面如下:
黄色部分就是我们要找的代码部分,右键点击字母c,选择查找用例:
结果如下:
选择第一个跳转:
选中sendRequest,按住ctrl进入:
在此页面下进行分析:
根据抓包工具fiddler中WebForms我们按顺序分析:
sign 的值是通过MD5进行加密过的,
getPaternerID 是pid
getGameID 是gid
分析结果:sign= pid + gid + refer + dev + version + time + appkey + uname + upwd
当然我们不需要每一个值都去分析,只需要分析变化的值。
(如何判断是否是变化的值,小技巧:用两个不同的账号密码抓取两个登录包进行对比!)
固定不变的值可以放在代码前:
fiddler中服务器响应结果:
{"state":1,"msg":"成功","data":{"token":"BASE64ZmI5OTd5UVhuNHc1dEo3ZU5mYW1JWjlqZ1JBdDdCOCt0RkgweVRsYzZWeGxGc2RITExTNk5KR0wzbDdnOUJoQTIxeEpRek05OTdaaHVaV2dnam9RczdScUdmT2tuTmt1MVRBOFNEWEc5b216eDNmK1lienBnNHYrVzFBSHFEL3gxZEZWWDY5TlFSY3lkOUpoK0dCMkEzZHFnNGZKVCtQT0VvZGMxT0pBNmJUakJTSHVRZVBQamoySUJ5bnROTlJrQUtRVXZrbWFUNmZqZGxVcWUzTWJWdDVnSWJ3","uid":1755727187,"uname":"jbzd3c757311","login_account":"jbzd3c757311","disname":"jbzd3c757311","sex":0,"alias":"","nick":"jbzd3c757311","birth":"","bp":"","bm":"","phone":"","nurl":"","lurl":"","turl":"","auth":{"code":0,"url":"https://39ej7e.com/sdk/sdk-smrz/?authType=0\u0026code=0\u0026triggerType=login\u0026operation=1\u0026gid=1006609\u0026pid=1\u0026dev=0d001e11875d004903dbabd464d31417\u0026token=BASE64ZmI5OTd5UVhuNHc1dEo3ZU5mV3JKWlV4ZzBkNHUwNCt2Vm4wd3pzQXZ3aGpRTWRCZTdUaFo4TGEzbDdwOUI1QTIxMGFUVE0xb09VNDdjTDEwMndVNUxwcUdmT2tuTmt1MVRBOFNEWEc5b216eDNmK1lienBnNHYrVzFBSHFEL3gxZEZWWDY5TlFSY3lkOUpoK0dCMkEzZHFnNGZKVCtQT0VvZGMxT0pBNmJUakJTSHVRZVBQamoySUJ5bnROTlJrQUtRVXZrbWFUNmZqZGxVcWUzTWJWdDVnSWJ3\u0026sversion=3.5.6\u0026refer=1_1006609_10913_1022\u0026scut=1","durl":"https://39ej7e.com/sdk/sdk-smrz/?authType=0\u0026code=0\u0026triggerType=login\u0026operation=1\u0026gid=1006609\u0026pid=1\u0026dev=0d001e11875d004903dbabd464d31417\u0026token=BASE64ZmI5OTd5UVhuNHc1dEo3ZU5mQ2dKNWxsZ2tGM3ZoeHQ2VkgveWpwVjZWeHZRTUFSS2JTNU41T0QzbDYxOVJaQWcxcFBURE0xcGJOdTY4YW4xVGtYNHJScUdmT2tuTmt1MVRBOFNEWEc5b216eDNmK1lienBnNHYrVzFBSHFEL3gxZEZWWDY5TlFSY3lkOUpoK0dCMkEzZHFnNGZKVCtQT0VvZGMxT0pBNmJUakJTSHVRZVBQamoySUJ5bnROTlJrQUtRVXZrbWFUNmZqZGxVcWUzTWJWdDVnSWJ3\u0026sversion=3.5.6\u0026refer=1_1006609_10913_1022\u0026scut=1","type":0,"isAuth":1,"needAddiction":0,"needAccumulateDuration":0,"interval":1,"allowRecharge":1},"iosinfo":{"gcopen":0,"gclogintimes":0}}}
代码中也要用这种响应结果来判断我们是否登陆成功:
运行代码后显示:
我们已经通过python发包成功登录该游戏!