September 18, 2022

2022复现

记录一些2022年乱七八糟的比赛的WP和复现。

第五空间

wb

这其实是个密码题,比赛的时候我给dbt👴在这题打下手,就顺便写一下逆向的部分,方便密码👴们复现这道题。

输出:

1
2
3
4
5
This is an highly obfuscated whitebox ECDSA implementation (on an certain standard elliptic curve)!
E.g. the sig of a message with empty hash is
0xBBDFAC1809250A2BB9415225F7C548CF8C03A5E100F95D52A4AA27F42A2F0FBE, 0x615ED230E3DCEF9712DC86AFE1C33F818EF1BA79212DA3E6D522D41D4C5D6C45
the flag is the ascii decoding of the private key in big endian
Hint: No need to do (much) reverse engineering!

main函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
__int64 __fastcall main(int a1, char **a2, char **a3)
{
char v4[64]; // [rsp+0h] [rbp-70h] BYREF
__int64 v5[5]; // [rsp+40h] [rbp-30h] BYREF
int j; // [rsp+68h] [rbp-8h]
int i; // [rsp+6Ch] [rbp-4h]

v5[0] = 0LL;
v5[1] = 0LL;
v5[2] = 0LL;
v5[3] = 0LL;
puts("This is an highly obfuscated whitebox ECDSA implementation (on an certain standard elliptic curve)!");
sub_404565(v4, v5);
printf("E.g. the sig of a message with empty hash is\n0x");
for ( i = 0; i <= 31; ++i )
printf("%02X", (unsigned __int8)v4[i]);
printf(", 0x");
for ( j = 32; j <= 63; ++j )
printf("%02X", (unsigned __int8)v4[j]);
puts("\nthe flag is the ascii decoding of the private key in big endian");
puts("Hint: No need to do (much) reverse engineering!");
return 0LL;
}

v5赋0,sub_404565向v4里写了一堆东西然后打印出来,v4不会影响结果,修改v5的值会得到不同的结果。

至于怎么修改v5?直接丢给队里的逆向手吧hhhhhhh

sub_404565里做了严重的混淆,无法逆向,只有两个函数能看。这两个函数分别在混淆的最初和最后调用,相关内容我已经写在注释里。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
__int64 __fastcall sub_409980(__int64 a1)
{
char v2[8]; // [rsp+18h] [rbp-38h] BYREF
char v3[16]; // [rsp+20h] [rbp-30h] BYREF
char v4[16]; // [rsp+30h] [rbp-20h] BYREF
char v5[16]; // [rsp+40h] [rbp-10h] BYREF

__gmpz_init(v5);
__gmpz_import(v5, 32LL, 1LL, 1LL, 0LL, 0LL, a1);// v5=0
__gmpz_init_set_str(v4, off_410E28, 16LL); // v4=8b98a63042f8d2ee616e680ab504de9b2e8a8effb4b413f85be9ba360b58e795
__gmpz_init_set_str(v3, "ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551", 16LL);
__gmpz_mul(v5, v5, v4); // v5*=v4
__gmpz_mod(v5, v5, v3); // v5%=v3
return __gmpz_export(a1, v2, 1LL, 1LL, 0LL, 0LL, v5);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
__int64 __fastcall sub_409A5F(__int64 a1)
{
char v2[8]; // [rsp+18h] [rbp-38h] BYREF
char v3[16]; // [rsp+20h] [rbp-30h] BYREF
char v4[16]; // [rsp+30h] [rbp-20h] BYREF
char v5[16]; // [rsp+40h] [rbp-10h] BYREF

__gmpz_init(v5);
__gmpz_import(v5, 32LL, 1LL, 1LL, 0LL, 0LL, a1 + 32);
__gmpz_init_set_str(v4, off_410E30, 16LL); // v4=8f6f7a2e53c0377e9afb357a510371ea7811df0ac47fb92b92f6baca90ebc282
__gmpz_init_set_str(v3, "ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551", 16LL);
__gmpz_mul(v5, v5, v4);
__gmpz_mod(v5, v5, v3);
return __gmpz_export(a1 + 32, v2, 1LL, 1LL, 0LL, 0LL, v5);
}

dbt让我修改v5的值,运行程序得到以下数据:

1
2
3
4
v5 = 1
//output:0xBBDFAC1809250A2BB9415225F7C548CF8C03A5E100F95D52A4AA27F42A2F0FBE, 0x49225E3C59E87FA62AEB73FD50239A6E03278B96A11319D54624AF8714F2C989
v5 = 2
//output:0xBBDFAC1809250A2BB9415225F7C548CF8C03A5E100F95D52A4AA27F42A2F0FBE, 0x30E5EA47CFF40FB542FA614ABE83F55A775D5CB420F88FC3B7268AF0DD8826CD

最终脚本(来自dbt👴):

1
2
3
4
5
6
7
8
9
10
11
12
13
n =0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551
k = 0x8b98a63042f8d2ee616e680ab504de9b2e8a8effb4b413f85be9ba360b58e795
k_inv = 0x8f6f7a2e53c0377e9afb357a510371ea7811df0ac47fb92b92f6baca90ebc282
assert k * k_inv % n == 1

r,s = 0xBBDFAC1809250A2BB9415225F7C548CF8C03A5E100F95D52A4AA27F42A2F0FBE, 0x615ED230E3DCEF9712DC86AFE1C33F818EF1BA79212DA3E6D522D41D4C5D6C45
r1,s1 = 0xBBDFAC1809250A2BB9415225F7C548CF8C03A5E100F95D52A4AA27F42A2F0FBE, 0x49225E3C59E87FA62AEB73FD50239A6E03278B96A11319D54624AF8714F2C989
r2,s2 = 0xBBDFAC1809250A2BB9415225F7C548CF8C03A5E100F95D52A4AA27F42A2F0FBE, 0x30E5EA47CFF40FB542FA614ABE83F55A775D5CB420F88FC3B7268AF0DD8826CD
assert ((s1*0-s*1)%n == (s2*1-s1*2) %n)

from Crypto.Util.number import *

print(long_to_bytes((s1*0-s*1)%n * inverse(r*(s-s1),n) % n))

re2

mips,ghidra可冲

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
undefined8 move(void)

{
int check;
int input_idx;
char input [528];
undefined *local_18;
char this_c;

local_18 = &_mips_gp0_value;
input_idx = 0;
input[0] = '\0';
input[1] = 0;
memset(input + 2,0,0x1fe);
printf("input: ");
__isoc99_scanf(&DAT_120001878,input);
while( true ) {
do {
check = 0;
find();
this_c = input[input_idx];
if (this_c == 'w') {
check = Up();
}
else if (this_c < 'x') {
if (this_c == 's') {
check = Down();
}
else if (this_c < 't') {
if (this_c == 'd') {
check = Right();
}
else if (this_c < 'e') {
if (this_c == '\x1b') {
return 0xffffffffffffffff;
}
if (this_c == 'a') {
check = Left();
}
}
}
}
input_idx = input_idx + 1;
} while (check != 1);
if (level == 2) break;
level = level + 1;
}
puts("flag is ctf{md5(your input)}");
return 1;
}

数据里找地图,注意是word类型的

1
map = [1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 3, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 3, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0]

打印出来迷宫手动走即可。
泪目,这么简单的签到题真的不多了

Universal

这题就是纯调试。。。没任何技巧。。。对着trace边看边调试,抽了3天的空终于调出来了,这对我这个调试菜鸡来说还是太艰难了😭😭😭
感觉这种东西还是要多练啊,做熟练了,比赛遇到的时候就不会紧张了
但是这个题莫名其妙的……好像没人写这个题的wp……(还是自己硬着头皮嗯啃汇编了…… 但还是想吐槽汇编真难看
现在面对着trace出来1w+行我终于也能说

区区1w行((( 这都小场面

泪目

ctrl s找data段,往下翻找到密文unk_415100,找交叉引用,反编译到sub_402747,主要的加密逻辑:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
if ( sub_40AE50() == 32 )
{
v7 = 0;
sub_40553C(v6, &v14);
sub_40553C(v8, &v14);
sub_40553C(v9, &v14);
sub_40553C(v10, &v14);
v11 = sub_405432();
do
{
v12 = v7++;
*((_BYTE *)v15 + (v12 & 0x1F)) = v11 ^ ~(*((_BYTE *)v15 + (v12 & 0x1F)) ^ *((_BYTE *)v15 + (v7 & 0x1F)));
v11 = sub_405432() ^ 0xA5;
}
while ( v7 != 64 );
if ( !(unsigned int)sub_40A530(v13, 0x20ui64) )
sub_405595();
}

sub_40553C加密了4次,然后用sub_405432加密,最后sub_40A530和密文对比。
可以知道flag长度是32,调试选项Paramenters加上一个长度为32的字符串就可以正常运行。此后下断点去trace,看trace去分析。

trace看逻辑,调试看内存。还原出来的逻辑如下:

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

input = [0x33323130, 0x37363534, 0x31303938, 0x35343332,0x39383736, 0x33323130, 0x37363534, 0x31303938]
xor0 = [0xDEADBEEF, 0x9E3779B9, 0xC6EF3720, 0xBEEFDEED, 0xDEADBEEF, 0x9E3779B9, 0xC6EF3720, 0xBEEFDEED, 0x33323130, 0x37363534, 0x31303938, 0x35343332,0x39383736, 0x33323130, 0x37363534, 0x31303938]
xor1 = [3, 0xF, 0xE, 0xA, 4, 7, 0, 9, 1, 0xD, 6, 2, 5, 0xC, 0xB, 8]
xor2 = [3, 0xA, 5, 8, 4, 0xB, 0xD, 0xC, 7, 6, 0, 1, 2, 9, 0xE, 0xF]
xor3 = [1, 0, 9, 0xB, 0xF, 5, 0xC, 4, 0xE, 0xD, 0xA, 8, 2, 6, 3, 7]
xor4 = [0xB, 3, 0xE, 5, 6, 9, 1, 7, 0, 0xD, 0xC, 4, 8, 2, 0xA, 0xF]
xor5 = [0xD, 8, 9, 5, 1, 4, 2, 0, 6, 0xA, 7, 0xB, 0xC, 3, 0xE, 0xF]
xor6 = [0xF, 0xC, 0xA, 6, 0, 9, 5, 0xE, 2, 0xB, 4, 7, 8, 1, 0xD, 3]
xor7 = [0xD, 2, 9, 0, 0xF, 3, 0xA, 0xB, 4, 5, 6, 0xE, 7, 0xC, 1, 8]
xor8 = [4, 0xE, 0, 0xF, 9, 3, 2, 0xD, 5, 1, 0xC, 8, 7, 0xA, 0xB, 6]
idx = [0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7, 7, 6, 5, 4, 3, 2, 1, 0]

def encode1(i0,i1):
tmp = input[i0] ^ xor0[0] ^ input[i1]
xor0_idx = 30
for i in range(31):
key = (xor1[(tmp>>0x1c)&0xf]<<28)|(xor2[(tmp>>0x18)&0xf]<<24)|(xor3[(tmp>>0x14)&0xf]<<20)|(xor4[(tmp>>0x10)&0xf]<<16)|(xor5[(tmp>>0xc)&0xf]<<12)|(xor6[(tmp>>0x8)&0xf]<<8)|(xor7[(tmp>>0x4)&0xf]<<4)|(xor8[(tmp)&0xf])
input[i1] = input[i0]
tmp = key ^ xor0[idx[xor0_idx]] ^ input[i1]
input[i0] = key
xor0_idx -= 1
key = (xor1[(tmp>>0x1c)&0xf]<<28)|(xor2[(tmp>>0x18)&0xf]<<24)|(xor3[(tmp>>0x14)&0xf]<<20)|(xor4[(tmp>>0x10)&0xf]<<16)|(xor5[(tmp>>0xc)&0xf]<<12)|(xor6[(tmp>>0x8)&0xf]<<8)|(xor7[(tmp>>0x4)&0xf]<<4)|(xor8[(tmp)&0xf])
input[i1] = key

encode1(0,3)
encode1(1,2)
encode1(4,6)
encode1(5,7)

input_byte = []
for k in input:
for i in pack('<I',k):
input_byte.append(i)

what = (input_byte[0] + input_byte[-1]) & 0xff

for i in range(32):
input_byte[i] = what ^ (input_byte[i] ^ input_byte[(i+1)&0x1f]) ^ 0xff
what += input_byte[i]
what ^= 0xa5
what &= 0xff

for i in range(32):
input_byte[i] = what ^ (input_byte[i] ^ input_byte[(i+1)&0x1f]) ^ 0xff
what += input_byte[i]
what ^= 0xa5
what &= 0xff

for i in range(32):
print(hex(input_byte[i]),end=',')

逆着去写解密脚本脚本即可。
注意decode2里面的what值是不可知的,所以只能爆破,可以通过限制what等于(input_byte[0] + input_byte[-1]) & 0xff来减少解的情况。

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

input_enc = [0xC2, 0x3A, 0x86, 0xC1, 0x44, 0x07, 0x13, 0x0C, 0x7B, 0xBE, 0x1A, 0x6D, 0xCB, 0xFA, 0x26, 0x99, 0x62, 0x7C, 0x82, 0x66, 0x9F, 0x1C, 0xD9, 0x99, 0x44, 0xC3, 0xB7, 0x1D, 0x67, 0x3C, 0x7B, 0x80]
decode_1 = []
xor0 = [0xDEADBEEF, 0x9E3779B9, 0xC6EF3720, 0xBEEFDEED, 0xDEADBEEF, 0x9E3779B9, 0xC6EF3720, 0xBEEFDEED, 0x33323130, 0x37363534, 0x31303938, 0x35343332,0x39383736, 0x33323130, 0x37363534, 0x31303938]
xor1 = [3, 0xF, 0xE, 0xA, 4, 7, 0, 9, 1, 0xD, 6, 2, 5, 0xC, 0xB, 8]
xor2 = [3, 0xA, 5, 8, 4, 0xB, 0xD, 0xC, 7, 6, 0, 1, 2, 9, 0xE, 0xF]
xor3 = [1, 0, 9, 0xB, 0xF, 5, 0xC, 4, 0xE, 0xD, 0xA, 8, 2, 6, 3, 7]
xor4 = [0xB, 3, 0xE, 5, 6, 9, 1, 7, 0, 0xD, 0xC, 4, 8, 2, 0xA, 0xF]
xor5 = [0xD, 8, 9, 5, 1, 4, 2, 0, 6, 0xA, 7, 0xB, 0xC, 3, 0xE, 0xF]
xor6 = [0xF, 0xC, 0xA, 6, 0, 9, 5, 0xE, 2, 0xB, 4, 7, 8, 1, 0xD, 3]
xor7 = [0xD, 2, 9, 0, 0xF, 3, 0xA, 0xB, 4, 5, 6, 0xE, 7, 0xC, 1, 8]
xor8 = [4, 0xE, 0, 0xF, 9, 3, 2, 0xD, 5, 1, 0xC, 8, 7, 0xA, 0xB, 6]
idx = [0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7, 7, 6, 5, 4, 3, 2, 1, 0]

def key_to_tmp(key):
return (xor1.index((key>>0x1c)&0xf)<<28)|(xor2.index((key>>0x18)&0xf)<<24)|(xor3.index((key>>0x14)&0xf)<<20)|(xor4.index((key>>0x10)&0xf)<<16)|(xor5.index((key>>0xc)&0xf)<<12)|(xor6.index((key>>0x8)&0xf)<<8)|(xor7.index((key>>0x4)&0xf)<<4)|(xor8.index((key)&0xf))

def decode1(input,i0,i1):
xor0_idx = 0
key = input[i1]
tmp = key_to_tmp(key)

for i in range(30,-1,-1):
key = input[i0]
input[i1] = key ^ tmp ^ xor0[idx[xor0_idx]]
input[i0] = input[i1]
tmp = key_to_tmp(key)
xor0_idx += 1

input[i1] = input[i0] ^ xor0[idx[xor0_idx]] ^ tmp

def decode2(what):
input_byte = input_enc.copy()
for i in range(31,-1,-1):
what ^= 0xa5
what -= input_byte[i]
if what < 0:
what += 0x100
input_byte[i] = what ^ input_byte[i] ^ input_byte[(i+1)&0x1f] ^ 0xff

for i in range(31,-1,-1):
what ^= 0xa5
what -= input_byte[i]
if what < 0:
what += 0x100
input_byte[i] = what ^ input_byte[i] ^ input_byte[(i+1)&0x1f] ^ 0xff

if what == ((input_byte[0] + input_byte[-1]) & 0xff):
dec = []
for i in range(0,32,4):
dec.append(input_byte[i]|(input_byte[i+1]<<8)|(input_byte[i+2]<<16)|(input_byte[i+3]<<24))
decode_1.append(dec)

for i in range(0xff):
decode2(i)

for i in decode_1:
decode1(i,0,3)
decode1(i,1,2)
decode1(i,4,6)
decode1(i,5,7)

for i in decode_1:
f = b''
for j in i:
f +=pack('<I',j)
print(f)
#b'S3hr0din7er_3_Uni4er3al_D00rs111'

5_crackme

还没复现,先占个位,等学弟浇浇我移动安全再来做(逃

CISCN 初赛

baby ast

算是拖了很久,对这题充满了不想复现的恐惧……其实比赛的时候早就装好swift了,也想过自己编译一段语法树出来对照代码看看,但是总觉得很麻烦,又耐不下心去看……
总觉得八百多行很多很恐惧,但是现在看也就还行……

测试代码tmp.swift:(语法好像有点问题,我也没仔细看swift的语法,凑合看8

1
2
3
4
5
6
7
8
9
10
11
12
13
func check(keyValue: String, encoded: String) -> Int {
let a = 9
let b = 10

return a ^ b
}

print(check("1234","dfgh"))

var n = [0,1,2,3]
for i in 0...3{
n[i] = 0
}

使用命令swiftc -dump-ast tmp.swift来得到抽象语法树。

func check(keyValue: String, encoded: String) -> Int {对应

1
2
3
4
5
6
7
(func_decl range=[tmp.swift:1:1 - line:6:1] "check(keyValue:encoded:)" interface type='(String, String) -> Int' access=internal
(parameter_list range=[tmp.swift:1:11 - line:1:45]
(parameter "keyValue" apiName=keyValue type='String' interface type='String')
(parameter "encoded" apiName=encoded type='String' interface type='String'))
(result
(type_ident
(component id='Int' bind=Swift.(file).Int)))

所以题目里的

1
2
3
4
5
6
7
(func_decl range=[re.swift:1:1 - line:14:1] "check(_:_:)" interface type='(String, String) -> Bool' access=internal
(parameter_list range=[re.swift:1:11 - line:1:49]
(parameter "encoded" type='String' interface type='String')
(parameter "keyValue" type='String' interface type='String'))
(result
(type_ident
(component id='Bool' bind=Swift.(file).Bool)))

对应的应该就是check(_: String,_: String) -> Bool,即定义一个check函数,返回值为布尔类型。

let a = 9对应

1
2
3
4
5
6
7
8
9
10
(pattern_binding_decl range=[tmp.swift:2:5 - line:2:13]
(pattern_named type='Int' 'a')
Original init:
(integer_literal_expr type='Int' location=tmp.swift:2:13 range=[tmp.swift:2:13 - line:2:13] value=9 builtin_initializer=Swift.(file).Int.init(_builtinIntegerLiteral:) initializer=**NULL**)
Processed init:
(integer_literal_expr type='Int' location=tmp.swift:2:13 range=[tmp.swift:2:13 - line:2:13] value=9 builtin_initializer=Swift.(file).Int.init(_builtinIntegerLiteral:) initializer=**NULL**))

(var_decl range=[tmp.swift:2:9 - line:2:9] "a" type='Int' interface type='Int' access=private let readImpl=stored immutable)

(pattern_binding_decl range=[tmp.swift:3:2 - line:3:10]

let b = 10同理。

return a ^ b对应

1
2
3
4
5
6
7
8
9
10
11
12
13
14
(return_stmt range=[tmp.swift:5:5 - line:5:16]
(binary_expr type='Int' location=tmp.swift:5:14 range=[tmp.swift:5:12 - line:5:16] nothrow
(dot_syntax_call_expr implicit type='(Int, Int) -> Int' location=tmp.swift:5:14 range=[tmp.swift:5:14 - line:5:14] nothrow
(declref_expr type='(Int.Type) -> (Int, Int) -> Int' location=tmp.swift:5:14 range=[tmp.swift:5:14 - line:5:14] decl=Swift.(file).Int extension.^ function_ref=single)
(argument_list implicit
(argument
(type_expr implicit type='Int.Type' location=tmp.swift:5:14 range=[tmp.swift:5:14 - line:5:14] typerepr='Int'))
))
(argument_list implicit
(argument
(declref_expr type='Int' location=tmp.swift:5:12 range=[tmp.swift:5:12 - line:5:12] decl=tmp.(file).check(keyValue:encoded:).a@tmp.swift:2:9 function_ref=unapplied))
(argument
(declref_expr type='Int' location=tmp.swift:5:16 range=[tmp.swift:5:16 - line:5:16] decl=tmp.(file).check(keyValue:encoded:).b@tmp.swift:3:6 function_ref=unapplied))
)))))

其中运算符^extension.^

print(check("1234","dfgh"))对应

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
(top_level_code_decl range=[tmp.swift:8:1 - line:8:27]
(brace_stmt implicit range=[tmp.swift:8:1 - line:8:27]
(call_expr type='<null>'
(overloaded_decl_ref_expr type='<null>' name=print number_of_decls=2 function_ref=single decls=[
Swift.(file).print(_:separator:terminator:),
Swift.(file).print(_:separator:terminator:to:)])
(argument_list
(argument
(call_expr type='<null>'
(declref_expr type='<null>' decl=tmp.(file).check(keyValue:encoded:)@tmp.swift:1:6 function_ref=single)
(argument_list
(argument
(string_literal_expr type='<null>' encoding=utf8 value="1234" builtin_initializer=**NULL** initializer=**NULL**))
(argument
(string_literal_expr type='<null>' encoding=utf8 value="dfgh" builtin_initializer=**NULL** initializer=**NULL**))
)))
))))

let n = [0,1,2,3]对应

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
  (top_level_code_decl range=[tmp.swift:10:1 - line:10:17]
(brace_stmt implicit range=[tmp.swift:10:1 - line:10:17]
(pattern_binding_decl range=[tmp.swift:10:1 - line:10:17]
(pattern_named type='[Int]' 'n')
Original init:
(array_expr type='[Int]' location=tmp.swift:10:9 range=[tmp.swift:10:9 - line:10:17] initializer=Swift.(file).Array extension.init(arrayLiteral:) [with (substitution_map generic_signature=<Element> (substitution Element -> Int))]
(integer_literal_expr type='Int' location=tmp.swift:10:10 range=[tmp.swift:10:10 - line:10:10] value=0 builtin_initializer=Swift.(file).Int.init(_builtinIntegerLiteral:) initializer=**NULL**)
(integer_literal_expr type='Int' location=tmp.swift:10:12 range=[tmp.swift:10:12 - line:10:12] value=1 builtin_initializer=Swift.(file).Int.init(_builtinIntegerLiteral:) initializer=**NULL**)
(integer_literal_expr type='Int' location=tmp.swift:10:14 range=[tmp.swift:10:14 - line:10:14] value=2 builtin_initializer=Swift.(file).Int.init(_builtinIntegerLiteral:) initializer=**NULL**)
(integer_literal_expr type='Int' location=tmp.swift:10:16 range=[tmp.swift:10:16 - line:10:16] value=3 builtin_initializer=Swift.(file).Int.init(_builtinIntegerLiteral:) initializer=**NULL**))
Processed init:
(array_expr type='[Int]' location=tmp.swift:10:9 range=[tmp.swift:10:9 - line:10:17] initializer=Swift.(file).Array extension.init(arrayLiteral:) [with (substitution_map generic_signature=<Element> (substitution Element -> Int))]
(integer_literal_expr type='Int' location=tmp.swift:10:10 range=[tmp.swift:10:10 - line:10:10] value=0 builtin_initializer=Swift.(file).Int.init(_builtinIntegerLiteral:) initializer=**NULL**)
(integer_literal_expr type='Int' location=tmp.swift:10:12 range=[tmp.swift:10:12 - line:10:12] value=1 builtin_initializer=Swift.(file).Int.init(_builtinIntegerLiteral:) initializer=**NULL**)
(integer_literal_expr type='Int' location=tmp.swift:10:14 range=[tmp.swift:10:14 - line:10:14] value=2 builtin_initializer=Swift.(file).Int.init(_builtinIntegerLiteral:) initializer=**NULL**)
(integer_literal_expr type='Int' location=tmp.swift:10:16 range=[tmp.swift:10:16 - line:10:16] value=3 builtin_initializer=Swift.(file).Int.init(_builtinIntegerLiteral:) initializer=**NULL**)))
))
(var_decl range=[tmp.swift:10:5 - line:10:5] "n" type='[Int]' interface type='[Int]' access=internal let readImpl=stored immutable)

for i in 0...3{}对应

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
(brace_stmt implicit range=[tmp.swift:11:1 - line:13:1]
(for_each_stmt range=[tmp.swift:11:1 - line:13:1]
(pattern_named type='Int' 'i')
(pattern_named type='Int' 'i')
(binary_expr type='ClosedRange<Int>' location=tmp.swift:11:11 range=[tmp.swift:11:10 - line:11:14] nothrow
(dot_syntax_call_expr implicit type='(Int, Int) -> ClosedRange<Int>' location=tmp.swift:11:11 range=[tmp.swift:11:11 - line:11:11] nothrow
(declref_expr type='(Int.Type) -> (Int, Int) -> ClosedRange<Int>' location=tmp.swift:11:11 range=[tmp.swift:11:11 - line:11:11] decl=Swift.(file).Comparable extension.... [with (substitution_map generic_signature=<Self where Self : Comparable> (substitution Self -> Int))] function_ref=double)
(argument_list implicit
(argument
(type_expr implicit type='Int.Type' location=tmp.swift:11:11 range=[tmp.swift:11:11 - line:11:11] typerepr='Int'))
))
(argument_list implicit
(argument
(integer_literal_expr type='Int' location=tmp.swift:11:10 range=[tmp.swift:11:10 - line:11:10] value=0 builtin_initializer=Swift.(file).Int.init(_builtinIntegerLiteral:) initializer=**NULL**))
(argument
(integer_literal_expr type='Int' location=tmp.swift:11:14 range=[tmp.swift:11:14 - line:11:14] value=3 builtin_initializer=Swift.(file).Int.init(_builtinIntegerLiteral:) initializer=**NULL**))
))
(var_decl implicit range=[tmp.swift:11:7 - line:11:7] "$i$generator" type='ClosedRange<Int>.Iterator' interface type='ClosedRange<Int>.Iterator' access=fileprivate readImpl=stored writeImpl=stored readWriteImpl=stored)

(declref_expr implicit type='@lvalue ClosedRange<Int>.Iterator' location=tmp.swift:11:7 range=[tmp.swift:11:7 - line:11:7] decl=tmp.(file).top-level code.$i$generator@tmp.swift:11:7 function_ref=unapplied)
(brace_stmt range=[tmp.swift:11:15 - line:13:1]

for_each_stmt创建循环。

n[i] = 0对应

1
2
3
4
5
6
7
8
9
(assign_expr type='()' location=tmp.swift:12:7 range=[tmp.swift:12:2 - line:12:9]
(subscript_expr type='@lvalue Int' location=tmp.swift:12:3 range=[tmp.swift:12:2 - line:12:5] decl=Swift.(file).Array extension.subscript(_:) [with (substitution_map generic_signature=<Element> (substitution Element -> Int))]
(inout_expr implicit type='inout Array<Int>' location=tmp.swift:12:2 range=[tmp.swift:12:2 - line:12:2]
(declref_expr type='@lvalue [Int]' location=tmp.swift:12:2 range=[tmp.swift:12:2 - line:12:2] decl=tmp.(file).n@tmp.swift:10:5 function_ref=unapplied))
(argument_list
(argument
(declref_expr type='Int' location=tmp.swift:12:4 range=[tmp.swift:12:4 - line:12:4] decl=tmp.(file).top-level code.i@tmp.swift:11:5 function_ref=unapplied))
))
(integer_literal_expr type='Int' location=tmp.swift:12:9 range=[tmp.swift:12:9 - line:12:9] value=0 builtin_initializer=Swift.(file).Int.init(_builtinIntegerLiteral:) initializer=**NULL**)))))))

extension.subscript(_:)表示切片操作。

题目中刚开始定义了一个check(_: String,_: String) -> Bool,然后给两个变量b和k赋值,大概是类似于bytes的操作,即对字符串解码存为ASCII码,然后定义4个变量r0,r1,r2,r3。

定义for循环:

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
(for_each_stmt range=[re.swift:5:5 - line:12:5]
(pattern_named type='Int' 'i')
(pattern_named type='Int' 'i')
(binary_expr type='ClosedRange<Int>' location=re.swift:5:15 range=[re.swift:5:14 - line:5:26] nothrow
(dot_syntax_call_expr implicit type='(Int, Int) -> ClosedRange<Int>' location=re.swift:5:15 range=[re.swift:5:15 - line:5:15] nothrow
(declref_expr type='(Int.Type) -> (Int, Int) -> ClosedRange<Int>' location=re.swift:5:15 range=[re.swift:5:15 - line:5:15] decl=Swift.(file).Comparable extension.... [with (substitution_map generic_signature=<Self where Self : Comparable> (substitution Self -> Int))] function_ref=double)
(argument_list implicit
(argument
(type_expr implicit type='Int.Type' location=re.swift:5:15 range=[re.swift:5:15 - line:5:15] typerepr='Int'))
))
(argument_list implicit
(argument
(integer_literal_expr type='Int' location=re.swift:5:14 range=[re.swift:5:14 - line:5:14] value=0 builtin_initializer=Swift.(file).Int.init(_builtinIntegerLiteral:) initializer=**NULL**))
(argument
(binary_expr type='Int' location=re.swift:5:25 range=[re.swift:5:18 - line:5:26] nothrow
(dot_syntax_call_expr implicit type='(Int, Int) -> Int' location=re.swift:5:25 range=[re.swift:5:25 - line:5:25] nothrow
(declref_expr type='(Int.Type) -> (Int, Int) -> Int' location=re.swift:5:25 range=[re.swift:5:25 - line:5:25] decl=Swift.(file).Int extension.- function_ref=double)
(argument_list implicit
(argument
(type_expr implicit type='Int.Type' location=re.swift:5:25 range=[re.swift:5:25 - line:5:25] typerepr='Int'))
))
(argument_list implicit
(argument
(member_ref_expr type='Int' location=re.swift:5:20 range=[re.swift:5:18 - line:5:20] decl=Swift.(file).Array extension.count [with (substitution_map generic_signature=<Element> (substitution Element -> UInt8))]
(load_expr implicit type='[UInt8]' location=re.swift:5:18 range=[re.swift:5:18 - line:5:18]
(declref_expr type='@lvalue [UInt8]' location=re.swift:5:18 range=[re.swift:5:18 - line:5:18] decl=re.(file).check(_:_:).b@re.swift:2:9 function_ref=unapplied))))
(argument
(integer_literal_expr type='Int' location=re.swift:5:26 range=[re.swift:5:26 - line:5:26] value=4 builtin_initializer=Swift.(file).Int.init(_builtinIntegerLiteral:) initializer=**NULL**))
)))
))
(var_decl implicit range=[re.swift:5:11 - line:5:11] "$i$generator" type='ClosedRange<Int>.Iterator' interface type='ClosedRange<Int>.Iterator' access=private readImpl=stored writeImpl=stored readWriteImpl=stored)

(declref_expr implicit type='@lvalue ClosedRange<Int>.Iterator' location=re.swift:5:11 range=[re.swift:5:11 - line:5:11] decl=re.(file).check(_:_:).$i$generator@re.swift:5:11 function_ref=unapplied)
(brace_stmt range=[re.swift:5:27 - line:12:5]

extension....表示for i in x...y的形式,x和y可以根据缩进来判断。
x定义在

1
2
(argument
(integer_literal_expr type='Int' location=re.swift:5:14 range=[re.swift:5:14 - line:5:14] value=0 builtin_initializer=Swift.(file).Int.init(_builtinIntegerLiteral:) initializer=**NULL**))

即x=0。

y定义在

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
  (argument
(binary_expr type='Int' location=re.swift:5:25 range=[re.swift:5:18 - line:5:26] nothrow
(dot_syntax_call_expr implicit type='(Int, Int) -> Int' location=re.swift:5:25 range=[re.swift:5:25 - line:5:25] nothrow
(declref_expr type='(Int.Type) -> (Int, Int) -> Int' location=re.swift:5:25 range=[re.swift:5:25 - line:5:25] decl=Swift.(file).Int extension.- function_ref=double)
(argument_list implicit
(argument
(type_expr implicit type='Int.Type' location=re.swift:5:25 range=[re.swift:5:25 - line:5:25] typerepr='Int'))
))
(argument_list implicit
(argument
(member_ref_expr type='Int' location=re.swift:5:20 range=[re.swift:5:18 - line:5:20] decl=Swift.(file).Array extension.count [with (substitution_map generic_signature=<Element> (substitution Element -> UInt8))]
(load_expr implicit type='[UInt8]' location=re.swift:5:18 range=[re.swift:5:18 - line:5:18]
(declref_expr type='@lvalue [UInt8]' location=re.swift:5:18 range=[re.swift:5:18 - line:5:18] decl=re.(file).check(_:_:).b@re.swift:2:9 function_ref=unapplied))))
(argument
(integer_literal_expr type='Int' location=re.swift:5:26 range=[re.swift:5:26 - line:5:26] value=4 builtin_initializer=Swift.(file).Int.init(_builtinIntegerLiteral:) initializer=**NULL**))
)))
))

y=b.count-4,翻译成python就是y=len(b)-4
由于swift的for in循环含首也含尾,所以这句翻译成python的形式应该是for i in range(len(b)-4+1)

再往下,

1
2
3
4
5
(tuple_expr type='(@lvalue UInt8, @lvalue UInt8, @lvalue UInt8, @lvalue UInt8)' location=re.swift:6:9 range=[re.swift:6:9 - line:6:24] names='','','',''
(declref_expr type='@lvalue UInt8' location=re.swift:6:10 range=[re.swift:6:10 - line:6:10] decl=re.(file).check(_:_:).r0@re.swift:4:9 function_ref=unapplied)
(declref_expr type='@lvalue UInt8' location=re.swift:6:14 range=[re.swift:6:14 - line:6:14] decl=re.(file).check(_:_:).r1@re.swift:4:13 function_ref=unapplied)
(declref_expr type='@lvalue UInt8' location=re.swift:6:18 range=[re.swift:6:18 - line:6:18] decl=re.(file).check(_:_:).r2@re.swift:4:17 function_ref=unapplied)
(declref_expr type='@lvalue UInt8' location=re.swift:6:22 range=[re.swift:6:22 - line:6:22] decl=re.(file).check(_:_:).r3@re.swift:4:21 function_ref=unapplied))

r0,r1,r2,r3 =

下一步切片操作,以第2个为例,即

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
(subscript_expr type='@lvalue UInt8' location=re.swift:6:36 range=[re.swift:6:35 - line:6:40] decl=Swift.(file).Array extension.subscript(_:) [with (substitution_map generic_signature=<Element> (substitution Element -> UInt8))]
(inout_expr implicit type='inout Array<UInt8>' location=re.swift:6:35 range=[re.swift:6:35 - line:6:35]
(declref_expr type='@lvalue [UInt8]' location=re.swift:6:35 range=[re.swift:6:35 - line:6:35] decl=re.(file).check(_:_:).b@re.swift:2:9 function_ref=unapplied))
(argument_list
(argument
(binary_expr type='Int' location=re.swift:6:38 range=[re.swift:6:37 - line:6:39] nothrow
(dot_syntax_call_expr implicit type='(Int, Int) -> Int' location=re.swift:6:38 range=[re.swift:6:38 - line:6:38] nothrow
(declref_expr type='(Int.Type) -> (Int, Int) -> Int' location=re.swift:6:38 range=[re.swift:6:38 - line:6:38] decl=Swift.(file).Int extension.+ function_ref=double)
(argument_list implicit
(argument
(type_expr implicit type='Int.Type' location=re.swift:6:38 range=[re.swift:6:38 - line:6:38] typerepr='Int'))
))
(argument_list implicit
(argument
(declref_expr type='Int' location=re.swift:6:37 range=[re.swift:6:37 - line:6:37] decl=re.(file).check(_:_:).i@re.swift:5:9 function_ref=unapplied))
(argument
(integer_literal_expr type='Int' location=re.swift:6:39 range=[re.swift:6:39 - line:6:39] value=1 builtin_initializer=Swift.(file).Int.init(_builtinIntegerLiteral:) initializer=**NULL**))
)))
)))

其中操作对象是b(re.(file).check(_:_:).b@re.swift)和i(re.(file).check(_:_:).i@re.swift),运算符是+(extension.+),值为1,即b[i+1]

整理一下就是r0,r1,r2,r3=b[i],b[i+1],b[i+2],b[i+3]

加密部分第一句

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
(assign_expr type='()' location=re.swift:7:16 range=[re.swift:7:9 - line:7:49]
(subscript_expr type='@lvalue UInt8' location=re.swift:7:10 range=[re.swift:7:9 - line:7:14] decl=Swift.(file).Array extension.subscript(_:) [with (substitution_map generic_signature=<Element> (substitution Element -> UInt8))]
(inout_expr implicit type='inout Array<UInt8>' location=re.swift:7:9 range=[re.swift:7:9 - line:7:9]
(declref_expr type='@lvalue [UInt8]' location=re.swift:7:9 range=[re.swift:7:9 - line:7:9] decl=re.(file).check(_:_:).b@re.swift:2:9 function_ref=unapplied))
(argument_list
(argument
(binary_expr type='Int' location=re.swift:7:12 range=[re.swift:7:11 - line:7:13] nothrow
(dot_syntax_call_expr implicit type='(Int, Int) -> Int' location=re.swift:7:12 range=[re.swift:7:12 - line:7:12] nothrow
(declref_expr type='(Int.Type) -> (Int, Int) -> Int' location=re.swift:7:12 range=[re.swift:7:12 - line:7:12] decl=Swift.(file).Int extension.+ function_ref=double)
(argument_list implicit
(argument
(type_expr implicit type='Int.Type' location=re.swift:7:12 range=[re.swift:7:12 - line:7:12] typerepr='Int'))
))
(argument_list implicit
(argument
(declref_expr type='Int' location=re.swift:7:11 range=[re.swift:7:11 - line:7:11] decl=re.(file).check(_:_:).i@re.swift:5:9 function_ref=unapplied))
(argument
(integer_literal_expr type='Int' location=re.swift:7:13 range=[re.swift:7:13 - line:7:13] value=0 builtin_initializer=Swift.(file).Int.init(_builtinIntegerLiteral:) initializer=**NULL**))
)))
))
(binary_expr type='UInt8' location=re.swift:7:21 range=[re.swift:7:18 - line:7:49] nothrow
(dot_syntax_call_expr implicit type='(UInt8, UInt8) -> UInt8' location=re.swift:7:21 range=[re.swift:7:21 - line:7:21] nothrow
(declref_expr type='(UInt8.Type) -> (UInt8, UInt8) -> UInt8' location=re.swift:7:21 range=[re.swift:7:21 - line:7:21] decl=Swift.(file).UInt8 extension.^ function_ref=single)
(argument_list implicit
(argument
(type_expr implicit type='UInt8.Type' location=re.swift:7:21 range=[re.swift:7:21 - line:7:21] typerepr='UInt8'))
))
(argument_list implicit
(argument
(load_expr implicit type='UInt8' location=re.swift:7:18 range=[re.swift:7:18 - line:7:18]
(declref_expr type='@lvalue UInt8' location=re.swift:7:18 range=[re.swift:7:18 - line:7:18] decl=re.(file).check(_:_:).r2@re.swift:4:17 function_ref=unapplied)))
(argument
(paren_expr type='(UInt8)' location=re.swift:7:43 range=[re.swift:7:23 - line:7:49]
(binary_expr type='UInt8' location=re.swift:7:43 range=[re.swift:7:24 - line:7:45] nothrow
(dot_syntax_call_expr implicit type='(UInt8, UInt8) -> UInt8' location=re.swift:7:43 range=[re.swift:7:43 - line:7:43] nothrow
(declref_expr type='(UInt8.Type) -> (UInt8, UInt8) -> UInt8' location=re.swift:7:43 range=[re.swift:7:43 - line:7:43] decl=Swift.(file).UInt8 extension.& function_ref=double)
(argument_list implicit
(argument
(type_expr implicit type='UInt8.Type' location=re.swift:7:43 range=[re.swift:7:43 - line:7:43] typerepr='UInt8'))
))
(argument_list implicit
(argument
(paren_expr type='(UInt8)' location=re.swift:7:30 range=[re.swift:7:24 - line:7:41]
(binary_expr type='UInt8' location=re.swift:7:30 range=[re.swift:7:25 - line:7:40] nothrow
(dot_syntax_call_expr implicit type='(UInt8, UInt8) -> UInt8' location=re.swift:7:30 range=[re.swift:7:30 - line:7:30] nothrow
(declref_expr type='(UInt8.Type) -> (UInt8, UInt8) -> UInt8' location=re.swift:7:30 range=[re.swift:7:30 - line:7:30] decl=Swift.(file).UInt8 extension.+ function_ref=double)
(argument_list implicit
(argument
(type_expr implicit type='UInt8.Type' location=re.swift:7:30 range=[re.swift:7:30 - line:7:30] typerepr='UInt8'))
))
(argument_list implicit
(argument
(load_expr implicit type='UInt8' location=re.swift:7:26 range=[re.swift:7:25 - line:7:28]
(subscript_expr type='@lvalue UInt8' location=re.swift:7:26 range=[re.swift:7:25 - line:7:28] decl=Swift.(file).Array extension.subscript(_:) [with (substitution_map generic_signature=<Element> (substitution Element -> UInt8))]
(inout_expr implicit type='inout Array<UInt8>' location=re.swift:7:25 range=[re.swift:7:25 - line:7:25]
(declref_expr type='@lvalue [UInt8]' location=re.swift:7:25 range=[re.swift:7:25 - line:7:25] decl=re.(file).check(_:_:).k@re.swift:3:9 function_ref=unapplied))
(argument_list
(argument
(integer_literal_expr type='Int' location=re.swift:7:27 range=[re.swift:7:27 - line:7:27] value=0 builtin_initializer=Swift.(file).Int.init(_builtinIntegerLiteral:) initializer=**NULL**))
))))
(argument
(paren_expr type='(UInt8)' location=re.swift:7:36 range=[re.swift:7:32 - line:7:40]
(binary_expr type='UInt8' location=re.swift:7:36 range=[re.swift:7:33 - line:7:39] nothrow
(dot_syntax_call_expr implicit type='(UInt8, Int) -> UInt8' location=re.swift:7:36 range=[re.swift:7:36 - line:7:36] nothrow
(declref_expr type='(UInt8.Type) -> (UInt8, Int) -> UInt8' location=re.swift:7:36 range=[re.swift:7:36 - line:7:36] decl=Swift.(file).FixedWidthInteger extension.>> [with (substitution_map generic_signature=<Self, Other where Self : FixedWidthInteger, Other : BinaryInteger> (substitution Self -> UInt8) (substitution Other -> Int))] function_ref=double)
(argument_list implicit
(argument
(type_expr implicit type='UInt8.Type' location=re.swift:7:36 range=[re.swift:7:36 - line:7:36] typerepr='UInt8'))
))
(argument_list implicit
(argument
(load_expr implicit type='UInt8' location=re.swift:7:33 range=[re.swift:7:33 - line:7:33]
(declref_expr type='@lvalue UInt8' location=re.swift:7:33 range=[re.swift:7:33 - line:7:33] decl=re.(file).check(_:_:).r0@re.swift:4:9 function_ref=unapplied)))
(argument
(integer_literal_expr type='Int' location=re.swift:7:39 range=[re.swift:7:39 - line:7:39] value=4 builtin_initializer=Swift.(file).Int.init(_builtinIntegerLiteral:) initializer=**NULL**))
))))
))))
(argument
(integer_literal_expr type='UInt8' location=re.swift:7:45 range=[re.swift:7:45 - line:7:45] value=0xff builtin_initializer=Swift.(file).UInt8.init(_builtinIntegerLiteral:) initializer=**NULL**))
))))
)))

这一句是由多个子句构成,从最内层的缩进看起,最内层的两个子句分别是

1
2
3
4
5
6
7
8
9
(argument
(load_expr implicit type='UInt8' location=re.swift:7:26 range=[re.swift:7:25 - line:7:28]
(subscript_expr type='@lvalue UInt8' location=re.swift:7:26 range=[re.swift:7:25 - line:7:28] decl=Swift.(file).Array extension.subscript(_:) [with (substitution_map generic_signature=<Element> (substitution Element -> UInt8))]
(inout_expr implicit type='inout Array<UInt8>' location=re.swift:7:25 range=[re.swift:7:25 - line:7:25]
(declref_expr type='@lvalue [UInt8]' location=re.swift:7:25 range=[re.swift:7:25 - line:7:25] decl=re.(file).check(_:_:).k@re.swift:3:9 function_ref=unapplied))
(argument_list
(argument
(integer_literal_expr type='Int' location=re.swift:7:27 range=[re.swift:7:27 - line:7:27] value=0 builtin_initializer=Swift.(file).Int.init(_builtinIntegerLiteral:) initializer=**NULL**))
))))

k[0]

1
2
3
4
5
6
7
8
9
10
11
12
13
(dot_syntax_call_expr implicit type='(UInt8, Int) -> UInt8' location=re.swift:7:36 range=[re.swift:7:36 - line:7:36] nothrow
(declref_expr type='(UInt8.Type) -> (UInt8, Int) -> UInt8' location=re.swift:7:36 range=[re.swift:7:36 - line:7:36] decl=Swift.(file).FixedWidthInteger extension.>> [with (substitution_map generic_signature=<Self, Other where Self : FixedWidthInteger, Other : BinaryInteger> (substitution Self -> UInt8) (substitution Other -> Int))] function_ref=double)
(argument_list implicit
(argument
(type_expr implicit type='UInt8.Type' location=re.swift:7:36 range=[re.swift:7:36 - line:7:36] typerepr='UInt8'))
))
(argument_list implicit
(argument
(load_expr implicit type='UInt8' location=re.swift:7:33 range=[re.swift:7:33 - line:7:33]
(declref_expr type='@lvalue UInt8' location=re.swift:7:33 range=[re.swift:7:33 - line:7:33] decl=re.(file).check(_:_:).r0@re.swift:4:9 function_ref=unapplied)))
(argument
(integer_literal_expr type='Int' location=re.swift:7:39 range=[re.swift:7:39 - line:7:39] value=4 builtin_initializer=Swift.(file).Int.init(_builtinIntegerLiteral:) initializer=**NULL**))
))))

r0>>4

处于同一缩进的子句是同级的关系,两子句的运算符要在次一级缩进处找。

k[0]+(r0>>4)

此后过程大致相同,这一句翻译过来即b[i]^=(k[0]+(r0>>4))&0xff,同理,下一段是b[i+1]^=(k[1]+(r1>>4))&0xff

完整加密过程:

1
2
3
4
5
6
7
for i in range(len(b)-4+1):
r0,r1,r2,r3=b[i],b[i+1],b[i+2],b[i+3]
b[i]^=(k[0]+(r0>>4))&0xff
b[i+1]^=(k[1]+(r1>>4))&0xff
b[i+2]^=k[2]
b[i+3]^=k[3]
k[0],k[1],k[2],k[3]=k[1],k[2],k[3],k[0]

程序使用的密文可以在五百多行的地方获取到,密钥是"345y"。据此写出解密脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
b=[88,35,88,225,7,201,57,94,77,56,75,168,72,218,64,91,16,101,32,207,73,130,74,128,76,201,16,248,41,205,103,84,91,99,79,202,22,131,63,255,20,16]
k = list(b'y345')
for i in range(len(b)-4,-1,-1):
k[1],k[2],k[3],k[0] = k[0],k[1],k[2],k[3]
r1 = b[i+3] ^ k[3]
r0 = b[i+2] ^ k[2]
r3 = b[i+1] ^ ((k[1]+(r1>>2))&0xff)
r2 = b[i] ^ ((k[0]+(r0>>4))&0xff)
b[i],b[i+1],b[i+2],b[i+3]=r0,r1,r2,r3

for i in b:
print(chr(i),end='')
#flag{30831242-56db-45b4-96fd-1f47e60da99d}

babycode

要装mruby,先装ruby,再装doxygen,注意把doxygen放到环境变量里,最后才能装mruby……
编译好之后在bin目录下可以反编译。

.\mruby -v -b .\babycode.mrb > ruby.txt

区区三百多行,看我手撕
屮……最开始输出的字节码少了四十多行,我就说为什么没有密文密钥,而且那个check方法看起来那么奇怪……心累
不想再看一遍了
又因为运算优先级出锅了……

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 struct
enc = b'f469358b7f165145116e127ad6105917bce5225d6d62a714c390c5ed93b22d8b6b102a8813488fdb'
key = b'aaaassssddddffff'
key = struct.unpack('LLLL', key)

def decode(num1, num2, key):
XX = 0x12345678
s = XX*16
y = num1
z = num2
for i in range(16):
z -= (((y<<3)^(y>>5))+y) ^ (key[(s+1)&3]+s)
z &= 0xffffffff
s -= XX
y -= (((z<<3)^(z>>5))+z) ^ (key[((s>>11)+1)&3]+s)
y &= 0xffffffff
return struct.pack('>I',y), struct.pack('>I',z)

dec = []
b = b''
for i in range(0,len(enc),8):
dec.append(int(enc[i:i+8],16))
for i in range(0,len(dec),2):
x,y = decode(dec[i],dec[i+1],key)
b += x + y
dec = [i for i in b]
for i in range(len(dec)):
l = 0 if i==0 else dec[i-1]
dec[i] ^= l ^ (i+1)
print(''.join(map(chr,dec)))
# flag{6ad1c70c-daa4-11ec-9d64-0242ac1200}

参考文章:https://www.anquanke.com/post/id/253572#h2-1

关于本文

本文作者 云之君, 许可由 CC BY-NC 4.0.