首页
社区
课程
招聘
[原创]AI逆向-自定义mcp辅助cursor实现app逆向
发表于: 2025-8-26 04:17 5471

[原创]AI逆向-自定义mcp辅助cursor实现app逆向

2025-8-26 04:17
5471

背景故事:偶然的机会,我发现了一个能在vscode里边就能反编译和重打包apk的工具-apklab(b44K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6m8f1p5E0x3j5h3u0Q4x3V1k6m8f1p5E0x3j5h3u0Q4x3U0W2Q4x3V1y4Q4c8e0g2Q4z5o6g2Q4b7U0k6Q4c8e0k6Q4b7f1y4Q4b7e0q4Q4x3V1y4Q4c8e0N6Q4z5f1y4Q4z5p5u0Q4c8e0g2Q4z5o6S2Q4b7U0m8Q4c8e0g2Q4b7V1g2Q4b7f1g2Q4c8e0c8Q4b7V1k6Q4b7e0q4Q4c8e0g2Q4z5o6g2Q4b7f1y4Q4c8e0c8Q4b7V1y4Q4z5e0N6Q4c8e0g2Q4z5p5k6Q4b7U0N6Q4c8e0c8Q4b7U0S2Q4z5p5q4Q4c8e0k6Q4z5f1y4Q4z5o6W2Q4c8e0c8Q4b7V1q4Q4b7V1q4Q4c8e0g2Q4z5p5k6Q4z5e0q4Q4c8e0g2Q4b7U0S2Q4z5e0k6Q4c8e0g2Q4b7f1c8Q4z5e0m8Q4c8e0c8Q4b7V1c8Q4b7V1k6Q4c8e0N6Q4z5e0c8Q4b7e0S2Q4c8e0g2Q4b7e0c8Q4b7e0N6Q4c8e0k6Q4b7e0S2Q4b7e0q4Q4c8e0g2Q4z5f1g2Q4z5p5u0Q4c8e0k6Q4z5f1c8Q4b7e0g2Q4c8e0S2Q4b7V1k6Q4z5f1u0Q4c8e0S2Q4b7e0q4Q4z5p5y4Q4c8e0k6Q4b7V1y4Q4z5p5k6Q4c8e0k6Q4b7U0c8Q4z5f1g2Q4c8e0g2Q4z5o6S2Q4z5o6k6Q4c8e0k6Q4z5f1g2Q4z5e0m8Q4c8e0y4Q4z5o6m8Q4z5o6u0Q4c8e0k6Q4z5o6S2Q4z5e0q4Q4c8e0g2Q4b7U0m8Q4b7U0q4Q4c8e0g2Q4z5f1y4Q4b7e0S2Q4c8e0k6Q4z5o6y4Q4b7U0y4Q4c8f1k6Q4b7V1y4Q4z5p5y4Q4c8e0S2Q4z5o6y4Q4b7V1c8Q4c8e0c8Q4b7U0S2Q4z5p5c8Q4c8e0S2Q4z5o6y4Q4b7V1c8Q4c8e0c8Q4b7V1c8Q4b7V1k6Q4c8e0N6Q4z5e0c8Q4b7e0S2m8d9g2!0q4y4g2!0m8y4q4!0m8y4#2!0q4y4W2!0m8z5q4!0m8x3g2!0q4y4g2)9&6c8g2)9^5b7W2!0q4y4W2)9&6c8q4!0m8y4g2!0q4y4g2!0m8c8g2)9^5b7#2!0q4y4W2)9^5z5q4)9&6x3q4!0q4y4W2)9&6y4g2!0n7y4q4!0q4y4q4!0n7z5q4!0m8b7g2!0q4y4W2!0n7y4g2)9^5x3g2!0q4y4#2!0m8z5q4)9^5b7W2!0q4y4#2)9&6b7g2)9^5y4q4!0q4z5g2)9^5x3q4)9^5y4W2!0q4y4g2)9&6x3q4)9&6x3g2!0q4y4g2)9^5z5q4)9^5y4W2!0q4y4W2)9&6c8g2)9&6x3q4!0q4y4g2)9&6x3g2!0m8x3W2)9K6c8R3`.`.

我发现,在目前AI编程软件顶多只能做静态分析,可以与电脑交互,但是无法与手机进行交互,更不用说进行动态分析。所以,要想让大模型进行逆向,要解决两个问题

  1. 大模型应该能够控制手机

  2. 大模型应该能够hook指定app

这两个工具,想必大家都不陌生,一个是adb,一个是frida,那么如何让大模型使用这两个工具呢?答案就是MCP!

MCP(Model Context Protocol,模型上下文协议) ,2024年11月底,由 Anthropic 推出的一种开放标准,旨在统一大模型与外部数据源和工具之间的通信协议。MCP 的主要目的在于解决当前 AI 模型因数据孤岛限制而无法充分发挥潜力的难题,MCP 使得 AI 应用能够安全地访问和操作本地及远程数据,为 AI 应用提供了连接万物的接口。

当然,市面上已经存在各种各样的MCP工具,有没有能够直接用的工具呢?adb的mcp工具倒是有一些,但是各有各的不足,frida相关的mcp比较少,且基本不可用,比如说不支持自定义frida路径,不能自动端口转发,工具定义太复杂等,于是,基于以上背景,我们自定义了两个mcp,分别是adb-mcpfrida-mcp,用于手机控制以及动态调试。


至于如何开发以及调试属于自己的MCP工具,后续会专门出文章,我们先来看结果,这两个mcp分别有自己的函数,大模型可以根据当前的上下文,调用这些工具的组合

比如安装一个app,大模型会先检查现在的连接的设备list_devices,拿到设备信息get_device_info,然后安装install_app,安装完成之后再次检查是否成功list_packages
这一切都不要我们关心,我们只需要发送一个指令,安装xxx就可以


在准备工作完成之后,来看看今天的案例

实战案例

某小众女权站点(x瓣)

本来APP不难,主要看AI能做到什么程度

我们这次挑战尽可能用cursor做一切操作,首先使用cursor安装app

可以看到调用了一些工具,app以及成功安装了

然后使用reqable进行抓包,可以看到

import requests

headers = {
    'User-Agent': 'Rexxar-Core/0.1.3 api-client/1 com.douban.frodo/7.89.0(307) Android/33 product/coral vendor/Google model/Pixel 4 XL brand/google  rom/android  network/wifi  udid/748659a92430f1e85b21daae1949c5698fdab92f  platform/mobile nd/1 com.douban.frodo/7.89.0(307) Rexxar/1.2.151  platform/mobile 1.2.151',
    # 'Accept-Encoding': 'br,gzip',
}

params = {
    'type': 'movie',
    'start': '0',
    'count': '10',
    'udid': '748659a92430f1e85b21daae1949c5698fdab92f',
    'rom': 'android',
    'apikey': '0dad551ec0f84ed02907ff5c42e8ec70',
    's': 'rexxar_new',
    'channel': 'ali_market',
    'timezone': 'Asia/Shanghai',
    'device_id': '748659a92430f1e85b21daae1949c5698fdab92f',
    'os_rom': 'android',
    'sugar': '0',
    'loc_id': '108288',
    '_sig': 's3haQycPjsj6HkvW36nNHArIsa4=',
    '_ts': '1756145025',
}

response = requests.get(
    'bafK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6X3M7X3!0V1L8#2)9J5k6h3c8G2N6h3u0S2L8W2)9J5k6h3y4G2L8g2)9J5c8X3q4H3K9g2)9J5c8Y4j5J5i4K6u0r3M7%4g2T1K9X3g2U0N6q4)9#2k6X3y4G2L8r3I4W2j5%4c8A6L8$3&6Q4x3V1k6E0L8%4k6A6k6g2)9#2k6Y4u0W2j5h3I4Q4y4h3k6@1K9h3#2W2i4K6g2X3K9r3!0@1k6i4y4@1i4K6u0r3K9i4c8W2L8i4y4Q4x3U0k6Q4x3U0x3K6z5g2)9K6b7W2)9J5b7H3`.`.
    params=params,
    headers=headers,
)
print(response.text)
with open("response.txt", "w", encoding="utf-8") as f:
    f.write(response.text)

_sig是主要的加密参数,

我们现在需要使用apklab来反编译整个apk

直接询问大模型加密字段和加密方法


可以看到已经分析出来加密的格式了,问下大模型还需要什么,大模型告诉我们的下一步方案,给出

这里需要注意的是,豆瓣有frida检测,大模型不知道,我已经过了,后续分享代码

大模型生成hook代码

    Java.perform(function() {
        // 1) 核心签名处:拿到 _sig/_ts、确认明文构造
        try {
          var Sig = Java.use("d0.a");
          Sig.C.overload('java.lang.String','java.lang.String','java.lang.String').implementation = function(url, method, token) {
            var ret = this.C(url, method, token);
            console.log("\n=== d0.a.C called ===");
            console.log("URL: " + url);
            console.log("Method: " + method);
            console.log("Token: " + (token || "null"));
            if (ret) {
              console.log("_sig: " + ret.first);
              console.log("_ts: " + ret.second);
            }
            return ret;
          };
          console.log("[+] Hooked d0.a.C");
        } catch (e) {
          console.log("[-] d0.a.C hook failed: " + e);
        }
     
        // 2) 拿密钥最佳点:HMAC-SHA1 的 SecretKeySpec 构造
        try {
          var SecretKeySpec = Java.use("javax.crypto.spec.SecretKeySpec");
          SecretKeySpec.$init.overload('[B','java.lang.String').implementation = function(keyBytes, alg) {
            if (alg === "HmacSHA1") {
              var StringCls = Java.use("java.lang.String");
              var keyStr = StringCls.$new(keyBytes);  // 若是可打印字符串
              var Base64 = Java.use("android.util.Base64");
              var b64 = Base64.encodeToString(keyBytes, 2);
              // 备用 hex
              var hex = (function(b){
                var out=[]; for (var i=0;i<b.length;i++){ var v=b[i]&0xff; out.push(("0"+v.toString(16)).slice(-2)); }
                return out.join("");
              })(keyBytes);
              console.log("\n=== Found HMAC key (SecretKeySpec) ===");
              console.log("alg: " + alg);
              console.log("key(ascii?): " + keyStr);
              console.log("key(base64): " + b64);
              console.log("key(hex): " + hex);
            }
            return this.$init(keyBytes, alg);
          };
          console.log("[+] Hooked SecretKeySpec([B,\"HmacSHA1\"])");
        } catch (e) {
          console.log("[-] SecretKeySpec hook failed: " + e);
        }
     
        // 3) 备选:拦截 Mac.init 也能拿到 key
        try {
          var Mac = Java.use("javax.crypto.Mac");
          Mac.init.overload('java.security.Key').implementation = function(key) {
            try {
              var alg = this.getAlgorithm();
              if (alg === "HmacSHA1" || alg === "HmacSHA256" || alg === "HmacSHA512") {
                var kclass = key.getClass().getName();
                var encField = null;
                try { encField = Java.cast(key, Java.use("javax.crypto.spec.SecretKeySpec")).getEncoded(); } catch (_){}
                var b64 = encField ? Java.use("android.util.Base64").encodeToString(encField, 2) : "N/A";
                console.log("\n=== Mac.init ===");
                console.log("Mac alg: " + alg);
                console.log("Key class: " + kclass);
                console.log("Key(base64): " + b64);
              }
            } catch (_e) {}
            this.init(key);
          };
          console.log("[+] Hooked Mac.init(Key)");
        } catch (e) {
          console.log("[-] Mac.init hook failed: " + e);
        }
     
        console.log("[*] Hooks ready. Trigger login to capture key/_sig/_ts.");
      });
完整过检测代码


function hook_sig() {
    Java.perform(function() {
        // 1) 核心签名处:拿到 _sig/_ts、确认明文构造
        try {
          var Sig = Java.use("d0.a");
          Sig.C.overload('java.lang.String','java.lang.String','java.lang.String').implementation = function(url, method, token) {
            var ret = this.C(url, method, token);
            console.log("\n=== d0.a.C called ===");
            console.log("URL: " + url);
            console.log("Method: " + method);
            console.log("Token: " + (token || "null"));
            if (ret) {
              console.log("_sig: " + ret.first);
              console.log("_ts: " + ret.second);
            }
            return ret;
          };
          console.log("[+] Hooked d0.a.C");
        } catch (e) {
          console.log("[-] d0.a.C hook failed: " + e);
        }
     
        // 2) 拿密钥最佳点:HMAC-SHA1 的 SecretKeySpec 构造
        try {
          var SecretKeySpec = Java.use("javax.crypto.spec.SecretKeySpec");
          SecretKeySpec.$init.overload('[B','java.lang.String').implementation = function(keyBytes, alg) {
            if (alg === "HmacSHA1") {
              var StringCls = Java.use("java.lang.String");
              var keyStr = StringCls.$new(keyBytes);  // 若是可打印字符串
              var Base64 = Java.use("android.util.Base64");
              var b64 = Base64.encodeToString(keyBytes, 2);
              // 备用 hex
              var hex = (function(b){
                var out=[]; for (var i=0;i<b.length;i++){ var v=b[i]&0xff; out.push(("0"+v.toString(16)).slice(-2)); }
                return out.join("");
              })(keyBytes);
              console.log("\n=== Found HMAC key (SecretKeySpec) ===");
              console.log("alg: " + alg);
              console.log("key(ascii?): " + keyStr);
              console.log("key(base64): " + b64);
              console.log("key(hex): " + hex);
            }
            return this.$init(keyBytes, alg);
          };
          console.log("[+] Hooked SecretKeySpec([B,\"HmacSHA1\"])");
        } catch (e) {
          console.log("[-] SecretKeySpec hook failed: " + e);
        }
     
        // 3) 备选:拦截 Mac.init 也能拿到 key
        try {
          var Mac = Java.use("javax.crypto.Mac");
          Mac.init.overload('java.security.Key').implementation = function(key) {
            try {
              var alg = this.getAlgorithm();
              if (alg === "HmacSHA1" || alg === "HmacSHA256" || alg === "HmacSHA512") {
                var kclass = key.getClass().getName();
                var encField = null;
                try { encField = Java.cast(key, Java.use("javax.crypto.spec.SecretKeySpec")).getEncoded(); } catch (_){}
                var b64 = encField ? Java.use("android.util.Base64").encodeToString(encField, 2) : "N/A";
                console.log("\n=== Mac.init ===");
                console.log("Mac alg: " + alg);
                console.log("Key class: " + kclass);
                console.log("Key(base64): " + b64);
              }
            } catch (_e) {}
            this.init(key);
          };
          console.log("[+] Hooked Mac.init(Key)");
        } catch (e) {
          console.log("[-] Mac.init hook failed: " + e);
        }
     
        console.log("[*] Hooks ready. Trigger login to capture key/_sig/_ts.");
      });
    }
   
function hook_dlopen(){
  //Android8.0之后加载so通过android_dlopen_ext函数
  var android_dlopen_ext = Module.findExportByName(null,"android_dlopen_ext");
  console.log("addr_android_dlopen_ext",android_dlopen_ext);
  Interceptor.attach(android_dlopen_ext,{
      onEnter:function(args){
          var pathptr = args[0];
          if(pathptr!=null && pathptr != undefined){
              var path = ptr(pathptr).readCString();
              if(path.indexOf("libmsaoaidsec.so")!=-1){
                  console.log("android_dlopen_ext:",path);
                  hook_call_constructors()
              }
          }
      },
      onLeave:function(retvel){
          //console.log("leave!");
      }
  })
}

function hook_call_constructors() {
    var linker64_base_addr = Module.getBaseAddress("linker64")
    var call_constructors_func_off = 0x4e4dc //这个地址是从手机上把linker64 pull出来,然后到IDA中找到的,不同的机型,地址可能不一样
    var call_constructors_func_addr = linker64_base_addr.add(call_constructors_func_off)
    var listener = Interceptor.attach(call_constructors_func_addr, {
        onEnter: function (args) {
            console.log("hooked call_constructors")
            var module = Process.findModuleByName("libmsaoaidsec.so")
            if (module != null) {
                Interceptor.replace(module.base.add(0x1c544), new NativeCallback(function () {
                    console.log("0x1c544:替换成功")
                }, "void", []))
                Interceptor.replace(module.base.add(0x1b924), new NativeCallback(function () {
                    console.log("0x1B924:替换成功")
                }, "void", []))
                Interceptor.replace(module.base.add(0x26e5c), new NativeCallback(function () {
                    console.log("0x26e5c:替换成功")
                }, "void", []))
                listener.detach()
            }
        },
    })
}
function main(){
    hook_dlopen()
    hook_sig()
}

main()

大模型进行hook,一切都不要我们操作自动验证结果

重写python请求

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

"""
豆瓣API请求发送演示
展示多种请求发送方式
"""

import json
from douban_signature_final import DoubanSignatureFinal

def demo_simple_request():
    """演示简单的API请求"""
   
    print("=== 方法1: 使用完整库发送请求 ===\n")
   
    # 创建签名器
    signer = DoubanSignatureFinal()
   
    # 电影热榜API
    url = "87aK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6X3M7X3!0V1L8#2)9J5k6h3c8G2N6h3u0S2L8W2)9J5k6h3y4G2L8g2)9J5c8X3q4H3K9g2)9J5c8Y4j5J5i4K6u0r3M7%4g2T1K9X3g2U0N6q4)9#2k6X3y4G2L8r3I4W2j5%4c8A6L8$3&6Q4x3V1k6E0L8%4k6A6k6g2)9#2k6Y4u0W2j5h3I4Q4y4h3k6@1K9h3#2W2i4K6g2X3K9r3!0@1k6i4y4@1i4K6u0r3K9i4c8W2L8i4y4Q4x3U0k6I4N6h3!0@1i4K6y4n7
    params = {
        'type': 'movie',
        'start': '0',
        'count': '5',  # 只获取5部电影
        'udid': '748659a92430f1e85b21daae1949c5698fdab92f',
        'rom': 'android',
        'apikey': '0dad551ec0f84ed02907ff5c42e8ec70',
        's': 'rexxar_new',
        'channel': 'ali_market',
        'timezone': 'Asia/Shanghai',
        'device_id': '748659a92430f1e85b21daae1949c5698fdab92f',
        'os_rom': 'android',
        'sugar': '0',
        'loc_id': '108288',
    }
   
    try:
        # 发送请求
        response = signer.make_request(url, params, "GET")
       
        print(f"状态码: {response.status_code}")
       
        if response.status_code == 200:
            data = response.json()
            print("✅ 请求成功!")
            print(f"总数: {data.get('count', 0)}")
           
            # 显示电影信息
            items = data.get('subject_collection_items', [])
            for i, item in enumerate(items, 1):
                movie = item.get('rating', {})
                print(f"{i}. {item.get('title', 'N/A')} - 评分: {movie.get('value', 'N/A')}")
        else:
            print(f"❌ 请求失败: {response.text}")
           
    except Exception as e:
        print(f"❌ 请求异常: {e}")


def demo_manual_request():
    """演示手动构造请求"""
   
    print(f"\n=== 方法2: 手动构造请求 ===\n")
   
    import requests
    from douban_signature_final import DoubanSignatureFinal
   
    signer = DoubanSignatureFinal()
   
    # 书籍推荐API
    url = "2b0K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6X3M7X3!0V1L8#2)9J5k6h3c8G2N6h3u0S2L8W2)9J5k6h3y4G2L8g2)9J5c8X3q4H3K9g2)9J5c8Y4j5J5i4K6u0r3M7%4g2T1K9X3g2U0N6q4)9#2k6X3y4G2L8r3I4W2j5%4c8A6L8$3&6Q4x3V1k6T1L8$3!0C8i4K6g2X3j5X3g2K6N6s2y4W2L8r3I4W2M7W2)9J5c8X3W2@1k6h3#2K6i4K6t1$3M7i4g2G2N6q4)9K6b7R3`.`.
    params = {
        'type': 'book',
        'start': '0',
        'count': '3',
        'apikey': '0dad551ec0f84ed02907ff5c42e8ec70',
    }
   
    # 手动生成签名
    sig, ts = signer.generate_signature(url, "GET")
    params['_sig'] = sig
    params['_ts'] = ts
   
    # 构造请求头
    headers = {
        'User-Agent': 'Rexxar-Core/0.1.3 api-client/1 com.douban.frodo/7.89.0(307) Android/33 product/coral vendor/Google model/Pixel 4 XL brand/google  rom/android  network/wifi  udid/748659a92430f1e85b21daae1949c5698fdab92f  platform/mobile nd/1 com.douban.frodo/7.89.0(307) Rexxar/1.2.151  platform/mobile 1.2.151',
        'Accept': 'application/json',
    }
   
    print(f"请求URL: {url}")
    print(f"生成的签名: {sig}")
    print(f"时间戳: {ts}")
   
    try:
        # 发送GET请求
        response = requests.get(url, params=params, headers=headers)
       
        print(f"\n状态码: {response.status_code}")
       
        if response.status_code == 200:
            data = response.json()
            print("✅ 请求成功!")
           
            # 显示书籍信息
            items = data.get('subject_collection_items', [])
            for i, item in enumerate(items, 1):
                rating = item.get('rating', {})
                print(f"{i}. {item.get('title', 'N/A')} - 评分: {rating.get('value', 'N/A')}")
        else:
            print(f"❌ 请求失败: {response.text}")
           
    except Exception as e:
        print(f"❌ 请求异常: {e}")


def demo_post_request():
    """演示POST请求 (注意:这只是演示,可能需要登录)"""
   
    print(f"\n=== 方法3: POST请求演示 ===\n")
   
    import requests
    from douban_signature_final import DoubanSignatureFinal
   
    signer = DoubanSignatureFinal()
   
    # 假设的用户API (可能需要登录)
    url = "0cbK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6X3M7X3!0V1L8#2)9J5k6h3c8G2N6h3u0S2L8W2)9J5k6h3y4G2L8g2)9J5c8X3q4H3K9g2)9J5c8Y4j5J5i4K6u0r3N6i4y4W2M7W2)9J5c8Y4m8J5L8$3k6A6L8r3g2Q4x3U0k6I4N6h3!0@1i4K6y4n7
   
    # POST请求体
    post_data = json.dumps({
        "action": "get_profile"
    })
   
    # 生成签名 (包含请求体)
    sig, ts = signer.generate_signature(url, "POST", post_data)
   
    # 查询参数
    params = {
        'apikey': '0dad551ec0f84ed02907ff5c42e8ec70',
        '_sig': sig,
        '_ts': ts,
    }
   
    headers = {
        'User-Agent': 'Rexxar-Core/0.1.3 api-client/1 com.douban.frodo/7.89.0(307) Android/33 product/coral vendor/Google model/Pixel 4 XL brand/google  rom/android  network/wifi  udid/748659a92430f1e85b21daae1949c5698fdab92f  platform/mobile nd/1 com.douban.frodo/7.89.0(307) Rexxar/1.2.151  platform/mobile 1.2.151',
        'Content-Type': 'application/json',
    }
   
    print(f"POST URL: {url}")
    print(f"请求体: {post_data}")
    print(f"生成的签名: {sig}")
   
    try:
        response = requests.post(url, params=params, data=post_data, headers=headers)
        print(f"\n状态码: {response.status_code}")
        print(f"响应: {response.text[:200]}...")
       
    except Exception as e:
        print(f"❌ 请求异常: {e}")


def demo_multiple_apis():
    """演示调用多个不同的API"""
   
    print(f"\n=== 方法4: 批量API调用 ===\n")
   
    signer = DoubanSignatureFinal()
   
    apis = [
        {
            "name": "电影正在热映",
            "url": "ffbK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6X3M7X3!0V1L8#2)9J5k6h3c8G2N6h3u0S2L8W2)9J5k6h3y4G2L8g2)9J5c8X3q4H3K9g2)9J5c8Y4j5J5i4K6u0r3M7%4g2T1K9X3g2U0N6q4)9#2k6X3y4G2L8r3I4W2j5%4c8A6L8$3&6Q4x3V1k6E0L8%4k6A6k6g2)9#2k6Y4y4Z5L8%4N6A6L8X3N6Q4x3V1k6A6N6r3g2E0M7#2)9J5y4Y4q4#2L8%4c8Q4x3@1u0Q4x3V1x3`.
            "params": {'type': 'movie', 'start': '0', 'count': '3', 'apikey': '0dad551ec0f84ed02907ff5c42e8ec70'}
        },
        {
            "name": "电视剧热榜",
            "url": "783K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6X3M7X3!0V1L8#2)9J5k6h3c8G2N6h3u0S2L8W2)9J5k6h3y4G2L8g2)9J5c8X3q4H3K9g2)9J5c8Y4j5J5i4K6u0r3M7%4g2T1K9X3g2U0N6q4)9#2k6X3y4G2L8r3I4W2j5%4c8A6L8$3&6Q4x3V1k6@1N6W2)9#2k6X3S2G2N6q4)9J5c8X3W2@1k6h3#2K6i4K6t1$3M7i4g2G2N6q4)9K6b7W2)9J5b7#2)9J5y4X3&6T1M7%4m8Q4x3@1t1`.
            "params": {'type': 'tv', 'start': '0', 'count': '3', 'apikey': '0dad551ec0f84ed02907ff5c42e8ec70'}
        },
        {
            "name": "音乐新碟榜",
            "url": "7d9K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6X3M7X3!0V1L8#2)9J5k6h3c8G2N6h3u0S2L8W2)9J5k6h3y4G2L8g2)9J5c8X3q4H3K9g2)9J5c8Y4j5J5i4K6u0r3M7%4g2T1K9X3g2U0N6q4)9#2k6X3y4G2L8r3I4W2j5%4c8A6L8$3&6Q4x3V1k6E0N6i4y4A6j5#2)9#2k6X3I4S2N6r3g2K6N6q4)9J5c8X3W2@1k6h3#2K6i4K6t1$3M7i4g2G2N6q4)9K6b7W2)9J5b7H3`.`.
            "params": {'type': 'music', 'start': '0', 'count': '3', 'apikey': '0dad551ec0f84ed02907ff5c42e8ec70'}
        }
    ]
   
    for api in apis:
        print(f" 调用API: {api['name']}")
       
        try:
            response = signer.make_request(api['url'], api['params'], "GET")
           
            if response.status_code == 200:
                data = response.json()
                count = data.get('count', 0)
                print(f"  ✅ 成功 - 获取到 {count} 条数据")
               
                # 显示第一条数据的标题
                items = data.get('subject_collection_items', [])
                if items:
                    first_item = items[0]
                    print(f"   首条: {first_item.get('title', 'N/A')}")
            else:
                print(f"  ❌ 失败 - 状态码: {response.status_code}")
               
        except Exception as e:
            print(f"  ❌ 异常: {e}")
       
        print()


def demo_save_response():
    """演示保存响应数据"""
   
    print(f"=== 方法5: 保存响应数据 ===\n")
   
    signer = DoubanSignatureFinal()
   
    url = "e82K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6X3M7X3!0V1L8#2)9J5k6h3c8G2N6h3u0S2L8W2)9J5k6h3y4G2L8g2)9J5c8X3q4H3K9g2)9J5c8Y4j5J5i4K6u0r3M7%4g2T1K9X3g2U0N6q4)9#2k6X3y4G2L8r3I4W2j5%4c8A6L8$3&6Q4x3V1k6E0L8%4k6A6k6g2)9#2k6Y4u0W2j5h3I4Q4y4h3k6@1K9h3#2W2i4K6g2X3K9r3!0@1k6i4y4@1i4K6u0r3K9i4c8W2L8i4y4Q4x3U0k6I4N6h3!0@1i4K6y4n7
    params = {
        'type': 'movie',
        'start': '0',
        'count': '10',
        'apikey': '0dad551ec0f84ed02907ff5c42e8ec70',
    }
   
    try:
        response = signer.make_request(url, params, "GET")
       
        if response.status_code == 200:
            data = response.json()
           
            # 保存原始响应
            with open("douban_movies.json", "w", encoding="utf-8") as f:
                json.dump(data, f, ensure_ascii=False, indent=2)
           
            print("✅ 数据已保存到 douban_movies.json")
           
            # 提取并保存简化版本
            simplified = []
            items = data.get('subject_collection_items', [])
           
            for item in items:
                simplified.append({
                    "title": item.get('title'),
                    "rating": item.get('rating', {}).get('value'),
                    "year": item.get('year'),
                    "directors": [d.get('name') for d in item.get('directors', [])],
                    "genres": item.get('genres', [])
                })
           
            with open("douban_movies_simple.json", "w", encoding="utf-8") as f:
                json.dump(simplified, f, ensure_ascii=False, indent=2)
           
            print("✅ 简化数据已保存到 douban_movies_simple.json")
            print(f" 共获取 {len(simplified)} 部电影数据")
           
        else:
            print(f"❌ 请求失败: {response.status_code}")
           
    except Exception as e:
        print(f"❌ 异常: {e}")


if __name__ == "__main__":
    print("???? 豆瓣API请求发送演示\n")
   
    # 运行所有演示
    demo_simple_request()
    demo_manual_request() 
    demo_post_request()
    demo_multiple_apis()
    demo_save_response()
   
    print(" 所有演示完成!")
    print("\n 使用提示:")
    print("1. 简单调用: 使用 DoubanSignatureFinal().make_request()")
    print("2. 手动控制: 先生成签名,再发送requests请求")  
    print("3. 批量调用: 循环调用不同API")
    print("4. 数据保存: 将响应保存为JSON文件")


mcp路径

be4K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6*7K9r3W2*7K9s2g2G2k6r3g2E0j5h3!0Q4x3V1k6S2k6r3u0Q4x3X3c8E0j5%4l9`.

92dK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6*7K9r3W2*7K9s2g2G2k6r3g2E0j5h3!0Q4x3V1k6X3M7X3W2V1j5g2)9J5k6r3#2U0M7l9`.`.


总结与展望:

adb-mcp与frida-mcp的出现,为ai逆向分析提供了一个新的思路,不仅可以静态分析,还可以动态调试,今后会分享mcp的写法以及如何使用MCP分析so函数


[培训]Windows内核深度攻防:从Hook技术到Rootkit实战!

收藏
免费 18
支持
分享
最新回复 (14)
雪    币: 7
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
2
感谢分享
2025-8-26 09:08
0
雪    币: 358
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
3
感谢分享
2025-8-26 10:10
0
雪    币: 5942
活跃值: (6341)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
思路不错,感谢分享。
2025-8-26 12:47
1
雪    币: 196
活跃值: (187)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
预测会火,火钳留名,以前只知道MCP 连接IDA 和JADX然后静态分析,frida部分都是自己手动的,然后反编译出来的APK目录也都是直接拉到cursor里直接让AI遍历去分析的,这样也可以做到。
2025-8-26 17:44
1
雪    币: 830
活跃值: (5352)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
6
mcp用户端选择的哪一款
2025-8-28 09:48
0
雪    币: 490
活跃值: (247)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
7
一只笨猫 mcp用户端选择的哪一款
目前是cursor和claude code,模型claude4和gpt5混着用
2025-8-28 11:26
0
雪    币: 70
活跃值: (2552)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
 token太贵了
2025-8-28 23:25
0
雪    币: 830
活跃值: (5352)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
9
执着的猫 目前是cursor和claude code,模型claude4和gpt5混着用
我使用的是deepchat和deepchat 目前老是自己停掉让我处理方案
2025-8-29 16:07
0
雪    币: 221
活跃值: (570)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
感谢分享
2025-8-31 22:15
0
雪    币: 2424
活跃值: (3851)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
11
佬 出现ERROR: Could not find a version that satisfies the requirement mcp[cli,fastmcp] (from versions: none)
ERROR: No matching distribution found for mcp[cli,fastmcp]
2025-8-31 22:58
0
雪    币: 6452
活跃值: (5157)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
12
adb没必要写成mcp,  aug会自己调的呀
2025-9-2 10:11
0
雪    币: 269
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
13
这个感觉也太无敌了
2025-9-12 18:12
0
雪    币: 379
活跃值: (681)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
期待大佬的MCP教程
2025-12-5 09:10
0
雪    币: 1898
活跃值: (542)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
15
期待
2025-12-10 02:02
0
游客
登录 | 注册 方可回帖
返回