Build an Advanced Persistent Threat module
Let's put the black hat on
Every day the news reports about some organization being hacked and their data stolen. I always asked myself: How is that possible? Is that hard to do? If it were me, how would I do that?
In this post I'll report my experience in building my own Advanced Persistent Threat (APT).
Some background info
An APT is the last step during compromising a target: you found a vulnerability, you exploited it, you gained root access. But this isn't just a "one time" hit, you want to stay connected to the machine and retrieve information in the upcoming months.
Since it will run for a long period of time, the most important thing is being stealthy: limit the usage of the filesystem, encrypt requests to elude network monitoring, avoid persistent connections. If something goes wrong during the communication, do not die, but intercept the error and try again later.
How hard can it be?
I was reading an article about APT28 - Sednit group and I was fascinated with the technical paper describing their attacks (here you can find part1, part2 and part3).
This is a very high profile group and it is suspected to be responsable for the attacks vs US Democratic National Committee (DNC), the German Parliament, the French TV network TV5Monde and WADA.
This sounded quite challanging, so I said: How hard can it be?
Why spend several hours to code something with no direct financial return and most likely no immediate practical usage?
Because I enjoy learning new things and I found that learning by doing is a great investement.
Given 100 hours of work, 50% consists in reapplying patterns you already know, 20% in studying the subject you want to develop and the final 30% is dedicated to learning something new from scratch. At the end of the day you have a working product, you acquired new skills (a new language, a new pattern or a new framework) and you had some fun without too much effort.
The main goal
My main goal was to develop a script with the following features:
- Encrypted communications
- No need for continuous connection with C&C servers
- Ability to dynamically fire features from remote. For example start/stop keylogger, watch file changes or execute shell commands
- Support multiple communication channels: HTTP or e-mail
- Create the server part, too. Reports usually give the details about the client part (because that's the only thing they can analyze), but what about the servers? How would you setup them?
Choosing the tools
For the client part, I chose Python as the language code. It's quite easy to implement, there are several different libraries available and there's plenty of documentation for a lot of different use cases.
All of this comes with a price: Python is not the right language if you ever want to write a serious APT. Unless you want to ask your target to kindly install Python interpreter on his machine, you have to compile your code into a single executable. Sadly, there are a lot of tools to decompile exe python files; moreover it's almost impossible to obfuscate the original code, meaning that's just a matter of time before your code get revealed and the main C&C server blacklisted.
On the other hand, you can translate Python code into C code and then compile it using Cython. This is not a trivial task and it's not for the faint of heart, that's why I left this step for the future, however it proves that is doable.
For the server part, instead, I chose Lumen, a micro-framework powered by Laravel.
First of all it's a very fast framework, that allows you to set an API endpoint in very few steps. Once again its documentation is great, you can find all your answers within a couple of Google queries. Finally, I was curious to learn Laravel and this seemed the perfect occasion.
The main logic
Communications are encrypted using RSA, each client should have their public and private keys hardcoded, plus a server public key.
The client will try to contact the server at random intervals providing its hard disk serial number and will ask for the AES key; further communications will be AES encrypted. Each request is performed using PUT or POST verbs, in order to reduce the amount of information leaked.
The client will ask for commands to run at random intervals, pass the command to the correct module and then store the result locally. Once again, at random intervals, those results will be uploaded to the server.
If no network is available, the APT will simply wait until it becomes available again. If the remote domain is not available, the APT will switch to an email-based channel (this part is not ready yet).
Wait, plain HTTP, no SSL? Are you nuts?
The web channel is using plain HTTP and not HTTPS. This could be seen as nonsense, but here's the situation. You can divide your targets into two categories: people that are not monitoring the connections and people doing that.
In the first case, using HTTPS won't change anything, since the target is not checking what's going on. In the latter case, most likely they installed their own root certificate on the machine, decrypting and encrypting all HTTPS connections on the fly, so HTTPS will not help you.
So at the end of the day I preferred using a strong AES encryptiong instead of relying on channel security.
Show me the code!
Here you can find the repository for the client and here the repository for the server.
Setup and usage
Please refer to the repository README files for further info (client and server).
Keep in mind that this is just a POC and a tool for developers, so most likely you'll have to dive into the code and tweak it for your own needs!
While developing this APT I got so many ideas, but sadly due to the lack of free time I had to drop them. Here's a non-comprensive list:
- Complete email communication channel
- Add a watcher for changed files and automatically exfiltrate them
- Split and zip the result of the commands if their size is too big
- Try to inject a shellcode in any browser process in order to obtain a network connection. From my test I was able to hijack Firefox only, while Chrome and Explorer crashed immediately
- Detect Anti-virus and if script is run in a sandbox
The original question was: How hard can it be?
Well, it requires a lot of work, but it's not impossible. The main issue is to tackle non-ordinary network settings (proxy or firewalls in place), but for more ordinary targets you can keep it simple and it should work.
During this exercise I was able to research and get a better understanding of RSA and AES implementations, both in Python and in PHP. Moreover I got more experience in managing threads within Python, something that seems trivial, but there are a lot of edge cases to cover. Finally, I had time to discover Lumen and Laravel and honestly I was fascinated at how easy and fast you can develop an API endpoint.
At the end of the day I put a lot of hours into this project, but the return in knowledge was really worth it.