Tags: web 


Originally Posted at [https://blog.abifog.com/dragonsec-dctf-2021-discord-pingpong-writeup/](https://blog.abifog.com/dragonsec-dctf-2021-discord-pingpong-writeup/)

### The Challenge

We were given a binary which, on being executed said:

_"Last message in #general is: Welcome to our secret server! Only trusted bots and users have access to the secret channels. Our secret plans have been moved from here to a secret channel. Bot is now running. Press CTRL-C to exit."_

Running `strings` and `file` on it told me it was written in Go.

discordbot: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked,
Go BuildID=_ZEAdEO-wvSQGBQYhkGM/xFUNbqa5yDNs4HrN4WQF/IfIgpWbUNMnt11lPcn7W/sNa0sC3hsaXC9dymZEeD, not stripped

### Extracting The Token

It was a web challenge so I decided reverse engineering was not the answer. Packet capture wouldn't reveal anything else either since requests would be SSL encrypted. I thought I might be able to solve it if I could see all its http traffic.

So I setup [mitmproxy](https://mitmproxy.org/) and added its root certificates to `/etc/pki/ca-trust/source/anchors` and then ran `sudo update-ca-trust` to enable them. (works this way for Fedora/RHEL family distributions) This needs to be done because otherwise applications using the proxy would throw untrusted certificate error. Instead of mitmproxy, you can also use any other http proxy like Owasp Zap or Burpsuite.

Now the problem was forcing the go binary to use my proxy. I thought of putting it in a container and then proxying all its traffic. I knew podman had a `--http-proxy` option but upon reading the documentation further, I realized all it did was create an environment variable and any program running inside the container may choose to ignore it. There is probably a way to pass all container traffic through a proxy, but it involved fighting with iptables so I decided against it.

Next thing I thought of was [proxychains](https://github.com/rofl0r/proxychains-ng). Its forces any TCP connection made by any given application to follow through a proxy even if the application does not have inbuilt support for proxies. It works by hooking network-related libc functions in dynamically linked programs via a preloaded DLL and redirects the connections through SOCKS4a/5 or HTTP proxies. Unfortunately this approach does not work in programs written in Go. Go does not use libc and programs written in Go are statically linked not dynamically linked.

In the issue tracker of proxychains, I came across this (relatively) obscure program called [graftcp](https://github.com/hmgle/graftcp). graftcp works in a different way than proxychains and is able to work against statically linked programs as well. This is what I needed.

There were no publicly available compiled builds of graftcp, so I had to compile it myself. Then:

# in one terminal
# mitmproxy is running on
./graftcp-local/graftcp-local -http_proxy -select_proxy_mode only_http_proxy

# in another terminal (discordbot is the name of the provided binary)
./graftcp -n discordbot

# now discordbot will use that proxy even if its dev never included proxy support

Now all discordbot traffic was going through my mitmproxy.

I found the `Authorization: Bot ODM4ODY3MDA4MTI3ODkzNTQ1.YJBVyA.zTQk10ZIQpMfT_Evi00sAkt5KIA` header in mitmproxy logs.

### Getting The Flag

This was simple.

import discord

class MyClient(discord.Client):
async def on_ready(self):
print('Logged on as', self.user)

for guild in client.guilds:
for channel in guild.text_channels:
# print all messages in all channels
async for message in channel.history(limit=200):

# since other teams had sent their greeting messages in the channel, I decided to send mine as well

# try:
# await channel.send('Hi from the Gungan Grand Army !')
# except:
# pass

async def on_message(self, message):
# don't respond to ourselves
if message.author == self.user:


client = MyClient()


Got the flag **dctf{7h3_R0b0t_Upr151ng_15_NEAR!}**

Original writeup (https://blog.abifog.com/dragonsec-dctf-2021-discord-pingpong-writeup/).