The InfoSecurity Challenge 2023
Writeup on The InfoSecurity Challenge 2023.
Level 1: Disk Archaeology
Unknown to the world, the sinister organization PALINDROME has been crafting a catastrophic malware that threatens to plunge civilization into chaos. Your mission, if you choose to accept it, is to infiltrate their secret digital lair, a disk image exfiltrated by our spies. This disk holds the key to unraveling their diabolical scheme and preventing the unleashing of a suspected destructive virus.
You will be provided with the following file:
md5(challenge.tar.xz) = 80ff51568943a39de4975648e688d6a3
Notes:
challenge.tar.xz
decompresses intochallenge.img
- FLAG FORMAT is
TISC{<some text you have to find>}
Downloadable File SHA256 checksum challenge.tar.xz 49d54865399dac9d03158a057b643f3691cd23d430d869714aff5c9b34e01aa2
Downloaded challenge.tar.xz
and performed some processing.
1
2
3
4
5
6
$ md5sum challenge.tar.xz
80ff51568943a39de4975648e688d6a3 challenge.tar.xz
$ tar -xvf challenge.tar.xz
challenge.img
$ md5sum challenge.img
8446ba456d81d8403a37e06fe7ebd8f8 challenge.img
Added challenge.img
in FTK Imager as evidence item and saw that it was Linux filesystem.
Performed strings
with grep
to do a quick search, but was tricked with a fake flag.
1
2
$ strings challenge.img | grep -i "TISC"
TISC{w4s_th3r3_s0m3th1ng_l3ft_%s}
Guessed that %s
may be referring to a string variable
. Explored the directories in hope of finding some program or script, but was unsuccessful.
Moved on to perform file carving using PhotoRec
to recover files from unallocated space.
1
$ sudo photorec challenge.img
Selected Disk challenge.img
for media, P ext4
for Partition, [ext2/ext3]
for filesystem type and Free
to scan for file from ext2/ext3 unallocated space only.
Recovery completed and f1315992.elf
was obtained.
1
2
$ md5sum f1315992.elf
fc344b7f694e727f06bc6dc0ed4ba402 f1315992.elf
Ran f1315992.elf
and encountered error. The file is in the directory though.
1
2
$ ./f1315992.elf
-bash: ./f1315992.elf: No such file or directory
Checked further and realised the problem is lack of interpreter.
1
2
$ readelf -a f1315992.elf | grep -i "interpreter"
[Requesting program interpreter: /lib/ld-musl-x86_64.so.1]
Found ld-musl-x86_64.so.1
in challenge.img
and exported it.
Moved ld-musl-x86_64.so.1
to /lib
of my VM and ran f1315992.elf
again.
1
2
3
$ sudo mv ld-musl-x86_64.so.1 /lib
$ ./f1315992.elf
TISC{w4s_th3r3_s0m3th1ng_l3ft_ubrekeslydsqdpotohujsgpzqiojwzfq}
Flag: TISC{w4s_th3r3_s0m3th1ng_l3ft_ubrekeslydsqdpotohujsgpzqiojwzfq}
Level 2: XIPHEREHPIX’s Reckless Mistake
Our sources told us that one of PALINDROME’s lieutenants, XIPHEREHPIX, wrote a special computer program for certain members of PALINDROME. We have somehow managed to get a copy of the source code and the compiled binary. The intention of the program is unclear, but we think encrypted blob inside the program could contain a valuable secret.
Downloadable File SHA256 checksum prog.c e06e901befa4cd1d9397a30d8e4418ac096539000057f92624e3d38d808a7ced XIPHEREHPIX 5e9639909fbe874b3c15a3c86c35c1fe3007c203e369b95a19677e78e4ad8284
Interacted with the program.
1
2
3
4
5
6
$ ./XIPHEREHPIX
Hello PALINDROME member, please enter password:
The password should be at least 40 characters as per PALINDROME's security policy.
$ ./XIPHEREHPIX
Hello PALINDROME member, please enter password:
Failure!
Reviewed the source code provided and used ChatGPT
to explain the various code functions.
Observed that initialise_key()
may be vulnerable.
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
void initialise_key(unsigned char *key, char *password, int password_length) {
const char *seed = "PALINDROME IS THE BEST!";
int i, j;
int counter = 0;
uint256_t *key256 = (uint256_t *)key;
key256->a0 = 0;
key256->a1 = 0;
key256->a2 = 0;
key256->a3 = 0;
uint256_t arr[20] = { 0 };
calculate_sha256((unsigned char *) arr, (unsigned char *) seed, strlen(seed));
for (i = 1; i < 20; i++) {
calculate_sha256((unsigned char *)(arr+i), (unsigned char *) (arr+i-1), 32);
}
for (i = 0; i < password_length; i++) {
int ch = password[i];
for (j = 0; j < 8; j++) {
counter = counter % 20;
if (ch & 0x1) {
accumulate_xor(key256, arr+counter);
}
ch = ch >> 1;
counter++;
}
}
}
Summarising the weakness found in initialise_key()
:
- Regardless of the password length, only the first three printable and non-printable ASCII characters matters.
- To be more specific, only the first 20 bits truly matters.
- The 20
arr
elements are being XORed with thekey256
elements under certain conditions. - As XOR is an involutory function - i.e. its own inverse, there can only be two outcomes.
- This restricts the number of possible outcomes resulting from performing multiple XOR operations with 20
arr
elements to2^20 = 1048576
. - By testing all combinations of 24 bits in 3 character array form as
password
, decryption can be achieved via brute-force method within reasonable time.
Used ChatGPT
to write a loop in C to generate all possible combinations of 24 bits and convert them into a 3 character array, then combine the loop with main()
.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
int main(int argc, char **argv) {
char password[MAX_PASSWORD_SIZE + 1] = { 0 };
int password_length;
unsigned char key[32];
password_length = 3;
for (unsigned int i = 0; i < (1 << 24); i++) {
// Convert the 24-bit value to a 3-character array
char password[4]; // 3 characters + null terminator
// Extract each 8-bit portion
password[0] = (i >> 16) & 0xFF;
password[1] = (i >> 8) & 0xFF;
password[2] = i & 0xFF;
password[3] = '\0'; // Null-terminate the string
initialise_key(key, password, password_length);
show_welcome_msg(key);
}
}
Modified show_welcome_message()
to print only if plaintext
contains TISC
and exit program.
1
2
3
4
if (strstr(plaintext,"TISC") != NULL) {
printf("Welcome PALINDROME member. Your secret message is %.*s\n", plaintext_length, plaintext);
exit(1);
}
Installed libssl-dev
.
1
sudo apt-get install libssl-dev
Compiled the edited c code.
1
gcc -o prog prog.c -lssl -lcrypto
Ran prog
.
1
2
./prog
Welcome PALINDROME member. Your secret message is TISC{K3ysP4ce_1s_t00_smol_d2g7d97agsd8yhr}
Flag: TISC{K3ysP4ce_1s_t00_smol_d2g7d97agsd8yhr}
Level 3: KPA
We’ve managed to grab an app from a suspicious device just before it got reset! The copying couldn’t finish so some of the last few bytes got corrupted… But not all is lost! We heard that the file shouldn’t have any comments in it! Help us uncover the secrets within this app!
Downloadable File SHA256 checksum kpa.apk 5e93e5f6ed5f2c8b7286a6d7d03a73da2f75d8999c33be6a5e97bc425cacb497
Removed bytes from comment length
of End of central directory
record.
Decompiled apk
using Decompiler.com
and reviewed the contents. Found code related to flag
at \sources\com\tisc\kappa\MainActivity.java
.
1
2
> adb connect 192.168.188.131
> adb install kpa.apk
Setup Frida
, a dynamic instrumentation toolkit to inject scripts.
1
2
3
4
> adb connect 192.168.188.131
> adb push frida-server /data/local/tmp/
> adb shell "chmod 755 /data/local/tmp/frida-server"
> adb shell "/data/local/tmp/frida-server &"
Checked processes.
Performed test on hooking functions
using python script and observed the variables.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import frida, sys
jscode = """
Java.perform(() => {
let b = Java.use("j1.b");
b["e"].implementation = function () {
console.log(`b.e is called`);
let result = this["e"]();
console.log(`b.e result=${result}`);
return result;
};
});
"""
process = frida.get_usb_device().attach('KaPpA')
script = process.create_script(jscode)
print('[*] Running CTF')
script.load()
sys.stdin.read()
Observed b.e
is called with result true
.
Changed b.e
to false
and a.a
is called.
Check back on the code.
Changed a.a
to 20
.
Prepared eventual python script to perform necessary changes.
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 frida, sys
jscode = """
Java.perform(() => {
let b = Java.use("j1.b");
b["e"].implementation = function () {
console.log(`b.e is called`);
let result = false;
console.log(`b.e result=${result}`);
return result;
};
let a = Java.use("j1.a");
a["a"].implementation = function (packageManager) {
console.log(`a.a is called: packageManager=${packageManager}`);
let result = 20;
console.log(`a.a result=${result}`);
return result;
};
let sw = Java.use("com.tisc.kappa.sw");
sw["css"].implementation = function () {
console.log(`sw.css is called`);
let result = this["css"]();
console.log(`sw.css result=${result}`);
return result;
};
});
"""
process = frida.get_usb_device().attach('KaPpA')
script = process.create_script(jscode)
print('[*] Running CTF')
script.load()
sys.stdin.read()
Submit ArBraCaDabra?KAPPACABANA!
to retrieve flag.
Flag obtained.
Flag: TISC{C0ngr@tS!us0lv3dIT,KaPpA!}
Level 4: Really Unfair Battleships Game
After last year’s hit online RPG game
Slay The Dragon
, the cybercriminal organization PALINDROME has once again released another seemingly impossible game calledReally Unfair Battleships Game
(RUBG). This version of Battleships is played on a 16x16 grid, and you only have one life. Once again, we suspect that the game is being used as a recruitment campaign. So once again, you’re up!Things are a little different this time. According to the intelligence we’ve gathered, just getting a
VICTORY
in the game is not enough.PALINDROME would only be handing out flags to hackers who can get a
FLAWLESS VICTORY
.You are tasked to beat the game and provide us with the flag (a string in the format
TISC{xxx}
) that would be displayed after getting aFLAWLESS VICTORY
. Our success is critical to ensure the safety of Singapore’s cyberspace, as it would allow us to send more undercover operatives to infiltrate PALINDROME.Godspeed!
You will be provided with the following:
1) Windows Client (.exe)
- Client takes a while to launch, please wait a few seconds.
- If Windows SmartScreen pops up, tell it to run the client anyway.
- If exe does not run, make sure Windows Defender isn’t putting it on quarantine.
2) Linux Client (.AppImage)
- Please install
fuse
before running, you can dosudo apt install -y fuse
- Tested to work on Ubuntu 22.04 LTS
Downloadable File SHA256 checksum rubg-1.0.0.AppImage 679dc457478e97bbc1a3adf247d9d3f4c1b178709ff29a3aa5a6820462842730 rubg_1.0.0.exe e599ba12bb11dbd2e7a2b0326f1c7cbb03f792fd278fdfd6ba4c7343b095500e
Interacted with the game.
Oh! After multiple DEFEAT
, finally a hit!
And then on next click, GGWP…
Use 7-Zip File Manager
to extract files from rubg_1.0.0.exe
. A directory $PLUGINSDIR
was extracted, containing app-64.7z
and 3 DLL files.
Use 7-Zip File Manager
to extract files from app-64.7z
. In \app-64\resources
found app.asar
.
Use 7-Zip File Manager
with Asar7z distribution package
to extract files from app.asar
. In \app\dist\assets
found index-c08c228b.js
, which is the source code for the game.
Reviewed index-c08c228b.js
to understand game logic.
Install http-server
by typing npm install -g http-server
. Change into working directory. Start http server by issuing http-server -c-1
.
Go to 127.0.0.1:8080
on Chrome Web Browser
and press Ctr+Shift+I
to open Developer tools
.
Set Breakpoint
, indicated by left blue tab. Watch t
, n
and r
values.
Used ChatGPT
to write a python script that take in t
as decimal_numbers
and produced the initial board configuration.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
decimal_numbers = [
0,
2048,
2048,
0,
0,
960,
14336,
0,
12288,
0,
0,
124,
0,
0,
0,
0
]
# Convert to 16-bit binary representation and reverse the order of bits
binary_representations = [bin(num)[2:].zfill(16)[::-1] for num in decimal_numbers]
for i, binary in enumerate(binary_representations):
print(f"Decimal: {decimal_numbers[i]:4}, Binary: {binary}")
Based on the initial board configuration, boxes marked with 1
are the position of enemy’s battleships.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Decimal: 0, Binary: 0000000000000000
Decimal: 2048, Binary: 0000000000010000
Decimal: 2048, Binary: 0000000000010000
Decimal: 0, Binary: 0000000000000000
Decimal: 0, Binary: 0000000000000000
Decimal: 960, Binary: 0000001111000000
Decimal: 14336, Binary: 0000000000011100
Decimal: 0, Binary: 0000000000000000
Decimal: 12288, Binary: 0000000000001100
Decimal: 0, Binary: 0000000000000000
Decimal: 0, Binary: 0000000000000000
Decimal: 124, Binary: 0011111000000000
Decimal: 0, Binary: 0000000000000000
Decimal: 0, Binary: 0000000000000000
Decimal: 0, Binary: 0000000000000000
Decimal: 0, Binary: 0000000000000000
Clicked on all the boxes indicated with 1
on the board configuration and achieved VICTORY
.
Analysed index-c08c228b.js
to determine FLAWLESS VICTORY
condition. The boxes indicated with 1
need to be clicked in a certain order.
Used ChatGPT
to add on code that will help to determine the order.
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
decimal_numbers = [
0,
16384,
16384,
0,
0,
0,
0,
15360,
0,
124,
0,
0,
0,
14528,
0,
0
]
# Convert to 16-bit binary representation and reverse the order of bits
binary_representations = [bin(num)[2:].zfill(16)[::-1] for num in decimal_numbers]
for i, binary in enumerate(binary_representations):
print(f"Decimal: {decimal_numbers[i]:4}, Binary: {binary}")
# Define the input values n and r (random large integers)
n = 14088954749275437540
r = 10806988793789711595
hex_n = hex(n)[2:]
hex_r = hex(r)[2:]
# print(hex_n)
# print(hex_r)
c_values = []
for i in range(len(binary_representations)):
for j in range(len(binary)):
if binary_representations[i][j] == '1':
c1 = hex_n[15 - j]
c2 = hex_r[i]
c12 = c1 + c2
c_values.append(c12)
# print(c_values)
sorted_c = sorted(c_values, key=lambda x: int(x, 16))
# print(sorted_c)
solution = []
for i in range(len(binary_representations)):
solution_line = list(binary_representations[i])
for j in range(len(binary)):
if binary_representations[i][j] == '1':
c1 = hex_n[15 - j]
c2 = hex_r[i]
c12 = c1 + c2
solution_line[j] = str(chr(ord('A') + sorted_c.index(c12)))
final_solution_line = ''.join(solution_line)
solution.append(final_solution_line)
for line in solution:
print(line)
The eventual python script was able to take in t
, n
and r
values, then produced the following board configuration.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
0000000000000000
00000000000000D0
00000000000000E0
0000000000000000
0000000000000000
0000000000000000
0000000000000000
0000000000FBHK00
0000000000000000
00LINCO000000000
0000000000000000
0000000000000000
0000000000000000
000000PM000AGJ00
0000000000000000
0000000000000000
All the boxes are then clicked in ascending alphabetical order, starting from A to P.
Achieved FLAWLESS VICTORY
and obtained flag.
Flag: TISC{t4rg3t5_4cqu1r3d_fl4wl355ly_64b35477ac}
Level 5: PALINDROME’s Invitation
Valuable intel suggests that PALINDROME has established a secret online chat room for their members to discuss on plans to invade Singapore’s cyber space. One of their junior developers accidentally left a repository public, but he was quick enough to remove all the commit history, only leaving some non-classified files behind. One might be able to just dig out some secrets of PALINDROME and get invited to their secret chat room…who knows?
Start here: https://github.com/palindrome-wow/PALINDROME-PORTAL
Navigated to Actions
and checked out Portal opening
, then Latest attempt #2
. When checking out the error associated with test_portal.yml
, observed that the portal’s ip address
and password
are in plaintext.
Visited 18.143.127.62:45938
on web broswer and log in using :dIcH:..uU9gp1%3C@%3C3Q%22DBM5F%3C)64S%3C(01tF(Jj%25ATV@$Gl
as password
A discord link was provided. Upon joining the discord channel, saw the following message.
Went back to the page, right click and View page source
. Obtained some sort of token
. Likely to be related to discord.
However, the token was not a Discord Token
that replace credentials for login purpose.
Reviewing all information on hand, managed to find a hint. Using CyberChef
with Magic
Recipe on the password
, it was suggested that URL Decode, From Base85
will produce PALINDROME has an AUTOMATED secretary
.
Used ChatGPT
to write a python script that uses the Discord API
via the discord.py
library to interact with Discord bot
.
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
import discord
from discord.ext import commands
intents = discord.Intents.default()
intents.typing = False
intents.presences = False
bot = commands.Bot(command_prefix='!', intents=intents)
@bot.command()
async def hello(ctx):
await ctx.send('Hello, world!')
@bot.command()
async def ping(ctx):
await ctx.send('Pong!')
@bot.event
async def on_ready():
print(f'Logged in as {bot.user.name}')
print('------')
# Print the list of servers (guilds)
print("Servers (Guilds):")
for guild in bot.guilds:
print(f"Server (Guild) Name: {guild.name} (ID: {guild.id})")
# Enumerate permissions in each guild
for channel in guild.channels:
permissions = channel.permissions_for(guild.me)
print(f"Channel: {channel.name} (ID: {channel.id})")
print(f"Bot's Permissions: {permissions}")
bot.run('YOUR_BOT_TOKEN')
Received the following output in terminal
.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
2023-10-01 13:21:35 WARNING discord.ext.commands.bot Privileged message content intent is missing, commands may not work as expected.
2023-10-01 13:21:35 INFO discord.client logging in using static token
2023-10-01 13:21:37 INFO discord.gateway Shard ID None has connected to Gateway (Session ID: 1546b42da2a112f5c1d4baf2de45d569).
Logged in as PALINDROME's secretary 5
------
Servers (Guilds):
Server (Guild) Name: PALINDROME's secret chat room (ID: 1130166064710426674)
Channel: Text Channels (ID: 1130166064710426676)
Bot's Permissions: <Permissions value=422212465132672>
Channel: general (ID: 1130166064710426678)
Bot's Permissions: <Permissions value=422212465132672>
Channel: secrets (ID: 1132169821623165142)
Bot's Permissions: <Permissions value=422212466181248>
Channel: meeting-records (ID: 1132170180101947504)
Bot's Permissions: <Permissions value=422212465132672>
Channel: flag (ID: 1132170608013226084)
Bot's Permissions: <Permissions value=422212465066112>
Use ChatGPT
to write a python script to understand Permissions value
and convert it to authorised actions that the bot can take in the flag
channel.
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
# Your permission value
permission_value = 422212465066112
# Convert the numeric value to a Permissions object
permissions = discord.Permissions(permission_value)
# Define a dictionary of permission flags and their meanings
permission_flags = {
"create_instant_invite": "Create Instant Invite",
"kick_members": "Kick Members",
"ban_members": "Ban Members",
"administrator": "Administrator",
"manage_channels": "Manage Channels",
"manage_guild": "Manage Guild",
"add_reactions": "Add Reactions",
"view_audit_log": "View Audit Log",
"priority_speaker": "Priority Speaker",
"stream": "Stream",
"read_messages": "Read Messages",
"send_messages": "Send Messages",
"send_tts_messages": "Send TTS Messages",
"manage_messages": "Manage Messages",
"embed_links": "Embed Links",
"attach_files": "Attach Files",
"read_message_history": "Read Message History",
"mention_everyone": "Mention Everyone",
"external_emojis": "Use External Emojis",
"view_guild_insights": "View Guild Insights",
"connect": "Connect (Voice)",
"speak": "Speak (Voice)",
"mute_members": "Mute Members (Voice)",
"deafen_members": "Deafen Members (Voice)",
"move_members": "Move Members (Voice)",
"use_voice_activation": "Use Voice Activation (Voice)",
"change_nickname": "Change Nickname",
"manage_nicknames": "Manage Nicknames",
"manage_roles": "Manage Roles",
"manage_webhooks": "Manage Webhooks",
"manage_emojis": "Manage Emojis"
}
# Print granted permissions
print("Granted Permissions:")
for flag, description in permission_flags.items():
if getattr(permissions, flag):
print(f"{description}: Granted")
# Print denied permissions
print("\nDenied Permissions:")
for flag, description in permission_flags.items():
if not getattr(permissions, flag):
print(f"{description}: Denied")
Observed that the bot can only perform View Audit Log
.
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
Granted Permissions:
View Audit Log: Granted
Denied Permissions:
Create Instant Invite: Denied
Kick Members: Denied
Ban Members: Denied
Administrator: Denied
Manage Channels: Denied
Manage Guild: Denied
Add Reactions: Denied
Priority Speaker: Denied
Stream: Denied
Read Messages: Denied
Send Messages: Denied
Send TTS Messages: Denied
Manage Messages: Denied
Embed Links: Denied
Attach Files: Denied
Read Message History: Denied
Mention Everyone: Denied
Use External Emojis: Denied
View Guild Insights: Denied
Connect (Voice): Denied
Speak (Voice): Denied
Mute Members (Voice): Denied
Deafen Members (Voice): Denied
Move Members (Voice): Denied
Use Voice Activation (Voice): Denied
Change Nickname: Denied
Manage Nicknames: Denied
Manage Roles: Denied
Manage Webhooks: Denied
Manage Emojis: Denied
Use ChatGPT
to write a python script to fetch the Audit Log
from flag
channel using the Discord bot
.
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
import discord
from discord.ext import commands
intents = discord.Intents.default()
bot = commands.Bot(command_prefix='!', intents=intents)
@bot.event
async def on_ready():
"""Returns all audit logs for the PALINDROME's secret chat room server and flag channel on startup."""
print(f'Logged in as {bot.user.name}')
print('------')
# Print the list of channels in each server (guild)
print("Channels in Servers (Guilds):")
for guild in bot.guilds:
print(f"Server (Guild) Name: {guild.name} (ID: {guild.id})")
print("Channels:")
for channel in guild.channels:
print(f"Channel Name: {channel.name} (ID: {channel.id})")
target_channel_id = 1132170608013226084 # ID of the 'flag' channel
# Find the target channel by ID
target_channel = None
for guild in bot.guilds:
for channel in guild.channels:
if channel.id == target_channel_id:
target_channel = channel
break
if target_channel:
break
if target_channel:
# Fetch the audit logs for the target channel
async for entry in target_channel.guild.audit_logs(limit=None):
print(f"{entry.user.name} did {entry.action.name} to {entry.target}")
else:
print("Channel 'flag' not found in any server (guild).")
print() # Add a blank line for readability
# Start the bot.
bot.run('YOUR_BOT_TOKEN')
Observed in terminal output that several discord invite urls were created and deleted.
Tested all discord invite urls.
1
2
3
4
5
6
7
8
9
10
palindromewow did invite_delete to https://discord.gg/RBjatqsJ
palindromewow did invite_create to https://discord.gg/HQvTm5DSTs <--- correct invite
palindromewow did invite_create to https://discord.gg/RBjatqsJ
palindromewow did invite_delete to https://discord.gg/pxbYNkbb
palindromewow did invite_create to https://discord.gg/pxbYNkbb
palindromewow did invite_delete to https://discord.gg/QB2VRCz3
palindromewow did invite_create to https://discord.gg/2cyZ6zpw7J
palindromewow did invite_create to https://discord.gg/QB2VRCz3
palindromewow did invite_delete to https://discord.gg/3kbjCcYZup
palindromewow did invite_delete to https://discord.gg/ReTcnwNzCZ
The correct invite allows one to view the content in flag
channel.
Flag: TISC{H4ppY_B1rThD4y_4nY4!}