2019 RCTF

比赛时间:5月18日-5月19日

XCTF联赛内的RCTF,由福州大学RIOS战队主办。

De1ta最终排第7名。re再次ak

下载地址

babyre

输入长度16,0-9a-z,然后hex转字节

之后用xxtea解密。根据提示,解密后要为Bingo!。xxtea最后一段逻辑,根据解密的最后一个字节的大小x,把明文倒数第x位用\0截断。

得到的明文先CRC16/CCITT,结果要为0x69E2。

明文每一位再异或0x17,然后输出。

即解密完应该是Bingo!异或0x17。

由于输出Bingo!,所以最后一位应该是,这样截断完再异或0x17就是Bingo!了。

这样我们得到了明文的前六位和最后一位,还差1位,这时可以用题目给出的hint爆出来。

也可以不爆破。因为根据用最后一位截断,可以推断出加密时的padding是用剩余字节数padding。即明文最后两位都是。

网上抄的xxtea代码:

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
#include<pch.h>
#include<iostream>

using namespace std;
#define MX ((z>>5^y<<2) + (y>>3^z<<4) ^ (sum^y) + (k[p&3^e]^z))

long btea(long* v, long n, long* k) {
unsigned long z = v[n - 1], y = v[0], sum = 0, e, DELTA = 0x9e3779b9;
long p, q;
if (n > 1) { /* Coding Part */
q = 6 + 52 / n;
while (q-- > 0) {
sum += DELTA;
e = (sum >> 2) & 3;
for (p = 0; p < n - 1; p++) y = v[p + 1], z = v[p] += MX;
y = v[0];
z = v[n - 1] += MX;
}
return 0;
}
else if (n < -1) { /* Decoding Part */
n = -n;
q = 6 + 52 / n;
sum = q * DELTA;
while (sum != 0) {
e = (sum >> 2) & 3;
for (p = n - 1; p > 0; p--) z = v[p - 1], y = v[p] -= MX;
z = v[n - 1];
y = v[0] -= MX;
sum -= DELTA;
}
return 0;
}
return 1;
}

int main()
{
long cipher[] = { 0,0 };
char cipher1[] = "Bingo!\x02\x02";
long key[] = { 0xE0C7E0C7, 0xC6F1D3D7, 0xC6D3C6D3, 0xC4D0D2CE };
int i = 0;
for (i = 0; i < 6; i++)
cipher1[i] ^= 0x17;
memcpy(cipher, cipher1, 8);
btea(cipher, 2, key);
char *b = (char *)cipher;
cout << "rctf{";
for (i = 0; i < 8; i++)
{
char c1 = *(b + i) >> 4 & 0xF;
char c2 = *(b + i) & 0xF;
if (c1 < 10)
cout << char(c1 + 0x30);
else
cout << char(c1 + 0x61 - 10);
if (c2 < 10)
cout << char(c2 + 0x30);
else
cout << char(c2 + 0x61 - 10);
}
cout << "}";
}

rctf{05e8a376e4e0446e}

babyre2

输入account,password,data。

还是xxtea,先用account作为key,加密一组常量。

password的每一位减去十位和个位,减去的结果作为下标从data取数据,得到data2.

用data2异或0xCC作为key密之前的密文。

于是直接构造account:'A'*16,data'8D'*256,password随便16位。

1
2
3
4
5
6
7
8
9
10
from pwn import *
p = process('./babyre2')
#p = remote('139.180.215.222','20000')
p.recvuntil('Please input the account:')
p.send('A'*16)
p.recvuntil('Please input the password:')
p.send('a'*16)
p.recvuntil('Please input the data:')
p.send('8D'*256)
p.interactive()

DontEatMe

开始有个反调试,直接跳过。

做的时候不清楚是啥加密,搜了一些常量也搜不到,于是自己逆。由于是Feistel密码结构,所以直接反向就可以了。

得到密文后,根据常量生成了一个迷宫,密文应是wasd来控制方向:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
1111111111111111
1000000000111111
1011111110111111
1011111110111111
101111000!000111
1011110111110111
1011110111110111
1011110000110111
1011111110110111
1011111110110111
10000>0000110111
1111101111110111
1111100000000111
1111111111111111
1111111111111111
1111111111111111

密文:

ddddwwwaaawwwddd

解密:

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
#include<pch.h>
#include<iostream>
using namespace std;
/*
unsigned int const0[] = { 0x459FC5A5, ... };
unsigned int const1[] = { 0x3B928883, ...};
unsigned int const2[] = { 0x5E476C95, ... };
unsigned int const3[] = { 0x0DA579091, ... };
unsigned int delta[] = { 0x0CDC56A63, ... };
*/

int main()
{
int i, j;
int a, b;
int tmp;
/*
//encrypt
int plain[] = { 0x11223344,0x55667788 };
a = plain[0];
b = plain[1];
for (i = 0; i < 16; i++)
{
unsigned int i0, i1, i2, i3;
tmp = delta[15-i] ^ a;
i0 = (tmp >> 24)&0xff;
i1 = (tmp >> 16) & 0xff;
i2 = (tmp >> 8) & 0xff;
i3 = tmp & 0xff;
a = b ^ (const3[i3] + (const2[i2] ^ (const1[i1] + const0[i0])));
b = tmp;
// cout<<hex << a <<' '<< b << endl;
}
b ^= 0xC12083C0;
a ^= 0x6809DCE2;
cout << hex << a << ' ' << b<<endl;
*/
//decrypt
int cipher[] = { 0x77646464, 0x61617777 ,0x77777761, 0x64646464 };
for (j = 1; j >= 0; j--)
{
a = cipher[j * 2];
b = cipher[j * 2 + 1];
a ^= 0x6809DCE2;
b ^= 0xC12083C0;
for (i = 0; i < 16; i++)
{
tmp = b;
unsigned int i0, i1, i2, i3;
i0 = (tmp >> 24) & 0xff;
i1 = (tmp >> 16) & 0xff;
i2 = (tmp >> 8) & 0xff;
i3 = tmp & 0xff;
b = a ^ (const3[i3] + (const2[i2] ^ (const1[i1] + const0[i0])));
a = tmp ^ delta[i];
}
cout << hex << a << b;
}
return 0;
}

RCTF{db824ef8605c5235b4bbacfa2ff8e087}

const和delta常量应该是开头某个的函数生成的,直接在调试过程中dump下来。

后面学习了一下密码算法,这是标准的blowfish算法,似乎当年是aes的备选算法之一。

asm

RISC-V架构。工具下载:https://github.com/riscv/riscv-gnu-toolchain

很大,慢慢下载。编译完总共3.6g...

指令手册没找到特别齐全的,官方的:http://crva.io/documents/RISC-V-Reader-Chinese-v2p1.pdf

讲的也不是特别细,没intel白皮书讲的那么详细,总之一条一条指令搜+连蒙带猜

用工具的objdump搞出汇编。一开始看到1w多行有点吓人,不过应该是静态编译的,所以很多都不用看。

先找主逻辑。strings一下发现有东西,能看到 flag plz 和%80s字符串。在010 editor中定位到字符串的位置在二进制文件的CF00处。结合反汇编的地址猜测偏移是0x10000,因此在寻找0x1cf00。刚好在0x101b6附近找到了0x1cf00的引用,以及0x1cf10的引用也找到了。

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
1017c:    000007b7            lui     a5,0x0
10180: 00078793 mv a5,a5
10184: cf99 beqz a5,0x101a2
10186: 0001f537 lui a0,0x1f
1018a: 1141 addi sp,sp,-16
1018c: 8c018593 addi a1,gp,-1856
10190: b8850513 addi a0,a0,-1144 # 0x1eb88
10194: e406 sd ra,8(sp)
10196: 00000097 auipc ra,0x0
1019a: 000000e7 jalr zero # 0x0
1019e: 60a2 ld ra,8(sp)
101a0: 0141 addi sp,sp,16
101a2: f6fff06f j 0x10110
101a6: df010113 addi sp,sp,-528
101aa: 20113423 sd ra,520(sp)
101ae: 20813023 sd s0,512(sp)
101b2: 0c00 addi s0,sp,528
101b4: 67f5 lui a5,0x1d
101b6: f0078513 addi a0,a5,-256 # 0x1cf00
101ba: 31c000ef jal ra,0x104d6 //printf?
101be: f8040793 addi a5,s0,-128
101c2: 85be mv a1,a5
101c4: 67f5 lui a5,0x1d
101c6: f1078513 addi a0,a5,-240 # 0x1cf10
101ca: 316000ef jal ra,0x104e0 //scanf
101ce: f8040793 addi a5,s0,-128
101d2: 853e mv a0,a5
101d4: 358000ef jal ra,0x1052c //? scanf?
101d8: 87aa mv a5,a0
101da: fef42423 sw a5,-24(s0) //len?
101de: fe042623 sw zero,-20(s0) // i
101e2: a041 j 0x10262

101e4: fec42783 lw a5,-20(s0)
101e8: ff040713 addi a4,s0,-16
101ec: 97ba add a5,a5,a4
101ee: f907c703 lbu a4,-112(a5)
101f2: fec42783 lw a5,-20(s0)
101f6: 2785 addiw a5,a5,1
101f8: 2781 sext.w a5,a5
101fa: 86be mv a3,a5
101fc: 47fd li a5,31
101fe: 02f6e7bb remw a5,a3,a5
10202: 2781 sext.w a5,a5
10204: ff040693 addi a3,s0,-16
10208: 97b6 add a5,a5,a3
1020a: f907c783 lbu a5,-112(a5)
1020e: 8fb9 xor a5,a5,a4
10210: 0ff7f793 andi a5,a5,255
10214: 0007869b sext.w a3,a5
10218: fec42703 lw a4,-20(s0)
1021c: 87ba mv a5,a4 //a4 = i
1021e: 0017979b slliw a5,a5,0x1 //
10222: 9fb9 addw a5,a5,a4 //
10224: 0057979b slliw a5,a5,0x5
10228: 9fb9 addw a5,a5,a4 //((((i<<1)+i)<<5)+i)
1022a: 2781 sext.w a5,a5
1022c: 873e mv a4,a5 // a4 = ((((i<<1)+i)<<5)+i)
1022e: 41f7579b sraiw a5,a4,0x1f //((((i<<1)+i)<<5)+i)>>0x1f
10232: 0187d79b srliw a5,a5,0x18 //((((((i<<1)+i)<<5)+i)>>0x1f)<<0x18)
10236: 9f3d addw a4,a4,a5 //((((((((i<<1)+i)<<5)+i)>>0x1f)<<0x18)+((((i<<1)+i)<<5)+i))&0xff)
10238: 0ff77713 andi a4,a4,255
1023c: 40f707bb subw a5,a4,a5
10240: 2781 sext.w a5,a5
10242: 8fb5 xor a5,a5,a3
10244: 0007871b sext.w a4,a5
10248: fec42783 lw a5,-20(s0)
1024c: 078a slli a5,a5,0x2 //i<<2
1024e: ff040693 addi a3,s0,-16
10252: 97b6 add a5,a5,a3 b[i<<2] =
10254: e0e7a023 sw a4,-512(a5)
10258: fec42783 lw a5,-20(s0)
1025c: 2785 addiw a5,a5,1
1025e: fef42623 sw a5,-20(s0)
10262: fec42703 lw a4,-20(s0)
10266: fe842783 lw a5,-24(s0)
1026a: 2701 sext.w a4,a4
1026c: 2781 sext.w a5,a5
1026e: f6f74be3 blt a4,a5,0x101e4

10272: fe042623 sw zero,-20(s0) //i = 0
10276: a825 j 0x102ae //
10278: fec42783 lw a5,-20(s0)
1027c: 078a slli a5,a5,0x2 //
1027e: ff040713 addi a4,s0,-16
10282: 97ba add a5,a5,a4
10284: e007a683 lw a3,-512(a5) //b[i]
10288: 0001f7b7 lui a5,0x1f
1028c: fec42703 lw a4,-20(s0)
10290: 070a slli a4,a4,0x2
10292: ba078793 addi a5,a5,-1120 # 0x1eba0
10296: 97ba add a5,a5,a4 //const[i]
10298: 439c lw a5,0(a5)
1029a: 8736 mv a4,a3
1029c: 00f70463 beq a4,a5,0x102a4
102a0: 4781 li a5,0
102a2: a025 j 0x102ca
102a4: fec42783 lw a5,-20(s0)
102a8: 2785 addiw a5,a5,1
102aa: fef42623 sw a5,-20(s0)
102ae: fec42703 lw a4,-20(s0)
102b2: fe842783 lw a5,-24(s0)
102b6: 2701 sext.w a4,a4
102b8: 2781 sext.w a5,a5
102ba: faf74fe3 blt a4,a5,0x10278

102be: 67f5 lui a5,0x1d
102c0: f1878513 addi a0,a5,-232 # 0x1cf18
102c4: 212000ef jal ra,0x104d6
102c8: 4781 li a5,0
102ca: 853e mv a0,a5
102cc: 20813083 ld ra,520(sp)
102d0: 20013403 ld s0,512(sp)
102d4: 21010113 addi sp,sp,528
102d8: 8082 ret

主逻辑并不长,慢慢看不难发现是两个循环,第一个加密,第二个对比。

另外提一句,最终对比常量的地址0x1eba0(objdump生成的)有问题,附近找一下应该是0x1dba0,即二进制文件中0xdba0的地方。

脚本:

1
2
3
4
5
6
7
cipher = [0x11, 0x76, 0xD0, 0x1E, 0x99, 0xB6, 0x2C, 0x91, 0x12, 0x45, 0xFB, 0x2A, 0x97, 0xC6, 0x63, 0xB8, 0x14, 0x7C, 0xE1, 0x1E, 0x83, 0xE6, 0x45, 0xA0, 0x19, 0x63, 0xDD, 0x32, 0xA4, 0xDF, 0x71]
plain = [ord('R')]
for i in range(30):
plain.append(0)
for i in range(30):
plain[i+1] = cipher[i]^plain[i]^(((((((((i<<1)+i)<<5)+i)>>0x1f)<<0x18)+((((i<<1)+i)<<5)+i))&0xff)-((((((i<<1)+i)<<5)+i)>>0x1f)<<0x18))
print(''.join(map(chr,plain)))

flag很秀:

RCTF{f5_is_not_real_reversing_}

所以真正的逆向应该是对着机器码逆向。

crack

通过字符串查找引用很容易找到主逻辑在sub_4025E0。

算法本质是这个问题:

https://projecteuler.net/problem=18

https://projecteuler.net/problem=67

总共有0x200*0x200行数据,每行的前n个元素是金字塔中对应元素,其余的元素根据输入的过程拼接起来变成一个函数,在00402762会被调用。

相加总和要为0x100758E540F。其实如果他没说这时最大值还真不好算。知道是要算最大值就好办了,可以用简单的动态规划来求出结果与过程。

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
from copy import deepcopy
f = open('data.mem','rb')
data = []
for i in range(0x200):
tmp = []
for j in range(0x200):
i1 = ord(f.read(1))
i2 = ord(f.read(1))
i3 = ord(f.read(1))
i4 = ord(f.read(1))
tmp.append((i4<<24)+(i3<<16)+(i2<<8)+i1)
data.append(tmp)
A = deepcopy(data)
B = ['' for i in range(len(A))]

for i in range(0,len(A)-1)[::-1]:
for j in range(i+1):
if A[i+1][j]>A[i+1][j+1]:
A[i][j]+=A[i+1][j]
B[i] += '0'
else:
A[i][j]+=A[i+1][j+1]
B[i] += '1'

print(hex(A[0][0]))
x = 0
y = 0
res = '0'
for x in range(0,0x1FF):
res+=B[x][y]
if B[x][y]=='1':
y+=1
print(res)
print(len(res))

得到512位的结果:

1
00000000010101000000000111100111111110100111100101001000101010010011101100111101011111111111111111001110111011011000000101110111001111100100011000000000000110001111110100000000001101110111010101011111000101110000011000111001110000000000000000000000011001000010000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000011100011111110000100111000000000000000000000000000000010000000000000001000001100000000000000101000000000100000010000000000000000010000000000000000000000

到这里还没完,进入第二部分。把之前生成的函数dump下来,分析一遍发现是个vm。bytecode就是搜字符串时的一大堆的一大堆01。实际上他把bytecode转成了六位二进制数。

写了个脚本解析了opcode:

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
code = '000000010101100100000000000000110000010000010110100000000011000000000000000000001100110000000000110000000000000000000000101000000000000000000000000000000000110000000000010000000000000000000000101000000000111000000000000000000000110000011000110000111000010010110000000000110000000000000000000000101000000000100000000000000000000000110000000000010000000000000000000000101000000000011000000000000000000000110000011000111000110100110000000000011000000000000000000000101000100000111000000000000000000000011000100000100000000000000000000000110100110000000000111000000000000000000000101000000000000000000000000000000000100110100000011000000000000000000000011000100000111000000000000000000000101100100000111111000100001011110000011010100000011011000011000000000000010110100000011000000000000000000000011000110000000000110000000000000000000000101000000000100000000000000000000000110000000000010000000000000000000000101000100000110100000000000000000000011000111000100010110000000000110100000000000000000000101000100000001100000000000000000000011000111000100010110000000000001100000000000000000000101000100000101100000000000000000000011000111000100010110000000000101100000000000000000000101000000000111000000000000000000000100000000000000000000000000000101000100000101100000000000000000000011000110000000000110000000000000000000000101000000000100000000000000000000000110000000000010000000000000000000000101000100000111000000000000000000000011000111000101010100000011011111001000000000000010110100000011000000000000000000000011000110000000000110000000000000000000000101000000000100000000000000000000000110000000000010000000000000000000000101000100000111000000000000000000000011000111000110100110000000000000010000000000000000000101000100000111000000000000000000000011000110000000000110000000000000000000000101000000000100000000000000000000000110000000000010000000000000000000000101000100000011100000000000000000000011000111000100100110000000000100010000000000000000000101000100000000010000000000000000000011000110000000000110000000000000000000000101000000000100000000000000000000000110000000000010000000000000000000000101000100000100010000000000000000000011000111000100010110000000000001000000000000000000000101000100000111000000000000000000000011000110000000000110000000000000000000000101000000000100000000000000000000000110000000000010000000000000000000000101000100000011100000000000000000000011000111000010100100000111000000000000000000000011000100000100000000000000000000000110100110000000000111000000000000000000000101000000000000001110010000000000000100110100000110100000000000000000000011000110000000000001000000000000000000000101000100000111100000000000000000000011000100000000000000000000000000000010100100000001100000000000000000000011000110000000000001000000000000000000000101000100000111100000000000000000000011000100000100000000000000000000000010100100000101100000000000000000000011000110000000000001000000000000000000000101000100000111100000000000000000000011000100000010000000000000000000000010100100000011100000000000000000000011000110000000000001000000000000000000000101000100000111100000000000000000000011000100000110000000000000000000000010100'
codes = []
i = 0
j = 0
while(i<len(code)):
op = eval('0b'+code[i:i+6][::-1])
i+=6
if op == 0:
num = eval('0b'+code[i:i+24][::-1])
print('mov r0, 0x%x'%num)
i+=24
elif op == 1:
num = eval('0b'+code[i:i+24][::-1])
print('mov r1, 0x%x'%num)
i+=24
elif op == 2:
print('mov r0, input[%d]'%j)
j+=1
elif op == 3:
print('mov r1, r0')
elif op == 4:
print('mov r3, r2')
elif op == 5:
print('if r0<128:')
print(' r[r0] = r1')
elif op == 6:
print('if r1<128:')
print(' r0 = r[r1]')
elif op == 7:
print('if r2<128:')
print(' r[r2] = r3')
elif op == 8:
print('if r3<128:')
print(' r2 = r[r3]')
elif op == 0xB:
print('add r0, r1')
elif op == 0xC:
print('sub r0, r1')
elif op == 0xD:
print('mul r0, r1')
elif op == 0xE:
print('div r0, r1')
elif op == 0xF:
print('and r0, r1')
elif op == 0x10:
print('or r0, r1')
elif op == 0x11:
print('xor r0, r1')
elif op == 0x12:
print('shl r0, r1')
elif op == 0x13:
print('shr r0, r1')
elif op == 0x14:
print('grate r0, r1')
elif op == 0x15:
print('below r0, r1')
elif op == 0x16:
print('equl r0, r1')
elif op == 0x17:
print('nequl r0, r1')
elif op == 0x18:
print('mov r0, ip')
elif op == 0x19:
print('mov ip, r0')
elif op == 0x1A:
print('cmp r0, 0')
print('je r1')
else:
print('?')

没有按照汇编标准写,因为里面有些if不知道干嘛的,可能是混淆。个别opcode也没搞懂是做什么的。

伪代码(未完成):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
mov r0, 0x26a
mov r1, r0
mov r0, input[0]
cmp r0, 0
je r1
mov r1, 0x30
sub r0, r1
mov r1, r0
mov r0, 0x3
if r0<128:
r[r0] = r1
mov r0, 0x0
mov r1, r0
mov r0, 0x2
if r0<128:
r[r0] = r1
mov r0, 0x7
mov r1, r0
if r1<128:
r0 = r[r1]
mov r1, r0
if r2<128:
r[r2] = r3
shl r0, r1
mov r1, r0
mov r0, 0x3
if r0<128:
r[r0] = r1
mov r0, 0x1
mov r1, r0
mov r0, 0x2
if r0<128:
r[r0] = r1
mov r0, 0x6
mov r1, r0
if r1<128:
r0 = r[r1]
if r2<128:
r[r2] = r3
add r0, r1
mov r1, r0
mov r0, 0x6
if r0<128:
r[r0] = r1
mov r1, 0x7
if r1<128:
r0 = r[r1]
mov r1, 0x1
add r0, r1
mov r1, r0
mov r0, 0x7
if r0<128:
r[r0] = r1
mov r0, 0x0
mov ip, r0
mov r1, 0x6
if r1<128:
r0 = r[r1]
mov r1, 0x7
mul r0, r1
mov r1, 0xf423f
equl r0, r1
mov r1, 0xc36
cmp r0, 0
je r1
mov r1, 0x6
if r1<128:
r0 = r[r1]
mov r1, r0
mov r0, 0x3
if r0<128:
r[r0] = r1
mov r0, 0x1
mov r1, r0
mov r0, 0x2
if r0<128:
r[r0] = r1
mov r1, 0xb
if r1<128:
r0 = r[r1]
if r2<128:
r[r2] = r3
xor r0, r1
mov r1, r0
mov r0, 0xb
if r0<128:
r[r0] = r1
mov r1, 0xc
if r1<128:
r0 = r[r1]
if r2<128:
r[r2] = r3
xor r0, r1
mov r1, r0
mov r0, 0xc
if r0<128:
r[r0] = r1
mov r1, 0xd
if r1<128:
r0 = r[r1]
if r2<128:
r[r2] = r3
xor r0, r1
mov r1, r0
mov r0, 0xd
if r0<128:
r[r0] = r1
mov r0, 0x7
mov r1, 0x0
if r0<128:
r[r0] = r1
mov r1, 0xd
if r1<128:
r0 = r[r1]
mov r1, r0
mov r0, 0x3
if r0<128:
r[r0] = r1
mov r0, 0x1
mov r1, r0
mov r0, 0x2
if r0<128:
r[r0] = r1
mov r1, 0x7
if r1<128:
r0 = r[r1]
if r2<128:
r[r2] = r3
below r0, r1
mov r1, 0x9f6
cmp r0, 0
je r1
mov r1, 0x6
if r1<128:
r0 = r[r1]
mov r1, r0
mov r0, 0x3
if r0<128:
r[r0] = r1
mov r0, 0x1
mov r1, r0
mov r0, 0x2
if r0<128:
r[r0] = r1
mov r1, 0x7
if r1<128:
r0 = r[r1]
if r2<128:
r[r2] = r3
add r0, r1
mov r1, r0
mov r0, 0x10
if r0<128:
r[r0] = r1
mov r1, 0x7
if r1<128:
r0 = r[r1]
mov r1, r0
mov r0, 0x3
if r0<128:
r[r0] = r1
mov r0, 0x1
mov r1, r0
mov r0, 0x2
if r0<128:
r[r0] = r1
mov r1, 0xe
if r1<128:
r0 = r[r1]
if r2<128:
r[r2] = r3
?
mov r1, r0
mov r0, 0x11
if r0<128:
r[r0] = r1
mov r1, 0x10
if r1<128:
r0 = r[r1]
mov r1, r0
mov r0, 0x3
if r0<128:
r[r0] = r1
mov r0, 0x1
mov r1, r0
mov r0, 0x2
if r0<128:
r[r0] = r1
mov r1, 0x11
if r1<128:
r0 = r[r1]
if r2<128:
r[r2] = r3
xor r0, r1
mov r1, r0
mov r0, 0x4
if r0<128:
r[r0] = r1
mov r1, 0x7
if r1<128:
r0 = r[r1]
mov r1, r0
mov r0, 0x3
if r0<128:
r[r0] = r1
mov r0, 0x1
mov r1, r0
mov r0, 0x2
if r0<128:
r[r0] = r1
mov r1, 0xe
if r1<128:
r0 = r[r1]
if r2<128:
r[r2] = r3
?
mov r1, 0x7
if r1<128:
r0 = r[r1]
mov r1, 0x1
add r0, r1
mov r1, r0
mov r0, 0x7
if r0<128:
r[r0] = r1
mov r0, 0x4e0
mov ip, r0
mov r1, 0xb
if r1<128:
r0 = r[r1]
mov r1, r0
mov r0, 0x4
if r0<128:
r[r0] = r1
mov r1, 0xf
if r1<128:
r0 = r[r1]
mov r1, 0x0
?
mov r1, 0xc
if r1<128:
r0 = r[r1]
mov r1, r0
mov r0, 0x4
if r0<128:
r[r0] = r1
mov r1, 0xf
if r1<128:
r0 = r[r1]
mov r1, 0x1
?
mov r1, 0xd
if r1<128:
r0 = r[r1]
mov r1, r0
mov r0, 0x4
if r0<128:
r[r0] = r1
mov r1, 0xf
if r1<128:
r0 = r[r1]
mov r1, 0x2
?
mov r1, 0xe
if r1<128:
r0 = r[r1]
mov r1, r0
mov r0, 0x4
if r0<128:
r[r0] = r1
mov r1, 0xf
if r1<128:
r0 = r[r1]
mov r1, 0x3
?

关键在前面有个乘法和对比,猜一下应该是输入后面再接一个二进制数,此数*7后等于0xf423f,即0x22e09 = 0b100010111000001001。测试一下是按照大端序的,即是100100000111010001,接在之前的512位后面就是最后的输入了。

flag画在一张图事实上。

13yR01sw3iy1l1n9

sourceguardian

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
#include<pch.h>
#include<iostream>

using namespace std;
#define MX ((z>>5^y<<2) + (y>>3^z<<4) ^ (sum^y) + (k[p&3^e]^z))

long btea(long* v, long n, long* k) {
unsigned long z = v[n - 1], y = v[0], sum = 0, e, DELTA = 0x9e3779b9;
long p, q;
if (n > 1) { /* Coding Part */
q = 6 + 52 / n;
while (q-- > 0) {
sum += DELTA;
e = (sum >> 2) & 3;
for (p = 0; p < n - 1; p++) y = v[p + 1], z = v[p] += MX;
y = v[0];
z = v[n - 1] += MX;
}
return 0;
}
else if (n < -1) { /* Decoding Part */
n = -n;
q = 6 + 52 / n;
sum = q * DELTA;
while (sum != 0) {
e = (sum >> 2) & 3;
for (p = n - 1; p > 0; p--) z = v[p - 1], y = v[p] -= MX;
z = v[n - 1];
y = v[0] -= MX;
sum -= DELTA;
}
return 0;
}
return 1;
}

int main()
{
long cipher[] = { 1029560848, 2323109303, 4208702724, 3423862500, 3597800709, 2222997091, 4137082249, 2050017171, 4045896598 ,0};
long key[] = { 1752186684, 1600069744, 1953259880, 1836016479 };
long k[] = { 1752186684, 1600069744, 1953259880, 1836016479 };
int i = 0;
for (i = 0; i < 9; i++)
{
cipher[i] ^= key[i % 4];
}
btea(cipher, -9, key);
cout << (char*)cipher << endl;
}