CTF,java層靜態分析
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: 37eaae0141f1a3adf8a1dee655853714
3.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-ER
複製程式碼
4. 備註
4.1 工具
- jadx
- jeb
- DB Browser for SQLite sqlitebrowser.org/