Android Hacking Event 2017 AES-Decrypt Writeup

はじめに

Android問に強くなる全然更新してないなと思ったので久々にやります。ちなみに途中までは自力しましたがわかんなくなったのでWriteupは見てます。

AES-Decrypt

とりあえずapkファイルがあるので実行してみる

+NvwsZ48j3vyDlaMu6LrjnNn8/OAnexGL

T9WoXhrsQHgY3NLr8SwBbw==

という文字列がある、試しにDecryptボタンを押すと

Key=AF03BC291F82という文字列が現れる

まぁ本題は2個目を復号したのが答えだろうと予想する。なのでとりあえず中身を見てみる

javaの解析

MainActivity.java

package challenge.teamsik.aesdecryption;

import android.content.Context;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.*;

public class MainActivity extends AppCompatActivity
{

    public MainActivity()
    {
    }

    public native String decryptAES(Context context);

    protected void onCreate(Bundle bundle)
    {
        super.onCreate(bundle);
        setContentView(0x7f04001b);
        mContext = this;
        ((Button)findViewById(0x7f0b005e)).setOnClickListener(new android.view.View.OnClickListener() {

            public void onClick(View view)
            {
                view = decryptAES(MainActivity.mContext);
                ((TextView)findViewById(0x7f0b0061)).setText(view);
                Toast.makeText(MainActivity.mContext, "Decryption Successfull!", 1).show();
            }

            final MainActivity this$0;

            
            {
                this$0 = MainActivity.this;
                super();
            }
        });
    }

    public static final String TAG = "CHALLENGE";
    public static Context mContext;

    static 
    {
        System.loadLibrary("native-lib");
    }
}

ソースコードを見て察した。これNDK問題だなと....

libnativeにdecryptAESという関数がありそこでdecryptしている。

libnativeの解析

radare2を使う

$ r2 lib/armeabi-v7a/libnative-lib.so 
 -- Set color to your screen with 'e scr.color=true'
[0x0000347c]> aaa
[x] Analyze all flags starting with sym. and entry0 (aa)
[ ] 
[Value from 0x00000000 to 0x00011144
aav: 0x00000000-0x00011144 in 0x0-0x11144
aav: 0x00000000-0x00011144 in 0x123d0-0x1300c
aav: 0x00000000-0x00011144 in 0x1300c-0x17f35
Value from 0x0001300c to 0x00017f35
aav: 0x0001300c-0x00017f35 in 0x0-0x11144
aav: 0x0001300c-0x00017f35 in 0x123d0-0x1300c
aav: 0x0001300c-0x00017f35 in 0x1300c-0x17f35
[x] Analyze len bytes of instructions for references (aar)
[x] Analyze function calls (aac)
[x] Use -AA or aaaa to perform additional experimental analysis.
[x] Constructing a function name for fcn.* and sym.func.* functions (aan)
[0x0000347c]> afl
....
0x00003518   10 1068         sym.Java_challenge_teamsik_aesdecryption_MainActivity_decryptAES
....

やはりdecryptAES関数を発見。中身を見てみる

[0x0000347c]> s sym.Java_challenge_teamsik_aesdecryption_MainActivity_decryptAES
[0x00003518]> pdf
...
0x00003906      00f0a7f8       bl sub.EVP_CIPHER_CTX_new_a58
...

とりあえずなんか怪しいのが見つかる。CIPHERとかあるししかもEVPだしOpensslのやつっぽい。

と思って調べたらOpenSSL EVP 関数を見つけた。予想は当たっていたようだ。

後は文字列調べるかなと思って調べた結果がこちら

[0x00003518]> iz
vaddr=0x0000f788 paddr=0x0000f788 ordinal=000 sz=10 len=9 section=.rodata type=ascii string=CHALLENGE
vaddr=0x0000f792 paddr=0x0000f792 ordinal=001 sz=6 len=5 section=.rodata type=ascii string=0x%2x
vaddr=0x0000f798 paddr=0x0000f798 ordinal=002 sz=18 len=17 section=.rodata type=ascii string=Invalid key used!
vaddr=0x0000f7aa paddr=0x0000f7aa ordinal=003 sz=21 len=20 section=.rodata type=ascii string=Initalizing OpenSSL:
vaddr=0x0000f7bf paddr=0x0000f7bf ordinal=004 sz=45 len=44 section=.rodata type=ascii string=0fk8j09RWT8+bKFQ0BdwRVjM+PuM5GeauUORaOtuP5A=
vaddr=0x0000f7ec paddr=0x0000f7ec ordinal=005 sz=65 len=64 section=.rodata type=ascii string=0fk8j09RWT8+bKFQ0BdwRTwVQHvav+HIQH3zWg0UtCw8RCtgr772N3KAfKdWMKZN
vaddr=0x0000f82d paddr=0x0000f82d ordinal=006 sz=45 len=44 section=.rodata type=ascii string=0fk8j09RWT8+bKFQ0BdwRWYaE95rIj008XoTqeq1YJU=
vaddr=0x0000f85a paddr=0x0000f85a ordinal=007 sz=45 len=44 section=.rodata type=ascii string=0fk8j09RWT8+bKFQ0BdwRVw0J6O9tU1N3bUR4SpMgIE=
vaddr=0x0000f887 paddr=0x0000f887 ordinal=008 sz=45 len=44 section=.rodata type=ascii string=pJolsMEG1ZjA39Z0RdSfbtgf/6QqiXXgLDYZWMRIpno=
vaddr=0x0000f8b4 paddr=0x0000f8b4 ordinal=009 sz=65 len=64 section=.rodata type=ascii string=5XN3JZ0qQnZOlVT+FvZutMspEknw0l2ylINvmahr58xEQL4+3GEWnF/ojZ8OwwdZ
vaddr=0x0000f8f5 paddr=0x0000f8f5 ordinal=010 sz=65 len=64 section=.rodata type=ascii string=5XN3JZ0qQnZOlVT+FvZutEVENxTKdhobEn9okV2h5Bj8PXPBkbRrEEDjxknjA16H
vaddr=0x0000f936 paddr=0x0000f936 ordinal=011 sz=65 len=64 section=.rodata type=ascii string=u9o2dJItY/yt633wMhsDP2BaKb9kHJm/HZtwOe4L1ADV+U+aiHgpGhZ7EEaEcHq9
vaddr=0x0000f977 paddr=0x0000f977 ordinal=012 sz=45 len=44 section=.rodata type=ascii string=ZrnY4AKdp5ByAoHREWtYv+NamtJA/p0Swvc6D6u7qx0=
vaddr=0x0000f9a4 paddr=0x0000f9a4 ordinal=013 sz=45 len=44 section=.rodata type=ascii string=P2m808wtZdzcP9ouyfWvjoGLm2jZi0D4uK5YnjsP+B4=
vaddr=0x0000f9d1 paddr=0x0000f9d1 ordinal=014 sz=65 len=64 section=.rodata type=ascii string=5jW+2fK2AEWXkb5wmwjbau9My2QuA9MhMDQP06c9e+pCDbCx7kdtJ6ZJQSkeJdWk
vaddr=0x0000fa12 paddr=0x0000fa12 ordinal=015 sz=25 len=24 section=.rodata type=ascii string=YqXS6chhZJr0JwhXiBTwSA==
vaddr=0x0000fa2b paddr=0x0000fa2b ordinal=016 sz=45 len=44 section=.rodata type=ascii string=l23Klp6+80bbLX8Aor0Aitb5I2paF+dxz8UpAQylJKI=
vaddr=0x0000fa58 paddr=0x0000fa58 ordinal=017 sz=25 len=24 section=.rodata type=ascii string=HUO0GJiv0BJHQu49yAOsvg==
vaddr=0x0000fa71 paddr=0x0000fa71 ordinal=018 sz=89 len=88 section=.rodata type=ascii string=me/LE9SHGipWIAdMwewSpNxMcbHu7koanAld8nvXh4Nkf7Mn9o/GPj6dCB95B00SaEw4OTn6MBdjKnFBmMEmQw==
vaddr=0x0000faca paddr=0x0000faca ordinal=019 sz=25 len=24 section=.rodata type=ascii string=9H7sv0baQSW+dJcuy1kTcg==
vaddr=0x0000fae3 paddr=0x0000fae3 ordinal=020 sz=45 len=44 section=.rodata type=ascii string=djcVuQzrYzzvIBzv6qwU78XoK9b9Axx6rzOipkBNI9M=
vaddr=0x0000fb10 paddr=0x0000fb10 ordinal=021 sz=25 len=24 section=.rodata type=ascii string=Tc6oeVRcAP5Ed1yKFb1y4Q==
vaddr=0x0000fb29 paddr=0x0000fb29 ordinal=022 sz=25 len=24 section=.rodata type=ascii string=k70Em+XsW/0rwt6FiPz5cw==
vaddr=0x0000fb42 paddr=0x0000fb42 ordinal=023 sz=25 len=24 section=.rodata type=ascii string=1mwCw3AgNVhGG+gPBXu7gQ==
vaddr=0x0000fb5b paddr=0x0000fb5b ordinal=024 sz=25 len=24 section=.rodata type=ascii string=j3PbP1T7rSkj3zq+hkGqLA==
vaddr=0x0000fb74 paddr=0x0000fb74 ordinal=025 sz=25 len=24 section=.rodata type=ascii string=FwB0AaNtkiZqymRhe2dV/g==
vaddr=0x0000fb8d paddr=0x0000fb8d ordinal=026 sz=89 len=88 section=.rodata type=ascii string=me/LE9SHGipWIAdMwewSpOgpB/hPmqJ505Coc0q+diYVOvgpUNs3r6VIZHETDSh3zKheQnLGhBEuPlgw/wRtxA==
vaddr=0x0000fbe6 paddr=0x0000fbe6 ordinal=027 sz=25 len=24 section=.rodata type=ascii string=26Ai/jguFtNz4eK3Rfcuxg==
vaddr=0x0000fbff paddr=0x0000fbff ordinal=028 sz=45 len=44 section=.rodata type=ascii string=1ZIXfbbppzkz4tclxQA3BtcRorc3mMLTivhI3S9tjUM=
vaddr=0x0000fc2c paddr=0x0000fc2c ordinal=029 sz=89 len=88 section=.rodata type=ascii string=+jrIt+CNy/la9PHTLuZUjvkays5GIPScMVpJpyV+nul+WkiY6pmTRD0v/pCtowvxt6mEAwXZXU4Zr9dx90s3Kw==
vaddr=0x0000fc85 paddr=0x0000fc85 ordinal=030 sz=25 len=24 section=.rodata type=ascii string=jHDAGbW9MO5AA/jXIj4VRA==
vaddr=0x0000fc9e paddr=0x0000fc9e ordinal=031 sz=45 len=44 section=.rodata type=ascii string=udv/kxBBdbg3PItkFW6Kms/ko9FHaJzGIagOHSAJsC0=
vaddr=0x0000fccb paddr=0x0000fccb ordinal=032 sz=25 len=24 section=.rodata type=ascii string=pV1HOig44OVVCUGk57OhuQ==
vaddr=0x0000fce4 paddr=0x0000fce4 ordinal=033 sz=45 len=44 section=.rodata type=ascii string=7fIEIbf6NxVvrVFmlEAdYLUSriDuoGdtLbvZWBjJ3LI=
vaddr=0x0000fd11 paddr=0x0000fd11 ordinal=034 sz=22 len=21 section=.rodata type=ascii string=You used a wrong key!
vaddr=0x0000fd28 paddr=0x0000fd28 ordinal=035 sz=45 len=44 section=.rodata type=ascii string=+NvwsZ48j3vyDIaMu6LrjnNn8/OAnexGUXn3POeavI8=
vaddr=0x0000fd5d paddr=0x0000fd5d ordinal=036 sz=5 len=4 section=.rodata type=ascii string=gI'f

base64が多いのが怪しいけどこれだけではわからない。アセンブラを読めばいいのだが諦めてWriteupを見た

動的解析

Fridaというものを使う。Fridaの使い方は多分別の日に記事にするよ。

AESの256の鍵の長さは32バイト、ivの長さは16バイトであることから動的解析を行いメモリ内の32バイトの値と16バイトの値を取る

そのコードはwriteup先と一緒なので割愛、keyとivが2組出てくるのでそれでデコードを行う。最後のsolverは書いたのでそれだけ載せます

solver

from Crypto.Cipher import AES
import hashlib
import base64

def get_decrypt_data(cipher_data_base64):
    cipher_data = base64.b64decode(cipher_data_base64)
    secret_key = base64.b64decode("AMKyAMuv7U4Us1KTVjb2AGV8QGy7jynAoU+77LatjlQ=")
    iv = base64.b64decode("mT92BqeIHGdJJ2YGjenYqg==")
    crypto = AES.new(secret_key, AES.MODE_CBC, iv)
    raw_data_base64_16byte = crypto.decrypt(cipher_data)
    #raw_data_base64 = raw_data_base64_16byte.split("_")[0]
    #raw_data = base64.b64decode(raw_data_base64)
    return raw_data_base64_16byte

print get_decrypt_data("T9WoXhrsQHgY3NLr8SwBbw==")

AHE17{Frida!}

おわり

なかなか学びを得た問題。Fridaってものをしれたのはでかい