on
DaaC2 - Using Discord as a C2
Introduction
It was a cold Sunday evening, and I was doing nothing but afk’ing cannonballs on OSRS (shout out to @TimGMichaud) when I had an urge to make something. I was thinking about a conversation I had on Friday with Sion (fellow colleague/hacker friend) about methods of dropping malware, communicating with C2’s, how implants go undetected but still communicate etc. I fired up VS code and built a skeleton project of a ‘client’ and a ‘server’. I immediately took a step back and thought ‘I have already made stuff using the common approach (http/https, GET/POST etc).’ I wanted to make something I hadn’t seen before as well as something that was brand new to me. It was then I thought about using Discord as my means of communication between a server (C2) and a client (agent).
Short(ish) Disclaimer
I don’t write Malware for a living, I am not a red teamer (I work as a pentester) so I don’t have a tonne of knowledge in this area. When I build a C2/agent I pretty much get it working to a point where I can use it to gain a foothold and then upgrade/migrate to something a bit more substantial (i.e meterpreter etc). I do however, have a big interest in malware, agents, implants, etc so I do enjoy writing little tools and PoC’s to scratch an itch. What you see here is no where near ‘production’ ready. I doubt it would be useful on site or in an engagement but hopefully it covers an area which hasn’t been discovered or hopefully it helps you, the reader, to build your own or even discover how wonderful Go is to write in. Don’t get triggered, I write things in a tonne of languages, Go just happens to be my current flavour at the moment. Use whatever you guys want, as long as you can bypass basic detection then you’re off to a good start.
Planning
Before I started implementing anything, I needed to figure out what I need to get a working PoC and how I might go about it. First things first, how am I going to use Discord as a method of communication.
What we know about Discord (basic, high level approach):
- Basically Skype but targetting gamers
- Any user can create a ‘server’ (something something vent)
- ‘Devs’ can create bots to automate certain features <- interesting
- Although a user can create a ’server’ they don’t host anything themselves
- Multiple clients are available, all using their API to have seamless cross platform <- also interesting
Okay, so if you haven’t spotted something we could do already by my interesting hints, then let’s run through a brief possible approach:
As we, the attacker, want to be able to issue commands to an agent on a remote system we can utilise the Discord client on the attacking system to send messages. We now want something to ‘receive’ those messages, the easiest approach would be to have a human on the other end - however, this isn’t a thing, so instead we want to create a bot to read the messages and react appropriately. So now we have a simple agent that should be able to receive a message and easily send a reply. We will want to utilise the Discord API to send and receive messages within our agent. Finally, we want to use a new ‘server’ created by us to ensure our messages don’t get ‘lost’ or our agents don’t get confused due to other users or a high amount of messages being thrown around.
The above should give us a low quality implementation (v0.1 if you will). The rest of the post will be following a structure similar to the above, effectively breaking up each chunk of the project and explaining what I did to implement a working PoC. The final product (or as it currently stands) went a pretty big step further than the above. That will be covered towards the end (it’s pretty cool and probably my favourite bit).
Creating our agent and making our initial PoC
First things first, I needed to create an ‘agent’ executable that would be dropped on a target system. I used the discordgo (https://github.com/bwmarrin/discordgo) to hook into the API, without this project I wouldn’t have gotten anywhere near where I did in the short amount of time - so big thanks!! The agent now acted like a Discord bot, when it was executed it would log in to the Discord service and sit and wait. So far, so good. Oh I forgot to mention, before getting a bot to authenticate properly you need to go to the developer portal for Discord and create an ‘app’ followed by a ‘bot’. This will give you an authentication token which is used to successfully authenticate and bring your bot to life. Simple, but pretty important. Once you have this, add your bot to a server you want to use (I created a new one so it was just my bot and my personal account). In theory, you now have your means of communication between an agent and you (the attacker).
So now I had an agent that did nothing. Strong start. But what do agents need to do? Well… anything really. I set up a listener that would fire off a function everytime a message was received in the server, and had the bot parse it. For now, the parser would just ‘assume’ that the message contained a system command and used the content of the message in a separate function, executing the command in the underlying OS. For arguments sake, I wrote this entire project in Mac OSX so in any examples I will be using Unix commands. Naturally, Go can be built to many different platforms so Windows (for example) could be done easily, in-fact it might exist in the project at the time of reading this - but it didn’t at the time of writing. Anyway, running the agent and sending the message ‘id’ from my personal Discord account would cause the agent to react and reply with the command output - listing my current system user and its groups, etc. Awesome, I have an agent that receives instructions from a fake C2. At this point, I thought “This is a working PoC of using Discord as a method of communication… done, right?” but my fear of being judged on Twitter (lel) beat me into a corner so I wanted to build something much cooler.
After a couple of hours of DnB and dev, the basic ‘manual’ message building had become something I was really happy with.
Now, ultimately, I don’t like Discord. I think it’s awful, the client is meh and no one wants to have to sit in a glorified text box all day. Especially when we have terminals that do everything for us. The best solution is to just uninstall Discord and write a cli tool that does everything for us. I mean, we have the API bindings, a ‘dedicated’ server and a means of authenticating right? So why do we need all the extra crap that Discord comes with… short answer; we don’t.
I think videos and pictures are worth way more than words so I will drop a video of the C2 and agent working together and then break down each feature I have implemented since the Twitter fear kicked in. Fun fact, I have shown this to a few people so far and they love it. I can’t wait for strangers to hate it and give me grief - it’s what we all live for right? RIGHT?! Anyway, here’s the video from the C2 point of view:
So, as we can see, it’s quite a bit more than the initial implementation and plan. We now have the following features:
A single discord bot is used for the C2 and the agents.
Agents have unique ID’s assigned during initialisation. This allows multiple agents to be used and communicate at the same time. With targetted interaction, the correct agent will react/respond every time.
All messages are chunks of base64 (secure, I know /flex - remember when I said this isn’t engagement ready? I wasn’t lying). These chunks of base64 are encoded JSON structures that hold various information:
- data body (target command, required data for task/job, command result etc)
- To / From ID’s so the server/agents know when to react/ignore messages
- Message ’type’ used when parsing to figure out the required steps
The discord server becomes quite busy during communication, as expected. An example of the agent and server communicating via the Discord server can be seen in here:
The ‘uname’ example shown in the screenshot below was completed using the following two messages sent to the agent and back to the server:
From the server:
{"FromServer":true,"ToID":"bNuHqEb4","FromID":"SERVER","MessageType":"cmd","Data":"uname"}
From the agent:
{"FromServer":false,"ToID":"","FromID":"bNuHqEb4","MessageType":"reply","Data":"Darwin\n"}
Agents can inject raw shellcode into themselves (upgrade the shell, start a new process, do whatever). Initially I used cgo to perform this but I had a mare when it came to cross compiling. Apparently after a billion years of coding I still don’t know how to build projects properly so I just changed my implementation. It currently only works on Unix/Darwin, not Windows.
Agents have a heartbeat and ping the server every minute (can be set to whatever value you want in the source) allowing the server to track which agents are alive and dead. These can be listed in a table, showing their ID’s for easy interaction. There is some form of persistence here, whereby the server checks if it knows about the pinging agent and adds it back to the server list for interaction if it has ‘forgotten’ about it. This would be handy if the server ever died and was relaunched as the agents would be able to let them know they are still alive (this should use some form of secret/token so a rogue agent couldn’t connect through to us if it was able to get the auth token from the Discord bot). An example heartbeat message structure can be seen below (decoded). In addition, the heartbeat can be see in the screenshot above - rendered in yellow:
{"FromServer":false,"ToID":"","FromID":"bNuHqEb4","MessageType":"ping","Data":"Ping at: 2020-01-25 19:38:54.466929 +0000 GMT m=+61.316731943"}
There are different cli menu states, allowing for easy message building and specific agent interaction. In addition, help menus can be listed per state to see the different options available:
All known agents can be listed in a table within the cli, showing information such as the hostname, the systems external facing IP, their OS (very buggy) and their agentID for easy interaction. This is shown below, when issuing the ‘agents’.
Agents can be killed by the server on request, removing them from the server and shutting down the process on the target; however, executable will still remain on the system. This can be seen in the following screenshot, issuing the ‘kill’ option whilst interacting with an Agent.
I haven’t dived into each of the above too much as hopefully the video shows it all off and as the source is available (https://github.com/crawl3r/DaaC2) - you can dive in and see what you can figure out. If you have any questions, suggestions or want me to cover each of the features more, tweet me and I can sort something out.
Finally, I am likely going to continue developing this as I really enjoyed the couple of hours I spent making it. I think with more time, it could grow pretty nicely. So far, I haven’t spent any time implementing methods of evading AV or trying to hide on the target system so it is likely that it will get caught or flagged almost instantly. So you know, be smart. Don’t be a skid like me.
Thanks for checking out my current project, hope you like it. If not, cool - I’m sure you can do miles better, right? Send it me when you have <3