Welcome back to Programming Thursday, where today we will leave Python behind and enter the world of compiled languages. Python is great for prototyping; Go is for deployment.

In the last five years, there has been a massive shift in the malware ecosystem. Threat groups and Red Teams alike are abandoning C# and PowerShell for Go (Golang). Why?

  1. Cross-Compilation: You can compile a Windows binary from your MacBook with one command.
  2. Binaries are Static: No dependency hell. No “Python not installed.” No “.NET framework version mismatch.”
  3. Speed: It’s near-C speed with Python-like readability.

1. The Cross-Compilation Superpower

The killer feature of Go is building for any target OS without installing a VM.

Scenario: You are on a Kali Linux machine, but you need an exploit (exploit.exe) for a Windows server.

1
2
3
4
5
# Build for Windows 64-bit
GOOS=windows GOARCH=amd64 go build -o loader.exe main.go

# Build for Linux (e.g., a router or IoT device)
GOOS=linux GOARCH=mips go build -o botnet main.go

2. Stealth: Hiding the Console

By default, a Go binary on Windows opens a cmd.exe window when run. This is bad OpSec for a background beacon. The Fix: Use linker flags (-ldflags) to tell the Windows GUI subsystem to run it without a window.

1
go build -ldflags "-H=windowsgui -w -s" -o stealth.exe main.go
  • -H=windowsgui: Hides the console window.
  • -w -s: Strips debug symbols (makes the binary smaller and harder to reverse engineer).

3. Interacting with Windows API (Syscalls)

You don’t need C++ to call VirtualAlloc. Go can do it via the syscall or golang.org/x/sys/windows packages. This is crucial for process injection.

Example: The Message Box (The “Hello World” of WinAPI)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package main

import (
    "syscall"
    "unsafe"
)

var (
    user32        = syscall.NewLazyDLL("user32.dll")
    procMessageBox = user32.NewProc("MessageBoxW")
)

func main() {
    title, _ := syscall.UTF16PtrFromString("Red Team")
    text, _ := syscall.UTF16PtrFromString("Go Native WinAPI Call")

    // Call MessageBoxW(0, text, title, 0)
    procMessageBox.Call(
        0,
        uintptr(unsafe.Pointer(text)),
        uintptr(unsafe.Pointer(title)),
        0,
    )
}

4. Building a Simple Port Scanner

Why use Nmap (which requires installation and flags bells) when you can write a focused scanner in 50 lines?

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
package main

import (
    "fmt"
    "net"
    "time"
)

func scan(target string, port int, results chan int) {
    address := fmt.Sprintf("%s:%d", target, port)
    conn, err := net.DialTimeout("tcp", address, 1*time.Second)
    if err == nil {
        results <- port
        conn.Close()
    } else {
        results <- 0
    }
}

func main() {
    target := "192.168.1.1"
    results := make(chan int)

    // Parallel scanning using Goroutines
    for i := 1; i <= 100; i++ {
        go scan(target, i, results)
    }

    // Collect results
    for i := 1; i <= 100; i++ {
        port := <-results
        if port != 0 {
            fmt.Printf("[+] Open: %d\n", port)
        }
    }
}

5. Major Tools Written in Go

You probably use these tools every engagement. They prove Go’s dominance:

  • Chisel: A fast TCP tunnel over HTTP. Essential for pivoting.
  • Gobuster: The standard for directory/DNS brute forcing.
  • Merlin: A C2 framework that uses HTTP/2.
  • Ligolo-ng: The modern replacement for VPN pivoting.

Conclusion

Go allows you to write tools that are easy to maintain but deploy as weaponized, standalone binaries. If you know Python, learning Go takes a weekend. For a Red Teamer, that weekend pays unmatched dividends in operational flexibility.

UncleSp1d3r