- 发布于
Frida 实战案例分析:真实场景下的动态分析应用
- 作者

- 姓名
- 全能波
- GitHub
- @weicracker
Frida 实战案例分析:真实场景下的动态分析应用
本文将通过多个真实案例,展示 Frida 在不同场景下的实际应用,包括移动应用安全分析、API 逆向工程、网络协议分析等。
案例一:移动应用登录绕过
场景描述
某移动应用使用复杂的登录验证机制,包括用户名密码验证、设备指纹检查和服务器端验证。我们需要分析其登录流程并实现绕过。
# login_bypass_analysis.py - 登录绕过分析
import frida
import sys
import json
import time
class LoginBypassAnalyzer:
def __init__(self, package_name):
self.package_name = package_name
self.device = None
self.session = None
self.script = None
self.login_data = {}
def connect_and_spawn(self):
"""连接设备并启动应用"""
try:
self.device = frida.get_usb_device()
pid = self.device.spawn([self.package_name])
self.session = self.device.attach(pid)
# 加载分析脚本
script_content = self.get_login_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"[+] 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') == 'login_attempt':
self.handle_login_attempt(payload)
elif payload.get('type') == 'network_request':
self.handle_network_request(payload)
elif payload.get('type') == 'crypto_operation':
self.handle_crypto_operation(payload)
else:
print(f"[Info] {payload}")
elif message['type'] == 'error':
print(f"[Error] {message['stack']}")
def handle_login_attempt(self, data):
"""处理登录尝试"""
print(f"\n[Login Attempt]")
print(f"Username: {data.get('username', 'N/A')}")
print(f"Password: {'*' * len(data.get('password', ''))}")
print(f"Method: {data.get('method', 'N/A')}")
print(f"Result: {data.get('result', 'N/A')}")
self.login_data['attempts'] = self.login_data.get('attempts', [])
self.login_data['attempts'].append(data)
def handle_network_request(self, data):
"""处理网络请求"""
print(f"\n[Network Request]")
print(f"URL: {data.get('url', 'N/A')}")
print(f"Method: {data.get('method', 'N/A')}")
print(f"Headers: {json.dumps(data.get('headers', {}), indent=2)}")
if data.get('body'):
print(f"Body: {data['body'][:200]}...")
def handle_crypto_operation(self, data):
"""处理加密操作"""
print(f"\n[Crypto Operation]")
print(f"Algorithm: {data.get('algorithm', 'N/A')}")
print(f"Operation: {data.get('operation', 'N/A')}")
print(f"Input Length: {data.get('input_length', 0)}")
print(f"Output Length: {data.get('output_length', 0)}")
def get_login_analysis_script(self):
"""获取登录分析脚本"""
return """
Java.perform(function() {
console.log("[+] Login analysis script loaded");
// 1. Hook 登录相关方法
hookLoginMethods();
// 2. Hook 网络请求
hookNetworkRequests();
// 3. Hook 加密操作
hookCryptographicOperations();
// 4. Hook 设备指纹
hookDeviceFingerprinting();
// 5. Hook 存储操作
hookStorageOperations();
});
function hookLoginMethods() {
try {
// 通用登录方法模式
var loginPatterns = [
"login", "signin", "authenticate", "verify", "check"
];
// 枚举所有类并查找登录相关方法
Java.enumerateLoadedClasses({
onMatch: function(className) {
if (className.indexOf("com.example.app") !== -1) {
try {
var targetClass = Java.use(className);
var methods = targetClass.class.getDeclaredMethods();
for (var i = 0; i < methods.length; i++) {
var method = methods[i];
var methodName = method.getName().toLowerCase();
// 检查是否为登录相关方法
for (var j = 0; j < loginPatterns.length; j++) {
if (methodName.indexOf(loginPatterns[j]) !== -1) {
hookLoginMethod(targetClass, method.getName());
}
}
}
} catch (e) {
// 忽略无法访问的类
}
}
},
onComplete: function() {
console.log("[+] Login method enumeration completed");
}
});
// Hook 常见的登录方法
hookSpecificLoginMethods();
} catch (e) {
console.log("[-] Failed to hook login methods: " + e);
}
}
function hookLoginMethod(targetClass, methodName) {
try {
var overloads = targetClass[methodName].overloads;
for (var i = 0; i < overloads.length; i++) {
overloads[i].implementation = function() {
console.log("[Login] Method called: " + methodName);
// 记录参数
var args = Array.prototype.slice.call(arguments);
var loginData = {
type: 'login_attempt',
method: methodName,
arguments: args.map(function(arg) {
return arg ? arg.toString() : 'null';
})
};
// 尝试提取用户名和密码
for (var j = 0; j < args.length; j++) {
var arg = args[j];
if (arg && typeof arg.toString === 'function') {
var argStr = arg.toString();
if (argStr.indexOf('@') !== -1 || argStr.length > 3) {
if (!loginData.username && argStr.indexOf('@') !== -1) {
loginData.username = argStr;
} else if (!loginData.password && argStr.length >= 6) {
loginData.password = argStr;
}
}
}
}
// 调用原始方法
var result = this[methodName].apply(this, arguments);
loginData.result = result ? result.toString() : 'null';
send(loginData);
// 尝试绕过:如果返回 false,改为返回 true
if (result === false || result === 0) {
console.log("[+] Login bypass: changing result to true");
return true;
}
return result;
};
}
console.log("[+] Hooked login method: " + methodName);
} catch (e) {
console.log("[-] Failed to hook method " + methodName + ": " + e);
}
}
function hookSpecificLoginMethods() {
try {
// Hook 常见的认证类
var authClasses = [
"com.example.app.auth.AuthManager",
"com.example.app.login.LoginManager",
"com.example.app.user.UserManager"
];
authClasses.forEach(function(className) {
try {
var AuthClass = Java.use(className);
// Hook 所有公共方法
var methods = AuthClass.class.getDeclaredMethods();
for (var i = 0; i < methods.length; i++) {
var method = methods[i];
if ((method.getModifiers() & 1) !== 0) { // 公共方法
hookLoginMethod(AuthClass, method.getName());
}
}
} catch (e) {
// 类不存在,继续
}
});
} catch (e) {
console.log("[-] Failed to hook specific login methods: " + e);
}
}
function hookNetworkRequests() {
try {
// Hook OkHttp
var OkHttpClient = Java.use("okhttp3.OkHttpClient");
var Request = Java.use("okhttp3.Request");
OkHttpClient.newCall.implementation = function(request) {
var url = request.url().toString();
var method = request.method();
// 检查是否为登录相关请求
if (url.indexOf("login") !== -1 ||
url.indexOf("auth") !== -1 ||
url.indexOf("signin") !== -1) {
var headers = {};
var headerNames = request.headers().names();
var iterator = headerNames.iterator();
while (iterator.hasNext()) {
var name = iterator.next();
headers[name] = request.headers().get(name);
}
var requestData = {
type: 'network_request',
url: url,
method: method,
headers: headers
};
// 尝试获取请求体
try {
var body = request.body();
if (body) {
// 这里需要更复杂的逻辑来读取请求体
requestData.body = "[Request Body Present]";
}
} catch (e) {
// 无法读取请求体
}
send(requestData);
}
return this.newCall(request);
};
// Hook HttpURLConnection
var HttpURLConnection = Java.use("java.net.HttpURLConnection");
HttpURLConnection.getResponseCode.implementation = function() {
var url = this.getURL().toString();
var responseCode = this.getResponseCode();
if (url.indexOf("login") !== -1 || url.indexOf("auth") !== -1) {
console.log("[Network] Login response: " + responseCode + " for " + url);
// 如果是认证失败,尝试修改为成功
if (responseCode === 401 || responseCode === 403) {
console.log("[+] Network bypass: changing response code to 200");
return 200;
}
}
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) {
var algorithm = this.getAlgorithm();
var result = this.doFinal(input);
send({
type: 'crypto_operation',
algorithm: algorithm,
operation: 'doFinal',
input_length: input.length,
output_length: result.length
});
return result;
};
// Hook MessageDigest
var MessageDigest = Java.use("java.security.MessageDigest");
MessageDigest.digest.overload('[B').implementation = function(input) {
var algorithm = this.getAlgorithm();
var result = this.digest(input);
send({
type: 'crypto_operation',
algorithm: algorithm,
operation: 'digest',
input_length: input.length,
output_length: result.length
});
return result;
};
console.log("[+] Cryptographic operation hooks installed");
} catch (e) {
console.log("[-] Failed to hook cryptographic operations: " + e);
}
}
function hookDeviceFingerprinting() {
try {
// Hook 设备信息获取
var TelephonyManager = Java.use("android.telephony.TelephonyManager");
var Settings = Java.use("android.provider.Settings$Secure");
var Build = Java.use("android.os.Build");
// Hook IMEI 获取
TelephonyManager.getDeviceId.implementation = function() {
console.log("[Device] IMEI requested");
var result = this.getDeviceId();
// 可以返回固定值来绕过设备检查
return result;
};
// Hook Android ID 获取
Settings.getString.implementation = function(resolver, name) {
var result = this.getString(resolver, name);
if (name === "android_id") {
console.log("[Device] Android ID requested: " + result);
}
return result;
};
console.log("[+] Device fingerprinting hooks installed");
} catch (e) {
console.log("[-] Failed to hook device fingerprinting: " + e);
}
}
function hookStorageOperations() {
try {
// Hook SharedPreferences
var SharedPreferences = Java.use("android.content.SharedPreferences");
var Editor = Java.use("android.content.SharedPreferences$Editor");
SharedPreferences.getBoolean.implementation = function(key, defValue) {
var result = this.getBoolean(key, defValue);
// 检查登录状态相关的键
if (key.indexOf("login") !== -1 ||
key.indexOf("auth") !== -1 ||
key.indexOf("logged") !== -1) {
console.log("[Storage] Login state check: " + key + " = " + result);
// 强制返回已登录状态
if (key.indexOf("logged_in") !== -1 || key.indexOf("is_login") !== -1) {
console.log("[+] Storage bypass: forcing login state to true");
return true;
}
}
return result;
};
SharedPreferences.getString.implementation = function(key, defValue) {
var result = this.getString(key, defValue);
if (key.indexOf("token") !== -1 || key.indexOf("session") !== -1) {
console.log("[Storage] Token/Session access: " + key);
}
return result;
};
console.log("[+] Storage operation hooks installed");
} catch (e) {
console.log("[-] Failed to hook storage operations: " + e);
}
}
"""
def generate_bypass_script(self):
"""生成绕过脚本"""
bypass_script = """
Java.perform(function() {
console.log("[+] Login bypass script loaded");
// 基于分析结果的绕过策略
implementLoginBypass();
});
function implementLoginBypass() {
try {
// 1. 强制登录成功
forceLoginSuccess();
// 2. 绕过设备检查
bypassDeviceCheck();
// 3. 修改网络响应
modifyNetworkResponse();
// 4. 修改存储状态
modifyStorageState();
} catch (e) {
console.log("[-] Bypass implementation failed: " + e);
}
}
function forceLoginSuccess() {
// 根据分析结果实现具体的绕过逻辑
console.log("[+] Login bypass strategies implemented");
}
function bypassDeviceCheck() {
// 设备检查绕过
console.log("[+] Device check bypass implemented");
}
function modifyNetworkResponse() {
// 网络响应修改
console.log("[+] Network response modification implemented");
}
function modifyStorageState() {
// 存储状态修改
console.log("[+] Storage state modification implemented");
}
"""
return bypass_script
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 login_bypass_analysis.py <package_name>")
return
package_name = sys.argv[1]
analyzer = LoginBypassAnalyzer(package_name)
if analyzer.connect_and_spawn():
print("[+] Analysis running. Perform login attempts in the app.")
print("[+] Press Enter to generate bypass script and exit")
input()
# 生成绕过脚本
bypass_script = analyzer.generate_bypass_script()
with open(f"bypass_script_{package_name}.js", 'w') as f:
f.write(bypass_script)
print(f"[+] Bypass script saved to bypass_script_{package_name}.js")
analyzer.cleanup()
if __name__ == "__main__":
main()
案例二:API 接口逆向分析
场景描述
某应用使用自定义的 API 协议,包含加密、签名验证等机制。我们需要逆向分析其 API 调用流程和参数构造方法。
// api_reverse_analysis.js - API 逆向分析脚本
Java.perform(function() {
console.log("[+] API reverse analysis script loaded");
// 1. Hook 网络库
hookNetworkLibraries();
// 2. Hook 加密算法
hookEncryptionAlgorithms();
// 3. Hook 签名生成
hookSignatureGeneration();
// 4. Hook JSON 处理
hookJsonProcessing();
// 5. Hook Base64 编码
hookBase64Operations();
});
function hookNetworkLibraries() {
try {
// Hook Retrofit (如果使用)
hookRetrofit();
// Hook Volley (如果使用)
hookVolley();
// Hook 原生 HTTP 客户端
hookNativeHttpClient();
} catch (e) {
console.log("[-] Failed to hook network libraries: " + e);
}
}
function hookRetrofit() {
try {
// 查找 Retrofit 相关类
Java.enumerateLoadedClasses({
onMatch: function(className) {
if (className.indexOf("retrofit") !== -1) {
console.log("[Retrofit] Found class: " + className);
try {
var RetrofitClass = Java.use(className);
// Hook create 方法
if (RetrofitClass.create) {
RetrofitClass.create.implementation = function(service) {
console.log("[Retrofit] Creating service: " + service);
var result = this.create(service);
// Hook 服务方法
hookServiceMethods(result, service);
return result;
};
}
} catch (e) {
// 忽略无法访问的类
}
}
},
onComplete: function() {
console.log("[+] Retrofit enumeration completed");
}
});
} catch (e) {
console.log("[-] Failed to hook Retrofit: " + e);
}
}
function hookServiceMethods(serviceInstance, serviceClass) {
try {
var methods = serviceClass.getDeclaredMethods();
for (var i = 0; i < methods.length; i++) {
var method = methods[i];
var methodName = method.getName();
// Hook API 方法
if (serviceInstance[methodName]) {
serviceInstance[methodName].implementation = function() {
console.log("[API] Calling method: " + methodName);
console.log("[API] Arguments: " + JSON.stringify(Array.prototype.slice.call(arguments)));
var result = this[methodName].apply(this, arguments);
console.log("[API] Result: " + result);
return result;
};
}
}
} catch (e) {
console.log("[-] Failed to hook service methods: " + e);
}
}
function hookVolley() {
try {
var RequestQueue = Java.use("com.android.volley.RequestQueue");
RequestQueue.add.implementation = function(request) {
console.log("[Volley] Adding request: " + request);
// 获取请求详情
try {
var url = request.getUrl();
var method = request.getMethod();
var headers = request.getHeaders();
console.log("[Volley] URL: " + url);
console.log("[Volley] Method: " + method);
console.log("[Volley] Headers: " + JSON.stringify(headers));
// 尝试获取请求体
var body = request.getBody();
if (body) {
var bodyStr = Java.use("java.lang.String").$new(body);
console.log("[Volley] Body: " + bodyStr);
}
} catch (e) {
console.log("[-] Failed to get request details: " + e);
}
return this.add(request);
};
} catch (e) {
console.log("[-] Failed to hook Volley: " + e);
}
}
function hookNativeHttpClient() {
try {
var HttpURLConnection = Java.use("java.net.HttpURLConnection");
// Hook connect 方法
HttpURLConnection.connect.implementation = function() {
var url = this.getURL().toString();
var method = this.getRequestMethod();
console.log("[HTTP] Connecting to: " + url);
console.log("[HTTP] Method: " + method);
// 获取请求头
var headerFields = this.getRequestProperties();
if (headerFields) {
console.log("[HTTP] Request headers:");
var keySet = headerFields.keySet();
var iterator = keySet.iterator();
while (iterator.hasNext()) {
var key = iterator.next();
var values = headerFields.get(key);
console.log(" " + key + ": " + values);
}
}
this.connect();
};
// Hook getInputStream
HttpURLConnection.getInputStream.implementation = function() {
var url = this.getURL().toString();
var responseCode = this.getResponseCode();
console.log("[HTTP] Response from " + url + ": " + responseCode);
var inputStream = this.getInputStream();
// 包装 InputStream 以读取响应内容
return wrapInputStream(inputStream, url);
};
} catch (e) {
console.log("[-] Failed to hook native HTTP client: " + e);
}
}
function wrapInputStream(originalStream, url) {
try {
var InputStreamWrapper = Java.registerClass({
name: 'com.frida.InputStreamWrapper',
superClass: Java.use('java.io.InputStream'),
fields: {
originalStream: 'java.io.InputStream',
buffer: 'java.io.ByteArrayOutputStream'
},
methods: {
$init: {
returnType: 'void',
argumentTypes: ['java.io.InputStream'],
implementation: function(stream) {
this.originalStream.value = stream;
this.buffer.value = Java.use('java.io.ByteArrayOutputStream').$new();
}
},
read: {
returnType: 'int',
argumentTypes: [],
implementation: function() {
var data = this.originalStream.value.read();
if (data !== -1) {
this.buffer.value.write(data);
} else {
// 流结束,打印内容
var content = this.buffer.value.toString();
console.log("[HTTP] Response content from " + url + ":");
console.log(content);
}
return data;
}
}
}
});
return InputStreamWrapper.$new(originalStream);
} catch (e) {
console.log("[-] Failed to wrap InputStream: " + e);
return originalStream;
}
}
function hookEncryptionAlgorithms() {
try {
// Hook AES 加密
var Cipher = Java.use("javax.crypto.Cipher");
Cipher.doFinal.overload('[B').implementation = function(input) {
var algorithm = this.getAlgorithm();
var mode = this.getOpmode();
console.log("[Crypto] Algorithm: " + algorithm);
console.log("[Crypto] Mode: " + (mode === 1 ? "ENCRYPT" : "DECRYPT"));
console.log("[Crypto] Input: " + bytesToHex(input));
var result = this.doFinal(input);
console.log("[Crypto] Output: " + bytesToHex(result));
return result;
};
// Hook 密钥生成
var KeyGenerator = Java.use("javax.crypto.KeyGenerator");
KeyGenerator.generateKey.implementation = function() {
var algorithm = this.getAlgorithm();
console.log("[Crypto] Generating key for: " + algorithm);
var key = this.generateKey();
// 尝试获取密钥内容
try {
var encoded = key.getEncoded();
console.log("[Crypto] Generated key: " + bytesToHex(encoded));
} catch (e) {
console.log("[Crypto] Cannot access key content");
}
return key;
};
} catch (e) {
console.log("[-] Failed to hook encryption algorithms: " + e);
}
}
function hookSignatureGeneration() {
try {
// Hook HMAC 签名
var Mac = Java.use("javax.crypto.Mac");
Mac.doFinal.overload('[B').implementation = function(input) {
var algorithm = this.getAlgorithm();
console.log("[Signature] Algorithm: " + algorithm);
console.log("[Signature] Input: " + bytesToHex(input));
var result = this.doFinal(input);
console.log("[Signature] Signature: " + bytesToHex(result));
return result;
};
// Hook 数字签名
var Signature = Java.use("java.security.Signature");
Signature.sign.implementation = function() {
var algorithm = this.getAlgorithm();
console.log("[DigitalSignature] Algorithm: " + algorithm);
var result = this.sign();
console.log("[DigitalSignature] Signature: " + bytesToHex(result));
return result;
};
} catch (e) {
console.log("[-] Failed to hook signature generation: " + e);
}
}
function hookJsonProcessing() {
try {
// Hook Gson
var Gson = Java.use("com.google.gson.Gson");
Gson.toJson.overload('java.lang.Object').implementation = function(obj) {
var result = this.toJson(obj);
console.log("[JSON] Serializing object to JSON: " + result);
return result;
};
Gson.fromJson.overload('java.lang.String', 'java.lang.Class').implementation = function(json, classOfT) {
console.log("[JSON] Deserializing JSON: " + json);
var result = this.fromJson(json, classOfT);
console.log("[JSON] Deserialized to: " + classOfT.getName());
return result;
};
// Hook JSONObject
var JSONObject = Java.use("org.json.JSONObject");
JSONObject.$init.overload('java.lang.String').implementation = function(json) {
console.log("[JSONObject] Creating from string: " + json);
this.$init(json);
};
JSONObject.toString.implementation = function() {
var result = this.toString();
console.log("[JSONObject] Converting to string: " + result);
return result;
};
} catch (e) {
console.log("[-] Failed to hook JSON processing: " + e);
}
}
function hookBase64Operations() {
try {
var Base64 = Java.use("android.util.Base64");
// Hook encode
Base64.encode.overload('[B', 'int').implementation = function(input, flags) {
console.log("[Base64] Encoding: " + bytesToHex(input));
var result = this.encode(input, flags);
console.log("[Base64] Encoded: " + Java.use("java.lang.String").$new(result));
return result;
};
// Hook decode
Base64.decode.overload('java.lang.String', 'int').implementation = function(str, flags) {
console.log("[Base64] Decoding: " + str);
var result = this.decode(str, flags);
console.log("[Base64] Decoded: " + bytesToHex(result));
return result;
};
} catch (e) {
console.log("[-] Failed to hook Base64 operations: " + 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;
}
// API 重放功能
function replayApiCall(url, method, headers, body) {
Java.perform(function() {
try {
var URL = Java.use("java.net.URL");
var HttpURLConnection = Java.use("java.net.HttpURLConnection");
var urlObj = URL.$new(url);
var connection = urlObj.openConnection();
connection.setRequestMethod(method);
// 设置请求头
for (var key in headers) {
connection.setRequestProperty(key, headers[key]);
}
// 设置请求体
if (body && method !== "GET") {
connection.setDoOutput(true);
var outputStream = connection.getOutputStream();
var bodyBytes = Java.use("java.lang.String").$new(body).getBytes();
outputStream.write(bodyBytes);
outputStream.close();
}
// 发送请求
var responseCode = connection.getResponseCode();
console.log("[Replay] Response code: " + responseCode);
// 读取响应
var inputStream = connection.getInputStream();
var response = readInputStream(inputStream);
console.log("[Replay] Response: " + response);
} catch (e) {
console.log("[-] API replay failed: " + e);
}
});
}
function readInputStream(inputStream) {
var BufferedReader = Java.use("java.io.BufferedReader");
var InputStreamReader = Java.use("java.io.InputStreamReader");
var StringBuilder = Java.use("java.lang.StringBuilder");
var reader = BufferedReader.$new(InputStreamReader.$new(inputStream));
var response = StringBuilder.$new();
var line;
while ((line = reader.readLine()) !== null) {
response.append(line);
}
reader.close();
return response.toString();
}
总结
Frida 实战案例的核心要点:
🎯 登录绕过案例
- 多层分析:登录方法、网络请求、加密操作、存储状态
- 动态绕过:实时修改方法返回值和网络响应
- 设备指纹:绕过设备检查和指纹识别
- 状态管理:修改本地存储的登录状态
✅ API 逆向案例
- 网络库 Hook 和请求拦截
- 加密算法和签名机制分析
- JSON 数据序列化和反序列化
- API 重放和参数构造
🚀 实战技巧
- 系统性的 Hook 策略
- 数据流跟踪和分析
- 实时修改和绕过
- 自动化脚本生成
💡 分析方法
- 从表层到深层的递进分析
- 多角度验证和交叉确认
- 动态调试和静态分析结合
- 完整的攻击链构建
通过实战案例掌握 Frida 的实际应用能力!
实战案例是学习 Frida 最有效的方式,通过真实场景的分析能够快速提升动态分析技能。