发布于

Frida 高级技巧与性能优化:提升动态分析效率的专业方法

作者

Frida 高级技巧与性能优化:提升动态分析效率的专业方法

随着 Frida 应用的深入,性能优化和高级技巧变得越来越重要。本文将介绍 Frida 的高级使用方法、性能优化策略和调试技巧。

高级 Hook 技巧

智能 Hook 管理

// advanced_hook_manager.js - 高级 Hook 管理器
class AdvancedHookManager {
    constructor() {
        this.hooks = new Map();
        this.hookGroups = new Map();
        this.statistics = {
            totalHooks: 0,
            activeHooks: 0,
            hookCalls: 0,
            errors: 0
        };
        this.performanceMonitor = new PerformanceMonitor();
    }
    
    // 创建智能 Hook
    createSmartHook(target, options = {}) {
        const hookId = this.generateHookId();
        const hookConfig = {
            id: hookId,
            target: target,
            enabled: true,
            callCount: 0,
            lastCalled: null,
            errors: 0,
            ...options
        };
        
        try {
            const hook = this.installHook(target, hookConfig);
            this.hooks.set(hookId, {
                config: hookConfig,
                hook: hook,
                performance: new HookPerformanceTracker()
            });
            
            this.statistics.totalHooks++;
            this.statistics.activeHooks++;
            
            console.log(`[HookManager] Created hook ${hookId} for ${target}`);
            return hookId;
            
        } catch (e) {
            console.log(`[HookManager] Failed to create hook for ${target}: ${e}`);
            this.statistics.errors++;
            return null;
        }
    }
    
    installHook(target, config) {
        const self = this;
        
        return Interceptor.attach(target, {
            onEnter: function(args) {
                if (!config.enabled) return;
                
                const startTime = Date.now();
                this.hookId = config.id;
                this.startTime = startTime;
                
                // 更新统计信息
                config.callCount++;
                config.lastCalled = startTime;
                self.statistics.hookCalls++;
                
                // 执行用户定义的 onEnter
                if (config.onEnter) {
                    try {
                        config.onEnter.call(this, args);
                    } catch (e) {
                        console.log(`[Hook ${config.id}] onEnter error: ${e}`);
                        config.errors++;
                        self.statistics.errors++;
                    }
                }
            },
            
            onLeave: function(retval) {
                if (!config.enabled) return;
                
                const endTime = Date.now();
                const duration = endTime - this.startTime;
                
                // 更新性能统计
                const hookData = self.hooks.get(this.hookId);
                if (hookData) {
                    hookData.performance.addSample(duration);
                }
                
                // 执行用户定义的 onLeave
                if (config.onLeave) {
                    try {
                        config.onLeave.call(this, retval);
                    } catch (e) {
                        console.log(`[Hook ${config.id}] onLeave error: ${e}`);
                        config.errors++;
                        self.statistics.errors++;
                    }
                }
            }
        });
    }
    
    // Hook 组管理
    createHookGroup(groupName, targets, sharedConfig = {}) {
        const groupId = this.generateGroupId();
        const hooks = [];
        
        for (const target of targets) {
            const hookId = this.createSmartHook(target, sharedConfig);
            if (hookId) {
                hooks.push(hookId);
            }
        }
        
        this.hookGroups.set(groupId, {
            name: groupName,
            hooks: hooks,
            config: sharedConfig
        });
        
        console.log(`[HookManager] Created group ${groupName} with ${hooks.length} hooks`);
        return groupId;
    }
    
    // 启用/禁用 Hook
    enableHook(hookId) {
        const hookData = this.hooks.get(hookId);
        if (hookData) {
            hookData.config.enabled = true;
            this.statistics.activeHooks++;
            console.log(`[HookManager] Enabled hook ${hookId}`);
        }
    }
    
    disableHook(hookId) {
        const hookData = this.hooks.get(hookId);
        if (hookData) {
            hookData.config.enabled = false;
            this.statistics.activeHooks--;
            console.log(`[HookManager] Disabled hook ${hookId}`);
        }
    }
    
    // 批量操作
    enableGroup(groupId) {
        const group = this.hookGroups.get(groupId);
        if (group) {
            group.hooks.forEach(hookId => this.enableHook(hookId));
            console.log(`[HookManager] Enabled group ${group.name}`);
        }
    }
    
    disableGroup(groupId) {
        const group = this.hookGroups.get(groupId);
        if (group) {
            group.hooks.forEach(hookId => this.disableHook(hookId));
            console.log(`[HookManager] Disabled group ${group.name}`);
        }
    }
    
    // 性能监控
    getPerformanceReport() {
        const report = {
            overview: this.statistics,
            hooks: [],
            groups: []
        };
        
        // Hook 性能统计
        this.hooks.forEach((hookData, hookId) => {
            const perf = hookData.performance.getStats();
            report.hooks.push({
                id: hookId,
                target: hookData.config.target.toString(),
                callCount: hookData.config.callCount,
                errors: hookData.config.errors,
                performance: perf
            });
        });
        
        // 按调用次数排序
        report.hooks.sort((a, b) => b.callCount - a.callCount);
        
        return report;
    }
    
    // 清理资源
    cleanup() {
        this.hooks.forEach((hookData, hookId) => {
            try {
                hookData.hook.detach();
            } catch (e) {
                console.log(`[HookManager] Failed to detach hook ${hookId}: ${e}`);
            }
        });
        
        this.hooks.clear();
        this.hookGroups.clear();
        
        console.log("[HookManager] Cleanup completed");
    }
    
    // 辅助方法
    generateHookId() {
        return 'hook_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9);
    }
    
    generateGroupId() {
        return 'group_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9);
    }
}

// Hook 性能跟踪器
class HookPerformanceTracker {
    constructor() {
        this.samples = [];
        this.maxSamples = 1000; // 限制样本数量
    }
    
    addSample(duration) {
        this.samples.push(duration);
        
        // 保持样本数量在限制内
        if (this.samples.length > this.maxSamples) {
            this.samples.shift();
        }
    }
    
    getStats() {
        if (this.samples.length === 0) {
            return { count: 0, avg: 0, min: 0, max: 0 };
        }
        
        const sorted = [...this.samples].sort((a, b) => a - b);
        const sum = this.samples.reduce((a, b) => a + b, 0);
        
        return {
            count: this.samples.length,
            avg: sum / this.samples.length,
            min: sorted[0],
            max: sorted[sorted.length - 1],
            median: sorted[Math.floor(sorted.length / 2)],
            p95: sorted[Math.floor(sorted.length * 0.95)]
        };
    }
}

// 性能监控器
class PerformanceMonitor {
    constructor() {
        this.startTime = Date.now();
        this.memoryUsage = [];
        this.cpuUsage = [];
        this.monitorInterval = null;
    }
    
    startMonitoring(interval = 5000) {
        this.monitorInterval = setInterval(() => {
            this.collectMetrics();
        }, interval);
        
        console.log("[PerformanceMonitor] Started monitoring");
    }
    
    stopMonitoring() {
        if (this.monitorInterval) {
            clearInterval(this.monitorInterval);
            this.monitorInterval = null;
        }
        
        console.log("[PerformanceMonitor] Stopped monitoring");
    }
    
    collectMetrics() {
        try {
            // 收集内存使用情况
            const memInfo = Process.enumerateRanges('rw-');
            let totalMemory = 0;
            
            memInfo.forEach(range => {
                totalMemory += range.size;
            });
            
            this.memoryUsage.push({
                timestamp: Date.now(),
                totalMemory: totalMemory,
                rangeCount: memInfo.length
            });
            
            // 限制历史数据
            if (this.memoryUsage.length > 100) {
                this.memoryUsage.shift();
            }
            
        } catch (e) {
            console.log("[PerformanceMonitor] Failed to collect metrics: " + e);
        }
    }
    
    getReport() {
        return {
            uptime: Date.now() - this.startTime,
            memoryUsage: this.memoryUsage,
            cpuUsage: this.cpuUsage
        };
    }
}

// 使用示例
function demonstrateAdvancedHookManager() {
    Java.perform(function() {
        const hookManager = new AdvancedHookManager();
        
        // 创建单个 Hook
        const stringHookId = hookManager.createSmartHook(
            Java.use("java.lang.String").equals.implementation,
            {
                onEnter: function(args) {
                    console.log("[String.equals] Called with: " + args[0]);
                },
                onLeave: function(retval) {
                    console.log("[String.equals] Result: " + retval);
                }
            }
        );
        
        // 创建 Hook 组
        const cryptoTargets = [
            Module.findExportByName("libc.so", "malloc"),
            Module.findExportByName("libc.so", "free")
        ].filter(addr => addr !== null);
        
        const cryptoGroupId = hookManager.createHookGroup(
            "Memory Operations",
            cryptoTargets,
            {
                onEnter: function(args) {
                    console.log("[Memory] Operation called");
                }
            }
        );
        
        // 定期生成性能报告
        setInterval(() => {
            const report = hookManager.getPerformanceReport();
            console.log("\n[Performance Report]");
            console.log("Total Hooks: " + report.overview.totalHooks);
            console.log("Active Hooks: " + report.overview.activeHooks);
            console.log("Total Calls: " + report.overview.hookCalls);
            console.log("Errors: " + report.overview.errors);
            
            // 显示前5个最活跃的 Hook
            console.log("\nTop 5 Most Active Hooks:");
            report.hooks.slice(0, 5).forEach((hook, index) => {
                console.log(`${index + 1}. ${hook.id}: ${hook.callCount} calls, avg: ${hook.performance.avg?.toFixed(2)}ms`);
            });
        }, 10000);
        
        // 清理(在适当的时候调用)
        // hookManager.cleanup();
    });
}

条件 Hook 和动态 Hook

// conditional_dynamic_hooks.js - 条件和动态 Hook
class ConditionalHookSystem {
    constructor() {
        this.conditions = new Map();
        this.dynamicHooks = new Map();
        this.contextStack = [];
    }
    
    // 创建条件 Hook
    createConditionalHook(target, condition, hookConfig) {
        const hookId = this.generateId();
        
        const hook = Interceptor.attach(target, {
            onEnter: function(args) {
                // 评估条件
                const shouldExecute = condition.call(this, args, this.context);
                
                if (shouldExecute) {
                    this.shouldExecuteLeave = true;
                    
                    if (hookConfig.onEnter) {
                        hookConfig.onEnter.call(this, args);
                    }
                } else {
                    this.shouldExecuteLeave = false;
                }
            },
            
            onLeave: function(retval) {
                if (this.shouldExecuteLeave && hookConfig.onLeave) {
                    hookConfig.onLeave.call(this, retval);
                }
            }
        });
        
        this.conditions.set(hookId, { hook, condition, config: hookConfig });
        return hookId;
    }
    
    // 创建上下文感知的 Hook
    createContextAwareHook(target, contextConditions, hookConfig) {
        return this.createConditionalHook(target, function(args, context) {
            // 检查调用栈上下文
            const stackTrace = Thread.backtrace(this.context, Backtracer.ACCURATE);
            
            for (const condition of contextConditions) {
                if (condition.type === 'caller') {
                    // 检查调用者
                    const found = stackTrace.some(frame => {
                        const symbol = DebugSymbol.fromAddress(frame);
                        return symbol.name && symbol.name.includes(condition.pattern);
                    });
                    
                    if (condition.required && !found) return false;
                    if (!condition.required && found) return false;
                }
                
                if (condition.type === 'thread') {
                    // 检查线程名称
                    const threadName = Process.getCurrentThreadId().toString();
                    if (!threadName.includes(condition.pattern)) return false;
                }
                
                if (condition.type === 'argument') {
                    // 检查参数值
                    const argValue = args[condition.index];
                    if (!condition.validator(argValue)) return false;
                }
            }
            
            return true;
        }, hookConfig);
    }
    
    // 创建频率限制的 Hook
    createRateLimitedHook(target, maxCallsPerSecond, hookConfig) {
        const callTimes = [];
        
        return this.createConditionalHook(target, function(args) {
            const now = Date.now();
            
            // 清理旧的调用记录
            while (callTimes.length > 0 && now - callTimes[0] > 1000) {
                callTimes.shift();
            }
            
            // 检查是否超过频率限制
            if (callTimes.length >= maxCallsPerSecond) {
                return false;
            }
            
            callTimes.push(now);
            return true;
        }, hookConfig);
    }
    
    // 动态 Hook 管理
    createDynamicHook(targetPattern, hookConfig) {
        const hookId = this.generateId();
        const hooks = new Set();
        
        // 监控模块加载
        const moduleListener = {
            onMatch: (module) => {
                this.scanModuleForTargets(module, targetPattern, hookConfig, hooks);
            }
        };
        
        // 扫描已加载的模块
        Process.enumerateModules().forEach(module => {
            moduleListener.onMatch(module);
        });
        
        // 监控新模块加载
        Process.setExceptionHandler((details) => {
            // 在异常处理中检查是否有新模块加载
            return false; // 不处理异常,只是监控
        });
        
        this.dynamicHooks.set(hookId, { hooks, pattern: targetPattern, config: hookConfig });
        return hookId;
    }
    
    scanModuleForTargets(module, pattern, hookConfig, hooks) {
        try {
            // 扫描导出函数
            const exports = module.enumerateExports();
            
            exports.forEach(exp => {
                if (this.matchesPattern(exp.name, pattern)) {
                    const hook = Interceptor.attach(exp.address, hookConfig);
                    hooks.add(hook);
                    
                    console.log(`[DynamicHook] Attached to ${exp.name} in ${module.name}`);
                }
            });
            
            // 扫描符号
            const symbols = module.enumerateSymbols();
            
            symbols.forEach(symbol => {
                if (symbol.type === 'function' && this.matchesPattern(symbol.name, pattern)) {
                    try {
                        const hook = Interceptor.attach(symbol.address, hookConfig);
                        hooks.add(hook);
                        
                        console.log(`[DynamicHook] Attached to symbol ${symbol.name} in ${module.name}`);
                    } catch (e) {
                        // 某些符号可能无法 Hook
                    }
                }
            });
            
        } catch (e) {
            console.log(`[DynamicHook] Failed to scan module ${module.name}: ${e}`);
        }
    }
    
    matchesPattern(name, pattern) {
        if (typeof pattern === 'string') {
            return name.includes(pattern);
        } else if (pattern instanceof RegExp) {
            return pattern.test(name);
        } else if (typeof pattern === 'function') {
            return pattern(name);
        }
        
        return false;
    }
    
    // 创建自适应 Hook
    createAdaptiveHook(target, adaptationConfig) {
        let currentConfig = { ...adaptationConfig.initial };
        let callCount = 0;
        let errorCount = 0;
        
        const hook = Interceptor.attach(target, {
            onEnter: function(args) {
                callCount++;
                
                // 根据调用频率调整行为
                if (adaptationConfig.adaptOnFrequency) {
                    const frequency = callCount / ((Date.now() - startTime) / 1000);
                    
                    if (frequency > adaptationConfig.highFrequencyThreshold) {
                        // 高频调用时简化处理
                        currentConfig = { ...adaptationConfig.highFrequency };
                    } else if (frequency < adaptationConfig.lowFrequencyThreshold) {
                        // 低频调用时详细处理
                        currentConfig = { ...adaptationConfig.lowFrequency };
                    }
                }
                
                // 执行当前配置的处理
                if (currentConfig.onEnter) {
                    try {
                        currentConfig.onEnter.call(this, args);
                    } catch (e) {
                        errorCount++;
                        
                        // 错误率过高时降级处理
                        if (errorCount / callCount > adaptationConfig.errorThreshold) {
                            currentConfig = { ...adaptationConfig.fallback };
                        }
                    }
                }
            },
            
            onLeave: function(retval) {
                if (currentConfig.onLeave) {
                    try {
                        currentConfig.onLeave.call(this, retval);
                    } catch (e) {
                        errorCount++;
                    }
                }
            }
        });
        
        const startTime = Date.now();
        return hook;
    }
    
    generateId() {
        return 'hook_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9);
    }
}

// 使用示例
function demonstrateConditionalHooks() {
    const hookSystem = new ConditionalHookSystem();
    
    // 1. 条件 Hook - 只在特定参数值时触发
    const mallocAddr = Module.findExportByName("libc.so", "malloc");
    if (mallocAddr) {
        hookSystem.createConditionalHook(
            mallocAddr,
            function(args) {
                const size = args[0].toInt32();
                return size > 1024; // 只 Hook 大于 1KB 的分配
            },
            {
                onEnter: function(args) {
                    console.log("[Conditional] Large malloc: " + args[0]);
                }
            }
        );
    }
    
    // 2. 上下文感知 Hook
    Java.perform(function() {
        const String = Java.use("java.lang.String");
        
        hookSystem.createContextAwareHook(
            String.equals.implementation,
            [
                {
                    type: 'caller',
                    pattern: 'password',
                    required: true
                },
                {
                    type: 'argument',
                    index: 0,
                    validator: (arg) => arg && arg.toString().length > 6
                }
            ],
            {
                onEnter: function(args) {
                    console.log("[ContextAware] Password comparison detected");
                }
            }
        );
    });
    
    // 3. 频率限制 Hook
    const strcmpAddr = Module.findExportByName("libc.so", "strcmp");
    if (strcmpAddr) {
        hookSystem.createRateLimitedHook(
            strcmpAddr,
            10, // 最多每秒10次
            {
                onEnter: function(args) {
                    const str1 = Memory.readUtf8String(args[0]);
                    const str2 = Memory.readUtf8String(args[1]);
                    console.log("[RateLimited] strcmp: " + str1 + " vs " + str2);
                }
            }
        );
    }
    
    // 4. 动态 Hook
    hookSystem.createDynamicHook(
        /crypto|encrypt|decrypt/i, // 正则表达式模式
        {
            onEnter: function(args) {
                const symbol = DebugSymbol.fromAddress(this.returnAddress);
                console.log("[Dynamic] Crypto function called: " + symbol.name);
            }
        }
    );
    
    // 5. 自适应 Hook
    if (mallocAddr) {
        hookSystem.createAdaptiveHook(
            mallocAddr,
            {
                initial: {
                    onEnter: function(args) {
                        console.log("[Adaptive] malloc: " + args[0]);
                    }
                },
                highFrequency: {
                    onEnter: function(args) {
                        // 高频时只记录大分配
                        if (args[0].toInt32() > 4096) {
                            console.log("[Adaptive-HF] Large malloc: " + args[0]);
                        }
                    }
                },
                lowFrequency: {
                    onEnter: function(args) {
                        // 低频时详细记录
                        const size = args[0].toInt32();
                        const caller = DebugSymbol.fromAddress(this.returnAddress);
                        console.log("[Adaptive-LF] malloc: " + size + " from " + caller.name);
                    }
                },
                fallback: {
                    onEnter: function(args) {
                        // 错误时的最简处理
                        console.log("[Adaptive-FB] malloc called");
                    }
                },
                highFrequencyThreshold: 100,
                lowFrequencyThreshold: 10,
                errorThreshold: 0.1,
                adaptOnFrequency: true
            }
        );
    }
}

内存管理和优化

内存泄漏检测

// memory_leak_detector.js - 内存泄漏检测器
class MemoryLeakDetector {
    constructor() {
        this.allocations = new Map();
        this.allocationStats = {
            totalAllocations: 0,
            totalDeallocations: 0,
            currentAllocations: 0,
            peakAllocations: 0,
            totalBytesAllocated: 0,
            totalBytesFreed: 0,
            currentBytesAllocated: 0,
            peakBytesAllocated: 0
        };
        this.leakThreshold = 1000; // 超过1000个未释放分配认为可能泄漏
        this.reportInterval = 30000; // 30秒报告一次
        this.isMonitoring = false;
    }
    
    startMonitoring() {
        if (this.isMonitoring) {
            console.log("[MemoryLeakDetector] Already monitoring");
            return;
        }
        
        this.isMonitoring = true;
        this.hookMemoryFunctions();
        this.startPeriodicReporting();
        
        console.log("[MemoryLeakDetector] Started monitoring");
    }
    
    stopMonitoring() {
        if (!this.isMonitoring) {
            console.log("[MemoryLeakDetector] Not monitoring");
            return;
        }
        
        this.isMonitoring = false;
        this.unhookMemoryFunctions();
        this.stopPeriodicReporting();
        
        console.log("[MemoryLeakDetector] Stopped monitoring");
    }
    
    hookMemoryFunctions() {
        // Hook malloc
        const mallocAddr = Module.findExportByName("libc.so", "malloc");
        if (mallocAddr) {
            this.mallocHook = Interceptor.attach(mallocAddr, {
                onEnter: function(args) {
                    this.size = args[0].toInt32();
                    this.stackTrace = Thread.backtrace(this.context, Backtracer.ACCURATE);
                },
                
                onLeave: function(retval) {
                    if (!retval.isNull()) {
                        const detector = MemoryLeakDetector.instance;
                        detector.recordAllocation(retval, this.size, this.stackTrace);
                    }
                }
            });
        }
        
        // Hook free
        const freeAddr = Module.findExportByName("libc.so", "free");
        if (freeAddr) {
            this.freeHook = Interceptor.attach(freeAddr, {
                onEnter: function(args) {
                    const ptr = args[0];
                    if (!ptr.isNull()) {
                        const detector = MemoryLeakDetector.instance;
                        detector.recordDeallocation(ptr);
                    }
                }
            });
        }
        
        // Hook calloc
        const callocAddr = Module.findExportByName("libc.so", "calloc");
        if (callocAddr) {
            this.callocHook = Interceptor.attach(callocAddr, {
                onEnter: function(args) {
                    this.size = args[0].toInt32() * args[1].toInt32();
                    this.stackTrace = Thread.backtrace(this.context, Backtracer.ACCURATE);
                },
                
                onLeave: function(retval) {
                    if (!retval.isNull()) {
                        const detector = MemoryLeakDetector.instance;
                        detector.recordAllocation(retval, this.size, this.stackTrace);
                    }
                }
            });
        }
        
        // Hook realloc
        const reallocAddr = Module.findExportByName("libc.so", "realloc");
        if (reallocAddr) {
            this.reallocHook = Interceptor.attach(reallocAddr, {
                onEnter: function(args) {
                    this.oldPtr = args[0];
                    this.newSize = args[1].toInt32();
                    this.stackTrace = Thread.backtrace(this.context, Backtracer.ACCURATE);
                },
                
                onLeave: function(retval) {
                    const detector = MemoryLeakDetector.instance;
                    
                    // 如果旧指针不为空,记录释放
                    if (!this.oldPtr.isNull()) {
                        detector.recordDeallocation(this.oldPtr);
                    }
                    
                    // 如果新指针不为空,记录分配
                    if (!retval.isNull()) {
                        detector.recordAllocation(retval, this.newSize, this.stackTrace);
                    }
                }
            });
        }
        
        MemoryLeakDetector.instance = this;
    }
    
    unhookMemoryFunctions() {
        if (this.mallocHook) {
            this.mallocHook.detach();
            this.mallocHook = null;
        }
        
        if (this.freeHook) {
            this.freeHook.detach();
            this.freeHook = null;
        }
        
        if (this.callocHook) {
            this.callocHook.detach();
            this.callocHook = null;
        }
        
        if (this.reallocHook) {
            this.reallocHook.detach();
            this.reallocHook = null;
        }
    }
    
    recordAllocation(ptr, size, stackTrace) {
        const ptrStr = ptr.toString();
        const timestamp = Date.now();
        
        this.allocations.set(ptrStr, {
            size: size,
            timestamp: timestamp,
            stackTrace: stackTrace
        });
        
        // 更新统计信息
        this.allocationStats.totalAllocations++;
        this.allocationStats.currentAllocations++;
        this.allocationStats.totalBytesAllocated += size;
        this.allocationStats.currentBytesAllocated += size;
        
        // 更新峰值
        if (this.allocationStats.currentAllocations > this.allocationStats.peakAllocations) {
            this.allocationStats.peakAllocations = this.allocationStats.currentAllocations;
        }
        
        if (this.allocationStats.currentBytesAllocated > this.allocationStats.peakBytesAllocated) {
            this.allocationStats.peakBytesAllocated = this.allocationStats.currentBytesAllocated;
        }
    }
    
    recordDeallocation(ptr) {
        const ptrStr = ptr.toString();
        const allocation = this.allocations.get(ptrStr);
        
        if (allocation) {
            this.allocations.delete(ptrStr);
            
            // 更新统计信息
            this.allocationStats.totalDeallocations++;
            this.allocationStats.currentAllocations--;
            this.allocationStats.totalBytesFreed += allocation.size;
            this.allocationStats.currentBytesAllocated -= allocation.size;
        } else {
            console.log("[MemoryLeakDetector] Warning: Freeing unknown pointer " + ptrStr);
        }
    }
    
    startPeriodicReporting() {
        this.reportTimer = setInterval(() => {
            this.generateReport();
        }, this.reportInterval);
    }
    
    stopPeriodicReporting() {
        if (this.reportTimer) {
            clearInterval(this.reportTimer);
            this.reportTimer = null;
        }
    }
    
    generateReport() {
        const stats = this.allocationStats;
        const currentTime = Date.now();
        
        console.log("\n[Memory Leak Report]");
        console.log("===================");
        console.log(`Current Allocations: ${stats.currentAllocations}`);
        console.log(`Current Bytes: ${this.formatBytes(stats.currentBytesAllocated)}`);
        console.log(`Peak Allocations: ${stats.peakAllocations}`);
        console.log(`Peak Bytes: ${this.formatBytes(stats.peakBytesAllocated)}`);
        console.log(`Total Allocations: ${stats.totalAllocations}`);
        console.log(`Total Deallocations: ${stats.totalDeallocations}`);
        console.log(`Leak Ratio: ${((stats.totalAllocations - stats.totalDeallocations) / stats.totalAllocations * 100).toFixed(2)}%`);
        
        // 检查潜在泄漏
        if (stats.currentAllocations > this.leakThreshold) {
            console.log("\n[POTENTIAL MEMORY LEAK DETECTED]");
            this.analyzePotentialLeaks(currentTime);
        }
        
        // 显示最大的分配
        this.showLargestAllocations();
    }
    
    analyzePotentialLeaks(currentTime) {
        const oldAllocations = [];
        const ageThreshold = 60000; // 1分钟
        
        this.allocations.forEach((allocation, ptr) => {
            const age = currentTime - allocation.timestamp;
            if (age > ageThreshold) {
                oldAllocations.push({
                    ptr: ptr,
                    size: allocation.size,
                    age: age,
                    stackTrace: allocation.stackTrace
                });
            }
        });
        
        // 按大小排序
        oldAllocations.sort((a, b) => b.size - a.size);
        
        console.log(`Found ${oldAllocations.length} allocations older than ${ageThreshold/1000}s`);
        
        // 显示前10个最大的旧分配
        const topLeaks = oldAllocations.slice(0, 10);
        topLeaks.forEach((leak, index) => {
            console.log(`\n${index + 1}. Ptr: ${leak.ptr}`);
            console.log(`   Size: ${this.formatBytes(leak.size)}`);
            console.log(`   Age: ${(leak.age/1000).toFixed(1)}s`);
            console.log(`   Stack trace:`);
            
            leak.stackTrace.slice(0, 5).forEach((frame, i) => {
                const symbol = DebugSymbol.fromAddress(frame);
                console.log(`     ${i}: ${symbol.name || frame}`);
            });
        });
    }
    
    showLargestAllocations() {
        const allocations = Array.from(this.allocations.entries())
            .map(([ptr, allocation]) => ({
                ptr: ptr,
                size: allocation.size,
                timestamp: allocation.timestamp
            }))
            .sort((a, b) => b.size - a.size)
            .slice(0, 5);
        
        if (allocations.length > 0) {
            console.log("\nTop 5 Largest Current Allocations:");
            allocations.forEach((allocation, index) => {
                console.log(`${index + 1}. ${allocation.ptr}: ${this.formatBytes(allocation.size)}`);
            });
        }
    }
    
    formatBytes(bytes) {
        if (bytes === 0) return '0 B';
        
        const k = 1024;
        const sizes = ['B', 'KB', 'MB', 'GB'];
        const i = Math.floor(Math.log(bytes) / Math.log(k));
        
        return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
    }
    
    // 手动触发泄漏检测
    detectLeaks() {
        this.generateReport();
    }
    
    // 清理检测器
    cleanup() {
        this.stopMonitoring();
        this.allocations.clear();
        
        // 重置统计信息
        this.allocationStats = {
            totalAllocations: 0,
            totalDeallocations: 0,
            currentAllocations: 0,
            peakAllocations: 0,
            totalBytesAllocated: 0,
            totalBytesFreed: 0,
            currentBytesAllocated: 0,
            peakBytesAllocated: 0
        };
        
        console.log("[MemoryLeakDetector] Cleanup completed");
    }
}

// 使用示例
function demonstrateMemoryLeakDetection() {
    const detector = new MemoryLeakDetector();
    
    // 开始监控
    detector.startMonitoring();
    
    // 模拟一些内存操作来测试检测器
    setTimeout(() => {
        // 手动触发报告
        detector.detectLeaks();
    }, 5000);
    
    // 在适当的时候停止监控
    setTimeout(() => {
        detector.stopMonitoring();
    }, 60000);
}

总结

Frida 高级技巧与性能优化的核心要点:

🎯 高级 Hook 技巧

  1. 智能管理:Hook 生命周期管理和性能监控
  2. 条件 Hook:基于上下文和条件的智能 Hook
  3. 动态 Hook:运行时发现和附加目标
  4. 自适应 Hook:根据运行状况自动调整行为

✅ 性能优化策略

  • 内存使用优化和泄漏检测
  • Hook 频率控制和批量处理
  • 资源管理和清理机制
  • 性能监控和统计分析

🚀 调试和监控

  • 实时性能指标收集
  • 内存分配跟踪和分析
  • 错误处理和恢复机制
  • 自动化报告和告警

💡 最佳实践

  • 合理的 Hook 粒度控制
  • 异常处理和容错设计
  • 资源清理和内存管理
  • 性能影响最小化

掌握这些高级技巧,构建高效稳定的 Frida 分析工具!


高级技巧和性能优化是 Frida 专业应用的关键,合理运用这些方法能够大大提升分析效率和稳定性。