发布于

Frida 动态分析框架入门指南:现代应用安全分析的强大工具

作者

Frida 动态分析框架入门指南:现代应用安全分析的强大工具

Frida 是一个强大的动态分析框架,支持 Windows、macOS、GNU/Linux、iOS、Android 等多个平台。它允许开发者和安全研究人员在运行时注入 JavaScript 代码来分析和修改应用程序的行为。

Frida 框架概述

什么是 Frida

Frida 是一个动态代码插桩工具包,它提供了一套丰富的 API 来进行运行时分析:

// 基础 Frida 脚本示例
Java.perform(function() {
    // 获取目标类
    var MainActivity = Java.use("com.example.app.MainActivity");
    
    // Hook 方法
    MainActivity.checkLicense.implementation = function() {
        console.log("[+] checkLicense() called");
        
        // 调用原始方法
        var result = this.checkLicense();
        console.log("[+] Original result: " + result);
        
        // 修改返回值
        console.log("[+] Returning true instead");
        return true;
    };
    
    console.log("[+] Hook installed successfully");
});

核心特性

// 1. 方法 Hook 和参数修改
Java.perform(function() {
    var String = Java.use("java.lang.String");
    
    // Hook String.equals 方法
    String.equals.implementation = function(other) {
        var result = this.equals(other);
        
        console.log("[String.equals] this: '" + this + "'");
        console.log("[String.equals] other: '" + other + "'");
        console.log("[String.equals] result: " + result);
        
        return result;
    };
});

// 2. 类实例化监控
Java.perform(function() {
    var File = Java.use("java.io.File");
    
    // Hook 构造函数
    File.$init.overload('java.lang.String').implementation = function(path) {
        console.log("[File] Creating file with path: " + path);
        
        // 调用原始构造函数
        this.$init(path);
    };
});

// 3. 字段访问和修改
Java.perform(function() {
    var targetClass = Java.use("com.example.app.Config");
    
    // 修改静态字段
    targetClass.DEBUG_MODE.value = true;
    console.log("[+] DEBUG_MODE set to true");
    
    // 监控实例字段
    targetClass.setApiKey.implementation = function(key) {
        console.log("[+] API Key being set: " + key);
        
        // 替换为自定义值
        this.setApiKey("custom_api_key");
    };
});

环境搭建和安装

安装 Frida

# 1. 安装 Python 和 pip
# 确保 Python 3.6+ 已安装

# 2. 安装 Frida
pip install frida-tools

# 3. 验证安装
frida --version

# 4. 安装 Frida 服务器 (Android)
# 下载对应架构的 frida-server
# https://github.com/frida/frida/releases

# 5. 推送到 Android 设备
adb push frida-server-15.2.2-android-arm64 /data/local/tmp/frida-server
adb shell chmod 755 /data/local/tmp/frida-server

# 6. 启动 Frida 服务器
adb shell su -c "/data/local/tmp/frida-server &"

开发环境配置

# frida_setup.py - Frida 开发环境配置
import frida
import sys
import time

class FridaEnvironment:
    def __init__(self):
        self.device = None
        self.session = None
        self.script = None
    
    def setup_device(self, device_id=None):
        """设置目标设备"""
        try:
            if device_id:
                self.device = frida.get_device(device_id)
            else:
                # 获取 USB 连接的设备
                self.device = frida.get_usb_device()
            
            print(f"[+] Connected to device: {self.device}")
            return True
        except Exception as e:
            print(f"[-] Failed to connect to device: {e}")
            return False
    
    def list_processes(self):
        """列出设备上的进程"""
        try:
            processes = self.device.enumerate_processes()
            print("\n[+] Running processes:")
            for process in processes:
                print(f"  PID: {process.pid:5d} | Name: {process.name}")
            return processes
        except Exception as e:
            print(f"[-] Failed to list processes: {e}")
            return []
    
    def attach_to_process(self, process_name_or_pid):
        """附加到目标进程"""
        try:
            if isinstance(process_name_or_pid, str):
                # 通过进程名附加
                self.session = self.device.attach(process_name_or_pid)
            else:
                # 通过 PID 附加
                self.session = self.device.attach(process_name_or_pid)
            
            print(f"[+] Attached to process: {process_name_or_pid}")
            return True
        except Exception as e:
            print(f"[-] Failed to attach to process: {e}")
            return False
    
    def spawn_and_attach(self, package_name):
        """启动并附加到应用"""
        try:
            # 启动应用
            pid = self.device.spawn([package_name])
            print(f"[+] Spawned process with PID: {pid}")
            
            # 附加到进程
            self.session = self.device.attach(pid)
            print(f"[+] Attached to spawned process")
            
            # 恢复进程执行
            self.device.resume(pid)
            print(f"[+] Resumed process execution")
            
            return True
        except Exception as e:
            print(f"[-] Failed to spawn and attach: {e}")
            return False
    
    def load_script(self, script_content):
        """加载 Frida 脚本"""
        try:
            self.script = self.session.create_script(script_content)
            self.script.on('message', self.on_message)
            self.script.load()
            print("[+] Script loaded successfully")
            return True
        except Exception as e:
            print(f"[-] Failed to load script: {e}")
            return False
    
    def on_message(self, message, data):
        """处理脚本消息"""
        if message['type'] == 'send':
            print(f"[Script] {message['payload']}")
        elif message['type'] == 'error':
            print(f"[Error] {message['stack']}")
    
    def cleanup(self):
        """清理资源"""
        if self.script:
            self.script.unload()
        if self.session:
            self.session.detach()
        print("[+] Cleanup completed")

# 使用示例
def main():
    frida_env = FridaEnvironment()
    
    # 设置设备
    if not frida_env.setup_device():
        return
    
    # 列出进程
    processes = frida_env.list_processes()
    
    # 附加到目标应用
    target_app = "com.example.targetapp"
    if frida_env.spawn_and_attach(target_app):
        
        # 基础 Hook 脚本
        script_content = """
        Java.perform(function() {
            console.log("[+] Starting Frida script");
            
            // Hook 示例
            var MainActivity = Java.use("com.example.targetapp.MainActivity");
            MainActivity.onCreate.implementation = function(savedInstanceState) {
                console.log("[+] MainActivity.onCreate() called");
                this.onCreate(savedInstanceState);
            };
        });
        """
        
        # 加载脚本
        if frida_env.load_script(script_content):
            print("[+] Press Ctrl+C to exit")
            try:
                sys.stdin.read()
            except KeyboardInterrupt:
                pass
    
    # 清理
    frida_env.cleanup()

if __name__ == "__main__":
    main()

基础 Hook 技术

Android Java Hook

// android_java_hooks.js - Android Java Hook 示例
Java.perform(function() {
    console.log("[+] Starting Android Java hooks");
    
    // 1. Hook Activity 生命周期
    hookActivityLifecycle();
    
    // 2. Hook 网络请求
    hookNetworkRequests();
    
    // 3. Hook 加密操作
    hookCryptographicOperations();
    
    // 4. Hook 文件操作
    hookFileOperations();
    
    // 5. Hook SharedPreferences
    hookSharedPreferences();
});

function hookActivityLifecycle() {
    try {
        var Activity = Java.use("android.app.Activity");
        
        Activity.onCreate.implementation = function(savedInstanceState) {
            console.log("[Activity] onCreate: " + this.getClass().getName());
            this.onCreate(savedInstanceState);
        };
        
        Activity.onResume.implementation = function() {
            console.log("[Activity] onResume: " + this.getClass().getName());
            this.onResume();
        };
        
        Activity.onPause.implementation = function() {
            console.log("[Activity] onPause: " + this.getClass().getName());
            this.onPause();
        };
        
        console.log("[+] Activity lifecycle hooks installed");
    } catch (e) {
        console.log("[-] Failed to hook Activity lifecycle: " + e);
    }
}

function hookNetworkRequests() {
    try {
        // Hook OkHttp
        var OkHttpClient = Java.use("okhttp3.OkHttpClient");
        var Request = Java.use("okhttp3.Request");
        
        OkHttpClient.newCall.implementation = function(request) {
            console.log("[OkHttp] Request URL: " + request.url().toString());
            console.log("[OkHttp] Request Method: " + request.method());
            
            // 打印请求头
            var headers = request.headers();
            var headerNames = headers.names();
            var iterator = headerNames.iterator();
            
            while (iterator.hasNext()) {
                var name = iterator.next();
                var value = headers.get(name);
                console.log("[OkHttp] Header: " + name + " = " + value);
            }
            
            return this.newCall(request);
        };
        
        // Hook HttpURLConnection
        var HttpURLConnection = Java.use("java.net.HttpURLConnection");
        
        HttpURLConnection.getResponseCode.implementation = function() {
            var responseCode = this.getResponseCode();
            console.log("[HttpURLConnection] Response Code: " + responseCode);
            console.log("[HttpURLConnection] URL: " + this.getURL().toString());
            
            return responseCode;
        };
        
        console.log("[+] Network request hooks installed");
    } catch (e) {
        console.log("[-] Failed to hook network requests: " + e);
    }
}

function hookCryptographicOperations() {
    try {
        // Hook Cipher
        var Cipher = Java.use("javax.crypto.Cipher");
        
        Cipher.doFinal.overload('[B').implementation = function(input) {
            console.log("[Cipher] doFinal called");
            console.log("[Cipher] Algorithm: " + this.getAlgorithm());
            console.log("[Cipher] Input length: " + input.length);
            
            var result = this.doFinal(input);
            console.log("[Cipher] Output length: " + result.length);
            
            return result;
        };
        
        // Hook MessageDigest
        var MessageDigest = Java.use("java.security.MessageDigest");
        
        MessageDigest.digest.overload('[B').implementation = function(input) {
            console.log("[MessageDigest] digest called");
            console.log("[MessageDigest] Algorithm: " + this.getAlgorithm());
            console.log("[MessageDigest] Input: " + bytesToHex(input));
            
            var result = this.digest(input);
            console.log("[MessageDigest] Hash: " + bytesToHex(result));
            
            return result;
        };
        
        console.log("[+] Cryptographic operation hooks installed");
    } catch (e) {
        console.log("[-] Failed to hook cryptographic operations: " + e);
    }
}

function hookFileOperations() {
    try {
        // Hook File operations
        var File = Java.use("java.io.File");
        
        File.$init.overload('java.lang.String').implementation = function(path) {
            console.log("[File] Creating file: " + path);
            this.$init(path);
        };
        
        File.exists.implementation = function() {
            var result = this.exists();
            console.log("[File] exists() called for: " + this.getAbsolutePath() + " -> " + result);
            return result;
        };
        
        // Hook FileInputStream
        var FileInputStream = Java.use("java.io.FileInputStream");
        
        FileInputStream.$init.overload('java.lang.String').implementation = function(name) {
            console.log("[FileInputStream] Opening file: " + name);
            this.$init(name);
        };
        
        console.log("[+] File operation hooks installed");
    } catch (e) {
        console.log("[-] Failed to hook file operations: " + e);
    }
}

function hookSharedPreferences() {
    try {
        var SharedPreferences = Java.use("android.content.SharedPreferences");
        var Editor = Java.use("android.content.SharedPreferences$Editor");
        
        // Hook getString
        SharedPreferences.getString.implementation = function(key, defValue) {
            var result = this.getString(key, defValue);
            console.log("[SharedPreferences] getString: " + key + " = " + result);
            return result;
        };
        
        // Hook putString
        Editor.putString.implementation = function(key, value) {
            console.log("[SharedPreferences] putString: " + key + " = " + value);
            return this.putString(key, value);
        };
        
        console.log("[+] SharedPreferences hooks installed");
    } catch (e) {
        console.log("[-] Failed to hook SharedPreferences: " + e);
    }
}

// 辅助函数
function bytesToHex(bytes) {
    var hex = "";
    for (var i = 0; i < bytes.length; i++) {
        var byte = bytes[i] & 0xFF;
        hex += ("0" + byte.toString(16)).slice(-2);
    }
    return hex.toUpperCase();
}

function hexToBytes(hex) {
    var bytes = [];
    for (var i = 0; i < hex.length; i += 2) {
        bytes.push(parseInt(hex.substr(i, 2), 16));
    }
    return bytes;
}

// 动态类加载和 Hook
function hookDynamicClass(className) {
    Java.perform(function() {
        try {
            var targetClass = Java.use(className);
            console.log("[+] Successfully loaded class: " + className);
            
            // 获取所有方法
            var methods = targetClass.class.getDeclaredMethods();
            console.log("[+] Found " + methods.length + " methods in " + className);
            
            // 打印方法信息
            for (var i = 0; i < methods.length; i++) {
                var method = methods[i];
                console.log("  Method: " + method.getName());
            }
            
        } catch (e) {
            console.log("[-] Failed to load class " + className + ": " + e);
        }
    });
}

// 运行时类发现
function discoverClasses(packagePrefix) {
    Java.perform(function() {
        Java.enumerateLoadedClasses({
            onMatch: function(className) {
                if (className.startsWith(packagePrefix)) {
                    console.log("[Discovery] Found class: " + className);
                }
            },
            onComplete: function() {
                console.log("[Discovery] Class enumeration completed");
            }
        });
    });
}

Native Hook 技术

// native_hooks.js - Native Hook 示例
console.log("[+] Starting Native hooks");

// 1. Hook libc 函数
hookLibcFunctions();

// 2. Hook JNI 函数
hookJniFunctions();

// 3. Hook 自定义 Native 库
hookCustomNativeLibrary();

function hookLibcFunctions() {
    try {
        // Hook malloc
        var malloc = Module.findExportByName("libc.so", "malloc");
        if (malloc) {
            Interceptor.attach(malloc, {
                onEnter: function(args) {
                    this.size = args[0].toInt32();
                    console.log("[malloc] Allocating " + this.size + " bytes");
                },
                onLeave: function(retval) {
                    console.log("[malloc] Allocated at: " + retval);
                }
            });
        }
        
        // Hook free
        var free = Module.findExportByName("libc.so", "free");
        if (free) {
            Interceptor.attach(free, {
                onEnter: function(args) {
                    console.log("[free] Freeing memory at: " + args[0]);
                }
            });
        }
        
        // Hook strcmp
        var strcmp = Module.findExportByName("libc.so", "strcmp");
        if (strcmp) {
            Interceptor.attach(strcmp, {
                onEnter: function(args) {
                    var str1 = Memory.readUtf8String(args[0]);
                    var str2 = Memory.readUtf8String(args[1]);
                    console.log("[strcmp] Comparing: '" + str1 + "' vs '" + str2 + "'");
                },
                onLeave: function(retval) {
                    console.log("[strcmp] Result: " + retval.toInt32());
                }
            });
        }
        
        console.log("[+] libc function hooks installed");
    } catch (e) {
        console.log("[-] Failed to hook libc functions: " + e);
    }
}

function hookJniFunctions() {
    try {
        // Hook JNI GetStringUTFChars
        var GetStringUTFChars = Module.findExportByName("libart.so", "_ZN3art3JNI17GetStringUTFCharsEP7_JNIEnvP8_jstringPh");
        if (!GetStringUTFChars) {
            GetStringUTFChars = Module.findExportByName("libdvm.so", "_Z20dvmGetStringUtfCharsP8_jstringPh");
        }
        
        if (GetStringUTFChars) {
            Interceptor.attach(GetStringUTFChars, {
                onEnter: function(args) {
                    this.jstring = args[1];
                },
                onLeave: function(retval) {
                    if (retval.isNull()) return;
                    
                    var str = Memory.readUtf8String(retval);
                    console.log("[JNI] GetStringUTFChars: " + str);
                }
            });
        }
        
        // Hook JNI NewStringUTF
        var NewStringUTF = Module.findExportByName("libart.so", "_ZN3art3JNI12NewStringUTFEP7_JNIEnvPKc");
        if (!NewStringUTF) {
            NewStringUTF = Module.findExportByName("libdvm.so", "_Z15dvmCreateStringPKc");
        }
        
        if (NewStringUTF) {
            Interceptor.attach(NewStringUTF, {
                onEnter: function(args) {
                    var str = Memory.readUtf8String(args[1]);
                    console.log("[JNI] NewStringUTF: " + str);
                }
            });
        }
        
        console.log("[+] JNI function hooks installed");
    } catch (e) {
        console.log("[-] Failed to hook JNI functions: " + e);
    }
}

function hookCustomNativeLibrary() {
    try {
        // 等待库加载
        var libName = "libnative.so";
        
        // 监控模块加载
        Process.enumerateModules({
            onMatch: function(module) {
                if (module.name === libName) {
                    console.log("[+] Found target library: " + libName);
                    hookNativeLibraryFunctions(module);
                }
            },
            onComplete: function() {
                console.log("[+] Module enumeration completed");
            }
        });
        
        // 或者等待库加载后再 Hook
        var intervalId = setInterval(function() {
            var module = Process.findModuleByName(libName);
            if (module) {
                clearInterval(intervalId);
                console.log("[+] Target library loaded: " + libName);
                hookNativeLibraryFunctions(module);
            }
        }, 1000);
        
    } catch (e) {
        console.log("[-] Failed to hook custom native library: " + e);
    }
}

function hookNativeLibraryFunctions(module) {
    try {
        // Hook 导出函数
        var exports = module.enumerateExports();
        console.log("[+] Found " + exports.length + " exports in " + module.name);
        
        exports.forEach(function(exp) {
            if (exp.name.indexOf("Java_") === 0) {
                console.log("[Export] JNI function: " + exp.name + " at " + exp.address);
                
                // Hook JNI 函数
                Interceptor.attach(exp.address, {
                    onEnter: function(args) {
                        console.log("[" + exp.name + "] Called");
                        
                        // 打印参数
                        for (var i = 0; i < 4; i++) {
                            console.log("  arg[" + i + "]: " + args[i]);
                        }
                    },
                    onLeave: function(retval) {
                        console.log("[" + exp.name + "] Return: " + retval);
                    }
                });
            }
        });
        
        // Hook 特定函数
        var targetFunction = module.findExportByName("native_function");
        if (targetFunction) {
            Interceptor.attach(targetFunction, {
                onEnter: function(args) {
                    console.log("[native_function] Called with args:");
                    console.log("  arg0: " + args[0]);
                    console.log("  arg1: " + args[1]);
                },
                onLeave: function(retval) {
                    console.log("[native_function] Return: " + retval);
                }
            });
        }
        
    } catch (e) {
        console.log("[-] Failed to hook native library functions: " + e);
    }
}

// 内存操作示例
function memoryOperations() {
    // 读取内存
    var address = ptr("0x12345678");
    var value = Memory.readU32(address);
    console.log("Value at " + address + ": " + value);
    
    // 写入内存
    Memory.writeU32(address, 0x41414141);
    
    // 搜索内存
    Memory.scan(ptr("0x10000000"), 0x1000, "41 41 41 41", {
        onMatch: function(address, size) {
            console.log("Found pattern at: " + address);
        },
        onComplete: function() {
            console.log("Memory scan completed");
        }
    });
    
    // 分配内存
    var buffer = Memory.alloc(1024);
    Memory.writeUtf8String(buffer, "Hello Frida!");
    var str = Memory.readUtf8String(buffer);
    console.log("Allocated string: " + str);
}

// 代码跟踪
function enableCodeTracing() {
    var targetModule = Process.findModuleByName("libnative.so");
    if (targetModule) {
        Stalker.follow(Process.getCurrentThreadId(), {
            events: {
                call: true,
                ret: true,
                exec: false
            },
            onReceive: function(events) {
                console.log("Stalker events: " + events.length);
            },
            transform: function(iterator) {
                var instruction = iterator.next();
                
                do {
                    if (instruction.address.compare(targetModule.base) >= 0 &&
                        instruction.address.compare(targetModule.base.add(targetModule.size)) < 0) {
                        
                        iterator.putCallout(function(context) {
                            console.log("Executing: " + instruction.address + " " + instruction.mnemonic);
                        });
                    }
                    
                    iterator.keep();
                } while ((instruction = iterator.next()) !== null);
            }
        });
    }
}

实际应用案例

应用安全分析

# security_analysis.py - 应用安全分析脚本
import frida
import sys
import json
import time

class SecurityAnalyzer:
    def __init__(self, package_name):
        self.package_name = package_name
        self.device = None
        self.session = None
        self.script = None
        self.findings = []
    
    def connect_device(self):
        """连接到设备"""
        try:
            self.device = frida.get_usb_device()
            print(f"[+] Connected to device: {self.device}")
            return True
        except Exception as e:
            print(f"[-] Failed to connect: {e}")
            return False
    
    def start_analysis(self):
        """开始安全分析"""
        if not self.connect_device():
            return False
        
        try:
            # 启动应用
            pid = self.device.spawn([self.package_name])
            self.session = self.device.attach(pid)
            
            # 加载分析脚本
            script_content = self.get_security_analysis_script()
            self.script = self.session.create_script(script_content)
            self.script.on('message', self.on_message)
            self.script.load()
            
            # 恢复应用执行
            self.device.resume(pid)
            
            print(f"[+] Security analysis started for {self.package_name}")
            return True
            
        except Exception as e:
            print(f"[-] Failed to start analysis: {e}")
            return False
    
    def on_message(self, message, data):
        """处理脚本消息"""
        if message['type'] == 'send':
            payload = message['payload']
            
            if payload.get('type') == 'security_finding':
                self.findings.append(payload)
                self.print_finding(payload)
            else:
                print(f"[Info] {payload}")
        elif message['type'] == 'error':
            print(f"[Error] {message['stack']}")
    
    def print_finding(self, finding):
        """打印安全发现"""
        severity = finding.get('severity', 'INFO')
        category = finding.get('category', 'UNKNOWN')
        description = finding.get('description', '')
        details = finding.get('details', {})
        
        print(f"\n[{severity}] {category}")
        print(f"Description: {description}")
        
        for key, value in details.items():
            print(f"  {key}: {value}")
    
    def get_security_analysis_script(self):
        """获取安全分析脚本"""
        return """
        Java.perform(function() {
            console.log("[+] Security analysis script loaded");
            
            // 1. 检查调试检测
            checkAntiDebugging();
            
            // 2. 检查根检测
            checkRootDetection();
            
            // 3. 检查SSL Pinning
            checkSSLPinning();
            
            // 4. 检查敏感数据存储
            checkSensitiveDataStorage();
            
            // 5. 检查加密实现
            checkCryptographicImplementation();
            
            // 6. 检查权限使用
            checkPermissionUsage();
        });
        
        function checkAntiDebugging() {
            try {
                var Debug = Java.use("android.os.Debug");
                
                Debug.isDebuggerConnected.implementation = function() {
                    var result = this.isDebuggerConnected();
                    
                    send({
                        type: 'security_finding',
                        severity: 'MEDIUM',
                        category: 'Anti-Debugging',
                        description: 'Application checks for debugger connection',
                        details: {
                            'method': 'Debug.isDebuggerConnected()',
                            'result': result
                        }
                    });
                    
                    return result;
                };
                
            } catch (e) {
                console.log("[-] Failed to check anti-debugging: " + e);
            }
        }
        
        function checkRootDetection() {
            try {
                var File = Java.use("java.io.File");
                
                File.exists.implementation = function() {
                    var result = this.exists();
                    var path = this.getAbsolutePath();
                    
                    // 检查常见的 root 检测路径
                    var rootPaths = [
                        "/system/app/Superuser.apk",
                        "/sbin/su",
                        "/system/bin/su",
                        "/system/xbin/su",
                        "/data/local/xbin/su",
                        "/data/local/bin/su",
                        "/system/sd/xbin/su",
                        "/system/bin/failsafe/su",
                        "/data/local/su"
                    ];
                    
                    if (rootPaths.indexOf(path) !== -1) {
                        send({
                            type: 'security_finding',
                            severity: 'HIGH',
                            category: 'Root Detection',
                            description: 'Application checks for root indicators',
                            details: {
                                'path': path,
                                'exists': result
                            }
                        });
                    }
                    
                    return result;
                };
                
            } catch (e) {
                console.log("[-] Failed to check root detection: " + e);
            }
        }
        
        function checkSSLPinning() {
            try {
                var CertificatePinner = Java.use("okhttp3.CertificatePinner");
                
                CertificatePinner.check.implementation = function(hostname, peerCertificates) {
                    send({
                        type: 'security_finding',
                        severity: 'INFO',
                        category: 'SSL Pinning',
                        description: 'Application implements SSL certificate pinning',
                        details: {
                            'hostname': hostname,
                            'certificates': peerCertificates.length
                        }
                    });
                    
                    return this.check(hostname, peerCertificates);
                };
                
            } catch (e) {
                // SSL Pinning 可能未实现
            }
        }
        
        function checkSensitiveDataStorage() {
            try {
                var SharedPreferences = Java.use("android.content.SharedPreferences");
                var Editor = Java.use("android.content.SharedPreferences$Editor");
                
                Editor.putString.implementation = function(key, value) {
                    // 检查敏感数据
                    var sensitiveKeywords = ['password', 'token', 'key', 'secret', 'pin'];
                    var isSensitive = sensitiveKeywords.some(keyword => 
                        key.toLowerCase().includes(keyword) || 
                        value.toLowerCase().includes(keyword)
                    );
                    
                    if (isSensitive) {
                        send({
                            type: 'security_finding',
                            severity: 'HIGH',
                            category: 'Sensitive Data Storage',
                            description: 'Sensitive data stored in SharedPreferences',
                            details: {
                                'key': key,
                                'value_length': value.length
                            }
                        });
                    }
                    
                    return this.putString(key, value);
                };
                
            } catch (e) {
                console.log("[-] Failed to check sensitive data storage: " + e);
            }
        }
        
        function checkCryptographicImplementation() {
            try {
                var Cipher = Java.use("javax.crypto.Cipher");
                
                Cipher.getInstance.overload('java.lang.String').implementation = function(transformation) {
                    var weakAlgorithms = ['DES', 'RC4', 'MD5'];
                    var isWeak = weakAlgorithms.some(alg => transformation.includes(alg));
                    
                    if (isWeak) {
                        send({
                            type: 'security_finding',
                            severity: 'HIGH',
                            category: 'Weak Cryptography',
                            description: 'Application uses weak cryptographic algorithm',
                            details: {
                                'algorithm': transformation
                            }
                        });
                    }
                    
                    return this.getInstance(transformation);
                };
                
            } catch (e) {
                console.log("[-] Failed to check cryptographic implementation: " + e);
            }
        }
        
        function checkPermissionUsage() {
            try {
                var ContextWrapper = Java.use("android.content.ContextWrapper");
                
                ContextWrapper.checkSelfPermission.implementation = function(permission) {
                    var result = this.checkSelfPermission(permission);
                    
                    var sensitivePermissions = [
                        'android.permission.ACCESS_FINE_LOCATION',
                        'android.permission.CAMERA',
                        'android.permission.RECORD_AUDIO',
                        'android.permission.READ_CONTACTS',
                        'android.permission.READ_SMS'
                    ];
                    
                    if (sensitivePermissions.includes(permission)) {
                        send({
                            type: 'security_finding',
                            severity: 'MEDIUM',
                            category: 'Permission Usage',
                            description: 'Application requests sensitive permission',
                            details: {
                                'permission': permission,
                                'granted': result === 0
                            }
                        });
                    }
                    
                    return result;
                };
                
            } catch (e) {
                console.log("[-] Failed to check permission usage: " + e);
            }
        }
        """
    
    def generate_report(self):
        """生成安全分析报告"""
        report = {
            'package_name': self.package_name,
            'analysis_time': time.strftime('%Y-%m-%d %H:%M:%S'),
            'total_findings': len(self.findings),
            'findings': self.findings
        }
        
        # 按严重程度分类
        severity_counts = {}
        for finding in self.findings:
            severity = finding.get('severity', 'UNKNOWN')
            severity_counts[severity] = severity_counts.get(severity, 0) + 1
        
        report['severity_summary'] = severity_counts
        
        # 保存报告
        report_file = f"security_report_{self.package_name}_{int(time.time())}.json"
        with open(report_file, 'w') as f:
            json.dump(report, f, indent=2)
        
        print(f"\n[+] Security analysis report saved to: {report_file}")
        print(f"[+] Total findings: {len(self.findings)}")
        
        for severity, count in severity_counts.items():
            print(f"  {severity}: {count}")
    
    def cleanup(self):
        """清理资源"""
        if self.script:
            self.script.unload()
        if self.session:
            self.session.detach()

# 使用示例
def main():
    if len(sys.argv) != 2:
        print("Usage: python security_analysis.py <package_name>")
        return
    
    package_name = sys.argv[1]
    analyzer = SecurityAnalyzer(package_name)
    
    if analyzer.start_analysis():
        print("[+] Press Enter to generate report and exit")
        input()
        
        analyzer.generate_report()
    
    analyzer.cleanup()

if __name__ == "__main__":
    main()

总结

Frida 动态分析框架入门要点:

🎯 核心概念

  1. 动态插桩:运行时代码注入和分析
  2. 跨平台支持:支持多种操作系统和架构
  3. JavaScript API:使用 JavaScript 编写分析脚本
  4. 实时交互:动态修改应用行为和数据

✅ 主要功能

  • Java 和 Native 代码 Hook
  • 内存读写和搜索
  • 函数调用跟踪
  • 加密算法分析
  • 网络通信监控

🚀 应用场景

  • 应用安全分析和漏洞发现
  • 逆向工程和协议分析
  • 恶意软件分析
  • API 调用监控
  • 性能分析和调试

💡 最佳实践

  • 合理使用 Hook 避免性能影响
  • 详细的日志记录和错误处理
  • 模块化脚本设计
  • 安全和合法的使用方式

掌握 Frida 框架,开启动态分析的强大能力!


Frida 是现代应用安全分析的重要工具,使用时需要遵守法律法规和道德规范。