使用在线工具:
python反编译 - 在线工具 (tool.lu)
反编译看到代码后发现这是一个简单的输入验证程序,(注意python的版本)接受一个27个字符长度的字符串,反转该字符串并将其每个字符的ASCII码值加上一个特定的数值和一个与字符串中字符位置相关的查找表中的数值的乘积,然后检查结果是否与一个预定义的列表中的值匹配。如果所有的值都匹配,那么程序输出"you are right!",否则输出"sorry, try again!"。
#!/usr/bin/env python
# visit https://tool.lu/pyc/ for more information
# Version: Python 3.8import sys
# 导入了sys模块,该模块提供了访问Python解释器使用或维护的一些变量和函数的方法
lookup = [
196, 153, 149, 206, 17, 221, 10, 217, 167, 18, 36, 135, 103, 61, 111, 31, 92, 152, 21, 228, 105, 191, 173, 41, 2, 245, 23, 144, 1, 246, 89, 178, 182, 119, 38, 85, 48,
226, 165, 241, 166, 214, 71, 90, 151, 3, 109, 169, 150, 224, 69, 156, 158, 57, 181, 29, 200, 37, 51, 252, 227, 93, 65, 82, 66, 80, 170, 77, 49, 177, 81, 94, 202, 107, 25, 73,
148, 98, 129, 231, 212, 14, 84, 121, 174, 171, 64, 180, 233, 74, 140, 242, 75, 104, 253, 44, 39, 87, 86, 27, 68, 22, 55, 76, 35, 248, 96, 5, 56, 20, 161, 213, 238, 220, 72,
100, 247, 8, 63, 249, 145, 243, 155, 222, 122, 32, 43, 186, 0, 102, 216, 126, 15, 42, 115, 138, 240, 147, 229, 204, 117, 223, 141, 159, 131, 232, 124, 254, 60, 116, 46, 113,
79, 16, 128, 6, 251, 40, 205, 137, 199, 83, 54, 188, 19, 184, 201, 110, 255, 26, 91, 211, 132, 160, 168, 154, 185, 183, 244, 78, 33, 123, 28, 59, 12, 210, 218, 47, 163, 215,
209, 108, 235, 237, 118, 101, 24, 234, 106, 143, 88, 9, 136, 95, 30, 193, 176, 225, 198, 197, 194, 239, 134, 162, 192, 11, 70, 58, 187, 50, 67, 236, 230, 13, 99, 190, 208,
207, 7, 53, 219, 203, 62, 114, 127, 125, 164, 179, 175, 112, 172, 250, 133, 130, 52, 189, 97, 146, 34, 157, 120, 195, 45, 4, 142, 139
]
a = [3, 6, 11, 58, 77, 15, 88, 25, 46, 55, 89, 12, 14, 92, 26, 6, 42, 46, 55, 21, 24, 76, 42, 80, 49, 44, 66]
b = [
6750333, 7110689, 1998965, 3047535, 458873, 3440735, 8290418, 5963887, 5931110, 2162783,
884857, 1343603, 753761, 8126533, 5439583, 6258789, 1671282, 2687065, 3506256, 5439611,
4948067, 2850917, 2162803, 2490485, 3506292, 5800033, 2457720
]
# 这是三个整数列表
flag = input("Input:").strip()
seed = 15
if len(flag) != 27:
print("sorry,try again! number worng!")
sys.exit(1)
flag = flag[::-1]
# 提示用户输入,去掉输入中的任何前导或尾随空格,并检查输入的长度是否为27。如果长度不为27,则打印错误消息并使用错误代码1退出程序。如果长度为27,则反转输入字符串的字符顺序。
for i in range(0, len(flag)):
if ord(flag[i]) + (lookup[i + a[i]] << seed) != b[i]:
print("sorry,try again!")
sys.exit(1)
continue
print("you are right!")
return None
# 这是一个循环,遍历反转后的输入字符串中的每个字符。
# 对于每个字符,它使用位移和加法运算符来计算一个值,并将该值与列表b中的相应值进行比较。
# 如果两个值不相等,则打印错误消息并使用错误代码1退出程序。
# 如果所有值都匹配,则打印成功消息。
# continue语句在这里并不是必需的,因为它只出现在sys.exit(1)语句之后,而该语句会立即退出循环。
为了解密该程序,我们需要逆推出这个加密算法的逆操作,来恢复原始的字符串。具体来说就是我们需要找到一个数值seed,使得对于每个预定义列表中的值b[i],存在一个字符c[i],满足(ord(c[i]) + (lookup[i + a[i]] << seed) == b[i])。这里与if ord(flag[i]) + (lookup[i + a[i]] << seed) != b[i]的逻辑是类推的,其中lookup和a是预定义的查找表。然后尝试使用穷举法来找到合适的seed值。可以尝试seed值从0到31的每个值,检查每个seed值下是否存在一个字符串可以满足上述条件。
实现该算法的Py代码:
lookup = [
196, 153, 149, 206, 17, 221, 10, 217, 167, 18,
36, 135, 103, 61, 111, 31, 92, 152, 21, 228,
105, 191, 173, 41, 2, 245, 23, 144, 1, 246, 89,
178, 182, 119, 38, 85, 48, 226, 165, 241, 166,
214, 71, 90, 151, 3, 109, 169, 150, 224, 69, 156,
158, 57, 181, 29, 200, 37, 51, 252, 227, 93, 65,
82, 66, 80, 170, 77, 49, 177, 81, 94, 202, 107,
25, 73, 148, 98, 129, 231, 212, 14, 84, 121, 174,
171, 64, 180, 233, 74, 140, 242, 75, 104, 253, 44,
39, 87, 86, 27, 68, 22, 55, 76, 35, 248, 96, 5,
56, 20, 161, 213, 238, 220, 72, 100, 247, 8, 63,
249, 145, 243, 155, 222, 122, 32, 43, 186, 0, 102,
216, 126, 15, 42, 115, 138, 240, 147, 229, 204, 117,
223, 141, 159, 131, 232, 124, 254, 60, 116, 46, 113,
79, 16, 128, 6, 251, 40, 205, 137, 199, 83, 54, 188,
19, 184, 201, 110, 255, 26, 91, 211, 132, 160, 168,
154, 185, 183, 244, 78, 33, 123, 28, 59, 12, 210,
218, 47, 163, 215, 209, 108, 235, 237, 118, 101,
24, 234, 106, 143, 88, 9, 136, 95, 30, 193, 176,
225, 198, 197, 194, 239, 134, 162, 192, 11, 70, 58,
187, 50, 67, 236, 230, 13, 99, 190, 208, 207, 7, 53,
219, 203, 62, 114, 127, 125, 164, 179, 175, 112,
172, 250, 133, 130, 52, 189, 97, 146, 34, 157, 120,
195, 45, 4, 142, 139]
# 定义一个名为 lookup 的列表,包含了 256 个整数。这些整数的值在 0 到 255 之间,这个列表用于解密密文
a = [
3, 6, 11, 58, 77, 15, 88, 25, 46, 55, 89, 12,
14, 92, 26, 6, 42, 46, 55, 21, 24, 76, 42, 80,
49, 44, 66]
# 定义一个名为 a 的列表,包含了 27 个整数。这些整数是硬编码的,它们用于解密密文
b = [
6750333, 7110689, 1998965, 3047535, 458873,
3440735, 8290418, 5963887, 5931110, 2162783,
884857, 1343603, 753761, 8126533, 5439583, 6258789,
1671282, 2687065, 3506256, 5439611, 4948067, 2850917,
2162803, 2490485, 3506292, 5800033, 2457720]
# 定义一个名为 b 的列表,包含了 26 个整数。这些整数用于解密密文flag = ''
# 定义一个名为 flag 的字符串,并将其初始化为空字符串
for s in range(32):
# 循环,其中 s 取值从 0 到 31。尝试不同的位移来解密密文
found = True
# 在每个位移 s 上开始循环之前,将 found 标记设置为 True
for i in range(len(b)):
# 循环,其中 i 取值从 0 到 25。这个循环是为了解密密文中的每个字符
v = b[i] - lookup[i + a[i]] * (1 << s)
# 使用预定义的 lookup 和 a 列表,以及当前的位移 s,计算出密文中第 i 个字符的解密值。
# 取出 lookup[i + a[i]] 的值,将其左移 s 位,然后将其从 b[i] 中减去
if v < 0 or v > 255:
# 如果解密出来的值 v 不在 0 到 255 之间,那么解密失败,将 found 标记设置为 False,并跳出内层循环
found = False
break
c = chr(v)
if not c.isprintable():
# 如果解密出来的值 v 对应的字符不是可打印字符,那么解密失败,将 found 标记设置为 False,并跳出内层循环
found = False
break
flag += c
# 如果解密成功,将解密出来的字符 c 添加到 flag 字符串中
if found:
break
# 如果成功解密出 26 个可打印字符,将 found 标记设置为 True,并跳出外层循环
if found:
print("wc nmlgb flag is:", flag)
else:
print("Sorry, ntm ye pei na flag?")
运行该程序,我们得到如下解密结果:**}!uoy_rof_ysaE_erYP{cesutax**,看起来不好看还是反转一下吧
if found:
reversed_flag = flag[::-1]
print("wc nmlgb flag is:", reversed_flag)
else:
print("Sorry, ntm ye pei na flag?")
FLAG:xatusec{PYre_Easy_for_you!}