[collapse title=“展开查看详情” status=“false”]
考点:手撕算法
部分函数名已重命名,懒得再找一份原题QAQ
开门见山,mainactivity 就能找到加密算法入口。函数将输入值剔除flag{}
,然后传入加密函数。
private static Boolean b(String string) { // 结尾}
Boolean result;
int index = 0;
if(!string.startsWith("flag{")) { // 开头flag{
result = Boolean.valueOf(false);
}
else if(!string.endsWith("}")) {
result = Boolean.valueOf(false);
}
else {
String string_1 = string.substring(5, string.length() - 1); // 分割字符串去除flag{}
Mb v4 = new Mb(Integer.valueOf(2));
Ma v5 = new Ma(Integer.valueOf(3));
StringBuilder c_string = new StringBuilder();
int v1 = 0;
while(index < string_1.length()) {
c_string.append(MainActivity.a(string_1.charAt(index) + "", v4, v5)); //加密函数
Integer v6 = Integer.valueOf(v4.b().intValue() / 25);
if(v6.intValue() > v1 && v6.intValue() >= 1) {
++v1;
}
++index;
}
result = Boolean.valueOf(c_string.toString().equals("wigwrkaugala"));
}
return result;
}
加密函数有两层最后调用为:
private static char a(String string, Mb b, Ma a) {
return a.a(b.a(string));
}
a b 加密逻辑大致一样,处理对象都是单字符,进行混淆后,对密钥进行更新。
b 加密函数主要如下:(忽略处理空格和字符不存在情况)
Mb.key_list = "abcdefghijklmnopqrstuvwxyz";
public Integer a(String string) {
int v0 = 0;
Integer v1 = Integer.valueOf(0);
if(Mb.key_list.contains(string.toLowerCase())) { // 转为小写,然后查询在不在key中
Integer index = Integer.valueOf(Mb.key_list.indexOf(string));
while(v0 < Mb.a_ArrayList.size() - 1) {
if(Mb.a_ArrayList.get(v0) == index) {
v1 = Integer.valueOf(v0);
}
++v0;
}
}
…………
Mb.a();
return v1;
}
加密操作为:检索字符在keylisit
的下标,记为index
,然后检索index
在a_ArrayList
的下标,记为v1
,检索成功就调用Mb.a()
生成新的密钥keylist
和a_ArrayList
,然后返回v1
。
a_ArrayList
不是一个静态变量,是经由public Mb(Integer arg9)
生成的,一开始以为动态生成的,然后动态调试了一下,发现是第一次调用时生成好了,后续字符加密沿用上一字符密钥。生成的偏移为 2 。
Mb.a()
处理逻辑就是:每一轮加密完成后,将两个密钥的首元素放置到最后一位。
public static void a() {
int v0 = Mb.a_ArrayList.get(0).intValue();
Mb.a_ArrayList.remove(0);
Mb.a_ArrayList.add(Integer.valueOf(v0)); // 将列表首个元素放到最后
Mb.key_list = Mb.key_list + "" + Mb.key_list.charAt(0);
Mb.key_list = Mb.key_list.substring(1, 27); // 将列表首个元素放到最后
Mb.d = Integer.valueOf(Mb.d.intValue() + 1); // 某个计算位加1
}
a.a(b.a(string))
b 函数加密完成后,返回值作为参数传入 a ,加密方式与 b 相近,较大不同点是每轮加密不会随机化密钥,密钥初始偏移为 3 。因为从最后判断函数可知 flag 中间字符为 12 位,不足以触发 a 随机化密钥函数要求。
解密EXP
from collections import deque # 双端队列简化随机密钥实现
alpha = deque("abcdefghijklmnopqrstuvwxyz")
#key_b = deque([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])
#key_a = deque([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])
key_b = deque([17, 23, 7, 22, 1, 16, 6, 9, 21, 0, 15, 5, 10, 18, 2, 24, 4, 11, 3, 14, 19, 12, 20, 13, 8, 25])
key_a = deque([21, 4, 24, 25, 20, 5, 15, 9, 17, 6, 13, 3, 18, 12, 10, 19, 0, 22, 2, 11, 23, 1, 8, 7, 14, 16])
c = 'wigwrkaugala'
def decode(s):
i = key_a[(ord(s) - ord('a'))]
i = key_b[(i)]
print(alpha[i], end='')
key_b.append(key_b.popleft())
alpha.append(alpha.popleft())
print("flag{",end='')
for s in c: decode(s)
print("}")
提交 flag 后看评论区好像题目有多解。
[/collapse]