CTFZone Paper: Trust Area — Client Part

About application architecture

The primary task of the Android client was to proxy the calls from other clients in the emulator, including the checker, to the team’s respective backend server. For this purpose, the following was implemented on the client side:

  • caching to reduce the backend load,
  • ability to create data backups.
Fig. 1. Android client architecture

How we developed the client and the problems we bumped into

The service client was written in Kotlin, which is used for the development of real mobile apps. (Although Java is also used, we opted for Kotlin so that our task embraced the latest trends in mobile software).

  • heap limitations — 2–36 MB,
  • an app can’t store more than 3.5 GB on /sdcard/Android/data/,
  • it can’t use more than 200 MB on /data/data/,
  • network traffic per app is not limited (but we would have seen the source in traffic dumps).

About client-to-client communication

While everything was clear as far as the communication between the Android client and the backend server was concerned (via an HTTP protocol), the client-to-client communication did not appear obvious.

  1. Client1, with an intent to send a request to Client 2, sends a PendingIntent to the IntentProxy specifying the recipient and data.
  2. The IntentProxy replaces the sender with itself and forwards the PendingIntent to Client 2.
  3. Client2 is unaware which of the clients has sent a PendingIntent since every client interacts solely with the IntentProxy by default.
  • The IntentProxy was a single point of load — hence, a single point of failure.
  • This was another service for us to write and administer.
  • A simple functionality concealed a number of problems — we had to decide how to deal with:
    - intent queues,
    - asynchronous delivery of responses,
    -a mechanism for processing such events as the absence of a response from the client, incorrect response formats, etc.
  1. Client1, with an intent to send a request to Client 2, registers in the system a BroadcastReceiver with a random action.
  2. Client1 sends a standard intent with a request and the said random action to Client 2.
  3. Client2 doesn’t see the sender in the standard intent, but the action indicates where to send the response (as a Broadcast Intent).
  4. Client1, upon receiving the response, closes the BroadcastReceiver.

About vulnerabilities

It’s essential for a good app to have no vulnerabilities unless it’s a CTF app.

  • the use of empty intents (Intent() as basic, during PendingIntent initialisation),
  • Intent Redirection.

About the teams' authenticity

During the competition, we monitored the vulnerabilities exploited by the participants. The screenshot below demonstrates the most bizarre code snippets.

Fig. 2. Code snippets

Source code:



Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store



International community conference for cybersecurity researchers and professionals. No suits, no business — only hardcore research.