kcsc-club / ctfs

repository for kscs-ctfs
8 stars 1 forks source link

Oak - rev - Pragyan2022 #25

Closed kudo104 closed 2 years ago

kudo104 commented 2 years ago

Bài Này cho 1 file Oak.class.Mình decomplie ra được đoạn code sau:

public static int t_helper(final int n, final int[] array) {
    if (array[n] != -1) {
        return array[n];
    }
    if (n == 0) {
        return array[0] = 0;
    }
    if (n == 1) {
        return array[1] = 1;
    }
    if (n == 2) {
        return array[2] = 3;
    }
    return array[n] = 3 * t_helper(n - 1, array) - 3 * t_helper(n - 2, array) + t_helper(n - 3, array);
}

public static int t(final int n) {
    final int[] array = new int[n + 1];
    for (int i = 0; i < array.length; ++i) {
        array[i] = -1;
    }
    return t_helper(n, array);
}

public static void main(final String[] array) {
    if (array.length != 1) {
        System.out.println("Usage: [flag]");
        return;
    }
    if (check(array[0])) {
        System.out.println("Correct!");
    }
    else {
        System.out.println("Incorrect");
    }
}

public static long[] conv(final String s) {
    final long[] array = new long[s.length()];
    for (int i = 0; i < s.length(); ++i) {
        array[i] = (s.charAt(i) << 8) + s.charAt((i + 1) % s.length());
    }
    return array;
}

public static boolean check(final String s) {
    final long[] conv = conv(s);
    for (int i = 0; i < conv.length; ++i) {
        if (Oak.data[i] != (conv[i] ^ (long)t(i * i))) {
            return false;
        }
    }
    return true;
}

static {
    Oak.data = new long[] { 28767L, 24418L, 25470L, 29771L, 26355L, 31349L, 13032L, 30456L, 14663L, 27592L, 8916L, 29409L, 7348L, 17474L, 5124L, 3345L, 49357L, 61058L, 65159L, 53773L, 67886L, 72426L, 103728L, 158125L, 179542L, 166504L, 212101L, 282674L, 320873L, 329272L, 400021L, 479881L, 535081L, 599886L, 662294L, 731441L, 831284L, 947032L, 1021482L };
}

}

Sau một lúc phân tích đoạn code thì được 1 chỗ quan trọng:

public static boolean check(final String s) {
    final long[] conv = conv(s);
    for (int i = 0; i < conv.length; ++i) {
        if (Oak.data[i] != (conv[i] ^ (long)t(i * i))) {
            return false;
        }
    }
    return true;
}

Tại hàm này thực hiện kiểm tra flag bằng vòng lặp kiểm tra từng kí tự và mình cũng không cần quan tâm hàm conv và hàm t làm gì.Để lấy flag mình chỉ cần thực hiện (Oak.data[i] ^ (long)t(i*i)) & 0xff.

ArrayList<Long> arr = new ArrayList<Long>(); 
for(int i = 0;i < 39;i++) {
    arr.add((Oak.data[i] ^ t(i*i)) & 0xff ); 
}

Flag:

p_ctf{0r1g1n4|_n@M3-0f_J4vA_Wa5_()/\|<}
TsukasaYuzaki commented 2 years ago

Cho em xin bổ xung cho mọi người hiểu sâu 1 chút là hàm conv() đơn giản là nối 2 ký tự liên tiếp thành 1 và đổi sang decimal.

Hàm check là xor thêm cái đó với t(i*i)

Nên các giá trị trong mảng Oak là từ 2 kí tự liên tiếp của flag nối với nhau (0,1), (1,2), (2,3),... Sau đó xor với t(i*i)