分析请求

环境:apk7.18.0,安卓5 32位

请求的参数如下:
在这
里插入图片描述
经过测试,_sig和_ts是变的,其他是固定的。_ts是时间戳,sig是加密参数,sig就是这次案例要逆向的参数。

查壳

用GDA查一下看是否加固在这里插入图片描述
发现并没有壳,这就简单多了

反编译

既然没有壳,直接用jadx反编译,搜索 “_sig”
在这里插入图片描述
搜索出来的结果并不多,而且还看到了 add(“_sig”),这种很大概率就是我们要找到的入口了。点击进去


在这里插入图片描述
果不其然,就是我们要找的入口,“_sig” 是a2.first赋值,而a2.first 由 ApiSignatureHelper.a()得到
继续追进去,

在这里插入图片描述

ApiSignatureHelper.a() 最终返回 (HMACHash1.a(str4, sb.toString()), String.valueOf(currentTimeMillis))
可得到:

_sig = HMACHash1.a(str4, sb.toString()
_ts = String.valueOf(currentTimeMillis) // 时间戳

加密逻辑

继续追进去
HMACHash1类 的具体代码
在这里插入图片描述
HMACHash1.a() 找到了,但str,str2 怎么生成的,具体是多少,我们还不知道。
接下来用 frida hook大法看看str,str2 究竟是怎么生成的。
hook 的代码:

Java.perform(
    function(){
        let HMACHash1 = Java.use("com.douban.frodo.utils.crypto.HMACHash1");
        HMACHash1["a"].implementation = function (str, str2) {
        console.log('a 函数被调用' + ', ' + 'str的值: ' + str + ', ' + 'str2的值: ' + str2);
        let ret = this.a(str, str2);
        console.log('a()返回的结果:' + ret);
        return ret;
        };
    }
)

hook 输出的结果:
在这里插入图片描述
hook的结果得到:

  • str是固定不变的
  • str2:GET&/api/v2/subject_collection/ECZU5SJAI/items&1677143681
    str2的构成是,请求方式 + url中的资源路径 + 时间戳
    url中的资源路径 如:https://xxx.xxx.com/api/v2/tv/year_ranks,那么资源路径就是:/api/v2/tv/year_ranks

Flask + rpc hook 搭建接口

加密的方法找到了,现在的问题是怎么供爬虫使用呢,一般有两种方法实现

  • python还原加密方法
  • rpc hook 接口的方式调用

还原加密方法

案例中这个加密的方法还是比较简单的,HMACSHA1加密通过hmac模块实现,返回Base64编码,python的还原代码:

import hmac
from hashlib import sha1

hmac_code = hmac.new(str1.encode(), str2.encode(), sha1).digest()
sig = base64.b64encode(hmac_code).decode()

rpc hook

但是如果的加密的方法很复杂的话,我们一般是用第二种方式,这种方法的优点是不用梳理加密的实现逻辑。做成接口方式提供给爬虫用
rpc hook 实现:


from flask import Flask
import frida
from flask import request

app = Flask(__name__)

def on_message(message, data):
    print("[%s] => %s" % (message, data))


jscode = """
    rpc.exports = {
        getsig: function(str2){
            console.log("start hook");
            var ret;
            Java.perform(
                function(){
                    let HMACHash1 = Java.use("com.douban.frodo.utils.crypto.HMACHash1");
                    let str = 'bf7dddc7c9cfe6f7';
                    ret = HMACHash1.a(str, str2);
                    console.log('a返回的结果:' + ret);
                })
            return ret;
        }
    };
"""
process = frida.get_usb_device().attach('xxx')# 包名

@app.route('/')
def index():
    return '<h1>Hello World</h1>'

@app.route('/sig')
def get_sig():
    script = process.create_script(jscode)
    script.on('message', on_message)
    script.load()
    content = request.args.get("content") # 获取提交的参数
    sig = script.exports.getsig(content) 
    return str(sig)


if __name__ == '__main__':
    app.run()

在这里插入图片描述

更多推荐