baby_xor

0x01 预期解

十分简单的签到题,逻辑就是简单异或加密。解出来的人数也十分对得上人口普查器的描述。

有一个小坑点:enflag[25]的值是 0 ,如果直接从 ida 上静态复制的话会发现 flag 少了一位,在 flag 的提交记录中可以发现有的师傅踩了这个坑而且十分遗憾地没有更正。

1
2
3
4
5
a = [18, 20, 7, 17, 4, 110, 10, 58, 25, 124, 32, 14, 122, 6, 123, 22, 100, 8, 6, 48, 4, 22, 34, 117, 27, 0, 36, 18, 40, 4, 105, 42, 57, 67, 43, 85, 13, 60, 5, 83, 19]

for i in range(41):
a[i] = i ^ a[i] ^ 0x46
print(chr(a[i]), end = "")

baby_upx

第一个版本的附件是 vs 编译版本的,这个版本的附件在脱壳后的代码逻辑十分易懂,但有很多师傅反映没有装 vs ,缺少 dll 无法运行,并且不想让 vs 强暴自己的 C 盘,于是更新了第二版附件。这一版的附件脱壳后代码逻辑就显得不那么清晰了。

0x00 一个trick

脱壳方面,这里有一个本来是 Jameshoi 用在 upx_revenge 上的trick,但 Linux 下好像没用了,就放这个题上面了

由于最新版upx解压含有随机基址功能的exe时,会导致解压后的exe无法运行,但仍然可以进行静态分析。

若需要动态调试,可以将脱壳前的exe的随机基址功能关闭,再进行脱壳;又或者直接利用软件进行调试断点。

可以考虑用 Study PE 或者 010 Editor 工具来关闭随机基址

0x01 脱壳

然后是脱壳环节,我们可以使用 exeinfo 来检查相关信息

可以发现,查壳的地方有 Don’t try: upx.exe -d,并且前面的[ ]没有识别出特征值。这是因为出题人把 upx 的某些特征抹的差不多了,工具脱壳是无效的,只能选择手动脱壳。

手动脱壳部分,可以参考博客:https://www.52pojie.cn/thread-1534675-1-1.html,大致过程是一模一样的,不再赘述。

0x02 代码逻辑分析

脱壳完成后,开始分析程序逻辑。

可以发现,v4 是输入的长度,qword_7FF68AE37750 是输入的 flag ,用 v3 承接了对 qword_7FF68AE37750[v5] 的一大坨位运算操作,并且最后与 qword_7FF68AE34480[v5] 进行比较。当进行了 32 次比较后,会进入一个 check,也就是 sub_7FF68AE31B60,这个 check 实际上是一个 MD5 校验,比对成功会提示 flag 正确。

现在的问题来到如何解决这一堆位运算。非常容易想到的思路是:既然只有 32 位,我们是否可以通过强行爆破来寻找每一种可能的值。

1
2
3
4
5
6
7
8
9
10
a = [0xAF, 0xAC, 0xEC, 0xAF, 0xE7, 0x159, 0xDE, 0x1FC, 0x16F, 0x1ED, 0x1EC, 0x1DE, 0xB5, 0x16F, 0xB5, 0xEE, 0xE8, 0xEE, 0x1FC, 0xB5, 0xAD, 0xAE, 0x1FE, 0xB5, 0x1EE, 0x1EE, 0x16E, 0x17E, 0xDF, 0x16C, 0x1D9, 0x1FD]

def enc(x):
return ((x & 32) << 3 | (x & 21) >> 2 | (x ^ 5) << 1 | (~x & 91) << 2)

for i in a:
for j in range(32, 129):
if enc(j) == i:
print(chr(j), end = "")
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
30
31
32
T
QS
C
T
F
-
HJ
y{
$4
u
cqs
hj
_
$4
_
@B
A
@B
y{
_
U
PR
xz
_
`bpr
`bpr
"02€
8:
L
#13
m
}

随后可以先手动整理一下,然后将可能的 flag 输入进 ida 动调进行校验。这样已经可以最终确定flag为 TSCTF-J{$uch_4_BABy_UPx_pr08L3m}

0x03 自动爆破

如果不想手动整理,这里分享一种通过 dfs 进行自动校验的做法,大概跑个十几秒就出来了:

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 subprocess
import sys

enflag = ['T', 'S', 'C', 'T', 'F', '-', 'J', '{', '$4', 'u', 'cqs', 'hj', '_', '$4', '_', '@B', 'A', '@B', 'y', '_', 'U', 'P', 'x', '_', '`bpr', '`bpr', '"02', '8:', 'L', '#13', 'm', '}']

def dfs(dep, flag):
if dep == 32:

file = "F:\\Desktop\\CTF\\Problems\\出题\\TSCTF-J 2022\\Reverse\\iPlayForSG - baby_upx\\baby_upx_upx_version.exe"

p = subprocess.Popen([file], stdin = subprocess.PIPE, stdout = subprocess.PIPE)

p.stdin.write(flag.encode())
p.stdin.close()

result = p.stdout.read()
p.stdout.close()

if b'YOU ARE GENIUS!!!' in result:
print(flag)
sys.exit(0)

else:
for i in enflag[dep]:
dfs(dep + 1, flag + i)

dfs(0, '')

byte_code

字节码嗯逆,源码如下,合理运用搜索引擎+亿点点耐心都能做出本题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
a = [114, 101, 118, 101, 114, 115, 101, 95, 116, 104, 101, 95, 98, 121, 116, 101]
b = [99, 111, 100, 101, 95, 116, 111, 95, 103, 101, 116, 95, 102, 108, 97, 103]
e = [80, 115, 193, 24, 226, 237, 202, 212, 126, 46, 205, 208, 215, 135, 228, 199, 63, 159, 117, 52, 254, 247, 0, 133, 163, 248, 47, 115, 109, 248, 236, 68]
pos = [9, 6, 15, 10, 1, 0, 11, 7, 4, 12, 5, 3, 8, 2, 14, 13]
d = [335833164, 1155265242, 627920619, 1951749419, 1931742276, 856821608, 489891514, 366025591, 1256805508, 1106091325, 128288025, 234430359, 314915121, 249627427, 207058976, 1573143998, 1443233295, 245654538, 1628003955, 220633541, 1412601456, 1029130440, 1556565611, 1644777223, 853364248, 58316711, 734735924, 1745226113, 1441619500, 1426836945, 500084794, 1534413607]
if __name__ == '__main__':
c = a + b
for i in range(31):
print(chr(c[i]), end = "")
print(chr(c[31]))
for i in range(16):
a[i] = (a[i] + d[i]) ^ b[pos[i]]
for i in range(16):
b[i] = b[i] ^ a[pos[i]]
c = a + b
for i in range(32):
c[i] = (c[i] * d[i]) % 256
c[i] ^= e[i]
print(chr(c[i]), end = "")

逆出来运行即可获得flagTSCTF-J{bY7ecoDe_I$_nOT_so_HArd}

baby_key

ELF文件,在Linux打开,让输入密码

用ida打开,scanf语句后面是sub_11B8函数,点进去发现是一个switch_case语句

根据memcmp函数可以知道密码长度为16位,爆破或者观察一下,构造出正确的opcode使得byte_4060和s2相同即可。

构造出来是一个倒装句:sO*h4hdsOm3!!sg!,输入以后提示PASSWORD CORRECT说明密码正确

然后进入加密函数部分,sub_15F0点进去一看是一个TEA加密算法,密文是byte_40C0,flag长度是44位且为TSCTF-J包裹。密钥就是我们之前输入的password,每四个char转化为一个unsigned int 32,得到4位密钥,注意密钥不是['s', 'O', '*', 'h'],哪个小可爱写成这个的可以再看看代码。

注意这里,在比对结果之前把小端序改成了大端序

爽上解密脚本,然后就错辣。

原因是__attribute__((constructor()))函数可以在main函数之前运行,偷偷修改了enflag的值,查看交叉引用或者动调即可获得正确的enflag

放上exp:

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
#include <iostream>
#include <cstdio>
#include <stdint.h>
using namespace std;

char opcode[20] = "sO*h4hdsOm3!!sg!";
uint32_t key[4];

unsigned char enc[] =
{
0x2f, 0x33, 0x20, 0x70, 0xac, 0x7e, 0x89, 0x4, 0xca, 0xd2, 0xfb, 0x3, 0x51, 0x8c, 0x80, 0x23, 0x69, 0xe0, 0xc0, 0xe5, 0x41, 0x62, 0xf2, 0x26, 0xb8, 0x87, 0xa4, 0x33, 0xfb, 0x7a, 0x29, 0xe4, 0x45, 0x20, 0x3c, 0x2a, 0xfe, 0x2c, 0xec, 0x18, 0xf3, 0x2, 0x1, 0xe, 0x99, 0x3b, 0x7, 0x21
};

uint32_t data[11];

void decrypt(uint32_t *v, uint32_t *key)
{
uint32_t l = v[0], r = v[1], sum = 0, delta = 1640531527;
sum = - delta * 32;
for (int i = 1; i <= 32; ++i)
{
r -= ((l << 4) + key[2]) ^ (l + sum) ^ ((l >> 5) + key[3]);
l -= ((r << 4) + key[0]) ^ (r + sum) ^ ((r >> 5) + key[1]);
sum += delta;
}
v[0] = l, v[1] = r;
}

int main()
{
for(int i = 0; i < 4; i++) key[i] = *(uint32_t*)&opcode[i * 4];
for(int i = 0; i < 11; i++)data[i] = *(uint32_t*)&enc[4 * i];
for(int i = 0; i < 48; i++)
{
enc[i] ^= 0x27;
}
for(int i = 0; i < 48; i += 4)swap(enc[i], enc[i + 3]), swap(enc[i + 1], enc[i + 2]);
for(int i = 10; i >= 0; i--)
{
decrypt((uint32_t*)&enc[4 * i], key);
}
cout << enc;
return 0;
}

运行得到flagTSCTF-J{T1ny_eNcryPtIoN_4LgOrIthm_Is_so_FUn}

Link_Game

0x01 获取相关信息

(如果在你的电脑跑的动的话)先随便玩一下这个游戏,然后会发现一个弹窗:

有的师傅在这里考虑使用了 Cheat Engine 进行数据修改

但是,会产生如下弹窗:

说明这次这个题的出题人不是很想让你直接用 CE 解题,那么只能考虑对程序进行逆向了。

0x02 逆向过程

用 exeinfo 可以得知该程序是 C# 编写的

可以考虑使用 Dnspy 来对C#进行逆向,该工具十分强大,甚至可以在反编译后直接将代码导入 VS 的工程,十分方便。

可以发现,程序内大量使用了 base64 对文本进行简单加密,经过尝试,可以发现Last_Dance()下的文本为

可以猜测这里就是最终 flag 的比对处。

0x03 解密

对其逆向即可。首先预处理密钥数组 k 的状态,然后根据异或可逆进行逆向即可。

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
#include <iostream>
#include <cstdio>
using namespace std;
int enc[] = {53, 71, 22, 108, 73, 97, 59, 107, 63, 126, 103, 125, 106, 80, 98, 66, 83, 93, 75, 2, 94, 96, 91, 48};
int k[] = {71, 65, 77, 51};

int main()
{
for (int i = 0; i <= 20; i++)
{
int num6 = k[0];
k[0] = k[1];
k[1] = k[2];
k[2] = k[3];
k[3] = num6;
}
for (int i = 20; i >= 0; i--)
{
int num6 = k[3];
k[3] = k[2];
k[2] = k[1];
k[1] = k[0];
k[0] = num6;
int num3 = (enc[i + 3] ^ k[3]);
int num2 = (enc[i + 2] ^ k[2]);
int num5 = (enc[i + 1] ^ (k[1] + (num3 >> 4) & 0x67));
int num4 = (enc[i] ^ (k[0] + (num2 >> 3) & 0x45));
enc[i + 3] = num5;
enc[i + 2] = num4;
enc[i + 1] = num3;
enc[i] = num2;
}
cout << "TSCTF-J{";
for (int i = 0; i < 24; ++i) printf("%c", enc[i]);
cout << "}";
}

ez_maze

0x01 简单的预期解

本题是添加了虚假控制流混淆的迷宫题,最初的预期解就是靠获得地图后猜测程序在干什么,也是想告诉大家:Reverse 方向很多时候需要猜想 & 尝试,而不是一直盯着代码嗯逆。

很喜欢 tipsy 学长的一句话:

在大概看过代码逻辑后,来到字符串窗口

可以猜测最下面那一大串是迷宫,简单整理一下就能拿到迷宫地图,然后可以考虑手走,也可以考虑写个搜索

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
#include <bits/stdc++.h>
using namespace std;
char mp[233][233] =
{
"+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+",
"|SS | | | | | |",
"+ + + +--+ + +--+--+ + +--+--+--+--+ +--+--+--+--+ +--+ + +--+ + +--+--+ + +",
"| | | | | | | | | | | | | | | | | |",
"+--+--+--+ +--+--+ + + +--+ +--+ +--+ + +--+ + +--+ + +--+ +--+ +--+ +--+ +",
"| | | | | | | | | | | | | | | | | | |",
"+ + +--+ +--+--+ + +--+ +--+ +--+ +--+ + + + + +--+--+ + + +--+ + +--+ +",
"| | | | | | | | | | | | | | | | | | |",
"+ +--+ +--+--+ + + + +--+ + + +--+--+--+ + + +--+ +--+ +--+--+ +--+ + +--+",
"| | | | | | | | | | | | | | | | | | |",
"+--+ + +--+ +--+ + +--+--+--+ + + + + + +--+--+ +--+ +--+ +--+ + +--+ + +",
"| | | | | | | | | | | | | | | | | |",
"+ +--+--+ + + + +--+--+ + + + + + +--+--+--+ +--+--+ + +--+ +--+ + + + +",
"| | | | | | | | | | | | | | | | | | | |",
"+--+ + + +--+--+--+--+ + +--+ + +--+--+ +--+ +--+ + + + + +--+ +--+ +--+ +",
"| | | | | | | | | | | | | | |",
"+ +--+--+--+ + +--+--+--+--+ +--+ + +--+--+ +--+ +--+ +--+--+--+--+ + +--+ +--+",
"| | | | | | | | | | | | | |",
"+--+ + +--+--+--+--+--+ + + + +--+ + +--+ + +--+--+--+--+--+ +--+--+--+ +--+ +",
"| | | | | | | | | | | | |",
"+ +--+ + +--+ + +--+--+ +--+--+ +--+ +--+--+--+ + +--+ +--+--+ +--+ + +--+--+",
"| | | | | | | | | | | | | | | | | |",
"+ + +--+ + + + + +--+--+ + +--+ +--+ + + + +--+ +--+--+ +--+ +--+ + + +",
"| | | | | | | | | | | | | | | | | | | | | |",
"+ +--+ + + + +--+ + +--+--+ + +--+ +--+--+ + +--+ + + +--+--+--+ +--+ + +",
"| | | | | | | | | | | | | | | | | | |",
"+ + + + + +--+--+--+--+ + +--+--+ + + + + +--+--+--+ +--+--+--+ + + +--+ +",
"| | | | | | | | | | | | | | | |",
"+ +--+ +--+--+--+ + + +--+--+--+--+--+ + + +--+ + + + +--+ + +--+--+--+--+ +",
"| | | | | | | | | | | | | |",
"+ + +--+--+--+--+ + + + +--+ +--+ +--+--+ + +--+--+--+--+ +--+--+--+--+--+--+ +",
"| | | | | | | | | | | | | | |",
"+ +--+--+ + + +--+ +--+ + +--+ + + + +--+ +--+--+--+ +--+--+--+--+ +--+--+ +",
"| | | | | | | | | | | | | | |",
"+ +--+ +--+--+ + +--+--+--+--+ +--+--+ +--+ +--+ +--+--+--+ + + + +--+--+ + +",
"| | | | | | | | | | | | | | | |",
"+--+--+ + + +--+ + + +--+--+--+ + +--+ + + +--+--+--+ +--+ + + + + +--+--+",
"| | | | | | | | | | | | | | | | | | |",
"+ + +--+ +--+ +--+ + +--+ +--+ + +--+--+--+--+--+--+--+--+ + +--+ + + + + +",
"| | | | | | | | | | | | | | |",
"+ +--+ +--+ +--+--+--+--+ +--+ + + + +--+--+--+ + + +--+--+--+--+--+ +--+ + +",
"| | | | | | | | | | | | | | | |",
"+ +--+ + +--+--+--+--+ +--+ +--+--+ + + +--+--+ +--+--+ +--+ + + +--+ +--+ +",
"| | | | | | | | | | | | | | | | |",
"+ +--+--+--+--+--+--+--+--+ + +--+ + + + + + +--+ + + + + +--+ + +--+ +--+",
"| | | | | | | | | | | | | | |",
"+ + +--+--+--+--+--+ +--+--+--+--+ +--+ + + +--+--+--+ +--+ +--+ +--+ + +--+ +",
"| | | | | | | | | | | | | | |",
"+ +--+--+--+ + + +--+ +--+--+ +--+ +--+--+ +--+ + +--+ +--+ +--+--+--+ + +--+",
"| | | | | | | | | | | | | | | | |",
"+--+--+ + + +--+--+ +--+ + +--+ + + + + +--+--+--+ +--+ + +--+ + +--+--+ +",
"| | | | | | | | | | | | | | | | |",
"+ +--+--+ +--+ + +--+--+ +--+--+--+ + +--+--+ + + +--+ + +--+ +--+--+ + +--+",
"| | | | | | | | | | | | | | | | | |",
"+ + + + + + + +--+--+--+--+ + +--+ + +--+--+ +--+ +--+ + +--+--+ +--+--+ +",
"| | | | | | | | | | | | | | | | |",
"+ + +--+--+ +--+--+--+ +--+--+--+--+ + +--+ + +--+ +--+ +--+ +--+ +--+--+ + +",
"| | | | | | | | | | | | | | | |",
"+ + +--+--+ +--+--+ + + +--+ +--+--+--+ +--+ +--+--+ +--+ +--+ + +--+ +--+ +",
"| | | | | | EE|",
"+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+",
};
int minsiz = 0x7f7f7f7f;
char rd[2333];
void dfs(int nx, int ny, int lx, int ly, int len)
{
if (nx >= 61 || nx < 0 || ny >= 91 || ny < 0) return;
if (mp[nx][ny] == 'E')
{
if (len <= minsiz)
{
minsiz = len;
cout << len << ": ";
for (int i = 0; i < len; ++i) putchar(rd[i]);
putchar('\n');
}
return;
}
if ((nx - 2 != lx) && mp[nx - 1][ny] == ' ') rd[len] = 'W', dfs(nx - 2, ny, nx, ny, len + 1);
if ((nx + 2 != lx) && mp[nx + 1][ny] == ' ') rd[len] = 'S', dfs(nx + 2, ny, nx, ny, len + 1);
if ((ny - 3 != ly) && mp[nx][ny - 1] == ' ') rd[len] = 'A', dfs(nx, ny - 3, nx, ny, len + 1);
if ((ny + 3 != ly) && mp[nx][ny + 2] == ' ') rd[len] = 'D', dfs(nx, ny + 3, nx, ny, len + 1);
}
int main()
{
dfs(1, 1, -10, -10, 0);
return 0;
}

0x02 关于混淆

对混淆感兴趣的师傅们可以大致看一下。这里先给出本题的源码帮助师傅们理解虚假控制流的效果。

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
#include <stdio.h>
#include <string.h>
char mp[23333] = "+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+| | | | | | |+ + + +--+ + +--+--+ + +--+--+--+--+ +--+--+--+--+ +--+ + +--+ + +--+--+ + +| | | | | | | | | | | | | | | | | |+--+--+--+ +--+--+ + + +--+ +--+ +--+ + +--+ + +--+ + +--+ +--+ +--+ +--+ +| | | | | | | | | | | | | | | | | | |+ + +--+ +--+--+ + +--+ +--+ +--+ +--+ + + + + +--+--+ + + +--+ + +--+ +| | | | | | | | | | | | | | | | | | |+ +--+ +--+--+ + + + +--+ + + +--+--+--+ + + +--+ +--+ +--+--+ +--+ + +--+| | | | | | | | | | | | | | | | | | |+--+ + +--+ +--+ + +--+--+--+ + + + + + +--+--+ +--+ +--+ +--+ + +--+ + +| | | | | | | | | | | | | | | | | |+ +--+--+ + + + +--+--+ + + + + + +--+--+--+ +--+--+ + +--+ +--+ + + + +| | | | | | | | | | | | | | | | | | | |+--+ + + +--+--+--+--+ + +--+ + +--+--+ +--+ +--+ + + + + +--+ +--+ +--+ +| | | | | | | | | | | | | | |+ +--+--+--+ + +--+--+--+--+ +--+ + +--+--+ +--+ +--+ +--+--+--+--+ + +--+ +--+| | | | | | | | | | | | | |+--+ + +--+--+--+--+--+ + + + +--+ + +--+ + +--+--+--+--+--+ +--+--+--+ +--+ +| | | | | | | | | | | | |+ +--+ + +--+ + +--+--+ +--+--+ +--+ +--+--+--+ + +--+ +--+--+ +--+ + +--+--+| | | | | | | | | | | | | | | | | |+ + +--+ + + + + +--+--+ + +--+ +--+ + + + +--+ +--+--+ +--+ +--+ + + +| | | | | | | | | | | | | | | | | | | | | |+ +--+ + + + +--+ + +--+--+ + +--+ +--+--+ + +--+ + + +--+--+--+ +--+ + +| | | | | | | | | | | | | | | | | | |+ + + + + +--+--+--+--+ + +--+--+ + + + + +--+--+--+ +--+--+--+ + + +--+ +| | | | | | | | | | | | | | | |+ +--+ +--+--+--+ + + +--+--+--+--+--+ + + +--+ + + + +--+ + +--+--+--+--+ +| | | | | | | | | | | | | |+ + +--+--+--+--+ + + + +--+ +--+ +--+--+ + +--+--+--+--+ +--+--+--+--+--+--+ +| | | | | | | | | | | | | | |+ +--+--+ + + +--+ +--+ + +--+ + + + +--+ +--+--+--+ +--+--+--+--+ +--+--+ +| | | | | | | | | | | | | | |+ +--+ +--+--+ + +--+--+--+--+ +--+--+ +--+ +--+ +--+--+--+ + + + +--+--+ + +| | | | | | | | | | | | | | | |+--+--+ + + +--+ + + +--+--+--+ + +--+ + + +--+--+--+ +--+ + + + + +--+--+| | | | | | | | | | | | | | | | | | |+ + +--+ +--+ +--+ + +--+ +--+ + +--+--+--+--+--+--+--+--+ + +--+ + + + + +| | | | | | | | | | | | | | |+ +--+ +--+ +--+--+--+--+ +--+ + + + +--+--+--+ + + +--+--+--+--+--+ +--+ + +| | | | | | | | | | | | | | | |+ +--+ + +--+--+--+--+ +--+ +--+--+ + + +--+--+ +--+--+ +--+ + + +--+ +--+ +| | | | | | | | | | | | | | | | |+ +--+--+--+--+--+--+--+--+ + +--+ + + + + + +--+ + + + + +--+ + +--+ +--+| | | | | | | | | | | | | | |+ + +--+--+--+--+--+ +--+--+--+--+ +--+ + + +--+--+--+ +--+ +--+ +--+ + +--+ +| | | | | | | | | | | | | | |+ +--+--+--+ + + +--+ +--+--+ +--+ +--+--+ +--+ + +--+ +--+ +--+--+--+ + +--+| | | | | | | | | | | | | | | | |+--+--+ + + +--+--+ +--+ + +--+ + + + + +--+--+--+ +--+ + +--+ + +--+--+ +| | | | | | | | | | | | | | | | |+ +--+--+ +--+ + +--+--+ +--+--+--+ + +--+--+ + + +--+ + +--+ +--+--+ + +--+| | | | | | | | | | | | | | | | | |+ + + + + + + +--+--+--+--+ + +--+ + +--+--+ +--+ +--+ + +--+--+ +--+--+ +| | | | | | | | | | | | | | | | |+ + +--+--+ +--+--+--+ +--+--+--+--+ + +--+ + +--+ +--+ +--+ +--+ +--+--+ + +| | | | | | | | | | | | | | | |+ + +--+--+ +--+--+ + + +--+ +--+--+--+ +--+ +--+--+ +--+ +--+ + +--+ +--+ +| | | | | | |+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+";
char rd[2333];
int main()
{
printf("Welcome To TSCTF-J 2022!!!\n");
printf("Lets Go Out Of The MAZE!!!\n");
int st = 92;
scanf("%s", rd);
if (strlen(rd) > 196)
{
printf("Wrong Path, Maybe it's not the best solution.");
return 0;
}
int i;
for (i = 0; i < strlen(rd); ++i)
{
switch (rd[i])
{
case 'W':
if (mp[st - 91] != ' ')
{
printf("Wrong Path");
return 0;
}
st -= 182;
break;
case 'S':
if (mp[st + 91] != ' ')
{
printf("Wrong Path");
return 0;
}
st += 182;
break;
case 'A':
if (mp[st - 1] != ' ')
{
printf("Wrong Path");
return 0;
}
st -= 3;
break;
case 'D':
if (mp[st + 2] != ' ')
{
printf("Wrong Path");
return 0;
}
st += 3;
break;
default:
printf("Wrong Format");
return 0;
}
if (st < 0 || st > 5550)
{
printf("Wrong Path");
return 0;
}
}
if (st == 5457)
{
printf("Good Job! The Flag is TSCTF-J{(MD5 32 Upper of Your Input)}");
}
else
{
printf("Wrong Path");
}
return 0;
}

这里给出混淆脚本(-199):

BogusControlFlow.cpp

Utils.cpp

Utils.h

SplitBasicBlock.h

可以考虑用 angr 去混淆,建议的参考学习链接:https://bbs.pediy.com/thread-266005.htm

Thunder_air

解压后打开exe文件发现没法运行,用010editor打开发现有hint:

根据提示,PE头信息有问题,这是一个I386平台的程序,我们需要修改文件的PE头信息,随便搜索一篇介绍PE LOADER的博客(比如出题人的blog),然后找到machine code,发现Intel 386平台对应的机器码是0x4c01,但是这里是0x0200,改掉然后把MZ前面的内容删掉即可。

运行发现是打飞机游戏,但是需要击落1000000架飞机才通关(不要尝试用Cheat Engine或者修改四个.in文档改变飞机大小),用ida打开,定位到关键代码,发现有花指令,patch掉即可,得到C代码

如图,把100000,Sleep,IsDebuggerPresent全给patch掉,然后Apply patches to input file,动调可以得到一串64位字符串。这里由于出题人偷懒且傻逼从网上copy了一个base64的变表,忘记改了,导致被某师傅直接贴到cyberchef里靠着历史记录跟本题的表一模一样给非预期了😅,出题人已🔪

一眼Base64换表,显然sub_470DA4是加密函数,点进去发现第二个花指令,修复以后得到加密函数

注意base64之后进行了一简单异或,解出来是PjU3Pa8EZT1MHnA9xP6SLYQeH0zTrgNAqYz7LucwU3jGrOROqjN1eP6TS0OMRrO=,base64换表解密

得到flagTSCTF-J{3nj0y_P1@Ylng_ThuNd3r_41r_B4tTle_g@m3!}

upx_revenge

0x01 脱壳

查壳的时候会发现是 UPX 壳,但 IDA 中给出的相关信息是 VPX

Info: This file is packed with the VPX executable packer http://upx.sf.net

VPX 3.95 Copyright (C) 1996-2018 the VPX Team. All Rights Reserved.

UPX 工具无法一键脱壳,这时已经可以想到出题人把壳中有关 UPX 的字串全改成了 VPX ,用 010 Editor 全改回去就可以工具脱壳了,也可以考虑手动脱壳,但无法使用 Ollydbg 等工具,可能会比较痛苦。

0x02 关于混淆

混淆为 Rimao 学长加的修改后的控制流平坦化,这里贴出学长对采用的混淆的讲解:https://bbs.pediy.com/thread-274778.htm

(反正我现在还不会去这个混淆)

考虑最原始的手段:动态调试 + 静态分析,还原代码逻辑。

这里放出源码,供各位师傅们复现的时候比对

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
#include <iostream>
#include <cstring>
using namespace std;

void matrix_mul(unsigned long long *A, unsigned long long *B,unsigned long long *C,int N){
//C = A*B
for (short i = 0; i < N; i++) {
for (short j = 0; j < N; j++) {
C[N*i+j] = 0;
for (short k = 0; k < N; k++) {
C[N*i+j] += (A[N*i+k])*(B[N*k+j]);
}
}
}
}

unsigned char dict[256] = { 25, 27, 5, 178, 36, 206, 119, 124, 126, 156, 34, 101, 244, 235, 190, 85, 216, 196, 44, 184, 62, 61, 111, 182, 189, 140, 57, 72, 203, 56, 115, 12, 106, 59, 129, 159, 125, 43, 103, 26, 210, 64, 252, 53, 211, 214, 65, 150, 86, 172, 107, 173, 133, 174, 162, 141, 66, 47, 215, 35, 84, 113, 10, 139, 30, 171, 197, 122, 114, 75, 236, 195, 246, 37, 137, 117, 245, 89, 255, 23, 148, 243, 48, 108, 231, 54, 100, 31, 105, 40, 46, 166, 99, 208, 50, 22, 8, 248, 32, 200, 143, 130, 238, 16, 253, 151, 109, 98, 58, 15, 198, 1, 11, 227, 192, 17, 88, 39, 13, 45, 90, 68, 29, 80, 230, 3, 38, 165, 110, 241, 158, 175, 116, 69, 127, 73, 102, 20, 9, 6, 181, 249, 177, 18, 77, 242, 123, 49, 93, 250, 134, 7, 254, 239, 224, 204, 160, 142, 92, 223, 120, 179, 186, 191, 247, 112, 180, 176, 219, 163, 229, 24, 207, 97, 135, 202, 155, 76, 55, 154, 145, 168, 169, 146, 87, 82, 237, 167, 121, 81, 161, 132, 60, 4, 96, 164, 21, 74, 225, 71, 218, 212, 79, 128, 170, 153, 157, 188, 70, 41, 51, 233, 147, 201, 118, 0, 138, 83, 52, 217, 240, 193, 220, 221, 19, 144, 183, 78, 95, 209, 226, 251, 185, 222, 232, 94, 42, 199, 63, 91, 67, 152, 131, 194, 2, 205, 213, 234, 149, 228, 104, 14, 187, 28, 33, 136 };
unsigned long long A0[16];
unsigned long long B0[16] = { 16,5,9,4,2,11,7,14,3,10,6,15,13,8,12,1 };
unsigned long long D0[16] = { 24,118,2,233,164,0,8,53,116,32,2,185,90,199,111,111 };
unsigned long long T0[16]; // temp
unsigned long long T1[16]; // temp
unsigned long long k = 15431;
unsigned long long vec[] = { 1,-1,0,2,0,0,0,0,0,0,0,0,0,0,0,0 };
unsigned long long enc[] = { 1734349686721832,15757252140869714,1092678154813168,9927501567100490,3808107480864345,671156288906057,5502646392645447,969808735442127,31519839691376038,46407861949122087,50371895260285662,74164462406703435,18361403837770193,28199216860800284,9248795116216354,14204238250162461 };
//TSCTF-J{651f31a7-5c6f-4ee4-a435-accb084dffb7}
int main(int argc, char *argv[])
{
char input[80];
scanf("%s", input);
if (input[0] != 'T' || input[1] != 'S' || input[2] != 'C' || input[3] != 'T' || input[4] != 'F' || input[5] != '-' || input[6] != 'J' || input[7] != '{' || input[16] != '-' || input[21] != '-' || input[26] != '-' || input[31] != '-' || strlen(input) != 45 || input[44] != '}')exit(0);
short j = 0; int tmp = 0;
for(int i=0;i<16;i++){
sscanf(&input[8+2*i+j], "%2x",&tmp);
A0[i] = dict[tmp]^0x35;
if (i == 3 || i == 5 || i == 7 || i == 9)j++;
}

for (int i = 0; i < 4; i++) {
matrix_mul(&B0[4*i], &A0[4*i], &T0[4*i], 2);
matrix_mul(&T0[4*i], &A0[4*i], &T1[4*i], 2);
matrix_mul(&T1[4*i], &D0[4*i], &T0[4*i], 2);
matrix_mul(&T0[4*i], &T0[4*i], &T1[4*i], 2);
for (int j = 0; j < 4; j++) {
T1[4*i+j] -= k*B0[4*i+j];
T1[4*i+j] /= 2;
}
}


for (int i = 0; i < 16; i++) {
if (enc[i] != T1[i])exit(0);
}
printf("Your Input is Correct.\n");
return 0;
}

0x03 分析逻辑

很明显前面是输入并判断flag的格式

input2 和 input 实际是相邻的,v3 为 long 类型,可以看出这里在转换为 long 类型并保存

将一些变量转换为 qword 方便分析。可以看出下图为加密验证

循环开始部分通过动调或其他方式很容易可以看出是 2x2 矩阵的乘法运算,函数的第三个参数为输出的矩阵,且循环每次只输出四个,正好是 2x2 的矩阵乘法。修改常量名称后很容易能得到加密表达式。

程序将输入的 uuid 提取转换为 4x4 的矩阵,假设这个矩阵为 A,加密结果为 E,那么满足以下式子,其中 C、D为常量矩阵,k 为常量。由于全程运算都为正整数,所以除二后为向下取整

由于除二后向下取整,所以需要通过爆破$16 * 4 = 64$次可能,量级非常小。由矩阵平方可以写出四元二次方程组,有四组解,根据题目选择正整数解,爆破时若发现没正整数解,便跳过进行下一轮爆破。

由于是一个数学题,可以考虑使用 sympy 进行求解。

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
from sympy import *

a = Symbol('a');
b = Symbol('b');
c = Symbol('c');
d = Symbol('d')
B0 = [16, 5, 9, 4, 2, 11, 7, 14, 3, 10, 6, 15, 13, 8, 12, 1]
D0 = [24, 118, 2, 233, 164, 0, 8, 53, 116, 32, 2, 185, 90, 199, 111, 111]
K = 15431
my_dict = [25, 27, 5, 178, 36, 206, 119, 124, 126, 156, 34, 101, 244, 235, 190, 85, 216, 196, 44, 184, 62, 61, 111, 182,
189, 140, 57, 72, 203, 56, 115, 12, 106, 59, 129, 159, 125, 43, 103, 26, 210, 64, 252, 53, 211, 214, 65, 150,
86, 172, 107, 173, 133, 174, 162, 141, 66, 47, 215, 35, 84, 113, 10, 139, 30, 171, 197, 122, 114, 75, 236,
195, 246, 37, 137, 117, 245, 89, 255, 23, 148, 243, 48, 108, 231, 54, 100, 31, 105, 40, 46, 166, 99, 208, 50,
22, 8, 248, 32, 200, 143, 130, 238, 16, 253, 151, 109, 98, 58, 15, 198, 1, 11, 227, 192, 17, 88, 39, 13, 45,
90, 68, 29, 80, 230, 3, 38, 165, 110, 241, 158, 175, 116, 69, 127, 73, 102, 20, 9, 6, 181, 249, 177, 18, 77,
242, 123, 49, 93, 250, 134, 7, 254, 239, 224, 204, 160, 142, 92, 223, 120, 179, 186, 191, 247, 112, 180, 176,
219, 163, 229, 24, 207, 97, 135, 202, 155, 76, 55, 154, 145, 168, 169, 146, 87, 82, 237, 167, 121, 81, 161,
132, 60, 4, 96, 164, 21, 74, 225, 71, 218, 212, 79, 128, 170, 153, 157, 188, 70, 41, 51, 233, 147, 201, 118,
0, 138, 83, 52, 217, 240, 193, 220, 221, 19, 144, 183, 78, 95, 209, 226, 251, 185, 222, 232, 94, 42, 199, 63,
91, 67, 152, 131, 194, 2, 205, 213, 234, 149, 228, 104, 14, 187, 28, 33, 136]
flag = "flag{"


def is_positive_integer(num):
if num < 0: return False
s = str(num).split('.')
if len(s) == 1: return True
return float(s[1]) == 0


def solve_square(B):
# A = B*B -> solve A
global a, b, c, d
S = eval("solve([a*a+b*c-%d, a*b+b*d-%d, a*c+c*d-%d, b*c+d*d-%d], [a,b,c,d])" % (B[0], B[1], B[2], B[3]))
for s in S:
s = [float(item) for item in list(s)]
if is_positive_integer(s[0]) and is_positive_integer(s[1]) and is_positive_integer(
s[2]) and is_positive_integer(s[3]):
return s
return None


def solve_inv(B, C):
# A*B = C -> solve A
global a, b, c, d
S = eval("solve([%d*a+%d*b-%d, %d*a+%d*b-%d, %d*c+%d*d-%d, %d*c+%d*d-%d], [a,b,c,d])" % (
B[0], B[2], C[0], B[1], B[3], C[1], B[0], B[2], C[2], B[1], B[3], C[3]))
A = [float(S[item]) for item in [a, b, c, d]]
if not is_positive_integer(A[0]): return None
return [int(item) for item in A]


def solve_inv2(A, C):
# A*B = C -> solve B
global a, b, c, d
S = eval("solve([%d*a+%d*c-%d, %d*b+%d*d-%d, %d*a+%d*c-%d, %d*b+%d*d-%d], [a,b,c,d])" % (
A[0], A[1], C[0], A[0], A[1], C[1], A[2], A[3], C[2], A[2], A[3], C[3]))
A = [float(S[item]) for item in [a, b, c, d]]
if not is_positive_integer(A[0]): return None
return [int(item) for item in A]


def solve_other(B, index, add="0000"):
# (A-D)/2 = B -> solve A
global B0, K
C = [0, 0, 0, 0]
for i in range(4):
C[i] = B[i] * 2 + int(add[i]) + K * B0[4 * index + i]
return C


def solve_once(B, index):
global my_dict, flag
for i in range(16):
print("Trying part %d.%d" % (index + 1, i))
s = solve_other(B, index, add=bin(i)[2:].zfill(4))
s = solve_square(s)
if s == None: continue # skip not integer
s = solve_inv(D0[4 * index:4 * index + 4], s)
if s == None: continue
s = solve_inv2(B0[4 * index:4 * index + 4], s)
if s == None: continue
s = solve_square(s)
if s == None: continue
s = [my_dict.index(item ^ cipher) for item in s]
s = "".join([hex(t)[2:] for t in s])
flag += s;
print(flag)
return


import time

start = time.time()
data = [1734349686721832, 15757252140869714, 1092678154813168, 9927501567100490, 3808107480864345, 671156288906057,
5502646392645447, 969808735442127, 31519839691376038, 46407861949122087, 50371895260285662, 74164462406703435,
18361403837770193, 28199216860800284, 9248795116216354, 14204238250162461]
for i in range(4):
solve_once(data[4 * i:4 * i + 4], i)
print(flag + "}")
print(time.time() - start)

🤖

空白✌赞助的防AK题,干到5点钟给干出来了,放上比较铸币的 opcode 嗯逆做法。

0x01 分析main函数逻辑

首先分析主函数逻辑

1666878585692

结合hint 发现主函数其实就干了下面这件事,那么显然v4就是整个虚拟机的 opcode,所有的操作都是通过对v4进行调度来实现,知道了这一点,先动调把程序未开始执行的v4初始化状态给dump下来,并且根据hint,所有的数据都是 int16 型的,写个脚本转化一下即可

1
2
3
4
5
6
7
8
9
10
while true do
i = mem[IP]
a = mem[i + 0]
b = mem[i + 1]
r = mem[i + 2]
mem[ip] = i + 3
f = nor(mem[a], mem[b])
mem[r] = f
mem[SHIFT_REG] = ((f >> 15) & 1) | ((f & 0x7FFF) << 1)
end

再写脚本实现一下main函数,先测试一下能否正常运行,并判断出 flag 长度为35位,发现程序可以正常输出wrong,说明main函数逻辑是正确的,那么接下来就是要搞明白这个 v4 到底是怎么只通过一些列 NOR 指令判断你输进去的 flag 到底对不对的,于是一个基本思路就有了。

0x02 生成指令

1666879491002

1666879635509

然后空白✌的答复是

1666878927068

可以硬刚,那就试试呗,写程序实现之前提到的思路,先写脚本把main函数的每一轮循环都变成 NOR 指令的格式

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
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
unsigned short opcode[] =
{
300, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8543, 8543, 7, 7, 7, 3, 312, 312, 7, 7, 7, 0, 314, 1, 313, 313, 7, 7, 7, 4, 8540, 8540, 7, 7, 7, 3, 332, 332, 7, 7, 7, 0, 334, 1, 333, 333, 7, 7, 7, 4, 8541, 8541, 7, 7, 7, 3, 352, 352, 7, 7, 7, 0, 354, 1, 353, 353, 7, 7, 7, 4, 8542, 8542, 7, 7, 7, 3, 372, 372, 7, 7, 7, 0, 374, 1, 373, 373, 7, 7, 7, 4, 8544, 8544, 7, 7, 7, 3, 392, 392, 7, 7, 7, 0, 394, 1, 393, 393, 7, 7, 7, 4, 8541, 8541, 7, 7, 7, 3, 412, 412, 7, 7, 7, 0, 414, 1, 413, 413, 7, 7, 7, 4, 8550, 8550, 7, 7, 7, 3, 432, 432, 7, 7, 7, 0, 434, 1, 433, 433, 7, 7, 7, 4, 8555, 8555, 7, 7, 7, 3, 452, 452, 7, 7, 7, 0, 454, 1, 453, 453, 7, 7, 7, 4, 8553, 8553, 7, 7, 7, 3, 472, 472, 7, 7, 7, 0, 474, 1, 473, 473, 7, 7, 7, 4, 8556, 8556, 7, 7, 7, 3, 492, 492, 7, 7, 7, 0, 494, 1, 493, 493, 7, 7, 7, 4, 8557, 8557, 7, 7, 7, 3, 512, 512, 7, 7, 7, 0, 514, 1, 513, 513, 7, 7, 7, 4, 8547, 8547, 7, 7, 7, 3, 532, 532, 7, 7, 7, 0, 534, 1, 533, 533, 7, 7, 7, 4, 8550, 8550, 7, 7, 7, 3, 552, 552, 7, 7, 7, 0, 554, 1, 553, 553, 7, 7, 7, 4, 8558, 8558, 7, 7, 7, 3, 572, 572, 7, 7, 7, 0, 574, 1, 573, 573, 7, 7, 7, 4, 8539, 8539, 7, 7, 7, 3, 592, 592, 7, 7, 7, 0, 594, 1, 593, 593, 7, 7, 7, 4, 8557, 8557, 7, 7, 7, 3, 612, 612, 7, 7, 7, 0, 614, 1, 613, 613, 7, 7, 7, 4, 8538, 8538, 7, 7, 7, 3, 632, 632, 7, 7, 7, 0, 634, 1, 633, 633, 7, 7, 7, 4, 8550, 8550, 7, 7, 7, 3, 652, 652, 7, 7, 7, 0, 654, 1, 653, 653, 7, 7, 7, 4, 8552, 8552, 7, 7, 7, 3, 672, 672, 7, 7, 7, 0, 674, 1, 673, 673, 7, 7, 7, 4, 8540, 8540, 7, 7, 7, 3, 692, 692, 7, 7, 7, 0, 694, 1, 693, 693, 7, 7, 7, 4, 8542, 8542, 7, 7, 7, 3, 712, 712, 7, 7, 7, 0, 714, 1, 713, 713, 7, 7, 7, 4, 8548, 8548, 7, 7, 7, 3, 732, 732, 7, 7, 7, 0, 734, 1, 733, 733, 7, 7, 7, 4, 8549, 8549, 7, 7, 7, 3, 752, 752, 7, 7, 7, 0, 754, 1, 753, 753, 7, 7, 7, 4, 766, 766, 7, 7, 7, 0, 768, 775, 767, 767, 7, 7, 7, 0, 0, 781, 781, 7, 7, 7, 0, 783, 1, 782, 782, 7, 7, 7, 6, 5, 5, 7, 7, 7, 8503, 801, 801, 7, 7, 7, 0, 803, 1, 802, 802, 7, 7, 7, 6, 5, 5, 7, 7, 7, 8504, 821, 821, 7, 7, 7, 0, 823, 1, 822, 822, 7, 7, 7, 6, 5, 5, 7, 7, 7, 8505, 841, 841, 7, 7, 7, 0, 843, 1, 842, 842, 7, 7, 7, 6, 5, 5, 7, 7, 7, 8506, 861, 861, 7, 7, 7, 0, 863, 1, 862, 862, 7, 7, 7, 6, 5, 5, 7, 7, 7, 8507, 881, 881, 7, 7, 7, 0, 883, 1, 882, 882, 7, 7, 7, 6, 5, 5, 7, 7, 7, 8508, 901, 901, 7, 7, 7, 0, 903, 1, 902, 902, 7, 7, 7, 6, 5, 5, 7, 7, 7, 8509, 921, 921, 7, 7, 7, 0, 923, 1, 922, 922, 7, 7, 7, 6, 5, 5, 7, 7, 7, 8510, 941, 941, 7, 7, 7, 0, 943, 1, 942, 942, 7, 7, 7, 6, 5, 5, 7, 7, 7, 8511, 961, 961, 7, 7, 7, 0, 963, 1, 962, 962, 7, 7, 7, 6, 5, 5, 7, 7, 7, 8512, 981, 981, 7, 7, 7, 0, 983, 1, 982, 982, 7, 7, 7, 6, 5, 5, 7, 7, 7, 8513, 1001, 1001, 7, 7, 7, 0, 1003, 1, 1002, 1002, 7, 7, 7, 6, 5, 5, 7, 7, 7, 8514, 1021, 1021, 7, 7, 7, 0, 1023, 1, 1022, 1022, 7, 7, 7, 6, 5, 5, 7, 7, 7, 8515, 1041, 1041, 7, 7, 7, 0, 1043, 1, 1042, 1042, 7, 7, 7, 6, 5, 5, 7, 7, 7, 8516, 1061, 1061, 7, 7, 7, 0, 1063, 1, 1062, 1062, 7, 7, 7, 6, 5, 5, 7, 7, 7, 8517, 1081, 1081, 7, 7, 7, 0, 1083, 1, 1082, 1082, 7, 7, 7, 6, 5, 5, 7, 7, 7, 8518, 1101, 1101, 7, 7, 7, 0, 1103, 1, 1102, 1102, 7, 7, 7, 6, 5, 5, 7, 7, 7, 8519, 1121, 1121, 7, 7, 7, 0, 1123, 1, 1122, 1122, 7, 7, 7, 6, 5, 5, 7, 7, 7, 8520, 1141, 1141, 7, 7, 7, 0, 1143, 1, 1142, 1142, 7, 7, 7, 6, 5, 5, 7, 7, 7, 8521, 1161, 1161, 7, 7, 7, 0, 1163, 1, 1162, 1162, 7, 7, 7, 6, 5, 5, 7, 7, 7, 8522, 1181, 1181, 7, 7, 7, 0, 1183, 1, 1182, 1182, 7, 7, 7, 6, 5, 5, 7, 7, 7, 8523, 1201, 1201, 7, 7, 7, 0, 1203, 1, 1202, 1202, 7, 7, 7, 6, 5, 5, 7, 7, 7, 8524, 1221, 1221, 7, 7, 7, 0, 1223, 1, 1222, 1222, 7, 7, 7, 6, 5, 5, 7, 7, 7, 8525, 1241, 1241, 7, 7, 7, 0, 1243, 1, 1242, 1242, 7, 7, 7, 6, 5, 5, 7, 7, 7, 8526, 1261, 1261, 7, 7, 7, 0, 1263, 1, 1262, 1262, 7, 7, 7, 6, 5, 5, 7, 7, 7, 8527, 1281, 1281, 7, 7, 7, 0, 1283, 1, 1282, 1282, 7, 7, 7, 6, 5, 5, 7, 7, 7, 8528, 1301, 1301, 7, 7, 7, 0, 1303, 1, 1302, 1302, 7, 7, 7, 6, 5, 5, 7, 7, 7, 8529, 1321, 1321, 7, 7, 7, 0, 1323, 1, 1322, 1322, 7, 7, 7, 6, 5, 5, 7, 7, 7, 8530, 1341, 1341, 7, 7, 7, 0, 1343, 1, 1342, 1342, 7, 7, 7, 6, 5, 5, 7, 7, 7, 8531, 1361, 1361, 7, 7, 7, 0, 1363, 1, 1362, 1362, 7, 7, 7, 6, 5, 5, 7, 7, 7, 8532, 1381, 1381, 7, 7, 7, 0, 1383, 1, 1382, 1382, 7, 7, 7, 6, 5, 5, 7, 7, 7, 8533, 1401, 1401, 7, 7, 7, 0, 1403, 1, 1402, 1402, 7, 7, 7, 6, 5, 5, 7, 7, 7, 8534, 1421, 1421, 7, 7, 7, 0, 1423, 1, 1422, 1422, 7, 7, 7, 6, 5, 5, 7, 7, 7, 8535, 1441, 1441, 7, 7, 7, 0, 1443, 1, 1442, 1442, 7, 7, 7, 6, 5, 5, 7, 7, 7, 8536, 1461, 1461, 7, 7, 7, 0, 1463, 1, 1462, 1462, 7, 7, 7, 6, 5, 5, 7, 7, 7, 8537, 8503, 8503, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 1667, 1667, 7, 7, 7, 0, 1670, 0, 0, 8239, 8239, 1668, 8492, 8492, 1669, 1682, 1682, 7, 7, 7, 0, 1685, 0, 0, 8239, 8239, 1683, 1669, 1669, 1684, 1683, 1684, 7, 7, 7, 7, 7, 7, 1669, 1706, 1706, 7, 7, 7, 0, 1709, 0, 0, 8492, 8492, 1707, 1668, 1668, 1708, 1707, 1708, 7, 7, 7, 7, 7, 7, 1668, 1668, 1669, 7, 7, 7, 8239, 8239, 774, 7, 7, 7, 774, 8504, 8504, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 1928, 1928, 7, 7, 7, 0, 1931, 0, 0, 8239, 8239, 1929, 8491, 8491, 1930, 1943, 1943, 7, 7, 7, 0, 1946, 0, 0, 8239, 8239, 1944, 1930, 1930, 1945, 1944, 1945, 7, 7, 7, 7, 7, 7, 1930, 1967, 1967, 7, 7, 7, 0, 1970, 0, 0, 8491, 8491, 1968, 1929, 1929, 1969, 1968, 1969, 7, 7, 7, 7, 7, 7, 1929, 1929, 1930, 7, 7, 7, 8239, 8239, 774, 7, 7, 7, 774, 8505, 8505, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 2189, 2189, 7, 7, 7, 0, 2192, 0, 0, 8239, 8239, 2190, 8483, 8483, 2191, 2204, 2204, 7, 7, 7, 0, 2207, 0, 0, 8239, 8239, 2205, 2191, 2191, 2206, 2205, 2206, 7, 7, 7, 7, 7, 7, 2191, 2228, 2228, 7, 7, 7, 0, 2231, 0, 0, 8483, 8483, 2229, 2190, 2190, 2230, 2229, 2230, 7, 7, 7, 7, 7, 7, 2190, 2190, 2191, 7, 7, 7, 8239, 8239, 774, 7, 7, 7, 774, 8506, 8506, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 2450, 2450, 7, 7, 7, 0, 2453, 0, 0, 8239, 8239, 2451, 8492, 8492, 2452, 2465, 2465, 7, 7, 7, 0, 2468, 0, 0, 8239, 8239, 2466, 2452, 2452, 2467, 2466, 2467, 7, 7, 7, 7, 7, 7, 2452, 2489, 2489, 7, 7, 7, 0, 2492, 0, 0, 8492, 8492, 2490, 2451, 2451, 2491, 2490, 2491, 7, 7, 7, 7, 7, 7, 2451, 2451, 2452, 7, 7, 7, 8239, 8239, 774, 7, 7, 7, 774, 8507, 8507, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 2711, 2711, 7, 7, 7, 0, 2714, 0, 0, 8239, 8239, 2712, 8485, 8485, 2713, 2726, 2726, 7, 7, 7, 0, 2729, 0, 0, 8239, 8239, 2727, 2713, 2713, 2728, 2727, 2728, 7, 7, 7, 7, 7, 7, 2713, 2750, 2750, 7, 7, 7, 0, 2753, 0, 0, 8485, 8485, 2751, 2712, 2712, 2752, 2751, 2752, 7, 7, 7, 7, 7, 7, 2712, 2712, 2713, 7, 7, 7, 8239, 8239, 774, 7, 7, 7, 774, 8508, 8508, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 2972, 2972, 7, 7, 7, 0, 2975, 0, 0, 8239, 8239, 2973, 8475, 8475, 2974, 2987, 2987, 7, 7, 7, 0, 2990, 0, 0, 8239, 8239, 2988, 2974, 2974, 2989, 2988, 2989, 7, 7, 7, 7, 7, 7, 2974, 3011, 3011, 7, 7, 7, 0, 3014, 0, 0, 8475, 8475, 3012, 2973, 2973, 3013, 3012, 3013, 7, 7, 7, 7, 7, 7, 2973, 2973, 2974, 7, 7, 7, 8239, 8239, 774, 7, 7, 7, 774, 8509, 8509, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 3233, 3233, 7, 7, 7, 0, 3236, 0, 0, 8239, 8239, 3234, 8487, 8487, 3235, 3248, 3248, 7, 7, 7, 0, 3251, 0, 0, 8239, 8239, 3249, 3235, 3235, 3250, 3249, 3250, 7, 7, 7, 7, 7, 7, 3235, 3272, 3272, 7, 7, 7, 0, 3275, 0, 0, 8487, 8487, 3273, 3234, 3234, 3274, 3273, 3274, 7, 7, 7, 7, 7, 7, 3234, 3234, 3235, 7, 7, 7, 8239, 8239, 774, 7, 7, 7, 774, 8510, 8510, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 3494, 3494, 7, 7, 7, 0, 3497, 0, 0, 8239, 8239, 3495, 8501, 8501, 3496, 3509, 3509, 7, 7, 7, 0, 3512, 0, 0, 8239, 8239, 3510, 3496, 3496, 3511, 3510, 3511, 7, 7, 7, 7, 7, 7, 3496, 3533, 3533, 7, 7, 7, 0, 3536, 0, 0, 8501, 8501, 3534, 3495, 3495, 3535, 3534, 3535, 7, 7, 7, 7, 7, 7, 3495, 3495, 3496, 7, 7, 7, 8239, 8239, 774, 7, 7, 7, 774, 8511, 8511, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 3755, 3755, 7, 7, 7, 0, 3758, 0, 0, 8239, 8239, 3756, 8491, 8491, 3757, 3770, 3770, 7, 7, 7, 0, 3773, 0, 0, 8239, 8239, 3771, 3757, 3757, 3772, 3771, 3772, 7, 7, 7, 7, 7, 7, 3757, 3794, 3794, 7, 7, 7, 0, 3797, 0, 0, 8491, 8491, 3795, 3756, 3756, 3796, 3795, 3796, 7, 7, 7, 7, 7, 7, 3756, 3756, 3757, 7, 7, 7, 8239, 8239, 774, 7, 7, 7, 774, 3830, 3830, 7, 7, 7, 0, 3833, 0, 0, 8512, 8512, 3831, 8472, 8472, 3832, 3845, 3845, 7, 7, 7, 0, 3848, 0, 0, 8512, 8512, 3846, 3832, 3832, 3847, 3846, 3847, 7, 7, 7, 7, 7, 7, 3832, 3869, 3869, 7, 7, 7, 0, 3872, 0, 0, 8472, 8472, 3870, 3831, 3831, 3871, 3870, 3871, 7, 7, 7, 7, 7, 7, 3831, 3831, 3832, 7, 7, 7, 8239, 3899, 3899, 7, 7, 7, 0, 3902, 0, 0, 8239, 8239, 3900, 8499, 8499, 3901, 3914, 3914, 7, 7, 7, 0, 3917, 0, 0, 8239, 8239, 3915, 3901, 3901, 3916, 3915, 3916, 7, 7, 7, 7, 7, 7, 3901, 3938, 3938, 7, 7, 7, 0, 3941, 0, 0, 8499, 8499, 3939, 3900, 3900, 3940, 3939, 3940, 7, 7, 7, 7, 7, 7, 3900, 3900, 3901, 7, 7, 7, 8239, 8239, 774, 7, 7, 7, 774, 3974, 3974, 7, 7, 7, 0, 3977, 0, 0, 8513, 8513, 3975, 8470, 8470, 3976, 3989, 3989, 7, 7, 7, 0, 3992, 0, 0, 8513, 8513, 3990, 3976, 3976, 3991, 3990, 3991, 7, 7, 7, 7, 7, 7, 3976, 4013, 4013, 7, 7, 7, 0, 4016, 0, 0, 8470, 8470, 4014, 3975, 3975, 4015, 4014, 4015, 7, 7, 7, 7, 7, 7, 3975, 3975, 3976, 7, 7, 7, 8239, 4043, 4043, 7, 7, 7, 0, 4046, 0, 0, 8239, 8239, 4044, 8479, 8479, 4045, 4058, 4058, 7, 7, 7, 0, 4061, 0, 0, 8239, 8239, 4059, 4045, 4045, 4060, 4059, 4060, 7, 7, 7, 7, 7, 7, 4045, 4082, 4082, 7, 7, 7, 0, 4085, 0, 0, 8479, 8479, 4083, 4044, 4044, 4084, 4083, 4084, 7, 7, 7, 7, 7, 7, 4044, 4044, 4045, 7, 7, 7, 8239, 8239, 774, 7, 7, 7, 774, 8514, 8514, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 4304, 4304, 7, 7, 7, 0, 4307, 0, 0, 8239, 8239, 4305, 8498, 8498, 4306, 4319, 4319, 7, 7, 7, 0, 4322, 0, 0, 8239, 8239, 4320, 4306, 4306, 4321, 4320, 4321, 7, 7, 7, 7, 7, 7, 4306, 4343, 4343, 7, 7, 7, 0, 4346, 0, 0, 8498, 8498, 4344, 4305, 4305, 4345, 4344, 4345, 7, 7, 7, 7, 7, 7, 4305, 4305, 4306, 7, 7, 7, 8239, 8239, 774, 7, 7, 7, 774, 8515, 8515, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 4565, 4565, 7, 7, 7, 0, 4568, 0, 0, 8239, 8239, 4566, 8477, 8477, 4567, 4580, 4580, 7, 7, 7, 0, 4583, 0, 0, 8239, 8239, 4581, 4567, 4567, 4582, 4581, 4582, 7, 7, 7, 7, 7, 7, 4567, 4604, 4604, 7, 7, 7, 0, 4607, 0, 0, 8477, 8477, 4605, 4566, 4566, 4606, 4605, 4606, 7, 7, 7, 7, 7, 7, 4566, 4566, 4567, 7, 7, 7, 8239, 8239, 774, 7, 7, 7, 774, 8516, 8516, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 4826, 4826, 7, 7, 7, 0, 4829, 0, 0, 8239, 8239, 4827, 8484, 8484, 4828, 4841, 4841, 7, 7, 7, 0, 4844, 0, 0, 8239, 8239, 4842, 4828, 4828, 4843, 4842, 4843, 7, 7, 7, 7, 7, 7, 4828, 4865, 4865, 7, 7, 7, 0, 4868, 0, 0, 8484, 8484, 4866, 4827, 4827, 4867, 4866, 4867, 7, 7, 7, 7, 7, 7, 4827, 4827, 4828, 7, 7, 7, 8239, 8239, 774, 7, 7, 7, 774, 8517, 8517, 7, 7, 7, 8517, 1, 1, 7, 7, 7, 8239, 4913, 4913, 7, 7, 7, 0, 4916, 0, 0, 8239, 8239, 4914, 8502, 8502, 4915, 4928, 4928, 7, 7, 7, 0, 4931, 0, 0, 8239, 8239, 4929, 4915, 4915, 4930, 4929, 4930, 7, 7, 7, 7, 7, 7, 4915, 4952, 4952, 7, 7, 7, 0, 4955, 0, 0, 8502, 8502, 4953, 4914, 4914, 4954, 4953, 4954, 7, 7, 7, 7, 7, 7, 4914, 4914, 4915, 7, 7, 7, 8239, 8239, 774, 7, 7, 7, 774, 8518, 8518, 7, 7, 7, 8518, 1, 1, 7, 7, 7, 8239, 5000, 5000, 7, 7, 7, 0, 5003, 0, 0, 8239, 8239, 5001, 8486, 8486, 5002, 5015, 5015, 7, 7, 7, 0, 5018, 0, 0, 8239, 8239, 5016, 5002, 5002, 5017, 5016, 5017, 7, 7, 7, 7, 7, 7, 5002, 5039, 5039, 7, 7, 7, 0, 5042, 0, 0, 8486, 8486, 5040, 5001, 5001, 5041, 5040, 5041, 7, 7, 7, 7, 7, 7, 5001, 5001, 5002, 7, 7, 7, 8239, 8239, 774, 7, 7, 7, 774, 8519, 8519, 7, 7, 7, 8519, 1, 1, 7, 7, 7, 8239, 5087, 5087, 7, 7, 7, 0, 5090, 0, 0, 8239, 8239, 5088, 8482, 8482, 5089, 5102, 5102, 7, 7, 7, 0, 5105, 0, 0, 8239, 8239, 5103, 5089, 5089, 5104, 5103, 5104, 7, 7, 7, 7, 7, 7, 5089, 5126, 5126, 7, 7, 7, 0, 5129, 0, 0, 8482, 8482, 5127, 5088, 5088, 5128, 5127, 5128, 7, 7, 7, 7, 7, 7, 5088, 5088, 5089, 7, 7, 7, 8239, 8239, 774, 7, 7, 7, 774, 8520, 8520, 7, 7, 7, 8520, 1, 1, 7, 7, 7, 8239, 5174, 5174, 7, 7, 7, 0, 5177, 0, 0, 8239, 8239, 5175, 8468, 8468, 5176, 5189, 5189, 7, 7, 7, 0, 5192, 0, 0, 8239, 8239, 5190, 5176, 5176, 5191, 5190, 5191, 7, 7, 7, 7, 7, 7, 5176, 5213, 5213, 7, 7, 7, 0, 5216, 0, 0, 8468, 8468, 5214, 5175, 5175, 5215, 5214, 5215, 7, 7, 7, 7, 7, 7, 5175, 5175, 5176, 7, 7, 7, 8239, 8239, 774, 7, 7, 7, 774, 5249, 5249, 7, 7, 7, 0, 5252, 0, 0, 8521, 8521, 5250, 8493, 8493, 5251, 5264, 5264, 7, 7, 7, 0, 5267, 0, 0, 8521, 8521, 5265, 5251, 5251, 5266, 5265, 5266, 7, 7, 7, 7, 7, 7, 5251, 5288, 5288, 7, 7, 7, 0, 5291, 0, 0, 8493, 8493, 5289, 5250, 5250, 5290, 5289, 5290, 7, 7, 7, 7, 7, 7, 5250, 5250, 5251, 7, 7, 7, 8239, 5318, 5318, 7, 7, 7, 0, 5321, 0, 0, 8239, 8239, 5319, 8469, 8469, 5320, 5333, 5333, 7, 7, 7, 0, 5336, 0, 0, 8239, 8239, 5334, 5320, 5320, 5335, 5334, 5335, 7, 7, 7, 7, 7, 7, 5320, 5357, 5357, 7, 7, 7, 0, 5360, 0, 0, 8469, 8469, 5358, 5319, 5319, 5359, 5358, 5359, 7, 7, 7, 7, 7, 7, 5319, 5319, 5320, 7, 7, 7, 8239, 8239, 774, 7, 7, 7, 774, 8522, 8522, 7, 7, 7, 8522, 1, 1, 7, 7, 7, 8239, 5405, 5405, 7, 7, 7, 0, 5408, 0, 0, 8239, 8239, 5406, 8490, 8490, 5407, 5420, 5420, 7, 7, 7, 0, 5423, 0, 0, 8239, 8239, 5421, 5407, 5407, 5422, 5421, 5422, 7, 7, 7, 7, 7, 7, 5407, 5444, 5444, 7, 7, 7, 0, 5447, 0, 0, 8490, 8490, 5445, 5406, 5406, 5446, 5445, 5446, 7, 7, 7, 7, 7, 7, 5406, 5406, 5407, 7, 7, 7, 8239, 8239, 774, 7, 7, 7, 774, 8523, 8523, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 5666, 5666, 7, 7, 7, 0, 5669, 0, 0, 8239, 8239, 5667, 8494, 8494, 5668, 5681, 5681, 7, 7, 7, 0, 5684, 0, 0, 8239, 8239, 5682, 5668, 5668, 5683, 5682, 5683, 7, 7, 7, 7, 7, 7, 5668, 5705, 5705, 7, 7, 7, 0, 5708, 0, 0, 8494, 8494, 5706, 5667, 5667, 5707, 5706, 5707, 7, 7, 7, 7, 7, 7, 5667, 5667, 5668, 7, 7, 7, 8239, 8239, 774, 7, 7, 7, 774, 5741, 5741, 7, 7, 7, 0, 5744, 0, 0, 8524, 8524, 5742, 8472, 8472, 5743, 5756, 5756, 7, 7, 7, 0, 5759, 0, 0, 8524, 8524, 5757, 5743, 5743, 5758, 5757, 5758, 7, 7, 7, 7, 7, 7, 5743, 5780, 5780, 7, 7, 7, 0, 5783, 0, 0, 8472, 8472, 5781, 5742, 5742, 5782, 5781, 5782, 7, 7, 7, 7, 7, 7, 5742, 5742, 5743, 7, 7, 7, 8239, 5810, 5810, 7, 7, 7, 0, 5813, 0, 0, 8239, 8239, 5811, 8497, 8497, 5812, 5825, 5825, 7, 7, 7, 0, 5828, 0, 0, 8239, 8239, 5826, 5812, 5812, 5827, 5826, 5827, 7, 7, 7, 7, 7, 7, 5812, 5849, 5849, 7, 7, 7, 0, 5852, 0, 0, 8497, 8497, 5850, 5811, 5811, 5851, 5850, 5851, 7, 7, 7, 7, 7, 7, 5811, 5811, 5812, 7, 7, 7, 8239, 8239, 774, 7, 7, 7, 774, 8525, 8525, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 6071, 6071, 7, 7, 7, 0, 6074, 0, 0, 8239, 8239, 6072, 8489, 8489, 6073, 6086, 6086, 7, 7, 7, 0, 6089, 0, 0, 8239, 8239, 6087, 6073, 6073, 6088, 6087, 6088, 7, 7, 7, 7, 7, 7, 6073, 6110, 6110, 7, 7, 7, 0, 6113, 0, 0, 8489, 8489, 6111, 6072, 6072, 6112, 6111, 6112, 7, 7, 7, 7, 7, 7, 6072, 6072, 6073, 7, 7, 7, 8239, 8239, 774, 7, 7, 7, 774, 6146, 6146, 7, 7, 7, 0, 6149, 0, 0, 8526, 8526, 6147, 8478, 8478, 6148, 6161, 6161, 7, 7, 7, 0, 6164, 0, 0, 8526, 8526, 6162, 6148, 6148, 6163, 6162, 6163, 7, 7, 7, 7, 7, 7, 6148, 6185, 6185, 7, 7, 7, 0, 6188, 0, 0, 8478, 8478, 6186, 6147, 6147, 6187, 6186, 6187, 7, 7, 7, 7, 7, 7, 6147, 6147, 6148, 7, 7, 7, 8239, 6215, 6215, 7, 7, 7, 0, 6218, 0, 0, 8239, 8239, 6216, 8492, 8492, 6217, 6230, 6230, 7, 7, 7, 0, 6233, 0, 0, 8239, 8239, 6231, 6217, 6217, 6232, 6231, 6232, 7, 7, 7, 7, 7, 7, 6217, 6254, 6254, 7, 7, 7, 0, 6257, 0, 0, 8492, 8492, 6255, 6216, 6216, 6256, 6255, 6256, 7, 7, 7, 7, 7, 7, 6216, 6216, 6217, 7, 7, 7, 8239, 8239, 774, 7, 7, 7, 774, 8527, 8527, 7, 7, 7, 8527, 1, 1, 7, 7, 7, 8239, 6302, 6302, 7, 7, 7, 0, 6305, 0, 0, 8239, 8239, 6303, 8496, 8496, 6304, 6317, 6317, 7, 7, 7, 0, 6320, 0, 0, 8239, 8239, 6318, 6304, 6304, 6319, 6318, 6319, 7, 7, 7, 7, 7, 7, 6304, 6341, 6341, 7, 7, 7, 0, 6344, 0, 0, 8496, 8496, 6342, 6303, 6303, 6343, 6342, 6343, 7, 7, 7, 7, 7, 7, 6303, 6303, 6304, 7, 7, 7, 8239, 8239, 774, 7, 7, 7, 774, 8528, 8528, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 6563, 6563, 7, 7, 7, 0, 6566, 0, 0, 8239, 8239, 6564, 8494, 8494, 6565, 6578, 6578, 7, 7, 7, 0, 6581, 0, 0, 8239, 8239, 6579, 6565, 6565, 6580, 6579, 6580, 7, 7, 7, 7, 7, 7, 6565, 6602, 6602, 7, 7, 7, 0, 6605, 0, 0, 8494, 8494, 6603, 6564, 6564, 6604, 6603, 6604, 7, 7, 7, 7, 7, 7, 6564, 6564, 6565, 7, 7, 7, 8239, 8239, 774, 7, 7, 7, 774, 8529, 8529, 7, 7, 7, 8529, 1, 1, 7, 7, 7, 8239, 6650, 6650, 7, 7, 7, 0, 6653, 0, 0, 8239, 8239, 6651, 8476, 8476, 6652, 6665, 6665, 7, 7, 7, 0, 6668, 0, 0, 8239, 8239, 6666, 6652, 6652, 6667, 6666, 6667, 7, 7, 7, 7, 7, 7, 6652, 6689, 6689, 7, 7, 7, 0, 6692, 0, 0, 8476, 8476, 6690, 6651, 6651, 6691, 6690, 6691, 7, 7, 7, 7, 7, 7, 6651, 6651, 6652, 7, 7, 7, 8239, 8239, 774, 7, 7, 7, 774, 6725, 6725, 7, 7, 7, 0, 6728, 0, 0, 8530, 8530, 6726, 8473, 8473, 6727, 6740, 6740, 7, 7, 7, 0, 6743, 0, 0, 8530, 8530, 6741, 6727, 6727, 6742, 6741, 6742, 7, 7, 7, 7, 7, 7, 6727, 6764, 6764, 7, 7, 7, 0, 6767, 0, 0, 8473, 8473, 6765, 6726, 6726, 6766, 6765, 6766, 7, 7, 7, 7, 7, 7, 6726, 6726, 6727, 7, 7, 7, 8239, 6794, 6794, 7, 7, 7, 0, 6797, 0, 0, 8239, 8239, 6795, 8488, 8488, 6796, 6809, 6809, 7, 7, 7, 0, 6812, 0, 0, 8239, 8239, 6810, 6796, 6796, 6811, 6810, 6811, 7, 7, 7, 7, 7, 7, 6796, 6833, 6833, 7, 7, 7, 0, 6836, 0, 0, 8488, 8488, 6834, 6795, 6795, 6835, 6834, 6835, 7, 7, 7, 7, 7, 7, 6795, 6795, 6796, 7, 7, 7, 8239, 8239, 774, 7, 7, 7, 774, 6869, 6869, 7, 7, 7, 0, 6872, 0, 0, 8531, 8531, 6870, 8495, 8495, 6871, 6884, 6884, 7, 7, 7, 0, 6887, 0, 0, 8531, 8531, 6885, 6871, 6871, 6886, 6885, 6886, 7, 7, 7, 7, 7, 7, 6871, 6908, 6908, 7, 7, 7, 0, 6911, 0, 0, 8495, 8495, 6909, 6870, 6870, 6910, 6909, 6910, 7, 7, 7, 7, 7, 7, 6870, 6870, 6871, 7, 7, 7, 8239, 6938, 6938, 7, 7, 7, 0, 6941, 0, 0, 8239, 8239, 6939, 8482, 8482, 6940, 6953, 6953, 7, 7, 7, 0, 6956, 0, 0, 8239, 8239, 6954, 6940, 6940, 6955, 6954, 6955, 7, 7, 7, 7, 7, 7, 6940, 6977, 6977, 7, 7, 7, 0, 6980, 0, 0, 8482, 8482, 6978, 6939, 6939, 6979, 6978, 6979, 7, 7, 7, 7, 7, 7, 6939, 6939, 6940, 7, 7, 7, 8239, 8239, 774, 7, 7, 7, 774, 7013, 7013, 7, 7, 7, 0, 7016, 0, 0, 8532, 8532, 7014, 8474, 8474, 7015, 7028, 7028, 7, 7, 7, 0, 7031, 0, 0, 8532, 8532, 7029, 7015, 7015, 7030, 7029, 7030, 7, 7, 7, 7, 7, 7, 7015, 7052, 7052, 7, 7, 7, 0, 7055, 0, 0, 8474, 8474, 7053, 7014, 7014, 7054, 7053, 7054, 7, 7, 7, 7, 7, 7, 7014, 7014, 7015, 7, 7, 7, 8239, 7082, 7082, 7, 7, 7, 0, 7085, 0, 0, 8239, 8239, 7083, 8480, 8480, 7084, 7097, 7097, 7, 7, 7, 0, 7100, 0, 0, 8239, 8239, 7098, 7084, 7084, 7099, 7098, 7099, 7, 7, 7, 7, 7, 7, 7084, 7121, 7121, 7, 7, 7, 0, 7124, 0, 0, 8480, 8480, 7122, 7083, 7083, 7123, 7122, 7123, 7, 7, 7, 7, 7, 7, 7083, 7083, 7084, 7, 7, 7, 8239, 8239, 774, 7, 7, 7, 774, 8533, 8533, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 8239, 8239, 7, 7, 7, 8239, 1, 1, 7, 7, 7, 8239, 7343, 7343, 7, 7, 7, 0, 7346, 0, 0, 8239, 8239, 7344, 8494, 8494, 7345, 7358, 7358, 7, 7, 7, 0, 7361, 0, 0, 8239, 8239, 7359, 7345, 7345, 7360, 7359, 7360, 7, 7, 7, 7, 7, 7, 7345, 7382, 7382, 7, 7, 7, 0, 7385, 0, 0, 8494, 8494, 7383, 7344, 7344, 7384, 7383, 7384, 7, 7, 7, 7, 7, 7, 7344, 7344, 7345, 7, 7, 7, 8239, 8239, 774, 7, 7, 7, 774, 7418, 7418, 7, 7, 7, 0, 7421, 0, 0, 8534, 8534, 7419, 8487, 8487, 7420, 7433, 7433, 7, 7, 7, 0, 7436, 0, 0, 8534, 8534, 7434, 7420, 7420, 7435, 7434, 7435, 7, 7, 7, 7, 7, 7, 7420, 7457, 7457, 7, 7, 7, 0, 7460, 0, 0, 8487, 8487, 7458, 7419, 7419, 7459, 7458, 7459, 7, 7, 7, 7, 7, 7, 7419, 7419, 7420, 7, 7, 7, 8239, 7487, 7487, 7, 7, 7, 0, 7490, 0, 0, 8239, 8239, 7488, 8471, 8471, 7489, 7502, 7502, 7, 7, 7, 0, 7505, 0, 0, 8239, 8239, 7503, 7489, 7489, 7504, 7503, 7504, 7, 7, 7, 7, 7, 7, 7489, 7526, 7526, 7, 7, 7, 0, 7529, 0, 0, 8471, 8471, 7527, 7488, 7488, 7528, 7527, 7528, 7, 7, 7, 7, 7, 7, 7488, 7488, 7489, 7, 7, 7, 8239, 8239, 774, 7, 7, 7, 774, 8535, 8535, 7, 7, 7, 8535, 1, 1, 7, 7, 7, 8239, 7574, 7574, 7, 7, 7, 0, 7577, 0, 0, 8239, 8239, 7575, 8482, 8482, 7576, 7589, 7589, 7, 7, 7, 0, 7592, 0, 0, 8239, 8239, 7590, 7576, 7576, 7591, 7590, 7591, 7, 7, 7, 7, 7, 7, 7576, 7613, 7613, 7, 7, 7, 0, 7616, 0, 0, 8482, 8482, 7614, 7575, 7575, 7615, 7614, 7615, 7, 7, 7, 7, 7, 7, 7575, 7575, 7576, 7, 7, 7, 8239, 8239, 774, 7, 7, 7, 774, 7649, 7649, 7, 7, 7, 0, 7652, 0, 0, 8536, 8536, 7650, 8474, 8474, 7651, 7664, 7664, 7, 7, 7, 0, 7667, 0, 0, 8536, 8536, 7665, 7651, 7651, 7666, 7665, 7666, 7, 7, 7, 7, 7, 7, 7651, 7688, 7688, 7, 7, 7, 0, 7691, 0, 0, 8474, 8474, 7689, 7650, 7650, 7690, 7689, 7690, 7, 7, 7, 7, 7, 7, 7650, 7650, 7651, 7, 7, 7, 8239, 7718, 7718, 7, 7, 7, 0, 7721, 0, 0, 8239, 8239, 7719, 8481, 8481, 7720, 7733, 7733, 7, 7, 7, 0, 7736, 0, 0, 8239, 8239, 7734, 7720, 7720, 7735, 7734, 7735, 7, 7, 7, 7, 7, 7, 7720, 7757, 7757, 7, 7, 7, 0, 7760, 0, 0, 8481, 8481, 7758, 7719, 7719, 7759, 7758, 7759, 7, 7, 7, 7, 7, 7, 7719, 7719, 7720, 7, 7, 7, 8239, 8239, 774, 7, 7, 7, 774, 8537, 8537, 7, 7, 7, 8537, 1, 1, 7, 7, 7, 8239, 7805, 7805, 7, 7, 7, 0, 7808, 0, 0, 8239, 8239, 7806, 8500, 8500, 7807, 7820, 7820, 7, 7, 7, 0, 7823, 0, 0, 8239, 8239, 7821, 7807, 7807, 7822, 7821, 7822, 7, 7, 7, 7, 7, 7, 7807, 7844, 7844, 7, 7, 7, 0, 7847, 0, 0, 8500, 8500, 7845, 7806, 7806, 7846, 7845, 7846, 7, 7, 7, 7, 7, 7, 7806, 7806, 7807, 7, 7, 7, 8239, 8239, 774, 7, 7, 7, 774, 7880, 7880, 7, 7, 7, 0, 7882, 0, 7881, 7881, 7, 7, 7, 8, 8, 774, 7, 7, 7, 8, 8, 8, 7, 7, 7, 8, 1, 1, 7, 7, 7, 8, 8, 774, 7, 7, 7, 8, 8, 8, 7, 7, 7, 8, 1, 1, 7, 7, 7, 8, 8, 774, 7, 7, 7, 8, 8, 8, 7, 7, 7, 8, 1, 1, 7, 7, 7, 8, 8, 774, 7, 7, 7, 8, 8, 8, 7, 7, 7, 8, 1, 1, 7, 7, 7, 8, 8, 774, 7, 7, 7, 8, 8, 8, 7, 7, 7, 8, 1, 1, 7, 7, 7, 8, 8, 774, 7, 7, 7, 8, 8, 8, 7, 7, 7, 8, 1, 1, 7, 7, 7, 8, 8, 774, 7, 7, 7, 8, 8, 8, 7, 7, 7, 8, 1, 1, 7, 7, 7, 8, 8, 774, 7, 7, 7, 8, 8, 8, 7, 7, 7, 8, 1, 1, 7, 7, 7, 8, 8, 774, 7, 7, 7, 8, 8, 8, 7, 7, 7, 8, 1, 1, 7, 7, 7, 8, 8, 774, 7, 7, 7, 8, 8, 8, 7, 7, 7, 8, 1, 1, 7, 7, 7, 8, 8, 774, 7, 7, 7, 8, 8, 8, 7, 7, 7, 8, 1, 1, 7, 7, 7, 8, 8, 774, 7, 7, 7, 8, 8, 8, 7, 7, 7, 8, 1, 1, 7, 7, 7, 8, 8, 774, 7, 7, 7, 8, 8, 8, 7, 7, 7, 8, 1, 1, 7, 7, 7, 8, 8, 774, 7, 7, 7, 8, 8, 8, 7, 7, 7, 8, 1, 1, 7, 7, 7, 8, 8, 774, 7, 7, 7, 8, 8, 8, 7, 7, 7, 8, 1, 1, 7, 7, 7, 8, 8, 774, 7, 7, 7, 8, 8170, 8170, 7, 7, 7, 0, 8173, 8354, 8239, 8179, 8179, 7, 7, 7, 0, 8182, 0, 0, 8188, 8188, 7, 7, 7, 0, 8191, 0, 0, 8172, 8172, 8189, 8, 8, 8190, 8189, 8190, 7, 7, 7, 7, 7, 7, 8180, 8, 8, 8181, 8215, 8215, 7, 7, 7, 0, 8218, 0, 0, 8171, 8171, 8216, 8181, 8181, 8217, 8216, 8217, 7, 7, 7, 7, 7, 7, 8181, 8180, 8181, 7, 7, 7, 0, 0, 8545, 8545, 7, 7, 7, 3, 8252, 8252, 7, 7, 7, 0, 8254, 1, 8253, 8253, 7, 7, 7, 4, 8538, 8538, 7, 7, 7, 3, 8272, 8272, 7, 7, 7, 0, 8274, 1, 8273, 8273, 7, 7, 7, 4, 8539, 8539, 7, 7, 7, 3, 8292, 8292, 7, 7, 7, 0, 8294, 1, 8293, 8293, 7, 7, 7, 4, 8553, 8553, 7, 7, 7, 3, 8312, 8312, 7, 7, 7, 0, 8314, 1, 8313, 8313, 7, 7, 7, 4, 8548, 8548, 7, 7, 7, 3, 8332, 8332, 7, 7, 7, 0, 8334, 1, 8333, 8333, 7, 7, 7, 4, 8346, 8346, 7, 7, 7, 0, 8348, -1, 8347, 8347, 7, 7, 7, 0, 8554, 8554, 7, 7, 7, 3, 8366, 8366, 7, 7, 7, 0, 8368, 1, 8367, 8367, 7, 7, 7, 4, 8555, 8555, 7, 7, 7, 3, 8386, 8386, 7, 7, 7, 0, 8388, 1, 8387, 8387, 7, 7, 7, 4, 8548, 8548, 7, 7, 7, 3, 8406, 8406, 7, 7, 7, 0, 8408, 1, 8407, 8407, 7, 7, 7, 4, 8559, 8559, 7, 7, 7, 3, 8426, 8426, 7, 7, 7, 0, 8428, 1, 8427, 8427, 7, 7, 7, 4, 8547, 8547, 7, 7, 7, 3, 8446, 8446, 7, 7, 7, 0, 8448, 1, 8447, 8447, 7, 7, 7, 4, 8460, 8460, 7, 7, 7, 0, 8462, -1, 8461, 8461, 7, 7, 7, 0, 132, 5, 9, 75, 77, 13, 15, -32746, 150, -32744, 27, 92, 120, 93, 96, -32735, 34, 35, 228, 37, 99, 39, 168, -32727, 42, 106, -32721, 47, 178, 125, 56, 57, 250, -32707, 190, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 114, 111, 108, 101, 97, 80, 115, 87, 100, 116, 103, 58, 32, 67, 102, 110, 82, 105, 112, 117, 121, 104
};

char flag[] = "TSCTF-J{12345678901234567890123456}";
int cnt;
int main()
{
unsigned int v8, v9, v10, v11;
unsigned short v12;
do
{
if(opcode[4] == 1)
{
opcode[4] = 0;
printf("print opcode[3](%c) ", opcode[3]); // 标记printf操作
}
else if(opcode[6] == 1)
{
opcode[6] = 0;
opcode[5]= flag[cnt++];
printf("scanf opcode[5](%c) ", opcode[5]); // 标记scanf操作
}
v8 = opcode[0]; cout << "IP=" << v8 <<" "; //输出IP
v9 = opcode[v8 + 1];
v10 = opcode[v8];
v11 = opcode[v8 + 2];
opcode[0] = v8 + 3;
v12 = ~ (opcode[v10] | opcode[v9]);
opcode[v11] = v12;
opcode[1] = ((v12 << 1) | (v12 >> 15)) & 0xffff;
printf("opcode[%d](%d) = NOR(opcode[%d](%d), opcode[%d](%d)) opcode[1] = %d\n\n", v11, opcode[v11], v10, opcode[v10], v9, opcode[v9], opcode[1]); // 输出NOR指令格式
}while(opcode[0] != 0xFFFF);
}

0x03 开始硬刚

当然,在此之前还需要根据 hint 中的内容熟悉一下各种指令用 NOR 指令是怎么实现的

1
2
3
macro NOT a, r
NOR a, a, r
endm
1
2
3
4
5
6
7
macro AND a, b, r
local t1, t2
NOT a, t1
NOT b, t2
OR t1, t2, t1
NOT t1, r
endm
1
2
3
4
5
macro OR a, b, r
local t
NOR a, b, t
NOT t, r
endm
1
2
3
4
5
6
7
8
macro XOR a, b, r
local t1, t2
NOT b, t1
AND a, t1, t1
NOT a, t2
AND t2, b, t2
OR t1, t2, r
endm
1
2
3
macro MOV from, to
OR from, from, to
endm
1
2
3
4
5
mem[IP] = OR(mem[from], mem[from])
// 另一种写法
macro JMP to_addr
OR to_addr, to_addr, IP
endm
1
2
3
4
5
6
7
8
9
mem[IP] = OR(AND(to_addr, condition), AND(mem[IP], NOT(condition)))
// 另一种写法
macro BRANCH true_addr, false_addr, condition
local t1, t2
AND true_addr, condition, t1
NOT condition, t2
AND false_addr, t2, t2
OR t1, t2, IP
endm

然后开始慢慢逆向路。。。

首先我们找到我们留下的 scanf 标识,发现就是我们构造的输入TSCTF-J。。。并且敏锐的发现 TS 的ASCII码分别是83, 84 那么很显然在接收到我们输入的flag之后,经过两次NOR操作,我们的输入被存放在opcode[8503], opcode[8504], opcode[8505]...处。

1666880281355

接着往下翻,在所有的scanf操作结束以后,加密操作就开始进行了

1666880684714

发现存入opcode[8537]后,开始对opcode[8503]进行加密操作,经过翻译发现加密操作共分为三种类型

第一种

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
opcode[7](65451) = NOR(opcode[8503](84), opcode[8503](84))  opcode[1] = 65367

opcode[8239](84) = NOR(opcode[7](65451), opcode[7](65451)) opcode[1] = 168 //0

opcode[7](65451) = NOR(opcode[8239](84), opcode[8239](84)) opcode[1] = 65367

opcode[8239](84) = NOR(opcode[7](65451), opcode[7](65451)) opcode[1] = 168

opcode[7](65367) = NOR(opcode[1](65199), opcode[1](65199)) opcode[1] = 65199

opcode[8239](168) = NOR(opcode[7](65367), opcode[7](65367)) opcode[1] = 336 //1

opcode[7](65367) = NOR(opcode[8239](168), opcode[8239](168)) opcode[1] = 65199

opcode[8239](168) = NOR(opcode[7](65367), opcode[7](65367)) opcode[1] = 336

opcode[7](65199) = NOR(opcode[1](64863), opcode[1](64863)) opcode[1] = 64863

opcode[8239](336) = NOR(opcode[7](65199), opcode[7](65199)) opcode[1] = 672 //2

opcode[7](65199) = NOR(opcode[8239](336), opcode[8239](336)) opcode[1] = 64863

opcode[8239](336) = NOR(opcode[7](65199), opcode[7](65199)) opcode[1] = 672

opcode[7](64863) = NOR(opcode[1](64191), opcode[1](64191)) opcode[1] = 64191

opcode[8239](672) = NOR(opcode[7](64863), opcode[7](64863)) opcode[1] = 1344 //3

opcode[7](64863) = NOR(opcode[8239](672), opcode[8239](672)) opcode[1] = 64191

opcode[8239](672) = NOR(opcode[7](64863), opcode[7](64863)) opcode[1] = 1344

opcode[7](64191) = NOR(opcode[1](62847), opcode[1](62847)) opcode[1] = 62847

opcode[8239](1344) = NOR(opcode[7](64191), opcode[7](64191)) opcode[1] = 2688 //4

opcode[7](64191) = NOR(opcode[8239](1344), opcode[8239](1344)) opcode[1] = 62847

opcode[8239](1344) = NOR(opcode[7](64191), opcode[7](64191)) opcode[1] = 2688

opcode[7](62847) = NOR(opcode[1](60159), opcode[1](60159)) opcode[1] = 60159

opcode[8239](2688) = NOR(opcode[7](62847), opcode[7](62847)) opcode[1] = 5376 //5

opcode[7](62847) = NOR(opcode[8239](2688), opcode[8239](2688)) opcode[1] = 60159

opcode[8239](2688) = NOR(opcode[7](62847), opcode[7](62847)) opcode[1] = 5376

opcode[7](60159) = NOR(opcode[1](54783), opcode[1](54783)) opcode[1] = 54783

opcode[8239](5376) = NOR(opcode[7](60159), opcode[7](60159)) opcode[1] = 10752 //6

opcode[7](60159) = NOR(opcode[8239](5376), opcode[8239](5376)) opcode[1] = 54783

opcode[8239](5376) = NOR(opcode[7](60159), opcode[7](60159)) opcode[1] = 10752

opcode[7](54783) = NOR(opcode[1](44031), opcode[1](44031)) opcode[1] = 44031

opcode[8239](10752) = NOR(opcode[7](54783), opcode[7](54783)) opcode[1] = 21504 //7

opcode[7](54783) = NOR(opcode[8239](10752), opcode[8239](10752)) opcode[1] = 44031

opcode[8239](10752) = NOR(opcode[7](54783), opcode[7](54783)) opcode[1] = 21504

opcode[7](44031) = NOR(opcode[1](22527), opcode[1](22527)) opcode[1] = 22527

opcode[8239](21504) = NOR(opcode[7](44031), opcode[7](44031)) opcode[1] = 43008 //8

opcode[7](44031) = NOR(opcode[8239](21504), opcode[8239](21504)) opcode[1] = 22527

opcode[8239](21504) = NOR(opcode[7](44031), opcode[7](44031)) opcode[1] = 43008

opcode[7](22527) = NOR(opcode[1](45054), opcode[1](45054)) opcode[1] = 45054

opcode[8239](43008) = NOR(opcode[7](22527), opcode[7](22527)) opcode[1] = 20481 //9

opcode[7](22527) = NOR(opcode[8239](43008), opcode[8239](43008)) opcode[1] = 45054

opcode[8239](43008) = NOR(opcode[7](22527), opcode[7](22527)) opcode[1] = 20481

opcode[7](45054) = NOR(opcode[1](24573), opcode[1](24573)) opcode[1] = 24573

opcode[8239](20481) = NOR(opcode[7](45054), opcode[7](45054)) opcode[1] = 40962 //10

opcode[7](45054) = NOR(opcode[8239](20481), opcode[8239](20481)) opcode[1] = 24573

opcode[8239](20481) = NOR(opcode[7](45054), opcode[7](45054)) opcode[1] = 40962

opcode[7](24573) = NOR(opcode[1](49146), opcode[1](49146)) opcode[1] = 49146

opcode[8239](40962) = NOR(opcode[7](24573), opcode[7](24573)) opcode[1] = 16389 //11

opcode[7](24573) = NOR(opcode[8239](40962), opcode[8239](40962)) opcode[1] = 49146

opcode[8239](40962) = NOR(opcode[7](24573), opcode[7](24573)) opcode[1] = 16389

opcode[7](49146) = NOR(opcode[1](32757), opcode[1](32757)) opcode[1] = 32757

opcode[8239](16389) = NOR(opcode[7](49146), opcode[7](49146)) opcode[1] = 32778 //12

opcode[7](49146) = NOR(opcode[8239](16389), opcode[8239](16389)) opcode[1] = 32757

opcode[8239](16389) = NOR(opcode[7](49146), opcode[7](49146)) opcode[1] = 32778

opcode[7](32757) = NOR(opcode[1](65514), opcode[1](65514)) opcode[1] = 65514

opcode[8239](32778) = NOR(opcode[7](32757), opcode[7](32757)) opcode[1] = 21 //13

opcode[7](32757) = NOR(opcode[8239](32778), opcode[8239](32778)) opcode[1] = 65514

opcode[8239](32778) = NOR(opcode[7](32757), opcode[7](32757)) opcode[1] = 21

opcode[7](65514) = NOR(opcode[1](65493), opcode[1](65493)) opcode[1] = 65493

opcode[8239](21) = NOR(opcode[7](65514), opcode[7](65514)) opcode[1] = 42 //14

opcode[7](65514) = NOR(opcode[8239](21), opcode[8239](21)) opcode[1] = 65493

opcode[8239](21) = NOR(opcode[7](65514), opcode[7](65514)) opcode[1] = 42

opcode[7](65493) = NOR(opcode[1](65451), opcode[1](65451)) opcode[1] = 65451

opcode[8239](42) = NOR(opcode[7](65493), opcode[7](65493)) opcode[1] = 84 //15

opcode[7](63865) = NOR(opcode[1667](1670), opcode[1667](1670)) opcode[1] = 62195

opcode[0](1670) = NOR(opcode[7](63865), opcode[7](63865)) opcode[1] = 3340 // opcode[0] = opcode[1667]

opcode[1668](65493) = NOR(opcode[8239](42), opcode[8239](42)) opcode[1] = 65451 // opcode[1668] = NOT(opcode[8239])

opcode[1669](65493) = NOR(opcode[8492](42), opcode[8492](42)) opcode[1] = 65451 // opcode[1669] = NOT(opcode[8492])

opcode[7](63850) = NOR(opcode[1682](1685), opcode[1682](1685)) opcode[1] = 62165

opcode[0](1685) = NOR(opcode[7](63850), opcode[7](63850)) opcode[1] = 3370 //opcode[0] = opcode[1682]

opcode[1683](65493) = NOR(opcode[8239](42), opcode[8239](42)) opcode[1] = 65451

opcode[1684](42) = NOR(opcode[1669](65493), opcode[1669](65493)) opcode[1] = 84

opcode[7](0) = NOR(opcode[1683](65493), opcode[1684](42)) opcode[1] = 0

opcode[7](65535) = NOR(opcode[7](65535), opcode[7](65535)) opcode[1] = 65535

opcode[1669](0) = NOR(opcode[7](65535), opcode[7](65535)) opcode[1] = 0 // opcode[1669] = AND(opcode[8239], NOT(opcode[8492])) = 0

opcode[7](63826) = NOR(opcode[1706](1709), opcode[1706](1709)) opcode[1] = 62117

opcode[0](1709) = NOR(opcode[7](63826), opcode[7](63826)) opcode[1] = 3418 //opcode[1709] = 0

opcode[1707](65493) = NOR(opcode[8492](42), opcode[8492](42)) opcode[1] = 65451 // opcode[1707] = NOT(opcode[8492])

opcode[1708](42) = NOR(opcode[1668](65493), opcode[1668](65493)) opcode[1] = 84 // opcode[1708] = NOT(opcode[1668])

opcode[7](0) = NOR(opcode[1707](65493), opcode[1708](42)) opcode[1] = 0

opcode[7](65535) = NOR(opcode[7](65535), opcode[7](65535)) opcode[1] = 65535

opcode[1668](0) = NOR(opcode[7](65535), opcode[7](65535)) opcode[1] = 0 // opcode[1668] = AND(NOT(opcode[8492], opcode[8239]) = 0

opcode[7](65535) = NOR(opcode[1668](0), opcode[1669](0)) opcode[1] = 65535

opcode[8239](0) = NOR(opcode[7](65535), opcode[7](65535)) opcode[1] = 0 //opcode[8239] = OR(opcode[1668], opcode[1669])

opcode[7](65535) = NOR(opcode[8239](0), opcode[774](0)) opcode[1] = 65535

opcode[774](0) = NOR(opcode[7](65535), opcode[7](65535)) opcode[1] = 0 //opcode[774] = OR(opcode[774], opcode[8239]

发现是把单个字节拿出来,存进opcode[8329]中,对其 ASCII 值进行 15 次循环左移操作,再和opcode[8942]进行比较

据此写出第一个解密算法

1
2
3
4
5
6
7
8
9
for(int i = 0; i < 14; i++)
{
int x = 15;
while(x--)
{
enc[i] = ((enc[i] >> 1)|(enc[i] << 15)) & 0xffff;
}
printf("%c ", enc[i]);
}

结合之前的分析,发现再每一次加密结束以后,会进行一次 Branch和一次JMP,其实可以不用管,我们只需要大胆猜测哪些是加密算法部分,然后利用这些重合的分支和跳转指令来区分每一次加密操作即可。

此时已是半夜两点半,做到此处的我以为所有的加密算法都是这样写的,还一度十分兴奋

1666881304120

第二种

按照第一种加密逻辑找了9个以后,我发现从第10位开始加密算法变了,tnnd

1666881390659

好死,只能按照之前的方法一步步翻译然后接着分析其加密方式,通过变化测试flag(这里说起来简单。。。)我发现opcode[8470], opcode[8479]是关键数据,因为不随测试flag而改变,opcode[8513]为输入,opcode[8239]更像是中间结果。

1666881604086

通过分析,我发现这一步的加密其实就是opcode[8513] ^ opcode[8470] == opcode[8479],直接找到这几个数据然后异或回去即可。

第三种

正当我以为即将大功告成时,接下来一位的加密算法又不一样了,经过反复观察,发现后面的几位用的是第一种加密,捏麻麻的😅,这玩意还是几种加密方法混着用是吧。

然后在opcode[8517]中,又出现了一种新加密方式

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
opcode[7](65480) = NOR(opcode[8517](55), opcode[8517](55))  opcode[1] = 65425

opcode[8517](55) = NOR(opcode[7](65480), opcode[7](65480)) opcode[1] = 110

opcode[7](65425) = NOR(opcode[1](65315), opcode[1](65315)) opcode[1] = 65315

opcode[8239](110) = NOR(opcode[7](65425), opcode[7](65425)) opcode[1] = 220

opcode[7](60619) = NOR(opcode[4913](4916), opcode[4913](4916)) opcode[1] = 55703

opcode[0](4916) = NOR(opcode[7](60619), opcode[7](60619)) opcode[1] = 9832

opcode[4914](65425) = NOR(opcode[8239](110), opcode[8239](110)) opcode[1] = 65315

opcode[4915](65345) = NOR(opcode[8502](190), opcode[8502](190)) opcode[1] = 65155

opcode[7](60604) = NOR(opcode[4928](4931), opcode[4928](4931)) opcode[1] = 55673

opcode[0](4931) = NOR(opcode[7](60604), opcode[7](60604)) opcode[1] = 9862

opcode[4929](65425) = NOR(opcode[8239](110), opcode[8239](110)) opcode[1] = 65315

opcode[4930](190) = NOR(opcode[4915](65345), opcode[4915](65345)) opcode[1] = 380

opcode[7](64) = NOR(opcode[4929](65425), opcode[4930](190)) opcode[1] = 128

opcode[7](65471) = NOR(opcode[7](65471), opcode[7](65471)) opcode[1] = 65407

opcode[4915](64) = NOR(opcode[7](65471), opcode[7](65471)) opcode[1] = 128

opcode[7](60580) = NOR(opcode[4952](4955), opcode[4952](4955)) opcode[1] = 55625

opcode[0](4955) = NOR(opcode[7](60580), opcode[7](60580)) opcode[1] = 9910

opcode[4953](65345) = NOR(opcode[8502](190), opcode[8502](190)) opcode[1] = 65155

opcode[4954](110) = NOR(opcode[4914](65425), opcode[4914](65425)) opcode[1] = 220

opcode[7](144) = NOR(opcode[4953](65345), opcode[4954](110)) opcode[1] = 288

opcode[7](65391) = NOR(opcode[7](65391), opcode[7](65391)) opcode[1] = 65247

opcode[4914](144) = NOR(opcode[7](65391), opcode[7](65391)) opcode[1] = 288

opcode[7](65327) = NOR(opcode[4914](144), opcode[4915](64)) opcode[1] = 65119

opcode[8239](208) = NOR(opcode[7](65327), opcode[7](65327)) opcode[1] = 416

opcode[7](65280) = NOR(opcode[8239](208), opcode[774](127)) opcode[1] = 65025

opcode[774](255) = NOR(opcode[7](65280), opcode[7](65280)) opcode[1] = 510

好在这里的加密算法还是很简单

1666882242995

一眼秒出opcode[8514] * 2 == opcode[8239],多次测试证实了猜想。

0x04 脚本解密

于是开始一个一个ctrl+F找每一位的加密方式,并且把特征数据dump出来,最终写出exp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>
#include <cstdio>
using namespace std;
unsigned short enc[] = {42, 32809, 32801, 42, 35, 32790, 37, 32829, 32809, 56, 32792, 34, 39, 32815};
int main()
{
for(int i = 0; i < 14; i++)
{
int x = 15;
while(x--)
{
enc[i] = ((enc[i] >> 1)|(enc[i] << 15)) & 0xffff;
}
printf("%c ", enc[i]);
}cout << endl;
printf("%c %c %c %c %c %c %c %c %c %c", (77 ^ 57), (9 ^ 92), (106 ^ 5), (77 ^ 125), (27 ^ 42), (13 ^ 99), (47 ^ 96), (15 ^ 120), (37 ^ 75), (15 ^ 93));cout << endl;
printf("%c %c %c %c %c %c %c %c %c %c %c", 190/2, 228/2, 96/2, 132/2, 168/2, 190/2, 178/2, 190/2, 150/2, 96/2, 250/2);
}

运行以后在拼接起来(这里要记录每一个字符对应的加密操作,分个类)

1666885399216

得到flagTSCTF-J{StUp1D_r0BoT_0N1Y_KnOw_n0R}