Android Services

Exported services are another attack surface in android.

used for long running bakcground tasks.

e.g. Media player in background.

Note:

  • Activity: Runs in the foreground and renders the UI

  • Broadcast Receiver: Runs in the background to execute a minimal task

  • Service: Executes long running tasks in the background

Services are also defined in manifest file. But that services can be protected with specific permission means apps with that permission can only call that service.

<service android:name="io.example.services.MyService"
 android:enabled="true" android:exported="true">
    <intent-filter>
        <action android:name="io.example.START"/>
    </intent-filter>
</service>
<service android:name=".MyJobService" 
 android:permission="android.permission.BIND_JOB_SERVICE"
 android:exported="true">
 </service>

android.permission.BIND_JOB_SERVICEthis permission is only available to system only.

Types of services:

  1. Bindable & non-bindable services

  2. LocalBinder

  3. Message Handler

  4. AIDL definitions

Starting service is similar to sending activity intent or broadcast. We just use startService()or bindService() funcitonto start it.

Receiving app handles our intent with onStartCommand()function

Since latest release for us able to start a service from a target app. The target app must be running in background.

Also since android 11, we need to specifically define in our manifest file that which app's service we want to interact with.

Note: similar to broadcasts, services can't start an activity if the target app is in background. The target app must be in use only then an activity of that app can be launched. It's ui thing so that user don't get disturebed.

There is generally bindable service which is used. So an application can bind with target seervice for exchanging data with that app.

in that bindservice function is used. It is facilitated by android IPC interface. In that function onBindbecomes interesting to us.

After identifying an exposed Service in the android manifest, the next step should be looking at the onBind() method to determine if the service can be bound to or not.

When the onBind() method returns nothing or even throws an exception, then the service definetly cannot be bount to.

There are also services where the onBind() method returns something, but it's only an internally bindable service, thus from our perspective it's a non-bindable service. These kind of services can usually be recognized by naming convention of "LocalBinder".

If app's service can only be bound to from inside the sme app. As an attacker this is essentially non-bindable service. i.e. LocalBinder.

Messenger

This is a wrapper around binder and high level which binds to a service and send and recive message to and from a target service respectively. More: https://developer.android.com/reference/android/os/Messenger

new IncomingHandler(Looper.getMainLooper())

  • IncomingHandler is a custom class extending Handler.

  • Looper.getMainLooper() ensures that the handler runs on the main thread (UI thread) instead of a background thread.

  • This is important because services do not have their own UI thread by default, so handlers must explicitly specify a looper.

new Messenger(...)

  • Messenger wraps the Handler, allowing it to receive Message objects from other components (such as Activities, Services, or even separate apps).

  • It provides a safe way to handle IPC (Inter-Process Communication) without directly dealing with AIDL (Android Interface Definition Language).

handleMessagefunction is overrided to handle incoming message logic from our app.

this message inside handleMessage can contain all kind of data an intent can support.

onBindfunction returns an object of type Messenger which can be binded by other apps.

To interact with boundable service we will use bindService function : https://developer.android.com/reference/android/content/Context#bindService(android.content.Intent,%20android.content.ServiceConnection,%20int)

e.g. 2 in particular condition this service will run success function

for this to solve we need to bind to service and use messenger to send mutiple message back and forth.

  1. using our button click we use bindService to bind to service.

  2. on binding we and service connected we call, setEcho, requestpassword. when password is recived we send that password to service.

AIDL(Android Interface Definition Language) Service

"The Android Interface Definition Language (AIDL) is similar to other IDLs: it lets you define the programming interface that both the client and service agree upon in order to communicate with each other using interprocess communication (IPC)."

link: https://developer.android.com/develop/background-work/services/aidl

When a service returns a onBind object that means it can be binded for communication.

And AIDL is another way to do that. AIDL code is written in .aidlfile in development phase. But while compilation that is converted to java code and can be found as java code while we decompile apk. e.g.

we can onbind returns a binder object.

IFlag28Interface.Stubis indicator of AIDL srvice.

  • In Android, when you define an AIDL interface (.aidl file), the Android build system generates a .Stub class that extends android.os.Binder.

  • This Stub class is used to expose IPC (Inter-Process Communication) methods.

When we want to interact with such a service we probably want to reverse engineer the original .aidl file.

  1. Look for the DESCRIPTOR variable, as it contains the original package path and .aidl filename

  2. The AIDL methods can be derived from the interface methods with the throws RemoteException

  3. The original method order is shown by the TRANSACTION_ integers

Binding to AIDL Service

Method 1: Writing Our AIDL definition to connect to target service

When it is confirmed AIDL is being used:

Interface.Stub() indicates this service is implemented using AIDL.

As discussed earlier AIDL files are converted to java code on compilation. So in jadx on looking IFlag28Interface code we can get idea of what original AIDL file looked.

DESCRIPTOR = "io.hextree.attacksurface.services.IFlag28Interface"; explains package path and name for AIDL definition

static final int TRANSACTION_openFlag = 1;

This maps the transaction code 1 to openFlag(),to identify the method openFlag() which can be called by client

another way to identify exposed methods as they are always defiend with RemoteException and have a TRANSACTION id attached to it.

When you define an AIDL interface, each method that you want to expose remotely is assigned a unique transaction code (represented by constants like TRANSACTION_openFLag

  1. Now let's go write aidl file as client to connect to target .

  2. before creating AIDL file we need to add to build grade properties.

  1. create a new AIDL file in android studio with same name as of your target app interface IFlag28Interface.

here package name must match extactly what target app DESCRIPTOR has.

Now dfinietly when you will import this AIDL usage in your launcher activity. You can't just write import io.hextree.attacksurface.services as there is no such folder in your project because write now your aidl file will be inside your project folder name

You need to manually create those folders , or

  1. right click on aidl folder and add a new package

  1. Now drag and drop your aidl file to that folder. you can file is moved form original folder to new folder

  1. now run/build the app this will generate a java file which can be imported in mainactivity for working.

java file is created and that is imported in mainactivity java file for usage.
  1. Now use bindservice to connect to this service and call openflag

you can see result of bindservice is casted to remote service of type IFlag28Interface

  • The IFlag28Interface.Stub class is an auto-generated class by Android when you define an AIDL interface.

  • asInterface() is a static method in the Stub class that converts the IBinder object into a local proxy object that implements the IFlag28Interface interface. This proxy allows you to interact with the remote service by calling methods like openFlag().

Note: don't forget to add <queries> tag in manifest file as discussed above.

Now there can be multiple methods in target app which are exported.

as you can see this is also a AIDL service. and lookign at IFlag29Service interface

you can see those three methods are defined. and have a corresponding transaction id.

Here order of TRANSACTION id matters. because we also have to match the order of methods in our aidl file. e.g.

Note: don't forget to name your aidl file also same as target app. ie.e. IFlag29Interface.

when this is converted to java class it assigned the transaction id in same order

If you mess up the order in your aidl file. then your generated java class have different transaction id which will not match with server transaction id. and your app will fail.

this is done because How Android's Binder IPC Works:

In Android, Binder IPC (Inter-Process Communication) relies on transaction codes to identify and differentiate between different method calls that are being made between processes.

  • When you define an AIDL interface, each method that you want to expose remotely is assigned a unique transaction code (represented by constants like TRANSACTION_init, TRANSACTION_success, etc.).

  • When the remote client calls a method (such as init(), success(), or authenticate()), it sends a transaction request to the server process using the corresponding transaction code.

  • The server-side Stub class uses these transaction codes to correctly map incoming requests to specific methods.

Now in target app code we have to execute 3 functions. which we have defined also in aidl file , now we just have to import that interface and call remote methods.

Method 2: Dynamic Remote class Loading

"Adding an .aidl file to your own project can be annoying. Another method that appears more complex at first, is actually quite convenient. By loading the class directly from the target app, we can just invoke the functions we need and do not have to bother about method order or package names."

example 1 , flag28

example 2, flag29

In both cases you can see we didn't need to create aidl file just dynamically load classes and methods and invoke them.

Last updated