Most types of malware are designed to communicate with their operators, enabling them to receive orders and send data back. Implementing these communications channels is the focus of the command and control tactic of the MITRE ATT&CK framework.
Introduction to encrypted channels
When implementing command and control infrastructure, confidentiality is a primary goal. If a cyber defender can see the communications between malware and its operator, then it is much easier to understand what the malware is doing and to eradicate the infection. Command and control traffic can be concealed in a variety of different ways. One of the most effective is to use an encrypted channel.
Encrypted channel
Encryption algorithms are designed to protect data confidentiality, and they’re good at it. The encryption algorithms in common use today have undergone extensive testing and attempts by cryptographers to break them. For example, the Advanced Encryption Standard (AES) algorithm was selected by a multi-year conference where cryptographers from around the world submitted candidates, debated their pros and cons and tried for years to break each candidate. This means that the winning AES candidate is a fairly secure encryption algorithm, and it’s pretty easy to use. All operating systems and many programming languages have built-in support for algorithms like AES and RSA, making it easy to use them to encrypt command and control communications.
Encrypted channels with Python
In Python, a number of different packages provide support for AES and similar algorithms, making it easy to build encryption and decryption functions.
The code above (available on Github) shows sample code for implementing an AES-encrypted channel for command and control. It includes hardcoded values for the server IP address, port and the AES encryption key. In the main function at the bottom of the code, the program uses the socket library to establish a connection to the server. Next, it generates a random initialization vector (IV) and sends it to the server. This value must be unique but is designed to be public, making it safe to share over the connection in the clear. After sending the IV and the length of the message, the client sends the message to the encrypt function, which pads it to the block length (AES encrypts data in 128-bit chunks) and encrypts it using the defined IV and key. The client then sends the resulting ciphertext to the server.
The code above is the server code designed to work with the client code above. It too uses the socket library but listens to a particular port rather than sending data over it. When data is available, it reads it in three steps: the 16-byte IV, a 1-byte message length and a ciphertext up to 1024 bytes. When the ciphertext is received, the server uses the decrypt function to decrypt it. It then decodes the message to UTF-8, uses the provided message length to strip off the padding, and prints the result to the terminal. If this program used a strong secret key, it would provide essentially unbreakable privacy for the transmitted data. This approach provides privacy for the command and control communications, but the communications are easily detectable in network traffic because they don’t look like a normal protocol. If the communications are detected and traced back to the malware, the script could be reverse engineered to find the encryption key and decrypt the data.
Introduction to protocol tunneling
Encrypted channels are designed to provide strong confidentiality. Another way to protect command and control traffic against snooping is to make it difficult to detect. This is the approach of the protocol tunneling technique from the MITRE ATT&CK framework.
Protocol tunneling
Protocol tunneling is not a new concept for network communications. Most network protocols are designed to be encapsulated within a different type of packet, creating a tunnel. For example, HTTP can be wrapped in TLS, which is wrapped in TCP, which is wrapped in an ethernet packet. The concept of protocol tunneling can be applied to hiding command and control traffic. By creating a tunnel where it isn’t expected, the command and control traffic can be protected against casual eavesdropping.
Protocol tunneling with Python
HTTP is a good protocol for implementing protocol tunneling. It’s commonly seen on the network, goes everywhere on the internet and has multiple different fields to hide data in.
The code sample above (from here) is designed to tunnel command and control data within HTTP cookies. Cookies are used to store configuration data about a website, and this data is commonly Base64 encoded and sometimes encrypted, meaning that encoded (and potentially encrypted) data doesn’t look suspicious there. This program uses the requests library in Python to easily build and send HTTP requests and parse their responses. It sends data in the cookie and receives it in the content of the requested page.
The code above implements the server that corresponds with the client code. It uses http.server to set up a simple web server that responds only to HTTP GET requests. In this case, the server is looking for a particular message: “C2 data.” If it receives it, it acknowledges the message. Otherwise, it returns an error. This code demonstrates a simple use of protocol tunneling over HTTP. Slight modifications could use different fields to carry values, integrate encryption and define a wider range of messages and responses.
Using Python for command and control
Subtle, private command and control traffic is vital to the success of many malware variants. Python can be used to implement command and control in a variety of different ways, including using encrypted channels and protocol tunneling.
Sources:
MITRE ATT&CK, MITRE Python for Cybersecurity, GitHub Socket, Python requests 2.25.1, PyPI