Broadcast Theft¶
Intercepting broadcast intents meant for other apps. Android's broadcast system sends messages to all registered receivers. If a broadcast carries sensitive data and isn't properly protected, any app can register a receiver and read it.
Requirements
| Requirement | Details |
|---|---|
| Permission | Varies. Some broadcasts require permissions (e.g., RECEIVE_SMS). Others are unprotected. |
| Condition | Target broadcast is not permission-protected or is ordered |
How Broadcasts Work¶
An app sends a broadcast, and all registered BroadcastReceiver components matching the intent filter receive it. Two types:
Normal broadcasts (sendBroadcast()): delivered to all receivers simultaneously. No ordering, no priority, no ability to cancel.
Ordered broadcasts (sendOrderedBroadcast()): delivered sequentially by priority. Higher-priority receivers run first and can modify or cancel the broadcast before lower-priority receivers see it.
Attack Patterns¶
SMS Interception¶
The SMS_RECEIVED broadcast is ordered. Malware registers a receiver with maximum priority:
<receiver android:name=".SmsReceiver" android:exported="true">
<intent-filter android:priority="999">
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
The malware receives the SMS first, extracts the OTP, and can call abortBroadcast() to prevent the default SMS app from showing it. The user never sees the message.
On Android 4.4+, only the default SMS app can abort SMS broadcasts, but malware can still read the content and forward it without aborting.
Sticky Broadcast Leakage¶
Sticky broadcasts (deprecated in API 21) persist after being sent. Any app calling registerReceiver() with the matching filter receives the last sticky broadcast. This was used to leak battery status, charging state, and other system info.
ACTION_BATTERY_CHANGED is still a sticky broadcast and leaks detailed battery information without any permission.
Custom Broadcast Interception¶
Apps that define custom broadcast actions without permission protection are vulnerable:
Any app with a matching receiver sees this:
<receiver android:name=".TokenStealer" android:exported="true">
<intent-filter>
<action android:name="com.myapp.USER_LOGGED_IN" />
</intent-filter>
</receiver>
Boot Broadcast Race¶
Multiple apps receiving BOOT_COMPLETED race to start. Malware that starts first can interfere with security software that starts later.
Security-Relevant System Broadcasts¶
| Broadcast | Data Exposed | Permission Required |
|---|---|---|
SMS_RECEIVED |
SMS content, sender | RECEIVE_SMS |
WAP_PUSH_RECEIVED |
MMS push data | RECEIVE_WAP_PUSH |
NEW_OUTGOING_CALL |
Dialed number | PROCESS_OUTGOING_CALLS |
PHONE_STATE |
Call state, phone number | READ_PHONE_STATE |
BATTERY_CHANGED |
Battery level, charging, temperature | None |
CONNECTIVITY_CHANGE |
Network state changes | None (deprecated API 28) |
PACKAGE_ADDED/REMOVED |
Package name of installed/removed app | None |
BOOT_COMPLETED |
Device booted | RECEIVE_BOOT_COMPLETED |
Android Mitigations¶
| Version | Mitigation | Bypass |
|---|---|---|
| Android 3.1 (API 12) | Apps in stopped state don't receive broadcasts | Must be launched once; malware is typically already running |
| Android 4.4 (API 19) | Only default SMS app can abort SMS_RECEIVED |
Malware can still read SMS content without aborting |
| Android 5.0 (API 21) | Sticky broadcasts deprecated | Legacy sticky broadcasts like ACTION_BATTERY_CHANGED still work |
| Android 8.0 (API 26) | Implicit broadcast restrictions; most not delivered to manifest receivers | Exempt broadcasts (BOOT_COMPLETED, SMS_RECEIVED) still delivered; dynamic registration still works |
| Android 14 (API 34) | Context-registered receivers must declare RECEIVER_EXPORTED or RECEIVER_NOT_EXPORTED |
Malware explicitly sets RECEIVER_EXPORTED |
Families Using This Technique¶
SMS and broadcast interception is used by virtually every banking trojan for OTP theft. This table covers the primary use case for each family.
| Family | Broadcast Type | Purpose |
|---|---|---|
| Cerberus | SMS_RECEIVED | 2FA OTP interception |
| Anubis | SMS_RECEIVED | OTP theft, SMS forwarding to C2 |
| Hook | SMS_RECEIVED | OTP interception during ATS |
| Ermac | SMS_RECEIVED | 2FA bypass |
| GodFather | SMS_RECEIVED, PHONE_STATE | OTP theft, call state monitoring |
| Hydra | SMS_RECEIVED | OTP interception |
| Octo | SMS_RECEIVED | OTP interception during remote access |
| Medusa | SMS_RECEIVED | 2FA bypass |
| Xenomorph | SMS_RECEIVED | OTP capture for ATS engine |
| Anatsa | SMS_RECEIVED | OTP theft during automated transfers |
| FluBot | SMS_RECEIVED | OTP theft, SMS worm propagation |
| Joker | SMS_RECEIVED | Premium subscription OTP confirmation |
| GriftHorse | SMS_RECEIVED | Premium SMS confirmation interception |
| Harly | SMS_RECEIVED | Subscription confirmation codes |
| SpyNote | SMS_RECEIVED, PHONE_STATE | Full SMS/call surveillance |
| Rafel RAT | SMS_RECEIVED | SMS interception, ransomware unlock codes |
| TrickMo | SMS_RECEIVED | OTP theft, originally TrickBot 2FA bypass |
| Vultur | SMS_RECEIVED | OTP interception |
| SharkBot | SMS_RECEIVED | OTP capture for ATS |
| Chameleon | SMS_RECEIVED | 2FA bypass after biometric prompt disable |
| Mamont | SMS_RECEIVED | Notification and SMS interception |
| TsarBot | SMS_RECEIVED | OTP capture, 750+ target apps |
| Antidot | SMS_RECEIVED | 2FA interception |
| Crocodilus | SMS_RECEIVED | OTP theft during DTO |
| Copybara | SMS_RECEIVED | OTP interception |
| Fakecalls | NEW_OUTGOING_CALL | Call interception and redirection |
| MoqHao | SMS_RECEIVED, PACKAGE_ADDED | SMS theft, app install monitoring |
| Alien | SMS_RECEIVED | Notification sniffing for 2FA codes |
| BRATA | SMS_RECEIVED | OTP theft before factory reset |
| BankBot | SMS_RECEIVED | Early SMS-based OTP theft |
| Albiriox | SMS_RECEIVED | OTP interception |
| FireScam | SMS_RECEIVED | Notification and SMS interception across all apps |
| DeVixor | SMS_RECEIVED | OTP interception for Iranian banking fraud |
Fakecalls is unique in using NEW_OUTGOING_CALL to intercept outgoing calls to bank numbers and redirect them to attacker-controlled lines with pre-recorded IVR audio.
Detection During Analysis¶
Static Indicators
BroadcastReceiverwith highandroid:priority(especially forSMS_RECEIVED)- Receivers for system broadcasts containing sensitive data
- Custom broadcasts sent with sensitive extras and no permission parameter
sendBroadcast()withoutLocalBroadcastManagerfor internal communication
Dynamic Indicators
- SMS content forwarded to C2 immediately after receipt
abortBroadcast()calls inside SMS receivers (suppressing notifications)- Broadcast receivers triggering network exfiltration on
BOOT_COMPLETED - Multiple apps competing for the same ordered broadcast