云计算百科
云计算领域专业知识百科平台

第十三节_Android_APP_目录结构

第十三节 Android APP 目录结构

(第1章 安卓逆向概论)

学习目标

学完本节,希望你能够:搞清 APP 目录结构,尤其是 /data/data/包名 下都有啥;会 SharedPreferences、SQLite、内部/外部存储;知道 APK 安装后文件咋分布,能备份、迁移、逆向;会提取 APP 数据做逆向和调试。


一、APP 安装后目录长啥样?

Android APP 安装后,其数据主要存放在 /data/data/<package_name>/ 目录下(需 Root 访问)。

查看所有已安装 APP 的数据目录

adb shell ls /data/data/

示例:某 APP 的目录结构

/data/data/com.example.app/
├── cache/ # 缓存文件(临时数据)
├── code_cache/ # ART 编译缓存
├── databases/ # SQLite 数据库存储目录
│ ├── user.db # 主要数据库文件
│ ├── user.db-shm # SQLite 共享内存文件
│ ├── user.db-wal # SQLite WAL 日志文件
├── files/ # 应用存储的文件(默认目录)
│ ├── logs/ # 日志文件
│ ├── config.json # 配置文件
├── shared_prefs/ # SharedPreferences(XML 格式存储)
│ ├── settings.xml # APP 设置存储
│ ├── user_data.xml # 用户数据
├── lib/ # Native C/C++ so 库
│ ├── libnative.so # 本地共享库
├── app_webview/ # WebView 存储数据
├── app_flutter/ # Flutter APP 资源
└── cache/ # 临时缓存文件

查看特定 APP 的目录

adb shell ls -l /data/data/com.example.app/



二、各目录在干啥?

目录作用存储方式是否可访问
cache/ 临时缓存数据 文件 可读写(应用内)
code_cache/ ART 编译缓存 OAT 文件 🚫 仅 Root 访问
databases/ APP 的 SQLite 数据库 SQLite3 🚫 仅 Root 访问
files/ APP 存储的文件 普通文件 可读写(应用内)
shared_prefs/ 共享存储,存储应用设置 XML 🚫 仅 Root 访问
lib/ 存储 Native .so 库 ELF 文件 🚫 仅 Root 访问
app_webview/ WebView 本地存储 Cache 🚫 仅 Root 访问
cache/ 临时缓存 Cache 可读写(应用内)

查看数据库文件

adb shell ls /data/data/com.example.app/databases/

查看 SharedPreferences

adb shell cat /data/data/com.example.app/shared_prefs/settings.xml



三、APP 咋存数据?

1. 内部存储(Internal Storage)

APP 私有存储,其他 APP 不能访问(无 Root 权限)。

File file = new File(getFilesDir(), "config.json");

查看 APP 内部存储

adb shell run-as com.example.app ls -l /data/data/com.example.app/files/


2. 外部存储(External Storage)

可被其他 APP 访问(需要权限 WRITE_EXTERNAL_STORAGE)。

File file = new File(Environment.getExternalStorageDirectory(), "myfile.txt");

查看外部存储文件

adb shell ls -l /sdcard/Android/data/com.example.app/


3. SharedPreferences(轻量级存储)

存储简单的键值对数据(XML 格式)。

SharedPreferences prefs = getSharedPreferences("settings", MODE_PRIVATE);
prefs.edit().putString("username", "admin").apply();

查看 SharedPreferences

adb shell cat /data/data/com.example.app/shared_prefs/settings.xml


4. SQLite 数据库

存储结构化数据

SQLiteDatabase db = openOrCreateDatabase("user.db", MODE_PRIVATE, null);
db.execSQL("CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY, name TEXT)");

Dump SQLite 数据库

adb shell "sqlite3 /data/data/com.example.app/databases/user.db 'SELECT * FROM users;'"



四、逆向里咋看 APP 目录?

1. 提取 APK 资源

adb pull /data/app/com.example.app/base.apk .
apktool d base.apk -o output/

修改 AndroidManifest.xml 以查看文件存储权限

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

重新打包:

apktool b output -o modded.apk
jarsigner -verbose -keystore my.keystore modded.apk alias_name
adb install modded.apk


2. 获取数据库数据

Dump SQLite 数据库

adb shell "sqlite3 /data/data/com.example.app/databases/user.db .dump"

复制数据库到本地

adb pull /data/data/com.example.app/databases/user.db .
sqlite3 user.db


3. Hook SharedPreferences

使用 Frida Hook 读取 SharedPreferences

Java.perform(function() {
var SharedPreferences = Java.use("android.app.SharedPreferencesImpl");
SharedPreferences.getString.implementation = function(key, defValue) {
console.log("Hooked SharedPreferences: " + key);
return this.getString(key, defValue);
};
});

执行:

frida -U -n com.example.app -e "…"


4. 拦截文件存取

使用 Xposed Hook open 读取 config.json

findAndHookMethod("java.io.FileInputStream", "open", String.class, new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) {
Log.d("Xposed", "File opened: " + param.args[0]);
}
});



动手练一练

  • 查询某应用的存储路径
  • adb shell ls -l /data/data/com.example.app/

  • 提取 SQLite 数据
  • adb pull /data/data/com.example.app/databases/user.db .
    sqlite3 user.db

  • 修改 SharedPreferences
  • adb shell cat /data/data/com.example.app/shared_prefs/settings.xml
    adb shell "echo '<string name=\\"is_premium\\">true</string>' >> /data/data/com.example.app/shared_prefs/settings.xml"

  • Hook 文件访问
  • Java.perform(function() {
    var File = Java.use("java.io.File");
    File.getAbsolutePath.implementation = function() {
    console.log("File Accessed: " + this.getAbsolutePath());
    return this.getAbsolutePath();
    };
    });


    本节小结

    你只要记住这几条就行:APP 数据在 /data/data/包名/ 下,有 cache、databases、shared_prefs、files、lib 等;SharedPreferences 是 XML,SQLite 在 databases;需 Root 或 run-as 才能读;逆向可 pull 数据库、改 shared_prefs、Hook 读写。


    本节思考与练习

  • 概念:内部存储和外部存储有啥区别?shared_prefs 和 databases 各存啥?
  • 动手:用 adb shell run-as 包名 ls 或 Root 下 ls 看某 APP 的目录。
  • 动手:pull 某 APP 的 shared_prefs 或 databases,用 sqlite3 查表。
  • 动手:用 Frida Hook SharedPreferences 的 get,打印 key。
  • 下一节预告:下一节讲 APK 是如何加载的(第十四节),把 DEX 加载、OAT、ClassLoader 讲清楚。

    赞(0)
    未经允许不得转载:网硕互联帮助中心 » 第十三节_Android_APP_目录结构
    分享到: 更多 (0)

    评论 抢沙发

    评论前必须登录!