diff --git a/README.md b/README.md index 03ae7f3..05280f4 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,14 @@ Do By You Self! `Python`执行`PyexecJs`通过`Js的AST树`结构获取`Frida-Js`脚本中`rpc.exports`的方法以及对应方法的参数个数,根据方法名和参数个数通过`types.FunctionDef`从`Python AST字节码`来动态生成新的`Function对象`,并且结合`pydantic`的`create_model`自动生成的参数模型注册到`FastAPI的路由系统`中,实现`Frida-RPC`的功能。 +## 核心功能 + +1. 对接多个`App`的`RPC接口暴露` + +2. 自动转化`Js export`方法变成接口 + +3. 自动生成接口文档 + ## Install ```sh diff --git a/apps/yuxueyuan.js b/apps/yuxueyuan.js new file mode 100644 index 0000000..53b3f4d --- /dev/null +++ b/apps/yuxueyuan.js @@ -0,0 +1,18 @@ +var result = null; +function get_sign(body) { + Java.perform(function () { + try { + var ksecurity = Java.use('com.drcuiyutao.lib.api.APIUtils'); + result = ksecurity.updateBodyString(body) + console.log("myfunc result: " + result); + } catch (e) { + console.log(e) + } + }); + return result; +} + + +rpc.exports = { + getSign: get_sign, +} \ No newline at end of file diff --git a/config.py b/config.py index a713f2b..a932dd7 100644 --- a/config.py +++ b/config.py @@ -11,3 +11,15 @@ ''' from pathlib import Path PRASE_PATH = Path(__file__).absolute().parent / "parse.js" +INJECTION_APPS = [ + { + "name": "育学园", + "path": "yuxueyuan", + "package_name": "com.drcuiyutao.babyhealth" + }, + { + "name": "快读作业", + "path": "kuaiduizuoye", + "package_name": "com.kuaiduizuoye.scan" + } +] diff --git a/main.py b/main.py index 3027509..7a25018 100644 --- a/main.py +++ b/main.py @@ -12,6 +12,7 @@ from pathlib import Path from pydantic import BaseModel, Field, create_model from fastapi import APIRouter +from fastapi.openapi.utils import get_openapi import time import frida from starlette.applications import Starlette @@ -31,40 +32,70 @@ function_params_hints = { "encryptData": [0, 0, 0, 0, "", 0, 0, 0, 0, 0, 0] } # app相关信息 +_frida_js_path1 = Path(__file__).absolute().parent/"apps/yuxueyuan.js" _frida_js_path = Path(__file__).absolute().parent/"apps/kuaiduizuoye.js" _package_name = "com.kuaiduizuoye.scan" +_package_name1 = "com.drcuiyutao.babyhealth" -# frida注入 +# frida启动前检测 if not detect_frida_state(): # 启动frida-server,增加延迟防止附加失败 start_frida_server() time.sleep(3) -session = frida.get_usb_device().attach(_package_name) -script = session.create_script( - open(_frida_js_path, encoding="utf-8").read() -) -script.load() + +for app_info in INJECTION_APPS: + session = frida.get_usb_device().attach(app_info["package_name"]) + app_info["absolute_path"] = Path(__file__).absolute().parent / \ + f"apps/{app_info['path']}.js" + script = session.create_script( + open( + app_info["absolute_path"], + encoding="utf-8" + ).read() + ) + script.load() + app_info["script"] = script def init_app() -> Starlette: app = FastAPI() # 每个app创建特有路由 - router = APIRouter() - for api_name, params in get_app_info(parse_path=PRASE_PATH, frida_js_path=_frida_js_path).items(): - params_dict = dict(zip(params, function_params_hints[api_name])) if ( - api_name in function_params_hints) else dict.fromkeys(params, "bb") - model_name = f"{api_name}Model" - Model = create_model(model_name, **params_dict) - new_api_name = name_transform(api_name) - func = generate_function( - new_api_name, - script, - model_name, - Model + for app_info in INJECTION_APPS: + router = APIRouter() + for api_name, params in get_app_info(parse_path=PRASE_PATH, frida_js_path=app_info["absolute_path"]).items(): + params_dict = dict(zip(params, function_params_hints[api_name])) if ( + api_name in function_params_hints) else dict.fromkeys(params, "bb") + model_name = f"{api_name}Model" + Model = create_model(model_name, **params_dict) + new_api_name = name_transform(api_name) + func = generate_function( + new_api_name, + app_info["script"], + model_name, + Model + ) + router.add_api_route(f"/{new_api_name}", func, methods=["POST"]) + app.include_router( + router, + prefix=f"/{app_info['path']}", + tags=[app_info["name"]] ) - router.add_api_route(f"/{new_api_name}", func, methods=["POST"]) - # 全局添加各app路由类 - app.include_router(router) + + def custom_openapi(): + if app.openapi_schema: + return app.openapi_schema + openapi_schema = get_openapi( + title="Arida框架", + version="0.0.1", + description="基于FastAPI实现的Frida-RPC工具 https://github.com/lateautumn4lin/arida", + routes=app.routes, + ) + openapi_schema["info"]["x-logo"] = { + "url": "https://fastapi.tiangolo.com/img/logo-margin/logo-teal.png" + } + app.openapi_schema = openapi_schema + return app.openapi_schema + app.openapi = custom_openapi return app diff --git a/source/fastapi_docs.png b/source/fastapi_docs.png index ec7145d..61f16e0 100644 Binary files a/source/fastapi_docs.png and b/source/fastapi_docs.png differ diff --git a/source/post_body_hints.png b/source/post_body_hints.png index 12c5d77..4790448 100644 Binary files a/source/post_body_hints.png and b/source/post_body_hints.png differ diff --git a/source/test.png b/source/test.png index 9841899..a665038 100644 Binary files a/source/test.png and b/source/test.png differ