This commit is contained in:
maxdcb
2026-04-19 15:32:04 +02:00
parent f1eee012d6
commit b080cbbb91
6 changed files with 332 additions and 108 deletions
+24
View File
@@ -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
+7 -108
View File
@@ -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
+2
View File
@@ -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;
}