IV - Android Reverse Engineering

Let's start by decompiling the APK using JADXarrow-up-right which is a Dex to Java decompiler:

jadx BountyPay.apk

In our case the interesting files are going to be in /sources/bounty:

/BountyPay/sources/bounty
└── pay
    ├── BuildConfig.java
    ├── CongratsActivity.java
    ├── MainActivity.java
    ├── PartOneActivity.java
    ├── PartThreeActivity.java
    ├── PartTwoActivity.java
    └── R.java

1 directory, 7 files

We can see that there is one MainActivity and three activities named PartOne, PartTwo and PartThree.

Looking at the Manifest we can see that there are actually 5 activities define:

  • bounty.pay.MainActivity

  • bounty.pay.PartOneActivity

  • bounty.pay.PartTwoActivity

  • bounty.pay.PartThreeActivity

  • bounty.pay.CongratsActivity

Something interesting to note is that PartOne, PartTwo and PartThree activities all defined an intent filter a scheme and an host:

  • one://part

  • two://part

  • three://part

Let's install the app on our favorite emulator (here I'm using Android Studioarrow-up-right's emulator) using adbarrow-up-right:

The fist screen invites us to enter a username and a Twitter handle.

BountyPay

PartOneActivity

The PartOne acitivity only has a button that gives use hints when we click on it:

  • Deep links.

  • Params.

circle-info

Deeplinks are a concept that help users navigate between the web and applications. They are basically URLs which navigate users directly to the specific content in applications. Optionally, some data or parameter can be passed along.

When we look at the code we can see the corresponding code:

Afterwards we can see that there are a few conditions to continue to the next activity:

  • The setting should contains a username (set on the first screen)

  • A query parameter named start should be present with a value of PartTwoActivity

If all the condiditions are met the PartTwo activity is started.

This can be done using adb using the following command:

PartTwoActivity

Here again we are presented with a white screen with a button giving us two hints:

  • Currently invisible.

  • Visible with the right params.

This seems to imply that there is some invisible content that will be revealed if we send the right parameters. Let's look at the code.

This time we can see that some conditions are required to be able to see the invisible content:

  • The username needs to be set

  • Part one needs to be complete

  • Two parameter are required, two with a value of light and switch with a value of on

Here again we can do this using adb:

circle-exclamation

As expected we can now see an input field expecting a Header value and underneath an MD5 hash.

Clicking on the submit button will trigger the submitInfo function. We can see that the header value should start with X- and if so the correctHeader function will be called which in turns will start PartThreeActivity.

PartThreeActivity

This time the conditions that needs to be met are:

  • First param three should be equal to Base64("PartThreeActivity")

  • Second param switch should be equal to Base64("on")

  • Third param header should be equal to the previously defined header, in our case X-Token

Now that we know all the requirement we can send the intent.

We are then asked to provide a "leaked hash".

Looking into the logs using abd logcat we can quickly see our leaked hash:

When submitted we get the Congrats activity 🥳

CongratsActivity

Last updated