bugku rev1(xman) WP

用JEB查看MainActivityonCreate函数。首先创建了一个CheckClass类的实例c,调用c.a()函数处理输入,最后判断c.check()的返回值。

this.button.setOnClickListener(new View$OnClickListener() {
            public void onClick(View arg4) {
                MainActivity.this.c = new CheckClass();
                MainActivity.this.c.a(MainActivity.this.text.getText().toString());
                if(MainActivity.this.c.check()) {
                    MainActivity.this.textView1.setText("flag is XMAN{" + MainActivity.this.text.getText().toString() + "}");
                }
                else {
                    MainActivity.this.textView1.setText("WORING!");
                }
            }

双击c.a()函数查看一下代码,就是将输入 一个字节一个字节的放入A数组中,没有其他的操作。

public void a(String arg5) {
    int v1 = 30;
    this.A = new byte[v1];
    this.B = arg5.getBytes();
    int v0;
    for(v0 = 0; v0 < arg5.length(); ++v0) {
        this.A[v0] = this.B[v0];
    }

    this.B = new byte[v1];
}

接下来看一下check()函数,这个函数有点长,定义了一个v0,有一个for循环,将v0传入b函数中,然后根据返回的值进行选择操作

public boolean check() {
        boolean v9 = false;
        int[] v0 = new int[]{40, 42, 65, 67, 68, 2, 0x40, 70, 0x60, 98, 0xB5, 7, 10, 0x40, 23, 17, 37, 20, 45, 91, 74, 72, 0x87, 33, 57, 43, 87, 99, 0x93, 53};
        byte[] v5 = new byte[]{52, 0x6F, 102, 0x71, 52, 52, 98};
        int v2 = 0;
        int v4 = 0;
        int v7 = 0;
        int v1;
        for(v1 = 0; v1 < v0.length; ++v1) {
            int v8 = this.b(v0[v1]);
            new String();
            Log.d("now array:", String.valueOf(v8));
            switch(v8) {
                case 0: {
                    this.A[v7] = ((byte)(this.A[v7] ^ v7));
                    break;
                }
                case 1: {
                    if(this.A[v4] != 0) {
                        ++v4;
                    }
                    else {
                    }

                    break;
                }
                case 2: {
                    v5[v4] = ((byte)(v5[v4] ^ v4));
                    ++v4;
                    break;
                }
                case 3: {
                    if(v5[v7] == this.A[v7]) {
                        ++v7;
                    }
                    else {
                    }

                    break;
                }
                case 4: {
                    if(v7 == v4) {
                        v9 = true;
                    }

                    return v9;
                }
                case 5: {
                    if(v4 != v5.length) {
                        v1 = v0.length - 3;
                    }
                    else {
                        v4 = 0;
                    }

                    break;
                }
                default: {
                    ++v2;
                    break;
                }
            }
        }

        return v9;
    }

switch语句中总共有6个分支,我们这个分析一下功能。

case 0:将A数组元素数组下标进行异或A数组就是输入

case 1:计数器的功能。

case 2:将:v5数组元素数组下标进行异或v5数组已经给出了,是一个长度为7的数组

case 3:比较v5A的元素是否相等。

case 4:比较v4v7是否相等,相等的话将v9置为True,v9是返回值,成功的标志。

case 5:对v4进行判断,如果等于v5的长度,那么置0,否则执行v1 = v0.length - 3;

其中v1、v4、v7可以看成i、j、k之类的,方便理解,在JEB中可以通过快捷键n来实现重命名。最终的目的是让返回值v9为True,也就是执行case4,使v4和v7相等v7的值的改变只和case3有关,v4的值通过case1case2case5都会发生改变。

我们看一下b函数b函数的作用是将数字10110101与数组中的数字进行运算,对应位置位1的时候取出数字,相加后得到的数字即为下标,范围是0~5。

public int b(int arg4) {
    int v0 = 0xB5 & arg4;
    return (v0 & 1) + ((v0 & 4) >> 2) + ((v0 & 16) >> 4) + ((v0 & 0x20) >> 5) + ((v0 & 0x80) >> 7);
}

写个脚本跑一下,看看程序是怎么运行的。

def fuc_b(arg4):
    v0 = 0xB5 & arg4
    return (v0 & 1) + ((v0 & 4) >> 2) + ((v0 & 16) >> 4) + ((v0 & 0x20) >> 5) + ((v0 & 0x80) >> 7)

v0 = [40, 42, 65, 67, 68, 2, 0x40, 70, 0x60, 98, 0xB5, 7, 10, 0x40, 23, 17, 37, 20, 45, 91, 74, 72, 0x87, 33, 57, 43, 87, 99, 0x93, 53]
v1 = list(map(fuc_b, v0))
print(v1)
# 结果为[1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 5, 2, 0, 0, 3, 2, 3, 2, 3, 2, 0, 0, 3, 2, 3, 2, 3, 2, 3, 4]

首先case0是异或操作,连续两个case0相当于执行了A[v7] ^ v7 ^ v7没有改动,因为是连续的两个case0,所以v7没有变化,可以忽略掉。

然后注意到前面有8个1(忽略0),也就是执行8case1相当于对你的输入进行计数,如果你的输入长度为7的话,那么v4=7,进入到case5的时候就会重置为0

然后忽略连续的两个0,你会发现是2,3的组合,也就是说执行一次case2就会执行一次case3,也就是v4和v7是同步增加的,实际上就是判断你的输入是否等于v5[v4] ^ v4

最后解题脚本如下

flag = ''
v5 = [52, 0x6F, 102, 0x71, 52, 52, 98]
for i, v in enumerate(v5):
    flag += chr(v^i)
print(flag)
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值