-
-
[原创] 看雪 2023 KCTF 年度赛 第二题 CN星际基地
-
发表于: 2023-9-5 04:57 9164
-
全部逻辑都在main函数sub_140001790中,IDA F5静态分析 + x64dbg动态调试确定各部分的逻辑:(函数太长,伪代码不贴了)
第一步:读入serial,检查长度为156
第二步:serial的每四个字符一组(四个字符的位置相差39,即把156长度的输入变成4*39的数组,然后取每列的四个字符组成一组),转换成十进制数字。另外,如果这4个字符中没有'2',则要求能按二进制转换成功且值不为15。注意15的二进制表示是1111,这里的限制暂可认为是检查一组四个字符组成的字符串不为"1111"
第三步:一些multibyte的转换,没有实质意义
第四步:继续检查一组四个字符,如果其中有'2',则不能有4个'2'。相当于检查四个字符组成的字符串不为"2222"
第五步:把第二部分转出的十进制数再转回了字符串,没有实质意义
第六步:(0x140001DF2)第二步得到了39个十进制数,检查它们是递增的,且最小的数大于0
第七步:(0x140001EF1)检查156个原始字符只能是'0'、'1'、'2'之一,并把'0'转换为0,'1'转换为1,'2'转换为-1,存入0x1400098A8的4*39矩阵中。回顾第二步,其每四个字符组成的字符串实际上只能包含'0''1''2'三种字符,且不为"0000""1111""2222"。
第八步:给0x1400098C0的矩阵赋值,没有实质意义。
第九步:对第七步得到的0x1400098A8矩阵,从0到38遍历,对每一行,如果对应位置的数是1,则计数器1加一,如果对应位置的数是-1,则计数器2加一;然后,根据计数器1和2的大小关系将1、0、-1存入0x1400098B8(实际上,最终存入的值一定等于0x1400098A8矩阵对应列的值);四行遍历完成后,再检查0x1400098B8的值与0x1400098A8矩阵的对应列的值相等。这是一个很奇怪的检查,代码很复杂但实际上没有任何效果,检查一定会无条件通过。另外,第七步的'2'->-1的转换也并没有实质效果
第十步:(0x140002512)在第九步的遍历中,对每一行,将该行的39个数求和,检查结果为0(当且仅当行内1和-1的个数相等时才满足)
以上是程序对serial的所有逻辑校验。如果都通过,则最后检查156字节的serial的md5值为"aac82b7ad77ab00dcef90ac079c9490d"。
举个例子总结一下校验逻辑:例如输入的serial为 000000000000011111111111112222222222222000011111111100001122222220000011222222011100011122200120200112220112202001122101201201201212001212020120121202010201
(这是题目的正确输入)
serial只能包含'0''1''2'三种字符。先转成4*39矩阵:
每一行的1和2的个数必须相等(第十步)(注意,这里对0的具体个数没有要求,第十步不要求0(或者1或2)的个数恰好占1/3)
按列重组:
把按列重组的每一行当做十进制数字,则这些数字要求严格单调递增、且不能等于0000、1111、2222(第二步、第四步、第六步)
仅此而已
可以看到,这些校验条件过于宽松,不足以缩小md5的爆破范围
后续作者给了两个提示:
说是提示并不合理,实际上是在修正题目的缺陷。这两个约束条件本就应该写进程序中,按理应当在开赛前的验题流程中被发现。
(所以,是验题人疏忽了,还是,根本就没有验过题???)
将程序中的约束和作者提示给出的约束综合在一起,可以直观的翻译为z3:
解出单个满足条件的答案非常轻松,但是,加上作者提示补充的约束条件后仍然过于宽松,满足所有条件的答案数量仍然非常多。由于要爆破哈希,必须要求出所有的答案。
z3可以通过把先前求出的答案作为反向约束加入求解器中找到新的解,但是题目的答案太多,性能显然不足。
合理的解法似乎只能是正向遍历生成所有的解。如果直接按照原始的约束,写遍历并不容易。
实际上,做一个抽象,题目的约束可以转换如下:一个立方体,抽离一些方块后,剩下各个截面的方块数量相同。
这里的立方体可以是任意维度,相应的截面是低一维的维度。
举一些例子:
先从二维开始,“立方体”是3*3的平面,截面是3*1的三条横线和1*3的三条竖线。
这9个方块的坐标分别为:(这里用2代替-1)
转置一下:
这个转置矩阵有两行,每行的0、1、2的个数恰好占1/3,并且如果把每列的两个数组合成十进制,9个列恰好是单调递增的。
我们现在从9个方块中抽走6个,剩余3个,并且要求3*3方格中,每行每列剩下的方块个数都相等。一种抽离方法如下:(o是保留的方块,x是抽离的方块。对角线的坐标为00,11,22,所以首先被抽离掉)
剩下的三个节点的坐标,转置后是:(仍然用2代替-1)
注意到,每行的0、1、2的个数仍然恰好占1/3,且任何关于中心方块00对称的一对方块,最后只留下了一个(例如01和02,12和21,20和10,都只留下了前者)
二维的例子已经与题目serial的格式有一些相似了,但仍然不太明确
下面将示例扩展到三维,对应关系会变得非常清晰
三维立方体共有27个方块,每个面有9个,这27个方块的坐标如下:(用2代替-1,转置)
第一行为0、1、2的列分别代表从垂直x轴方向切分得到的三个平面的方块
第二行为0、1、2的列分别代表从垂直y轴方向切分得到的三个平面的方块
第三行为0、1、2的列分别代表从垂直z轴方向切分得到的三个平面的方块
排除主对角线上的三个方块(000、111、222),还有24个方块。我们抽离一半,那么只剩下12个方块,平均到每个面上是4个。剩余12个方块坐标如下:(其中前4列、中间4列、后4列分别表示一个平面)
?表示待定,但是我们要保证无论沿着与哪个坐标轴垂直的方向切分,得到的平面都要恰好只剩4个方块,所以第二行的0、1、2的个数必须相等,第三行同理。
题目需要求解四维的情况。
四维立方体共81个方块,每个面(四维立方体的面是三维立方体)有27个方块。
排除主对角线方块3个(坐标0000、1111、2222),剩余78个方块抽离一半,剩余39个,平均到每个面上是13个。
剩余的39个方块,每个方块的坐标要用4个维度表示,恰好是main函数第七步存入0x140001EF1的矩阵。
矩阵的每一行要求0、1、-1 (2) 的个数都是1/3,即13个,恰好等于平均到每个面上的方块数量。
排除主对角线(第二步、第四步、第六步的约束)后,剩余的78方块恰好是两两关于中心点0000对称的。抽离的数量是一半,而作者提示的补充约束1指明相反的值不能同时存在,结合二者,实际上抽离时不能随意选择一半的方块,而是要求从每对关于中心点对称的方块中抽走一个留下另一个。
定义81个变量表示81个方块,取值0表示被抽离走,取值1表示最终留存,则所有的约束可以精确的等价为方程:
最终,我们有81个变量以及一个线性方程组,只需要在满足方程组约束的前提下找到所有变量的所有可能取值,即可反推出所有可能的serial。
这里使用了sympy对线性方程组做符号化简:
得到的输出如下:
总共81个变量,有46个方程,也就是只有81-46=35个变量是自由的,只要这35个变量的值是确定的,即可计算出全部81个变量的值。
从上面46个方程的右边找到这35个自由变量,分别是:x6, x7, x8, x9, x20, x22, x23, x24, x25, x26, x55, x56, x57, x58, x59, x60, x61, x62, x63, x64, x65, x66, x67, x68, x69, x70, x71, x72, x73, x74, x75, x76, x77, x78, x79
2**35的量级,用C/C++语言完全能够在分钟量级遍历完成。
当35个自由变量确定值后,可以解出全部81个变量,而唯一这46个方程没能体现的约束则是每个变量只取0和1两个值。观察上面的46个方程,只需要对x1、x11、x15、x19、x2、x21、x27、x54做额外检验即可。再进一步,注意到x1+x2==1、x11+x19==1、x15+x21==1、x27+x54==1恒成立,实际上只需要额外检验四个变量。
(在64位Linux下运行,保证long是8个字节)
gcc -O3编译,单线程大约19min跑完,stderr的输出(stderr.txt,3.22GB!)即为合法的35个自由变量的取值,共计 294511600 个!(2.9亿,这也是实际满足题目所有约束(除了哈希)的所有解的个数)
最后一步,将这294511600个结果反推为serial,逐一计算md5,检查是否满足预设值。
(下面的python脚本要用pypy3跑,单线程大约十几到二十几分钟(当然,可以拆分输入开多进程加速)。普通的cpython不行,速度太慢)
最后,在 i = 281453140、n = 31608758280 的时候爆破成功,正确的serial为:
按照题目程序的校验却无法反推出唯一的serial,只能作为约束减少爆破的范围,使得题目最后变成了哈希爆破的游戏,不得不说是一个巨大的遗憾,完全失去了题目算法原本的优雅。
(虽然爆破时间可以控制在30分钟内不违反规则,但显然规则也明确不鼓励爆破。而且,作为逆向题,如果多解需要依靠哈希校验才能控制住,是不是说明本身程序的逻辑是不完备的呢?)
000000000000011111111111112222222222222
000011111111100001122222220000011222222
011100011122200120200112220112202001122
101201201201212001212020120121202010201
000000000000011111111111112222222222222
000011111111100001122222220000011222222
011100011122200120200112220112202001122
101201201201212001212020120121202010201
0001
0010
0011
0012
...
2210
2212
2220
2221
0001
0010
0011
0012
...
2210
2212
2220
2221
1
、列向量组里不存在相反值,如[
1
,
-
1
,
1
,
0
]与[
-
1
,
1
,
-
1
,
0
]不能同时存在
2
、每个行向量里的
0
的数量 占
1
/
3
1
、列向量组里不存在相反值,如[
1
,
-
1
,
1
,
0
]与[
-
1
,
1
,
-
1
,
0
]不能同时存在
2
、每个行向量里的
0
的数量 占
1
/
3
from
z3
import
*
def
build_integer(a, b, c, d):
return
a
*
1000
+
b
*
100
+
c
*
10
+
d
def
check_inverse(x, y):
conds
=
[Or(And(x[i]
=
=
0
, y[i]
=
=
0
), And(x[i]
=
=
1
, y[i]
=
=
2
), And(x[i]
=
=
2
, y[i]
=
=
1
))
for
i
in
range
(
4
)]
return
And(conds)
v
=
[
Int
(f
"{i}"
)
for
i
in
range
(
156
)]
s
=
Solver()
for
bad
in
badvalues:
s.add(Not(And([v[i]
=
=
bad[i]
for
i
in
range
(
156
)])))
for
n
in
v:
s.add(Or(n
=
=
0
, n
=
=
1
, n
=
=
2
))
integers
=
[build_integer(v[i], v[
39
+
i], v[
39
*
2
+
i], v[
39
*
3
+
i])
for
i
in
range
(
39
)]
s.add(integers[
0
] >
0
)
s.add(integers[
38
] !
=
1111
)
s.add(integers[
38
] <
2222
)
for
i
in
range
(
39
-
1
):
s.add(integers[i] < integers[i
+
1
])
s.add(integers[i] !
=
1111
)
for
i
in
range
(
39
):
for
j
in
range
(i
+
1
,
39
):
s.add(Not(check_inverse([v[i], v[
39
+
i], v[
39
*
2
+
i], v[
39
*
3
+
i]], [v[j], v[
39
+
j], v[
39
*
2
+
j], v[
39
*
3
+
j]])))
for
k
in
range
(
4
):
sum_minus_1
=
Sum
([If(v[
39
*
k
+
i]
=
=
2
,
1
,
0
)
for
i
in
range
(
39
)])
sum_1
=
Sum
([If(v[
39
*
k
+
i]
=
=
1
,
1
,
0
)
for
i
in
range
(
39
)])
sum_0
=
Sum
([If(v[
39
*
k
+
i]
=
=
0
,
1
,
0
)
for
i
in
range
(
39
)])
s.add(sum_minus_1
=
=
sum_1)
s.add(sum_0
=
=
13
)
s.check()
/
/
sat
from
z3
import
*
def
build_integer(a, b, c, d):
return
a
*
1000
+
b
*
100
+
c
*
10
+
d
def
check_inverse(x, y):
conds
=
[Or(And(x[i]
=
=
0
, y[i]
=
=
0
), And(x[i]
=
=
1
, y[i]
=
=
2
), And(x[i]
=
=
2
, y[i]
=
=
1
))
for
i
in
range
(
4
)]
return
And(conds)
v
=
[
Int
(f
"{i}"
)
for
i
in
range
(
156
)]
s
=
Solver()
for
bad
in
badvalues:
s.add(Not(And([v[i]
=
=
bad[i]
for
i
in
range
(
156
)])))
for
n
in
v:
s.add(Or(n
=
=
0
, n
=
=
1
, n
=
=
2
))
integers
=
[build_integer(v[i], v[
39
+
i], v[
39
*
2
+
i], v[
39
*
3
+
i])
for
i
in
range
(
39
)]
s.add(integers[
0
] >
0
)
s.add(integers[
38
] !
=
1111
)
s.add(integers[
38
] <
2222
)
for
i
in
range
(
39
-
1
):
s.add(integers[i] < integers[i
+
1
])
s.add(integers[i] !
=
1111
)
for
i
in
range
(
39
):
for
j
in
range
(i
+
1
,
39
):
s.add(Not(check_inverse([v[i], v[
39
+
i], v[
39
*
2
+
i], v[
39
*
3
+
i]], [v[j], v[
39
+
j], v[
39
*
2
+
j], v[
39
*
3
+
j]])))
for
k
in
range
(
4
):
sum_minus_1
=
Sum
([If(v[
39
*
k
+
i]
=
=
2
,
1
,
0
)
for
i
in
range
(
39
)])
sum_1
=
Sum
([If(v[
39
*
k
+
i]
=
=
1
,
1
,
0
)
for
i
in
range
(
39
)])
sum_0
=
Sum
([If(v[
39
*
k
+
i]
=
=
0
,
1
,
0
)
for
i
in
range
(
39
)])
s.add(sum_minus_1
=
=
sum_1)
s.add(sum_0
=
=
13
)
s.check()
/
/
sat
-
1
0
1
-
-
-
1
| o o o
0
| o o o
-
1
| o o o
-
1
0
1
-
-
-
1
| o o o
0
| o o o
-
1
| o o o
0
,
0
0
,
1
0
,
2
1
,
0
1
,
1
1
,
2
2
,
0
2
,
1
2
,
2
0
,
0
0
,
1
0
,
2
1
,
0
1
,
1
1
,
2
2
,
0
2
,
1
2
,
2
000111222
012012012
000111222
012012012
-
1
0
1
-
-
-
1
| x o x
0
| o x x
-
1
| x x o
-
1
0
1
-
-
-
1
| x o x
0
| o x x
-
1
| x x o
012
120
012
120
000000000111111111222222222
000111222000111222000111222
012012012012012012012012012
000000000111111111222222222
000111222000111222000111222
012012012012012012012012012
000011112222
????????????
????????????
000011112222
????????????
????????????
from
pprint
import
pprint
from
sympy
import
Symbol, symbols, solve
def
i2abcd(i):
a, b, c, d
=
(i
/
/
27
)
%
3
, (i
/
/
9
)
%
3
, (i
/
/
3
)
%
3
, i
%
3
return
a, b, c, d
def
abcd2i(a, b, c, d):
return
a
*
27
+
b
*
9
+
c
*
3
+
d
def
i2n(i):
a, b, c, d
=
i2abcd(i)
return
a
*
1000
+
b
*
100
+
c
*
10
+
d
def
n2i(n):
a, b, c, d
=
(n
/
/
1000
)
%
10
, (n
/
/
100
)
%
10
, (n
/
/
10
)
%
10
, n
%
10
return
abcd2i(a, b, c, d)
def
opposite(i):
a, b, c, d
=
i2abcd(i)
a, b, c, d
=
(
3
-
a)
%
3
, (
3
-
b)
%
3
, (
3
-
c)
%
3
, (
3
-
d)
%
3
return
abcd2i(a, b, c, d)
def
build_all_opposite_pairs():
pairs
=
[]
known
=
set
()
for
i
in
range
(
81
):
if
i
in
known:
continue
if
i2n(i)
in
[
0
,
1111
,
2222
]:
continue
ii
=
opposite(i)
assert
ii
not
in
known
known.add(i)
known.add(ii)
pairs.append((i, ii))
return
pairs
def
build_row_parts(row):
parts
=
([], [], [])
for
i
in
range
(
81
):
abcd
=
i2abcd(i)
parts[abcd[row]].append(i)
return
parts
row0_parts
=
build_row_parts(
0
)
row1_parts
=
build_row_parts(
1
)
row2_parts
=
build_row_parts(
2
)
row3_parts
=
build_row_parts(
3
)
all_opposite_pairs
=
build_all_opposite_pairs()
x
=
list
(symbols(
'x:81'
))
equations
=
[]
for
i
in
range
(
81
):
if
i2n(i)
in
[
0
,
1111
,
2222
]:
equations.append(x[i])
for
a, b
in
all_opposite_pairs:
equations.append(x[a]
+
x[b]
-
1
)
for
i
in
range
(
3
):
equations.append(
sum
(x[c]
for
c
in
row0_parts[i])
-
13
)
for
i
in
range
(
3
):
equations.append(
sum
(x[c]
for
c
in
row1_parts[i])
-
13
)
for
i
in
range
(
3
):
equations.append(
sum
(x[c]
for
c
in
row2_parts[i])
-
13
)
for
i
in
range
(
3
):
equations.append(
sum
(x[c]
for
c
in
row3_parts[i])
-
13
)
# print(equations)
r
=
solve(equations)
for
k, v
in
r.items():
print
(k,
"="
, v)
from
pprint
import
pprint
from
sympy
import
Symbol, symbols, solve
def
i2abcd(i):
a, b, c, d
=
(i
/
/
27
)
%
3
, (i
/
/
9
)
%
3
, (i
/
/
3
)
%
3
, i
%
3
return
a, b, c, d
def
abcd2i(a, b, c, d):
return
a
*
27
+
b
*
9
+
c
*
3
+
d
def
i2n(i):
a, b, c, d
=
i2abcd(i)
return
a
*
1000
+
b
*
100
+
c
*
10
+
d
def
n2i(n):
a, b, c, d
=
(n
/
/
1000
)
%
10
, (n
/
/
100
)
%
10
, (n
/
/
10
)
%
10
, n
%
10
return
abcd2i(a, b, c, d)
def
opposite(i):
a, b, c, d
=
i2abcd(i)
a, b, c, d
=
(
3
-
a)
%
3
, (
3
-
b)
%
3
, (
3
-
c)
%
3
, (
3
-
d)
%
3
return
abcd2i(a, b, c, d)
def
build_all_opposite_pairs():
pairs
=
[]
known
=
set
()
for
i
in
range
(
81
):
if
i
in
known:
continue
if
i2n(i)
in
[
0
,
1111
,
2222
]:
continue
ii
=
opposite(i)
assert
ii
not
in
known
known.add(i)
known.add(ii)
pairs.append((i, ii))
return
pairs
def
build_row_parts(row):
parts
=
([], [], [])
for
i
in
range
(
81
):
abcd
=
i2abcd(i)
parts[abcd[row]].append(i)
return
parts
row0_parts
=
build_row_parts(
0
)
row1_parts
=
build_row_parts(
1
)
row2_parts
=
build_row_parts(
2
)
row3_parts
=
build_row_parts(
3
)
all_opposite_pairs
=
build_all_opposite_pairs()
x
=
list
(symbols(
'x:81'
))
equations
=
[]
for
i
in
range
(
81
):
if
i2n(i)
in
[
0
,
1111
,
2222
]:
equations.append(x[i])
for
a, b
in
all_opposite_pairs:
equations.append(x[a]
+
x[b]
-
1
)
for
i
in
range
(
3
):
equations.append(
sum
(x[c]
for
c
in
row0_parts[i])
-
13
)
for
i
in
range
(
3
):
equations.append(
sum
(x[c]
for
c
in
row1_parts[i])
-
13
)
for
i
in
range
(
3
):
equations.append(
sum
(x[c]
for
c
in
row2_parts[i])
-
13
)
for
i
in
range
(
3
):
equations.append(
sum
(x[c]
for
c
in
row3_parts[i])
-
13
)
# print(equations)
r
=
solve(equations)
for
k, v
in
r.items():
print
(k,
"="
, v)
x0
=
0
x1
=
2
*
x20
-
x22
+
x23
+
2
*
x24
+
x25
+
3
*
x26
-
x55
+
x56
-
x57
-
2
*
x58
+
x6
+
x60
+
2
*
x62
-
x63
-
2
*
x64
-
2
*
x66
-
3
*
x67
-
x68
-
x70
+
x71
+
x72
+
2
*
x74
-
x76
+
x77
+
2
*
x78
+
x79
+
2
*
x8
-
x9
-
3
x10
=
1
-
x20
x11
=
x20
+
2
*
x24
+
2
*
x25
+
2
*
x26
-
x57
-
x58
-
x59
+
x6
+
x60
+
x61
+
x62
-
x63
-
x64
-
x65
-
2
*
x66
-
2
*
x67
-
2
*
x68
+
x7
+
x72
+
x73
+
x74
+
2
*
x78
+
2
*
x79
+
x8
-
x9
-
3
x12
=
1
-
x24
x13
=
1
-
x26
x14
=
1
-
x25
x15
=
x22
+
x23
-
x24
-
x25
-
x26
+
x57
+
x58
+
x59
-
x6
-
x60
-
x61
-
x62
+
x66
+
x67
+
x68
-
x69
-
x7
-
x70
-
x71
+
x75
+
x76
+
x77
-
x78
-
x79
-
x8
+
2
x16
=
1
-
x23
x17
=
1
-
x22
x18
=
1
-
x9
x19
=
-
x20
-
2
*
x24
-
2
*
x25
-
2
*
x26
+
x57
+
x58
+
x59
-
x6
-
x60
-
x61
-
x62
+
x63
+
x64
+
x65
+
2
*
x66
+
2
*
x67
+
2
*
x68
-
x7
-
x72
-
x73
-
x74
-
2
*
x78
-
2
*
x79
-
x8
+
x9
+
4
x2
=
-
2
*
x20
+
x22
-
x23
-
2
*
x24
-
x25
-
3
*
x26
+
x55
-
x56
+
x57
+
2
*
x58
-
x6
-
x60
-
2
*
x62
+
x63
+
2
*
x64
+
2
*
x66
+
3
*
x67
+
x68
+
x70
-
x71
-
x72
-
2
*
x74
+
x76
-
x77
-
2
*
x78
-
x79
-
2
*
x8
+
x9
+
4
x21
=
-
x22
-
x23
+
x24
+
x25
+
x26
-
x57
-
x58
-
x59
+
x6
+
x60
+
x61
+
x62
-
x66
-
x67
-
x68
+
x69
+
x7
+
x70
+
x71
-
x75
-
x76
-
x77
+
x78
+
x79
+
x8
-
1
x27
=
x55
+
x56
+
x57
+
x58
+
x59
+
x60
+
x61
+
x62
+
x63
+
x64
+
x65
+
x66
+
x67
+
x68
+
x69
+
x70
+
x71
+
x72
+
x73
+
x74
+
x75
+
x76
+
x77
+
x78
+
x79
-
12
x28
=
1
-
x56
x29
=
1
-
x55
x3
=
1
-
x6
x30
=
1
-
x60
x31
=
1
-
x62
x32
=
1
-
x61
x33
=
1
-
x57
x34
=
1
-
x59
x35
=
1
-
x58
x36
=
1
-
x72
x37
=
1
-
x74
x38
=
1
-
x73
x39
=
1
-
x78
x4
=
1
-
x8
x40
=
0
x41
=
1
-
x79
x42
=
1
-
x75
x43
=
1
-
x77
x44
=
1
-
x76
x45
=
1
-
x63
x46
=
1
-
x65
x47
=
1
-
x64
x48
=
1
-
x69
x49
=
1
-
x71
x5
=
1
-
x7
x50
=
1
-
x70
x51
=
1
-
x66
x52
=
1
-
x68
x53
=
1
-
x67
x54
=
-
x55
-
x56
-
x57
-
x58
-
x59
-
x60
-
x61
-
x62
-
x63
-
x64
-
x65
-
x66
-
x67
-
x68
-
x69
-
x70
-
x71
-
x72
-
x73
-
x74
-
x75
-
x76
-
x77
-
x78
-
x79
+
13
x80
=
0
x0
=
0
x1
=
2
*
x20
-
x22
+
x23
+
2
*
x24
+
x25
+
3
*
x26
-
x55
+
x56
-
x57
-
2
*
x58
+
x6
+
x60
+
2
*
x62
-
x63
-
2
*
x64
-
2
*
x66
-
3
*
x67
-
x68
-
x70
+
x71
+
x72
+
2
*
x74
-
x76
+
x77
+
2
*
x78
+
x79
+
2
*
x8
-
x9
-
3
x10
=
1
-
x20
x11
=
x20
+
2
*
x24
+
2
*
x25
+
2
*
x26
-
x57
-
x58
-
x59
+
x6
+
x60
+
x61
+
x62
-
x63
-
x64
-
x65
-
2
*
x66
-
2
*
x67
-
2
*
x68
+
x7
+
x72
+
x73
+
x74
+
2
*
x78
+
2
*
x79
+
x8
-
x9
-
3
x12
=
1
-
x24
x13
=
1
-
x26
x14
=
1
-
x25
x15
=
x22
+
x23
-
x24
-
x25
-
x26
+
x57
+
x58
+
x59
-
x6
-
x60
-
x61
-
x62
+
x66
+
x67
+
x68
-
x69
-
x7
-
x70
-
x71
+
x75
+
x76
+
x77
-
x78
-
x79
-
x8
+
2
x16
=
1
-
x23
x17
=
1
-
x22
x18
=
1
-
x9
x19
=
-
x20
-
2
*
x24
-
2
*
x25
-
2
*
x26
+
x57
+
x58
+
x59
-
x6
-
x60
-
x61
-
x62
+
x63
+
x64
+
x65
+
2
*
x66
+
2
*
x67
+
2
*
x68
-
x7
-
x72
-
x73
-
x74
-
2
*
x78
-
2
*
x79
-
x8
+
x9
+
4
x2
=
-
2
*
x20
+
x22
-
x23
-
2
*
x24
-
x25
-
3
*
x26
+
x55
-
x56
+
x57
+
2
*
x58
-
x6
-
x60
-
2
*
x62
+
x63
+
2
*
x64
+
2
*
x66
+
3
*
x67
+
x68
+
x70
-
x71
-
x72
-
2
*
x74
+
x76
-
x77
-
2
*
x78
-
x79
-
2
*
x8
+
x9
+
4
x21
=
-
x22
-
x23
+
x24
+
x25
+
x26
-
x57
-
x58
-
x59
+
x6
+
x60
+
x61
+
x62
-
x66
-
x67
-
x68
+
x69
+
x7
+
x70
+
x71
-
x75
-
x76
-
x77
+
x78
+
x79
+
x8
-
1
x27
=
x55
+
x56
+
x57
+
x58
+
x59
+
x60
+
x61
+
x62
+
x63
+
x64
+
x65
+
x66
+
x67
+
x68
+
x69
+
x70
+
x71
+
x72
+
x73
+
x74
+
x75
+
x76
+
x77
+
x78
+
x79
-
12
x28
=
1
-
x56
x29
=
1
-
x55
x3
=
1
-
x6
x30
=
1
-
x60
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)