Skip to content

GDA: "Unpacking Decompiling Decrypting" to Capture the Flag in CTF Game

charles2gan edited this page Apr 26, 2021 · 2 revisions

Recommended to use the latest version of GDA: it’s more stable.

Download the latest version

Download the CTF case

一、CTF case

The case is from a Flag game in the 2020 WANGDING CUP. There is an apk file that you should find the flag as soon as possible. Drag it into GDA, we find it packed & protected by 360. So the key to winning is how to unpack/decrypt it.

In this paper, We only use GDA's dumping, decompilation, and decryption features to solve it.

二、Let’s Begin

1.Unpacking

First, we press the Dump button to start the GDA Device Dumper, and then click Install APK to install the apk file, and press to run in your device(need be root). After Right-click the 'refresh' menu to refresh the package list and we will see the new package whose PID is 5165. Double click the process (package name) to see the memory spatial distribution of the process.

Next, click the REF radio to display the modules most related to the process name (as shown in the figure below). The oat file actually contains the DEX of the original app (if you are not sure, you can dump all the modules and check them, sometimes the original DEX will exist in the heap, we'll discuss it later).

We need to dump a module completely. how? for example, dumping classes.oat module, first press the left mouse button on the first line of classes.oat, and then drag to the last line of classes.oat module, right-click Dump Module and wait a moment, the dialog box will pop up.

Click OK to view the dump file, as shown in the figure.

The dumped file is an oat file, and the decrypted DEX file (actually the magic in the dex head is erased, GDA just automatically repairs it when parsing OAT) is in this file.

2. Decompiling

Here, modify the file suffix as .oat and drag it to the GDA to decompile the decrypted dex (if you want to convert it to DEX, you can convert it into dex with menu tool > oat2dex)

Then, after a general look, we found the suspicious flag class quickly. The Flag class is likely to be the answer. Here are two functions (calcFlagFirstStep() and calcFlagSecondStep()) that seem to be used to calculate the flag by Flag.keyFirstand and Flag.keySecond, which two are decoded by Base64 and then transmitted to Flag.comm() method. Double click Flag.comm() to see:

If you don't like to watch try-catch here, you can right-click to disable it, as shown in the figure:

This feature is implemented by GDA's flexible structured algorithm. Especially when there are a large number of nested try-catch structures, we don't care about exception handling code, so turning off try-catch will greatly simplify the complexity of the code.

This code is more clear. The two flags first decodes by Base64, then decrypts with Flag.comm(), and at last connects into the Flag that we need.

3.Decrypte Flag

Here, we use the GDA Encryption&Decryption to decode the two flags and then use the GDA java plugin to decrypt and connect.

First, open the GDA Encryption &Decryption tool in menu>tools>ALG Tool, select Base64 to decode the two strings quickly.    

Get two decoded strings:

fmcj.97;A7G462H;2F/7<I9496EH1 [Zm1jan85NztBN0c0NjJIOzJGLzc8STk0OTZFSDE=]

A:HI9E4I1E6<} [QTpISTlFNEkxRTY8fQ==]

Then copy the Flag.comm() method directly to the script file (download the java plugin case of GDA from here, it is recommended to create the java file directly under the directory example, and note that the java class name must be the same as the file name), and then call the comm () method according to the following call method.

//File: DecodeCtfString.java
//decode ctf flag by gjden

package example;
import com.gda.api.*;

class DecodeCtfString {
	//copy from Request.ALLATORIxDEMO decompiled by GDA
	public static String comm(String str,int num){	
       String res = "";
       byte[] cmdbyte = str.getBytes();
       byte i = 0;
       while (i < cmdbyte.length) {	
          cmdbyte[i] = (byte)(cmdbyte[i]-(i%num));
          i = (byte)(i+1);
       }	
       try{	
          res = new String(cmdbyte, "UTF-8");
          return res;
       }catch(java.io.UnsupportedEncodingException e2){	
          e2.printStackTrace();
          return res;
       }	
    }

	public int GDA_MAIN(GDAInterface gda)
	{
		String str1="fmcj.97;A7G462H;2F/7<I9496EH1";
		String str2="A:HI9E4I1E6<}";
		String res=comm(str1,8)+comm(str2,4);
		gda.log(res);
		return 0;
	}
}

Finally, click Menu>file>Run Java/Class to run the .java/.class file and the Flag directly will be printed on GDA, as shown in the figure: