DUMB-DISCORD
DUMB-DISCORD
Proof of flag
ctf{1b8fa7f33da67dfeb1d5f79850dcf13630b5563e98566bf7b76281d409d728c6}
Summary of the vulnerabilities identified
Invite the bot to a Discord server, give it the ‘dctf2020.cyberedu.ro’ role, use the payload ‘/s基ay //getflaggetflag’ to get the encoded flag and then decode it.
Proof of solving
First off, we need to decompile the binary using ‘uncompyle6’ and look at the code. But before I copy paste all the code we need to replace the obfuscated strings. A simple xor encoding is used, and we can use the included decoding function to replace them with the real strings. And we end up with this:
from discord.ext import commands
import discord, json
from discord.utils import get
def obfuscate(byt):
mask = b'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['token']
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('pong')
@client.event
async def on_message(message): # where the magic happens
await client.process_commands(message)
if '!ping' in message.content.lower(): # pong
await message.channel.send('pong')

So, we need a specific user that has the role ‘dctf2020.cyberedu.ro’ to send ‘/getflag’. But who is that user anyway?
DCTFTargetWhyNot#1969
Bot: True
Badges: None
ID: 783473293554352141
Created: 2020-12-01 23:23:09 UTC
I think that our target! We can invite it to our server by going to ‘https://discord.com/oauth2/authorize?client\_id=783473293554352141&scope=bot’ Giving it the role is simple enough, nothing fancy. Now we need to make it speak In the ‘/s基ay’ command ‘/getflag’ is only replaced once so we can craft a message that becomes ‘/getflag’ after replacing A possible message is ‘/s基ay //getflaggetflag’

Xabifk 12/05/2020 stai ca mai e un check /s基ay //getflaggetflag

DCTFTargetWhyNot 📴 12/05/2020
/getflag
b'\x00\x00\x00E\x10A\x0e\x00E\x02VA\x00\x0eXC\x17\x12\x17\x0b\_\x0 3H\x05C\_CAB\x1d\x0b\x07CWSAT\r[AEG\x17PVRKU\x16\x00L\x16EOZYC\x00 QB]\x0bYFK\x17D\x14'

Xabifk 12/05/2020 We did it boys
Finally the flag can easily be decoded with the same function