爬虫 APP 逆向 ---> 粉笔考研

发布时间:2026/5/20 5:53:22

爬虫 APP 逆向 ---> 粉笔考研 环境粉笔考研 v6.3.15https://www.wandoujia.com/apps/1220941/history_v6031500雷电9 模拟器https://www.ldmnq.com/安装 magiskhttps://blog.csdn.net/Ruaki/article/details/135580772安装 Dia 插件 (作用禁用弹窗)https://github.com/Xposed-Modules-Repo/dialog.boxDia 插件 功能取消弹窗。(取消 app 的强制升级。例如得物app、粉笔考研app)禁用退出退出完成可以与键控制组合按关键字禁用弹出框悬停窗口对话框可与按键控制结合使用版本自定义版本号版本名称伪装系统时间系统时间 GPS时间本地访问服务器时间此模块的反检测XposedRoot启动时禁用网络可设置禁用时间强制结束当前活动Activity通过组合键控制反禁用Xposed简单禁用开始 逆向直接搜索关键字 major/school_scoremajor/major_score分析后发现是 rsa 加密方式rsa 是非对称加密需要一个公钥、一个私钥。通过 hook 验证发现 函数a 就是用来解密的。方法 1逆向算法直接 python 实现方法 2用 java 实现然后打包成 jar 包python 调用 jar 包方法 3通过 rpc 方式RPC 代码实现下面 通过 rpc 方式实现。模拟器中执行 frida-server并设置端口转发。rcp 方式调用import time import frida import uvicorn from pathlib import Path from fastapi import FastAPI, Request js_code console.log(Script loaded successfully ); function callDecryptFunc(mi_str) { //定义导出函数 let local_result; Java.perform(function x() { console.log(hook 成功); console.log(mi_str); let li9 Java.use(li9); let result li9.a(mi_str); console.log(result --- ${result}); local_result result return result; }); return local_result; } rpc.exports { // 导出名不可以有大写字母或者下划线 calldecrypyfunc: callDecryptFunc }; def my_message_handler(message, payload): print(message) print(payload) def get_session(): device frida.get_usb_device() time.sleep(2) # 睡眠2秒, 防止程序运行过快从而导致附加不上 session device.attach(粉笔考研) return session g_session get_session() script g_session.create_script(js_code) script.on(message, my_message_handler) script.load() app FastAPI() app.get(/decrypt_data) app.post(/decrypt_data) async def root(request: Request): data_dict await request.json() encrypt_data data_dict[encrypt_data] global script decrypt_data script.exports_sync.calldecrypyfunc(encrypt_data) ret_val { encrypt_data: encrypt_data, decrypt_data: decrypt_data } return ret_val if __name__ __main__: uvicorn.run(f{Path(__file__).stem}:app, host0.0.0.0, port6666) pass执行结果测试脚本。Cookie: 换成自己的cookiesimport json import requests requests.packages.urllib3.disable_warnings() headers { User-Agent: fenbi-android, Host: schoolapi.fenbi.com, Cookie: 换成自己的cookies } def get_decrypt_data(data_dictNone): url http://127.0.0.1:6666/decrypt_data resp_2 requests.post(url, jsondata_dict, verifyFalse) ret_val { name: data_dict[name], decrypt_data: resp_2.json()[decrypt_data], } return ret_val def main(): url_1 https://schoolapi.fenbi.com/kaoyan/android/kyzz/major/school_score url_2 https://schoolapi.fenbi.com/kaoyan/android/kyzz/major/major_score college_info [ {dm: 10001, name: 北京大学}, {dm: 10003, name: 清华大学}, ] for item in college_info: dm item[dm] name item[name] querystring_1 { # school: 10007, type: 01, year: 0, school: dm, type: 01, year: 0, # client_context_id: 2F3B0BCDA482C2DE2D23, # version: 6.3.15, vendor: Huawei, # app: kaoyan, av: 69, kav: 27, hav: 4, # deviceId: AKJWMHTPfy/pM1yprG3inw, # quizId: 0, imei: , oaid: , } querystring_2 { school: dm, type: 01, year: 0, department: , # client_context_id: A28D05AA5A8943BF6D8F, # version: 6.3.15, vendor: Huawei, # app: kaoyan, av: 69, kav: 27, hav: 4, # deviceId: AKJWMHTPfy/pM1yprG3inw, # quizId: 0, imei: , oaid: , } resp requests.get(url_1, headersheaders, paramsquerystring_1, verifyFalse) resp_json resp.json() post_data { name: name, encrypt_data: resp_json[data] } data_1 get_decrypt_data(post_data) resp requests.get(url_2, headersheaders, paramsquerystring_2, verifyFalse) resp_json resp.json() post_data { name: name, encrypt_data: resp_json[data] } data_2 get_decrypt_data(post_data) data { name: name, school_score: data_1[decrypt_data], major_score: data_2[decrypt_data] } print(data) if __name__ __main__: main() pass执行结果查看 app 验证结果

相关新闻