因为一直忙于考试,很久没有学习了,今天随意分析了一个app就当是恢复训练了

某APP登录协议分析

一、抓包

主要分析的是该APP的手机验证登录协议,首先启动Fillder开始抓包,打开该app,输入相关手机号和验证码

抓到的包如下:

POST https://api.gotokeep.com/account/v2/sms HTTP/1.1
Content-Type: application/json; charset=UTF-8
Content-Length: 163
Host: api.gotokeep.com
Connection: Keep-Alive
Accept-Encoding: gzip
x-os-version: 5.1.1
x-geo: 0.0,0.0
x-channel: adhub_cpa__siruifan_04
x-ads: gYdZHMFkdTLC1JvfK4AsSmouEN3+S+OsjkFGaZ9kygpo/FGeJ5N7iJdMyIBtadqqUBgJnRBFi+Ri6KYKwFCVqFVPgWMaqbAAp5JiY9yFM4rGVByS9EsGHY0DB9ekNkSw+9v/Xu/BsbMxxEm9Et4MJT4QbLGf9ifhngIO3aDdE3bN+3aB801nvmOb8ZYsJ2U4Mw2sAGcnJrcDFU2kX3ASbUfhJYGWCkELV8Y6iKoPrPr/wNfkDmtuWUNYUSpSdYlPWWrANkgrPW5YL4wWIQwfVf7cDX5ItxTOGl00XYlKUcnwOsm6JAjdF5Voc0u9mmiT
x-locale: zh--CN
x-screen-height: 800
x-is-new-device: true
x-carrier: 70120
User-Agent: Keep+6.43.0%2FAndroid+5.1.1-24528+Xiaomi+MI+9
x-manufacturer: Xiaomi
x-keep-timezone: Asia/Shanghai
x-timestamp: 1594278593217
x-screen-width: 450
x-connection-type: 4
x-app-platform: keepapp
x-os: Android
x-device-id: 865166020644319111111111111111119da6a866
x-version-name: 6.43.0
x-user-id:
x-version-code: 24528
x-model: MI+9
sign: 5257caf9b35de7f6f9805f3e814773036f6c73e1

二、X-ads

首先分析x-ads:

x-ads: gYdZHMFkdTLC1JvfK4AsSmouEN3+S+OsjkFGaZ9kygpo/FGeJ5N7iJdMyIBtadqqUBgJnRBFi+Ri6KYKwFCVqFVPgWMaqbAAp5JiY9yFM4rGVByS9EsGHY0DB9ekNkSw+9v/Xu/BsbMxxEm9Et4MJT4QbLGf9ifhngIO3aDdE3bN+3aB801nvmOb8ZYsJ2U4Mw2sAGcnJrcDFU2kX3ASbUfhJYGWCkELV8Y6iKoPrPr/wNfkDmtuWUNYUSpSdYlPWWrANkgrPW5YL4wWIQwfVf7cDX5ItxTOGl00XYlKUcnwOsm6JAjdF5Voc0u9mmiT

我们通直接搜索字符串,收到了x-ads

显然b()返回的就是我们要分析的字符串,直接进去


可以看到b方法也就是将一些参数进行序列化,然后调用m.b()处理后返回

继续跟进

到这里我们就可以得到这个加密算法是AES算法,通过AES算法进行加密后再进行base64编码,对应AES算法,我们可以看到IV已经给出2346892432920300,key是由一个c(CypLib.a())返回的

继续分析发现CypLib.a()有两种返回值,若为true则进入native方法进行计算,若为false,则直接返回一个key。
那么怎么判断这个key呢,大概有下面几种思路

(1)查找a(Context context)的交叉引用,判断在对字符串进行加密处理时,是否调用了该方法,若没有调用
,就会返回false,直接对"Pl*Rxe76fx'fWWqR"加密,反之"Pl*Rxe76fx'fWWqR"就会进入native层进行处理。(2)由于只有这两个key,我们可以通过穷举的方式,直接分析得出这两个key,当然也是比较复杂的(3)动态调试smali代码,直接定位到返回的地方,获取c()方法的返回值(4)frida Hook直接找到c()方法返回值

显然通过分析,使用动态调试或者frida hook会简单很多,如果采用(1),(2)分析的话就很有可能需要分析so文件,这里可能需要手动copy一下so层伪c代码,然后修改运行,得到返回值。

这里直接采用frida hook,关于frida hook的教程很多,这里不多赘述,启动frida-server,运行脚本如下

import frida, sysdef on_message(message, data):if message['type'] == 'send':print("[*] {0}".format(message['payload']))else:print(message)jscode = """
Java.perform(function () {var m = Java.use('l.q.a.y.p.m');m.c.implementation = function (param1) {send("Hook Start...");send(param1);var result=this.c(param1);send("AESKey is :"+result);return result;}
});
"""process = frida.get_usb_device().attach('com.gotokeep.keep')
script = process.create_script(jscode)
script.on('message', on_message)
script.load()
sys.stdin.read()

最后可以得到key

到这一步,x-ads算法的主要逻辑就已经弄清楚了,
key=56fe59;82g:d873c,iv=2346892432920300

那么直接开始解密操作:

import base64
from Crypto.Cipher import AES
def base64_encode(bdate):return base64.b64encode(bdate).decode()def base64_decode(date_str):return base64.b64decode(date_str)def aes_decrypt(Key,iv,crypted):decryptor=AES.new(Key,AES.MODE_CBC,iv=iv)return decryptor.decrypt(crypted)def aes_encrypt(Key,iv,raw_data):if isinstance(raw_data,str):raw_data=raw_data.encode()#不满足8的倍数补齐if len(raw_data)%8 !=0:pad_len=8-(len(raw_data)%8)raw_data+=bytes([pad_len]*pad_len)encryptor=AES.new(Key,AES.MODE_CBC,iv=iv)return encryptor.encrypt(raw_data)if __name__=='__main__':import jsonkey='56fe59;82g:d873c'.encode()iv='2346892432920300'.encode()data='gYdZHMFkdTLC1JvfK4AsSmouEN3+S+OsjkFGaZ9kygpo/FGeJ5N7iJdMyIBtadqqUBgJnRBFi+Ri6KYKwFCVqFVPgWMaqbAAp5JiY9yFM4rGVByS9EsGHY0DB9ekNkSw+9v/Xu/BsbMxxEm9Et4MJT4QbLGf9ifhngIO3aDdE3bN+3aB801nvmOb8ZYsJ2U4Mw2sAGcnJrcDFU2kX3ASbUfhJYGWCkELV8Y6iKoPrPr/wNfkDmtuWUNYUSpSdYlPWWrANkgrPW5YL4wWIQwfVf7cDX5ItxTOGl00XYlKUcnwOsm6JAjdF5Voc0u9mmiT'crypted=base64_decode(data)decrypt=aes_decrypt(key,iv,crypted)print(decrypt.decode())

运行python脚本,得到结果

{"imei":"865166020644319","adua":"Mozilla\/5.0 (Linux; Android 5.1.1; MI 9) AppleWebKit\/537.36 (KHTML, like Gecko) Version\/4.0 Chrome\/70.0.3538.64 Mobile Safari\/537.36","androidId":"e2437690c1181ef5","device":"phone","oaid":""}

同理,可以分析得出x-device-id

三、sign

我们全局搜索sign字段,发现了一个极有可能的地方

通过分析我们可以得出,sb和各种值进行的拼接,然后通过l.q.a.y.p.b0.a(sb.toString()),进行了一次MD5得到32位的值,再进入CrypLib.a()方法中进行判断

这里我们不妨进入native层看看

jstring __fastcall Java_com_gotokeep_keep_common_utils_CrypLib_getEncryptDeviceId(JNIEnv *a1, jclass a2, jstring a3)
{int v3; // r3int v4; // r0int v5; // r3jstring v7; // [sp+4h] [bp-70h]JNIEnv *v8; // [sp+Ch] [bp-68h]int v9; // [sp+14h] [bp-60h]signed int i; // [sp+18h] [bp-5Ch]char *s; // [sp+1Ch] [bp-58h]int v12; // [sp+24h] [bp-50h]int v13; // [sp+28h] [bp-4Ch]int v14; // [sp+2Ch] [bp-48h]int v15; // [sp+34h] [bp-40h]int v16; // [sp+38h] [bp-3Ch]int v17; // [sp+3Ch] [bp-38h]int v18; // [sp+40h] [bp-34h]int v19; // [sp+44h] [bp-30h]int v20; // [sp+48h] [bp-2Ch]int v21; // [sp+4Ch] [bp-28h]int v22; // [sp+50h] [bp-24h]int v23; // [sp+54h] [bp-20h]int v24; // [sp+58h] [bp-1Ch]int v25; // [sp+5Ch] [bp-18h]char v26; // [sp+60h] [bp-14h]char v27[12]; // [sp+68h] [bp-Ch]v8 = a1;v7 = a3;if ( getSignHashCode(a1) != 1580769512 )return v7;s = ((*v8)->GetStringUTFChars)(v8, v7, 0);v16 = 0;v17 = 0;v18 = 0;v19 = 0;v20 = 0;v21 = 0;v22 = 0;v23 = 0;v24 = 0;v25 = 0;v26 = 0;if ( strlen(s) == 32 ){v9 = 0;for ( i = 7; i >= 0; --i ){v27[i - 48] = s[i];v27[i - 40] = s[i + 8];v27[i - 32] = s[i + 16];v27[i - 24] = s[i + 24];v12 = get_int(s[i]);v13 = get_int(s[i + 8]);v14 = get_int(s[i + 16]);v4 = get_int(s[i + 24]);v15 = v12 + v13 + v14 + v4 + v9 + 929;v5 = v12 + v13 + v14 + v4 + v9 + 929;if ( v5 < 0 )v5 = v12 + v13 + v14 + v4 + v9 + 944;v9 = v5 >> 4;v27[i - 16] = get_char(v15 % 16);}((*v8)->ReleaseStringUTFChars)(v8, v7, s);v3 = ((*v8)->NewStringUTF)(v8, &v16);}else{((*v8)->ReleaseStringUTFChars)(v8, v7, s);v3 = v7;}return v3;
}

是一个特别简单的算法,让人不解的是


这里居然进行了一次签名校验,而且居然直接把签名校验值返回了,看到这里如果想要修改相关资源文件就变得很容易了

然后,我们分析一下sb字段的拼接结果,直接使用frida hook l.q.a.y.p.b0.a(sb.toString())获取到入参即可,代码还是和上一个差不多,但这里有一个小小的不同点,a是一个重载方法,要记得用overload(‘入参类型’)来区别

import frida, sysdef on_message(message, data):if message['type'] == 'send':print("[*] {0}".format(message['payload']))else:print(message)jscode = """
Java.perform(function () {var b0 = Java.use('l.q.a.y.p.b0');b0.a.overload('java.lang.String').implementation = function (param1) {send("Hook Start...");send("sb is"+param1);var result=this.a(param1);send("ret is :"+result);return result;}
});
"""process = frida.get_usb_device().attach('com.gotokeep.keep')
script = process.create_script(jscode)
script.on('message', on_message)
script.load()
sys.stdin.read()

打印结果为:

[*] Hook Start...
[*] sb is{"captcha":"1111","countryCode":"86","countryName":"CHN","mobile":"18202870881","type":"login"}/account/v3/login/smsV1QiLCJhbGciOiJIUzI1NiJ9

总结

总的来说,这个app比较简单,而且很多的逻辑写的也不是很好,通过frida Hook就能很快的获取关键值

某运动APP登录协议分析相关推荐

  1. 某app登录协议逆向分析

    某app登录协议逆向分析 设备 iphone 5s Mac Os app:神奇的字符串57qm5Y2V 本文主要通过frida-trace.fridaHook.lldb动态调试完成破解相应的登录算法, ...

  2. webqq登录协议分析

    webqq登录协议分析 通过webqq接口,可以实现发送.接收qq消息. 1.首先调用:http://ptlogin2.qq.com/check?appid=1002101&uin=qq号码& ...

  3. 某游戏盒登录协议分析

    前言 距离上次写博客已经过去了一个月,博主本人在这期间也分析了不少案列,这次分享一个比较综合的案例,难易程度偏简单,适合协议分析练手,下面直接进入正题. 准备工作 首先我们得安装抓包软件,我这里是用F ...

  4. 小米登录协议分析_小米智能家居设备流量分析及脚本控制

    原标题:小米智能家居设备流量分析及脚本控制 *本文作者:scu-igroup,本文属 FreeBuf 原创奖励计划,未经许可禁止转载. 前言 万物互联的时代即将来临,而现阶段,我们能感触到的,当属智能 ...

  5. 小米登录协议分析_小米回应小米11充电头兼容问题

    小米11从上市销售至今已经几天时间,相信第一批入手的消费者也都收到了这款骁龙888旗舰.从网友们的使用反馈来看,小米11(点此查看评测)在充电方面出现了一些问题,并且该问题现在得到了官方的回应.元旦期 ...

  6. 小米登录协议分析_小米温湿度传感器协议分析

    博主喜欢玩智能家居的东西,智能家居确实能给家里带了不少的方便. 天气热了,博主想做一个:当屋子有人,并温度高于33度时,开空调.博主已有了一套自家的智能家居系统,有网关.人体红外传感器.红外转发器,就 ...

  7. 小米登录协议分析_性能测试篇之Loadrunner与ida工具结合完成java vuser协议的脚本...

    你这么优秀,一定只想把"柠檬班"置顶 ▲ → 性能3期优秀作业 利用lr的java vuser协议完成 (登录,md5加密完成重置支付密码,获取订单列表)请求,并加if判断完善脚本 ...

  8. “陌x”登录协议分析

    1.抓包 抓两次 2.对比 3.我们来方法刨析一下 登录 他一定有一个点击事件 我们搜onclick 方法刨析了一下 发现没找到有效的信息 4.我们来直接使用jadx-gui来搜索抓取到的字段 居然只 ...

  9. 小米登录协议分析_联想前副总裁常程跳槽小米数月后,波澜再起

    ►  文 观察者网 吕栋今年初,联想集团前副总裁常程离职2天即加盟小米,这一举动是否违反竞业协议,双方当时曾各执一词.最近,由于联想方面在北京提起劳动仲裁,此事也再度引发舆论关注.9月21日,针对&q ...

  10. IOS 最右 注册 登录协议分析记录

    目前 App Store 最新版是V5.5.28  我用的是V5.5.27 下载后载入Xcode ,准备进行动态调试 进程:tieba 不料有反调试这个文件打开,并打开这个注释,就可以调试了 经过追中 ...

最新文章

  1. call_user_func
  2. Spring - Java/J2EE Application Framework 应用框架 第 9 章 DAO支持
  3. java arraylist 源代码_Java中ArrayList源码浅析
  4. SAP CRM WebClient UI和CRM Fiori应用里Opportunity的显示过滤逻辑
  5. layui 数字步进器_图解全新奔驰S级:从“传统豪华”向“数字豪华”转型
  6. 电脑装机完没有efi_电脑装机如何选内存?看完这篇就全懂了
  7. 老李谈HTTP1.1的长连接
  8. ORA-15260 diskgroup space exhausted Problem
  9. 无需第三方app,清理Mac缓存垃圾
  10. 10 个功能独特且饱受好评的开源人工智能项目
  11. C# 访问 带密码的access数据库
  12. 前端开发之谷歌实用插件fehelper JSON助手
  13. eNSP实验二:VLAN划分与配置
  14. 抖音怎么去除水印方法及小工具
  15. Vue中报如下错误Uncaught (in promise) NavigationDuplicated解决方案
  16. openGL中向量的加减乘除运算
  17. jQuery播放音乐
  18. python(第九天)
  19. java学习之服务器第28天( --jsp--三个指令--六个动作标签--PageContext域--EL表达式--)
  20. perl mysql 数据推拉_用perl 从mysql取出数据做统计分析代码

热门文章

  1. 计算机中word音乐符号在哪里找,word音乐符号怎么打出来|word音乐符号怎么打
  2. 西工大机考《概率论与数理统计》大作业网考
  3. 单片机学习方法总结资料分享
  4. 复旦大学《高等代数学(第三版)》教材勘误表
  5. iso22000食品安全管理体系_ISO22000-食品安全管理体系认证
  6. Java实现最简单局域网QQ
  7. 凤凰职教网计算机一级成绩查询,一-凤凰职教网.PPT
  8. 服务器系统如何设置屏幕保护,在windows中要设置屏幕保护程序可以使用控制面板的什么功能?_网站服务器运行维护,windows,屏幕保护程序,控制面板...
  9. Java调用WebService接口
  10. VB编程的RS485通讯操作界面源码 本程序适应各类带RS485通讯的设备,参数可以自由修改,主要是针对各类变频器RS485通讯(RTU)格式!