题目链接
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
3v10 = _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吧。然后我们再看一下check1/2/3的具体内容,发现其实就是对input做了一些加减操作,然后再传进去,递归调用chec。1
2
3
4if ( num_99 - 1 <= 0 )
result = input_user;
else
result = _JNIEnv::CallIntMethod(vEnv, v9, *(&v10 + 2 * num_99 % 3), input_user, num_99 - 1);
至此我们已经可以写出脚本来算出flag了。
其实就是把它做的操作倒过来走一遍,从输出反推到输入即可。计算得到:2364924081
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
34def 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