mirror of https://github.com/infosecn1nja/C3.git
update in response to merge comments. Covenant connector now looks for C3Bridge listener before creating one. User now only supplies listener port, url, username and password
parent
6a7598c814
commit
86244b322d
|
@ -136,9 +136,54 @@ namespace MWR::C3::Interfaces::Connectors
|
||||||
|
|
||||||
/// Map of all connections.
|
/// Map of all connections.
|
||||||
std::unordered_map<std::string, std::unique_ptr<Connection>> m_ConnectionMap;
|
std::unordered_map<std::string, std::unique_ptr<Connection>> m_ConnectionMap;
|
||||||
|
|
||||||
|
bool GetListenerId();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool MWR::C3::Interfaces::Connectors::Covenant::GetListenerId()
|
||||||
|
{
|
||||||
|
std::string url = this->m_webHost + OBF("/api/listeners");
|
||||||
|
json response;
|
||||||
|
|
||||||
|
web::http::client::http_client_config config;
|
||||||
|
config.set_validate_certificates(false); //Covenant framework is unlikely to have a valid cert.
|
||||||
|
|
||||||
|
web::http::client::http_client webClient(utility::conversions::to_string_t(url), config);
|
||||||
|
web::http::http_request request;
|
||||||
|
|
||||||
|
request = web::http::http_request(web::http::methods::GET);
|
||||||
|
|
||||||
|
std::string authHeader = OBF("Bearer ") + this->m_token;
|
||||||
|
request.headers().add(OBF_W(L"Authorization"), utility::conversions::to_string_t(authHeader));
|
||||||
|
pplx::task<web::http::http_response> task = webClient.request(request);
|
||||||
|
|
||||||
|
web::http::http_response resp = task.get();
|
||||||
|
|
||||||
|
if (resp.status_code() == web::http::status_codes::OK)
|
||||||
|
{
|
||||||
|
//Get the json response
|
||||||
|
auto respData = resp.extract_string();
|
||||||
|
response = json::parse(respData.get());
|
||||||
|
|
||||||
|
for (auto& listeners : response)
|
||||||
|
{
|
||||||
|
if (listeners[OBF("name")] == OBF("C3Bridge"))
|
||||||
|
{
|
||||||
|
this->m_ListenerId = listeners[OBF("id")].get<int>();
|
||||||
|
this->m_ListeningPostAddress = listeners[OBF("connectAddresses")][0].get<std::string>();
|
||||||
|
this->m_ListeningPostPort = listeners[OBF("connectPort")];
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false; //we didn't find the listener
|
||||||
|
}
|
||||||
|
else
|
||||||
|
throw std::exception((OBF("[Covenant] Error getting Listeners, HTTP resp: ") + std::to_string(resp.status_code())).c_str());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
MWR::C3::Interfaces::Connectors::Covenant::Covenant(ByteView arguments)
|
MWR::C3::Interfaces::Connectors::Covenant::Covenant(ByteView arguments)
|
||||||
|
@ -146,7 +191,12 @@ MWR::C3::Interfaces::Connectors::Covenant::Covenant(ByteView arguments)
|
||||||
json postData;
|
json postData;
|
||||||
json response;
|
json response;
|
||||||
|
|
||||||
std::tie(m_ListeningPostAddress, m_ListeningPostPort, m_webHost, m_username, m_password) = arguments.Read<std::string, uint16_t, std::string, std::string, std::string>();
|
std::tie(m_ListeningPostPort, m_webHost, m_username, m_password) = arguments.Read<uint16_t, std::string, std::string, std::string>();
|
||||||
|
|
||||||
|
// if the last character is '/' remove it
|
||||||
|
if (this->m_webHost.back() == '/')
|
||||||
|
this->m_webHost.pop_back();
|
||||||
|
|
||||||
|
|
||||||
/***Authenticate to Web API ***/
|
/***Authenticate to Web API ***/
|
||||||
std::string url = this->m_webHost + OBF("/api/users/login");
|
std::string url = this->m_webHost + OBF("/api/users/login");
|
||||||
|
@ -182,6 +232,16 @@ MWR::C3::Interfaces::Connectors::Covenant::Covenant(ByteView arguments)
|
||||||
else
|
else
|
||||||
throw std::exception(OBF("[Covenant] Could not get token, invalid logon"));
|
throw std::exception(OBF("[Covenant] Could not get token, invalid logon"));
|
||||||
|
|
||||||
|
//If the listener doesn't already exist create it.
|
||||||
|
if (!GetListenerId())
|
||||||
|
{
|
||||||
|
//extract ip address from url
|
||||||
|
size_t start = 0, end = 0;
|
||||||
|
start = url.find("://") + 3;
|
||||||
|
end = url.find(":", start + 1);
|
||||||
|
|
||||||
|
this->m_ListeningPostAddress = url.substr(start, end - start);
|
||||||
|
|
||||||
///Create the bridge listener
|
///Create the bridge listener
|
||||||
url = this->m_webHost + OBF("/listener/createbridge");
|
url = this->m_webHost + OBF("/listener/createbridge");
|
||||||
web::http::client::http_client webClientBridge(utility::conversions::to_string_t(url), config);
|
web::http::client::http_client webClientBridge(utility::conversions::to_string_t(url), config);
|
||||||
|
@ -200,51 +260,12 @@ MWR::C3::Interfaces::Connectors::Covenant::Covenant(ByteView arguments)
|
||||||
resp = task.get();
|
resp = task.get();
|
||||||
|
|
||||||
if (resp.status_code() == web::http::status_codes::OK)
|
if (resp.status_code() == web::http::status_codes::OK)
|
||||||
{
|
GetListenerId(); //now get the id of the listener
|
||||||
//Find the listener we just created
|
else
|
||||||
url = this->m_webHost + OBF("/api/listeners");
|
throw std::exception((OBF("[Covenant] Error setting up BridgeListener, HTTP resp: ") + std::to_string(resp.status_code())).c_str());
|
||||||
web::http::client::http_client webClientListeners(utility::conversions::to_string_t(url), config);
|
|
||||||
|
|
||||||
request = web::http::http_request(web::http::methods::GET);
|
|
||||||
|
|
||||||
std::string authHeader = OBF("Bearer ") + this->m_token;
|
|
||||||
request.headers().add(OBF_W(L"Authorization"), utility::conversions::to_string_t(authHeader));
|
|
||||||
|
|
||||||
task = webClientListeners.request(request);
|
|
||||||
resp = task.get();
|
|
||||||
|
|
||||||
bool found = false;
|
|
||||||
|
|
||||||
|
|
||||||
if (resp.status_code() == web::http::status_codes::OK)
|
|
||||||
{
|
|
||||||
//Get the json response
|
|
||||||
auto respData = resp.extract_string();
|
|
||||||
response = json::parse(respData.get());
|
|
||||||
|
|
||||||
for (auto& listeners : response)
|
|
||||||
{
|
|
||||||
if (listeners[OBF("name")] == OBF("C3Bridge"))
|
|
||||||
{
|
|
||||||
this->m_ListenerId = listeners[OBF("id")].get<int>();
|
|
||||||
found = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
//will be true if status_code != OK or C3Bridge wasn't found
|
|
||||||
if (!found)
|
|
||||||
{
|
|
||||||
throw std::exception(OBF("[Covenant] unable to identify ID of Bridge Listener"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
InitializeSockets();
|
InitializeSockets();
|
||||||
}
|
|
||||||
else
|
|
||||||
throw std::exception((OBF("[Covenant] Error setting up BridgeListener, HTTP resp: ") + std::to_string(resp.status_code())).c_str());
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
MWR::C3::Interfaces::Connectors::Covenant::~Covenant()
|
MWR::C3::Interfaces::Connectors::Covenant::~Covenant()
|
||||||
|
@ -328,10 +349,17 @@ MWR::ByteVector MWR::C3::Interfaces::Connectors::Covenant::GeneratePayload(ByteV
|
||||||
task = webClient.request(request);
|
task = webClient.request(request);
|
||||||
resp = task.get();
|
resp = task.get();
|
||||||
|
|
||||||
|
if (resp.status_code() == web::http::status_codes::OK)
|
||||||
|
{
|
||||||
auto respData = resp.extract_string();
|
auto respData = resp.extract_string();
|
||||||
json resp = json::parse(respData.get());
|
json resp = json::parse(respData.get());
|
||||||
binary = resp[OBF("base64ILByteString")].get<std::string>(); //Contains the base64 encoded .NET assembly.
|
binary = resp[OBF("base64ILByteString")].get<std::string>(); //Contains the base64 encoded .NET assembly.
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
throw std::runtime_error(OBF("[Covenant] Non-200 HTTP code returned: ") + std::to_string(resp.status_code()));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
throw std::runtime_error(OBF("[Covenant] Non-200 HTTP code returned: ") + std::to_string(resp.status_code()));
|
||||||
|
|
||||||
auto payload = cppcodec::base64_rfc4648::decode(binary);
|
auto payload = cppcodec::base64_rfc4648::decode(binary);
|
||||||
|
|
||||||
|
@ -348,8 +376,7 @@ MWR::ByteVector MWR::C3::Interfaces::Connectors::Covenant::GeneratePayload(ByteV
|
||||||
|
|
||||||
MWR::ByteVector MWR::C3::Interfaces::Connectors::Covenant::CloseConnection(ByteView arguments)
|
MWR::ByteVector MWR::C3::Interfaces::Connectors::Covenant::CloseConnection(ByteView arguments)
|
||||||
{
|
{
|
||||||
auto id = arguments.Read<std::string>();
|
m_ConnectionMap.erase(arguments);
|
||||||
m_ConnectionMap.erase(id);
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -377,16 +404,11 @@ MWR::ByteView MWR::C3::Interfaces::Connectors::Covenant::GetCapability()
|
||||||
{
|
{
|
||||||
"arguments":
|
"arguments":
|
||||||
[
|
[
|
||||||
{
|
|
||||||
"type": "ip",
|
|
||||||
"name": "Address",
|
|
||||||
"description": "C2Bridge ip address - this will be setup automatically"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"type": "uint16",
|
"type": "uint16",
|
||||||
"name": "Port",
|
"name": "C2BridgePort",
|
||||||
"min": 1,
|
"min": 1,
|
||||||
"description": "C2Bridge port - this will be setup automatically"
|
"description": "The port for the C2Bridge Listener if it doesn't already exist."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "string",
|
"type": "string",
|
||||||
|
@ -560,3 +582,4 @@ MWR::ByteVector MWR::C3::Interfaces::Connectors::Covenant::PeripheralCreationCom
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -193,7 +193,7 @@ MWR::C3::Interfaces::Peripherals::Grunt::Grunt(ByteView arguments)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::runtime_error{ OBF("Grunt creation failed") };
|
throw std::runtime_error{ OBF("Grunt creation failed") };
|
||||||
}
|
}
|
||||||
|
|
||||||
void MWR::C3::Interfaces::Peripherals::Grunt::OnCommandFromConnector(ByteView data)
|
void MWR::C3::Interfaces::Peripherals::Grunt::OnCommandFromConnector(ByteView data)
|
||||||
|
|
Loading…
Reference in New Issue