跟着超弟学逆向之——Android逆向脱壳分析(某漫画软件签名参数逆向罕见完整版)稀缺资源,看到就是赚到

软件下载官网:aHR0cHM6Ly9tc21oLnNpdGUv

一. 起因

很久之前为了看擅长捉弄的高木同学,问别人要到了这个漫画软件,但是有广告...
那么就想办法下载下来吧(以后还能看)

二. 抓包

先抓个搜索功能开开胃。

靠,有加密数据。好好好,你这么玩是吧。那我就要掏出我的算法助手了。

启动算法助手并尝试获取加密方式和秘钥

没获取到什么有用的东西

SimpleHook再试试

出乎意料的是SimpleHook结果中也没有找到有用的数据,但是比算法助手多了几个DES的结果

好好好,这样玩的话,我可就只能尝试逆向代码了。

三. 脱壳

  1. 打开MT管理器提取安装包,发现被360加固了捏。还好我有珍惜大佬的FunDex
  2. LSPosed启用模块,选择作用域;FunDex选择软件,一套组合拳打出来,然后打开软件,把每个Tab都点一下确保dex脱的干净一点。
  3. 再打开MT管理器,找到该软件的data目录,就能看到脱出来的dex啦。然后全选、移动、压缩、发送到电脑一气呵成。
  4. 四. 分析

  5. 直接搜索关键字

  6. 用jadx直接打开压缩包,搜索safetyData
  7. 这类名,这函数名,太符合我的想象了。
    我们回味一下抓到的数据包的json格式。
    然后我们立马就看到了重点的几行
  8. ResponseSafetyInfo cast = (cls2 != null ? cls2 : ResponseSafetyInfo.class).cast(b8);
    String type2 = cast.getType();
    String[] token = cast.getToken();
    INetSafety encryptor = NetSafetyUtils.getEncryptor(type2);
    if (encryptor != null && token != null && token.length != 0) {
        Long valueOf = Long.valueOf(System.currentTimeMillis());
        c8 = encryptor.decrypt(c8, token);
        System.currentTimeMillis();
        valueOf.longValue();
    }

  9. 首先是转为ResponseSafetyInfo类,这不是对应safety字段嘛。
    所以变量type2就是14339,token就是YD6YTGLPA
    再看NetSafetyUtils.getEncryptor(type2),追进去

  10. 这个encryptoMap肯定有用,看一下啥时定义的

  11. 可以看到是在static里面定义的,在根据变量f7372e2 = '14339'和刚才的type2 = 14339,找到对应的NetSafetyUtils.a(),再追

  12. 再追

  13. 终于看到希望了,再追进去

  14. 豁然开朗,加密方法非常明了,非常简单。
    此时我们可以看到左边还有很多DES的类,肯定是有用的,我们稍后再看。
    先看一下

  15. new DESHelper(new StringBuilder(strArr[0].substring(1)).reverse().toString()).decrypt(str);

  16. 很显然,秘钥是处理之后的字符串,翻译成python就是[-1:0:-1]。
  17. 五. 实现

  18. 从网上找一个DES加解密的类
  19. from Crypto.Cipher import DES
    from binascii import b2a_base64, a2b_base64
    
    class PrpCrypt(object):
        def __init__(self, key):
            self.key = key.encode('utf-8')
            self.mode = DES.MODE_ECB
            
        def changeKey(self, key):
            self.key = key.encode('utf-8')
            
        def encrypt(self, text):
            text = text.encode('utf-8')
            cryptor = DES.new(self.key, self.mode)
            length = 16
            count = len(text)
            if count < length:
                add = (length - count)
                text = text + ('\07' * add).encode('utf-8')
                print(text)
            elif count > length:
                add = (length - (count % length))
                text = text + ('\07' * add).encode('utf-8')
                print(text)
            self.ciphertext = cryptor.encrypt(text)
            return b2a_base64(self.ciphertext)
    
        def decrypt(self, text):
            cryptor = DES.new(self.key, self.mode)
            plain_text = cryptor.decrypt(a2b_base64(text))
            return plain_text.decode("utf-8").rstrip("\01").rstrip("\03")

  20. 1.搜索功能

  21. 发个请求测试一下
  22. import requests
    headers = {
        'Cache-Control': 'public,max-age=60',
        'Content-Type': 'application/json; charset=UTF-8',
        'Host': '43.248.116.78:20256',
        'Connection': 'Keep-Alive',
        'User-Agent': 'okhttp/4.10.0',
    }
    
    data = {
        'key': '擅长捉弄的高木同学',
        'appChannel': 'normal',
        'appKey': 'com.aster.zhbj',
        'appVersion': 'v1.10.5',
        'clientTime': 1696328622216,
        'deviceBrand': 'Xiaomi',
        'deviceType': '22041211AC',
        'ipAddr': '192.168.0.221',
        'netType': 'WIFI',
        'platform': 0,
        'sign': '',
        'systemVersion': '12',
        'userId': '1526xxxxxxxc8f70abce2',
        'uuid': 'df82xxxxxxx65d407e64ddf',
        'versionCode': 48
    }
    response = requests.post(
        'http://43.248.116.78:20256/api/novel/search/associate', headers=headers, json=data).json()
    # 秘钥处理方法14239,14339
    token = response['safety']["token"][0][-1:0:-1]
    cry = PrpCrypt(token)  # 初始化密钥
    decode = cry.decrypt(response["safetyData"])
    decode = json.loads(decode)
    print(decode)

    看看输出结果(部分)

  23. [
        {
            "key": "<word>擅长</word><word>捉弄</word><word>的</word><word>高木</word><word>同学</word>",
            "relationType": 1,
            "relationId": "af0580069e7031e3f03f27fb4ff26cdb",
            "extra": "{"authorName":"山本崇一朗"}"
        },
        {
            "key": "<word>擅长</word><word>捉弄</word><word>的</word>(<word>原</word>)<word>高木</word><word>同学</word>",
            "relationType": 1,
            "relationId": "9d8b4dad7954734a471cb21452e917e0",
            "extra": "{"authorName":"山本崇一朗"}"
        }
    ]

很好,解密成功了,这是一个好的开始

之后的按照我上面的思路进行下去,基本没什么大问题,剩下的你们尝试解决,实在不行,可私信留言

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值