[XCTF] mobile esayjava

下载附件,用jadx打开

安装

看来是校验输入是否为flag

直奔按钮 onClick 事件的代码(本人对主要逻辑部分做了抽取和适当简化)

String inputVal = findViewById(R.id.edit)).getText();
if (b(inputVal)) {
    Toast.makeText(this, "You are right!", 1).show();
    return;
}
Toast.makeText(this, "You are wrong! Bye~", 1).show();

可以看到这部分就是对输入内容用MainActiveity.b()进行校验,那我们再来看看b()函数里有啥


public boolean b(String str) {
    // 首先这里判断flag必须为flag{xxx格式}
    if (str.startsWith("flag{") && str.endsWith("}")) {
        // 这里是截取flag{xxx} 中间的 xx 部分
        String substring = str.substring(5, str.length() - 1);
        b bVar = new b(2);
        a aVar = new a(3);
        StringBuilder sb = new StringBuilder();
        int i = 0;
        for (int i2 = 0; i2 < substring.length(); i2++) {
            char c = aVar.a(bVar.a(substring.charAt(i2)+""));
            sb.append(c);
            int valueOf = bVar.b() / 25;
            if (valueOf > i && valueOf >= 1) {
                i++;
            }
        }
        return sb.toString().equals("wigwrkaugala");
    }
    return false;
}

首先分别调用了a类和b类的有参构造方法创建了a和b的实例,

然后用循环对flag内容每一位做处理,再重新拼接起来

看一眼a和b的构造方法

// Class c
public class a {
    public static ArrayList<Integer> a = new ArrayList<>();
    Integer[] c = {7, 14, 16, 21, 4, 24, 25, 20, 5, 15, 9, 17, 6, 13, 3, 18, 12, 10, 19, 0, 22, 2, 11, 23, 1, 8};
    public a(Integer num) {
        for (int intValue = num; intValue < this.c.length; intValue++) {
            a.add(this.c[intValue]);
        }
        for (int i = 0; i < num; i++) {
            a.add(this.c[i]);
        }
    }
}

public class b {
    public static ArrayList<Integer> a = new ArrayList<>();
    Integer[] c = {8, 25, 17, 23, 7, 22, 1, 16, 6, 9, 21, 0, 15, 5, 10, 18, 2, 24, 4, 11, 3, 14, 19, 12, 20, 13};
    public b(Integer num) {
        for (int intValue = num; intValue < this.c.length; intValue++) {
            a.add(this.c[intValue]);
        }
        for (int i = 0; i < num; i++) {
            a.add(this.c[i]);
        }
    }
}

一通分析发现,不难看出,这就是在对数组c做循环左移的操作。传入num是几就左移几位,结果用a保存。

再对每一位处理的函数进行分析。

aVar.a( bVar.a( substring.charAt(i) ) );

看一下bVar.a()函数做了什么

public class b{
    static String b = "abcdefghijklmnopqrstuvwxyz";
    static Integer d = 0;
    public Integer a(String str) {
        int i = 0;
        if (b.contains(str.toLowerCase())) {
            Integer valueOf = b.indexOf(str);
            for (int i2 = 0; i2 < a.size() - 1; i2++) {
                if (a.get(i2) == valueOf) {
                    i = i2;
                }
            }
        } else {
            i = str.contains(" ") ? -10 : -1;
        }
        a();
        return i;
    }
}

逻辑很简单,就是判断传入的是否是b中26个字母,

如果是的话,找到它在26个字母中的位置,并赋值给valueOf

然后在ArrayList a中遍历比对valueOf的值,然后返回在valueOf在a中的索引赋值给i

那如果传入的不是b中的26个字母的话,再判断是否是空格,如果是的话返回-10,不是的话返回-1

最后再调用一个无参a函数收尾

public class b{
    public static void a() {
        int intValue = a.get(0);
        a.remove(0);
        a.add(intValue);
        b += "" + b.charAt(0);
        b = b.substring(1, 27);
        Integer num = d;
        d = d + 1;
    }
}

可以看出,这里又是对ArrayList a和b字母表做循环左移,也就是说下一次调用的时候a和b的状态会改变。

接下来分析一下外层的aVar.a()。

啊不对,源码都在我手上,分析个锤子,稍作改造,看我爆破

(记得把a和b类中的静态方法和静态变量的static关键字去掉,否则会全局变量值不隔离)

public class MainActivity{
    //去掉外层if,直接返回值
    public static String b(String str) {
        b bVar = new b(2);
        a aVar = new a(3);
        StringBuilder sb = new StringBuilder();
        int i = 0;
        for (int i2 = 0; i2 < str.length(); i2++) {
            sb.append(a(str.charAt(i2) + "", bVar, aVar));
            int valueOf = bVar.b() / 25;
            if (valueOf > i && valueOf >= 1) {
                i++;
            }
        }
        return sb.toString();
    }
}

可以看到字符串某些位置的答案不唯一

比如最后一位可能是i,也可能是r,都试一下了。

 可以看到也都能通过真机测试,经过最后平台测试,答案其实是flag{venividivkcr}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值