mirror of
https://github.com/maxDcb/C2TeamServer
synced 2026-06-06 16:14:27 +00:00
Extract
This commit is contained in:
@@ -5,6 +5,7 @@ include_directories(../core/modules/ModuleCmd)
|
||||
set(SOURCES_TEAMSERVER
|
||||
teamServer/TeamServer.cpp
|
||||
teamServer/TeamServerAuth.cpp
|
||||
teamServer/TeamServerHelpService.cpp
|
||||
teamServer/TeamServerRuntimeConfig.cpp
|
||||
teamServer/TeamServerBootstrap.cpp
|
||||
teamServer/TeamServerListenerSessionService.cpp
|
||||
@@ -36,8 +37,11 @@ if(WITH_TESTS)
|
||||
add_executable(testsTestServer
|
||||
tests/testsTestServer.cpp
|
||||
teamServer/TeamServerAuth.cpp
|
||||
teamServer/TeamServerHelpService.cpp
|
||||
teamServer/TeamServerRuntimeConfig.cpp
|
||||
teamServer/TeamServerBootstrap.cpp
|
||||
../core/listener/Listener.cpp
|
||||
../../thirdParty/base64/base64.cpp
|
||||
)
|
||||
target_include_directories(testsTestServer PRIVATE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/teamServer
|
||||
@@ -54,6 +58,26 @@ if(WITH_TESTS)
|
||||
|
||||
add_test(NAME testsTestServer COMMAND "${C2_TEST_BIN_OUTPUT_DIR}/$<TARGET_FILE_NAME:testsTestServer>")
|
||||
|
||||
add_executable(testsTeamServerHelpService
|
||||
tests/TeamServerHelpServiceTests.cpp
|
||||
teamServer/TeamServerHelpService.cpp
|
||||
../core/listener/Listener.cpp
|
||||
../../thirdParty/base64/base64.cpp
|
||||
)
|
||||
target_include_directories(testsTeamServerHelpService PRIVATE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/teamServer
|
||||
)
|
||||
if(WIN32)
|
||||
target_link_libraries(testsTeamServerHelpService GrpcMessages openssl::openssl ${OPENSSL_CRYPTO_LIBRARY} ZLIB::ZLIB grpc::grpc spdlog::spdlog)
|
||||
else()
|
||||
target_link_libraries(testsTeamServerHelpService GrpcMessages pthread openssl::openssl ZLIB::ZLIB grpc::grpc spdlog::spdlog httplib::httplib Crow::Crow dl rt)
|
||||
endif()
|
||||
|
||||
add_custom_command(TARGET testsTeamServerHelpService POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy
|
||||
$<TARGET_FILE:testsTeamServerHelpService> "${C2_TEST_BIN_OUTPUT_DIR}/$<TARGET_FILE_NAME:testsTeamServerHelpService>")
|
||||
|
||||
add_test(NAME testsTeamServerHelpService COMMAND "${C2_TEST_BIN_OUTPUT_DIR}/$<TARGET_FILE_NAME:testsTeamServerHelpService>")
|
||||
|
||||
add_executable(testsTeamServerListenerSessionService
|
||||
tests/TeamServerListenerSessionServiceTests.cpp
|
||||
teamServer/TeamServerListenerSessionService.cpp
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include "TeamServerAuth.hpp"
|
||||
#include "TeamServerBootstrap.hpp"
|
||||
#include "TeamServerHelpService.hpp"
|
||||
#include "TeamServerListenerSessionService.hpp"
|
||||
#include "TeamServerRuntimeConfig.hpp"
|
||||
|
||||
@@ -53,6 +54,11 @@ TeamServer::TeamServer(const nlohmann::json& config)
|
||||
|
||||
m_authManager = std::make_unique<TeamServerAuthManager>(m_logger);
|
||||
m_authManager->configure(config);
|
||||
m_helpService = std::make_unique<TeamServerHelpService>(
|
||||
m_logger,
|
||||
m_listeners,
|
||||
m_moduleCmd,
|
||||
m_commonCommands);
|
||||
m_listenerSessionService = std::make_unique<TeamServerListenerSessionService>(
|
||||
m_logger,
|
||||
m_config,
|
||||
@@ -398,119 +404,12 @@ grpc::Status TeamServer::GetResponseFromSession(grpc::ServerContext* context, co
|
||||
{ return writer->Write(commandResponse); });
|
||||
}
|
||||
|
||||
const std::string HelpCmd = "help";
|
||||
|
||||
grpc::Status TeamServer::GetHelp(grpc::ServerContext* context, const teamserverapi::Command* command, teamserverapi::CommandResponse* commandResponse)
|
||||
{
|
||||
auto authStatus = ensureAuthenticated(context);
|
||||
if (!authStatus.ok())
|
||||
return authStatus;
|
||||
|
||||
m_logger->trace("GetHelp");
|
||||
|
||||
std::string input = command->cmd();
|
||||
std::string beaconHash = command->beaconhash();
|
||||
std::string listenerHash = command->listenerhash();
|
||||
|
||||
bool isWindows = false;
|
||||
for (int i = 0; i < m_listeners.size(); i++)
|
||||
{
|
||||
if (m_listeners[i]->isSessionExist(beaconHash, listenerHash))
|
||||
{
|
||||
std::shared_ptr<Session> session = m_listeners[i]->getSessionPtr(beaconHash, listenerHash);
|
||||
std::string os = session->getOs();
|
||||
if (os == "Windows")
|
||||
isWindows = true;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::string> splitedCmd;
|
||||
std::string delimiter = " ";
|
||||
splitList(input, delimiter, splitedCmd);
|
||||
|
||||
string instruction = splitedCmd[0];
|
||||
|
||||
std::string output;
|
||||
if (instruction == HelpCmd)
|
||||
{
|
||||
if (splitedCmd.size() < 2)
|
||||
{
|
||||
output += "- Beacon Commands:\n";
|
||||
for (int i = 0; i < m_commonCommands.getNumberOfCommand(); i++)
|
||||
{
|
||||
output += " ";
|
||||
output += m_commonCommands.getCommand(i);
|
||||
output += "\n";
|
||||
}
|
||||
|
||||
if (isWindows)
|
||||
{
|
||||
output += "\n- Modules Commands Windows:\n";
|
||||
for (auto it = m_moduleCmd.begin(); it != m_moduleCmd.end(); ++it)
|
||||
{
|
||||
if ((*it)->osCompatibility() & OS_WINDOWS)
|
||||
{
|
||||
output += " ";
|
||||
output += (*it)->getName();
|
||||
output += "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
output += "\n- Modules Commands Linux:\n";
|
||||
for (auto it = m_moduleCmd.begin(); it != m_moduleCmd.end(); ++it)
|
||||
{
|
||||
if ((*it)->osCompatibility() & OS_LINUX)
|
||||
{
|
||||
output += " ";
|
||||
output += (*it)->getName();
|
||||
output += "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
string instruction = splitedCmd[1];
|
||||
bool isModuleFound = false;
|
||||
for (int i = 0; i < m_commonCommands.getNumberOfCommand(); i++)
|
||||
{
|
||||
if (instruction == m_commonCommands.getCommand(i))
|
||||
{
|
||||
output += m_commonCommands.getHelp(instruction);
|
||||
output += "\n";
|
||||
isModuleFound = true;
|
||||
}
|
||||
}
|
||||
for (auto it = m_moduleCmd.begin(); it != m_moduleCmd.end(); ++it)
|
||||
{
|
||||
if (instruction == (*it)->getName())
|
||||
{
|
||||
output += (*it)->getInfo();
|
||||
output += "\n";
|
||||
isModuleFound = true;
|
||||
}
|
||||
}
|
||||
if (!isModuleFound)
|
||||
{
|
||||
output += "Module ";
|
||||
output += instruction;
|
||||
output += " not found.";
|
||||
output += "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
teamserverapi::CommandResponse commandResponseTmp;
|
||||
commandResponseTmp.set_cmd(input);
|
||||
commandResponseTmp.set_response(output);
|
||||
|
||||
*commandResponse = commandResponseTmp;
|
||||
|
||||
m_logger->trace("GetHelp end");
|
||||
|
||||
return grpc::Status::OK;
|
||||
return m_helpService->getHelp(*command, commandResponse);
|
||||
}
|
||||
|
||||
// Split input based on spaces and single quotes
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include "nlohmann/json.hpp"
|
||||
|
||||
class TeamServerAuthManager;
|
||||
class TeamServerHelpService;
|
||||
class TeamServerListenerSessionService;
|
||||
|
||||
class TeamServer final : public teamserverapi::TeamServerApi::Service
|
||||
@@ -97,5 +98,6 @@ private:
|
||||
std::vector<C2Message> m_sentC2Messages;
|
||||
|
||||
std::unique_ptr<TeamServerAuthManager> m_authManager;
|
||||
std::unique_ptr<TeamServerHelpService> m_helpService;
|
||||
std::unique_ptr<TeamServerListenerSessionService> m_listenerSessionService;
|
||||
};
|
||||
|
||||
@@ -0,0 +1,136 @@
|
||||
#include "TeamServerHelpService.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "modules/ModuleCmd/Common.hpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
const std::string HelpCmd = "help";
|
||||
}
|
||||
|
||||
TeamServerHelpService::TeamServerHelpService(
|
||||
std::shared_ptr<spdlog::logger> logger,
|
||||
std::vector<std::shared_ptr<Listener>>& listeners,
|
||||
std::vector<std::unique_ptr<ModuleCmd>>& moduleCmd,
|
||||
CommonCommands& commonCommands)
|
||||
: m_logger(std::move(logger)),
|
||||
m_listeners(listeners),
|
||||
m_moduleCmd(moduleCmd),
|
||||
m_commonCommands(commonCommands)
|
||||
{
|
||||
}
|
||||
|
||||
grpc::Status TeamServerHelpService::getHelp(const teamserverapi::Command& command, teamserverapi::CommandResponse* commandResponse) const
|
||||
{
|
||||
m_logger->trace("GetHelp");
|
||||
|
||||
const std::string input = command.cmd();
|
||||
const std::string beaconHash = command.beaconhash();
|
||||
const std::string listenerHash = command.listenerhash();
|
||||
|
||||
std::vector<std::string> splitedCmd;
|
||||
splitList(input, " ", splitedCmd);
|
||||
|
||||
std::string output;
|
||||
if (!splitedCmd.empty() && splitedCmd[0] == HelpCmd)
|
||||
{
|
||||
if (splitedCmd.size() < 2)
|
||||
output = buildGeneralHelp(isWindowsSession(beaconHash, listenerHash));
|
||||
else
|
||||
output = buildSpecificHelp(splitedCmd[1]);
|
||||
}
|
||||
|
||||
teamserverapi::CommandResponse commandResponseTmp;
|
||||
commandResponseTmp.set_cmd(input);
|
||||
commandResponseTmp.set_response(output);
|
||||
*commandResponse = commandResponseTmp;
|
||||
|
||||
m_logger->trace("GetHelp end");
|
||||
return grpc::Status::OK;
|
||||
}
|
||||
|
||||
bool TeamServerHelpService::isWindowsSession(const std::string& beaconHash, const std::string& listenerHash) const
|
||||
{
|
||||
for (const std::shared_ptr<Listener>& listener : m_listeners)
|
||||
{
|
||||
if (!listener->isSessionExist(beaconHash, listenerHash))
|
||||
continue;
|
||||
|
||||
std::shared_ptr<Session> session = listener->getSessionPtr(beaconHash, listenerHash);
|
||||
return session && session->getOs() == "Windows";
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string TeamServerHelpService::buildGeneralHelp(bool isWindows) const
|
||||
{
|
||||
std::string output;
|
||||
output += "- Beacon Commands:\n";
|
||||
for (int i = 0; i < m_commonCommands.getNumberOfCommand(); i++)
|
||||
{
|
||||
output += " ";
|
||||
output += m_commonCommands.getCommand(i);
|
||||
output += "\n";
|
||||
}
|
||||
|
||||
if (isWindows)
|
||||
output += "\n- Modules Commands Windows:\n";
|
||||
else
|
||||
output += "\n- Modules Commands Linux:\n";
|
||||
|
||||
for (const std::unique_ptr<ModuleCmd>& module : m_moduleCmd)
|
||||
{
|
||||
if (isWindows && (module->osCompatibility() & OS_WINDOWS))
|
||||
{
|
||||
output += " ";
|
||||
output += module->getName();
|
||||
output += "\n";
|
||||
}
|
||||
else if (!isWindows && (module->osCompatibility() & OS_LINUX))
|
||||
{
|
||||
output += " ";
|
||||
output += module->getName();
|
||||
output += "\n";
|
||||
}
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
std::string TeamServerHelpService::buildSpecificHelp(const std::string& instruction) const
|
||||
{
|
||||
std::string output;
|
||||
bool isModuleFound = false;
|
||||
|
||||
for (int i = 0; i < m_commonCommands.getNumberOfCommand(); i++)
|
||||
{
|
||||
if (instruction == m_commonCommands.getCommand(i))
|
||||
{
|
||||
output += m_commonCommands.getHelp(instruction);
|
||||
output += "\n";
|
||||
isModuleFound = true;
|
||||
}
|
||||
}
|
||||
|
||||
for (const std::unique_ptr<ModuleCmd>& module : m_moduleCmd)
|
||||
{
|
||||
if (instruction == module->getName())
|
||||
{
|
||||
output += module->getInfo();
|
||||
output += "\n";
|
||||
isModuleFound = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!isModuleFound)
|
||||
{
|
||||
output += "Module ";
|
||||
output += instruction;
|
||||
output += " not found.\n";
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <grpcpp/support/status.h>
|
||||
|
||||
#include "TeamServerApi.pb.h"
|
||||
#include "listener/Listener.hpp"
|
||||
#include "modules/ModuleCmd/CommonCommand.hpp"
|
||||
#include "modules/ModuleCmd/ModuleCmd.hpp"
|
||||
#include "spdlog/logger.h"
|
||||
|
||||
class TeamServerHelpService
|
||||
{
|
||||
public:
|
||||
TeamServerHelpService(
|
||||
std::shared_ptr<spdlog::logger> logger,
|
||||
std::vector<std::shared_ptr<Listener>>& listeners,
|
||||
std::vector<std::unique_ptr<ModuleCmd>>& moduleCmd,
|
||||
CommonCommands& commonCommands);
|
||||
|
||||
grpc::Status getHelp(const teamserverapi::Command& command, teamserverapi::CommandResponse* commandResponse) const;
|
||||
|
||||
private:
|
||||
bool isWindowsSession(const std::string& beaconHash, const std::string& listenerHash) const;
|
||||
std::string buildGeneralHelp(bool isWindows) const;
|
||||
std::string buildSpecificHelp(const std::string& instruction) const;
|
||||
|
||||
std::shared_ptr<spdlog::logger> m_logger;
|
||||
std::vector<std::shared_ptr<Listener>>& m_listeners;
|
||||
std::vector<std::unique_ptr<ModuleCmd>>& m_moduleCmd;
|
||||
CommonCommands& m_commonCommands;
|
||||
};
|
||||
@@ -0,0 +1,128 @@
|
||||
#include <cassert>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "TeamServerHelpService.hpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
class TestListener final : public Listener
|
||||
{
|
||||
public:
|
||||
explicit TestListener(const std::string& hash)
|
||||
: Listener("127.0.0.1", "8443", ListenerHttpsType)
|
||||
{
|
||||
m_listenerHash = hash;
|
||||
}
|
||||
|
||||
std::shared_ptr<Session> addSession(
|
||||
const std::string& listenerHash,
|
||||
const std::string& beaconHash,
|
||||
const std::string& os)
|
||||
{
|
||||
auto session = std::make_shared<Session>(listenerHash, beaconHash, "host", "user", "x64", "admin", os);
|
||||
m_sessions.push_back(session);
|
||||
return session;
|
||||
}
|
||||
};
|
||||
|
||||
class FakeModule final : public ModuleCmd
|
||||
{
|
||||
public:
|
||||
FakeModule(std::string name, std::string info, int compatibility)
|
||||
: ModuleCmd(std::move(name)),
|
||||
m_info(std::move(info)),
|
||||
m_compatibility(compatibility)
|
||||
{
|
||||
}
|
||||
|
||||
std::string getInfo() override
|
||||
{
|
||||
return m_info;
|
||||
}
|
||||
|
||||
int init(std::vector<std::string>&, C2Message&) override
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int process(C2Message&, C2Message&) override
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int osCompatibility() override
|
||||
{
|
||||
return m_compatibility;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string m_info;
|
||||
int m_compatibility;
|
||||
};
|
||||
|
||||
std::shared_ptr<spdlog::logger> makeLogger()
|
||||
{
|
||||
auto logger = std::make_shared<spdlog::logger>("help-tests");
|
||||
logger->set_level(spdlog::level::off);
|
||||
return logger;
|
||||
}
|
||||
|
||||
void testGeneralHelpUsesSessionPlatform()
|
||||
{
|
||||
auto logger = makeLogger();
|
||||
std::vector<std::shared_ptr<Listener>> listeners;
|
||||
auto listener = std::make_shared<TestListener>("listener-primary");
|
||||
listener->addSession("listener-primary", "ABCDEFGH12345678", "Windows");
|
||||
listeners.push_back(listener);
|
||||
|
||||
std::vector<std::unique_ptr<ModuleCmd>> moduleCmd;
|
||||
moduleCmd.push_back(std::make_unique<FakeModule>("winmod", "windows module info", OS_WINDOWS));
|
||||
moduleCmd.push_back(std::make_unique<FakeModule>("linmod", "linux module info", OS_LINUX));
|
||||
|
||||
CommonCommands commonCommands;
|
||||
TeamServerHelpService service(logger, listeners, moduleCmd, commonCommands);
|
||||
|
||||
teamserverapi::Command command;
|
||||
command.set_cmd("help");
|
||||
command.set_beaconhash("ABCDEFGH12345678");
|
||||
command.set_listenerhash("listener-primary");
|
||||
|
||||
teamserverapi::CommandResponse response;
|
||||
assert(service.getHelp(command, &response).ok());
|
||||
assert(response.response().find("- Modules Commands Windows:") != std::string::npos);
|
||||
assert(response.response().find("winmod") != std::string::npos);
|
||||
assert(response.response().find("linmod") == std::string::npos);
|
||||
}
|
||||
|
||||
void testSpecificHelpResolvesModuleInfoAndMissingModule()
|
||||
{
|
||||
auto logger = makeLogger();
|
||||
std::vector<std::shared_ptr<Listener>> listeners;
|
||||
std::vector<std::unique_ptr<ModuleCmd>> moduleCmd;
|
||||
moduleCmd.push_back(std::make_unique<FakeModule>("winmod", "windows module info", OS_WINDOWS));
|
||||
|
||||
CommonCommands commonCommands;
|
||||
TeamServerHelpService service(logger, listeners, moduleCmd, commonCommands);
|
||||
|
||||
teamserverapi::Command moduleCommand;
|
||||
moduleCommand.set_cmd("help winmod");
|
||||
teamserverapi::CommandResponse moduleResponse;
|
||||
assert(service.getHelp(moduleCommand, &moduleResponse).ok());
|
||||
assert(moduleResponse.response().find("windows module info") != std::string::npos);
|
||||
|
||||
teamserverapi::Command missingCommand;
|
||||
missingCommand.set_cmd("help nope");
|
||||
teamserverapi::CommandResponse missingResponse;
|
||||
assert(service.getHelp(missingCommand, &missingResponse).ok());
|
||||
assert(missingResponse.response() == "Module nope not found.\n");
|
||||
}
|
||||
} // namespace
|
||||
|
||||
int main()
|
||||
{
|
||||
testGeneralHelpUsesSessionPlatform();
|
||||
testSpecificHelpResolvesModuleInfoAndMissingModule();
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user