2

爬虫利器:Frida Rpc算法转发

 1 year ago
source link: https://netsecurity.51cto.com/article/712428.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

爬虫利器:Frida Rpc算法转发-51CTO.COM

爬虫利器:Frida Rpc算法转发
作者:Python进阶者 2022-06-27 09:23:14
本章来给大家介绍一个爬虫利器,app协议还原利器更合适,这个东西我们一般称它为frida rpc算法转发。
94663dd284331d4fc2d213fbc8a7147fcf3dd9.jpg

本章来给大家介绍一个爬虫利器,嗯。。。,app协议还原利器更合适,当然,自己用的话是利器,别人用是折磨,因为它需要依赖模拟器或手机。对于环境来说是有些麻烦的!

这个东西我们一般称它为frida rpc算法转发。

为什么使用rpc算法转发

我们都知道现在开发app主流的方案是Java,一些中大厂app是Java+C++,C++最后生成的是so,是arm汇编。

一般分析arm汇编才是最难的,所以中大厂会更倾向把重要加密放在so中,来增强爬虫或者破解的难度!!!

但是如果使用rpc的话,你就不太需要分析繁琐的Java层和so层的加密了!

你需要通过frida主动调用Java层或so层的方法,然后拿到被加密的内容,然后其他的操作不是就可以为所欲为了?

pixel2   v10(已root)
Magisk   v23.0
Charles  v4.6.2
Drony    v1.3.154
Python   v3.8.6
frida    v14.2.18

rpc转发案例

本次使用的app是嘟嘟牛,百年只刚嘟嘟牛,哈哈哈!

通过抓包发现,走的接口是http://api.dodovip.com/api/user/login

图片

提交的是一个Encrypt:xxxx,返回的是一串字符串,这???啥玩意???

所以我们要模拟这个请求,必定要捋清这个请求和响应是怎么生成的!

app拖入jadx中,搜索关键字Encrypt:

图片

主要加密逻辑在这一块:

图片

分析不是这一章的重点,相关hook代码,稍微研究一下就懂了!

Java.perform(function () {

    function printMap2(map) {
        return Java.cast(map, Java.use("java.util.HashMap"));
    }

    //
    Java.use("com.dodonew.online.http.RequestUtil").encodeDesMap.overload('java.lang.String', 'java.lang.String', 'java.lang.String').implementation = function (data, desKey, desIV) {
        console.log("RequestUtil encodeDesMap is call")
        console.log("data:", data)
        console.log("desKey:", desKey)//65102933
        console.log("desIV:", desIV)//32028092
        let result = this.encodeDesMap(data, desKey, desIV)
        console.log("RequestUtil encodeDesMap result:", result)

        return result
    }


    Java.use("com.dodonew.online.http.RequestUtil").paraMap.overload('java.util.Map', 'java.lang.String', 'java.lang.String').implementation = function (addMap, append, sign) {
        console.log("RequestUtil paraMap is call")
        console.log("addMap:", addMap)
        console.log("addMap:", printMap2(addMap))
        console.log("append:", append)
        console.log("sign:", sign)
        let result = this.paraMap(addMap, append, sign)
        console.log("RequestUtil paraMap result:", result)

        return result
    }

    Java.use("com.dodonew.online.http.RequestUtil").decodeDesJson.implementation = function (json, desKey, desIV) {
        console.log("RequestUtil decodeDesJson is call")
        console.log("json:", json)
        console.log("desKey:", desKey)
        console.log("desIV:", desIV)
        let result = this.decodeDesJson(json, desKey, desIV)
        console.log("RequestUtil decodeDesJson result:", result)

        return result
    }


})

根据上述hook,整理出来主动调用应该是这样调用的,一个加密,一个解密。

//请求加密
function callparaMap(username, userPwd, timeStamp) {
    let result = "";
    Java.perform(function () {
        let map = Java.use("java.util.HashMap").$new();
        map.put("timeStamp", timeStamp)
        map.put("loginImei", "Androidnull")
        map.put("equtype", "ANDROID")
        map.put("userPwd", userPwd)
        map.put("username", username)
        //
        let r1 = Java.use("com.dodonew.online.http.RequestUtil").paraMap(map, "sdlkjsdljf0j2fsjk", "sign")
        // console.log("r1:", r1)
        //
        result = Java.use("com.dodonew.online.http.RequestUtil").encodeDesMap(r1, "65102933", "32028092")
        // console.log("r2:", r2)
    })
    return result;

}
//响应加密
function calldecodedesjson(data) {
    let result = "";
    Java.perform(function () {
        result = Java.use("com.dodonew.online.http.RequestUtil").decodeDesJson(data, "65102933", "32028092")
        // console.log("decode:", decode)
    })
    return result;
}

既然上述已经把逻辑捋清楚了,并且也已经写好的主动调用的js代码。

那么就来了,如何和python结合到一起,跑成一个web,这样爬虫只需要响应的参数拿到返回值即可。

from fastapi import FastAPI
import uvicorn
import frida

jsCode = """
    function callparamap(username, userPwd, timeStamp) {
        let result = "";
        Java.perform(function () {
            let map = Java.use("java.util.HashMap").$new();
            map.put("timeStamp", timeStamp)
            map.put("loginImei", "Androidnull")
            map.put("equtype", "ANDROID")
            map.put("userPwd", userPwd)
            map.put("username", username)
            //
            let r1 = Java.use("com.dodonew.online.http.RequestUtil").paraMap(map, "sdlkjsdljf0j2fsjk", "sign")
            // console.log("r1:", r1)
            //
            result = Java.use("com.dodonew.online.http.RequestUtil").encodeDesMap(r1, "65102933", "32028092")
            // console.log("r2:", r2)
        })
        return result;
    
    }
    
    function calldecodedesjson(data) {
        let result = "";
        Java.perform(function () {
            result = Java.use("com.dodonew.online.http.RequestUtil").decodeDesJson(data, "65102933", "32028092")
            // console.log("decode:", decode)
        })
        return result;
    }
    rpc.exports = {
        encrypt: callparamap,
        decode: calldecodedesjson,
    };
"""
# 准备工作
# process = frida.get_device_manager().add_remote_device('192.168.3.68:27042').attach("com.dodonew.online")
process = frida.get_usb_device().attach('com.dodonew.online')
script = process.create_script(jsCode)
print('[*] Running 小肩膀')
script.load()

app = FastAPI()


# http://127.0.0.1:8080/getencrypt?username=18903916120&password=1111&timestamp=1647662720061
@app.get("/getencrypt")
async def getencrypt(username, password, timestamp):
    result = script.exports.encrypt(username, password, timestamp)
    return {"data": result}


from pydantic import BaseModel


class Item(BaseModel):
    data: str


@app.post("/getdecode")
async def getdecode(item: Item):
    result = script.exports.decode(item.data)
    return {"data": result}


if __name__ == '__main__':
    uvicorn.run(app, port=8080)
图片
import requests
import time
import json

dt = time.time() * 1000

# 请求加密
url = f"http://127.0.0.1:8080/getencrypt?username=18903916120&password=1111&timestamp={dt}"
r1 = requests.get(url)
print(r1.json())
# 登录
url = "http://api.dodovip.com/api/user/login"
headers = {
    "Content-Type": "application/json;charset=utf-8"
}
data = {
    "Encrypt": r1.json().get("data")
}
print(data)
r = requests.post(url=url, headers=headers, data=json.dumps(data))
print(r.text)
# 拿到请求解密
data = {
    "data": r.text
}
url = "http://127.0.0.1:8080/getdecode"
r = requests.post(url=url,headers=headers, data=json.dumps(data))
print(r.text)
图片

这个app还是很简单的,但是应该用到了俩加密,如果要是硬刚代码的话,还是需要研究研究的。

但是如果使用rpc这种转发方案的话,你就可以发现几行代码就完事了!

但是缺陷也是明显的,需要依赖电脑和手机,如果只是采集数据的话,应该还是挺合适的!


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK