Broadcast Receivers
A BroadcastReceiver is a component designed to respond to broadcasted messages (intents, yes they are also intent) from the Android system or other applications. It does not have a UI and operates in the background.
Characteristics of BroadcastReceivers:
Event-driven: Listens for specific events or broadcasts.
No UI: Does not provide a user interface.
Passive: Reacts to events by executing code (e.g., starting a service, sending notifications).
Trigger Background Actions: Often used to perform small, quick tasks in response to system events.
Examples of BroadcastReceiver Usage:
Responding to a system boot (
BOOT_COMPLETED
).Reacting to a network change (
CONNECTIVITY_CHANGE
).Receiving a custom broadcast from another app or component.
Unlike Activity , which uses onCreate when intitialized. Broadcast uses onReceive when a broadcast is received.
Similar to Activity, we are more interested in Broadcast which are exported. e.g
Key Components
<receiver>
Tag:Declares a BroadcastReceiver class (
SPAReceiver
in this case) to handle broadcast intents.android:name
: Specifies the fully qualified name of the BroadcastReceiver class.android:exported
: Indicates whether this BroadcastReceiver can receive broadcasts from other applications.true
: Allows broadcasts from external apps or components.false
: Restricts the broadcasts to within the app.
<intent-filter>
:Defines the types of intents the BroadcastReceiver should respond to.
The receiver will only trigger when the intent matches an action specified in the
<intent-filter>
.
<action>
:Specifies the action of the intent that the BroadcastReceiver listens for.
In this case, the action is
de.danoeh.antennapdsp.intent.SP_APPS_QUERY_FEEDS_RESPONSE
. Any intent with this action will trigger theSPAReceiver
.
Triggering the BroadcastReceiver:
When a broadcast is sent with the action
de.danoeh.antennapdsp.intent.SP_APPS_QUERY_FEEDS_RESPONSE
, by system or any other app, the Android system will look for a matching BroadcastReceiver.Since the
SPAReceiver
is registered for this action in the manifest, itsonReceive()
method will be called.
ADB can also be used for sending broadcast
Dynamic Broadcase Receiver
Unlike Activities which is always present in AndroidManifest.xml file. Broadcat Recivers can be created and destroyed dynamically and not necessary be present in manifest file.
Utilizing registerReceiver
& unregisterReceiver
function
android internally also uses these functions, but we are more interested in recivers created by our apps.
e.g
registerReceiver
:This method dynamically registers a BroadcastReceiver at runtime.
It takes two parameters:
The receiver instance (
this.headsetDisconnected
in this case).An
IntentFilter
object that specifies which actions the receiver should listen for.
this.headsetDisconnected
:Refers to an instance of a
BroadcastReceiver
defined elsewhere in the class.This receiver will handle the broadcast when a headset is plugged in or unplugged.
new IntentFilter("android.intent.action.HEADSET_PLUG")
:Creates an
IntentFilter
for the actionandroid.intent.action.HEADSET_PLUG
.This action is broadcasted by the system when a headset is plugged into or unplugged from the device
Code that handles this broadcast by system is defined as following
where onReceive function executes to handle broadcasts sent by system when headphone lugged or unplugged.
an custom app to send a intent to this broadcast reciver
from android 8 we can only send explicit broadast intents
read more : https://developer.android.com/develop/background-work/background-tasks/broadcasts/broadcast-exceptions
If we expect some result back from broadcast reciver then we can use to handle response
There exist several broadcast actions that are used by the system - obviously regular apps are not allowed to send them. But that doesn't mean the receivers that handle these are properly protected.
Which means broadcast recivers can be launched anyway, if no intent actions are defined in broadcast then what reciver does is upto them.
Hijack Broadcast
you may wanna hijack some implicit broadcast calls from app. It can be done
create a receiver class to handle onRecive functions and send rsult back
As discussed earlier implicit broadcasts are not supported in newer versions. We will have to dynamically register our broadcast. In your launcher activity(Mainactivity for example) create a broadcast receiver of particular action you want to hijack e.g.
Now when a app try to broadcast a intent of action io.hextree.broadcast.FREE_FLAG
our app can handle it.
But for this to work our attacker app should be running in background. This way system doesn't have to wake our app and implicit intents work.
If multiple apps are listening for broadcast then each one get the broadcast.
Just one more concept if multiple recivers are thre, then comes a concept of priority. https://developer.android.com/guide/topics/manifest/intent-filter-element#priority
Higher the number higher the prirority. SO you wanna set your app prirority high.
e.g. report :https://hackerone.com/reports/167481
Widgets Brodcast
You know about widgets tiny utilities from your app that you add to your home screen. These widgets are actually a wrapper around Broadcast receivers. So when you change something in widget it gets brodcasted to your target app.
Which means it also uses onReceive functions. which can be triggered from our app also by sending a brodcast
Here Flag19Widget extends from AppWidgetProvider
which is extended from BrodcastReceiver class.
from our app we can triger this
Note: While sending broadcast intent action should match completely in android 13 otherwise it wont open target class. However in android 14 you can send the broadcast but if its valid or not depends on class itself, how it verifies that. We discussed this earllier also.
More read:
The AppWidgetProvider
is actually a wrapper around BroadcastReceiver
to update the widget data in the background. It can also handle interactions with the widget such as button presses. But because the widget is running inside the home screen, broadcast PendingIntents
are used to handle the button presses.
Widgets, in Android, often act as "remote views" — meaning they can display content and allow user interactions, but they don't have the same privileges as regular app components (like activities or services). Specifically, widgets cannot just initiate actions directly using a normal Intent
because:
Android enforces a security model where it does not allow arbitrary intents to be sent from a widget to start activities, services, or even broadcast intents without proper validation and authorization.
Widgets must use
PendingIntent
because they need to request the system to execute the action on behalf of the app, at a later time, in a secure manner.PendingIntent
ensures that the system will only execute the action if it is from a valid, authorized source (your app).
Also from liveoverlfow sir:
There exists a problem triggering activities from background broadcast receivers. In many cases android does not allow to open the activity. There are two things you can try:
open the app yourself right afterwards, maybe the OS will deliver the background activity
quit the target app, open the target app and immediatly execute the attack. because the target app is new and active the background broadcast receiver might be allowed to startActivity.
which can be explained
In recent Android versions, security and battery optimization features have become stricter, making it harder to launch activities directly from background services or broadcast receivers, especially when the app is in the background or not in the foreground.
Why is it Difficult to Start Activities from Background Broadcast Receivers?
In recent versions of Android (starting with Android 8.0 Oreo, API 26), Android introduced Background Execution Limits. These limits restrict the ability to start certain components (such as Activity
, Service
, and BroadcastReceiver
) while the app is not in the foreground. This is part of the Doze Mode and App Standby features, which are designed to save battery and reduce resource consumption for apps that are running in the background.
When an activity is started from a background context (like a broadcast receiver or service), especially when the app is not actively running or in the foreground, Android might prevent the activity from being launched to avoid disruptions to the user experience.
The Problem with Triggering Activities from Broadcast Receivers
Activity Launch Restrictions: Android's newer versions might not allow an activity to be launched from a background broadcast receiver. For example, when an app is in the background, the OS may restrict the
startActivity()
call for security and usability reasons.Security Concerns: Launching activities from the background might confuse users or lead to unwanted UI interruptions, which Android tries to avoid.
These behaviors are part of Android's attempts to protect the user experience and prevent potentially intrusive behavior from apps running in the background.
Notification Broadcast
In android notifications can be easily created using the notification builder. Inside of notifications you can also add button actions by preparing a PendingIntent
. The reason for that is because the notification is again handled by a different app.
So your pendingintent can be handles by your target app. Which is actually a broadcast from notification to your app.
More side learning:
When you dynamically register a receiver in your app, it's important to note that the receiver is only active when your app is running. This might be why you're able to send implicit broadcasts to it but not explicit ones.
Here's a quick rundown:
Implicit Broadcasts: These are system-wide broadcasts that any app can listen to. Since your receiver is dynamically registered and active while your app is running, it can receive these implicit broadcasts.
Explicit Broadcasts: These are targeted specifically at one receiver. If your receiver is not declared in the manifest, it won't be able to receive explicit broadcasts from other apps.
If you'd like your app to receive explicit broadcasts as well, you should declare the receiver in the manifest with android:exported="true"
. This will allow other apps to target your receiver with explicit broadcasts. e.g.
in this target app broadcast reciver is registered for incoming broadcast from notification
Now this can only be reached by implicit intents as its not declared in manifest file and not exported. So if target app is running and activity is launched this receiver can be called from your app too.
also after registering receiver from notification bar it sends a broadcast of implicit intent.
This can be hijacked from our app and send the broadcast intent forward to receiver. by modifying it.
in our launcher class we register our broadcast receiber
and from HijackReceiver class we receive the broadcast and modify it and send it back
Since our original intent has filter of "GIVE_FLAG" so on broadcast it will send it to register broadcats receiver of our target app only. Also we have unregistered ourselves from listener so we won't recive any such broadcast in future.
Last updated