java层静态分析题目地址:https://github.com/ctf-wiki/c…1. 运行点击右上按钮,出现输入Key的界面。随便输入几个字符,发现报错。2. 定位关键代码根据报错信息 Your licence key is incorrect…! Please try again with another,定位关键代码。 private void checkLicenceKey(final Context context) { //检测是否已绑定证书 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.详细分析3.1 分析参数观察得出,关键代码为KeyVerifier.isValidLicenceKey(userInput.getText().toString(), MainActivity.this.app.getDataHelper().getConfig().getSecurityKey(), MainActivity.this.app.getDataHelper().getConfig().getSecurityIv())共有三个参数用户输入的字符串函数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; }数据库相关信息: 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”;逻辑:Cursor cursor = this.myDataBase.rawQuery(SELECT_QUERY, null); 获取表config的首行agency.setSecurityIv(cursor.getString(4)); 表中第四行赋值给Ivagency.setSecurityKey(cursor.getString(5)); 表中第五行赋值给Key用jeb打开apk,导出db.db ,用 DB browser 打开。SecurityIv:a5efdbd57b84ca36 SecurityKey: 37eaae0141f1a3adf8a1dee6558537143.2 分析加密算法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; } // 调用加密算法 public static boolean isValidLicenceKey(String arg2, String arg3, String arg4) { boolean v1 = KeyVerifier.encrypt(arg2, arg3, arg4).equals(“29a002d9340fc4bd54492f327269f3e051619b889dc8da723e135ce486965d84”) ? true : false; return v1; }}加密算法为AES/CBC/PKCS5Padding,写出对应的解密算法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)); } }}运行得到结果:fl-ag-IS-se-ri-al-NU-MB-ER4. 备注4.1 工具jadxjebDB Browser for SQLite http://sqlitebrowser.org/4.2 参考文章Sharif University Quals CTF 2014 Commercial Application WriteupCTF-wiki 2014 Sharif University Quals CTF Commercial Application