### Initialize and Start Multiple HTTP Webserver Instances (Go) Source: https://context7.com/mythicc2profiles/http/llms.txt This Go code initializes and starts multiple Gin HTTP server instances based on a configuration file. It handles SSL/TLS setup, routing, and reverse proxy logic. Dependencies include the Gin web framework and MythicContainer logging. Input is derived from a local configuration file. ```go package main import ( "mythicHTTP/webserver" "github.com/MythicMeta/MythicContainer/logging" ) func main() { // Load configuration from config.json webserver.InitializeLocalConfig() // Initialize and start each configured webserver instance for index, instance := range webserver.Config.Instances { logging.LogInfo("Initializing webserver", "instance", index+1) // Create Gin router with routes and middleware router := webserver.Initialize(instance) // Start the webserver (SSL or non-SSL based on config) logging.LogInfo("Starting webserver", "instance", index+1) webserver.StartServer(router, instance) } // Block forever to keep servers running forever := make(chan bool) <-forever } // Example webserver configuration // From C2_Profiles/http/http/c2_code/config.json type instanceConfig struct { Port int `json:"port"` // 80 KeyPath string `json:"key_path"` // "privkey.pem" CertPath string `json:"cert_path"` // "fullchain.pem" Debug bool `json:"debug"` // true UseSSL bool `json:"use_ssl"` // false Headers map[string]string `json:"ServerHeaders"` // Custom headers PayloadHostPaths map[string]string `json:"payloads"` // Path to file UUID mapping BindIP string `json:"bind_ip"` // Optional bind address ErrorFilePath string `json:"error_file_path"` // Custom error page ErrorStatusCode int `json:"error_status_code"` // 404 } ``` -------------------------------- ### Install and Manage HTTP C2 Profile with mythic-cli (Bash) Source: https://context7.com/mythicc2profiles/http/llms.txt Provides commands for installing and managing the HTTP C2 profile using the `mythic-cli` utility. This includes installation from GitHub (main branch or specific branches), local folders, starting/stopping the C2 container, restarting all Mythic services, and viewing container logs for debugging. ```bash # Install from GitHub main branch sudo ./mythic-cli install github https://github.com/MythicC2Profiles/http # Install from specific branch sudo ./mythic-cli install github https://github.com/MythicC2Profiles/http dev-branch # Install from local folder sudo ./mythic-cli install folder /path/to/cloned/http # Start the HTTP C2 profile container sudo ./mythic-cli c2 start http # Stop the HTTP C2 profile container sudo ./mythic-cli c2 stop http # Restart all Mythic services including new profile sudo ./mythic-cli mythic start # View container logs for debugging sudo ./mythic-cli c2 logs http ``` -------------------------------- ### HTTP C2 Server Startup Output Example Source: https://github.com/mythicc2profiles/http/blob/master/documentation-c2/http/_index.md This output indicates that the HTTP C2 server has started successfully. It shows the process ID, debugging status, and the address the server is listening on. This output is typically seen when debugging is enabled. ```text Messages will disappear when this dialog is closed. Received Message: Started with pid: 16... Output: Opening config and starting instances... Debugging statements are enabled. This gives more context, but might be a performance hit not using SSL for port 80 [2020-07-29 21:48:26 +0000] [16] [INFO] Goin' Fast @ http://0.0.0.0:80 ``` -------------------------------- ### Generate Sample Curl Commands (Go) Source: https://context7.com/mythicc2profiles/http/llms.txt Generates example curl commands for both GET and POST requests to test agent connectivity. It takes configuration parameters like headers, callback host and port, and extracts a sample encrypted payload. The function supports creating base64 URL-encoded and standard-encoded payloads. ```go SampleMessageFunction: func(message c2structs.C2SampleMessageMessage) c2structs.C2SampleMessageResponse { response := c2structs.C2SampleMessageResponse{Success: true} // Extract configuration parameters headers, _ := message.GetDictionaryArg("headers") callbackHost, _ := message.GetStringArg("callback_host") callbackPort, _ := message.GetNumberArg("callback_port") // Create sample encrypted payload sampleRawBytesGeneric, _ := base64.URLEncoding.DecodeString( "MjQ1M2Q2NjQtYmZhNC00ZTI5LTgzMjEtNTgxYzQwNDBjYWM5Iv_gaPq1yVK76sNsMwCgtIOOQPWJ_fO0YBZGtyvdGIcDXnaTmlG6GLJ-ZV9NdhfNKxlM4u7JOHQeB4zJmQiNf1mqokqvhh1Vm9dYRc8O87J8oIv-H1sIENR-NDW1mirT") sampleRawBytes := make([]byte, len(sampleRawBytesGeneric)) sourceUUID := "00000000-0000-0000-0000-000000000000" copy(sampleRawBytes, sourceUUID) copy(sampleRawBytes[len(sourceUUID):], sampleRawBytesGeneric[len(sourceUUID):]) // Generate base64 encodings for GET and POST base64URLEncoding := base64.URLEncoding.EncodeToString(sampleRawBytes) base64StdEncoding := base64.StdEncoding.EncodeToString(sampleRawBytes) // Build curl command for GET request sampleCURLGet := "curl " for key, value := range headers { sampleCURLGet += fmt.Sprintf("-H \"%s: %s\" ", key, value) } getURI, _ := message.GetStringArg("get_uri") queryPathForGet, _ := message.GetStringArg("query_path_name") sampleCURLGet += fmt.Sprintf("%s:%d/%s?%s=%s", callbackHost, int(callbackPort), getURI, queryPathForGet, base64URLEncoding) // Build curl command for POST request sampleCURLPost := fmt.Sprintf("curl -X POST -d \"%s\" ", base64StdEncoding) for key, value := range headers { sampleCURLPost += fmt.Sprintf("-H \"%s: %s\" ", key, value) } postURI, _ := message.GetStringArg("post_uri") sampleCURLPost += fmt.Sprintf("%s:%d/%s", callbackHost, int(callbackPort), postURI) response.Message = fmt.Sprintf("GET:\n%s\n\nPOST:\n%s\n\n", sampleCURLGet, sampleCURLPost) return response } ``` -------------------------------- ### Build Mythic HTTP C2 Docker Image Source: https://context7.com/mythicc2profiles/http/llms.txt This Dockerfile defines the build process for the Mythic HTTP C2 container. It uses a multi-stage build, first compiling the Go binaries and then copying them into a lightweight Alpine Linux image. The container is configured to start the server using 'make run' on launch. ```dockerfile FROM golang:1.25 as builder WORKDIR /Mythic/ COPY . . # Build both main container and webserver binaries RUN make build FROM alpine:latest WORKDIR /Mythic/ # Copy compiled binaries from builder stage COPY --from=builder /Mythic/ /Mythic/ # Start the server on container launch CMD ["make", "run"] ``` -------------------------------- ### Register HTTP C2 Profile with Mythic Framework (Go) Source: https://context7.com/mythicc2profiles/http/llms.txt This Go code snippet initializes the HTTP C2 profile functions and registers them with the Mythic framework. It then starts the container service to listen for gRPC messages. Dependencies include MythicContainer and custom httpfunctions. ```go package main import ( httpfunctions "MyContainer/http/c2functions" "github.com/MythicMeta/MythicContainer" ) func main() { // Initialize HTTP C2 profile functions and register with Mythic httpfunctions.Initialize() // Start the container service and listen for gRPC messages from Mythic MythicContainer.StartAndRunForever([]MythicContainer.MythicServices{ MythicContainer.MythicServiceC2, }) } // The Initialize function registers the profile definition // From c2functions/builder.go func Initialize() { c2structs.AllC2Data.Get("http").AddC2Definition(httpc2definition) c2structs.AllC2Data.Get("http").AddIcon(filepath.Join(".", "http.svg")) c2structs.AllC2Data.Get("http").AddParameters(httpc2parameters) } ``` -------------------------------- ### Validate C2 Configuration (Go) Source: https://context7.com/mythicc2profiles/http/llms.txt Validates callback host and port configurations against the C2 server's settings. It detects SSL mismatches and provides guidance for redirector setups. This function takes a C2ConfigCheckMessage and returns a C2ConfigCheckMessageResponse. ```go ConfigCheckFunction: func(message c2structs.C2ConfigCheckMessage) c2structs.C2ConfigCheckMessageResponse { response := c2structs.C2ConfigCheckMessageResponse{Success: true} // Extract callback parameters suppliedPort := int(message.Parameters["callback_port"].(float64)) suppliedHost := message.Parameters["callback_host"].(string) // Load current webserver configuration currentConfig, err := getC2JsonConfig() if err != nil { response.Success = false response.Error = err.Error() return response } // Check each configured instance for port and SSL match for _, instance := range currentConfig.Instances { if instance.Port == suppliedPort { // Validate SSL configuration matches between agent and server if strings.HasPrefix(suppliedHost, "https") && !instance.UseSSL { message := fmt.Sprintf( "C2 Profile container is configured to NOT use SSL on port %d, " + "but the callback host for the agent is using https, %s.\n\n" + "This means there should be the following connectivity for success:\n" + "Agent via SSL to %s on port %d, then redirection to C2 Profile " + "container WITHOUT SSL on port %d", instance.Port, suppliedHost, suppliedHost, suppliedPort, suppliedPort) response.Error = message return response } else if !strings.HasPrefix(suppliedHost, "https") && instance.UseSSL { message := fmt.Sprintf( "C2 Profile container is configured to use SSL on port %d, " + "but the callback host for the agent is using http, %s.\n\n" + "This means there should be the following connectivity for success:\n" + "Agent via NO SSL to %s on port %d, then redirection to C2 Profile " + "container WITH SSL on port %d", instance.Port, suppliedHost, suppliedHost, suppliedPort, suppliedPort) response.Error = message return response } // Configuration is valid response.Message = fmt.Sprintf( "C2 Profile container and agent configuration match port, %d, " + "and SSL expectations (%v)\n", instance.Port, instance.UseSSL) return response } } // Port not found - likely using redirector response.Message = "Specified use of SSL and ports indicate the use of a redirector" return response } ``` -------------------------------- ### Extract Indicators of Compromise (IOCs) from C2 Configuration Source: https://context7.com/mythicc2profiles/http/llms.txt Extracts Indicators of Compromise (IOCs) from C2 callback configurations. It identifies and formats URLs for POST and GET requests, including query parameters, as well as the base URL. This aids in threat intelligence and defensive analysis. ```go GetIOCFunction: func(message c2structs.C2GetIOCMessage) c2structs.C2GetIOCMessageResponse { response := c2structs.C2GetIOCMessageResponse{Success: true} // Extract basic connection information callbackHost, _ := message.GetStringArg("callback_host") callbackPort, _ := message.GetNumberArg("callback_port") // Add POST URI as IOC if present postURI, err := message.GetStringArg("post_uri") if err == nil { response.IOCs = append(response.IOCs, c2structs.IOC{ Type: "url", IOC: fmt.Sprintf("%s:%v/%s", callbackHost, callbackPort, postURI), }) } // Add GET URI with query parameter as IOC if present getURI, err := message.GetStringArg("get_uri") if err == nil { queryPathForGet, err := message.GetStringArg("query_path_name") if err == nil { response.IOCs = append(response.IOCs, c2structs.IOC{ Type: "url", IOC: fmt.Sprintf("%s:%v/%s?%s=", callbackHost, callbackPort, getURI, queryPathForGet), }) } } // Add base URL as IOC response.IOCs = append(response.IOCs, c2structs.IOC{ Type: "url", IOC: fmt.Sprintf("%s:%v", callbackHost, callbackPort), }) return response } ``` -------------------------------- ### Load Webserver Configuration from JSON (Go) Source: https://context7.com/mythicc2profiles/http/llms.txt Loads webserver configuration from a `config.json` file. It ensures the file exists, creating it if necessary. The function reads the file content and unmarshals it into a `config` struct, handling potential errors during file reading and JSON parsing. It uses predefined `config` and `instanceConfig` structs to define the configuration schema. ```go type config struct { Instances []instanceConfig `json:"instances"` } type instanceConfig struct { Port int `json:"port"` KeyPath string `json:"key_path"` CertPath string `json:"cert_path"` Debug bool `json:"debug"` UseSSL bool `json:"use_ssl"` Headers map[string]string `json:"ServerHeaders"` PayloadHostPaths map[string]string `json:"payloads"` BindIP string `json:"bind_ip"` ErrorFilePath string `json:"error_file_path"` ErrorStatusCode int `json:"error_status_code"` } func InitializeLocalConfig() { // Ensure config.json exists if !fileExists(filepath.Join(getCwdFromExe(), "config.json")) { if _, err := os.Create(filepath.Join(getCwdFromExe(), "config.json")); err != nil { logging.LogFatalError(err, "config.json doesn't exist and couldn't be created") } } // Read and unmarshal configuration fileData, err := os.ReadFile("config.json") if err != nil { logging.LogError(err, "Failed to read in config.json file") return } err = json.Unmarshal(fileData, &Config) if err != nil { logging.LogError(err, "Failed to unmarshal config bytes") return } logging.LogInfo("[+] Successfully read in config.json") } ``` -------------------------------- ### Manage Mythic HTTP C2 Docker Containers Source: https://context7.com/mythicc2profiles/http/llms.txt A collection of bash commands for managing the Mythic HTTP C2 Docker image and containers. This includes building the image locally, running a container with environment variables, building with custom arguments, viewing logs, and pulling a pre-built image. ```bash # Build Docker image locally cd C2_Profiles/http docker build -t mythic-http-c2:latest . # Run container with environment variables docker run -d \ --name mythic-http \ -e MYTHIC_SERVER_HOST=mythic_server \ -e MYTHIC_SERVER_PORT=17443 \ -p 80:80 \ mythic-http-c2:latest # Build with custom configuration docker build --build-arg GO_VERSION=1.25 -t mythic-http-c2:custom . # View container logs docker logs -f mythic-http # Use pre-built image from GitHub Container Registry docker pull ghcr.io/mythicc2profiles/http:v0.0.3.2 ``` -------------------------------- ### Multi-stage Docker Build for HTTP C2 Profile (Dockerfile) Source: https://context7.com/mythicc2profiles/http/llms.txt Illustrates a multi-stage Docker build process designed for creating optimized production containers. This approach typically involves a builder stage for compiling code and dependencies, followed by a final stage that includes only the necessary artifacts for runtime, resulting in smaller and more secure images. The provided snippet is a placeholder for the actual Dockerfile content. ```dockerfile # Placeholder for multi-stage Docker build instructions. # Actual content would define builder and runtime stages. ``` -------------------------------- ### Configure Go Reverse Proxy with Custom Routing and Headers Source: https://context7.com/mythicc2profiles/http/llms.txt This Go function `setRoutes` configures a `gin.Engine` to act as a reverse proxy. It uses `httputil.ReverseProxy` to forward requests to a Mythic API endpoint. The `director` function modifies request headers and URL before forwarding, while `modifyResponse` can customize error responses. The `getRequest` function applies additional headers for evasion before proxying. ```go func setRoutes(r *gin.Engine, configInstance instanceConfig) { // Configure director to modify requests before forwarding to Mythic director := func(req *http.Request) { // Add custom headers for Mythic identification and tracking req.Header.Add("mythic", "http") req.Header.Add("X-forwarded-user-agent", req.Header.Get("User-Agent")) req.Header.Add("x-forwarded-url", req.URL.RequestURI()) req.Header.Add("x-forwarded-for", req.RemoteAddr) req.Header.Add("x-forwarded-host", req.Host) // Rewrite request to target Mythic's agent_message endpoint req.URL.Scheme = "http" req.URL.Host = fmt.Sprintf("%s:%d", mythicConfig.MythicConfig.MythicServerHost, mythicConfig.MythicConfig.MythicServerPort) req.Host = req.URL.Host req.URL.Path = "/agent_message" } // Configure response modifier to handle errors with custom pages modifyResponse := func(resp *http.Response) error { if resp.StatusCode != http.StatusOK { if configInstance.ErrorFilePath != "" { statusCode := configInstance.ErrorStatusCode if statusCode == 0 { statusCode = 200 } file, err := os.Open(configInstance.ErrorFilePath) if err != nil { return err } fileStat, _ := file.Stat() resp.Body = io.NopCloser(file) resp.Header["Content-Length"] = []string{fmt.Sprint(fileStat.Size())} resp.StatusCode = statusCode } } return nil } // Create reverse proxy with custom transport settings proxy := &httputil.ReverseProxy{ Director: director, ModifyResponse: modifyResponse, Transport: &http.Transport{ DialContext: (&net.Dialer{ Timeout: 30 * time.Second, }).DialContext, MaxIdleConns: 10, TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, }, } // Register routes for GET and POST requests r.GET("/:val/*action", getRequest(configInstance, proxy)) r.POST("/:val/*action", postRequest(configInstance, proxy)) r.GET("/:val", getRequest(configInstance, proxy)) r.POST("/:val", postRequest(configInstance, proxy)) r.GET("/", getRequest(configInstance, proxy)) r.POST("/", postRequest(configInstance, proxy)) } // Handler that applies custom headers and forwards to proxy func getRequest(configInstance instanceConfig, proxy *httputil.ReverseProxy) gin.HandlerFunc { return func(c *gin.Context) { // Apply custom server headers for evasion for header, val := range configInstance.Headers { c.Header(header, val) } // Set X-Forwarded-For if not already set if c.Request.Header.Get("X-Forwarded-For") == "" { c.Request.Header.Set("X-Forwarded-For", c.ClientIP()) } // Forward request through reverse proxy proxy.ServeHTTP(c.Writer, c.Request) } } ``` -------------------------------- ### HTTP C2 Profile Configuration JSON Source: https://github.com/mythicc2profiles/http/blob/master/documentation-c2/http/_index.md This JSON configuration defines instances of HTTP servers, including headers, ports, SSL settings, and error handling parameters. It allows customization of server responses and error behavior. ```json { "instances": [ { "ServerHeaders": { "Server": "NetDNA-cache/2.2", "Cache-Control": "max-age=0, no-cache", "Pragma": "no-cache", "Connection": "keep-alive", "Content-Type": "application/javascript; charset=utf-8" }, "port": 80, "key_path": "privkey.pem", "cert_path": "fullchain.pem", "debug": true, "use_ssl": false, "error_file_path": "", "error_status_code": 404, "payloads": {} } ] } ``` -------------------------------- ### Host Payload Files (Go) Source: https://context7.com/mythicc2profiles/http/llms.txt Dynamically hosts payload files on specific URL paths by updating the C2 configuration. It can add or remove payload hosting based on a file UUID and a desired URL path. This function requires restarting the internal Mythic server to apply changes. ```go HostFileFunction: func(message c2structs.C2HostFileMessage) c2structs.C2HostFileMessageResponse { // Load current configuration config, err := getC2JsonConfig() if err != nil { return c2structs.C2HostFileMessageResponse{ Success: false, Error: err.Error(), } } // Update all instances with the new payload hosting path for i := range config.Instances { if config.Instances[i].PayloadHostPaths == nil { config.Instances[i].PayloadHostPaths = make(map[string]string) } if message.Remove { // Remove payload hosting for this file for path, fileUUID := range config.Instances[i].PayloadHostPaths { if fileUUID == message.FileUUID { delete(config.Instances[i].PayloadHostPaths, path) } } } else { // Add payload hosting at specified URL path config.Instances[i].PayloadHostPaths[message.HostURL] = message.FileUUID } } // Write updated configuration err = writeC2JsonConfig(config) if err != nil { return c2structs.C2HostFileMessageResponse{ Success: false, Error: err.Error(), } } // Notify Mythic to restart internal server to apply changes return c2structs.C2HostFileMessageResponse{ Success: true, RestartInternalServer: true, } } ``` -------------------------------- ### Generate Apache Redirector Rules (Go) Source: https://context7.com/mythicc2profiles/http/llms.txt Generates Apache mod_rewrite rules for redirector configuration. It uses agent parameters such as URIs and User-Agent strings to create dynamic rules. This function takes a C2GetRedirectorRuleMessage and returns a C2GetRedirectorRuleMessageResponse. ```go GetRedirectorRulesFunction: func(message c2structs.C2GetRedirectorRuleMessage) c2structs.C2GetRedirectorRuleMessageResponse { response := c2structs.C2GetRedirectorRuleMessageResponse{Success: true} // Extract User-Agent from headers ua := "" if headersInterface, ok := message.Parameters["headers"]; ok { headers := headersInterface.(map[string]interface{}) if userAgent, ok := headers["User-Agent"]; ok { ua = userAgent.(string) } } // Extract GET and POST URIs uris := []string{} if getURI, ok := message.Parameters["get_uri"]; ok { uris = append(uris, "/"+getURI.(string)) } if postURI, ok := message.Parameters["post_uri"]; ok { uris = append(uris, "/"+postURI.(string)) } // Escape special characters in User-Agent for mod_rewrite uaString := strings.ReplaceAll(ua, "(", "\\(") uaString = strings.ReplaceAll(uaString, ")", "\\)") // Create URI regex pattern urisString := strings.Join(uris, ".*|") + ".*" // Generate rewrite rules for each configured instance currentConfig, _ := getC2JsonConfig() c2RewriteOutput := []string{} for _, instance := range currentConfig.Instances { scheme := "http" if instance.UseSSL { scheme = "https" } serverURL := fmt.Sprintf("%s://C2_SERVER_HERE:%d", scheme, instance.Port) c2RewriteOutput = append(c2RewriteOutput, fmt.Sprintf("RewriteRule ^.*$ \"%s%%{REQUEST_URI}\" [P,L]", serverURL)) } // Generate complete .htaccess file htaccessTemplate := "\n" "########################################\n" + "## .htaccess START\n" + "RewriteEngine On\n" + "## C2 Traffic (HTTP-GET, HTTP-POST, HTTP-STAGER URIs)\n" + "## Only allow GET and POST methods to pass to the C2 server\n" + "RewriteCond %%{REQUEST_METHOD} ^(GET|POST) [NC]\n" + "## Profile URIs\n" + "RewriteCond %%{REQUEST_URI} ^(%s)$\n" + "## Profile UserAgent\n" + "RewriteCond %%{HTTP_USER_AGENT} \"%s\"\n" + "%s\n" + "## Redirect all other traffic here\n" + "RewriteRule ^.*$ redirect/? [L,R=302]\n" response.Message = fmt.Sprintf(htaccesstemplate, urisString, uaString, strings.Join(c2RewriteOutput, "\n")) return response } ``` -------------------------------- ### Generate Self-Signed ECDSA SSL Certificates (Go) Source: https://context7.com/mythicc2profiles/http/llms.txt Automatically generates self-signed ECDSA certificates (P-384 curve) with a one-year validity period. This function is triggered when SSL is enabled in the configuration but the certificate and key files do not exist. It requires the `configInstance` which specifies the paths for the certificate and key files. ```go func generateCerts(configInstance instanceConfig) error { logging.LogInfo("[*] generating certs now...") // Generate ECDSA private key using P-384 curve priv, err := ecdsa.GenerateKey(elliptic.P384(), rand.Reader) if err != nil { return err } // Set certificate validity period (1 year) notBefore := time.Now() notAfter := notBefore.Add(365 * 24 * time.Hour) // Generate random serial number serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128) serialNumber, err := rand.Int(rand.Reader, serialNumberLimit) if err != nil { return err } // Create certificate template template := x509.Certificate{ SerialNumber: serialNumber, Subject: pkix.Name{ Organization: []string{"Mythic C2"}, }, NotBefore: notBefore, NotAfter: notAfter, KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, BasicConstraintsValid: true, } // Create self-signed certificate derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &priv.PublicKey, priv) if err != nil { return err } // Write certificate to file certOut, err := os.Create(configInstance.CertPath) if err != nil { return err } pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes}) certOut.Close() // Write private key to file keyOut, err := os.OpenFile(configInstance.KeyPath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600) if err != nil { return err } marshalKey, err := x509.MarshalECPrivateKey(priv) if err != nil { return err } pem.Encode(keyOut, &pem.Block{Type: "EC PRIVATE KEY", Bytes: marshalKey}) keyOut.Close() logging.LogInfo("Successfully generated new SSL certs\n") return nil } ``` -------------------------------- ### Generate .htaccess for HTTP C2 Redirection Source: https://context7.com/mythicc2profiles/http/llms.txt Generates an .htaccess file content for Apache servers. This is used to redirect specific traffic based on URI, user agent, and HTTP method to a C2 server, with a fallback redirect for other traffic. It takes URI strings, user agent strings, and rewrite rules as input. ```go func generateHtaccess(urisString string, uaString string, c2RewriteOutput []string) Response { htaccess := fmt.Sprintf(htaccessTemplate, urisString, uaString, strings.Join(c2RewriteOutput, "\n")) response.Message = "#Replace 'C2_SERVER_HERE' with the IP/Domain of C2 server\n" response.Message += "#Replace 'redirect' with redirect destination for non-matching traffic\n\n" response.Message += htaccess return response } ``` -------------------------------- ### Validate OPSEC for HTTP C2 Callback Configuration Source: https://context7.com/mythicc2profiles/http/llms.txt Validates operational security aspects of callback configurations for C2 servers. It checks for default placeholder values, ensures the host format does not include a port, and flags unusual HTTPS ports. Requires callback host and port as parameters. ```go OPSECCheckFunction: func(message c2structs.C2OPSECMessage) c2structs.C2OPSECMessageResponse { response := c2structs.C2OPSECMessageResponse{Success: true} callbackHost := message.Parameters["callback_host"].(string) callbackPort := int(message.Parameters["callback_port"].(float64)) // Check for default placeholder values if callbackHost == "https://domain.com" { response.Success = false response.Error = "Callback Host is set to default of https://domain.com!\n" return response } // Validate host format doesn't include port if len(strings.Split(callbackHost, ":")) != 2 { response.Success = false response.Error = fmt.Sprintf( "callback host is improperly configured! %v shouldn't specify a port, "+ "that should be in the callback_port field", callbackHost) return response } // Check for unusual HTTPS ports that may raise suspicion if strings.HasPrefix(callbackHost, "https") { standardHttpsPorts := []int{443, 8443, 7443} isStandardPort := false for _, port := range standardHttpsPorts { if port == callbackPort { isStandardPort = true break } } if !isStandardPort { response.Success = true response.Message = fmt.Sprintf( "Callback port, %d, is unusual for https scheme", callbackPort) return response } } response.Message = "No immediate issues with configuration" return response } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.