大神论坛

找回密码
快速注册
查看: 3003 | 回复: 0

[Android] 某(dewu)app NewSign 抓包分析全过程记录

digest

主题

帖子

11

积分

初入江湖

UID
28
积分
11
精华
威望
22 点
违规
大神币
68 枚
注册时间
2021-04-10 15:59
发表于 2021-04-11 17:30
本帖最后由 rong 于 2021-04-11 17:30 编辑

得物NewSign分析过程

目的: 分析NewSign算法

使用到工具

jadx
frida
ida

该app很恶心,有些同学设置了https证书和代{过}{滤}理后,都无法抓包,是因为它在调用okhttp3的时候设置了 NO_PROXY模式 所以需要先把它干掉,不然我们抓不到包,话不多说,直接上脚本

try {
    var URL = Java.use('java.net.URL')
    URL.openConnection.overload('java.net.Proxy').implementation = function (
      arg1
    ) {
      return this.openConnection()
    }
  } catch (e) {
    console.log('' + e)
  }

  try {
    var Builder = Java.use('okhttp3.OkHttpClient$Builder')
    var mybuilder = Builder.$new()
    Builder.proxy.overload('java.net.Proxy').implementation = function (arg1) {
      return mybuilder
    }
  } catch (e) {
    console.log('' + e)
  }

然后我们就可以欢快的抓包了

图片
很好,我们抓到包了.
我们大概看一下结构
header部分我们暂时不用管.只需要注意timestamp.
我们看postdata部分
newSign 这是我们今天的主角.....
返回内容是明文,我们没什么好研究的.

我们先看下这个东西怎么来了.

把得物.apk拖入jadx先分析
搜索字符串 "newSign"
图片

看到有5个地方
咱们从第一个开始,进入后看到
图片
newSign是从 RequestUtils.c(hashMap2, currentTimeMillis) 来的
先看看hashMap2 是什么
图片
发现hashMap2只是一个 HashMap 字典.
currentTimeMillis 就是一个时间戳,做了一个运算,减去一个超时时间,在实际使用中 直接传当前时间戳-1000 就可以有效了.
然后我们进 RequestUtils.c 看看是什么
图片
该函数分解
在我们传进来的字典中添加 uuid, platform, v, loginToken, timestamp
然后对字典的所有key 进行升序排序
接下来生成一个新的字符串

比如hashMap 是 {"c": 1, "a": 2}
那么经过上面的过程生成的新字符串是: a2c1

然后最后返回是 a(AESEncrypt.b(DuHttpConfig.c, sb2));

我们继续先进到 AESEncrypt.b 看看
图片

拆解b干了些啥

先调用 getByteValues 获取值
然后将该值就行反转,所谓反转的意思是 0变1 非0变0
如: 1ac100 反转后 结果是 000011
因为非0 都是0  0是1

然后调用 encodeByte 就行计算并返回

然后 getByteValues encodeByte 都是so里面的函数,我们拉到上面可以看到
图片
这两个函数都是 JNIEncrypt 这个so文件的
(不会有人不会提取吧,好吧.把.apk文件改成.rar,然后打开,在lib里面找.全名是 lib + 引用库名 + .so, 上面的结果就应该是 libJNIEncrypt.so)

图片

现在就需要上我们的ida了
图片
图片

直接看到了 java函数和so函数的对应关系
getByteValues -> get_bytes
encodeByte -> encode

我们先进入 get_bytes 看看
图片

我的天啊 一堆字符拼接,要取这里的内容 可以直接用frida调用一次就出来了.不用深究.我们看 encode

图片

发现关键点了. AES ECB PKCS5PADDING
我们看看 这个函数是干嘛的
进去以后看到各种算法,在最后返回了一个base64
我们猜测这个就是加密的关键函数,但是我们没有明文和密钥.
现在我们就来取一下看看
先看改函数的声明如下:
图片
有两个参数,我们用frida直接hook它 看看能得到什么?
直接上脚本

var AESBase = Module.findExportByName("libJNIEncrypt.so", "AES_128_ECB_PKCS5Padding_Encrypt")
console.log(AESBase);
Interceptor.attach(AESBase, {
    onEnter: function(args){
        console.log("-------------参数 1-------------");
        console.log(args[0].readUtf8String())
        console.log("-------------参数 2-------------");
        console.log(args[1].readUtf8String());
    },
    onLeave: function(retValue){
        console.log("-------------返回-------------");
        console.log(retValue.readUtf8String());
    }
})

图片

通过以上返回结合我们抓包时提交和上面看到的hashmap处理方式 我们可以基本断定 16个X 就是aes加密的key

到此 encodeByte 分析完毕

接下来回到java代码中,因为aes后还有一个 a 函数的调用

我们进到a函数....

图片

好吧 就是一个MD5,非魔改的md5.....

结论

newSign = MD5(aes_ecb_pk5padding(排序拼接成的字符, 16个x))

感谢各位......
写教程不易,请不要吝啬各位的免费积分.再次感谢各位.

返回顶部