[color=]茅台脚本我会在今晚上传到g**hub上(如果来得及的话
[color=])。
首先要感谢作者@公过水蚊的所做工作,我在此基础上写的更加详细明白一点。
本文主要目的是阐述如何通过python脚本获取到sign签名,以用于各种请求的提交。
工具:模拟器(夜神和网易MuMu),我在mac和win10平台均测试过。
前戏:
1. 模拟器上需要安装frida-server模块(模拟器安装frida-server有很多教程),在模拟器上安装完frida-server后,python也要安装frida模块。需要注意的是模拟器和python上的版本好最好一致。
2. 安装京东App,建议安装版本9.2.0,高版本的app会检测frida,而版本过低不能抢茅台。
3. 运行模拟器上的frida-server
4. 运行京东App
完成上述步骤后,运行以下脚本
[Python] 纯文本查看 复制代码import frida
import json

rpc_sign = """
rpc.exports = {
 getsign: function(function_id, body_string, uuid){
 var sig = "";
 Java.perform(
 function(){
 //拿到context上下文
 var currentApplication = Java.use('android.app.ActivityThread').currentApplication();
 var context = currentApplication.getApplicationContext();
 var BitmapkitUtils = Java.use('com.jingdong.common.utils.BitmapkitUtils');
 sig = BitmapkitUtils.getSignFromJni(context, function_id, body_string, uuid, 'android', '9.2.0');
 
 
 //console.log(context, uuid)
 } 
 )
 return sig;
 }
};

"""


def get_sign(function_id, body_string, u):
 process = frida.get_remote_device().attach('com.jingdong.app.mall')
 script = process.create_script(rpc_sign)
 script.load()
 sign = script.exports.getsign(function_id, body_string, u)
 return sign


if __name__ == '__main__':
 body_data = {"appId": "jd.mall",
 "content": "tbV8seY199tCdw6GllmkWyCNNENuGsgwLByA7svt5HbPXvlI9wQhHMk3dT7f0ldfpq6M0MCiUD+A\nVrY390Yct0FSub03INUml9n1bS9rZSF3XT0q1kQdehKPO4CccMiEA6NQXYiqYn9wLsDDYEIjmkVA\nEbXI88CwO0K7uhwemdhQMZrcIFj6jMmyiDNDxSA1OjFw88hR0oSCF0m8ll9o9iU2MVSHDipF5ZDn\nFR4E+82mwfRYIxamafB+nWG8GuHcKhiQOWGbChTcG3TxcGT053wfcc6uuMD7+L4PcsNRQjM9syFc\nXR6FBu/sCV/kH/3rT8w/m3zV1c9JpW9lq/7WVzCVvAIj7RNt2zzYFisymCE="}
 body_string = json.dumps(body_data, ensure_ascii=False).replace(" ", "")
 function_id = 'liveauth'
 u = '-a08d16f38776'
 sign = get_sign(function_id, body_string, u)
 print(sign)

运行后返回
[Python] 纯文本查看 复制代码st=1621657345424&sign=438ba149d2c6a7958a028e4bac757261&sv=102
代表sign签名成功,值的注意的是sign签名每次运行都会不一样的。
如果报错的话,则是前戏中的四个步骤出错,请认真核对。
最后我给大家一个实际的例子,来说明如何使用方法
get_sign(function_id, body_string, u)
function_id可以任意选择,我这里以function_id为genToken为例,我们看这样一个post类型请求:
[Python] 纯文本查看 复制代码https://api.m.jd.com/client.action?functionId=genToken&clientVersion=9.2.0&build=85134&client=android&d_brand=HUAWEI&d_model=LIO-AN00&osVersion=7.1.2&screen=1920*1080&partner=hhqj02&aid=38af3fc36a99f737&oaid=&eid=eidAcbd281217fsds90FMZ**********************pndb4UddGOyrt0Z1mN4AkQ/9CUAQFAp+PnQY5raGSEnBC&sdkVersion=25&lang=zh_CN&uuid=863064425269521-080027d76df4&area=15_1255_1258_51608&networkType=wifi&wifiBssid=43236c80b42dbe2ba**********************IrvpVNHXtnDGiAtxo16XtDlLP72vz7EVd5Tyv%2BmQpUjyRkKBoym0u%2BwFm2%2Bx9****************ZHXLOhGlI4Wmi4pXJgauDlcWv7Zx20kZO%2BdXkyn3601UvHAc52hlwcbYFCa5V1vo4i4MzHRNI0G5bOjODrkfP7CXQzCv7ZxBA%3D%3D&st=1621594850112&sign=17861f5b1791b36d99aeb7e479cba11d&sv=101
分解后,请求的链接为:
[Python] 纯文本查看 复制代码https://api.m.jd.com/client.action?
Query Params 参数为
[Python] 纯文本查看 复制代码query_params = {
 'functionId': self.function_id,
 'clientVersion': '9.2.0',
 'build': '85134',
 'client': 'android',
 'd_brand': 'HUAWEI',
 'd_model': 'LIO-AN00',
 'osVersion': '7.1.2',
 'screen': '1920*1080',
 'partner': 'hhqj02',
 'aid': '38af3fc36a99f737',
 'eid': eid,
 'sdkVersion': '25',
 'lang': 'zh_CN',
 'uuid': self.uuid,
 'area': '2_2830_51811_0',
 'networkType': 'wifi',
 'wifiBssid': '43236c80b42dbe2ba38bd9ab1ae41eb7',
 'uts': '0f31TVRjBSsqndu4/jg*JxhCAuLrGelkGqZ7vmHNN/jFolcDLqtEBSFY7Fou5xPR7en5iaWp6tQJpCvsAaneoaYw==',
 'st': '1621657345424',
 'sign': '438ba149d2c6a7958a028e4bac757261',
 'sv': '102',
}
post提交的data为:
[Python] 纯文本查看 复制代码body_string = '{"action":"to","to":"https%3A%2F%2Fh5.m.jd.com%2FbabelDiy%2FZeus%2F2NUvze9e1uWf4amBhe1AV6ynmSuH%2Findex.html"}'


data = {'body': body_string}
get_sign(function_id, body_string, u)中的三个参数说明:
function_id为genToken
body_string为post里面data['body']值,如果body_string传错,sign签名肯定无法通过核验
u参数为
query_params里面的uuid
最后重新提交post请求,带上你自己生成的sign签名,如果获取到tokenKey,代表sign签名是正确的。