XYCTF 2025 WriteUp

19k 词

驱动题直到最后也是零解,之前腾讯也出了个驱动,看来该抽时间好好学学驱动相关了…

本次比赛搞笑事件颇多(),包括但不限于:
因为之前做了NPC²CTF的babyvm,所以ezvm不小心非预期了(
出题人更换附件时和出题人聊天走神导致被抢一血(
做EzObf的时候有点入迷了,没发现附件更新了,不过本来剩下的时间也不够了就是了(

Crypto方向:

reed:

发现是仿射密码,flag的中间段在字符集中的索引(0~61)被使用c = (a * index + b) mod 19198111的方式进行仿射加密,其中ab为随机数,考虑一种情况:若a、b均为极小值,则a * index + b不足以被mod 19198111,连接靶机进行获取:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
import socket
import string

HOST = '8.147.132.32'
PORT = 36002
SEED = "0"
table = string.ascii_letters + string.digits

def fetch_encrypted_data():
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.connect((HOST, PORT))
s.recv(1024)
s.sendall(f"{SEED}\n".encode())
data = s.recv(1024).decode()
enc = eval(data.strip())
return enc

index = 0
while True:
enc = fetch_encrypted_data()
print(f"Processing sample {index + 1}: {enc}")
index += 1

encs = sorted(enc)
delta = []
for i in range(len(encs) - 1):
if encs[i + 1] - encs[i] != 0 and (encs[i + 1] - encs[i]) not in delta:
delta.append(encs[i + 1] - encs[i])
if not delta:
print("No valid deltas found, skipping...\n")
continue
a = min(delta)

valid = True
for i in range(len(encs) - 1):
if (encs[i + 1] - encs[i]) % a != 0:
print("Delta validation failed, skipping...\n")
valid = False
break

if not valid:
continue

m = []
for c in enc:
index = (c - min(enc)) // a
if index < 0 or index >= len(table):
print("Index out of range, skipping...\n")
valid = False
break
m.append(index)

if not valid:
continue
print(f"offsets: {m}")

返回一组数据:

1
2
3
4
5
[3628596, 3628596, 3437163, 3373352, 3628596, 3437163, 6691524, 6500091, 5542926, 
6755335, 6819146, 6053414, 6117225, 6500091, 6181036, 5798170, 6500091, 5861981,
5861981, 6117225, 6819146, 7010579, 6181036, 6627713, 6755335, 5925792, 6117225,
5734359, 5861981, 3628596, 3118108, 3628596, 3118108, 3181919, 3628596, 3692407]

计算得其公差d为63811,最小值3118108,均极小,且全部数据均遵循该公差,则该组数据符合要求,得到偏移量:[8, 8, 5, 4, 8, 5, 56, 53, 38, 57, 58, 46, 47, 53, 48, 42, 53, 43, 43, 47, 58, 61, 48, 55, 57, 44, 47, 41, 43, 8, 0, 8, 0, 1, 8, 9],解密得到iifeif41M56UV1WQ1RRV69W35SVPRiaiabij,发现不对,考虑到a有可能为负值,计算61减去对应索引,得到flag:XYCTF{114514fixedpointissodangerous1919810}.

脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import string

table = string.ascii_letters + string.digits

enc = [3628596, 3628596, 3437163, 3373352, 3628596, 3437163, 6691524, 6500091, 5542926,
6755335, 6819146, 6053414, 6117225, 6500091, 6181036, 5798170, 6500091, 5861981,
5861981, 6117225, 6819146, 7010579, 6181036, 6627713, 6755335, 5925792, 6117225,
5734359, 5861981, 3628596, 3118108, 3628596, 3118108, 3181919, 3628596, 3692407]

encs = sorted(enc)
delta = []

for i in range(len(encs)-1):
if not encs[i+1]-encs[i] in delta and not encs[i+1]-encs[i] == 0:
delta.append(encs[i+1]-encs[i])
print(f"deltas: {sorted(delta)}")
a = min(delta)
for i in range(len(encs)-1):
assert (encs[i+1]-encs[i]) % a == 0
print(f"a = {a}")
m = []
for i in range(len(enc)):
m.append((enc[i] - min(enc)) // a)
print(f"delta times of a = {m}")
for i in range(len(m)):
print(table[61-m[i]],end="")
print()

勒索病毒:

题目给了一个enc文件和一个exe,解析发现该exe为python打包,pyinstxtractor解包,pycdc反编译得到主代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
import re
import base64
import os
import sys
from gmssl import sm4
from Crypto.Util.Padding import pad
import binascii
from random import shuffle, randrange

N = 49
p = 3
q = 128
d = 3
assert q > (6 * d + 1) * p
R.<x> = ZZ[]
def generate_T(d1, d2):
assert N >= d1 + d2
s = [1] * d1 + [-1] * d2 + [0] * (N - d1 - d2)
shuffle(s)
return R(s)

def invert_mod_prime(f, p):
Rp = R.change_ring(Integers(p)).quotient(x^N - 1)
return R(lift(1 / Rp(f)))

def convolution(f, g):
return (f * g) % (x^N - 1)

def lift_mod(f, q):
return R([((f[i] + q // 2) % q) - q // 2 for i in range(N)])

def poly_mod(f, q):
return R([f[i] % q for i in range(N)])

def invert_mod_pow2(f, q):
assert q.is_power_of(2)
g = invert_mod_prime(f, 2)
while True:
r = lift_mod(convolution(g, f), q)
if r == 1:
return g
g = lift_mod(convolution(g, 2 - r), q)

def generate_message():
return R([randrange(p) - 1 for _ in range(N)])

def generate_key():
while True:
try:
f = generate_T(d + 1, d)
g = generate_T(d, d)
Fp = poly_mod(invert_mod_prime(f, p), p)
Fq = poly_mod(invert_mod_pow2(f, q), q)
break
except:
continue
h = poly_mod(convolution(Fq, g), q)
return h, (f, g)

def encrypt_message(m, h):
e = lift_mod(p * convolution(h, generate_T(d, d)) + m, q)
return e

def save_ntru_keys():
h, secret = generate_key()
with open("pub_key.txt", "w") as f:
f.write(str(h))
m = generate_message()
with open("priv_key.txt", "w") as f:
f.write(str(m))
e = encrypt_message(m, h)
with open("enc.txt", "w") as f:
f.write(str(e))

def terms(poly_str):
terms = []
pattern = r'([+-]?\s*x\^?\d*|[-+]?\s*\d+)'
matches = re.finditer(pattern, poly_str.replace(' ', ''))

for match in matches:
term = match.group()
if term == '+x' or term == 'x':
terms.append(1)
elif term == '-x':
terms.append(-1)
elif 'x^' in term:
coeff_part = term.split('x^')[0]
exponent = int(term.split('x^')[1])
if not coeff_part or coeff_part == '+':
coeff = 1
elif coeff_part == '-':
coeff = -1
else:
coeff = int(coeff_part)
terms.append(coeff * exponent)
elif 'x' in term:
coeff_part = term.split('x')[0]
if not coeff_part or coeff_part == '+':
terms.append(1)
elif coeff_part == '-':
terms.append(-1)
else:
terms.append(int(coeff_part))
else:
if term == '+1' or term == '1':
terms.append(0)
terms.append(-0)
return terms

def gen_key(poly_terms):
binary = [0] * 128
for term in poly_terms:
exponent = abs(term)
if term > 0 and exponent <= 127:
binary[127 - exponent] = 1
binary_str = ''.join(map(str, binary))
hex_key = hex(int(binary_str, 2))[2:].upper().zfill(32)
return hex_key

def read_polynomial_from_file(filename):
with open(filename, 'r') as file:
return file.read().strip()

def sm4_encrypt(key, plaintext):
assert len(key) == 16, "SM4 key must be 16 bytes"
cipher = sm4.CryptSM4()
cipher.set_key(key, sm4.SM4_ENCRYPT)
padded_plaintext = pad(plaintext, 16)
return cipher.crypt_ecb(padded_plaintext)

def sm4_encrypt_file(input_path, output_path, key):
with open(input_path, 'rb') as f:
plaintext = f.read()

ciphertext = sm4_encrypt(key, plaintext)

with open(output_path, 'wb') as f:
f.write(ciphertext)

def resource_path(relative_path):
if getattr(sys, 'frozen', False):
base_path = sys._MEIPASS
else:
base_path = os.path.abspath(".")
return os.path.join(base_path, relative_path)

def encrypt_directory(directory, sm4_key, extensions=[".txt"]):
if not os.path.exists(directory):
print(f"Directory does not exist: {directory}")
return

for root, _, files in os.walk(directory):
for file in files:
if any(file.endswith(ext) for ext in extensions):
input_path = os.path.join(root, file)
output_path = input_path + ".enc"

try:
sm4_encrypt_file(input_path, output_path, sm4_key)
os.remove(input_path)
print(f"Encrypted: {input_path} -> {output_path}")
except Exception as e:
print(f"Error encrypting {input_path}: {str(e)}")

def main():
try:
save_ntru_keys()
poly_str = read_polynomial_from_file("priv_key.txt")
poly_terms = terms(poly_str)
sm4_key = binascii.unhexlify(poly_terms)
user_name = os.getlogin()
target_dir = os.path.join("C:\Users", user_name, "Desktop", "test_files")

if not os.path.exists(target_dir):
os.makedirs(target_dir, exist_ok=True)
print(f"Created directory: {target_dir}")
return

txt_files = [f for f in os.listdir(target_dir)
if f.endswith('.txt') and os.path.isfile(os.path.join(target_dir, f))]

if not txt_files:
print("No .txt files found in directory")
return

for txt_file in txt_files:
file_path = os.path.join(target_dir, txt_file)
try:
with open(file_path, 'rb') as f:
test_data = f.read()

ciphertext = sm4_encrypt(sm4_key, test_data)
encrypted_path = file_path + '.enc'

with open(encrypted_path, 'wb') as f:
f.write(ciphertext)
except Exception as e:
print(f"Error processing {txt_file}: {str(e)}")

except Exception as e:
print(f"Fatal error: {str(e)}")

if __name__ == "__main__":
main()

发现了一个NTRU和一个SM4加密,NTRU加密了SM4的密钥,同时在解包时找到了enc.txt和公钥,注意到enc.txt中有两个多项式,其中一个标记为e,另一个多项式则显得十分简单:-x^48 - x^46 + x^45 + x^43 - x^42 + x^41 + x^40 + x^36 - x^35 + x^34 - x^33 + x^32 - x^30 + x^29 - x^28 - x^27 - x^26 - x^25 - x^23 - x^22 + x^21 + x^20 + x^19 + x^18 - x^17 - x^16 - x^15 - x^14 - x^12 + x^9 - x^7 - x^6 - x^5 - x^4 + x^3 - x + 1,系数只有±1,合理猜测这个可能是e对应的m,编写sagemath脚本计算SM4的密钥:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
import re
import binascii
from sage.all import *
R.<x> = PolynomialRing(ZZ, 'x')
N = 49
m = -x^48 - x^46 + x^45 + x^43 - x^42 + x^41 + x^40 + x^36 - x^35 + x^34 - x^33 + x^32 - x^30 + x^29 - x^28 - x^27 - x^26 - x^25 - x^23 - x^22 + x^21 + x^20 + x^19 + x^18 - x^17 - x^16 - x^15 - x^14 - x^12 + x^9 - x^7 - x^6 - x^5 - x^4 + x^3 - x + 1
poly_str = str(m)
def terms(poly_str):
terms = []
pattern = r'([+-]?\s*x\^?\d*|[-+]?\s*\d+)'
matches = re.finditer(pattern, poly_str.replace(' ', ''))
for match in matches:
term = match.group()
if term == '+x' or term == 'x':
terms.append(1)
elif term == '-x':
terms.append(-1)
elif 'x^' in term:
coeff_part = term.split('x^')[0]
exponent = int(term.split('x^')[1])
if not coeff_part or coeff_part == '+':
coeff = 1
elif coeff_part == '-':
coeff = -1
else:
coeff = int(coeff_part)
terms.append(coeff * exponent)
elif 'x' in term:
coeff_part = term.split('x')[0]
if not coeff_part or coeff_part == '+':
terms.append(1)
elif coeff_part == '-':
terms.append(-1)
else:
terms.append(int(coeff_part))
else:
if term == '+1' or term == '1':
terms.append(0)
terms.append(-0)
return terms
poly_terms = terms(poly_str)
def gen_key(poly_terms):
binary = [0] * 128
for term in poly_terms:
exponent = abs(term)
if term > 0 and exponent <= 127:
binary[127 - exponent] = 1
binary_str = ''.join(map(str, binary))
hex_key = hex(int(binary_str, 2))[2:].upper().zfill(32)
return binascii.unhexlify(hex_key)
sm4_key = gen_key(poly_terms)
print("Generated SM4 key (hex):", sm4_key.hex().upper())
print("Generated SM4 key (bytes):", sm4_key)

运行得到密钥:

1
2
3
(sage-sh) LENOVO@BY-OTSA-Ultima-001:Sage$ sage find.sage
Generated SM4 key (hex): 000000000000000000002B15203C0208
Generated SM4 key (bytes): b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00+\x15 <\x02\x08'

解密得到flag:XYCTF{Crypto0_can_n0t_So1ve_it}.

Reverse方向:

WARMUP:

用python脚本解析原VBscript中的chr内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import re

vbscript = """
Execute(chr( 667205/8665 ) & chr( -7671+7786 ) & chr( 8541-8438 ) & chr( 422928/6408 ) & chr( -1948+2059 ) & chr( -3066+3186 ) & chr( 756-724 ) & chr( 4080/120 ) & chr( -3615+3683 ) & chr( -1619+1720 ) & chr( -2679+2776 ) & chr( 659718/5787 ) & chr( 302752/9461 ) & chr( -6627+6694 ) & chr( -4261+4345 ) & chr( 81690/1167 ) & chr( 636180/9220 ) & chr( 538658/6569 ) & chr( -1542+1588 ) & chr( -1644+1676 ) & chr( 122184/1697 ) & chr( 966411/9963 ) & chr( 2186-2068 ) & chr( -5283+5384 ) & chr( 305056/9533 ) & chr( 66402/651 ) & chr( 1141452/9756 ) & chr( 882090/8019 ) & chr( -4243+4275 ) & chr( 2669-2564 ) & chr( 83+27 ) & chr( 254880/7965 ) & chr( -1291+1379 ) & chr( -4699+4788 ) & chr( 4730-4663 ) & chr( -1179+1263 ) & chr( 5274-5204 ) & chr( 210144/6567 ) & chr( -6803+6853 ) & chr( 6655-6607 ) & chr( 4067-4017 ) & chr( 121900/2300 ) & chr( -6158+6191 ) & chr( 11934/351 ) & chr( 64883/4991 ) & chr( 65420/6542 ) & chr( 3781-3679 ) & chr( 1612-1504 ) & chr( 892788/9204 ) & chr( 927618/9006 ) & chr( -6692+6724 ) & chr( 410591/6731 ) & chr( 6675-6643 ) & chr( 697880/9560 ) & chr( 4250-4140 ) & chr( 5464-5352 ) & chr( -1082+1199 ) & chr( 3343-3227 ) & chr( 1211-1145 ) & chr( 482406/4346 ) & chr( -5549+5669 ) & chr( -5150+5190 ) & chr( 4400-4366 ) & chr( -3277+3346 ) & chr( -6649+6759 ) & chr( -5669+5785 ) & chr( -6734+6835 ) & chr( 9757-9643 ) & chr( 109-77 ) & chr( 5620-5504 ) & chr( -2887+2991 ) & chr( -3081+3182 ) & chr( -5109+5141 ) & chr( 699860/9998 ) & chr( -3603+3679 ) & chr( 1631-1566 ) & chr( 445-374 ) & chr( 294118/5071 ) & chr( -1115+1149 ) & chr( 222376/5054 ) & chr( 8137-8105 ) & chr( -1653+1687 ) & chr( 357104/4058 ) & chr( 1650-1561 ) & chr( -9501+9568 ) & chr( 1047-963 ) & chr( 2540-2470 ) & chr( 1692-1658 ) & chr( 9947-9906 ) & chr( 9186-9173 ) & chr( -2846+2856 ) & chr( 425187/3573 ) & chr( -3066+3167 ) & chr( 2850-2748 ) & chr( -2992+3090 ) & chr( 958230/8190 ) & chr( 869295/7305 ) & chr( 3380-3275 ) & chr( -7338+7455 ) & chr( 408848/4048 ) & chr( 9211-9179 ) & chr( -2437+2498 ) & chr( 1672-1640 ) & chr( 2378-2344 ) & chr( 544749/9557 ) & chr( 351120/7315 ) & chr( 773800/7738 ) & chr( 2033-1931 ) & chr( -8059+8111 ) & chr( -4731+4783 ) & chr( -9204+9252 ) & chr( -4261+4316 ) & chr( 850521/8421 ) & chr( -7011+7112 ) & chr( 292272/6089 ) & chr( -8609+8666 ) & chr( -2921+2972 ) & chr( 6772-6672 ) & chr( 487611/9561 ) & chr( -6754+6802 ) & chr( 464835/8155 ) & chr( -939+987 ) & chr( 421173/7389 ) & chr( -8145+8201 ) & chr( 9368-9268 ) & chr( -7682+7738 ) & chr( -8646+8699 ) & chr( 484612/4996 ) & chr( 286832/5516 ) & chr( -9710+9760 ) & chr( 884156/9022 ) & chr( 7080-6979 ) & chr( 265477/5009 ) & chr( 6+49 ) & chr( 5395-5298 ) & chr( 6645-6595 ) & chr( -9706+9763 ) & chr( -6697+6752 ) & chr( 927-870 ) & chr( 4048-3946 ) & chr( 34398/702 ) & chr( 825675/8175 ) & chr( -438+491 ) & chr( 87808/1792 ) & chr( -2601+2653 ) & chr( 420228/7782 ) & chr( -5266+5317 ) & chr( 53059/547 ) & chr( 477054/9354 ) & chr( 9238-9189 ) & chr( 799112/7912 ) & chr( 3340-3284 ) & chr( 8544-8444 ) & chr( 1220-1171 ) & chr( -7192+7245 ) & chr( 73629/729 ) & chr( 6523-6473 ) & chr( 2761-2659 ) & chr( 358124/3692 ) & chr( -6167+6266 ) & chr( -3842+3894 ) & chr( 7840-7739 ) & chr( -3980+4036 ) & chr( 987-935 ) & chr( 6868/68 ) & chr( -559+656 ) & chr( 6513-6465 ) & chr( 843300/8433 ) & chr( -8159+8261 ) & chr( -753+807 ) & chr( 278700/5574 ) & chr( 5600/112 ) & chr( -549+646 ) & chr( -7697+7750 ) & chr( 390292/7364 ) & chr( 988020/9980 ) & chr( -3250+3302 ) & chr( 6295-6195 ) & chr( 4342-4242 ) & chr( -9602+9704 ) & chr( 1312-1214 ) & chr( 1065-1012 ) & chr( 1122/22 ) & chr( 191012/3604 ) & chr( 330775/3275 ) & chr( 226848/2224 ) & chr( 4973-4922 ) & chr( 369357/3657 ) & chr( -7229+7282 ) & chr( 588/12 ) & chr( 57570/570 ) & chr( 4554-4498 ) & chr( 483924/4938 ) & chr( 485600/9712 ) & chr( 5051-4998 ) & chr( 8467-8417 ) & chr( -6799+6855 ) & chr( 668360/6820 ) & chr( 428008/7643 ) & chr( -309+359 ) & chr( -7495+7549 ) & chr( 198200/1982 ) & chr( -4298+4351 ) & chr( 2979-2928 ) & chr( -391+443 ) & chr( -5951+6006 ) & chr( -2271+2372 ) & chr( 1431-1382 ) & chr( -2812+2866 ) & chr( 4906-4853 ) & chr( -5308+5365 ) & chr( -8587+8636 ) & chr( -1003+1053 ) & chr( 468741/4641 ) & chr( 8449-8392 ) & chr( 14877/261 ) & chr( -5097+5146 ) & chr( 6695-6646 ) & chr( -2866+2922 ) & chr( 483786/9486 ) & chr( -4142+4193 ) & chr( 2347-2296 ) & chr( -1784+1833 ) & chr( 116229/2193 ) & chr( -1099+1148 ) & chr( 8230-8180 ) & chr( -4351+4406 ) & chr( 1975-1924 ) & chr( 779229/7871 ) & chr( 102960/1040 ) & chr( 67830/1330 ) & chr( -4771+4873 ) & chr( -32+129 ) & chr( 155456/2776 ) & chr( 9798-9700 ) & chr( 4944-4894 ) & chr( -2496+2594 ) & chr( 5495-5444 ) & chr( 8113-8015 ) & chr( -8444+8496 ) & chr( 3896-3847 ) & chr( 6306-6255 ) & chr( 1284-1185 ) & chr( 1003986/9843 ) & chr( -1321+1371 ) & chr( 2676-2578 ) & chr( -5421+5521 ) & chr( 564186/5757 ) & chr( 6608-6559 ) & chr( 7038-6937 ) & chr( 209720/3745 ) & chr( -616+715 ) & chr( 9766-9709 ) & chr( 2111-2012 ) & chr( 528993/9981 ) & chr( 1901-1851 ) & chr( 281344/5024 ) & chr( 5695-5641 ) & chr( 4815-4762 ) & chr( 399556/3956 ) & chr( 572730/5615 ) & chr( -5718+5817 ) & chr( 21+27 ) & chr( 4532-4475 ) & chr( -8446+8499 ) & chr( 5786-5689 ) & chr( 4177-4121 ) & chr( -8411+8511 ) & chr( -9499+9599 ) & chr( 479528/8563 ) & chr( 6850-6793 ) & chr( -3725+3823 ) & chr( -8692+8743 ) & chr( 284298/2901 ) & chr( 214302/4202 ) & chr( 576675/5825 ) & chr( -4565+4667 ) & chr( -7223+7321 ) & chr( 383278/3911 ) & chr( -2540+2590 ) & chr( 35+13 ) & chr( -5549+5597 ) & chr( 969122/9889 ) & chr( 964712/9844 ) & chr( -6231+6328 ) & chr( -1560+1660 ) & chr( -7416+7514 ) & chr( 609144/5972 ) & chr( 471432/9066 ) & chr( -4500+4597 ) & chr( 8620-8566 ) & chr( 7113-7014 ) & chr( -2488+2588 ) & chr( -3599+3651 ) & chr( 211956/6234 ) & chr( 1697-1665 ) & chr( -5122+5161 ) & chr( -3189+3221 ) & chr( -5840+114 ) & chr( -37790+6278 ) & chr( -8.231351E+07/3957 ) & chr( -14110+7864 ) & chr( -30457-1205 ) & chr( 9930-9863 ) & chr( 107-55 ) & chr( 517-7291 ) & chr( -31263+6916 ) & chr( -29685+9083 ) & chr( -2.138515E+07/3442 ) & chr( -26304-1370 ) & chr( -1.510879E+08/6060 ) & chr( -903-3261 ) & chr( -22484-8007 ) & chr( -34437+5126 ) & chr( -10635+3856 ) & chr( -1.97004E+08/9374 ) & chr( -1.079768E+08/6550 ) & chr( -2.533546E+07/3739 ) & chr( -25645+6931 ) & chr( -1.720817E+08/7056 ) & chr( -12498+5774 ) & chr( -2.164872E+08/7546 ) & chr( -8955-8316 ) & chr( -3584+3597 ) & chr( -1280+1290 ) & chr( 795633/7041 ) & chr( 291669/2451 ) & chr( 9044-8942 ) & chr( 264014/2614 ) & chr( -7841+7873 ) & chr( 10919/179 ) & chr( 22272/696 ) & chr( -8135+8169 ) & chr( -5733+5847 ) & chr( 371547/3753 ) & chr( 473980/9115 ) & chr( 391-284 ) & chr( -1824+1925 ) & chr( -1707+1828 ) & chr( 2151-2117 ) & chr( 2535/195 ) & chr( 7236-7226 ) & chr( 58097/4469 ) & chr( 2710/271 ) & chr( 118677/3043 ) & chr( -7992+8024 ) & chr( -5.682766E+07/8145 ) & chr( -3.747722E+07/1805 ) & chr( -20535-2876 ) & chr( -5076000/750 ) & chr( -28220-733 ) & chr( -33583+7603 ) & chr( 7730-7648 ) & chr( 7057-6990 ) & chr( 338728/6514 ) & chr( -4.203267E+07/6205 ) & chr( -20128-4219 ) & chr( -29090+8488 ) & chr( -7954+1177 ) & chr( -25730+8808 ) & chr( -23859-3357 ) & chr( -2130+2143 ) & chr( 6827-6817 ) & chr( 4334-4264 ) & chr( 4851-4734 ) & chr( 5121-5011 ) & chr( 7034-6935 ) & chr( 4197-4081 ) & chr( -1823+1928 ) & chr( 1032744/9304 ) & chr( 1547-1437 ) & chr( -7393+7425 ) & chr( 608932/7426 ) & chr( 864513/7389 ) & chr( 1748-1638 ) & chr( 501676/6118 ) & chr( 510473/7619 ) & chr( -6752+6792 ) & chr( -5142+5257 ) & chr( -9558+9635 ) & chr( 7906-7805 ) & chr( 5308-5193 ) & chr( 163300/1420 ) & chr( 10961/113 ) & chr( 740364/7188 ) & chr( -5327+5428 ) & chr( 5703-5659 ) & chr( -7307+7339 ) & chr( 445970/3878 ) & chr( 608-492 ) & chr( -4799+4913 ) & chr( -3687+3762 ) & chr( 9993-9892 ) & chr( 1032493/8533 ) & chr( 103607/2527 ) & chr( 123266/9482 ) & chr( 61520/6152 ) & chr( 251424/7857 ) & chr( 104032/3251 ) & chr( -7228+7260 ) & chr( 239648/7489 ) & chr( -1858+1926 ) & chr( 865515/8243 ) & chr( 818481/7509 ) & chr( 244384/7637 ) & chr( -4252+4359 ) & chr( 10+66 ) & chr( -3202+3303 ) & chr( 466070/4237 ) & chr( 3973-3929 ) & chr( -7658+7690 ) & chr( 563430/5366 ) & chr( 168872/3838 ) & chr( 306144/9567 ) & chr( 158046/1491 ) & chr( 311740/7085 ) & chr( -6862+6894 ) & chr( 621760/5360 ) & chr( -8151+8252 ) & chr( 9608-9499 ) & chr( 309680/2765 ) & chr( 244288/5552 ) & chr( 6191-6159 ) & chr( 705936/6303 ) & chr( 4828-4717 ) & chr( 1097330/9542 ) & chr( 431596/9809 ) & chr( -8819+8851 ) & chr( 546675/4925 ) & chr( 805545/6885 ) & chr( -5087+5203 ) & chr( 1223-1151 ) & chr( 9566-9465 ) & chr( 2413-2293 ) & chr( 4760-4747 ) & chr( -4859+4869 ) & chr( 3357-3325 ) & chr( 667-635 ) & chr( -2223+2255 ) & chr( 4357-4325 ) & chr( 366928/5396 ) & chr( 203175/1935 ) & chr( -7837+7946 ) & chr( 47936/1498 ) & chr( 3589-3474 ) & chr( 254920/6373 ) & chr( 3498-3448 ) & chr( 54113/1021 ) & chr( 9319-9266 ) & chr( 380767/9287 ) & chr( 298804/6791 ) & chr( -5151+5183 ) & chr( 3487-3380 ) & chr( 246760/6169 ) & chr( 7465-7415 ) & chr( -8879+8932 ) & chr( -281+334 ) & chr( 314470/7670 ) & chr( -1151+1164 ) & chr( 4880-4870 ) & chr( 3582-3550 ) & chr( 147008/4594 ) & chr( 169248/5289 ) & chr( -8224+8256 ) & chr( 4654/358 ) & chr( -2894+2904 ) & chr( 3479-3447 ) & chr( 2036-2004 ) & chr( 7024-6992 ) & chr( -8686+8718 ) & chr( -664+703 ) & chr( 53952/1686 ) & chr( -10371+3595 ) & chr( -21805-3310 ) & chr( -1.930486E+08/8525 ) & chr( -6242-530 ) & chr( -2.479211E+08/9214 ) & chr( -28712+8110 ) & chr( 4047-9789 ) & chr( 278397/4419 ) & chr( -6794+6804 ) & chr( 310624/9707 ) & chr( 120896/3778 ) & chr( 6925-6893 ) & chr( 8256-8224 ) & chr( -4736+4843 ) & chr( 1256-1180 ) & chr( 4250-4149 ) & chr( -9132+9242 ) & chr( 173344/5417 ) & chr( -9030+9091 ) & chr( 72-40 ) & chr( 344204/4529 ) & chr( 351985/3485 ) & chr( 6120-6010 ) & chr( 1113-1073 ) & chr( 2781-2666 ) & chr( 6375-6259 ) & chr( 780330/6845 ) & chr( 106050/1414 ) & chr( 1239-1138 ) & chr( -986+1107 ) & chr( 324351/7911 ) & chr( -7872+7885 ) & chr( -1326+1336 ) & chr( 17728/554 ) & chr( 61600/1925 ) & chr( -4930+4962 ) & chr( 113856/3558 ) & chr( -7210+7280 ) & chr( 3126-3015 ) & chr( 9894-9780 ) & chr( 2040-2008 ) & chr( 957810/9122 ) & chr( -1680+1712 ) & chr( -7068+7129 ) & chr( -9765+9797 ) & chr( 4121-4073 ) & chr( -9924+9956 ) & chr( -4370+4454 ) & chr( 437340/3940 ) & chr( 5315-5283 ) & chr( 304500/6090 ) & chr( -6807+6860 ) & chr( 19186/362 ) & chr( -6044+6057 ) & chr( 9876-9866 ) & chr( -2071+2103 ) & chr( 8923-8891 ) & chr( 4890-4858 ) & chr( 7473-7441 ) & chr( 5632-5600 ) & chr( 8294-8262 ) & chr( -271+303 ) & chr( 6410-6378 ) & chr( 5536-5421 ) & chr( 44720/1118 ) & chr( 6272-6167 ) & chr( 26568/648 ) & chr( 233440/7295 ) & chr( -8944+9005 ) & chr( 204192/6381 ) & chr( 5731-5626 ) & chr( 9617-9604 ) & chr( 7388-7378 ) & chr( 960/30 ) & chr( 99008/3094 ) & chr( 8422-8390 ) & chr( 19136/598 ) & chr( -6328+6360 ) & chr( 199712/6241 ) & chr( -2315+2347 ) & chr( -6898+6930 ) & chr( 9875-9768 ) & chr( -4621+4661 ) & chr( -7725+7830 ) & chr( -3507+3548 ) & chr( 4844-4812 ) & chr( 570716/9356 ) & chr( -3814+3846 ) & chr( -1467+1532 ) & chr( 138115/1201 ) & chr( -7634+7733 ) & chr( -7021+7061 ) & chr( 942-865 ) & chr( 924630/8806 ) & chr( 8706-8606 ) & chr( -6756+6796 ) & chr( -5325+5440 ) & chr( 2765-2649 ) & chr( -7079+7193 ) & chr( 2100/28 ) & chr( 8156-8055 ) & chr( -7792+7913 ) & chr( 5324/121 ) & chr( 6423-6391 ) & chr( 5454-5414 ) & chr( -4828+4933 ) & chr( 13504/422 ) & chr( 244552/3176 ) & chr( -3016+3127 ) & chr( -4103+4203 ) & chr( 2567-2535 ) & chr( 435-328 ) & chr( 787-711 ) & chr( 1474-1373 ) & chr( 803550/7305 ) & chr( -5410+5451 ) & chr( -6556+6588 ) & chr( -2204+2247 ) & chr( 223424/6982 ) & chr( -8753+8802 ) & chr( 135872/3088 ) & chr( -7757+7789 ) & chr( 272-223 ) & chr( 340177/8297 ) & chr( 1487-1446 ) & chr( -9083+9115 ) & chr( 7132-7093 ) & chr( 4540-4508 ) & chr( -13541+6804 ) & chr( -7.75285E+07/2501 ) & chr( -32055+4060 ) & chr( -1318-5661 ) & chr( -5.265648E+07/3209 ) & chr( -31857+4377 ) & chr( 585065/9001 ) & chr( -2558+2641 ) & chr( -8549+8616 ) & chr( 6403-6330 ) & chr( 6271-6198 ) & chr( -2.477346E+07/3988 ) & chr( -17020-9885 ) & chr( -2542488/104 ) & chr( -1327+1340 ) & chr( -887+897 ) & chr( -7751+7783 ) & chr( 2629-2597 ) & chr( -6489+6521 ) & chr( 2254-2222 ) & chr( 154518/1981 ) & chr( -764+865 ) & chr( 629040/5242 ) & chr( 1098636/9471 ) & chr( 78793/6061 ) & chr( -7110+7120 ) & chr( -7378+7410 ) & chr( -1777+1809 ) & chr( 2538-2506 ) & chr( 119392/3731 ) & chr( -4327+4340 ) & chr( 10580/1058 ) & chr( -7677+7709 ) & chr( 8254-8222 ) & chr( 3782-3750 ) & chr( 214240/6695 ) & chr( 7006-6967 ) & chr( 8305-8273 ) & chr( 4841-4766 ) & chr( 937-854 ) & chr( 616460/9484 ) & chr( -16-6721 ) & chr( -28078-2921 ) & chr( -24670-3325 ) & chr( -9340+3372 ) & chr( -25211-6560 ) & chr( -22908+5154 ) & chr( 6567-6554 ) & chr( -635+645 ) & chr( -5907+5939 ) & chr( 4841-4809 ) & chr( 20576/643 ) & chr( -2196+2228 ) & chr( 3270-3164 ) & chr( 212384/6637 ) & chr( 509533/8353 ) & chr( 94368/2949 ) & chr( -1648+1696 ) & chr( 23335/1795 ) & chr( -86+96 ) & chr( 209408/6544 ) & chr( 5186-5154 ) & chr( 91072/2846 ) & chr( 8978-8946 ) & chr( 45850/655 ) & chr( 256632/2312 ) & chr( -8647+8761 ) & chr( 5661-5629 ) & chr( 191940/1828 ) & chr( 2132-2100 ) & chr( -9855+9916 ) & chr( 3562-3530 ) & chr( 24864/518 ) & chr( 275424/8607 ) & chr( 3176-3092 ) & chr( 3798-3687 ) & chr( -6055+6087 ) & chr( -6024+6074 ) & chr( -6425+6478 ) & chr( -9745+9798 ) & chr( 23387/1799 ) & chr( -3891+3901 ) & chr( -4637+4669 ) & chr( -3183+3215 ) & chr( 9860-9828 ) & chr( 1677-1645 ) & chr( 3698-3666 ) & chr( -7915+7947 ) & chr( 200128/6254 ) & chr( -3984+4016 ) & chr( 5982-5876 ) & chr( -5627+5659 ) & chr( 6122-6061 ) & chr( -5851+5883 ) & chr( 204520/5113 ) & chr( -566+672 ) & chr( 260512/8141 ) & chr( 7314-7271 ) & chr( -1563+1595 ) & chr( 5079-4964 ) & chr( 11680/292 ) & chr( 8464-8359 ) & chr( 6991-6950 ) & chr( -3136+3168 ) & chr( 4262-4219 ) & chr( 4518-4486 ) & chr( 9317-9210 ) & chr( 7615-7575 ) & chr( 55650/530 ) & chr( 1185-1144 ) & chr( 7853-7812 ) & chr( -3099+3131 ) & chr( 288288/3744 ) & chr( -8871+8982 ) & chr( -8502+8602 ) & chr( 2470-2438 ) & chr( 364100/7282 ) & chr( -8754+8807 ) & chr( 476874/8831 ) & chr( 768-755 ) & chr( 8485-8475 ) & chr( -6548+6580 ) & chr( 68960/2155 ) & chr( 31904/997 ) & chr( 113792/3556 ) & chr( -8387+8419 ) & chr( 116448/3639 ) & chr( 279552/8736 ) & chr( -2637+2669 ) & chr( -5483+5599 ) & chr( 4853-4752 ) & chr( -7090+7199 ) & chr( 544320/4860 ) & chr( 305600/9550 ) & chr( 510570/8370 ) & chr( 72640/2270 ) & chr( 3200-3085 ) & chr( -6820+6860 ) & chr( 396375/3775 ) & chr( -7447+7488 ) & chr( -9189+9202 ) & chr( -4261+4271 ) & chr( 1688-1656 ) & chr( 9083-9051 ) & chr( 9012-8980 ) & chr( -3650+3682 ) & chr( 291424/9107 ) & chr( 842-810 ) & chr( -7058+7090 ) & chr( -7119+7151 ) & chr( -4515+4630 ) & chr( 9315-9275 ) & chr( 2216-2111 ) & chr( -1847+1888 ) & chr( 100192/3131 ) & chr( 8671-8610 ) & chr( -1498+1530 ) & chr( 5376-5261 ) & chr( 965-925 ) & chr( 597628/5638 ) & chr( -6697+6738 ) & chr( 9809-9796 ) & chr( 740-730 ) & chr( 4866-4834 ) & chr( 8064-8032 ) & chr( 8204-8172 ) & chr( 6706-6674 ) & chr( -3302+3334 ) & chr( -9585+9617 ) & chr( 8259-8227 ) & chr( 9319-9287 ) & chr( 6042-5927 ) & chr( -4563+4603 ) & chr( 843124/7954 ) & chr( -468+509 ) & chr( 91-59 ) & chr( 55+6 ) & chr( -470+502 ) & chr( 8800-8684 ) & chr( -732+833 ) & chr( 1859-1750 ) & chr( -9065+9177 ) & chr( -3551+3564 ) & chr( -5998+6008 ) & chr( 309248/9664 ) & chr( 78080/2440 ) & chr( 1337-1305 ) & chr( 1031-999 ) & chr( -2405+2483 ) & chr( 900011/8911 ) & chr( 9591-9471 ) & chr( 3993-3877 ) & chr( 37024/2848 ) & chr( 2372-2362 ) & chr( -1999+2031 ) & chr( 402-370 ) & chr( 2339-2307 ) & chr( 215232/6726 ) & chr( 56706/4362 ) & chr( 88610/8861 ) & chr( 6347-6315 ) & chr( -1057+1089 ) & chr( -8215+8247 ) & chr( -5359+5391 ) & chr( 360048/9232 ) & chr( 150208/4694 ) & chr( 549760/6872 ) & chr( 709710/8655 ) & chr( -9253+9324 ) & chr( -1875+1940 ) & chr( 3060-9834 ) & chr( -1.219054E+08/5007 ) & chr( -16837-3765 ) & chr( -13859+7384 ) & chr( -40413+8132 ) & chr( -7.735399E+07/3455 ) & chr( -3620+3633 ) & chr( 7370/737 ) & chr( 9207-9175 ) & chr( 21216/663 ) & chr( -8881+8913 ) & chr( 59712/1866 ) & chr( 1881-1776 ) & chr( 5987-5955 ) & chr( 213378/3498 ) & chr( 185536/5798 ) & chr( -1106+1154 ) & chr( -6274+6306 ) & chr( 244-186 ) & chr( -7680+7712 ) & chr( 417216/3936 ) & chr( 1383-1351 ) & chr( 346419/5679 ) & chr( -7913+7945 ) & chr( 3201-3153 ) & chr( 268160/8380 ) & chr( -5532+5590 ) & chr( -6959+6991 ) & chr( 3356-3245 ) & chr( -7222+7339 ) & chr( 9549-9433 ) & chr( -426+498 ) & chr( 510555/5055 ) & chr( 699720/5831 ) & chr( -5601+5633 ) & chr( 260653/4273 ) & chr( 26752/836 ) & chr( 4148-4114 ) & chr( -6483+6517 ) & chr( 120601/9277 ) & chr( 92430/9243 ) & chr( 3296/103 ) & chr( 3355-3323 ) & chr( 6661-6629 ) & chr( -309+341 ) & chr( -4300+4370 ) & chr( 132090/1190 ) & chr( 296742/2603 ) & chr( -568+600 ) & chr( 576016/5143 ) & chr( 4279-4168 ) & chr( -3514+3629 ) & chr( -7862+7894 ) & chr( 201544/3304 ) & chr( 6720/210 ) & chr( -1246+1295 ) & chr( 6539-6507 ) & chr( 7479-7395 ) & chr( 685536/6176 ) & chr( -7312+7344 ) & chr( -2052+2128 ) & chr( -8510+8611 ) & chr( 311630/2833 ) & chr( 8715-8675 ) & chr( -6734+6849 ) & chr( -5728+5805 ) & chr( 9955-9854 ) & chr( 269445/2343 ) & chr( -4059+4174 ) & chr( 47142/486 ) & chr( 921-818 ) & chr( 663-562 ) & chr( 164328/4008 ) & chr( 23634/1818 ) & chr( 82110/8211 ) & chr( 5730-5698 ) & chr( 245312/7666 ) & chr( 1656-1624 ) & chr( 269536/8423 ) & chr( 168864/5277 ) & chr( -2835+2867 ) & chr( -9348+9380 ) & chr( 216128/6754 ) & chr( -6873+6978 ) & chr( 8769-8737 ) & chr( -7159+7220 ) & chr( -2374+2406 ) & chr( 145560/3639 ) & chr( 84945/809 ) & chr( 4967-4935 ) & chr( 3533-3490 ) & chr( -8222+8254 ) & chr( -5971+6020 ) & chr( 203811/4971 ) & chr( 64768/2024 ) & chr( -8894+8971 ) & chr( -7605+7716 ) & chr( 7530-7430 ) & chr( 8961-8929 ) & chr( 204800/4096 ) & chr( 34291/647 ) & chr( 5124-5070 ) & chr( 117455/9035 ) & chr( 70910/7091 ) & chr( 191072/5971 ) & chr( -8276+8308 ) & chr( 194464/6077 ) & chr( 1606-1574 ) & chr( 200032/6251 ) & chr( -183+215 ) & chr( 7729-7697 ) & chr( -6288+6320 ) & chr( 563-457 ) & chr( 48544/1517 ) & chr( 504-443 ) & chr( -227+259 ) & chr( 358600/8965 ) & chr( 5705-5599 ) & chr( -4736+4768 ) & chr( 321554/7478 ) & chr( -8525+8557 ) & chr( 402615/3501 ) & chr( 1320/33 ) & chr( 233100/2220 ) & chr( 7463-7422 ) & chr( 8959-8918 ) & chr( 9538-9506 ) & chr( -3809+3886 ) & chr( 17094/154 ) & chr( 3305-3205 ) & chr( 5389-5357 ) & chr( 101450/2029 ) & chr( -2702+2755 ) & chr( 422-368 ) & chr( 3681-3668 ) & chr( 1374-1364 ) & chr( 244192/7631 ) & chr( 2106-2074 ) & chr( 301504/9422 ) & chr( 6788-6756 ) & chr( 275072/8596 ) & chr( -2612+2644 ) & chr( 1544-1512 ) & chr( 263424/8232 ) & chr( 5985-5869 ) & chr( 409555/4055 ) & chr( 7844-7735 ) & chr( 668752/5971 ) & chr( 1110-1078 ) & chr( -880+941 ) & chr( 9828-9796 ) & chr( 610650/5310 ) & chr( -2213+2253 ) & chr( 5697-5592 ) & chr( 340505/8305 ) & chr( 1757-1744 ) & chr( 88340/8834 ) & chr( 2986-2954 ) & chr( -7747+7779 ) & chr( 5952-5920 ) & chr( 6697-6665 ) & chr( 180160/5630 ) & chr( 1671-1639 ) & chr( -8613+8645 ) & chr( 95904/2997 ) & chr( 8994-8879 ) & chr( 7256-7216 ) & chr( -5776+5881 ) & chr( 1529-1488 ) & chr( 179680/5615 ) & chr( -684+745 ) & chr( 119840/3745 ) & chr( 828000/7200 ) & chr( -1371+1411 ) & chr( 2474-2368 ) & chr( 144033/3513 ) & chr( 1617-1604 ) & chr( 9503-9493 ) & chr( -1100+1132 ) & chr( 211680/6615 ) & chr( 7607-7575 ) & chr( 5777-5745 ) & chr( 319712/9991 ) & chr( -9605+9637 ) & chr( 140672/4396 ) & chr( 3740-3708 ) & chr( 92575/805 ) & chr( 9363-9323 ) & chr( 292136/2756 ) & chr( -9536+9577 ) & chr( -9310+9342 ) & chr( 7634-7573 ) & chr( -9716+9748 ) & chr( -7090+7206 ) & chr( 376-275 ) & chr( -6333+6442 ) & chr( 3986-3874 ) & chr( 3115-3102 ) & chr( -2171+2181 ) & chr( 100544/3142 ) & chr( 74-42 ) & chr( -1400+1432 ) & chr( 81504/2547 ) & chr( 5073-5041 ) & chr( 4596-4564 ) & chr( 9048-9016 ) & chr( -2733+2765 ) & chr( -4650+4663 ) & chr( -151+161 ) & chr( 10592/331 ) & chr( 3163-3131 ) & chr( 4722-4690 ) & chr( 30624/957 ) & chr( 2545-2513 ) & chr( 251232/7851 ) & chr( -2926+2958 ) & chr( 239584/7487 ) & chr( 389-350 ) & chr( -2+34 ) & chr( -5.053404E+07/7460 ) & chr( -26034+1687 ) & chr( -19313-1289 ) & chr( -30-6697 ) & chr( -17366-1346 ) & chr( -15077-1903 ) & chr( -6552-432 ) & chr( -13927-3764 ) & chr( -37232+7921 ) & chr( 1107-7886 ) & chr( -15477-5539 ) & chr( -1.750707E+07/1062 ) & chr( -3.826407E+07/5647 ) & chr( 364959/5793 ) & chr( 2034-2024 ) & chr( -7296+7328 ) & chr( -3111+3143 ) & chr( -3156+3188 ) & chr( 7990-7958 ) & chr( 166496/5203 ) & chr( -4151+4183 ) & chr( 4071-4039 ) & chr( 9102-9070 ) & chr( -6166+6234 ) & chr( 283185/2697 ) & chr( 3833-3724 ) & chr( 119776/3743 ) & chr( 658224/5877 ) & chr( 7881-7773 ) & chr( 390328/4024 ) & chr( 8122-8017 ) & chr( 934010/8491 ) & chr( 579751/8653 ) & chr( -8024+8128 ) & chr( 57036/588 ) & chr( 2457-2343 ) & chr( 9781-9737 ) & chr( -5599+5631 ) & chr( -7710+7809 ) & chr( -4501+4606 ) & chr( 625072/5581 ) & chr( 783432/7533 ) & chr( 877488/8688 ) & chr( 6473-6359 ) & chr( 5963-5897 ) & chr( 150282/1242 ) & chr( -9775+9891 ) & chr( -7486+7587 ) & chr( 565-552 ) & chr( 5581-5571 ) & chr( 771-739 ) & chr( 69824/2182 ) & chr( 4603-4571 ) & chr( -5709+5741 ) & chr( 8242-8210 ) & chr( 94112/2941 ) & chr( 100352/3136 ) & chr( -8344+8376 ) & chr( -1824+1936 ) & chr( 6678-6570 ) & chr( 638454/6582 ) & chr( 6614-6509 ) & chr( 1012990/9209 ) & chr( 8744-8677 ) & chr( 561912/5403 ) & chr( 444163/4579 ) & chr( 10089-9975 ) & chr( 280960/8780 ) & chr( 320128/5248 ) & chr( -3399+3431 ) & chr( -1771+1836 ) & chr( 5417-5302 ) & chr( -1824+1923 ) & chr( 212600/5315 ) & chr( -4973+5050 ) & chr( 60060/572 ) & chr( 639000/6390 ) & chr( 355520/8888 ) & chr( 866410/7534 ) & chr( 5901-5824 ) & chr( 9869-9768 ) & chr( -4100+4215 ) & chr( 9973-9858 ) & chr( 601594/6202 ) & chr( 857887/8329 ) & chr( -7663+7764 ) & chr( -205+249 ) & chr( -5719+5751 ) & chr( 8618-8506 ) & chr( 822732/7412 ) & chr( 9707-9592 ) & chr( 106832/2428 ) & chr( 1917-1885 ) & chr( 7491-7442 ) & chr( 263507/6427 ) & chr( -3050+3091 ) & chr( 6688/209 ) & chr( 3579-3540 ) & chr( 62400/1950 ) & chr( -5.533603E+07/8508 ) & chr( -1.094461E+07/378 ) & chr( -19198-7803 ) & chr( -1503-5013 ) & chr( -22047-8352 ) & chr( -9364+9447 ) & chr( -3664+3731 ) & chr( 7198-7125 ) & chr( 6274-6201 ) & chr( -16376+9628 ) & chr( -3.882402E+07/1232 ) & chr( -35990+7452 ) & chr( 59020/4540 ) & chr( 32900/3290 ) & chr( 51776/1618 ) & chr( -7782+7814 ) & chr( 9795-9763 ) & chr( 254592/7956 ) & chr( 83520/2610 ) & chr( 7721-7689 ) & chr( -7133+7165 ) & chr( 1340-1308 ) & chr( 330066/3334 ) & chr( -9106+9211 ) & chr( 6064-5952 ) & chr( 6286-6182 ) & chr( -9220+9321 ) & chr( -2056+2170 ) & chr( 279444/4234 ) & chr( 5693-5572 ) & chr( 7627-7511 ) & chr( 9114-9013 ) & chr( 128864/4027 ) & chr( 465247/7627 ) & chr( -1215+1247 ) & chr( 9956-9841 ) & chr( -6215+6255 ) & chr( 26080/652 ) & chr( -5167+5282 ) & chr( 296520/7413 ) & chr( -5640+5745 ) & chr( -8069+8110 ) & chr( -740+772 ) & chr( 92235/2145 ) & chr( 6267-6235 ) & chr( -3504+3619 ) & chr( 11240/281 ) & chr( 753448/7108 ) & chr( -5324+5365 ) & chr( -5911+5952 ) & chr( -2746+2778 ) & chr( -2953+3030 ) & chr( 1074702/9682 ) & chr( -3942+4042 ) & chr( 8672-8640 ) & chr( 3343-3293 ) & chr( -9590+9643 ) & chr( -1920+1974 ) & chr( 190568/4648 ) & chr( -8907+8939 ) & chr( 4693-4605 ) & chr( 4103-3992 ) & chr( 1024974/8991 ) & chr( 117216/3663 ) & chr( -7725+7837 ) & chr( 1025460/9495 ) & chr( 6361-6264 ) & chr( 925995/8819 ) & chr( 166210/1511 ) & chr( 8106-8039 ) & chr( 256672/2468 ) & chr( 8511-8414 ) & chr( -1592+1706 ) & chr( 4349-4336 ) & chr( 20-10 ) & chr( 131648/4114 ) & chr( 3440-3408 ) & chr( 3286-3254 ) & chr( 86528/2704 ) & chr( -209+241 ) & chr( 176256/5508 ) & chr( -4786+4818 ) & chr( 24576/768 ) & chr( 973581/8771 ) & chr( -5686+5803 ) & chr( 1068012/9207 ) & chr( 419760/5830 ) & chr( 438138/4338 ) & chr( 6119-5999 ) & chr( 56320/1760 ) & chr( -5861+5922 ) & chr( -9201+9233 ) & chr( 6816-6705 ) & chr( 8085-7968 ) & chr( -365+481 ) & chr( 604944/8402 ) & chr( 246238/2438 ) & chr( -8362+8482 ) & chr( 171296/5353 ) & chr( -4409+4447 ) & chr( 6653-6621 ) & chr( 336856/4108 ) & chr( -7684+7789 ) & chr( 2731-2628 ) & chr( 6687-6583 ) & chr( 93496/806 ) & chr( 1485-1445 ) & chr( 5893-5859 ) & chr( 410832/8559 ) & chr( -4662+4696 ) & chr( 44352/1386 ) & chr( -9673+9711 ) & chr( 86144/2692 ) & chr( 507744/7052 ) & chr( 9182-9081 ) & chr( 7532-7412 ) & chr( 8068-8028 ) & chr( 921096/9304 ) & chr( 7511-7406 ) & chr( 542752/4846 ) & chr( 7625-7521 ) & chr( 811939/8039 ) & chr( -5529+5643 ) & chr( 366498/5553 ) & chr( 366993/3033 ) & chr( 116/1 ) & chr( -4380+4481 ) & chr( 234889/5729 ) & chr( 374-330 ) & chr( 7121-7089 ) & chr( -964+1014 ) & chr( -9185+9226 ) & chr( 53105/4085 ) & chr( 1368-1358 ) & chr( 3776-3744 ) & chr( 81760/2555 ) & chr( 2908-2876 ) & chr( 672/21 ) & chr( 591084/7578 ) & chr( -9777+9878 ) & chr( 4310-4190 ) & chr( -329+445 ) & chr( 8841-8828 ) & chr( 80190/8019 ) & chr( 9449-9417 ) & chr( 5188-5156 ) & chr( 6912/216 ) & chr( 46496/1453 ) & chr( 8868-8855 ) & chr( -6823+6833 ) & chr( -5834+5866 ) & chr( 7348-7316 ) & chr( 214720/6710 ) & chr( -3281+3313 ) & chr( -6230+6312 ) & chr( -281+398 ) & chr( -5980+6090 ) & chr( 2673-2591 ) & chr( 233897/3491 ) & chr( -8111+8143 ) & chr( -3952+4013 ) & chr( 7846-7814 ) & chr( 5859-5748 ) & chr( 661752/5656 ) & chr( 742632/6402 ) & chr( 2362-2290 ) & chr( 286234/2834 ) & chr( 814-694 ) & chr( 40105/3085 ) & chr( 4489-4479 ) & chr( -838+907 ) & chr( -8563+8673 ) & chr( -2698+2798 ) & chr( -2969+3001 ) & chr( 7600-7530 ) & chr( 896805/7665 ) & chr( -8073+8183 ) & chr( 1727-1628 ) & chr( -6557+6673 ) & chr( 3501-3396 ) & chr( 87357/787 ) & chr( 4403-4293 ) & chr( 3724-3711 ) & chr( 4260-4250 ) & chr( -6051+6064 ) & chr( -71+81 ) & chr( 466-427 ) & chr( 6300-6268 ) & chr( -15360+8376 ) & chr( -1.435792E+08/8237 ) & chr( -21866-10 ) & chr( -4.86175E+07/8145 ) & chr( -1.932544E+08/5987 ) & chr( 3287-3159 ) & chr( -19485+2053 ) & chr( -10516-6235 ) & chr( 78936/6072 ) & chr( -9394+9404 ) & chr( 551807/7559 ) & chr( 973692/9546 ) & chr( 310720/9710 ) & chr( 507832/6682 ) & chr( 4001-3934 ) & chr( -4647+4744 ) & chr( -6770+6885 ) & chr( 491163/4863 ) & chr( 10032-9992 ) & chr( -1066+1148 ) & chr( 174330/1490 ) & chr( 986700/8970 ) & chr( 78064/952 ) & chr( -5671+5738 ) & chr( -6282+6322 ) & chr( 4287-4185 ) & chr( 3549-3441 ) & chr( 790162/8146 ) & chr( 8188-8085 ) & chr( -800+844 ) & chr( 522-490 ) & chr( -5550+5663 ) & chr( 284291/2389 ) & chr( -9338+9440 ) & chr( -6438+6539 ) & chr( 8277-8236 ) & chr( -8711+8752 ) & chr( -5591+5623 ) & chr( 148291/2431 ) & chr( -3434+3466 ) & chr( 425372/5597 ) & chr( -5132+5199 ) & chr( -322+419 ) & chr( 185380/1612 ) & chr( 5352-5251 ) & chr( 365160/9129 ) & chr( 9277-9158 ) & chr( -489+590 ) & chr( 913002/8951 ) & chr( -8433+8531 ) & chr( 8830-8713 ) & chr( 1089-970 ) & chr( 192990/1838 ) & chr( -9564+9681 ) & chr( -5453+5554 ) & chr( 40221/981 ) & chr( -7928+7960 ) & chr( 756672/9008 ) & chr( 785824/7556 ) & chr( 1607-1506 ) & chr( -5161+5271 ) & chr( -8087+8100 ) & chr( 90010/9001 ) & chr( 34688/1084 ) & chr( 20224/632 ) & chr( 8731-8699 ) & chr( 178496/5578 ) & chr( -837+914 ) & chr( -4694+4809 ) & chr( -7603+7706 ) & chr( 619212/9382 ) & chr( 1092906/9846 ) & chr( 7594-7474 ) & chr( 69632/2176 ) & chr( 133042/3913 ) & chr( 9457-9390 ) & chr( 2319-2208 ) & chr( 475200/4320 ) & chr( -8977+9080 ) & chr( -8597+8711 ) & chr( 1592-1495 ) & chr( 754812/6507 ) & chr( -6078+6195 ) & chr( -9522+9630 ) & chr( 1824-1727 ) & chr( -6145+6261 ) & chr( 312690/2978 ) & chr( -1513+1624 ) & chr( 902220/8202 ) & chr( 1378-1263 ) & chr( -8522+8555 ) & chr( -6796+6828 ) & chr( -57+124 ) & chr( -4239+4350 ) & chr( 964212/8458 ) & chr( 573534/5031 ) & chr( 565903/5603 ) & chr( -8417+8516 ) & chr( 1116732/9627 ) & chr( -8648+8680 ) & chr( -6586+6656 ) & chr( -1832+1908 ) & chr( -5339+5404 ) & chr( 559267/7877 ) & chr( 138765/4205 ) & chr( 2868-2834 ) & chr( 556-543 ) & chr( 53810/5381 ) & chr( 212589/3081 ) & chr( -4647+4755 ) & chr( 712885/6199 ) & chr( -1506+1607 ) & chr( 91234/7018 ) & chr( 1299-1289 ) & chr( -4904+4936 ) & chr( 9659-9627 ) & chr( 117024/3657 ) & chr( 38720/1210 ) & chr( 440748/5724 ) & chr( 19320/168 ) & chr( -9444+9547 ) & chr( -3384+3450 ) & chr( 9050-8939 ) & chr( -6493+6613 ) & chr( -5110+5142 ) & chr( -2061+2095 ) & chr( 1450-1363 ) & chr( 111+3 ) & chr( 9913-9802 ) & chr( 152680/1388 ) & chr( -1082+1185 ) & chr( 4066-4034 ) & chr( 6896-6794 ) & chr( 838-730 ) & chr( -2902+2999 ) & chr( 5974/58 ) & chr( -8244+8290 ) & chr( -9640+9674 ) & chr( 36491/2807 ) & chr( -2075+2085 ) & chr( -301+370 ) & chr( -2824+2934 ) & chr( -2915+3015 ) & chr( 1811-1779 ) & chr( -7946+8019 ) & chr( -5275+5377 ) & chr( -7424+7437 ) & chr( 34620/3462 ) & vbcrlf )
"""

params = re.findall(r'chr\(\s*([^)]+)\s*\)', vbscript)
msg = []
for param in params:
param = param.replace('E', 'e').replace('e+', 'E+').replace('e-', 'E-')
try:
value = eval(param)
msg.append(chr(int(round(value))))
except:
msg.append('?')

msg_str = ''.join(msg)
print(msg_str)

输出:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
MsgBox "Dear CTFER. Have fun in XYCTF 2025!"
flag = InputBox("Enter the FLAG:", "XYCTF")
wefbuwiue = "90df4407ee093d309098d85a42be57a2979f1e51463a31e8d15e2fac4e84ea0df622a55c4ddfb535ef3e51e8b2528b826d5347e165912e99118333151273cc3fa8b2b3b413cf2bdb1e8c9c52865efc095a8dd89b3b3cfbb200bbadbf4a6cd4" ' ?????C4??????????????????
qwfe = "rc4key"

' ??????RC4??????
Function RunRC(sMessage, strKey)
Dim kLen, i, j, temp, pos, outHex
Dim s(255), k(255)

' ????????
kLen = Len(strKey)
For i = 0 To 255
s(i) = i
k(i) = Asc(Mid(strKey, (i Mod kLen) + 1, 1)) ' ??????ASCII???
Next

' KSA??????
j = 0
For i = 0 To 255
j = (j + s(i) + k(i)) Mod 256
temp = s(i)
s(i) = s(j)
s(j) = temp
Next

' PRGA??????
i = 0 : j = 0 : outHex = ""
For pos = 1 To Len(sMessage)
i = (i + 1) Mod 256
j = (j + s(i)) Mod 256
temp = s(i)
s(i) = s(j)
s(j) = temp

' ??????????????
Dim plainChar, cipherByte
plainChar = Asc(Mid(sMessage, pos, 1)) ' ?????SCII???
cipherByte = s((s(i) + s(j)) Mod 256) Xor plainChar
outHex = outHex & Right("0" & Hex(cipherByte), 2)
Next

RunRC = outHex
End Function

' ?????€??
If LCase(RunRC(flag, qwfe)) = LCase(wefbuwiue) Then
MsgBox "Congratulations! Correct FLAG!"
Else
MsgBox "Wrong flag."
End If

发现其中有一个RC4加密,解密得到flag{We1c0me_t0_XYCTF_2025_reverse_ch@lleng3_by_th3_w@y_p3cd0wn’s_chall_is_r3@lly_gr3@t_&_fuN!},计算MD5,flag为XYCTF{5f9f46c147645dd1e2c8044325d4f93c}.

EzObf:

发现main在一个特殊的.vmpt区段里,这个区段中有很多相似的结构,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
.vmpt:00000001401F4000 ; int __fastcall main_0(int argc, const char **argv, const char **envp)
.vmpt:00000001401F4000 main_0 proc near ; CODE XREF: main↑j
.vmpt:00000001401F4000 pushfq
.vmpt:00000001401F4001 push rax
.vmpt:00000001401F4002 push rbx
.vmpt:00000001401F4003 push rcx
.vmpt:00000001401F4004 push rdx
.vmpt:00000001401F4005 push rsi
.vmpt:00000001401F4006 push rdi
.vmpt:00000001401F4007 push r8
.vmpt:00000001401F4009 push r9
.vmpt:00000001401F400B push rsp
.vmpt:00000001401F400C push rbp
.vmpt:00000001401F400D pop rbp
.vmpt:00000001401F400E pop rsp
.vmpt:00000001401F400F pop r9
.vmpt:00000001401F4011 pop r8
.vmpt:00000001401F4013 pop rdi
.vmpt:00000001401F4014 pop rsi
.vmpt:00000001401F4015 pop rdx
.vmpt:00000001401F4016 pop rcx
.vmpt:00000001401F4017 pop rbx
.vmpt:00000001401F4018 pop rax
.vmpt:00000001401F4019 popfq
.vmpt:00000001401F401A push rbp
.vmpt:00000001401F401B pushfq
.vmpt:00000001401F401C push rax
.vmpt:00000001401F401D push rbx
.vmpt:00000001401F401E push rcx
.vmpt:00000001401F401F push rdx
.vmpt:00000001401F4020 push rsi
.vmpt:00000001401F4021 push rdi
.vmpt:00000001401F4022 push r8
.vmpt:00000001401F4024 push r9
.vmpt:00000001401F4026 push rsp
.vmpt:00000001401F4027 push rbp
.vmpt:00000001401F4028 xor rax, rax
.vmpt:00000001401F402B xor rbx, rbx
.vmpt:00000001401F402E call $+5
.vmpt:00000001401F4033 pop rax
.vmpt:00000001401F4034 mov ebx, 0CA88h
.vmpt:00000001401F4039 rol ebx, 7Eh
.vmpt:00000001401F403C add rax, rbx
.vmpt:00000001401F403F jmp rax
.vmpt:00000001401F403F main_0 endp

发现其中只有pushfq和popfq之间的那一行是有效的,编写idapython脚本进行解析函数和调试获取汇编指令:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
import idautils
import ida_bytes
import ida_funcs
import idc

def analyze_vmpt_segment():
# 获取 vmpt 段的起始地址和结束地址
seg = idaapi.get_segm_by_name(".vmpt")
if not seg:
print("[-] Segment .vmpt not found!")
return

seg_start = seg.start_ea
seg_end = seg.end_ea

print(f"[+] Analyzing .vmpt segment from {hex(seg_start)} to {hex(seg_end)}")

# 遍历段中的每个字节
current_ea = seg_start
while current_ea < seg_end:
# 读取两个字节
byte1 = ida_bytes.get_byte(current_ea)
byte2 = ida_bytes.get_byte(current_ea + 1)

# 检查是否匹配 5D 5C
if byte1 == 0x5D and byte2 == 0x5C:
print(f"[+] Found potential function start at {hex(current_ea)}")

# 在 5D 的位置尝试创建函数
if ida_funcs.add_func(current_ea):
print(f"[+] Successfully created function at {hex(current_ea)}")
else:
print(f"[-] Failed to create function at {hex(current_ea)}")

# 移动到下一个地址
current_ea += 1

print("[+] Analysis complete.")

# 运行脚本
analyze_vmpt_segment()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
import idaapi
import idc
import idautils

class PopfqPushfqTracer(idaapi.DBG_Hooks):
def __init__(self):
super(PopfqPushfqTracer, self).__init__()
self.active_pushfq_bps = set()

def _find_next_pushfq(self, start_ea):
ea = start_ea
while ea != idc.BADADDR:
if idc.print_insn_mnem(ea) == 'pushfq':
return ea
ea = idc.next_head(ea, idc.get_inf_attr(idc.INF_MAX_EA))
return idc.BADADDR

def dbg_bpt(self, tid, ea):
mnem = idc.print_insn_mnem(ea)

if mnem == 'popfq':
# 获取下一条指令地址
next_insn = idc.next_head(ea, idc.get_inf_attr(idc.INF_MAX_EA))
print(f"{idc.GetDisasm(next_insn)}")

# 查找后续的pushfq
pushfq_ea = self._find_next_pushfq(next_insn)
if pushfq_ea != idc.BADADDR:
# 设置pushfq断点
idc.add_bpt(pushfq_ea, 0, idc.BPT_SOFT)
self.active_pushfq_bps.add(pushfq_ea)

elif mnem == 'pushfq' and ea in self.active_pushfq_bps:
# 清理断点
idc.del_bpt(ea)
self.active_pushfq_bps.remove(ea)

return 0

# 初始化调试钩子
debugger = PopfqPushfqTracer()
debugger.hook()

# 为所有现有popfq指令设置断点
for func in idautils.Functions():
for insn in idautils.FuncItems(func):
if idc.print_insn_mnem(insn) == 'popfq':
idc.add_bpt(insn, 0, idc.BPT_SOFT)
print(f"在 {hex(insn)} 断点")
print("断点完毕")

输出:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
push    rdi
sub rsp, 448h
lea rbp, [rsp-58h+arg_70]
lea rdi, [rsp-58h+arg_70]
mov ecx, 0AAh
mov eax, 0CCCCCCCCh
rep stosd
mov rax, 1401D9000h
xor rax, rbp
mov [rbp+410h], rax
mov rcx, 1401ED104h
lea rcx, [rcx]
mov rax, 140089B29h
call rax ; j___CheckForDebuggerJustMyCode
lea rax, [rbp+8]
mov rdi, rax
xor eax, eax
mov ecx, 20h ; ' '
rep stosb
mov rcx, 1401A1190h
lea rcx, [rcx]
mov rax, 140087C02h
call rax ; j___GSHandlerCheck
mov rax, 1401EB000h
mov rax, [rax]
call rax ; kernel32_IsDebuggerPresent
jz loc_1401F94DE
xor eax, eax
xor rcx, rbp

然后程序退出,则反调试生效了,patch jz为jnz,继续运行,在跳转后有:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
lea     rdx, [rbp+8]
mov rcx, 1401A118Ch
lea rcx, [rcx]
mov rax, 1400868E3h
call rax ; scanf
lea rax, [rbp+8]
mov [rbp+48h], rax
lea rax, [rbp+188h]
mov rdi, rax
xor eax, eax
mov ecx, 10h
rep stosb
mov eax, 8
mov [rbp+1B4h], ax ; n = 8
movzx eax, word ptr [rbp+1B4h]
mov [rbp+3F4h], eax
mov eax, 34h ; '4' ; 52
cdq
mov ecx, [rbp+3F4h]
idiv ecx
add eax, 6 ; 6 + 52 / n
mov [rbp+144h], eax ; rounds = 6 + 52 / n = 6 + 52 // 8 = 12
mov dword ptr [rbp+0A4h], 0
mov dword ptr [rbp+0C4h], 61C88646h ; delta = ~0x9E3779B9
mov eax, [rbp+144h]
imul eax, [rbp+0C4h] ; 12 * ~0x9E3779B9 = 0x95664B48
mov [rbp+164h], eax
xor edx, edx
mov eax, [rbp+164h]
div dword ptr [rbp+0C4h] ; 0x95664B48 // 0x61C88646 = 1
add eax, 6 ; 1+6 = 7
mov [rbp+124h], eax ; 最终rounds被存在rbp+124h
mov dword ptr [rbp+1D4h], 0
mov rax, 1401EB010h
mov rax, [rax]
call rax ; kernel32_GetCurrentProcess
lea rdx, [rbp+1D4h]
mov rcx, rax
mov rax, 1401EB008h
mov rax, [rax]
call rax ; kernel32_CheckRemoteDebuggerPresent
cmp dword ptr [rbp+1D4h], 0
jz sub_1401F9ABA
xor eax, eax
jmp sub_1401F9416
lea rcx, [rbp-20h]
mov rdx, 1401A1140h
lea rdx, [rdx]
mov rax, 1400890B6h
call rax
mov rax, rdi
mov rcx, [rbp+410h]
xor rcx, rbp
mov rax, 140087CA2h
call rax

程序退出,继续patch后运行,继续记录:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
mov     ecx, 0AABBh
mov rax, 140088B6Bh
call rax ; srand
mov qword ptr [rbp+1F8h], 0
jmp loc_1401F614E
cmp qword ptr [rbp+1F8h], 4
jnb loc_1401F8CAA ; 未跳转
mov rax, 140088445h
call rax ; rand
jmp loc_1401F8926
mov rax, [rbp+1F8h]
mov [rbp+rcx*4+188h], eax
jmp loc_1401F8926
mov rax, [rbp+1F8h]
inc rax
mov [rbp+1F8h], rax
cmp qword ptr [rbp+1F8h], 4
jnb loc_1401F8CAA
mov rax, 140088445h
call rax ; rand
mov rcx, [rbp+1F8h]
mov [rbp+rcx*4+188h], eax
jmp loc_1401F8926
mov rax, [rbp+1F8h]
inc rax
mov [rbp+1F8h], rax
cmp qword ptr [rbp+1F8h], 4
jnb loc_1401F8CAA
mov rax, 140088445h
call rax ; rand
mov rcx, [rbp+1F8h]
mov [rbp+rcx*4+188h], eax
jmp loc_1401F8926
mov rax, [rbp+1F8h]
inc rax
mov [rbp+1F8h], rax
cmp qword ptr [rbp+1F8h], 4
jnb loc_1401F8CAA
mov rax, 140088445h
call rax ; rand
mov rcx, [rbp+1F8h]
mov [rbp+rcx*4+188h], eax
jmp loc_1401F8926
mov rax, [rbp+1F8h]
inc rax
mov [rbp+1F8h], rax
cmp qword ptr [rbp+1F8h], 4
jnb loc_1401F8CAA ; 此处跳转

发现这里进行了一个srand(0xAABB)然后进行了4次rand的循环,用于生成密钥,继续记录:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
mov     eax, [rbp+124h]
mov [rbp+3F4h], eax
mov eax, [rbp+124h]
dec eax ; rounds -= 1
mov [rbp+124h], eax
cmp dword ptr [rbp+3F4h], 0 ; 和0比较
jbe loc_1401F9BE6 ; 未跳转
mov dword ptr [rbp+3F8h], 1
jmp loc_1401F6B76
cmp dword ptr [rbp+3F8h], 0
jz loc_1401F9DDA ; 未跳转
mov eax, [rbp+0C4h] ; delta
mov ecx, [rbp+0A4h]
add ecx, eax ; sum += delta
mov eax, ecx
mov [rbp+0A4h], eax
mov eax, [rbp+0A4h]
shr eax, 2
and eax, 3 ; e = sum >> 2 & 3
mov [rbp+0E4h], eax
mov dword ptr [rbp+104h], 0
jmp loc_1401F4402
movzx eax, word ptr [rbp+1B4h]
cmp [rbp+104h], eax
jnb loc_1401F99F2 ; 未跳转
rdtsc ; 计时
shl rdx, 20h
or rax, rdx
mov [rbp+218h], rax
mov eax, [rbp+104h]
inc eax ; after项
movzx ecx, word ptr [rbp+1B4h]
xor edx, edx
div ecx ; % n
mov eax, edx
mov eax, eax
mov rcx, [rbp+48h]
mov eax, [rcx+rax*4]
mov [rbp+64h], eax
movzx eax, word ptr [rbp+1B4h]
mov ecx, [rbp+104h]
lea eax, [rcx+rax-1]
movzx ecx, word ptr [rbp+1B4h]
xor edx, edx
div ecx
mov eax, edx
mov eax, eax
mov rcx, [rbp+48h]
mov eax, [rcx+rax*4]
shr eax, 5
mov ecx, [rbp+64h]
shl ecx, 2
xor eax, ecx
mov [rbp+3F4h], eax
mov ecx, [rbp+64h]
shr ecx, 3
movzx edx, word ptr [rbp+1B4h]
mov edi, [rbp+104h]
lea edx, [rdi+rdx-1]
mov [rbp+3F8h], edx
movzx edi, word ptr [rbp+1B4h]
xor edx, edx
mov r8d, [rbp+3F8h]
mov eax, r8d
div edi
mov eax, edx
mov eax, eax
mov rdx, [rbp+48h]
mov eax, [rdx+rax*4]
shl eax, 4
xor ecx, eax
mov eax, ecx
mov ecx, [rbp+3F4h]
add ecx, eax
mov eax, ecx
mov [rbp+3FCh], eax
mov ecx, [rbp+64h]
mov edx, [rbp+0A4h]
xor edx, ecx
mov ecx, edx
mov edx, [rbp+0E4h]
mov edi, [rbp+104h]
xor edi, edx
mov edx, edi
and edx, 3
mov edx, edx
mov [rbp+400h], rdx
movzx edi, word ptr [rbp+1B4h]
mov r8d, [rbp+104h]
lea edi, [r8+rdi-1]
movzx r8d, word ptr [rbp+1B4h]
xor edx, edx
mov eax, edi
div r8d
mov eax, edx
mov eax, eax
mov rdx, [rbp+48h]
mov eax, [rdx+rax*4]
mov rdx, [rbp+400h]
mov edx, [rbp+rdx*4+188h]
xor edx, eax
mov eax, edx
add ecx, eax
mov eax, ecx
mov ecx, [rbp+3FCh]
xor ecx, eax
mov eax, ecx
mov ecx, [rbp+104h]
mov rdx, [rbp+48h]
mov ecx, [rdx+rcx*4]
add ecx, eax
mov [rbp+408h], ecx
mov eax, [rbp+104h]
mov rcx, [rbp+48h]
mov edx, [rbp+408h]
mov [rcx+rax*4], edx
mov eax, [rbp+408h]
mov [rbp+84h], eax
rdtsc
shl rdx, 20h
or rax, rdx
sub rax, [rbp+218h]
cmp rax, 83C0h
jbe loc_1401F8DD6 ; 此处未跳转
xor eax, eax
jmp sub_1401F9416
mov rdi, rax
lea rcx, [rbp-20h]
mov rdx, 1401A1140h
lea rdx, [rdx]
mov rax, 1400890B6h
call rax
mov rax, rdi
mov rcx, [rbp+410h]
xor rcx, rbp
mov rax, 140087CA2h
call rax

程序到此退出,先分析上面的结构可以发现这是一个XXTEA加密,只不过还没循环就被时间差反调试拦下了,修改跳转指令为不等跳转,继续分析:

1
2
3
4
5
6
7
8
jmp     loc_1401F407E
mov eax, [rbp+104h]
inc eax
mov [rbp+104h], eax
movzx eax, word ptr [rbp+1B4h]
cmp [rbp+104h], eax
jnb loc_1401F99F2
rdtsc

……后面就是循环了,直接修改跳转条件,循环结束后:

1
2
3
4
5
6
7
8
9
jnb     loc_1401F99F2
jmp loc_1401F8CAA
mov eax, [rbp+124h]
mov [rbp+3F4h], eax
mov eax, [rbp+124h]
dec eax ; --rounds
mov [rbp+124h], eax
cmp dword ptr [rbp+3F4h], 0
jbe loc_1401F9BE6 ; 根据XXTEA结构,这个循环也要退出

继续修改跳转条件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
mov     dword ptr [rbp+3F8h], 0
cmp dword ptr [rbp+3F8h], 0
jz loc_1401F9DDA ; 这里应该是加密次数
mov dword ptr [rbp+238h], 0A9934E2Fh
mov dword ptr [rbp+23Ch], 30B90FAh
mov dword ptr [rbp+240h], 0DCBF1D3h
mov dword ptr [rbp+244h], 328B5BDEh
mov dword ptr [rbp+248h], 44FAB4Eh
mov dword ptr [rbp+24Ch], 1DCF0051h
mov dword ptr [rbp+250h], 85EBBE55h
mov dword ptr [rbp+254h], 93AA773Ah
mov qword ptr [rbp+278h], 0
jmp loc_1401F8DD6
cmp qword ptr [rbp+278h], 4
jnb loc_1401F9286

这里如果跳转,下一条是:

1
mov     rcx, 1401A11C0h ; 对应right!

则说明上面的8个dword就是密文,解析上面的汇编,动调得到密钥[0x2daf, 0x669d, 0x3954, 0x3e5a],重构加密逻辑并解密:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
def dwords_to_bytes_little_endian(dword_array):
byte_list = []
for dword in dword_array:
byte_list.extend(dword.to_bytes(4, byteorder='little'))
return byte_list

def XXTEA(m, k):
n = 8
delta = 0x61C88646
r = 6 + 52 // n
mul = (r * delta) & 0xFFFFFFFF
rounds = 6 + mul // delta
ttl = 0
for j in range(rounds-1, -1, -1):
ttl = (ttl + delta) & 0xFFFFFFFF
e = ttl >> 2 & 3
for i in range(n):
after = m[(i + 1) % n]
before = m[(i - 1) % n]
m[i] = (m[i] + (((before >> 5) ^ (after << 2)) + ((after >> 3) ^ (before << 4)) ^ ((ttl ^ after) + (k[(i ^ e) & 3] ^ before)))) & 0xFFFFFFFF
return m

def de_XXTEA(m, k):
n = 8
delta = 0x61C88646
r = 6 + 52 // n
mul = (r * delta) & 0xFFFFFFFF
rounds = 6 + mul // delta
ttl = ((rounds + 1) * delta) & 0xFFFFFFFF
for j in range(0, rounds, 1):
ttl = (ttl - delta) & 0xFFFFFFFF
e = ttl >> 2 & 3
for i in range(n-1, -1, -1):
after = m[(i + 1) % n]
before = m[(i - 1) % n]
m[i] = (m[i] - (((before >> 5) ^ (after << 2)) + ((after >> 3) ^ (before << 4)) ^ ((ttl ^ after) + (k[(i ^ e) & 3] ^ before)))) & 0xFFFFFFFF
return m

dwordenc = [0xA9934E2F, 0x030B90FA, 0x0DCBF1D3, 0x328B5BDE,
0x044FAB4E, 0x1DCF0051, 0x85EBBE55, 0x93AA773A]
dwordkey = [0x2daf, 0x669d, 0x3954, 0x3e5a]

# 解密flag
dwordflag = de_XXTEA(dwordenc, dwordkey)
flag = bytearray(dwords_to_bytes_little_endian(dwordflag))
print(flag.decode())

得到flag:flag{th15_15_51mpLe_obf_R19Ht?}.

Moon:

在pyd文件中发现一个十六进制字符串:
426b87abd0ceaa3c58761bbb0172606dd8ab064491a2a76af9a93e1ae56fa84206a2f7,猜测是密文,观察发现貌似是用固定的seed进行random异或,编写脚本爆破:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import random

c = bytearray(b'\x42\x6b\x87\xab\xd0\xce\xaa\x3c\x58\x76\x1b\xbb\x01\x72\x60\x6d\xd8\xab\x06\x44\x91\xa2\xa7\x6a\xf9\xa9\x3e\x1a\xe5\x6f\xa8\x42\x06\xa2\xf7')
target = b"flag{"
rnums = [None] * len(c)

def randomXor(c, rnums, seed):
random.seed(seed)
for i in range(len(c)):
rnums[i] = random.randint(0, 255)
c[i] ^= rnums[i]
return bytes(c)

def crack():
for seed in range(10000000):
if seed % 100000 == 0:
print(f"Testing seed: {seed}")
random.seed(seed)
rnums = [random.randint(0, 255) for _ in range(len(c))]
match = True
for k in range(len(target)):
if c[k] ^ rnums[k] != target[k]:
match = False
break
if match:
print(f"\nMatch found with seed: {seed}")
decrypted = randomXor(bytearray(c), rnums, seed)
print(f"Decrypted: {decrypted.decode('utf-8', errors='ignore')}")
return

crack()

得到flag:flag{but_y0u_l00k3d_up_@t_th3_mOOn}.

Lake:

程序是用pascal语言写的,而且字符是一个一个打印的,无法直接查找,但是注意到字符串之间有时间间隔,查询sleep函数的xref,找到了main函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
int __fastcall __noreturn main(int argc, const char **argv, const char **envp)
{
// [COLLAPSED LOCAL DECLARATIONS. PRESS KEYPAD CTRL-"+" TO EXPAND]

sub_100008570();
index = -1;
do
{
text1[++index] ^= 0x33u;
v3 = sub_10000C190();
sub_10000C760(0i64, v3, LOBYTE(text1[index]));
sub_100008510();
sub_10000C2F0(v3);
sub_100008510();
if ( qword_100021B50 )
v4 = (void *)qword_100021B50(unk_100020580);
else
v4 = &unk_100020588;
sub_10000C0C0(v4);
sub_100008510();
Sleep_0(0);
}
while ( (__int16)index < 94 );
v5 = sub_10000C190();
sub_10000C310(v5);
sub_100008510();
index = -1;
do
{
text2[++index] -= 37;
v6 = sub_10000C190();
sub_10000C760(0i64, v6, LOBYTE(text2[index]));
sub_100008510();
sub_10000C2F0(v6);
sub_100008510();
if ( qword_100021B50 )
v7 = (void *)qword_100021B50(unk_100020580);
else
v7 = &unk_100020588;
sub_10000C0C0(v7);
sub_100008510();
Sleep_0(0);
}
while ( (__int16)index < 73 );
v8 = sub_10000C190();
sub_10000C310(v8);
sub_100008510();
index = -1;
do
{
text3[++index] ^= 0x77u;
v9 = sub_10000C190();
sub_10000C760(0i64, v9, LOBYTE(text3[index]));
sub_100008510();
sub_10000C2F0(v9);
sub_100008510();
if ( qword_100021B50 )
v10 = (void *)qword_100021B50(unk_100020580);
else
v10 = &unk_100020588;
sub_10000C0C0(v10);
sub_100008510();
Sleep_0(0);
}
while ( (__int16)index < 55 );
v11 = sub_10000C190();
sub_10000C310(v11);
sub_100008510();
Sleep_0(0x1F4u);
index = -1;
do
{
text4[++index] += 8;
v12 = sub_10000C190();
sub_10000C760(0i64, v12, LOBYTE(text4[index]));
sub_100008510();
sub_10000C2F0(v12);
sub_100008510();
if ( qword_100021B50 )
v13 = (void *)qword_100021B50(unk_100020580);
else
v13 = &unk_100020588;
sub_10000C0C0(v13);
sub_100008510();
Sleep_0(0);
}
while ( (__int16)index < 49 );
v14 = sub_10000C190();
sub_10000C310(v14);
sub_100008510();
v15 = (const char *)sub_10000C160();
scanf(v15, inputstr, 255i64);
sub_100008510();
sub_10000C940(v15);
sub_100008510();
sub_1000026E0(input, 40i64, 0i64);
v16 = (unsigned __int8)inputstr[0];
if ( inputstr[0] )
{
index = 0;
do
{
if ( (__int16)++index - 1i64 <= 39 )
input[(__int16)index - 1] = inputstr[(unsigned __int8)index];
}
while ( v16 > (__int16)index );
}
index = 0;
while ( (__int16)index < 300i64 )
{
opcode = opc[index];
arg1 = opc[(__int16)index + 1];
arg2 = opc[(__int16)index + 2];
index += 3;
if ( opcode >= 1 )
{
switch ( opcode )
{
case 1:
add(arg1, arg2);
break;
case 2:
sub(arg1, arg2);
break;
case 3:
mul(arg1, arg2);
break;
case 4:
div_((__int16)arg1, (unsigned __int8)arg2);
break;
case 5:
mod(arg1, arg2);
break;
case 6:
and(arg1, arg2);
break;
case 7:
or(arg1, arg2);
break;
case 8:
xor(arg1, arg2);
break;
}
}
}
enc((__int64)input, 39i64);
tag = 0;
index_ = -1;
while ( 1 )
{
++index_;
if ( input[(unsigned __int16)index_] != cipher[(unsigned __int16)index_] )
tag = 1;
if ( index_ >= 39 )
{
if ( tag )
{
index = -1;
do
{
text6[++index] ^= 0x28u;
v19 = sub_10000C190();
sub_10000C760(0i64, v19, LOBYTE(text6[index]));
sub_100008510();
sub_10000C2F0(v19);
sub_100008510();
if ( qword_100021B50 )
v20 = (void *)qword_100021B50(unk_100020580);
else
v20 = &unk_100020588;
sub_10000C0C0(v20);
sub_100008510();
Sleep_0(0x64u);
}
while ( (__int16)index < 35 );
}
else
{
index = -1;
do
{
text5[++index] ^= 0x28u;
v17 = sub_10000C190();
sub_10000C760(0i64, v17, LOBYTE(text5[index]));
sub_100008510();
sub_10000C2F0(v17);
sub_100008510();
if ( qword_100021B50 )
v18 = (void *)qword_100021B50(unk_100020580);
else
v18 = &unk_100020588;
sub_10000C0C0(v18);
sub_100008510();
Sleep_0(0x64u);
}
while ( (__int16)index < 43 );
}
v21 = sub_10000C190();
sub_10000C310(v21);
sub_100008510();
sub_100008980();
}
}
}

发现是一个VM+加密,提取字节码编写同构脚本并解密:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
opc = [0x02, 0x02, 0x0C, 0x01, 0x1A, 0x55, 0x01, 0x23, 0x0C, 0x02, 0x0E, 0x09, 
0x01, 0x1B, 0x06, 0x08, 0x06, 0x05, 0x08, 0x01, 0x05, 0x02, 0x1B, 0x0E,
0x02, 0x19, 0x03, 0x02, 0x1A, 0x04, 0x08, 0x04, 0x08, 0x01, 0x03, 0x0C,
0x02, 0x0C, 0x0A, 0x01, 0x25, 0x02, 0x01, 0x20, 0x02, 0x01, 0x09, 0x0C,
0x08, 0x1A, 0x05, 0x02, 0x04, 0x0D, 0x08, 0x08, 0x0F, 0x02, 0x0A, 0x0E,
0x01, 0x10, 0x07, 0x01, 0x0C, 0x07, 0x08, 0x22, 0x08, 0x08, 0x15, 0x0A,
0x01, 0x27, 0x7E, 0x02, 0x07, 0x02, 0x08, 0x0F, 0x03, 0x08, 0x0A, 0x0A,
0x01, 0x22, 0x0B, 0x02, 0x12, 0x08, 0x02, 0x19, 0x09, 0x08, 0x0E, 0x06,
0x08, 0x00, 0x05, 0x01, 0x0A, 0x08, 0x08, 0x1B, 0x07, 0x08, 0x0D, 0x06,
0x08, 0x0D, 0x04, 0x08, 0x17, 0x0C, 0x08, 0x22, 0x0E, 0x02, 0x12, 0x34,
0x01, 0x26, 0x77]

for i in range(0, len(opc), 3):
a = opc[i]
b = opc[i+1]
c = opc[i+2]
if a == 0:
break
elif a == 1:
print(f"m[{b}] = (m[{b}] + {hex(c)}) & 0xFF")
elif a == 2:
print(f"m[{b}] = (m[{b}] - {hex(c)}) & 0xFF")
elif a == 3:
print(f"m[{b}] = (m[{b}] * {hex(c)}) & 0xFF")
elif a == 4:
print(f"m[{b}] = (m[{b}] // {hex(c)}) & 0xFF")
elif a == 5:
print(f"m[{b}] = (m[{b}] % {hex(c)}) & 0xFF")
elif a == 6:
print(f"m[{b}] = (m[{b}] & {hex(c)}) & 0xFF")
elif a == 7:
print(f"m[{b}] = (m[{b}] | {hex(c)}) & 0xFF")
elif a == 8:
print(f"m[{b}] = (m[{b}] ^ {hex(c)}) & 0xFF")
else:
print(f"unknown opcode")

def VM(m):
m[2] = (m[2] - 0xc) & 0xFF
m[26] = (m[26] + 0x55) & 0xFF
m[35] = (m[35] + 0xc) & 0xFF
m[14] = (m[14] - 0x9) & 0xFF
m[27] = (m[27] + 0x6) & 0xFF
m[6] = (m[6] ^ 0x5) & 0xFF
m[1] = (m[1] ^ 0x5) & 0xFF
m[27] = (m[27] - 0xe) & 0xFF
m[25] = (m[25] - 0x3) & 0xFF
m[26] = (m[26] - 0x4) & 0xFF
m[4] = (m[4] ^ 0x8) & 0xFF
m[3] = (m[3] + 0xc) & 0xFF
m[12] = (m[12] - 0xa) & 0xFF
m[37] = (m[37] + 0x2) & 0xFF
m[32] = (m[32] + 0x2) & 0xFF
m[9] = (m[9] + 0xc) & 0xFF
m[26] = (m[26] ^ 0x5) & 0xFF
m[4] = (m[4] - 0xd) & 0xFF
m[8] = (m[8] ^ 0xf) & 0xFF
m[10] = (m[10] - 0xe) & 0xFF
m[16] = (m[16] + 0x7) & 0xFF
m[12] = (m[12] + 0x7) & 0xFF
m[34] = (m[34] ^ 0x8) & 0xFF
m[21] = (m[21] ^ 0xa) & 0xFF
m[39] = (m[39] + 0x7e) & 0xFF
m[7] = (m[7] - 0x2) & 0xFF
m[15] = (m[15] ^ 0x3) & 0xFF
m[10] = (m[10] ^ 0xa) & 0xFF
m[34] = (m[34] + 0xb) & 0xFF
m[18] = (m[18] - 0x8) & 0xFF
m[25] = (m[25] - 0x9) & 0xFF
m[14] = (m[14] ^ 0x6) & 0xFF
m[0] = (m[0] ^ 0x5) & 0xFF
m[10] = (m[10] + 0x8) & 0xFF
m[27] = (m[27] ^ 0x7) & 0xFF
m[13] = (m[13] ^ 0x6) & 0xFF
m[13] = (m[13] ^ 0x4) & 0xFF
m[23] = (m[23] ^ 0xc) & 0xFF
m[34] = (m[34] ^ 0xe) & 0xFF
m[18] = (m[18] - 0x34) & 0xFF
m[38] = (m[38] + 0x77) & 0xFF
return m

def rotate(data):
result = [0] * 40
for i in range(0, 40, 4):
result[i + 0] = (data[i + 1] << 3) | (data[i + 2] >> 5)
result[i + 1] = (data[i + 2] << 3) | (data[i + 3] >> 5)
result[i + 2] = (data[i + 3] << 3) | (data[i + 0] >> 5)
result[i + 3] = (data[i + 0] << 3) | (data[i + 1] >> 5)
for v4 in range(40):
data[v4] = result[v4] & 0xFF
return data

def de_rotate(data):
result = [0] * 40
for i in range(0, 40, 4):
result[i + 0] = (data[i + 3] >> 3) | ((data[i + 2] & 0x1F) << 5)
result[i + 1] = (data[i + 0] >> 3) | ((data[i + 3] & 0x1F) << 5)
result[i + 2] = (data[i + 1] >> 3) | ((data[i + 0] & 0x1F) << 5)
result[i + 3] = (data[i + 2] >> 3) | ((data[i + 1] & 0x1F) << 5)
for v4 in range(40):
data[v4] = result[v4] & 0xFF
return data

def encrypt(data):
return rotate(VM(data))

# 测试加密
# a = [102, 108, 97, 103]*10
# b = encrypt(a)
# print(b)
# assert b = [74, 171, 155, 27, 99, 35, 43, 11, 195, 11, 59, 75, 114, 243, 35, 27, 97, 43, 59, 107, 51, 11, 91, 51, 5, 186, 195, 51, 99, 11, 59, 51, 99, 211, 155, 67, 118, 199, 43, 51]

# 解密
cipher = [0x4A, 0xAB, 0x9B, 0x1B, 0x61, 0xB1, 0xF3, 0x32, 0xD1, 0x8B,
0x73, 0xEB, 0xE9, 0x73, 0x6B, 0x22, 0x81, 0x83, 0x23, 0x31,
0xCB, 0x1B, 0x22, 0xFB, 0x25, 0xC2, 0x81, 0x81, 0x73, 0x22,
0xFA, 0x03, 0x9C, 0x4B, 0x5B, 0x49, 0x97, 0x87, 0xDB, 0x51]

cipher = de_rotate(cipher)

dm = [0]*40
for i in range(40):
m = dm
possible = []
for j in range(255):
m[i] = j
c = VM(m)
if c[i] == cipher[i]:
possible.append(j)
print(hex(possible[0]),end=", ")

得到flag:flag{L3@rn1ng_1n_0ld_sch00l_@nd_g3t_j0y}.

ezVM:

从start找到main:

1
2
3
4
5
6
7
8
9
10
11
12
13
// positive sp value has been detected, the output may be wrong!
void __fastcall __noreturn start(__int64 a1, __int64 a2, int a3)
{
__int64 v3; // rax
int v4; // esi
__int64 v5; // [rsp-8h] [rbp-8h] BYREF
_UNKNOWN *retaddr; // [rsp+0h] [rbp+0h] BYREF

v4 = v5;
v5 = v3;
sub_11B7B30((unsigned int)main, v4, (unsigned int)&retaddr, 0, 0, a3, (__int64)&v5);
__halt();
}

main:

1
2
3
4
5
6
7
8
9
10
11
12
13
int __fastcall main(int argc, const char **argv, const char **envp)
{
printf((__int64)"Welcome come to house of Showmaker \nPlease input your flag ");
scanf((__int64)"%32s", &input);
if ( j_strlen_ifunc(&input) != 32 )
printf((__int64)"Wrong! ");
VM();
if ( !(unsigned int)memcmp(&enc, &cipher, 32LL) )
printf((__int64)"Right! ");
else
printf((__int64)"Wrong1 ");
return 0;
}

查看VM:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
unsigned __int64 VM()
{
__int64 v0; // r8
__int64 v1; // r8
unsigned __int64 result; // rax
__int64 v3; // [rsp+10h] [rbp-10h] BYREF
unsigned __int64 v4; // [rsp+18h] [rbp-8h]

v4 = __readfsqword(0x28u);
if ( !(unsigned int)sub_4042B0(2u, 0, &v3) )
{
sub_4054E0(v3, 0LL, (__int64)&loc_1000000, 7u, v0);
sub_4054E0(v3, (unsigned __int64)off_1639E60 - 4096, 0x4000LL, 7u, v1);
sub_405100(v3, qword_1639E68, (__int64)input, 0x20uLL);
sub_405100(v3, qword_1639E90, (__int64)byte_1637180, 0x2288uLL);
sub_405100(v3, qword_1639E70, (__int64)dword_1639420, 0x9B8uLL);
sub_405100(v3, qword_1639E78, (__int64)dword_1639DE0, 0x54uLL);
sub_405100(v3, qword_1639E80, (__int64)&qword_1639E88, 8uLL);
sub_404D60(v3, 199LL, &qword_1639E68);
sub_404D60(v3, 4LL, &off_1639E60);
if ( !(unsigned int)sub_406670(v3, qword_1639E90, qword_1639E98, 0LL, 0LL) )
sub_404F90(v3, qword_1639E68, (__int64)&enc, 0x30uLL);
}
result = v4 - __readfsqword(0x28u);
if ( result )
sub_1215E60();
return result;
}

注意到dword_1639420是字节码,进行提取,观察发现和NPC²CTF的babyVM的字节码不能说是完全无关,也只能说是一模一样,直接套之前的板子求解,发现opc4-1的行为未定义,经过测试发现大小为4,猜测作用为寄存器+寄存器,补全运行得到执行流,观察执行流:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
op 101: 0x2, 0x2, 0x4, 0xffffffb0, 0x53, asm: mov (0#BYTE)memory[41] = 0x0, reg[83] = 0x53
op 106: 0x2, 0x2, 0x4, 0xffffffb1, 0x68, asm: mov (1#BYTE)memory[41] = 0x0, reg[104] = 0x68
op 111: 0x2, 0x2, 0x4, 0xffffffb2, 0x6f, asm: mov (2#BYTE)memory[41] = 0x0, reg[111] = 0x6f
op 116: 0x2, 0x2, 0x4, 0xffffffb3, 0x77, asm: mov (3#BYTE)memory[41] = 0x0, reg[119] = 0x77
op 121: 0x2, 0x2, 0x4, 0xffffffb4, 0x6d, asm: mov (0#BYTE)memory[42] = 0x0, reg[109] = 0x6d
op 126: 0x2, 0x2, 0x4, 0xffffffb5, 0x61, asm: mov (1#BYTE)memory[42] = 0x0, reg[97] = 0x61
op 131: 0x2, 0x2, 0x4, 0xffffffb6, 0x6b, asm: mov (2#BYTE)memory[42] = 0x0, reg[107] = 0x6b
op 136: 0x2, 0x2, 0x4, 0xffffffb7, 0x65, asm: mov (3#BYTE)memory[42] = 0x0, reg[101] = 0x65
op 141: 0x2, 0x2, 0x4, 0xffffffb8, 0x72, asm: mov (0#BYTE)memory[43] = 0x0, reg[114] = 0x72
op 146: 0x2, 0x2, 0x4, 0xffffffb9, 0x5f, asm: mov (1#BYTE)memory[43] = 0x0, reg[95] = 0x5f
op 151: 0x2, 0x2, 0x4, 0xffffffba, 0x6d, asm: mov (2#BYTE)memory[43] = 0x0, reg[109] = 0x6d
op 156: 0x2, 0x2, 0x4, 0xffffffbb, 0x61, asm: mov (3#BYTE)memory[43] = 0x0, reg[97] = 0x61
op 161: 0x2, 0x2, 0x4, 0xffffffbc, 0x64, asm: mov (0#BYTE)memory[44] = 0x0, reg[100] = 0x64
op 166: 0x2, 0x2, 0x4, 0xffffffbd, 0x65, asm: mov (1#BYTE)memory[44] = 0x0, reg[101] = 0x65
op 171: 0x2, 0x2, 0x4, 0xffffffbe, 0x69, asm: mov (2#BYTE)memory[44] = 0x0, reg[105] = 0x69
op 176: 0x2, 0x2, 0x4, 0xffffffbf, 0x74, asm: mov (3#BYTE)memory[44] = 0x0, reg[116] = 0x74

得到密钥:Showmaker_madeit

查看加密流:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
op 311: 0x9, 0x2, 0x4, 0xfffffff8, 0x8, asm: cmp (#0BYTE)memory[59] = 0x0, 0x8 ; 8个dword
op 316: 0x13, 0x268, asm: je(xmm[1],xmm[3]) 0x268 unjump here
op 318: 0x2, 0x3, 0x2, 0x4, 0xfffffff8, asm: mov reg[2] = 0xa4, memory[59] = 0x0
op 323: 0x2, 0x3, 0x3, 0x4, 0xffffffe0, asm: mov reg[3] = 0x74696564, memory[53] = 0x200
op 328: 0x2, 0x9, 0x0, 0x3, 0x2, 0x4, asm: mov reg[0] = 0xc, memory[128] = 0x30303030
op 334: 0x2, 0x0, 0x4, 0xffffffec, 0x0, asm: mov memory[56] = 0x0, reg[0] = 0x30303030
op 339: 0x2, 0x3, 0x2, 0x4, 0xfffffff8, asm: mov reg[2] = 0x0, memory[59] = 0x0
op 344: 0x2, 0x3, 0x3, 0x4, 0xffffffe0, asm: mov reg[3] = 0x200, memory[53] = 0x200
op 349: 0x2, 0xa, 0x0, 0x3, 0x2, 0x4, 0x4, asm: mov reg[0] = 0x30303030, memory[129] = 0x31313131
op 356: 0x2, 0x0, 0x4, 0xffffffe8, 0x0, asm: mov memory[55] = 0x0, reg[0] = 0x31313131
op 361: 0x2, 0x7, 0x4, 0xfffffff0, 0x0, asm: mov memory[57] = 0x0, 0x0
op 366: 0x2, 0x7, 0x4, 0xffffffdc, 0x0, asm: mov memory[52] = 0x0, 0x0
op 371: 0xc, 0x183, asm: jmp 0x183
op 387: 0x9, 0x2, 0x4, 0xffffffdc, 0x48, asm: cmp (#0BYTE)memory[52] = 0x0, 0x48 ; 72轮循环
op 392: 0x14, 0x23b, asm: jz(xmm[2]) 0x23b unjump here
op 394: 0x2, 0x3, 0x3, 0x4, 0xffffffe8, asm: mov reg[3] = 0x200, memory[55] = 0x31313131
op 399: 0x7, 0x4, 0x3, 0x5, asm: shr reg[3] = 0x31313131, 0x5
op 403: 0x2, 0x3, 0x0, 0x4, 0xffffffe8, asm: mov reg[0] = 0x31313131, memory[55] = 0x31313131
op 408: 0x8, 0x4, 0x0, 0x6, asm: shl reg[0] = 0x31313131, 0x6
op 412: 0x5, 0x1, 0x3, 0x0, asm: xor reg[3] = 0x1898989, reg[0] = 0x4c4c4c40
op 416: 0x2, 0x3, 0x2, 0x4, 0xffffffe8, asm: mov reg[2] = 0x0, memory[55] = 0x31313131
op 421: 0x5, 0x4, 0x2, 0x11223344, asm: xor reg[2] = 0x31313131, 0x11223344
op 425: 0x4, 0x1, 0x3, 0x2, asm: add reg[3] = 0x4dc5c5c9, 0x20130275
op 429: 0x2, 0x3, 0x2, 0x4, 0xfffffff0, asm: mov reg[2] = 0x20130275, memory[57] = 0x0
op 434: 0xd, 0x4, 0x2, 0x3, asm: and reg[2] = 0x0, 0x3
op 438: 0x2, 0x3, 0x0, 0x4, 0xfffffff4, asm: mov reg[0] = 0x4c4c4c40, memory[58] = 0xa4
op 443: 0x2, 0x9, 0x2, 0x0, 0x2, 0x4, asm: mov reg[2] = 0x0, memory[41] = 0x776f6853
op 449: 0x4, 0x3, 0x2, 0x4, 0xfffffff0, asm: add reg[2] = 0x776f6853, memory[57] = 0x0
op 454: 0x5, 0x4, 0x2, 0xabab1212, asm: xor reg[2] = 0x776f6853, 0xabab1212
op 458: 0x5, 0x1, 0x3, 0x2, asm: xor reg[3] = 0x6dd8c83e, reg[2] = 0xdcc47a41
op 462: 0x4, 0x3, 0x3, 0x4, 0xffffffec, asm: add reg[3] = 0xb11cb27f, memory[56] = 0x30303030
op 467: 0x2, 0x0, 0x4, 0xffffffec, 0x3, asm: mov memory[56] = 0x30303030, reg[3] = 0xe14ce2af
op 472: 0x2, 0x3, 0x3, 0x4, 0xfffffff0, asm: mov reg[3] = 0xe14ce2af, memory[57] = 0x0
op 477: 0x3, 0x3, 0x3, 0x4, 0xffffffd0, asm: sub reg[3] = 0x0, memory[49] = 0xa0a01919
op 482: 0x2, 0x0, 0x4, 0xfffffff0, 0x3, asm: mov memory[57] = 0x0, reg[3] = 0x5f5fe6e7
op 487: 0x2, 0x3, 0x3, 0x4, 0xffffffec, asm: mov reg[3] = 0x5f5fe6e7, memory[56] = 0xe14ce2af
op 492: 0x7, 0x4, 0x3, 0x4, asm: shr reg[3] = 0xe14ce2af, 0x4
op 496: 0x2, 0x3, 0x0, 0x4, 0xffffffec, asm: mov reg[0] = 0xa4, memory[56] = 0xe14ce2af
op 501: 0x8, 0x4, 0x0, 0x7, asm: shl reg[0] = 0xe14ce2af, 0x7
op 505: 0x5, 0x1, 0x3, 0x0, asm: xor reg[3] = 0xe14ce2a, reg[0] = 0xa6715780
op 509: 0x2, 0x3, 0x2, 0x4, 0xffffffec, asm: mov reg[2] = 0xdcc47a41, memory[56] = 0xe14ce2af
op 514: 0x5, 0x4, 0x2, 0x55667788, asm: xor reg[2] = 0xe14ce2af, 0x55667788
op 518: 0x4, 0x1, 0x3, 0x2, asm: add reg[3] = 0xa86599aa, 0xb42a9527
op 522: 0x2, 0x3, 0x0, 0x4, 0xfffffff0, asm: mov reg[0] = 0xa6715780, memory[57] = 0x5f5fe6e7
op 527: 0x7, 0x4, 0x0, 0xb, asm: shr reg[0] = 0x5f5fe6e7, 0xb
op 531: 0xd, 0x4, 0x0, 0x3, asm: and reg[0] = 0xbebfc, 0x3
op 535: 0x2, 0x3, 0x2, 0x4, 0xfffffff4, asm: mov reg[2] = 0xb42a9527, memory[58] = 0xa4
op 540: 0x2, 0x9, 0x0, 0x2, 0x0, 0x4, asm: mov reg[0] = 0x0, memory[41] = 0x776f6853
op 546: 0x4, 0x3, 0x0, 0x4, 0xfffffff0, asm: add reg[0] = 0x776f6853, memory[57] = 0x5f5fe6e7
op 551: 0x5, 0x4, 0x0, 0x23235566, asm: xor reg[0] = 0xd6cf4f3a, 0x23235566
op 555: 0x5, 0x1, 0x0, 0x3, asm: xor reg[0] = 0xf5ec1a5c, reg[3] = 0x5c902ed1
op 559: 0x4, 0x3, 0x0, 0x4, 0xffffffe8, asm: add reg[0] = 0xa97c348d, memory[55] = 0x31313131
op 564: 0x2, 0x0, 0x4, 0xffffffe8, 0x0, asm: mov memory[55] = 0x31313131, reg[0] = 0xdaad65be
op 569: 0xc, 0x175, asm: jmp 0x175
op 373: 0x2, 0x3, 0x2, 0x4, 0xffffffdc, asm: mov reg[2] = 0xa4, memory[52] = 0x0
op 378: 0x4, 0x4, 0x2, 0x1, asm: add reg[2] = 0x0, 0x1
op 382: 0x2, 0x0, 0x4, 0xffffffdc, 0x2, asm: mov memory[52] = 0x0, reg[2] = 0x1
op 387: 0x9, 0x2, 0x4, 0xffffffdc, 0x48, asm: cmp (#0BYTE)memory[52] = 0x1, 0x48
op 392: 0x14, 0x23b, asm: jz(xmm[2]) 0x23b unjump here

编写同构脚本测试加密并解密:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
import random
import time
import sys

opc = [0x00000000, 0x00000001, 0x00000200, 0x00000000, 0x00000000, 0x00000006, 0x00000000, 0x00000000, 0x00000004, 0x00000002, 0x00000001, 0x00000004, 0x00000005, 0x00000003, 0x00000004, 0x00000005,
0x00000050, 0x00000002, 0x00000003, 0x00000000, 0x00000004, 0x00000008, 0x00000002, 0x00000000, 0x00000004, 0xFFFFFFE4, 0x00000000, 0x00000002, 0x00000003, 0x00000002, 0x00000004, 0xFFFFFFE4,
0x00000004, 0x00000004, 0x00000002, 0x00000001, 0x00000002, 0x00000000, 0x00000004, 0xFFFFFFD8, 0x00000002, 0x00000002, 0x00000003, 0x00000003, 0x00000004, 0xFFFFFFE4, 0x00000002, 0x00000006,
0x00000000, 0x00000003, 0x00000000, 0x00000002, 0x00000005, 0x00000004, 0xFFFFFFFF, 0x00000000, 0x00000004, 0x00000002, 0x00000004, 0xFFFFFFE4, 0x00000001, 0x00000009, 0x00000002, 0x00000004,
0xFFFFFFFF, 0x00000000, 0x0000000A, 0x00000029, 0x00000002, 0x00000003, 0x00000002, 0x00000004, 0xFFFFFFE4, 0x00000003, 0x00000003, 0x00000002, 0x00000004, 0xFFFFFFD8, 0x00000002, 0x00000000,
0x00000004, 0xFFFFFFD4, 0x00000002, 0x00000009, 0x00000002, 0x00000004, 0xFFFFFFD4, 0x00000020, 0x0000000F, 0x0000005B, 0x00000011, 0x00000002, 0x00000003, 0x00000003, 0x00000004, 0x00000008,
0x00000002, 0x00000000, 0x00000004, 0xFFFFFFE0, 0x00000003, 0x00000002, 0x00000002, 0x00000004, 0xFFFFFFB0, 0x00000053, 0x00000002, 0x00000002, 0x00000004, 0xFFFFFFB1, 0x00000068, 0x00000002,
0x00000002, 0x00000004, 0xFFFFFFB2, 0x0000006F, 0x00000002, 0x00000002, 0x00000004, 0xFFFFFFB3, 0x00000077, 0x00000002, 0x00000002, 0x00000004, 0xFFFFFFB4, 0x0000006D, 0x00000002, 0x00000002,
0x00000004, 0xFFFFFFB5, 0x00000061, 0x00000002, 0x00000002, 0x00000004, 0xFFFFFFB6, 0x0000006B, 0x00000002, 0x00000002, 0x00000004, 0xFFFFFFB7, 0x00000065, 0x00000002, 0x00000002, 0x00000004,
0xFFFFFFB8, 0x00000072, 0x00000002, 0x00000002, 0x00000004, 0xFFFFFFB9, 0x0000005F, 0x00000002, 0x00000002, 0x00000004, 0xFFFFFFBA, 0x0000006D, 0x00000002, 0x00000002, 0x00000004, 0xFFFFFFBB,
0x00000061, 0x00000002, 0x00000002, 0x00000004, 0xFFFFFFBC, 0x00000064, 0x00000002, 0x00000002, 0x00000004, 0xFFFFFFBD, 0x00000065, 0x00000002, 0x00000002, 0x00000004, 0xFFFFFFBE, 0x00000069,
0x00000002, 0x00000002, 0x00000004, 0xFFFFFFBF, 0x00000074, 0x00000006, 0x00000003, 0x00000000, 0x00000004, 0xFFFFFFB0, 0x00000002, 0x00000000, 0x00000004, 0xFFFFFFF4, 0x00000000, 0x00000002,
0x00000007, 0x00000004, 0xFFFFFFD0, 0xA0A01919, 0x00000002, 0x00000004, 0x00000002, 0x00000004, 0x00000012, 0x00000004, 0x00000003, 0x00000002, 0x00000000, 0x00000002, 0x00000003, 0x00000000,
0x00000004, 0xFFFFFFF4, 0x00000002, 0x00000008, 0x00000002, 0x00000000, 0x00000003, 0x00000002, 0x00000000, 0x00000004, 0xFFFFFFCC, 0x00000002, 0x00000002, 0x00000004, 0x00000003, 0x00000004,
0x00000008, 0x00000004, 0x00000003, 0x00000000, 0x00000002, 0x00000003, 0x00000000, 0x00000004, 0xFFFFFFF4, 0x00000002, 0x00000008, 0x00000002, 0x00000000, 0x00000003, 0x00000002, 0x00000000,
0x00000004, 0xFFFFFFC8, 0x00000002, 0x00000002, 0x00000004, 0x00000003, 0x00000004, 0x00000008, 0x00000004, 0x00000003, 0x00000001, 0x00000002, 0x00000003, 0x00000000, 0x00000004, 0xFFFFFFF4,
0x00000002, 0x00000008, 0x00000002, 0x00000000, 0x00000003, 0x00000002, 0x00000000, 0x00000004, 0xFFFFFFC4, 0x00000002, 0x00000002, 0x00000004, 0x00000003, 0x00000004, 0x00000012, 0x00000004,
0x00000000, 0x00000003, 0x00000003, 0x00000002, 0x00000003, 0x00000002, 0x00000004, 0xFFFFFFF4, 0x00000002, 0x00000008, 0x00000003, 0x00000002, 0x00000000, 0x00000002, 0x00000000, 0x00000004,
0xFFFFFFC0, 0x00000003, 0x00000002, 0x00000007, 0x00000004, 0xFFFFFFF8, 0x00000000, 0x0000000C, 0x00000137, 0x00000002, 0x00000003, 0x00000000, 0x00000004, 0xFFFFFFF8, 0x00000004, 0x00000004,
0x00000000, 0x00000002, 0x00000002, 0x00000000, 0x00000004, 0xFFFFFFF8, 0x00000000, 0x00000009, 0x00000002, 0x00000004, 0xFFFFFFF8, 0x00000008, 0x00000013, 0x00000268, 0x00000002, 0x00000003,
0x00000002, 0x00000004, 0xFFFFFFF8, 0x00000002, 0x00000003, 0x00000003, 0x00000004, 0xFFFFFFE0, 0x00000002, 0x00000009, 0x00000000, 0x00000003, 0x00000002, 0x00000004, 0x00000002, 0x00000000,
0x00000004, 0xFFFFFFEC, 0x00000000, 0x00000002, 0x00000003, 0x00000002, 0x00000004, 0xFFFFFFF8, 0x00000002, 0x00000003, 0x00000003, 0x00000004, 0xFFFFFFE0, 0x00000002, 0x0000000A, 0x00000000,
0x00000003, 0x00000002, 0x00000004, 0x00000004, 0x00000002, 0x00000000, 0x00000004, 0xFFFFFFE8, 0x00000000, 0x00000002, 0x00000007, 0x00000004, 0xFFFFFFF0, 0x00000000, 0x00000002, 0x00000007,
0x00000004, 0xFFFFFFDC, 0x00000000, 0x0000000C, 0x00000183, 0x00000002, 0x00000003, 0x00000002, 0x00000004, 0xFFFFFFDC, 0x00000004, 0x00000004, 0x00000002, 0x00000001, 0x00000002, 0x00000000,
0x00000004, 0xFFFFFFDC, 0x00000002, 0x00000009, 0x00000002, 0x00000004, 0xFFFFFFDC, 0x00000048, 0x00000014, 0x0000023B, 0x00000002, 0x00000003, 0x00000003, 0x00000004, 0xFFFFFFE8, 0x00000007,
0x00000004, 0x00000003, 0x00000005, 0x00000002, 0x00000003, 0x00000000, 0x00000004, 0xFFFFFFE8, 0x00000008, 0x00000004, 0x00000000, 0x00000006, 0x00000005, 0x00000001, 0x00000003, 0x00000000,
0x00000002, 0x00000003, 0x00000002, 0x00000004, 0xFFFFFFE8, 0x00000005, 0x00000004, 0x00000002, 0x11223344, 0x00000004, 0x00000001, 0x00000003, 0x00000002, 0x00000002, 0x00000003, 0x00000002,
0x00000004, 0xFFFFFFF0, 0x0000000D, 0x00000004, 0x00000002, 0x00000003, 0x00000002, 0x00000003, 0x00000000, 0x00000004, 0xFFFFFFF4, 0x00000002, 0x00000009, 0x00000002, 0x00000000, 0x00000002,
0x00000004, 0x00000004, 0x00000003, 0x00000002, 0x00000004, 0xFFFFFFF0, 0x00000005, 0x00000004, 0x00000002, 0xABAB1212, 0x00000005, 0x00000001, 0x00000003, 0x00000002, 0x00000004, 0x00000003,
0x00000003, 0x00000004, 0xFFFFFFEC, 0x00000002, 0x00000000, 0x00000004, 0xFFFFFFEC, 0x00000003, 0x00000002, 0x00000003, 0x00000003, 0x00000004, 0xFFFFFFF0, 0x00000003, 0x00000003, 0x00000003,
0x00000004, 0xFFFFFFD0, 0x00000002, 0x00000000, 0x00000004, 0xFFFFFFF0, 0x00000003, 0x00000002, 0x00000003, 0x00000003, 0x00000004, 0xFFFFFFEC, 0x00000007, 0x00000004, 0x00000003, 0x00000004,
0x00000002, 0x00000003, 0x00000000, 0x00000004, 0xFFFFFFEC, 0x00000008, 0x00000004, 0x00000000, 0x00000007, 0x00000005, 0x00000001, 0x00000003, 0x00000000, 0x00000002, 0x00000003, 0x00000002,
0x00000004, 0xFFFFFFEC, 0x00000005, 0x00000004, 0x00000002, 0x55667788, 0x00000004, 0x00000001, 0x00000003, 0x00000002, 0x00000002, 0x00000003, 0x00000000, 0x00000004, 0xFFFFFFF0, 0x00000007,
0x00000004, 0x00000000, 0x0000000B, 0x0000000D, 0x00000004, 0x00000000, 0x00000003, 0x00000002, 0x00000003, 0x00000002, 0x00000004, 0xFFFFFFF4, 0x00000002, 0x00000009, 0x00000000, 0x00000002,
0x00000000, 0x00000004, 0x00000004, 0x00000003, 0x00000000, 0x00000004, 0xFFFFFFF0, 0x00000005, 0x00000004, 0x00000000, 0x23235566, 0x00000005, 0x00000001, 0x00000000, 0x00000003, 0x00000004,
0x00000003, 0x00000000, 0x00000004, 0xFFFFFFE8, 0x00000002, 0x00000000, 0x00000004, 0xFFFFFFE8, 0x00000000, 0x0000000C, 0x00000175, 0x00000002, 0x00000003, 0x00000000, 0x00000004, 0xFFFFFFF8,
0x00000002, 0x00000003, 0x00000002, 0x00000004, 0xFFFFFFE0, 0x00000002, 0x00000003, 0x00000003, 0x00000004, 0xFFFFFFEC, 0x00000002, 0x0000000B, 0x00000002, 0x00000000, 0x00000004, 0x00000003,
0x00000002, 0x00000003, 0x00000000, 0x00000004, 0xFFFFFFF8, 0x00000002, 0x00000003, 0x00000002, 0x00000004, 0xFFFFFFE0, 0x00000002, 0x00000003, 0x00000003, 0x00000004, 0xFFFFFFE8, 0x00000002,
0x0000000C, 0x00000002, 0x00000000, 0x00000004, 0x00000004, 0x00000003, 0x0000000C, 0x00000129, 0x00000002, 0x00000001, 0x00000005, 0x00000004, 0x00000001, 0x00000000, 0x00000000, 0x00000000]

reg = [0x0] * 11
memory = [0x0] * 144
# m = str(input())
memory[128] = 0x30303030
memory[129] = 0x31313131
memory[130] = 0x31313131
memory[131] = 0x31313131
memory[132] = 0x32323232
memory[133] = 0x32323232
memory[134] = 0x33333333
memory[135] = 0x33333333
reg[4] = 0
reg[5] = 0x100
result = []
# xmm寄存器为reg[7]~reg[10]
# 读取字节码,reg[6]就是索引

# 操作符opc:opc[reg[6]]
# 参数arg:opc[reg[6]+n]
# reg寄存器:reg[opc[reg[6]+n]]
# memory内存:memory[reg[opc[reg[6]+n]]+opc[reg[6]+n]]

while reg[6] < len(opc):
# mov(其实是push)
if opc[reg[6]] == 0:
index = (reg[5]-4)//4
reg[5] -= 4
if opc[reg[6]+1] == 0:
print(f"op {reg[6]}: {hex(opc[reg[6]])}, {hex(opc[reg[6]+1])}, {hex(opc[reg[6]+2])}, asm: mov memory[{index}], reg[{opc[reg[6]+2]}] = {hex(reg[opc[reg[6]+2]])}")
memory[index] = reg[opc[reg[6]+2]]
elif opc[reg[6]+1] == 1:
print(f"op {reg[6]}: {hex(opc[reg[6]])}, {hex(opc[reg[6]+1])}, {hex(opc[reg[6]+2])}, asm: mov memory[{index}], {hex(opc[reg[6]+2])}")
memory[index] = opc[reg[6]+2]
reg[6] += 3
# end
elif opc[reg[6]] == 1:
print(f"op {reg[6]}: {hex(opc[reg[6]])}, asm: end of VM")
for j in range(128, 136):
result.append(memory[j])
reg[6] += 2
break
# mov
elif opc[reg[6]] == 2:
if opc[reg[6]+1] == 0:
print(f"op {reg[6]}: {hex(opc[reg[6]])}, {hex(opc[reg[6]+1])}, {hex(opc[reg[6]+2])}, {hex(opc[reg[6]+3])}, {hex(opc[reg[6]+4])}, asm: mov memory[{((reg[opc[reg[6]+2]]+opc[reg[6]+3])&0xFFFFFFFF)//4}] = {hex(memory[((reg[opc[reg[6]+2]]+opc[reg[6]+3])&0xFFFFFFFF)//4])}, reg[{opc[reg[6]+4]}] = {hex(reg[opc[reg[6]+4]])}")
memory[((reg[opc[reg[6]+2]]+opc[reg[6]+3])&0xFFFFFFFF)//4] = reg[opc[reg[6]+4]]
reg[6] += 5
elif opc[reg[6]+1] == 1:
print(f"op {reg[6]}: {hex(opc[reg[6]])}, {hex(opc[reg[6]+1])}, {hex(opc[reg[6]+2])}, {hex(opc[reg[6]+3])}, asm: mov reg[{opc[reg[6]+2]}] = {hex(reg[opc[reg[6]+2]])}, reg[{opc[reg[6]+3]}] = {hex(reg[opc[reg[6]+3]])}")
reg[opc[reg[6]+2]] = reg[opc[reg[6]+3]]
reg[6] += 4
elif opc[reg[6]+1] == 2:
BYTEPlace = ((reg[opc[reg[6]+2]]+opc[reg[6]+3])&0xFFFFFFFF)%4
print(f"op {reg[6]}: {hex(opc[reg[6]])}, {hex(opc[reg[6]+1])}, {hex(opc[reg[6]+2])}, {hex(opc[reg[6]+3])}, {hex(opc[reg[6]+4])}, asm: mov ({BYTEPlace}#BYTE)memory[{((reg[opc[reg[6]+2]]+opc[reg[6]+3])&0xFFFFFFFF)//4}] = {hex((memory[((reg[opc[reg[6]+2]]+opc[reg[6]+3])&0xFFFFFFFF)//4]&(0xFF<<(BYTEPlace*8)))>>BYTEPlace*8)}, reg[{opc[reg[6]+4]}] = {hex(opc[reg[6]+4])}")
if BYTEPlace == 0: memory[((reg[opc[reg[6]+2]]+opc[reg[6]+3])&0xFFFFFFFF)//4] = (memory[((reg[opc[reg[6]+2]]+opc[reg[6]+3])&0xFFFFFFFF)//4]&0xFFFFFF00)|((opc[reg[6]+4]&0xFF)<<(8*BYTEPlace))
elif BYTEPlace == 1: memory[((reg[opc[reg[6]+2]]+opc[reg[6]+3])&0xFFFFFFFF)//4] = (memory[((reg[opc[reg[6]+2]]+opc[reg[6]+3])&0xFFFFFFFF)//4]&0xFFFF00FF)|((opc[reg[6]+4]&0xFF)<<(8*BYTEPlace))
elif BYTEPlace == 2: memory[((reg[opc[reg[6]+2]]+opc[reg[6]+3])&0xFFFFFFFF)//4] = (memory[((reg[opc[reg[6]+2]]+opc[reg[6]+3])&0xFFFFFFFF)//4]&0xFF00FFFF)|((opc[reg[6]+4]&0xFF)<<(8*BYTEPlace))
elif BYTEPlace == 3: memory[((reg[opc[reg[6]+2]]+opc[reg[6]+3])&0xFFFFFFFF)//4] = (memory[((reg[opc[reg[6]+2]]+opc[reg[6]+3])&0xFFFFFFFF)//4]&0x00FFFFFF)|((opc[reg[6]+4]&0xFF)<<(8*BYTEPlace))
reg[6] += 5
elif opc[reg[6]+1] == 3:
print(f"op {reg[6]}: {hex(opc[reg[6]])}, {hex(opc[reg[6]+1])}, {hex(opc[reg[6]+2])}, {hex(opc[reg[6]+3])}, {hex(opc[reg[6]+4])}, asm: mov reg[{opc[reg[6]+2]}] = {hex(reg[opc[reg[6]+2]])}, memory[{((reg[opc[reg[6]+3]]+opc[reg[6]+4])&0xFFFFFFFF)//4}] = {hex(memory[((reg[opc[reg[6]+3]]+opc[reg[6]+4])&0xFFFFFFFF)//4])}")
reg[opc[reg[6]+2]] = memory[((reg[opc[reg[6]+3]]+opc[reg[6]+4])&0xFFFFFFFF)//4]
reg[6] += 5
elif opc[reg[6]+1] == 4:
print(f"op {reg[6]}: {hex(opc[reg[6]])}, {hex(opc[reg[6]+1])}, {hex(opc[reg[6]+2])}, {hex(opc[reg[6]+3])}, asm: mov reg[{opc[reg[6]+2]}] = {hex(reg[opc[reg[6]+2]])}, {hex(opc[reg[6]+3])}")
reg[opc[reg[6]+2]] = opc[reg[6]+3]
reg[6] += 4
elif opc[reg[6]+1] == 5:
BYTEPlace = ((reg[opc[reg[6]+2]]+opc[reg[6]+3])&0xFFFFFFFF)%4
print(f"op {reg[6]}: {hex(opc[reg[6]])}, {hex(opc[reg[6]+1])}, {hex(opc[reg[6]+2])}, {hex(opc[reg[6]+3])}, {hex(opc[reg[6]+4])}, asm: mov ({BYTEPlace}#BYTE)memory[{((reg[opc[reg[6]+2]]+opc[reg[6]+3])&0xFFFFFFFF)//4}] = {hex((memory[((reg[opc[reg[6]+2]]+opc[reg[6]+3])&0xFFFFFFFF)//4]&(0xFF<<(BYTEPlace*8)))>>BYTEPlace*8)}, (BYTE)reg[{opc[reg[6]+4]}] = {hex(reg[opc[reg[6]+4]]&0xFF)}")
if BYTEPlace == 0: memory[((reg[opc[reg[6]+2]]+opc[reg[6]+3])&0xFFFFFFFF)//4] = ((memory[((reg[opc[reg[6]+2]]+opc[reg[6]+3])&0xFFFFFFFF)//4])&0xFFFFFF00)+((reg[opc[reg[6]+4]]*0x00000001)&0x000000FF)
elif BYTEPlace == 1: memory[((reg[opc[reg[6]+2]]+opc[reg[6]+3])&0xFFFFFFFF)//4] = ((memory[((reg[opc[reg[6]+2]]+opc[reg[6]+3])&0xFFFFFFFF)//4])&0xFFFF00FF)+((reg[opc[reg[6]+4]]*0x00000100)&0x0000FF00)
elif BYTEPlace == 2: memory[((reg[opc[reg[6]+2]]+opc[reg[6]+3])&0xFFFFFFFF)//4] = ((memory[((reg[opc[reg[6]+2]]+opc[reg[6]+3])&0xFFFFFFFF)//4])&0xFF00FFFF)+((reg[opc[reg[6]+4]]*0x00010000)&0x00FF0000)
elif BYTEPlace == 3: memory[((reg[opc[reg[6]+2]]+opc[reg[6]+3])&0xFFFFFFFF)//4] = ((memory[((reg[opc[reg[6]+2]]+opc[reg[6]+3])&0xFFFFFFFF)//4])&0x00FFFFFF)+((reg[opc[reg[6]+4]]*0x01000000)&0xFF000000)
reg[6] += 5
elif opc[reg[6]+1] == 6:
print(f"op {reg[6]}: {hex(opc[reg[6]])}, {hex(opc[reg[6]+1])}, {hex(opc[reg[6]+2])}, {hex(opc[reg[6]+3])}, {hex(opc[reg[6]+4])}, asm: mov (LOBYTE)reg[{opc[reg[6]+2]}] = {hex(reg[opc[reg[6]+2]]&0xFF)}, ({((reg[opc[reg[6]+3]]+opc[reg[6]+4])&0xFFFFFFFF)%4}#BYTE)memory[{((reg[opc[reg[6]+3]]+opc[reg[6]+4])&0xFFFFFFFF)//4}] = {hex(((memory[((reg[opc[reg[6]+3]]+opc[reg[6]+4])&0xFFFFFFFF)//4]>>((((reg[opc[reg[6]+3]]+opc[reg[6]+4])&0xFFFFFFFF)%4)*8))&0xFF))}")
reg[opc[reg[6]+2]] = (reg[opc[reg[6]+2]]&0xFFFFFF00)+((memory[((reg[opc[reg[6]+3]]+opc[reg[6]+4])&0xFFFFFFFF)//4]>>((((reg[opc[reg[6]+3]]+opc[reg[6]+4])&0xFFFFFFFF)%4)*8))&0xFF)
reg[6] += 5
elif opc[reg[6]+1] == 7:
print(f"op {reg[6]}: {hex(opc[reg[6]])}, {hex(opc[reg[6]+1])}, {hex(opc[reg[6]+2])}, {hex(opc[reg[6]+3])}, {hex(opc[reg[6]+4])}, asm: mov memory[{((reg[opc[reg[6]+2]]+opc[reg[6]+3])&0xFFFFFFFF)//4}] = {hex(memory[((reg[opc[reg[6]+2]]+opc[reg[6]+3])&0xFFFFFFFF)//4])}, {hex(opc[reg[6]+4])}")
memory[((reg[opc[reg[6]+2]]+opc[reg[6]+3])&0xFFFFFFFF)//4] = opc[reg[6]+4]
reg[6] += 5
elif opc[reg[6]+1] == 8:
print(f"op {reg[6]}: {hex(opc[reg[6]])}, {hex(opc[reg[6]+1])}, {hex(opc[reg[6]+2])}, {hex(opc[reg[6]+3])}, {hex(opc[reg[6]+4])}, asm: mov reg[{opc[reg[6]+2]}] = {hex(reg[opc[reg[6]+2]])}, memory[{((reg[opc[reg[6]+3]]+reg[opc[reg[6]+4]])&0xFFFFFFFF)//4}] = {hex(memory[((reg[opc[reg[6]+3]]+reg[opc[reg[6]+4]])&0xFFFFFFFF)//4])}")
reg[opc[reg[6]+2]] = memory[((reg[opc[reg[6]+3]]+reg[opc[reg[6]+4]])&0xFFFFFFFF)//4]
reg[6] += 5
elif opc[reg[6]+1] == 9:
print(f"op {reg[6]}: {hex(opc[reg[6]])}, {hex(opc[reg[6]+1])}, {hex(opc[reg[6]+2])}, {hex(opc[reg[6]+3])}, {hex(opc[reg[6]+4])}, {hex(opc[reg[6]+5])}, asm: mov reg[{opc[reg[6]+2]}] = {hex(reg[opc[reg[6]+2]])}, memory[{((reg[opc[reg[6]+3]]+reg[opc[reg[6]+4]]*opc[reg[6]+5])&0xFFFFFFFF)//4}] = {hex(memory[((reg[opc[reg[6]+3]]+reg[opc[reg[6]+4]]*opc[reg[6]+5])&0xFFFFFFFF)//4])}")
reg[opc[reg[6]+2]] = memory[((reg[opc[reg[6]+3]]+reg[opc[reg[6]+4]]*opc[reg[6]+5])&0xFFFFFFFF)//4]
reg[6] += 6
elif opc[reg[6]+1] == 10:
print(f"op {reg[6]}: {hex(opc[reg[6]])}, {hex(opc[reg[6]+1])}, {hex(opc[reg[6]+2])}, {hex(opc[reg[6]+3])}, {hex(opc[reg[6]+4])}, {hex(opc[reg[6]+5])}, {hex(opc[reg[6]+6])}, asm: mov reg[{opc[reg[6]+2]}] = {hex(reg[opc[reg[6]+2]])}, memory[{((reg[opc[reg[6]+3]]+reg[opc[reg[6]+4]]*opc[reg[6]+5]+opc[reg[6]+6])&0xFFFFFFFF)//4}] = {hex(memory[((reg[opc[reg[6]+3]]+reg[opc[reg[6]+4]]*opc[reg[6]+5]+opc[reg[6]+6])&0xFFFFFFFF)//4])}")
reg[opc[reg[6]+2]] = memory[((reg[opc[reg[6]+3]]+reg[opc[reg[6]+4]]*opc[reg[6]+5]+opc[reg[6]+6])&0xFFFFFFFF)//4]
reg[6] += 7
elif opc[reg[6]+1] == 11:
print(f"op {reg[6]}: {hex(opc[reg[6]])}, {hex(opc[reg[6]+1])}, {hex(opc[reg[6]+2])}, {hex(opc[reg[6]+3])}, {hex(opc[reg[6]+4])}, {hex(opc[reg[6]+5])}, asm: mov memory[{((reg[opc[reg[6]+2]]+reg[opc[reg[6]+3]*opc[reg[6]+4]])&0xFFFFFFFF)//4}] = {hex(memory[((reg[opc[reg[6]+2]]+reg[opc[reg[6]+3]*opc[reg[6]+4]])&0xFFFFFFFF)//4])}, reg[{opc[reg[6]+5]}] = {hex(reg[opc[reg[6]+5]])}")
memory[((reg[opc[reg[6]+2]]+reg[opc[reg[6]+3]]*opc[reg[6]+4])&0xFFFFFFFF)//4] = reg[opc[reg[6]+5]]
reg[6] += 6
elif opc[reg[6]+1] == 12:
print(f"op {reg[6]}: {hex(opc[reg[6]])}, {hex(opc[reg[6]+1])}, {hex(opc[reg[6]+2])}, {hex(opc[reg[6]+3])}, {hex(opc[reg[6]+4])}, {hex(opc[reg[6]+5])}, {hex(opc[reg[6]+6])}, asm: mov memory[{((reg[opc[reg[6]+2]]+reg[opc[reg[6]+3]]*opc[reg[6]+4]+opc[reg[6]+5])&0xFFFFFFFF)//4}] = {hex(memory[((reg[opc[reg[6]+2]]+reg[opc[reg[6]+3]]*opc[reg[6]+4]+opc[reg[6]+5])&0xFFFFFFFF)//4])}, reg[{opc[reg[6]+6]}] = {hex(reg[opc[reg[6]+6]])}")
memory[((reg[opc[reg[6]+2]]+reg[opc[reg[6]+3]]*opc[reg[6]+4]+opc[reg[6]+5])&0xFFFFFFFF)//4] = reg[opc[reg[6]+6]]
reg[6] += 7
# sub
elif opc[reg[6]] == 3:
if opc[reg[6]+1] == 3:
print(f"op {reg[6]}: {hex(opc[reg[6]])}, {hex(opc[reg[6]+1])}, {hex(opc[reg[6]+2])}, {hex(opc[reg[6]+3])}, {hex(opc[reg[6]+4])}, asm: sub reg[{opc[reg[6]+2]}] = {hex(reg[opc[reg[6]+2]])}, memory[{((reg[opc[reg[6]+3]]+opc[reg[6]+4])&0xFFFFFFFF)//4}] = {hex(memory[((reg[opc[reg[6]+3]]+opc[reg[6]+4])&0xFFFFFFFF)//4])}")
reg[opc[reg[6]+2]] = (reg[opc[reg[6]+2]]-memory[(
(reg[opc[reg[6]+3]]+opc[reg[6]+4]) & 0xFFFFFFFF)//4]) & 0xFFFFFFFF
reg[6] += 5
elif opc[reg[6]+1] == 4:
print(f"op {reg[6]}: {hex(opc[reg[6]])}, {hex(opc[reg[6]+1])}, {hex(opc[reg[6]+2])}, {hex(opc[reg[6]+3])}, asm: sub reg[{opc[reg[6]+2]}] = {hex(reg[opc[reg[6]+2]])}, {hex(opc[reg[6]+3])}")
reg[opc[reg[6]+2]] -= opc[reg[6]+3]
reg[6] += 4
# add
elif opc[reg[6]] == 4:
if opc[reg[6]+1] == 1:
print(f"op {reg[6]}: {hex(opc[reg[6]])}, {hex(opc[reg[6]+1])}, {hex(opc[reg[6]+2])}, {hex(opc[reg[6]+3])}, asm: add reg[{opc[reg[6]+2]}] = {hex(reg[opc[reg[6]+2]])}, {hex(reg[opc[reg[6]+3]])}")
reg[opc[reg[6]+2]] = (reg[opc[reg[6]+2]]+reg[opc[reg[6]+3]])&0xFFFFFFFF
reg[6] += 4
elif opc[reg[6]+1] == 2:
print(f"op {reg[6]}: {hex(opc[reg[6]])}, {hex(opc[reg[6]+1])}, {hex(opc[reg[6]+2])}, {hex(opc[reg[6]+3])}, {hex(opc[reg[6]+4])}, asm: add memory[{((reg[opc[reg[6]+2]]+opc[reg[6]+3])&0xFFFFFFFF)//4}] = {hex(memory[((reg[opc[reg[6]+2]]+opc[reg[6]+3])&0xFFFFFFFF)//4])}, {hex(opc[reg[6]+4])}")
memory[((reg[opc[reg[6]+2]]+opc[reg[6]+3])&0xFFFFFFFF)//4] = (memory[((reg[opc[reg[6]+2]]+opc[reg[6]+3])&0xFFFFFFFF)//4]+opc[reg[6]+4])&0xFFFFFFFF
reg[6] += 5
elif opc[reg[6]+1] == 3:
print(f"op {reg[6]}: {hex(opc[reg[6]])}, {hex(opc[reg[6]+1])}, {hex(opc[reg[6]+2])}, {hex(opc[reg[6]+3])}, {hex(opc[reg[6]+4])}, asm: add reg[{opc[reg[6]+2]}] = {hex(reg[opc[reg[6]+2]])}, memory[{((reg[opc[reg[6]+3]]+opc[reg[6]+4])&0xFFFFFFFF)//4}] = {hex(memory[((reg[opc[reg[6]+3]]+opc[reg[6]+4])&0xFFFFFFFF)//4])}")
reg[opc[reg[6]+2]] = (reg[opc[reg[6]+2]]+memory[((reg[opc[reg[6]+3]]+opc[reg[6]+4])&0xFFFFFFFF)//4])&0xFFFFFFFF
reg[6] += 5
elif opc[reg[6]+1] == 4:
print(f"op {reg[6]}: {hex(opc[reg[6]])}, {hex(opc[reg[6]+1])}, {hex(opc[reg[6]+2])}, {hex(opc[reg[6]+3])}, asm: add reg[{opc[reg[6]+2]}] = {hex(reg[opc[reg[6]+2]])}, {hex(opc[reg[6]+3])}")
reg[opc[reg[6]+2]] = (reg[opc[reg[6]+2]]+opc[reg[6]+3])&0xFFFFFFFF
reg[6] += 4
# xor
elif opc[reg[6]] == 5:
if opc[reg[6]+1] == 1:
print(f"op {reg[6]}: {hex(opc[reg[6]])}, {hex(opc[reg[6]+1])}, {hex(opc[reg[6]+2])}, {hex(opc[reg[6]+3])}, asm: xor reg[{opc[reg[6]+2]}] = {hex(reg[opc[reg[6]+2]])}, reg[{opc[reg[6]+3]}] = {hex(reg[opc[reg[6]+3]])}")
reg[opc[reg[6]+2]] = reg[opc[reg[6]+2]] ^ reg[opc[reg[6]+3]]
reg[6] += 4
elif opc[reg[6]+1] == 2:
print(f"op {reg[6]}: {hex(opc[reg[6]])}, {hex(opc[reg[6]+1])}, {hex(opc[reg[6]+2])}, {hex(opc[reg[6]+3])}, {hex(opc[reg[6]+4])}, asm: xor memory[reg[arg2]+arg3], arg4")
reg[6] += 5
elif opc[reg[6]+1] == 3:
print(f"op {reg[6]}: {hex(opc[reg[6]])}, {hex(opc[reg[6]+1])}, {hex(opc[reg[6]+2])}, {hex(opc[reg[6]+3])}, {hex(opc[reg[6]+4])}, asm: xor arg2, memory[reg[arg3]+arg4]")
reg[6] += 5
elif opc[reg[6]+1] == 4:
print(f"op {reg[6]}: {hex(opc[reg[6]])}, {hex(opc[reg[6]+1])}, {hex(opc[reg[6]+2])}, {hex(opc[reg[6]+3])}, asm: xor reg[{opc[reg[6]+2]}] = {hex(reg[opc[reg[6]+2]])}, {hex(opc[reg[6]+3])}")
reg[opc[reg[6]+2]] = reg[opc[reg[6]+2]] ^ opc[reg[6]+3]
reg[6] += 4
# add
elif opc[reg[6]] == 6:
assert opc[reg[6]+1] == 3
print(f"op {reg[6]}: {hex(opc[reg[6]])}, {hex(opc[reg[6]+1])}, {hex(opc[reg[6]+2])}, {hex(opc[reg[6]+3])}, {hex(opc[reg[6]+4])}, asm: add reg[{opc[reg[6]+2]}] = {hex(reg[opc[reg[6]+2]])}, reg[{opc[reg[6]+3]}] = {hex(reg[opc[reg[6]+3]])}, {hex(opc[reg[6]+4])}")
reg[opc[reg[6]+2]] = (reg[opc[reg[6]+3]]+opc[reg[6]+4])&0xFFFFFFFF
reg[6] += 5
# shr
elif opc[reg[6]] == 7:
if opc[reg[6]+1] == 3:
print(f"op {reg[6]}: {hex(opc[reg[6]])}, {hex(opc[reg[6]+1])}, {hex(opc[reg[6]+2])}, {hex(opc[reg[6]+3])}, {hex(opc[reg[6]+4])}, asm: shr reg[{opc[reg[6]+2]}] = {hex(reg[opc[reg[6]+2]])}, memory[{((reg[opc[reg[6]+3]]+opc[reg[6]+4])&0xFFFFFFFF)//4}] = {hex(memory[((reg[opc[reg[6]+3]]+opc[reg[6]+4])&0xFFFFFFFF)//4])}")
reg[opc[reg[6]+2]] = reg[opc[reg[6]+2]] >> memory[((reg[opc[reg[6]+3]]+opc[reg[6]+4])&0xFFFFFFFF)//4]
reg[6] += 5
elif opc[reg[6]+1] == 4:
print(f"op {reg[6]}: {hex(opc[reg[6]])}, {hex(opc[reg[6]+1])}, {hex(opc[reg[6]+2])}, {hex(opc[reg[6]+3])}, asm: shr reg[{opc[reg[6]+2]}] = {hex(reg[opc[reg[6]+2]])}, {hex(opc[reg[6]+3])}")
reg[opc[reg[6]+2]] = reg[opc[reg[6]+2]] >> opc[reg[6]+3]
reg[6] += 4
# shl
elif opc[reg[6]] == 8:
if opc[reg[6]+1] == 3:
print(f"op {reg[6]}: {hex(opc[reg[6]])}, {hex(opc[reg[6]+1])}, {hex(opc[reg[6]+2])}, {hex(opc[reg[6]+3])}, {hex(opc[reg[6]+4])}, asm: shl reg[{opc[reg[6]+2]}] = {hex(reg[opc[reg[6]+2]])}, memory[{((reg[opc[reg[6]+3]]+opc[reg[6]+4])&0xFFFFFFFF)//4}] = {hex(memory[((reg[opc[reg[6]+3]]+opc[reg[6]+4])&0xFFFFFFFF)//4])}")
reg[opc[reg[6]+2]] = (reg[opc[reg[6]+2]] << memory[((reg[opc[reg[6]+3]]+opc[reg[6]+4])&0xFFFFFFFF)//4])&0xFFFFFFFF
reg[6] += 5
elif opc[reg[6]+1] == 4:
print(f"op {reg[6]}: {hex(opc[reg[6]])}, {hex(opc[reg[6]+1])}, {hex(opc[reg[6]+2])}, {hex(opc[reg[6]+3])}, asm: shl reg[{opc[reg[6]+2]}] = {hex(reg[opc[reg[6]+2]])}, {hex(opc[reg[6]+3])}")
reg[opc[reg[6]+2]] = (reg[opc[reg[6]+2]] << opc[reg[6]+3])&0xFFFFFFFF
reg[6] += 4
# cmp
elif opc[reg[6]] == 9:
BYTEPlace = ((reg[opc[reg[6]+2]]+opc[reg[6]+3])&0xFFFFFFFF)%4
print(f"op {reg[6]}: {hex(opc[reg[6]])}, {hex(opc[reg[6]+1])}, {hex(opc[reg[6]+2])}, {hex(opc[reg[6]+3])}, {hex(opc[reg[6]+4])}, asm: cmp (#{BYTEPlace}BYTE)memory[{((reg[opc[reg[6]+2]]+opc[reg[6]+3])&0xFFFFFFFF)//4}] = {hex((memory[((reg[opc[reg[6]+2]]+opc[reg[6]+3])&0xFFFFFFFF)//4]&int('0xFF'+'00'*BYTEPlace,16))>>BYTEPlace*8)}, {hex(opc[reg[6]+4])}")
if (memory[((reg[opc[reg[6]+2]]+opc[reg[6]+3])&0xFFFFFFFF)//4]&(0xFF<<(BYTEPlace*8)))>>BYTEPlace*8 == opc[reg[6]+4]:
reg[7] = 1
reg[8] = reg[9] = reg[10] = 0
elif (memory[((reg[opc[reg[6]+2]]+opc[reg[6]+3])&0xFFFFFFFF)//4]&(0xFF<<(BYTEPlace*8)))>>BYTEPlace*8 > opc[reg[6]+4]:
reg[7] = reg[8] = reg[9] = reg[10] = 0
elif (memory[((reg[opc[reg[6]+2]]+opc[reg[6]+3])&0xFFFFFFFF)//4]&(0xFF<<(BYTEPlace*8)))>>BYTEPlace*8 < opc[reg[6]+4]:
reg[7] = reg[10] = 0
reg[8] = reg[9] = 1
reg[6] += 5
# jz(xmm[0])
elif opc[reg[6]] == 10:
print(f"op {reg[6]}: {hex(opc[reg[6]])}, {hex(opc[reg[6]+1])}, asm: jz(xmm[0]) {hex(opc[reg[6]+1])}",end=" ")
if reg[7] == 0:
print("jumped here")
reg[6] = opc[reg[6]+1]
elif reg[7] == 1:
print("unjump here")
reg[6] += 2
# jmp
elif opc[reg[6]] == 12:
print(f"op {reg[6]}: {hex(opc[reg[6]])}, {hex(opc[reg[6]+1])}, asm: jmp {hex(opc[reg[6]+1])}")
reg[6] = opc[reg[6]+1]
# and
elif opc[reg[6]] == 13:
if opc[reg[6]+1] == 3:
print(f"op {reg[6]}: {hex(opc[reg[6]])}, {hex(opc[reg[6]+1])}, {hex(opc[reg[6]+2])}, {hex(opc[reg[6]+3])}, {hex(opc[reg[6]+4])}, asm: and reg[{opc[reg[6]+2]}] = {hex(reg[opc[reg[6]+2]])}, memory[{((reg[opc[reg[6]+3]]+opc[reg[6]+4])&0xFFFFFFFF)//4}] = {hex(memory[((reg[opc[reg[6]+3]]+opc[reg[6]+4])&0xFFFFFFFF)//4])}")
reg[opc[reg[6]+2]] = reg[opc[reg[6]+2]] & memory[((reg[opc[reg[6]+3]]+opc[reg[6]+4])&0xFFFFFFFF)//4]
reg[6] += 5
elif opc[reg[6]+1] == 4:
print(f"op {reg[6]}: {hex(opc[reg[6]])}, {hex(opc[reg[6]+1])}, {hex(opc[reg[6]+2])}, {hex(opc[reg[6]+3])}, asm: and reg[{opc[reg[6]+2]}] = {hex(reg[opc[reg[6]+2]])}, {hex(opc[reg[6]+3])}")
reg[opc[reg[6]+2]] = reg[opc[reg[6]+2]] & opc[reg[6]+3]
reg[6] += 4
# jnz(xmm[0])
elif opc[reg[6]] == 15:
print(f"op {reg[6]}: {hex(opc[reg[6]])}, {hex(opc[reg[6]+1])}, asm: jnz {hex(opc[reg[6]+1])}",end=" ")
if reg[7] == 1:
print("jumped here")
reg[6] = opc[reg[6]+1]
elif reg[7] == 0:
print("unjump here")
reg[6] += 2
# nop
elif opc[reg[6]] == 16:
print("op {reg[6]}: {hex(opc[reg[6]])}, asm: nop")
reg[6] += 1
# wrong_length
elif opc[reg[6]] == 17:
print("Length Wrong!")
exit(0)
# mul
elif opc[reg[6]] == 18:
assert opc[reg[6]+1] == 4
print(f"op {reg[6]}: {hex(opc[reg[6]])}, {hex(opc[reg[6]+1])}, {hex(opc[reg[6]+2])}, {hex(opc[reg[6]+3])}, asm: mul reg[{opc[reg[6]+2]}] = {hex(reg[opc[reg[6]+2]])}, reg[{opc[reg[6]+3]}] = {hex(reg[opc[reg[6]+3]])}, {hex(opc[reg[6]+4])}")
reg[opc[reg[6]+2]] = (reg[opc[reg[6]+3]]*opc[reg[6]+4])&0xFFFFFFFF
reg[6] += 5
# je(xmm[1],xmm[3])
elif opc[reg[6]] == 19:
print(f"op {reg[6]}: {hex(opc[reg[6]])}, {hex(opc[reg[6]+1])}, asm: je(xmm[1],xmm[3]) {hex(opc[reg[6]+1])}",end=" ")
if reg[8] == reg[10]:
print("jumped here")
reg[6] = opc[reg[6]+1]
else:
print("unjump here")
reg[6] += 2
# jz(xmm[2])
elif opc[reg[6]] == 20:
print(f"op {reg[6]}: {hex(opc[reg[6]])}, {hex(opc[reg[6]+1])}, asm: jz(xmm[2]) {hex(opc[reg[6]+1])}",end=" ")
if reg[9] == 0:
print("jumped here")
reg[6] = opc[reg[6]+1]
elif reg[9] == 1:
print("unjump here")
reg[6] += 2
else:
print("opcode unknown: ", opc[reg[6]])
break
# time.sleep(0.001)
print("memory:")
for i in range(len(memory)):
print(f'{memory[i]:#10x}', end=' ')
if (i%16 == 15):
print()
print("reg:")
for i in range(len(reg)):
print(f'{reg[i]:#10x}', end=" ")
print()
# time.sleep(0.001)
print("result:")
for i in range(len(result)):
print(f'{result[i]:#10x}', end=" ")
print()

def bytes_to_dwords_little_endian(byte_array):
return [int.from_bytes(byte_array[i:i+4], byteorder='little', signed=False) for i in range(0, len(byte_array), 4)]

def dwords_to_bytes_little_endian(dword_array):
byte_list = []
for dword in dword_array:
byte_list.extend(dword.to_bytes(4, byteorder='little'))
return byte_list

m1 = 0x30303030
m2 = 0x31313131
delta = 0xA0A01919
key = [0x776F6853, 0x656B616D, 0x616D5F72, 0x74696564]
ttl = 0
for i in range(0x48):
m1 = (m1 + ((((m2 >> 5) ^ (m2 << 6)) + (m2 ^ 0x11223344)) ^ ((key[ttl & 3] + ttl) ^ 0xABAB1212))) & 0xFFFFFFFF
ttl = (ttl - delta) & 0xFFFFFFFF
m2 = (m2 + ((((m1 >> 4) ^ (m1 << 7)) + (m1 ^ 0x55667788)) ^ ((key[(ttl >> 11) & 3] + ttl) ^ 0x23235566))) & 0xFFFFFFFF
print(hex(m1), hex(m2))
time.sleep(1)
encflag = [0x9a,0x2e,0x6c,0x69,0xe1,0xe8,0xad,0x76,0xa4,0x5c,0x7d,0xe6,0x38,0xbd,0x76,0x5c,
0x87,0x07,0xac,0xb7,0x65,0x0c,0xea,0xbf,0x10,0xff,0xc2,0x01,0x38,0xfd,0x16,0x6d]
dwordenc = bytes_to_dwords_little_endian(encflag)
result = []
for j in range(0,len(dwordenc)//2):
m1 = dwordenc[2*j]
m2 = dwordenc[2*j+1]
ttl = (0 - 0x48 * delta) & 0xFFFFFFFF
for j in range(0x48):
m2 = (m2 - ((((m1 >> 4) ^ (m1 << 7)) + (m1 ^ 0x55667788)) ^ ((key[(ttl >> 11) & 3] + ttl) ^ 0x23235566))) & 0xFFFFFFFF
ttl = (ttl + delta) & 0xFFFFFFFF
m1 = (m1 - ((((m2 >> 5) ^ (m2 << 6)) + (m2 ^ 0x11223344)) ^ ((key[ttl & 3] + ttl) ^ 0xABAB1212))) & 0xFFFFFFFF
result.append(m1)
result.append(m2)
flag = dwords_to_bytes_little_endian(result)
time.sleep(1)
strflag = ''.join([chr(i) for i in flag])
print(strflag)

得到flag:XYCTF{fun_un1c0rn_with_4rm64_VM}.

注:这题因为我做过NPC²CTF的原题所以出得快一些,如果没见过原题,通过f12搜索字符串可以注意到有qemu字样,可以注意到VM字节码上面那部分还有一块字节码,合理猜测那是arm64的字节码,用arm64解析源程序后就可以得到那个vm函数,后续同NPC²CTF.

Dragon:

.bc文件是llvm中间文件,用llvm-dis反编译为.ll代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
; ModuleID = 'Dragon.bc'
source_filename = "1.cpp"
target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
target triple = "x86_64-pc-windows-msvc19.39.33522"

$printf = comdat any

$scanf = comdat any

$_vfprintf_l = comdat any

$__local_stdio_printf_options = comdat any

$_vfscanf_l = comdat any

$__local_stdio_scanf_options = comdat any

$"??_C@_0O@FIGNKBOM@Input?5U?5flag?3?$AA@" = comdat any

$"??_C@_02DKCKIIND@?$CFs?$AA@" = comdat any

$"??_C@_06JPHCLLC@Error?$CB?$AA@" = comdat any

$"??_C@_07PBILKAFL@Success?$AA@" = comdat any

$"?_OptionsStorage@?1??__local_stdio_printf_options@@9@4_KA" = comdat any

$"?_OptionsStorage@?1??__local_stdio_scanf_options@@9@4_KA" = comdat any

@__const.main.enc = private unnamed_addr constant [12 x i64] [i64 -2565957437423125689, i64 224890624719110086, i64 1357324823849588894, i64 -8941695979231947288, i64 -253413330424273460, i64 -7817463785137710741, i64 -5620500441869335673, i64 984060876288820705, i64 -6993555743080142153, i64 -7892488171899690683, i64 7190415315123037707, i64 -7218240302740981077], align 16
@"??_C@_0O@FIGNKBOM@Input?5U?5flag?3?$AA@" = linkonce_odr dso_local unnamed_addr constant [14 x i8] c"Input U flag:\00", comdat, align 1
@"??_C@_02DKCKIIND@?$CFs?$AA@" = linkonce_odr dso_local unnamed_addr constant [3 x i8] c"%s\00", comdat, align 1
@"??_C@_06JPHCLLC@Error?$CB?$AA@" = linkonce_odr dso_local unnamed_addr constant [7 x i8] c"Error!\00", comdat, align 1
@"??_C@_07PBILKAFL@Success?$AA@" = linkonce_odr dso_local unnamed_addr constant [8 x i8] c"Success\00", comdat, align 1
@"?_OptionsStorage@?1??__local_stdio_printf_options@@9@4_KA" = linkonce_odr dso_local global i64 0, comdat, align 8
@"?_OptionsStorage@?1??__local_stdio_scanf_options@@9@4_KA" = linkonce_odr dso_local global i64 0, comdat, align 8

; Function Attrs: mustprogress noinline nounwind optnone uwtable
define dso_local noundef i64 @"?calculate_crc64_direct@@YA_KPEBE_K@Z"(ptr noundef %data, i64 noundef %length) #0 {
entry:
%length.addr = alloca i64, align 8
%data.addr = alloca ptr, align 8
%crc = alloca i64, align 8
%i = alloca i64, align 8
%j = alloca i64, align 8
store i64 %length, ptr %length.addr, align 8
store ptr %data, ptr %data.addr, align 8
store i64 -1, ptr %crc, align 8
store i64 0, ptr %i, align 8
br label %for.cond

for.cond: ; preds = %for.inc7, %entry
%0 = load i64, ptr %i, align 8
%1 = load i64, ptr %length.addr, align 8
%cmp = icmp ult i64 %0, %1
br i1 %cmp, label %for.body, label %for.end9

for.body: ; preds = %for.cond
%2 = load ptr, ptr %data.addr, align 8
%3 = load i64, ptr %i, align 8
%arrayidx = getelementptr inbounds i8, ptr %2, i64 %3
%4 = load i8, ptr %arrayidx, align 1
%conv = zext i8 %4 to i64
%shl = shl i64 %conv, 56
%5 = load i64, ptr %crc, align 8
%xor = xor i64 %5, %shl
store i64 %xor, ptr %crc, align 8
store i64 0, ptr %j, align 8
br label %for.cond1

for.cond1: ; preds = %for.inc, %for.body
%6 = load i64, ptr %j, align 8
%cmp2 = icmp ult i64 %6, 8
br i1 %cmp2, label %for.body3, label %for.end

for.body3: ; preds = %for.cond1
%7 = load i64, ptr %crc, align 8
%and = and i64 %7, -9223372036854775808
%tobool = icmp ne i64 %and, 0
br i1 %tobool, label %if.then, label %if.else

if.then: ; preds = %for.body3
%8 = load i64, ptr %crc, align 8
%shl4 = shl i64 %8, 1
%xor5 = xor i64 %shl4, 4823603603198064275
store i64 %xor5, ptr %crc, align 8
br label %if.end

if.else: ; preds = %for.body3
%9 = load i64, ptr %crc, align 8
%shl6 = shl i64 %9, 1
store i64 %shl6, ptr %crc, align 8
br label %if.end

if.end: ; preds = %if.else, %if.then
br label %for.inc

for.inc: ; preds = %if.end
%10 = load i64, ptr %j, align 8
%inc = add i64 %10, 1
store i64 %inc, ptr %j, align 8
br label %for.cond1, !llvm.loop !12

for.end: ; preds = %for.cond1
br label %for.inc7

for.inc7: ; preds = %for.end
%11 = load i64, ptr %i, align 8
%inc8 = add i64 %11, 1
store i64 %inc8, ptr %i, align 8
br label %for.cond, !llvm.loop !14

for.end9: ; preds = %for.cond
%12 = load i64, ptr %crc, align 8
%xor10 = xor i64 %12, -1
ret i64 %xor10
}

; Function Attrs: mustprogress noinline norecurse optnone uwtable
define dso_local noundef i32 @main() #1 {
entry:
%retval = alloca i32, align 4
%enc = alloca [12 x i64], align 16
%data = alloca [66 x i8], align 16
%i = alloca i64, align 8
%j = alloca i64, align 8
%crc = alloca i64, align 8
store i32 0, ptr %retval, align 4
call void @llvm.memcpy.p0.p0.i64(ptr align 16 %enc, ptr align 16 @__const.main.enc, i64 96, i1 false)
call void @llvm.memset.p0.i64(ptr align 16 %data, i8 0, i64 66, i1 false)
%call = call i32 (ptr, ...) @printf(ptr noundef @"??_C@_0O@FIGNKBOM@Input?5U?5flag?3?$AA@")
%arraydecay = getelementptr inbounds [66 x i8], ptr %data, i64 0, i64 0
%call1 = call i32 (ptr, ...) @scanf(ptr noundef @"??_C@_02DKCKIIND@?$CFs?$AA@", ptr noundef %arraydecay)
store i64 0, ptr %i, align 8
store i64 0, ptr %j, align 8
br label %for.cond

for.cond: ; preds = %for.inc, %entry
%0 = load i64, ptr %i, align 8
%arraydecay2 = getelementptr inbounds [66 x i8], ptr %data, i64 0, i64 0
%call3 = call i64 @strlen(ptr noundef %arraydecay2)
%div = udiv i64 %call3, 2
%cmp = icmp ult i64 %0, %div
br i1 %cmp, label %for.body, label %for.end

for.body: ; preds = %for.cond
%1 = load i64, ptr %i, align 8
%arrayidx = getelementptr inbounds [66 x i8], ptr %data, i64 0, i64 %1
%call4 = call noundef i64 @"?calculate_crc64_direct@@YA_KPEBE_K@Z"(ptr noundef %arrayidx, i64 noundef 2)
store i64 %call4, ptr %crc, align 8
%2 = load i64, ptr %crc, align 8
%3 = load i64, ptr %j, align 8
%arrayidx5 = getelementptr inbounds [12 x i64], ptr %enc, i64 0, i64 %3
%4 = load i64, ptr %arrayidx5, align 8
%cmp6 = icmp ne i64 %2, %4
br i1 %cmp6, label %if.then, label %if.end

if.then: ; preds = %for.body
%call7 = call i32 (ptr, ...) @printf(ptr noundef @"??_C@_06JPHCLLC@Error?$CB?$AA@")
store i32 0, ptr %retval, align 4
br label %return

if.end: ; preds = %for.body
br label %for.inc

for.inc: ; preds = %if.end
%5 = load i64, ptr %i, align 8
%add = add i64 %5, 2
store i64 %add, ptr %i, align 8
%6 = load i64, ptr %j, align 8
%inc = add i64 %6, 1
store i64 %inc, ptr %j, align 8
br label %for.cond, !llvm.loop !15

for.end: ; preds = %for.cond
%call8 = call i32 (ptr, ...) @printf(ptr noundef @"??_C@_07PBILKAFL@Success?$AA@")
store i32 0, ptr %retval, align 4
br label %return

return: ; preds = %for.end, %if.then
%7 = load i32, ptr %retval, align 4
ret i32 %7
}

; Function Attrs: nocallback nofree nounwind willreturn memory(argmem: readwrite)
declare void @llvm.memcpy.p0.p0.i64(ptr noalias nocapture writeonly, ptr noalias nocapture readonly, i64, i1 immarg) #2

; Function Attrs: nocallback nofree nounwind willreturn memory(argmem: write)
declare void @llvm.memset.p0.i64(ptr nocapture writeonly, i8, i64, i1 immarg) #3

; Function Attrs: mustprogress noinline optnone uwtable
define linkonce_odr dso_local i32 @printf(ptr noundef %_Format, ...) #4 comdat {
entry:
%_Format.addr = alloca ptr, align 8
%_Result = alloca i32, align 4
%_ArgList = alloca ptr, align 8
store ptr %_Format, ptr %_Format.addr, align 8
call void @llvm.va_start(ptr %_ArgList)
%0 = load ptr, ptr %_ArgList, align 8
%1 = load ptr, ptr %_Format.addr, align 8
%call = call ptr @__acrt_iob_func(i32 noundef 1)
%call1 = call i32 @_vfprintf_l(ptr noundef %call, ptr noundef %1, ptr noundef null, ptr noundef %0)
store i32 %call1, ptr %_Result, align 4
call void @llvm.va_end(ptr %_ArgList)
%2 = load i32, ptr %_Result, align 4
ret i32 %2
}

; Function Attrs: mustprogress noinline optnone uwtable
define linkonce_odr dso_local i32 @scanf(ptr noundef %_Format, ...) #4 comdat {
entry:
%_Format.addr = alloca ptr, align 8
%_Result = alloca i32, align 4
%_ArgList = alloca ptr, align 8
store ptr %_Format, ptr %_Format.addr, align 8
call void @llvm.va_start(ptr %_ArgList)
%0 = load ptr, ptr %_ArgList, align 8
%1 = load ptr, ptr %_Format.addr, align 8
%call = call ptr @__acrt_iob_func(i32 noundef 0)
%call1 = call i32 @_vfscanf_l(ptr noundef %call, ptr noundef %1, ptr noundef null, ptr noundef %0)
store i32 %call1, ptr %_Result, align 4
call void @llvm.va_end(ptr %_ArgList)
%2 = load i32, ptr %_Result, align 4
ret i32 %2
}

declare dso_local i64 @strlen(ptr noundef) #5

; Function Attrs: nocallback nofree nosync nounwind willreturn
declare void @llvm.va_start(ptr) #6

; Function Attrs: mustprogress noinline optnone uwtable
define linkonce_odr dso_local i32 @_vfprintf_l(ptr noundef %_Stream, ptr noundef %_Format, ptr noundef %_Locale, ptr noundef %_ArgList) #4 comdat {
entry:
%_ArgList.addr = alloca ptr, align 8
%_Locale.addr = alloca ptr, align 8
%_Format.addr = alloca ptr, align 8
%_Stream.addr = alloca ptr, align 8
store ptr %_ArgList, ptr %_ArgList.addr, align 8
store ptr %_Locale, ptr %_Locale.addr, align 8
store ptr %_Format, ptr %_Format.addr, align 8
store ptr %_Stream, ptr %_Stream.addr, align 8
%0 = load ptr, ptr %_ArgList.addr, align 8
%1 = load ptr, ptr %_Locale.addr, align 8
%2 = load ptr, ptr %_Format.addr, align 8
%3 = load ptr, ptr %_Stream.addr, align 8
%call = call ptr @__local_stdio_printf_options()
%4 = load i64, ptr %call, align 8
%call1 = call i32 @__stdio_common_vfprintf(i64 noundef %4, ptr noundef %3, ptr noundef %2, ptr noundef %1, ptr noundef %0)
ret i32 %call1
}

declare dso_local ptr @__acrt_iob_func(i32 noundef) #5

; Function Attrs: nocallback nofree nosync nounwind willreturn
declare void @llvm.va_end(ptr) #6

declare dso_local i32 @__stdio_common_vfprintf(i64 noundef, ptr noundef, ptr noundef, ptr noundef, ptr noundef) #5

; Function Attrs: mustprogress noinline nounwind optnone uwtable
define linkonce_odr dso_local ptr @__local_stdio_printf_options() #0 comdat {
entry:
ret ptr @"?_OptionsStorage@?1??__local_stdio_printf_options@@9@4_KA"
}

; Function Attrs: mustprogress noinline optnone uwtable
define linkonce_odr dso_local i32 @_vfscanf_l(ptr noundef %_Stream, ptr noundef %_Format, ptr noundef %_Locale, ptr noundef %_ArgList) #4 comdat {
entry:
%_ArgList.addr = alloca ptr, align 8
%_Locale.addr = alloca ptr, align 8
%_Format.addr = alloca ptr, align 8
%_Stream.addr = alloca ptr, align 8
store ptr %_ArgList, ptr %_ArgList.addr, align 8
store ptr %_Locale, ptr %_Locale.addr, align 8
store ptr %_Format, ptr %_Format.addr, align 8
store ptr %_Stream, ptr %_Stream.addr, align 8
%0 = load ptr, ptr %_ArgList.addr, align 8
%1 = load ptr, ptr %_Locale.addr, align 8
%2 = load ptr, ptr %_Format.addr, align 8
%3 = load ptr, ptr %_Stream.addr, align 8
%call = call ptr @__local_stdio_scanf_options()
%4 = load i64, ptr %call, align 8
%call1 = call i32 @__stdio_common_vfscanf(i64 noundef %4, ptr noundef %3, ptr noundef %2, ptr noundef %1, ptr noundef %0)
ret i32 %call1
}

declare dso_local i32 @__stdio_common_vfscanf(i64 noundef, ptr noundef, ptr noundef, ptr noundef, ptr noundef) #5

; Function Attrs: mustprogress noinline nounwind optnone uwtable
define linkonce_odr dso_local ptr @__local_stdio_scanf_options() #0 comdat {
entry:
ret ptr @"?_OptionsStorage@?1??__local_stdio_scanf_options@@9@4_KA"
}

attributes #0 = { mustprogress noinline nounwind optnone uwtable "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }
attributes #1 = { mustprogress noinline norecurse optnone uwtable "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }
attributes #2 = { nocallback nofree nounwind willreturn memory(argmem: readwrite) }
attributes #3 = { nocallback nofree nounwind willreturn memory(argmem: write) }
attributes #4 = { mustprogress noinline optnone uwtable "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }
attributes #5 = { "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }
attributes #6 = { nocallback nofree nosync nounwind willreturn }

!llvm.linker.options = !{!0, !1, !2, !3, !4, !5, !6}
!llvm.module.flags = !{!7, !8, !9, !10}
!llvm.ident = !{!11}

!0 = !{!"/FAILIFMISMATCH:\22_CRT_STDIO_ISO_WIDE_SPECIFIERS=0\22"}
!1 = !{!"/FAILIFMISMATCH:\22_MSC_VER=1900\22"}
!2 = !{!"/FAILIFMISMATCH:\22_ITERATOR_DEBUG_LEVEL=0\22"}
!3 = !{!"/FAILIFMISMATCH:\22RuntimeLibrary=MT_StaticRelease\22"}
!4 = !{!"/DEFAULTLIB:libcpmt.lib"}
!5 = !{!"/FAILIFMISMATCH:\22annotate_string=0\22"}
!6 = !{!"/FAILIFMISMATCH:\22annotate_vector=0\22"}
!7 = !{i32 1, !"wchar_size", i32 2}
!8 = !{i32 8, !"PIC Level", i32 2}
!9 = !{i32 7, !"uwtable", i32 2}
!10 = !{i32 1, !"MaxTLSAlign", i32 65536}
!11 = !{!"clang version 17.0.1"}
!12 = distinct !{!12, !13}
!13 = !{!"llvm.loop.mustprogress"}
!14 = distinct !{!14, !13}
!15 = distinct !{!15, !13}

发现要爆破每两位字符的CRC64,编写脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
def calculate_crc64_direct(data):
crc = 0xFFFFFFFFFFFFFFFF
poly = 0x42F0E1EBA9EA3693

for byte in data:
crc ^= (byte << 56)
for _ in range(8):
if crc & (1 << 63):
crc = (crc << 1) ^ poly
else:
crc <<= 1
crc &= 0xFFFFFFFFFFFFFFFF

return crc ^ 0xFFFFFFFFFFFFFFFF

enc = [0xdc63e34e419f7b47, 0x31ef8d4e7b2bfc6, 0x12d62fbc625fd89e, 0x83e8b6e1cc5755e8, 0xfc7bb1eb2ab665cc, 0x9382ca1b2a62d96b,
0xb1fff8a07673c387, 0xda81627388e05e1, 0x9ef1e61ae8d0aab7, 0x92783fd2e7f26145, 0x63c97ca1f56fe60b, 0x9bd3a8b043b73aab]

flag = bytearray()

for i, target in enumerate(enc):
found = False
for b in range(0x10000):
pair = bytes([b >> 8, b & 0xff])
crc = calculate_crc64_direct(pair)
if crc == target:
flag.extend(pair)
print(f"Segment {i+1} found: {pair.hex()}")
found = True
break
if not found:
print(f"No valid pair found for segment {i+1}")
exit()

print("Flag:", flag.decode())

得到flag:flag{LLVM_1s_Fun_Ri9h7?}.

总结 (犯病)

主播主播,平时的确实很,但还是太常规了,有没有更加罕见、更加不寻常、更偏难怪一点的题目?

有的兄弟,有的!

这次比赛一共有个这样的题目,都是十分甚至九分的不常见十分甚至九分的稀有十分甚至九分的罕见题目.

在本次比赛,你可以看见:

VBScriptDriverUnicorn Arm VMHaskellCythonLLVMPascal

考点不常见倒不是坏事,也能学到很多东西()

希望明年叉歪西替埃弗还有这样的石来赤😋 (小馋猫)