首页
留言
动态
归档
推荐
音乐
工具
Search
1
Emby公益服-上万部电影电视剧免费看
55,764 阅读
2
openwrt-docker部署lxk0301京东自动签到脚本
12,093 阅读
3
QuantumultX-京东签到撸京东豆
10,346 阅读
4
LXK0301京东签到脚本-自动提交互助码
8,972 阅读
5
微信-域名被封监测以及自动更换被封域名
8,723 阅读
随便写写
科学上网
Web开发
瞎折腾
登录
Search
标签搜索
quantumultx
laravel
openwrt
laravel nova
laradock
telegram
薅羊毛
google adsense
jd_scripts
京东签到
ubuntu
oh-my-zsh
web开发环境
nginx
工具
shadowsocks shadowsocksR
RBAC
权限管理
内网穿透
Python
orzlee
累计撰写
43
篇文章
累计收到
595
条评论
首页
栏目
随便写写
科学上网
Web开发
瞎折腾
页面
留言
动态
归档
推荐
音乐
工具
搜索到
1
篇与
京东APP逆向
的结果
2021-09-06
折腾京东APP签名-获取wskey相关签名参数
前言 前几天随手撸了个自动上传京东open token(open token其实就是用户cookie)的脚本(有兴趣可以看看:京东cookie自动更新维护),虽然可以自动上传了,但是每天都得去打开京东APP才行,而且两次打开时间不能超过24小时,不然open token就过期了。这方法怎么看都不是很省事! 最近一直在找替代方法,发现Zy143L大佬脚本中提到wskey可以申请open token,wskey有效期应该比较长,我使用好几天之前抓包到的wskey依然可以获取到open token。wskey在APP抓包中经常看到,使用wskey的请求里面都有签名,感觉签名方法应该是一样的。通过genToken的接口获取open token,那个签名方法虽然短时间可以重复使用(请求只需要变动wskey就好,签名没有加入wskey做计算),但是还不清楚有效期,如果一直靠抓包获取签名的话那比上面直接抓包open token还恶心! 分析 wskey很重要,京东APP很多敏感接口都是使用wskey,不要泄露!!! 既然可以通过wskey获取open token,wskey有效期有比较长,那么它是一个很好代替每天上传open token的方法。 我的思路: 不定期通过手机app抓包wskey上传到服务器,服务器接收到后写入wskeys.list。 每天定时通过wskey换取open token(open token 24小时有效期,应该每天获取两次比较保险),并且写入cookies.list。 目前还不清楚wskey有效期,所以在第二步中wskey过期及时发送通知以便重新上传wskey。 经过一下午折腾,确实可行。但是看Zy143L大佬源码发现genToken接口中的签名是请求coding.net返回的(应该是大佬自建部署的吧!)!这个动作引起了我的好奇心,没有公布签名算法,究竟是何等高级的玩意儿?请求没有任何数据,就一个get请求即可返回所有签名参数,难道签名参与计算的值都是固定的吗? 这类资料比较少,不过还是有乐于分享的大佬。找到几篇文章: JD app sign 加密参数破解 - unidbg 逆向工具之unidbg(在pc端模拟执行so文件中的函数) Unidbg使用指南(一) Unidbg模拟执行大厂so实操教程(一) 先把框架搭起来 Unidbg模拟执行大厂so实操教程(二) 借鸡生蛋之SandHook的使用(一) 借鸡生蛋之某电商App签名so的使用(二) 借鸡生蛋之某电商App签名so的使用(三) 对于我来说难度比较大,涉及知识面广,不过如果有信心那就没问题。 我总结了一下经过步骤: 首先得搭建一个android开发环境。 下载京东安卓APP,apk文件可以当作压缩文件打开,从lib里面提取出libjdbitmapkit.so。 用ida修改libjdbitmapkit.so文件,需要修改一些地方屏蔽错误。 使用unidbg载入libjdbitmapkit.so,调用签名方法签名。 打包编译,部署到服务器。 步骤虽然简单,但是操作过程对于一个从来没有接触过andriod、汇编的人来说每一步都掉坑!!! 过大坑纪要 Exception in thread "main" java.lang.IllegalStateException: Illegal JNI version: 0xffffffff,这个问题坑了我好久,起初我以为自己环境有问题,因为根本找不到什么资料。其实就是so文件问题,如果你没有使用unidbg-0.9.1版本的话会出现这个错误,引发错误的根本原因就是先按借鸡生蛋之某电商App签名so的使用(三)对so文件打补丁,如果按上文推荐的文章顺序阅读那么就会被卡住,建议全部读一遍后再动手。 打补丁使用的ida软件,对于汇编是一脸懵逼的,借鸡生蛋之某电商App签名so的使用(三)一文中把修改位置写得很明白了,但是ida真心不会用,其中包括安装ida插件: keystone中下载msi安装文件,Version 0.9.1有提供32位和64位装一个就行。安装过程一定要勾选安装pthon2.7,我就取消了,最后插件无法使用,还是自己手动去安装的,如果你也是手动安装记得安装six模块:pip install six。 把keypatch代码复制,到ida plugins目录建一个新文件Keypatch.py,把代码复制进去。 ida中Options-General-Disassembly-Number of opcode bytes设置成16,以十六进制显示字节码: 使用keypatch插件修改sourceDir部分,JNI_OnLoad部分使用ida功能Edit-Patch program-Change byte就好了。000037CC 04 25 C0 F2 01 05 MOVS R5, #0x10004这段我是用keypatch一直报错,浪费一两个小时,使用Patch program替换中间字节就行了: 修改摘要: 00002D08 40 F0 40 81 BNE.W loc_2F8C -> 00002D08 40 E1 B loc_2F8C 00002F8C 6F F0 02 00 MOV R0, #0xFFFFFFFD -> 00002F8C 4F F0 01 00 MOV.W R0, \#1 000037C8 FF F7 96 F9 BL check_status -> 000037C8 FF F7 96 F9 BL check_status 000037C8 FF F7 96 F9 BL check_status 000037CC 80 46 MOV R8, R0 000037CE 00 28 CMP R0, \#0 000037D0 67 D1 BNE loc_38A2 -> 000037C8 FF F7 96 F9 BL check_status 000037CC 04 25 C0 F2 01 05 MOVS R5, #0x10004 000037D2 2A E0 B loc_382A; 打包一定要看Unidbg使用指南(一),所有操作都是在test文件夹完成的,不然会缺少包,装又装不上!打包也要载入test文件夹! 搭建服务 如果你能坚持到这步就已经成功了,只要能获取到签名参数想怎么玩就怎么玩!我还是用http服务比较顺手,网上找了个java socket代码一顿改!!! 在JD app sign 加密参数破解 - unidbg文中代码基础上修改,加入socket模拟http: ... public static void service(final Socket socket, final JingDong jd) { InputStream inSocket; try { //获取HTTP请求头 inSocket = socket.getInputStream(); int size = inSocket.available(); byte[] buffer = new byte[size]; inSocket.read(buffer); String request = new String(buffer); System.out.println("ClientBrowser:\n" + request + "\n" + "------------------------------------------------------------------"); String httpCode = "200 OK"; String result = ""; if (request.length() > 0) { try { JSONObject data = JSON.parseObject(request.substring(request.lastIndexOf("\r\n")).trim()); if (data != null) { String uuid = data.getString("uuid"); String functionId = data.getString("functionId"); try { String body = new URLCodec().decode(data.getString("body")); String version = data.getString("version"); if (!uuid.isEmpty() && !functionId.isEmpty() && !body.isEmpty() && !version.isEmpty()) { result = convert(jd.runJni(uuid, functionId, body, version)); System.out.println(result); System.out.println(convert(result)); } } catch (DecoderException e) { e.printStackTrace(); } } } catch (JSONException e) { e.printStackTrace(); result = "{\"code\": \"400\", \"message\": \"Invalid param\"}"; httpCode = "400 Bad Request"; } } //将响应头发送给客户端 String responseFirstLine = "HTTP/1.1 " + httpCode + "\r\n"; String responseHead = "Content-Type:application/json\r\n"; OutputStream outSocket = socket.getOutputStream(); System.out.println("ServerResponse:\n" + responseFirstLine + "\n" + responseHead + "\n" + result + "\n" + "--------------------------------------------------------------------"); System.out.println("current thread:" + Thread.currentThread().getName()); System.out.println("threads count:" + Thread.activeCount()); outSocket.write(responseFirstLine.getBytes()); outSocket.write(responseHead.getBytes()); outSocket.write("\r\n".getBytes()); outSocket.write(result.getBytes()); outSocket.close(); socket.close(); } catch (IOException e) { e.printStackTrace(); } } public static void main(String[] args) throws IOException { //獲取參數,服務監聽地址和端口 //java -Daddress=0.0.0.0 -Dport=9999 -jar unidbg-android.jar address = System.getProperty("address", "127.0.0.1"); port = Integer.parseInt(System.getProperty("port", "8668")); threadCount = Integer.parseInt(System.getProperty("thread", "10")); //綫程池 ExecutorService executorService = Executors.newFixedThreadPool(threadCount); final ServerSocket serverSocket; final JingDong jd = new JingDong(); try { //建立服务器Socket,监听客户端请求 serverSocket = new ServerSocket(port, 50, InetAddress.getByName(address)); System.out.println("Server is running on " + serverSocket.getLocalSocketAddress()); //死循环不间断监听客户端请求 while (true) { final Socket socket = serverSocket.accept(); System.out.println("biuld a new tcp link with client,the cient address:" + socket.getInetAddress() + ":" + socket.getPort()); //并发处理HTTP客户端请求 executorService.execute(new Runnable() { @Override public void run() { service(socket, jd); } }); } } catch (Exception e) { e.printStackTrace(); } finally { jd.destroy(); executorService.shutdown(); } } ... 网上七拼八凑折腾出来这么个玩意,使用: java -Daddress=127.0.0.1 -Dport=8668 -DthreadCount=5 -jar xxx.jar address:绑定地址,port:绑定端口,threadCount:线城数量。 请求参数: //没有限制请求方法,GET POST随意,以下是请求body {"uuid":"随机字符串,随机生成就行了","functionId":"接口(genToken)","body":"URI编码的json,不要带任何多余东西","version":"安卓版本"} //返回结果 { "uuid": "9d53afe389f6ae5f", "st": "1630922926986", "sign": "0a9b72a4fc6ffd5d799642dd295623f8", "sv": "111" } 然后外面再套一层nginx反代,或者和自己jd_script同服务器,内网请求。你要是绑定0.0.0.0暴漏出去也行! 结语 为了个签名折腾了好久,整个签名使用了functionId,body,uuid,client,clientVersion五个参数,client基本可以固定android了。使用ida汇编长了不少知识。 至此应该是不用在操心京东登陆方面的问题了,只要使用京东APP全部都自动更新了!
2021年09月06日
5,710 阅读
23 评论
0 点赞