{"id":13778137,"url":"https://github.com/cobbr/c2bridge","last_synced_at":"2025-04-13T01:08:25.295Z","repository":{"id":97441538,"uuid":"218523309","full_name":"cobbr/C2Bridge","owner":"cobbr","description":"C2Bridges allow developers to create new custom communication protocols and quickly utilize them within Covenant.","archived":false,"fork":false,"pushed_at":"2021-02-13T23:01:37.000Z","size":374,"stargazers_count":69,"open_issues_count":1,"forks_count":19,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-04-13T01:08:20.810Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://github.com/cobbr/Covenant","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/cobbr.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2019-10-30T12:33:00.000Z","updated_at":"2024-11-01T22:32:48.000Z","dependencies_parsed_at":"2023-03-13T16:13:48.581Z","dependency_job_id":null,"html_url":"https://github.com/cobbr/C2Bridge","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cobbr%2FC2Bridge","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cobbr%2FC2Bridge/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cobbr%2FC2Bridge/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cobbr%2FC2Bridge/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cobbr","download_url":"https://codeload.github.com/cobbr/C2Bridge/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248650762,"owners_count":21139681,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-03T18:00:51.481Z","updated_at":"2025-04-13T01:08:25.250Z","avatar_url":"https://github.com/cobbr.png","language":"C#","funding_links":[],"categories":["\u003ca id=\"1acc99cd2330bc55f1dffecfa75b9c7d\"\u003e\u003c/a\u003eCovenant"],"sub_categories":["\u003ca id=\"05d2a0aed9499aea447e90668c8d5103\"\u003e\u003c/a\u003e工具"],"readme":"C2Bridges allow developers to create new custom communication protocols and quickly utilize them within [Covenant](https://github.com/cobbr/Covenant).\n\n## C2Bridges\n\nC2Bridges are used to develop an outbound command and control protocol without editing any Covenant code. For developers that feel comfortable integrating new listeners, a new C2 protocol should be added as a first-class new listener type that is fully integrated into the interface. However, it may be faster in some situations to create a C2Bridge outside of Covenant and connect it with a `BridgeListener` for proof-of-concepts or testing out new protocols.\n\nDevelopers can use the [C2Bridge](https://github.com/cobbr/C2Bridge) project as a template for creating new C2Bridges. Within the C2Bridge project, there is an abstract `C2Bridge` class. A developer can inherit from this class and implement the needed functions to read and write from implants to the BridgeListener using the new chosen C2 protocol.\n\n```\nusing System.Threading;\nusing System.Threading.Tasks;\n\nnamespace C2Bridge\n{\n    /// \u003csummary\u003e\n    /// IC2Bridge is an interface implemented by the C2Bridge class.\n    /// \u003c/summary\u003e\n    public interface IC2Bridge\n    {\n        Task RunAsync(CancellationToken token);\n    }\n\n    /// \u003csummary\u003e\n    /// C2Bridge is an abstract class that new C2Bridges should inherit from. \n    /// \u003c/summary\u003e\n    public abstract class C2Bridge : IC2Bridge\n    {\n        // The BridgeConnector handles communication between the Covenant server and the C2Bridge\n        protected BridgeConnector BridgeConnector { get; set; }\n        // The BridgeProfile handles parsing and formatting data passed between the implant and Covenant\n        protected BridgeProfile BridgeProfile { get; set; }\n\n        /// \u003csummary\u003e\n        /// The constructor for the C2Bridge. New C2Bridges should use their own constructor that accepts\n        /// any command line arguments needed for the C2Bridge to function.\n        /// \u003c/summary\u003e\n        /// \u003cparam name=\"Connector\"\u003eThe BridgeConnector that handles communication with the Covenant server.\u003c/param\u003e\n        /// \u003cparam name=\"Profile\"\u003eThe BridgeProfile that handles the parsing and formatting of data.\u003c/param\u003e\n        protected C2Bridge(BridgeConnector Connector, BridgeProfile Profile)\n        {\n            this.BridgeConnector = Connector;\n            this.BridgeProfile = Profile;\n            BridgeConnector.OnReadBridge += OnReadBridge;\n        }\n\n        /// \u003csummary\u003e\n        /// The RunAsync function is the main function that should start the C2Bridge and continue to run until you\n        /// are done with your operation. C2Bridge developers should implement the logic to start and run the listener\n        /// within this function.\n        /// \u003c/summary\u003e\n        /// \u003cparam name=\"Token\"\u003eThe CancellationToken that will cancel the C2Bridge if the source of the token is cancelled.\u003c/param\u003e\n        /// \u003creturns\u003e\u003c/returns\u003e\n        public abstract Task RunAsync(CancellationToken Token);\n\n        /// \u003csummary\u003e\n        /// The OnReadBridge function is called each time data is read from the Covenant server meant for an implant.\n        /// C2Bridge developers should implement the logic to determine which implant this data is meant for and write\n        /// this data to the implant.\n        /// \u003c/summary\u003e\n        /// \u003cparam name=\"sender\"\u003e\n        /// Sender is the object that called the OnReadBridge function. C2Bridge developers can safely ignore this parameter.\n        /// \u003c/param\u003e\n        /// \u003cparam name=\"args\"\u003eArgs contains the data that should be written from the Covenant server to the implant.\u003c/param\u003e\n        protected abstract void OnReadBridge(object sender, BridgeConnector.ReadBridgeArgs args);\n\n        /// \u003csummary\u003e\n        /// The WriteToConnector function handles writing data from an implant to the Covenant server. This logic should be the\n        /// same for all C2Bridge types, but can be overloaded by the C2Bridge developer if custom logic is needed.\n        ///\n        /// When calling this function, the returned GUID string should be used to track implant GUID values by the C2Bridge.\n        /// \u003c/summary\u003e\n        /// \u003cparam name=\"Data\"\u003eThe data read from the implant that should be written to the Covenant server.\u003c/param\u003e\n        /// \u003creturns\u003e\n        /// Returns the GUID value parsed out of the Data. This value should be used to track implant GUID values by the C2Bridge.\n        /// \u003c/returns\u003e\n        protected virtual string WriteToConnector(string Data)\n        {\n            var parsed = this.BridgeProfile.ParseWrite(Data);\n            if (parsed != null)\n            {\n                _ = this.BridgeConnector.Write(this.BridgeProfile.FormatRead(parsed));\n                return parsed.Guid;\n            }\n            return null;\n        }\n\n        /// \u003csummary\u003e\n        /// The GetBridgeMessengerCode function should contain the code to be embedded in the implant for communication with\n        /// the C2Bridge. This function is not actually used anywhere within the project, but is here so that the necessary\n        /// implant code can be found along with the C2Bridge. C2Bridge developers should place the code here for use within\n        /// a BridgeProfile's BridgeMessengerCode property.\n        /// \u003c/summary\u003e\n        /// \u003creturns\u003e\u003c/returns\u003e\n        protected abstract string GetBridgeMessengerCode();\n    }\n}\n```\n\nThe C2Bridge project contains an example `TCPC2Bridge` class that inherits from this interface and provides an example of how to implement one.\n\n![TCPC2Bridge](https://github.com/cobbr/Covenant/wiki/images/covenant-tcpc2bridge.png)\n\nOnce you have written your new C2Bridge, the constructor call for `TCPC2Bridge` within the `Main()` function can be replaced with the new constructor:\n\n![C2Bridge Constructor](https://github.com/cobbr/Covenant/wiki/images/covenant-c2bridgeconstructor.png)\n\nThe abstract `GetBridgeMessengerCode()` method is not actually used anywhere within the C2Bridge project but is used to tie together a C2Bridge with an implant. An implant needs code that is able to read and write to the outbound C2Bridge. This code is specific to a given C2Bridge, and should be placed within the inherited `GetBridgeMessengerCode()` method. A Covenant user that utilizes a C2Bridge will take the `BridgeMessengerCode` from this method and use it within a `BridgeProfile`.\n\n### BridgeProfile\n\nCovenant users that utilize a C2Bridge will need to configure a `BridgeProfile` that is specific to the C2Bridge. The Grunt implants need to know how to read and write to the outbound C2Bridge. The `BridgeProfile.BridgeMessengerCode` property represents the code that will be placed in the implant and is responsible for reading and writing to the outbound C2Bridge. This code should be found in a C2Bridge's `GetBridgeMessengerCode()` method.\n\nUsers can create an entirely new `BridgeProfile` or edit the `DefaultBridgeProfile` with the correct `BridgeMessengerCode`. To do so, you'll navigate to the listeners navigation page and select the \"Profiles\" tab:\n\n![Profiles Table](https://github.com/cobbr/Covenant/wiki/images/covenant-gui-profiles.png)\n\nTo create a new profile, click on the \"Create\" button. To edit a particular profile, click on the name of the profile. Keep in mind, that you cannot edit profiles that are associated with active listeners.\n\nAfter clicking \"Create\", select the \"BridgeProfile\" tab:\n\n![Create BridgeProfile](https://github.com/cobbr/Covenant/wiki/images/covenant-gui-bridgeprofilecreate.png)\n\nThe following options will need to be configured when editing or creating a profile:\n\n* **Name** - The `Name` of the profile that will be used throughout the interface. Pick something recognizable!\n* **Description** - The `Description` of the profile. This should be a thorough description of the profile that operators can read and easily understand how the profile works, and the use cases for which it would be appropriate to use the profile. \n* **MessageTransform** - The `MessageTransform` is a unique way to specify how the communication data will be transformed before being placed into the formats specified in the `ReadFormat` and `WriteFormat`. An `MessageTransform` should be a static C# class named `MessageTransform` that includes a public `Transform` and a public `Invert` function. The class can transform the data in any way that you desire, as long as the Transform and Invert functions mirror each other (i.e. `data == MessageTransform.Invert(MessageTransform.Transform(data))`). The `MessageTransform` class must be cross-platform compatible and compile under `Net40`, `Net35`, and `NetCore21`.\n* **ReadFormat** - The `ReadFormat` is the format of a message when a Grunt reads data from a C2Bridge. The format must include a location for the data and Grunt GUID to be placed. Include the string \"{DATA}\" to indicate the location that the data should be placed and the string \"{GUID}\" to indicate the location that the GUID should be placed.\n* **WriteFormat** - The `WriteFormat` is the format of a message when a Grunt writes data to a C2Bridge. The format must include a location for the data and Grunt GUID to be placed. Include the string \"{DATA}\" to indicate the location that the data should be placed and the string \"{GUID}\" to indicate the location that the GUID should be placed.\n* **BridgeMessengerCode** - The `BridgeMessengerCode` is the code that will be placed in the implant and is responsible for reading and writing to the outbound C2Bridge. This code should be found in a C2Bridge's `GetBridgeMessengerCode()` method.\n\nWhen configuring these options, the Covenant user has total freedom to configure any of these values any way they would like, except for the `BridgeMessengerCode` property. The `BridgeMessengerCode` propery must be taken from the C2Bridge.\n\nIf a Covenant user does edit the `ReadFormat` and/or `WriteFormat` properties, the C2Bridge must be informed of this change when starting the C2Bridge. The [C2Bridge](https://github.com/cobbr/C2Bridge) project accepts a `--profile \u003cprofile.yaml\u003e` parameter that accepts a profile YAML file, which can optionally be used when these properties are customized.\n\n### Summary\n\nThe overall process for developing and utilizing a C2Bridge is as follows:\n\n1. Write the \"listener\" code for reading and writing on a custom command and control protocol to an implant.\n2. Write the implant code for reading and writing on a custom command and control protocol to a \"listener\".\n3. Implement a C2Bridge using the \"listener\" and implant code that inherits from the abstract `C2Bridge` class from the [C2Bridge](https://github.com/cobbr/C2Bridge) project. Reference the `TCPC2Bridge` class as an example.\n4. Within Covenant, create a `BridgeProfile` that uses the `BridgeMessengerCode` found in the C2Bridge's `GetBridgeMessengerCode()` method.\n5. Start a [BridgeListener](https://github.com/cobbr/Covenant/wiki/Bridge-Listeners) that uses the created `BridgeProfile`.\n6. Start the C2Bridge that connects to the BridgeListener. If you customized the BridgeProfile's `ReadFormat` and/or `WriteFormat` properties, use the optional `--profile \u003cprofile.yaml\u003e` CLI parameter to inform the C2Bridge of these customizations.\n7. Generate launchers that utilize the `GruntBridge` ImplantTemplate and the BridgeListener you started.\n8. Test out your new launcher that utilizes a custom command and control protocol!\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcobbr%2Fc2bridge","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcobbr%2Fc2bridge","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcobbr%2Fc2bridge/lists"}