自动化渗透脚本:Python编写批量扫描、Frida脚本自动化

说实话,做移动安全测试这几年,我最大的体会就是——手动重复劳动是最大的敌人。你想想看,一个App几十个Activity,每个都要手工测一遍注入、调试、Hook,那得测到猴年马月去?

所以这一章,我们来聊聊怎么让机器替我们干活。我会把我在实际项目中沉淀下来的两套自动化方案分享给你:Python批量扫描框架Frida脚本自动化。这两套东西配合起来,基本能覆盖90%的日常渗透场景。

核心思路:用Python做"广度"覆盖(批量发现漏洞入口),用Frida做"深度"突破(动态Hook关键逻辑)。两者结合,效率翻倍。

一、Python批量扫描框架设计

先说说Python这块。我个人习惯把扫描框架拆成三个模块:信息收集层、漏洞检测层、报告输出层。这样后期维护起来特别方便,哪个模块出了问题,直接替换就行。

Python批量扫描框架架构 信息收集层 APK反编译 AndroidManifest解析 Activity/Service枚举 Content Provider发现 漏洞检测层 Intent劫持检测 WebView漏洞扫描 SQL注入检测 文件目录遍历 报告输出层 JSON/HTML报告 漏洞等级标记 修复建议 核心流程:APK → 反编译 → 信息提取 → 漏洞检测 → 报告生成 |-- 支持多线程并发扫描,默认8线程 --| |-- 可扩展自定义检测插件 --|

二、核心代码实现

下面这段代码是我从实际项目中抽出来的核心骨架。你直接拿去改改就能用。

import subprocess
import os
import json
from concurrent.futures import ThreadPoolExecutor

class AndroidScanner:
    def __init__(self, apk_path, threads=8):
        self.apk_path = apk_path
        self.threads = threads
        self.results = []
        self.decompile_dir = "decompiled_" + os.path.basename(apk_path)
    
    def decompile_apk(self):
        """第一步:反编译APK"""
        cmd = f"apktool d {self.apk_path} -o {self.decompile_dir} -f"
        subprocess.run(cmd, shell=True, capture_output=True)
        print(f"[+] 反编译完成: {self.decompile_dir}")
    
    def extract_activities(self):
        """提取所有导出的Activity"""
        manifest_path = os.path.join(self.decompile_dir, "AndroidManifest.xml")
        # 实际项目中用xml解析库处理
        activities = []
        # ... 解析逻辑省略
        return activities
    
    def check_intent_hijack(self, activity):
        """检测Intent劫持风险"""
        # 检查exported="true"且没有自定义权限的Activity
        # 我在项目中遇到过,某社交App的分享Activity没加权限
        # 结果被恶意App直接调起,弹出了钓鱼登录页
        pass
    
    def scan_all(self):
        """多线程批量扫描"""
        self.decompile_apk()
        activities = self.extract_activities()
        
        with ThreadPoolExecutor(max_workers=self.threads) as executor:
            futures = []
            for act in activities:
                futures.append(executor.submit(self.check_intent_hijack, act))
            
            for future in futures:
                result = future.result()
                if result:
                    self.results.append(result)
        
        self.generate_report()
    
    def generate_report(self):
        """生成JSON报告"""
        report = {
            "apk": self.apk_path,
            "vulnerabilities": self.results,
            "total": len(self.results)
        }
        with open("scan_report.json", "w") as f:
            json.dump(report, f, indent=2)
        print(f"[+] 报告已生成: scan_report.json")

if __name__ == "__main__":
    scanner = AndroidScanner("target.apk")
    scanner.scan_all()

我的经验:多线程数别开太大,8-12个线程就够了。开太多反而会因为I/O瓶颈导致速度下降。另外,记得加个超时机制,有些Activity解析起来特别慢。

三、Frida脚本自动化

Python搞定了"广度",接下来用Frida搞"深度"。说白了,Frida就是让我们能在App运行时动态地注入JavaScript代码,去Hook关键函数、修改返回值、甚至绕过SSL Pinning。

我常用的Frida自动化脚本分三类:

  • 信息采集类:Hook加密函数,抓取密钥和算法
  • 绕过检测类:绕过Root检测、模拟器检测、调试检测
  • 逻辑篡改类:修改支付金额、跳过验证码、伪造签名

四、Frida批量Hook脚本示例

下面这个脚本,是我在一次金融App测试中写的。当时需要批量Hook所有加密相关的方法,手动一个个写太慢了,于是写了这个自动化生成脚本。

// frida_bulk_hook.js
// 批量Hook所有包含"encrypt"、"decrypt"、"sign"的方法

Java.perform(function() {
    var targetClasses = [];
    
    // 先枚举所有已加载的类
    Java.enumerateLoadedClasses({
        onMatch: function(className) {
            if (className.indexOf("crypto") !== -1 || 
                className.indexOf("security") !== -1 ||
                className.indexOf("encrypt") !== -1) {
                targetClasses.push(className);
            }
        },
        onComplete: function() {
            console.log("[+] 找到 " + targetClasses.length + " 个目标类");
            targetClasses.forEach(function(clsName) {
                hookClassMethods(clsName);
            });
        }
    });
    
    function hookClassMethods(className) {
        try {
            var targetClass = Java.use(className);
            var methods = targetClass.class.getDeclaredMethods();
            
            methods.forEach(function(method) {
                var methodName = method.getName();
                // 只Hook关键方法
                if (methodName.indexOf("encrypt") !== -1 ||
                    methodName.indexOf("decrypt") !== -1 ||
                    methodName.indexOf("sign") !== -1 ||
                    methodName.indexOf("verify") !== -1) {
                    
                    var overloads = targetClass[methodName].overloads;
                    overloads.forEach(function(overload) {
                        overload.implementation = function() {
                            console.log("[Hook] " + className + "." + methodName);
                            console.log("[Args] " + JSON.stringify(arguments));
                            var result = this[methodName].apply(this, arguments);
                            console.log("[Result] " + result);
                            return result;
                        };
                    });
                    console.log("  [OK] Hooked: " + methodName);
                }
            });
        } catch(e) {
            console.log("  [ERR] " + className + ": " + e);
        }
    }
});

注意:批量Hook虽然方便,但也会产生大量日志。我建议你加个过滤条件,只Hook你真正关心的类和方法。否则日志刷屏,反而找不到关键信息。

五、Python + Frida 联动自动化

这才是真正的杀手锏。用Python启动Frida,自动注入脚本,然后收集结果。整个过程不需要人工干预。

import frida
import time
import json

class FridaAutomation:
    def __init__(self, package_name, script_path):
        self.package_name = package_name
        self.script_path = script_path
        self.session = None
        self.script = None
        self.hook_results = []
    
    def connect_to_device(self):
        """连接到设备或模拟器"""
        try:
            device = frida.get_usb_device()
            print("[+] 已连接到USB设备")
            return device
        except:
            print("[!] 未找到USB设备,尝试连接模拟器")
            device = frida.get_remote_device()
            return device
    
    def spawn_and_hook(self):
        """启动App并注入脚本"""
        device = self.connect_to_device()
        
        # 启动App(spawn方式)
        pid = device.spawn([self.package_name])
        self.session = device.attach(pid)
        
        # 加载脚本
        with open(self.script_path, 'r') as f:
            script_code = f.read()
        
        self.script = self.session.create_script(script_code)
        
        # 注册消息回调
        self.script.on('message', self.on_message)
        
        self.script.load()
        device.resume(pid)
        
        print(f"[+] App已启动,PID: {pid}")
        
        # 等待一段时间收集数据
        time.sleep(10)
        
        self.cleanup()
    
    def on_message(self, message, data):
        """处理Frida返回的消息"""
        if message['type'] == 'send':
            self.hook_results.append(message['payload'])
            print(f"[数据] {message['payload']}")
        elif message['type'] == 'error':
            print(f"[错误] {message['description']}")
    
    def cleanup(self):
        """清理资源"""
        if self.script:
            self.script.unload()
        if self.session:
            self.session.detach()
        
        # 保存结果
        with open("frida_results.json", "w") as f:
            json.dump(self.hook_results, f, indent=2)
        print(f"[+] 共收集 {len(self.hook_results)} 条Hook数据")

if __name__ == "__main__":
    automation = FridaAutomation(
        package_name="com.example.target",
        script_path="frida_bulk_hook.js"
    )
    automation.spawn_and_hook()

实战效果:这套联动方案在我之前的项目中,把单个App的渗透测试时间从2天压缩到了4小时。Python负责批量扫描暴露面,Frida负责深度Hook关键逻辑。两者配合,基本没有漏网之鱼。

六、避坑指南

做自动化渗透,有几个坑我踩过,你一定要注意:

  • App加固问题:很多App用了360加固、腾讯加固。反编译后代码全是壳,根本看不到真实逻辑。我的做法是先脱壳,或者直接用Frida在运行时Hook。
  • 多线程死锁:Python多线程扫描时,如果目标App有反调试机制,可能会触发死锁。我建议每个线程加个超时,超过30秒直接跳过。
  • Frida版本兼容:不同Android版本对Frida的支持不一样。Android 10以上有些Hook方式会失效。我一般准备两套脚本,一套针对低版本,一套针对高版本。

我曾经踩过的坑:有一次在测试某银行App时,Frida脚本一直注入失败。折腾了半天才发现,是App里集成了Frida检测库,检测到Frida进程就直接退出。后来我用Frida的"spawn"模式,在App启动前就注入,才绕过了检测。

七、总结

自动化渗透脚本的核心就两句话:Python做广度覆盖,Frida做深度突破。你不需要一开始就写一个完美的框架,先从一个简单的扫描脚本开始,慢慢积累自己的Hook库。用不了半年,你就能攒出一套属于自己的自动化渗透工具箱。

记住,自动化不是目的,效率才是。别为了自动化而自动化,有些场景手工测反而更快。灵活切换,才是老手该有的样子。


公众号:蓝海资料掘金营,微信deep3321