XCTF-easyjni

前期工作

查壳无壳

逆向分析

文件结构

image-20200727210718727

MainActivity代码

public class MainActivity extends c {
    static {
        System.loadLibrary("native");
    }

    /* access modifiers changed from: private */
    public boolean a(String str) {
        try {
            return ncheck(new a().a(str.getBytes()));
        } catch (Exception e) {
            return false;
        }
    }

    private native boolean ncheck(String str);

    /* access modifiers changed from: protected */
    public void onCreate(Bundle bundle) {
        super.onCreate(bundle);
        setContentView((int) R.layout.activity_main);
        findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
            public void onClick(View view) {
                if (MainActivity.this.a(((EditText) ((MainActivity) this).findViewById(R.id.edit)).getText().toString())) {
                    Toast.makeText(this, "You are right!", 1).show();
                } else {
                    Toast.makeText(this, "You are wrong! Bye~", 1).show();
                }
            }
        });
    }
}

可以看到点击触发MainActivity的a方法,调用了a类的a方法对输入的字符串处理再对结果用native方法ncheck处理。

来看看a类的a方法

public class a {
    private static final char[] a = {'i', '5', 'j', 'L', 'W', '7', 'S', '0', 'G', 'X', '6', 'u', 'f', '1', 'c', 'v', '3', 'n', 'y', '4', 'q', '8', 'e', 's', '2', 'Q', '+', 'b', 'd', 'k', 'Y', 'g', 'K', 'O', 'I', 'T', '/', 't', 'A', 'x', 'U', 'r', 'F', 'l', 'V', 'P', 'z', 'h', 'm', 'o', 'w', '9', 'B', 'H', 'C', 'M', 'D', 'p', 'E', 'a', 'J', 'R', 'Z', 'N'};

    public String a(byte[] bArr) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i <= bArr.length - 1; i += 3) {
            byte[] bArr2 = new byte[4];
            byte b = 0;
            for (int i2 = 0; i2 <= 2; i2++) {
                if (i + i2 <= bArr.length - 1) {
                    bArr2[i2] = (byte) (b | ((bArr[i + i2] & 255) >>> ((i2 * 2) + 2)));
                    b = (byte) ((((bArr[i + i2] & 255) << (((2 - i2) * 2) + 2)) & 255) >>> 2);
                } else {
                    bArr2[i2] = b;
                    b = 64;
                }
            }
            bArr2[3] = b;
            for (int i3 = 0; i3 <= 3; i3++) {
                if (bArr2[i3] <= 63) {
                    sb.append(a[bArr2[i3]]);
                } else {
                    sb.append('=');
                }
            }
        }
        return sb.toString();
    }
}

又是一个换表的Base64

使用IDA查看so层的ncheck方法,先看看字符串

image-20200727212935214

在最下面看到了个可以的字符串,上面也看到了ncheck的方法名,跟进这个字符串

在IDA导入jni.h的过程中出了点问题,导入后还是无法显示JNI接口函数,参考了https://www.52pojie.cn/thread-503009-1-1.html中的方法解决

选中env变量,按一下“y”键,将_JNIEnv 改成JNIEnv*,即可解决

image-20200727214527923

ncheck代码

image-20200727215015275

第一个dowhile作用为将字符串前后两半互换。

第二个dowhile中__ OFSUB __ 功能是产生(v10-30)的溢出标志位,__ OFSUB __功能参考了

https://blog.csdn.net/youyou519/article/details/103782264

https://jingyan.baidu.com/article/5d6edee23100a3d8eadeecf0.html

因为正数减正数是不会溢出的,所以溢出标志位为0,v12为0。当v10大于或等于30时v11也为0,二者异或为0,所以第二个dowhile的条件其实相当于v10 <= 30。这个循环的功能为将字符串两两互换。

之后和MbT3sQgX039i3g==AQOoMQFPskB1Bsc7比较,相等则返回1。

脚本编写

a = [
    'i', '5', 'j', 'L', 'W', '7', 'S', '0', 'G', 'X', '6', 'u', 'f', '1', 'c',
    'v', '3', 'n', 'y', '4', 'q', '8', 'e', 's', '2', 'Q', '+', 'b', 'd', 'k',
    'Y', 'g', 'K', 'O', 'I', 'T', '/', 't', 'A', 'x', 'U', 'r', 'F', 'l', 'V',
    'P', 'z', 'h', 'm', 'o', 'w', '9', 'B', 'H', 'C', 'M', 'D', 'p', 'E', 'a',
    'J', 'R', 'Z', 'N'
]
s = ''.join(a)


def My_base64_decode(inputs):
    # 将字符串转化为2进制
    bin_str = []
    for i in inputs:
        if i != '=':
            x = str(bin(s.index(i))).replace('0b', '')
            bin_str.append('{:0>6}'.format(x))
    #print(bin_str)
    # 输出的字符串
    outputs = ""
    nums = inputs.count('=')
    while bin_str:
        temp_list = bin_str[:4]
        temp_str = "".join(temp_list)
        #print(temp_str)
        # 补足8位字节
        if (len(temp_str) % 8 != 0):
            temp_str = temp_str[0:-1 * nums * 2]
        # 将四个6字节的二进制转换为三个字符
        for i in range(0, int(len(temp_str) / 8)):
            outputs += chr(int(temp_str[i * 8:(i + 1) * 8], 2))
        bin_str = bin_str[4:]
    print("Decrypted String:\n%s " % outputs)


raw = list('MbT3sQgX039i3g==AQOoMQFPskB1Bsc7')

for i in range(0, len(raw), 2):
    raw[i], raw[i + 1] = raw[i + 1], raw[i]

raw[:16], raw[16:] = raw[16:], raw[:16]

My_base64_decode(''.join(raw))

flag

flag{just_ANot#er_@p3}

posted @ 2020-07-27 22:44  S1mba  阅读(350)  评论(0编辑  收藏  举报