2016AliCTF-LoopAndLoop writeup

题目链接

https://github.com/eternalsakura/ctf_pwn/blob/master/android%E9%80%86%E5%90%91/LoopAndLoop.apk

考察知识点

  • native层代码分析

分析

java层

首先用jadx-gui反编译,找到主要逻辑

如果我们能check(input,99)==1835996258,这个input就是flag。
那么check函数是什么呢?

可以看到check函数实际上就是调用chec函数,而chec函数是一个native方法。

native层

找到chec后,修复一些类型和重命名变量。

关于怎么修正,可以看我的另一篇wp

主要代码如下:

  • 首先得到java层的check1/2/3三个函数的MethodID,供调用。
    1
    2
    3
    v10 = _JNIEnv::GetMethodID(vEnv, jclass_MainActivity, "check1", "(II)I");
    v11 = _JNIEnv::GetMethodID(vEnv, jclass_MainActivity, "check2", "(II)I");
    v12 = _JNIEnv::GetMethodID(vEnv, jclass_MainActivity, "check3", "(II)I");
  • 通过*(&v10 + 2 * num_99 % 3)来选择调用哪个函数.
    num%3,得到的结果可能是0,1,2;
    然后以v10为基准来加,emmm,只能解释到这了,再不懂的话看asm吧。

    1
    2
    3
    4
    if ( num_99 - 1 <= 0 )
    result = input_user;
    else
    result = _JNIEnv::CallIntMethod(vEnv, v9, *(&v10 + 2 * num_99 % 3), input_user, num_99 - 1);
    然后我们再看一下check1/2/3的具体内容,发现其实就是对input做了一些加减操作,然后再传进去,递归调用chec。

    至此我们已经可以写出脚本来算出flag了。
    其实就是把它做的操作倒过来走一遍,从输出反推到输入即可。
    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
    def re_check1(input, s):
    t = input
    for i in xrange(1, 100):
    t -= i
    return t

    def re_check2(input, s):
    t = input
    if (s % 2 == 0):
    for i in xrange(1, 1000):
    t -= i
    else:
    for i in xrange(1, 1000):
    t += i
    return t


    def re_check3(input, s):
    t = input
    for i in xrange(1, 10000):
    t -= i
    return t


    if __name__ == '__main__':
    output = 1835996258
    for i in xrange(2, 100):
    if ((2 * i) % 3 == 0):
    output = re_check1(output, i + 1)
    elif ((2 * i) % 3 == 1):
    output = re_check2(output, i + 1)
    else:
    output = re_check3(output, i + 1)
    print output
    计算得到:236492408