Crack App | 某赢+ 二手车 App 登录参数加密逻辑分析

本文涉及的产品
密钥管理服务KMS,1000个密钥,100个凭据,1个月
简介: Crack App | 某赢+ 二手车 App 登录参数加密逻辑分析

加固

经过查壳,没有发现加固

抓包分析

打开 app ,进入登录界面

随便输入账号密码,点击登录,提示版本过低,虽然提示这个但是并不妨碍我们抓包

打开小黄鸟,重新登录一下,可以看到下面的结果包

请求提交的参数如下

除了 username 之外这里还对 password 加密了

目前未知的参数有 udid、_sign、pwd 这三个参数

加密参数定位与分析

使用 jadx 直接打开 apk

udid

直接搜索关键字 udid

搜索关键词类似的结果很多

可以全部都打开看看

基本都类似下面的代码

而且可以看到,所有生成 udid 的方法都使用了 encode3Des 加密了这么一大串的值getIMEI(context) + "|" + System.nanoTime() + "|" + SPUtils.getDeviceId()

找到离加密最近的地方才有机会看到真相

所以直接 hook encode3Des这个加密的方法,先拿到加密的 str 和结果看看

function main(){
    Java.perform(function () {
        var EncryptUtil = Java.use("com.xx.xx.xx.SecurityUtil");
        EncryptUtil.encode3Des.implementation = function (arg1, arg2) {
            console.log("参数 str2 ==> " + arg2);
            var result = this.encode3Des(arg1,arg2);
            console.log("result ==> " + result);
            return result;
        }
    })
}
setImmediate(main)

然后使用命令运行 hook 脚本

frida -U -F xx.xx.xx-l hook.js

hook 结果如下

多次尝试下,

参数 2 的第一部分是getIMEI,中间部分是动态时间戳,第三部分是getDeviceId

只有中间部分是动态的

接下来可以看看 encode3Des  的加密部分了

这里可以看到加密使用的是 CBC 加密模式,然后这里的 iv 就在 class 的上方,也是一个固定值

看过之前文章的朋友应该知道,现在就缺少 key,我们就可以直接复现 udid 的加密了

这里的 key 由String desKey = AHAPIHelper.getDesKey(context);生成

跟进去可以看到加密由 native方法生成

直接 hook 一下看看

function main(){
    Java.perform(function () {
        var EncryptUtil = Java.use("com.xxx.xxx.xxx.xxx");
        EncryptUtil.encode3Des.implementation = function (arg1, arg2) {
            console.log("参数 arg2 ==> " + arg2);
            var result = this.encode3Des(arg1,arg2);
            console.log("result ==> " + result);
            return result;
        }
        var deskey = Java.use('com.xxx.xxx');
        deskey.getDesKey.implementation=function (arg1){
            var result = this.getDesKey(arg1);
            console.log("deskey result ==> " + result);
            return result;
        }
        var jni_check = Java.use("com.xxx.xxx.xxx.xxx");
        jni_check.checkSignimplementation = function (arg1) {
            var result = this.encode3Des(arg1);
            console.log("jni_check result ==> " + result);
            return result;
        }
    })
}
setImmediate(main)

然后再运行一下,打印结果如下

注意这里 jni_check 想要 hook  上记得使用 spawn 模式,上面的两个方法可以使用 attach 模式直接hook

以上就获取到了udid加密的 key iv mod 和加密的内容和结果,可以直接使用 Python 复现一下

import pyDes
import base64
def decrypt_response(data):
    secretkey = "这里key"[:-8]
    iv = "appapich"
    des_obj = pyDes.triple_des(key=secretkey, IV=iv, padmode=pyDes.PAD_PKCS5, mode=pyDes.CBC)
    print(base64.b64encode(des_obj.encrypt(data)).decode())
if __name__ == '__main__':
    decrypt_response("351615080737802|16936902758945|332220")

输出结果如下

和 hook 的结果一样,这样就完成了 udid 的生成

pwd

pwd 的结果是一串 32 位的字符串

同样的搜索一下,可以搜索 pwd 得到的结果有很多

但是搜索"pwd"

结果如下,而且所在位置也是请求登录的逻辑中,所以大胆猜测就是这里了

可以看到这里使用 encodeMD5

我输入的结果是12345678,通过抓包可以知道,pwd加密好的结果是25d55ad283aa400af464c76d713c07ad

直接扔到加密站里测试一下,看看结果是不是标准的 MD5 ,是的话连分析都免了

和标准的 MD5 加密结果相同

_sign

同样的搜索一下关键字

找到下面这段逻辑,是生成请求参数的逻辑

这里的 toSign 方法继续追进去

用到了上面 pwd 相同的 encodeMD5 逻辑

不过这里就需要 hook 一下 encodeMD5看一下入参

function main(){
    Java.perform(function () {
        var EncryptUtil = Java.use("com.xxx.xxx.xxx.xxx");
        EncryptUtil.encode3Des.implementation = function (arg1, arg2) {
            console.log("参数 arg2 ==> " + arg2);
            var result = this.encode3Des(arg1,arg2);
            console.log("result ==> " + result);
            return result;
        }
        EncryptUtil.encodeMD5.implementation = function (arg1) {
            console.log("encodeMD5 参数 arg1 ==> " + arg1);
            var result = this.encodeMD5(arg1);
            console.log("result ==> " + result);
            return result;
        }
        var deskey = Java.use('com.xxx.xxx.xxx');
        deskey.getDesKey.implementation=function (arg1){
            var result = this.getDesKey(arg1);
            console.log("deskey result ==> " + result);
            return result;
        }
    })
}
setImmediate(main)

hook 结果如下

对比一下抓包,大致就清楚了,这里的hash 内容就是请求提交的参数,做这个 sign 就是防止改包的

到这里我们就完成了这个 app 请求包中所有加密参数的分析

我们试着用 Python 复现一下请求流程

Python 实现请求全流程

结果和抓包是一样的

这次研究的样本是网上找的旧版样本,之后有机会试试新版的

End.

相关文章
|
2月前
|
XML Java 数据库
安卓项目:app注册/登录界面设计
本文介绍了如何设计一个Android应用的注册/登录界面,包括布局文件的创建、登录和注册逻辑的实现,以及运行效果的展示。
159 0
安卓项目:app注册/登录界面设计
|
2月前
|
UED
|
2月前
|
移动开发 前端开发 Android开发
开发指南059-App实现微信扫描登录
App是用uniapp开发的,打包为apk,上传到安卓平板中使用
|
4月前
【Azure Logic App】消费型逻辑应用在消费Service Bus时遇见消息并发速度慢,消息积压
【Azure Logic App】消费型逻辑应用在消费Service Bus时遇见消息并发速度慢,消息积压
|
4月前
【Azure Logic App】在逻辑应用中开启或关闭一个工作流是否会对其它工作流产生影响呢?
【Azure Logic App】在逻辑应用中开启或关闭一个工作流是否会对其它工作流产生影响呢?
|
4月前
|
存储 SQL JSON
【Azure Logic App】微软云逻辑应用连接到数据库,执行存储过程并转换执行结果为JSON数据
【Azure Logic App】微软云逻辑应用连接到数据库,执行存储过程并转换执行结果为JSON数据
【Azure Logic App】微软云逻辑应用连接到数据库,执行存储过程并转换执行结果为JSON数据
|
4月前
|
API 网络架构
【Azure Logic App】在中国区的微软云服务上,使用逻辑应用是否可以下载SharePoint上的文件呢?
【Azure Logic App】在中国区的微软云服务上,使用逻辑应用是否可以下载SharePoint上的文件呢?
【Azure Logic App】在中国区的微软云服务上,使用逻辑应用是否可以下载SharePoint上的文件呢?
|
4月前
|
Java
【Azure 应用服务】如何查看App Service Java堆栈JVM相关的参数默认配置值?
【Azure 应用服务】如何查看App Service Java堆栈JVM相关的参数默认配置值?
【Azure 应用服务】如何查看App Service Java堆栈JVM相关的参数默认配置值?
|
4月前
|
安全 API 网络架构
【Azure Logic App】使用 Easy Auth 在标准逻辑应用(Standard Logic App)中触发工作流
【Azure Logic App】使用 Easy Auth 在标准逻辑应用(Standard Logic App)中触发工作流