首页
论坛
课程
招聘
[原创]KCTF2020秋季赛 第四题 突破重围
2020-11-24 23:04 1345

[原创]KCTF2020秋季赛 第四题 突破重围

2020-11-24 23:04
1345

老规矩,直接上jadx,部分函数关键如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView((int) R.layout.activity_main);
        int sdkVersion = VERSION.SDK_INT;
        if (System.getProperty("os.arch").toLowerCase().contains("x86")) {
            Toast.makeText(getApplicationContext(), "This APP is only support arm and arm64,exit......!", 1).show();
            new Thread(new Runnable() {
                public void run() {
                    try {
                        Thread.currentThread();
                        Thread.sleep(5000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.exit(0);
                }
            }).start();
        }
        if (sdkVersion < 24 || sdkVersion > 28) {
            Toast.makeText(getApplicationContext(), "This APP is only support Android 7,Android 7.1,Android 8,Android 8.1,Android 9,exit......!", 1).show();
            new Thread(new Runnable() {
                public void run() {
                    try {
                        Thread.currentThread();
                        Thread.sleep(5000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.exit(0);
                }
            }).start();
        }
        appContext = getApplicationContext();
        final Context tmpcontext = this;
        System.loadLibrary("crack");
        init();
        final EditText inputEditText = (EditText) findViewById(R.id.inputEditText);
        ((Button) findViewById(R.id.checkButton)).setOnClickListener(new OnClickListener() {
            public void onClick(View view) {
                boolean check = MainActivity.this.check(inputEditText.getText().toString());
                CharSequence charSequence = BuildConfig.FLAVOR;
                CharSequence charSequence2 = "result";
                if (check) {
                    new Builder(tmpcontext).setTitle(charSequence2).setMessage("Congratulations! app is exit.....").show();
                    inputEditText.setText(charSequence);
                    new Thread(new Runnable() {
                        public void run() {
                            try {
                                Thread.currentThread();
                                Thread.sleep(5000);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                            System.exit(0);
                        }
                    }).start();
                    return;
                }
                new Builder(tmpcontext).setTitle(charSequence2).setMessage("Sorry,wrong key ,app is exit.....").show();
                inputEditText.setText(charSequence);
                new Thread(new Runnable() {
                    public void run() {
                        try {
                            Thread.currentThread();
                            Thread.sleep(5000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        System.exit(0);
                    }
                }).start();
            }
        });
    }
 
    public void init() {
        String filename = "b.txt";
        copyAssetAndWrite(filename);
        testDexClassLoader(appContext, new File(appContext.getCacheDir(), filename).getAbsolutePath());
    }
 
    public boolean check(String content) {
        DexClassLoader dexClassLoader = dexClassLoader;
        if (dexClassLoader != null) {
            Class<?> clazz = null;
            try {
                clazz = dexClassLoader.loadClass("com.kanxue.crackme.Crack");
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
            if (clazz != null) {
                try {
                    Method testFuncMethod = null;
                    for (Method i : clazz.getDeclaredMethods()) {
                        if (i.getName().contains("check")) {
                            testFuncMethod = i;
                        }
                    }
                    return ((Boolean) testFuncMethod.invoke(null, new Object[]{content})).booleanValue();
                } catch (IllegalAccessException e2) {
                    e2.printStackTrace();
                } catch (InvocationTargetException e3) {
                    e3.printStackTrace();
                }
            }
        }
        return false;
    }

在assets找到 b.txt,实际上是个dex,类反编译后的代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
package com.kanxue.crackme;
 
import android.util.Base64;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
 
public class Crack {
    public static boolean check(String content) {
        if (content != null) {
            if (content.length() == 16) {
                Class MyCrackClass = null;
                Field cryptfield = null;
                byte[] result = crypt(content.getBytes());
                Method crackjni = null;
                try {
                    MyCrackClass = Crack.class.getClassLoader().loadClass("com.kanxue.crackme.MyCrack");
                    cryptfield = MyCrackClass.getDeclaredField("crypt");
                    Method[] methods = MyCrackClass.getDeclaredMethods();
                    for (int i = 0; i < methods.length; i++) {
                        if (methods[i].getName().equals("crackjni")) {
                            crackjni = methods[i];
                        }
                    }
                } catch (ClassNotFoundException e) {
                    e.printStackTrace();
                } catch (NoSuchFieldException e2) {
                    e2.printStackTrace();
                }
                if (crackjni != null) {
                    try {
                        result = (byte[]) crackjni.invoke(null, new Object[]{result});
                    } catch (IllegalAccessException e3) {
                        e3.printStackTrace();
                    } catch (InvocationTargetException e4) {
                        e4.printStackTrace();
                    }
                }
                String finalresult = Base64.encodeToString(crypt(result), 0);
                String cryptcontent = "test";
                if (!(cryptfield == null || MyCrackClass == null)) {
                    try {
                        cryptcontent = (String) cryptfield.get(null);
                    } catch (IllegalAccessException e5) {
                        e5.printStackTrace();
                    }
                }
                if (finalresult.equals(cryptcontent)) {
                    return true;
                }
                return false;
            }
        }
        return false;
    }
 
    public static byte[] crypt(byte[] b_data) {
        String mKkey = "kaokaonio";
        if (b_data == null) {
            return null;
        }
        int i;
        int x = 0;
        int y = 0;
        byte[] b_key = mKkey.getBytes();
        byte[] key = new byte[256];
        for (i = 0; i < 256; i++) {
            key[i] = (byte) i;
        }
        i = 0;
        int index2 = 0;
        if (b_key != null) {
            if (b_key.length != 0) {
                byte tmp;
                for (int i2 = 0; i2 < 256; i2++) {
                    index2 = (((b_key[i] & 255) + (key[i2] & 255)) + index2) & 255;
                    tmp = key[i2];
                    key[i2] = key[index2];
                    key[index2] = tmp;
                    i = (i + 1) % b_key.length;
                }
                byte[] result = new byte[b_data.length];
                for (int i3 = 0; i3 < b_data.length; i3++) {
                    x = (x + 1) & 255;
                    y = ((key[x] & 255) + y) & 255;
                    tmp = key[x];
                    key[x] = key[y];
                    key[y] = tmp;
                    result[i3] = (byte) (b_data[i3] ^ key[((key[x] & 255) + (key[y] & 255)) & 255]);
                }
                return result;
            }
        }
        return null;
    }
}

check函数将input加密后再跟内置的加密flag比较,容易看出crypt方法是RC4算法。那么重点就是crackjni函数
so对字符串做了加密,可以弄个脚本解密,或者直接附加。
crackjni函数主要是把RC4过的输入再做一次AES加密,以及对b.txt这个DEX动一点手脚
图片描述
总结一下input加密流程:RC4("kaokaonio")->AESEncrypt("kaokaonikaokaoni")->RC4("keepGoing")->base64
逆回去搞定了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
from Crypto.Cipher import AES
from Crypto.Cipher import ARC4
 
 
def AESDecrypt(data, key):
    aes1 = AES.new(key)
    encrypted = aes1.decrypt(data)
    return encrypted
 
 
def RC4Decrypt(data, key):
    rc4 = ARC4.new(key)
    decrypted = rc4.decrypt(data)
    return decrypted
 
 
result = 'l+x7fKd2FBaaEY4NV4309A=='.decode('base64')
result = RC4Decrypt(result, 'keepGoing')
result = AESDecrypt(result, 'kaokaonikaokaoni')
print RC4Decrypt(result, 'kaokaonio')

得到flag:flag{thisiskey!}


[招聘] 欢迎你加入看雪团队!

收藏
点赞0
打赏
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回