simple
反编译发现动态解密了assets中的zip文件,由于解密的dex会落地因此可以直接运行后从文件目录中pull出来
再反编译这个load.dex,onClick函数中接收了24个字符并以每8个字符一组构造Square,最后调用其中的check函数要求全部为True
构造方法为
new Square((v1[i + x] << 8) + v12 + 255, i / 2 + 4);
这里的i取值范围为{0, 8, 16},x取值范围为[0, 7]
即
a1 = 0x315f00ff | (input[i*8+x]<<8)
即4字节a1的第二字节为input的那个字节,其他字节固定
a2 = i/2+4
还要注意要求每组中的后一个字符大于前一个字符
于是继续查看Square内部的方法
构造方法显示每个Square内有5x5=25个Point
a1为input,a2为turncout
Square(int arg2, int arg3) {
super();
this.point = new Point[25];
this.input = arg2;
this.turncout = arg3;
this.initpoint();
if(this.check()) {
this.turnpoint();
}
}
通过initpoint()方法来为25个Point赋值
简单来说就是从右往左逐位取值
对于a1而言,每个Squre如下所示
0 | 1 | 2 | 3 | 4 |
---|---|---|---|---|
1 | 1 | 1 | 1 | 1 |
1 | 1 | 1 | input7 | input6 |
input5 | input4 | input3 | input2 | input1 |
input0 | 1 | 1 | 1 | 1 |
1 | 0 | 1 | 0 | 1 |
check方法则很简单
Point[i][i]和Point[4-i][i]皆为1即可,即两条对角线上的Point要求为1
turnpoint也并不复杂,循环将每个Point左移一位,最左边的Point顺位移到上一行的最后一位。循环执行的次数为turncout,即参数a2
函数理清以后梳理一下逻辑
目标是最终check成功,那么必然构造Squre时的check也必须成功,即要求每个Squre构造好以后check()==True -> turnopint() -> check()==True
解题思路为首先构造符合check()的Squre,然后按照turnpoint反向右移,再符合check()一次,此时的Squre为通解
再为了满足每组中input[i]
c = [0 for i in range(25)]
l = [4, 8, 12]
a = []
def v(c):
for i in range(5):
c[i*5+i] = 1
c[i*5+4-i] = 1
for i in range(5):
print(c[i*5:i*5+5])
def getr(c):
return c[8:16][::-1]
v(c)
print()
for x in l:
a.append(c[-x:] + c[:-x])
for k in a:
v(k)
r = getr(k)
print("Input :")
print(r)
print()
得到符合要求的input通解,例如
[1, 0, 0, 1, 1]
[0, 1, 0, 1, 0]
[1, 0, 1, 0, 0]
[0, 1, 0, 1, 0]
[1, 0, 1, 0, 1]
Input :
[0, 0, 0, 1, 0, 1, 0, 1]
然后根据0b00010101逐步递增求解input值即可
脚本如下:
s = [0b00010101, 0b01010001, 0b00011001]
print("SCTF{", end='')
for x in s:
l = 48
for i in range(8):
while((l&x)<x):
l += 1
print(chr(l), end='')
l += 1
print("}")
PS:这flag是真的丑
Where is my 13th count?
运行发现只有12个球可得分,根据题目来看应该需要第13分
文件名提示CheatEngine,但运行会闪退
反编译Cheat Engine_Data\Managed
目录下的Assembly-CSharp.dll,查看逻辑,发现有反调试
不过主逻辑都已经是囊中之物了,还CE个锤子呀,直接改count的初值为12,运行游戏吃一个球即可满足条件出现flag
PS:这flag更丑了