Context :

This week-end, I participated in the Defcamp Capture the Flag 2020 with my team RootMeUpBeforeYouGoGo We have been ranked 10th.

I did this challenge with my team-mates Grillette and DSpiricate.

Description

Well here is an example of a funny discord bot.

Solution

We are given a Python compiled bytecode file

To decompile it, I used Decompiler.com and it gave me this :

    # uncompyle6 version 3.7.4
# Python bytecode 3.6 (3379)
# Decompiled from: Python 2.7.17 (default, Sep 30 2020, 13:38:04) 
# [GCC 7.5.0]
# Warning: this version of Python has problems handling the Python 3 "byte" type in constants properly.

# Embedded file name: server.py
# Compiled at: 2020-12-02 03:30:35
# Size of source mod 2**32: 1909 bytes
from discord.ext import commands
import discord, json
from discord.utils import get

def obfuscate(byt):
    mask = 'ctf{tryharderdontstring}'
    lmask = len(mask)
    return bytes(c ^ mask[(i % lmask)] for i, c in enumerate(byt))


def test(s):
    data = obfuscate(s.encode())
    return data


intents = discord.Intents.default()
intents.members = True
cfg = open('config.json', 'r')
tmpconfig = cfg.read()
cfg.close()
config = json.loads(tmpconfig)
token = config[test('\x17\x1b\r\x1e\x1a').decode()]
client = commands.Bot(command_prefix='/')

@client.event
async def on_ready():
    print('Connected to bot: {}'.format(client.user.name))
    print('Bot ID: {}'.format(client.user.id))


@client.command()
async def getflag(ctx):
    await ctx.send(test('\x13\x1b\x08\x1c').decode())


@client.event
async def on_message(message):
    await client.process_commands(message)
    if test('B\x04\x0f\x15\x13').decode() in message.content.lower():
        await message.channel.send(test('\x13\x1b\x08\x1c').decode())
    if test('L\x13\x03\x0f\x12\x1e\x18\x0f').decode() in message.content.lower():
        if message.author.id == 783473293554352141L:
            role = discord.utils.get((message.author.guild.roles), name=(test('\x07\x17\x12\x1dFBKXO\x11\x1d\x07\x17\x16\n\n\x01]\x06\x1d').decode()))
            member = discord.utils.get((message.author.guild.members), id=(message.author.id))
            if role in member.roles:
                await message.channel.send(test(config[test('\x05\x18\x07\x1c').decode()]))
    if test('L\x1c\x03\x17\x04').decode() in message.content.lower():
        await message.channel.send(test('7\x06\x1f[\x1c\x13\x0b\x0c\x04\x00E').decode())
    if u'/s\u57faay' in message.content.lower():
        await message.channel.send(message.content.replace(u'/s\u57faay', '').replace(test('L\x13\x03\x0f\x12\x1e\x18\x0f').decode(), ''))


client.run(token)

It is a basic python discord bot.

We have a function obfuscating strings, I re-used this function to de-obfuscate some bot’s strings :

@client.event
async def on_message(message):
    await client.process_commands(message)
    if '!ping' in message.content.lower():
        await message.channel.send('pong')
    if '/getflag' in message.content.lower():
        if message.author.id == 783473293554352141L:
            role = discord.utils.get((message.author.guild.roles), name=('dctf2020.cyberedu.ro'))
            member = discord.utils.get((message.author.guild.members), id=(message.author.id))
            if role in member.roles:
                await message.channel.send(test(config['flag']))
    if '/help' in message.content.lower():
        await message.channel.send('Try harder!')
    if u'/s\u57faay' in message.content.lower():
        await message.channel.send(message.content.replace(u'/s\u57faay', '').replace('/getflag', ''))

So, the bot’s id is probably 783473293554352141 and we have to make it send /getflag. Moreover, it needs to have the role : dctf2020.cyberedu.ro.

When we send it u'/s\u57faay', the bot send what we said after removing u'/s\u57faay' and /getflag from our message.

Then, we simply have to send u'/s\u57faay'+'/get/getflagflag'

With the id’s bot we can simply invite him into our discord server with this link :

https://discord.com/oauth2/authorize?client_id=783473293554352141&permissions=8&scope=bot

/getFlag

Finally, with the obfuscate function we get the flag :

Le Flag !