We are giving an APK file ‘EZfill.apk’. To start analyzying this we can either unzip it using a zip tool or preferably use apktool so we can look at the resources, Manifest file and the smali code.

Examining the AndroidManifest.xml file reveals this a rather small APK with on main activity.

The next step we will be to load our APK into our emulator.

Our app shows up in our app’s list:

Opening the app gives a login screen. Let’s input some fake data and see what we get:

Seems the app is doing some checking as far email and password. At this point we can start analyzing the app’s code. We can go straight into viewing smali code or we can use Bytecodeviewer. You can read more about this tool at http://bytecodeviewer.com.

By examining the code we can see decompile code in java. We quickly notice a function that takes an array of char as a parameter and returns an array of char. Inside that function we have an array of int’s which if we were to guess is the encoded flag. First we need to find where this function is being called from and the char array that is passed as an argument. In order to trace it back we need to look for the onCreate function. This is the first callback when an Android application is started. If you recall from loading the app into the emulator, we saw a button so this leads us to believe a function handles the action of clicking it. Inside the onCreate function we see setOnClickListener. Let’s follow the what is passed to this setOnClickListener. It points to a class ‘b’ which has the function OnClick.

The onClick calls back to a function in CupsLogin. Being that the code is slightly obfuscated and a bit hard to trace, let us try to focus on key points in order to trace this. We noticed these two little functions:

Assuming the check for the char ‘@’ and length check of 4 we can conclude is checking the email and/or password. Tracing this back we can see that is being used in private void m()

Inspecting that code inside that function reveals that the ‘string’ & ‘string2’ is being passed to an object.

The object being created extends AsyncTask. According to Android’s documentation AsynTask when executed it goes thru 4 steps, more details here: https://developer.android.com/reference/android/os/AsyncTask.html

Inside this class we some more checks in regards to chars. Analyzing the code we see that doInBackground calls function ‘a’. Inside this function we see a call to:

Analyzing that function, we can see that is doing checks and building an array of char and then passing it to a function. Let’s see what values it expects.

After spending time in figuring out what char values is expecting we can statically determine few values for the password:

-   key = [‘@’, ?, ?, ‘u’, ‘I’, ‘d’, ?]

For the remaining chars we can write a python script to brute force it. Don’t forget to transpose the decoding function we found earlier into python. Below is a sample script to decode this.

def decode(key):

   secret = [] #new char[66];
   flag = [453, 431, 409, 342, 318, 293, 460, 273, 383, 369, 374, 466, 261, 
   380, 513, 267, 301, 266, 310, 437, 260, 325, 379, 333, 454, 350, 345, 
   460, 293, 303, 289, 290, 438, 373, 264, 309, 351]

   key = bytearray(key)
   kidx = 0
   for f in flag:
       t = f - 2
       t = ((key[kidx] - 19 + 86) ^ t) >> 2
       secret.append(t)
       kidx = kidx + 1
       if kidx == len(key):
           kidx = 0

   return secret

def char2enum():
   x =[]
   for a in range(32,127):
       t = a & 0xf ^ a
       if t == 96:
           x.append(a)

   return x

def char1_6enum():
   chars = []
   for a in range(32,127):
       for b in range(32,127):
           if a ^ b == 21:
               if [chr(a),chr(b)] in chars:
                   continue
               chars.append([chr(a),chr(b)])

   return chars


char2 = char2enum()
char16 = char1_6enum()

key  = ['@', ' ', ' ', 'u', 'i', 'd', ' ']

for c1 in char2:
   for c in char16:
       key[2] = c1
       key[1] = c[0]
       key[6] = c[1]
       test = decode(key)
       k = "".join(chr(k) for k in bytearray(key))
       flg = "".join(chr(t) for t in test)
       print "%s:\t%s" % (k,flg)

This will generate about 1500 different variations. We can then grep for lines that have ‘PAN{‘ and that slims it down to 16. Interesting enough we get the flag with 8 different keys.

If we enter any of the right combos in the app we get: