← All cheat sheets

GO-SECURITY

Authorized use only. Offensive reference for systems you own or are explicitly permitted to test. You are responsible for staying within the law.

Go basics for building security tools. Static binaries, built-in
concurrency, and fast compilation — the language behind many
modern offensive and defensive security tools.

WHY GO FOR SECURITY#

  - Compiles to single static binary (no dependencies)
  - Cross-compilation built-in (GOOS/GOARCH)
  - Goroutines for massive concurrency (scanning, fuzzing)
  - Strong standard library (net, crypto, os)
  - Most modern security tools written in Go
  - Tools: Nuclei, Subfinder, Gobuster, Sliver, Chisel, Ligolo

PROJECT SETUP#

# Install Go
# https://go.dev/dl/

# New project
mkdir mytool && cd mytool
go mod init mytool

# Build
go build -o mytool .                        # Build
go build -ldflags="-s -w" -o mytool .       # Stripped binary
go run main.go                              # Build and run

# Cross-compile
GOOS=windows GOARCH=amd64 go build -o mytool.exe .
GOOS=linux GOARCH=amd64 go build -o mytool .
GOOS=darwin GOARCH=arm64 go build -o mytool .

# Static binary (no CGO)
CGO_ENABLED=0 go build -ldflags="-s -w" -o mytool .

NETWORKING#

package main
import (
    "fmt"
    "net"
    "time"
)

// TCP client
func tcpClient() {
    conn, err := net.Dial("tcp", "10.10.10.5:80")
    if err != nil { panic(err) }
    defer conn.Close()
    conn.Write([]byte("GET / HTTP/1.1\r\nHost: target\r\n\r\n"))
    buf := make([]byte, 4096)
    n, _ := conn.Read(buf)
    fmt.Println(string(buf[:n]))
}

// TCP server
func tcpServer() {
    ln, _ := net.Listen("tcp", "0.0.0.0:4444")
    for {
        conn, _ := ln.Accept()
        go handleConn(conn)  // Handle each connection in goroutine
    }
}

// Port scanner with goroutines
func scanPort(host string, port int, results chan<- int) {
    addr := fmt.Sprintf("%s:%d", host, port)
    conn, err := net.DialTimeout("tcp", addr, 500*time.Millisecond)
    if err == nil {
        conn.Close()
        results <- port
    }
}

func main() {
    results := make(chan int, 100)
    for port := 1; port <= 65535; port++ {
        go scanPort("10.10.10.5", port, results)
    }
    // Collect results with timeout
}

// Concurrent scanner with semaphore
func scanWithLimit() {
    sem := make(chan struct{}, 100) // Max 100 concurrent
    var wg sync.WaitGroup

    for port := 1; port <= 65535; port++ {
        wg.Add(1)
        sem <- struct{}{}  // Acquire semaphore
        go func(p int) {
            defer wg.Done()
            defer func() { <-sem }()  // Release
            addr := fmt.Sprintf("10.10.10.5:%d", p)
            conn, err := net.DialTimeout("tcp", addr, 500*time.Millisecond)
            if err == nil {
                fmt.Printf("Port %d open\n", p)
                conn.Close()
            }
        }(port)
    }
    wg.Wait()
}

HTTP#

import "net/http"
import "io"

// GET request
resp, err := http.Get("http://target.com")
body, _ := io.ReadAll(resp.Body)
resp.Body.Close()
fmt.Println(string(body))

// POST request
resp, err := http.Post("http://target.com/login",
    "application/x-www-form-urlencoded",
    strings.NewReader("user=admin&pass=password"))

// Custom client (timeouts, proxy, skip TLS)
import "crypto/tls"
client := &http.Client{
    Timeout: 10 * time.Second,
    Transport: &http.Transport{
        TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
        Proxy: http.ProxyURL(proxyURL),
    },
}
req, _ := http.NewRequest("GET", "https://target.com", nil)
req.Header.Set("User-Agent", "Mozilla/5.0")
req.Header.Set("Authorization", "Bearer TOKEN")
resp, err := client.Do(req)

// HTTP server (for C2, callbacks, file hosting)
http.HandleFunc("/callback", func(w http.ResponseWriter, r *http.Request) {
    body, _ := io.ReadAll(r.Body)
    fmt.Printf("Received: %s\n", body)
    w.Write([]byte("OK"))
})
http.ListenAndServe(":8080", nil)

CONCURRENCY (GOROUTINES)#

import "sync"

// Fan-out pattern (parallel tasks)
var wg sync.WaitGroup
targets := []string{"10.10.10.1", "10.10.10.2", "10.10.10.3"}

for _, target := range targets {
    wg.Add(1)
    go func(t string) {
        defer wg.Done()
        // Scan target
    }(target)
}
wg.Wait()

// Worker pool pattern
func worker(jobs <-chan string, results chan<- string) {
    for target := range jobs {
        // Process target
        results <- fmt.Sprintf("%s: done", target)
    }
}

jobs := make(chan string, 100)
results := make(chan string, 100)
for w := 0; w < 10; w++ {  // 10 workers
    go worker(jobs, results)
}

FILE & CRYPTO#

import (
    "crypto/md5"
    "crypto/sha256"
    "encoding/hex"
    "os"
)

// File hash
data, _ := os.ReadFile("file.exe")
md5Hash := md5.Sum(data)
sha256Hash := sha256.Sum256(data)
fmt.Printf("MD5: %s\n", hex.EncodeToString(md5Hash[:]))
fmt.Printf("SHA256: %s\n", hex.EncodeToString(sha256Hash[:]))

// AES encryption
import "crypto/aes"
import "crypto/cipher"
import "crypto/rand"

key := make([]byte, 32) // AES-256
rand.Read(key)
block, _ := aes.NewCipher(key)
gcm, _ := cipher.NewGCM(block)
nonce := make([]byte, gcm.NonceSize())
rand.Read(nonce)
ciphertext := gcm.Seal(nonce, nonce, plaintext, nil)

// XOR
func xor(data, key []byte) []byte {
    out := make([]byte, len(data))
    for i := range data {
        out[i] = data[i] ^ key[i%len(key)]
    }
    return out
}

CLI ARGUMENTS#

// Standard library (flag package)
import "flag"
target := flag.String("target", "", "Target host")
port := flag.Int("port", 80, "Target port")
threads := flag.Int("threads", 10, "Concurrent threads")
flag.Parse()

// Or use cobra for complex CLIs
// go get github.com/spf13/cobra

OS / EXEC#

import "os/exec"

// Run command
out, err := exec.Command("whoami").Output()
fmt.Println(string(out))

// Run with arguments
cmd := exec.Command("nmap", "-sV", "10.10.10.5")
cmd.Stdout = os.Stdout
cmd.Run()

// Run shell command
cmd := exec.Command("sh", "-c", "cat /etc/passwd | grep root")
out, _ := cmd.Output()

USEFUL LIBRARIES#

net/http                    # HTTP client/server (stdlib)
crypto/*                    # Crypto (stdlib)
encoding/json               # JSON parsing (stdlib)
os/exec                     # Command execution (stdlib)
github.com/spf13/cobra      # CLI framework
github.com/projectdiscovery/goflags  # PD-style flags
github.com/go-resty/resty   # HTTP client (easier)
github.com/gorilla/websocket # WebSocket
golang.org/x/crypto         # Extended crypto (SSH, etc.)
golang.org/x/net            # Extended networking
github.com/fatih/color      # Terminal colors

EXISTING GO SECURITY TOOLS#

Nuclei            # Template vulnerability scanner
Subfinder          # Subdomain discovery
httpx              # HTTP probing
Katana             # Web crawler
Gobuster           # Directory/DNS brute force
Sliver             # C2 framework
Chisel             # TCP/UDP tunnel
Ligolo-ng          # Tunneling/pivoting
Garble             # Go binary obfuscation
Merlin             # C2 framework

TIPS#

  - CGO_ENABLED=0 for truly static binaries
  - -ldflags="-s -w" strips debug info (smaller binary)
  - Goroutines are cheap — spawn thousands for scanning
  - Use sync.WaitGroup to wait for goroutine completion
  - Channels for safe communication between goroutines
  - Cross-compile with GOOS and GOARCH env vars
  - Go binaries are larger than C/Rust (~5-15MB)
  - Use garble to obfuscate Go binaries for offensive use
  - Strong stdlib means fewer external dependencies
  - go install tool@latest installs Go tools instantly