SHELL CTF 2022
SHELL CTF 2022 writeups
Sanity Check
10 points
Problem Description
- Check the #announcement channel of the discord server.
Solution
Found the flag in the discord server
How to defeat a dragon
100 points
Problem Description
- Dragonairre,the dragon with the hexadecimal head has attacked the village to take revenge on his last defeat,we need to get the ultimate weapon. Flag Format : SHELLCTF{}.
Given File
vault
Solution
Check file
Disassemble & Decompile & Reverse
main
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
58undefined8 main(void)
{
long in_FS_OFFSET;
int local_7c;
undefined8 local_78;
undefined8 local_70;
undefined8 local_68;
undefined8 local_60;
undefined8 local_58;
undefined8 local_50;
undefined8 local_48;
undefined8 local_40;
undefined8 local_38;
undefined8 local_30;
undefined8 local_28;
undefined8 local_20;
undefined4 local_18;
long local_10;
local_10 = *(long *)(in_FS_OFFSET + 0x28);
local_78 = 0x4654434c4c454853;
local_70 = 0x343534383433357b;
local_68 = 0x3434353334633463;
local_60 = 0x3535333133623736;
local_58 = 0x3336373333323566;
local_50 = 0x3631333533323733;
local_48 = 0x3333336635373665;
local_40 = 0x3766333937333734;
local_38 = 0x7d64;
local_30 = 0;
local_28 = 0;
local_20 = 0;
local_18 = 0;
printf("Help us defeat the dragon!! Enter the code:");
__isoc99_scanf(&DAT_00102034,&local_7c);
if (local_7c == 0x10f2c) {
printf("Yeahh!!,we did it,We defeated the dragon.Thanks for your help here\'s your reward : %s",
&local_78);
}
else {
if (local_7c == 0x45) {
printf("Nice,but this is not the code :(.");
}
else {
if (local_7c == 0x1a4) {
printf("Bruh!! Seriously?");
}
else {
printf("wron..aaaaaahhhhhhhh");
}
}
}
if (local_10 != *(long *)(in_FS_OFFSET + 0x28)) {
/* WARNING: Subroutine does not return */
__stack_chk_fail();
}
return 0;
}
We need to satisfy
(local_7c == 0x10f2c)
to get the flag.0x10f2c = 69420
Enter
69420
to get the flagConvert the numbers from hex to string to get the real flag
warmup
100 points
Problem Descrition
Here's a quick rev challenge to get started. Reverse the binary to obtain the flag.
The flag format is shellctf{...}
Given File
warmup
Solution
Check file
Disassemble & Decompile & Reverse
main
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
63undefined8 main(void)
{
size_t input_str_len;
long in_FS_OFFSET;
int i;
int maybe_real_flag [28];
char input_flag [40];
long local_10;
bool check_valid_flag;
local_10 = *(long *)(in_FS_OFFSET + 0x28);
printf("enter the flag: ");
__isoc99_scanf(&DAT_00102015,input_flag);
input_str_len = strlen(input_flag);
if (input_str_len == 0x1b) {
maybe_real_flag[0] = 0x1cc;
maybe_real_flag[1] = 0x1a0;
maybe_real_flag[2] = 0x194;
maybe_real_flag[3] = 0x1b0;
maybe_real_flag[4] = 0x1b0;
maybe_real_flag[5] = 0x18c;
maybe_real_flag[6] = 0x1d0;
maybe_real_flag[7] = 0x198;
maybe_real_flag[8] = 0x1ec;
maybe_real_flag[9] = 0x188;
maybe_real_flag[10] = 0xc4;
maybe_real_flag[11] = 0x1d0;
maybe_real_flag[12] = 0x15c;
maybe_real_flag[13] = 0x1a4;
maybe_real_flag[14] = 0xd4;
maybe_real_flag[15] = 0x194;
maybe_real_flag[16] = 0x17c;
maybe_real_flag[17] = 0xc0;
maybe_real_flag[18] = 0x1c0;
maybe_real_flag[19] = 0xcc;
maybe_real_flag[20] = 0x1c8;
maybe_real_flag[21] = 0x104;
maybe_real_flag[22] = 0x1d0;
maybe_real_flag[23] = 0xc0;
maybe_real_flag[24] = 0x1c8;
maybe_real_flag[25] = 0x14c;
maybe_real_flag[26] = 500;
check_valid_flag = true;
for (i = 0; i < 0x1b; i = i + 1) {
check_valid_flag = (bool)(check_valid_flag & maybe_real_flag[i] >> 2 == (int)input_flag[i]);
}
if (check_valid_flag) {
puts("yes, that\'s it");
}
else {
puts("nah that\'s not it");
}
}
else {
puts("wrong length");
}
if (local_10 != *(long *)(in_FS_OFFSET + 0x28)) {
/* WARNING: Subroutine does not return */
__stack_chk_fail();
}
return 0;
}
check_valid_flag
must be true if the flag is valid.get_flag.py
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
40from pwn import *
p = process("./warmup")
input_str = b""
input_str += bytes(chr(0x1cc >> 2), 'ascii')
input_str += bytes(chr(0x1a0 >> 2), 'ascii')
input_str += bytes(chr(0x194 >> 2), 'ascii')
input_str += bytes(chr(0x1b0 >> 2), 'ascii')
input_str += bytes(chr(0x1b0 >> 2), 'ascii')
input_str += bytes(chr(0x18c >> 2), 'ascii')
input_str += bytes(chr(0x1d0 >> 2), 'ascii')
input_str += bytes(chr(0x198 >> 2), 'ascii')
input_str += bytes(chr(0x1ec >> 2), 'ascii')
input_str += bytes(chr(0x188 >> 2), 'ascii')
input_str += bytes(chr(0xc4 >> 2), 'ascii')
input_str += bytes(chr(0x1d0 >> 2), 'ascii')
input_str += bytes(chr(0x15c >> 2), 'ascii')
input_str += bytes(chr(0x1a4 >> 2), 'ascii')
input_str += bytes(chr(0xd4 >> 2), 'ascii')
input_str += bytes(chr(0x194 >> 2), 'ascii')
input_str += bytes(chr(0x17c >> 2), 'ascii')
input_str += bytes(chr(0xc0 >> 2), 'ascii')
input_str += bytes(chr(0x1c0 >> 2), 'ascii')
input_str += bytes(chr(0xcc >> 2), 'ascii')
input_str += bytes(chr(0x1c8 >> 2), 'ascii')
input_str += bytes(chr(0x104 >> 2), 'ascii')
input_str += bytes(chr(0x1d0 >> 2), 'ascii')
input_str += bytes(chr(0xc0 >> 2), 'ascii')
input_str += bytes(chr(0x1c8 >> 2), 'ascii')
input_str += bytes(chr(0x14c >> 2), 'ascii')
input_str += bytes(chr(500 >> 2), 'ascii')
print(b"input_str: " + input_str)
p.send(input_str + b"\n")
print(p.recvline())
p.interactive()Run
get_flag.py
and get the flag
tea
268 points
Problem Description
- It's tea time. The flag format is shellctf{...}
Given File
tea
Solution
Check file
Disassemble & Decompile & Reverse
main
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17undefined8 main(void)
{
size_t sVar1;
boilWater();
sVar1 = strlen(pwd);
if (sVar1 == 0x20) {
addSugar();
addTea();
addMilk();
strainAndServe();
}
else {
puts("wrong length");
}
return 0;
}boilWater
1
2
3
4
5
6void boilWater(void)
{
printf("Enter the flag: ");
__isoc99_scanf(&DAT_00102019,pwd);
return;
}addSugar
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
40void addSugar(void)
{
size_t pwd_len;
long in_FS_OFFSET;
uint i;
char pwd_part2_sugar;
undefined8 local_50;
undefined local_48;
char pwd_part1;
undefined8 local_30;
undefined local_28;
long local_20;
local_20 = *(long *)(in_FS_OFFSET + 0x28);
_pwd_part2_sugar = 0;
local_50 = 0;
local_48 = 0;
_pwd_part1 = 0;
local_30 = 0;
local_28 = 0;
i = 0;
while( true ) {
pwd_len = strlen(pwd);
if (pwd_len <= (ulong)(long)(int)i) break;
if ((i & 1) == 0) {
strncat(&pwd_part1,pwd + (int)i,1);
}
else {
strncat(&pwd_part2_sugar,pwd + (int)i,1);
}
i = i + 1;
}
strncat(&pwd_part2_sugar,&pwd_part1,0x11);
strcpy(pwd,&pwd_part2_sugar);
if (local_20 != *(long *)(in_FS_OFFSET + 0x28)) {
/* WARNING: Subroutine does not return */
__stack_chk_fail();
}
return;
}addTea
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
47void addTea(void)
{
size_t pwd_len;
ulong cur_index;
long in_FS_OFFSET;
char cal_val;
int i;
int half_pwd_len_16;
undefined8 pwd_part_tea;
undefined8 local_40;
undefined8 local_38;
undefined8 local_30;
undefined local_28;
long local_20;
local_20 = *(long *)(in_FS_OFFSET + 0x28);
pwd_part_tea = 0;
local_40 = 0;
local_38 = 0;
local_30 = 0;
local_28 = 0;
i = 0;
while( true ) {
cur_index = (ulong)i;
pwd_len = strlen(pwd);
if (pwd_len >> 1 <= cur_index) break;
cal_val = (char)(i / 2) * -3 + pwd[i];
strncat((char *)&pwd_part_tea,&cal_val,1);
i = i + 1;
}
pwd_len = strlen(pwd);
half_pwd_len_16 = (int)(pwd_len >> 1);
while( true ) {
cur_index = (ulong)half_pwd_len_16;
pwd_len = strlen(pwd);
if (pwd_len <= cur_index) break;
cal_val = (char)(half_pwd_len_16 / 6) + pwd[half_pwd_len_16];
strncat((char *)&pwd_part_tea,&cal_val,1);
half_pwd_len_16 = half_pwd_len_16 + 1;
}
strcpy(pwd,(char *)&pwd_part_tea);
if (local_20 != *(long *)(in_FS_OFFSET + 0x28)) {
/* WARNING: Subroutine does not return */
__stack_chk_fail();
}
return;
}addMilk
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
59void addMilk(void)
{
size_t pwd_len;
long in_FS_OFFSET;
int i;
char pwd_part1_milk;
undefined8 local_a0;
undefined8 local_98;
undefined8 local_90;
undefined local_88;
char pwd_part2_milk;
undefined8 local_70;
undefined8 local_68;
undefined8 local_60;
undefined local_58;
char pwd_part_milk;
undefined8 local_40;
undefined8 local_38;
undefined8 local_30;
undefined local_28;
long local_20;
local_20 = *(long *)(in_FS_OFFSET + 0x28);
_pwd_part1_milk = 0;
local_a0 = 0;
local_98 = 0;
local_90 = 0;
local_88 = 0;
_pwd_part2_milk = 0;
local_70 = 0;
local_68 = 0;
local_60 = 0;
local_58 = 0;
_pwd_part_milk = 0;
local_40 = 0;
local_38 = 0;
local_30 = 0;
local_28 = 0;
for (i = 0; (pwd[i] != '5' && (pwd_len = strlen(pwd), (ulong)(long)i < pwd_len)); i = i + 1) {
strncat(&pwd_part1_milk,pwd + i,1);
}
for (; (pwd[i] != 'R' && (pwd_len = strlen(pwd), (ulong)(long)i < pwd_len)); i = i + 1) {
strncat(&pwd_part2_milk,pwd + i,1);
}
for (; pwd_len = strlen(pwd), (ulong)(long)i < pwd_len; i = i + 1) {
strncat(&pwd_part_milk,pwd + i,1);
}
pwd_len = strlen(&pwd_part1_milk);
strncat(&pwd_part_milk,&pwd_part1_milk,pwd_len);
pwd_len = strlen(&pwd_part2_milk);
strncat(&pwd_part_milk,&pwd_part2_milk,pwd_len);
strcpy(pwd,&pwd_part_milk);
if (local_20 == *(long *)(in_FS_OFFSET + 0x28)) {
return;
}
/* WARNING: Subroutine does not return */
__stack_chk_fail();
}strainAndServe
1
2
3
4
5
6
7
8
9
10
11
12
13void strainAndServe(void)
{
int iVar1;
iVar1 = strcmp("R;crc75ihl`cNYe`]m%50gYhugow~34i",pwd);
if (iVar1 == 0) {
puts("yep, that\'s right");
}
else {
puts("nope, that\'s not it");
}
return;
}
User input will become
R;crc75ihl`cNYe`]m%50gYhugow~34i
if it is the right flag1
2
3
4
5flag ---- [addSugar] ---> flag2
flag2 --- [addTea] -----> flag3
flag3 --- [addMilk] ----> flag4
flag4 is R;crc75ihl`cNYe`]m%50gYhugow~34iWe need to reverse the operations in
addMilk
,addTea
,addSugar
.There is a problem. There are several answers when reversing the operations in
addMilk
.In
addMilk
, the program splits flag3 into 3 part and reassembly the parts to generate flag41
2
3
4
5part1: String with no '5'.
part2: String starts with '5' and with no 'R'
part3: String starts with 'R'
flag4 = ( part3 + part1 + part2 )Notice that flag4 is just simply move part3 to the front. The length of part2 is knowned. If we know the length of part3, we can calculate the length of part1 immediately. So we can brute force part3's length.
Why the length of part2 is knowned? Because (part1 + part2) is not modified. If we found a '5' in (part1 + part2), that '5' must be the start of part2. A the end of part2 is the end of flag4 , obviously.
reverse_get_flag.py
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
67final_pwd_str = 'R;crc75ihl`cNYe`]m%50gYhugow~34i'
pwd_len = len(final_pwd_str)
print("final_pwd_str: " + final_pwd_str)
print("len(final_pwd_str): " + str(pwd_len))
for len_guess in range(32):
pwd_milk_str1 = ""
pwd_milk_str2 = ""
pwd_milk_str3 = ""
pwd_milk_str3_len_guess = len_guess
i = 0
if i < pwd_len:
if final_pwd_str[i] == 'R':
while i < pwd_milk_str3_len_guess:
pwd_milk_str3 += final_pwd_str[i]
i = i + 1
while i < pwd_len and final_pwd_str[i] != '5':
pwd_milk_str1 += final_pwd_str[i]
i = i + 1
if i < pwd_len:
if final_pwd_str[i] == '5':
while i < pwd_len:
pwd_milk_str2 += final_pwd_str[i]
i = i + 1
# print("pwd_milk_str: " + pwd_milk_str1 + " " + pwd_milk_str2 + " " + pwd_milk_str3)
# print("len: " + str(len(pwd_milk_str1)) + " " + str(len(pwd_milk_str2)) + " " + str(len(pwd_milk_str3)))
# print("total len: " + str(len(pwd_milk_str1) + len(pwd_milk_str2) + len(pwd_milk_str3)))
# print("\n---\n")
milk_pwd_str = pwd_milk_str1 + pwd_milk_str2 + pwd_milk_str3
pwd_tea_str1 = milk_pwd_str[0:16]
pwd_tea_str2 = milk_pwd_str[16:32]
# print(pwd_tea_str1 + pwd_tea_str2)
i = 0
while i < 16:
pwd_tea_str1 = pwd_tea_str1[0:i] + chr(ord(pwd_tea_str1[i]) + (i // 2) * 3) + pwd_tea_str1[i+1:16]
i = i + 1
i = 0
while i < 16:
pwd_tea_str2 = pwd_tea_str2[0:i] + chr(ord(pwd_tea_str2[i]) - ((16 + i) // 6)) + pwd_tea_str2[i+1:16]
i = i + 1
# print(pwd_tea_str1 + " " + pwd_tea_str2)
# print("\n---\n")
tea_pwd_str = pwd_tea_str1 + pwd_tea_str2
flag_list = []
for i in range(32):
flag_list.append("?")
pwd_sugar_odd = tea_pwd_str[0:16]
pwd_sugar_even = tea_pwd_str[16:32]
# fill odd
for i in range(16):
flag_list[2 * i + 1] = pwd_sugar_odd[i]
# fill even
for i in range(16):
flag_list[2 * i] = pwd_sugar_even[i]
print(''.join(flag_list))Run
reverse_get_flag.py
and grep the flag
Alien Communication
100 points
Problem Description
- Aliens are trying to communicate something. They belive in seeing more than what they are hearing. can you help us trying to decode what they are trying to say?
Given File
Alien_voice.wav
Solution
Seems like morse code, so throw the file to online morse code decoder: https://morsecode.world/international/decoder/audio-decoder-adaptive.html
Then we can get the flag
Tweeeet
100 points
Problem Description
What are they trying to say?
Flag Format: SHELL{SOMETHINGHERE}
Given File
image.jpeg
Solution
Open
image.jpeg
and we can see birds...Go to birds-on-a-wire-cipher online decoder ( https://www.dcode.fr/birds-on-a-wire-cipher ) and get the flag
Tring Tring....
100 points
Problem Description
Tring Tring my mobile started ringing. "Hey Check your SMS!!"
----. ----. ----. / -.... -.... -.... / ---.. ---.. / ..--- ..--- ..--- / ..--- / -.... -.... / --... --... --... / ...-- ...-- / ..--- / ...-- / -.... / ----. ----. ----. / --... --... --... --... / -.... / --... --... --... --...
Flag Format: SHELL{SOMETHINGHERE}
Solution
Morse code decode ( https://morsecode.world/international/translator.html )
Multi-tap Phone (SMS) ( https://www.dcode.fr/multitap-abc-cipher )
OX9OR2
200 points
Problem Description
Given File
encrypted
encryption.py
Solution
encrypted
in hexencryption.py
code1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17def xor(msg, key):
o = ''
for i in range(len(msg)):
o += chr(ord(msg[i]) ^ ord(key[i % len(key)]))
return o
with open('message', 'r') as f:
msg = ''.join(f.readlines()).rstrip('\n')
with open('key', 'r') as k:
key = ''.join(k.readlines()).rstrip('\n')
assert key.isalnum() and (len(key) == 9)
assert 'SHELL' in msg
with open('encrypted', 'w') as fo:
fo.write(xor(msg, key))SHELL
is in msg --> maybeSHELL{
?We now know
6/9
of the key! And the key isXORISC
+ (3 char).The key seems like XOR IS C??? .
We can use a list of common words which starts with
C
to brute force the right key and get the flag.getenc.py
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
33import re
enc = [0x0B ,0x07 ,0x17 ,0x05 ,0x1F ,0x38 ,0x17 ,0x7F ,0x1E ,0x07 ,0x7E ,0x01 ,0x16 ,0x01 ,0x70 ,0x19 ,0x2A ,0x1E ,0x6D ,0x7E ,0x10 ,0x05 ,0x60 ,0x3E]
dec = ['?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?']
c_dict = ['cabin', 'cabinet', 'cable', 'cake', 'calculate', 'call', 'camera', 'camp', 'campaign', 'campus', 'can', 'Canadian', 'cancer', 'candidate', 'cap', 'capability', 'capable', 'capacity', 'capital', 'captain', 'capture', 'car', 'carbon', 'card', 'care', 'career', 'careful', 'carefully', 'carrier', 'carry', 'case', 'cash', 'cast', 'cat', 'catch', 'category', 'Catholic', 'cause', 'ceiling', 'celebrate', 'celebration', 'celebrity', 'cell', 'center', 'central', 'century', 'CEO', 'ceremony', 'certain', 'certainly', 'chain', 'chair', 'chairman', 'challenge', 'chamber', 'champion', 'championship', 'chance', 'change', 'changing', 'channel', 'chapter', 'character', 'characteristic', 'characterize', 'charge', 'charity', 'chart', 'chase', 'cheap', 'check', 'cheek', 'cheese', 'chef', 'chemical', 'chest', 'chicken', 'chief', 'child', 'childhood', 'Chinese', 'chip', 'chocolate', 'choice', 'cholesterol', 'choose', 'Christian', 'Christmas', 'church', 'cigarette', 'circle', 'circumstance', 'cite', 'citizen', 'city', 'civil', 'civilian', 'claim', 'class', 'classic', 'classroom', 'clean', 'clear', 'clearly', 'client', 'climate', 'climb', 'clinic', 'clinical', 'clock', 'close', 'closely', 'closer', 'clothes', 'clothing', 'cloud', 'club', 'clue', 'cluster', 'coach', 'coal', 'coalition', 'coast', 'coat', 'code', 'coffee', 'cognitive', 'cold', 'collapse', 'colleague', 'collect', 'collection', 'collective', 'college', 'colonial', 'color', 'column', 'combination', 'combine', 'come', 'comedy', 'comfort', 'comfortable', 'command', 'commander', 'comment', 'commercial', 'commission', 'commit', 'commitment', 'committee', 'common', 'communicate', 'communication', 'community', 'company', 'compare', 'comparison', 'compete', 'competition', 'competitive', 'competitor', 'complain', 'complaint', 'complete', 'completely', 'complex', 'complicated', 'component', 'compose', 'composition', 'comprehensive', 'computer', 'concentrate', 'concentration', 'concept', 'concern', 'concerned', 'concert', 'conclude', 'conclusion', 'concrete', 'condition', 'conduct', 'conference', 'confidence', 'confident', 'confirm', 'conflict', 'confront', 'confusion', 'Congress', 'congressional', 'connect', 'connection', 'consciousness', 'consensus', 'consequence', 'conservative', 'consider', 'considerable', 'consideration', 'consist', 'consistent', 'constant', 'constantly', 'constitute', 'constitutional', 'construct', 'construction', 'consultant', 'consume', 'consumer', 'consumption', 'contact', 'contain', 'container', 'contemporary', 'content', 'contest', 'context', 'continue', 'continued', 'contract', 'contrast', 'contribute', 'contribution', 'control', 'controversial', 'controversy', 'convention', 'conventional', 'conversation', 'convert', 'conviction', 'convince', 'cook', 'cookie', 'cooking', 'cool', 'cooperation', 'cop', 'cope', 'copy', 'core', 'corn', 'corner', 'corporate', 'corporation', 'correct', 'correspondent', 'cost', 'cotton', 'couch', 'could', 'council', 'counselor', 'count', 'counter', 'country', 'county', 'couple', 'courage', 'course', 'court', 'cousin', 'cover', 'coverage', 'cow', 'crack', 'craft', 'crash', 'crazy', 'cream', 'create', 'creation', 'creative', 'creature', 'credit', 'crew', 'crime', 'criminal', 'crisis', 'criteria', 'critic', 'critical', 'criticism', 'criticize', 'crop', 'cross', 'crowd', 'crucial', 'cry', 'cultural', 'culture', 'cup', 'curious', 'current', 'currently', 'curriculum', 'custom', 'customer', 'cut', 'cycle']
key_len = 9
# flag prefix
str_known = "SHELL{"
for i in range(len(str_known)):
dec[i] = str_known[i]
keey = ""
for i in range(len(str_known)):
keey += chr(enc[i] ^ ord(dec[i]))
str_unknown_len = key_len - len(str_known)
for i in range(str_unknown_len):
keey += "?"
print(keey)
for j in range(len(c_dict)):
if len(c_dict[j]) != (str_unknown_len + 1):
continue
keey = keey[:-4] + c_dict[j].upper()
for i in range(len(dec)):
dec[i] = chr(enc[i] ^ ord(keey[i % key_len]))
if re.search("^SHELL{[0-9A-Za-z_]+}$", ''.join(dec)):
print(''.join(dec) + " , " + keey)Run
getenc.py
and find the flag