安卓逆向(Bundle)
android.os.Bundle
是 Android 中一个非常常用的类,用于在不同组件之间传递数据。你可以把它想象成一个容器,它可以存储各种数据(如字符串、整数、布尔值等),并且可以通过键(key)来访问这些数据。
作用
Bundle
主要用于以下几种场景:
- 传递数据到另一个 Activity 或 Fragment
- 保存和恢复应用的状态
基本示例
1. Activity 之间传递数据
如果你要从一个 Activity
向另一个 Activity
传递数据,通常会用到 Intent
和 Bundle
。
在 Activity
A 中创建并传递数据:
Intent intent = new Intent(ActivityA.this, ActivityB.class);
// 创建一个 Bundle
Bundle bundle = new Bundle();
bundle.putString("key", "Hello from Activity A");
bundle.putInt("number", 100);
// 把 Bundle 添加到 Intent 中
intent.putExtras(bundle);
// 启动 ActivityB
startActivity(intent);
在 Activity
B 中获取数据:
// 从 Intent 获取 Bundle
Bundle bundle = getIntent().getExtras();
if (bundle != null) {
String message = bundle.getString("key");
int number = bundle.getInt("number");
// 使用获取到的数据
}
ActivityA.java
示例:
package com.example.myapp;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
public class ActivityA extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_a);
// 启动 ActivityB
Intent intent = new Intent(ActivityA.this, ActivityB.class);
startActivity(intent);
}
}
1. 编写 Frida 脚本
假设你要 hook MainActivity
中的 onCreate()
方法,并打印出 Bundle
中的内容:
Java.perform(function () {
// 获取 MainActivity 类
var MainActivity = Java.use('com.example.app.MainActivity');
// Hook onCreate 方法,捕捉传入的 Bundle
MainActivity.onCreate.overload('android.os.Bundle').implementation = function (bundle) {
console.log('onCreate called');
// 打印 Bundle 中的所有键值对
if (bundle != null) {
var keys = bundle.keySet(); // 获取所有的键
var iterator = keys.iterator();
while (iterator.hasNext()) {
var key = iterator.next();
var value = bundle.get(key); // 获取每个键对应的值
console.log('Key: ' + key + ', Value: ' + value);
}
}
// 调用原始的 onCreate 方法
this.onCreate(bundle);
};
});
bundle.keySet()
方法
- 作用:返回
Bundle
中所有键的集合(即数据的字段名),这个集合是一个Set<String>
。 - 返回类型:
Set<String>
,表示Bundle
中的所有键。 - 用法:你可以通过
keySet()
获取Bundle
中的所有键,然后逐一访问每个键对应的值。
假设有一个 Bundle
,存储了多个键值对:
Bundle bundle = new Bundle();
bundle.putString("name", "John");
bundle.putInt("age", 25);
bundle.putBoolean("isStudent", true);
你可以使用 keySet()
来获取所有的键:
Set<String> keys = bundle.keySet();
for (String key : keys) {
Log.d("Bundle", "Key: " + key + ", Value: " + bundle.get(key));
}
这段代码会输出:
Key: name, Value: John
Key: age, Value: 25
Key: isStudent, Value: true
追踪数据流向:Activity A 到 Activity B
当 Activity A
向 Activity B
传递数据时,通常会使用 Intent
来启动 Activity B
。你可以通过 hook Activity A
启动 Activity B
时传递的 Intent
来追踪数据。
假设在 Activity A
中,你使用如下代码传递数据:
Intent intent = new Intent(ActivityA.this, ActivityB.class);
intent.putExtra("username", "john_doe");
startActivity(intent);
使用 Frida hook Intent.putExtra()
和 Intent.getExtras()
方法后,Frida 会显示 username
和它的值 john_doe
。
检查 Activity
启动过程
你可以在 Activity
的生命周期中捕获 Intent
数据,例如在 onCreate()
或 onNewIntent()
中。通过 Frida 你可以 hook 这些生命周期方法,并打印出 Intent
的内容。
Java.perform(function() {
var Activity = Java.use("android.app.Activity");
// Hook onCreate 方法
Activity.onCreate.overload('android.os.Bundle').implementation = function(savedInstanceState) {
var intent = this.getIntent(); // 获取启动当前 Activity 的 Intent
var extras = intent.getExtras();
if (extras != null) {
var keys = extras.keySet();
keys.forEach(function(key) {
var value = extras.get(key);
console.log("[+] onCreate - key: " + key + ", value: " + value);
});
}
this.onCreate(savedInstanceState); // 调用原始方法
};
});