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月前
|
JavaScript 应用服务中间件 Linux
【应用服务 App Service】解决无法从Azure门户SSH登录问题
【应用服务 App Service】解决无法从Azure门户SSH登录问题
|
1月前
|
安全
【Azure App Service】App service无法使用的情况分析
App Service集成子网后,如果子网网段中的剩余IP地址非常少的情况下,会在App Service实例升级时( 先加入新实例,然后在移除老实例 )。新加入的实例不能被分配到正确的内网IP地址,无法成功的访问内网资源。 解决方法就是为App Service增加子网地址, 最少需要/26 子网网段地址。
|
2月前
【Azure Logic App】消费型逻辑应用在消费Service Bus时遇见消息并发速度慢,消息积压
【Azure Logic App】消费型逻辑应用在消费Service Bus时遇见消息并发速度慢,消息积压
|
2月前
【Azure Function App】本地运行的Function发布到Azure上无法运行的错误分析
【Azure Function App】本地运行的Function发布到Azure上无法运行的错误分析
|
2月前
【Azure Logic App】在逻辑应用中开启或关闭一个工作流是否会对其它工作流产生影响呢?
【Azure Logic App】在逻辑应用中开启或关闭一个工作流是否会对其它工作流产生影响呢?
|
2月前
|
存储 SQL JSON
【Azure Logic App】微软云逻辑应用连接到数据库,执行存储过程并转换执行结果为JSON数据
【Azure Logic App】微软云逻辑应用连接到数据库,执行存储过程并转换执行结果为JSON数据
【Azure Logic App】微软云逻辑应用连接到数据库,执行存储过程并转换执行结果为JSON数据
|
2月前
|
API 网络架构
【Azure Logic App】在中国区的微软云服务上,使用逻辑应用是否可以下载SharePoint上的文件呢?
【Azure Logic App】在中国区的微软云服务上,使用逻辑应用是否可以下载SharePoint上的文件呢?
【Azure Logic App】在中国区的微软云服务上,使用逻辑应用是否可以下载SharePoint上的文件呢?
|
2月前
|
安全 API 网络架构
【Azure Logic App】使用 Easy Auth 在标准逻辑应用(Standard Logic App)中触发工作流
【Azure Logic App】使用 Easy Auth 在标准逻辑应用(Standard Logic App)中触发工作流
|
2月前
|
开发者
【Azure Logic App】中国区标准版本的逻辑应用(Standard Logic App)无法查看历史执行记录的解决之道
【Azure Logic App】中国区标准版本的逻辑应用(Standard Logic App)无法查看历史执行记录的解决之道
|
2月前
|
开发框架 缓存 .NET
【App Service】在Azure App Service中分析.NET应用程序的性能的好帮手(Review Stack Traces)
【App Service】在Azure App Service中分析.NET应用程序的性能的好帮手(Review Stack Traces)
下一篇
无影云桌面