Back to Course

Where to From Here

You’ve built a functional C2 framework. Now what? Here are paths to continue your learning and extend your skills.

Extend Your Framework

Add More Commands

Using the patterns you’ve learned, adding new commands is straightforward:

Command IdeaDescription
uploadSend files TO the agent (reverse of download)
executeRun shell commands and return output
screenshotCapture the agent’s screen
keyloggerStart/stop keystroke logging
process_listEnumerate running processes
injectInject into other processes
migrateMove agent to another process

Each follows the same pattern:

// 1. Types
type ExecuteArgsClient struct { Command string }
type ExecuteArgsAgent struct { Command string }
type ExecuteResult struct { Stdout, Stderr string }

// 2. Server validator/processor
func validateExecuteCommand(rawArgs json.RawMessage) error { ... }
func processExecuteCommand(rawArgs json.RawMessage) (json.RawMessage, error) { ... }

// 3. Agent orchestrator
func (agent *HTTPSAgent) orchestrateExecute(job *server.HTTPSResponse) AgentTaskResult { ... }

// 4. Agent doer
func doExecute(command string) ExecuteResult { ... }

// 5. Register
validCommands["execute"] = {...}
agent.commandOrchestrators["execute"] = (*HTTPSAgent).orchestrateExecute

Improve Existing Features

Communication:

  • Add more protocol options (ICMP, WebSocket, gRPC)
  • Implement domain fronting for HTTPS
  • Add data chunking for DNS (handle large payloads)
  • Implement message compression

Security:

  • Add certificate pinning
  • Implement key rotation
  • Add anti-forensics (memory-only operation)
  • Implement process hollowing

Operations:

  • Add agent grouping/targeting
  • Implement task scheduling
  • Add agent health monitoring
  • Create a web UI for operators

Cross-Platform Support

Currently, shellcode execution is Windows-only. Consider:

  • Linux shellcode - ELF loading, ptrace injection
  • macOS shellcode - Mach-O loading, code signing bypass
  • Cross-platform persistence - cron jobs, launch agents, systemd

Learn the Underlying Concepts

Windows Internals

The reflective DLL loader touches many Windows concepts:

  • PE file format - Headers, sections, imports, exports
  • Memory management - VirtualAlloc, page protections
  • Process injection - Remote threads, APC injection
  • API hooking - IAT hooking, inline hooks

Resources:

Network Security

Understanding how defenders detect C2:

  • Beacon analysis - Timing patterns, jitter detection
  • Protocol analysis - Anomalous DNS, certificate inspection
  • Machine learning - Traffic classification, anomaly detection

Malware Analysis

Understanding how your tools get analyzed:

  • Static analysis - String extraction, PE parsing, YARA rules
  • Dynamic analysis - Sandboxing, behavior monitoring
  • Evasion techniques - Packing, obfuscation, anti-analysis

Advanced Go Topics

Concurrency Patterns

Go excels at concurrent programming:

// Worker pools for parallel command execution
type Worker struct {
    jobs    chan Job
    results chan Result
}

// Fan-out/fan-in for multiple agents
func fanOut(agents []Agent, command Command) []Result {
    results := make(chan Result, len(agents))
    for _, agent := range agents {
        go func(a Agent) {
            results <- a.Execute(command)
        }(agent)
    }
    return collect(results, len(agents))
}

Plugin Architecture

Consider making commands loadable at runtime:

// plugin.go
type CommandPlugin interface {
    Name() string
    Validate(json.RawMessage) error
    Process(json.RawMessage) (json.RawMessage, error)
    Execute(json.RawMessage) (json.RawMessage, error)
}

// Load plugins from .so files (Linux/Mac)
p, _ := plugin.Open("commands/screenshot.so")
sym, _ := p.Lookup("Command")
cmd := sym.(CommandPlugin)

Testing

Add comprehensive tests:

func TestValidateShellcodeCommand(t *testing.T) {
    tests := []struct {
        name    string
        input   json.RawMessage
        wantErr bool
    }{
        {"valid", []byte(`{"file_path":"test.dll","export_name":"Run"}`), false},
        {"missing path", []byte(`{"export_name":"Run"}`), true},
        {"empty", []byte(`{}`), true},
    }

    for _, tt := range tests {
        t.Run(tt.name, func(t *testing.T) {
            err := validateShellcodeCommand(tt.input)
            if (err != nil) != tt.wantErr {
                t.Errorf("got error %v, wantErr %v", err, tt.wantErr)
            }
        })
    }
}

Real-World Considerations

Operational Security

If using for authorized testing:

  • Separate infrastructure - Don’t reuse C2 domains
  • Log everything - For reporting and deconfliction
  • Kill switches - Ability to terminate all agents
  • Unique identifiers - Track which agent is which

Detection Evasion

Understand what defenders look for:

  • Network indicators - User agents, JA3 fingerprints, beacon patterns
  • Host indicators - Process names, file hashes, registry keys
  • Behavioral indicators - API call sequences, memory patterns

Legal and Ethical

Always ensure:

  • Written authorization - Scope, systems, timeframe
  • Defined boundaries - What’s in/out of scope
  • Incident response - How to handle discoveries
  • Data handling - Protection of collected data

Study Existing Frameworks

Learn from open-source C2 frameworks:

FrameworkLanguageNotable Features
SliverGoMulti-protocol, operator UI
HavocC++/PythonModern, modular
CovenantC#.NET focused, collaborative
MythicPython/ReactExtensible, great UI
MerlinGoHTTP/2, QUIC support

Reading their code teaches patterns you can adapt.

Certifications and Courses

Consider formal training:

  • OSCP/OSCE - Offensive Security certifications
  • CRTO - Certified Red Team Operator
  • GPEN/GXPN - GIAC penetration testing
  • Malware development courses - Various providers

Build a Portfolio

Document what you’ve learned:

  • Blog posts - Explain concepts you’ve mastered
  • GitHub projects - Showcase your code (sanitized)
  • CTF writeups - Demonstrate problem-solving
  • Conference talks - Share your research

Final Advice

  1. Keep building - The best way to learn is to create
  2. Read source code - Study how others solve problems
  3. Stay legal - Only test on systems you own or have authorization for
  4. Share knowledge - The community grows when we teach each other
  5. Stay curious - There’s always more to learn

You now have a solid foundation in C2 development. The patterns you’ve learned apply far beyond this specific project. Go build something amazing!