首页
社区
课程
招聘
[原创]Nic*app的native层算法破解
2020-9-27 22:40 8415

[原创]Nic*app的native层算法破解

2020-9-27 22:40
8415

Nic*app的native层算法破解 原文

Nic*app的native层算法破解

案例:就不放了

抓包分析

这里抓包分析的过程不详细说了
可以看到主要有两个参数
sign和signV1
file
file

反编译

1、 sign破解

搜索关键词定位以及跳转到声明之后,最后就是一个md5,用objection看看就完事了
file
file
file
file
这是java层的sign破解,完事。

2、*-sign-v1破解

这个算法主要是在native层,这里借助了frida进行破解,最后换成cpp代码。
这里定位到这个,刚开始我也不知道这里,就瞎找,分析到这里。
file
最后确定到这两个方法,用objection确定下,最后native走的那个方法
file
可以看到最后走的是getSignRequest这个方法,并且根据上图,就可以看到so是libsalt.so。
file

2.1 分析so
  • 导入jni头文件,这里没有jni_onload,就是静态注册的。
    Java_com_*_main_helpers_utils_*SignUtils_getSignRequest找到一个加密的函数,追下去看看。
    file
    看到这么多函数,根据名字就猜测一下了,md5操作,看看是不是导出函数。
    file
    file
    file
    果然是导出函数,直接frida就去Hook一下导出函数。
    1
    2
    3
    4
    5
    6
    7
    8
    Interceptor.attach(Module.findExportByName("libsalt.so", "*_md5"), {
      onEnter: function (args) {
          console.log("*_md5 onEnter", Memory.readCString(args[0]))
      },
      onLeave: function (retvalue) {
          console.log("*_md5 onLeave", Memory.readCString(retvalue))
      }
    })
    Hook之后得到这么多
    file
    其实a4698cf0eea7a9b92a0194618079aba9是did2a0194618079aba9a4698cf0eea7a9b9
    中间进行切割,然后交换位置。
    5nhrec75lf3drenb09a349366a5b7eda4ee99d7a104fb38b8a5f746c1c9c99c0b458e1ed510845e5
    是随机字符串+md5(a4698cf0eea7a9b92a0194618079aba9)+8a5f746c1c9c99c0b458e1ed510845e5的结果
    8a5f746c1c9c99c0b458e1ed510845e5是固定值,随机字符串是java层算法。
    python这一部分的实现
    1
    2
    3
    4
    5
    6
    did = '2a0194618079aba9a4698cf0eea7a9b9'
     rstr = 'yqkdfs6y4d2ci8wm'  # 随机字did[:符串
     new_did = did[len(did) // 2:] + len(did) // 2]
     did_md5 = get_md5(new_did)
     sss = rstr + did_md5 + '8a5f746c1c9c99c0b458e1ed510845e5'
     dest = get_md5(sss)
    cpp实现:
    1
    2
    3
    4
    5
    6
    string did = "2a0194618079aba9a4698cf0eea7a9b9";
    string ranstr = "28npqz4cpmw6ifpc";
    string new_did = getStringSubs(did);
    string did_md5 = getMd5(new_did);
    string sss = ranstr + did_md5 + "8a5f746c1c9c99c0b458e1ed510845e5";
    string dest = getStringSubs(getMd5(sss));
    上边的dest是新字符串拼接需要的
    file
    这里有一个json的操作,其实刚开始我也不知道干了什么,最后我用frida-trac 就轻松解决了。
    1
    frida-trace -FU -i "strlen"
    file
    1
    array[i] = buffer[2 * i] & 0xF0 | buffer[2 * i + 1] & 0xF;
    这个是对字符串进行了高低位的操作,也就是这个app的signV3唯一个非标准算法。
    拿到高低位操作之后的字符串之后,拼接了之前的dest(我自己写的那个),然后进行sha1操作。
    sha1之后取了第8位到最后的字符串,然后又中间进行切割,然后交换位置,最后生成的就是signV3的结果。
    cpp最后实现的算法:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    string getMd5(const string &message) {
      return MD5(message).toStr();
    }
    string getSha1(const string &message) {
      SHA1 checksum;
      checksum.update(message);
      const string hash = checksum.final();
      return hash;
    }
    string getStringSubs(const string &message) {
      string string1 = message.substr(0, message.length() / 2);
      string string2 = message.substr(message.length() / 2);
      return string2 + string1;
    }
    1
    2
    3
    4
    5
    6
    7
    8
    void SignV3() {
      string did = "2a0194618079aba9a4698cf0eea7a9b9";
      string ranstr = "28npqz4cpmw6ifpc";
      string new_did = getStringSubs(did);
      string did_md5 = getMd5(new_did);
      string sss = ranstr + did_md5 + "8a5f746c1c9c99c0b458e1ed510845e5";
      string dest = getStringSubs(getMd5(sss));
      string arr = "aid=fbef33334c2388ccee5757dc2dbb0b45&comments_sort=asc&isnewsession=false&mark_read_sid=361595316249559936&mcc=&mnc=&nextkey=&timestamp=1592463682&ua=Mozilla/5.0 (Linux; Android 8.1.0; AOSP on msm8996 Build/OPM4.171019.021.D1; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/61.0.3163.98 Mobile Safari/537.36";
1
2
3
4
5
6
7
8
9
10
11
12
    const char *buffer = "aid=fbef33334c2388ccee5757dc2dbb0b45&comments_sort=asc&isnewsession=false&mark_read_sid=361595316249559936&mcc=&mnc=&nextkey=&timestamp=1592463682&ua=Mozilla/5.0 (Linux; Android 8.1.0; AOSP on msm8996 Build/OPM4.171019.021.D1; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/61.0.3163.98 Mobile Safari/537.36";
    int i = 0;
//这里的算法可以看看ida的图 自己实现呐
   string new_sss = arr.substr(0, i) + dest;
    string sha1Res = getSha1(new_sss).substr(8);
    string sign_v3 = getStringSubs(sha1Res);
    cout << "_sign_v3=" << sign_v3;
}
int main() {
    SignV3();
    return 0;
}

算法检验

file
至于为什么最后不放python算法,实在是因为,还原成python之后,高低位操作的时候,部分数据不对了。。就只有cpp了
此文章仅用于学习交流,请勿商业用途和传播。
Nic*app的native层算法破解 原文


[培训]二进制漏洞攻防(第3期);满10人开班;模糊测试与工具使用二次开发;网络协议漏洞挖掘;Linux内核漏洞挖掘与利用;AOSP漏洞挖掘与利用;代码审计。

收藏
点赞1
打赏
分享
最新回复 (9)
雪    币: 6790
活跃值: (8540)
能力值: ( LV17,RANK:797 )
在线值:
发帖
回帖
粉丝
无名侠 12 2020-9-28 01:24
2
0
我猜,这种情况,你可以用 ctypes 库解决。 
雪    币: 162
活跃值: (61)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
LC 2020-9-28 18:30
3
0
楼主方便给下联系方式吗? Q578878142
雪    币: 4932
活跃值: (5296)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
mb_aoooaosd 2020-9-28 21:02
4
0
无名侠 我猜,这种情况,你可以用 ctypes 库解决。
谢谢大佬指点
雪    币: 2719
活跃值: (1507)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
Vn小帆 2020-9-29 08:55
5
0
数据  他是走的  TCP 协议 ?
雪    币: 2719
活跃值: (1507)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
Vn小帆 2020-9-29 08:55
6
0
python  base64 解决不了 后来 用java 才解决的
雪    币: 1454
活跃值: (267)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
愤怒的平头哥 2020-9-29 09:59
7
0
感谢分享
雪    币: 4932
活跃值: (5296)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
mb_aoooaosd 2020-9-29 19:40
8
0
Vn小帆 数据 他是走的 TCP 协议 ?
我看是http   base64没懂??
雪    币: 304
活跃值: (683)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
tianhaoday 2020-9-30 09:51
9
0
大佬能分析一下 MJTQ(墨迹)的签名算法么
雪    币: 2063
活跃值: (3823)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
lhxdiao 2020-10-2 18:21
10
0
tianhaoday 大佬能分析一下 MJTQ(墨迹)的签名算法么
https://www.die.lu/core/index.php/2020/09/15/332/
游客
登录 | 注册 方可回帖
返回