天天看點

android ctf 密碼破解1.樣本概況2.具體分析

目錄

1.樣本概況... 3

1.1 樣本資訊... 3

1.2 測試環境及工具... 3

1.3 分析目标... 3

2.具體分析... 4

2.1 加強情況... 4

2.2 代碼片段分析... 4

1.樣本概況

1.1 樣本資訊

名稱:dc3c4ec3ea5b7de2de4feb122e33b1a2e91d9ffa

MD5值:5d21be09f3a1fcf545afaf0f81844fea

SHA1值:dc3c4ec3ea5b7de2de4feb122e33b1a2e91d9ffa

CRC32:d6741def

主界面:

android ctf 密碼破解1.樣本概況2.具體分析

1.2 測試環境及工具

Nexus5 + IDA pro

1.3 分析目标

破解密碼

2.具體分析

2.1 加強情況

android ctf 密碼破解1.樣本概況2.具體分析

2.2 代碼片段分析

    直接對樣本進行調試,使用apktool反編譯樣本,擷取包名及類名,确定JNI_OnLoad的偏移,在JNI_OnLoad中通過寄存器調用,可以确定是RegisterClass,檢視寄存器,在R2中調用了aMUMU,轉到記憶體可以确定對應的函數位址。如下圖所示:

android ctf 密碼破解1.樣本概況2.具體分析
android ctf 密碼破解1.樣本概況2.具體分析

如下所示為attachBaseContext位址,跳轉到該位址,并下斷點

android ctf 密碼破解1.樣本概況2.具體分析

如下所示為onCreate位址跳轉到該位址,并下斷點

android ctf 密碼破解1.樣本概況2.具體分析

在跟進到此處時跳出,程式直接運作起來,說明B loc_75252EAE裡加載了dex

android ctf 密碼破解1.樣本概況2.具體分析

重新啟動調試,後跟進這個跳轉,如下圖所示:

android ctf 密碼破解1.樣本概況2.具體分析

中斷後重新附加調試函數位址會改變,不能按照上一次斷點跟蹤,如下圖所示:

android ctf 密碼破解1.樣本概況2.具體分析

再次分析_Z9parse_dexP7_JNIEnvPx函數,該函數會在log中列印日志,顯示dex的記憶體位址及dex大小等資訊,如下下圖所示:

android ctf 密碼破解1.樣本概況2.具體分析

調用opendexfile, 如下圖所示:

android ctf 密碼破解1.樣本概況2.具體分析

可以根據寄存器R8的值知道dex的位置,然後根據dex檔案格式可知0x752A9028為dex檔案大小(0x19cf4),計算結束位址為:0x752C2CFC,如下圖所示:

android ctf 密碼破解1.樣本概況2.具體分析

執行完成之後進入onCreate函數,如下圖所示:

android ctf 密碼破解1.樣本概況2.具體分析

onCreate函數結束,進入libdvm.so子產品,

android ctf 密碼破解1.樣本概況2.具體分析

這個時候dex已經在上述的記憶體位址出還原,在_ZN3ali16dex_juicer_patchEPhjPKc函數中可以使用下圖所示關鍵字在ddms中過濾log資訊

android ctf 密碼破解1.樣本概況2.具體分析

在ddms中檢視log,如下所示:

android ctf 密碼破解1.樣本概況2.具體分析

根據上面分析的起始位址和偏移計算出結束位址,再使用IDC腳本将其dump到檔案中,

static main(void)

{

auto fp, begin, end, dexbyte;

fp = fopen("d:\\dumpali.so", "wb");

begin = 0x752AA008;

end = begin + 0x30090;

for ( dexbyte = begin; dexbyte < end; dexbyte ++ )

fputc(Byte(dexbyte), fp);

}

然後使用jadx工具檢視dump出來的結果,代碼已經還原,如下圖所示:

android ctf 密碼破解1.樣本概況2.具體分析

    脫殼成功,使用GDA檢測如下圖所示:

android ctf 密碼破解1.樣本概況2.具體分析

然後進行動态調試擷取密碼:通過動态調試smali擷取到加密後的字元串:

000a0a0a0a0202aa5458d715704493d8e6b9bd38f8b6be0e

android ctf 密碼破解1.樣本概況2.具體分析
android ctf 密碼破解1.樣本概況2.具體分析

key = 1f98ceab209770efa875c245853ece761f98ceab209770ef

android ctf 密碼破解1.樣本概況2.具體分析

根據以上分析和dump出的smali代碼,對解密代碼進行編寫:

import javax.crypto.*;

import javax.crypto.spec.IvParameterSpec;

import javax.crypto.spec.SecretKeySpec;

import java.io.UnsupportedEncodingException;

import java.security.*;

import java.security.spec.AlgorithmParameterSpec;

public class Main {

    private static String a = "DESede";

    private static Key b;

    private static int c = 5;

    public static byte[] step1_string(String arg9) {

        byte[] v1 = arg9.getBytes();

        int v2 = v1.length;

        byte[] v3 = new byte[v2 / 2];

        int v0;

        for(v0 = 0; v0 < v2; v0 += 2) {

            v3[v0 / 2] = ((byte)Integer.parseInt(new String(v1, v0, 2), 16));

        }

        return v3;

    }

    public static String step3_byte(byte[] arg6) {

        StringBuffer v2 = new StringBuffer();

        int v1;

        for(v1 = 0; v1 < arg6.length; ++v1) {

            System.out.print(arg6[v1] + " ");

            String v0 = Integer.toHexString(arg6[v1] & 255);

            if(v0.length() == 1) {

                v0 = String.valueOf('0') + v0;

            }

            v2.append(v0);

        }

        //System.out.println(v2);

        return v2.toString();

    }

    public static byte[] step3_string(String arg6) {

        String arg16[] = new String[32];

        byte [] abyte = new byte[32];

        for (int i = 0; i < arg16.length; i = i+2){

            arg16[i] = arg6.substring(i, i+2);

            Integer in = Integer.parseInt(arg16[i], 16);

            byte intnum = in.byteValue();

            abyte[i] = (byte) (intnum & 255);

            System.out.print(abyte[i] + " ");

        }

        return abyte;

    }

    private static byte[] step2_key(byte[] arg7, byte[] arg8) {

        IvParameterSpec v0 = new IvParameterSpec(arg7);

        Cipher v1 = null;

        try {

            v1 = Cipher.getInstance(String.valueOf(a) + "/CBC/PKCS5Padding");

            v1.init(1, b, ((AlgorithmParameterSpec)v0));

            c = v1.getBlockSize();

            byte[] v0_1 = v1.doFinal(arg8);

            byte[] v1_1 = new byte[v0_1.length + c];

            System.arraycopy(arg7, 0, v1_1, 0, c);

            System.arraycopy(v0_1, 0, v1_1, c, v0_1.length);

            return v1_1;

        } catch (NoSuchAlgorithmException e) {

            e.printStackTrace();

        } catch (NoSuchPaddingException e) {

            e.printStackTrace();

        } catch (BadPaddingException e) {

            e.printStackTrace();

        } catch (InvalidKeyException e) {

            e.printStackTrace();

        } catch (IllegalBlockSizeException e) {

            e.printStackTrace();

        } catch (InvalidAlgorithmParameterException e) {

            e.printStackTrace();

        }

        return null;

    }

    private static byte[] step2_dekey(byte[] arg7, byte[] arg8) {

        IvParameterSpec v0 = new IvParameterSpec(arg7);

        Cipher v1 = null;

        try {

            v1 = Cipher.getInstance(String.valueOf(a) + "/CBC/NoPadding");

            v1.init(Cipher.DECRYPT_MODE, b, ((AlgorithmParameterSpec)v0)); // 操作模式為解密,key為密鑰

            byte[] sourceText = v1.doFinal(arg8);

            System.out.println();

            for (int j = 0 ; j < sourceText.length; j++){

                System.out.print(sourceText[j] + " ");

            }

            return sourceText;

        }catch (BadPaddingException e) {

            e.printStackTrace();

        }catch (IllegalBlockSizeException e) {

            e.printStackTrace();

        }catch (InvalidKeyException e) {

            e.printStackTrace();

        } catch (NoSuchPaddingException e) {

            e.printStackTrace();

        } catch (NoSuchAlgorithmException e) {

            e.printStackTrace();

        } catch (InvalidAlgorithmParameterException e) {

            e.printStackTrace();

        }

        return null;

    }

    public static Key get_key(byte[] arg4) {

        SecretKey v0_1 = null;

        try {

            if(arg4 == null) {

                KeyGenerator v0 = KeyGenerator.getInstance(a);

                v0.init(new SecureRandom());

                v0_1 = v0.generateKey();

            }

            else {

                SecretKeySpec v0_2 = new SecretKeySpec(arg4, a);

                return ((Key)v0_2);

            }

        } catch (NoSuchAlgorithmException e) {

            e.printStackTrace();

        }

        return ((Key)v0_1);

    }

    public static void main(String []args){

        //加密模拟

        //1.給key  b 指派  v0.a(v0.a(a.a(arg5)));

        //argc5 = 1f98ceab209770efa875c245853ece761f98ceab209770ef

        b = get_key(step1_string("1f98ceab209770efa875c245853ece761f98ceab209770ef"));

        //2.擷取 arg6 = a.a(v0.a(a.a("000a0a0a0a0202aa"), arg6.getBytes()));

        String result = step3_byte(step2_key(step1_string("000a0a0a0a0202aa"), "日天@土侸".getBytes()));

        System.out.println(result);

        //解密部分

        //000a0a0a0a0202aa5458d715704493d8e6b9bd38f8b6be0e

        //step2_key傳回的位元組數組:84 88 -41 21 112 68 -109 -40 -26 -71 -67 56 -8 -74 -66 14

        step3_string("5458d715704493d8e6b9bd38f8b6be0e");

        //構造解密的位元組

        byte[] bytedecode = new byte[16];

        bytedecode[0] = 84;

        bytedecode[1] = 88;

        bytedecode[2] = -41;

        bytedecode[3] = 21;

        bytedecode[4] = 112;

        bytedecode[5] = 68;

        bytedecode[6] = -109;

        bytedecode[7] = -40;

        bytedecode[8] = -26;

        bytedecode[9] = -71;

        bytedecode[10] = -67;

        bytedecode[11] = 56;

        bytedecode[12] = -8;

        bytedecode[13] = -74;

        bytedecode[14] = -66;

        bytedecode[15] = 14;

        step2_dekey(step1_string("000a0a0a0a0202aa"), bytedecode);

        //-26 -105 -91 -27 -92 -87 64 -27 -100 -97 -28 -66 -72 3 3 3

        byte[] sourcebyte = new byte[16];

        sourcebyte[0] = -26;

        sourcebyte[1] = -105;

        sourcebyte[2] = -91;

        sourcebyte[3] = -27;

        sourcebyte[4] = -92;

        sourcebyte[5] = -87;

        sourcebyte[6] = 64;

        sourcebyte[7] = -27;

        sourcebyte[8] = -100;

        sourcebyte[9] = -97;

        sourcebyte[10] = -28;

        sourcebyte[11] = -66;

        sourcebyte[12] = -72;

        sourcebyte[13] = 3;

        sourcebyte[14] = 3;

        sourcebyte[15] = 3;

        try {

            String str = new String(sourcebyte, "utf-8");

            System.out.println(str);

        } catch (UnsupportedEncodingException e) {

            e.printStackTrace();

        }

        System.out.println();

        for (int i = 0; i < sourcebyte.length; i++){

            System.out.print(sourcebyte[i] + " ");

        }

    }

}

運作結果如下所示:

android ctf 密碼破解1.樣本概況2.具體分析
android ctf 密碼破解1.樣本概況2.具體分析

繼續閱讀