记悠学派APP逆向及利用

news/2024/12/29 3:43:49/

记悠学派APP逆向及利用

  • 0×00 前言
  • 0×01 逆向部分
    • 抓包部分
      • 登录
    • APK逆向
      • sign鉴权算法
  • 0×02 功能实现
    • sign生成
    • 软件实现
  • 0×03 结论

0×00 前言


学校为促进学生们参加活动的积极性,通过学分制度来让学生们提高参加率,并通过该APP进行签到、记录学分,作为一个爱搞事情的好孩子,当然是对他进行一番嘿嘿嘿。
带着这样的想法,我们来进行分析

注:本文所提及到的内容,仅仅为技术讨论,切勿用到非法行为。

0×01 逆向部分

抓包部分

对于APP来说,一般都会通过HTTP协议来进行传输(当然也会有TCP、UDP协议传输的)。
那么第一步就是对APP进行抓包了,我用的抓包工具是Packet Capture,选择好要抓包的程序。从登录、获取我的活动、签到历史查询、签到、评价等几个操作进行抓包。
下面来分析上述所说的登录API的调用。

注:所有API都是通过POST方式进行请求。

登录

请求包

POST /wisdomprovider/router? HTTP/1.1
Content-Length: 267
Host: manage.cisau.com.cn:8080
Connection: Keep-Alive
Accept-Encoding: gzip
content-type: application/x-www-form-urlencoded;charset=utf8anonymousId=00000000-0000-0000-0000-000000000000&loginId=20*****0&method=wisdom.system.login&sign=D96DBA******0C50B4A&format=json&tenantCode=sxxyzhxy&deviceId=1*****c&password=2****2&v=1.0&appType=2&appKey=00000001&timestamp=1555600646//loginId为登录账号 password为登录密码 deviceId为设备ID sign为APP产生操作时的鉴权密钥

返回包

HTTP/1.1 200 
Access-Control-Allow-Origin: *
Content-Type: text/html;charset=UTF-8
Content-Language: en-US
Content-Length: 799
Date: Thu, 18 Apr 2019 15:17:26 GMT{"code":"0","data":{"userId":"0*******-****-4***-***4-1*************3","userName":"*********2","studentNo":"2*****0","nickName":"**宇","realName":"**宇","mobile":"","email":"2********1@qq.com","qq":"","wechat":"","address":"北京市朝阳区***","batchCode":"00*","batchName":"201*年级","orgCode":"00*","orgName":"信息工程学院","specialtyName":"计算机科学与技术","remark":"","imageUrl":"http://smartclass.chinaedu.net:8000/sxxyzhxy/image/user/20*****2/f********1-****-****-***c-2b*******6.png","roleTypes":1,"checkinState":2,"userInfoConfirm":1,"checkinNoticeConfirm":1,"appDownloadUrl":"http://smartclass.chinaedu.net:8000/smartcampus/appdown/index.html","isBindCellphone":1},"detailCode":"0"}

注:此版本用的是老版本,该版本没有验证设备ID。

APK逆向

sign鉴权算法

由于开学的时候学过一些Java,我觉得用jadx将APK拖进去先把代码看个究竟。
在这里插入图片描述
看了一大圈也没找到啥有用的东西,还看的是一头汗水,我决定尝试最直接的办法就是直接搜索关键字sign。
在这里插入图片描述
经过长达20分钟的加载,心里一直想着等了这么久要是没搜到心态不得爆炸。但是事实并非我所料,竟然搜到了一个SignUtils.java
在这里插入图片描述
下面上代码,我们来具体分析下到底是怎么计算的这个Sign

public class SignUtils {public static String sign(Map<String, String> map, String str) {return sign(map, null, str); //递归}public static String sign(Map<String, String> map, List<String> list, String str) {  //重写方法try {StringBuilder stringBuilder = new StringBuilder();List<String> arrayList = new ArrayList(map.size());arrayList.addAll(map.keySet());if (list != null && list.size() > 0) {for (String remove : list) {arrayList.remove(remove);}}Collections.sort(arrayList);stringBuilder.append(str);for (String str2 : arrayList) {stringBuilder.append(str2);stringBuilder.append((String) map.get(str2));}stringBuilder.append(str); //通过map表排序的方法将未加密的信息存入stringBuilder中return byte2hex(getSHA1Digest(stringBuilder.toString())); //返回通过SHA-1加密后的全大写sign} catch (Throwable e) {throw new RuntimeException(e);}}.........}

通过观察登录时的代码,我们可以清楚的看到会在map表中添加所需的参数

 private void login() {if (this.mLoginTenantEntity == null) {Toast.makeText(this, getString(R.string.login_check_tenant_tip), 0).show();} else if (StringUtil.isEmpty(this.mobile) || StringUtil.isEmpty(this.pwd)) {Toast.makeText(this, getString(R.string.username_pwd_not_null), 0).show();} else {this.preference.save("username", this.mobile);CommonTenant commonTenant = (CommonTenant) TenantManager.getInstance().getCurrentTenant();commonTenant.setTenantRealCode(this.mLoginTenantEntity.getCode());CommonUrl commonUrl = (CommonUrl) commonTenant.getCurrentHttpRoot();commonUrl.setAppRootHttpUrl(this.mLoginTenantEntity.getAppUrl());commonUrl.setUploadHttpUrl(this.mLoginTenantEntity.getAppUploadUrl());commonUrl.setUmengShareHttpUrl(this.mLoginTenantEntity.getAppUmengShareUrl());if (!StringUtil.isEmpty(WisdomHttpUtil.getAppRootUrl())) {LoadingProgressDialog.showLoadingProgressDialog(this);Map hashMap = new HashMap();hashMap.put("loginId", this.mobile); //参数loginIdhashMap.put(PreferenceService.KEY_USER_PWD, this.pwd); //参数passwordhashMap.put("appType", String.valueOf(AppTypeEnum.Android.getValue())); //参数appTypehashMap.put("deviceBindingId", BindkeyUtil.getBindKey(this)); //参数deviceIdWisdomHttpUtil.sendAsyncPostRequest(Urls.LOGIN_URI, InterfaceVersionConfig.VERSION_2, hashMap, this.handler, (int) Vars.LOGIN_REQUEST, new TypeToken<User>() {});}}}

在继续跟踪POST请求这个方法的时候,还发现了method、timestamp等等。
在这里插入图片描述

public static String SECRET_KEY = "52c203760cf28798a44f6ac4"; //这个是在生成sign时必要的KEY

生成sign时,要注意必要的KEY以及参数的完整性。

0×02 功能实现

sign生成

在这里插入图片描述

package lanqiao;import java.io.IOException;
import java.security.MessageDigest;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;public class SignUtils {public static void main(String[] args) {SignUtils s = new SignUtils();Map<String, String> map = new HashMap<String, String>();Map<String, String> hashMap = new HashMap<String, String>();hashMap.put("loginId", "[loginid]");hashMap.put("password", "[password]");hashMap.put("appType", "2");hashMap.put("appKey", "00000001");hashMap.put("method", "wisdom.system.login");hashMap.put("format", "json");hashMap.put("v", "1.0");hashMap.put("timestamp", String.valueOf(System.currentTimeMillis() / 1000));//String.valueOf(System.currentTimeMillis() / 1000)hashMap.put("sign", SignUtils.sign(hashMap, "52c203760cf28798a44f6ac4"));}public static String sign(Map<String, String> map, String str) {return sign(map, null, str);}public static String sign(Map<String, String> map, List<String> list, String str) {try {StringBuilder stringBuilder = new StringBuilder();List<String> arrayList = new ArrayList(map.size());arrayList.addAll(map.keySet());if (list != null && list.size() > 0) {for (String remove : list) {arrayList.remove(remove);}}Collections.sort(arrayList);stringBuilder.append(str);for (String str2 : arrayList) {stringBuilder.append(str2);stringBuilder.append((String) map.get(str2));}stringBuilder.append(str);System.out.println(stringBuilder.toString());System.out.println(byte2hex(getSHA1Digest(stringBuilder.toString())));return byte2hex(getSHA1Digest(stringBuilder.toString()));} catch (Throwable e) {throw new RuntimeException(e);}}public static String utf8Encoding(String str, String str2) {try {return new String(str.getBytes(str2), "UTF8");} catch (Throwable e) {throw new IllegalArgumentException(e);}}private static byte[] getSHA1Digest(String str) throws IOException {try {return MessageDigest.getInstance("SHA-1").digest(str.getBytes("UTF8"));} catch (Throwable e) {throw new IOException(e);}}private static byte[] getMD5Digest(String str) throws IOException {try {return MessageDigest.getInstance("MD5").digest(str.getBytes("UTF8"));} catch (Throwable e) {throw new IOException(e);}}private static String byte2hex(byte[] bArr) {StringBuilder stringBuilder = new StringBuilder();for (byte b : bArr) {String toHexString = Integer.toHexString(b & 255);if (toHexString.length() == 1) {stringBuilder.append("0");}stringBuilder.append(toHexString.toUpperCase());}return stringBuilder.toString();}
}

这里我直接复制原包中的代码加以修改后直接利用。
为了方便在易语言中方便使用,我直接生成里stringBuilder中的字符,然后通过直接替换字符来快捷使用。

软件实现

.版本 2
.支持库 iext.子程序 登陆账号
.局部变量 未加密数据, 文本型
.局部变量 提交数据, 文本型
.局部变量 sign, 文本型
.局部变量 i, 整数型
.局部变量 返回文本, 文本型
.局部变量 username, 文本型
.局部变量 password, 文本型
.局部变量 deviceid, 文本型
.局部变量 timestamp, 文本型.计次循环首 (账号列表框.取表项数 (), i)username = 账号列表框.取标题 (i - 1, 1)password = 账号列表框.取标题 (i - 1, 2)deviceid = 账号列表框.取标题 (i - 1, 3)timestamp = 时间_取现行时间戳 (真)提交数据 = “anonymousId=00000000-0000-0000-0000-000000000000&loginId=[loginid]&method=wisdom.system.login&sign=[sign]&format=json&tenantCode=sxxyzhxy&deviceId=[deviceid]&password=[password]&v=1.0&appType=2&appKey=00000001&timestamp=[timestamp]”未加密数据 = “52c203760cf28798a44f6ac4anonymousId00000000-0000-0000-0000-000000000000appKey00000001appType2deviceId[deviceid]formatjsonloginId[loginid]methodwisdom.system.loginpassword[password]tenantCodesxxyzhxytimestamp[timestamp]v1.052c203760cf28798a44f6ac4”提交数据 = 子文本替换 (提交数据, “[loginid]”, username, , , 真)提交数据 = 子文本替换 (提交数据, “[password]”, password, , , 真)提交数据 = 子文本替换 (提交数据, “[deviceid]”, deviceid, , , 真)提交数据 = 子文本替换 (提交数据, “[timestamp]”, timestamp, , , 真)未加密数据 = 子文本替换 (未加密数据, “[loginid]”, username, , , 真)未加密数据 = 子文本替换 (未加密数据, “[password]”, password, , , 真)未加密数据 = 子文本替换 (未加密数据, “[deviceid]”, deviceid, , , 真)未加密数据 = 子文本替换 (未加密数据, “[timestamp]”, timestamp, , , 真)sign = 到大写 (校验_取sha1 (到字节集 (未加密数据)))提交数据 = 子文本替换 (提交数据, “[sign]”, sign, , , 真)' “application/x-www-form-urlencoded;charset=utf8”返回文本 = 编码_utf8到gb2312 (到文本 (网页_访问_对象 (“http://manage.cisau.com.cn:8080/wisdomprovider/router”, 1, 提交数据, , , , , , , , )))程序_写日志 (“[” + 时间_格式化 (取现行时间 (), “yy-MM-dd ”, “hh:mm:ss”, 真) + “]  登陆返回信息:” + 返回文本, 取运行目录 () + “\log\return.txt”)json.解析 (返回文本).如果 (json.取通用属性 (“data.userId”) ≠ “”)' 登陆成功账号列表框.置标题 (i - 1, 4, json.取通用属性 (“data.userId”))编辑框1.加入文本 (“[” + 时间_格式化 (取现行时间 (), “yy-MM-dd ”, “hh:mm:ss”, 真) + “] ” + username + “登陆成功...” + #换行符).否则' 登陆失败json.取通用属性 (“msg”)编辑框1.加入文本 (“[” + 时间_格式化 (取现行时间 (), “yy-MM-dd ”, “hh:mm:ss”, 真) + “] ” + username + “登陆失败:” + json.取通用属性 (“msg”) + #换行符).如果结束.计次循环尾 ()

为了防止白嫖党,我把签到、评价的代码删除咯,欢迎大家自己来编写代码。
由于技术太渣就不给大家提供其他语言的代码了,这里就用易语言做示例了。
我的代码就随缘写法,如果有可以改进的地方,联系我。

0×03 结论


通过对APP逆向后,提取接口后,实现自动登录、报名、签到、评价等等功能……
同样可以做一个通知机器人来通知你有什么新活动可以参加。

*如果有写的有问题的地方,欢迎留言告知
*本文原创作者:WeiShaos,未经许可禁止转载


http://www.ppmy.cn/news/215402.html

相关文章

优学派看视频显示连接服务器,为何优学派WiFi连起了却进不去腾讯网

满意答案 毛0518 2015.09.24 采纳率&#xff1a;44% 等级&#xff1a;5 已帮助&#xff1a;355人 1.检测硬件&#xff0c;就是看看电脑能连上并上网不.... 2.找着自己的wifi热点&#xff0c;输入密码并连接&#xff0c;并确定信号良好【一格信号的话你就可以当成没信号了&am…

小米5s升级Android8,小米5s、小米5s Plus升级8.0提前,好消息!

小米MIUI早前发布公告表示&#xff1a;小米5s升级 Android 8.0 遇到技术难点&#xff0c;为保证稳定性&#xff0c;预计升级时间为11月。如今&#xff0c;最新消息显示&#xff0c;小米5s、小米5s Plus将提前升级Android 8.0。 今天下午&#xff0c;MIUI官方发布公告&#xff1…

小米平板4P拆机内部结构

这里主要是内部卡扣等细节&#xff0c;我看到的拆机基本上没有细节&#xff0c;什么指甲就能扣开&#xff0c;四个指甲都折里面了&#xff0c;只能拿出螺丝刀硬撬 屏幕翘起来了 庐山真面目 电池上的易拉胶&#xff0c;撕开&#xff0c;轻轻的往下拉 具体卡扣细节 不知…

小米5s plus 刷机 国际版

官方禁止国际国内互刷&#xff1a; http://en.miui.com/forum.php?modviewthread&tid3831680&highlightimportant%2Bannouncement%2Babout%2Bflashing%2Bmi%2Bphones http://bbs.zol.com.cn/sjbbs/d34002_211114.html 总结之后&#xff0c;发现&#xff0c;刷机太过麻…

小米5s plus android8,喜大普奔!小米5s/Plus升级安卓8.0:最快10月初,澄清非ODM机型...

IT之家7月18日消息 此前小米5s、小米5s Plus用户集中抗议官方不给升级安卓8.0系统更新&#xff0c;现在小米及MIUI官方给出了新的进展&#xff0c;表示小米手机5s升级安卓O的超声波指纹技术难点已找到解决方案&#xff0c;预计升级时间为11月&#xff1b;小米手机5s Plus机型双…

android8 小米5s,终于来了!小米5s、小米5s Plus将提前升级Android 8.0!

原标题&#xff1a;终于来了&#xff01;小米5s、小米5s Plus将提前升级Android 8.0&#xff01; 如今&#xff0c;就华为、小米、OPPO、vivo等智能手机厂商&#xff0c;旗下的机型已经基本上都升级到安卓8.0系统了。不过&#xff0c;就小米这家智能手机厂商&#xff0c;MIUI早…

小米平板4(Plus) LTE 开通话模式教程+root权限获取

小米平板4&#xff08;Plus&#xff09; LTE 版本&#xff0c;开通话模式教程&#xff08;第三方固件&#xff09; 详细流程如下&#xff1a; 800咸鱼收台小米平板4 PLUS LTE一台。 解BL锁 百度搜索小米解锁 http://www.miui.com/unlock/index.html 下载完成后&#xff0c;解…

(最详细)小米平板4 Plus的usb调试模式在哪里打开的教程

每次我们使用安卓手机通过数据线链上Pc的时候&#xff0c;或者使用的有些APP比如我们单位营销团队每次使用的APP引号精灵&#xff0c;之前使用的老版本就需要开启USB开发者调试模式下使用&#xff0c;现每次新版本不需要了&#xff0c;如果手机没有开启USB开发者调试模式&#…