Static analysis of java layer
Topic address: https://github.com/ctf-wiki/c...
1. operation
Click on the upper right button to enter Key.
Enter a few characters at random and find an error.
2. Locate key code
According to the error message Your licence key is incorrect...!Please try again with another, locate the key code.
private void checkLicenceKey(final Context context) { //Check whether the certificate is bound if (this.app.getDataHelper().getConfig().hasLicence()) { showAlertDialog(context, OK_LICENCE_MSG); return; } View promptsView = LayoutInflater.from(context).inflate(R.layout.propmt, null); Builder alertDialogBuilder = new Builder(context); alertDialogBuilder.setView(promptsView); final EditText userInput = (EditText) promptsView.findViewById(R.id.editTextDialogUserInput); alertDialogBuilder.setCancelable(false).setPositiveButton("Continue", new OnClickListener() { public void onClick(DialogInterface dialog, int id) { if (KeyVerifier.isValidLicenceKey(userInput.getText().toString(), MainActivity.this.app.getDataHelper().getConfig().getSecurityKey(), MainActivity.this.app.getDataHelper().getConfig().getSecurityIv())) { MainActivity.this.app.getDataHelper().updateLicence(2014); MainActivity.isRegisterd = true; MainActivity.this.showAlertDialog(context, MainActivity.OK_LICENCE_MSG); return; } MainActivity.this.showAlertDialog(context, MainActivity.NOK_LICENCE_MSG); } }).setNegativeButton("Cancel", new OnClickListener() { public void onClick(DialogInterface dialog, int id) { dialog.cancel(); } }); alertDialogBuilder.create().show(); }
3. Detailed analysis
3.1 Analysis parameters
As you can see, the key code is
KeyVerifier.isValidLicenceKey( userInput.getText().toString(), MainActivity.this.app.getDataHelper().getConfig().getSecurityKey(), MainActivity.this.app.getDataHelper().getConfig().getSecurityIv() )
There are three parameters
- A string entered by the user
- Functions getSecurityKey(), getSecurityIv()
public AppConfig getConfig() { boolean z = true; AppConfig agency = new AppConfig(); Cursor cursor = this.myDataBase.rawQuery(SELECT_QUERY, null); if (cursor.moveToFirst()) { agency.setId(cursor.getInt(0)); agency.setName(cursor.getString(1)); agency.setInstallDate(cursor.getString(2)); if (cursor.getInt(3) <= 0) { z = false; } agency.setValidLicence(z); agency.setSecurityIv(cursor.getString(4)); agency.setSecurityKey(cursor.getString(5)); agency.setDesc(cursor.getString(7)); } return agency; }
Database related information:
private static String DB_NAME = "db.db"; private static String DB_PATH = "/data/data/edu.sharif.ctf/databases/"; public static final String SELECT_QUERY = ("SELECT * FROM " + TABLE_NAME + " WHERE a=1"); private static String TABLE_NAME = "config";
Logic:
- Cursor cursor = this.myDataBase.rawQuery(SELECT_QUERY, null); get the first line of the table config
- Agency. setSecurity Iv (cursor. getString (4)); the fourth row in the table is assigned to Iv
- agency.setSecurityKey(cursor.getString(5)); the fifth row in the table is assigned to Key
Open apk with jeb, export db.db, and open with DB browser.
SecurityIv: a5efdbd57b84ca36
SecurityKey: 37eaae0141f1a3adf8a1dee655853714
3.2 Analytical Encryption Algorithms
package edu.sharif.ctf.security; import java.security.Key; import javax.crypto.Cipher; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; public class KeyVerifier { public static final String CIPHER_ALGORITHM = "AES/CBC/PKCS5Padding"; public static final String VALID_LICENCE = "29a002d9340fc4bd54492f327269f3e051619b889dc8da723e135ce486965d84"; public KeyVerifier() { super(); } public static String bytesToHexString(byte[] arg8) { StringBuilder v1 = new StringBuilder(); int v4 = arg8.length; int v2; for(v2 = 0; v2 < v4; ++v2) { v1.append(String.format("%02x", Integer.valueOf(arg8[v2] & 0xFF))); } return v1.toString(); } public static String encrypt(String arg8, String arg9, String arg10) { String v3; try { SecretKeySpec v5 = new SecretKeySpec(KeyVerifier.hexStringToBytes(arg9), "AES"); Cipher v0 = Cipher.getInstance("AES/CBC/PKCS5Padding"); v0.init(1, ((Key)v5), new IvParameterSpec(arg10.getBytes())); v3 = KeyVerifier.bytesToHexString(v0.doFinal(arg8.getBytes())); } catch(Exception v1) { v1.printStackTrace(); } return v3; } public static byte[] hexStringToBytes(String arg7) { int v6 = 16; int v2 = arg7.length(); byte[] v0 = new byte[v2 / 2]; int v1; for(v1 = 0; v1 < v2; v1 += 2) { v0[v1 / 2] = ((byte)((Character.digit(arg7.charAt(v1), v6) << 4) + Character.digit(arg7.charAt(v1 + 1), v6))); } return v0; } // Call encryption algorithm public static boolean isValidLicenceKey(String arg2, String arg3, String arg4) { boolean v1 = KeyVerifier.encrypt(arg2, arg3, arg4).equals("29a002d9340fc4bd54492f327269f3e051619b889dc8da723e135ce486965d84") ? true : false; return v1; } }
The encryption algorithm is AES/CBC/PKCS5 Padding, and the corresponding decryption algorithm is written out.
import javax.crypto.Cipher; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; public class Main { public static void main(String[] args) { // write your code here String encrypted = "29a002d9340fc4bd54492f327269f3e051619b889dc8da723e135ce486965d84"; String securityKey = "37eaae0141f1a3adf8a1dee655853714"; String securityIv = "a5efdbd57b84ca36"; String result = decrypt(encrypted, securityKey, securityIv); System.out.println(result); } public static String bytesToHexString(byte[] paramArrayOfByte) { StringBuilder localStringBuilder = new StringBuilder(); int i = paramArrayOfByte.length; for (int j = 0; ; j++) { if (j >= i) return localStringBuilder.toString(); int k = paramArrayOfByte[j]; Object[] arrayOfObject = new Object[1]; arrayOfObject[0] = Integer.valueOf(k & 0xFF); localStringBuilder.append(String.format("%02x", arrayOfObject)); } } public static String decrypt(String paramString1, String paramString2, String paramString3) { try { SecretKeySpec localSecretKeySpec = new SecretKeySpec(hexStringToBytes(paramString2), "AES"); Cipher localCipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); localCipher.init(Cipher.DECRYPT_MODE, localSecretKeySpec, new IvParameterSpec(paramString3.getBytes())); byte[] bytes = localCipher.doFinal(hexStringToBytes(paramString1)); String flag = ""; for (byte b : bytes) { flag += (char) b; } return flag; } catch (Exception localException) { localException.printStackTrace(); } return ""; } public static byte[] hexStringToBytes(String paramString) { int i = paramString.length(); byte[] arrayOfByte = new byte[i / 2]; for (int j = 0; ; j += 2) { if (j >= i) return arrayOfByte; arrayOfByte[(j / 2)] = (byte) ((Character.digit(paramString.charAt(j), 16) << 4) + Character.digit(paramString.charAt(j + 1), 16)); } } }
The operation results are as follows:
fl-ag-IS-se-ri-al-NU-MB-ER
4. remarks
4.1 tools
- jadx
- jeb
- DB Browser for SQLite http://sqlitebrowser.org/