rpc hook某瓣APP的_sig参数
·
分析请求
环境: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()

更多推荐



所有评论(0)