2014 Sharif University Quals CTF Commercial Application

lushann發表於2019-04-03

CTF,java層靜態分析

題目地址:github.com/ctf-wiki/ct…

1. 執行

點選右上按鈕,出現輸入Key的介面。

2014 Sharif University Quals CTF Commercial Application

隨便輸入幾個字元,發現報錯。

2014 Sharif University Quals CTF Commercial Application

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()
)
複製程式碼

共有三個引數

  1. 使用者輸入的字串
  2. 函式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";
複製程式碼

邏輯:

  1. Cursor cursor = this.myDataBase.rawQuery(SELECT_QUERY, null); 獲取表config的首行
  2. agency.setSecurityIv(cursor.getString(4)); 表中第四行賦值給Iv
  3. agency.setSecurityKey(cursor.getString(5)); 表中第五行賦值給Key

用jeb開啟apk,匯出db.db ,用 DB browser 開啟。

2014 Sharif University Quals CTF Commercial Application

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 工具

  1. jadx
  2. jeb
  3. DB Browser for SQLite sqlitebrowser.org/

4.2 參考文章

  1. Sharif University Quals CTF 2014 Commercial Application Writeup
  2. CTF-wiki 2014 Sharif University Quals CTF Commercial Application

相關文章